Ejemplo n.º 1
0
static void
start_kernel(char *kernel, char *bootline, void *ofw, int isfloppy,
	int boothowto)
{
	int fd;
	u_long marks[MARK_MAX] = {0};
	int flags = LOAD_ALL;

	if (isfloppy)
		flags &= ~LOAD_BACKWARDS;

	/*
	 * First, load headers using default allocator and check whether kernel
	 * entry address matches kernel text load address. If yes, this is the
	 * old kernel designed for ofwboot v1.8 and therefore it must be mapped
	 * by PROM. Otherwise, map the kernel with 4MB permanent pages.
	 */
	loadfile_set_allocator(LOADFILE_NOP_ALLOCATOR);
	if ( (fd = loadfile(kernel, marks, LOAD_HDR|COUNT_TEXT)) != -1) {
		if (COMPAT_BOOT(marks) || compatmode) {
			(void)printf("[c] ");
			loadfile_set_allocator(LOADFILE_OFW_ALLOCATOR);
		} else {
			loadfile_set_allocator(LOADFILE_MMU_ALLOCATOR);
		}
		(void)printf("Loading %s: ", kernel);

		if (fdloadfile(fd, marks, flags) != -1) {
			close(fd);
			jump_to_kernel(marks, kernel, bootline, ofw, boothowto);
		}
	}
	(void)printf("Failed to load '%s'.\n", kernel);
}
Ejemplo n.º 2
0
/*
 * Open 'filename', read in program and return the opened file
 * descriptor if ok, or -1 on error.
 * Fill in marks
 */
