1 /* Yaboot - secondary boot loader for Linux on ppc.
3 Copyright (C) 1999 Benjamin Herrenschmidt
7 Copyright (C) 1999 Marius Vollmer
11 Copyright (C) 1996 Paul Mackerras.
13 Because this program is derived from the corresponding file in the
14 silo-0.64 distribution, it is also
16 Copyright (C) 1996 Pete A. Zaitcev
22 This program is free software; you can redistribute it and/or modify
23 it under the terms of the GNU General Public License as published by
24 the Free Software Foundation; either version 2 of the License, or
25 (at your option) any later version.
27 This program is distributed in the hope that it will be useful,
28 but WITHOUT ANY WARRANTY; without even the implied warranty of
29 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30 GNU General Public License for more details.
32 You should have received a copy of the GNU General Public License
33 along with this program; if not, write to the Free Software
34 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
47 #include "linux/elf.h"
51 #define CONFIG_FILE_NAME "yaboot.conf"
52 #define CONFIG_FILE_MAX 0x8000 /* 32k */
54 #ifdef USE_MD5_PASSWORDS
56 #endif /* USE_MD5_PASSWORDS */
58 /* align addr on a size boundry - adjust address up if needed -- Cort */
59 #define _ALIGN(addr,size) (((addr)+size-1)&(~(size-1)))
61 /* Addresses where the PPC32 and PPC64 vmlinux kernels are linked at.
62 * These are used to determine whether we are booting a vmlinux, in
63 * which case, it will be loaded at KERNELADDR. Otherwise (eg zImage),
64 * we load the binary where it was linked at (ie, e_entry field in
67 #define KERNEL_LINK_ADDR_PPC32 0xC0000000UL
68 #define KERNEL_LINK_ADDR_PPC64 0xC000000000000000ULL
76 unsigned long memsize;
77 unsigned long filesize;
79 unsigned long load_loc;
83 typedef void (*kernel_entry_t)( void *,
89 /* Imported functions */
90 extern unsigned long reloc_offset(void);
91 extern long flush_icache_range(unsigned long start, unsigned long stop);
93 /* Exported functions */
94 int yaboot_start(unsigned long r3, unsigned long r4, unsigned long r5);
97 static int yaboot_main(void);
98 static int is_elf32(loadinfo_t *loadinfo);
99 static int is_elf64(loadinfo_t *loadinfo);
100 static int load_elf32(struct boot_file_t *file, loadinfo_t *loadinfo);
101 static int load_elf64(struct boot_file_t *file, loadinfo_t *loadinfo);
102 static void setup_display(void);
104 /* Locals & globals */
107 char bootdevice[1024];
108 char *password = NULL;
109 struct boot_fspec_t boot;
110 int _machine = _MACH_Pmac;
112 #ifdef CONFIG_COLOR_TEXT
114 /* Color values for text ui */
115 static struct ansi_color_t {
119 } ansi_color_table[] = {
127 { "light-gray", 0, 37 },
128 { "dark-gray", 1, 30 },
129 { "light-blue", 1, 31 },
130 { "light-green", 1, 32 },
131 { "light-cyan", 1, 33 },
132 { "light-red", 1, 34 },
133 { "light-purple", 1, 35 },
139 /* Default colors for text ui */
142 #endif /* CONFIG_COLOR_TEXT */
146 static int test_data = 0;
148 static int pause_after;
149 static char *pause_message = "Type go<return> to continue.\n";
150 static char given_bootargs[1024];
151 static int given_bootargs_by_user = 0;
153 extern unsigned char linux_logo_red[];
154 extern unsigned char linux_logo_green[];
155 extern unsigned char linux_logo_blue[];
157 #define DEFAULT_TIMEOUT -1
159 /* Entry, currently called directly by crt0 (bss not inited) */
161 extern char* __bss_start;
164 static struct first_info *quik_fip = NULL;
167 yaboot_start (unsigned long r3, unsigned long r4, unsigned long r5)
170 void* malloc_base = NULL;
173 /* OF seems to do it, but I'm not very confident */
174 memset(&__bss_start, 0, &_end - &__bss_start);
176 /* Check for quik first stage bootloader (but I don't think we are
177 * compatible with it anyway, I'll look into backporting to older OF
180 if (r5 == 0xdeadbeef) {
182 quik_fip = (struct first_info *)r4;
185 /* Initialize OF interface */
186 prom_init ((prom_entry) r5);
188 /* Allocate some memory for malloc'ator */
189 malloc_base = prom_claim((void *)MALLOCADDR, MALLOCSIZE, 0);
190 if (malloc_base == (void *)-1) {
191 prom_printf("Can't claim malloc buffer (%d bytes at 0x%08x)\n",
192 MALLOCSIZE, MALLOCADDR);
195 malloc_init(malloc_base, MALLOCSIZE);
196 DEBUG_F("Malloc buffer allocated at %p (%d bytes)\n",
197 malloc_base, MALLOCSIZE);
199 /* A few useless DEBUG_F's */
200 DEBUG_F("reloc_offset : %ld (should be 0)\n", reloc_offset());
201 DEBUG_F("test_bss : %d (should be 0)\n", test_bss);
202 DEBUG_F("test_data : %d (should be 0)\n", test_data);
203 DEBUG_F("&test_data : %p\n", &test_data);
204 DEBUG_F("&test_bss : %p\n", &test_bss);
205 DEBUG_F("linked at : 0x%08x\n", TEXTADDR);
207 /* ask the OF info if we're a chrp or pmac */
208 /* we need to set _machine before calling finish_device_tree */
209 root = prom_finddevice("/");
211 static char model[256];
212 if (prom_getprop(root, "device_type", model, 256 ) > 0 &&
213 !strncmp("chrp", model, 4))
214 _machine = _MACH_chrp;
216 if (prom_getprop(root, "model", model, 256 ) > 0 &&
217 !strncmp(model, "IBM", 3))
218 _machine = _MACH_chrp;
222 DEBUG_F("Running on _machine = %d\n", _machine);
226 result = yaboot_main();
228 /* Get rid of malloc pool */
230 prom_release(malloc_base, MALLOCSIZE);
231 DEBUG_F("Malloc buffer released. Exiting with code %d\n",
241 #ifdef CONFIG_COLOR_TEXT
243 * Validify color for text ui
246 check_color_text_ui(char *color)
249 while(ansi_color_table[i].name) {
250 if (!strcmp(color, ansi_color_table[i].name))
256 #endif /* CONFIG_COLOR_TEXT */
259 void print_message_file(char *filename)
263 char *defdev = boot.dev;
264 int defpart = boot.part;
269 struct boot_file_t file;
270 struct boot_fspec_t msgfile;
272 defdev = cfg_get_strg(0, "device");
275 p = cfg_get_strg(0, "partition");
277 n = simple_strtol(p, &endp, 10);
278 if (endp != p && *endp == 0)
282 strncpy(msgpath, filename, sizeof(msgpath));
283 if (!parse_device_path(msgpath, defdev, defpart, "/etc/yaboot.msg", &msgfile)) {
284 prom_printf("%s: Unable to parse\n", msgpath);
288 result = open_file(&msgfile, &file);
289 if (result != FILE_ERR_OK) {
290 prom_printf("%s:%d,", msgfile.dev, msgfile.part);
291 prom_perror(result, msgfile.file);
300 memset(msg, 0, sizeof(*msg));
302 if (file.fs->read(&file, 2000, msg) <= 0)
305 prom_printf("%s", msg);
309 file.fs->close(&file);
318 /* Currently, the config file must be at the root of the filesystem.
319 * todo: recognize the full path to myself and use it to load the
320 * config file. Handle the "\\" (blessed system folder)
323 load_config_file(char *device, char* path, int partition)
325 char *conf_file = NULL, *p;
326 struct boot_file_t file;
327 int sz, opened = 0, result = 0;
329 struct boot_fspec_t fspec;
331 /* Allocate a buffer for the config file */
332 conf_file = malloc(CONFIG_FILE_MAX);
334 prom_printf("Can't alloc config file buffer\n");
338 /* Build the path to the file */
340 strcpy(conf_path, path);
341 else if ( _machine == _MACH_chrp )
342 strcpy(conf_path, "/etc/");
345 strcat(conf_path, CONFIG_FILE_NAME);
349 fspec.file = conf_path;
350 fspec.part = partition;
351 result = open_file(&fspec, &file);
352 if (result != FILE_ERR_OK) {
353 prom_printf("%s:%d,", fspec.dev, fspec.part);
354 prom_perror(result, fspec.file);
355 prom_printf("Can't open config file\n");
361 sz = file.fs->read(&file, CONFIG_FILE_MAX, conf_file);
363 prom_printf("Error, can't read config file\n");
366 prom_printf("Config file read, %d bytes\n", sz);
370 file.fs->close(&file);
373 /* Call the parsing code in cfg.c */
374 if (cfg_parse(conf_path, conf_file, sz) < 0) {
375 prom_printf ("Syntax error or read error config\n");
379 DEBUG_F("Config file successfully parsed, %d bytes\n", sz);
381 /* Now, we do the initialisations stored in the config file */
382 p = cfg_get_strg(0, "init-code");
386 password = cfg_get_strg(0, "password");
388 #ifdef CONFIG_COLOR_TEXT
389 p = cfg_get_strg(0, "fgcolor");
391 DEBUG_F("fgcolor=%s\n", p);
392 fgcolor = check_color_text_ui(p);
394 prom_printf("Invalid fgcolor: \"%s\".\n", p);
397 p = cfg_get_strg(0, "bgcolor");
399 DEBUG_F("bgcolor=%s\n", p);
400 bgcolor = check_color_text_ui(p);
402 prom_printf("Invalid bgcolor: \"%s\".\n", p);
406 sprintf(temp, "%x to background-color", bgcolor);
407 prom_interpret(temp);
414 sprintf(temp, "%x to foreground-color", fgcolor);
415 prom_interpret(temp);
417 #endif /* CONFIG_COLOR_TEXT */
419 p = cfg_get_strg(0, "init-message");
421 prom_printf("%s\n", p);
423 p = cfg_get_strg(0, "message");
425 print_message_file(p);
432 file.fs->close(&file);
434 if (result != 1 && conf_file)
440 void maintabfunc (void)
444 prom_printf("boot: %s", cbuff);
449 word_split(char **linep, char **paramsp)
464 while (*p != 0 && *p != ' ')
473 make_params(char *label, char *params)
476 static char buffer[2048];
481 p = cfg_get_strg(label, "literal");
493 p = cfg_get_strg(label, "root");
500 if (cfg_get_flag(label, "read-only")) {
504 if (cfg_get_flag(label, "read-write")) {
508 p = cfg_get_strg(label, "ramdisk");
510 strcpy (q, "ramdisk=");
515 p = cfg_get_strg(label, "initrd-size");
517 strcpy (q, "ramdisk_size=");
522 if (cfg_get_flag(label, "novideo")) {
523 strcpy (q, "video=ofonly");
527 p = cfg_get_strg (label, "append");
534 pause_after = cfg_get_flag (label, "pause-after");
535 p = cfg_get_strg(label, "pause-message");
544 void check_password(char *str)
548 for (i = 0; i < 3; i++) {
549 prom_printf ("\n%sassword: ", str);
551 cmdedit ((void (*)(void)) 0, 1);
553 #ifdef USE_MD5_PASSWORDS
554 if (!strncmp (password, "$1$", 3)) {
555 if (!check_md5_password(passwdbuff, password))
558 else if (!strcmp (password, passwdbuff))
561 if (!strcmp (password, passwdbuff))
563 #endif /* USE_MD5_PASSWORDS */
565 prom_printf ("Password incorrect. Please try again...");
567 prom_printf ("Seems like you don't know the access password. Go away!\n");
569 prom_interpret("reset-all");
572 int get_params(struct boot_param_t* params)
578 char *imagename = 0, *label;
583 static int first = 1;
584 static char bootargs[1024];
585 static char imagepath[1024];
586 static char initrdpath[1024];
587 static char sysmappath[1024];
590 memset(params, 0, sizeof(*params));
592 params->kernel.part = -1;
593 params->rd.part = -1;
594 params->sysmap.part = -1;
601 prom_get_chosen("bootargs", bootargs, sizeof(bootargs));
602 imagename = bootargs;
603 word_split(&imagename, ¶ms->args);
604 timeout = DEFAULT_TIMEOUT;
606 prom_printf("Default supplied on the command line: %s ", imagename);
608 prom_printf("%s", params->args);
611 if (useconf && (q = cfg_get_strg(0, "timeout")) != 0 && *q != 0)
612 timeout = simple_strtol(q, NULL, 0);
615 prom_printf("boot: ");
620 end = beg + 100 * timeout;
622 c = prom_nbgetchar();
623 } while (c == -1 && prom_getms() <= end);
627 else if (c != '\n' && c != '\t' && c != '\r' && c != '\b' ) {
633 if (c != -1 && c != '\n' && c != '\r') {
636 } else if (c >= ' ') {
639 if ((cfg_get_flag (cbuff, "single-key")) && useconf) {
642 prom_printf("%s\n", cbuff);
647 if (c == '\n' || c == '\r') {
649 imagename = cfg_get_default();
651 prom_printf("%s", imagename);
653 prom_printf(" %s", params->args);
655 } else if (!singlekey) {
656 cmdedit(maintabfunc, 0);
658 strcpy(given_bootargs, cbuff);
659 given_bootargs_by_user = 1;
661 word_split(&imagename, ¶ms->args);
664 /* chrp gets this wrong, force it -- Cort */
665 if ( useconf && (!imagename || imagename[0] == 0 ))
666 imagename = cfg_get_default();
669 defdevice = boot.dev;
672 defdevice = cfg_get_strg(0, "device");
673 p = cfg_get_strg(0, "partition");
675 n = simple_strtol(p, &endp, 10);
676 if (endp != p && *endp == 0)
679 p = cfg_get_strg(0, "pause-message");
682 if (cfg_get_flag(0, "restricted"))
684 p = cfg_get_strg(imagename, "image");
688 defdevice = cfg_get_strg(label, "device");
689 if(!defdevice) defdevice=boot.dev;
690 p = cfg_get_strg(label, "partition");
692 n = simple_strtol(p, &endp, 10);
693 if (endp != p && *endp == 0)
696 if (cfg_get_flag(label, "restricted"))
699 if (params->args && password && restricted)
700 check_password ("To specify image arguments you must enter the p");
701 else if (password && !restricted)
702 check_password ("P");
704 params->args = make_params(label, params->args);
708 if (!strcmp (imagename, "help")) {
710 "\nPress the tab key for a list of defined images.\n"
711 "The label marked with a \"*\" is is the default image, "
712 "press <return> to boot it.\n\n"
713 "To boot any other label simply type its name and press <return>.\n\n"
714 "To boot a kernel image which is not defined in the yaboot configuration \n"
715 "file, enter the kernel image name as [[device:][partno],]/path, where \n"
716 "\"device:\" is the OpenFirmware device path to the disk the image \n"
717 "resides on, and \"partno\" is the partition number the image resides on.\n"
718 "Note that the comma (,) is only required if you specify an OpenFirmware\n"
719 "device, if you only specify a filename you should not start it with a \",\"\n\n"
720 "If you omit \"device:\" and \"partno\" yaboot will use the values of \n"
721 "\"device=\" and \"partition=\" in yaboot.conf, right now those are set to: \n"
723 "partition=%d\n\n", defdevice, defpart);
727 if (!strcmp (imagename, "halt")) {
729 check_password ("P");
733 if (!strcmp (imagename, "bye")) {
735 check_password ("P");
741 if (imagename[0] == '$') {
742 /* forth command string */
744 check_password ("P");
745 prom_interpret(imagename+1);
749 strncpy(imagepath, imagename, 1024);
751 if (!label && password)
752 check_password ("To boot a custom image you must enter the p");
754 if (!parse_device_path(imagepath, defdevice, defpart,
755 "/vmlinux", ¶ms->kernel)) {
756 prom_printf("%s: Unable to parse\n", imagepath);
759 DEBUG_F("after parse_device_path: dev=%s part=%d file=%s\n", params->kernel.dev,
760 params->kernel.part, params->kernel.file);
763 p = cfg_get_strg(label, "initrd");
765 DEBUG_F("Parsing initrd path <%s>\n", p);
766 strncpy(initrdpath, p, 1024);
767 if (!parse_device_path(initrdpath, defdevice, defpart,
768 "/root.bin", ¶ms->rd)) {
769 prom_printf("%s: Unable to parse\n", imagepath);
773 p = cfg_get_strg(label, "sysmap");
775 DEBUG_F("Parsing sysmap path <%s>\n", p);
776 strncpy(sysmappath, p, 1024);
777 if (!parse_device_path(sysmappath, defdevice, defpart,
778 "/boot/System.map", ¶ms->sysmap)) {
779 prom_printf("%s: Unable to parse\n", imagepath);
787 /* This is derived from quik core. To be changed to first parse the headers
788 * doing lazy-loading, and then claim the memory before loading the kernel
790 * We also need to add initrd support to this whole mecanism
795 #define MAX_HEADERS 32
797 struct boot_file_t file;
799 static struct boot_param_t params;
801 unsigned long initrd_size;
803 unsigned long sysmap_size;
804 kernel_entry_t kernel_entry;
805 struct bi_record* birec;
808 void *initrd_more,*initrd_want;
809 unsigned long initrd_read;
811 loadinfo.load_loc = 0;
819 if (get_params(¶ms))
821 if (!params.kernel.file)
824 prom_printf("Please wait, loading kernel...\n");
826 memset(&file, 0, sizeof(file));
828 if (strlen(boot.file) && !strcmp(boot.file,"\\\\") && params.kernel.file[0] != '/'
829 && params.kernel.file[0] != '\\') {
830 loc=(char*)malloc(strlen(params.kernel.file)+3);
832 prom_printf ("malloc error\n");
835 strcpy(loc,boot.file);
836 strcat(loc,params.kernel.file);
837 free(params.kernel.file);
838 params.kernel.file=loc;
840 result = open_file(¶ms.kernel, &file);
841 if (result != FILE_ERR_OK) {
842 prom_printf("%s:%d,", params.kernel.dev, params.kernel.part);
843 prom_perror(result, params.kernel.file);
847 /* Read the Elf e_ident, e_type and e_machine fields to
848 * determine Elf file type
850 if (file.fs->read(&file, sizeof(Elf_Ident), &loadinfo.elf) < sizeof(Elf_Ident)) {
851 prom_printf("\nCan't read Elf e_ident/e_type/e_machine info\n");
852 file.fs->close(&file);
853 memset(&file, 0, sizeof(file));
857 if (is_elf32(&loadinfo)) {
858 if (!load_elf32(&file, &loadinfo)) {
859 file.fs->close(&file);
860 memset(&file, 0, sizeof(file));
863 prom_printf(" Elf32 kernel loaded...\n");
864 } else if (is_elf64(&loadinfo)) {
865 if (!load_elf64(&file, &loadinfo)) {
866 file.fs->close(&file);
867 memset(&file, 0, sizeof(file));
870 prom_printf(" Elf64 kernel loaded...\n");
872 prom_printf ("%s: Not a valid ELF image\n", params.kernel.file);
873 file.fs->close(&file);
874 memset(&file, 0, sizeof(file));
877 file.fs->close(&file);
878 memset(&file, 0, sizeof(file));
880 /* If sysmap, load it.
882 if (params.sysmap.file) {
883 prom_printf("Loading System.map ...\n");
884 if(strlen(boot.file) && !strcmp(boot.file,"\\\\") && params.sysmap.file[0] != '/'
885 && params.sysmap.file[0] != '\\') {
887 loc=(char*)malloc(strlen(params.sysmap.file)+3);
889 prom_printf ("malloc error\n");
892 strcpy(loc,boot.file);
893 strcat(loc,params.sysmap.file);
894 free(params.sysmap.file);
895 params.sysmap.file=loc;
898 result = open_file(¶ms.sysmap, &file);
899 if (result != FILE_ERR_OK) {
900 prom_printf("%s:%d,", params.sysmap.dev, params.sysmap.part);
901 prom_perror(result, params.sysmap.file);
904 sysmap_base = prom_claim(loadinfo.base+loadinfo.memsize, 0x100000, 0);
905 if (sysmap_base == (void *)-1) {
906 prom_printf("Claim failed for sysmap memory\n");
909 sysmap_size = file.fs->read(&file, 0xfffff, sysmap_base);
910 if (sysmap_size == 0)
913 ((char *)sysmap_base)[sysmap_size++] = 0;
915 file.fs->close(&file);
916 memset(&file, 0, sizeof(file));
919 prom_printf("System.map loaded at %p, size: %lu Kbytes\n",
920 sysmap_base, sysmap_size >> 10);
921 loadinfo.memsize += _ALIGN(0x100000, 0x1000);
923 prom_printf("System.map load failed !\n");
928 /* If ramdisk, load it. For now, we can't tell the size it will be
929 * so we claim an arbitrary amount of 4Mb
931 if (params.rd.file) {
932 if(strlen(boot.file) && !strcmp(boot.file,"\\\\") && params.rd.file[0] != '/'
933 && params.kernel.file[0] != '\\')
936 loc=(char*)malloc(strlen(params.rd.file)+3);
938 prom_printf ("Malloc error\n");
941 strcpy(loc,boot.file);
942 strcat(loc,params.rd.file);
943 free(params.rd.file);
946 prom_printf("Loading ramdisk...\n");
947 result = open_file(¶ms.rd, &file);
948 if (result != FILE_ERR_OK) {
949 prom_printf("%s:%d,", params.rd.dev, params.rd.part);
950 prom_perror(result, params.rd.file);
953 #define INITRD_CHUNKSIZE 0x400000
954 initrd_base = prom_claim(loadinfo.base+loadinfo.memsize, INITRD_CHUNKSIZE, 0);
955 if (initrd_base == (void *)-1) {
956 prom_printf("Claim failed for initrd memory\n");
959 initrd_size = file.fs->read(&file, INITRD_CHUNKSIZE, initrd_base);
960 if (initrd_size == 0)
962 initrd_read = initrd_size;
963 initrd_more = initrd_base;
964 while (initrd_read == INITRD_CHUNKSIZE ) { /* need to read more? */
965 initrd_want = (void *)((unsigned long)initrd_more+INITRD_CHUNKSIZE);
966 initrd_more = prom_claim(initrd_want, INITRD_CHUNKSIZE, 0);
967 if (initrd_more != initrd_want) {
968 prom_printf("Claim failed for initrd memory at %p rc=%p\n",initrd_want,initrd_more);
971 initrd_read = file.fs->read(&file, INITRD_CHUNKSIZE, initrd_more);
972 DEBUG_F(" block at %p rc=%lu\n",initrd_more,initrd_read);
973 initrd_size += initrd_read;
976 file.fs->close(&file);
977 memset(&file, 0, sizeof(file));
980 prom_printf("ramdisk loaded at %p, size: %lu Kbytes\n",
981 initrd_base, initrd_size >> 10);
983 prom_printf("ramdisk load failed !\n");
988 DEBUG_F("setting kernel args to: %s\n", params.args);
989 prom_setargs(params.args);
990 DEBUG_F("flushing icache...");
991 flush_icache_range ((long)loadinfo.base, (long)loadinfo.base+loadinfo.memsize);
995 * Fill mew boot infos
997 * The birec is low on memory, probably inside the malloc pool, so
998 * we don't write it earlier. At this point, we should not use anything
999 * coming from the malloc pool
1001 birec = (struct bi_record *)_ALIGN(loadinfo.filesize+(1<<20)-1,(1<<20));
1003 /* We make sure it's mapped. We map only 64k for now, it's plenty enough
1004 * we don't claim since this precise memory range may already be claimed
1005 * by the malloc pool
1007 prom_map (birec, birec, 0x10000);
1008 DEBUG_F("birec at %p\n", birec);
1011 birec->tag = BI_FIRST;
1012 birec->size = sizeof(struct bi_record);
1013 birec = (struct bi_record *)((unsigned long)birec + birec->size);
1015 birec->tag = BI_BOOTLOADER_ID;
1016 sprintf( (char *)birec->data, "yaboot");
1017 birec->size = sizeof(struct bi_record) + strlen("yaboot") + 1;
1018 birec = (struct bi_record *)((unsigned long)birec + birec->size);
1020 birec->tag = BI_MACHTYPE;
1021 birec->data[0] = _machine;
1022 birec->size = sizeof(struct bi_record) + sizeof(unsigned long);
1023 birec = (struct bi_record *)((unsigned long)birec + birec->size);
1026 birec->tag = BI_SYSMAP;
1027 birec->data[0] = (unsigned long)sysmap_base;
1028 birec->data[1] = sysmap_size;
1029 birec->size = sizeof(struct bi_record) + sizeof(unsigned long)*2;
1030 birec = (struct bi_record *)((unsigned long)birec + birec->size);
1032 birec->tag = BI_LAST;
1033 birec->size = sizeof(struct bi_record);
1034 birec = (struct bi_record *)((unsigned long)birec + birec->size);
1036 /* compute the kernel's entry point. */
1037 kernel_entry = loadinfo.base + loadinfo.entry - loadinfo.load_loc;
1039 DEBUG_F("Kernel entry point = %p\n", kernel_entry);
1040 DEBUG_F("kernel: arg1 = %p,\n"
1041 " arg2 = 0x%08lx,\n"
1045 initrd_base + loadinfo.load_loc, initrd_size, prom, 0, 0);
1047 DEBUG_F("Entering kernel...\n");
1049 /* call the kernel with our stack. */
1050 kernel_entry(initrd_base + loadinfo.load_loc, initrd_size, prom, 0, 0);
1058 load_elf32(struct boot_file_t *file, loadinfo_t *loadinfo)
1061 Elf32_Ehdr *e = &(loadinfo->elf.elf32hdr);
1063 int size = sizeof(Elf32_Ehdr) - sizeof(Elf_Ident);
1064 unsigned long addr, loadaddr;
1066 /* Read the rest of the Elf header... */
1067 if ((*(file->fs->read))(file, size, &e->e_version) < size) {
1068 prom_printf("\nCan't read Elf32 image header\n");
1072 DEBUG_F("Elf32 header:\n");
1073 DEBUG_F(" e.e_type = %d\n", (int)e->e_type);
1074 DEBUG_F(" e.e_machine = %d\n", (int)e->e_machine);
1075 DEBUG_F(" e.e_version = %d\n", (int)e->e_version);
1076 DEBUG_F(" e.e_entry = 0x%08x\n", (int)e->e_entry);
1077 DEBUG_F(" e.e_phoff = 0x%08x\n", (int)e->e_phoff);
1078 DEBUG_F(" e.e_shoff = 0x%08x\n", (int)e->e_shoff);
1079 DEBUG_F(" e.e_flags = %d\n", (int)e->e_flags);
1080 DEBUG_F(" e.e_ehsize = 0x%08x\n", (int)e->e_ehsize);
1081 DEBUG_F(" e.e_phentsize = 0x%08x\n", (int)e->e_phentsize);
1082 DEBUG_F(" e.e_phnum = %d\n", (int)e->e_phnum);
1084 loadinfo->entry = e->e_entry;
1086 if (e->e_phnum > MAX_HEADERS) {
1087 prom_printf ("Can only load kernels with one program header\n");
1091 ph = (Elf32_Phdr *)malloc(sizeof(Elf32_Phdr) * e->e_phnum);
1093 prom_printf ("Malloc error\n");
1097 /* Now, we read the section header */
1098 if ((*(file->fs->seek))(file, e->e_phoff) != FILE_ERR_OK) {
1099 prom_printf ("seek error\n");
1102 if ((*(file->fs->read))(file, sizeof(Elf32_Phdr) * e->e_phnum, ph) !=
1103 sizeof(Elf32_Phdr) * e->e_phnum) {
1104 prom_printf ("read error\n");
1108 /* Scan through the program header
1109 * HACK: We must return the _memory size of the kernel image, not the
1110 * file size (because we have to leave room before other boot
1111 * infos. This code works as a side effect of the fact that
1112 * we have one section and vaddr == p_paddr
1114 loadinfo->memsize = loadinfo->filesize = loadinfo->offset = 0;
1116 for (i = 0; i < e->e_phnum; ++i, ++p) {
1117 if (p->p_type != PT_LOAD || p->p_offset == 0)
1119 if (loadinfo->memsize == 0) {
1120 loadinfo->offset = p->p_offset;
1121 loadinfo->memsize = p->p_memsz;
1122 loadinfo->filesize = p->p_filesz;
1123 loadinfo->load_loc = p->p_vaddr;
1125 loadinfo->memsize = p->p_offset + p->p_memsz - loadinfo->offset; /* XXX Bogus */
1126 loadinfo->filesize = p->p_offset + p->p_filesz - loadinfo->offset;
1130 if (loadinfo->memsize == 0) {
1131 prom_printf("Can't find a loadable segment !\n");
1135 /* leave some room (1Mb) for boot infos */
1136 loadinfo->memsize = _ALIGN(loadinfo->memsize,(1<<20)) + 0x100000;
1137 /* Claim OF memory */
1138 DEBUG_F("Before prom_claim, mem_sz: 0x%08lx\n", loadinfo->memsize);
1140 /* On some systems, loadaddr may already be claimed, so try some
1141 * other nearby addresses before giving up.
1143 loadaddr = (e->e_entry == KERNEL_LINK_ADDR_PPC32 ||
1144 e->e_entry == 0) ? KERNELADDR : e->e_entry;
1145 for(addr=loadaddr; addr <= loadaddr * 8 ;addr+=0x100000) {
1146 loadinfo->base = prom_claim((void *)addr, loadinfo->memsize, 0);
1147 if (loadinfo->base != (void *)-1) break;
1149 if (loadinfo->base == (void *)-1) {
1150 prom_printf("Claim error, can't allocate kernel memory\n");
1154 DEBUG_F("After ELF parsing, load base: %p, mem_sz: 0x%08lx\n",
1155 loadinfo->base, loadinfo->memsize);
1156 DEBUG_F(" wanted load base: 0x%08lx, mem_sz: 0x%08lx\n",
1157 loadaddr, loadinfo->memsize);
1159 /* Load the program segments... */
1161 for (i = 0; i < e->e_phnum; ++i, ++p) {
1162 unsigned long offset;
1163 if (p->p_type != PT_LOAD || p->p_offset == 0)
1166 /* Now, we skip to the image itself */
1167 if ((*(file->fs->seek))(file, p->p_offset) != FILE_ERR_OK) {
1168 prom_printf ("Seek error\n");
1169 prom_release(loadinfo->base, loadinfo->memsize);
1172 offset = p->p_vaddr - loadinfo->load_loc;
1173 if ((*(file->fs->read))(file, p->p_filesz, loadinfo->base+offset) != p->p_filesz) {
1174 prom_printf ("Read failed\n");
1175 prom_release(loadinfo->base, loadinfo->memsize);
1182 /* Return success at loading the Elf32 kernel */
1187 load_elf64(struct boot_file_t *file, loadinfo_t *loadinfo)
1190 Elf64_Ehdr *e = &(loadinfo->elf.elf64hdr);
1192 int size = sizeof(Elf64_Ehdr) - sizeof(Elf_Ident);
1193 unsigned long addr, loadaddr;
1195 /* Read the rest of the Elf header... */
1196 if ((*(file->fs->read))(file, size, &e->e_version) < size) {
1197 prom_printf("\nCan't read Elf64 image header\n");
1201 DEBUG_F("Elf64 header:\n");
1202 DEBUG_F(" e.e_type = %d\n", (int)e->e_type);
1203 DEBUG_F(" e.e_machine = %d\n", (int)e->e_machine);
1204 DEBUG_F(" e.e_version = %d\n", (int)e->e_version);
1205 DEBUG_F(" e.e_entry = 0x%016lx\n", (long)e->e_entry);
1206 DEBUG_F(" e.e_phoff = 0x%016lx\n", (long)e->e_phoff);
1207 DEBUG_F(" e.e_shoff = 0x%016lx\n", (long)e->e_shoff);
1208 DEBUG_F(" e.e_flags = %d\n", (int)e->e_flags);
1209 DEBUG_F(" e.e_ehsize = 0x%08x\n", (int)e->e_ehsize);
1210 DEBUG_F(" e.e_phentsize = 0x%08x\n", (int)e->e_phentsize);
1211 DEBUG_F(" e.e_phnum = %d\n", (int)e->e_phnum);
1213 loadinfo->entry = e->e_entry;
1215 if (e->e_phnum > MAX_HEADERS) {
1216 prom_printf ("Can only load kernels with one program header\n");
1220 ph = (Elf64_Phdr *)malloc(sizeof(Elf64_Phdr) * e->e_phnum);
1222 prom_printf ("Malloc error\n");
1226 /* Now, we read the section header */
1227 if ((*(file->fs->seek))(file, e->e_phoff) != FILE_ERR_OK) {
1228 prom_printf ("Seek error\n");
1231 if ((*(file->fs->read))(file, sizeof(Elf64_Phdr) * e->e_phnum, ph) !=
1232 sizeof(Elf64_Phdr) * e->e_phnum) {
1233 prom_printf ("Read error\n");
1237 /* Scan through the program header
1238 * HACK: We must return the _memory size of the kernel image, not the
1239 * file size (because we have to leave room before other boot
1240 * infos. This code works as a side effect of the fact that
1241 * we have one section and vaddr == p_paddr
1243 loadinfo->memsize = loadinfo->filesize = loadinfo->offset = 0;
1245 for (i = 0; i < e->e_phnum; ++i, ++p) {
1246 if (p->p_type != PT_LOAD || p->p_offset == 0)
1248 if (loadinfo->memsize == 0) {
1249 loadinfo->offset = p->p_offset;
1250 loadinfo->memsize = p->p_memsz;
1251 loadinfo->filesize = p->p_filesz;
1252 loadinfo->load_loc = p->p_vaddr;
1254 loadinfo->memsize = p->p_offset + p->p_memsz - loadinfo->offset; /* XXX Bogus */
1255 loadinfo->filesize = p->p_offset + p->p_filesz - loadinfo->offset;
1259 if (loadinfo->memsize == 0) {
1260 prom_printf("Can't find a loadable segment !\n");
1264 /* leave some room (1Mb) for boot infos */
1265 loadinfo->memsize = _ALIGN(loadinfo->memsize,(1<<20)) + 0x100000;
1266 /* Claim OF memory */
1267 DEBUG_F("Before prom_claim, mem_sz: 0x%08lx\n", loadinfo->memsize);
1269 /* On some systems, loadaddr may already be claimed, so try some
1270 * other nearby addresses before giving up.
1272 loadaddr = (e->e_entry == KERNEL_LINK_ADDR_PPC64) ? KERNELADDR : e->e_entry;
1273 for(addr=loadaddr; addr <= loadaddr * 8 ;addr+=0x100000) {
1274 loadinfo->base = prom_claim((void *)addr, loadinfo->memsize, 0);
1275 if (loadinfo->base != (void *)-1) break;
1277 if (loadinfo->base == (void *)-1) {
1278 prom_printf("Claim error, can't allocate kernel memory\n");
1282 DEBUG_F("After ELF parsing, load base: %p, mem_sz: 0x%08lx\n",
1283 loadinfo->base, loadinfo->memsize);
1284 DEBUG_F(" wanted load base: 0x%08lx, mem_sz: 0x%08lx\n",
1285 loadaddr, loadinfo->memsize);
1287 /* Load the program segments... */
1289 for (i = 0; i < e->e_phnum; ++i, ++p) {
1290 unsigned long offset;
1291 if (p->p_type != PT_LOAD || p->p_offset == 0)
1294 /* Now, we skip to the image itself */
1295 if ((*(file->fs->seek))(file, p->p_offset) != FILE_ERR_OK) {
1296 prom_printf ("Seek error\n");
1297 prom_release(loadinfo->base, loadinfo->memsize);
1300 offset = p->p_vaddr - loadinfo->load_loc;
1301 if ((*(file->fs->read))(file, p->p_filesz, loadinfo->base+offset) != p->p_filesz) {
1302 prom_printf ("Read failed\n");
1303 prom_release(loadinfo->base, loadinfo->memsize);
1310 /* Return success at loading the Elf64 kernel */
1315 is_elf32(loadinfo_t *loadinfo)
1317 Elf32_Ehdr *e = &(loadinfo->elf.elf32hdr);
1319 return (e->e_ident[EI_MAG0] == ELFMAG0 &&
1320 e->e_ident[EI_MAG1] == ELFMAG1 &&
1321 e->e_ident[EI_MAG2] == ELFMAG2 &&
1322 e->e_ident[EI_MAG3] == ELFMAG3 &&
1323 e->e_ident[EI_CLASS] == ELFCLASS32 &&
1324 e->e_ident[EI_DATA] == ELFDATA2MSB &&
1325 e->e_type == ET_EXEC &&
1326 e->e_machine == EM_PPC);
1330 is_elf64(loadinfo_t *loadinfo)
1332 Elf64_Ehdr *e = &(loadinfo->elf.elf64hdr);
1334 return (e->e_ident[EI_MAG0] == ELFMAG0 &&
1335 e->e_ident[EI_MAG1] == ELFMAG1 &&
1336 e->e_ident[EI_MAG2] == ELFMAG2 &&
1337 e->e_ident[EI_MAG3] == ELFMAG3 &&
1338 e->e_ident[EI_CLASS] == ELFCLASS64 &&
1339 e->e_ident[EI_DATA] == ELFDATA2MSB &&
1340 e->e_type == ET_EXEC &&
1341 e->e_machine == EM_PPC64);
1347 #ifdef CONFIG_SET_COLORMAP
1348 static unsigned char default_colors[] = {
1367 prom_handle scrn = PROM_INVALID_HANDLE;
1369 /* Try Apple's mac-boot screen ihandle */
1370 result = (int)call_prom_return("interpret", 1, 2,
1371 "\" _screen-ihandle\" $find if execute else 0 then", &scrn);
1372 DEBUG_F("Trying to get screen ihandle, result: %d, scrn: %p\n", result, scrn);
1374 if (scrn == 0 || scrn == PROM_INVALID_HANDLE) {
1376 /* Hrm... check to see if stdout is a display */
1377 scrn = call_prom ("instance-to-package", 1, 1, prom_stdout);
1378 DEBUG_F("instance-to-package of stdout is: %p\n", scrn);
1379 if (prom_getprop(scrn, "device_type", type, 32) > 0 && !strncmp(type, "display", 7)) {
1380 DEBUG_F("got it ! stdout is a screen\n");
1383 /* Else, we try to open the package */
1384 scrn = (prom_handle)call_prom( "open", 1, 1, "screen" );
1385 DEBUG_F("Open screen result: %p\n", scrn);
1389 if (scrn == PROM_INVALID_HANDLE) {
1390 prom_printf("No screen device found !/n");
1394 prom_set_color(scrn, i, default_colors[i*3],
1395 default_colors[i*3+1], default_colors[i*3+2]);
1397 prom_printf("\x1b[1;37m\x1b[2;40m");
1399 for (i=0;i<16; i++) {
1400 prom_printf("\x1b[%d;%dm\x1b[1;47m%s \x1b[2;40m %s\n",
1401 ansi_color_table[i].index,
1402 ansi_color_table[i].value,
1403 ansi_color_table[i].name,
1404 ansi_color_table[i].name);
1405 prom_printf("\x1b[%d;%dm\x1b[1;37m%s \x1b[2;30m %s\n",
1406 ansi_color_table[i].index,
1407 ansi_color_table[i].value+10,
1408 ansi_color_table[i].name,
1409 ansi_color_table[i].name);
1411 prom_printf("\x1b[1;37m\x1b[2;40m");
1412 #endif /* COLOR_TEST */
1418 #endif /* CONFIG_SET_COLORMAP */
1426 if (_machine == _MACH_Pmac)
1429 prom_get_chosen("bootpath", bootdevice, sizeof(bootdevice));
1430 DEBUG_F("/chosen/bootpath = %s\n", bootdevice);
1431 if (bootdevice[0] == 0)
1432 prom_get_options("boot-device", bootdevice, sizeof(bootdevice));
1433 if (bootdevice[0] == 0) {
1434 prom_printf("Couldn't determine boot device\n");
1438 if (!parse_device_path(bootdevice, (_machine == _MACH_Pmac) ? "hd" : "disc",
1440 prom_printf("%s: Unable to parse\n", bootdevice);
1443 DEBUG_F("After parse_device_path: dev=%s, part=%d, file=%s\n",
1444 boot.dev, boot.part, boot.file);
1446 if (strlen(boot.file)) {
1447 if (!strncmp(boot.file, "\\\\", 2))
1451 p = last = boot.file;
1461 if (strlen(boot.file))
1462 strcat(boot.file, "\\");
1465 DEBUG_F("After path fixup: dev=%s, part=%d, file=%s\n",
1466 boot.dev, boot.part, boot.file);
1468 useconf = load_config_file(boot.dev, boot.file, boot.part);
1470 prom_printf("Welcome to yaboot version " VERSION "\n");
1471 prom_printf("Enter \"help\" to get some basic usage information\n");
1473 /* I am fed up with lusers using the wrong partition type and
1474 mailing me *when* it breaks */
1476 if (_machine == _MACH_Pmac) {
1477 char *entry = cfg_get_strg(0, "ptypewarning");
1480 warn = strcmp(entry,
1481 "I_know_the_partition_type_is_wrong_and_will_NOT_send_mail_when_booting_breaks");
1483 ptype = get_part_type(boot.dev, boot.part);
1484 if ((ptype != NULL) && (strcmp(ptype, "Apple_Bootstrap")))
1485 prom_printf("\nWARNING: Bootstrap partition type is wrong: \"%s\"\n"
1486 " type should be: \"Apple_Bootstrap\"\n\n", ptype);
1492 prom_printf("Bye.\n");
1498 * c-file-style: "k&r"