boot: add command line editor

This commit is contained in:
K. Lange 2021-08-21 07:55:48 +09:00
parent 61b7444192
commit 079db87617
7 changed files with 150 additions and 3 deletions

View File

@ -48,7 +48,7 @@ int kmain() {
"Enable debug output in the bootloader and enable the",
"serial debug log in the operating system itself.");
BOOT_OPTION(_nosmp, 0, "Disable SMP",
BOOT_OPTION(_smp, 1, "Enable SMP",
"SMP support may not be completely stable and can be",
"disabled with this option if desired.");
@ -76,6 +76,10 @@ int kmain() {
"Migrates the ramdisk from tarball to an in-memory",
"temporary filesystem at boot. Needed for packages.");
BOOT_OPTION(_qemubug, 0, "QEMU PS/2 workaround",
"Work around a bug in QEMU's PS/2 controller",
"prior to 6.0.50.");
/* Loop over rendering the menu */
show_menu();
@ -120,10 +124,18 @@ int kmain() {
strcat(cmdline, "novmwareresset ");
}
if (_nosmp) {
if (!_smp) {
strcat(cmdline, "nosmp ");
}
if (_qemubug) {
strcat(cmdline, "sharedps2 ");
}
if (boot_edit) {
boot_editor();
}
boot();
while (1) {}

68
boot/editor.c Normal file
View File

@ -0,0 +1,68 @@
#include <stdint.h>
#include "options.h"
#include "text.h"
#include "util.h"
extern int read_key(char * c);
void boot_editor(void) {
int len = strlen(cmdline);
int cursor = len;
while (1) {
move_cursor(0,0);
for (int i = 0; i <= len; ++i) {
set_attr(i == cursor ? 0x70 : 0x07);
print_((char[]){cmdline[i],'\0'});
}
print_(" ");
set_attr(0x07);
do {
do {
print_(" ");
} while (x);
} while (y);
char data = 0;
int status = read_key(&data);
if (status == 0) {
/* Handle a few special characters */
if (data == '\n') {
return;
} else if (data == '\b') {
if (!cursor) continue;
if (cursor == len) {
cmdline[len-1] = '\0';
cursor--;
len--;
} else {
cmdline[cursor-1] = '\0';
strcat(cmdline,&cmdline[cursor]);
cursor--;
len--;
}
} else {
if (len > 1022) continue;
/* Move everything from the cursor onward forward */
if (cursor < len) {
int x = len + 1;
while (x > cursor) {
cmdline[x] = cmdline[x-1];
x--;
}
}
cmdline[cursor] = data;
len++;
cursor++;
}
} else if (status == 2) {
/* Left */
if (cursor) cursor--;
} else if (status == 3) {
if (cursor < len) cursor++;
}
}
}

View File

@ -6,6 +6,54 @@ int read_cmos_seconds(void) {
return inportb(0x71);
}
static char kbd_us[128] = {
0, 27, '1','2','3','4','5','6','7','8','9','0',
'-','=','\b', '\t', 'q','w','e','r','t','y','u','i','o','p','[',']','\n',
0, 'a','s','d','f','g','h','j','k','l',';','\'', '`',
0, '\\','z','x','c','v','b','n','m',',','.','/',
0, '*', 0, ' ', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
'-', 0, 0, 0, '+', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
};
static char kbd_us_l2[128] = {
0, 27, '!','@','#','$','%','^','&','*','(',')',
'_','+','\b', '\t', 'Q','W','E','R','T','Y','U','I','O','P','{','}','\n',
0, 'A','S','D','F','G','H','J','K','L',':','"', '~',
0, '|','Z','X','C','V','B','N','M','<','>','?',
0, '*', 0, ' ', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
'-', 0, 0, 0, '+', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
};
int read_key(char * c) {
static int shift_state = 0;
int sc = read_scancode(0);
switch (sc) {
/* Shift down */
case 0x2A:
case 0x36:
shift_state = 1;
return 1;
/* Shift up */
case 0xAA:
case 0xB6:
shift_state = 0;
return 1;
/* Keft left and right */
case 0x4B: return 2;
case 0x4D: return 3;
}
if (!(sc & 0x80)) {
*c = shift_state ? kbd_us_l2[sc] : kbd_us[sc];
return *c == 0;
}
return 1;
}
int read_scancode(int timeout) {
if (timeout) {
int start_s = read_cmos_seconds();

View File

@ -9,6 +9,7 @@ struct option boot_options[20] = {{0}};
int sel_max = 0;
int sel = 0;
int boot_mode = 0;
int boot_edit = 0;
void toggle(int ndx, int value, char *str) {
set_attr(sel == ndx ? 0x70 : 0x07);
@ -80,7 +81,7 @@ void show_menu(void) {
}
set_attr(0x07);
move_cursor(x,15);
move_cursor(0,15);
if (timeout) {
*timeout_val = timeout + '0';
print_banner(timeout_msg);
@ -148,6 +149,12 @@ void show_menu(void) {
int index = sel - base_sel - 1;
*boot_options[index].value = !*boot_options[index].value;
}
} else if (s == 0x12) { /* e */
if (sel <= base_sel) {
boot_edit = 1;
boot_mode = boot_mode_names[sel].index;
break;
}
} else if (s >= 2 && s <= 10) {
int i = s - 2;
if (i <= base_sel) {

View File

@ -1,4 +1,6 @@
#pragma once
extern int boot_mode;
extern int boot_edit;
void show_menu(void);
void boot_editor(void);

View File

@ -31,6 +31,15 @@ char * strchr(const char * s, int c) {
return 0;
}
unsigned long strlen(const char *s) {
unsigned long out = 0;
while (*s) {
out++;
s++;
}
return out;
}
char * strcat(char *dest, const char *src) {
char * end = dest;
while (*end != '\0') {

View File

@ -41,5 +41,6 @@ char * strchr(const char * s, int c);
char * strcat(char *dest, const char *src);
void copy_sectors(unsigned long lba, unsigned char * buf, int sectors);
void copy_sector(unsigned long lba, unsigned char * buf);
unsigned long strlen(const char *s);
#define DATA_LOAD_BASE 0x4000000