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 */
259 void print_message_file(char *filename)
263 char *defdev = boot.dev;
264 int defpart = boot.part;
269 struct boot_file_t file;
270 struct boot_fspec_t msgfile;
272 defdev = cfg_get_strg(0, "device");
275 p = cfg_get_strg(0, "partition");
277 n = simple_strtol(p, &endp, 10);
278 if (endp != p && *endp == 0)
282 strncpy(msgpath, filename, sizeof(msgpath));
283 if (!parse_device_path(msgpath, defdev, defpart, "/etc/yaboot.msg", &msgfile)) {
284 prom_printf("%s: Unable to parse\n", msgpath);
288 result = open_file(&msgfile, &file);
289 if (result != FILE_ERR_OK) {
290 prom_printf("%s:%d,", msgfile.dev, msgfile.part);
291 prom_perror(result, msgfile.file);
300 memset(msg, 0, 2001);
302 if (file.fs->read(&file, 2000, msg) <= 0)
305 prom_printf("%s", msg);
309 file.fs->close(&file);
314 /* Currently, the config file must be at the root of the filesystem.
315 * todo: recognize the full path to myself and use it to load the
316 * config file. Handle the "\\" (blessed system folder)
319 load_config_file(char *device, char* path, int partition)
321 char *conf_file = NULL, *p;
322 struct boot_file_t file;
323 int sz, opened = 0, result = 0;
325 struct boot_fspec_t fspec;
327 /* Allocate a buffer for the config file */
328 conf_file = malloc(CONFIG_FILE_MAX);
330 prom_printf("Can't alloc config file buffer\n");
334 /* Build the path to the file */
336 strcpy(conf_path, path);
337 else if ( _machine == _MACH_chrp )
338 strcpy(conf_path, "/etc/");
341 strcat(conf_path, CONFIG_FILE_NAME);
345 fspec.file = conf_path;
346 fspec.part = partition;
347 result = open_file(&fspec, &file);
348 if (result != FILE_ERR_OK) {
349 prom_printf("%s:%d,", fspec.dev, fspec.part);
350 prom_perror(result, fspec.file);
351 prom_printf("Can't open config file\n");
357 sz = file.fs->read(&file, CONFIG_FILE_MAX, conf_file);
359 prom_printf("Error, can't read config file\n");
362 prom_printf("Config file read, %d bytes\n", sz);
366 file.fs->close(&file);
369 /* Call the parsing code in cfg.c */
370 if (cfg_parse(conf_path, conf_file, sz) < 0) {
371 prom_printf ("Syntax error or read error config\n");
375 DEBUG_F("Config file successfully parsed, %d bytes\n", sz);
377 /* Now, we do the initialisations stored in the config file */
378 p = cfg_get_strg(0, "init-code");
382 password = cfg_get_strg(0, "password");
384 #ifdef CONFIG_COLOR_TEXT
385 p = cfg_get_strg(0, "fgcolor");
387 DEBUG_F("fgcolor=%s\n", p);
388 fgcolor = check_color_text_ui(p);
390 prom_printf("Invalid fgcolor: \"%s\".\n", p);
393 p = cfg_get_strg(0, "bgcolor");
395 DEBUG_F("bgcolor=%s\n", p);
396 bgcolor = check_color_text_ui(p);
398 prom_printf("Invalid bgcolor: \"%s\".\n", p);
402 sprintf(temp, "%x to background-color", bgcolor);
403 prom_interpret(temp);
410 sprintf(temp, "%x to foreground-color", fgcolor);
411 prom_interpret(temp);
413 #endif /* CONFIG_COLOR_TEXT */
415 p = cfg_get_strg(0, "init-message");
417 prom_printf("%s\n", p);
419 p = cfg_get_strg(0, "message");
421 print_message_file(p);
428 file.fs->close(&file);
430 if (result != 1 && conf_file)
436 void maintabfunc (void)
440 prom_printf("boot: %s", cbuff);
445 word_split(char **linep, char **paramsp)
460 while (*p != 0 && *p != ' ')
469 make_params(char *label, char *params)
472 static char buffer[2048];
477 p = cfg_get_strg(label, "literal");
489 p = cfg_get_strg(label, "root");
496 if (cfg_get_flag(label, "read-only")) {
500 if (cfg_get_flag(label, "read-write")) {
504 p = cfg_get_strg(label, "ramdisk");
506 strcpy (q, "ramdisk=");
511 p = cfg_get_strg(label, "initrd-size");
513 strcpy (q, "ramdisk_size=");
518 if (cfg_get_flag(label, "novideo")) {
519 strcpy (q, "video=ofonly");
523 p = cfg_get_strg (label, "append");
530 pause_after = cfg_get_flag (label, "pause-after");
531 p = cfg_get_strg(label, "pause-message");
540 void check_password(char *str)
544 for (i = 0; i < 3; i++) {
545 prom_printf ("\n%sassword: ", str);
547 cmdedit ((void (*)(void)) 0, 1);
549 #ifdef USE_MD5_PASSWORDS
550 if (!strncmp (password, "$1$", 3)) {
551 if (!check_md5_password(passwdbuff, password))
554 else if (!strcmp (password, passwdbuff))
557 if (!strcmp (password, passwdbuff))
559 #endif /* USE_MD5_PASSWORDS */
561 prom_printf ("Password incorrect. Please try again...");
563 prom_printf ("Seems like you don't know the access password. Go away!\n");
565 prom_interpret("reset-all");
568 int get_params(struct boot_param_t* params)
574 char *imagename = 0, *label;
579 static int first = 1;
580 static char bootargs[1024];
581 static char imagepath[1024];
582 static char initrdpath[1024];
583 static char sysmappath[1024];
586 memset(params, 0, sizeof(*params));
588 params->kernel.part = -1;
589 params->rd.part = -1;
590 params->sysmap.part = -1;
597 prom_get_chosen("bootargs", bootargs, sizeof(bootargs));
598 imagename = bootargs;
599 word_split(&imagename, ¶ms->args);
600 timeout = DEFAULT_TIMEOUT;
602 prom_printf("Default supplied on the command line: %s ", imagename);
604 prom_printf("%s", params->args);
607 if (useconf && (q = cfg_get_strg(0, "timeout")) != 0 && *q != 0)
608 timeout = simple_strtol(q, NULL, 0);
611 prom_printf("boot: ");
616 end = beg + 100 * timeout;
618 c = prom_nbgetchar();
619 } while (c == -1 && prom_getms() <= end);
623 else if (c != '\n' && c != '\t' && c != '\r' && c != '\b' ) {
629 if (c != -1 && c != '\n' && c != '\r') {
632 } else if (c >= ' ') {
635 if ((cfg_get_flag (cbuff, "single-key")) && useconf) {
638 prom_printf("%s\n", cbuff);
643 if (c == '\n' || c == '\r') {
645 imagename = cfg_get_default();
647 prom_printf("%s", imagename);
649 prom_printf(" %s", params->args);
651 } else if (!singlekey) {
652 cmdedit(maintabfunc, 0);
654 strcpy(given_bootargs, cbuff);
655 given_bootargs_by_user = 1;
657 word_split(&imagename, ¶ms->args);
660 /* chrp gets this wrong, force it -- Cort */
661 if ( useconf && (!imagename || imagename[0] == 0 ))
662 imagename = cfg_get_default();
665 defdevice = boot.dev;
668 defdevice = cfg_get_strg(0, "device");
669 p = cfg_get_strg(0, "partition");
671 n = simple_strtol(p, &endp, 10);
672 if (endp != p && *endp == 0)
675 p = cfg_get_strg(0, "pause-message");
678 if (cfg_get_flag(0, "restricted"))
680 p = cfg_get_strg(imagename, "image");
684 defdevice = cfg_get_strg(label, "device");
685 if(!defdevice) defdevice=boot.dev;
686 p = cfg_get_strg(label, "partition");
688 n = simple_strtol(p, &endp, 10);
689 if (endp != p && *endp == 0)
692 if (cfg_get_flag(label, "restricted"))
695 if (params->args && password && restricted)
696 check_password ("To specify image arguments you must enter the p");
697 else if (password && !restricted)
698 check_password ("P");
700 params->args = make_params(label, params->args);
704 if (!strcmp (imagename, "help")) {
706 "\nPress the tab key for a list of defined images.\n"
707 "The label marked with a \"*\" is is the default image, "
708 "press <return> to boot it.\n\n"
709 "To boot any other label simply type its name and press <return>.\n\n"
710 "To boot a kernel image which is not defined in the yaboot configuration \n"
711 "file, enter the kernel image name as [[device:][partno],]/path, where \n"
712 "\"device:\" is the OpenFirmware device path to the disk the image \n"
713 "resides on, and \"partno\" is the partition number the image resides on.\n"
714 "Note that the comma (,) is only required if you specify an OpenFirmware\n"
715 "device, if you only specify a filename you should not start it with a \",\"\n\n"
716 "If you omit \"device:\" and \"partno\" yaboot will use the values of \n"
717 "\"device=\" and \"partition=\" in yaboot.conf, right now those are set to: \n"
719 "partition=%d\n\n", defdevice, defpart);
723 if (!strcmp (imagename, "halt")) {
725 check_password ("P");
729 if (!strcmp (imagename, "bye")) {
731 check_password ("P");
737 if (imagename[0] == '$') {
738 /* forth command string */
740 check_password ("P");
741 prom_interpret(imagename+1);
745 strncpy(imagepath, imagename, 1024);
747 if (!label && password)
748 check_password ("To boot a custom image you must enter the p");
750 if (!parse_device_path(imagepath, defdevice, defpart,
751 "/vmlinux", ¶ms->kernel)) {
752 prom_printf("%s: Unable to parse\n", imagepath);
755 DEBUG_F("after parse_device_path: dev=%s part=%d file=%s\n", params->kernel.dev,
756 params->kernel.part, params->kernel.file);
759 p = cfg_get_strg(label, "initrd");
761 DEBUG_F("Parsing initrd path <%s>\n", p);
762 strncpy(initrdpath, p, 1024);
763 if (!parse_device_path(initrdpath, defdevice, defpart,
764 "/root.bin", ¶ms->rd)) {
765 prom_printf("%s: Unable to parse\n", imagepath);
769 p = cfg_get_strg(label, "sysmap");
771 DEBUG_F("Parsing sysmap path <%s>\n", p);
772 strncpy(sysmappath, p, 1024);
773 if (!parse_device_path(sysmappath, defdevice, defpart,
774 "/boot/System.map", ¶ms->sysmap)) {
775 prom_printf("%s: Unable to parse\n", imagepath);
783 /* This is derived from quik core. To be changed to first parse the headers
784 * doing lazy-loading, and then claim the memory before loading the kernel
786 * We also need to add initrd support to this whole mecanism
791 #define MAX_HEADERS 32
793 struct boot_file_t file;
795 static struct boot_param_t params;
797 unsigned long initrd_size;
799 unsigned long sysmap_size;
800 kernel_entry_t kernel_entry;
801 struct bi_record* birec;
804 void *initrd_more,*initrd_want;
805 unsigned long initrd_read;
807 loadinfo.load_loc = 0;
815 if (get_params(¶ms))
817 if (!params.kernel.file)
820 prom_printf("Please wait, loading kernel...\n");
822 memset(&file, 0, sizeof(file));
824 if (strlen(boot.file) && !strcmp(boot.file,"\\\\") && params.kernel.file[0] != '/'
825 && params.kernel.file[0] != '\\') {
826 loc=(char*)malloc(strlen(params.kernel.file)+3);
828 prom_printf ("malloc error\n");
831 strcpy(loc,boot.file);
832 strcat(loc,params.kernel.file);
833 free(params.kernel.file);
834 params.kernel.file=loc;
836 result = open_file(¶ms.kernel, &file);
837 if (result != FILE_ERR_OK) {
838 prom_printf("%s:%d,", params.kernel.dev, params.kernel.part);
839 prom_perror(result, params.kernel.file);
843 /* Read the Elf e_ident, e_type and e_machine fields to
844 * determine Elf file type
846 if (file.fs->read(&file, sizeof(Elf_Ident), &loadinfo.elf) < sizeof(Elf_Ident)) {
847 prom_printf("\nCan't read Elf e_ident/e_type/e_machine info\n");
848 file.fs->close(&file);
849 memset(&file, 0, sizeof(file));
853 if (is_elf32(&loadinfo)) {
854 if (!load_elf32(&file, &loadinfo)) {
855 file.fs->close(&file);
856 memset(&file, 0, sizeof(file));
859 prom_printf(" Elf32 kernel loaded...\n");
860 } else if (is_elf64(&loadinfo)) {
861 if (!load_elf64(&file, &loadinfo)) {
862 file.fs->close(&file);
863 memset(&file, 0, sizeof(file));
866 prom_printf(" Elf64 kernel loaded...\n");
868 prom_printf ("%s: Not a valid ELF image\n", params.kernel.file);
869 file.fs->close(&file);
870 memset(&file, 0, sizeof(file));
873 file.fs->close(&file);
874 memset(&file, 0, sizeof(file));
876 /* If sysmap, load it.
878 if (params.sysmap.file) {
879 prom_printf("Loading System.map ...\n");
880 if(strlen(boot.file) && !strcmp(boot.file,"\\\\") && params.sysmap.file[0] != '/'
881 && params.sysmap.file[0] != '\\') {
883 loc=(char*)malloc(strlen(params.sysmap.file)+3);
885 prom_printf ("malloc error\n");
888 strcpy(loc,boot.file);
889 strcat(loc,params.sysmap.file);
890 free(params.sysmap.file);
891 params.sysmap.file=loc;
894 result = open_file(¶ms.sysmap, &file);
895 if (result != FILE_ERR_OK) {
896 prom_printf("%s:%d,", params.sysmap.dev, params.sysmap.part);
897 prom_perror(result, params.sysmap.file);
900 sysmap_base = prom_claim(loadinfo.base+loadinfo.memsize, 0x100000, 0);
901 if (sysmap_base == (void *)-1) {
902 prom_printf("Claim failed for sysmap memory\n");
905 sysmap_size = file.fs->read(&file, 0xfffff, sysmap_base);
906 if (sysmap_size == 0)
909 ((char *)sysmap_base)[sysmap_size++] = 0;
911 file.fs->close(&file);
912 memset(&file, 0, sizeof(file));
915 prom_printf("System.map loaded at %p, size: %lu Kbytes\n",
916 sysmap_base, sysmap_size >> 10);
917 loadinfo.memsize += _ALIGN(0x100000, 0x1000);
919 prom_printf("System.map load failed !\n");
924 /* If ramdisk, load it. For now, we can't tell the size it will be
925 * so we claim an arbitrary amount of 4Mb
927 if (params.rd.file) {
928 if(strlen(boot.file) && !strcmp(boot.file,"\\\\") && params.rd.file[0] != '/'
929 && params.kernel.file[0] != '\\')
932 loc=(char*)malloc(strlen(params.rd.file)+3);
934 prom_printf ("Malloc error\n");
937 strcpy(loc,boot.file);
938 strcat(loc,params.rd.file);
939 free(params.rd.file);
942 prom_printf("Loading ramdisk...\n");
943 result = open_file(¶ms.rd, &file);
944 if (result != FILE_ERR_OK) {
945 prom_printf("%s:%d,", params.rd.dev, params.rd.part);
946 prom_perror(result, params.rd.file);
949 #define INITRD_CHUNKSIZE 0x400000
950 initrd_base = prom_claim(loadinfo.base+loadinfo.memsize, INITRD_CHUNKSIZE, 0);
951 if (initrd_base == (void *)-1) {
952 prom_printf("Claim failed for initrd memory\n");
955 initrd_size = file.fs->read(&file, INITRD_CHUNKSIZE, initrd_base);
956 if (initrd_size == 0)
958 initrd_read = initrd_size;
959 initrd_more = initrd_base;
960 while (initrd_read == INITRD_CHUNKSIZE ) { /* need to read more? */
961 initrd_want = (void *)((unsigned long)initrd_more+INITRD_CHUNKSIZE);
962 initrd_more = prom_claim(initrd_want, INITRD_CHUNKSIZE, 0);
963 if (initrd_more != initrd_want) {
964 prom_printf("Claim failed for initrd memory at %p rc=%p\n",initrd_want,initrd_more);
967 initrd_read = file.fs->read(&file, INITRD_CHUNKSIZE, initrd_more);
968 DEBUG_F(" block at %p rc=%lu\n",initrd_more,initrd_read);
969 initrd_size += initrd_read;
972 file.fs->close(&file);
973 memset(&file, 0, sizeof(file));
976 prom_printf("ramdisk loaded at %p, size: %lu Kbytes\n",
977 initrd_base, initrd_size >> 10);
979 prom_printf("ramdisk load failed !\n");
984 DEBUG_F("setting kernel args to: %s\n", params.args);
985 prom_setargs(params.args);
986 DEBUG_F("flushing icache...");
987 flush_icache_range ((long)loadinfo.base, (long)loadinfo.base+loadinfo.memsize);
991 * Fill mew boot infos
993 * The birec is low on memory, probably inside the malloc pool, so
994 * we don't write it earlier. At this point, we should not use anything
995 * coming from the malloc pool
997 birec = (struct bi_record *)_ALIGN(loadinfo.filesize+(1<<20)-1,(1<<20));
999 /* We make sure it's mapped. We map only 64k for now, it's plenty enough
1000 * we don't claim since this precise memory range may already be claimed
1001 * by the malloc pool
1003 prom_map (birec, birec, 0x10000);
1004 DEBUG_F("birec at %p\n", birec);
1007 birec->tag = BI_FIRST;
1008 birec->size = sizeof(struct bi_record);
1009 birec = (struct bi_record *)((unsigned long)birec + birec->size);
1011 birec->tag = BI_BOOTLOADER_ID;
1012 sprintf( (char *)birec->data, "yaboot");
1013 birec->size = sizeof(struct bi_record) + strlen("yaboot") + 1;
1014 birec = (struct bi_record *)((unsigned long)birec + birec->size);
1016 birec->tag = BI_MACHTYPE;
1017 birec->data[0] = _machine;
1018 birec->size = sizeof(struct bi_record) + sizeof(unsigned long);
1019 birec = (struct bi_record *)((unsigned long)birec + birec->size);
1022 birec->tag = BI_SYSMAP;
1023 birec->data[0] = (unsigned long)sysmap_base;
1024 birec->data[1] = sysmap_size;
1025 birec->size = sizeof(struct bi_record) + sizeof(unsigned long)*2;
1026 birec = (struct bi_record *)((unsigned long)birec + birec->size);
1028 birec->tag = BI_LAST;
1029 birec->size = sizeof(struct bi_record);
1030 birec = (struct bi_record *)((unsigned long)birec + birec->size);
1032 /* compute the kernel's entry point. */
1033 kernel_entry = loadinfo.base + loadinfo.entry - loadinfo.load_loc;
1035 DEBUG_F("Kernel entry point = %p\n", kernel_entry);
1036 DEBUG_F("kernel: arg1 = %p,\n"
1037 " arg2 = 0x%08lx,\n"
1041 initrd_base + loadinfo.load_loc, initrd_size, prom, 0, 0);
1043 DEBUG_F("Entering kernel...\n");
1045 /* call the kernel with our stack. */
1046 kernel_entry(initrd_base + loadinfo.load_loc, initrd_size, prom, 0, 0);
1054 load_elf32(struct boot_file_t *file, loadinfo_t *loadinfo)
1057 Elf32_Ehdr *e = &(loadinfo->elf.elf32hdr);
1059 int size = sizeof(Elf32_Ehdr) - sizeof(Elf_Ident);
1060 unsigned long addr, loadaddr;
1062 /* Read the rest of the Elf header... */
1063 if ((*(file->fs->read))(file, size, &e->e_version) < size) {
1064 prom_printf("\nCan't read Elf32 image header\n");
1068 DEBUG_F("Elf32 header:\n");
1069 DEBUG_F(" e.e_type = %d\n", (int)e->e_type);
1070 DEBUG_F(" e.e_machine = %d\n", (int)e->e_machine);
1071 DEBUG_F(" e.e_version = %d\n", (int)e->e_version);
1072 DEBUG_F(" e.e_entry = 0x%08x\n", (int)e->e_entry);
1073 DEBUG_F(" e.e_phoff = 0x%08x\n", (int)e->e_phoff);
1074 DEBUG_F(" e.e_shoff = 0x%08x\n", (int)e->e_shoff);
1075 DEBUG_F(" e.e_flags = %d\n", (int)e->e_flags);
1076 DEBUG_F(" e.e_ehsize = 0x%08x\n", (int)e->e_ehsize);
1077 DEBUG_F(" e.e_phentsize = 0x%08x\n", (int)e->e_phentsize);
1078 DEBUG_F(" e.e_phnum = %d\n", (int)e->e_phnum);
1080 loadinfo->entry = e->e_entry;
1082 if (e->e_phnum > MAX_HEADERS) {
1083 prom_printf ("Can only load kernels with one program header\n");
1087 ph = (Elf32_Phdr *)malloc(sizeof(Elf32_Phdr) * e->e_phnum);
1089 prom_printf ("Malloc error\n");
1093 /* Now, we read the section header */
1094 if ((*(file->fs->seek))(file, e->e_phoff) != FILE_ERR_OK) {
1095 prom_printf ("seek error\n");
1098 if ((*(file->fs->read))(file, sizeof(Elf32_Phdr) * e->e_phnum, ph) !=
1099 sizeof(Elf32_Phdr) * e->e_phnum) {
1100 prom_printf ("read error\n");
1104 /* Scan through the program header
1105 * HACK: We must return the _memory size of the kernel image, not the
1106 * file size (because we have to leave room before other boot
1107 * infos. This code works as a side effect of the fact that
1108 * we have one section and vaddr == p_paddr
1110 loadinfo->memsize = loadinfo->filesize = loadinfo->offset = 0;
1112 for (i = 0; i < e->e_phnum; ++i, ++p) {
1113 if (p->p_type != PT_LOAD || p->p_offset == 0)
1115 if (loadinfo->memsize == 0) {
1116 loadinfo->offset = p->p_offset;
1117 loadinfo->memsize = p->p_memsz;
1118 loadinfo->filesize = p->p_filesz;
1119 loadinfo->load_loc = p->p_vaddr;
1121 loadinfo->memsize = p->p_offset + p->p_memsz - loadinfo->offset; /* XXX Bogus */
1122 loadinfo->filesize = p->p_offset + p->p_filesz - loadinfo->offset;
1126 if (loadinfo->memsize == 0) {
1127 prom_printf("Can't find a loadable segment !\n");
1131 /* leave some room (1Mb) for boot infos */
1132 loadinfo->memsize = _ALIGN(loadinfo->memsize,(1<<20)) + 0x100000;
1133 /* Claim OF memory */
1134 DEBUG_F("Before prom_claim, mem_sz: 0x%08lx\n", loadinfo->memsize);
1136 /* On some systems, loadaddr may already be claimed, so try some
1137 * other nearby addresses before giving up.
1139 loadaddr = (e->e_entry == KERNEL_LINK_ADDR_PPC32 ||
1140 e->e_entry == 0) ? KERNELADDR : e->e_entry;
1141 for(addr=loadaddr; addr <= loadaddr * 8 ;addr+=0x100000) {
1142 loadinfo->base = prom_claim((void *)addr, loadinfo->memsize, 0);
1143 if (loadinfo->base != (void *)-1) break;
1145 if (loadinfo->base == (void *)-1) {
1146 prom_printf("Claim error, can't allocate kernel memory\n");
1150 DEBUG_F("After ELF parsing, load base: %p, mem_sz: 0x%08lx\n",
1151 loadinfo->base, loadinfo->memsize);
1152 DEBUG_F(" wanted load base: 0x%08lx, mem_sz: 0x%08lx\n",
1153 loadaddr, loadinfo->memsize);
1155 /* Load the program segments... */
1157 for (i = 0; i < e->e_phnum; ++i, ++p) {
1158 unsigned long offset;
1159 if (p->p_type != PT_LOAD || p->p_offset == 0)
1162 /* Now, we skip to the image itself */
1163 if ((*(file->fs->seek))(file, p->p_offset) != FILE_ERR_OK) {
1164 prom_printf ("Seek error\n");
1165 prom_release(loadinfo->base, loadinfo->memsize);
1168 offset = p->p_vaddr - loadinfo->load_loc;
1169 if ((*(file->fs->read))(file, p->p_filesz, loadinfo->base+offset) != p->p_filesz) {
1170 prom_printf ("Read failed\n");
1171 prom_release(loadinfo->base, loadinfo->memsize);
1178 /* Return success at loading the Elf32 kernel */
1183 load_elf64(struct boot_file_t *file, loadinfo_t *loadinfo)
1186 Elf64_Ehdr *e = &(loadinfo->elf.elf64hdr);
1188 int size = sizeof(Elf64_Ehdr) - sizeof(Elf_Ident);
1189 unsigned long addr, loadaddr;
1191 /* Read the rest of the Elf header... */
1192 if ((*(file->fs->read))(file, size, &e->e_version) < size) {
1193 prom_printf("\nCan't read Elf64 image header\n");
1197 DEBUG_F("Elf64 header:\n");
1198 DEBUG_F(" e.e_type = %d\n", (int)e->e_type);
1199 DEBUG_F(" e.e_machine = %d\n", (int)e->e_machine);
1200 DEBUG_F(" e.e_version = %d\n", (int)e->e_version);
1201 DEBUG_F(" e.e_entry = 0x%016lx\n", (long)e->e_entry);
1202 DEBUG_F(" e.e_phoff = 0x%016lx\n", (long)e->e_phoff);
1203 DEBUG_F(" e.e_shoff = 0x%016lx\n", (long)e->e_shoff);
1204 DEBUG_F(" e.e_flags = %d\n", (int)e->e_flags);
1205 DEBUG_F(" e.e_ehsize = 0x%08x\n", (int)e->e_ehsize);
1206 DEBUG_F(" e.e_phentsize = 0x%08x\n", (int)e->e_phentsize);
1207 DEBUG_F(" e.e_phnum = %d\n", (int)e->e_phnum);
1209 loadinfo->entry = e->e_entry;
1211 if (e->e_phnum > MAX_HEADERS) {
1212 prom_printf ("Can only load kernels with one program header\n");
1216 ph = (Elf64_Phdr *)malloc(sizeof(Elf64_Phdr) * e->e_phnum);
1218 prom_printf ("Malloc error\n");
1222 /* Now, we read the section header */
1223 if ((*(file->fs->seek))(file, e->e_phoff) != FILE_ERR_OK) {
1224 prom_printf ("Seek error\n");
1227 if ((*(file->fs->read))(file, sizeof(Elf64_Phdr) * e->e_phnum, ph) !=
1228 sizeof(Elf64_Phdr) * e->e_phnum) {
1229 prom_printf ("Read error\n");
1233 /* Scan through the program header
1234 * HACK: We must return the _memory size of the kernel image, not the
1235 * file size (because we have to leave room before other boot
1236 * infos. This code works as a side effect of the fact that
1237 * we have one section and vaddr == p_paddr
1239 loadinfo->memsize = loadinfo->filesize = loadinfo->offset = 0;
1241 for (i = 0; i < e->e_phnum; ++i, ++p) {
1242 if (p->p_type != PT_LOAD || p->p_offset == 0)
1244 if (loadinfo->memsize == 0) {
1245 loadinfo->offset = p->p_offset;
1246 loadinfo->memsize = p->p_memsz;
1247 loadinfo->filesize = p->p_filesz;
1248 loadinfo->load_loc = p->p_vaddr;
1250 loadinfo->memsize = p->p_offset + p->p_memsz - loadinfo->offset; /* XXX Bogus */
1251 loadinfo->filesize = p->p_offset + p->p_filesz - loadinfo->offset;
1255 if (loadinfo->memsize == 0) {
1256 prom_printf("Can't find a loadable segment !\n");
1260 /* leave some room (1Mb) for boot infos */
1261 loadinfo->memsize = _ALIGN(loadinfo->memsize,(1<<20)) + 0x100000;
1262 /* Claim OF memory */
1263 DEBUG_F("Before prom_claim, mem_sz: 0x%08lx\n", loadinfo->memsize);
1265 /* On some systems, loadaddr may already be claimed, so try some
1266 * other nearby addresses before giving up.
1268 loadaddr = (e->e_entry == KERNEL_LINK_ADDR_PPC64) ? KERNELADDR : e->e_entry;
1269 for(addr=loadaddr; addr <= loadaddr * 8 ;addr+=0x100000) {
1270 loadinfo->base = prom_claim((void *)addr, loadinfo->memsize, 0);
1271 if (loadinfo->base != (void *)-1) break;
1273 if (loadinfo->base == (void *)-1) {
1274 prom_printf("Claim error, can't allocate kernel memory\n");
1278 DEBUG_F("After ELF parsing, load base: %p, mem_sz: 0x%08lx\n",
1279 loadinfo->base, loadinfo->memsize);
1280 DEBUG_F(" wanted load base: 0x%08lx, mem_sz: 0x%08lx\n",
1281 loadaddr, loadinfo->memsize);
1283 /* Load the program segments... */
1285 for (i = 0; i < e->e_phnum; ++i, ++p) {
1286 unsigned long offset;
1287 if (p->p_type != PT_LOAD || p->p_offset == 0)
1290 /* Now, we skip to the image itself */
1291 if ((*(file->fs->seek))(file, p->p_offset) != FILE_ERR_OK) {
1292 prom_printf ("Seek error\n");
1293 prom_release(loadinfo->base, loadinfo->memsize);
1296 offset = p->p_vaddr - loadinfo->load_loc;
1297 if ((*(file->fs->read))(file, p->p_filesz, loadinfo->base+offset) != p->p_filesz) {
1298 prom_printf ("Read failed\n");
1299 prom_release(loadinfo->base, loadinfo->memsize);
1306 /* Return success at loading the Elf64 kernel */
1311 is_elf32(loadinfo_t *loadinfo)
1313 Elf32_Ehdr *e = &(loadinfo->elf.elf32hdr);
1315 return (e->e_ident[EI_MAG0] == ELFMAG0 &&
1316 e->e_ident[EI_MAG1] == ELFMAG1 &&
1317 e->e_ident[EI_MAG2] == ELFMAG2 &&
1318 e->e_ident[EI_MAG3] == ELFMAG3 &&
1319 e->e_ident[EI_CLASS] == ELFCLASS32 &&
1320 e->e_ident[EI_DATA] == ELFDATA2MSB &&
1321 e->e_type == ET_EXEC &&
1322 e->e_machine == EM_PPC);
1326 is_elf64(loadinfo_t *loadinfo)
1328 Elf64_Ehdr *e = &(loadinfo->elf.elf64hdr);
1330 return (e->e_ident[EI_MAG0] == ELFMAG0 &&
1331 e->e_ident[EI_MAG1] == ELFMAG1 &&
1332 e->e_ident[EI_MAG2] == ELFMAG2 &&
1333 e->e_ident[EI_MAG3] == ELFMAG3 &&
1334 e->e_ident[EI_CLASS] == ELFCLASS64 &&
1335 e->e_ident[EI_DATA] == ELFDATA2MSB &&
1336 e->e_type == ET_EXEC &&
1337 e->e_machine == EM_PPC64);
1343 #ifdef CONFIG_SET_COLORMAP
1344 static unsigned char default_colors[] = {
1363 prom_handle scrn = PROM_INVALID_HANDLE;
1365 /* Try Apple's mac-boot screen ihandle */
1366 result = (int)call_prom_return("interpret", 1, 2,
1367 "\" _screen-ihandle\" $find if execute else 0 then", &scrn);
1368 DEBUG_F("Trying to get screen ihandle, result: %d, scrn: %p\n", result, scrn);
1370 if (scrn == 0 || scrn == PROM_INVALID_HANDLE) {
1372 /* Hrm... check to see if stdout is a display */
1373 scrn = call_prom ("instance-to-package", 1, 1, prom_stdout);
1374 DEBUG_F("instance-to-package of stdout is: %p\n", scrn);
1375 if (prom_getprop(scrn, "device_type", type, 32) > 0 && !strncmp(type, "display", 7)) {
1376 DEBUG_F("got it ! stdout is a screen\n");
1379 /* Else, we try to open the package */
1380 scrn = (prom_handle)call_prom( "open", 1, 1, "screen" );
1381 DEBUG_F("Open screen result: %p\n", scrn);
1385 if (scrn == PROM_INVALID_HANDLE) {
1386 prom_printf("No screen device found !/n");
1390 prom_set_color(scrn, i, default_colors[i*3],
1391 default_colors[i*3+1], default_colors[i*3+2]);
1393 prom_printf("\x1b[1;37m\x1b[2;40m");
1395 for (i=0;i<16; i++) {
1396 prom_printf("\x1b[%d;%dm\x1b[1;47m%s \x1b[2;40m %s\n",
1397 ansi_color_table[i].index,
1398 ansi_color_table[i].value,
1399 ansi_color_table[i].name,
1400 ansi_color_table[i].name);
1401 prom_printf("\x1b[%d;%dm\x1b[1;37m%s \x1b[2;30m %s\n",
1402 ansi_color_table[i].index,
1403 ansi_color_table[i].value+10,
1404 ansi_color_table[i].name,
1405 ansi_color_table[i].name);
1407 prom_printf("\x1b[1;37m\x1b[2;40m");
1408 #endif /* COLOR_TEST */
1414 #endif /* CONFIG_SET_COLORMAP */
1422 if (_machine == _MACH_Pmac)
1425 prom_get_chosen("bootpath", bootdevice, sizeof(bootdevice));
1426 DEBUG_F("/chosen/bootpath = %s\n", bootdevice);
1427 if (bootdevice[0] == 0)
1428 prom_get_options("boot-device", bootdevice, sizeof(bootdevice));
1429 if (bootdevice[0] == 0) {
1430 prom_printf("Couldn't determine boot device\n");
1434 if (!parse_device_path(bootdevice, (_machine == _MACH_Pmac) ? "hd" : "disc",
1436 prom_printf("%s: Unable to parse\n", bootdevice);
1439 DEBUG_F("After parse_device_path: dev=%s, part=%d, file=%s\n",
1440 boot.dev, boot.part, boot.file);
1442 if (strlen(boot.file)) {
1443 if (!strncmp(boot.file, "\\\\", 2))
1447 p = last = boot.file;
1457 if (strlen(boot.file))
1458 strcat(boot.file, "\\");
1461 DEBUG_F("After path fixup: dev=%s, part=%d, file=%s\n",
1462 boot.dev, boot.part, boot.file);
1464 useconf = load_config_file(boot.dev, boot.file, boot.part);
1466 prom_printf("Welcome to yaboot version " VERSION "\n");
1467 prom_printf("Enter \"help\" to get some basic usage information\n");
1469 /* I am fed up with lusers using the wrong partition type and
1470 mailing me *when* it breaks */
1472 if (_machine == _MACH_Pmac) {
1473 char *entry = cfg_get_strg(0, "ptypewarning");
1476 warn = strcmp(entry,
1477 "I_know_the_partition_type_is_wrong_and_will_NOT_send_mail_when_booting_breaks");
1479 ptype = get_part_type(boot.dev, boot.part);
1480 if ((ptype != NULL) && (strcmp(ptype, "Apple_Bootstrap")))
1481 prom_printf("\nWARNING: Bootstrap partition type is wrong: \"%s\"\n"
1482 " type should be: \"Apple_Bootstrap\"\n\n", ptype);
1488 prom_printf("Bye.\n");
1494 * c-file-style: "k&r"