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("%s:%d", fspec.dev, fspec.part);
295 prom_perror(result, fspec.file);
296 prom_printf("Can't open config file\n");
302 sz = file.fs->read(&file, CONFIG_FILE_MAX, conf_file);
304 prom_printf("Error, can't read config file\n");
307 prom_printf("Config file read, %d bytes\n", sz);
311 file.fs->close(&file);
314 /* Call the parsing code in cfg.c */
315 if (cfg_parse(conf_path, conf_file, sz) < 0) {
316 prom_printf ("Syntax error or read error config\n");
320 DEBUG_F("Config file successfully parsed, %d bytes\n", sz);
322 /* Now, we do the initialisations stored in the config file */
323 p = cfg_get_strg(0, "init-code");
327 password = cfg_get_strg(0, "password");
329 #ifdef CONFIG_COLOR_TEXT
330 p = cfg_get_strg(0, "fgcolor");
332 DEBUG_F("fgcolor=%s\n", p);
333 fgcolor = check_color_text_ui(p);
335 prom_printf("Invalid fgcolor: \"%s\".\n", p);
338 p = cfg_get_strg(0, "bgcolor");
340 DEBUG_F("bgcolor=%s\n", p);
341 bgcolor = check_color_text_ui(p);
343 prom_printf("Invalid bgcolor: \"%s\".\n", p);
347 sprintf(temp, "%x to background-color", bgcolor);
348 prom_interpret(temp);
355 sprintf(temp, "%x to foreground-color", fgcolor);
356 prom_interpret(temp);
358 #endif /* CONFIG_COLOR_TEXT */
360 p = cfg_get_strg(0, "init-message");
362 prom_printf("%s\n", p);
364 p = cfg_get_strg(0, "message");
366 print_message_file(p);
374 file.fs->close(&file);
376 if (result != 1 && conf_file)
382 void maintabfunc (void)
386 prom_printf("boot: %s", cbuff);
391 word_split(char **linep, char **paramsp)
406 while (*p != 0 && *p != ' ')
415 make_params(char *label, char *params)
418 static char buffer[2048];
423 p = cfg_get_strg(label, "literal");
435 p = cfg_get_strg(label, "root");
442 if (cfg_get_flag(label, "read-only")) {
446 if (cfg_get_flag(label, "read-write")) {
450 p = cfg_get_strg(label, "ramdisk");
452 strcpy (q, "ramdisk=");
457 p = cfg_get_strg(label, "initrd-size");
459 strcpy (q, "ramdisk_size=");
464 if (cfg_get_flag(label, "novideo")) {
465 strcpy (q, "video=ofonly");
469 p = cfg_get_strg (label, "append");
476 pause_after = cfg_get_flag (label, "pause-after");
477 p = cfg_get_strg(label, "pause-message");
486 void check_password(char *str)
490 for (i = 0; i < 3; i++) {
491 prom_printf ("\n%sassword: ", str);
493 cmdedit ((void (*)(void)) 0, 1);
495 #ifdef USE_MD5_PASSWORDS
496 if (!strncmp (password, "$1$", 3)) {
497 if (!check_md5_password(passwdbuff, password))
500 else if (!strcmp (password, passwdbuff))
503 if (!strcmp (password, passwdbuff))
505 #endif /* USE_MD5_PASSWORDS */
507 prom_printf ("Password incorrect. Please try again...");
509 prom_printf ("Seems like you don't know the access password. Go away!\n");
511 prom_interpret("reset-all");
514 int get_params(struct boot_param_t* params)
520 char *imagename = 0, *label;
525 static int first = 1;
526 static char bootargs[1024];
527 static char imagepath[1024];
528 static char initrdpath[1024];
529 static char sysmappath[1024];
532 memset(params, 0, sizeof(*params));
534 params->kernel.part = -1;
535 params->rd.part = -1;
536 params->sysmap.part = -1;
543 prom_get_chosen("bootargs", bootargs, sizeof(bootargs));
544 imagename = bootargs;
545 word_split(&imagename, ¶ms->args);
546 timeout = DEFAULT_TIMEOUT;
548 prom_printf("Default supplied on the command line: %s ", imagename);
550 prom_printf("%s", params->args);
553 if (useconf && (q = cfg_get_strg(0, "timeout")) != 0 && *q != 0)
554 timeout = simple_strtol(q, NULL, 0);
557 prom_printf("boot: ");
562 end = beg + 100 * timeout;
564 c = prom_nbgetchar();
565 } while (c == -1 && prom_getms() <= end);
569 else if (c != '\n' && c != '\t' && c != '\r' && c != '\b' ) {
575 if (c != -1 && c != '\n' && c != '\r') {
578 } else if (c >= ' ') {
581 if ((cfg_get_flag (cbuff, "single-key")) && useconf) {
584 prom_printf("%s\n", cbuff);
589 if (c == '\n' || c == '\r') {
591 imagename = cfg_get_default();
593 prom_printf("%s", imagename);
595 prom_printf(" %s", params->args);
597 } else if (!singlekey) {
598 cmdedit(maintabfunc, 0);
600 strcpy(given_bootargs, cbuff);
601 given_bootargs_by_user = 1;
603 word_split(&imagename, ¶ms->args);
606 /* chrp gets this wrong, force it -- Cort */
607 if ( useconf && (!imagename || imagename[0] == 0 ))
608 imagename = cfg_get_default();
611 defdevice = boot.dev;
614 defdevice = cfg_get_strg(0, "device");
615 p = cfg_get_strg(0, "partition");
617 n = simple_strtol(p, &endp, 10);
618 if (endp != p && *endp == 0)
621 p = cfg_get_strg(0, "pause-message");
624 if (cfg_get_flag(0, "restricted"))
626 p = cfg_get_strg(imagename, "image");
630 defdevice = cfg_get_strg(label, "device");
631 if(!defdevice) defdevice=boot.dev;
632 p = cfg_get_strg(label, "partition");
634 n = simple_strtol(p, &endp, 10);
635 if (endp != p && *endp == 0)
638 if (cfg_get_flag(label, "restricted"))
641 if (params->args && password && restricted)
642 check_password ("To specify image arguments you must enter the p");
643 else if (password && !restricted)
644 check_password ("P");
646 params->args = make_params(label, params->args);
650 if (!strcmp (imagename, "help")) {
652 "\nPress the tab key for a list of defined images.\n"
653 "The label marked with a \"*\" is is the default image, "
654 "press <return> to boot it.\n\n"
655 "To boot any other label simply type its name and press <return>.\n\n"
656 "To boot a kernel image which is not defined in the yaboot configuration \n"
657 "file, enter the kernel image name as [device:][partno],/path, where \n"
658 "\"device:\" is the OpenFirmware device path to the disk the image \n"
659 "resides on, and \"partno\" is the partition number the image resides on.\n\n"
660 "If you omit \"device:\" and \"partno\" yaboot will use the values of \n"
661 "\"device=\" and \"partition=\" in yaboot.conf, right now those are set to: \n"
663 "partition=%d\n\n", defdevice, defpart);
667 if (!strcmp (imagename, "halt")) {
669 check_password ("P");
673 if (!strcmp (imagename, "bye")) {
675 check_password ("P");
681 if (imagename[0] == '$') {
682 /* forth command string */
684 check_password ("P");
685 prom_interpret(imagename+1);
689 strncpy(imagepath, imagename, 1024);
691 if (!label && password)
692 check_password ("To boot a custom image you must enter the p");
694 if (!parse_device_path(imagepath, defdevice, defpart,
695 "/vmlinux", ¶ms->kernel)) {
696 prom_printf("%s: Unable to parse\n", imagepath);
699 DEBUG_F("after parse_device_path: dev=%s part=%d file=%s\n", params->kernel.dev,
700 params->kernel.part, params->kernel.file);
703 p = cfg_get_strg(label, "initrd");
705 DEBUG_F("Parsing initrd path <%s>\n", p);
706 strncpy(initrdpath, p, 1024);
707 if (!parse_device_path(initrdpath, defdevice, defpart,
708 "/root.bin", ¶ms->rd)) {
709 prom_printf("%s: Unable to parse\n", imagepath);
713 p = cfg_get_strg(label, "sysmap");
715 DEBUG_F("Parsing sysmap path <%s>\n", p);
716 strncpy(sysmappath, p, 1024);
717 if (!parse_device_path(sysmappath, defdevice, defpart,
718 "/boot/System.map", ¶ms->sysmap)) {
719 prom_printf("%s: Unable to parse\n", imagepath);
727 /* This is derived from quik core. To be changed to first parse the headers
728 * doing lazy-loading, and then claim the memory before loading the kernel
730 * We also need to add initrd support to this whole mecanism
735 #define MAX_HEADERS 32
737 struct boot_file_t file;
739 static struct boot_param_t params;
741 unsigned long initrd_size;
743 unsigned long sysmap_size;
744 kernel_entry_t kernel_entry;
745 struct bi_record* birec;
748 void *initrd_more,*initrd_want;
749 unsigned long initrd_read;
751 loadinfo.load_loc = 0;
759 if (get_params(¶ms))
761 if (!params.kernel.file)
764 prom_printf("Please wait, loading kernel...\n");
766 memset(&file, 0, sizeof(file));
768 if (strlen(boot.file) && !strcmp(boot.file,"\\\\") && params.kernel.file[0] != '/'
769 && params.kernel.file[0] != '\\') {
770 loc=(char*)malloc(strlen(params.kernel.file)+3);
772 prom_printf ("malloc error\n");
775 strcpy(loc,boot.file);
776 strcat(loc,params.kernel.file);
777 free(params.kernel.file);
778 params.kernel.file=loc;
780 result = open_file(¶ms.kernel, &file);
781 if (result != FILE_ERR_OK) {
782 prom_printf("%s:%d,", params.kernel.dev, params.kernel.part);
783 prom_perror(result, params.kernel.file);
787 /* Read the Elf e_ident, e_type and e_machine fields to
788 * determine Elf file type
790 if (file.fs->read(&file, sizeof(Elf_Ident), &loadinfo.elf) < sizeof(Elf_Ident)) {
791 prom_printf("\nCan't read Elf e_ident/e_type/e_machine info\n");
792 file.fs->close(&file);
793 memset(&file, 0, sizeof(file));
797 if (is_elf32(&loadinfo)) {
798 if (!load_elf32(&file, &loadinfo)) {
799 file.fs->close(&file);
800 memset(&file, 0, sizeof(file));
803 prom_printf(" Elf32 kernel loaded...\n");
804 } else if (is_elf64(&loadinfo)) {
805 if (!load_elf64(&file, &loadinfo)) {
806 file.fs->close(&file);
807 memset(&file, 0, sizeof(file));
810 prom_printf(" Elf64 kernel loaded...\n");
812 prom_printf ("%s: Not a valid ELF image\n", params.kernel.file);
813 file.fs->close(&file);
814 memset(&file, 0, sizeof(file));
817 file.fs->close(&file);
818 memset(&file, 0, sizeof(file));
820 /* If sysmap, load it.
822 if (params.sysmap.file) {
823 prom_printf("Loading System.map ...\n");
824 if(strlen(boot.file) && !strcmp(boot.file,"\\\\") && params.sysmap.file[0] != '/'
825 && params.sysmap.file[0] != '\\') {
827 loc=(char*)malloc(strlen(params.sysmap.file)+3);
829 prom_printf ("malloc error\n");
832 strcpy(loc,boot.file);
833 strcat(loc,params.sysmap.file);
834 free(params.sysmap.file);
835 params.sysmap.file=loc;
838 result = open_file(¶ms.sysmap, &file);
839 if (result != FILE_ERR_OK) {
840 prom_printf("%s:%d,", params.sysmap.dev, params.sysmap.part);
841 prom_perror(result, params.sysmap.file);
844 sysmap_base = prom_claim(loadinfo.base+loadinfo.memsize, 0x100000, 0);
845 if (sysmap_base == (void *)-1) {
846 prom_printf("Claim failed for sysmap memory\n");
849 sysmap_size = file.fs->read(&file, 0xfffff, sysmap_base);
850 if (sysmap_size == 0)
853 ((char *)sysmap_base)[sysmap_size++] = 0;
855 file.fs->close(&file);
856 memset(&file, 0, sizeof(file));
859 prom_printf("System.map loaded at %p, size: %lu Kbytes\n",
860 sysmap_base, sysmap_size >> 10);
861 loadinfo.memsize += _ALIGN(0x100000, 0x1000);
863 prom_printf("System.map load failed !\n");
868 /* If ramdisk, load it. For now, we can't tell the size it will be
869 * so we claim an arbitrary amount of 4Mb
871 if (params.rd.file) {
872 if(strlen(boot.file) && !strcmp(boot.file,"\\\\") && params.rd.file[0] != '/'
873 && params.kernel.file[0] != '\\')
876 loc=(char*)malloc(strlen(params.rd.file)+3);
878 prom_printf ("Malloc error\n");
881 strcpy(loc,boot.file);
882 strcat(loc,params.rd.file);
883 free(params.rd.file);
886 prom_printf("Loading ramdisk...\n");
887 result = open_file(¶ms.rd, &file);
888 if (result != FILE_ERR_OK) {
889 prom_printf("%s:%d,", params.rd.dev, params.rd.part);
890 prom_perror(result, params.rd.file);
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 %p rc=%p\n",initrd_want,initrd_more);
911 initrd_read = file.fs->read(&file, INITRD_CHUNKSIZE, initrd_more);
912 DEBUG_F(" block at %p rc=%lu\n",initrd_more,initrd_read);
913 initrd_size += initrd_read;
916 file.fs->close(&file);
917 memset(&file, 0, sizeof(file));
920 prom_printf("ramdisk loaded at %p, size: %lu Kbytes\n",
921 initrd_base, initrd_size >> 10);
923 prom_printf("ramdisk load failed !\n");
928 DEBUG_F("setting kernel args to: %s\n", params.args);
929 prom_setargs(params.args);
930 DEBUG_F("flushing icache...");
931 flush_icache_range ((long)loadinfo.base, (long)loadinfo.base+loadinfo.memsize);
935 * Fill mew boot infos
937 * The birec is low on memory, probably inside the malloc pool, so
938 * we don't write it earlier. At this point, we should not use anything
939 * coming from the malloc pool
941 birec = (struct bi_record *)_ALIGN(loadinfo.filesize+(1<<20)-1,(1<<20));
943 /* We make sure it's mapped. We map only 64k for now, it's plenty enough
944 * we don't claim since this precise memory range may already be claimed
947 prom_map (birec, birec, 0x10000);
948 DEBUG_F("birec at %p\n", birec);
951 birec->tag = BI_FIRST;
952 birec->size = sizeof(struct bi_record);
953 birec = (struct bi_record *)((unsigned long)birec + birec->size);
955 birec->tag = BI_BOOTLOADER_ID;
956 sprintf( (char *)birec->data, "yaboot");
957 birec->size = sizeof(struct bi_record) + strlen("yaboot") + 1;
958 birec = (struct bi_record *)((unsigned long)birec + birec->size);
960 birec->tag = BI_MACHTYPE;
961 birec->data[0] = _machine;
962 birec->size = sizeof(struct bi_record) + sizeof(unsigned long);
963 birec = (struct bi_record *)((unsigned long)birec + birec->size);
966 birec->tag = BI_SYSMAP;
967 birec->data[0] = (unsigned long)sysmap_base;
968 birec->data[1] = sysmap_size;
969 birec->size = sizeof(struct bi_record) + sizeof(unsigned long)*2;
970 birec = (struct bi_record *)((unsigned long)birec + birec->size);
972 birec->tag = BI_LAST;
973 birec->size = sizeof(struct bi_record);
974 birec = (struct bi_record *)((unsigned long)birec + birec->size);
976 /* compute the kernel's entry point. */
977 kernel_entry = loadinfo.base + loadinfo.entry - loadinfo.load_loc;
979 DEBUG_F("Kernel entry point = %p\n", kernel_entry);
980 DEBUG_F("kernel: arg1 = %p,\n"
985 initrd_base + loadinfo.load_loc, initrd_size, prom, 0, 0);
987 DEBUG_F("Entering kernel...\n");
989 /* call the kernel with our stack. */
990 kernel_entry(initrd_base + loadinfo.load_loc, initrd_size, prom, 0, 0);
998 load_elf32(struct boot_file_t *file, loadinfo_t *loadinfo)
1001 Elf32_Ehdr *e = &(loadinfo->elf.elf32hdr);
1003 int size = sizeof(Elf32_Ehdr) - sizeof(Elf_Ident);
1004 unsigned long addr, loadaddr;
1006 /* Read the rest of the Elf header... */
1007 if ((*(file->fs->read))(file, size, &e->e_version) < size) {
1008 prom_printf("\nCan't read Elf32 image header\n");
1012 DEBUG_F("Elf32 header:\n");
1013 DEBUG_F(" e.e_type = %d\n", (int)e->e_type);
1014 DEBUG_F(" e.e_machine = %d\n", (int)e->e_machine);
1015 DEBUG_F(" e.e_version = %d\n", (int)e->e_version);
1016 DEBUG_F(" e.e_entry = 0x%08x\n", (int)e->e_entry);
1017 DEBUG_F(" e.e_phoff = 0x%08x\n", (int)e->e_phoff);
1018 DEBUG_F(" e.e_shoff = 0x%08x\n", (int)e->e_shoff);
1019 DEBUG_F(" e.e_flags = %d\n", (int)e->e_flags);
1020 DEBUG_F(" e.e_ehsize = 0x%08x\n", (int)e->e_ehsize);
1021 DEBUG_F(" e.e_phentsize = 0x%08x\n", (int)e->e_phentsize);
1022 DEBUG_F(" e.e_phnum = %d\n", (int)e->e_phnum);
1024 loadinfo->entry = e->e_entry;
1026 if (e->e_phnum > MAX_HEADERS) {
1027 prom_printf ("Can only load kernels with one program header\n");
1031 ph = (Elf32_Phdr *)malloc(sizeof(Elf32_Phdr) * e->e_phnum);
1033 prom_printf ("Malloc error\n");
1037 /* Now, we read the section header */
1038 if ((*(file->fs->seek))(file, e->e_phoff) != FILE_ERR_OK) {
1039 prom_printf ("seek error\n");
1042 if ((*(file->fs->read))(file, sizeof(Elf32_Phdr) * e->e_phnum, ph) !=
1043 sizeof(Elf32_Phdr) * e->e_phnum) {
1044 prom_printf ("read error\n");
1048 /* Scan through the program header
1049 * HACK: We must return the _memory size of the kernel image, not the
1050 * file size (because we have to leave room before other boot
1051 * infos. This code works as a side effect of the fact that
1052 * we have one section and vaddr == p_paddr
1054 loadinfo->memsize = loadinfo->filesize = loadinfo->offset = 0;
1056 for (i = 0; i < e->e_phnum; ++i, ++p) {
1057 if (p->p_type != PT_LOAD || p->p_offset == 0)
1059 if (loadinfo->memsize == 0) {
1060 loadinfo->offset = p->p_offset;
1061 loadinfo->memsize = p->p_memsz;
1062 loadinfo->filesize = p->p_filesz;
1063 loadinfo->load_loc = p->p_vaddr;
1065 loadinfo->memsize = p->p_offset + p->p_memsz - loadinfo->offset; /* XXX Bogus */
1066 loadinfo->filesize = p->p_offset + p->p_filesz - loadinfo->offset;
1070 if (loadinfo->memsize == 0) {
1071 prom_printf("Can't find a loadable segment !\n");
1075 /* leave some room (1Mb) for boot infos */
1076 loadinfo->memsize = _ALIGN(loadinfo->memsize,(1<<20)) + 0x100000;
1077 /* Claim OF memory */
1078 DEBUG_F("Before prom_claim, mem_sz: 0x%08lx\n", loadinfo->memsize);
1080 /* On some systems, loadaddr may already be claimed, so try some
1081 * other nearby addresses before giving up.
1083 loadaddr = (e->e_entry == KERNEL_LINK_ADDR_PPC32 ||
1084 e->e_entry == 0) ? KERNELADDR : e->e_entry;
1085 for(addr=loadaddr; addr <= loadaddr * 8 ;addr+=0x100000) {
1086 loadinfo->base = prom_claim((void *)addr, loadinfo->memsize, 0);
1087 if (loadinfo->base != (void *)-1) break;
1089 if (loadinfo->base == (void *)-1) {
1090 prom_printf("Claim error, can't allocate kernel memory\n");
1094 DEBUG_F("After ELF parsing, load base: %p, mem_sz: 0x%08lx\n",
1095 loadinfo->base, loadinfo->memsize);
1096 DEBUG_F(" wanted load base: 0x%08lx, mem_sz: 0x%08lx\n",
1097 loadaddr, loadinfo->memsize);
1099 /* Load the program segments... */
1101 for (i = 0; i < e->e_phnum; ++i, ++p) {
1102 unsigned long offset;
1103 if (p->p_type != PT_LOAD || p->p_offset == 0)
1106 /* Now, we skip to the image itself */
1107 if ((*(file->fs->seek))(file, p->p_offset) != FILE_ERR_OK) {
1108 prom_printf ("Seek error\n");
1109 prom_release(loadinfo->base, loadinfo->memsize);
1112 offset = p->p_vaddr - loadinfo->load_loc;
1113 if ((*(file->fs->read))(file, p->p_filesz, loadinfo->base+offset) != p->p_filesz) {
1114 prom_printf ("Read failed\n");
1115 prom_release(loadinfo->base, loadinfo->memsize);
1122 /* Return success at loading the Elf32 kernel */
1127 load_elf64(struct boot_file_t *file, loadinfo_t *loadinfo)
1130 Elf64_Ehdr *e = &(loadinfo->elf.elf64hdr);
1132 int size = sizeof(Elf64_Ehdr) - sizeof(Elf_Ident);
1133 unsigned long addr, loadaddr;
1135 /* Read the rest of the Elf header... */
1136 if ((*(file->fs->read))(file, size, &e->e_version) < size) {
1137 prom_printf("\nCan't read Elf64 image header\n");
1141 DEBUG_F("Elf64 header:\n");
1142 DEBUG_F(" e.e_type = %d\n", (int)e->e_type);
1143 DEBUG_F(" e.e_machine = %d\n", (int)e->e_machine);
1144 DEBUG_F(" e.e_version = %d\n", (int)e->e_version);
1145 DEBUG_F(" e.e_entry = 0x%016lx\n", (long)e->e_entry);
1146 DEBUG_F(" e.e_phoff = 0x%016lx\n", (long)e->e_phoff);
1147 DEBUG_F(" e.e_shoff = 0x%016lx\n", (long)e->e_shoff);
1148 DEBUG_F(" e.e_flags = %d\n", (int)e->e_flags);
1149 DEBUG_F(" e.e_ehsize = 0x%08x\n", (int)e->e_ehsize);
1150 DEBUG_F(" e.e_phentsize = 0x%08x\n", (int)e->e_phentsize);
1151 DEBUG_F(" e.e_phnum = %d\n", (int)e->e_phnum);
1153 loadinfo->entry = e->e_entry;
1155 if (e->e_phnum > MAX_HEADERS) {
1156 prom_printf ("Can only load kernels with one program header\n");
1160 ph = (Elf64_Phdr *)malloc(sizeof(Elf64_Phdr) * e->e_phnum);
1162 prom_printf ("Malloc error\n");
1166 /* Now, we read the section header */
1167 if ((*(file->fs->seek))(file, e->e_phoff) != FILE_ERR_OK) {
1168 prom_printf ("Seek error\n");
1171 if ((*(file->fs->read))(file, sizeof(Elf64_Phdr) * e->e_phnum, ph) !=
1172 sizeof(Elf64_Phdr) * e->e_phnum) {
1173 prom_printf ("Read error\n");
1177 /* Scan through the program header
1178 * HACK: We must return the _memory size of the kernel image, not the
1179 * file size (because we have to leave room before other boot
1180 * infos. This code works as a side effect of the fact that
1181 * we have one section and vaddr == p_paddr
1183 loadinfo->memsize = loadinfo->filesize = loadinfo->offset = 0;
1185 for (i = 0; i < e->e_phnum; ++i, ++p) {
1186 if (p->p_type != PT_LOAD || p->p_offset == 0)
1188 if (loadinfo->memsize == 0) {
1189 loadinfo->offset = p->p_offset;
1190 loadinfo->memsize = p->p_memsz;
1191 loadinfo->filesize = p->p_filesz;
1192 loadinfo->load_loc = p->p_vaddr;
1194 loadinfo->memsize = p->p_offset + p->p_memsz - loadinfo->offset; /* XXX Bogus */
1195 loadinfo->filesize = p->p_offset + p->p_filesz - loadinfo->offset;
1199 if (loadinfo->memsize == 0) {
1200 prom_printf("Can't find a loadable segment !\n");
1204 /* leave some room (1Mb) for boot infos */
1205 loadinfo->memsize = _ALIGN(loadinfo->memsize,(1<<20)) + 0x100000;
1206 /* Claim OF memory */
1207 DEBUG_F("Before prom_claim, mem_sz: 0x%08lx\n", loadinfo->memsize);
1209 /* On some systems, loadaddr may already be claimed, so try some
1210 * other nearby addresses before giving up.
1212 loadaddr = (e->e_entry == KERNEL_LINK_ADDR_PPC64) ? KERNELADDR : e->e_entry;
1213 for(addr=loadaddr; addr <= loadaddr * 8 ;addr+=0x100000) {
1214 loadinfo->base = prom_claim((void *)addr, loadinfo->memsize, 0);
1215 if (loadinfo->base != (void *)-1) break;
1217 if (loadinfo->base == (void *)-1) {
1218 prom_printf("Claim error, can't allocate kernel memory\n");
1222 DEBUG_F("After ELF parsing, load base: %p, mem_sz: 0x%08lx\n",
1223 loadinfo->base, loadinfo->memsize);
1224 DEBUG_F(" wanted load base: 0x%08lx, mem_sz: 0x%08lx\n",
1225 loadaddr, loadinfo->memsize);
1227 /* Load the program segments... */
1229 for (i = 0; i < e->e_phnum; ++i, ++p) {
1230 unsigned long offset;
1231 if (p->p_type != PT_LOAD || p->p_offset == 0)
1234 /* Now, we skip to the image itself */
1235 if ((*(file->fs->seek))(file, p->p_offset) != FILE_ERR_OK) {
1236 prom_printf ("Seek error\n");
1237 prom_release(loadinfo->base, loadinfo->memsize);
1240 offset = p->p_vaddr - loadinfo->load_loc;
1241 if ((*(file->fs->read))(file, p->p_filesz, loadinfo->base+offset) != p->p_filesz) {
1242 prom_printf ("Read failed\n");
1243 prom_release(loadinfo->base, loadinfo->memsize);
1250 /* Return success at loading the Elf64 kernel */
1255 is_elf32(loadinfo_t *loadinfo)
1257 Elf32_Ehdr *e = &(loadinfo->elf.elf32hdr);
1259 return (e->e_ident[EI_MAG0] == ELFMAG0 &&
1260 e->e_ident[EI_MAG1] == ELFMAG1 &&
1261 e->e_ident[EI_MAG2] == ELFMAG2 &&
1262 e->e_ident[EI_MAG3] == ELFMAG3 &&
1263 e->e_ident[EI_CLASS] == ELFCLASS32 &&
1264 e->e_ident[EI_DATA] == ELFDATA2MSB &&
1265 e->e_type == ET_EXEC &&
1266 e->e_machine == EM_PPC);
1270 is_elf64(loadinfo_t *loadinfo)
1272 Elf64_Ehdr *e = &(loadinfo->elf.elf64hdr);
1274 return (e->e_ident[EI_MAG0] == ELFMAG0 &&
1275 e->e_ident[EI_MAG1] == ELFMAG1 &&
1276 e->e_ident[EI_MAG2] == ELFMAG2 &&
1277 e->e_ident[EI_MAG3] == ELFMAG3 &&
1278 e->e_ident[EI_CLASS] == ELFCLASS64 &&
1279 e->e_ident[EI_DATA] == ELFDATA2MSB &&
1280 e->e_type == ET_EXEC &&
1281 e->e_machine == EM_PPC64);
1287 #ifdef CONFIG_SET_COLORMAP
1288 static unsigned char default_colors[] = {
1307 prom_handle scrn = PROM_INVALID_HANDLE;
1309 /* Try Apple's mac-boot screen ihandle */
1310 result = (int)call_prom_return("interpret", 1, 2,
1311 "\" _screen-ihandle\" $find if execute else 0 then", &scrn);
1312 DEBUG_F("Trying to get screen ihandle, result: %d, scrn: %p\n", result, scrn);
1314 if (scrn == 0 || scrn == PROM_INVALID_HANDLE) {
1316 /* Hrm... check to see if stdout is a display */
1317 scrn = call_prom ("instance-to-package", 1, 1, prom_stdout);
1318 DEBUG_F("instance-to-package of stdout is: %p\n", scrn);
1319 if (prom_getprop(scrn, "device_type", type, 32) > 0 && !strncmp(type, "display", 7)) {
1320 DEBUG_F("got it ! stdout is a screen\n");
1323 /* Else, we try to open the package */
1324 scrn = (prom_handle)call_prom( "open", 1, 1, "screen" );
1325 DEBUG_F("Open screen result: %p\n", scrn);
1329 if (scrn == PROM_INVALID_HANDLE) {
1330 prom_printf("No screen device found !/n");
1334 prom_set_color(scrn, i, default_colors[i*3],
1335 default_colors[i*3+1], default_colors[i*3+2]);
1337 prom_printf("\x1b[1;37m\x1b[2;40m");
1339 for (i=0;i<16; i++) {
1340 prom_printf("\x1b[%d;%dm\x1b[1;47m%s \x1b[2;40m %s\n",
1341 ansi_color_table[i].index,
1342 ansi_color_table[i].value,
1343 ansi_color_table[i].name,
1344 ansi_color_table[i].name);
1345 prom_printf("\x1b[%d;%dm\x1b[1;37m%s \x1b[2;30m %s\n",
1346 ansi_color_table[i].index,
1347 ansi_color_table[i].value+10,
1348 ansi_color_table[i].name,
1349 ansi_color_table[i].name);
1351 prom_printf("\x1b[1;37m\x1b[2;40m");
1352 #endif /* COLOR_TEST */
1358 #endif /* CONFIG_SET_COLORMAP */
1364 if (_machine == _MACH_Pmac)
1367 prom_get_chosen("bootpath", bootdevice, sizeof(bootdevice));
1368 DEBUG_F("/chosen/bootpath = %s\n", bootdevice);
1369 if (bootdevice[0] == 0)
1370 prom_get_options("boot-device", bootdevice, sizeof(bootdevice));
1371 if (bootdevice[0] == 0) {
1372 prom_printf("Couldn't determine boot device\n");
1376 if (!parse_device_path(bootdevice, (_machine == _MACH_Pmac) ? "hd" : "disc",
1378 prom_printf("%s: Unable to parse\n", bootdevice);
1381 DEBUG_F("After parse_device_path: dev=%s, part=%d, file=%s\n",
1382 boot.dev, boot.part, boot.file);
1384 if (strlen(boot.file)) {
1385 if (!strncmp(boot.file, "\\\\", 2))
1389 p = last = boot.file;
1399 if (strlen(boot.file))
1400 strcat(boot.file, "\\");
1403 DEBUG_F("After path fixup: dev=%s, part=%d, file=%s\n",
1404 boot.dev, boot.part, boot.file);
1406 useconf = load_config_file(boot.dev, boot.file, boot.part);
1408 prom_printf("Welcome to yaboot version " VERSION "\n");
1409 prom_printf("Enter \"help\" to get some basic usage information\n");
1413 prom_printf("Bye.\n");
1418 * c-file-style: "K&R"