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 *password = NULL;
118 struct boot_fspec_t boot;
119 int _machine = _MACH_Pmac;
122 #ifdef CONFIG_COLOR_TEXT
124 /* Color values for text ui */
125 static struct ansi_color_t {
129 } ansi_color_table[] = {
137 { "light-gray", 0, 37 },
138 { "dark-gray", 1, 30 },
139 { "light-blue", 1, 31 },
140 { "light-green", 1, 32 },
141 { "light-cyan", 1, 33 },
142 { "light-red", 1, 34 },
143 { "light-purple", 1, 35 },
149 /* Default colors for text ui */
152 #endif /* CONFIG_COLOR_TEXT */
156 static int test_data = 0;
158 static int pause_after;
159 static char *pause_message = "Type go<return> to continue.\n";
160 static char given_bootargs[1024];
161 static int given_bootargs_by_user = 0;
163 extern unsigned char linux_logo_red[];
164 extern unsigned char linux_logo_green[];
165 extern unsigned char linux_logo_blue[];
167 #define DEFAULT_TIMEOUT -1
169 /* Entry, currently called directly by crt0 (bss not inited) */
171 extern char* __bss_start;
174 static struct first_info *quik_fip = NULL;
177 yaboot_start (unsigned long r3, unsigned long r4, unsigned long r5)
180 void* malloc_base = NULL;
184 /* OF seems to do it, but I'm not very confident */
185 memset(&__bss_start, 0, &_end - &__bss_start);
187 /* Check for quik first stage bootloader (but I don't think we are
188 * compatible with it anyway, I'll look into backporting to older OF
191 if (r5 == 0xdeadbeef) {
193 quik_fip = (struct first_info *)r4;
196 /* Initialize OF interface */
197 prom_init ((prom_entry) r5);
199 /* Allocate some memory for malloc'ator */
200 for (addr = MALLOCADDR; addr <= MALLOCADDR * 16 ;addr+=0x100000) {
201 malloc_base = prom_claim((void *)addr, MALLOCSIZE, 0);
202 if (malloc_base != (void *)-1) break;
204 if (malloc_base == (void *)-1) {
205 prom_printf("Can't claim malloc buffer (%d bytes at 0x%08x)\n",
206 MALLOCSIZE, MALLOCADDR);
209 malloc_init(malloc_base, MALLOCSIZE);
210 DEBUG_F("Malloc buffer allocated at %p (%d bytes)\n",
211 malloc_base, MALLOCSIZE);
213 /* A few useless DEBUG_F's */
214 DEBUG_F("reloc_offset : %ld (should be 0)\n", reloc_offset());
215 DEBUG_F("test_bss : %d (should be 0)\n", test_bss);
216 DEBUG_F("test_data : %d (should be 0)\n", test_data);
217 DEBUG_F("&test_data : %p\n", &test_data);
218 DEBUG_F("&test_bss : %p\n", &test_bss);
219 DEBUG_F("linked at : 0x%08x\n", TEXTADDR);
221 /* ask the OF info if we're a chrp or pmac */
222 /* we need to set _machine before calling finish_device_tree */
223 root = prom_finddevice("/");
225 static char model[256];
226 if (prom_getprop(root, "device_type", model, 256 ) > 0 &&
227 !strncmp("chrp", model, 4))
228 _machine = _MACH_chrp;
230 if (prom_getprop(root, "model", model, 256 ) > 0 &&
231 !strncmp(model, "IBM", 3))
232 _machine = _MACH_chrp;
236 DEBUG_F("Running on _machine = %d\n", _machine);
240 result = yaboot_main();
242 /* Get rid of malloc pool */
244 prom_release(malloc_base, MALLOCSIZE);
245 DEBUG_F("Malloc buffer released. Exiting with code %d\n",
255 #ifdef CONFIG_COLOR_TEXT
257 * Validify color for text ui
260 check_color_text_ui(char *color)
263 while(ansi_color_table[i].name) {
264 if (!strcmp(color, ansi_color_table[i].name))
270 #endif /* CONFIG_COLOR_TEXT */
273 void print_message_file(char *filename)
277 char *defdev = boot.dev;
278 int defpart = boot.part;
283 struct boot_file_t file;
284 struct boot_fspec_t msgfile;
286 defdev = cfg_get_strg(0, "device");
289 p = cfg_get_strg(0, "partition");
291 n = simple_strtol(p, &endp, 10);
292 if (endp != p && *endp == 0)
296 strncpy(msgpath, filename, sizeof(msgpath));
297 if (!parse_device_path(msgpath, defdev, defpart, "/etc/yaboot.msg", &msgfile)) {
298 prom_printf("%s: Unable to parse\n", msgpath);
302 result = open_file(&msgfile, &file);
303 if (result != FILE_ERR_OK) {
304 prom_printf("%s:%d,", msgfile.dev, msgfile.part);
305 prom_perror(result, msgfile.file);
314 memset(msg, 0, 2001);
316 if (file.fs->read(&file, 2000, msg) <= 0)
319 prom_printf("%s", msg);
323 file.fs->close(&file);
328 /* Currently, the config file must be at the root of the filesystem.
329 * todo: recognize the full path to myself and use it to load the
330 * config file. Handle the "\\" (blessed system folder)
333 load_config_file(struct boot_fspec_t *fspec)
335 char *conf_file = NULL, *p;
336 struct boot_file_t file;
337 int sz, opened = 0, result = 0;
339 /* Allocate a buffer for the config file */
340 conf_file = malloc(CONFIG_FILE_MAX);
342 prom_printf("Can't alloc config file buffer\n");
347 result = open_file(fspec, &file);
348 if (result != FILE_ERR_OK) {
349 prom_printf("%s:%d,", fspec->dev, fspec->part);
350 prom_perror(result, fspec->file);
351 prom_printf("Can't open config file\n");
357 sz = file.fs->read(&file, CONFIG_FILE_MAX, conf_file);
359 prom_printf("Error, can't read config file\n");
362 prom_printf("Config file read, %d bytes\n", sz);
366 file.fs->close(&file);
369 /* Call the parsing code in cfg.c */
370 if (cfg_parse(fspec->file, conf_file, sz) < 0) {
371 prom_printf ("Syntax error or read error config\n");
376 * set the default cf_option to label that has the same MAC addr
377 * it only works if there is a label with the MAC addr on yaboot.conf
379 if (prom_get_devtype(fspec->dev) == FILE_DEVICE_NET) {
380 /* change the variable bellow to get the MAC dinamicaly */
381 char * macaddr = NULL;
384 macaddr = prom_get_mac(prom_get_netinfo());
385 default_mac = cfg_set_default_by_mac(macaddr);
386 if (default_mac >= 1) {
387 prom_printf("Default label was changed to macaddr label.\n");
391 DEBUG_F("Config file successfully parsed, %d bytes\n", sz);
393 /* Now, we do the initialisations stored in the config file */
394 p = cfg_get_strg(0, "init-code");
398 password = cfg_get_strg(0, "password");
400 #ifdef CONFIG_COLOR_TEXT
401 p = cfg_get_strg(0, "fgcolor");
403 DEBUG_F("fgcolor=%s\n", p);
404 fgcolor = check_color_text_ui(p);
406 prom_printf("Invalid fgcolor: \"%s\".\n", p);
409 p = cfg_get_strg(0, "bgcolor");
411 DEBUG_F("bgcolor=%s\n", p);
412 bgcolor = check_color_text_ui(p);
414 prom_printf("Invalid bgcolor: \"%s\".\n", p);
418 sprintf(temp, "%x to background-color", bgcolor);
419 prom_interpret(temp);
426 sprintf(temp, "%x to foreground-color", fgcolor);
427 prom_interpret(temp);
429 #endif /* CONFIG_COLOR_TEXT */
431 p = cfg_get_strg(0, "init-message");
433 prom_printf("%s\n", p);
435 p = cfg_get_strg(0, "message");
437 print_message_file(p);
444 file.fs->close(&file);
453 * Search for config file by MAC address, then by IP address.
454 * Basically copying pxelinux's algorithm.
455 * http://syslinux.zytor.com/pxe.php#config
457 static int load_my_config_file(struct boot_fspec_t *orig_fspec)
459 struct bootp_packet *packet;
461 struct boot_fspec_t fspec = *orig_fspec;
462 char *cfgpath = (_machine == _MACH_chrp) ? "/etc/" : "";
466 packet = prom_get_netinfo();
469 * First, try to match on mac address with the hardware type
473 /* 3 chars per byte in chaddr + 2 chars for htype + /etc/ +\0 */
474 fspec.file = malloc(packet->hlen * 3 + 2 + 6);
478 sprintf(fspec.file, "%s%02x-", cfgpath, packet->htype);
479 strcat(fspec.file, prom_get_mac(packet));
481 rc = load_config_file(&fspec);
486 * Now try to match on IP.
488 /* no need to realloc for /etc/ + 8 chars in yiaddr + \0 */
489 sprintf(fspec.file, "%s%s", cfgpath, prom_get_ip(packet));
491 for (flen = strlen(fspec.file),
492 minlen = strlen(cfgpath); flen > minlen; flen--) {
493 rc = load_config_file(&fspec);
496 /* Chop one digit off the end, try again */
497 fspec.file[flen - 1] = '\0';
501 if (rc) /* modify original only on success */
502 orig_fspec->file = fspec.file;
508 void maintabfunc (void)
512 prom_printf("boot: %s", cbuff);
517 word_split(char **linep, char **paramsp)
532 while (*p != 0 && *p != ' ')
541 make_params(char *label, char *params)
544 static char buffer[2048];
549 p = cfg_get_strg(label, "literal");
561 p = cfg_get_strg(label, "root");
568 if (cfg_get_flag(label, "read-only")) {
572 if (cfg_get_flag(label, "read-write")) {
576 p = cfg_get_strg(label, "ramdisk");
578 strcpy (q, "ramdisk=");
583 p = cfg_get_strg(label, "initrd-size");
585 strcpy (q, "ramdisk_size=");
590 if (cfg_get_flag(label, "novideo")) {
591 strcpy (q, "video=ofonly");
595 p = cfg_get_strg (label, "append");
602 pause_after = cfg_get_flag (label, "pause-after");
603 p = cfg_get_strg(label, "pause-message");
612 void check_password(char *str)
616 prom_printf("\n%s", str);
617 for (i = 0; i < 3; i++) {
618 prom_printf ("\nPassword: ");
620 cmdedit ((void (*)(void)) 0, 1);
622 #ifdef USE_MD5_PASSWORDS
623 if (!strncmp (password, "$1$", 3)) {
624 if (!check_md5_password(passwdbuff, password))
627 else if (!strcmp (password, passwdbuff))
630 if (!strcmp (password, passwdbuff))
632 #endif /* USE_MD5_PASSWORDS */
635 prom_printf ("Incorrect password. Try again.");
638 prom_printf(" ___________________\n< Permission denied >\n -------------------\n"
639 " \\ ^__^\n \\ (oo)\\_______\n (__)\\ )\\/\\\n"
640 " ||----w |\n || ||\n");
642 prom_interpret("reset-all");
645 int get_params(struct boot_param_t* params)
649 char defdevice_bak[1024];
652 char *imagename = 0, *label;
657 static int first = 1;
658 static char imagepath[1024];
659 static char initrdpath[1024];
660 static char sysmappath[1024];
661 static char manualinitrd[1024];
662 static int definitrd = 1, hasarg = 0;
665 memset(params, 0, sizeof(*params));
667 params->kernel.part = -1;
668 params->rd.part = -1;
669 params->sysmap.part = -1;
676 imagename = bootargs;
677 word_split(&imagename, ¶ms->args);
678 timeout = DEFAULT_TIMEOUT;
680 prom_printf("Default supplied on the command line: %s ", imagename);
682 prom_printf("%s", params->args);
685 if (useconf && (q = cfg_get_strg(0, "timeout")) != 0 && *q != 0)
686 timeout = simple_strtol(q, NULL, 0);
689 prom_printf("boot: ");
694 end = beg + 100 * timeout;
696 c = prom_nbgetchar();
697 } while (c == -1 && prom_getms() <= end);
701 else if (c != '\n' && c != '\t' && c != '\r' && c != '\b' ) {
707 if (c != -1 && c != '\n' && c != '\r') {
710 } else if (c >= ' ') {
713 if ((cfg_get_flag (cbuff, "single-key")) && useconf) {
716 prom_printf("%s\n", cbuff);
721 if (c == '\n' || c == '\r') {
723 if (bootoncelabel[0] != 0)
724 imagename = bootoncelabel;
726 imagename = cfg_get_default();
729 prom_printf("%s", imagename);
731 prom_printf(" %s", params->args);
733 } else if (!singlekey) {
734 cmdedit(maintabfunc, 0);
736 strcpy(given_bootargs, cbuff);
737 given_bootargs_by_user = 1;
739 word_split(&imagename, ¶ms->args);
742 /* initrd setup via cmd console */
743 /* first, check if the user uses it with some label */
744 if (!strncmp(params->args, "initrd=", 7)) {
745 DEBUG_F("params->args: %s\n", params->args);
748 /* after, check if there is the 'initrd=' in the imagename string */
749 if (!strncmp(imagename, "initrd=", 7) || !definitrd) {
751 /* return the value of definitrd to 1 */
755 /* args = "initrd=blah" */
766 /* copy the string after the '=' to manualinitrd */
767 strcpy(manualinitrd, args+7);
769 prom_printf("New initrd file specified: %s\n", manualinitrd);
771 prom_printf("ERROR: no initrd specified!\n");
775 /* set imagename with the default values of the config file */
776 if ((prom_get_devtype(boot.dev) == FILE_DEVICE_NET) && !hasarg)
777 imagename = cfg_get_default();
779 imagename = cfg_get_default();
782 /* chrp gets this wrong, force it -- Cort */
783 if ( useconf && (!imagename || imagename[0] == 0 ))
784 imagename = cfg_get_default();
787 defdevice = boot.dev;
789 strcpy(defdevice_bak,defdevice);
792 defdevice = cfg_get_strg(0, "device");
793 p = cfg_get_strg(0, "partition");
795 n = simple_strtol(p, &endp, 10);
796 if (endp != p && *endp == 0)
799 p = cfg_get_strg(0, "pause-message");
802 if (cfg_get_flag(0, "restricted"))
804 p = cfg_get_strg(imagename, "image");
808 defdevice = cfg_get_strg(label, "device");
809 if(!defdevice) defdevice=boot.dev;
810 p = cfg_get_strg(label, "partition");
812 n = simple_strtol(p, &endp, 10);
813 if (endp != p && *endp == 0)
816 if (cfg_get_flag(label, "restricted"))
819 if (params->args && password && restricted)
820 check_password ("To specify arguments for this image "
821 "you must enter the password.");
822 else if (password && !restricted)
823 check_password ("This image is restricted.");
825 params->args = make_params(label, params->args);
829 if (!strcmp (imagename, "help")) {
830 /* FIXME: defdevice shouldn't need to be reset all over the place */
831 if(!defdevice) defdevice = boot.dev;
833 "\nPress the tab key for a list of defined images.\n"
834 "The label marked with a \"*\" is is the default image, "
835 "press <return> to boot it.\n\n"
836 "To boot any other label simply type its name and press <return>.\n\n"
837 "To boot a kernel image which is not defined in the yaboot configuration \n"
838 "file, enter the kernel image name as [[device:][partno],]/path, where \n"
839 "\"device:\" is the OpenFirmware device path to the disk the image \n"
840 "resides on, and \"partno\" is the partition number the image resides on.\n"
841 "Note that the comma (,) is only required if you specify an OpenFirmware\n"
842 "device, if you only specify a filename you should not start it with a \",\"\n\n"
843 "To boot a alternative initrd file rather than specified in the yaboot\n"
844 "configuration file, use the \"initrd\" command on Yaboot's prompt: \n"
845 "\"initrd=[name.img]\". This will load the \"name.img\" file after the default\n"
846 "kernel image. You can, also, specify a different initrd file to any other\n"
847 "label of the yaboot configuration file. Just type \"label initrd=[name.img]\"\n"
848 "and the specified initrd file will be loaded.\n\n"
849 "To load an alternative config file rather than /etc/yaboot.conf, enter\n"
850 "its device, partno and path, on Open Firmware Prompt:\n"
851 "boot conf=device:partno,/path/to/configfile\n."
852 "To reload the config file or load a new one, use the \"conf\" command\n"
853 "on Yaboot's prompt:\n"
854 "conf [device=device] [partition=partno] [file=/path/to/configfile]\n\n"
855 "If you omit \"device\" and \"partno\", Yaboot will use their current\n"
856 "values. You can check them by entering \"conf\" on Yaboot's prompt.\n");
861 if (!strcmp (imagename, "halt")) {
863 check_password ("Restricted command.");
867 if (!strcmp (imagename, "bye")) {
869 check_password ("Restricted command.");
875 if (!strncmp (imagename, "conf", 4)) {
877 // imagename = "conf file=blah dev=bleh part=blih"
878 DEBUG_F("Loading user-specified config file: %s\n",imagename);
880 check_password ("Restricted command.");
884 // args= "file=blah dev=bleh part=blih"
885 char *args = params->args;
889 // set a pointer to the first space in args
890 char *space = strchr(args,' ');
894 char temp[1024] = "0";
896 // copy next argument to temp
897 strncpy(temp, args, space-args);
899 // parse temp and set boot arguments
900 if (!strncmp (temp, "file=", 5)){
901 DEBUG_F("conf file: %s\n", temp+5);
902 strcpy(boot.file, temp+5);
903 } else if (!strncmp (temp, "device=", 7)){
904 DEBUG_F("conf device: %s\n", temp+7);
905 strcpy(boot.dev, temp+7);
906 } else if (!strncmp (temp, "partition=", 10)){
907 DEBUG_F("conf partition: %s\n", temp+10);
908 boot.part=simple_strtol(temp+10,NULL,10);
912 // set the pointer to the next space in args;
913 // set the loop control variable
914 if (strlen(space)>1){
915 // Go to the next argument
919 if (strchr(args,' ') == NULL)
920 space = &args[strlen(args)];
922 space = strchr(args,' ');
929 prom_printf("Loading config file...\n");
930 useconf = load_config_file(&boot);
932 if ((q = cfg_get_strg(0, "timeout")) != 0 && *q != 0)
933 timeout = simple_strtol(q, NULL, 0);
935 prom_printf("Restoring default values.\n");
936 strcpy(boot.file,"");
937 strcpy(boot.dev, defdevice_bak);
942 prom_printf("Current configuration:\n");
943 prom_printf("device: %s\n", boot.dev);
945 prom_printf("partition: auto\n");
947 prom_printf("partition: %d\n", boot.part);
948 if (strlen(boot.file))
949 prom_printf("file: %s\n", boot.file);
951 prom_printf("file: /etc/%s\n",CONFIG_FILE_NAME);
960 if (imagename[0] == '$') {
961 /* forth command string */
963 check_password ("OpenFirmware commands are restricted.");
964 prom_interpret(imagename+1);
968 strncpy(imagepath, imagename, 1024);
970 if (!label && password)
971 check_password ("To boot a custom image you must enter the password.");
973 if (!parse_device_path(imagepath, defdevice, defpart,
974 "/vmlinux", ¶ms->kernel)) {
975 prom_printf("%s: Unable to parse\n", imagepath);
978 DEBUG_F("after parse_device_path: dev=%s part=%d file=%s\n", params->kernel.dev, params->kernel.part, params->kernel.file);
980 p = cfg_get_strg(label, "initrd");
983 /* check if user seted to use a initrd file from boot console */
984 if (!definitrd && p != manualinitrd) {
985 if (manualinitrd[0] != "/" && (prom_get_devtype(defdevice_bak) != FILE_DEVICE_NET)) {
986 strcpy(initrdpath, "/");
987 strcat(initrdpath, manualinitrd);
989 strncpy(initrdpath, manualinitrd, 1024);
991 strncpy(initrdpath, p, 1024);
993 DEBUG_F("Parsing initrd path <%s>\n", initrdpath);
994 if (!parse_device_path(initrdpath, defdevice, defpart,
995 "/root.bin", ¶ms->rd)) {
996 prom_printf("%s: Unable to parse\n", imagepath);
1000 p = cfg_get_strg(label, "sysmap");
1002 DEBUG_F("Parsing sysmap path <%s>\n", p);
1003 strncpy(sysmappath, p, 1024);
1004 if (!parse_device_path(sysmappath, defdevice, defpart,
1005 "/boot/System.map", ¶ms->sysmap)) {
1006 prom_printf("%s: Unable to parse\n", imagepath);
1014 /* This is derived from quik core. To be changed to first parse the headers
1015 * doing lazy-loading, and then claim the memory before loading the kernel
1017 * We also need to add initrd support to this whole mecanism
1020 yaboot_text_ui(void)
1022 #define MAX_HEADERS 32
1024 struct boot_file_t file;
1026 static struct boot_param_t params;
1028 unsigned long initrd_size;
1030 unsigned long sysmap_size;
1031 kernel_entry_t kernel_entry;
1032 struct bi_record* birec;
1034 loadinfo_t loadinfo;
1035 void *initrd_more,*initrd_want;
1036 unsigned long initrd_read;
1038 loadinfo.load_loc = 0;
1046 if (get_params(¶ms))
1048 if (!params.kernel.file)
1051 prom_printf("Please wait, loading kernel...\n");
1053 memset(&file, 0, sizeof(file));
1055 if (strlen(boot.file) && !strcmp(boot.file,"\\\\") && params.kernel.file[0] != '/'
1056 && params.kernel.file[0] != '\\') {
1057 loc=(char*)malloc(strlen(params.kernel.file)+3);
1059 prom_printf ("malloc error\n");
1062 strcpy(loc,boot.file);
1063 strcat(loc,params.kernel.file);
1064 free(params.kernel.file);
1065 params.kernel.file=loc;
1067 result = open_file(¶ms.kernel, &file);
1068 if (result != FILE_ERR_OK) {
1069 prom_printf("%s:%d,", params.kernel.dev, params.kernel.part);
1070 prom_perror(result, params.kernel.file);
1074 /* Read the Elf e_ident, e_type and e_machine fields to
1075 * determine Elf file type
1077 if (file.fs->read(&file, sizeof(Elf_Ident), &loadinfo.elf) < sizeof(Elf_Ident)) {
1078 prom_printf("\nCan't read Elf e_ident/e_type/e_machine info\n");
1079 file.fs->close(&file);
1080 memset(&file, 0, sizeof(file));
1084 if (is_elf32(&loadinfo)) {
1085 if (!load_elf32(&file, &loadinfo)) {
1086 file.fs->close(&file);
1087 memset(&file, 0, sizeof(file));
1090 prom_printf(" Elf32 kernel loaded...\n");
1091 } else if (is_elf64(&loadinfo)) {
1092 if (!load_elf64(&file, &loadinfo)) {
1093 file.fs->close(&file);
1094 memset(&file, 0, sizeof(file));
1097 prom_printf(" Elf64 kernel loaded...\n");
1099 prom_printf ("%s: Not a valid ELF image\n", params.kernel.file);
1100 file.fs->close(&file);
1101 memset(&file, 0, sizeof(file));
1104 file.fs->close(&file);
1105 memset(&file, 0, sizeof(file));
1107 /* If sysmap, load it (only if booting a vmlinux).
1109 if (flat_vmlinux && params.sysmap.file) {
1110 prom_printf("Loading System.map ...\n");
1111 if(strlen(boot.file) && !strcmp(boot.file,"\\\\") && params.sysmap.file[0] != '/'
1112 && params.sysmap.file[0] != '\\') {
1114 loc=(char*)malloc(strlen(params.sysmap.file)+3);
1116 prom_printf ("malloc error\n");
1119 strcpy(loc,boot.file);
1120 strcat(loc,params.sysmap.file);
1121 free(params.sysmap.file);
1122 params.sysmap.file=loc;
1125 result = open_file(¶ms.sysmap, &file);
1126 if (result != FILE_ERR_OK) {
1127 prom_printf("%s:%d,", params.sysmap.dev, params.sysmap.part);
1128 prom_perror(result, params.sysmap.file);
1131 sysmap_base = prom_claim(loadinfo.base+loadinfo.memsize, 0x100000, 0);
1132 if (sysmap_base == (void *)-1) {
1133 prom_printf("Claim failed for sysmap memory\n");
1137 sysmap_size = file.fs->read(&file, 0xfffff, sysmap_base);
1138 if (sysmap_size == 0)
1141 ((char *)sysmap_base)[sysmap_size++] = 0;
1143 file.fs->close(&file);
1144 memset(&file, 0, sizeof(file));
1147 prom_printf("System.map loaded at %p, size: %lu Kbytes\n",
1148 sysmap_base, sysmap_size >> 10);
1149 loadinfo.memsize += _ALIGN(0x100000, 0x1000);
1151 prom_printf("System.map load failed !\n");
1156 /* If ramdisk, load it (only if booting a vmlinux). For now, we
1157 * can't tell the size it will be so we claim an arbitrary amount
1160 if (flat_vmlinux && params.rd.file) {
1161 if(strlen(boot.file) && !strcmp(boot.file,"\\\\") && params.rd.file[0] != '/'
1162 && params.kernel.file[0] != '\\')
1165 loc=(char*)malloc(strlen(params.rd.file)+3);
1167 prom_printf ("Malloc error\n");
1170 strcpy(loc,boot.file);
1171 strcat(loc,params.rd.file);
1172 free(params.rd.file);
1175 prom_printf("Loading ramdisk...\n");
1176 result = open_file(¶ms.rd, &file);
1177 if (result != FILE_ERR_OK) {
1178 prom_printf("%s:%d,", params.rd.dev, params.rd.part);
1179 prom_perror(result, params.rd.file);
1182 #define INITRD_CHUNKSIZE 0x100000
1183 initrd_base = prom_claim(loadinfo.base+loadinfo.memsize, INITRD_CHUNKSIZE, 0);
1184 if (initrd_base == (void *)-1) {
1185 prom_printf("Claim failed for initrd memory\n");
1188 initrd_size = file.fs->read(&file, INITRD_CHUNKSIZE, initrd_base);
1189 if (initrd_size == 0)
1191 initrd_read = initrd_size;
1192 initrd_more = initrd_base;
1193 while (initrd_read == INITRD_CHUNKSIZE ) { /* need to read more? */
1194 initrd_want = (void *)((unsigned long)initrd_more+INITRD_CHUNKSIZE);
1195 initrd_more = prom_claim(initrd_want, INITRD_CHUNKSIZE, 0);
1196 if (initrd_more != initrd_want) {
1197 prom_printf("Claim failed for initrd memory at %p rc=%p\n",initrd_want,initrd_more);
1201 initrd_read = file.fs->read(&file, INITRD_CHUNKSIZE, initrd_more);
1202 DEBUG_F(" block at %p rc=%lu\n",initrd_more,initrd_read);
1203 initrd_size += initrd_read;
1206 file.fs->close(&file);
1207 memset(&file, 0, sizeof(file));
1210 prom_printf("ramdisk loaded at %p, size: %lu Kbytes\n",
1211 initrd_base, initrd_size >> 10);
1213 prom_printf("ramdisk load failed !\n");
1218 DEBUG_F("setting kernel args to: %s\n", params.args);
1219 prom_setargs(params.args);
1220 DEBUG_F("flushing icache...");
1221 flush_icache_range ((long)loadinfo.base, (long)loadinfo.base+loadinfo.memsize);
1226 * Fill new boot infos (only if booting a vmlinux).
1228 * The birec is low on memory, probably inside the malloc pool,
1229 * so we don't write it earlier. At this point, we should not
1230 * use anything coming from the malloc pool.
1232 birec = (struct bi_record *)_ALIGN(loadinfo.filesize+(1<<20)-1,(1<<20));
1234 /* We make sure it's mapped. We map only 64k for now, it's
1235 * plenty enough we don't claim since this precise memory
1236 * range may already be claimed by the malloc pool.
1238 prom_map (birec, birec, 0x10000);
1239 DEBUG_F("birec at %p\n", birec);
1242 birec->tag = BI_FIRST;
1243 birec->size = sizeof(struct bi_record);
1244 birec = (struct bi_record *)((ulong)birec + birec->size);
1246 birec->tag = BI_BOOTLOADER_ID;
1247 sprintf( (char *)birec->data, "yaboot");
1248 birec->size = sizeof(struct bi_record) + strlen("yaboot") + 1;
1249 birec = (struct bi_record *)((ulong)birec + birec->size);
1251 birec->tag = BI_MACHTYPE;
1252 birec->data[0] = _machine;
1253 birec->size = sizeof(struct bi_record) + sizeof(ulong);
1254 birec = (struct bi_record *)((ulong)birec + birec->size);
1257 birec->tag = BI_SYSMAP;
1258 birec->data[0] = (ulong)sysmap_base;
1259 birec->data[1] = sysmap_size;
1260 birec->size = sizeof(struct bi_record) + sizeof(ulong)*2;
1261 birec = (struct bi_record *)((ulong)birec + birec->size);
1263 birec->tag = BI_LAST;
1264 birec->size = sizeof(struct bi_record);
1265 birec = (struct bi_record *)((ulong)birec + birec->size);
1268 /* compute the kernel's entry point. */
1269 kernel_entry = loadinfo.base + loadinfo.entry - loadinfo.load_loc;
1271 DEBUG_F("Kernel entry point = %p\n", kernel_entry);
1272 DEBUG_F("kernel: arg1 = %p,\n"
1273 " arg2 = 0x%08lx,\n"
1277 initrd_base + loadinfo.load_loc, initrd_size, prom, 0, 0);
1279 DEBUG_F("Entering kernel...\n");
1281 /* call the kernel with our stack. */
1282 kernel_entry(initrd_base + loadinfo.load_loc, initrd_size, prom, 0, 0);
1290 load_elf32(struct boot_file_t *file, loadinfo_t *loadinfo)
1293 Elf32_Ehdr *e = &(loadinfo->elf.elf32hdr);
1295 int size = sizeof(Elf32_Ehdr) - sizeof(Elf_Ident);
1296 unsigned long loadaddr;
1298 /* Read the rest of the Elf header... */
1299 if ((*(file->fs->read))(file, size, &e->e_version) < size) {
1300 prom_printf("\nCan't read Elf32 image header\n");
1304 DEBUG_F("Elf32 header:\n");
1305 DEBUG_F(" e.e_type = %d\n", (int)e->e_type);
1306 DEBUG_F(" e.e_machine = %d\n", (int)e->e_machine);
1307 DEBUG_F(" e.e_version = %d\n", (int)e->e_version);
1308 DEBUG_F(" e.e_entry = 0x%08x\n", (int)e->e_entry);
1309 DEBUG_F(" e.e_phoff = 0x%08x\n", (int)e->e_phoff);
1310 DEBUG_F(" e.e_shoff = 0x%08x\n", (int)e->e_shoff);
1311 DEBUG_F(" e.e_flags = %d\n", (int)e->e_flags);
1312 DEBUG_F(" e.e_ehsize = 0x%08x\n", (int)e->e_ehsize);
1313 DEBUG_F(" e.e_phentsize = 0x%08x\n", (int)e->e_phentsize);
1314 DEBUG_F(" e.e_phnum = %d\n", (int)e->e_phnum);
1316 loadinfo->entry = e->e_entry;
1318 if (e->e_phnum > MAX_HEADERS) {
1319 prom_printf ("Can only load kernels with one program header\n");
1323 ph = (Elf32_Phdr *)malloc(sizeof(Elf32_Phdr) * e->e_phnum);
1325 prom_printf ("Malloc error\n");
1329 /* Now, we read the section header */
1330 if ((*(file->fs->seek))(file, e->e_phoff) != FILE_ERR_OK) {
1331 prom_printf ("seek error\n");
1334 if ((*(file->fs->read))(file, sizeof(Elf32_Phdr) * e->e_phnum, ph) !=
1335 sizeof(Elf32_Phdr) * e->e_phnum) {
1336 prom_printf ("read error\n");
1340 /* Scan through the program header
1341 * HACK: We must return the _memory size of the kernel image, not the
1342 * file size (because we have to leave room before other boot
1343 * infos. This code works as a side effect of the fact that
1344 * we have one section and vaddr == p_paddr
1346 loadinfo->memsize = loadinfo->filesize = loadinfo->offset = 0;
1348 for (i = 0; i < e->e_phnum; ++i, ++p) {
1349 if (p->p_type != PT_LOAD || p->p_offset == 0)
1351 if (loadinfo->memsize == 0) {
1352 loadinfo->offset = p->p_offset;
1353 loadinfo->memsize = p->p_memsz;
1354 loadinfo->filesize = p->p_filesz;
1355 loadinfo->load_loc = p->p_vaddr;
1357 loadinfo->memsize = p->p_offset + p->p_memsz - loadinfo->offset; /* XXX Bogus */
1358 loadinfo->filesize = p->p_offset + p->p_filesz - loadinfo->offset;
1362 if (loadinfo->memsize == 0) {
1363 prom_printf("Can't find a loadable segment !\n");
1367 /* leave some room (1Mb) for boot infos */
1368 loadinfo->memsize = _ALIGN(loadinfo->memsize,(1<<20)) + 0x100000;
1369 /* Claim OF memory */
1370 DEBUG_F("Before prom_claim, mem_sz: 0x%08lx\n", loadinfo->memsize);
1372 /* Determine whether we are trying to boot a vmlinux or some
1373 * other binary image (eg, zImage). We load vmlinux's at
1374 * KERNELADDR and all other binaries at their e_entry value.
1376 if (e->e_entry == KERNEL_LINK_ADDR_PPC32) {
1378 loadaddr = KERNELADDR;
1381 loadaddr = loadinfo->load_loc;
1384 loadinfo->base = prom_claim_chunk((void *)loadaddr, loadinfo->memsize, 0);
1385 if (loadinfo->base == (void *)-1) {
1386 prom_printf("Claim error, can't allocate kernel memory\n");
1390 DEBUG_F("After ELF parsing, load base: %p, mem_sz: 0x%08lx\n",
1391 loadinfo->base, loadinfo->memsize);
1392 DEBUG_F(" wanted load base: 0x%08lx, mem_sz: 0x%08lx\n",
1393 loadaddr, loadinfo->memsize);
1395 /* Load the program segments... */
1397 for (i = 0; i < e->e_phnum; ++i, ++p) {
1398 unsigned long offset;
1399 if (p->p_type != PT_LOAD || p->p_offset == 0)
1402 /* Now, we skip to the image itself */
1403 if ((*(file->fs->seek))(file, p->p_offset) != FILE_ERR_OK) {
1404 prom_printf ("Seek error\n");
1405 prom_release(loadinfo->base, loadinfo->memsize);
1408 offset = p->p_vaddr - loadinfo->load_loc;
1409 if ((*(file->fs->read))(file, p->p_filesz, loadinfo->base+offset) != p->p_filesz) {
1410 prom_printf ("Read failed\n");
1411 prom_release(loadinfo->base, loadinfo->memsize);
1418 /* Return success at loading the Elf32 kernel */
1428 load_elf64(struct boot_file_t *file, loadinfo_t *loadinfo)
1431 Elf64_Ehdr *e = &(loadinfo->elf.elf64hdr);
1433 int size = sizeof(Elf64_Ehdr) - sizeof(Elf_Ident);
1434 unsigned long loadaddr;
1436 /* Read the rest of the Elf header... */
1437 if ((*(file->fs->read))(file, size, &e->e_version) < size) {
1438 prom_printf("\nCan't read Elf64 image header\n");
1442 DEBUG_F("Elf64 header:\n");
1443 DEBUG_F(" e.e_type = %d\n", (int)e->e_type);
1444 DEBUG_F(" e.e_machine = %d\n", (int)e->e_machine);
1445 DEBUG_F(" e.e_version = %d\n", (int)e->e_version);
1446 DEBUG_F(" e.e_entry = 0x%016lx\n", (long)e->e_entry);
1447 DEBUG_F(" e.e_phoff = 0x%016lx\n", (long)e->e_phoff);
1448 DEBUG_F(" e.e_shoff = 0x%016lx\n", (long)e->e_shoff);
1449 DEBUG_F(" e.e_flags = %d\n", (int)e->e_flags);
1450 DEBUG_F(" e.e_ehsize = 0x%08x\n", (int)e->e_ehsize);
1451 DEBUG_F(" e.e_phentsize = 0x%08x\n", (int)e->e_phentsize);
1452 DEBUG_F(" e.e_phnum = %d\n", (int)e->e_phnum);
1454 loadinfo->entry = e->e_entry;
1456 if (e->e_phnum > MAX_HEADERS) {
1457 prom_printf ("Can only load kernels with one program header\n");
1461 ph = (Elf64_Phdr *)malloc(sizeof(Elf64_Phdr) * e->e_phnum);
1463 prom_printf ("Malloc error\n");
1467 /* Now, we read the section header */
1468 if ((*(file->fs->seek))(file, e->e_phoff) != FILE_ERR_OK) {
1469 prom_printf ("Seek error\n");
1472 if ((*(file->fs->read))(file, sizeof(Elf64_Phdr) * e->e_phnum, ph) !=
1473 sizeof(Elf64_Phdr) * e->e_phnum) {
1474 prom_printf ("Read error\n");
1478 /* Scan through the program header
1479 * HACK: We must return the _memory size of the kernel image, not the
1480 * file size (because we have to leave room before other boot
1481 * infos. This code works as a side effect of the fact that
1482 * we have one section and vaddr == p_paddr
1484 loadinfo->memsize = loadinfo->filesize = loadinfo->offset = 0;
1486 for (i = 0; i < e->e_phnum; ++i, ++p) {
1487 if (p->p_type != PT_LOAD || p->p_offset == 0)
1489 if (loadinfo->memsize == 0) {
1490 loadinfo->offset = p->p_offset;
1491 loadinfo->memsize = p->p_memsz;
1492 loadinfo->filesize = p->p_filesz;
1493 loadinfo->load_loc = p->p_vaddr;
1495 loadinfo->memsize = p->p_offset + p->p_memsz - loadinfo->offset; /* XXX Bogus */
1496 loadinfo->filesize = p->p_offset + p->p_filesz - loadinfo->offset;
1500 if (loadinfo->memsize == 0) {
1501 prom_printf("Can't find a loadable segment !\n");
1505 /* leave some room (1Mb) for boot infos */
1506 loadinfo->memsize = _ALIGN(loadinfo->memsize,(1<<20)) + 0x100000;
1507 /* Claim OF memory */
1508 DEBUG_F("Before prom_claim, mem_sz: 0x%08lx\n", loadinfo->memsize);
1510 /* Determine whether we are trying to boot a vmlinux or some
1511 * other binary image (eg, zImage). We load vmlinux's at
1512 * KERNELADDR and all other binaries at their e_entry value.
1514 if (e->e_entry == KERNEL_LINK_ADDR_PPC64) {
1516 loadaddr = KERNELADDR;
1519 loadaddr = e->e_entry;
1522 loadinfo->base = prom_claim_chunk((void *)loadaddr, loadinfo->memsize, 0);
1523 if (loadinfo->base == (void *)-1) {
1524 prom_printf("Claim error, can't allocate kernel memory\n");
1528 DEBUG_F("After ELF parsing, load base: %p, mem_sz: 0x%08lx\n",
1529 loadinfo->base, loadinfo->memsize);
1530 DEBUG_F(" wanted load base: 0x%08lx, mem_sz: 0x%08lx\n",
1531 loadaddr, loadinfo->memsize);
1533 /* Load the program segments... */
1535 for (i = 0; i < e->e_phnum; ++i, ++p) {
1536 unsigned long offset;
1537 if (p->p_type != PT_LOAD || p->p_offset == 0)
1540 /* Now, we skip to the image itself */
1541 if ((*(file->fs->seek))(file, p->p_offset) != FILE_ERR_OK) {
1542 prom_printf ("Seek error\n");
1543 prom_release(loadinfo->base, loadinfo->memsize);
1546 offset = p->p_vaddr - loadinfo->load_loc;
1547 if ((*(file->fs->read))(file, p->p_filesz, loadinfo->base+offset) != p->p_filesz) {
1548 prom_printf ("Read failed\n");
1549 prom_release(loadinfo->base, loadinfo->memsize);
1556 /* Return success at loading the Elf64 kernel */
1566 is_elf32(loadinfo_t *loadinfo)
1568 Elf32_Ehdr *e = &(loadinfo->elf.elf32hdr);
1570 return (e->e_ident[EI_MAG0] == ELFMAG0 &&
1571 e->e_ident[EI_MAG1] == ELFMAG1 &&
1572 e->e_ident[EI_MAG2] == ELFMAG2 &&
1573 e->e_ident[EI_MAG3] == ELFMAG3 &&
1574 e->e_ident[EI_CLASS] == ELFCLASS32 &&
1575 e->e_ident[EI_DATA] == ELFDATA2MSB &&
1576 e->e_type == ET_EXEC &&
1577 e->e_machine == EM_PPC);
1581 is_elf64(loadinfo_t *loadinfo)
1583 Elf64_Ehdr *e = &(loadinfo->elf.elf64hdr);
1585 return (e->e_ident[EI_MAG0] == ELFMAG0 &&
1586 e->e_ident[EI_MAG1] == ELFMAG1 &&
1587 e->e_ident[EI_MAG2] == ELFMAG2 &&
1588 e->e_ident[EI_MAG3] == ELFMAG3 &&
1589 e->e_ident[EI_CLASS] == ELFCLASS64 &&
1590 e->e_ident[EI_DATA] == ELFDATA2MSB &&
1591 e->e_type == ET_EXEC &&
1592 e->e_machine == EM_PPC64);
1598 #ifdef CONFIG_SET_COLORMAP
1599 static unsigned char default_colors[] = {
1618 prom_handle scrn = PROM_INVALID_HANDLE;
1620 /* Try Apple's mac-boot screen ihandle */
1621 result = (int)call_prom_return("interpret", 1, 2,
1622 "\" _screen-ihandle\" $find if execute else 0 then", &scrn);
1623 DEBUG_F("Trying to get screen ihandle, result: %d, scrn: %p\n", result, scrn);
1625 if (scrn == 0 || scrn == PROM_INVALID_HANDLE) {
1627 /* Hrm... check to see if stdout is a display */
1628 scrn = call_prom ("instance-to-package", 1, 1, prom_stdout);
1629 DEBUG_F("instance-to-package of stdout is: %p\n", scrn);
1630 if (prom_getprop(scrn, "device_type", type, 32) > 0 && !strncmp(type, "display", 7)) {
1631 DEBUG_F("got it ! stdout is a screen\n");
1634 /* Else, we try to open the package */
1635 scrn = (prom_handle)call_prom( "open", 1, 1, "screen" );
1636 DEBUG_F("Open screen result: %p\n", scrn);
1640 if (scrn == PROM_INVALID_HANDLE) {
1641 prom_printf("No screen device found !\n");
1645 prom_set_color(scrn, i, default_colors[i*3],
1646 default_colors[i*3+1], default_colors[i*3+2]);
1648 prom_printf("\x1b[1;37m\x1b[2;40m");
1650 for (i=0;i<16; i++) {
1651 prom_printf("\x1b[%d;%dm\x1b[1;47m%s \x1b[2;40m %s\n",
1652 ansi_color_table[i].index,
1653 ansi_color_table[i].value,
1654 ansi_color_table[i].name,
1655 ansi_color_table[i].name);
1656 prom_printf("\x1b[%d;%dm\x1b[1;37m%s \x1b[2;30m %s\n",
1657 ansi_color_table[i].index,
1658 ansi_color_table[i].value+10,
1659 ansi_color_table[i].name,
1660 ansi_color_table[i].name);
1662 prom_printf("\x1b[1;37m\x1b[2;40m");
1663 #endif /* COLOR_TEST */
1669 #endif /* CONFIG_SET_COLORMAP */
1677 char conf_path[1024];
1679 if (_machine == _MACH_Pmac)
1682 prom_get_chosen("bootargs", bootargs, sizeof(bootargs));
1683 DEBUG_F("/chosen/bootargs = %s\n", bootargs);
1684 prom_get_chosen("bootpath", bootdevice, BOOTDEVSZ);
1685 DEBUG_F("/chosen/bootpath = %s\n", bootdevice);
1687 /* If conf= specified on command line, it overrides
1688 Usage: conf=device:partition,/path/to/conffile
1689 Example: On Open Firmware Prompt, type
1690 boot conf=/pci@8000000f8000000/pci@1/pci1014,028C@1/scsi@0/sd@1,0:3,/etc/yaboot.conf */
1692 if (!strncmp(bootargs, "conf=", 5)) {
1693 DEBUG_F("Using conf argument in Open Firmware\n");
1694 char *end = strchr(bootargs,' ');
1698 strcpy(bootdevice, bootargs + 5);
1700 DEBUG_F("Using conf=%s\n", bootdevice);
1702 /* Remove conf=xxx from bootargs */
1704 memmove(bootargs, end+1, strlen(end+1)+1);
1708 if (bootdevice[0] == 0) {
1709 prom_get_options("boot-device", bootdevice, BOOTDEVSZ);
1710 DEBUG_F("boot-device = %s\n", bootdevice);
1712 if (bootdevice[0] == 0) {
1713 prom_printf("Couldn't determine boot device\n");
1717 if (bootoncelabel[0] == 0) {
1718 prom_get_options("boot-once", bootoncelabel,
1719 sizeof(bootoncelabel));
1720 if (bootoncelabel[0] != 0)
1721 DEBUG_F("boot-once: [%s]\n", bootoncelabel);
1723 prom_set_options("boot-once", NULL, 0);
1725 if (!parse_device_path(bootdevice, NULL, -1, "", &boot)) {
1726 prom_printf("%s: Unable to parse\n", bootdevice);
1729 DEBUG_F("After parse_device_path: dev=%s, part=%d, file=%s\n",
1730 boot.dev, boot.part, boot.file);
1733 if (_machine == _MACH_chrp)
1734 boot.file = "/etc/";
1735 else if (strlen(boot.file)) {
1736 if (!strncmp(boot.file, "\\\\", 2))
1740 p = last = boot.file;
1750 if (strlen(boot.file))
1751 strcat(boot.file, "\\");
1754 strcpy(conf_path, boot.file);
1755 strcat(conf_path, CONFIG_FILE_NAME);
1756 boot.file = conf_path;
1757 DEBUG_F("After path kludgeup: dev=%s, part=%d, file=%s\n",
1758 boot.dev, boot.part, boot.file);
1762 * If we're doing a netboot, first look for one which matches our
1765 if (prom_get_devtype(boot.dev) == FILE_DEVICE_NET) {
1766 prom_printf("Try to netboot\n");
1767 useconf = load_my_config_file(&boot);
1771 useconf = load_config_file(&boot);
1773 prom_printf("Welcome to yaboot version " VERSION "\n");
1774 prom_printf("Enter \"help\" to get some basic usage information\n");
1776 /* I am fed up with lusers using the wrong partition type and
1777 mailing me *when* it breaks */
1779 if (_machine == _MACH_Pmac) {
1780 char *entry = cfg_get_strg(0, "ptypewarning");
1783 warn = strcmp(entry,
1784 "I_know_the_partition_type_is_wrong_and_will_NOT_send_mail_when_booting_breaks");
1786 ptype = get_part_type(boot.dev, boot.part);
1787 if ((ptype != NULL) && (strcmp(ptype, "Apple_Bootstrap")))
1788 prom_printf("\nWARNING: Bootstrap partition type is wrong: \"%s\"\n"
1789 " type should be: \"Apple_Bootstrap\"\n\n", ptype);
1797 prom_printf("Bye.\n");
1803 * c-file-style: "k&r"