📄 bootimage.c
字号:
return;
}
procp= &process[i];
/* Read header. */
for (;;) {
if ((buf= get_sector(vsec++)) == nil) return;
memcpy(&hdr, buf, sizeof(hdr));
if (BADMAG(hdr.process)) { errno= ENOEXEC; return; }
/* Check the optional label on the process. */
if (selected(hdr.name)) break;
/* Bad label, skip this process. */
vsec+= proc_size(&hdr);
}
/* Place a copy of the header where the kernel can get it. */
raw_copy(HEADERPOS + i * A_MINHDR, mon2abs(&hdr.process),
A_MINHDR);
/* Sanity check: an 8086 can't run a 386 kernel. */
if (hdr.process.a_cpu == A_I80386 && processor < 386) {
printf("You can't run a 386 kernel on this 80%ld\n",
processor);
errno= 0;
return;
}
/* Get the click shift from the kernel text segment. */
if (i == KERNEL) {
if (!get_clickshift(vsec, &hdr)) return;
addr= align(addr, click_size);
}
if (!banner) {
printf(" cs ds text data bss");
if (k_flags & K_CHMEM) printf(" stack");
putchar('\n');
banner= 1;
}
/* Segment sizes. */
a_text= hdr.process.a_text;
a_data= hdr.process.a_data;
a_bss= hdr.process.a_bss;
if (k_flags & K_CHMEM) {
a_stack= hdr.process.a_total - a_data - a_bss;
if (!(hdr.process.a_flags & A_SEP)) a_stack-= a_text;
} else {
a_stack= 0;
}
/* Collect info about the process to be. */
strcpy(procp->name, hdr.name);
procp->cs= addr;
/* Process may be page aligned so that the text segment contains
* the header, or have an unmapped zero page against vaxisms.
*/
procp->entry= hdr.process.a_entry;
if (hdr.process.a_flags & A_PAL) a_text+= hdr.process.a_hdrlen;
if (hdr.process.a_flags & A_UZP) procp->cs-= click_size;
/* Separate I&D: two segments. Common I&D: only one. */
if (hdr.process.a_flags & A_SEP) {
/* Read the text segment. */
if (!get_segment(&vsec, &a_text, &addr, limit)) return;
/* The data segment follows. */
procp->ds= addr;
if (hdr.process.a_flags & A_UZP) procp->ds-= click_size;
procp->data= addr;
} else {
/* Add text to data to form one segment. */
procp->data= addr + a_text;
procp->ds= procp->cs;
a_data+= a_text;
}
printf("%06lx %06lx%8ld%8ld%8ld",
procp->cs, procp->ds,
hdr.process.a_text, hdr.process.a_data,
hdr.process.a_bss
);
if (k_flags & K_CHMEM) printf("%8ld", a_stack);
printf(" %s\n", hdr.name);
/* Read the data segment. */
if (!get_segment(&vsec, &a_data, &addr, limit)) return;
/* Make space for bss and stack unless... */
if (i != KERNEL && (k_flags & K_CLAIM)) a_bss= a_stack= 0;
/* Note that a_data may be negative now, but we can look at it
* as -a_data bss bytes.
*/
/* Compute the number of bss clicks left. */
a_bss+= a_data;
n= align(a_bss, click_size);
a_bss-= n;
/* Zero out bss. */
if (addr + n > limit) { errno= ENOMEM; return; }
raw_clear(addr, n);
addr+= n;
/* And the number of stack clicks. */
a_stack+= a_bss;
n= align(a_stack, click_size);
a_stack-= n;
/* Add space for the stack. */
addr+= n;
/* Process endpoint. */
procp->end= addr;
if (i == 0 && (k_flags & K_HIGH)) {
/* Load the rest in extended memory. */
addr= 0x100000L;
limit= 0x100000L + get_ext_memsize() * 1024L;
}
}
if ((n_procs= i) == 0) {
printf("There are no programs in %s\n", image);
errno= 0;
return;
}
/* Check the kernel magic number. */
if (get_word(process[KERNEL].data + MAGIC_OFF) != KERNEL_D_MAGIC) {
printf("%s magic number is incorrect\n", process[KERNEL].name);
errno= 0;
return;
}
/* Patch sizes, etc. into kernel data. */
patch_sizes();
/* Wait a while if delay is set, bail out if ESC typed. */
msec= b_value("delay");
if (!delay(msec != nil ? msec : "0")) { errno= 0; return; }
/* Reset the screen setting the proper video mode. This is more
* important than it seems, Minix depends on the mode set right.
*/
mode= strcmp(b_value("chrome"), "color") == 0 ? COLOR_MODE : MONO_MODE;
console= b_value("console");
if (console != nil && a2x(console) != 0) mode= a2x(console);
reset_video(mode);
/* Minix. */
reboot_code= minix(process[KERNEL].entry, process[KERNEL].cs,
process[KERNEL].ds, params, paramsize);
/* Boot file system still around? */
fsok= r_super() != 0;
errno= 0;
}
char *params2params(size_t *size)
/* Repackage the environment settings for the kernel. */
{
char *parms;
size_t i, z;
environment *e;
i= 0;
z= 64;
parms= malloc(z * sizeof(char *));
for (e= env; e != nil; e= e->next) {
char *name= e->name, *value= e->value;
size_t n;
dev_t dev;
if (!(e->flags & E_VAR)) continue;
if (e->flags & E_DEV) {
if ((dev= name2dev(value)) == -1) {
free(parms);
errno= 0;
return nil;
}
value= u2a((u16_t) dev);
}
n= i + strlen(name) + 1 + strlen(value) + 1;
if (n > z) {
z+= n;
parms= realloc(parms, z * sizeof(char));
}
strcpy(parms + i, name);
strcat(parms + i, "=");
strcat(parms + i, value);
i= n;
}
parms[i++]= 0; /* End marked with empty string. */
*size= i;
return parms;
}
ino_t latest_version(char *version, struct stat *stp)
/* Recursively read the current directory, selecting the newest image on
* the way up. (One can't use r_stat while reading a directory.)
*/
{
char name[NAME_MAX + 1];
ino_t ino, newest;
time_t mtime;
if ((ino= r_readdir(name)) == 0) { stp->st_mtime= 0; return 0; }
newest= latest_version(version, stp);
mtime= stp->st_mtime;
r_stat(ino, stp);
if (S_ISREG(stp->st_mode) && stp->st_mtime > mtime) {
newest= ino;
strcpy(version, name);
} else {
stp->st_mtime= mtime;
}
return newest;
}
char *select_image(char *image)
/* Look image up on the filesystem, if it is a file then we're done, but
* if its a directory then we want the newest file in that directory. If
* it doesn't exist at all, then see if it is 'number:number' and get the
* image from that absolute offset off the disk.
*/
{
ino_t image_ino;
struct stat st;
image= strcpy(malloc((strlen(image) + 1 + NAME_MAX + 1)
* sizeof(char)), image);
if (!fsok || (image_ino= r_lookup(ROOT_INO, image)) == 0) {
char *size;
if (numprefix(image, &size) && *size++ == ':'
&& numeric(size)) {
vir2sec= flat_vir2sec;
image_off= a2l(image);
image_size= a2l(size);
strcpy(image, "Minix");
return image;
}
if (!fsok)
printf("No image selected\n");
else
printf("Can't load %s: %s\n", image, unix_err(errno));
goto bail_out;
}
r_stat(image_ino, &st);
if (!S_ISREG(st.st_mode)) {
char *version= image + strlen(image);
char dots[NAME_MAX + 1];
if (!S_ISDIR(st.st_mode)) {
printf("%s: %s\n", image, unix_err(ENOTDIR));
goto bail_out;
}
(void) r_readdir(dots);
(void) r_readdir(dots); /* "." & ".." */
*version++= '/';
*version= 0;
if ((image_ino= latest_version(version, &st)) == 0) {
printf("There are no images in %s/\n", image);
goto bail_out;
}
r_stat(image_ino, &st);
}
vir2sec= file_vir2sec;
image_size= (st.st_size + SECTOR_SIZE - 1) >> SECTOR_SHIFT;
return image;
bail_out:
free(image);
return nil;
}
void bootminix(void)
/* Load Minix and run it. (Given the size of this program it is surprising
* that it ever gets to that.)
*/
{
char *image;
char *minixparams;
size_t paramsize;
/* Translate the bootparameters to what Minix likes best. */
if ((minixparams= params2params(¶msize)) == nil) return;
if ((image= select_image(b_value("image"))) == nil) return;
/* Things are getting serious, kill the cache! */
invalidate_cache();
printf("\nLoading ");
pretty_image(image);
printf(".\n\n");
exec_image(image, minixparams, paramsize);
switch (errno) {
case ENOEXEC:
printf("%s contains a bad program header\n", image);
break;
case ENOMEM:
printf("Not enough memory to load %s\n", image);
break;
case EIO:
printf("Unsuspected EOF on %s\n", image);
case 0:
/* No error or error already reported. */;
}
/* Put all that free memory to use again. */
init_cache();
free(minixparams);
free(image);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -