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;
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 */
260 void print_message_file(char *filename)
264 char *defdev = boot.dev;
265 int defpart = boot.part;
270 struct boot_file_t file;
271 struct boot_fspec_t msgfile;
273 defdev = cfg_get_strg(0, "device");
276 p = cfg_get_strg(0, "partition");
278 n = simple_strtol(p, &endp, 10);
279 if (endp != p && *endp == 0)
283 strncpy(msgpath, filename, sizeof(msgpath));
284 if (!parse_device_path(msgpath, defdev, defpart, "/etc/yaboot.msg", &msgfile)) {
285 prom_printf("%s: Unable to parse\n", msgpath);
289 result = open_file(&msgfile, &file);
290 if (result != FILE_ERR_OK) {
291 prom_printf("%s:%d,", msgfile.dev, msgfile.part);
292 prom_perror(result, msgfile.file);
301 memset(msg, 0, 2001);
303 if (file.fs->read(&file, 2000, msg) <= 0)
306 prom_printf("%s", msg);
310 file.fs->close(&file);
315 /* Currently, the config file must be at the root of the filesystem.
316 * todo: recognize the full path to myself and use it to load the
317 * config file. Handle the "\\" (blessed system folder)
320 load_config_file(char *device, char* path, int partition)
322 char *conf_file = NULL, *p;
323 struct boot_file_t file;
324 int sz, opened = 0, result = 0;
326 struct boot_fspec_t fspec;
328 /* Allocate a buffer for the config file */
329 conf_file = malloc(CONFIG_FILE_MAX);
331 prom_printf("Can't alloc config file buffer\n");
335 /* Build the path to the file */
336 if (_machine == _MACH_chrp)
337 strcpy(conf_path, "/etc/");
338 else if (path && *path)
339 strcpy(conf_path, path);
342 strcat(conf_path, CONFIG_FILE_NAME);
346 fspec.file = conf_path;
347 fspec.part = partition;
348 result = open_file(&fspec, &file);
349 if (result != FILE_ERR_OK) {
350 prom_printf("%s:%d,", fspec.dev, fspec.part);
351 prom_perror(result, fspec.file);
352 prom_printf("Can't open config file\n");
358 sz = file.fs->read(&file, CONFIG_FILE_MAX, conf_file);
360 prom_printf("Error, can't read config file\n");
363 prom_printf("Config file read, %d bytes\n", sz);
367 file.fs->close(&file);
370 /* Call the parsing code in cfg.c */
371 if (cfg_parse(conf_path, conf_file, sz) < 0) {
372 prom_printf ("Syntax error or read error config\n");
376 DEBUG_F("Config file successfully parsed, %d bytes\n", sz);
378 /* Now, we do the initialisations stored in the config file */
379 p = cfg_get_strg(0, "init-code");
383 password = cfg_get_strg(0, "password");
385 #ifdef CONFIG_COLOR_TEXT
386 p = cfg_get_strg(0, "fgcolor");
388 DEBUG_F("fgcolor=%s\n", p);
389 fgcolor = check_color_text_ui(p);
391 prom_printf("Invalid fgcolor: \"%s\".\n", p);
394 p = cfg_get_strg(0, "bgcolor");
396 DEBUG_F("bgcolor=%s\n", p);
397 bgcolor = check_color_text_ui(p);
399 prom_printf("Invalid bgcolor: \"%s\".\n", p);
403 sprintf(temp, "%x to background-color", bgcolor);
404 prom_interpret(temp);
411 sprintf(temp, "%x to foreground-color", fgcolor);
412 prom_interpret(temp);
414 #endif /* CONFIG_COLOR_TEXT */
416 p = cfg_get_strg(0, "init-message");
418 prom_printf("%s\n", p);
420 p = cfg_get_strg(0, "message");
422 print_message_file(p);
429 file.fs->close(&file);
431 if (result != 1 && conf_file)
437 void maintabfunc (void)
441 prom_printf("boot: %s", cbuff);
446 word_split(char **linep, char **paramsp)
461 while (*p != 0 && *p != ' ')
470 make_params(char *label, char *params)
473 static char buffer[2048];
478 p = cfg_get_strg(label, "literal");
490 p = cfg_get_strg(label, "root");
497 if (cfg_get_flag(label, "read-only")) {
501 if (cfg_get_flag(label, "read-write")) {
505 p = cfg_get_strg(label, "ramdisk");
507 strcpy (q, "ramdisk=");
512 p = cfg_get_strg(label, "initrd-size");
514 strcpy (q, "ramdisk_size=");
519 if (cfg_get_flag(label, "novideo")) {
520 strcpy (q, "video=ofonly");
524 p = cfg_get_strg (label, "append");
531 pause_after = cfg_get_flag (label, "pause-after");
532 p = cfg_get_strg(label, "pause-message");
541 void check_password(char *str)
545 for (i = 0; i < 3; i++) {
546 prom_printf ("\n%sassword: ", str);
548 cmdedit ((void (*)(void)) 0, 1);
550 #ifdef USE_MD5_PASSWORDS
551 if (!strncmp (password, "$1$", 3)) {
552 if (!check_md5_password(passwdbuff, password))
555 else if (!strcmp (password, passwdbuff))
558 if (!strcmp (password, passwdbuff))
560 #endif /* USE_MD5_PASSWORDS */
562 prom_printf ("Password incorrect. Please try again...");
564 prom_printf ("Seems like you don't know the access password. Go away!\n");
566 prom_interpret("reset-all");
569 int get_params(struct boot_param_t* params)
575 char *imagename = 0, *label;
580 static int first = 1;
581 static char bootargs[1024];
582 static char imagepath[1024];
583 static char initrdpath[1024];
584 static char sysmappath[1024];
587 memset(params, 0, sizeof(*params));
589 params->kernel.part = -1;
590 params->rd.part = -1;
591 params->sysmap.part = -1;
598 prom_get_chosen("bootargs", bootargs, sizeof(bootargs));
599 imagename = bootargs;
600 word_split(&imagename, ¶ms->args);
601 timeout = DEFAULT_TIMEOUT;
603 prom_printf("Default supplied on the command line: %s ", imagename);
605 prom_printf("%s", params->args);
608 if (useconf && (q = cfg_get_strg(0, "timeout")) != 0 && *q != 0)
609 timeout = simple_strtol(q, NULL, 0);
612 prom_printf("boot: ");
617 end = beg + 100 * timeout;
619 c = prom_nbgetchar();
620 } while (c == -1 && prom_getms() <= end);
624 else if (c != '\n' && c != '\t' && c != '\r' && c != '\b' ) {
630 if (c != -1 && c != '\n' && c != '\r') {
633 } else if (c >= ' ') {
636 if ((cfg_get_flag (cbuff, "single-key")) && useconf) {
639 prom_printf("%s\n", cbuff);
644 if (c == '\n' || c == '\r') {
646 imagename = cfg_get_default();
648 prom_printf("%s", imagename);
650 prom_printf(" %s", params->args);
652 } else if (!singlekey) {
653 cmdedit(maintabfunc, 0);
655 strcpy(given_bootargs, cbuff);
656 given_bootargs_by_user = 1;
658 word_split(&imagename, ¶ms->args);
661 /* chrp gets this wrong, force it -- Cort */
662 if ( useconf && (!imagename || imagename[0] == 0 ))
663 imagename = cfg_get_default();
666 defdevice = boot.dev;
669 defdevice = cfg_get_strg(0, "device");
670 p = cfg_get_strg(0, "partition");
672 n = simple_strtol(p, &endp, 10);
673 if (endp != p && *endp == 0)
676 p = cfg_get_strg(0, "pause-message");
679 if (cfg_get_flag(0, "restricted"))
681 p = cfg_get_strg(imagename, "image");
685 defdevice = cfg_get_strg(label, "device");
686 if(!defdevice) defdevice=boot.dev;
687 p = cfg_get_strg(label, "partition");
689 n = simple_strtol(p, &endp, 10);
690 if (endp != p && *endp == 0)
693 if (cfg_get_flag(label, "restricted"))
696 if (params->args && password && restricted)
697 check_password ("To specify image arguments you must enter the p");
698 else if (password && !restricted)
699 check_password ("P");
701 params->args = make_params(label, params->args);
705 if (!strcmp (imagename, "help")) {
707 "\nPress the tab key for a list of defined images.\n"
708 "The label marked with a \"*\" is is the default image, "
709 "press <return> to boot it.\n\n"
710 "To boot any other label simply type its name and press <return>.\n\n"
711 "To boot a kernel image which is not defined in the yaboot configuration \n"
712 "file, enter the kernel image name as [[device:][partno],]/path, where \n"
713 "\"device:\" is the OpenFirmware device path to the disk the image \n"
714 "resides on, and \"partno\" is the partition number the image resides on.\n"
715 "Note that the comma (,) is only required if you specify an OpenFirmware\n"
716 "device, if you only specify a filename you should not start it with a \",\"\n\n"
717 "If you omit \"device:\" and \"partno\" yaboot will use the values of \n"
718 "\"device=\" and \"partition=\" in yaboot.conf, right now those are set to: \n"
720 "partition=%d\n\n", defdevice, defpart);
724 if (!strcmp (imagename, "halt")) {
726 check_password ("P");
730 if (!strcmp (imagename, "bye")) {
732 check_password ("P");
738 if (imagename[0] == '$') {
739 /* forth command string */
741 check_password ("P");
742 prom_interpret(imagename+1);
746 strncpy(imagepath, imagename, 1024);
748 if (!label && password)
749 check_password ("To boot a custom image you must enter the p");
751 if (!parse_device_path(imagepath, defdevice, defpart,
752 "/vmlinux", ¶ms->kernel)) {
753 prom_printf("%s: Unable to parse\n", imagepath);
756 DEBUG_F("after parse_device_path: dev=%s part=%d file=%s\n", params->kernel.dev,
757 params->kernel.part, params->kernel.file);
760 p = cfg_get_strg(label, "initrd");
762 DEBUG_F("Parsing initrd path <%s>\n", p);
763 strncpy(initrdpath, p, 1024);
764 if (!parse_device_path(initrdpath, defdevice, defpart,
765 "/root.bin", ¶ms->rd)) {
766 prom_printf("%s: Unable to parse\n", imagepath);
770 p = cfg_get_strg(label, "sysmap");
772 DEBUG_F("Parsing sysmap path <%s>\n", p);
773 strncpy(sysmappath, p, 1024);
774 if (!parse_device_path(sysmappath, defdevice, defpart,
775 "/boot/System.map", ¶ms->sysmap)) {
776 prom_printf("%s: Unable to parse\n", imagepath);
784 /* This is derived from quik core. To be changed to first parse the headers
785 * doing lazy-loading, and then claim the memory before loading the kernel
787 * We also need to add initrd support to this whole mecanism
792 #define MAX_HEADERS 32
794 struct boot_file_t file;
796 static struct boot_param_t params;
798 unsigned long initrd_size;
800 unsigned long sysmap_size;
801 kernel_entry_t kernel_entry;
802 struct bi_record* birec;
805 void *initrd_more,*initrd_want;
806 unsigned long initrd_read;
808 loadinfo.load_loc = 0;
816 if (get_params(¶ms))
818 if (!params.kernel.file)
821 prom_printf("Please wait, loading kernel...\n");
823 memset(&file, 0, sizeof(file));
825 if (strlen(boot.file) && !strcmp(boot.file,"\\\\") && params.kernel.file[0] != '/'
826 && params.kernel.file[0] != '\\') {
827 loc=(char*)malloc(strlen(params.kernel.file)+3);
829 prom_printf ("malloc error\n");
832 strcpy(loc,boot.file);
833 strcat(loc,params.kernel.file);
834 free(params.kernel.file);
835 params.kernel.file=loc;
837 result = open_file(¶ms.kernel, &file);
838 if (result != FILE_ERR_OK) {
839 prom_printf("%s:%d,", params.kernel.dev, params.kernel.part);
840 prom_perror(result, params.kernel.file);
844 /* Read the Elf e_ident, e_type and e_machine fields to
845 * determine Elf file type
847 if (file.fs->read(&file, sizeof(Elf_Ident), &loadinfo.elf) < sizeof(Elf_Ident)) {
848 prom_printf("\nCan't read Elf e_ident/e_type/e_machine info\n");
849 file.fs->close(&file);
850 memset(&file, 0, sizeof(file));
854 if (is_elf32(&loadinfo)) {
855 if (!load_elf32(&file, &loadinfo)) {
856 file.fs->close(&file);
857 memset(&file, 0, sizeof(file));
860 prom_printf(" Elf32 kernel loaded...\n");
861 } else if (is_elf64(&loadinfo)) {
862 if (!load_elf64(&file, &loadinfo)) {
863 file.fs->close(&file);
864 memset(&file, 0, sizeof(file));
867 prom_printf(" Elf64 kernel loaded...\n");
869 prom_printf ("%s: Not a valid ELF image\n", params.kernel.file);
870 file.fs->close(&file);
871 memset(&file, 0, sizeof(file));
874 file.fs->close(&file);
875 memset(&file, 0, sizeof(file));
877 /* If sysmap, load it (only if booting a vmlinux).
879 if (flat_vmlinux && params.sysmap.file) {
880 prom_printf("Loading System.map ...\n");
881 if(strlen(boot.file) && !strcmp(boot.file,"\\\\") && params.sysmap.file[0] != '/'
882 && params.sysmap.file[0] != '\\') {
884 loc=(char*)malloc(strlen(params.sysmap.file)+3);
886 prom_printf ("malloc error\n");
889 strcpy(loc,boot.file);
890 strcat(loc,params.sysmap.file);
891 free(params.sysmap.file);
892 params.sysmap.file=loc;
895 result = open_file(¶ms.sysmap, &file);
896 if (result != FILE_ERR_OK) {
897 prom_printf("%s:%d,", params.sysmap.dev, params.sysmap.part);
898 prom_perror(result, params.sysmap.file);
901 sysmap_base = prom_claim(loadinfo.base+loadinfo.memsize, 0x100000, 0);
902 if (sysmap_base == (void *)-1) {
903 prom_printf("Claim failed for sysmap memory\n");
906 sysmap_size = file.fs->read(&file, 0xfffff, sysmap_base);
907 if (sysmap_size == 0)
910 ((char *)sysmap_base)[sysmap_size++] = 0;
912 file.fs->close(&file);
913 memset(&file, 0, sizeof(file));
916 prom_printf("System.map loaded at %p, size: %lu Kbytes\n",
917 sysmap_base, sysmap_size >> 10);
918 loadinfo.memsize += _ALIGN(0x100000, 0x1000);
920 prom_printf("System.map load failed !\n");
925 /* If ramdisk, load it (only if booting a vmlinux). For now, we
926 * can't tell the size it will be so we claim an arbitrary amount
929 if (flat_vmlinux && params.rd.file) {
930 if(strlen(boot.file) && !strcmp(boot.file,"\\\\") && params.rd.file[0] != '/'
931 && params.kernel.file[0] != '\\')
934 loc=(char*)malloc(strlen(params.rd.file)+3);
936 prom_printf ("Malloc error\n");
939 strcpy(loc,boot.file);
940 strcat(loc,params.rd.file);
941 free(params.rd.file);
944 prom_printf("Loading ramdisk...\n");
945 result = open_file(¶ms.rd, &file);
946 if (result != FILE_ERR_OK) {
947 prom_printf("%s:%d,", params.rd.dev, params.rd.part);
948 prom_perror(result, params.rd.file);
951 #define INITRD_CHUNKSIZE 0x400000
952 initrd_base = prom_claim(loadinfo.base+loadinfo.memsize, INITRD_CHUNKSIZE, 0);
953 if (initrd_base == (void *)-1) {
954 prom_printf("Claim failed for initrd memory\n");
957 initrd_size = file.fs->read(&file, INITRD_CHUNKSIZE, initrd_base);
958 if (initrd_size == 0)
960 initrd_read = initrd_size;
961 initrd_more = initrd_base;
962 while (initrd_read == INITRD_CHUNKSIZE ) { /* need to read more? */
963 initrd_want = (void *)((unsigned long)initrd_more+INITRD_CHUNKSIZE);
964 initrd_more = prom_claim(initrd_want, INITRD_CHUNKSIZE, 0);
965 if (initrd_more != initrd_want) {
966 prom_printf("Claim failed for initrd memory at %p rc=%p\n",initrd_want,initrd_more);
969 initrd_read = file.fs->read(&file, INITRD_CHUNKSIZE, initrd_more);
970 DEBUG_F(" block at %p rc=%lu\n",initrd_more,initrd_read);
971 initrd_size += initrd_read;
974 file.fs->close(&file);
975 memset(&file, 0, sizeof(file));
978 prom_printf("ramdisk loaded at %p, size: %lu Kbytes\n",
979 initrd_base, initrd_size >> 10);
981 prom_printf("ramdisk load failed !\n");
986 DEBUG_F("setting kernel args to: %s\n", params.args);
987 prom_setargs(params.args);
988 DEBUG_F("flushing icache...");
989 flush_icache_range ((long)loadinfo.base, (long)loadinfo.base+loadinfo.memsize);
994 * Fill new boot infos (only if booting a vmlinux).
996 * The birec is low on memory, probably inside the malloc pool,
997 * so we don't write it earlier. At this point, we should not
998 * use anything coming from the malloc pool.
1000 birec = (struct bi_record *)_ALIGN(loadinfo.filesize+(1<<20)-1,(1<<20));
1002 /* We make sure it's mapped. We map only 64k for now, it's
1003 * plenty enough we don't claim since this precise memory
1004 * range may already be claimed by the malloc pool.
1006 prom_map (birec, birec, 0x10000);
1007 DEBUG_F("birec at %p\n", birec);
1010 birec->tag = BI_FIRST;
1011 birec->size = sizeof(struct bi_record);
1012 birec = (struct bi_record *)((ulong)birec + birec->size);
1014 birec->tag = BI_BOOTLOADER_ID;
1015 sprintf( (char *)birec->data, "yaboot");
1016 birec->size = sizeof(struct bi_record) + strlen("yaboot") + 1;
1017 birec = (struct bi_record *)((ulong)birec + birec->size);
1019 birec->tag = BI_MACHTYPE;
1020 birec->data[0] = _machine;
1021 birec->size = sizeof(struct bi_record) + sizeof(ulong);
1022 birec = (struct bi_record *)((ulong)birec + birec->size);
1025 birec->tag = BI_SYSMAP;
1026 birec->data[0] = (ulong)sysmap_base;
1027 birec->data[1] = sysmap_size;
1028 birec->size = sizeof(struct bi_record) + sizeof(ulong)*2;
1029 birec = (struct bi_record *)((ulong)birec + birec->size);
1031 birec->tag = BI_LAST;
1032 birec->size = sizeof(struct bi_record);
1033 birec = (struct bi_record *)((ulong)birec + birec->size);
1036 /* compute the kernel's entry point. */
1037 kernel_entry = loadinfo.base + loadinfo.entry - loadinfo.load_loc;
1039 DEBUG_F("Kernel entry point = %p\n", kernel_entry);
1040 DEBUG_F("kernel: arg1 = %p,\n"
1041 " arg2 = 0x%08lx,\n"
1045 initrd_base + loadinfo.load_loc, initrd_size, prom, 0, 0);
1047 DEBUG_F("Entering kernel...\n");
1049 /* call the kernel with our stack. */
1050 kernel_entry(initrd_base + loadinfo.load_loc, initrd_size, prom, 0, 0);
1058 load_elf32(struct boot_file_t *file, loadinfo_t *loadinfo)
1061 Elf32_Ehdr *e = &(loadinfo->elf.elf32hdr);
1063 int size = sizeof(Elf32_Ehdr) - sizeof(Elf_Ident);
1064 unsigned long addr, loadaddr;
1066 /* Read the rest of the Elf header... */
1067 if ((*(file->fs->read))(file, size, &e->e_version) < size) {
1068 prom_printf("\nCan't read Elf32 image header\n");
1072 DEBUG_F("Elf32 header:\n");
1073 DEBUG_F(" e.e_type = %d\n", (int)e->e_type);
1074 DEBUG_F(" e.e_machine = %d\n", (int)e->e_machine);
1075 DEBUG_F(" e.e_version = %d\n", (int)e->e_version);
1076 DEBUG_F(" e.e_entry = 0x%08x\n", (int)e->e_entry);
1077 DEBUG_F(" e.e_phoff = 0x%08x\n", (int)e->e_phoff);
1078 DEBUG_F(" e.e_shoff = 0x%08x\n", (int)e->e_shoff);
1079 DEBUG_F(" e.e_flags = %d\n", (int)e->e_flags);
1080 DEBUG_F(" e.e_ehsize = 0x%08x\n", (int)e->e_ehsize);
1081 DEBUG_F(" e.e_phentsize = 0x%08x\n", (int)e->e_phentsize);
1082 DEBUG_F(" e.e_phnum = %d\n", (int)e->e_phnum);
1084 loadinfo->entry = e->e_entry;
1086 if (e->e_phnum > MAX_HEADERS) {
1087 prom_printf ("Can only load kernels with one program header\n");
1091 ph = (Elf32_Phdr *)malloc(sizeof(Elf32_Phdr) * e->e_phnum);
1093 prom_printf ("Malloc error\n");
1097 /* Now, we read the section header */
1098 if ((*(file->fs->seek))(file, e->e_phoff) != FILE_ERR_OK) {
1099 prom_printf ("seek error\n");
1102 if ((*(file->fs->read))(file, sizeof(Elf32_Phdr) * e->e_phnum, ph) !=
1103 sizeof(Elf32_Phdr) * e->e_phnum) {
1104 prom_printf ("read error\n");
1108 /* Scan through the program header
1109 * HACK: We must return the _memory size of the kernel image, not the
1110 * file size (because we have to leave room before other boot
1111 * infos. This code works as a side effect of the fact that
1112 * we have one section and vaddr == p_paddr
1114 loadinfo->memsize = loadinfo->filesize = loadinfo->offset = 0;
1116 for (i = 0; i < e->e_phnum; ++i, ++p) {
1117 if (p->p_type != PT_LOAD || p->p_offset == 0)
1119 if (loadinfo->memsize == 0) {
1120 loadinfo->offset = p->p_offset;
1121 loadinfo->memsize = p->p_memsz;
1122 loadinfo->filesize = p->p_filesz;
1123 loadinfo->load_loc = p->p_vaddr;
1125 loadinfo->memsize = p->p_offset + p->p_memsz - loadinfo->offset; /* XXX Bogus */
1126 loadinfo->filesize = p->p_offset + p->p_filesz - loadinfo->offset;
1130 if (loadinfo->memsize == 0) {
1131 prom_printf("Can't find a loadable segment !\n");
1135 /* leave some room (1Mb) for boot infos */
1136 loadinfo->memsize = _ALIGN(loadinfo->memsize,(1<<20)) + 0x100000;
1137 /* Claim OF memory */
1138 DEBUG_F("Before prom_claim, mem_sz: 0x%08lx\n", loadinfo->memsize);
1140 /* Determine whether we are trying to boot a vmlinux or some
1141 * other binary image (eg, zImage). We load vmlinux's at
1142 * KERNELADDR and all other binaries at their e_entry value.
1144 if (e->e_entry == KERNEL_LINK_ADDR_PPC32) {
1146 loadaddr = KERNELADDR;
1149 loadaddr = e->e_entry;
1152 /* On some systems, loadaddr may already be claimed, so try some
1153 * other nearby addresses before giving up.
1155 for(addr=loadaddr; addr <= loadaddr * 8 ;addr+=0x100000) {
1156 loadinfo->base = prom_claim((void *)addr, loadinfo->memsize, 0);
1157 if (loadinfo->base != (void *)-1) break;
1159 if (loadinfo->base == (void *)-1) {
1160 prom_printf("Claim error, can't allocate kernel memory\n");
1164 DEBUG_F("After ELF parsing, load base: %p, mem_sz: 0x%08lx\n",
1165 loadinfo->base, loadinfo->memsize);
1166 DEBUG_F(" wanted load base: 0x%08lx, mem_sz: 0x%08lx\n",
1167 loadaddr, loadinfo->memsize);
1169 /* Load the program segments... */
1171 for (i = 0; i < e->e_phnum; ++i, ++p) {
1172 unsigned long offset;
1173 if (p->p_type != PT_LOAD || p->p_offset == 0)
1176 /* Now, we skip to the image itself */
1177 if ((*(file->fs->seek))(file, p->p_offset) != FILE_ERR_OK) {
1178 prom_printf ("Seek error\n");
1179 prom_release(loadinfo->base, loadinfo->memsize);
1182 offset = p->p_vaddr - loadinfo->load_loc;
1183 if ((*(file->fs->read))(file, p->p_filesz, loadinfo->base+offset) != p->p_filesz) {
1184 prom_printf ("Read failed\n");
1185 prom_release(loadinfo->base, loadinfo->memsize);
1192 /* Return success at loading the Elf32 kernel */
1197 load_elf64(struct boot_file_t *file, loadinfo_t *loadinfo)
1200 Elf64_Ehdr *e = &(loadinfo->elf.elf64hdr);
1202 int size = sizeof(Elf64_Ehdr) - sizeof(Elf_Ident);
1203 unsigned long addr, loadaddr;
1205 /* Read the rest of the Elf header... */
1206 if ((*(file->fs->read))(file, size, &e->e_version) < size) {
1207 prom_printf("\nCan't read Elf64 image header\n");
1211 DEBUG_F("Elf64 header:\n");
1212 DEBUG_F(" e.e_type = %d\n", (int)e->e_type);
1213 DEBUG_F(" e.e_machine = %d\n", (int)e->e_machine);
1214 DEBUG_F(" e.e_version = %d\n", (int)e->e_version);
1215 DEBUG_F(" e.e_entry = 0x%016lx\n", (long)e->e_entry);
1216 DEBUG_F(" e.e_phoff = 0x%016lx\n", (long)e->e_phoff);
1217 DEBUG_F(" e.e_shoff = 0x%016lx\n", (long)e->e_shoff);
1218 DEBUG_F(" e.e_flags = %d\n", (int)e->e_flags);
1219 DEBUG_F(" e.e_ehsize = 0x%08x\n", (int)e->e_ehsize);
1220 DEBUG_F(" e.e_phentsize = 0x%08x\n", (int)e->e_phentsize);
1221 DEBUG_F(" e.e_phnum = %d\n", (int)e->e_phnum);
1223 loadinfo->entry = e->e_entry;
1225 if (e->e_phnum > MAX_HEADERS) {
1226 prom_printf ("Can only load kernels with one program header\n");
1230 ph = (Elf64_Phdr *)malloc(sizeof(Elf64_Phdr) * e->e_phnum);
1232 prom_printf ("Malloc error\n");
1236 /* Now, we read the section header */
1237 if ((*(file->fs->seek))(file, e->e_phoff) != FILE_ERR_OK) {
1238 prom_printf ("Seek error\n");
1241 if ((*(file->fs->read))(file, sizeof(Elf64_Phdr) * e->e_phnum, ph) !=
1242 sizeof(Elf64_Phdr) * e->e_phnum) {
1243 prom_printf ("Read error\n");
1247 /* Scan through the program header
1248 * HACK: We must return the _memory size of the kernel image, not the
1249 * file size (because we have to leave room before other boot
1250 * infos. This code works as a side effect of the fact that
1251 * we have one section and vaddr == p_paddr
1253 loadinfo->memsize = loadinfo->filesize = loadinfo->offset = 0;
1255 for (i = 0; i < e->e_phnum; ++i, ++p) {
1256 if (p->p_type != PT_LOAD || p->p_offset == 0)
1258 if (loadinfo->memsize == 0) {
1259 loadinfo->offset = p->p_offset;
1260 loadinfo->memsize = p->p_memsz;
1261 loadinfo->filesize = p->p_filesz;
1262 loadinfo->load_loc = p->p_vaddr;
1264 loadinfo->memsize = p->p_offset + p->p_memsz - loadinfo->offset; /* XXX Bogus */
1265 loadinfo->filesize = p->p_offset + p->p_filesz - loadinfo->offset;
1269 if (loadinfo->memsize == 0) {
1270 prom_printf("Can't find a loadable segment !\n");
1274 /* leave some room (1Mb) for boot infos */
1275 loadinfo->memsize = _ALIGN(loadinfo->memsize,(1<<20)) + 0x100000;
1276 /* Claim OF memory */
1277 DEBUG_F("Before prom_claim, mem_sz: 0x%08lx\n", loadinfo->memsize);
1279 /* Determine whether we are trying to boot a vmlinux or some
1280 * other binary image (eg, zImage). We load vmlinux's at
1281 * KERNELADDR and all other binaries at their e_entry value.
1283 if (e->e_entry == KERNEL_LINK_ADDR_PPC64) {
1285 loadaddr = KERNELADDR;
1288 loadaddr = e->e_entry;
1291 /* On some systems, loadaddr may already be claimed, so try some
1292 * other nearby addresses before giving up.
1294 for(addr=loadaddr; addr <= loadaddr * 8 ;addr+=0x100000) {
1295 loadinfo->base = prom_claim((void *)addr, loadinfo->memsize, 0);
1296 if (loadinfo->base != (void *)-1) break;
1298 if (loadinfo->base == (void *)-1) {
1299 prom_printf("Claim error, can't allocate kernel memory\n");
1303 DEBUG_F("After ELF parsing, load base: %p, mem_sz: 0x%08lx\n",
1304 loadinfo->base, loadinfo->memsize);
1305 DEBUG_F(" wanted load base: 0x%08lx, mem_sz: 0x%08lx\n",
1306 loadaddr, loadinfo->memsize);
1308 /* Load the program segments... */
1310 for (i = 0; i < e->e_phnum; ++i, ++p) {
1311 unsigned long offset;
1312 if (p->p_type != PT_LOAD || p->p_offset == 0)
1315 /* Now, we skip to the image itself */
1316 if ((*(file->fs->seek))(file, p->p_offset) != FILE_ERR_OK) {
1317 prom_printf ("Seek error\n");
1318 prom_release(loadinfo->base, loadinfo->memsize);
1321 offset = p->p_vaddr - loadinfo->load_loc;
1322 if ((*(file->fs->read))(file, p->p_filesz, loadinfo->base+offset) != p->p_filesz) {
1323 prom_printf ("Read failed\n");
1324 prom_release(loadinfo->base, loadinfo->memsize);
1331 /* Return success at loading the Elf64 kernel */
1336 is_elf32(loadinfo_t *loadinfo)
1338 Elf32_Ehdr *e = &(loadinfo->elf.elf32hdr);
1340 return (e->e_ident[EI_MAG0] == ELFMAG0 &&
1341 e->e_ident[EI_MAG1] == ELFMAG1 &&
1342 e->e_ident[EI_MAG2] == ELFMAG2 &&
1343 e->e_ident[EI_MAG3] == ELFMAG3 &&
1344 e->e_ident[EI_CLASS] == ELFCLASS32 &&
1345 e->e_ident[EI_DATA] == ELFDATA2MSB &&
1346 e->e_type == ET_EXEC &&
1347 e->e_machine == EM_PPC);
1351 is_elf64(loadinfo_t *loadinfo)
1353 Elf64_Ehdr *e = &(loadinfo->elf.elf64hdr);
1355 return (e->e_ident[EI_MAG0] == ELFMAG0 &&
1356 e->e_ident[EI_MAG1] == ELFMAG1 &&
1357 e->e_ident[EI_MAG2] == ELFMAG2 &&
1358 e->e_ident[EI_MAG3] == ELFMAG3 &&
1359 e->e_ident[EI_CLASS] == ELFCLASS64 &&
1360 e->e_ident[EI_DATA] == ELFDATA2MSB &&
1361 e->e_type == ET_EXEC &&
1362 e->e_machine == EM_PPC64);
1368 #ifdef CONFIG_SET_COLORMAP
1369 static unsigned char default_colors[] = {
1388 prom_handle scrn = PROM_INVALID_HANDLE;
1390 /* Try Apple's mac-boot screen ihandle */
1391 result = (int)call_prom_return("interpret", 1, 2,
1392 "\" _screen-ihandle\" $find if execute else 0 then", &scrn);
1393 DEBUG_F("Trying to get screen ihandle, result: %d, scrn: %p\n", result, scrn);
1395 if (scrn == 0 || scrn == PROM_INVALID_HANDLE) {
1397 /* Hrm... check to see if stdout is a display */
1398 scrn = call_prom ("instance-to-package", 1, 1, prom_stdout);
1399 DEBUG_F("instance-to-package of stdout is: %p\n", scrn);
1400 if (prom_getprop(scrn, "device_type", type, 32) > 0 && !strncmp(type, "display", 7)) {
1401 DEBUG_F("got it ! stdout is a screen\n");
1404 /* Else, we try to open the package */
1405 scrn = (prom_handle)call_prom( "open", 1, 1, "screen" );
1406 DEBUG_F("Open screen result: %p\n", scrn);
1410 if (scrn == PROM_INVALID_HANDLE) {
1411 prom_printf("No screen device found !/n");
1415 prom_set_color(scrn, i, default_colors[i*3],
1416 default_colors[i*3+1], default_colors[i*3+2]);
1418 prom_printf("\x1b[1;37m\x1b[2;40m");
1420 for (i=0;i<16; i++) {
1421 prom_printf("\x1b[%d;%dm\x1b[1;47m%s \x1b[2;40m %s\n",
1422 ansi_color_table[i].index,
1423 ansi_color_table[i].value,
1424 ansi_color_table[i].name,
1425 ansi_color_table[i].name);
1426 prom_printf("\x1b[%d;%dm\x1b[1;37m%s \x1b[2;30m %s\n",
1427 ansi_color_table[i].index,
1428 ansi_color_table[i].value+10,
1429 ansi_color_table[i].name,
1430 ansi_color_table[i].name);
1432 prom_printf("\x1b[1;37m\x1b[2;40m");
1433 #endif /* COLOR_TEST */
1439 #endif /* CONFIG_SET_COLORMAP */
1447 if (_machine == _MACH_Pmac)
1450 prom_get_chosen("bootpath", bootdevice, sizeof(bootdevice));
1451 DEBUG_F("/chosen/bootpath = %s\n", bootdevice);
1452 if (bootdevice[0] == 0) {
1453 prom_get_options("boot-device", bootdevice, sizeof(bootdevice));
1454 DEBUG_F("boot-device = %s\n", bootdevice);
1456 if (bootdevice[0] == 0) {
1457 prom_printf("Couldn't determine boot device\n");
1461 if (!parse_device_path(bootdevice, NULL, -1, "", &boot)) {
1462 prom_printf("%s: Unable to parse\n", bootdevice);
1465 DEBUG_F("After parse_device_path: dev=%s, part=%d, file=%s\n",
1466 boot.dev, boot.part, boot.file);
1468 if (strlen(boot.file)) {
1469 if (!strncmp(boot.file, "\\\\", 2))
1473 p = last = boot.file;
1483 if (strlen(boot.file))
1484 strcat(boot.file, "\\");
1487 DEBUG_F("After pmac path kludgeup: dev=%s, part=%d, file=%s\n",
1488 boot.dev, boot.part, boot.file);
1490 useconf = load_config_file(boot.dev, boot.file, boot.part);
1492 prom_printf("Welcome to yaboot version " VERSION "\n");
1493 prom_printf("Enter \"help\" to get some basic usage information\n");
1495 /* I am fed up with lusers using the wrong partition type and
1496 mailing me *when* it breaks */
1498 if (_machine == _MACH_Pmac) {
1499 char *entry = cfg_get_strg(0, "ptypewarning");
1502 warn = strcmp(entry,
1503 "I_know_the_partition_type_is_wrong_and_will_NOT_send_mail_when_booting_breaks");
1505 ptype = get_part_type(boot.dev, boot.part);
1506 if ((ptype != NULL) && (strcmp(ptype, "Apple_Bootstrap")))
1507 prom_printf("\nWARNING: Bootstrap partition type is wrong: \"%s\"\n"
1508 " type should be: \"Apple_Bootstrap\"\n\n", ptype);
1514 prom_printf("Bye.\n");
1520 * c-file-style: "k&r"