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;
335 /* Allocate a buffer for the config file */
336 conf_file = malloc(CONFIG_FILE_MAX);
338 prom_printf("Can't alloc config file buffer\n");
343 result = open_file(fspec, &file);
344 if (result != FILE_ERR_OK) {
345 prom_printf("%s:%d,", fspec->dev, fspec->part);
346 prom_perror(result, fspec->file);
347 prom_printf("Can't open config file\n");
353 sz = file.fs->read(&file, CONFIG_FILE_MAX, conf_file);
355 prom_printf("Error, can't read config file\n");
358 prom_printf("Config file read, %d bytes\n", sz);
362 file.fs->close(&file);
365 /* Call the parsing code in cfg.c */
366 if (cfg_parse(fspec->file, conf_file, sz) < 0) {
367 prom_printf ("Syntax error or read error config\n");
372 * set the default cf_option to label that has the same MAC addr
373 * it only works if there is a label with the MAC addr on yaboot.conf
375 if (prom_get_devtype(fspec->dev) == FILE_DEVICE_NET) {
376 /* change the variable bellow to get the MAC dinamicaly */
377 char * macaddr = NULL;
380 macaddr = prom_get_mac(prom_get_netinfo());
381 default_mac = cfg_set_default_by_mac(macaddr);
382 if (default_mac >= 1) {
383 prom_printf("Default label was changed to macaddr label.\n");
387 DEBUG_F("Config file successfully parsed, %d bytes\n", sz);
389 /* Now, we do the initialisations stored in the config file */
390 p = cfg_get_strg(0, "init-code");
394 password = cfg_get_strg(0, "password");
396 #ifdef CONFIG_COLOR_TEXT
397 p = cfg_get_strg(0, "fgcolor");
399 DEBUG_F("fgcolor=%s\n", p);
400 fgcolor = check_color_text_ui(p);
402 prom_printf("Invalid fgcolor: \"%s\".\n", p);
405 p = cfg_get_strg(0, "bgcolor");
407 DEBUG_F("bgcolor=%s\n", p);
408 bgcolor = check_color_text_ui(p);
410 prom_printf("Invalid bgcolor: \"%s\".\n", p);
414 sprintf(temp, "%x to background-color", bgcolor);
415 prom_interpret(temp);
422 sprintf(temp, "%x to foreground-color", fgcolor);
423 prom_interpret(temp);
425 #endif /* CONFIG_COLOR_TEXT */
427 p = cfg_get_strg(0, "init-message");
429 prom_printf("%s\n", p);
431 p = cfg_get_strg(0, "message");
433 print_message_file(p);
440 file.fs->close(&file);
449 * Search for config file by MAC address, then by IP address.
450 * Basically copying pxelinux's algorithm.
451 * http://syslinux.zytor.com/pxe.php#config
453 static int load_my_config_file(struct boot_fspec_t *orig_fspec)
455 struct bootp_packet *packet;
457 struct boot_fspec_t fspec = *orig_fspec;
458 char *cfgpath = (_machine == _MACH_chrp) ? "/etc/" : "";
462 packet = prom_get_netinfo();
465 * First, try to match on mac address with the hardware type
469 /* 3 chars per byte in chaddr + 2 chars for htype + /etc/ +\0 */
470 fspec.file = malloc(packet->hlen * 3 + 2 + 6);
474 sprintf(fspec.file, "%s%02x-", cfgpath, packet->htype);
475 strcat(fspec.file, prom_get_mac(packet));
477 rc = load_config_file(&fspec);
482 * Now try to match on IP.
484 /* no need to realloc for /etc/ + 8 chars in yiaddr + \0 */
485 sprintf(fspec.file, "%s%s", cfgpath, prom_get_ip(packet));
487 for (flen = strlen(fspec.file),
488 minlen = strlen(cfgpath); flen > minlen; flen--) {
489 rc = load_config_file(&fspec);
492 /* Chop one digit off the end, try again */
493 fspec.file[flen - 1] = '\0';
497 if (rc) /* modify original only on success */
498 orig_fspec->file = fspec.file;
504 void maintabfunc (void)
508 prom_printf("boot: %s", cbuff);
513 word_split(char **linep, char **paramsp)
528 while (*p != 0 && *p != ' ')
537 make_params(char *label, char *params)
540 static char buffer[2048];
545 p = cfg_get_strg(label, "literal");
557 p = cfg_get_strg(label, "root");
564 if (cfg_get_flag(label, "read-only")) {
568 if (cfg_get_flag(label, "read-write")) {
572 p = cfg_get_strg(label, "ramdisk");
574 strcpy (q, "ramdisk=");
579 p = cfg_get_strg(label, "initrd-size");
581 strcpy (q, "ramdisk_size=");
586 if (cfg_get_flag(label, "novideo")) {
587 strcpy (q, "video=ofonly");
591 p = cfg_get_strg (label, "append");
598 pause_after = cfg_get_flag (label, "pause-after");
599 p = cfg_get_strg(label, "pause-message");
608 void check_password(char *str)
612 prom_printf("\n%s", str);
613 for (i = 0; i < 3; i++) {
614 prom_printf ("\nPassword: ");
616 cmdedit ((void (*)(void)) 0, 1);
618 #ifdef USE_MD5_PASSWORDS
619 if (!strncmp (password, "$1$", 3)) {
620 if (!check_md5_password(passwdbuff, password))
623 else if (!strcmp (password, passwdbuff))
626 if (!strcmp (password, passwdbuff))
628 #endif /* USE_MD5_PASSWORDS */
631 prom_printf ("Incorrect password. Try again.");
634 prom_printf(" ___________________\n< Permission denied >\n -------------------\n"
635 " \\ ^__^\n \\ (oo)\\_______\n (__)\\ )\\/\\\n"
636 " ||----w |\n || ||\n");
638 prom_interpret("reset-all");
641 int get_params(struct boot_param_t* params)
645 char defdevice_bak[1024];
648 char *imagename = 0, *label;
653 static int first = 1;
654 static char imagepath[1024];
655 static char initrdpath[1024];
656 static char sysmappath[1024];
657 static char manualinitrd[1024];
658 static int definitrd = 1, hasarg = 0;
661 memset(params, 0, sizeof(*params));
663 params->kernel.part = -1;
664 params->rd.part = -1;
665 params->sysmap.part = -1;
672 imagename = bootargs;
673 word_split(&imagename, ¶ms->args);
674 timeout = DEFAULT_TIMEOUT;
676 prom_printf("Default supplied on the command line: %s ", imagename);
678 prom_printf("%s", params->args);
681 if (useconf && (q = cfg_get_strg(0, "timeout")) != 0 && *q != 0)
682 timeout = simple_strtol(q, NULL, 0);
685 prom_printf("boot: ");
690 end = beg + 100 * timeout;
692 c = prom_nbgetchar();
693 } while (c == -1 && prom_getms() <= end);
697 else if (c != '\n' && c != '\t' && c != '\r' && c != '\b' ) {
703 if (c != -1 && c != '\n' && c != '\r') {
706 } else if (c >= ' ') {
709 if ((cfg_get_flag (cbuff, "single-key")) && useconf) {
712 prom_printf("%s\n", cbuff);
717 if (c == '\n' || c == '\r') {
719 if (bootoncelabel[0] != 0)
720 imagename = bootoncelabel;
722 imagename = cfg_get_default();
725 prom_printf("%s", imagename);
727 prom_printf(" %s", params->args);
729 } else if (!singlekey) {
730 cmdedit(maintabfunc, 0);
732 strcpy(given_bootargs, cbuff);
733 given_bootargs_by_user = 1;
735 word_split(&imagename, ¶ms->args);
738 /* initrd setup via cmd console */
739 /* first, check if the user uses it with some label */
740 if (!strncmp(params->args, "initrd=", 7)) {
741 DEBUG_F("params->args: %s\n", params->args);
744 /* after, check if there is the 'initrd=' in the imagename string */
745 if (!strncmp(imagename, "initrd=", 7) || !definitrd) {
747 /* return the value of definitrd to 1 */
751 /* args = "initrd=blah" */
762 /* copy the string after the '=' to manualinitrd */
763 strcpy(manualinitrd, args+7);
765 prom_printf("New initrd file specified: %s\n", manualinitrd);
767 prom_printf("ERROR: no initrd specified!\n");
771 /* set imagename with the default values of the config file */
772 if ((prom_get_devtype(boot.dev) == FILE_DEVICE_NET) && !hasarg)
773 imagename = cfg_get_default();
775 imagename = cfg_get_default();
778 /* chrp gets this wrong, force it -- Cort */
779 if ( useconf && (!imagename || imagename[0] == 0 ))
780 imagename = cfg_get_default();
783 defdevice = boot.dev;
785 strcpy(defdevice_bak,defdevice);
788 defdevice = cfg_get_strg(0, "device");
789 p = cfg_get_strg(0, "partition");
791 n = simple_strtol(p, &endp, 10);
792 if (endp != p && *endp == 0)
795 p = cfg_get_strg(0, "pause-message");
798 if (cfg_get_flag(0, "restricted"))
800 p = cfg_get_strg(imagename, "image");
804 defdevice = cfg_get_strg(label, "device");
805 if(!defdevice) defdevice=boot.dev;
806 p = cfg_get_strg(label, "partition");
808 n = simple_strtol(p, &endp, 10);
809 if (endp != p && *endp == 0)
812 if (cfg_get_flag(label, "restricted"))
815 if (params->args && password && restricted)
816 check_password ("To specify arguments for this image "
817 "you must enter the password.");
818 else if (password && !restricted)
819 check_password ("This image is restricted.");
821 params->args = make_params(label, params->args);
825 if (!strcmp (imagename, "help")) {
826 /* FIXME: defdevice shouldn't need to be reset all over the place */
827 if(!defdevice) defdevice = boot.dev;
829 "\nPress the tab key for a list of defined images.\n"
830 "The label marked with a \"*\" is is the default image, "
831 "press <return> to boot it.\n\n"
832 "To boot any other label simply type its name and press <return>.\n\n"
833 "To boot a kernel image which is not defined in the yaboot configuration \n"
834 "file, enter the kernel image name as [[device:][partno],]/path, where \n"
835 "\"device:\" is the OpenFirmware device path to the disk the image \n"
836 "resides on, and \"partno\" is the partition number the image resides on.\n"
837 "Note that the comma (,) is only required if you specify an OpenFirmware\n"
838 "device, if you only specify a filename you should not start it with a \",\"\n\n"
839 "To boot a alternative initrd file rather than specified in the yaboot\n"
840 "configuration file, use the \"initrd\" command on Yaboot's prompt: \n"
841 "\"initrd=[name.img]\". This will load the \"name.img\" file after the default\n"
842 "kernel image. You can, also, specify a different initrd file to any other\n"
843 "label of the yaboot configuration file. Just type \"label initrd=[name.img]\"\n"
844 "and the specified initrd file will be loaded.\n\n"
845 "To load an alternative config file rather than /etc/yaboot.conf, enter\n"
846 "its device, partno and path, on Open Firmware Prompt:\n"
847 "boot conf=device:partno,/path/to/configfile\n."
848 "To reload the config file or load a new one, use the \"conf\" command\n"
849 "on Yaboot's prompt:\n"
850 "conf [device=device] [partition=partno] [file=/path/to/configfile]\n\n"
851 "If you omit \"device\" and \"partno\", Yaboot will use their current\n"
852 "values. You can check them by entering \"conf\" on Yaboot's prompt.\n");
857 if (!strcmp (imagename, "halt")) {
859 check_password ("Restricted command.");
863 if (!strcmp (imagename, "bye")) {
865 check_password ("Restricted command.");
871 if (!strncmp (imagename, "conf", 4)) {
873 // imagename = "conf file=blah dev=bleh part=blih"
874 DEBUG_F("Loading user-specified config file: %s\n",imagename);
876 check_password ("Restricted command.");
880 // args= "file=blah dev=bleh part=blih"
881 char *args = params->args;
885 // set a pointer to the first space in args
886 char *space = strchr(args,' ');
890 char temp[1024] = "0";
892 // copy next argument to temp
893 strncpy(temp, args, space-args);
895 // parse temp and set boot arguments
896 if (!strncmp (temp, "file=", 5)){
897 DEBUG_F("conf file: %s\n", temp+5);
898 strcpy(boot.file, temp+5);
899 } else if (!strncmp (temp, "device=", 7)){
900 DEBUG_F("conf device: %s\n", temp+7);
901 strcpy(boot.dev, temp+7);
902 } else if (!strncmp (temp, "partition=", 10)){
903 DEBUG_F("conf partition: %s\n", temp+10);
904 boot.part=simple_strtol(temp+10,NULL,10);
908 // set the pointer to the next space in args;
909 // set the loop control variable
910 if (strlen(space)>1){
911 // Go to the next argument
915 if (strchr(args,' ') == NULL)
916 space = &args[strlen(args)];
918 space = strchr(args,' ');
925 prom_printf("Loading config file...\n");
926 useconf = load_config_file(&boot);
928 if ((q = cfg_get_strg(0, "timeout")) != 0 && *q != 0)
929 timeout = simple_strtol(q, NULL, 0);
931 prom_printf("Restoring default values.\n");
932 strcpy(boot.file,"");
933 strcpy(boot.dev, defdevice_bak);
938 prom_printf("Current configuration:\n");
939 prom_printf("device: %s\n", boot.dev);
941 prom_printf("partition: auto\n");
943 prom_printf("partition: %d\n", boot.part);
944 if (strlen(boot.file))
945 prom_printf("file: %s\n", boot.file);
947 prom_printf("file: /etc/%s\n",CONFIG_FILE_NAME);
956 if (imagename[0] == '$') {
957 /* forth command string */
959 check_password ("OpenFirmware commands are restricted.");
960 prom_interpret(imagename+1);
964 strncpy(imagepath, imagename, 1024);
966 if (!label && password)
967 check_password ("To boot a custom image you must enter the password.");
969 if (!parse_device_path(imagepath, defdevice, defpart,
970 "/vmlinux", ¶ms->kernel)) {
971 prom_printf("%s: Unable to parse\n", imagepath);
974 DEBUG_F("after parse_device_path: dev=%s part=%d file=%s\n", params->kernel.dev, params->kernel.part, params->kernel.file);
976 p = cfg_get_strg(label, "initrd");
979 /* check if user seted to use a initrd file from boot console */
980 if (!definitrd && p != manualinitrd) {
981 if (manualinitrd[0] != "/" && (prom_get_devtype(defdevice_bak) != FILE_DEVICE_NET)) {
982 strcpy(initrdpath, "/");
983 strcat(initrdpath, manualinitrd);
985 strncpy(initrdpath, manualinitrd, 1024);
987 strncpy(initrdpath, p, 1024);
989 DEBUG_F("Parsing initrd path <%s>\n", initrdpath);
990 if (!parse_device_path(initrdpath, defdevice, defpart,
991 "/root.bin", ¶ms->rd)) {
992 prom_printf("%s: Unable to parse\n", imagepath);
996 p = cfg_get_strg(label, "sysmap");
998 DEBUG_F("Parsing sysmap path <%s>\n", p);
999 strncpy(sysmappath, p, 1024);
1000 if (!parse_device_path(sysmappath, defdevice, defpart,
1001 "/boot/System.map", ¶ms->sysmap)) {
1002 prom_printf("%s: Unable to parse\n", imagepath);
1010 /* This is derived from quik core. To be changed to first parse the headers
1011 * doing lazy-loading, and then claim the memory before loading the kernel
1013 * We also need to add initrd support to this whole mecanism
1016 yaboot_text_ui(void)
1018 #define MAX_HEADERS 32
1020 struct boot_file_t file;
1022 static struct boot_param_t params;
1024 unsigned long initrd_size;
1026 unsigned long sysmap_size;
1027 kernel_entry_t kernel_entry;
1028 struct bi_record* birec;
1030 loadinfo_t loadinfo;
1031 void *initrd_more,*initrd_want;
1032 unsigned long initrd_read;
1034 loadinfo.load_loc = 0;
1042 if (get_params(¶ms))
1044 if (!params.kernel.file)
1047 prom_printf("Please wait, loading kernel...\n");
1049 memset(&file, 0, sizeof(file));
1051 if (strlen(boot.file) && !strcmp(boot.file,"\\\\") && params.kernel.file[0] != '/'
1052 && params.kernel.file[0] != '\\') {
1053 loc=(char*)malloc(strlen(params.kernel.file)+3);
1055 prom_printf ("malloc error\n");
1058 strcpy(loc,boot.file);
1059 strcat(loc,params.kernel.file);
1060 free(params.kernel.file);
1061 params.kernel.file=loc;
1063 result = open_file(¶ms.kernel, &file);
1064 if (result != FILE_ERR_OK) {
1065 prom_printf("%s:%d,", params.kernel.dev, params.kernel.part);
1066 prom_perror(result, params.kernel.file);
1070 /* Read the Elf e_ident, e_type and e_machine fields to
1071 * determine Elf file type
1073 if (file.fs->read(&file, sizeof(Elf_Ident), &loadinfo.elf) < sizeof(Elf_Ident)) {
1074 prom_printf("\nCan't read Elf e_ident/e_type/e_machine info\n");
1075 file.fs->close(&file);
1076 memset(&file, 0, sizeof(file));
1080 if (is_elf32(&loadinfo)) {
1081 if (!load_elf32(&file, &loadinfo)) {
1082 file.fs->close(&file);
1083 memset(&file, 0, sizeof(file));
1086 prom_printf(" Elf32 kernel loaded...\n");
1087 } else if (is_elf64(&loadinfo)) {
1088 if (!load_elf64(&file, &loadinfo)) {
1089 file.fs->close(&file);
1090 memset(&file, 0, sizeof(file));
1093 prom_printf(" Elf64 kernel loaded...\n");
1095 prom_printf ("%s: Not a valid ELF image\n", params.kernel.file);
1096 file.fs->close(&file);
1097 memset(&file, 0, sizeof(file));
1100 file.fs->close(&file);
1101 memset(&file, 0, sizeof(file));
1103 /* If sysmap, load it (only if booting a vmlinux).
1105 if (flat_vmlinux && params.sysmap.file) {
1106 prom_printf("Loading System.map ...\n");
1107 if(strlen(boot.file) && !strcmp(boot.file,"\\\\") && params.sysmap.file[0] != '/'
1108 && params.sysmap.file[0] != '\\') {
1110 loc=(char*)malloc(strlen(params.sysmap.file)+3);
1112 prom_printf ("malloc error\n");
1115 strcpy(loc,boot.file);
1116 strcat(loc,params.sysmap.file);
1117 free(params.sysmap.file);
1118 params.sysmap.file=loc;
1121 result = open_file(¶ms.sysmap, &file);
1122 if (result != FILE_ERR_OK) {
1123 prom_printf("%s:%d,", params.sysmap.dev, params.sysmap.part);
1124 prom_perror(result, params.sysmap.file);
1127 sysmap_base = prom_claim(loadinfo.base+loadinfo.memsize, 0x100000, 0);
1128 if (sysmap_base == (void *)-1) {
1129 prom_printf("Claim failed for sysmap memory\n");
1133 sysmap_size = file.fs->read(&file, 0xfffff, sysmap_base);
1134 if (sysmap_size == 0)
1137 ((char *)sysmap_base)[sysmap_size++] = 0;
1139 file.fs->close(&file);
1140 memset(&file, 0, sizeof(file));
1143 prom_printf("System.map loaded at %p, size: %lu Kbytes\n",
1144 sysmap_base, sysmap_size >> 10);
1145 loadinfo.memsize += _ALIGN(0x100000, 0x1000);
1147 prom_printf("System.map load failed !\n");
1152 /* If ramdisk, load it (only if booting a vmlinux). For now, we
1153 * can't tell the size it will be so we claim an arbitrary amount
1156 if (flat_vmlinux && params.rd.file) {
1157 if(strlen(boot.file) && !strcmp(boot.file,"\\\\") && params.rd.file[0] != '/'
1158 && params.kernel.file[0] != '\\')
1161 loc=(char*)malloc(strlen(params.rd.file)+3);
1163 prom_printf ("Malloc error\n");
1166 strcpy(loc,boot.file);
1167 strcat(loc,params.rd.file);
1168 free(params.rd.file);
1171 prom_printf("Loading ramdisk...\n");
1172 result = open_file(¶ms.rd, &file);
1173 if (result != FILE_ERR_OK) {
1174 prom_printf("%s:%d,", params.rd.dev, params.rd.part);
1175 prom_perror(result, params.rd.file);
1178 #define INITRD_CHUNKSIZE 0x100000
1179 initrd_base = prom_claim(loadinfo.base+loadinfo.memsize, INITRD_CHUNKSIZE, 0);
1180 if (initrd_base == (void *)-1) {
1181 prom_printf("Claim failed for initrd memory\n");
1184 initrd_size = file.fs->read(&file, INITRD_CHUNKSIZE, initrd_base);
1185 if (initrd_size == 0)
1187 initrd_read = initrd_size;
1188 initrd_more = initrd_base;
1189 while (initrd_read == INITRD_CHUNKSIZE ) { /* need to read more? */
1190 initrd_want = (void *)((unsigned long)initrd_more+INITRD_CHUNKSIZE);
1191 initrd_more = prom_claim(initrd_want, INITRD_CHUNKSIZE, 0);
1192 if (initrd_more != initrd_want) {
1193 prom_printf("Claim failed for initrd memory at %p rc=%p\n",initrd_want,initrd_more);
1197 initrd_read = file.fs->read(&file, INITRD_CHUNKSIZE, initrd_more);
1198 DEBUG_F(" block at %p rc=%lu\n",initrd_more,initrd_read);
1199 initrd_size += initrd_read;
1202 file.fs->close(&file);
1203 memset(&file, 0, sizeof(file));
1206 prom_printf("ramdisk loaded at %p, size: %lu Kbytes\n",
1207 initrd_base, initrd_size >> 10);
1209 prom_printf("ramdisk load failed !\n");
1214 DEBUG_F("setting kernel args to: %s\n", params.args);
1215 prom_setargs(params.args);
1216 DEBUG_F("flushing icache...");
1217 flush_icache_range ((long)loadinfo.base, (long)loadinfo.base+loadinfo.memsize);
1222 * Fill new boot infos (only if booting a vmlinux).
1224 * The birec is low on memory, probably inside the malloc pool,
1225 * so we don't write it earlier. At this point, we should not
1226 * use anything coming from the malloc pool.
1228 birec = (struct bi_record *)_ALIGN(loadinfo.filesize+(1<<20)-1,(1<<20));
1230 /* We make sure it's mapped. We map only 64k for now, it's
1231 * plenty enough we don't claim since this precise memory
1232 * range may already be claimed by the malloc pool.
1234 prom_map (birec, birec, 0x10000);
1235 DEBUG_F("birec at %p\n", birec);
1238 birec->tag = BI_FIRST;
1239 birec->size = sizeof(struct bi_record);
1240 birec = (struct bi_record *)((ulong)birec + birec->size);
1242 birec->tag = BI_BOOTLOADER_ID;
1243 sprintf( (char *)birec->data, "yaboot");
1244 birec->size = sizeof(struct bi_record) + strlen("yaboot") + 1;
1245 birec = (struct bi_record *)((ulong)birec + birec->size);
1247 birec->tag = BI_MACHTYPE;
1248 birec->data[0] = _machine;
1249 birec->size = sizeof(struct bi_record) + sizeof(ulong);
1250 birec = (struct bi_record *)((ulong)birec + birec->size);
1253 birec->tag = BI_SYSMAP;
1254 birec->data[0] = (ulong)sysmap_base;
1255 birec->data[1] = sysmap_size;
1256 birec->size = sizeof(struct bi_record) + sizeof(ulong)*2;
1257 birec = (struct bi_record *)((ulong)birec + birec->size);
1259 birec->tag = BI_LAST;
1260 birec->size = sizeof(struct bi_record);
1261 birec = (struct bi_record *)((ulong)birec + birec->size);
1264 /* compute the kernel's entry point. */
1265 kernel_entry = loadinfo.base + loadinfo.entry - loadinfo.load_loc;
1267 DEBUG_F("Kernel entry point = %p\n", kernel_entry);
1268 DEBUG_F("kernel: arg1 = %p,\n"
1269 " arg2 = 0x%08lx,\n"
1273 initrd_base + loadinfo.load_loc, initrd_size, prom, 0, 0);
1275 DEBUG_F("Entering kernel...\n");
1277 /* call the kernel with our stack. */
1278 kernel_entry(initrd_base + loadinfo.load_loc, initrd_size, prom, 0, 0);
1286 load_elf32(struct boot_file_t *file, loadinfo_t *loadinfo)
1289 Elf32_Ehdr *e = &(loadinfo->elf.elf32hdr);
1291 int size = sizeof(Elf32_Ehdr) - sizeof(Elf_Ident);
1292 unsigned long loadaddr;
1294 /* Read the rest of the Elf header... */
1295 if ((*(file->fs->read))(file, size, &e->e_version) < size) {
1296 prom_printf("\nCan't read Elf32 image header\n");
1300 DEBUG_F("Elf32 header:\n");
1301 DEBUG_F(" e.e_type = %d\n", (int)e->e_type);
1302 DEBUG_F(" e.e_machine = %d\n", (int)e->e_machine);
1303 DEBUG_F(" e.e_version = %d\n", (int)e->e_version);
1304 DEBUG_F(" e.e_entry = 0x%08x\n", (int)e->e_entry);
1305 DEBUG_F(" e.e_phoff = 0x%08x\n", (int)e->e_phoff);
1306 DEBUG_F(" e.e_shoff = 0x%08x\n", (int)e->e_shoff);
1307 DEBUG_F(" e.e_flags = %d\n", (int)e->e_flags);
1308 DEBUG_F(" e.e_ehsize = 0x%08x\n", (int)e->e_ehsize);
1309 DEBUG_F(" e.e_phentsize = 0x%08x\n", (int)e->e_phentsize);
1310 DEBUG_F(" e.e_phnum = %d\n", (int)e->e_phnum);
1312 loadinfo->entry = e->e_entry;
1314 if (e->e_phnum > MAX_HEADERS) {
1315 prom_printf ("Can only load kernels with one program header\n");
1319 ph = (Elf32_Phdr *)malloc(sizeof(Elf32_Phdr) * e->e_phnum);
1321 prom_printf ("Malloc error\n");
1325 /* Now, we read the section header */
1326 if ((*(file->fs->seek))(file, e->e_phoff) != FILE_ERR_OK) {
1327 prom_printf ("seek error\n");
1330 if ((*(file->fs->read))(file, sizeof(Elf32_Phdr) * e->e_phnum, ph) !=
1331 sizeof(Elf32_Phdr) * e->e_phnum) {
1332 prom_printf ("read error\n");
1336 /* Scan through the program header
1337 * HACK: We must return the _memory size of the kernel image, not the
1338 * file size (because we have to leave room before other boot
1339 * infos. This code works as a side effect of the fact that
1340 * we have one section and vaddr == p_paddr
1342 loadinfo->memsize = loadinfo->filesize = loadinfo->offset = 0;
1344 for (i = 0; i < e->e_phnum; ++i, ++p) {
1345 if (p->p_type != PT_LOAD || p->p_offset == 0)
1347 if (loadinfo->memsize == 0) {
1348 loadinfo->offset = p->p_offset;
1349 loadinfo->memsize = p->p_memsz;
1350 loadinfo->filesize = p->p_filesz;
1351 loadinfo->load_loc = p->p_vaddr;
1353 loadinfo->memsize = p->p_offset + p->p_memsz - loadinfo->offset; /* XXX Bogus */
1354 loadinfo->filesize = p->p_offset + p->p_filesz - loadinfo->offset;
1358 if (loadinfo->memsize == 0) {
1359 prom_printf("Can't find a loadable segment !\n");
1363 /* leave some room (1Mb) for boot infos */
1364 loadinfo->memsize = _ALIGN(loadinfo->memsize,(1<<20)) + 0x100000;
1365 /* Claim OF memory */
1366 DEBUG_F("Before prom_claim, mem_sz: 0x%08lx\n", loadinfo->memsize);
1368 /* Determine whether we are trying to boot a vmlinux or some
1369 * other binary image (eg, zImage). We load vmlinux's at
1370 * KERNELADDR and all other binaries at their e_entry value.
1372 if (e->e_entry == KERNEL_LINK_ADDR_PPC32) {
1374 loadaddr = KERNELADDR;
1377 loadaddr = loadinfo->load_loc;
1380 loadinfo->base = prom_claim_chunk((void *)loadaddr, loadinfo->memsize, 0);
1381 if (loadinfo->base == (void *)-1) {
1382 prom_printf("Claim error, can't allocate kernel memory\n");
1386 DEBUG_F("After ELF parsing, load base: %p, mem_sz: 0x%08lx\n",
1387 loadinfo->base, loadinfo->memsize);
1388 DEBUG_F(" wanted load base: 0x%08lx, mem_sz: 0x%08lx\n",
1389 loadaddr, loadinfo->memsize);
1391 /* Load the program segments... */
1393 for (i = 0; i < e->e_phnum; ++i, ++p) {
1394 unsigned long offset;
1395 if (p->p_type != PT_LOAD || p->p_offset == 0)
1398 /* Now, we skip to the image itself */
1399 if ((*(file->fs->seek))(file, p->p_offset) != FILE_ERR_OK) {
1400 prom_printf ("Seek error\n");
1401 prom_release(loadinfo->base, loadinfo->memsize);
1404 offset = p->p_vaddr - loadinfo->load_loc;
1405 if ((*(file->fs->read))(file, p->p_filesz, loadinfo->base+offset) != p->p_filesz) {
1406 prom_printf ("Read failed\n");
1407 prom_release(loadinfo->base, loadinfo->memsize);
1414 /* Return success at loading the Elf32 kernel */
1424 load_elf64(struct boot_file_t *file, loadinfo_t *loadinfo)
1427 Elf64_Ehdr *e = &(loadinfo->elf.elf64hdr);
1429 int size = sizeof(Elf64_Ehdr) - sizeof(Elf_Ident);
1430 unsigned long loadaddr;
1432 /* Read the rest of the Elf header... */
1433 if ((*(file->fs->read))(file, size, &e->e_version) < size) {
1434 prom_printf("\nCan't read Elf64 image header\n");
1438 DEBUG_F("Elf64 header:\n");
1439 DEBUG_F(" e.e_type = %d\n", (int)e->e_type);
1440 DEBUG_F(" e.e_machine = %d\n", (int)e->e_machine);
1441 DEBUG_F(" e.e_version = %d\n", (int)e->e_version);
1442 DEBUG_F(" e.e_entry = 0x%016lx\n", (long)e->e_entry);
1443 DEBUG_F(" e.e_phoff = 0x%016lx\n", (long)e->e_phoff);
1444 DEBUG_F(" e.e_shoff = 0x%016lx\n", (long)e->e_shoff);
1445 DEBUG_F(" e.e_flags = %d\n", (int)e->e_flags);
1446 DEBUG_F(" e.e_ehsize = 0x%08x\n", (int)e->e_ehsize);
1447 DEBUG_F(" e.e_phentsize = 0x%08x\n", (int)e->e_phentsize);
1448 DEBUG_F(" e.e_phnum = %d\n", (int)e->e_phnum);
1450 loadinfo->entry = e->e_entry;
1452 if (e->e_phnum > MAX_HEADERS) {
1453 prom_printf ("Can only load kernels with one program header\n");
1457 ph = (Elf64_Phdr *)malloc(sizeof(Elf64_Phdr) * e->e_phnum);
1459 prom_printf ("Malloc error\n");
1463 /* Now, we read the section header */
1464 if ((*(file->fs->seek))(file, e->e_phoff) != FILE_ERR_OK) {
1465 prom_printf ("Seek error\n");
1468 if ((*(file->fs->read))(file, sizeof(Elf64_Phdr) * e->e_phnum, ph) !=
1469 sizeof(Elf64_Phdr) * e->e_phnum) {
1470 prom_printf ("Read error\n");
1474 /* Scan through the program header
1475 * HACK: We must return the _memory size of the kernel image, not the
1476 * file size (because we have to leave room before other boot
1477 * infos. This code works as a side effect of the fact that
1478 * we have one section and vaddr == p_paddr
1480 loadinfo->memsize = loadinfo->filesize = loadinfo->offset = 0;
1482 for (i = 0; i < e->e_phnum; ++i, ++p) {
1483 if (p->p_type != PT_LOAD || p->p_offset == 0)
1485 if (loadinfo->memsize == 0) {
1486 loadinfo->offset = p->p_offset;
1487 loadinfo->memsize = p->p_memsz;
1488 loadinfo->filesize = p->p_filesz;
1489 loadinfo->load_loc = p->p_vaddr;
1491 loadinfo->memsize = p->p_offset + p->p_memsz - loadinfo->offset; /* XXX Bogus */
1492 loadinfo->filesize = p->p_offset + p->p_filesz - loadinfo->offset;
1496 if (loadinfo->memsize == 0) {
1497 prom_printf("Can't find a loadable segment !\n");
1501 /* leave some room (1Mb) for boot infos */
1502 loadinfo->memsize = _ALIGN(loadinfo->memsize,(1<<20)) + 0x100000;
1503 /* Claim OF memory */
1504 DEBUG_F("Before prom_claim, mem_sz: 0x%08lx\n", loadinfo->memsize);
1506 /* Determine whether we are trying to boot a vmlinux or some
1507 * other binary image (eg, zImage). We load vmlinux's at
1508 * KERNELADDR and all other binaries at their e_entry value.
1510 if (e->e_entry == KERNEL_LINK_ADDR_PPC64) {
1512 loadaddr = KERNELADDR;
1515 loadaddr = e->e_entry;
1518 loadinfo->base = prom_claim_chunk((void *)loadaddr, loadinfo->memsize, 0);
1519 if (loadinfo->base == (void *)-1) {
1520 prom_printf("Claim error, can't allocate kernel memory\n");
1524 DEBUG_F("After ELF parsing, load base: %p, mem_sz: 0x%08lx\n",
1525 loadinfo->base, loadinfo->memsize);
1526 DEBUG_F(" wanted load base: 0x%08lx, mem_sz: 0x%08lx\n",
1527 loadaddr, loadinfo->memsize);
1529 /* Load the program segments... */
1531 for (i = 0; i < e->e_phnum; ++i, ++p) {
1532 unsigned long offset;
1533 if (p->p_type != PT_LOAD || p->p_offset == 0)
1536 /* Now, we skip to the image itself */
1537 if ((*(file->fs->seek))(file, p->p_offset) != FILE_ERR_OK) {
1538 prom_printf ("Seek error\n");
1539 prom_release(loadinfo->base, loadinfo->memsize);
1542 offset = p->p_vaddr - loadinfo->load_loc;
1543 if ((*(file->fs->read))(file, p->p_filesz, loadinfo->base+offset) != p->p_filesz) {
1544 prom_printf ("Read failed\n");
1545 prom_release(loadinfo->base, loadinfo->memsize);
1552 /* Return success at loading the Elf64 kernel */
1562 is_elf32(loadinfo_t *loadinfo)
1564 Elf32_Ehdr *e = &(loadinfo->elf.elf32hdr);
1566 return (e->e_ident[EI_MAG0] == ELFMAG0 &&
1567 e->e_ident[EI_MAG1] == ELFMAG1 &&
1568 e->e_ident[EI_MAG2] == ELFMAG2 &&
1569 e->e_ident[EI_MAG3] == ELFMAG3 &&
1570 e->e_ident[EI_CLASS] == ELFCLASS32 &&
1571 e->e_ident[EI_DATA] == ELFDATA2MSB &&
1572 e->e_type == ET_EXEC &&
1573 e->e_machine == EM_PPC);
1577 is_elf64(loadinfo_t *loadinfo)
1579 Elf64_Ehdr *e = &(loadinfo->elf.elf64hdr);
1581 return (e->e_ident[EI_MAG0] == ELFMAG0 &&
1582 e->e_ident[EI_MAG1] == ELFMAG1 &&
1583 e->e_ident[EI_MAG2] == ELFMAG2 &&
1584 e->e_ident[EI_MAG3] == ELFMAG3 &&
1585 e->e_ident[EI_CLASS] == ELFCLASS64 &&
1586 e->e_ident[EI_DATA] == ELFDATA2MSB &&
1587 e->e_type == ET_EXEC &&
1588 e->e_machine == EM_PPC64);
1594 #ifdef CONFIG_SET_COLORMAP
1595 static unsigned char default_colors[] = {
1614 prom_handle scrn = PROM_INVALID_HANDLE;
1616 /* Try Apple's mac-boot screen ihandle */
1617 result = (int)call_prom_return("interpret", 1, 2,
1618 "\" _screen-ihandle\" $find if execute else 0 then", &scrn);
1619 DEBUG_F("Trying to get screen ihandle, result: %d, scrn: %p\n", result, scrn);
1621 if (scrn == 0 || scrn == PROM_INVALID_HANDLE) {
1623 /* Hrm... check to see if stdout is a display */
1624 scrn = call_prom ("instance-to-package", 1, 1, prom_stdout);
1625 DEBUG_F("instance-to-package of stdout is: %p\n", scrn);
1626 if (prom_getprop(scrn, "device_type", type, 32) > 0 && !strncmp(type, "display", 7)) {
1627 DEBUG_F("got it ! stdout is a screen\n");
1630 /* Else, we try to open the package */
1631 scrn = (prom_handle)call_prom( "open", 1, 1, "screen" );
1632 DEBUG_F("Open screen result: %p\n", scrn);
1636 if (scrn == PROM_INVALID_HANDLE) {
1637 prom_printf("No screen device found !\n");
1641 prom_set_color(scrn, i, default_colors[i*3],
1642 default_colors[i*3+1], default_colors[i*3+2]);
1644 prom_printf("\x1b[1;37m\x1b[2;40m");
1646 for (i=0;i<16; i++) {
1647 prom_printf("\x1b[%d;%dm\x1b[1;47m%s \x1b[2;40m %s\n",
1648 ansi_color_table[i].index,
1649 ansi_color_table[i].value,
1650 ansi_color_table[i].name,
1651 ansi_color_table[i].name);
1652 prom_printf("\x1b[%d;%dm\x1b[1;37m%s \x1b[2;30m %s\n",
1653 ansi_color_table[i].index,
1654 ansi_color_table[i].value+10,
1655 ansi_color_table[i].name,
1656 ansi_color_table[i].name);
1658 prom_printf("\x1b[1;37m\x1b[2;40m");
1659 #endif /* COLOR_TEST */
1665 #endif /* CONFIG_SET_COLORMAP */
1673 char conf_path[1024];
1675 if (_machine == _MACH_Pmac)
1678 prom_get_chosen("bootargs", bootargs, sizeof(bootargs));
1679 DEBUG_F("/chosen/bootargs = %s\n", bootargs);
1680 prom_get_chosen("bootpath", bootdevice, BOOTDEVSZ);
1681 DEBUG_F("/chosen/bootpath = %s\n", bootdevice);
1683 /* If conf= specified on command line, it overrides
1684 Usage: conf=device:partition,/path/to/conffile
1685 Example: On Open Firmware Prompt, type
1686 boot conf=/pci@8000000f8000000/pci@1/pci1014,028C@1/scsi@0/sd@1,0:3,/etc/yaboot.conf */
1688 if (!strncmp(bootargs, "conf=", 5)) {
1689 DEBUG_F("Using conf argument in Open Firmware\n");
1690 char *end = strchr(bootargs,' ');
1694 strcpy(bootdevice, bootargs + 5);
1696 DEBUG_F("Using conf=%s\n", bootdevice);
1698 /* Remove conf=xxx from bootargs */
1700 memmove(bootargs, end+1, strlen(end+1)+1);
1704 if (bootdevice[0] == 0) {
1705 prom_get_options("boot-device", bootdevice, BOOTDEVSZ);
1706 DEBUG_F("boot-device = %s\n", bootdevice);
1708 if (bootdevice[0] == 0) {
1709 prom_printf("Couldn't determine boot device\n");
1713 if (bootoncelabel[0] == 0) {
1714 prom_get_options("boot-once", bootoncelabel,
1715 sizeof(bootoncelabel));
1716 if (bootoncelabel[0] != 0)
1717 DEBUG_F("boot-once: [%s]\n", bootoncelabel);
1719 prom_set_options("boot-once", NULL, 0);
1721 if (!parse_device_path(bootdevice, NULL, -1, "", &boot)) {
1722 prom_printf("%s: Unable to parse\n", bootdevice);
1725 DEBUG_F("After parse_device_path: dev=%s, part=%d, file=%s\n",
1726 boot.dev, boot.part, boot.file);
1729 if (_machine == _MACH_chrp)
1730 boot.file = "/etc/";
1731 else if (strlen(boot.file)) {
1732 if (!strncmp(boot.file, "\\\\", 2))
1736 p = last = boot.file;
1746 if (strlen(boot.file))
1747 strcat(boot.file, "\\");
1750 strcpy(conf_path, boot.file);
1751 strcat(conf_path, CONFIG_FILE_NAME);
1752 boot.file = conf_path;
1753 DEBUG_F("After path kludgeup: dev=%s, part=%d, file=%s\n",
1754 boot.dev, boot.part, boot.file);
1758 * If we're doing a netboot, first look for one which matches our
1761 if (prom_get_devtype(boot.dev) == FILE_DEVICE_NET) {
1762 prom_printf("Try to netboot\n");
1763 useconf = load_my_config_file(&boot);
1767 useconf = load_config_file(&boot);
1769 prom_printf("Welcome to yaboot version " VERSION "\n");
1770 prom_printf("Enter \"help\" to get some basic usage information\n");
1772 /* I am fed up with lusers using the wrong partition type and
1773 mailing me *when* it breaks */
1775 if (_machine == _MACH_Pmac) {
1776 char *entry = cfg_get_strg(0, "ptypewarning");
1779 warn = strcmp(entry,
1780 "I_know_the_partition_type_is_wrong_and_will_NOT_send_mail_when_booting_breaks");
1782 ptype = get_part_type(boot.dev, boot.part);
1783 if ((ptype != NULL) && (strcmp(ptype, "Apple_Bootstrap")))
1784 prom_printf("\nWARNING: Bootstrap partition type is wrong: \"%s\"\n"
1785 " type should be: \"Apple_Bootstrap\"\n\n", ptype);
1793 prom_printf("Bye.\n");
1799 * c-file-style: "k&r"