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"
50 #define CONFIG_FILE_NAME "yaboot.conf"
51 #define CONFIG_FILE_MAX 0x8000 /* 32k */
53 #ifdef USE_MD5_PASSWORDS
55 #endif /* USE_MD5_PASSWORDS */
57 /* align addr on a size boundry - adjust address up if needed -- Cort */
58 #define _ALIGN(addr,size) (((addr)+size-1)&(~(size-1)))
60 /* Addresses where the PPC32 and PPC64 vmlinux kernels are linked at.
61 * These are used to determine whether we are booting a vmlinux, in
62 * which case, it will be loaded at KERNELADDR. Otherwise (eg zImage),
63 * we load the binary where it was linked at (ie, e_entry field in
66 #define KERNEL_LINK_ADDR_PPC32 0xC0000000UL
67 #define KERNEL_LINK_ADDR_PPC64 0xC000000000000000ULL
75 unsigned long memsize;
76 unsigned long filesize;
78 unsigned long load_loc;
82 typedef void (*kernel_entry_t)( void *,
88 /* Imported functions */
89 extern unsigned long reloc_offset(void);
90 extern long flush_icache_range(unsigned long start, unsigned long stop);
92 /* Exported functions */
93 int yaboot_start(unsigned long r3, unsigned long r4, unsigned long r5);
96 static int yaboot_main(void);
97 static int is_elf32(loadinfo_t *loadinfo);
98 static int is_elf64(loadinfo_t *loadinfo);
99 static int load_elf32(struct boot_file_t *file, loadinfo_t *loadinfo);
100 static int load_elf64(struct boot_file_t *file, loadinfo_t *loadinfo);
101 static void setup_display(void);
103 /* Locals & globals */
106 char bootdevice[1024];
107 //char *bootpath = NULL;
108 char *password = NULL;
109 //int bootpartition = -1;
110 struct boot_fspec_t boot;
111 int _machine = _MACH_Pmac;
113 #ifdef CONFIG_COLOR_TEXT
115 /* Color values for text ui */
116 static struct ansi_color_t {
120 } ansi_color_table[] = {
128 { "light-gray", 0, 37 },
129 { "dark-gray", 1, 30 },
130 { "light-blue", 1, 31 },
131 { "light-green", 1, 32 },
132 { "light-cyan", 1, 33 },
133 { "light-red", 1, 34 },
134 { "light-purple", 1, 35 },
140 /* Default colors for text ui */
143 #endif /* CONFIG_COLOR_TEXT */
147 static int test_data = 0;
149 static int pause_after;
150 static char *pause_message = "Type go<return> to continue.\n";
151 static char given_bootargs[1024];
152 static int given_bootargs_by_user = 0;
154 extern unsigned char linux_logo_red[];
155 extern unsigned char linux_logo_green[];
156 extern unsigned char linux_logo_blue[];
158 #define DEFAULT_TIMEOUT -1
160 /* Entry, currently called directly by crt0 (bss not inited) */
162 extern char* __bss_start;
165 static struct first_info *quik_fip = NULL;
168 yaboot_start (unsigned long r3, unsigned long r4, unsigned long r5)
171 void* malloc_base = NULL;
174 /* OF seems to do it, but I'm not very confident */
175 memset(&__bss_start, 0, &_end - &__bss_start);
177 /* Check for quik first stage bootloader (but I don't think we are
178 * compatible with it anyway, I'll look into backporting to older OF
181 if (r5 == 0xdeadbeef) {
183 quik_fip = (struct first_info *)r4;
186 /* Initialize OF interface */
187 prom_init ((prom_entry) r5);
189 /* Allocate some memory for malloc'ator */
190 malloc_base = prom_claim((void *)MALLOCADDR, MALLOCSIZE, 0);
191 if (malloc_base == (void *)-1) {
192 prom_printf("Can't claim malloc buffer (%d bytes at 0x%08x)\n",
193 MALLOCSIZE, MALLOCADDR);
196 malloc_init(malloc_base, MALLOCSIZE);
197 DEBUG_F("Malloc buffer allocated at %p (%d bytes)\n",
198 malloc_base, MALLOCSIZE);
200 /* A few useless DEBUG_F's */
201 DEBUG_F("reloc_offset : %ld (should be 0)\n", reloc_offset());
202 DEBUG_F("test_bss : %d (should be 0)\n", test_bss);
203 DEBUG_F("test_data : %d (should be 0)\n", test_data);
204 DEBUG_F("&test_data : %p\n", &test_data);
205 DEBUG_F("&test_bss : %p\n", &test_bss);
206 DEBUG_F("linked at : 0x%08x\n", TEXTADDR);
208 /* ask the OF info if we're a chrp or pmac */
209 /* we need to set _machine before calling finish_device_tree */
210 root = prom_finddevice("/");
212 static char model[256];
213 if (prom_getprop(root, "device_type", model, 256 ) > 0 &&
214 !strncmp("chrp", model, 4))
215 _machine = _MACH_chrp;
217 if (prom_getprop(root, "model", model, 256 ) > 0 &&
218 !strncmp(model, "IBM", 3))
219 _machine = _MACH_chrp;
223 DEBUG_F("Running on _machine = %d\n", _machine);
227 result = yaboot_main();
229 /* Get rid of malloc pool */
231 prom_release(malloc_base, MALLOCSIZE);
232 DEBUG_F("Malloc buffer released. Exiting with code %d\n",
242 #ifdef CONFIG_COLOR_TEXT
244 * Validify color for text ui
247 check_color_text_ui(char *color)
250 while(ansi_color_table[i].name) {
251 if (!strcmp(color, ansi_color_table[i].name))
257 #endif /* CONFIG_COLOR_TEXT */
259 /* Currently, the config file must be at the root of the filesystem.
260 * todo: recognize the full path to myself and use it to load the
261 * config file. Handle the "\\" (blessed system folder)
264 load_config_file(char *device, char* path, int partition)
266 char *conf_file = NULL, *p;
267 struct boot_file_t file;
268 int sz, opened = 0, result = 0;
270 struct boot_fspec_t fspec;
272 /* Allocate a buffer for the config file */
273 conf_file = malloc(CONFIG_FILE_MAX);
275 prom_printf("Can't alloc config file buffer\n");
279 /* Build the path to the file */
281 strcpy(conf_path, path);
282 else if ( _machine == _MACH_chrp )
283 strcpy(conf_path, "/etc/");
286 strcat(conf_path, CONFIG_FILE_NAME);
290 fspec.file = conf_path;
291 fspec.part = partition;
292 result = open_file(&fspec, &file);
293 if (result != FILE_ERR_OK) {
294 prom_printf("Can't open config file '%s', err: %d\n", conf_path, result);
300 sz = file.fs->read(&file, CONFIG_FILE_MAX, conf_file);
302 prom_printf("Error, can't read config file\n");
305 prom_printf("Config file read, %d bytes\n", sz);
309 file.fs->close(&file);
312 /* Call the parsing code in cfg.c */
313 if (cfg_parse(conf_path, conf_file, sz) < 0) {
314 prom_printf ("Syntax error or read error config\n");
318 DEBUG_F("Config file successfully parsed, %d bytes\n", sz);
320 /* Now, we do the initialisations stored in the config file */
321 p = cfg_get_strg(0, "init-code");
325 password = cfg_get_strg(0, "password");
327 #ifdef CONFIG_COLOR_TEXT
328 p = cfg_get_strg(0, "fgcolor");
330 DEBUG_F("fgcolor=%s\n", p);
331 fgcolor = check_color_text_ui(p);
333 prom_printf("Invalid fgcolor: \"%s\".\n", p);
336 p = cfg_get_strg(0, "bgcolor");
338 DEBUG_F("bgcolor=%s\n", p);
339 bgcolor = check_color_text_ui(p);
341 prom_printf("Invalid bgcolor: \"%s\".\n", p);
345 sprintf(temp, "%x to background-color", bgcolor);
346 prom_interpret(temp);
353 sprintf(temp, "%x to foreground-color", fgcolor);
354 prom_interpret(temp);
356 #endif /* CONFIG_COLOR_TEXT */
358 p = cfg_get_strg(0, "init-message");
360 prom_printf("%s\n", p);
362 p = cfg_get_strg(0, "message");
364 print_message_file(p);
372 file.fs->close(&file);
374 if (result != 1 && conf_file)
380 void maintabfunc (void)
384 prom_printf("boot: %s", cbuff);
389 word_split(char **linep, char **paramsp)
404 while (*p != 0 && *p != ' ')
413 make_params(char *label, char *params)
416 static char buffer[2048];
421 p = cfg_get_strg(label, "literal");
433 p = cfg_get_strg(label, "root");
440 if (cfg_get_flag(label, "read-only")) {
444 if (cfg_get_flag(label, "read-write")) {
448 p = cfg_get_strg(label, "ramdisk");
450 strcpy (q, "ramdisk=");
455 p = cfg_get_strg(label, "initrd-size");
457 strcpy (q, "ramdisk_size=");
462 if (cfg_get_flag(label, "novideo")) {
463 strcpy (q, "video=ofonly");
467 p = cfg_get_strg (label, "append");
474 pause_after = cfg_get_flag (label, "pause-after");
475 p = cfg_get_strg(label, "pause-message");
484 void check_password(char *str)
488 for (i = 0; i < 3; i++) {
489 prom_printf ("\n%sassword: ", str);
491 cmdedit ((void (*)(void)) 0, 1);
493 #ifdef USE_MD5_PASSWORDS
494 if (!strncmp (password, "$1$", 3)) {
495 if (!check_md5_password(passwdbuff, password))
498 else if (!strcmp (password, passwdbuff))
501 if (!strcmp (password, passwdbuff))
503 #endif /* USE_MD5_PASSWORDS */
505 prom_printf ("Password incorrect. Please try again...");
507 prom_printf ("Seems like you don't know the access password. Go away!\n");
509 prom_interpret("reset-all");
512 int get_params(struct boot_param_t* params)
518 char *imagename = 0, *label;
523 static int first = 1;
524 static char bootargs[1024];
525 static char imagepath[1024];
526 static char initrdpath[1024];
527 static char sysmappath[1024];
530 memset(params, 0, sizeof(*params));
532 params->kernel.part = -1;
533 params->rd.part = -1;
534 params->sysmap.part = -1;
541 prom_get_chosen("bootargs", bootargs, sizeof(bootargs));
542 imagename = bootargs;
543 word_split(&imagename, ¶ms->args);
544 timeout = DEFAULT_TIMEOUT;
546 prom_printf("Default supplied on the command line: %s ", imagename);
548 prom_printf("%s", params->args);
551 if (useconf && (q = cfg_get_strg(0, "timeout")) != 0 && *q != 0)
552 timeout = simple_strtol(q, NULL, 0);
555 prom_printf("boot: ");
560 end = beg + 100 * timeout;
562 c = prom_nbgetchar();
563 } while (c == -1 && prom_getms() <= end);
567 else if (c != '\n' && c != '\t' && c != '\r' && c != '\b' ) {
573 if (c != -1 && c != '\n' && c != '\r') {
576 } else if (c >= ' ') {
579 if ((cfg_get_flag (cbuff, "single-key")) && useconf) {
582 prom_printf("%s\n", cbuff);
587 if (c == '\n' || c == '\r') {
589 imagename = cfg_get_default();
591 prom_printf("%s", imagename);
593 prom_printf(" %s", params->args);
595 } else if (!singlekey) {
596 cmdedit(maintabfunc, 0);
598 strcpy(given_bootargs, cbuff);
599 given_bootargs_by_user = 1;
601 word_split(&imagename, ¶ms->args);
604 /* chrp gets this wrong, force it -- Cort */
605 if ( useconf && (!imagename || imagename[0] == 0 ))
606 imagename = cfg_get_default();
609 defdevice = boot.dev;
612 defdevice = cfg_get_strg(0, "device");
613 p = cfg_get_strg(0, "partition");
615 n = simple_strtol(p, &endp, 10);
616 if (endp != p && *endp == 0)
619 p = cfg_get_strg(0, "pause-message");
622 if (cfg_get_flag(0, "restricted"))
624 p = cfg_get_strg(imagename, "image");
628 defdevice = cfg_get_strg(label, "device");
629 if(!defdevice) defdevice=boot.dev;
630 p = cfg_get_strg(label, "partition");
632 n = simple_strtol(p, &endp, 10);
633 if (endp != p && *endp == 0)
636 if (cfg_get_flag(label, "restricted"))
639 if (params->args && password && restricted)
640 check_password ("To specify image arguments you must enter the p");
641 else if (password && !restricted)
642 check_password ("P");
644 params->args = make_params(label, params->args);
648 if (!strcmp (imagename, "help")) {
650 "\nPress the tab key for a list of defined images.\n"
651 "The label marked with a \"*\" is is the default image, "
652 "press <return> to boot it.\n\n"
653 "To boot any other label simply type its name and press <return>.\n\n"
654 "To boot a kernel image which is not defined in the yaboot configuration \n"
655 "file, enter the kernel image name as [device:][partno],/path, where \n"
656 "\"device:\" is the OpenFirmware device path to the disk the image \n"
657 "resides on, and \"partno\" is the partition number the image resides on.\n\n"
658 "If you omit \"device:\" and \"partno\" yaboot will use the values of \n"
659 "\"device=\" and \"partition=\" in yaboot.conf, right now those are set to: \n"
661 "partition=%d\n\n", defdevice, defpart);
665 if (!strcmp (imagename, "halt")) {
667 check_password ("P");
671 if (!strcmp (imagename, "bye")) {
673 check_password ("P");
679 if (imagename[0] == '$') {
680 /* forth command string */
682 check_password ("P");
683 prom_interpret(imagename+1);
687 strncpy(imagepath, imagename, 1024);
689 if (!label && password)
690 check_password ("To boot a custom image you must enter the p");
692 if (!parse_device_path(imagepath, defdevice, defpart,
693 "/vmlinux", ¶ms->kernel)) {
694 prom_printf("%s: Unable to parse\n", imagepath);
697 DEBUG_F("after parse_device_path: dev=%s part=%d file=%s\n", params->kernel.dev,
698 params->kernel.part, params->kernel.file);
701 p = cfg_get_strg(label, "initrd");
703 DEBUG_F("Parsing initrd path <%s>\n", p);
704 strncpy(initrdpath, p, 1024);
705 if (!parse_device_path(initrdpath, defdevice, defpart,
706 "/root.bin", ¶ms->rd)) {
707 prom_printf("%s: Unable to parse\n", imagepath);
711 p = cfg_get_strg(label, "sysmap");
713 DEBUG_F("Parsing sysmap path <%s>\n", p);
714 strncpy(sysmappath, p, 1024);
715 if (!parse_device_path(sysmappath, defdevice, defpart,
716 "/boot/System.map", ¶ms->sysmap)) {
717 prom_printf("%s: Unable to parse\n", imagepath);
725 /* This is derived from quik core. To be changed to first parse the headers
726 * doing lazy-loading, and then claim the memory before loading the kernel
728 * We also need to add initrd support to this whole mecanism
733 #define MAX_HEADERS 32
735 struct boot_file_t file;
737 static struct boot_param_t params;
739 unsigned long initrd_size;
741 unsigned long sysmap_size;
742 kernel_entry_t kernel_entry;
743 struct bi_record* birec;
746 void *initrd_more,*initrd_want;
747 unsigned long initrd_read;
749 loadinfo.load_loc = 0;
757 if (get_params(¶ms))
759 if (!params.kernel.file)
762 prom_printf("Please wait, loading kernel...\n");
764 memset(&file, 0, sizeof(file));
766 if (strlen(boot.file) && !strcmp(boot.file,"\\\\") && params.kernel.file[0] != '/'
767 && params.kernel.file[0] != '\\') {
768 loc=(char*)malloc(strlen(params.kernel.file)+3);
770 prom_printf ("malloc error\n");
773 strcpy(loc,boot.file);
774 strcat(loc,params.kernel.file);
775 free(params.kernel.file);
776 params.kernel.file=loc;
778 result = open_file(¶ms.kernel, &file);
779 if (result != FILE_ERR_OK) {
780 prom_printf("%s:%d,", params.kernel.dev, params.kernel.part);
781 prom_perror(result, params.kernel.file);
785 /* Read the Elf e_ident, e_type and e_machine fields to
786 * determine Elf file type
788 if (file.fs->read(&file, sizeof(Elf_Ident), &loadinfo.elf) < sizeof(Elf_Ident)) {
789 prom_printf("\nCan't read Elf e_ident/e_type/e_machine info\n");
790 file.fs->close(&file);
791 memset(&file, 0, sizeof(file));
795 if (is_elf32(&loadinfo)) {
796 if (!load_elf32(&file, &loadinfo)) {
797 file.fs->close(&file);
798 memset(&file, 0, sizeof(file));
801 prom_printf(" Elf32 kernel loaded...\n");
802 } else if (is_elf64(&loadinfo)) {
803 if (!load_elf64(&file, &loadinfo)) {
804 file.fs->close(&file);
805 memset(&file, 0, sizeof(file));
808 prom_printf(" Elf64 kernel loaded...\n");
810 prom_printf ("%s: Not a valid ELF image\n", params.kernel.file);
811 file.fs->close(&file);
812 memset(&file, 0, sizeof(file));
815 file.fs->close(&file);
816 memset(&file, 0, sizeof(file));
818 /* If sysmap, load it.
820 if (params.sysmap.file) {
821 prom_printf("Loading System.map ...\n");
822 if(strlen(boot.file) && !strcmp(boot.file,"\\\\") && params.sysmap.file[0] != '/'
823 && params.sysmap.file[0] != '\\') {
825 loc=(char*)malloc(strlen(params.sysmap.file)+3);
827 prom_printf ("malloc error\n");
830 strcpy(loc,boot.file);
831 strcat(loc,params.sysmap.file);
832 free(params.sysmap.file);
833 params.sysmap.file=loc;
836 result = open_file(¶ms.sysmap, &file);
837 if (result != FILE_ERR_OK) {
838 prom_printf("%s:%d,", params.sysmap.dev, params.sysmap.part);
839 prom_perror(result, params.sysmap.file);
842 sysmap_base = prom_claim(loadinfo.base+loadinfo.memsize, 0x100000, 0);
843 if (sysmap_base == (void *)-1) {
844 prom_printf("Claim failed for sysmap memory\n");
847 sysmap_size = file.fs->read(&file, 0xfffff, sysmap_base);
848 if (sysmap_size == 0)
851 ((char *)sysmap_base)[sysmap_size++] = 0;
853 file.fs->close(&file);
854 memset(&file, 0, sizeof(file));
857 prom_printf("System.map loaded at %p, size: %lu Kbytes\n",
858 sysmap_base, sysmap_size >> 10);
859 loadinfo.memsize += _ALIGN(0x100000, 0x1000);
861 prom_printf("System.map load failed !\n");
866 /* If ramdisk, load it. For now, we can't tell the size it will be
867 * so we claim an arbitrary amount of 4Mb
869 if (params.rd.file) {
870 if(strlen(boot.file) && !strcmp(boot.file,"\\\\") && params.rd.file[0] != '/'
871 && params.kernel.file[0] != '\\')
874 loc=(char*)malloc(strlen(params.rd.file)+3);
876 prom_printf ("Malloc error\n");
879 strcpy(loc,boot.file);
880 strcat(loc,params.rd.file);
881 free(params.rd.file);
884 prom_printf("Loading ramdisk...\n");
885 result = open_file(¶ms.rd, &file);
886 if (result != FILE_ERR_OK) {
887 prom_printf("%s:%d,", params.rd.dev, params.rd.part);
888 prom_perror(result, params.rd.file);
891 #define INITRD_CHUNKSIZE 0x400000
892 initrd_base = prom_claim(loadinfo.base+loadinfo.memsize, INITRD_CHUNKSIZE, 0);
893 if (initrd_base == (void *)-1) {
894 prom_printf("Claim failed for initrd memory\n");
897 initrd_size = file.fs->read(&file, INITRD_CHUNKSIZE, initrd_base);
898 if (initrd_size == 0)
900 initrd_read = initrd_size;
901 initrd_more = initrd_base;
902 while (initrd_read == INITRD_CHUNKSIZE ) { /* need to read more? */
903 initrd_want = (void *)((unsigned long)initrd_more+INITRD_CHUNKSIZE);
904 initrd_more = prom_claim(initrd_want, INITRD_CHUNKSIZE, 0);
905 if (initrd_more != initrd_want) {
906 prom_printf("Claim failed for initrd memory at %p rc=%p\n",initrd_want,initrd_more);
909 initrd_read = file.fs->read(&file, INITRD_CHUNKSIZE, initrd_more);
910 DEBUG_F(" block at %p rc=%lu\n",initrd_more,initrd_read);
911 initrd_size += initrd_read;
914 file.fs->close(&file);
915 memset(&file, 0, sizeof(file));
918 prom_printf("ramdisk loaded at %p, size: %lu Kbytes\n",
919 initrd_base, initrd_size >> 10);
921 prom_printf("ramdisk load failed !\n");
926 DEBUG_F("setting kernel args to: %s\n", params.args);
927 prom_setargs(params.args);
928 DEBUG_F("flushing icache...");
929 flush_icache_range ((long)loadinfo.base, (long)loadinfo.base+loadinfo.memsize);
933 * Fill mew boot infos
935 * The birec is low on memory, probably inside the malloc pool, so
936 * we don't write it earlier. At this point, we should not use anything
937 * coming from the malloc pool
939 birec = (struct bi_record *)_ALIGN(loadinfo.filesize+(1<<20)-1,(1<<20));
941 /* We make sure it's mapped. We map only 64k for now, it's plenty enough
942 * we don't claim since this precise memory range may already be claimed
945 prom_map (birec, birec, 0x10000);
946 DEBUG_F("birec at %p\n", birec);
949 birec->tag = BI_FIRST;
950 birec->size = sizeof(struct bi_record);
951 birec = (struct bi_record *)((unsigned long)birec + birec->size);
953 birec->tag = BI_BOOTLOADER_ID;
954 sprintf( (char *)birec->data, "yaboot");
955 birec->size = sizeof(struct bi_record) + strlen("yaboot") + 1;
956 birec = (struct bi_record *)((unsigned long)birec + birec->size);
958 birec->tag = BI_MACHTYPE;
959 birec->data[0] = _machine;
960 birec->size = sizeof(struct bi_record) + sizeof(unsigned long);
961 birec = (struct bi_record *)((unsigned long)birec + birec->size);
964 birec->tag = BI_SYSMAP;
965 birec->data[0] = (unsigned long)sysmap_base;
966 birec->data[1] = sysmap_size;
967 birec->size = sizeof(struct bi_record) + sizeof(unsigned long)*2;
968 birec = (struct bi_record *)((unsigned long)birec + birec->size);
970 birec->tag = BI_LAST;
971 birec->size = sizeof(struct bi_record);
972 birec = (struct bi_record *)((unsigned long)birec + birec->size);
974 /* compute the kernel's entry point. */
975 kernel_entry = loadinfo.base + loadinfo.entry - loadinfo.load_loc;
977 DEBUG_F("Kernel entry point = %p\n", kernel_entry);
978 DEBUG_F("kernel: arg1 = %p,\n"
983 initrd_base + loadinfo.load_loc, initrd_size, prom, 0, 0);
985 DEBUG_F("Entering kernel...\n");
987 /* call the kernel with our stack. */
988 kernel_entry(initrd_base + loadinfo.load_loc, initrd_size, prom, 0, 0);
996 load_elf32(struct boot_file_t *file, loadinfo_t *loadinfo)
999 Elf32_Ehdr *e = &(loadinfo->elf.elf32hdr);
1001 int size = sizeof(Elf32_Ehdr) - sizeof(Elf_Ident);
1002 unsigned long addr, loadaddr;
1004 /* Read the rest of the Elf header... */
1005 if ((*(file->fs->read))(file, size, &e->e_version) < size) {
1006 prom_printf("\nCan't read Elf32 image header\n");
1010 DEBUG_F("Elf32 header:\n");
1011 DEBUG_F(" e.e_type = %d\n", (int)e->e_type);
1012 DEBUG_F(" e.e_machine = %d\n", (int)e->e_machine);
1013 DEBUG_F(" e.e_version = %d\n", (int)e->e_version);
1014 DEBUG_F(" e.e_entry = 0x%08x\n", (int)e->e_entry);
1015 DEBUG_F(" e.e_phoff = 0x%08x\n", (int)e->e_phoff);
1016 DEBUG_F(" e.e_shoff = 0x%08x\n", (int)e->e_shoff);
1017 DEBUG_F(" e.e_flags = %d\n", (int)e->e_flags);
1018 DEBUG_F(" e.e_ehsize = 0x%08x\n", (int)e->e_ehsize);
1019 DEBUG_F(" e.e_phentsize = 0x%08x\n", (int)e->e_phentsize);
1020 DEBUG_F(" e.e_phnum = %d\n", (int)e->e_phnum);
1022 loadinfo->entry = e->e_entry;
1024 if (e->e_phnum > MAX_HEADERS) {
1025 prom_printf ("Can only load kernels with one program header\n");
1029 ph = (Elf32_Phdr *)malloc(sizeof(Elf32_Phdr) * e->e_phnum);
1031 prom_printf ("Malloc error\n");
1035 /* Now, we read the section header */
1036 if ((*(file->fs->seek))(file, e->e_phoff) != FILE_ERR_OK) {
1037 prom_printf ("seek error\n");
1040 if ((*(file->fs->read))(file, sizeof(Elf32_Phdr) * e->e_phnum, ph) !=
1041 sizeof(Elf32_Phdr) * e->e_phnum) {
1042 prom_printf ("read error\n");
1046 /* Scan through the program header
1047 * HACK: We must return the _memory size of the kernel image, not the
1048 * file size (because we have to leave room before other boot
1049 * infos. This code works as a side effect of the fact that
1050 * we have one section and vaddr == p_paddr
1052 loadinfo->memsize = loadinfo->filesize = loadinfo->offset = 0;
1054 for (i = 0; i < e->e_phnum; ++i, ++p) {
1055 if (p->p_type != PT_LOAD || p->p_offset == 0)
1057 if (loadinfo->memsize == 0) {
1058 loadinfo->offset = p->p_offset;
1059 loadinfo->memsize = p->p_memsz;
1060 loadinfo->filesize = p->p_filesz;
1061 loadinfo->load_loc = p->p_vaddr;
1063 loadinfo->memsize = p->p_offset + p->p_memsz - loadinfo->offset; /* XXX Bogus */
1064 loadinfo->filesize = p->p_offset + p->p_filesz - loadinfo->offset;
1068 if (loadinfo->memsize == 0) {
1069 prom_printf("Can't find a loadable segment !\n");
1073 /* leave some room (1Mb) for boot infos */
1074 loadinfo->memsize = _ALIGN(loadinfo->memsize,(1<<20)) + 0x100000;
1075 /* Claim OF memory */
1076 DEBUG_F("Before prom_claim, mem_sz: 0x%08lx\n", loadinfo->memsize);
1078 /* On some systems, loadaddr may already be claimed, so try some
1079 * other nearby addresses before giving up.
1081 loadaddr = (e->e_entry == KERNEL_LINK_ADDR_PPC32 ||
1082 e->e_entry == 0) ? KERNELADDR : e->e_entry;
1083 for(addr=loadaddr; addr <= loadaddr * 8 ;addr+=0x100000) {
1084 loadinfo->base = prom_claim((void *)addr, loadinfo->memsize, 0);
1085 if (loadinfo->base != (void *)-1) break;
1087 if (loadinfo->base == (void *)-1) {
1088 prom_printf("Claim error, can't allocate kernel memory\n");
1092 DEBUG_F("After ELF parsing, load base: %p, mem_sz: 0x%08lx\n",
1093 loadinfo->base, loadinfo->memsize);
1094 DEBUG_F(" wanted load base: 0x%08lx, mem_sz: 0x%08lx\n",
1095 loadaddr, loadinfo->memsize);
1097 /* Load the program segments... */
1099 for (i = 0; i < e->e_phnum; ++i, ++p) {
1100 unsigned long offset;
1101 if (p->p_type != PT_LOAD || p->p_offset == 0)
1104 /* Now, we skip to the image itself */
1105 if ((*(file->fs->seek))(file, p->p_offset) != FILE_ERR_OK) {
1106 prom_printf ("Seek error\n");
1107 prom_release(loadinfo->base, loadinfo->memsize);
1110 offset = p->p_vaddr - loadinfo->load_loc;
1111 if ((*(file->fs->read))(file, p->p_filesz, loadinfo->base+offset) != p->p_filesz) {
1112 prom_printf ("Read failed\n");
1113 prom_release(loadinfo->base, loadinfo->memsize);
1120 /* Return success at loading the Elf32 kernel */
1125 load_elf64(struct boot_file_t *file, loadinfo_t *loadinfo)
1128 Elf64_Ehdr *e = &(loadinfo->elf.elf64hdr);
1130 int size = sizeof(Elf64_Ehdr) - sizeof(Elf_Ident);
1131 unsigned long addr, loadaddr;
1133 /* Read the rest of the Elf header... */
1134 if ((*(file->fs->read))(file, size, &e->e_version) < size) {
1135 prom_printf("\nCan't read Elf64 image header\n");
1139 DEBUG_F("Elf64 header:\n");
1140 DEBUG_F(" e.e_type = %d\n", (int)e->e_type);
1141 DEBUG_F(" e.e_machine = %d\n", (int)e->e_machine);
1142 DEBUG_F(" e.e_version = %d\n", (int)e->e_version);
1143 DEBUG_F(" e.e_entry = 0x%016lx\n", (long)e->e_entry);
1144 DEBUG_F(" e.e_phoff = 0x%016lx\n", (long)e->e_phoff);
1145 DEBUG_F(" e.e_shoff = 0x%016lx\n", (long)e->e_shoff);
1146 DEBUG_F(" e.e_flags = %d\n", (int)e->e_flags);
1147 DEBUG_F(" e.e_ehsize = 0x%08x\n", (int)e->e_ehsize);
1148 DEBUG_F(" e.e_phentsize = 0x%08x\n", (int)e->e_phentsize);
1149 DEBUG_F(" e.e_phnum = %d\n", (int)e->e_phnum);
1151 loadinfo->entry = e->e_entry;
1153 if (e->e_phnum > MAX_HEADERS) {
1154 prom_printf ("Can only load kernels with one program header\n");
1158 ph = (Elf64_Phdr *)malloc(sizeof(Elf64_Phdr) * e->e_phnum);
1160 prom_printf ("Malloc error\n");
1164 /* Now, we read the section header */
1165 if ((*(file->fs->seek))(file, e->e_phoff) != FILE_ERR_OK) {
1166 prom_printf ("Seek error\n");
1169 if ((*(file->fs->read))(file, sizeof(Elf64_Phdr) * e->e_phnum, ph) !=
1170 sizeof(Elf64_Phdr) * e->e_phnum) {
1171 prom_printf ("Read error\n");
1175 /* Scan through the program header
1176 * HACK: We must return the _memory size of the kernel image, not the
1177 * file size (because we have to leave room before other boot
1178 * infos. This code works as a side effect of the fact that
1179 * we have one section and vaddr == p_paddr
1181 loadinfo->memsize = loadinfo->filesize = loadinfo->offset = 0;
1183 for (i = 0; i < e->e_phnum; ++i, ++p) {
1184 if (p->p_type != PT_LOAD || p->p_offset == 0)
1186 if (loadinfo->memsize == 0) {
1187 loadinfo->offset = p->p_offset;
1188 loadinfo->memsize = p->p_memsz;
1189 loadinfo->filesize = p->p_filesz;
1190 loadinfo->load_loc = p->p_vaddr;
1192 loadinfo->memsize = p->p_offset + p->p_memsz - loadinfo->offset; /* XXX Bogus */
1193 loadinfo->filesize = p->p_offset + p->p_filesz - loadinfo->offset;
1197 if (loadinfo->memsize == 0) {
1198 prom_printf("Can't find a loadable segment !\n");
1202 /* leave some room (1Mb) for boot infos */
1203 loadinfo->memsize = _ALIGN(loadinfo->memsize,(1<<20)) + 0x100000;
1204 /* Claim OF memory */
1205 DEBUG_F("Before prom_claim, mem_sz: 0x%08lx\n", loadinfo->memsize);
1207 /* On some systems, loadaddr may already be claimed, so try some
1208 * other nearby addresses before giving up.
1210 loadaddr = (e->e_entry == KERNEL_LINK_ADDR_PPC64) ? KERNELADDR : e->e_entry;
1211 for(addr=loadaddr; addr <= loadaddr * 8 ;addr+=0x100000) {
1212 loadinfo->base = prom_claim((void *)addr, loadinfo->memsize, 0);
1213 if (loadinfo->base != (void *)-1) break;
1215 if (loadinfo->base == (void *)-1) {
1216 prom_printf("Claim error, can't allocate kernel memory\n");
1220 DEBUG_F("After ELF parsing, load base: %p, mem_sz: 0x%08lx\n",
1221 loadinfo->base, loadinfo->memsize);
1222 DEBUG_F(" wanted load base: 0x%08lx, mem_sz: 0x%08lx\n",
1223 loadaddr, loadinfo->memsize);
1225 /* Load the program segments... */
1227 for (i = 0; i < e->e_phnum; ++i, ++p) {
1228 unsigned long offset;
1229 if (p->p_type != PT_LOAD || p->p_offset == 0)
1232 /* Now, we skip to the image itself */
1233 if ((*(file->fs->seek))(file, p->p_offset) != FILE_ERR_OK) {
1234 prom_printf ("Seek error\n");
1235 prom_release(loadinfo->base, loadinfo->memsize);
1238 offset = p->p_vaddr - loadinfo->load_loc;
1239 if ((*(file->fs->read))(file, p->p_filesz, loadinfo->base+offset) != p->p_filesz) {
1240 prom_printf ("Read failed\n");
1241 prom_release(loadinfo->base, loadinfo->memsize);
1248 /* Return success at loading the Elf64 kernel */
1253 is_elf32(loadinfo_t *loadinfo)
1255 Elf32_Ehdr *e = &(loadinfo->elf.elf32hdr);
1257 return (e->e_ident[EI_MAG0] == ELFMAG0 &&
1258 e->e_ident[EI_MAG1] == ELFMAG1 &&
1259 e->e_ident[EI_MAG2] == ELFMAG2 &&
1260 e->e_ident[EI_MAG3] == ELFMAG3 &&
1261 e->e_ident[EI_CLASS] == ELFCLASS32 &&
1262 e->e_ident[EI_DATA] == ELFDATA2MSB &&
1263 e->e_type == ET_EXEC &&
1264 e->e_machine == EM_PPC);
1268 is_elf64(loadinfo_t *loadinfo)
1270 Elf64_Ehdr *e = &(loadinfo->elf.elf64hdr);
1272 return (e->e_ident[EI_MAG0] == ELFMAG0 &&
1273 e->e_ident[EI_MAG1] == ELFMAG1 &&
1274 e->e_ident[EI_MAG2] == ELFMAG2 &&
1275 e->e_ident[EI_MAG3] == ELFMAG3 &&
1276 e->e_ident[EI_CLASS] == ELFCLASS64 &&
1277 e->e_ident[EI_DATA] == ELFDATA2MSB &&
1278 e->e_type == ET_EXEC &&
1279 e->e_machine == EM_PPC64);
1285 #ifdef CONFIG_SET_COLORMAP
1286 static unsigned char default_colors[] = {
1305 prom_handle scrn = PROM_INVALID_HANDLE;
1307 /* Try Apple's mac-boot screen ihandle */
1308 result = (int)call_prom_return("interpret", 1, 2,
1309 "\" _screen-ihandle\" $find if execute else 0 then", &scrn);
1310 DEBUG_F("Trying to get screen ihandle, result: %d, scrn: %p\n", result, scrn);
1312 if (scrn == 0 || scrn == PROM_INVALID_HANDLE) {
1314 /* Hrm... check to see if stdout is a display */
1315 scrn = call_prom ("instance-to-package", 1, 1, prom_stdout);
1316 DEBUG_F("instance-to-package of stdout is: %p\n", scrn);
1317 if (prom_getprop(scrn, "device_type", type, 32) > 0 && !strncmp(type, "display", 7)) {
1318 DEBUG_F("got it ! stdout is a screen\n");
1321 /* Else, we try to open the package */
1322 scrn = (prom_handle)call_prom( "open", 1, 1, "screen" );
1323 DEBUG_F("Open screen result: %p\n", scrn);
1327 if (scrn == PROM_INVALID_HANDLE) {
1328 prom_printf("No screen device found !/n");
1332 prom_set_color(scrn, i, default_colors[i*3],
1333 default_colors[i*3+1], default_colors[i*3+2]);
1335 prom_printf("\x1b[1;37m\x1b[2;40m");
1337 for (i=0;i<16; i++) {
1338 prom_printf("\x1b[%d;%dm\x1b[1;47m%s \x1b[2;40m %s\n",
1339 ansi_color_table[i].index,
1340 ansi_color_table[i].value,
1341 ansi_color_table[i].name,
1342 ansi_color_table[i].name);
1343 prom_printf("\x1b[%d;%dm\x1b[1;37m%s \x1b[2;30m %s\n",
1344 ansi_color_table[i].index,
1345 ansi_color_table[i].value+10,
1346 ansi_color_table[i].name,
1347 ansi_color_table[i].name);
1349 prom_printf("\x1b[1;37m\x1b[2;40m");
1350 #endif /* COLOR_TEST */
1356 #endif /* CONFIG_SET_COLORMAP */
1362 if (_machine == _MACH_Pmac)
1365 prom_get_chosen("bootpath", bootdevice, sizeof(bootdevice));
1366 DEBUG_F("/chosen/bootpath = %s\n", bootdevice);
1367 if (bootdevice[0] == 0)
1368 prom_get_options("boot-device", bootdevice, sizeof(bootdevice));
1369 if (bootdevice[0] == 0) {
1370 prom_printf("Couldn't determine boot device\n");
1374 if (!parse_device_path(bootdevice, (_machine == _MACH_Pmac) ? "hd" : "disc",
1376 prom_printf("%s: Unable to parse\n", bootdevice);
1379 DEBUG_F("After parse_device_path: dev=%s, part=%d, file=%s\n",
1380 boot.dev, boot.part, boot.file);
1382 if (strlen(boot.file)) {
1383 if (!strncmp(boot.file, "\\\\", 2))
1387 p = last = boot.file;
1397 if (strlen(boot.file))
1398 strcat(boot.file, "\\");
1401 DEBUG_F("After path fixup: dev=%s, part=%d, file=%s\n",
1402 boot.dev, boot.part, boot.file);
1404 useconf = load_config_file(boot.dev, boot.file, boot.part);
1406 prom_printf("Welcome to yaboot version " VERSION "\n");
1407 prom_printf("Enter \"help\" to get some basic usage information\n");
1411 prom_printf("Bye.\n");
1416 * c-file-style: "K&R"