📄 boot.c
字号:
bootdev.primary= p; else bootdev.secondary= p; break; } /* This happens when lightning strikes while booting: */ if (p == NR_PARTITIONS || bootdev.primary >= 0) { printf("Can't find the partition starting at %lu???\n", lowsec); reboot(); } /* See if the primary partition is subpartitioned. */ bootdev.primary= p; masterpos= table[p]->lowsec; }}char null[]= "";void sfree(s) char *s;/* Free a non-null string. */{ if (s != nil && s != null) free((void *) s);}char *copystr(s) char *s;/* Copy a non-null string using malloc. */{ char *c; if (*s == 0) return null; c= (char *) malloc((strlen(s) + 1) * sizeof(char)); strcpy(c, s); return c;}int is_default(e) environment *e;{ return (e->flags & E_SPECIAL) && e->defval == nil;}environment **searchenv(name) char *name;{ environment **aenv= &env; while (*aenv != nil && strcmp((*aenv)->name, name) != 0) aenv= &(*aenv)->next; return aenv;}#define b_getenv(name) (*searchenv(name))/* Return the environment *structure* belonging to name, or nil if not found. */char *b_value(name) char *name;/* The value of a variable. */{ environment *e= b_getenv(name); return e == nil || !(e->flags & E_VAR) ? nil : e->value;}char *b_body(name) char *name;/* The value of a function. */{ environment *e= b_getenv(name); return e == nil || !(e->flags & E_FUNCTION) ? nil : e->value;}// b_setenv(E_RESERVED|E_FUNCTION, "\1", "=,Start Minix", "boot");int b_setenv(flags, name, arg, value) int flags; char *name, *arg, *value;/* Change the value of an environment variable. Returns the flags of the * variable if you are not allowed to change it, 0 otherwise. */{ environment **aenv, *e; if (*(aenv= searchenv(name)) == nil) { e= (environment *) malloc(sizeof(*e)); e->name= copystr(name); e->flags= flags; e->defval= nil; e->next= nil; *aenv= e; } else { e= *aenv; /* Don't touch reserved names and don't change special * variables to functions or vv. */ if (e->flags & E_RESERVED || (e->flags & E_SPECIAL && (e->flags & E_FUNCTION) != (flags & E_FUNCTION) )) return e->flags; e->flags= (e->flags & E_STICKY) | flags; if (is_default(e)) e->defval= e->value; else sfree(e->value); sfree(e->arg); } e->arg= copystr(arg); e->value= copystr(value); return 0;}int b_setvar(flags, name, value) int flags; char *name, *value;/* Set variable or simple function. */{ return b_setenv(flags, name, null, value);}void b_unset(name) char *name;/* Remove a variable from the environment. A special variable is reset to * its default value. */{ environment **aenv, *e; if ((e= *(aenv= searchenv(name))) == nil) return; if (e->flags & E_SPECIAL) { if (e->defval != nil) { sfree(e->arg); e->arg= null; sfree(e->value); e->value= e->defval; e->defval= nil; } } else { sfree(e->name); sfree(e->arg); sfree(e->value); *aenv= e->next; free((void *) e); }}#define between(a, c, z) ((unsigned) ((c) - (a)) <= ((z) - (a)))long a2l(a) char *a;/* Cheap atol(). */{ int sign= 1; long l= 0; if (*a == '-') { sign= -1; a++; } while (between('0', *a, '9')) l= l * 10 + (*a++ - '0'); return sign * l;}char *ul2a(n) u32_t n;/* Transform a long number to ascii digits. */{ static char num[3 * sizeof(n)]; char *pn= arraylimit(num) - 1; do *--pn = (n % 10) + '0'; while ((n/= 10) > 0); return pn;}char *u2a(n) u16_t n;/* Transform a short number to ascii digits. */{ return ul2a((u32_t) n);}void get_parameters(){ char params[SECTOR_SIZE + 1]; token **acmds; int vid, r, fundef= 0; static char *vid_type[] = { "mda", "cga", "ega", "ega", "vga", "vga" }; /* Variables that Minix needs: */ b_setvar(E_SPECIAL|E_VAR|E_DEV, "rootdev", "ram"); b_setvar(E_SPECIAL|E_VAR|E_DEV, "ramimagedev", "bootdev"); b_setvar(E_SPECIAL|E_VAR, "ramsize", "0"); b_setvar(E_SPECIAL|E_VAR, "keyboard", "standard"); b_setvar(E_SPECIAL|E_VAR, "processor", u2a(get_processor())); b_setvar(E_SPECIAL|E_VAR, "memsize", u2a(get_low_memsize())); b_setvar(E_SPECIAL|E_VAR, "emssize", u2a(get_ext_memsize())); vid= get_video(); b_setvar(E_SPECIAL|E_VAR, "chrome", (vid & 1) ? "color" : "mono"); b_setvar(E_SPECIAL|E_VAR, "video", vid_type[vid]); /* Variables boot needs: */ b_setvar(E_SPECIAL|E_VAR, "image", "minix"); b_setvar(E_SPECIAL|E_FUNCTION, "main", "menu"); /* Default menu functions: */ b_setenv(E_RESERVED|E_FUNCTION, "\1", "=,Start Minix", "boot"); /* Reserved names: */ b_setvar(E_RESERVED, "scancode", null); b_setvar(E_RESERVED, "boot", null); b_setvar(E_RESERVED, "menu", null); b_setvar(E_RESERVED, "set", null); b_setvar(E_RESERVED, "unset", null); b_setvar(E_RESERVED, "save", null); b_setvar(E_RESERVED, "ls", null); b_setvar(E_RESERVED, "echo", null); b_setvar(E_RESERVED, "trap", null); /* Tokenize bootparams sector. */ if ((r= readsectors((u16_t) params, dseg, lowsec+PARAMSEC, 1)) != 0) readerr(lowsec+PARAMSEC, r); else { params[SECTOR_SIZE]= 0; acmds= tokenize(&cmds, params, &fundef); /* Reboot code may have new parameters. */ if (device >= 0x80 && boot_part.sysind == NO_PART) { raw_copy((u16_t) params, dseg, (u16_t) (boot_part.size & 0x0F), (u16_t) (boot_part.size >> 4), SECTOR_SIZE); acmds= tokenize(&cmds, params, &fundef); } /* Stuff the default action into the command chain. */ (void) tokenize(acmds, ":;main", &fundef); }}void addparm(ap, n) char **ap, *n;{ char *p= *ap; while (*n != 0 && *p != 0) *p++ = *n++; *ap= p;}void save_parameters()/* Save nondefault environment variables to the bootparams sector. */{ environment *e; char params[SECTOR_SIZE + 1]; char *p= params; int r; /* Default filling: */ memset((void *) params, '\n', (size_t) SECTOR_SIZE); /* Don't touch the 0! */ params[SECTOR_SIZE]= 0; for (e= env; e != nil; e= e->next) { if (e->flags & E_RESERVED || is_default(e)) continue; addparm(&p, e->name); if (e->flags & E_FUNCTION) { addparm(&p, "("); addparm(&p, e->arg); addparm(&p, "){"); } else { addparm(&p, (e->flags & (E_DEV|E_SPECIAL)) != E_DEV ? "=" : "=d "); } addparm(&p, e->value); if (e->flags & E_FUNCTION) addparm(&p, "}"); if (*p == 0) { printf("The environment is too big\n"); return; } *p++= '\n'; } /* Save the parameters on disk. */ if ((r= writesectors((u16_t) params, dseg, lowsec+PARAMSEC, 1)) != 0) { writerr(lowsec+PARAMSEC, r); printf("Can't save environment\n"); }}void show_env()/* Show the environment settings. */{ environment *e; for (e= env; e != nil; e= e->next) { if (e->flags & E_RESERVED) continue; if (e->flags & E_FUNCTION) printf("%s(%s) {%s}", e->name, e->arg, e->value); else { printf("%s = ", e->name); if (is_default(e)) putchar('('); printf("%s", e->value); if (is_default(e)) putchar(')'); } putchar('\n'); }}int numprefix(s, ps) char *s, **ps;/* True iff s is a string of digits. *ps will be set to the first nondigit * if non-nil, otherwise the string should end. */{ char *n= s; while (between('0', *n, '9')) n++; if (n == s) return 0; if (ps == nil) return *n == 0; *ps= n; return 1;}int numeric(s) char *s;{ return numprefix(s, (char **) nil);}#ifdef MINIX15 /* Now by default Minix 1.6! */#define DEV_PS0 0x21c /* Major, minor of 1.44M drive 0. */#endif#define DEV_HD1a (DEV_HD0 + 128) /* First subpartition /dev/hd1a. */dev_t name2dev(name) char *name;/* Translate, say, /dev/hd3 to a device number. If the name can't be * found on the boot device, then do some guesswork. The global structure * "tmpdev" will be filled in based on the name, so that "boot hd6" knows * what device to boot without interpreting device numbers. */{ dev_t dev= -1; ino_t ino; struct stat st; char *n, *s; static char fdN[] = "fdN"; static char hdNX[] = "hdNNX"; static char sub[] = "a"; tmpdev.primary= tmpdev.secondary= -1; /* "boot *hd3" means: make partition 3 active before you boot it. */ if (activate= (name[0] == '*')) name++; /* The special name "bootdev" must be translated to the boot device. */ if (strcmp(name, "bootdev") == 0) { if (device < 0x80) { /* Floppy disk. */#ifdef MINIX15 /* A Minix 1.5 kernel can't detect a 1.44Mb floppy. It * needs this kluge enabled. */ strcpy(fdN, sectors == 18 ? "PS" : "fd");#endif strcpy(fdN+2, u2a(device)); name= fdN; } else { /* Hard disk */ strcpy(hdNX+2, u2a((device - 0x80) * (1 + NR_PARTITIONS) + 1 + bootdev.primary)); if (bootdev.secondary >= 0) { sub[0] = 'a' + bootdev.secondary; strcat(hdNX, sub); } name= hdNX; } } /* Now translate fd0, hd6, etc. the BIOS way. */ n= name; if (strncmp(n, "/dev/", 5) == 0) n+= 5; if (n[0] == 'f' && n[1] == 'd' && numeric(n+2)) tmpdev.device= a2l(n+2); else#ifdef MINIX15 if (n[0] == 'P' && n[1] == 'S' && numeric(n+2)) tmpdev.device= a2l(n+2); else#endif if (n[0] == 'h' && n[1] == 'd' && numprefix(n+2, &s)) { tmpdev.primary= a2l(n+2); tmpdev.device= 0x80 + tmpdev.primary / (1 + NR_PARTITIONS); tmpdev.primary= (tmpdev.primary % (1 + NR_PARTITIONS)) - 1; if (*s == 0) /* Not a secondary */ ; else if (tmpdev.primary >= 0 && between('a', *s, 'd') && s[1] == 0) tmpdev.secondary= *s - 'a'; else tmpdev.device= -1; } else tmpdev.device= -1; if (tmpdev.primary < 0) activate= 0; /* Careful now! */ /* Look the name up on the boot device for the UNIX device number. */ if (fsok) { /* The current working directory is "/dev". */ ino= r_lookup(r_lookup(ROOT_INO, "dev"), name); if (ino != 0) { /* Name has been found, extract the device number. */ r_stat(ino, &st); if (!S_ISBLK(st.st_mode)) { printf("%s is not a block device\n"); errno= 0; return (dev_t) -1; } dev= st.st_rdev; } } if (dev == -1 && tmpdev.device >= 0) { /* The name can't be found on the boot device, do guesswork. */ if (tmpdev.device < 0x80)#ifdef MINIX15 dev= (sectors==18 ? DEV_PS0 : DEV_FD0) + tmpdev.device;#else dev= DEV_FD0 + tmpdev.device;#endif else if (tmpdev.secondary < 0) dev= DEV_HD0 + (tmpdev.device - 0x80) * (1 + NR_PARTITIONS) + (1 + tmpdev.primary); else dev= DEV_HD1a + ((tmpdev.device - 0x80) * NR_PARTITIONS + tmpdev.primary) * NR_PARTITIONS + tmpdev.secondary; } /* Don't forget the ram device. */ if (dev == -1 && strcmp(n, "ram") == 0) dev= DEV_RAM; if (dev == -1) { printf("Can't recognize %s as a device\n", name); errno= 0; } return dev;}#define B_NODEV -1#define B_NOSIG -2int exec_bootstrap()/* Load boot sector from the disk or floppy described by tmpdev and execute it. * The floppy parameters may not be right for the floppy we want to read, but * reading sector 0 seems to be no problem. */{ int r, n, dirty= 0; char master[SECTOR_SIZE]; struct part_entry *table[NR_PARTITIONS], dummy, *active= &dummy; u32_t masterpos;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -