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 msgfile = boot; /* Copy all the original paramters */
304 if (!parse_device_path(msgpath, defdev, defpart, "/etc/yaboot.msg", &msgfile)) {
305 prom_printf("%s: Unable to parse\n", msgpath);
309 result = open_file(&msgfile, &file);
310 if (result != FILE_ERR_OK) {
311 prom_printf("%s:%d,", msgfile.dev, msgfile.part);
312 prom_perror(result, msgfile.file);
321 memset(msg, 0, 2001);
323 if (file.fs->read(&file, 2000, msg) <= 0)
326 prom_printf("%s", msg);
330 file.fs->close(&file);
335 /* Currently, the config file must be at the root of the filesystem.
336 * todo: recognize the full path to myself and use it to load the
337 * config file. Handle the "\\" (blessed system folder)
340 load_config_file(struct boot_fspec_t *fspec)
342 char *conf_file = NULL, *p;
343 struct boot_file_t file;
344 int sz, opened = 0, result = 0;
346 /* Allocate a buffer for the config file */
347 conf_file = malloc(CONFIG_FILE_MAX);
349 prom_printf("Can't alloc config file buffer\n");
354 result = open_file(fspec, &file);
355 if (result != FILE_ERR_OK) {
356 prom_printf("%s:%d,", fspec->dev, fspec->part);
357 prom_perror(result, fspec->file);
358 prom_printf("Can't open config file\n");
364 sz = file.fs->read(&file, CONFIG_FILE_MAX, conf_file);
366 prom_printf("Error, can't read config file\n");
369 prom_printf("Config file read, %d bytes\n", sz);
373 file.fs->close(&file);
376 /* Call the parsing code in cfg.c */
377 if (cfg_parse(fspec->file, conf_file, sz) < 0) {
378 prom_printf ("Syntax error or read error config\n");
383 * set the default cf_option to label that has the same MAC addr
384 * it only works if there is a label with the MAC addr on yaboot.conf
386 if (prom_get_devtype(fspec->dev) == FILE_DEVICE_NET) {
387 /* change the variable bellow to get the MAC dinamicaly */
388 char * macaddr = NULL;
391 macaddr = prom_get_mac(prom_get_netinfo());
392 default_mac = cfg_set_default_by_mac(macaddr);
393 if (default_mac >= 1) {
394 prom_printf("Default label was changed to macaddr label.\n");
398 DEBUG_F("Config file successfully parsed, %d bytes\n", sz);
400 /* Now, we do the initialisations stored in the config file */
401 p = cfg_get_strg(0, "init-code");
405 password = cfg_get_strg(0, "password");
407 #ifdef CONFIG_COLOR_TEXT
408 p = cfg_get_strg(0, "fgcolor");
410 DEBUG_F("fgcolor=%s\n", p);
411 fgcolor = check_color_text_ui(p);
413 prom_printf("Invalid fgcolor: \"%s\".\n", p);
416 p = cfg_get_strg(0, "bgcolor");
418 DEBUG_F("bgcolor=%s\n", p);
419 bgcolor = check_color_text_ui(p);
421 prom_printf("Invalid bgcolor: \"%s\".\n", p);
425 sprintf(temp, "%x to background-color", bgcolor);
426 prom_interpret(temp);
433 sprintf(temp, "%x to foreground-color", fgcolor);
434 prom_interpret(temp);
436 #endif /* CONFIG_COLOR_TEXT */
438 p = cfg_get_strg(0, "init-message");
440 prom_printf("%s\n", p);
442 p = cfg_get_strg(0, "message");
444 print_message_file(p);
451 file.fs->close(&file);
460 * Search for config file by MAC address, then by IP address.
461 * Basically copying pxelinux's algorithm.
462 * http://syslinux.zytor.com/pxe.php#config
464 static int load_my_config_file(struct boot_fspec_t *orig_fspec)
466 struct bootp_packet *packet;
468 struct boot_fspec_t fspec = *orig_fspec;
469 char *cfgpath = (_machine == _MACH_chrp || _machine == _MACH_bplan) ? "/etc/" : "";
473 packet = prom_get_netinfo();
478 * First, try to match on mac address with the hardware type
482 /* 3 chars per byte in chaddr + 2 chars for htype + /etc/ +\0 */
483 fspec.file = malloc(packet->hlen * 3 + 2 + 6);
487 sprintf(fspec.file, "%s%02x-", cfgpath, packet->htype);
488 strcat(fspec.file, prom_get_mac(packet));
490 rc = load_config_file(&fspec);
495 * Now try to match on IP.
497 /* no need to realloc for /etc/ + 8 chars in yiaddr + \0 */
498 sprintf(fspec.file, "%s%s", cfgpath, prom_get_ip(packet));
500 for (flen = strlen(fspec.file),
501 minlen = strlen(cfgpath); flen > minlen; flen--) {
502 rc = load_config_file(&fspec);
505 /* Chop one digit off the end, try again */
506 fspec.file[flen - 1] = '\0';
510 if (rc) /* modify original only on success */
511 orig_fspec->file = fspec.file;
517 void maintabfunc (void)
521 prom_printf("boot: %s", cbuff);
526 word_split(char **linep, char **paramsp)
541 while (*p != 0 && *p != ' ')
550 make_params(char *label, char *params)
553 static char buffer[2048];
558 p = cfg_get_strg(label, "literal");
570 p = cfg_get_strg(label, "root");
577 if (cfg_get_flag(label, "read-only")) {
581 if (cfg_get_flag(label, "read-write")) {
585 p = cfg_get_strg(label, "ramdisk");
587 strcpy (q, "ramdisk=");
592 p = cfg_get_strg(label, "initrd-size");
594 strcpy (q, "ramdisk_size=");
599 if (cfg_get_flag(label, "novideo")) {
600 strcpy (q, "video=ofonly");
604 p = cfg_get_strg (label, "append");
611 pause_after = cfg_get_flag (label, "pause-after");
612 p = cfg_get_strg(label, "pause-message");
621 void check_password(char *str)
625 prom_printf("\n%s", str);
626 for (i = 0; i < 3; i++) {
627 prom_printf ("\nPassword: ");
629 cmdedit ((void (*)(void)) 0, 1);
631 #ifdef USE_MD5_PASSWORDS
632 if (!strncmp (password, "$1$", 3)) {
633 if (!check_md5_password(passwdbuff, password))
636 else if (!strcmp (password, passwdbuff))
639 if (!strcmp (password, passwdbuff))
641 #endif /* USE_MD5_PASSWORDS */
644 prom_printf ("Incorrect password. Try again.");
647 prom_printf(" ___________________\n< Permission denied >\n -------------------\n"
648 " \\ ^__^\n \\ (oo)\\_______\n (__)\\ )\\/\\\n"
649 " ||----w |\n || ||\n");
651 prom_interpret("reset-all");
654 int get_params(struct boot_param_t* params)
658 char defdevice_bak[1024];
661 char *imagename = 0, *label;
666 static int first = 1;
667 static char imagepath[1024];
668 static char initrdpath[1024];
669 static char sysmappath[1024];
670 static char manualinitrd[1024];
671 static int definitrd = 1, hasarg = 0;
674 memset(params, 0, sizeof(*params));
676 params->kernel.part = -1;
677 params->rd.part = -1;
678 params->sysmap.part = -1;
683 if (first && !fw_reboot_cnt) {
685 imagename = bootargs;
686 word_split(&imagename, ¶ms->args);
687 timeout = DEFAULT_TIMEOUT;
689 prom_printf("Default supplied on the command line: %s ", imagename);
691 prom_printf("%s", params->args);
694 if (useconf && (q = cfg_get_strg(0, "timeout")) != 0 && *q != 0)
695 timeout = simple_strtol(q, NULL, 0);
698 /* If this is a reboot due to FW detecting CAS changes then
699 * set timeout to 1. The last kernel booted will be booted
700 * again automatically. It should seem seamless to the user
705 prom_printf("boot: ");
710 end = beg + 100 * timeout;
712 c = prom_nbgetchar();
713 } while (c == -1 && prom_getms() <= end);
717 else if (c != '\n' && c != '\t' && c != '\r' && c != '\b' ) {
723 if (c != -1 && c != '\n' && c != '\r') {
726 } else if (c >= ' ') {
729 if ((cfg_get_flag (cbuff, "single-key")) && useconf) {
732 prom_printf("%s\n", cbuff);
737 if (c == '\n' || c == '\r') {
739 if (bootoncelabel[0] != 0)
740 imagename = bootoncelabel;
741 else if (bootlastlabel[0] != 0)
742 imagename = bootlastlabel;
744 imagename = cfg_get_default();
747 prom_printf("%s", imagename);
749 prom_printf(" %s", params->args);
751 } else if (!singlekey) {
752 cmdedit(maintabfunc, 0);
754 strcpy(given_bootargs, cbuff);
755 given_bootargs_by_user = 1;
757 word_split(&imagename, ¶ms->args);
760 /* initrd setup via cmd console */
761 /* first, check if the user uses it with some label */
762 if (!strncmp(params->args, "initrd=", 7)) {
763 DEBUG_F("params->args: %s\n", params->args);
766 /* after, check if there is the 'initrd=' in the imagename string */
767 if (!strncmp(imagename, "initrd=", 7) || !definitrd) {
769 /* return the value of definitrd to 1 */
773 /* args = "initrd=blah" */
784 /* copy the string after the '=' to manualinitrd */
785 strcpy(manualinitrd, args+7);
787 prom_printf("New initrd file specified: %s\n", manualinitrd);
789 prom_printf("ERROR: no initrd specified!\n");
793 /* set imagename with the default values of the config file */
794 if ((prom_get_devtype(boot.dev) == FILE_DEVICE_NET) && !hasarg)
795 imagename = cfg_get_default();
797 imagename = cfg_get_default();
800 /* chrp gets this wrong, force it -- Cort */
801 if ( useconf && (!imagename || imagename[0] == 0 ))
802 imagename = cfg_get_default();
804 /* write the imagename out so it can be reused on reboot if necessary */
805 prom_set_options("boot-last-label", imagename, strlen(imagename));
808 defdevice = boot.dev;
810 strcpy(defdevice_bak,defdevice);
813 defdevice = cfg_get_strg(0, "device");
814 p = cfg_get_strg(0, "partition");
816 n = simple_strtol(p, &endp, 10);
817 if (endp != p && *endp == 0)
820 p = cfg_get_strg(0, "pause-message");
823 if (cfg_get_flag(0, "restricted"))
825 p = cfg_get_strg(imagename, "image");
829 defdevice = cfg_get_strg(label, "device");
830 if(!defdevice) defdevice=boot.dev;
831 p = cfg_get_strg(label, "partition");
833 n = simple_strtol(p, &endp, 10);
834 if (endp != p && *endp == 0)
837 if (cfg_get_flag(label, "restricted"))
840 if (params->args && password && restricted)
841 check_password ("To specify arguments for this image "
842 "you must enter the password.");
843 else if (password && !restricted)
844 check_password ("This image is restricted.");
846 params->args = make_params(label, params->args);
850 if (!strcmp (imagename, "help")) {
851 /* FIXME: defdevice shouldn't need to be reset all over the place */
852 if(!defdevice) defdevice = boot.dev;
854 "\nPress the tab key for a list of defined images.\n"
855 "The label marked with a \"*\" is is the default image, "
856 "press <return> to boot it.\n\n"
857 "To boot any other label simply type its name and press <return>.\n\n"
858 "To boot a kernel image which is not defined in the yaboot configuration \n"
859 "file, enter the kernel image name as [[device:][partno],]/path, where \n"
860 "\"device:\" is the OpenFirmware device path to the disk the image \n"
861 "resides on, and \"partno\" is the partition number the image resides on.\n"
862 "Note that the comma (,) is only required if you specify an OpenFirmware\n"
863 "device, if you only specify a filename you should not start it with a \",\"\n\n"
864 "To boot a alternative initrd file rather than specified in the yaboot\n"
865 "configuration file, use the \"initrd\" command on Yaboot's prompt: \n"
866 "\"initrd=[name.img]\". This will load the \"name.img\" file after the default\n"
867 "kernel image. You can, also, specify a different initrd file to any other\n"
868 "label of the yaboot configuration file. Just type \"label initrd=[name.img]\"\n"
869 "and the specified initrd file will be loaded.\n\n"
870 "To load an alternative config file rather than /etc/yaboot.conf, enter\n"
871 "its device, partno and path, on Open Firmware Prompt:\n"
872 "boot conf=device:partno,/path/to/configfile\n."
873 "To reload the config file or load a new one, use the \"conf\" command\n"
874 "on Yaboot's prompt:\n"
875 "conf [device=device] [partition=partno] [file=/path/to/configfile]\n\n"
876 "If you omit \"device\" and \"partno\", Yaboot will use their current\n"
877 "values. You can check them by entering \"conf\" on Yaboot's prompt.\n");
882 if (!strcmp (imagename, "halt")) {
884 check_password ("Restricted command.");
888 if (!strcmp (imagename, "bye")) {
890 check_password ("Restricted command.");
896 if (!strncmp (imagename, "conf", 4)) {
898 // imagename = "conf file=blah dev=bleh part=blih"
899 DEBUG_F("Loading user-specified config file: %s\n",imagename);
901 check_password ("Restricted command.");
905 // args= "file=blah dev=bleh part=blih"
906 char *args = params->args;
910 // set a pointer to the first space in args
911 char *space = strchr(args,' ');
915 char temp[1024] = "0";
917 // copy next argument to temp
918 strncpy(temp, args, space-args);
920 // parse temp and set boot arguments
921 if (!strncmp (temp, "file=", 5)){
922 DEBUG_F("conf file: %s\n", temp+5);
923 strcpy(boot.file, temp+5);
924 } else if (!strncmp (temp, "device=", 7)){
925 DEBUG_F("conf device: %s\n", temp+7);
926 strcpy(boot.dev, temp+7);
927 } else if (!strncmp (temp, "partition=", 10)){
928 DEBUG_F("conf partition: %s\n", temp+10);
929 boot.part=simple_strtol(temp+10,NULL,10);
933 // set the pointer to the next space in args;
934 // set the loop control variable
935 if (strlen(space)>1){
936 // Go to the next argument
940 if (strchr(args,' ') == NULL)
941 space = &args[strlen(args)];
943 space = strchr(args,' ');
950 prom_printf("Loading config file...\n");
951 useconf = load_config_file(&boot);
953 if ((q = cfg_get_strg(0, "timeout")) != 0 && *q != 0)
954 timeout = simple_strtol(q, NULL, 0);
956 prom_printf("Restoring default values.\n");
957 strcpy(boot.file,"");
958 strcpy(boot.dev, defdevice_bak);
963 prom_printf("Current configuration:\n");
964 prom_printf("device: %s\n", boot.dev);
966 prom_printf("partition: auto\n");
968 prom_printf("partition: %d\n", boot.part);
969 if (strlen(boot.file))
970 prom_printf("file: %s\n", boot.file);
972 prom_printf("file: /etc/%s\n",CONFIG_FILE_NAME);
981 if (imagename[0] == '$') {
982 /* forth command string */
984 check_password ("OpenFirmware commands are restricted.");
985 prom_interpret(imagename+1);
989 strncpy(imagepath, imagename, 1024);
991 if (!label && password)
992 check_password ("To boot a custom image you must enter the password.");
994 params->kernel = boot; /* Copy all the original paramters */
995 if (!parse_device_path(imagepath, defdevice, defpart,
996 "/vmlinux", ¶ms->kernel)) {
997 prom_printf("%s: Unable to parse\n", imagepath);
1000 DEBUG_F("after parse_device_path: dev=%s part=%d file=%s\n", params->kernel.dev, params->kernel.part, params->kernel.file);
1002 p = cfg_get_strg(label, "initrd");
1005 /* check if user seted to use a initrd file from boot console */
1006 if (!definitrd && p != manualinitrd) {
1007 if (manualinitrd[0] != "/" && (prom_get_devtype(defdevice_bak) != FILE_DEVICE_NET)) {
1008 strcpy(initrdpath, "/");
1009 strcat(initrdpath, manualinitrd);
1011 strncpy(initrdpath, manualinitrd, 1024);
1013 strncpy(initrdpath, p, 1024);
1015 DEBUG_F("Parsing initrd path <%s>\n", initrdpath);
1016 params->rd = boot; /* Copy all the original paramters */
1017 if (!parse_device_path(initrdpath, defdevice, defpart,
1018 "/root.bin", ¶ms->rd)) {
1019 prom_printf("%s: Unable to parse\n", imagepath);
1023 p = cfg_get_strg(label, "sysmap");
1025 DEBUG_F("Parsing sysmap path <%s>\n", p);
1026 strncpy(sysmappath, p, 1024);
1027 params->sysmap = boot; /* Copy all the original paramters */
1028 if (!parse_device_path(sysmappath, defdevice, defpart,
1029 "/boot/System.map", ¶ms->sysmap)) {
1030 prom_printf("%s: Unable to parse\n", imagepath);
1038 /* This is derived from quik core. To be changed to first parse the headers
1039 * doing lazy-loading, and then claim the memory before loading the kernel
1041 * We also need to add initrd support to this whole mecanism
1044 yaboot_text_ui(void)
1046 #define MAX_HEADERS 32
1048 struct boot_file_t file;
1050 static struct boot_param_t params;
1052 unsigned long initrd_size;
1054 unsigned long sysmap_size;
1055 kernel_entry_t kernel_entry;
1056 struct bi_record* birec;
1058 loadinfo_t loadinfo;
1059 void *initrd_more,*initrd_want;
1060 unsigned long initrd_read;
1062 loadinfo.load_loc = 0;
1070 if (get_params(¶ms))
1072 if (!params.kernel.file)
1075 prom_printf("Please wait, loading kernel...\n");
1077 memset(&file, 0, sizeof(file));
1079 if (strlen(boot.file) && !strcmp(boot.file,"\\\\") && params.kernel.file[0] != '/'
1080 && params.kernel.file[0] != '\\') {
1081 loc=(char*)malloc(strlen(params.kernel.file)+3);
1083 prom_printf ("malloc error\n");
1086 strcpy(loc,boot.file);
1087 strcat(loc,params.kernel.file);
1088 free(params.kernel.file);
1089 params.kernel.file=loc;
1091 result = open_file(¶ms.kernel, &file);
1092 if (result != FILE_ERR_OK) {
1093 prom_printf("%s:%d,", params.kernel.dev, params.kernel.part);
1094 prom_perror(result, params.kernel.file);
1098 /* Read the Elf e_ident, e_type and e_machine fields to
1099 * determine Elf file type
1101 if (file.fs->read(&file, sizeof(Elf_Ident), &loadinfo.elf) < sizeof(Elf_Ident)) {
1102 prom_printf("\nCan't read Elf e_ident/e_type/e_machine info\n");
1103 file.fs->close(&file);
1104 memset(&file, 0, sizeof(file));
1108 if (is_elf32(&loadinfo)) {
1109 if (!load_elf32(&file, &loadinfo)) {
1110 file.fs->close(&file);
1111 memset(&file, 0, sizeof(file));
1114 prom_printf(" Elf32 kernel loaded...\n");
1115 } else if (is_elf64(&loadinfo)) {
1116 if (!load_elf64(&file, &loadinfo)) {
1117 file.fs->close(&file);
1118 memset(&file, 0, sizeof(file));
1121 prom_printf(" Elf64 kernel loaded...\n");
1123 prom_printf ("%s: Not a valid ELF image\n", params.kernel.file);
1124 file.fs->close(&file);
1125 memset(&file, 0, sizeof(file));
1128 file.fs->close(&file);
1129 memset(&file, 0, sizeof(file));
1131 /* If sysmap, load it (only if booting a vmlinux).
1133 if (flat_vmlinux && params.sysmap.file) {
1134 prom_printf("Loading System.map ...\n");
1135 if(strlen(boot.file) && !strcmp(boot.file,"\\\\") && params.sysmap.file[0] != '/'
1136 && params.sysmap.file[0] != '\\') {
1138 loc=(char*)malloc(strlen(params.sysmap.file)+3);
1140 prom_printf ("malloc error\n");
1143 strcpy(loc,boot.file);
1144 strcat(loc,params.sysmap.file);
1145 free(params.sysmap.file);
1146 params.sysmap.file=loc;
1149 result = open_file(¶ms.sysmap, &file);
1150 if (result != FILE_ERR_OK) {
1151 prom_printf("%s:%d,", params.sysmap.dev, params.sysmap.part);
1152 prom_perror(result, params.sysmap.file);
1155 sysmap_base = prom_claim(loadinfo.base+loadinfo.memsize, 0x100000, 0);
1156 if (sysmap_base == (void *)-1) {
1157 prom_printf("Claim failed for sysmap memory\n");
1161 sysmap_size = file.fs->read(&file, 0xfffff, sysmap_base);
1162 if (sysmap_size == 0)
1165 ((char *)sysmap_base)[sysmap_size++] = 0;
1167 file.fs->close(&file);
1168 memset(&file, 0, sizeof(file));
1171 prom_printf("System.map loaded at %p, size: %lu Kbytes\n",
1172 sysmap_base, sysmap_size >> 10);
1173 loadinfo.memsize += _ALIGN(0x100000, 0x1000);
1175 prom_printf("System.map load failed !\n");
1180 /* If ramdisk, load it (only if booting a vmlinux). For now, we
1181 * can't tell the size it will be so we claim an arbitrary amount
1184 if (flat_vmlinux && params.rd.file) {
1185 if(strlen(boot.file) && !strcmp(boot.file,"\\\\") && params.rd.file[0] != '/'
1186 && params.kernel.file[0] != '\\')
1189 loc=(char*)malloc(strlen(params.rd.file)+3);
1191 prom_printf ("Malloc error\n");
1194 strcpy(loc,boot.file);
1195 strcat(loc,params.rd.file);
1196 free(params.rd.file);
1199 prom_printf("Loading ramdisk...\n");
1200 result = open_file(¶ms.rd, &file);
1201 if (result != FILE_ERR_OK) {
1202 prom_printf("%s:%d,", params.rd.dev, params.rd.part);
1203 prom_perror(result, params.rd.file);
1206 #define INITRD_CHUNKSIZE 0x100000
1207 initrd_base = prom_claim(loadinfo.base+loadinfo.memsize, INITRD_CHUNKSIZE, 0);
1208 if (initrd_base == (void *)-1) {
1209 prom_printf("Claim failed for initrd memory\n");
1212 initrd_size = file.fs->read(&file, INITRD_CHUNKSIZE, initrd_base);
1213 if (initrd_size == 0)
1215 initrd_read = initrd_size;
1216 initrd_more = initrd_base;
1217 while (initrd_read == INITRD_CHUNKSIZE ) { /* need to read more? */
1218 initrd_want = (void *)((unsigned long)initrd_more+INITRD_CHUNKSIZE);
1219 initrd_more = prom_claim(initrd_want, INITRD_CHUNKSIZE, 0);
1220 if (initrd_more != initrd_want) {
1221 prom_printf("Claim failed for initrd memory at %p rc=%p\n",initrd_want,initrd_more);
1225 initrd_read = file.fs->read(&file, INITRD_CHUNKSIZE, initrd_more);
1226 DEBUG_F(" block at %p rc=%lu\n",initrd_more,initrd_read);
1227 initrd_size += initrd_read;
1230 file.fs->close(&file);
1231 memset(&file, 0, sizeof(file));
1234 prom_printf("ramdisk loaded at %p, size: %lu Kbytes\n",
1235 initrd_base, initrd_size >> 10);
1237 prom_printf("ramdisk load failed !\n");
1242 DEBUG_F("setting kernel args to: %s\n", params.args);
1243 prom_setargs(params.args);
1244 DEBUG_F("flushing icache...");
1245 flush_icache_range ((long)loadinfo.base, (long)loadinfo.base+loadinfo.memsize);
1250 * Fill new boot infos (only if booting a vmlinux).
1252 * The birec is low on memory, probably inside the malloc pool,
1253 * so we don't write it earlier. At this point, we should not
1254 * use anything coming from the malloc pool.
1256 birec = (struct bi_record *)_ALIGN(loadinfo.filesize+(1<<20)-1,(1<<20));
1258 /* We make sure it's mapped. We map only 64k for now, it's
1259 * plenty enough we don't claim since this precise memory
1260 * range may already be claimed by the malloc pool.
1262 prom_map (birec, birec, 0x10000);
1263 DEBUG_F("birec at %p\n", birec);
1266 birec->tag = BI_FIRST;
1267 birec->size = sizeof(struct bi_record);
1268 birec = (struct bi_record *)((ulong)birec + birec->size);
1270 birec->tag = BI_BOOTLOADER_ID;
1271 sprintf( (char *)birec->data, "yaboot");
1272 birec->size = sizeof(struct bi_record) + strlen("yaboot") + 1;
1273 birec = (struct bi_record *)((ulong)birec + birec->size);
1275 birec->tag = BI_MACHTYPE;
1276 birec->data[0] = _machine;
1277 birec->size = sizeof(struct bi_record) + sizeof(ulong);
1278 birec = (struct bi_record *)((ulong)birec + birec->size);
1281 birec->tag = BI_SYSMAP;
1282 birec->data[0] = (ulong)sysmap_base;
1283 birec->data[1] = sysmap_size;
1284 birec->size = sizeof(struct bi_record) + sizeof(ulong)*2;
1285 birec = (struct bi_record *)((ulong)birec + birec->size);
1287 birec->tag = BI_LAST;
1288 birec->size = sizeof(struct bi_record);
1289 birec = (struct bi_record *)((ulong)birec + birec->size);
1292 /* compute the kernel's entry point. */
1293 kernel_entry = loadinfo.base + loadinfo.entry - loadinfo.load_loc;
1295 DEBUG_F("Kernel entry point = %p\n", kernel_entry);
1296 DEBUG_F("kernel: arg1 = %p,\n"
1297 " arg2 = 0x%08lx,\n"
1301 initrd_base + loadinfo.load_loc, initrd_size, prom, 0, 0);
1303 DEBUG_F("Entering kernel...\n");
1305 /* call the kernel with our stack. */
1306 kernel_entry(initrd_base + loadinfo.load_loc, initrd_size, prom, 0, 0);
1314 load_elf32(struct boot_file_t *file, loadinfo_t *loadinfo)
1317 Elf32_Ehdr *e = &(loadinfo->elf.elf32hdr);
1319 int size = sizeof(Elf32_Ehdr) - sizeof(Elf_Ident);
1320 unsigned long loadaddr;
1322 /* Read the rest of the Elf header... */
1323 if ((*(file->fs->read))(file, size, &e->e_version) < size) {
1324 prom_printf("\nCan't read Elf32 image header\n");
1328 DEBUG_F("Elf32 header:\n");
1329 DEBUG_F(" e.e_type = %d\n", (int)e->e_type);
1330 DEBUG_F(" e.e_machine = %d\n", (int)e->e_machine);
1331 DEBUG_F(" e.e_version = %d\n", (int)e->e_version);
1332 DEBUG_F(" e.e_entry = 0x%08x\n", (int)e->e_entry);
1333 DEBUG_F(" e.e_phoff = 0x%08x\n", (int)e->e_phoff);
1334 DEBUG_F(" e.e_shoff = 0x%08x\n", (int)e->e_shoff);
1335 DEBUG_F(" e.e_flags = %d\n", (int)e->e_flags);
1336 DEBUG_F(" e.e_ehsize = 0x%08x\n", (int)e->e_ehsize);
1337 DEBUG_F(" e.e_phentsize = 0x%08x\n", (int)e->e_phentsize);
1338 DEBUG_F(" e.e_phnum = %d\n", (int)e->e_phnum);
1340 loadinfo->entry = e->e_entry;
1342 if (e->e_phnum > MAX_HEADERS) {
1343 prom_printf ("Can only load kernels with one program header\n");
1347 ph = (Elf32_Phdr *)malloc(sizeof(Elf32_Phdr) * e->e_phnum);
1349 prom_printf ("Malloc error\n");
1353 /* Now, we read the section header */
1354 if ((*(file->fs->seek))(file, e->e_phoff) != FILE_ERR_OK) {
1355 prom_printf ("seek error\n");
1358 if ((*(file->fs->read))(file, sizeof(Elf32_Phdr) * e->e_phnum, ph) !=
1359 sizeof(Elf32_Phdr) * e->e_phnum) {
1360 prom_printf ("read error\n");
1364 /* Scan through the program header
1365 * HACK: We must return the _memory size of the kernel image, not the
1366 * file size (because we have to leave room before other boot
1367 * infos. This code works as a side effect of the fact that
1368 * we have one section and vaddr == p_paddr
1370 loadinfo->memsize = loadinfo->filesize = loadinfo->offset = 0;
1372 for (i = 0; i < e->e_phnum; ++i, ++p) {
1373 if (p->p_type != PT_LOAD || p->p_offset == 0)
1375 if (loadinfo->memsize == 0) {
1376 loadinfo->offset = p->p_offset;
1377 loadinfo->memsize = p->p_memsz;
1378 loadinfo->filesize = p->p_filesz;
1379 loadinfo->load_loc = p->p_vaddr;
1381 loadinfo->memsize = p->p_offset + p->p_memsz - loadinfo->offset; /* XXX Bogus */
1382 loadinfo->filesize = p->p_offset + p->p_filesz - loadinfo->offset;
1386 if (loadinfo->memsize == 0) {
1387 prom_printf("Can't find a loadable segment !\n");
1391 /* leave some room (1Mb) for boot infos */
1392 loadinfo->memsize = _ALIGN(loadinfo->memsize,(1<<20)) + 0x100000;
1393 /* Claim OF memory */
1394 DEBUG_F("Before prom_claim, mem_sz: 0x%08lx\n", loadinfo->memsize);
1396 /* Determine whether we are trying to boot a vmlinux or some
1397 * other binary image (eg, zImage). We load vmlinux's at
1398 * KERNELADDR and all other binaries at their e_entry value.
1400 if (e->e_entry == KERNEL_LINK_ADDR_PPC32) {
1402 loadaddr = KERNELADDR;
1405 loadaddr = loadinfo->load_loc;
1408 loadinfo->base = prom_claim_chunk((void *)loadaddr, loadinfo->memsize, 0);
1409 if (loadinfo->base == (void *)-1) {
1410 prom_printf("Claim error, can't allocate kernel memory\n");
1414 DEBUG_F("After ELF parsing, load base: %p, mem_sz: 0x%08lx\n",
1415 loadinfo->base, loadinfo->memsize);
1416 DEBUG_F(" wanted load base: 0x%08lx, mem_sz: 0x%08lx\n",
1417 loadaddr, loadinfo->memsize);
1419 /* Load the program segments... */
1421 for (i = 0; i < e->e_phnum; ++i, ++p) {
1422 unsigned long offset;
1423 if (p->p_type != PT_LOAD || p->p_offset == 0)
1426 /* Now, we skip to the image itself */
1427 if ((*(file->fs->seek))(file, p->p_offset) != FILE_ERR_OK) {
1428 prom_printf ("Seek error\n");
1429 prom_release(loadinfo->base, loadinfo->memsize);
1432 offset = p->p_vaddr - loadinfo->load_loc;
1433 if ((*(file->fs->read))(file, p->p_filesz, loadinfo->base+offset) != p->p_filesz) {
1434 prom_printf ("Read failed\n");
1435 prom_release(loadinfo->base, loadinfo->memsize);
1442 /* Return success at loading the Elf32 kernel */
1452 load_elf64(struct boot_file_t *file, loadinfo_t *loadinfo)
1455 Elf64_Ehdr *e = &(loadinfo->elf.elf64hdr);
1457 int size = sizeof(Elf64_Ehdr) - sizeof(Elf_Ident);
1458 unsigned long loadaddr;
1460 /* Read the rest of the Elf header... */
1461 if ((*(file->fs->read))(file, size, &e->e_version) < size) {
1462 prom_printf("\nCan't read Elf64 image header\n");
1466 DEBUG_F("Elf64 header:\n");
1467 DEBUG_F(" e.e_type = %d\n", (int)e->e_type);
1468 DEBUG_F(" e.e_machine = %d\n", (int)e->e_machine);
1469 DEBUG_F(" e.e_version = %d\n", (int)e->e_version);
1470 DEBUG_F(" e.e_entry = 0x%016lx\n", (long)e->e_entry);
1471 DEBUG_F(" e.e_phoff = 0x%016lx\n", (long)e->e_phoff);
1472 DEBUG_F(" e.e_shoff = 0x%016lx\n", (long)e->e_shoff);
1473 DEBUG_F(" e.e_flags = %d\n", (int)e->e_flags);
1474 DEBUG_F(" e.e_ehsize = 0x%08x\n", (int)e->e_ehsize);
1475 DEBUG_F(" e.e_phentsize = 0x%08x\n", (int)e->e_phentsize);
1476 DEBUG_F(" e.e_phnum = %d\n", (int)e->e_phnum);
1478 loadinfo->entry = e->e_entry;
1480 if (e->e_phnum > MAX_HEADERS) {
1481 prom_printf ("Can only load kernels with one program header\n");
1485 ph = (Elf64_Phdr *)malloc(sizeof(Elf64_Phdr) * e->e_phnum);
1487 prom_printf ("Malloc error\n");
1491 /* Now, we read the section header */
1492 if ((*(file->fs->seek))(file, e->e_phoff) != FILE_ERR_OK) {
1493 prom_printf ("Seek error\n");
1496 if ((*(file->fs->read))(file, sizeof(Elf64_Phdr) * e->e_phnum, ph) !=
1497 sizeof(Elf64_Phdr) * e->e_phnum) {
1498 prom_printf ("Read error\n");
1502 /* Scan through the program header
1503 * HACK: We must return the _memory size of the kernel image, not the
1504 * file size (because we have to leave room before other boot
1505 * infos. This code works as a side effect of the fact that
1506 * we have one section and vaddr == p_paddr
1508 loadinfo->memsize = loadinfo->filesize = loadinfo->offset = 0;
1510 for (i = 0; i < e->e_phnum; ++i, ++p) {
1511 if (p->p_type != PT_LOAD || p->p_offset == 0)
1513 if (loadinfo->memsize == 0) {
1514 loadinfo->offset = p->p_offset;
1515 loadinfo->memsize = p->p_memsz;
1516 loadinfo->filesize = p->p_filesz;
1517 loadinfo->load_loc = p->p_vaddr;
1519 loadinfo->memsize = p->p_offset + p->p_memsz - loadinfo->offset; /* XXX Bogus */
1520 loadinfo->filesize = p->p_offset + p->p_filesz - loadinfo->offset;
1524 if (loadinfo->memsize == 0) {
1525 prom_printf("Can't find a loadable segment !\n");
1529 /* leave some room (1Mb) for boot infos */
1530 loadinfo->memsize = _ALIGN(loadinfo->memsize,(1<<20)) + 0x100000;
1531 /* Claim OF memory */
1532 DEBUG_F("Before prom_claim, mem_sz: 0x%08lx\n", loadinfo->memsize);
1534 /* Determine whether we are trying to boot a vmlinux or some
1535 * other binary image (eg, zImage). We load vmlinux's at
1536 * KERNELADDR and all other binaries at their e_entry value.
1538 if (e->e_entry == KERNEL_LINK_ADDR_PPC64) {
1540 loadaddr = KERNELADDR;
1543 loadaddr = e->e_entry;
1546 loadinfo->base = prom_claim_chunk((void *)loadaddr, loadinfo->memsize, 0);
1547 if (loadinfo->base == (void *)-1) {
1548 prom_printf("Claim error, can't allocate kernel memory\n");
1552 DEBUG_F("After ELF parsing, load base: %p, mem_sz: 0x%08lx\n",
1553 loadinfo->base, loadinfo->memsize);
1554 DEBUG_F(" wanted load base: 0x%08lx, mem_sz: 0x%08lx\n",
1555 loadaddr, loadinfo->memsize);
1557 /* Load the program segments... */
1559 for (i = 0; i < e->e_phnum; ++i, ++p) {
1560 unsigned long offset;
1561 if (p->p_type != PT_LOAD || p->p_offset == 0)
1564 /* Now, we skip to the image itself */
1565 if ((*(file->fs->seek))(file, p->p_offset) != FILE_ERR_OK) {
1566 prom_printf ("Seek error\n");
1567 prom_release(loadinfo->base, loadinfo->memsize);
1570 offset = p->p_vaddr - loadinfo->load_loc;
1571 if ((*(file->fs->read))(file, p->p_filesz, loadinfo->base+offset) != p->p_filesz) {
1572 prom_printf ("Read failed\n");
1573 prom_release(loadinfo->base, loadinfo->memsize);
1580 /* Return success at loading the Elf64 kernel */
1590 is_elf32(loadinfo_t *loadinfo)
1592 Elf32_Ehdr *e = &(loadinfo->elf.elf32hdr);
1594 return (e->e_ident[EI_MAG0] == ELFMAG0 &&
1595 e->e_ident[EI_MAG1] == ELFMAG1 &&
1596 e->e_ident[EI_MAG2] == ELFMAG2 &&
1597 e->e_ident[EI_MAG3] == ELFMAG3 &&
1598 e->e_ident[EI_CLASS] == ELFCLASS32 &&
1599 e->e_ident[EI_DATA] == ELFDATA2MSB &&
1600 e->e_type == ET_EXEC &&
1601 e->e_machine == EM_PPC);
1605 is_elf64(loadinfo_t *loadinfo)
1607 Elf64_Ehdr *e = &(loadinfo->elf.elf64hdr);
1609 return (e->e_ident[EI_MAG0] == ELFMAG0 &&
1610 e->e_ident[EI_MAG1] == ELFMAG1 &&
1611 e->e_ident[EI_MAG2] == ELFMAG2 &&
1612 e->e_ident[EI_MAG3] == ELFMAG3 &&
1613 e->e_ident[EI_CLASS] == ELFCLASS64 &&
1614 e->e_ident[EI_DATA] == ELFDATA2MSB &&
1615 (e->e_type == ET_EXEC || e->e_type == ET_DYN) &&
1616 e->e_machine == EM_PPC64);
1622 #ifdef CONFIG_SET_COLORMAP
1623 static unsigned char default_colors[] = {
1642 prom_handle scrn = PROM_INVALID_HANDLE;
1644 /* Try Apple's mac-boot screen ihandle */
1645 result = (int)call_prom_return("interpret", 1, 2,
1646 "\" _screen-ihandle\" $find if execute else 0 then", &scrn);
1647 DEBUG_F("Trying to get screen ihandle, result: %d, scrn: %p\n", result, scrn);
1649 if (scrn == 0 || scrn == PROM_INVALID_HANDLE) {
1651 /* Hrm... check to see if stdout is a display */
1652 scrn = call_prom ("instance-to-package", 1, 1, prom_stdout);
1653 DEBUG_F("instance-to-package of stdout is: %p\n", scrn);
1654 if (prom_getprop(scrn, "device_type", type, 32) > 0 && !strncmp(type, "display", 7)) {
1655 DEBUG_F("got it ! stdout is a screen\n");
1658 /* Else, we try to open the package */
1659 scrn = (prom_handle)call_prom( "open", 1, 1, "screen" );
1660 DEBUG_F("Open screen result: %p\n", scrn);
1664 if (scrn == PROM_INVALID_HANDLE) {
1665 prom_printf("No screen device found !\n");
1669 prom_set_color(scrn, i, default_colors[i*3],
1670 default_colors[i*3+1], default_colors[i*3+2]);
1672 prom_printf("\x1b[1;37m\x1b[2;40m");
1674 for (i=0;i<16; i++) {
1675 prom_printf("\x1b[%d;%dm\x1b[1;47m%s \x1b[2;40m %s\n",
1676 ansi_color_table[i].index,
1677 ansi_color_table[i].value,
1678 ansi_color_table[i].name,
1679 ansi_color_table[i].name);
1680 prom_printf("\x1b[%d;%dm\x1b[1;37m%s \x1b[2;30m %s\n",
1681 ansi_color_table[i].index,
1682 ansi_color_table[i].value+10,
1683 ansi_color_table[i].name,
1684 ansi_color_table[i].name);
1686 prom_printf("\x1b[1;37m\x1b[2;40m");
1687 #endif /* COLOR_TEST */
1693 #endif /* CONFIG_SET_COLORMAP */
1702 char conf_path[1024];
1704 if (_machine == _MACH_Pmac)
1707 prom_get_chosen("bootargs", bootargs, sizeof(bootargs));
1708 DEBUG_F("/chosen/bootargs = %s\n", bootargs);
1709 prom_get_chosen("bootpath", bootdevice, BOOTDEVSZ);
1710 DEBUG_F("/chosen/bootpath = %s\n", bootdevice);
1711 if (prom_get_options("ibm,client-architecture-support-reboot",fw_nbr_reboots, FW_NBR_REBOOTSZ) == -1 )
1712 prom_get_options("ibm,fw-nbr-reboots",fw_nbr_reboots, FW_NBR_REBOOTSZ);
1713 fw_reboot_cnt = simple_strtol(fw_nbr_reboots,&endp,10);
1714 if (fw_reboot_cnt > 0L)
1715 prom_get_options("boot-last-label", bootlastlabel, BOOTLASTSZ);
1717 /* If conf= specified on command line, it overrides
1718 Usage: conf=device:partition,/path/to/conffile
1719 Example: On Open Firmware Prompt, type
1720 boot conf=/pci@8000000f8000000/pci@1/pci1014,028C@1/scsi@0/sd@1,0:3,/etc/yaboot.conf */
1722 if (!strncmp(bootargs, "conf=", 5)) {
1723 DEBUG_F("Using conf argument in Open Firmware\n");
1724 char *end = strchr(bootargs,' ');
1728 strcpy(bootdevice, bootargs + 5);
1730 DEBUG_F("Using conf=%s\n", bootdevice);
1732 /* Remove conf=xxx from bootargs */
1734 memmove(bootargs, end+1, strlen(end+1)+1);
1738 if (bootdevice[0] == 0) {
1739 prom_get_options("boot-device", bootdevice, BOOTDEVSZ);
1740 DEBUG_F("boot-device = %s\n", bootdevice);
1742 if (bootdevice[0] == 0) {
1743 prom_printf("Couldn't determine boot device\n");
1747 if (bootoncelabel[0] == 0) {
1748 prom_get_options("boot-once", bootoncelabel,
1749 sizeof(bootoncelabel));
1750 if (bootoncelabel[0] != 0)
1751 DEBUG_F("boot-once: [%s]\n", bootoncelabel);
1753 prom_set_options("boot-once", NULL, 0);
1755 if (!parse_device_path(bootdevice, NULL, -1, "", &boot)) {
1756 prom_printf("%s: Unable to parse\n", bootdevice);
1759 if (_machine == _MACH_bplan && !conf_given)
1761 DEBUG_F("After parse_device_path: dev=%s, part=%d, file=%s\n",
1762 boot.dev, boot.part, boot.file);
1765 if (_machine == _MACH_chrp || _machine == _MACH_bplan)
1766 boot.file = "/etc/";
1767 else if (strlen(boot.file)) {
1768 if (!strncmp(boot.file, "\\\\", 2))
1772 p = last = boot.file;
1782 if (strlen(boot.file))
1783 strcat(boot.file, "\\");
1786 strcpy(conf_path, boot.file);
1787 strcat(conf_path, CONFIG_FILE_NAME);
1788 boot.file = conf_path;
1789 DEBUG_F("After path kludgeup: dev=%s, part=%d, file=%s\n",
1790 boot.dev, boot.part, boot.file);
1794 * If we're doing a netboot, first look for one which matches our
1797 if (prom_get_devtype(boot.dev) == FILE_DEVICE_NET) {
1798 prom_printf("Try to netboot\n");
1799 useconf = load_my_config_file(&boot);
1803 useconf = load_config_file(&boot);
1805 prom_printf("Welcome to yaboot version " VERSION "\n");
1806 prom_printf("Enter \"help\" to get some basic usage information\n");
1808 /* I am fed up with lusers using the wrong partition type and
1809 mailing me *when* it breaks */
1811 if (_machine == _MACH_Pmac) {
1812 char *entry = cfg_get_strg(0, "ptypewarning");
1815 warn = strcmp(entry,
1816 "I_know_the_partition_type_is_wrong_and_will_NOT_send_mail_when_booting_breaks");
1818 ptype = get_part_type(boot.dev, boot.part);
1819 if ((ptype != NULL) && (strcmp(ptype, "Apple_Bootstrap")))
1820 prom_printf("\nWARNING: Bootstrap partition type is wrong: \"%s\"\n"
1821 " type should be: \"Apple_Bootstrap\"\n\n", ptype);
1829 prom_printf("Bye.\n");
1835 * c-file-style: "k&r"