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); fsok= r_super(&block_size) != 0; 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_sectors= 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); image_bytes = st.st_size; 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_sectors= (st.st_size + SECTOR_SIZE - 1) >> SECTOR_SHIFT; return image; bail_out: free(image); return nil; }
void exec_image(char *image) /* Get a Minix image into core, patch it up and execute. */ { int i; struct image_header hdr; char *buf; u32_t vsec, addr, limit, aout, n; struct process *procp; /* Process under construction. */ long a_text, a_data, a_bss, a_stack; int banner= 0; long processor= a2l(b_value("processor")); u16_t mode; char *console; char params[SECTOR_SIZE]; extern char *sbrk(int); /* The stack is pretty deep here, so check if heap and stack collide. */ (void) sbrk(0); printf("\nLoading "); pretty_image(image); printf(".\n\n"); vsec= 0; /* Load this sector from image next. */ addr= mem[0].base; /* Into this memory block. */ limit= mem[0].base + mem[0].size; if (limit > caddr) limit= caddr; /* Allocate and clear the area where the headers will be placed. */ aout = (limit -= PROCESS_MAX * A_MINHDR); /* Clear the area where the headers will be placed. */ raw_clear(aout, PROCESS_MAX * A_MINHDR); /* Read the many different processes: */ for (i= 0; vsec < image_size; i++) { if (i == PROCESS_MAX) { printf("There are more then %d programs in %s\n", PROCESS_MAX, image); errno= 0; 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); } /* 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); } /* Save a copy of the header for the kernel, with a_syms * misused as the address where the process is loaded at. */ hdr.process.a_syms= addr; raw_copy(aout + i * A_MINHDR, mon2abs(&hdr.process), A_MINHDR); if (!banner) { printf(" cs ds text data bss"); if (k_flags & K_CHMEM) printf(" stack"); putch('\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. */ 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 %7ld %7ld %7ld", 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= mem[1].base; limit= mem[1].base + mem[1].size; } } 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("Kernel magic number is incorrect\n"); errno= 0; return; } /* Patch sizes, etc. into kernel data. */ patch_sizes(); #if !DOS if (!(k_flags & K_MEML)) { /* Copy the a.out headers to the old place. */ raw_copy(HEADERPOS, aout, PROCESS_MAX * A_MINHDR); } #endif /* Run the trailer function just before starting Minix. */ if (!run_trailer()) { errno= 0; return; } /* Translate the boot parameters to what Minix likes best. */ if (!params2params(params, sizeof(params))) { errno= 0; return; } /* Set the video to the required mode. */ if ((console= b_value("console")) == nil || (mode= a2x(console)) == 0) { mode= strcmp(b_value("chrome"), "color") == 0 ? COLOR_MODE : MONO_MODE; } set_mode(mode); /* Close the disk. */ (void) dev_close(); /* Minix. */ minix(process[KERNEL].entry, process[KERNEL].cs, process[KERNEL].ds, params, sizeof(params), aout); if (!(k_flags & K_BRET)) { extern u32_t reboot_code; raw_copy(mon2abs(params), reboot_code, sizeof(params)); } parse_code(params); /* Return from Minix; boot file system still around? */ (void) dev_open(); fsok= r_super() != 0; errno= 0; }