1 /* Yaboot - secondary boot loader for Linux on ppc.
3 Copyright (C) 1999 Benjamin Herrenschmidt
7 Copyright (C) 1999 Marius Vollmer
11 Copyright (C) 1996 Paul Mackerras.
13 Because this program is derived from the corresponding file in the
14 silo-0.64 distribution, it is also
16 Copyright (C) 1996 Pete A. Zaitcev
22 This program is free software; you can redistribute it and/or modify
23 it under the terms of the GNU General Public License as published by
24 the Free Software Foundation; either version 2 of the License, or
25 (at your option) any later version.
27 This program is distributed in the hope that it will be useful,
28 but WITHOUT ANY WARRANTY; without even the implied warranty of
29 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30 GNU General Public License for more details.
32 You should have received a copy of the GNU General Public License
33 along with this program; if not, write to the Free Software
34 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
47 #include "linux/elf.h"
51 #define CONFIG_FILE_NAME "yaboot.conf"
52 #define CONFIG_FILE_MAX 0x8000 /* 32k */
54 #ifdef USE_MD5_PASSWORDS
56 #endif /* USE_MD5_PASSWORDS */
58 /* align addr on a size boundry - adjust address up if needed -- Cort */
59 #define _ALIGN(addr,size) (((addr)+size-1)&(~(size-1)))
61 /* Addresses where the PPC32 and PPC64 vmlinux kernels are linked at.
62 * These are used to determine whether we are booting a vmlinux, in
63 * which case, it will be loaded at KERNELADDR. Otherwise (eg zImage),
64 * we load the binary where it was linked at (ie, e_entry field in
67 #define KERNEL_LINK_ADDR_PPC32 0xC0000000UL
68 #define KERNEL_LINK_ADDR_PPC64 0xC000000000000000ULL
76 unsigned long memsize;
77 unsigned long filesize;
79 unsigned long load_loc;
83 typedef void (*kernel_entry_t)( void *,
89 /* Imported functions */
90 extern unsigned long reloc_offset(void);
91 extern long flush_icache_range(unsigned long start, unsigned long stop);
93 /* Exported functions */
94 int yaboot_start(unsigned long r3, unsigned long r4, unsigned long r5);
97 static int yaboot_main(void);
98 static int is_elf32(loadinfo_t *loadinfo);
99 static int is_elf64(loadinfo_t *loadinfo);
100 static int load_elf32(struct boot_file_t *file, loadinfo_t *loadinfo);
101 static int load_elf64(struct boot_file_t *file, loadinfo_t *loadinfo);
102 static void setup_display(void);
104 /* Locals & globals */
107 char bootdevice[1024];
108 char *password = NULL;
109 struct boot_fspec_t boot;
110 int _machine = _MACH_Pmac;
112 #ifdef CONFIG_COLOR_TEXT
114 /* Color values for text ui */
115 static struct ansi_color_t {
119 } ansi_color_table[] = {
127 { "light-gray", 0, 37 },
128 { "dark-gray", 1, 30 },
129 { "light-blue", 1, 31 },
130 { "light-green", 1, 32 },
131 { "light-cyan", 1, 33 },
132 { "light-red", 1, 34 },
133 { "light-purple", 1, 35 },
139 /* Default colors for text ui */
142 #endif /* CONFIG_COLOR_TEXT */
146 static int test_data = 0;
148 static int pause_after;
149 static char *pause_message = "Type go<return> to continue.\n";
150 static char given_bootargs[1024];
151 static int given_bootargs_by_user = 0;
153 extern unsigned char linux_logo_red[];
154 extern unsigned char linux_logo_green[];
155 extern unsigned char linux_logo_blue[];
157 #define DEFAULT_TIMEOUT -1
159 /* Entry, currently called directly by crt0 (bss not inited) */
161 extern char* __bss_start;
164 static struct first_info *quik_fip = NULL;
167 yaboot_start (unsigned long r3, unsigned long r4, unsigned long r5)
170 void* malloc_base = NULL;
173 /* OF seems to do it, but I'm not very confident */
174 memset(&__bss_start, 0, &_end - &__bss_start);
176 /* Check for quik first stage bootloader (but I don't think we are
177 * compatible with it anyway, I'll look into backporting to older OF
180 if (r5 == 0xdeadbeef) {
182 quik_fip = (struct first_info *)r4;
185 /* Initialize OF interface */
186 prom_init ((prom_entry) r5);
188 /* Allocate some memory for malloc'ator */
189 malloc_base = prom_claim((void *)MALLOCADDR, MALLOCSIZE, 0);
190 if (malloc_base == (void *)-1) {
191 prom_printf("Can't claim malloc buffer (%d bytes at 0x%08x)\n",
192 MALLOCSIZE, MALLOCADDR);
195 malloc_init(malloc_base, MALLOCSIZE);
196 DEBUG_F("Malloc buffer allocated at %p (%d bytes)\n",
197 malloc_base, MALLOCSIZE);
199 /* A few useless DEBUG_F's */
200 DEBUG_F("reloc_offset : %ld (should be 0)\n", reloc_offset());
201 DEBUG_F("test_bss : %d (should be 0)\n", test_bss);
202 DEBUG_F("test_data : %d (should be 0)\n", test_data);
203 DEBUG_F("&test_data : %p\n", &test_data);
204 DEBUG_F("&test_bss : %p\n", &test_bss);
205 DEBUG_F("linked at : 0x%08x\n", TEXTADDR);
207 /* ask the OF info if we're a chrp or pmac */
208 /* we need to set _machine before calling finish_device_tree */
209 root = prom_finddevice("/");
211 static char model[256];
212 if (prom_getprop(root, "device_type", model, 256 ) > 0 &&
213 !strncmp("chrp", model, 4))
214 _machine = _MACH_chrp;
216 if (prom_getprop(root, "model", model, 256 ) > 0 &&
217 !strncmp(model, "IBM", 3))
218 _machine = _MACH_chrp;
222 DEBUG_F("Running on _machine = %d\n", _machine);
226 result = yaboot_main();
228 /* Get rid of malloc pool */
230 prom_release(malloc_base, MALLOCSIZE);
231 DEBUG_F("Malloc buffer released. Exiting with code %d\n",
241 #ifdef CONFIG_COLOR_TEXT
243 * Validify color for text ui
246 check_color_text_ui(char *color)
249 while(ansi_color_table[i].name) {
250 if (!strcmp(color, ansi_color_table[i].name))
256 #endif /* CONFIG_COLOR_TEXT */
258 /* Currently, the config file must be at the root of the filesystem.
259 * todo: recognize the full path to myself and use it to load the
260 * config file. Handle the "\\" (blessed system folder)
263 load_config_file(char *device, char* path, int partition)
265 char *conf_file = NULL, *p;
266 struct boot_file_t file;
267 int sz, opened = 0, result = 0;
269 struct boot_fspec_t fspec;
271 /* Allocate a buffer for the config file */
272 conf_file = malloc(CONFIG_FILE_MAX);
274 prom_printf("Can't alloc config file buffer\n");
278 /* Build the path to the file */
280 strcpy(conf_path, path);
281 else if ( _machine == _MACH_chrp )
282 strcpy(conf_path, "/etc/");
285 strcat(conf_path, CONFIG_FILE_NAME);
289 fspec.file = conf_path;
290 fspec.part = partition;
291 result = open_file(&fspec, &file);
292 if (result != FILE_ERR_OK) {
293 prom_printf("%s:%d,", fspec.dev, fspec.part);
294 prom_perror(result, fspec.file);
295 prom_printf("Can't open config file\n");
301 sz = file.fs->read(&file, CONFIG_FILE_MAX, conf_file);
303 prom_printf("Error, can't read config file\n");
306 prom_printf("Config file read, %d bytes\n", sz);
310 file.fs->close(&file);
313 /* Call the parsing code in cfg.c */
314 if (cfg_parse(conf_path, conf_file, sz) < 0) {
315 prom_printf ("Syntax error or read error config\n");
319 DEBUG_F("Config file successfully parsed, %d bytes\n", sz);
321 /* Now, we do the initialisations stored in the config file */
322 p = cfg_get_strg(0, "init-code");
326 password = cfg_get_strg(0, "password");
328 #ifdef CONFIG_COLOR_TEXT
329 p = cfg_get_strg(0, "fgcolor");
331 DEBUG_F("fgcolor=%s\n", p);
332 fgcolor = check_color_text_ui(p);
334 prom_printf("Invalid fgcolor: \"%s\".\n", p);
337 p = cfg_get_strg(0, "bgcolor");
339 DEBUG_F("bgcolor=%s\n", p);
340 bgcolor = check_color_text_ui(p);
342 prom_printf("Invalid bgcolor: \"%s\".\n", p);
346 sprintf(temp, "%x to background-color", bgcolor);
347 prom_interpret(temp);
354 sprintf(temp, "%x to foreground-color", fgcolor);
355 prom_interpret(temp);
357 #endif /* CONFIG_COLOR_TEXT */
359 p = cfg_get_strg(0, "init-message");
361 prom_printf("%s\n", p);
363 p = cfg_get_strg(0, "message");
365 print_message_file(p);
373 file.fs->close(&file);
375 if (result != 1 && conf_file)
381 void maintabfunc (void)
385 prom_printf("boot: %s", cbuff);
390 word_split(char **linep, char **paramsp)
405 while (*p != 0 && *p != ' ')
414 make_params(char *label, char *params)
417 static char buffer[2048];
422 p = cfg_get_strg(label, "literal");
434 p = cfg_get_strg(label, "root");
441 if (cfg_get_flag(label, "read-only")) {
445 if (cfg_get_flag(label, "read-write")) {
449 p = cfg_get_strg(label, "ramdisk");
451 strcpy (q, "ramdisk=");
456 p = cfg_get_strg(label, "initrd-size");
458 strcpy (q, "ramdisk_size=");
463 if (cfg_get_flag(label, "novideo")) {
464 strcpy (q, "video=ofonly");
468 p = cfg_get_strg (label, "append");
475 pause_after = cfg_get_flag (label, "pause-after");
476 p = cfg_get_strg(label, "pause-message");
485 void check_password(char *str)
489 for (i = 0; i < 3; i++) {
490 prom_printf ("\n%sassword: ", str);
492 cmdedit ((void (*)(void)) 0, 1);
494 #ifdef USE_MD5_PASSWORDS
495 if (!strncmp (password, "$1$", 3)) {
496 if (!check_md5_password(passwdbuff, password))
499 else if (!strcmp (password, passwdbuff))
502 if (!strcmp (password, passwdbuff))
504 #endif /* USE_MD5_PASSWORDS */
506 prom_printf ("Password incorrect. Please try again...");
508 prom_printf ("Seems like you don't know the access password. Go away!\n");
510 prom_interpret("reset-all");
513 int get_params(struct boot_param_t* params)
519 char *imagename = 0, *label;
524 static int first = 1;
525 static char bootargs[1024];
526 static char imagepath[1024];
527 static char initrdpath[1024];
528 static char sysmappath[1024];
531 memset(params, 0, sizeof(*params));
533 params->kernel.part = -1;
534 params->rd.part = -1;
535 params->sysmap.part = -1;
542 prom_get_chosen("bootargs", bootargs, sizeof(bootargs));
543 imagename = bootargs;
544 word_split(&imagename, ¶ms->args);
545 timeout = DEFAULT_TIMEOUT;
547 prom_printf("Default supplied on the command line: %s ", imagename);
549 prom_printf("%s", params->args);
552 if (useconf && (q = cfg_get_strg(0, "timeout")) != 0 && *q != 0)
553 timeout = simple_strtol(q, NULL, 0);
556 prom_printf("boot: ");
561 end = beg + 100 * timeout;
563 c = prom_nbgetchar();
564 } while (c == -1 && prom_getms() <= end);
568 else if (c != '\n' && c != '\t' && c != '\r' && c != '\b' ) {
574 if (c != -1 && c != '\n' && c != '\r') {
577 } else if (c >= ' ') {
580 if ((cfg_get_flag (cbuff, "single-key")) && useconf) {
583 prom_printf("%s\n", cbuff);
588 if (c == '\n' || c == '\r') {
590 imagename = cfg_get_default();
592 prom_printf("%s", imagename);
594 prom_printf(" %s", params->args);
596 } else if (!singlekey) {
597 cmdedit(maintabfunc, 0);
599 strcpy(given_bootargs, cbuff);
600 given_bootargs_by_user = 1;
602 word_split(&imagename, ¶ms->args);
605 /* chrp gets this wrong, force it -- Cort */
606 if ( useconf && (!imagename || imagename[0] == 0 ))
607 imagename = cfg_get_default();
610 defdevice = boot.dev;
613 defdevice = cfg_get_strg(0, "device");
614 p = cfg_get_strg(0, "partition");
616 n = simple_strtol(p, &endp, 10);
617 if (endp != p && *endp == 0)
620 p = cfg_get_strg(0, "pause-message");
623 if (cfg_get_flag(0, "restricted"))
625 p = cfg_get_strg(imagename, "image");
629 defdevice = cfg_get_strg(label, "device");
630 if(!defdevice) defdevice=boot.dev;
631 p = cfg_get_strg(label, "partition");
633 n = simple_strtol(p, &endp, 10);
634 if (endp != p && *endp == 0)
637 if (cfg_get_flag(label, "restricted"))
640 if (params->args && password && restricted)
641 check_password ("To specify image arguments you must enter the p");
642 else if (password && !restricted)
643 check_password ("P");
645 params->args = make_params(label, params->args);
649 if (!strcmp (imagename, "help")) {
651 "\nPress the tab key for a list of defined images.\n"
652 "The label marked with a \"*\" is is the default image, "
653 "press <return> to boot it.\n\n"
654 "To boot any other label simply type its name and press <return>.\n\n"
655 "To boot a kernel image which is not defined in the yaboot configuration \n"
656 "file, enter the kernel image name as [device:][partno],/path, where \n"
657 "\"device:\" is the OpenFirmware device path to the disk the image \n"
658 "resides on, and \"partno\" is the partition number the image resides on.\n\n"
659 "If you omit \"device:\" and \"partno\" yaboot will use the values of \n"
660 "\"device=\" and \"partition=\" in yaboot.conf, right now those are set to: \n"
662 "partition=%d\n\n", defdevice, defpart);
666 if (!strcmp (imagename, "halt")) {
668 check_password ("P");
672 if (!strcmp (imagename, "bye")) {
674 check_password ("P");
680 if (imagename[0] == '$') {
681 /* forth command string */
683 check_password ("P");
684 prom_interpret(imagename+1);
688 strncpy(imagepath, imagename, 1024);
690 if (!label && password)
691 check_password ("To boot a custom image you must enter the p");
693 if (!parse_device_path(imagepath, defdevice, defpart,
694 "/vmlinux", ¶ms->kernel)) {
695 prom_printf("%s: Unable to parse\n", imagepath);
698 DEBUG_F("after parse_device_path: dev=%s part=%d file=%s\n", params->kernel.dev,
699 params->kernel.part, params->kernel.file);
702 p = cfg_get_strg(label, "initrd");
704 DEBUG_F("Parsing initrd path <%s>\n", p);
705 strncpy(initrdpath, p, 1024);
706 if (!parse_device_path(initrdpath, defdevice, defpart,
707 "/root.bin", ¶ms->rd)) {
708 prom_printf("%s: Unable to parse\n", imagepath);
712 p = cfg_get_strg(label, "sysmap");
714 DEBUG_F("Parsing sysmap path <%s>\n", p);
715 strncpy(sysmappath, p, 1024);
716 if (!parse_device_path(sysmappath, defdevice, defpart,
717 "/boot/System.map", ¶ms->sysmap)) {
718 prom_printf("%s: Unable to parse\n", imagepath);
726 /* This is derived from quik core. To be changed to first parse the headers
727 * doing lazy-loading, and then claim the memory before loading the kernel
729 * We also need to add initrd support to this whole mecanism
734 #define MAX_HEADERS 32
736 struct boot_file_t file;
738 static struct boot_param_t params;
740 unsigned long initrd_size;
742 unsigned long sysmap_size;
743 kernel_entry_t kernel_entry;
744 struct bi_record* birec;
747 void *initrd_more,*initrd_want;
748 unsigned long initrd_read;
750 loadinfo.load_loc = 0;
758 if (get_params(¶ms))
760 if (!params.kernel.file)
763 prom_printf("Please wait, loading kernel...\n");
765 memset(&file, 0, sizeof(file));
767 if (strlen(boot.file) && !strcmp(boot.file,"\\\\") && params.kernel.file[0] != '/'
768 && params.kernel.file[0] != '\\') {
769 loc=(char*)malloc(strlen(params.kernel.file)+3);
771 prom_printf ("malloc error\n");
774 strcpy(loc,boot.file);
775 strcat(loc,params.kernel.file);
776 free(params.kernel.file);
777 params.kernel.file=loc;
779 result = open_file(¶ms.kernel, &file);
780 if (result != FILE_ERR_OK) {
781 prom_printf("%s:%d,", params.kernel.dev, params.kernel.part);
782 prom_perror(result, params.kernel.file);
786 /* Read the Elf e_ident, e_type and e_machine fields to
787 * determine Elf file type
789 if (file.fs->read(&file, sizeof(Elf_Ident), &loadinfo.elf) < sizeof(Elf_Ident)) {
790 prom_printf("\nCan't read Elf e_ident/e_type/e_machine info\n");
791 file.fs->close(&file);
792 memset(&file, 0, sizeof(file));
796 if (is_elf32(&loadinfo)) {
797 if (!load_elf32(&file, &loadinfo)) {
798 file.fs->close(&file);
799 memset(&file, 0, sizeof(file));
802 prom_printf(" Elf32 kernel loaded...\n");
803 } else if (is_elf64(&loadinfo)) {
804 if (!load_elf64(&file, &loadinfo)) {
805 file.fs->close(&file);
806 memset(&file, 0, sizeof(file));
809 prom_printf(" Elf64 kernel loaded...\n");
811 prom_printf ("%s: Not a valid ELF image\n", params.kernel.file);
812 file.fs->close(&file);
813 memset(&file, 0, sizeof(file));
816 file.fs->close(&file);
817 memset(&file, 0, sizeof(file));
819 /* If sysmap, load it.
821 if (params.sysmap.file) {
822 prom_printf("Loading System.map ...\n");
823 if(strlen(boot.file) && !strcmp(boot.file,"\\\\") && params.sysmap.file[0] != '/'
824 && params.sysmap.file[0] != '\\') {
826 loc=(char*)malloc(strlen(params.sysmap.file)+3);
828 prom_printf ("malloc error\n");
831 strcpy(loc,boot.file);
832 strcat(loc,params.sysmap.file);
833 free(params.sysmap.file);
834 params.sysmap.file=loc;
837 result = open_file(¶ms.sysmap, &file);
838 if (result != FILE_ERR_OK) {
839 prom_printf("%s:%d,", params.sysmap.dev, params.sysmap.part);
840 prom_perror(result, params.sysmap.file);
843 sysmap_base = prom_claim(loadinfo.base+loadinfo.memsize, 0x100000, 0);
844 if (sysmap_base == (void *)-1) {
845 prom_printf("Claim failed for sysmap memory\n");
848 sysmap_size = file.fs->read(&file, 0xfffff, sysmap_base);
849 if (sysmap_size == 0)
852 ((char *)sysmap_base)[sysmap_size++] = 0;
854 file.fs->close(&file);
855 memset(&file, 0, sizeof(file));
858 prom_printf("System.map loaded at %p, size: %lu Kbytes\n",
859 sysmap_base, sysmap_size >> 10);
860 loadinfo.memsize += _ALIGN(0x100000, 0x1000);
862 prom_printf("System.map load failed !\n");
867 /* If ramdisk, load it. For now, we can't tell the size it will be
868 * so we claim an arbitrary amount of 4Mb
870 if (params.rd.file) {
871 if(strlen(boot.file) && !strcmp(boot.file,"\\\\") && params.rd.file[0] != '/'
872 && params.kernel.file[0] != '\\')
875 loc=(char*)malloc(strlen(params.rd.file)+3);
877 prom_printf ("Malloc error\n");
880 strcpy(loc,boot.file);
881 strcat(loc,params.rd.file);
882 free(params.rd.file);
885 prom_printf("Loading ramdisk...\n");
886 result = open_file(¶ms.rd, &file);
887 if (result != FILE_ERR_OK) {
888 prom_printf("%s:%d,", params.rd.dev, params.rd.part);
889 prom_perror(result, params.rd.file);
892 #define INITRD_CHUNKSIZE 0x400000
893 initrd_base = prom_claim(loadinfo.base+loadinfo.memsize, INITRD_CHUNKSIZE, 0);
894 if (initrd_base == (void *)-1) {
895 prom_printf("Claim failed for initrd memory\n");
898 initrd_size = file.fs->read(&file, INITRD_CHUNKSIZE, initrd_base);
899 if (initrd_size == 0)
901 initrd_read = initrd_size;
902 initrd_more = initrd_base;
903 while (initrd_read == INITRD_CHUNKSIZE ) { /* need to read more? */
904 initrd_want = (void *)((unsigned long)initrd_more+INITRD_CHUNKSIZE);
905 initrd_more = prom_claim(initrd_want, INITRD_CHUNKSIZE, 0);
906 if (initrd_more != initrd_want) {
907 prom_printf("Claim failed for initrd memory at %p rc=%p\n",initrd_want,initrd_more);
910 initrd_read = file.fs->read(&file, INITRD_CHUNKSIZE, initrd_more);
911 DEBUG_F(" block at %p rc=%lu\n",initrd_more,initrd_read);
912 initrd_size += initrd_read;
915 file.fs->close(&file);
916 memset(&file, 0, sizeof(file));
919 prom_printf("ramdisk loaded at %p, size: %lu Kbytes\n",
920 initrd_base, initrd_size >> 10);
922 prom_printf("ramdisk load failed !\n");
927 DEBUG_F("setting kernel args to: %s\n", params.args);
928 prom_setargs(params.args);
929 DEBUG_F("flushing icache...");
930 flush_icache_range ((long)loadinfo.base, (long)loadinfo.base+loadinfo.memsize);
934 * Fill mew boot infos
936 * The birec is low on memory, probably inside the malloc pool, so
937 * we don't write it earlier. At this point, we should not use anything
938 * coming from the malloc pool
940 birec = (struct bi_record *)_ALIGN(loadinfo.filesize+(1<<20)-1,(1<<20));
942 /* We make sure it's mapped. We map only 64k for now, it's plenty enough
943 * we don't claim since this precise memory range may already be claimed
946 prom_map (birec, birec, 0x10000);
947 DEBUG_F("birec at %p\n", birec);
950 birec->tag = BI_FIRST;
951 birec->size = sizeof(struct bi_record);
952 birec = (struct bi_record *)((unsigned long)birec + birec->size);
954 birec->tag = BI_BOOTLOADER_ID;
955 sprintf( (char *)birec->data, "yaboot");
956 birec->size = sizeof(struct bi_record) + strlen("yaboot") + 1;
957 birec = (struct bi_record *)((unsigned long)birec + birec->size);
959 birec->tag = BI_MACHTYPE;
960 birec->data[0] = _machine;
961 birec->size = sizeof(struct bi_record) + sizeof(unsigned long);
962 birec = (struct bi_record *)((unsigned long)birec + birec->size);
965 birec->tag = BI_SYSMAP;
966 birec->data[0] = (unsigned long)sysmap_base;
967 birec->data[1] = sysmap_size;
968 birec->size = sizeof(struct bi_record) + sizeof(unsigned long)*2;
969 birec = (struct bi_record *)((unsigned long)birec + birec->size);
971 birec->tag = BI_LAST;
972 birec->size = sizeof(struct bi_record);
973 birec = (struct bi_record *)((unsigned long)birec + birec->size);
975 /* compute the kernel's entry point. */
976 kernel_entry = loadinfo.base + loadinfo.entry - loadinfo.load_loc;
978 DEBUG_F("Kernel entry point = %p\n", kernel_entry);
979 DEBUG_F("kernel: arg1 = %p,\n"
984 initrd_base + loadinfo.load_loc, initrd_size, prom, 0, 0);
986 DEBUG_F("Entering kernel...\n");
988 /* call the kernel with our stack. */
989 kernel_entry(initrd_base + loadinfo.load_loc, initrd_size, prom, 0, 0);
997 load_elf32(struct boot_file_t *file, loadinfo_t *loadinfo)
1000 Elf32_Ehdr *e = &(loadinfo->elf.elf32hdr);
1002 int size = sizeof(Elf32_Ehdr) - sizeof(Elf_Ident);
1003 unsigned long addr, loadaddr;
1005 /* Read the rest of the Elf header... */
1006 if ((*(file->fs->read))(file, size, &e->e_version) < size) {
1007 prom_printf("\nCan't read Elf32 image header\n");
1011 DEBUG_F("Elf32 header:\n");
1012 DEBUG_F(" e.e_type = %d\n", (int)e->e_type);
1013 DEBUG_F(" e.e_machine = %d\n", (int)e->e_machine);
1014 DEBUG_F(" e.e_version = %d\n", (int)e->e_version);
1015 DEBUG_F(" e.e_entry = 0x%08x\n", (int)e->e_entry);
1016 DEBUG_F(" e.e_phoff = 0x%08x\n", (int)e->e_phoff);
1017 DEBUG_F(" e.e_shoff = 0x%08x\n", (int)e->e_shoff);
1018 DEBUG_F(" e.e_flags = %d\n", (int)e->e_flags);
1019 DEBUG_F(" e.e_ehsize = 0x%08x\n", (int)e->e_ehsize);
1020 DEBUG_F(" e.e_phentsize = 0x%08x\n", (int)e->e_phentsize);
1021 DEBUG_F(" e.e_phnum = %d\n", (int)e->e_phnum);
1023 loadinfo->entry = e->e_entry;
1025 if (e->e_phnum > MAX_HEADERS) {
1026 prom_printf ("Can only load kernels with one program header\n");
1030 ph = (Elf32_Phdr *)malloc(sizeof(Elf32_Phdr) * e->e_phnum);
1032 prom_printf ("Malloc error\n");
1036 /* Now, we read the section header */
1037 if ((*(file->fs->seek))(file, e->e_phoff) != FILE_ERR_OK) {
1038 prom_printf ("seek error\n");
1041 if ((*(file->fs->read))(file, sizeof(Elf32_Phdr) * e->e_phnum, ph) !=
1042 sizeof(Elf32_Phdr) * e->e_phnum) {
1043 prom_printf ("read error\n");
1047 /* Scan through the program header
1048 * HACK: We must return the _memory size of the kernel image, not the
1049 * file size (because we have to leave room before other boot
1050 * infos. This code works as a side effect of the fact that
1051 * we have one section and vaddr == p_paddr
1053 loadinfo->memsize = loadinfo->filesize = loadinfo->offset = 0;
1055 for (i = 0; i < e->e_phnum; ++i, ++p) {
1056 if (p->p_type != PT_LOAD || p->p_offset == 0)
1058 if (loadinfo->memsize == 0) {
1059 loadinfo->offset = p->p_offset;
1060 loadinfo->memsize = p->p_memsz;
1061 loadinfo->filesize = p->p_filesz;
1062 loadinfo->load_loc = p->p_vaddr;
1064 loadinfo->memsize = p->p_offset + p->p_memsz - loadinfo->offset; /* XXX Bogus */
1065 loadinfo->filesize = p->p_offset + p->p_filesz - loadinfo->offset;
1069 if (loadinfo->memsize == 0) {
1070 prom_printf("Can't find a loadable segment !\n");
1074 /* leave some room (1Mb) for boot infos */
1075 loadinfo->memsize = _ALIGN(loadinfo->memsize,(1<<20)) + 0x100000;
1076 /* Claim OF memory */
1077 DEBUG_F("Before prom_claim, mem_sz: 0x%08lx\n", loadinfo->memsize);
1079 /* On some systems, loadaddr may already be claimed, so try some
1080 * other nearby addresses before giving up.
1082 loadaddr = (e->e_entry == KERNEL_LINK_ADDR_PPC32 ||
1083 e->e_entry == 0) ? KERNELADDR : e->e_entry;
1084 for(addr=loadaddr; addr <= loadaddr * 8 ;addr+=0x100000) {
1085 loadinfo->base = prom_claim((void *)addr, loadinfo->memsize, 0);
1086 if (loadinfo->base != (void *)-1) break;
1088 if (loadinfo->base == (void *)-1) {
1089 prom_printf("Claim error, can't allocate kernel memory\n");
1093 DEBUG_F("After ELF parsing, load base: %p, mem_sz: 0x%08lx\n",
1094 loadinfo->base, loadinfo->memsize);
1095 DEBUG_F(" wanted load base: 0x%08lx, mem_sz: 0x%08lx\n",
1096 loadaddr, loadinfo->memsize);
1098 /* Load the program segments... */
1100 for (i = 0; i < e->e_phnum; ++i, ++p) {
1101 unsigned long offset;
1102 if (p->p_type != PT_LOAD || p->p_offset == 0)
1105 /* Now, we skip to the image itself */
1106 if ((*(file->fs->seek))(file, p->p_offset) != FILE_ERR_OK) {
1107 prom_printf ("Seek error\n");
1108 prom_release(loadinfo->base, loadinfo->memsize);
1111 offset = p->p_vaddr - loadinfo->load_loc;
1112 if ((*(file->fs->read))(file, p->p_filesz, loadinfo->base+offset) != p->p_filesz) {
1113 prom_printf ("Read failed\n");
1114 prom_release(loadinfo->base, loadinfo->memsize);
1121 /* Return success at loading the Elf32 kernel */
1126 load_elf64(struct boot_file_t *file, loadinfo_t *loadinfo)
1129 Elf64_Ehdr *e = &(loadinfo->elf.elf64hdr);
1131 int size = sizeof(Elf64_Ehdr) - sizeof(Elf_Ident);
1132 unsigned long addr, loadaddr;
1134 /* Read the rest of the Elf header... */
1135 if ((*(file->fs->read))(file, size, &e->e_version) < size) {
1136 prom_printf("\nCan't read Elf64 image header\n");
1140 DEBUG_F("Elf64 header:\n");
1141 DEBUG_F(" e.e_type = %d\n", (int)e->e_type);
1142 DEBUG_F(" e.e_machine = %d\n", (int)e->e_machine);
1143 DEBUG_F(" e.e_version = %d\n", (int)e->e_version);
1144 DEBUG_F(" e.e_entry = 0x%016lx\n", (long)e->e_entry);
1145 DEBUG_F(" e.e_phoff = 0x%016lx\n", (long)e->e_phoff);
1146 DEBUG_F(" e.e_shoff = 0x%016lx\n", (long)e->e_shoff);
1147 DEBUG_F(" e.e_flags = %d\n", (int)e->e_flags);
1148 DEBUG_F(" e.e_ehsize = 0x%08x\n", (int)e->e_ehsize);
1149 DEBUG_F(" e.e_phentsize = 0x%08x\n", (int)e->e_phentsize);
1150 DEBUG_F(" e.e_phnum = %d\n", (int)e->e_phnum);
1152 loadinfo->entry = e->e_entry;
1154 if (e->e_phnum > MAX_HEADERS) {
1155 prom_printf ("Can only load kernels with one program header\n");
1159 ph = (Elf64_Phdr *)malloc(sizeof(Elf64_Phdr) * e->e_phnum);
1161 prom_printf ("Malloc error\n");
1165 /* Now, we read the section header */
1166 if ((*(file->fs->seek))(file, e->e_phoff) != FILE_ERR_OK) {
1167 prom_printf ("Seek error\n");
1170 if ((*(file->fs->read))(file, sizeof(Elf64_Phdr) * e->e_phnum, ph) !=
1171 sizeof(Elf64_Phdr) * e->e_phnum) {
1172 prom_printf ("Read error\n");
1176 /* Scan through the program header
1177 * HACK: We must return the _memory size of the kernel image, not the
1178 * file size (because we have to leave room before other boot
1179 * infos. This code works as a side effect of the fact that
1180 * we have one section and vaddr == p_paddr
1182 loadinfo->memsize = loadinfo->filesize = loadinfo->offset = 0;
1184 for (i = 0; i < e->e_phnum; ++i, ++p) {
1185 if (p->p_type != PT_LOAD || p->p_offset == 0)
1187 if (loadinfo->memsize == 0) {
1188 loadinfo->offset = p->p_offset;
1189 loadinfo->memsize = p->p_memsz;
1190 loadinfo->filesize = p->p_filesz;
1191 loadinfo->load_loc = p->p_vaddr;
1193 loadinfo->memsize = p->p_offset + p->p_memsz - loadinfo->offset; /* XXX Bogus */
1194 loadinfo->filesize = p->p_offset + p->p_filesz - loadinfo->offset;
1198 if (loadinfo->memsize == 0) {
1199 prom_printf("Can't find a loadable segment !\n");
1203 /* leave some room (1Mb) for boot infos */
1204 loadinfo->memsize = _ALIGN(loadinfo->memsize,(1<<20)) + 0x100000;
1205 /* Claim OF memory */
1206 DEBUG_F("Before prom_claim, mem_sz: 0x%08lx\n", loadinfo->memsize);
1208 /* On some systems, loadaddr may already be claimed, so try some
1209 * other nearby addresses before giving up.
1211 loadaddr = (e->e_entry == KERNEL_LINK_ADDR_PPC64) ? KERNELADDR : e->e_entry;
1212 for(addr=loadaddr; addr <= loadaddr * 8 ;addr+=0x100000) {
1213 loadinfo->base = prom_claim((void *)addr, loadinfo->memsize, 0);
1214 if (loadinfo->base != (void *)-1) break;
1216 if (loadinfo->base == (void *)-1) {
1217 prom_printf("Claim error, can't allocate kernel memory\n");
1221 DEBUG_F("After ELF parsing, load base: %p, mem_sz: 0x%08lx\n",
1222 loadinfo->base, loadinfo->memsize);
1223 DEBUG_F(" wanted load base: 0x%08lx, mem_sz: 0x%08lx\n",
1224 loadaddr, loadinfo->memsize);
1226 /* Load the program segments... */
1228 for (i = 0; i < e->e_phnum; ++i, ++p) {
1229 unsigned long offset;
1230 if (p->p_type != PT_LOAD || p->p_offset == 0)
1233 /* Now, we skip to the image itself */
1234 if ((*(file->fs->seek))(file, p->p_offset) != FILE_ERR_OK) {
1235 prom_printf ("Seek error\n");
1236 prom_release(loadinfo->base, loadinfo->memsize);
1239 offset = p->p_vaddr - loadinfo->load_loc;
1240 if ((*(file->fs->read))(file, p->p_filesz, loadinfo->base+offset) != p->p_filesz) {
1241 prom_printf ("Read failed\n");
1242 prom_release(loadinfo->base, loadinfo->memsize);
1249 /* Return success at loading the Elf64 kernel */
1254 is_elf32(loadinfo_t *loadinfo)
1256 Elf32_Ehdr *e = &(loadinfo->elf.elf32hdr);
1258 return (e->e_ident[EI_MAG0] == ELFMAG0 &&
1259 e->e_ident[EI_MAG1] == ELFMAG1 &&
1260 e->e_ident[EI_MAG2] == ELFMAG2 &&
1261 e->e_ident[EI_MAG3] == ELFMAG3 &&
1262 e->e_ident[EI_CLASS] == ELFCLASS32 &&
1263 e->e_ident[EI_DATA] == ELFDATA2MSB &&
1264 e->e_type == ET_EXEC &&
1265 e->e_machine == EM_PPC);
1269 is_elf64(loadinfo_t *loadinfo)
1271 Elf64_Ehdr *e = &(loadinfo->elf.elf64hdr);
1273 return (e->e_ident[EI_MAG0] == ELFMAG0 &&
1274 e->e_ident[EI_MAG1] == ELFMAG1 &&
1275 e->e_ident[EI_MAG2] == ELFMAG2 &&
1276 e->e_ident[EI_MAG3] == ELFMAG3 &&
1277 e->e_ident[EI_CLASS] == ELFCLASS64 &&
1278 e->e_ident[EI_DATA] == ELFDATA2MSB &&
1279 e->e_type == ET_EXEC &&
1280 e->e_machine == EM_PPC64);
1286 #ifdef CONFIG_SET_COLORMAP
1287 static unsigned char default_colors[] = {
1306 prom_handle scrn = PROM_INVALID_HANDLE;
1308 /* Try Apple's mac-boot screen ihandle */
1309 result = (int)call_prom_return("interpret", 1, 2,
1310 "\" _screen-ihandle\" $find if execute else 0 then", &scrn);
1311 DEBUG_F("Trying to get screen ihandle, result: %d, scrn: %p\n", result, scrn);
1313 if (scrn == 0 || scrn == PROM_INVALID_HANDLE) {
1315 /* Hrm... check to see if stdout is a display */
1316 scrn = call_prom ("instance-to-package", 1, 1, prom_stdout);
1317 DEBUG_F("instance-to-package of stdout is: %p\n", scrn);
1318 if (prom_getprop(scrn, "device_type", type, 32) > 0 && !strncmp(type, "display", 7)) {
1319 DEBUG_F("got it ! stdout is a screen\n");
1322 /* Else, we try to open the package */
1323 scrn = (prom_handle)call_prom( "open", 1, 1, "screen" );
1324 DEBUG_F("Open screen result: %p\n", scrn);
1328 if (scrn == PROM_INVALID_HANDLE) {
1329 prom_printf("No screen device found !/n");
1333 prom_set_color(scrn, i, default_colors[i*3],
1334 default_colors[i*3+1], default_colors[i*3+2]);
1336 prom_printf("\x1b[1;37m\x1b[2;40m");
1338 for (i=0;i<16; i++) {
1339 prom_printf("\x1b[%d;%dm\x1b[1;47m%s \x1b[2;40m %s\n",
1340 ansi_color_table[i].index,
1341 ansi_color_table[i].value,
1342 ansi_color_table[i].name,
1343 ansi_color_table[i].name);
1344 prom_printf("\x1b[%d;%dm\x1b[1;37m%s \x1b[2;30m %s\n",
1345 ansi_color_table[i].index,
1346 ansi_color_table[i].value+10,
1347 ansi_color_table[i].name,
1348 ansi_color_table[i].name);
1350 prom_printf("\x1b[1;37m\x1b[2;40m");
1351 #endif /* COLOR_TEST */
1357 #endif /* CONFIG_SET_COLORMAP */
1365 if (_machine == _MACH_Pmac)
1368 prom_get_chosen("bootpath", bootdevice, sizeof(bootdevice));
1369 DEBUG_F("/chosen/bootpath = %s\n", bootdevice);
1370 if (bootdevice[0] == 0)
1371 prom_get_options("boot-device", bootdevice, sizeof(bootdevice));
1372 if (bootdevice[0] == 0) {
1373 prom_printf("Couldn't determine boot device\n");
1377 if (!parse_device_path(bootdevice, (_machine == _MACH_Pmac) ? "hd" : "disc",
1379 prom_printf("%s: Unable to parse\n", bootdevice);
1382 DEBUG_F("After parse_device_path: dev=%s, part=%d, file=%s\n",
1383 boot.dev, boot.part, boot.file);
1385 if (strlen(boot.file)) {
1386 if (!strncmp(boot.file, "\\\\", 2))
1390 p = last = boot.file;
1400 if (strlen(boot.file))
1401 strcat(boot.file, "\\");
1404 DEBUG_F("After path fixup: dev=%s, part=%d, file=%s\n",
1405 boot.dev, boot.part, boot.file);
1407 useconf = load_config_file(boot.dev, boot.file, boot.part);
1409 prom_printf("Welcome to yaboot version " VERSION "\n");
1410 prom_printf("Enter \"help\" to get some basic usage information\n");
1412 /* I am fed up with lusers using the wrong partition type and
1413 mailing me *when* it breaks */
1415 if (_machine == _MACH_Pmac) {
1416 char *entry = cfg_get_strg(0, "ptypewarning");
1419 warn = strcmp(entry,
1420 "I_know_the_partition_type_is_wrong_and_will_NOT_send_mail_when_booting_breaks");
1422 ptype = get_part_type(boot.dev, boot.part);
1423 if ((ptype != NULL) && (strcmp(ptype, "Apple_Bootstrap")))
1424 prom_printf("\nWARNING: Bootstrap partition type is wrong: \"%s\"\n"
1425 " type should be: \"Apple_Bootstrap\"\n\n", ptype);
1431 prom_printf("Bye.\n");
1437 * c-file-style: "K&R"