Home | History | Annotate | Line # | Download | only in ofwboot
boot.c revision 1.30.2.1
      1  1.30.2.1   thorpej /*	$NetBSD: boot.c,v 1.30.2.1 2021/04/03 22:28:30 thorpej Exp $	*/
      2       1.1    tsubai 
      3       1.1    tsubai /*-
      4       1.1    tsubai  * Copyright (c) 1997 The NetBSD Foundation, Inc.
      5       1.1    tsubai  * All rights reserved.
      6       1.1    tsubai  *
      7       1.1    tsubai  * This code is derived from software contributed to The NetBSD Foundation
      8       1.1    tsubai  * by Jason R. Thorpe.
      9       1.1    tsubai  *
     10       1.1    tsubai  * Redistribution and use in source and binary forms, with or without
     11       1.1    tsubai  * modification, are permitted provided that the following conditions
     12       1.1    tsubai  * are met:
     13       1.1    tsubai  * 1. Redistributions of source code must retain the above copyright
     14       1.1    tsubai  *    notice, this list of conditions and the following disclaimer.
     15       1.1    tsubai  * 2. Redistributions in binary form must reproduce the above copyright
     16       1.1    tsubai  *    notice, this list of conditions and the following disclaimer in the
     17       1.1    tsubai  *    documentation and/or other materials provided with the distribution.
     18       1.1    tsubai  *
     19       1.1    tsubai  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20       1.1    tsubai  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21       1.1    tsubai  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22       1.1    tsubai  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23       1.1    tsubai  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24       1.1    tsubai  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25       1.1    tsubai  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26       1.1    tsubai  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27       1.1    tsubai  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28       1.1    tsubai  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29       1.1    tsubai  * POSSIBILITY OF SUCH DAMAGE.
     30       1.1    tsubai  */
     31       1.1    tsubai 
     32       1.1    tsubai /*
     33       1.1    tsubai  * Copyright (C) 1995, 1996 Wolfgang Solfrank.
     34       1.1    tsubai  * Copyright (C) 1995, 1996 TooLs GmbH.
     35       1.1    tsubai  * All rights reserved.
     36       1.1    tsubai  *
     37       1.1    tsubai  * ELF support derived from NetBSD/alpha's boot loader, written
     38       1.1    tsubai  * by Christopher G. Demetriou.
     39       1.1    tsubai  *
     40       1.1    tsubai  * Redistribution and use in source and binary forms, with or without
     41       1.1    tsubai  * modification, are permitted provided that the following conditions
     42       1.1    tsubai  * are met:
     43       1.1    tsubai  * 1. Redistributions of source code must retain the above copyright
     44       1.1    tsubai  *    notice, this list of conditions and the following disclaimer.
     45       1.1    tsubai  * 2. Redistributions in binary form must reproduce the above copyright
     46       1.1    tsubai  *    notice, this list of conditions and the following disclaimer in the
     47       1.1    tsubai  *    documentation and/or other materials provided with the distribution.
     48       1.1    tsubai  * 3. All advertising materials mentioning features or use of this software
     49       1.1    tsubai  *    must display the following acknowledgement:
     50       1.1    tsubai  *	This product includes software developed by TooLs GmbH.
     51       1.1    tsubai  * 4. The name of TooLs GmbH may not be used to endorse or promote products
     52       1.1    tsubai  *    derived from this software without specific prior written permission.
     53       1.1    tsubai  *
     54       1.1    tsubai  * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
     55       1.1    tsubai  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     56       1.1    tsubai  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     57       1.1    tsubai  * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     58       1.1    tsubai  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     59       1.1    tsubai  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
     60       1.1    tsubai  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     61       1.1    tsubai  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     62       1.1    tsubai  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
     63       1.1    tsubai  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     64       1.1    tsubai  */
     65       1.1    tsubai 
     66       1.1    tsubai /*
     67       1.1    tsubai  * First try for the boot code
     68       1.1    tsubai  *
     69       1.1    tsubai  * Input syntax is:
     70       1.1    tsubai  *	[promdev[{:|,}partition]]/[filename] [flags]
     71       1.1    tsubai  */
     72       1.1    tsubai 
     73      1.17   aymeric #include "boot.h"
     74      1.17   aymeric 
     75       1.1    tsubai #include <sys/param.h>
     76       1.9  jdolecek #include <sys/boot_flag.h>
     77      1.23   tsutsui #include <sys/disklabel.h>
     78       1.1    tsubai 
     79       1.1    tsubai #include <lib/libsa/stand.h>
     80       1.6    tsubai #include <lib/libsa/loadfile.h>
     81       1.1    tsubai #include <lib/libkern/libkern.h>
     82       1.1    tsubai 
     83       1.1    tsubai #include "ofdev.h"
     84       1.1    tsubai #include "openfirm.h"
     85       1.1    tsubai 
     86      1.20       uwe extern void __syncicache(void *, size_t); /* in libkern */
     87      1.20       uwe 
     88      1.20       uwe 
     89      1.12    tsubai #ifdef DEBUG
     90      1.12    tsubai # define DPRINTF printf
     91      1.12    tsubai #else
     92      1.12    tsubai # define DPRINTF while (0) printf
     93      1.12    tsubai #endif
     94      1.12    tsubai 
     95      1.23   tsutsui char bootdev[MAXBOOTPATHLEN];
     96      1.30     joerg extern char bootfile[MAXBOOTPATHLEN];
     97       1.1    tsubai int boothowto;
     98      1.23   tsutsui bool floppyboot;
     99      1.27   tsutsui int ofw_version = 0;
    100       1.1    tsubai 
    101      1.20       uwe static const char *kernels[] = { "/netbsd", "/netbsd.gz", "/netbsd.macppc", NULL };
    102       1.7    tsubai 
    103       1.1    tsubai static void
    104      1.17   aymeric prom2boot(char *dev)
    105       1.1    tsubai {
    106       1.1    tsubai 	char *cp;
    107      1.14   tsutsui 
    108       1.7    tsubai 	cp = dev + strlen(dev) - 1;
    109       1.7    tsubai 	for (; *cp; cp--) {
    110       1.1    tsubai 		if (*cp == ':') {
    111       1.7    tsubai 			if (ofw_version < 3) {
    112       1.7    tsubai 				/* sd@0:0 -> sd@0 */
    113       1.7    tsubai 				*cp = 0;
    114       1.7    tsubai 				break;
    115       1.7    tsubai 			} else {
    116       1.7    tsubai 				/* disk@0:5,boot -> disk@0:0 */
    117       1.7    tsubai 				strcpy(cp, ":0");
    118       1.7    tsubai 				break;
    119       1.7    tsubai 			}
    120       1.1    tsubai 		}
    121       1.7    tsubai 	}
    122       1.1    tsubai }
    123       1.1    tsubai 
    124       1.1    tsubai static void
    125      1.17   aymeric parseargs(char *str, int *howtop)
    126       1.1    tsubai {
    127       1.1    tsubai 	char *cp;
    128       1.1    tsubai 
    129       1.1    tsubai 	/* Allow user to drop back to the PROM. */
    130       1.1    tsubai 	if (strcmp(str, "exit") == 0)
    131       1.1    tsubai 		OF_exit();
    132       1.1    tsubai 
    133       1.1    tsubai 	*howtop = 0;
    134       1.4    tsubai 
    135       1.4    tsubai 	cp = str;
    136       1.4    tsubai 	if (*cp == '-')
    137       1.4    tsubai 		goto found;
    138       1.1    tsubai 	for (cp = str; *cp; cp++)
    139       1.4    tsubai 		if (*cp == ' ')
    140       1.4    tsubai 			goto found;
    141       1.4    tsubai 	return;
    142       1.4    tsubai 
    143       1.4    tsubai found:
    144       1.1    tsubai 	*cp++ = 0;
    145       1.9  jdolecek 	while (*cp)
    146       1.9  jdolecek 		BOOT_FLAG(*cp++, *howtop);
    147       1.1    tsubai }
    148       1.1    tsubai 
    149      1.23   tsutsui static bool
    150      1.23   tsutsui is_floppyboot(const char *path, const char *defaultdev)
    151      1.23   tsutsui {
    152      1.23   tsutsui 	char dev[MAXBOOTPATHLEN];
    153      1.23   tsutsui 	char nam[16];
    154      1.23   tsutsui 	int handle, rv;
    155      1.23   tsutsui 
    156      1.23   tsutsui 	if (parsefilepath(path, dev, NULL, NULL)) {
    157      1.23   tsutsui 		if (dev[0] == '\0' && defaultdev != NULL)
    158      1.23   tsutsui 			strlcpy(dev, defaultdev, sizeof(dev));
    159      1.23   tsutsui 
    160      1.23   tsutsui 		/* check properties */
    161      1.23   tsutsui 		handle = OF_finddevice(dev);
    162      1.23   tsutsui 		if (handle != -1) {
    163      1.23   tsutsui 			rv = OF_getprop(handle, "name", nam, sizeof(nam));
    164      1.23   tsutsui 			if (rv >= 0 &&
    165      1.23   tsutsui 			    (strcmp(nam, "swim3") == 0 ||
    166      1.23   tsutsui 			     strcmp(nam, "floppy") == 0))
    167      1.23   tsutsui 				return true;
    168      1.23   tsutsui 		}
    169      1.23   tsutsui 
    170      1.23   tsutsui 		/* also check devalias */
    171      1.23   tsutsui 		if (strcmp(dev, "fd") == 0)
    172      1.23   tsutsui 			return true;
    173      1.23   tsutsui 	}
    174      1.23   tsutsui 
    175      1.23   tsutsui 	return false;
    176      1.23   tsutsui }
    177      1.23   tsutsui 
    178       1.1    tsubai static void
    179      1.17   aymeric chain(boot_entry_t entry, char *args, void *ssym, void *esym)
    180       1.1    tsubai {
    181       1.1    tsubai 	extern char end[];
    182      1.10     soren 	int l;
    183       1.1    tsubai 
    184      1.29       uwe #if !defined(HEAP_VARIABLE)
    185      1.21       uwe 	freeall();
    186      1.29       uwe #endif
    187      1.21       uwe 
    188       1.1    tsubai 	/*
    189       1.1    tsubai 	 * Stash pointer to end of symbol table after the argument
    190       1.1    tsubai 	 * strings.
    191       1.1    tsubai 	 */
    192       1.1    tsubai 	l = strlen(args) + 1;
    193      1.11       wiz 	memcpy(args + l, &ssym, sizeof(ssym));
    194       1.6    tsubai 	l += sizeof(ssym);
    195      1.11       wiz 	memcpy(args + l, &esym, sizeof(esym));
    196       1.1    tsubai 	l += sizeof(esym);
    197      1.13    tsubai 	l += sizeof(int);	/* XXX */
    198       1.1    tsubai 
    199      1.17   aymeric 	OF_chain((void *) RELOC, end - (char *) RELOC, entry, args, l);
    200       1.1    tsubai 	panic("chain");
    201       1.1    tsubai }
    202       1.1    tsubai 
    203       1.1    tsubai __dead void
    204      1.17   aymeric _rtt(void)
    205       1.1    tsubai {
    206       1.1    tsubai 
    207       1.1    tsubai 	OF_exit();
    208       1.1    tsubai }
    209       1.1    tsubai 
    210       1.1    tsubai void
    211      1.17   aymeric main(void)
    212       1.1    tsubai {
    213      1.26     joerg 	extern char bootprog_name[], bootprog_rev[];
    214       1.1    tsubai 	char bootline[512];		/* Should check size? */
    215  1.30.2.1   thorpej 	char prop[32];
    216       1.1    tsubai 	char *cp;
    217       1.6    tsubai 	u_long marks[MARK_MAX];
    218       1.6    tsubai 	u_int32_t entry;
    219       1.6    tsubai 	void *ssym, *esym;
    220       1.1    tsubai 
    221       1.1    tsubai 	printf("\n");
    222       1.1    tsubai 	printf(">> %s, Revision %s\n", bootprog_name, bootprog_rev);
    223       1.7    tsubai 
    224       1.7    tsubai 	/*
    225       1.7    tsubai 	 * Figure out what version of Open Firmware...
    226       1.7    tsubai 	 */
    227  1.30.2.1   thorpej 	if (ofw_openprom != -1) {
    228  1.30.2.1   thorpej 		memset(prop, 0, sizeof prop);
    229  1.30.2.1   thorpej 		OF_getprop(ofw_openprom, "model", prop, sizeof prop);
    230  1.30.2.1   thorpej 		for (cp = prop; *cp; cp++)
    231       1.7    tsubai 			if (*cp >= '0' && *cp <= '9') {
    232       1.7    tsubai 				ofw_version = *cp - '0';
    233       1.7    tsubai 				break;
    234       1.7    tsubai 			}
    235  1.30.2.1   thorpej 		printf(">> Open Firmware version %d.x\n", ofw_version);
    236       1.7    tsubai 	}
    237  1.30.2.1   thorpej 	printf(">> Open Firmware running in %s-mode.\n",
    238  1.30.2.1   thorpej 	    ofw_real_mode ? "real" : "virtual");
    239       1.1    tsubai 
    240       1.1    tsubai 	/*
    241       1.1    tsubai 	 * Get the boot arguments from Openfirmware
    242       1.1    tsubai 	 */
    243  1.30.2.1   thorpej 	if (OF_getprop(ofw_chosen, "bootpath", bootdev, sizeof bootdev) < 0 ||
    244  1.30.2.1   thorpej 	    OF_getprop(ofw_chosen, "bootargs", bootline, sizeof bootline) < 0) {
    245       1.1    tsubai 		printf("Invalid Openfirmware environment\n");
    246       1.1    tsubai 		OF_exit();
    247       1.2    tsubai 	}
    248       1.2    tsubai 
    249       1.2    tsubai 	/*
    250       1.2    tsubai 	 * Some versions of Openfirmware sets bootpath to "".
    251       1.2    tsubai 	 * We use boot-device instead if it occurs.
    252       1.2    tsubai 	 */
    253       1.2    tsubai 	if (bootdev[0] == 0) {
    254       1.2    tsubai 		printf("Cannot use bootpath\n");
    255  1.30.2.1   thorpej 		if (ofw_options == -1 ||
    256  1.30.2.1   thorpej 		    OF_getprop(ofw_options, "boot-device", bootdev,
    257       1.2    tsubai 			       sizeof bootdev) < 0) {
    258       1.2    tsubai 			printf("Invalid Openfirmware environment\n");
    259       1.2    tsubai 			OF_exit();
    260       1.2    tsubai 		}
    261       1.2    tsubai 		printf("Using boot-device instead\n");
    262       1.1    tsubai 	}
    263       1.1    tsubai 
    264       1.1    tsubai 	prom2boot(bootdev);
    265       1.1    tsubai 	parseargs(bootline, &boothowto);
    266      1.12    tsubai 	DPRINTF("bootline=%s\n", bootline);
    267       1.1    tsubai 
    268       1.1    tsubai 	for (;;) {
    269      1.23   tsutsui 		int i, loadflag;
    270      1.12    tsubai 
    271       1.1    tsubai 		if (boothowto & RB_ASKNAME) {
    272       1.1    tsubai 			printf("Boot: ");
    273      1.28  dholland 			kgets(bootline, sizeof(bootline));
    274       1.1    tsubai 			parseargs(bootline, &boothowto);
    275       1.1    tsubai 		}
    276      1.12    tsubai 
    277      1.12    tsubai 		if (bootline[0]) {
    278      1.12    tsubai 			kernels[0] = bootline;
    279      1.12    tsubai 			kernels[1] = NULL;
    280      1.12    tsubai 		}
    281      1.12    tsubai 
    282      1.12    tsubai 		for (i = 0; kernels[i]; i++) {
    283      1.23   tsutsui 			floppyboot = is_floppyboot(kernels[i], bootdev);
    284      1.23   tsutsui 
    285      1.23   tsutsui 			DPRINTF("Trying %s%s\n", kernels[i],
    286      1.23   tsutsui 			    floppyboot ? " (floppyboot)" : "");
    287      1.23   tsutsui 
    288      1.23   tsutsui 			loadflag = LOAD_KERNEL;
    289      1.23   tsutsui 			if (floppyboot)
    290      1.25  christos 				loadflag &= ~LOAD_BACKWARDS;
    291      1.12    tsubai 
    292      1.12    tsubai 			marks[MARK_START] = 0;
    293      1.23   tsutsui 			if (loadfile(kernels[i], marks, loadflag) >= 0)
    294      1.12    tsubai 				goto loaded;
    295      1.12    tsubai 		}
    296       1.1    tsubai 		boothowto |= RB_ASKNAME;
    297       1.1    tsubai 	}
    298      1.12    tsubai loaded:
    299      1.12    tsubai 
    300       1.1    tsubai #ifdef	__notyet__
    301  1.30.2.1   thorpej 	OF_setprop(ofw_chosen, "bootpath", opened_name,
    302  1.30.2.1   thorpej 		   strlen(opened_name) + 1);
    303       1.1    tsubai 	cp = bootline;
    304       1.1    tsubai #else
    305       1.1    tsubai 	strcpy(bootline, opened_name);
    306       1.1    tsubai 	cp = bootline + strlen(bootline);
    307       1.1    tsubai 	*cp++ = ' ';
    308       1.1    tsubai #endif
    309       1.1    tsubai 	*cp = '-';
    310       1.1    tsubai 	if (boothowto & RB_ASKNAME)
    311       1.1    tsubai 		*++cp = 'a';
    312      1.18   schmonz 	if (boothowto & RB_USERCONF)
    313      1.18   schmonz 		*++cp = 'c';
    314       1.1    tsubai 	if (boothowto & RB_SINGLE)
    315       1.1    tsubai 		*++cp = 's';
    316       1.1    tsubai 	if (boothowto & RB_KDB)
    317       1.1    tsubai 		*++cp = 'd';
    318       1.1    tsubai 	if (*cp == '-')
    319       1.1    tsubai #ifdef	__notyet__
    320       1.1    tsubai 		*cp = 0;
    321       1.1    tsubai #else
    322       1.1    tsubai 		*--cp = 0;
    323       1.1    tsubai #endif
    324       1.1    tsubai 	else
    325       1.1    tsubai 		*++cp = 0;
    326       1.1    tsubai #ifdef	__notyet__
    327  1.30.2.1   thorpej 	OF_setprop(ofw_chosen, "bootargs", bootline, strlen(bootline) + 1);
    328       1.1    tsubai #endif
    329       1.6    tsubai 
    330       1.6    tsubai 	entry = marks[MARK_ENTRY];
    331       1.6    tsubai 	ssym = (void *)marks[MARK_SYM];
    332       1.6    tsubai 	esym = (void *)marks[MARK_END];
    333      1.14   tsutsui 
    334       1.6    tsubai 	printf(" start=0x%x\n", entry);
    335      1.24       mrg 	__syncicache((void *)(uintptr_t)entry, (size_t)ssym - entry);
    336      1.24       mrg 	chain((boot_entry_t)(uintptr_t)entry, bootline, ssym, esym);
    337       1.1    tsubai 
    338       1.1    tsubai 	OF_exit();
    339       1.1    tsubai }
    340      1.16   tsutsui 
    341      1.16   tsutsui #ifdef HAVE_CHANGEDISK_HOOK
    342      1.16   tsutsui void
    343      1.17   aymeric changedisk_hook(struct open_file *of)
    344      1.16   tsutsui {
    345      1.16   tsutsui 	struct of_dev *op = of->f_devdata;
    346      1.16   tsutsui 	int c;
    347      1.16   tsutsui 
    348  1.30.2.1   thorpej 	OF_call_method("eject", op->handle, 0, 0, NULL);
    349      1.16   tsutsui 
    350      1.16   tsutsui 	c = getchar();
    351      1.16   tsutsui 	if (c == 'q') {
    352      1.16   tsutsui 		printf("quit\n");
    353      1.16   tsutsui 		OF_exit();
    354      1.16   tsutsui 	}
    355      1.16   tsutsui 
    356  1.30.2.1   thorpej 	OF_call_method("close", op->handle, 0, 0, NULL);
    357  1.30.2.1   thorpej 	OF_call_method("open", op->handle, 0, 0, NULL);
    358      1.16   tsutsui }
    359      1.16   tsutsui #endif
    360