Ejemplo n.º 1
0
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;
}
Ejemplo n.º 2
0
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;
}