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
46 #include "linux/elf.h"
49 #define CONFIG_FILE_NAME "yaboot.conf"
50 #define CONFIG_FILE_MAX 0x8000 /* 32k */
52 #ifdef CONFIG_SPLASH_SCREEN
54 #endif /* CONFIG_SPLASH_SCREEN */
56 #ifdef USE_MD5_PASSWORDS
58 #endif /* USE_MD5_PASSWORDS */
60 /* align addr on a size boundry - adjust address up if needed -- Cort */
61 #define _ALIGN(addr,size) (((addr)+size-1)&(~(size-1)))
63 /* Addresses where the PPC32 and PPC64 vmlinux kernels are linked at.
64 * These are used to determine whether we are booting a vmlinux, in
65 * which case, it will be loaded at KERNELADDR. Otherwise (eg zImage),
66 * we load the binary where it was linked at (ie, e_entry field in
69 #define KERNEL_LINK_ADDR_PPC32 0xC0000000UL
70 #define KERNEL_LINK_ADDR_PPC64 0xC000000000000000ULL
78 unsigned long memsize;
79 unsigned long filesize;
81 unsigned long load_loc;
85 typedef void (*kernel_entry_t)( void *,
91 /* Imported functions */
92 extern unsigned long reloc_offset(void);
93 extern long flush_icache_range(unsigned long start, unsigned long stop);
95 /* Exported functions */
96 int yaboot_start(unsigned long r3, unsigned long r4, unsigned long r5);
99 static int yaboot_main(void);
100 static int is_elf32(loadinfo_t *loadinfo);
101 static int is_elf64(loadinfo_t *loadinfo);
102 static int load_elf32(struct boot_file_t *file, loadinfo_t *loadinfo);
103 static int load_elf64(struct boot_file_t *file, loadinfo_t *loadinfo);
104 static void setup_display(void);
106 /* Locals & globals */
109 char bootdevice[1024];
110 char *bootpath = NULL;
111 char *password = NULL;
112 int bootpartition = -1;
113 int _machine = _MACH_Pmac;
115 #ifdef CONFIG_COLOR_TEXT
117 /* Color values for text ui */
118 static struct ansi_color_t {
122 } ansi_color_table[] = {
130 { "light-gray", 0, 37 },
131 { "dark-gray", 1, 30 },
132 { "light-blue", 1, 31 },
133 { "light-green", 1, 32 },
134 { "light-cyan", 1, 33 },
135 { "light-red", 1, 34 },
136 { "light-purple", 1, 35 },
142 /* Default colors for text ui */
145 #endif /* CONFIG_COLOR_TEXT */
149 static int test_data = 0;
151 static int pause_after;
152 static char *pause_message = "Type go<return> to continue.\n";
153 static char given_bootargs[1024];
154 static int given_bootargs_by_user = 0;
156 extern unsigned char linux_logo_red[];
157 extern unsigned char linux_logo_green[];
158 extern unsigned char linux_logo_blue[];
160 #define DEFAULT_TIMEOUT -1
162 /* Entry, currently called directly by crt0 (bss not inited) */
164 extern char* __bss_start;
167 static struct first_info *quik_fip = NULL;
170 yaboot_start (unsigned long r3, unsigned long r4, unsigned long r5)
173 void* malloc_base = NULL;
176 /* OF seems to do it, but I'm not very confident */
177 memset(&__bss_start, 0, &_end - &__bss_start);
179 /* Check for quik first stage bootloader (but I don't think we are
180 * compatible with it anyway, I'll look into backporting to older OF
183 if (r5 == 0xdeadbeef) {
185 quik_fip = (struct first_info *)r4;
188 /* Initialize OF interface */
189 prom_init ((prom_entry) r5);
191 /* Allocate some memory for malloc'ator */
192 malloc_base = prom_claim((void *)MALLOCADDR, MALLOCSIZE, 0);
193 if (malloc_base == (void *)-1) {
194 prom_printf("Can't claim malloc buffer (%d bytes at 0x%08lx)\n",
195 MALLOCSIZE, MALLOCADDR);
198 malloc_init(malloc_base, MALLOCSIZE);
200 prom_printf("Malloc buffer allocated at 0x%x (%d bytes)\n",
201 malloc_base, MALLOCSIZE);
204 /* A few useless printf's */
206 prom_printf("reloc_offset : %ld (should be 0)\n", reloc_offset());
207 prom_printf("test_bss : %d (should be 0)\n", test_bss);
208 prom_printf("test_data : %d (should be 0)\n", test_data);
209 prom_printf("&test_data : 0x%08lx\n", &test_data);
210 prom_printf("&test_bss : 0x%08lx\n", &test_bss);
211 prom_printf("linked at : 0x%08lx\n", TEXTADDR);
213 /* ask the OF info if we're a chrp or pmac */
214 /* we need to set _machine before calling finish_device_tree */
215 root = prom_finddevice("/");
217 static char model[256];
218 if (prom_getprop(root, "device_type", model, 256 ) > 0 &&
219 !strncmp("chrp", model, 4))
220 _machine = _MACH_chrp;
222 if (prom_getprop(root, "model", model, 256 ) > 0 &&
223 !strncmp(model, "IBM", 3))
224 _machine = _MACH_chrp;
229 prom_printf("Running on _machine = %d\n", _machine);
233 result = yaboot_main();
235 /* Get rid of malloc pool */
237 prom_release(malloc_base, MALLOCSIZE);
239 prom_printf("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 */
268 /* Currently, the config file must be at the root of the filesystem.
269 * todo: recognize the full path to myself and use it to load the
270 * config file. Handle the "\\" (blessed system folder)
273 load_config_file(char *device, char* path, int partition)
275 char *conf_file = NULL, *p;
276 struct boot_file_t file;
277 int sz, opened = 0, result = 0;
279 struct boot_fspec_t fspec;
281 /* Allocate a buffer for the config file */
282 conf_file = malloc(CONFIG_FILE_MAX);
284 prom_printf("Can't alloc config file buffer\n");
288 /* Build the path to the file */
290 strcpy(conf_path, path);
291 else if ( _machine == _MACH_chrp )
292 strcpy(conf_path, "/etc/");
295 strcat(conf_path, CONFIG_FILE_NAME);
299 fspec.file = conf_path;
300 fspec.part = partition;
301 result = open_file(&fspec, &file);
302 if (result != FILE_ERR_OK) {
303 prom_printf("Can't open config file '%s', err: %d\n", conf_path, result);
309 sz = file.fs->read(&file, CONFIG_FILE_MAX, conf_file);
311 prom_printf("Error, can't read config file\n");
314 prom_printf("Config file read, %d bytes\n", sz);
318 file.fs->close(&file);
321 /* Call the parsing code in cfg.c */
322 if (cfg_parse(conf_path, conf_file, sz) < 0) {
323 prom_printf ("Syntax error or read error config\n");
328 prom_printf("Config file successfully parsed\n", sz);
331 /* Now, we do the initialisations stored in the config file */
332 p = cfg_get_strg(0, "init-code");
336 password = cfg_get_strg(0, "password");
338 #ifdef CONFIG_COLOR_TEXT
339 p = cfg_get_strg(0, "fgcolor");
342 prom_printf("fgcolor=%s\n", p);
344 fgcolor = check_color_text_ui(p);
346 prom_printf("Invalid fgcolor: \"%s\".\n", p);
349 p = cfg_get_strg(0, "bgcolor");
352 prom_printf("bgcolor=%s\n", p);
354 bgcolor = check_color_text_ui(p);
356 prom_printf("Invalid bgcolor: \"%s\".\n", p);
360 sprintf(temp, "%x to background-color", bgcolor);
361 prom_interpret(temp);
368 sprintf(temp, "%x to foreground-color", fgcolor);
369 prom_interpret(temp);
371 #endif /* CONFIG_COLOR_TEXT */
373 p = cfg_get_strg(0, "init-message");
375 prom_printf("%s\n", p);
377 p = cfg_get_strg(0, "message");
379 print_message_file(p);
387 file.fs->close(&file);
389 if (result != 1 && conf_file)
395 void maintabfunc (void)
399 prom_printf("boot: %s", cbuff);
404 word_split(char **linep, char **paramsp)
419 while (*p != 0 && *p != ' ')
428 make_params(char *label, char *params)
431 static char buffer[2048];
436 p = cfg_get_strg(label, "literal");
448 p = cfg_get_strg(label, "root");
455 if (cfg_get_flag(label, "read-only")) {
459 if (cfg_get_flag(label, "read-write")) {
463 p = cfg_get_strg(label, "ramdisk");
465 strcpy (q, "ramdisk=");
470 p = cfg_get_strg(label, "initrd-size");
472 strcpy (q, "ramdisk_size=");
477 if (cfg_get_flag(label, "novideo")) {
478 strcpy (q, "video=ofonly");
482 p = cfg_get_strg (label, "append");
489 pause_after = cfg_get_flag (label, "pause-after");
490 p = cfg_get_strg(label, "pause-message");
499 void check_password(char *str)
503 for (i = 0; i < 3; i++) {
504 prom_printf ("\n%sassword: ", str);
506 cmdedit ((void (*)(void)) 0, 1);
508 #ifdef USE_MD5_PASSWORDS
509 if (!strncmp (password, "$1$", 3)) {
510 if (!check_md5_password(passwdbuff, password))
513 else if (!strcmp (password, passwdbuff))
516 if (!strcmp (password, passwdbuff))
520 prom_printf ("Password incorrect. Please try again...");
522 prom_printf ("Seems like you don't know the access password. Go away!\n");
523 end = (prom_getms() + 3000);
524 while (prom_getms() <= end);
525 prom_interpret("reset-all");
528 int get_params(struct boot_param_t* params)
534 char *imagename = 0, *label;
539 static int first = 1;
540 static char bootargs[1024];
541 static char imagepath[1024];
542 static char initrdpath[1024];
543 static char sysmappath[1024];
544 #ifdef CONFIG_SPLASH_SCREEN
545 static char splashpath[1024];
546 #endif /* CONFIG_SPLASH_SCREEN */
549 memset(params, 0, sizeof(*params));
551 params->kernel.part = -1;
552 params->rd.part = -1;
553 params->sysmap.part = -1;
554 params->splash.part = -1;
555 defpart = bootpartition;
561 prom_get_chosen("bootargs", bootargs, sizeof(bootargs));
562 imagename = bootargs;
563 word_split(&imagename, ¶ms->args);
564 timeout = DEFAULT_TIMEOUT;
566 prom_printf("Default supplied on the command line: ");
567 prom_printf("%s ", imagename);
569 prom_printf("%s", params->args);
572 if (useconf && (q = cfg_get_strg(0, "timeout")) != 0 && *q != 0)
573 timeout = simple_strtol(q, NULL, 0);
576 prom_printf("boot: ");
581 end = beg + 100 * timeout;
583 c = prom_nbgetchar();
584 } while (c == -1 && prom_getms() <= end);
588 else if (c != '\n' && c != '\t' && c != '\r' && c != '\b' ) {
594 if (c != -1 && c != '\n' && c != '\r') {
597 } else if (c >= ' ') {
600 if ((cfg_get_flag (cbuff, "single-key")) && useconf) {
603 prom_printf("%s\n", cbuff);
608 if (c == '\n' || c == '\r') {
610 imagename = cfg_get_default();
612 prom_printf("%s", imagename);
614 prom_printf(" %s", params->args);
616 } else if (!singlekey) {
617 cmdedit(maintabfunc, 0);
619 strcpy(given_bootargs, cbuff);
620 given_bootargs_by_user = 1;
622 word_split(&imagename, ¶ms->args);
625 /* chrp gets this wrong, force it -- Cort */
626 if ( useconf && (!imagename || imagename[0] == 0 ))
627 imagename = cfg_get_default();
630 defdevice = bootdevice;
633 defdevice = cfg_get_strg(0, "device");
634 p = cfg_get_strg(0, "partition");
636 n = simple_strtol(p, &endp, 10);
637 if (endp != p && *endp == 0)
640 p = cfg_get_strg(0, "pause-message");
643 if (cfg_get_flag(0, "restricted"))
645 p = cfg_get_strg(imagename, "image");
649 defdevice = cfg_get_strg(label, "device");
650 if(!defdevice) defdevice=bootdevice;
651 p = cfg_get_strg(label, "partition");
653 n = simple_strtol(p, &endp, 10);
654 if (endp != p && *endp == 0)
657 if (cfg_get_flag(label, "restricted"))
660 if (params->args && password && restricted)
661 check_password ("To specify image arguments you must enter the p");
662 else if (password && !restricted)
663 check_password ("P");
665 params->args = make_params(label, params->args);
669 if (!strcmp (imagename, "halt")) {
671 check_password ("P");
675 if (!strcmp (imagename, "bye")) {
677 check_password ("P");
683 if (imagename[0] == '$') {
684 /* forth command string */
686 check_password ("P");
687 prom_interpret(imagename+1);
691 strncpy(imagepath, imagename, 1024);
693 if (!label && password)
694 check_password ("To boot a custom image you must enter the p");
696 params->kernel.dev = parse_device_path(imagepath, ¶ms->kernel.file,
697 ¶ms->kernel.part);
698 if (validate_fspec(¶ms->kernel, defdevice, defpart) != FILE_ERR_OK) {
700 "Enter the kernel image name as [device:][partno]/path, where partno is a\n"
701 "number from 0 to 16. Instead of /path you can type [mm-nn] to specify a\n"
702 "range of disk blocks (512B)\n"
703 "Example: hd:3,/vmlinux\n");
708 p = cfg_get_strg(label, "initrd");
711 prom_printf("parsing initrd path <%s>\n", p);
713 strncpy(initrdpath, p, 1024);
714 params->rd.dev = parse_device_path(initrdpath,
715 ¶ms->rd.file, ¶ms->rd.part);
716 validate_fspec(¶ms->rd, defdevice, defpart);
718 p = cfg_get_strg(label, "sysmap");
721 prom_printf("parsing sysmap path <%s>\n", p);
723 strncpy(sysmappath, p, 1024);
724 params->sysmap.dev = parse_device_path(sysmappath,
725 ¶ms->sysmap.file, ¶ms->sysmap.part);
726 validate_fspec(¶ms->sysmap, defdevice, defpart);
728 #ifdef CONFIG_SPLASH_SCREEN
729 p = cfg_get_strg(label, "splash");
732 prom_printf("parsing splash path <%s>\n", p);
734 strncpy(splashpath, p, 1024);
735 params->splash.dev = parse_device_path(splashpath,
736 ¶ms->splash.file, ¶ms->splash.part);
737 validate_fspec(¶ms->splash, defdevice, defpart);
739 #endif /* CONFIG_SPLASH_SCREEN */
745 /* This is derived from quik core. To be changed to first parse the headers
746 * doing lazy-loading, and then claim the memory before loading the kernel
748 * We also need to add initrd support to this whole mecanism
753 #define MAX_HEADERS 32
755 struct boot_file_t file;
757 static struct boot_param_t params;
759 unsigned long initrd_size;
761 unsigned long sysmap_size;
762 kernel_entry_t kernel_entry;
763 struct bi_record* birec;
766 void *initrd_more,*initrd_want;
767 unsigned long initrd_read;
769 loadinfo.load_loc = 0;
777 if (get_params(¶ms))
779 if (!params.kernel.file)
782 #ifdef CONFIG_SPLASH_SCREEN
783 if (params.splash.file)
784 fxDisplaySplash(¶ms.splash);
785 #endif /* CONFIG_SPLASH_SCREEN */
786 prom_printf("Please wait, loading kernel...\n");
788 if(bootpath && !strcmp(bootpath,"\\\\") && params.kernel.file[0] != '/') {
789 loc=(char*)malloc(strlen(params.kernel.file)+3);
791 prom_printf ("malloc error\n");
794 strcpy(loc,bootpath);
795 strcat(loc,params.kernel.file);
796 free(params.kernel.file);
797 params.kernel.file=loc;
799 result = open_file(¶ms.kernel, &file);
800 if (result != FILE_ERR_OK) {
801 prom_printf("\nImage not found.... try again\n");
805 /* Read the Elf e_ident, e_type and e_machine fields to
806 * determine Elf file type
808 if (file.fs->read(&file, sizeof(Elf_Ident), &loadinfo.elf) < sizeof(Elf_Ident)) {
809 prom_printf("\nCan't read Elf e_ident/e_type/e_machine info\n");
813 if ( is_elf32(&loadinfo) ) {
814 if ( !load_elf32(&file, &loadinfo) )
816 prom_printf(" Elf32 kernel loaded...\n");
817 } else if ( is_elf64(&loadinfo) ) {
818 if ( !load_elf64(&file, &loadinfo) )
820 prom_printf(" Elf64 kernel loaded...\n");
822 prom_printf ("Not a valid ELF image\n");
825 file.fs->close(&file);
827 /* If sysmap, load it.
829 if (params.sysmap.file) {
830 prom_printf("Loading System.map ...\n");
831 if(bootpath && !strcmp(bootpath,"\\\\") && params.sysmap.file[0] != '/') {
833 loc=(char*)malloc(strlen(params.sysmap.file)+3);
835 prom_printf ("malloc error\n");
838 strcpy(loc,bootpath);
839 strcat(loc,params.sysmap.file);
840 free(params.sysmap.file);
841 params.sysmap.file=loc;
844 result = open_file(¶ms.sysmap, &file);
845 if (result != FILE_ERR_OK)
846 prom_printf("\nSystem.map file not found.\n");
848 sysmap_base = prom_claim(loadinfo.base+loadinfo.memsize, 0x100000, 0);
849 if (sysmap_base == (void *)-1) {
850 prom_printf("claim failed for sysmap memory\n");
853 sysmap_size = file.fs->read(&file, 0xfffff, sysmap_base);
854 if (sysmap_size == 0)
857 ((char *)sysmap_base)[sysmap_size++] = 0;
859 file.fs->close(&file);
862 prom_printf("System.map loaded at 0x%08lx, size: %d Kbytes\n",
863 sysmap_base, sysmap_size >> 10);
864 loadinfo.memsize += _ALIGN(0x100000, 0x1000);
866 prom_printf("System.map load failed !\n");
871 /* If ramdisk, load it. For now, we can't tell the size it will be
872 * so we claim an arbitrary amount of 4Mb
874 if (params.rd.file) {
875 if(bootpath && !strcmp(bootpath,"\\\\") && params.rd.file[0] != '/')
878 loc=(char*)malloc(strlen(params.rd.file)+3);
880 prom_printf ("malloc error\n");
883 strcpy(loc,bootpath);
884 strcat(loc,params.rd.file);
885 free(params.rd.file);
888 prom_printf("Loading ramdisk...\n");
889 result = open_file(¶ms.rd, &file);
890 if (result != FILE_ERR_OK)
891 prom_printf("\nRamdisk image not found.\n");
893 #define INITRD_CHUNKSIZE 0x400000
894 initrd_base = prom_claim(loadinfo.base+loadinfo.memsize, INITRD_CHUNKSIZE, 0);
895 if (initrd_base == (void *)-1) {
896 prom_printf("claim failed for initrd memory\n");
899 initrd_size = file.fs->read(&file, INITRD_CHUNKSIZE, initrd_base);
900 if (initrd_size == 0)
902 initrd_read = initrd_size;
903 initrd_more = initrd_base;
904 while (initrd_read == INITRD_CHUNKSIZE ) { /* need to read more? */
905 initrd_want = (void *)((unsigned long)initrd_more+INITRD_CHUNKSIZE);
906 initrd_more = prom_claim(initrd_want, INITRD_CHUNKSIZE, 0);
907 if (initrd_more != initrd_want) {
908 prom_printf("claim failed for initrd memory at %x rc=%x\n",initrd_want,initrd_more);
911 initrd_read = file.fs->read(&file, INITRD_CHUNKSIZE, initrd_more);
913 prom_printf(" block at %x rc=%x\n",initrd_more,initrd_read);
915 initrd_size += initrd_read;
918 file.fs->close(&file);
921 prom_printf("ramdisk loaded at 0x%08lx, size: %d Kbytes\n",
922 initrd_base, initrd_size >> 10);
924 prom_printf("ramdisk load failed !\n");
930 prom_printf("setting kernel args to: %s\n", params.args);
932 prom_setargs(params.args);
934 prom_printf("flushing icache...");
936 flush_icache_range ((long)loadinfo.base, (long)loadinfo.base+loadinfo.memsize);
938 prom_printf(" done\n");
942 * Fill mew boot infos
944 * The birec is low on memory, probably inside the malloc pool, so
945 * we don't write it earlier. At this point, we should not use anything
946 * coming from the malloc pool
948 birec = (struct bi_record *)_ALIGN(loadinfo.filesize+(1<<20)-1,(1<<20));
950 /* We make sure it's mapped. We map only 64k for now, it's plenty enough
951 * we don't claim since this precise memory range may already be claimed
954 prom_map (birec, birec, 0x10000);
956 prom_printf("birec at 0x%08lx\n", birec);
958 int i = prom_getms();
959 while((prom_getms() - i) < 2000)
964 birec->tag = BI_FIRST;
965 birec->size = sizeof(struct bi_record);
966 birec = (struct bi_record *)((unsigned long)birec + birec->size);
968 birec->tag = BI_BOOTLOADER_ID;
969 sprintf( (char *)birec->data, "yaboot");
970 birec->size = sizeof(struct bi_record) + strlen("yaboot") + 1;
971 birec = (struct bi_record *)((unsigned long)birec + birec->size);
973 birec->tag = BI_MACHTYPE;
974 birec->data[0] = _machine;
975 birec->size = sizeof(struct bi_record) + sizeof(unsigned long);
976 birec = (struct bi_record *)((unsigned long)birec + birec->size);
979 birec->tag = BI_SYSMAP;
980 birec->data[0] = (unsigned long)sysmap_base;
981 birec->data[1] = sysmap_size;
982 birec->size = sizeof(struct bi_record) + sizeof(unsigned long)*2;
983 birec = (struct bi_record *)((unsigned long)birec + birec->size);
985 birec->tag = BI_LAST;
986 birec->size = sizeof(struct bi_record);
987 birec = (struct bi_record *)((unsigned long)birec + birec->size);
989 /* compute the kernel's entry point. */
990 kernel_entry = loadinfo.base + loadinfo.entry - loadinfo.load_loc;
993 prom_printf("Kernel entry point = 0x%08lx\n", kernel_entry);
994 prom_printf("kernel: arg1 = 0x%08lx,\n"
998 " arg5 = 0x%08lx\n\n",
999 initrd_base + loadinfo.load_loc, initrd_size, prom, 0, 0);
1004 prom_printf("entering kernel...\n");
1006 /* call the kernel with our stack. */
1007 kernel_entry(initrd_base + loadinfo.load_loc, initrd_size, prom, 0, 0);
1010 if( file.fs != NULL )
1011 file.fs->close(&file);
1016 load_elf32(struct boot_file_t *file, loadinfo_t *loadinfo)
1019 Elf32_Ehdr *e = &(loadinfo->elf.elf32hdr);
1021 int size = sizeof(Elf32_Ehdr) - sizeof(Elf_Ident);
1022 unsigned long addr, loadaddr;
1024 /* Read the rest of the Elf header... */
1025 if ((*(file->fs->read))(file, size, &e->e_version) < size) {
1026 prom_printf("\nCan't read Elf32 image header\n");
1031 prom_printf("Elf32 header:\n");
1032 prom_printf(" e.e_type = %d\n", (int)e->e_type);
1033 prom_printf(" e.e_machine = %d\n", (int)e->e_machine);
1034 prom_printf(" e.e_version = %d\n", (int)e->e_version);
1035 prom_printf(" e.e_entry = 0x%08x\n", (int)e->e_entry);
1036 prom_printf(" e.e_phoff = 0x%08x\n", (int)e->e_phoff);
1037 prom_printf(" e.e_shoff = 0x%08x\n", (int)e->e_shoff);
1038 prom_printf(" e.e_flags = %d\n", (int)e->e_flags);
1039 prom_printf(" e.e_ehsize = 0x%08x\n", (int)e->e_ehsize);
1040 prom_printf(" e.e_phentsize = 0x%08x\n", (int)e->e_phentsize);
1041 prom_printf(" e.e_phnum = %d\n", (int)e->e_phnum);
1044 loadinfo->entry = e->e_entry;
1046 if (e->e_phnum > MAX_HEADERS) {
1047 prom_printf ("can only load kernels with one program header\n");
1051 ph = (Elf32_Phdr *)malloc(sizeof(Elf32_Phdr) * e->e_phnum);
1053 prom_printf ("malloc error\n");
1057 /* Now, we read the section header */
1058 if ((*(file->fs->seek))(file, e->e_phoff) != FILE_ERR_OK) {
1059 prom_printf ("seek error\n");
1062 if ((*(file->fs->read))(file, sizeof(Elf32_Phdr) * e->e_phnum, ph) !=
1063 sizeof(Elf32_Phdr) * e->e_phnum) {
1064 prom_printf ("read error\n");
1068 /* Scan through the program header
1069 * HACK: We must return the _memory size of the kernel image, not the
1070 * file size (because we have to leave room before other boot
1071 * infos. This code works as a side effect of the fact that
1072 * we have one section and vaddr == p_paddr
1074 loadinfo->memsize = loadinfo->filesize = loadinfo->offset = 0;
1076 for (i = 0; i < e->e_phnum; ++i, ++p) {
1077 if (p->p_type != PT_LOAD || p->p_offset == 0)
1079 if (loadinfo->memsize == 0) {
1080 loadinfo->offset = p->p_offset;
1081 loadinfo->memsize = p->p_memsz;
1082 loadinfo->filesize = p->p_filesz;
1083 loadinfo->load_loc = p->p_vaddr;
1085 loadinfo->memsize = p->p_offset + p->p_memsz - loadinfo->offset; /* XXX Bogus */
1086 loadinfo->filesize = p->p_offset + p->p_filesz - loadinfo->offset;
1090 if (loadinfo->memsize == 0) {
1091 prom_printf("Can't find a loadable segment !\n");
1095 /* leave some room (1Mb) for boot infos */
1096 loadinfo->memsize = _ALIGN(loadinfo->memsize,(1<<20)) + 0x100000;
1097 /* Claim OF memory */
1099 prom_printf("Before prom_claim, mem_sz: 0x%08lx\n", loadinfo->memsize);
1102 /* On some systems, loadaddr may already be claimed, so try some
1103 * other nearby addresses before giving up.
1105 loadaddr = (e->e_entry == KERNEL_LINK_ADDR_PPC32) ? KERNELADDR : e->e_entry;
1106 for(addr=loadaddr; addr <= loadaddr * 8 ;addr+=0x100000) {
1107 loadinfo->base = prom_claim((void *)addr, loadinfo->memsize, 0);
1108 if (loadinfo->base != (void *)-1) break;
1110 if (loadinfo->base == (void *)-1) {
1111 prom_printf("claim error, can't allocate kernel memory\n");
1116 prom_printf("After ELF parsing, load base: 0x%08lx, mem_sz: 0x%08lx\n",
1117 loadinfo->base, loadinfo->memsize);
1118 prom_printf(" wanted load base: 0x%08lx, mem_sz: 0x%08lx\n",
1119 loadaddr, loadinfo->memsize);
1122 /* Load the program segments... */
1124 for (i = 0; i < e->e_phnum; ++i, ++p) {
1125 unsigned long offset;
1126 if (p->p_type != PT_LOAD || p->p_offset == 0)
1129 /* Now, we skip to the image itself */
1130 if ((*(file->fs->seek))(file, p->p_offset) != FILE_ERR_OK) {
1131 prom_printf ("seek error\n");
1132 prom_release(loadinfo->base, loadinfo->memsize);
1135 offset = p->p_vaddr - loadinfo->load_loc;
1136 #ifdef CONFIG_SPLASH_SCREEN
1137 if (fxReadImage(file, p->p_filesz, loadinfo->base+offset) != p->p_filesz) {
1138 #else /* CONFIG_SPLASH_SCREEN */
1139 if ((*(file->fs->read))(file, p->p_filesz, loadinfo->base+offset) != p->p_filesz) {
1140 #endif /* CONFIG_SPLASH_SCREEN */
1141 prom_printf ("read failed\n");
1142 prom_release(loadinfo->base, loadinfo->memsize);
1147 #if 0 /* to make editor happy */
1150 (*(file->fs->close))(file);
1154 /* Return success at loading the Elf32 kernel */
1159 load_elf64(struct boot_file_t *file, loadinfo_t *loadinfo)
1162 Elf64_Ehdr *e = &(loadinfo->elf.elf64hdr);
1164 int size = sizeof(Elf64_Ehdr) - sizeof(Elf_Ident);
1165 unsigned long addr, loadaddr;
1167 /* Read the rest of the Elf header... */
1168 if ((*(file->fs->read))(file, size, &e->e_version) < size) {
1169 prom_printf("\nCan't read Elf64 image header\n");
1174 prom_printf("Elf64 header:\n");
1175 prom_printf(" e.e_type = %d\n", (int)e->e_type);
1176 prom_printf(" e.e_machine = %d\n", (int)e->e_machine);
1177 prom_printf(" e.e_version = %d\n", (int)e->e_version);
1178 prom_printf(" e.e_entry = 0x%016lx\n", (long)e->e_entry);
1179 prom_printf(" e.e_phoff = 0x%016lx\n", (long)e->e_phoff);
1180 prom_printf(" e.e_shoff = 0x%016lx\n", (long)e->e_shoff);
1181 prom_printf(" e.e_flags = %d\n", (int)e->e_flags);
1182 prom_printf(" e.e_ehsize = 0x%08x\n", (int)e->e_ehsize);
1183 prom_printf(" e.e_phentsize = 0x%08x\n", (int)e->e_phentsize);
1184 prom_printf(" e.e_phnum = %d\n", (int)e->e_phnum);
1187 loadinfo->entry = e->e_entry;
1189 if (e->e_phnum > MAX_HEADERS) {
1190 prom_printf ("can only load kernels with one program header\n");
1194 ph = (Elf64_Phdr *)malloc(sizeof(Elf64_Phdr) * e->e_phnum);
1196 prom_printf ("malloc error\n");
1200 /* Now, we read the section header */
1201 if ((*(file->fs->seek))(file, e->e_phoff) != FILE_ERR_OK) {
1202 prom_printf ("seek error\n");
1205 if ((*(file->fs->read))(file, sizeof(Elf64_Phdr) * e->e_phnum, ph) !=
1206 sizeof(Elf64_Phdr) * e->e_phnum) {
1207 prom_printf ("read error\n");
1211 /* Scan through the program header
1212 * HACK: We must return the _memory size of the kernel image, not the
1213 * file size (because we have to leave room before other boot
1214 * infos. This code works as a side effect of the fact that
1215 * we have one section and vaddr == p_paddr
1217 loadinfo->memsize = loadinfo->filesize = loadinfo->offset = 0;
1219 for (i = 0; i < e->e_phnum; ++i, ++p) {
1220 if (p->p_type != PT_LOAD || p->p_offset == 0)
1222 if (loadinfo->memsize == 0) {
1223 loadinfo->offset = p->p_offset;
1224 loadinfo->memsize = p->p_memsz;
1225 loadinfo->filesize = p->p_filesz;
1226 loadinfo->load_loc = p->p_vaddr;
1228 loadinfo->memsize = p->p_offset + p->p_memsz - loadinfo->offset; /* XXX Bogus */
1229 loadinfo->filesize = p->p_offset + p->p_filesz - loadinfo->offset;
1233 if (loadinfo->memsize == 0) {
1234 prom_printf("Can't find a loadable segment !\n");
1238 /* leave some room (1Mb) for boot infos */
1239 loadinfo->memsize = _ALIGN(loadinfo->memsize,(1<<20)) + 0x100000;
1240 /* Claim OF memory */
1242 prom_printf("Before prom_claim, mem_sz: 0x%08lx\n", loadinfo->memsize);
1245 /* On some systems, loadaddr may already be claimed, so try some
1246 * other nearby addresses before giving up.
1248 loadaddr = (e->e_entry == KERNEL_LINK_ADDR_PPC64) ? KERNELADDR : e->e_entry;
1249 for(addr=loadaddr; addr <= loadaddr * 8 ;addr+=0x100000) {
1250 loadinfo->base = prom_claim((void *)addr, loadinfo->memsize, 0);
1251 if (loadinfo->base != (void *)-1) break;
1253 if (loadinfo->base == (void *)-1) {
1254 prom_printf("claim error, can't allocate kernel memory\n");
1259 prom_printf("After ELF parsing, load base: 0x%08lx, mem_sz: 0x%08lx\n",
1260 loadinfo->base, loadinfo->memsize);
1261 prom_printf(" wanted load base: 0x%08lx, mem_sz: 0x%08lx\n",
1262 loadaddr, loadinfo->memsize);
1265 /* Load the program segments... */
1267 for (i = 0; i < e->e_phnum; ++i, ++p) {
1268 unsigned long offset;
1269 if (p->p_type != PT_LOAD || p->p_offset == 0)
1272 /* Now, we skip to the image itself */
1273 if ((*(file->fs->seek))(file, p->p_offset) != FILE_ERR_OK) {
1274 prom_printf ("seek error\n");
1275 prom_release(loadinfo->base, loadinfo->memsize);
1278 offset = p->p_vaddr - loadinfo->load_loc;
1279 #ifdef CONFIG_SPLASH_SCREEN
1280 if (fxReadImage(file, p->p_filesz, loadinfo->base+offset) != p->p_filesz) {
1281 #else /* CONFIG_SPLASH_SCREEN */
1282 if ((*(file->fs->read))(file, p->p_filesz, loadinfo->base+offset) != p->p_filesz) {
1283 #endif /* CONFIG_SPLASH_SCREEN */
1284 prom_printf ("read failed\n");
1285 prom_release(loadinfo->base, loadinfo->memsize);
1290 #if 0 /* to make editor happy */
1293 (*(file->fs->close))(file);
1297 /* Return success at loading the Elf64 kernel */
1302 is_elf32(loadinfo_t *loadinfo)
1304 Elf32_Ehdr *e = &(loadinfo->elf.elf32hdr);
1306 return (e->e_ident[EI_MAG0] == ELFMAG0 &&
1307 e->e_ident[EI_MAG1] == ELFMAG1 &&
1308 e->e_ident[EI_MAG2] == ELFMAG2 &&
1309 e->e_ident[EI_MAG3] == ELFMAG3 &&
1310 e->e_ident[EI_CLASS] == ELFCLASS32 &&
1311 e->e_ident[EI_DATA] == ELFDATA2MSB &&
1312 e->e_type == ET_EXEC &&
1313 e->e_machine == EM_PPC);
1317 is_elf64(loadinfo_t *loadinfo)
1319 Elf64_Ehdr *e = &(loadinfo->elf.elf64hdr);
1321 return (e->e_ident[EI_MAG0] == ELFMAG0 &&
1322 e->e_ident[EI_MAG1] == ELFMAG1 &&
1323 e->e_ident[EI_MAG2] == ELFMAG2 &&
1324 e->e_ident[EI_MAG3] == ELFMAG3 &&
1325 e->e_ident[EI_CLASS] == ELFCLASS64 &&
1326 e->e_ident[EI_DATA] == ELFDATA2MSB &&
1327 e->e_type == ET_EXEC &&
1328 e->e_machine == EM_PPC64);
1334 #ifdef CONFIG_SET_COLORMAP
1335 static unsigned char default_colors[] = {
1354 prom_handle scrn = PROM_INVALID_HANDLE;
1356 /* Try Apple's mac-boot screen ihandle */
1357 result = (int)call_prom_return("interpret", 1, 2,
1358 "\" _screen-ihandle\" $find if execute else 0 then", &scrn);
1360 prom_printf("trying to get screen ihandle, result: 0x%x, scrn: 0x%x\n", result, scrn);
1362 if (scrn == 0 || scrn == PROM_INVALID_HANDLE) {
1364 /* Hrm... check to see if stdout is a display */
1365 scrn = call_prom ("instance-to-package", 1, 1, prom_stdout);
1367 prom_printf("instance-to-package of stdout is: 0x%x\n", scrn);
1369 if (prom_getprop(scrn, "device_type", type, 32) > 0 && !strncmp(type, "display", 7)) {
1371 prom_printf("got it ! stdout is a screen\n");
1375 /* Else, we try to open the package */
1376 scrn = (prom_handle)call_prom( "open", 1, 1, "screen" );
1378 prom_printf("Open screen result: 0x%x\n", scrn);
1383 if (scrn == PROM_INVALID_HANDLE) {
1384 prom_printf("no screen device found !/n");
1388 prom_set_color(scrn, i, default_colors[i*3],
1389 default_colors[i*3+1], default_colors[i*3+2]);
1391 prom_printf("\x1b[1;37m\x1b[2;40m");
1393 for (i=0;i<16; i++) {
1394 prom_printf("\x1b[%d;%dm\x1b[1;47m%s \x1b[2;40m %s\n",
1395 ansi_color_table[i].index,
1396 ansi_color_table[i].value,
1397 ansi_color_table[i].name,
1398 ansi_color_table[i].name);
1399 prom_printf("\x1b[%d;%dm\x1b[1;37m%s \x1b[2;30m %s\n",
1400 ansi_color_table[i].index,
1401 ansi_color_table[i].value+10,
1402 ansi_color_table[i].name,
1403 ansi_color_table[i].name);
1405 prom_printf("\x1b[1;37m\x1b[2;40m");
1410 #endif /* CONFIG_SET_COLORMAP */
1416 if (_machine == _MACH_Pmac)
1419 prom_get_chosen("bootpath", bootdevice, sizeof(bootdevice));
1421 prom_printf("/chosen/bootpath = %s\n", bootdevice);
1423 if (bootdevice[0] == 0)
1424 prom_get_options("boot-device", bootdevice, sizeof(bootdevice));
1425 if (bootdevice[0] == 0) {
1426 prom_printf("Couldn't determine boot device\n");
1429 parse_device_path(bootdevice, &bootpath, &bootpartition);
1431 prom_printf("after parse_device_path: device:%s, path: %s, partition: %d\n",
1432 bootdevice, bootpath ? bootpath : NULL, bootpartition);
1435 if (!strncmp(bootpath, "\\\\", 2))
1439 p = last = bootpath;
1449 if (bootpath && strlen(bootpath))
1450 strcat(bootpath, "\\");
1454 prom_printf("after path fixup: device:%s, path: %s, partition: %d\n",
1455 bootdevice, bootpath ? bootpath : NULL, bootpartition);
1457 useconf = load_config_file(bootdevice, bootpath, bootpartition);
1459 prom_printf("Welcome to yaboot version " VERSION "\n");
1463 prom_printf("Bye.\n");