int
loadfile(const char *fname, u_long *marks, int flags)
{
	int fd, error;

	/* Open the file. */
	if ((fd = open(fname, 0)) < 0) {
		WARN(("open %s", fname ? fname : "<default>"));
		return -1;
	}

	/* Load it; save the value of errno across the close() call */
	if ((error = fdloadfile(fd, marks, flags)) != 0) {
		(void)close(fd);
		errno = error;
		return -1;
	}

	return fd;
}
Ejemplo n.º 3
0
void
main(int argc, char *argv[], char *bootargs_start, char *bootargs_end)
{
	unsigned long marks[MARK_MAX];
	struct brdprop *brdprop;
	char *new_argv[MAX_ARGS];
	char *bname;
	ssize_t len;
	int err, fd, howto, i, n;

	printf("\n>> %s altboot, revision %s\n", bootprog_name, bootprog_rev);

	brdprop = brd_lookup(brdtype);
	printf(">> %s, cpu %u MHz, bus %u MHz, %dMB SDRAM\n", brdprop->verbose,
	    cpuclock / 1000000, busclock / 1000000, bi_mem.memsize >> 20);

	nata = pcilookup(PCI_CLASS_IDE, lata, 2);
	if (nata == 0)
		nata = pcilookup(PCI_CLASS_RAID, lata, 2);
	if (nata == 0)
		nata = pcilookup(PCI_CLASS_MISCSTORAGE, lata, 2);
	if (nata == 0)
		nata = pcilookup(PCI_CLASS_SCSI, lata, 2);
	nnif = pcilookup(PCI_CLASS_ETH, lnif, 2);
	nusb = pcilookup(PCI_CLASS_USB, lusb, 3);

#ifdef DEBUG
	if (nata == 0)
		printf("No IDE/SATA found\n");
	else for (n = 0; n < nata; n++) {
		int b, d, f, bdf, pvd;
		bdf = lata[n].bdf;
		pvd = lata[n].pvd;
		pcidecomposetag(bdf, &b, &d, &f);
		printf("%04x.%04x DSK %02d:%02d:%02d\n",
		    PCI_VENDOR(pvd), PCI_PRODUCT(pvd), b, d, f);
	}
	if (nnif == 0)
		printf("no NET found\n");
	else for (n = 0; n < nnif; n++) {
		int b, d, f, bdf, pvd;
		bdf = lnif[n].bdf;
		pvd = lnif[n].pvd;
		pcidecomposetag(bdf, &b, &d, &f);
		printf("%04x.%04x NET %02d:%02d:%02d\n",
		    PCI_VENDOR(pvd), PCI_PRODUCT(pvd), b, d, f);
	}
	if (nusb == 0)
		printf("no USB found\n");
	else for (n = 0; n < nusb; n++) {
		int b, d, f, bdf, pvd;
		bdf = lusb[0].bdf;
		pvd = lusb[0].pvd;
		pcidecomposetag(bdf, &b, &d, &f);
		printf("%04x.%04x USB %02d:%02d:%02d\n",
		    PCI_VENDOR(pvd), PCI_PRODUCT(pvd), b, d, f);
	}
#endif

	pcisetup();
	pcifixup();

	/*
	 * When argc is too big then it is probably a pointer, which could
	 * indicate that we were launched as a Linux kernel module using
	 * "bootm".
	 */
	if (argc > MAX_ARGS) {
		if (argv != NULL) {
			/*
			 * initrd image was loaded:
			 * check if it contains a valid altboot command line
			 */
			char *p = (char *)argv;

			if (strncmp(p, "altboot:", 8) == 0) {
				*p = 0;
				for (p = p + 8; *p >= ' '; p++);
				argc = parse_cmdline(new_argv, MAX_ARGS,
				    ((char *)argv) + 8, p);
				argv = new_argv;
			} else
				argc = 0;	/* boot default */
		} else {
			/* parse standard Linux bootargs */
			argc = parse_cmdline(new_argv, MAX_ARGS,
			    bootargs_start, bootargs_end);
			argv = new_argv;
		}
	}

	/* look for a PATA drive configuration string under the arguments */
	for (n = 1; n < argc; n++) {
		if (strncmp(argv[n], "ide:", 4) == 0 &&
		    argv[n][4] >= '0' && argv[n][4] <= '2') {
			drive_config = &argv[n][4];
			break;
		}
	}

	/* intialize a disk driver */
	for (i = 0, n = 0; i < nata; i++)
		n += dskdv_init(&lata[i]);
	if (n == 0)
		printf("IDE/SATA device driver was not found\n");

	/* initialize a network interface */
	for (n = 0; n < nnif; n++)
		if (netif_init(&lnif[n]) != 0)
			break;
	if (n >= nnif)
		printf("no NET device driver was found\n");

	/* wait 2s for user to enter interactive mode */
	for (n = 200; n >= 0; n--) {
		if (n % 100 == 0)
			printf("\rHit any key to enter interactive mode: %d",
			    n / 100);
		if (tstchar()) {
#ifdef DEBUG
			unsigned c;

			c = toupper(getchar());
			if (c == 'C') {
				/* controller test terminal */
				sat_test();
				n = 200;
				continue;
			}
			else if (c == 'F') {
				/* find strings in Flash ROM */
				findflash();
				n = 200;
				continue;
			}
#else
			(void)getchar();
#endif
			/* enter command line */
			argv = new_argv;
			argc = input_cmdline(argv, MAX_ARGS);
			break;
		}
		delay(10000);
	}
	putchar('\n');

	howto = RB_AUTOBOOT;		/* default is autoboot = 0 */

	/* get boot options and determine bootname */
	for (n = 1; n < argc; n++) {
		if (strncmp(argv[n], "ide:", 4) == 0)
			continue; /* ignore drive configuration argument */

		for (i = 0; i < sizeof(bootargs) / sizeof(bootargs[0]); i++) {
			if (strncasecmp(argv[n], bootargs[i].name,
			    strlen(bootargs[i].name)) == 0) {
				howto |= bootargs[i].value;
				break;
			}
		}
		if (i >= sizeof(bootargs) / sizeof(bootargs[0]))
			break;	/* break on first unknown string */
	}

	/*
	 * If no device name is given, we construct a list of drives
	 * which have valid disklabels.
	 */
	if (n >= argc) {
		static const size_t blen = sizeof("wdN:");
		n = 0;
		argc = 0;
		argv = alloc(MAX_UNITS * (sizeof(char *) + blen));
		bname = (char *)(argv + MAX_UNITS);
		for (i = 0; i < MAX_UNITS; i++) {
			if (!dlabel_valid(i))
				continue;
			snprintf(bname, blen, "wd%d:", i);
			argv[argc++] = bname;
			bname += blen;
		}
		/* use default drive if no valid disklabel is found */
		if (argc == 0) {
			argc = 1;
			argv[0] = BNAME_DEFAULT;
		}
	}

	/* try to boot off kernel from the drive list */
	while (n < argc) {
		bname = argv[n++];

		if (check_bootname(bname) == 0) {
			printf("%s not a valid bootname\n", bname);
			continue;
		}

		if ((fd = open(bname, 0)) < 0) {
			if (errno == ENOENT)
				printf("\"%s\" not found\n", bi_path.bootpath);
			continue;
		}
		printf("loading \"%s\" ", bi_path.bootpath);
		marks[MARK_START] = 0;

		if (howto == -1) {
			/* load another altboot binary and replace ourselves */
			len = read(fd, (void *)0x100000, 0x1000000 - 0x100000);
			if (len == -1)
				goto loadfail;
			close(fd);
			netif_shutdown_all();

			memcpy((void *)0xf0000, newaltboot,
			    newaltboot_end - newaltboot);
			__syncicache((void *)0xf0000,
			    newaltboot_end - newaltboot);
			printf("Restarting...\n");
			run((void *)1, argv, (void *)0x100000, (void *)len,
			    (void *)0xf0000);
		}

		err = fdloadfile(fd, marks, LOAD_KERNEL);
		close(fd);
		if (err < 0)
			continue;

		printf("entry=%p, ssym=%p, esym=%p\n",
		    (void *)marks[MARK_ENTRY],
		    (void *)marks[MARK_SYM],
		    (void *)marks[MARK_END]);

		bootinfo = (void *)0x4000;
		bi_init(bootinfo);
		bi_add(&bi_cons, BTINFO_CONSOLE, sizeof(bi_cons));
		bi_add(&bi_mem, BTINFO_MEMORY, sizeof(bi_mem));
		bi_add(&bi_clk, BTINFO_CLOCK, sizeof(bi_clk));
		bi_add(&bi_path, BTINFO_BOOTPATH, sizeof(bi_path));
		bi_add(&bi_rdev, BTINFO_ROOTDEVICE, sizeof(bi_rdev));
		bi_add(&bi_fam, BTINFO_PRODFAMILY, sizeof(bi_fam));
		if (brdtype == BRD_SYNOLOGY || brdtype == BRD_DLINKDSM) {
			/* need to pass this MAC address to kernel */
			bi_add(&bi_net, BTINFO_NET, sizeof(bi_net));
		}

		if (modules_enabled) {
			if (fsmod != NULL)
				module_add(fsmod);
			kmodloadp = marks[MARK_END];
			btinfo_modulelist = NULL;
			module_load(bname);
			if (btinfo_modulelist != NULL &&
			    btinfo_modulelist->num > 0)
				bi_add(btinfo_modulelist, BTINFO_MODULELIST,
				    btinfo_modulelist_size);
		}

		launchfixup();
		netif_shutdown_all();

		__syncicache((void *)marks[MARK_ENTRY],
		    (u_int)marks[MARK_SYM] - (u_int)marks[MARK_ENTRY]);

		run((void *)marks[MARK_SYM], (void *)marks[MARK_END],
		    (void *)howto, bootinfo, (void *)marks[MARK_ENTRY]);

		/* should never come here */
		printf("exec returned. Restarting...\n");
		_rtt();
	}
  loadfail:
	printf("load failed. Restarting...\n");
	_rtt();
}
Ejemplo n.º 4
0
static int
loadk(char *file, u_long *marks)
{
    int fd, error, flags;
    vaddr_t va;
    paddr_t pa;
    u_long minsize, size;
    vaddr_t extra;

    /*
     * Regardless of the address where we load the kernel, we need to
     * make sure it has enough valid space to use during pmap_bootstrap.
     * locore.s tries to map the 512KB following the kernel image, and
     * we need to make sure this extra room does not overwrite PROM data
     * (such as the PROM page tables which are immediately below 4MB on
     * most sun4c).
     */
    extra = 512 * 1024;

    if ((fd = open(file, O_RDONLY)) < 0)
        return (errno ? errno : ENOENT);

    /*
     * We need to know whether we are booting off a tape or not,
     * because we can not seek backwards off tapes.
     */

    if (files[fd].f_flags & F_RAW) {
        flags = (COUNT_KERNEL & ~COUNT_SYM) | (LOAD_KERNEL & ~LOAD_SYM);
        minsize = FOURMB;
        va = 0xf8000000;		/* KERNBASE */
#ifdef DEBUG
        printf("Tape boot: expecting a bsd.rd kernel smaller than %p\n",
               minsize);
#endif
        /* compensate for extra room below */
        minsize -= extra;
    } else {
        /*
         * If we did not load a random.seed file yet, try and load
         * one.
         */
        if (rnd_loaded == 0) {
            /*
             * Some PROM do not like having a network device
             * open()ed twice; better close and reopen after
             * trying to get randomness.
             */
            close(fd);

            rnd_loaded = loadrandom(BOOTRANDOM, rnddata,
                                    sizeof(rnddata));

            if ((fd = open(file, O_RDONLY)) < 0)
                return (errno ? errno : ENOENT);
        }

        flags = LOAD_KERNEL;
        marks[MARK_START] = 0;

        /*
         * Even though we just have opened the file, the gzip code
         * has tried to read from it. Be sure to reset position in
         * case the file is not compressed (transparent mode isn't
         * so transparent...)
         */
        if (lseek(fd, 0, SEEK_SET) == (off_t)-1) {
            error = errno;
            goto out;
        }

        if ((error = fdloadfile(fd, marks, COUNT_KERNEL)) != 0)
            goto out;

        /* rewind file for the actual load operation later */
        if (lseek(fd, 0, SEEK_SET) == (off_t)-1) {
            error = errno;
            goto out;
        }

        minsize = marks[MARK_END] - marks[MARK_START];

        /* We want that leading 16K in front of the kernel image */
        minsize += PROM_LOADADDR;
        va = marks[MARK_START] - PROM_LOADADDR;
    }

    /*
     * If the kernel would entirely fit under the boot code, and the
     * boot code has been loaded 1:1, we do not need to allocate
     * breathing room after it.
     */
    size = minsize + extra;
    if (compat != 0) {
        if (minsize + extra <= RELOC2 - LOWSTACK)
            size = RELOC2 - LOWSTACK;
        else
            compat = 0;
    }

    /* Get a physical load address */
#ifdef DEBUG
    printf("kernel footprint %p, requesting %p\n", minsize, size);
#endif
    pa = getphysmem(size);
    if (pa == (paddr_t)-1) {
        /*
         * The extra bootstrap memory estimate might have been
         * too much, if physical memory doesn't have any contiguous
         * large chunks (e.g. on sun4c systems with 4MB regions).
         * If that increase caused us to cross a 4MB boundary, try
         * to limit ourselves to a 4MB multiple.
         */
        if (compat == 0 && size / FOURMB != minsize / FOURMB) {
            size = roundup(minsize, FOURMB);
#ifdef DEBUG
            printf("now trying %p\n", size);
#endif
            pa = getphysmem(size);
        }
        if (pa == (paddr_t)-1) {
            error = EFBIG;
            goto out;
        }
    }

    printf("Loading at physical address %lx\n", pa);
    if (pmap_map(va, pa, size) != 0) {
        error = EFAULT;
        goto out;
    }

    /* try and double-map at VA 0 for compatibility */
    if (pa + size > bstart) {
#ifdef DEBUG
        printf("WARNING: %s is too large for compat mode.\n"
               "If your kernel is too old, it will not run correctly.\n",
               file);
#endif
    } else {
        if (pa != 0 && pmap_map(0, pa, size) != 0) {
            error = EFAULT;
            goto out;
        }
    }

    marks[MARK_START] = 0;
    error = fdloadfile(fd, marks, flags);
out:
    close(fd);
    return (error);
}
Ejemplo n.º 5
0
static int
loadk(char *kernel, u_long *marks)
{
	int fd, error;
	vaddr_t va;
	paddr_t pa;
	u_long size;
	int flags = LOAD_KERNEL;

	if ((fd = open(kernel, 0)) < 0)
		return (errno ? errno : ENOENT);

	marks[MARK_START] = 0;
	if ((error = fdloadfile(fd, marks, COUNT_KERNEL)) != 0)
		goto out;

	size = marks[MARK_END] - marks[MARK_START];

	/* We want that leading 16K in front of the kernel image */
	size += PROM_LOADADDR;
	va = marks[MARK_START] - PROM_LOADADDR;

	/*
	 * Extra space for bootinfo and kernel bootstrap.
	 * In compat mode, we get to re-use the space occupied by the
	 * boot program. Traditionally, we've silently assumed that
	 * is enough for the kernel to work with.
	 */
	size += BOOTINFO_SIZE;
	if (!compatmode)
		size += 512 * 1024;

	/* Get a physical load address */
	pa = getphysmem(size);
	if (pa == (paddr_t)-1) {
		error = EFBIG;
		goto out;
	}

	if (boothowto & AB_VERBOSE)
		printf("Loading at physical address %lx\n", pa);
	if (pmap_map(va, pa, size) != 0) {
		error = EFAULT;
		goto out;
	}

	/* XXX - to do: inspect kernel image and set compat mode */
	if (compatmode) {
		/* Double-map at VA 0 for compatibility */
		if (pa + size >= bstart) {
			printf("%s: too large for compat mode\n", kernel);
			error = EFBIG;
			goto out;
		}

		if (pa != 0 && pmap_map(0, pa, size) != 0) {
			error = EFAULT;
			goto out;
		}
		loadaddrmask = 0x07ffffffUL;
	}

	if (bootdev_isfloppy(prom_bootdevice))
		flags &= ~LOAD_BACKWARDS;

	marks[MARK_START] = 0;
	error = fdloadfile(fd, marks, flags);
out:
	close(fd);
	return (error);
}