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;
183 /* OF seems to do it, but I'm not very confident */
184 memset(&__bss_start, 0, &_end - &__bss_start);
186 /* Check for quik first stage bootloader (but I don't think we are
187 * compatible with it anyway, I'll look into backporting to older OF
190 if (r5 == 0xdeadbeef) {
192 quik_fip = (struct first_info *)r4;
195 /* Initialize OF interface */
196 prom_init ((prom_entry) r5);
198 /* Allocate some memory for malloc'ator */
199 malloc_base = prom_claim((void *)MALLOCADDR, MALLOCSIZE, 0);
200 if (malloc_base == (void *)-1) {
201 prom_printf("Can't claim malloc buffer (%d bytes at 0x%08x)\n",
202 MALLOCSIZE, MALLOCADDR);
205 malloc_init(malloc_base, MALLOCSIZE);
206 DEBUG_F("Malloc buffer allocated at %p (%d bytes)\n",
207 malloc_base, MALLOCSIZE);
209 /* A few useless DEBUG_F's */
210 DEBUG_F("reloc_offset : %ld (should be 0)\n", reloc_offset());
211 DEBUG_F("test_bss : %d (should be 0)\n", test_bss);
212 DEBUG_F("test_data : %d (should be 0)\n", test_data);
213 DEBUG_F("&test_data : %p\n", &test_data);
214 DEBUG_F("&test_bss : %p\n", &test_bss);
215 DEBUG_F("linked at : 0x%08x\n", TEXTADDR);
217 /* ask the OF info if we're a chrp or pmac */
218 /* we need to set _machine before calling finish_device_tree */
219 root = prom_finddevice("/");
221 static char model[256];
222 if (prom_getprop(root, "device_type", model, 256 ) > 0 &&
223 !strncmp("chrp", model, 4))
224 _machine = _MACH_chrp;
226 if (prom_getprop(root, "model", model, 256 ) > 0 &&
227 !strncmp(model, "IBM", 3))
228 _machine = _MACH_chrp;
232 DEBUG_F("Running on _machine = %d\n", _machine);
236 result = yaboot_main();
238 /* Get rid of malloc pool */
240 prom_release(malloc_base, MALLOCSIZE);
241 DEBUG_F("Malloc buffer released. Exiting with code %d\n",
251 #ifdef CONFIG_COLOR_TEXT
253 * Validify color for text ui
256 check_color_text_ui(char *color)
259 while(ansi_color_table[i].name) {
260 if (!strcmp(color, ansi_color_table[i].name))
266 #endif /* CONFIG_COLOR_TEXT */
269 void print_message_file(char *filename)
273 char *defdev = boot.dev;
274 int defpart = boot.part;
279 struct boot_file_t file;
280 struct boot_fspec_t msgfile;
282 defdev = cfg_get_strg(0, "device");
285 p = cfg_get_strg(0, "partition");
287 n = simple_strtol(p, &endp, 10);
288 if (endp != p && *endp == 0)
292 strncpy(msgpath, filename, sizeof(msgpath));
293 if (!parse_device_path(msgpath, defdev, defpart, "/etc/yaboot.msg", &msgfile)) {
294 prom_printf("%s: Unable to parse\n", msgpath);
298 result = open_file(&msgfile, &file);
299 if (result != FILE_ERR_OK) {
300 prom_printf("%s:%d,", msgfile.dev, msgfile.part);
301 prom_perror(result, msgfile.file);
310 memset(msg, 0, 2001);
312 if (file.fs->read(&file, 2000, msg) <= 0)
315 prom_printf("%s", msg);
319 file.fs->close(&file);
324 /* Currently, the config file must be at the root of the filesystem.
325 * todo: recognize the full path to myself and use it to load the
326 * config file. Handle the "\\" (blessed system folder)
329 load_config_file(struct boot_fspec_t *fspec)
331 char *conf_file = NULL, *p;
332 struct boot_file_t file;
333 int sz, opened = 0, result = 0;
336 /* Allocate a buffer for the config file */
337 conf_file = malloc(CONFIG_FILE_MAX);
339 prom_printf("Can't alloc config file buffer\n");
343 /* Build the path to the file */
344 if (_machine == _MACH_chrp)
345 strcpy(conf_path, "/etc/");
348 if (fspec->file && *fspec->file)
349 strcat(conf_path, fspec->file);
351 strcat(conf_path, CONFIG_FILE_NAME);
355 fspec->file = conf_path;
356 result = open_file(fspec, &file);
357 if (result != FILE_ERR_OK) {
358 prom_printf("%s:%d,", fspec->dev, fspec->part);
359 prom_perror(result, fspec->file);
360 prom_printf("Can't open config file\n");
366 sz = file.fs->read(&file, CONFIG_FILE_MAX, conf_file);
368 prom_printf("Error, can't read config file\n");
371 prom_printf("Config file read, %d bytes\n", sz);
375 file.fs->close(&file);
378 /* Call the parsing code in cfg.c */
379 if (cfg_parse(fspec->file, conf_file, sz) < 0) {
380 prom_printf ("Syntax error or read error config\n");
384 DEBUG_F("Config file successfully parsed, %d bytes\n", sz);
386 /* Now, we do the initialisations stored in the config file */
387 p = cfg_get_strg(0, "init-code");
391 password = cfg_get_strg(0, "password");
393 #ifdef CONFIG_COLOR_TEXT
394 p = cfg_get_strg(0, "fgcolor");
396 DEBUG_F("fgcolor=%s\n", p);
397 fgcolor = check_color_text_ui(p);
399 prom_printf("Invalid fgcolor: \"%s\".\n", p);
402 p = cfg_get_strg(0, "bgcolor");
404 DEBUG_F("bgcolor=%s\n", p);
405 bgcolor = check_color_text_ui(p);
407 prom_printf("Invalid bgcolor: \"%s\".\n", p);
411 sprintf(temp, "%x to background-color", bgcolor);
412 prom_interpret(temp);
419 sprintf(temp, "%x to foreground-color", fgcolor);
420 prom_interpret(temp);
422 #endif /* CONFIG_COLOR_TEXT */
424 p = cfg_get_strg(0, "init-message");
426 prom_printf("%s\n", p);
428 p = cfg_get_strg(0, "message");
430 print_message_file(p);
437 file.fs->close(&file);
446 * "bootp-response" is the property name which is specified in
447 * the recommended practice doc for obp-tftp. However, pmac
448 * provides a "dhcp-response" property and chrp provides a
449 * "bootpreply-packet" property. The latter appears to begin the
450 * bootp packet at offset 0x2a in the property for some reason.
453 struct bootp_property_offset {
454 char *name; /* property name */
455 int offset; /* offset into property where bootp packet occurs */
457 static const struct bootp_property_offset bootp_response_properties[] = {
458 { .name = "bootp-response", .offset = 0 },
459 { .name = "dhcp-response", .offset = 0 },
460 { .name = "bootpreply-packet", .offset = 0x2a },
463 struct bootp_packet {
464 u8 op, htype, hlen, hops;
467 u32 ciaddr, yiaddr, siaddr, giaddr;
468 unsigned char chaddr[16];
469 unsigned char sname[64];
470 unsigned char file[128];
471 /* vendor options go here if we need them */
475 * Search for config file by MAC address, then by IP address.
476 * Basically copying pxelinux's algorithm.
477 * http://syslinux.zytor.com/pxe.php#config
479 static int load_my_config_file(struct boot_fspec_t *orig_fspec)
481 void *bootp_response = NULL;
483 struct bootp_packet *packet;
484 int i = 0, size, offset = 0, rc = 0;
486 struct boot_fspec_t fspec = *orig_fspec;
487 #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
489 chosen = prom_finddevice("/chosen");
491 prom_printf("chosen=%d\n", chosen);
495 for (i = 0; i < ARRAY_SIZE(bootp_response_properties); i++) {
496 propname = bootp_response_properties[i].name;
497 size = prom_getproplen(chosen, propname);
501 DEBUG_F("using /chosen/%s\n", propname);
502 offset = bootp_response_properties[i].offset;
509 if (sizeof(*packet) > size - offset) {
510 prom_printf("Malformed %s property?\n", propname);
514 bootp_response = malloc(size);
518 if (prom_getprop(chosen, propname, bootp_response, size) < 0)
521 packet = bootp_response + offset;
524 * First, try to match on mac address with the hardware type
528 /* 3 chars per byte in chaddr + 2 chars for htype + \0 */
529 fspec.file = malloc(packet->hlen * 3 + 2 + 1);
533 sprintf(fspec.file, "%02x", packet->htype);
535 for (i = 0; i < packet->hlen; i++) {
537 sprintf(tmp, "-%02x", packet->chaddr[i]);
538 strcat(fspec.file, tmp);
541 //DEBUG_F("----> mac addr: %s\n", fspec.file);
543 rc = load_config_file(&fspec);
549 * Now try to match on IP.
552 fspec.file = malloc(9);
553 sprintf(fspec.file, "%08X", packet->yiaddr);
555 while (strlen(fspec.file)) {
556 rc = load_config_file(&fspec);
559 /* Chop one digit off the end, try again */
560 fspec.file[strlen(fspec.file) - 1] = '\0';
564 if (rc) /* modify original only on success */
565 orig_fspec->file = fspec.file;
568 free(bootp_response);
572 void maintabfunc (void)
576 prom_printf("boot: %s", cbuff);
581 word_split(char **linep, char **paramsp)
596 while (*p != 0 && *p != ' ')
605 make_params(char *label, char *params)
608 static char buffer[2048];
613 p = cfg_get_strg(label, "literal");
625 p = cfg_get_strg(label, "root");
632 if (cfg_get_flag(label, "read-only")) {
636 if (cfg_get_flag(label, "read-write")) {
640 p = cfg_get_strg(label, "ramdisk");
642 strcpy (q, "ramdisk=");
647 p = cfg_get_strg(label, "initrd-size");
649 strcpy (q, "ramdisk_size=");
654 if (cfg_get_flag(label, "novideo")) {
655 strcpy (q, "video=ofonly");
659 p = cfg_get_strg (label, "append");
666 pause_after = cfg_get_flag (label, "pause-after");
667 p = cfg_get_strg(label, "pause-message");
676 void check_password(char *str)
680 prom_printf("\n%s", str);
681 for (i = 0; i < 3; i++) {
682 prom_printf ("\nPassword: ");
684 cmdedit ((void (*)(void)) 0, 1);
686 #ifdef USE_MD5_PASSWORDS
687 if (!strncmp (password, "$1$", 3)) {
688 if (!check_md5_password(passwdbuff, password))
691 else if (!strcmp (password, passwdbuff))
694 if (!strcmp (password, passwdbuff))
696 #endif /* USE_MD5_PASSWORDS */
699 prom_printf ("Incorrect password. Try again.");
702 prom_printf(" ___________________\n< Permission denied >\n -------------------\n"
703 " \\ ^__^\n \\ (oo)\\_______\n (__)\\ )\\/\\\n"
704 " ||----w |\n || ||\n");
706 prom_interpret("reset-all");
709 int get_params(struct boot_param_t* params)
713 char defdevice_bak[1024];
716 char *imagename = 0, *label;
721 static int first = 1;
722 static char imagepath[1024];
723 static char initrdpath[1024];
724 static char sysmappath[1024];
727 memset(params, 0, sizeof(*params));
729 params->kernel.part = -1;
730 params->rd.part = -1;
731 params->sysmap.part = -1;
738 imagename = bootargs;
739 word_split(&imagename, ¶ms->args);
740 timeout = DEFAULT_TIMEOUT;
742 prom_printf("Default supplied on the command line: %s ", imagename);
744 prom_printf("%s", params->args);
747 if (useconf && (q = cfg_get_strg(0, "timeout")) != 0 && *q != 0)
748 timeout = simple_strtol(q, NULL, 0);
751 prom_printf("boot: ");
756 end = beg + 100 * timeout;
758 c = prom_nbgetchar();
759 } while (c == -1 && prom_getms() <= end);
763 else if (c != '\n' && c != '\t' && c != '\r' && c != '\b' ) {
769 if (c != -1 && c != '\n' && c != '\r') {
772 } else if (c >= ' ') {
775 if ((cfg_get_flag (cbuff, "single-key")) && useconf) {
778 prom_printf("%s\n", cbuff);
783 if (c == '\n' || c == '\r') {
785 if (bootoncelabel[0] != 0)
786 imagename = bootoncelabel;
788 imagename = cfg_get_default();
791 prom_printf("%s", imagename);
793 prom_printf(" %s", params->args);
795 } else if (!singlekey) {
796 cmdedit(maintabfunc, 0);
798 strcpy(given_bootargs, cbuff);
799 given_bootargs_by_user = 1;
801 word_split(&imagename, ¶ms->args);
804 /* chrp gets this wrong, force it -- Cort */
805 if ( useconf && (!imagename || imagename[0] == 0 ))
806 imagename = cfg_get_default();
809 defdevice = boot.dev;
811 strcpy(defdevice_bak,defdevice);
814 defdevice = cfg_get_strg(0, "device");
815 p = cfg_get_strg(0, "partition");
817 n = simple_strtol(p, &endp, 10);
818 if (endp != p && *endp == 0)
821 p = cfg_get_strg(0, "pause-message");
824 if (cfg_get_flag(0, "restricted"))
826 p = cfg_get_strg(imagename, "image");
830 defdevice = cfg_get_strg(label, "device");
831 if(!defdevice) defdevice=boot.dev;
832 p = cfg_get_strg(label, "partition");
834 n = simple_strtol(p, &endp, 10);
835 if (endp != p && *endp == 0)
838 if (cfg_get_flag(label, "restricted"))
841 if (params->args && password && restricted)
842 check_password ("To specify arguments for this image "
843 "you must enter the password.");
844 else if (password && !restricted)
845 check_password ("This image is restricted.");
847 params->args = make_params(label, params->args);
851 if (!strcmp (imagename, "help")) {
852 /* FIXME: defdevice shouldn't need to be reset all over the place */
853 if(!defdevice) defdevice = boot.dev;
855 "\nPress the tab key for a list of defined images.\n"
856 "The label marked with a \"*\" is is the default image, "
857 "press <return> to boot it.\n\n"
858 "To boot any other label simply type its name and press <return>.\n\n"
859 "To boot a kernel image which is not defined in the yaboot configuration \n"
860 "file, enter the kernel image name as [[device:][partno],]/path, where \n"
861 "\"device:\" is the OpenFirmware device path to the disk the image \n"
862 "resides on, and \"partno\" is the partition number the image resides on.\n"
863 "Note that the comma (,) is only required if you specify an OpenFirmware\n"
864 "device, if you only specify a filename you should not start it with a \",\"\n\n"
865 "To load an alternative config file rather than /etc/yaboot.conf, enter\n"
866 "its device, partno and path, on Open Firmware Prompt:\n"
867 "boot conf=device:partno,/path/to/configfile\n."
868 "To reload the config file or load a new one, use the \"conf\" command\n"
869 "on Yaboot's prompt:\n"
870 "conf [device=device] [partition=partno] [file=/path/to/configfile]\n\n"
871 "If you omit \"device\" and \"partno\", Yaboot will use their current\n"
872 "values. You can check them by entering \"conf\" on Yaboot's prompt.\n");
877 if (!strcmp (imagename, "halt")) {
879 check_password ("Restricted command.");
883 if (!strcmp (imagename, "bye")) {
885 check_password ("Restricted command.");
891 if (!strncmp (imagename, "conf", 4)) {
893 // imagename = "conf file=blah dev=bleh part=blih"
894 DEBUG_F("Loading user-specified config file: %s\n",imagename);
896 check_password ("Restricted command.");
900 // args= "file=blah dev=bleh part=blih"
901 char *args = params->args;
905 // set a pointer to the first space in args
906 char *space = strchr(args,' ');
910 char temp[1024] = "0";
912 // copy next argument to temp
913 strncpy(temp, args, space-args);
915 // parse temp and set boot arguments
916 if (!strncmp (temp, "file=", 5)){
917 DEBUG_F("conf file: %s\n", temp+5);
918 strcpy(boot.file, temp+5);
919 } else if (!strncmp (temp, "device=", 7)){
920 DEBUG_F("conf device: %s\n", temp+7);
921 strcpy(boot.dev, temp+7);
922 } else if (!strncmp (temp, "partition=", 10)){
923 DEBUG_F("conf partition: %s\n", temp+10);
924 boot.part=simple_strtol(temp+10,NULL,10);
928 // set the pointer to the next space in args;
929 // set the loop control variable
930 if (strlen(space)>1){
931 // Go to the next argument
935 if (strchr(args,' ') == NULL)
936 space = &args[strlen(args)];
938 space = strchr(args,' ');
945 prom_printf("Loading config file...\n");
946 useconf = load_config_file(&boot);
948 if ((q = cfg_get_strg(0, "timeout")) != 0 && *q != 0)
949 timeout = simple_strtol(q, NULL, 0);
951 prom_printf("Restoring default values.\n");
952 strcpy(boot.file,"");
953 strcpy(boot.dev, defdevice_bak);
958 prom_printf("Current configuration:\n");
959 prom_printf("device: %s\n", boot.dev);
961 prom_printf("partition: auto\n");
963 prom_printf("partition: %d\n", boot.part);
964 if (strlen(boot.file))
965 prom_printf("file: %s\n", boot.file);
967 prom_printf("file: /etc/%s\n",CONFIG_FILE_NAME);
976 if (imagename[0] == '$') {
977 /* forth command string */
979 check_password ("OpenFirmware commands are restricted.");
980 prom_interpret(imagename+1);
984 strncpy(imagepath, imagename, 1024);
986 if (!label && password)
987 check_password ("To boot a custom image you must enter the password.");
989 if (!parse_device_path(imagepath, defdevice, defpart,
990 "/vmlinux", ¶ms->kernel)) {
991 prom_printf("%s: Unable to parse\n", imagepath);
994 DEBUG_F("after parse_device_path: dev=%s part=%d file=%s\n", params->kernel.dev,
995 params->kernel.part, params->kernel.file);
998 p = cfg_get_strg(label, "initrd");
1000 DEBUG_F("Parsing initrd path <%s>\n", p);
1001 strncpy(initrdpath, p, 1024);
1002 if (!parse_device_path(initrdpath, defdevice, defpart,
1003 "/root.bin", ¶ms->rd)) {
1004 prom_printf("%s: Unable to parse\n", imagepath);
1008 p = cfg_get_strg(label, "sysmap");
1010 DEBUG_F("Parsing sysmap path <%s>\n", p);
1011 strncpy(sysmappath, p, 1024);
1012 if (!parse_device_path(sysmappath, defdevice, defpart,
1013 "/boot/System.map", ¶ms->sysmap)) {
1014 prom_printf("%s: Unable to parse\n", imagepath);
1022 /* This is derived from quik core. To be changed to first parse the headers
1023 * doing lazy-loading, and then claim the memory before loading the kernel
1025 * We also need to add initrd support to this whole mecanism
1028 yaboot_text_ui(void)
1030 #define MAX_HEADERS 32
1032 struct boot_file_t file;
1034 static struct boot_param_t params;
1036 unsigned long initrd_size;
1038 unsigned long sysmap_size;
1039 kernel_entry_t kernel_entry;
1040 struct bi_record* birec;
1042 loadinfo_t loadinfo;
1043 void *initrd_more,*initrd_want;
1044 unsigned long initrd_read;
1046 loadinfo.load_loc = 0;
1054 if (get_params(¶ms))
1056 if (!params.kernel.file)
1059 prom_printf("Please wait, loading kernel...\n");
1061 memset(&file, 0, sizeof(file));
1063 if (strlen(boot.file) && !strcmp(boot.file,"\\\\") && params.kernel.file[0] != '/'
1064 && params.kernel.file[0] != '\\') {
1065 loc=(char*)malloc(strlen(params.kernel.file)+3);
1067 prom_printf ("malloc error\n");
1070 strcpy(loc,boot.file);
1071 strcat(loc,params.kernel.file);
1072 free(params.kernel.file);
1073 params.kernel.file=loc;
1075 result = open_file(¶ms.kernel, &file);
1076 if (result != FILE_ERR_OK) {
1077 prom_printf("%s:%d,", params.kernel.dev, params.kernel.part);
1078 prom_perror(result, params.kernel.file);
1082 /* Read the Elf e_ident, e_type and e_machine fields to
1083 * determine Elf file type
1085 if (file.fs->read(&file, sizeof(Elf_Ident), &loadinfo.elf) < sizeof(Elf_Ident)) {
1086 prom_printf("\nCan't read Elf e_ident/e_type/e_machine info\n");
1087 file.fs->close(&file);
1088 memset(&file, 0, sizeof(file));
1092 if (is_elf32(&loadinfo)) {
1093 if (!load_elf32(&file, &loadinfo)) {
1094 file.fs->close(&file);
1095 memset(&file, 0, sizeof(file));
1098 prom_printf(" Elf32 kernel loaded...\n");
1099 } else if (is_elf64(&loadinfo)) {
1100 if (!load_elf64(&file, &loadinfo)) {
1101 file.fs->close(&file);
1102 memset(&file, 0, sizeof(file));
1105 prom_printf(" Elf64 kernel loaded...\n");
1107 prom_printf ("%s: Not a valid ELF image\n", params.kernel.file);
1108 file.fs->close(&file);
1109 memset(&file, 0, sizeof(file));
1112 file.fs->close(&file);
1113 memset(&file, 0, sizeof(file));
1115 /* If sysmap, load it (only if booting a vmlinux).
1117 if (flat_vmlinux && params.sysmap.file) {
1118 prom_printf("Loading System.map ...\n");
1119 if(strlen(boot.file) && !strcmp(boot.file,"\\\\") && params.sysmap.file[0] != '/'
1120 && params.sysmap.file[0] != '\\') {
1122 loc=(char*)malloc(strlen(params.sysmap.file)+3);
1124 prom_printf ("malloc error\n");
1127 strcpy(loc,boot.file);
1128 strcat(loc,params.sysmap.file);
1129 free(params.sysmap.file);
1130 params.sysmap.file=loc;
1133 result = open_file(¶ms.sysmap, &file);
1134 if (result != FILE_ERR_OK) {
1135 prom_printf("%s:%d,", params.sysmap.dev, params.sysmap.part);
1136 prom_perror(result, params.sysmap.file);
1139 sysmap_base = prom_claim(loadinfo.base+loadinfo.memsize, 0x100000, 0);
1140 if (sysmap_base == (void *)-1) {
1141 prom_printf("Claim failed for sysmap memory\n");
1145 sysmap_size = file.fs->read(&file, 0xfffff, sysmap_base);
1146 if (sysmap_size == 0)
1149 ((char *)sysmap_base)[sysmap_size++] = 0;
1151 file.fs->close(&file);
1152 memset(&file, 0, sizeof(file));
1155 prom_printf("System.map loaded at %p, size: %lu Kbytes\n",
1156 sysmap_base, sysmap_size >> 10);
1157 loadinfo.memsize += _ALIGN(0x100000, 0x1000);
1159 prom_printf("System.map load failed !\n");
1164 /* If ramdisk, load it (only if booting a vmlinux). For now, we
1165 * can't tell the size it will be so we claim an arbitrary amount
1168 if (flat_vmlinux && params.rd.file) {
1169 if(strlen(boot.file) && !strcmp(boot.file,"\\\\") && params.rd.file[0] != '/'
1170 && params.kernel.file[0] != '\\')
1173 loc=(char*)malloc(strlen(params.rd.file)+3);
1175 prom_printf ("Malloc error\n");
1178 strcpy(loc,boot.file);
1179 strcat(loc,params.rd.file);
1180 free(params.rd.file);
1183 prom_printf("Loading ramdisk...\n");
1184 result = open_file(¶ms.rd, &file);
1185 if (result != FILE_ERR_OK) {
1186 prom_printf("%s:%d,", params.rd.dev, params.rd.part);
1187 prom_perror(result, params.rd.file);
1190 #define INITRD_CHUNKSIZE 0x100000
1191 initrd_base = prom_claim(loadinfo.base+loadinfo.memsize, INITRD_CHUNKSIZE, 0);
1192 if (initrd_base == (void *)-1) {
1193 prom_printf("Claim failed for initrd memory\n");
1196 initrd_size = file.fs->read(&file, INITRD_CHUNKSIZE, initrd_base);
1197 if (initrd_size == 0)
1199 initrd_read = initrd_size;
1200 initrd_more = initrd_base;
1201 while (initrd_read == INITRD_CHUNKSIZE ) { /* need to read more? */
1202 initrd_want = (void *)((unsigned long)initrd_more+INITRD_CHUNKSIZE);
1203 initrd_more = prom_claim(initrd_want, INITRD_CHUNKSIZE, 0);
1204 if (initrd_more != initrd_want) {
1205 prom_printf("Claim failed for initrd memory at %p rc=%p\n",initrd_want,initrd_more);
1209 initrd_read = file.fs->read(&file, INITRD_CHUNKSIZE, initrd_more);
1210 DEBUG_F(" block at %p rc=%lu\n",initrd_more,initrd_read);
1211 initrd_size += initrd_read;
1214 file.fs->close(&file);
1215 memset(&file, 0, sizeof(file));
1218 prom_printf("ramdisk loaded at %p, size: %lu Kbytes\n",
1219 initrd_base, initrd_size >> 10);
1221 prom_printf("ramdisk load failed !\n");
1226 DEBUG_F("setting kernel args to: %s\n", params.args);
1227 prom_setargs(params.args);
1228 DEBUG_F("flushing icache...");
1229 flush_icache_range ((long)loadinfo.base, (long)loadinfo.base+loadinfo.memsize);
1234 * Fill new boot infos (only if booting a vmlinux).
1236 * The birec is low on memory, probably inside the malloc pool,
1237 * so we don't write it earlier. At this point, we should not
1238 * use anything coming from the malloc pool.
1240 birec = (struct bi_record *)_ALIGN(loadinfo.filesize+(1<<20)-1,(1<<20));
1242 /* We make sure it's mapped. We map only 64k for now, it's
1243 * plenty enough we don't claim since this precise memory
1244 * range may already be claimed by the malloc pool.
1246 prom_map (birec, birec, 0x10000);
1247 DEBUG_F("birec at %p\n", birec);
1250 birec->tag = BI_FIRST;
1251 birec->size = sizeof(struct bi_record);
1252 birec = (struct bi_record *)((ulong)birec + birec->size);
1254 birec->tag = BI_BOOTLOADER_ID;
1255 sprintf( (char *)birec->data, "yaboot");
1256 birec->size = sizeof(struct bi_record) + strlen("yaboot") + 1;
1257 birec = (struct bi_record *)((ulong)birec + birec->size);
1259 birec->tag = BI_MACHTYPE;
1260 birec->data[0] = _machine;
1261 birec->size = sizeof(struct bi_record) + sizeof(ulong);
1262 birec = (struct bi_record *)((ulong)birec + birec->size);
1265 birec->tag = BI_SYSMAP;
1266 birec->data[0] = (ulong)sysmap_base;
1267 birec->data[1] = sysmap_size;
1268 birec->size = sizeof(struct bi_record) + sizeof(ulong)*2;
1269 birec = (struct bi_record *)((ulong)birec + birec->size);
1271 birec->tag = BI_LAST;
1272 birec->size = sizeof(struct bi_record);
1273 birec = (struct bi_record *)((ulong)birec + birec->size);
1276 /* compute the kernel's entry point. */
1277 kernel_entry = loadinfo.base + loadinfo.entry - loadinfo.load_loc;
1279 DEBUG_F("Kernel entry point = %p\n", kernel_entry);
1280 DEBUG_F("kernel: arg1 = %p,\n"
1281 " arg2 = 0x%08lx,\n"
1285 initrd_base + loadinfo.load_loc, initrd_size, prom, 0, 0);
1287 DEBUG_F("Entering kernel...\n");
1289 /* call the kernel with our stack. */
1290 kernel_entry(initrd_base + loadinfo.load_loc, initrd_size, prom, 0, 0);
1298 load_elf32(struct boot_file_t *file, loadinfo_t *loadinfo)
1301 Elf32_Ehdr *e = &(loadinfo->elf.elf32hdr);
1303 int size = sizeof(Elf32_Ehdr) - sizeof(Elf_Ident);
1304 unsigned long addr, loadaddr;
1306 /* Read the rest of the Elf header... */
1307 if ((*(file->fs->read))(file, size, &e->e_version) < size) {
1308 prom_printf("\nCan't read Elf32 image header\n");
1312 DEBUG_F("Elf32 header:\n");
1313 DEBUG_F(" e.e_type = %d\n", (int)e->e_type);
1314 DEBUG_F(" e.e_machine = %d\n", (int)e->e_machine);
1315 DEBUG_F(" e.e_version = %d\n", (int)e->e_version);
1316 DEBUG_F(" e.e_entry = 0x%08x\n", (int)e->e_entry);
1317 DEBUG_F(" e.e_phoff = 0x%08x\n", (int)e->e_phoff);
1318 DEBUG_F(" e.e_shoff = 0x%08x\n", (int)e->e_shoff);
1319 DEBUG_F(" e.e_flags = %d\n", (int)e->e_flags);
1320 DEBUG_F(" e.e_ehsize = 0x%08x\n", (int)e->e_ehsize);
1321 DEBUG_F(" e.e_phentsize = 0x%08x\n", (int)e->e_phentsize);
1322 DEBUG_F(" e.e_phnum = %d\n", (int)e->e_phnum);
1324 loadinfo->entry = e->e_entry;
1326 if (e->e_phnum > MAX_HEADERS) {
1327 prom_printf ("Can only load kernels with one program header\n");
1331 ph = (Elf32_Phdr *)malloc(sizeof(Elf32_Phdr) * e->e_phnum);
1333 prom_printf ("Malloc error\n");
1337 /* Now, we read the section header */
1338 if ((*(file->fs->seek))(file, e->e_phoff) != FILE_ERR_OK) {
1339 prom_printf ("seek error\n");
1342 if ((*(file->fs->read))(file, sizeof(Elf32_Phdr) * e->e_phnum, ph) !=
1343 sizeof(Elf32_Phdr) * e->e_phnum) {
1344 prom_printf ("read error\n");
1348 /* Scan through the program header
1349 * HACK: We must return the _memory size of the kernel image, not the
1350 * file size (because we have to leave room before other boot
1351 * infos. This code works as a side effect of the fact that
1352 * we have one section and vaddr == p_paddr
1354 loadinfo->memsize = loadinfo->filesize = loadinfo->offset = 0;
1356 for (i = 0; i < e->e_phnum; ++i, ++p) {
1357 if (p->p_type != PT_LOAD || p->p_offset == 0)
1359 if (loadinfo->memsize == 0) {
1360 loadinfo->offset = p->p_offset;
1361 loadinfo->memsize = p->p_memsz;
1362 loadinfo->filesize = p->p_filesz;
1363 loadinfo->load_loc = p->p_vaddr;
1365 loadinfo->memsize = p->p_offset + p->p_memsz - loadinfo->offset; /* XXX Bogus */
1366 loadinfo->filesize = p->p_offset + p->p_filesz - loadinfo->offset;
1370 if (loadinfo->memsize == 0) {
1371 prom_printf("Can't find a loadable segment !\n");
1375 /* leave some room (1Mb) for boot infos */
1376 loadinfo->memsize = _ALIGN(loadinfo->memsize,(1<<20)) + 0x100000;
1377 /* Claim OF memory */
1378 DEBUG_F("Before prom_claim, mem_sz: 0x%08lx\n", loadinfo->memsize);
1380 /* Determine whether we are trying to boot a vmlinux or some
1381 * other binary image (eg, zImage). We load vmlinux's at
1382 * KERNELADDR and all other binaries at their e_entry value.
1384 if (e->e_entry == KERNEL_LINK_ADDR_PPC32) {
1386 loadaddr = KERNELADDR;
1389 loadaddr = loadinfo->load_loc;
1392 /* On some systems, loadaddr may already be claimed, so try some
1393 * other nearby addresses before giving up.
1395 for(addr=loadaddr; addr <= loadaddr * 8 ;addr+=0x100000) {
1396 loadinfo->base = prom_claim((void *)addr, loadinfo->memsize, 0);
1397 if (loadinfo->base != (void *)-1) break;
1399 if (loadinfo->base == (void *)-1) {
1400 prom_printf("Claim error, can't allocate kernel memory\n");
1404 DEBUG_F("After ELF parsing, load base: %p, mem_sz: 0x%08lx\n",
1405 loadinfo->base, loadinfo->memsize);
1406 DEBUG_F(" wanted load base: 0x%08lx, mem_sz: 0x%08lx\n",
1407 loadaddr, loadinfo->memsize);
1409 /* Load the program segments... */
1411 for (i = 0; i < e->e_phnum; ++i, ++p) {
1412 unsigned long offset;
1413 if (p->p_type != PT_LOAD || p->p_offset == 0)
1416 /* Now, we skip to the image itself */
1417 if ((*(file->fs->seek))(file, p->p_offset) != FILE_ERR_OK) {
1418 prom_printf ("Seek error\n");
1419 prom_release(loadinfo->base, loadinfo->memsize);
1422 offset = p->p_vaddr - loadinfo->load_loc;
1423 if ((*(file->fs->read))(file, p->p_filesz, loadinfo->base+offset) != p->p_filesz) {
1424 prom_printf ("Read failed\n");
1425 prom_release(loadinfo->base, loadinfo->memsize);
1432 /* Return success at loading the Elf32 kernel */
1442 load_elf64(struct boot_file_t *file, loadinfo_t *loadinfo)
1445 Elf64_Ehdr *e = &(loadinfo->elf.elf64hdr);
1447 int size = sizeof(Elf64_Ehdr) - sizeof(Elf_Ident);
1448 unsigned long addr, loadaddr;
1450 /* Read the rest of the Elf header... */
1451 if ((*(file->fs->read))(file, size, &e->e_version) < size) {
1452 prom_printf("\nCan't read Elf64 image header\n");
1456 DEBUG_F("Elf64 header:\n");
1457 DEBUG_F(" e.e_type = %d\n", (int)e->e_type);
1458 DEBUG_F(" e.e_machine = %d\n", (int)e->e_machine);
1459 DEBUG_F(" e.e_version = %d\n", (int)e->e_version);
1460 DEBUG_F(" e.e_entry = 0x%016lx\n", (long)e->e_entry);
1461 DEBUG_F(" e.e_phoff = 0x%016lx\n", (long)e->e_phoff);
1462 DEBUG_F(" e.e_shoff = 0x%016lx\n", (long)e->e_shoff);
1463 DEBUG_F(" e.e_flags = %d\n", (int)e->e_flags);
1464 DEBUG_F(" e.e_ehsize = 0x%08x\n", (int)e->e_ehsize);
1465 DEBUG_F(" e.e_phentsize = 0x%08x\n", (int)e->e_phentsize);
1466 DEBUG_F(" e.e_phnum = %d\n", (int)e->e_phnum);
1468 loadinfo->entry = e->e_entry;
1470 if (e->e_phnum > MAX_HEADERS) {
1471 prom_printf ("Can only load kernels with one program header\n");
1475 ph = (Elf64_Phdr *)malloc(sizeof(Elf64_Phdr) * e->e_phnum);
1477 prom_printf ("Malloc error\n");
1481 /* Now, we read the section header */
1482 if ((*(file->fs->seek))(file, e->e_phoff) != FILE_ERR_OK) {
1483 prom_printf ("Seek error\n");
1486 if ((*(file->fs->read))(file, sizeof(Elf64_Phdr) * e->e_phnum, ph) !=
1487 sizeof(Elf64_Phdr) * e->e_phnum) {
1488 prom_printf ("Read error\n");
1492 /* Scan through the program header
1493 * HACK: We must return the _memory size of the kernel image, not the
1494 * file size (because we have to leave room before other boot
1495 * infos. This code works as a side effect of the fact that
1496 * we have one section and vaddr == p_paddr
1498 loadinfo->memsize = loadinfo->filesize = loadinfo->offset = 0;
1500 for (i = 0; i < e->e_phnum; ++i, ++p) {
1501 if (p->p_type != PT_LOAD || p->p_offset == 0)
1503 if (loadinfo->memsize == 0) {
1504 loadinfo->offset = p->p_offset;
1505 loadinfo->memsize = p->p_memsz;
1506 loadinfo->filesize = p->p_filesz;
1507 loadinfo->load_loc = p->p_vaddr;
1509 loadinfo->memsize = p->p_offset + p->p_memsz - loadinfo->offset; /* XXX Bogus */
1510 loadinfo->filesize = p->p_offset + p->p_filesz - loadinfo->offset;
1514 if (loadinfo->memsize == 0) {
1515 prom_printf("Can't find a loadable segment !\n");
1519 /* leave some room (1Mb) for boot infos */
1520 loadinfo->memsize = _ALIGN(loadinfo->memsize,(1<<20)) + 0x100000;
1521 /* Claim OF memory */
1522 DEBUG_F("Before prom_claim, mem_sz: 0x%08lx\n", loadinfo->memsize);
1524 /* Determine whether we are trying to boot a vmlinux or some
1525 * other binary image (eg, zImage). We load vmlinux's at
1526 * KERNELADDR and all other binaries at their e_entry value.
1528 if (e->e_entry == KERNEL_LINK_ADDR_PPC64) {
1530 loadaddr = KERNELADDR;
1533 loadaddr = e->e_entry;
1536 /* On some systems, loadaddr may already be claimed, so try some
1537 * other nearby addresses before giving up.
1539 for(addr=loadaddr; addr <= loadaddr * 8 ;addr+=0x100000) {
1540 loadinfo->base = prom_claim((void *)addr, loadinfo->memsize, 0);
1541 if (loadinfo->base != (void *)-1) break;
1543 if (loadinfo->base == (void *)-1) {
1544 prom_printf("Claim error, can't allocate kernel memory\n");
1548 DEBUG_F("After ELF parsing, load base: %p, mem_sz: 0x%08lx\n",
1549 loadinfo->base, loadinfo->memsize);
1550 DEBUG_F(" wanted load base: 0x%08lx, mem_sz: 0x%08lx\n",
1551 loadaddr, loadinfo->memsize);
1553 /* Load the program segments... */
1555 for (i = 0; i < e->e_phnum; ++i, ++p) {
1556 unsigned long offset;
1557 if (p->p_type != PT_LOAD || p->p_offset == 0)
1560 /* Now, we skip to the image itself */
1561 if ((*(file->fs->seek))(file, p->p_offset) != FILE_ERR_OK) {
1562 prom_printf ("Seek error\n");
1563 prom_release(loadinfo->base, loadinfo->memsize);
1566 offset = p->p_vaddr - loadinfo->load_loc;
1567 if ((*(file->fs->read))(file, p->p_filesz, loadinfo->base+offset) != p->p_filesz) {
1568 prom_printf ("Read failed\n");
1569 prom_release(loadinfo->base, loadinfo->memsize);
1576 /* Return success at loading the Elf64 kernel */
1586 is_elf32(loadinfo_t *loadinfo)
1588 Elf32_Ehdr *e = &(loadinfo->elf.elf32hdr);
1590 return (e->e_ident[EI_MAG0] == ELFMAG0 &&
1591 e->e_ident[EI_MAG1] == ELFMAG1 &&
1592 e->e_ident[EI_MAG2] == ELFMAG2 &&
1593 e->e_ident[EI_MAG3] == ELFMAG3 &&
1594 e->e_ident[EI_CLASS] == ELFCLASS32 &&
1595 e->e_ident[EI_DATA] == ELFDATA2MSB &&
1596 e->e_type == ET_EXEC &&
1597 e->e_machine == EM_PPC);
1601 is_elf64(loadinfo_t *loadinfo)
1603 Elf64_Ehdr *e = &(loadinfo->elf.elf64hdr);
1605 return (e->e_ident[EI_MAG0] == ELFMAG0 &&
1606 e->e_ident[EI_MAG1] == ELFMAG1 &&
1607 e->e_ident[EI_MAG2] == ELFMAG2 &&
1608 e->e_ident[EI_MAG3] == ELFMAG3 &&
1609 e->e_ident[EI_CLASS] == ELFCLASS64 &&
1610 e->e_ident[EI_DATA] == ELFDATA2MSB &&
1611 e->e_type == ET_EXEC &&
1612 e->e_machine == EM_PPC64);
1618 #ifdef CONFIG_SET_COLORMAP
1619 static unsigned char default_colors[] = {
1638 prom_handle scrn = PROM_INVALID_HANDLE;
1640 /* Try Apple's mac-boot screen ihandle */
1641 result = (int)call_prom_return("interpret", 1, 2,
1642 "\" _screen-ihandle\" $find if execute else 0 then", &scrn);
1643 DEBUG_F("Trying to get screen ihandle, result: %d, scrn: %p\n", result, scrn);
1645 if (scrn == 0 || scrn == PROM_INVALID_HANDLE) {
1647 /* Hrm... check to see if stdout is a display */
1648 scrn = call_prom ("instance-to-package", 1, 1, prom_stdout);
1649 DEBUG_F("instance-to-package of stdout is: %p\n", scrn);
1650 if (prom_getprop(scrn, "device_type", type, 32) > 0 && !strncmp(type, "display", 7)) {
1651 DEBUG_F("got it ! stdout is a screen\n");
1654 /* Else, we try to open the package */
1655 scrn = (prom_handle)call_prom( "open", 1, 1, "screen" );
1656 DEBUG_F("Open screen result: %p\n", scrn);
1660 if (scrn == PROM_INVALID_HANDLE) {
1661 prom_printf("No screen device found !/n");
1665 prom_set_color(scrn, i, default_colors[i*3],
1666 default_colors[i*3+1], default_colors[i*3+2]);
1668 prom_printf("\x1b[1;37m\x1b[2;40m");
1670 for (i=0;i<16; i++) {
1671 prom_printf("\x1b[%d;%dm\x1b[1;47m%s \x1b[2;40m %s\n",
1672 ansi_color_table[i].index,
1673 ansi_color_table[i].value,
1674 ansi_color_table[i].name,
1675 ansi_color_table[i].name);
1676 prom_printf("\x1b[%d;%dm\x1b[1;37m%s \x1b[2;30m %s\n",
1677 ansi_color_table[i].index,
1678 ansi_color_table[i].value+10,
1679 ansi_color_table[i].name,
1680 ansi_color_table[i].name);
1682 prom_printf("\x1b[1;37m\x1b[2;40m");
1683 #endif /* COLOR_TEST */
1689 #endif /* CONFIG_SET_COLORMAP */
1697 char conf_path[1024];
1699 if (_machine == _MACH_Pmac)
1702 prom_get_chosen("bootargs", bootargs, sizeof(bootargs));
1703 DEBUG_F("/chosen/bootargs = %s\n", bootargs);
1704 prom_get_chosen("bootpath", bootdevice, BOOTDEVSZ);
1705 DEBUG_F("/chosen/bootpath = %s\n", bootdevice);
1707 /* If conf= specified on command line, it overrides
1708 Usage: conf=device:partition,/path/to/conffile
1709 Example: On Open Firmware Prompt, type
1710 boot conf=/pci@8000000f8000000/pci@1/pci1014,028C@1/scsi@0/sd@1,0:3,/etc/yaboot.conf */
1712 if (!strncmp(bootargs, "conf=", 5)) {
1713 DEBUG_F("Using conf argument in Open Firmware\n");
1714 char *end = strchr(bootargs,' ');
1718 strcpy(bootdevice, bootargs + 5);
1720 DEBUG_F("Using conf=%s\n", bootdevice);
1722 /* Remove conf=xxx from bootargs */
1724 memmove(bootargs, end+1, strlen(end+1)+1);
1728 if (bootdevice[0] == 0) {
1729 prom_get_options("boot-device", bootdevice, BOOTDEVSZ);
1730 DEBUG_F("boot-device = %s\n", bootdevice);
1732 if (bootdevice[0] == 0) {
1733 prom_printf("Couldn't determine boot device\n");
1737 if (bootoncelabel[0] == 0) {
1738 prom_get_options("boot-once", bootoncelabel,
1739 sizeof(bootoncelabel));
1740 if (bootoncelabel[0] != 0)
1741 DEBUG_F("boot-once: [%s]\n", bootoncelabel);
1743 prom_set_options("boot-once", NULL, 0);
1745 if (!parse_device_path(bootdevice, NULL, -1, "", &boot)) {
1746 prom_printf("%s: Unable to parse\n", bootdevice);
1749 DEBUG_F("After parse_device_path: dev=%s, part=%d, file=%s\n",
1750 boot.dev, boot.part, boot.file);
1753 if (_machine == _MACH_chrp)
1754 boot.file = "/etc/";
1755 else if (strlen(boot.file)) {
1756 if (!strncmp(boot.file, "\\\\", 2))
1760 p = last = boot.file;
1770 if (strlen(boot.file))
1771 strcat(boot.file, "\\");
1774 strcpy(conf_path, boot.file);
1775 strcat(conf_path, CONFIG_FILE_NAME);
1776 boot.file = conf_path;
1777 DEBUG_F("After path kludgeup: dev=%s, part=%d, file=%s\n",
1778 boot.dev, boot.part, boot.file);
1782 * If we're doing a netboot, first look for one which matches our
1785 if (prom_get_devtype(boot.dev) == FILE_DEVICE_NET) {
1786 prom_printf("Try to netboot\n");
1787 useconf = load_my_config_file(&boot);
1791 useconf = load_config_file(&boot);
1793 prom_printf("Welcome to yaboot version " VERSION "\n");
1794 prom_printf("Enter \"help\" to get some basic usage information\n");
1796 /* I am fed up with lusers using the wrong partition type and
1797 mailing me *when* it breaks */
1799 if (_machine == _MACH_Pmac) {
1800 char *entry = cfg_get_strg(0, "ptypewarning");
1803 warn = strcmp(entry,
1804 "I_know_the_partition_type_is_wrong_and_will_NOT_send_mail_when_booting_breaks");
1806 ptype = get_part_type(boot.dev, boot.part);
1807 if ((ptype != NULL) && (strcmp(ptype, "Apple_Bootstrap")))
1808 prom_printf("\nWARNING: Bootstrap partition type is wrong: \"%s\"\n"
1809 " type should be: \"Apple_Bootstrap\"\n\n", ptype);
1817 prom_printf("Bye.\n");
1823 * c-file-style: "k&r"