📄 boot.c
字号:
active->bootind= ACTIVE_FLAG;
dirty= 1;
}
/* Read the boot sector. */
if ((r= readsectors(BOOTPOS, active->lowsec, 1)) != 0) return r;
/* Check signature word. */
if (get_word(BOOTPOS+SIGNATOFF) != SIGNATURE) return B_NOSIG;
/* Write the partition table if a member must be made active. */
if (dirty && (r= writesectors(mon2abs(master), masterpos, 1)) != 0)
return r;
bootstrap(device, active);
}
void boot_device(char *devname)
/* Boot the device named by devname. */
{
dev_t dev= name2dev(devname);
int save_dev= device;
int r;
if (tmpdev.device < 0) {
if (dev != -1) printf("Can't boot from %s\n", devname);
return;
}
switch (r= exec_bootstrap(dev)) {
case B_NODEV:
printf("%s: device not present\n", devname);
break;
case B_NOSIG:
printf("%s is not bootable\n", devname);
break;
default:
printf("Can't boot %s: %s\n", devname, bios_err(r));
}
/* Restore boot device setting. */
device= save_dev;
(void) dev_geometry();
}
#else /* DOS */
void boot_device(char *devname)
/* No booting of other devices under DOS */
{
printf("Can't boot devices under MS-DOS\n");
}
#endif /* DOS */
void ls(char *dir)
/* List the contents of a directory. */
{
ino_t ino;
struct stat st;
char name[NAME_MAX+1];
if (!fsok) return;
if ((ino= r_lookup(ROOT_INO, dir)) == 0
|| (r_stat(ino, &st), r_readdir(name)) == -1
) {
printf("ls: %s: %s\n", dir, unix_err(errno));
return;
}
(void) r_readdir(name); /* Skip ".." too. */
while ((ino= r_readdir(name)) != 0) printf("%s/%s\n", dir, name);
}
u32_t milli_time(void)
{
return get_tick() * MSEC_PER_TICK;
}
u32_t milli_since(u32_t base)
{
return (milli_time() + (TICKS_PER_DAY*MSEC_PER_TICK) - base)
% (TICKS_PER_DAY*MSEC_PER_TICK);
}
char *Thandler;
u32_t Tbase, Tcount;
void unschedule(void)
/* Invalidate a waiting command. */
{
if (Thandler != nil) {
free(Thandler);
Thandler= nil;
}
}
void schedule(long msec, char *cmd)
/* Schedule command at a certain time from now. */
{
unschedule();
Thandler= cmd;
Tbase= milli_time();
Tcount= msec;
}
int expired(void)
/* Check if the timer expired. If so prepend the scheduled command to
* the command chain and return 1.
*/
{
int fundef= 0;
if (Thandler == nil || milli_since(Tbase) < Tcount) return 0;
(void) tokenize(tokenize(&cmds, Thandler, &fundef), ";", &fundef);
unschedule();
return 1;
}
int delay(char *msec)
/* Delay for a given time. Returns true iff delay was not interrupted.
* Make sure no time functions are used if msec == 0, because get_tick()
* may do funny things on the original IBM PC (not the XT!).
* If msec happens to be the string "swap" then wait till the user hits
* return after changing diskettes.
*/
{
int swap= 0;
u32_t base, count;
if (strcmp(msec, "swap") == 0) {
swap= 1;
count= 0;
printf("\nInsert the root diskette then hit RETURN\n");
} else
if ((count= a2l(msec)) > 0) {
base= milli_time();
}
do {
switch (peekchar()) {
case -1: break;
case ESC: interrupt(); return 0;
case '\n': swap= 0;
default: (void) getchar();
}
} while (!expired()
&& (swap || (count > 0 && milli_since(base) < count))
);
return 1;
}
enum whatfun { NOFUN, SELECT, DEFFUN, USERFUN } menufun(environment *e)
{
if (!(e->flags & E_FUNCTION) || e->arg[0] == 0) return NOFUN;
if (e->arg[1] != ',') return SELECT;
return e->flags & E_RESERVED ? DEFFUN : USERFUN;
}
void menu(void)
/* By default: Show a simple menu.
* Multiple kernels/images: Show extra selection options.
* User defined function: Kill the defaults and show these.
* Wait for a keypress and execute the given function.
*/
{
int fundef= 0, c, def= 1;
char *choice= nil;
environment *e;
/* Just a default menu? */
for (e= env; e != nil; e= e->next) if (menufun(e) == USERFUN) def= 0;
printf("\nHit a key as follows:\n\n");
/* Show the choices. */
for (e= env; e != nil; e= e->next) {
switch (menufun(e)) {
case DEFFUN:
if (!def) break;
/*FALL THROUGH*/
case USERFUN:
printf(" %c %s\n", e->arg[0], e->arg+2);
break;
case SELECT:
printf(" %c Select %s kernel\n", e->arg[0],e->name);
}
}
/* Wait for a keypress. */
do {
while (peekchar() == -1) if (expired()) return;
unschedule();
if ((c= getchar()) == ESC) { interrupt(); return; }
for (e= env; e != nil; e= e->next) {
switch (menufun(e)) {
case DEFFUN:
if (!def) break;
case USERFUN:
case SELECT:
if (c == e->arg[0]) choice= e->value;
}
}
} while (choice == nil);
/* Execute the chosen function. */
printf("%c\n", c);
(void) tokenize(&cmds, choice, &fundef);
}
void help(void)
/* Not everyone is a rocket scientist. */
{
struct help {
char *thing;
char *help;
} *pi;
static struct help info[] = {
{ nil, "Names:" },
{ "rootdev", "Root device" },
{ "ramimagedev", "RAM disk image if root is RAM" },
{ "ramsize", "RAM disk size if root is not RAM" },
{ "bootdev", "Special name for the boot device" },
{ "fd0, hd3, hd2a", "Devices (as in /dev)" },
{ "image", "Name of the kernel image" },
{ "main", "Startup function" },
{ nil, "Commands:" },
{ "name = [device] value", "Set environment variable" },
{ "name() { ... }", "Define function" },
{ "name(key,text) { ... }",
"A menu function like: minix(=,Start Minix) {boot}" },
{ "name", "Call function" },
{ "boot [device]", "Boot Minix or another O.S." },
{ "delay [msec]", "Delay (500 msec default)" },
{ "echo word ...", "Print the words" },
{ "ls [directory]", "List contents of directory" },
{ "menu", "Choose a menu function" },
{ "save", "Save environment" },
{ "set", "Show environment" },
{ "trap msec command", "Schedule command" },
{ "unset name ...", "Unset variable or set to default" },
{ "exit", "Exit the Monitor" },
};
for (pi= info; pi < arraylimit(info); pi++) {
if (pi->thing != nil) printf(" %-24s- ", pi->thing);
printf("%s\n", pi->help);
}
}
void execute(void)
/* Get one command from the command chain and execute it. */
{
token *second, *third, *fourth, *fifth, *sep;
char *name= cmds->token;
size_t n= 0;
/* There must be a separator lurking somewhere. */
for (sep= cmds; sep != nil && sep->token[0] != ';'; sep= sep->next) n++;
if ((second= cmds->next) != nil
&& (third= second->next) != nil
&& (fourth= third->next) != nil)
fifth= fourth->next;
/* Null command? */
if (n == 0) {
voidtoken();
return;
} else
/* name = [device] value? */
if ((n == 3 || n == 4)
&& !sugar(name)
&& second->token[0] == '='
&& !sugar(third->token)
&& (n == 3 || (n == 4 && third->token[0] == 'd'
&& !sugar(fourth->token)
))) {
char *value= third->token;
int flags= E_VAR;
if (n == 4) { value= fourth->token; flags|= E_DEV; }
if ((flags= b_setvar(flags, name, value)) != 0) {
printf("%s is a %s\n", name,
flags & E_RESERVED ? "reserved word" :
"special function");
err= 1;
}
while (cmds != sep) voidtoken();
return;
} else
/* name '(' arg ')' '{' ... '}'? */
if (n >= 5
&& !sugar(name)
&& second->token[0] == '('
&& fourth->token[0] == ')'
&& fifth->token[0] == '{'
) {
token *fun= fifth->next;
int ok= 1, flags;
char *body;
size_t len= 1;
sep= fun;
while (sep != nil && sep->token[0] != '}') {
len+= strlen(sep->token) + 1;
sep= sep->next;
}
if (sep == nil || (sep= sep->next) == nil
|| sep->token[0] != ';'
) ok= 0;
if (ok) {
body= malloc(len * sizeof(char));
*body= 0;
while (fun->token[0] != '}') {
strcat(body, fun->token);
if (!sugar(fun->token)
&& !sugar(fun->next->token)
) strcat(body, " ");
fun= fun->next;
}
if ((flags= b_setenv(E_FUNCTION, name,
third->token, body)) != 0) {
printf("%s is a %s\n", name,
flags & E_RESERVED ? "reserved word" :
"special variable");
err= 1;
}
while (cmds != sep) voidtoken();
free(body);
return;
}
} else
/* Command coming up, check if ESC typed. */
if (peekchar() == ESC) {
interrupt();
return;
} else
/* unset name ..., echo word ...? */
if (n >= 1 && (
strcmp(name, "unset") == 0
|| strcmp(name, "echo") == 0
)) {
int cmd= name[0];
char *arg= poptoken();
for (;;) {
free(arg);
if (cmds == sep) break;
arg= poptoken();
if (cmd == 'u') {
b_unset(arg);
} else {
printf("%s", arg);
if (cmds != sep) putchar(' ');
}
}
if (cmd == 'e') putchar('\n');
return;
} else
/* boot -opts? */
if (n == 2 && strcmp(name, "boot") == 0 && second->token[0] == '-') {
static char optsvar[]= "bootopts";
(void) b_setvar(E_VAR, optsvar, second->token);
bootminix();
b_unset(optsvar);
voidtoken();
voidtoken();
return;
} else
/* boot device, ls dir, delay msec? */
if (n == 2 && (
strcmp(name, "boot") == 0
|| strcmp(name, "delay") == 0
|| strcmp(name, "ls") == 0
)) {
if (name[0] == 'b') boot_device(second->token);
if (name[0] == 'd') (void) delay(second->token);
if (name[0] == 'l') ls(second->token);
voidtoken();
voidtoken();
return;
} else
/* trap msec command? */
if (n == 3 && strcmp(name, "trap") == 0 && numeric(second->token)) {
long msec= a2l(second->token);
voidtoken();
voidtoken();
schedule(msec, poptoken());
return;
} else
/* Simple command. */
if (n == 1) {
char *cmd= poptoken();
char *body;
int fundef= 0;
int ok= 0;
if (strcmp(cmd, "boot") == 0) { bootminix(); ok= 1; }
if (strcmp(cmd, "delay") == 0) { (void) delay("500"); ok= 1; }
if (strcmp(cmd, "ls") == 0) { ls(null); ok= 1; }
if (strcmp(cmd, "menu") == 0) { menu(); ok= 1; }
if (strcmp(cmd, "save") == 0) { save_parameters(); ok= 1; }
if (strcmp(cmd, "set") == 0) { show_env(); ok= 1; }
if (strcmp(cmd, "help") == 0) { help(); ok= 1; }
if (strcmp(cmd, "exit") == 0) { exit(0); }
/* Command to check bootparams: */
if (strcmp(cmd, ":") == 0) ok= 1;
/* User defined function. */
if (!ok && (body= b_body(cmd)) != nil) {
(void) tokenize(&cmds, body, &fundef);
ok= 1;
}
if (!ok) printf("%s: unknown function", cmd);
free(cmd);
if (ok) return;
} else {
/* Syntax error. */
printf("Can't parse:");
while (cmds != sep) {
printf(" %s", cmds->token); voidtoken();
}
}
/* Getting here means that the command is not understood. */
printf("\nTry 'help'\n");
err= 1;
}
void monitor(void)
/* Read one or more lines and tokenize them. */
{
char *line;
int fundef= 0;
token **acmds= &cmds;
unschedule(); /* Kill a trap. */
do {
printf("%s%c", bootdev.name, fundef == 0 ? '>' : '+');
line= readline();
acmds= tokenize(acmds, line, &fundef);
free(line);
} while (fundef != 0);
}
void boot(void)
/* Load Minix and start it, among other things. */
{
/* Print greeting message. The copyright message is not yet displayed,
* because this boot program need not necessarily start Minix.
*/
reset_video(get_video() & 1 ? COLOR_MODE : MONO_MODE);
printf("\nMinix boot monitor %s\n", version);
printf("\nPress ESC to enter the monitor\n");
/* Initialize tables under DOS. */
if (DOS) initialize();
/* Relocate program to the end of memory. */
migrate();
/* Initialize tables under the BIOS. */
if (!DOS) initialize();
/* Block cache. */
init_cache();
/* Get environment variables from the parameter sector. */
get_parameters();
/* Read and check the superblock. */
fsok= r_super() != 0;
while (1) {
/* While there are commands, execute them! */
while (cmds != nil) {
execute();
if (err) {
/* An error, stop interpreting. */
while (cmds != nil) voidtoken();
err= 0;
break;
}
(void) expired();
remote_code();
}
/* The "monitor" is just a "read one command" thing. */
monitor();
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -