2 * Yaboot - secondary boot loader for Linux on PowerPC.
4 * Copyright (C) 2001, 2002 Ethan Benson
6 * Copyright (C) 1999, 2000, 2001 Benjamin Herrenschmidt
10 * Copyright (C) 2001 Peter Bergner
12 * portions based on poof
14 * Copyright (C) 1999 Marius Vollmer
16 * portions based on quik
18 * Copyright (C) 1996 Paul Mackerras.
20 * Because this program is derived from the corresponding file in the
21 * silo-0.64 distribution, it is also
23 * Copyright (C) 1996 Pete A. Zaitcev
25 * 1996 David S. Miller
26 * 1996 Miguel de Icaza
29 * This program is free software; you can redistribute it and/or modify
30 * it under the terms of the GNU General Public License as published by
31 * the Free Software Foundation; either version 2 of the License, or
32 * (at your option) any later version.
34 * This program is distributed in the hope that it will be useful,
35 * but WITHOUT ANY WARRANTY; without even the implied warranty of
36 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
37 * GNU General Public License for more details.
39 * You should have received a copy of the GNU General Public License
40 * along with this program; if not, write to the Free Software
41 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
54 #include "linux/elf.h"
58 #define CONFIG_FILE_NAME "yaboot.conf"
59 #define CONFIG_FILE_MAX 0x8000 /* 32k */
61 #ifdef USE_MD5_PASSWORDS
63 #endif /* USE_MD5_PASSWORDS */
65 /* align addr on a size boundry - adjust address up if needed -- Cort */
66 #define _ALIGN(addr,size) (((addr)+size-1)&(~(size-1)))
68 /* Addresses where the PPC32 and PPC64 vmlinux kernels are linked at.
69 * These are used to determine whether we are booting a vmlinux, in
70 * which case, it will be loaded at KERNELADDR. Otherwise (eg zImage),
71 * we load the binary where it was linked at (ie, e_entry field in
74 #define KERNEL_LINK_ADDR_PPC32 0xC0000000UL
75 #define KERNEL_LINK_ADDR_PPC64 0xC000000000000000ULL
83 unsigned long memsize;
84 unsigned long filesize;
86 unsigned long load_loc;
90 typedef void (*kernel_entry_t)( void *,
96 /* Imported functions */
97 extern unsigned long reloc_offset(void);
98 extern long flush_icache_range(unsigned long start, unsigned long stop);
100 /* Exported functions */
101 int yaboot_start(unsigned long r3, unsigned long r4, unsigned long r5);
103 /* Local functions */
104 static int yaboot_main(void);
105 static int is_elf32(loadinfo_t *loadinfo);
106 static int is_elf64(loadinfo_t *loadinfo);
107 static int load_elf32(struct boot_file_t *file, loadinfo_t *loadinfo);
108 static int load_elf64(struct boot_file_t *file, loadinfo_t *loadinfo);
109 static void setup_display(void);
111 /* Locals & globals */
114 char bootdevice[BOOTDEVSZ];
115 char bootoncelabel[1024];
117 char bootlastlabel[BOOTLASTSZ] = {0};
118 char fw_nbr_reboots[FW_NBR_REBOOTSZ] = {0};
119 long fw_reboot_cnt = 0;
120 char *password = NULL;
121 struct boot_fspec_t boot;
122 int _machine = _MACH_Pmac;
125 #ifdef CONFIG_COLOR_TEXT
127 /* Color values for text ui */
128 static struct ansi_color_t {
132 } ansi_color_table[] = {
140 { "light-gray", 0, 37 },
141 { "dark-gray", 1, 30 },
142 { "light-blue", 1, 31 },
143 { "light-green", 1, 32 },
144 { "light-cyan", 1, 33 },
145 { "light-red", 1, 34 },
146 { "light-purple", 1, 35 },
152 /* Default colors for text ui */
155 #endif /* CONFIG_COLOR_TEXT */
159 static int test_data = 0;
161 static int pause_after;
162 static char *pause_message = "Type go<return> to continue.\n";
163 static char given_bootargs[1024];
164 static int given_bootargs_by_user = 0;
166 extern unsigned char linux_logo_red[];
167 extern unsigned char linux_logo_green[];
168 extern unsigned char linux_logo_blue[];
170 #define DEFAULT_TIMEOUT -1
172 /* Entry, currently called directly by crt0 (bss not inited) */
174 extern char* __bss_start;
177 static struct first_info *quik_fip = NULL;
180 yaboot_start (unsigned long r3, unsigned long r4, unsigned long r5)
183 void* malloc_base = NULL;
187 /* OF seems to do it, but I'm not very confident */
188 memset(&__bss_start, 0, &_end - &__bss_start);
190 /* Check for quik first stage bootloader (but I don't think we are
191 * compatible with it anyway, I'll look into backporting to older OF
194 if (r5 == 0xdeadbeef) {
196 quik_fip = (struct first_info *)r4;
199 /* Initialize OF interface */
200 prom_init ((prom_entry) r5);
202 /* Allocate some memory for malloc'ator */
203 for (addr = MALLOCADDR; addr <= MALLOCADDR * 16 ;addr+=0x100000) {
204 malloc_base = prom_claim((void *)addr, MALLOCSIZE, 0);
205 if (malloc_base != (void *)-1) break;
207 if (malloc_base == (void *)-1) {
208 prom_printf("Can't claim malloc buffer (%d bytes at 0x%08x)\n",
209 MALLOCSIZE, MALLOCADDR);
212 malloc_init(malloc_base, MALLOCSIZE);
213 DEBUG_F("Malloc buffer allocated at %p (%d bytes)\n",
214 malloc_base, MALLOCSIZE);
216 /* A few useless DEBUG_F's */
217 DEBUG_F("reloc_offset : %ld (should be 0)\n", reloc_offset());
218 DEBUG_F("test_bss : %d (should be 0)\n", test_bss);
219 DEBUG_F("test_data : %d (should be 0)\n", test_data);
220 DEBUG_F("&test_data : %p\n", &test_data);
221 DEBUG_F("&test_bss : %p\n", &test_bss);
222 DEBUG_F("linked at : 0x%08x\n", TEXTADDR);
224 /* ask the OF info if we're a chrp or pmac */
225 /* we need to set _machine before calling finish_device_tree */
226 root = prom_finddevice("/");
228 static char model[256];
229 if (prom_getprop(root, "CODEGEN,vendor", model, 256) > 0 &&
230 !strncmp("bplan", model, 5))
231 _machine = _MACH_bplan;
232 else if (prom_getprop(root, "device_type", model, 256 ) > 0 &&
233 !strncmp("chrp", model, 4))
234 _machine = _MACH_chrp;
236 if (prom_getprop(root, "model", model, 256 ) > 0 &&
237 !strncmp(model, "IBM", 3))
238 _machine = _MACH_chrp;
242 DEBUG_F("Running on _machine = %d\n", _machine);
246 result = yaboot_main();
248 /* Get rid of malloc pool */
250 prom_release(malloc_base, MALLOCSIZE);
251 DEBUG_F("Malloc buffer released. Exiting with code %d\n",
261 #ifdef CONFIG_COLOR_TEXT
263 * Validify color for text ui
266 check_color_text_ui(char *color)
269 while(ansi_color_table[i].name) {
270 if (!strcmp(color, ansi_color_table[i].name))
276 #endif /* CONFIG_COLOR_TEXT */
279 void print_message_file(char *filename)
283 char *defdev = boot.dev;
284 int defpart = boot.part;
289 struct boot_file_t file;
290 struct boot_fspec_t msgfile;
292 defdev = cfg_get_strg(0, "device");
295 p = cfg_get_strg(0, "partition");
297 n = simple_strtol(p, &endp, 10);
298 if (endp != p && *endp == 0)
302 strncpy(msgpath, filename, sizeof(msgpath));
303 if (!parse_device_path(msgpath, defdev, defpart, "/etc/yaboot.msg", &msgfile)) {
304 prom_printf("%s: Unable to parse\n", msgpath);
308 result = open_file(&msgfile, &file);
309 if (result != FILE_ERR_OK) {
310 prom_printf("%s:%d,", msgfile.dev, msgfile.part);
311 prom_perror(result, msgfile.file);
320 memset(msg, 0, 2001);
322 if (file.fs->read(&file, 2000, msg) <= 0)
325 prom_printf("%s", msg);
329 file.fs->close(&file);
334 /* Currently, the config file must be at the root of the filesystem.
335 * todo: recognize the full path to myself and use it to load the
336 * config file. Handle the "\\" (blessed system folder)
339 load_config_file(struct boot_fspec_t *fspec)
341 char *conf_file = NULL, *p;
342 struct boot_file_t file;
343 int sz, opened = 0, result = 0;
345 /* Allocate a buffer for the config file */
346 conf_file = malloc(CONFIG_FILE_MAX);
348 prom_printf("Can't alloc config file buffer\n");
353 result = open_file(fspec, &file);
354 if (result != FILE_ERR_OK) {
355 prom_printf("%s:%d,", fspec->dev, fspec->part);
356 prom_perror(result, fspec->file);
357 prom_printf("Can't open config file\n");
363 sz = file.fs->read(&file, CONFIG_FILE_MAX, conf_file);
365 prom_printf("Error, can't read config file\n");
368 prom_printf("Config file read, %d bytes\n", sz);
372 file.fs->close(&file);
375 /* Call the parsing code in cfg.c */
376 if (cfg_parse(fspec->file, conf_file, sz) < 0) {
377 prom_printf ("Syntax error or read error config\n");
382 * set the default cf_option to label that has the same MAC addr
383 * it only works if there is a label with the MAC addr on yaboot.conf
385 if (prom_get_devtype(fspec->dev) == FILE_DEVICE_NET) {
386 /* change the variable bellow to get the MAC dinamicaly */
387 char * macaddr = NULL;
390 macaddr = prom_get_mac(prom_get_netinfo());
391 default_mac = cfg_set_default_by_mac(macaddr);
392 if (default_mac >= 1) {
393 prom_printf("Default label was changed to macaddr label.\n");
397 DEBUG_F("Config file successfully parsed, %d bytes\n", sz);
399 /* Now, we do the initialisations stored in the config file */
400 p = cfg_get_strg(0, "init-code");
404 password = cfg_get_strg(0, "password");
406 #ifdef CONFIG_COLOR_TEXT
407 p = cfg_get_strg(0, "fgcolor");
409 DEBUG_F("fgcolor=%s\n", p);
410 fgcolor = check_color_text_ui(p);
412 prom_printf("Invalid fgcolor: \"%s\".\n", p);
415 p = cfg_get_strg(0, "bgcolor");
417 DEBUG_F("bgcolor=%s\n", p);
418 bgcolor = check_color_text_ui(p);
420 prom_printf("Invalid bgcolor: \"%s\".\n", p);
424 sprintf(temp, "%x to background-color", bgcolor);
425 prom_interpret(temp);
432 sprintf(temp, "%x to foreground-color", fgcolor);
433 prom_interpret(temp);
435 #endif /* CONFIG_COLOR_TEXT */
437 p = cfg_get_strg(0, "init-message");
439 prom_printf("%s\n", p);
441 p = cfg_get_strg(0, "message");
443 print_message_file(p);
450 file.fs->close(&file);
459 * Search for config file by MAC address, then by IP address.
460 * Basically copying pxelinux's algorithm.
461 * http://syslinux.zytor.com/pxe.php#config
463 static int load_my_config_file(struct boot_fspec_t *orig_fspec)
465 struct bootp_packet *packet;
467 struct boot_fspec_t fspec = *orig_fspec;
468 char *cfgpath = (_machine == _MACH_chrp || _machine == _MACH_bplan) ? "/etc/" : "";
472 packet = prom_get_netinfo();
475 * First, try to match on mac address with the hardware type
479 /* 3 chars per byte in chaddr + 2 chars for htype + /etc/ +\0 */
480 fspec.file = malloc(packet->hlen * 3 + 2 + 6);
484 sprintf(fspec.file, "%s%02x-", cfgpath, packet->htype);
485 strcat(fspec.file, prom_get_mac(packet));
487 rc = load_config_file(&fspec);
492 * Now try to match on IP.
494 /* no need to realloc for /etc/ + 8 chars in yiaddr + \0 */
495 sprintf(fspec.file, "%s%s", cfgpath, prom_get_ip(packet));
497 for (flen = strlen(fspec.file),
498 minlen = strlen(cfgpath); flen > minlen; flen--) {
499 rc = load_config_file(&fspec);
502 /* Chop one digit off the end, try again */
503 fspec.file[flen - 1] = '\0';
507 if (rc) /* modify original only on success */
508 orig_fspec->file = fspec.file;
514 void maintabfunc (void)
518 prom_printf("boot: %s", cbuff);
523 word_split(char **linep, char **paramsp)
538 while (*p != 0 && *p != ' ')
547 make_params(char *label, char *params)
550 static char buffer[2048];
555 p = cfg_get_strg(label, "literal");
567 p = cfg_get_strg(label, "root");
574 if (cfg_get_flag(label, "read-only")) {
578 if (cfg_get_flag(label, "read-write")) {
582 p = cfg_get_strg(label, "ramdisk");
584 strcpy (q, "ramdisk=");
589 p = cfg_get_strg(label, "initrd-size");
591 strcpy (q, "ramdisk_size=");
596 if (cfg_get_flag(label, "novideo")) {
597 strcpy (q, "video=ofonly");
601 p = cfg_get_strg (label, "append");
608 pause_after = cfg_get_flag (label, "pause-after");
609 p = cfg_get_strg(label, "pause-message");
618 void check_password(char *str)
622 prom_printf("\n%s", str);
623 for (i = 0; i < 3; i++) {
624 prom_printf ("\nPassword: ");
626 cmdedit ((void (*)(void)) 0, 1);
628 #ifdef USE_MD5_PASSWORDS
629 if (!strncmp (password, "$1$", 3)) {
630 if (!check_md5_password(passwdbuff, password))
633 else if (!strcmp (password, passwdbuff))
636 if (!strcmp (password, passwdbuff))
638 #endif /* USE_MD5_PASSWORDS */
641 prom_printf ("Incorrect password. Try again.");
644 prom_printf(" ___________________\n< Permission denied >\n -------------------\n"
645 " \\ ^__^\n \\ (oo)\\_______\n (__)\\ )\\/\\\n"
646 " ||----w |\n || ||\n");
648 prom_interpret("reset-all");
651 int get_params(struct boot_param_t* params)
655 char defdevice_bak[1024];
658 char *imagename = 0, *label;
663 static int first = 1;
664 static char imagepath[1024];
665 static char initrdpath[1024];
666 static char sysmappath[1024];
667 static char manualinitrd[1024];
668 static int definitrd = 1, hasarg = 0;
671 memset(params, 0, sizeof(*params));
673 params->kernel.part = -1;
674 params->rd.part = -1;
675 params->sysmap.part = -1;
680 if (first && !fw_reboot_cnt) {
682 imagename = bootargs;
683 word_split(&imagename, ¶ms->args);
684 timeout = DEFAULT_TIMEOUT;
686 prom_printf("Default supplied on the command line: %s ", imagename);
688 prom_printf("%s", params->args);
691 if (useconf && (q = cfg_get_strg(0, "timeout")) != 0 && *q != 0)
692 timeout = simple_strtol(q, NULL, 0);
695 /* If this is a reboot due to FW detecting CAS changes then
696 * set timeout to 1. The last kernel booted will be booted
697 * again automatically. It should seem seamless to the user
702 prom_printf("boot: ");
707 end = beg + 100 * timeout;
709 c = prom_nbgetchar();
710 } while (c == -1 && prom_getms() <= end);
714 else if (c != '\n' && c != '\t' && c != '\r' && c != '\b' ) {
720 if (c != -1 && c != '\n' && c != '\r') {
723 } else if (c >= ' ') {
726 if ((cfg_get_flag (cbuff, "single-key")) && useconf) {
729 prom_printf("%s\n", cbuff);
734 if (c == '\n' || c == '\r') {
736 if (bootoncelabel[0] != 0)
737 imagename = bootoncelabel;
738 else if (bootlastlabel[0] != 0)
739 imagename = bootlastlabel;
741 imagename = cfg_get_default();
744 prom_printf("%s", imagename);
746 prom_printf(" %s", params->args);
748 } else if (!singlekey) {
749 cmdedit(maintabfunc, 0);
751 strcpy(given_bootargs, cbuff);
752 given_bootargs_by_user = 1;
754 word_split(&imagename, ¶ms->args);
757 /* initrd setup via cmd console */
758 /* first, check if the user uses it with some label */
759 if (!strncmp(params->args, "initrd=", 7)) {
760 DEBUG_F("params->args: %s\n", params->args);
763 /* after, check if there is the 'initrd=' in the imagename string */
764 if (!strncmp(imagename, "initrd=", 7) || !definitrd) {
766 /* return the value of definitrd to 1 */
770 /* args = "initrd=blah" */
781 /* copy the string after the '=' to manualinitrd */
782 strcpy(manualinitrd, args+7);
784 prom_printf("New initrd file specified: %s\n", manualinitrd);
786 prom_printf("ERROR: no initrd specified!\n");
790 /* set imagename with the default values of the config file */
791 if ((prom_get_devtype(boot.dev) == FILE_DEVICE_NET) && !hasarg)
792 imagename = cfg_get_default();
794 imagename = cfg_get_default();
797 /* chrp gets this wrong, force it -- Cort */
798 if ( useconf && (!imagename || imagename[0] == 0 ))
799 imagename = cfg_get_default();
801 /* write the imagename out so it can be reused on reboot if necessary */
802 prom_set_options("boot-last-label", imagename, strlen(imagename));
805 defdevice = boot.dev;
807 strcpy(defdevice_bak,defdevice);
810 defdevice = cfg_get_strg(0, "device");
811 p = cfg_get_strg(0, "partition");
813 n = simple_strtol(p, &endp, 10);
814 if (endp != p && *endp == 0)
817 p = cfg_get_strg(0, "pause-message");
820 if (cfg_get_flag(0, "restricted"))
822 p = cfg_get_strg(imagename, "image");
826 defdevice = cfg_get_strg(label, "device");
827 if(!defdevice) defdevice=boot.dev;
828 p = cfg_get_strg(label, "partition");
830 n = simple_strtol(p, &endp, 10);
831 if (endp != p && *endp == 0)
834 if (cfg_get_flag(label, "restricted"))
837 if (params->args && password && restricted)
838 check_password ("To specify arguments for this image "
839 "you must enter the password.");
840 else if (password && !restricted)
841 check_password ("This image is restricted.");
843 params->args = make_params(label, params->args);
847 if (!strcmp (imagename, "help")) {
848 /* FIXME: defdevice shouldn't need to be reset all over the place */
849 if(!defdevice) defdevice = boot.dev;
851 "\nPress the tab key for a list of defined images.\n"
852 "The label marked with a \"*\" is is the default image, "
853 "press <return> to boot it.\n\n"
854 "To boot any other label simply type its name and press <return>.\n\n"
855 "To boot a kernel image which is not defined in the yaboot configuration \n"
856 "file, enter the kernel image name as [[device:][partno],]/path, where \n"
857 "\"device:\" is the OpenFirmware device path to the disk the image \n"
858 "resides on, and \"partno\" is the partition number the image resides on.\n"
859 "Note that the comma (,) is only required if you specify an OpenFirmware\n"
860 "device, if you only specify a filename you should not start it with a \",\"\n\n"
861 "To boot a alternative initrd file rather than specified in the yaboot\n"
862 "configuration file, use the \"initrd\" command on Yaboot's prompt: \n"
863 "\"initrd=[name.img]\". This will load the \"name.img\" file after the default\n"
864 "kernel image. You can, also, specify a different initrd file to any other\n"
865 "label of the yaboot configuration file. Just type \"label initrd=[name.img]\"\n"
866 "and the specified initrd file will be loaded.\n\n"
867 "To load an alternative config file rather than /etc/yaboot.conf, enter\n"
868 "its device, partno and path, on Open Firmware Prompt:\n"
869 "boot conf=device:partno,/path/to/configfile\n."
870 "To reload the config file or load a new one, use the \"conf\" command\n"
871 "on Yaboot's prompt:\n"
872 "conf [device=device] [partition=partno] [file=/path/to/configfile]\n\n"
873 "If you omit \"device\" and \"partno\", Yaboot will use their current\n"
874 "values. You can check them by entering \"conf\" on Yaboot's prompt.\n");
879 if (!strcmp (imagename, "halt")) {
881 check_password ("Restricted command.");
885 if (!strcmp (imagename, "bye")) {
887 check_password ("Restricted command.");
893 if (!strncmp (imagename, "conf", 4)) {
895 // imagename = "conf file=blah dev=bleh part=blih"
896 DEBUG_F("Loading user-specified config file: %s\n",imagename);
898 check_password ("Restricted command.");
902 // args= "file=blah dev=bleh part=blih"
903 char *args = params->args;
907 // set a pointer to the first space in args
908 char *space = strchr(args,' ');
912 char temp[1024] = "0";
914 // copy next argument to temp
915 strncpy(temp, args, space-args);
917 // parse temp and set boot arguments
918 if (!strncmp (temp, "file=", 5)){
919 DEBUG_F("conf file: %s\n", temp+5);
920 strcpy(boot.file, temp+5);
921 } else if (!strncmp (temp, "device=", 7)){
922 DEBUG_F("conf device: %s\n", temp+7);
923 strcpy(boot.dev, temp+7);
924 } else if (!strncmp (temp, "partition=", 10)){
925 DEBUG_F("conf partition: %s\n", temp+10);
926 boot.part=simple_strtol(temp+10,NULL,10);
930 // set the pointer to the next space in args;
931 // set the loop control variable
932 if (strlen(space)>1){
933 // Go to the next argument
937 if (strchr(args,' ') == NULL)
938 space = &args[strlen(args)];
940 space = strchr(args,' ');
947 prom_printf("Loading config file...\n");
948 useconf = load_config_file(&boot);
950 if ((q = cfg_get_strg(0, "timeout")) != 0 && *q != 0)
951 timeout = simple_strtol(q, NULL, 0);
953 prom_printf("Restoring default values.\n");
954 strcpy(boot.file,"");
955 strcpy(boot.dev, defdevice_bak);
960 prom_printf("Current configuration:\n");
961 prom_printf("device: %s\n", boot.dev);
963 prom_printf("partition: auto\n");
965 prom_printf("partition: %d\n", boot.part);
966 if (strlen(boot.file))
967 prom_printf("file: %s\n", boot.file);
969 prom_printf("file: /etc/%s\n",CONFIG_FILE_NAME);
978 if (imagename[0] == '$') {
979 /* forth command string */
981 check_password ("OpenFirmware commands are restricted.");
982 prom_interpret(imagename+1);
986 strncpy(imagepath, imagename, 1024);
988 if (!label && password)
989 check_password ("To boot a custom image you must enter the password.");
991 if (!parse_device_path(imagepath, defdevice, defpart,
992 "/vmlinux", ¶ms->kernel)) {
993 prom_printf("%s: Unable to parse\n", imagepath);
996 DEBUG_F("after parse_device_path: dev=%s part=%d file=%s\n", params->kernel.dev, params->kernel.part, params->kernel.file);
998 p = cfg_get_strg(label, "initrd");
1001 /* check if user seted to use a initrd file from boot console */
1002 if (!definitrd && p != manualinitrd) {
1003 if (manualinitrd[0] != "/" && (prom_get_devtype(defdevice_bak) != FILE_DEVICE_NET)) {
1004 strcpy(initrdpath, "/");
1005 strcat(initrdpath, manualinitrd);
1007 strncpy(initrdpath, manualinitrd, 1024);
1009 strncpy(initrdpath, p, 1024);
1011 DEBUG_F("Parsing initrd path <%s>\n", initrdpath);
1012 if (!parse_device_path(initrdpath, defdevice, defpart,
1013 "/root.bin", ¶ms->rd)) {
1014 prom_printf("%s: Unable to parse\n", imagepath);
1018 p = cfg_get_strg(label, "sysmap");
1020 DEBUG_F("Parsing sysmap path <%s>\n", p);
1021 strncpy(sysmappath, p, 1024);
1022 if (!parse_device_path(sysmappath, defdevice, defpart,
1023 "/boot/System.map", ¶ms->sysmap)) {
1024 prom_printf("%s: Unable to parse\n", imagepath);
1032 /* This is derived from quik core. To be changed to first parse the headers
1033 * doing lazy-loading, and then claim the memory before loading the kernel
1035 * We also need to add initrd support to this whole mecanism
1038 yaboot_text_ui(void)
1040 #define MAX_HEADERS 32
1042 struct boot_file_t file;
1044 static struct boot_param_t params;
1046 unsigned long initrd_size;
1048 unsigned long sysmap_size;
1049 kernel_entry_t kernel_entry;
1050 struct bi_record* birec;
1052 loadinfo_t loadinfo;
1053 void *initrd_more,*initrd_want;
1054 unsigned long initrd_read;
1056 loadinfo.load_loc = 0;
1064 if (get_params(¶ms))
1066 if (!params.kernel.file)
1069 prom_printf("Please wait, loading kernel...\n");
1071 memset(&file, 0, sizeof(file));
1073 if (strlen(boot.file) && !strcmp(boot.file,"\\\\") && params.kernel.file[0] != '/'
1074 && params.kernel.file[0] != '\\') {
1075 loc=(char*)malloc(strlen(params.kernel.file)+3);
1077 prom_printf ("malloc error\n");
1080 strcpy(loc,boot.file);
1081 strcat(loc,params.kernel.file);
1082 free(params.kernel.file);
1083 params.kernel.file=loc;
1085 result = open_file(¶ms.kernel, &file);
1086 if (result != FILE_ERR_OK) {
1087 prom_printf("%s:%d,", params.kernel.dev, params.kernel.part);
1088 prom_perror(result, params.kernel.file);
1092 /* Read the Elf e_ident, e_type and e_machine fields to
1093 * determine Elf file type
1095 if (file.fs->read(&file, sizeof(Elf_Ident), &loadinfo.elf) < sizeof(Elf_Ident)) {
1096 prom_printf("\nCan't read Elf e_ident/e_type/e_machine info\n");
1097 file.fs->close(&file);
1098 memset(&file, 0, sizeof(file));
1102 if (is_elf32(&loadinfo)) {
1103 if (!load_elf32(&file, &loadinfo)) {
1104 file.fs->close(&file);
1105 memset(&file, 0, sizeof(file));
1108 prom_printf(" Elf32 kernel loaded...\n");
1109 } else if (is_elf64(&loadinfo)) {
1110 if (!load_elf64(&file, &loadinfo)) {
1111 file.fs->close(&file);
1112 memset(&file, 0, sizeof(file));
1115 prom_printf(" Elf64 kernel loaded...\n");
1117 prom_printf ("%s: Not a valid ELF image\n", params.kernel.file);
1118 file.fs->close(&file);
1119 memset(&file, 0, sizeof(file));
1122 file.fs->close(&file);
1123 memset(&file, 0, sizeof(file));
1125 /* If sysmap, load it (only if booting a vmlinux).
1127 if (flat_vmlinux && params.sysmap.file) {
1128 prom_printf("Loading System.map ...\n");
1129 if(strlen(boot.file) && !strcmp(boot.file,"\\\\") && params.sysmap.file[0] != '/'
1130 && params.sysmap.file[0] != '\\') {
1132 loc=(char*)malloc(strlen(params.sysmap.file)+3);
1134 prom_printf ("malloc error\n");
1137 strcpy(loc,boot.file);
1138 strcat(loc,params.sysmap.file);
1139 free(params.sysmap.file);
1140 params.sysmap.file=loc;
1143 result = open_file(¶ms.sysmap, &file);
1144 if (result != FILE_ERR_OK) {
1145 prom_printf("%s:%d,", params.sysmap.dev, params.sysmap.part);
1146 prom_perror(result, params.sysmap.file);
1149 sysmap_base = prom_claim(loadinfo.base+loadinfo.memsize, 0x100000, 0);
1150 if (sysmap_base == (void *)-1) {
1151 prom_printf("Claim failed for sysmap memory\n");
1155 sysmap_size = file.fs->read(&file, 0xfffff, sysmap_base);
1156 if (sysmap_size == 0)
1159 ((char *)sysmap_base)[sysmap_size++] = 0;
1161 file.fs->close(&file);
1162 memset(&file, 0, sizeof(file));
1165 prom_printf("System.map loaded at %p, size: %lu Kbytes\n",
1166 sysmap_base, sysmap_size >> 10);
1167 loadinfo.memsize += _ALIGN(0x100000, 0x1000);
1169 prom_printf("System.map load failed !\n");
1174 /* If ramdisk, load it (only if booting a vmlinux). For now, we
1175 * can't tell the size it will be so we claim an arbitrary amount
1178 if (flat_vmlinux && params.rd.file) {
1179 if(strlen(boot.file) && !strcmp(boot.file,"\\\\") && params.rd.file[0] != '/'
1180 && params.kernel.file[0] != '\\')
1183 loc=(char*)malloc(strlen(params.rd.file)+3);
1185 prom_printf ("Malloc error\n");
1188 strcpy(loc,boot.file);
1189 strcat(loc,params.rd.file);
1190 free(params.rd.file);
1193 prom_printf("Loading ramdisk...\n");
1194 result = open_file(¶ms.rd, &file);
1195 if (result != FILE_ERR_OK) {
1196 prom_printf("%s:%d,", params.rd.dev, params.rd.part);
1197 prom_perror(result, params.rd.file);
1200 #define INITRD_CHUNKSIZE 0x100000
1201 initrd_base = prom_claim(loadinfo.base+loadinfo.memsize, INITRD_CHUNKSIZE, 0);
1202 if (initrd_base == (void *)-1) {
1203 prom_printf("Claim failed for initrd memory\n");
1206 initrd_size = file.fs->read(&file, INITRD_CHUNKSIZE, initrd_base);
1207 if (initrd_size == 0)
1209 initrd_read = initrd_size;
1210 initrd_more = initrd_base;
1211 while (initrd_read == INITRD_CHUNKSIZE ) { /* need to read more? */
1212 initrd_want = (void *)((unsigned long)initrd_more+INITRD_CHUNKSIZE);
1213 initrd_more = prom_claim(initrd_want, INITRD_CHUNKSIZE, 0);
1214 if (initrd_more != initrd_want) {
1215 prom_printf("Claim failed for initrd memory at %p rc=%p\n",initrd_want,initrd_more);
1219 initrd_read = file.fs->read(&file, INITRD_CHUNKSIZE, initrd_more);
1220 DEBUG_F(" block at %p rc=%lu\n",initrd_more,initrd_read);
1221 initrd_size += initrd_read;
1224 file.fs->close(&file);
1225 memset(&file, 0, sizeof(file));
1228 prom_printf("ramdisk loaded at %p, size: %lu Kbytes\n",
1229 initrd_base, initrd_size >> 10);
1231 prom_printf("ramdisk load failed !\n");
1236 DEBUG_F("setting kernel args to: %s\n", params.args);
1237 prom_setargs(params.args);
1238 DEBUG_F("flushing icache...");
1239 flush_icache_range ((long)loadinfo.base, (long)loadinfo.base+loadinfo.memsize);
1244 * Fill new boot infos (only if booting a vmlinux).
1246 * The birec is low on memory, probably inside the malloc pool,
1247 * so we don't write it earlier. At this point, we should not
1248 * use anything coming from the malloc pool.
1250 birec = (struct bi_record *)_ALIGN(loadinfo.filesize+(1<<20)-1,(1<<20));
1252 /* We make sure it's mapped. We map only 64k for now, it's
1253 * plenty enough we don't claim since this precise memory
1254 * range may already be claimed by the malloc pool.
1256 prom_map (birec, birec, 0x10000);
1257 DEBUG_F("birec at %p\n", birec);
1260 birec->tag = BI_FIRST;
1261 birec->size = sizeof(struct bi_record);
1262 birec = (struct bi_record *)((ulong)birec + birec->size);
1264 birec->tag = BI_BOOTLOADER_ID;
1265 sprintf( (char *)birec->data, "yaboot");
1266 birec->size = sizeof(struct bi_record) + strlen("yaboot") + 1;
1267 birec = (struct bi_record *)((ulong)birec + birec->size);
1269 birec->tag = BI_MACHTYPE;
1270 birec->data[0] = _machine;
1271 birec->size = sizeof(struct bi_record) + sizeof(ulong);
1272 birec = (struct bi_record *)((ulong)birec + birec->size);
1275 birec->tag = BI_SYSMAP;
1276 birec->data[0] = (ulong)sysmap_base;
1277 birec->data[1] = sysmap_size;
1278 birec->size = sizeof(struct bi_record) + sizeof(ulong)*2;
1279 birec = (struct bi_record *)((ulong)birec + birec->size);
1281 birec->tag = BI_LAST;
1282 birec->size = sizeof(struct bi_record);
1283 birec = (struct bi_record *)((ulong)birec + birec->size);
1286 /* compute the kernel's entry point. */
1287 kernel_entry = loadinfo.base + loadinfo.entry - loadinfo.load_loc;
1289 DEBUG_F("Kernel entry point = %p\n", kernel_entry);
1290 DEBUG_F("kernel: arg1 = %p,\n"
1291 " arg2 = 0x%08lx,\n"
1295 initrd_base + loadinfo.load_loc, initrd_size, prom, 0, 0);
1297 DEBUG_F("Entering kernel...\n");
1299 /* call the kernel with our stack. */
1300 kernel_entry(initrd_base + loadinfo.load_loc, initrd_size, prom, 0, 0);
1308 load_elf32(struct boot_file_t *file, loadinfo_t *loadinfo)
1311 Elf32_Ehdr *e = &(loadinfo->elf.elf32hdr);
1313 int size = sizeof(Elf32_Ehdr) - sizeof(Elf_Ident);
1314 unsigned long loadaddr;
1316 /* Read the rest of the Elf header... */
1317 if ((*(file->fs->read))(file, size, &e->e_version) < size) {
1318 prom_printf("\nCan't read Elf32 image header\n");
1322 DEBUG_F("Elf32 header:\n");
1323 DEBUG_F(" e.e_type = %d\n", (int)e->e_type);
1324 DEBUG_F(" e.e_machine = %d\n", (int)e->e_machine);
1325 DEBUG_F(" e.e_version = %d\n", (int)e->e_version);
1326 DEBUG_F(" e.e_entry = 0x%08x\n", (int)e->e_entry);
1327 DEBUG_F(" e.e_phoff = 0x%08x\n", (int)e->e_phoff);
1328 DEBUG_F(" e.e_shoff = 0x%08x\n", (int)e->e_shoff);
1329 DEBUG_F(" e.e_flags = %d\n", (int)e->e_flags);
1330 DEBUG_F(" e.e_ehsize = 0x%08x\n", (int)e->e_ehsize);
1331 DEBUG_F(" e.e_phentsize = 0x%08x\n", (int)e->e_phentsize);
1332 DEBUG_F(" e.e_phnum = %d\n", (int)e->e_phnum);
1334 loadinfo->entry = e->e_entry;
1336 if (e->e_phnum > MAX_HEADERS) {
1337 prom_printf ("Can only load kernels with one program header\n");
1341 ph = (Elf32_Phdr *)malloc(sizeof(Elf32_Phdr) * e->e_phnum);
1343 prom_printf ("Malloc error\n");
1347 /* Now, we read the section header */
1348 if ((*(file->fs->seek))(file, e->e_phoff) != FILE_ERR_OK) {
1349 prom_printf ("seek error\n");
1352 if ((*(file->fs->read))(file, sizeof(Elf32_Phdr) * e->e_phnum, ph) !=
1353 sizeof(Elf32_Phdr) * e->e_phnum) {
1354 prom_printf ("read error\n");
1358 /* Scan through the program header
1359 * HACK: We must return the _memory size of the kernel image, not the
1360 * file size (because we have to leave room before other boot
1361 * infos. This code works as a side effect of the fact that
1362 * we have one section and vaddr == p_paddr
1364 loadinfo->memsize = loadinfo->filesize = loadinfo->offset = 0;
1366 for (i = 0; i < e->e_phnum; ++i, ++p) {
1367 if (p->p_type != PT_LOAD || p->p_offset == 0)
1369 if (loadinfo->memsize == 0) {
1370 loadinfo->offset = p->p_offset;
1371 loadinfo->memsize = p->p_memsz;
1372 loadinfo->filesize = p->p_filesz;
1373 loadinfo->load_loc = p->p_vaddr;
1375 loadinfo->memsize = p->p_offset + p->p_memsz - loadinfo->offset; /* XXX Bogus */
1376 loadinfo->filesize = p->p_offset + p->p_filesz - loadinfo->offset;
1380 if (loadinfo->memsize == 0) {
1381 prom_printf("Can't find a loadable segment !\n");
1385 /* leave some room (1Mb) for boot infos */
1386 loadinfo->memsize = _ALIGN(loadinfo->memsize,(1<<20)) + 0x100000;
1387 /* Claim OF memory */
1388 DEBUG_F("Before prom_claim, mem_sz: 0x%08lx\n", loadinfo->memsize);
1390 /* Determine whether we are trying to boot a vmlinux or some
1391 * other binary image (eg, zImage). We load vmlinux's at
1392 * KERNELADDR and all other binaries at their e_entry value.
1394 if (e->e_entry == KERNEL_LINK_ADDR_PPC32) {
1396 loadaddr = KERNELADDR;
1399 loadaddr = loadinfo->load_loc;
1402 loadinfo->base = prom_claim_chunk((void *)loadaddr, loadinfo->memsize, 0);
1403 if (loadinfo->base == (void *)-1) {
1404 prom_printf("Claim error, can't allocate kernel memory\n");
1408 DEBUG_F("After ELF parsing, load base: %p, mem_sz: 0x%08lx\n",
1409 loadinfo->base, loadinfo->memsize);
1410 DEBUG_F(" wanted load base: 0x%08lx, mem_sz: 0x%08lx\n",
1411 loadaddr, loadinfo->memsize);
1413 /* Load the program segments... */
1415 for (i = 0; i < e->e_phnum; ++i, ++p) {
1416 unsigned long offset;
1417 if (p->p_type != PT_LOAD || p->p_offset == 0)
1420 /* Now, we skip to the image itself */
1421 if ((*(file->fs->seek))(file, p->p_offset) != FILE_ERR_OK) {
1422 prom_printf ("Seek error\n");
1423 prom_release(loadinfo->base, loadinfo->memsize);
1426 offset = p->p_vaddr - loadinfo->load_loc;
1427 if ((*(file->fs->read))(file, p->p_filesz, loadinfo->base+offset) != p->p_filesz) {
1428 prom_printf ("Read failed\n");
1429 prom_release(loadinfo->base, loadinfo->memsize);
1436 /* Return success at loading the Elf32 kernel */
1446 load_elf64(struct boot_file_t *file, loadinfo_t *loadinfo)
1449 Elf64_Ehdr *e = &(loadinfo->elf.elf64hdr);
1451 int size = sizeof(Elf64_Ehdr) - sizeof(Elf_Ident);
1452 unsigned long loadaddr;
1454 /* Read the rest of the Elf header... */
1455 if ((*(file->fs->read))(file, size, &e->e_version) < size) {
1456 prom_printf("\nCan't read Elf64 image header\n");
1460 DEBUG_F("Elf64 header:\n");
1461 DEBUG_F(" e.e_type = %d\n", (int)e->e_type);
1462 DEBUG_F(" e.e_machine = %d\n", (int)e->e_machine);
1463 DEBUG_F(" e.e_version = %d\n", (int)e->e_version);
1464 DEBUG_F(" e.e_entry = 0x%016lx\n", (long)e->e_entry);
1465 DEBUG_F(" e.e_phoff = 0x%016lx\n", (long)e->e_phoff);
1466 DEBUG_F(" e.e_shoff = 0x%016lx\n", (long)e->e_shoff);
1467 DEBUG_F(" e.e_flags = %d\n", (int)e->e_flags);
1468 DEBUG_F(" e.e_ehsize = 0x%08x\n", (int)e->e_ehsize);
1469 DEBUG_F(" e.e_phentsize = 0x%08x\n", (int)e->e_phentsize);
1470 DEBUG_F(" e.e_phnum = %d\n", (int)e->e_phnum);
1472 loadinfo->entry = e->e_entry;
1474 if (e->e_phnum > MAX_HEADERS) {
1475 prom_printf ("Can only load kernels with one program header\n");
1479 ph = (Elf64_Phdr *)malloc(sizeof(Elf64_Phdr) * e->e_phnum);
1481 prom_printf ("Malloc error\n");
1485 /* Now, we read the section header */
1486 if ((*(file->fs->seek))(file, e->e_phoff) != FILE_ERR_OK) {
1487 prom_printf ("Seek error\n");
1490 if ((*(file->fs->read))(file, sizeof(Elf64_Phdr) * e->e_phnum, ph) !=
1491 sizeof(Elf64_Phdr) * e->e_phnum) {
1492 prom_printf ("Read error\n");
1496 /* Scan through the program header
1497 * HACK: We must return the _memory size of the kernel image, not the
1498 * file size (because we have to leave room before other boot
1499 * infos. This code works as a side effect of the fact that
1500 * we have one section and vaddr == p_paddr
1502 loadinfo->memsize = loadinfo->filesize = loadinfo->offset = 0;
1504 for (i = 0; i < e->e_phnum; ++i, ++p) {
1505 if (p->p_type != PT_LOAD || p->p_offset == 0)
1507 if (loadinfo->memsize == 0) {
1508 loadinfo->offset = p->p_offset;
1509 loadinfo->memsize = p->p_memsz;
1510 loadinfo->filesize = p->p_filesz;
1511 loadinfo->load_loc = p->p_vaddr;
1513 loadinfo->memsize = p->p_offset + p->p_memsz - loadinfo->offset; /* XXX Bogus */
1514 loadinfo->filesize = p->p_offset + p->p_filesz - loadinfo->offset;
1518 if (loadinfo->memsize == 0) {
1519 prom_printf("Can't find a loadable segment !\n");
1523 /* leave some room (1Mb) for boot infos */
1524 loadinfo->memsize = _ALIGN(loadinfo->memsize,(1<<20)) + 0x100000;
1525 /* Claim OF memory */
1526 DEBUG_F("Before prom_claim, mem_sz: 0x%08lx\n", loadinfo->memsize);
1528 /* Determine whether we are trying to boot a vmlinux or some
1529 * other binary image (eg, zImage). We load vmlinux's at
1530 * KERNELADDR and all other binaries at their e_entry value.
1532 if (e->e_entry == KERNEL_LINK_ADDR_PPC64) {
1534 loadaddr = KERNELADDR;
1537 loadaddr = e->e_entry;
1540 loadinfo->base = prom_claim_chunk((void *)loadaddr, loadinfo->memsize, 0);
1541 if (loadinfo->base == (void *)-1) {
1542 prom_printf("Claim error, can't allocate kernel memory\n");
1546 DEBUG_F("After ELF parsing, load base: %p, mem_sz: 0x%08lx\n",
1547 loadinfo->base, loadinfo->memsize);
1548 DEBUG_F(" wanted load base: 0x%08lx, mem_sz: 0x%08lx\n",
1549 loadaddr, loadinfo->memsize);
1551 /* Load the program segments... */
1553 for (i = 0; i < e->e_phnum; ++i, ++p) {
1554 unsigned long offset;
1555 if (p->p_type != PT_LOAD || p->p_offset == 0)
1558 /* Now, we skip to the image itself */
1559 if ((*(file->fs->seek))(file, p->p_offset) != FILE_ERR_OK) {
1560 prom_printf ("Seek error\n");
1561 prom_release(loadinfo->base, loadinfo->memsize);
1564 offset = p->p_vaddr - loadinfo->load_loc;
1565 if ((*(file->fs->read))(file, p->p_filesz, loadinfo->base+offset) != p->p_filesz) {
1566 prom_printf ("Read failed\n");
1567 prom_release(loadinfo->base, loadinfo->memsize);
1574 /* Return success at loading the Elf64 kernel */
1584 is_elf32(loadinfo_t *loadinfo)
1586 Elf32_Ehdr *e = &(loadinfo->elf.elf32hdr);
1588 return (e->e_ident[EI_MAG0] == ELFMAG0 &&
1589 e->e_ident[EI_MAG1] == ELFMAG1 &&
1590 e->e_ident[EI_MAG2] == ELFMAG2 &&
1591 e->e_ident[EI_MAG3] == ELFMAG3 &&
1592 e->e_ident[EI_CLASS] == ELFCLASS32 &&
1593 e->e_ident[EI_DATA] == ELFDATA2MSB &&
1594 e->e_type == ET_EXEC &&
1595 e->e_machine == EM_PPC);
1599 is_elf64(loadinfo_t *loadinfo)
1601 Elf64_Ehdr *e = &(loadinfo->elf.elf64hdr);
1603 return (e->e_ident[EI_MAG0] == ELFMAG0 &&
1604 e->e_ident[EI_MAG1] == ELFMAG1 &&
1605 e->e_ident[EI_MAG2] == ELFMAG2 &&
1606 e->e_ident[EI_MAG3] == ELFMAG3 &&
1607 e->e_ident[EI_CLASS] == ELFCLASS64 &&
1608 e->e_ident[EI_DATA] == ELFDATA2MSB &&
1609 e->e_type == ET_EXEC &&
1610 e->e_machine == EM_PPC64);
1616 #ifdef CONFIG_SET_COLORMAP
1617 static unsigned char default_colors[] = {
1636 prom_handle scrn = PROM_INVALID_HANDLE;
1638 /* Try Apple's mac-boot screen ihandle */
1639 result = (int)call_prom_return("interpret", 1, 2,
1640 "\" _screen-ihandle\" $find if execute else 0 then", &scrn);
1641 DEBUG_F("Trying to get screen ihandle, result: %d, scrn: %p\n", result, scrn);
1643 if (scrn == 0 || scrn == PROM_INVALID_HANDLE) {
1645 /* Hrm... check to see if stdout is a display */
1646 scrn = call_prom ("instance-to-package", 1, 1, prom_stdout);
1647 DEBUG_F("instance-to-package of stdout is: %p\n", scrn);
1648 if (prom_getprop(scrn, "device_type", type, 32) > 0 && !strncmp(type, "display", 7)) {
1649 DEBUG_F("got it ! stdout is a screen\n");
1652 /* Else, we try to open the package */
1653 scrn = (prom_handle)call_prom( "open", 1, 1, "screen" );
1654 DEBUG_F("Open screen result: %p\n", scrn);
1658 if (scrn == PROM_INVALID_HANDLE) {
1659 prom_printf("No screen device found !\n");
1663 prom_set_color(scrn, i, default_colors[i*3],
1664 default_colors[i*3+1], default_colors[i*3+2]);
1666 prom_printf("\x1b[1;37m\x1b[2;40m");
1668 for (i=0;i<16; i++) {
1669 prom_printf("\x1b[%d;%dm\x1b[1;47m%s \x1b[2;40m %s\n",
1670 ansi_color_table[i].index,
1671 ansi_color_table[i].value,
1672 ansi_color_table[i].name,
1673 ansi_color_table[i].name);
1674 prom_printf("\x1b[%d;%dm\x1b[1;37m%s \x1b[2;30m %s\n",
1675 ansi_color_table[i].index,
1676 ansi_color_table[i].value+10,
1677 ansi_color_table[i].name,
1678 ansi_color_table[i].name);
1680 prom_printf("\x1b[1;37m\x1b[2;40m");
1681 #endif /* COLOR_TEST */
1687 #endif /* CONFIG_SET_COLORMAP */
1696 char conf_path[1024];
1698 if (_machine == _MACH_Pmac)
1701 prom_get_chosen("bootargs", bootargs, sizeof(bootargs));
1702 DEBUG_F("/chosen/bootargs = %s\n", bootargs);
1703 prom_get_chosen("bootpath", bootdevice, BOOTDEVSZ);
1704 DEBUG_F("/chosen/bootpath = %s\n", bootdevice);
1705 if (prom_get_options("ibm,client-architecture-support-reboot",fw_nbr_reboots, FW_NBR_REBOOTSZ) == -1 )
1706 prom_get_options("ibm,fw-nbr-reboots",fw_nbr_reboots, FW_NBR_REBOOTSZ);
1707 fw_reboot_cnt = simple_strtol(fw_nbr_reboots,&endp,10);
1708 if (fw_reboot_cnt > 0L)
1709 prom_get_options("boot-last-label", bootlastlabel, BOOTLASTSZ);
1711 /* If conf= specified on command line, it overrides
1712 Usage: conf=device:partition,/path/to/conffile
1713 Example: On Open Firmware Prompt, type
1714 boot conf=/pci@8000000f8000000/pci@1/pci1014,028C@1/scsi@0/sd@1,0:3,/etc/yaboot.conf */
1716 if (!strncmp(bootargs, "conf=", 5)) {
1717 DEBUG_F("Using conf argument in Open Firmware\n");
1718 char *end = strchr(bootargs,' ');
1722 strcpy(bootdevice, bootargs + 5);
1724 DEBUG_F("Using conf=%s\n", bootdevice);
1726 /* Remove conf=xxx from bootargs */
1728 memmove(bootargs, end+1, strlen(end+1)+1);
1732 if (bootdevice[0] == 0) {
1733 prom_get_options("boot-device", bootdevice, BOOTDEVSZ);
1734 DEBUG_F("boot-device = %s\n", bootdevice);
1736 if (bootdevice[0] == 0) {
1737 prom_printf("Couldn't determine boot device\n");
1741 if (bootoncelabel[0] == 0) {
1742 prom_get_options("boot-once", bootoncelabel,
1743 sizeof(bootoncelabel));
1744 if (bootoncelabel[0] != 0)
1745 DEBUG_F("boot-once: [%s]\n", bootoncelabel);
1747 prom_set_options("boot-once", NULL, 0);
1749 if (!parse_device_path(bootdevice, NULL, -1, "", &boot)) {
1750 prom_printf("%s: Unable to parse\n", bootdevice);
1753 if (_machine == _MACH_bplan)
1755 DEBUG_F("After parse_device_path: dev=%s, part=%d, file=%s\n",
1756 boot.dev, boot.part, boot.file);
1759 if (_machine == _MACH_chrp || _machine == _MACH_bplan)
1760 boot.file = "/etc/";
1761 else if (strlen(boot.file)) {
1762 if (!strncmp(boot.file, "\\\\", 2))
1766 p = last = boot.file;
1776 if (strlen(boot.file))
1777 strcat(boot.file, "\\");
1780 strcpy(conf_path, boot.file);
1781 strcat(conf_path, CONFIG_FILE_NAME);
1782 boot.file = conf_path;
1783 DEBUG_F("After path kludgeup: dev=%s, part=%d, file=%s\n",
1784 boot.dev, boot.part, boot.file);
1788 * If we're doing a netboot, first look for one which matches our
1791 if (prom_get_devtype(boot.dev) == FILE_DEVICE_NET) {
1792 prom_printf("Try to netboot\n");
1793 useconf = load_my_config_file(&boot);
1797 useconf = load_config_file(&boot);
1799 prom_printf("Welcome to yaboot version " VERSION "\n");
1800 prom_printf("Enter \"help\" to get some basic usage information\n");
1802 /* I am fed up with lusers using the wrong partition type and
1803 mailing me *when* it breaks */
1805 if (_machine == _MACH_Pmac) {
1806 char *entry = cfg_get_strg(0, "ptypewarning");
1809 warn = strcmp(entry,
1810 "I_know_the_partition_type_is_wrong_and_will_NOT_send_mail_when_booting_breaks");
1812 ptype = get_part_type(boot.dev, boot.part);
1813 if ((ptype != NULL) && (strcmp(ptype, "Apple_Bootstrap")))
1814 prom_printf("\nWARNING: Bootstrap partition type is wrong: \"%s\"\n"
1815 " type should be: \"Apple_Bootstrap\"\n\n", ptype);
1823 prom_printf("Bye.\n");
1829 * c-file-style: "k&r"