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 prom_printf("\n%s", str);
546 for (i = 0; i < 3; i++) {
547 prom_printf ("\nPassword: ");
549 cmdedit ((void (*)(void)) 0, 1);
551 #ifdef USE_MD5_PASSWORDS
552 if (!strncmp (password, "$1$", 3)) {
553 if (!check_md5_password(passwdbuff, password))
556 else if (!strcmp (password, passwdbuff))
559 if (!strcmp (password, passwdbuff))
561 #endif /* USE_MD5_PASSWORDS */
564 prom_printf ("Incorrect password. Try again.");
567 prom_printf(" ___________________\n< Permission denied >\n -------------------\n"
568 " \\ ^__^\n \\ (oo)\\_______\n (__)\\ )\\/\\\n"
569 " ||----w |\n || ||\n");
571 prom_interpret("reset-all");
574 int get_params(struct boot_param_t* params)
580 char *imagename = 0, *label;
585 static int first = 1;
586 static char bootargs[1024];
587 static char imagepath[1024];
588 static char initrdpath[1024];
589 static char sysmappath[1024];
592 memset(params, 0, sizeof(*params));
594 params->kernel.part = -1;
595 params->rd.part = -1;
596 params->sysmap.part = -1;
603 prom_get_chosen("bootargs", bootargs, sizeof(bootargs));
604 imagename = bootargs;
605 word_split(&imagename, ¶ms->args);
606 timeout = DEFAULT_TIMEOUT;
608 prom_printf("Default supplied on the command line: %s ", imagename);
610 prom_printf("%s", params->args);
613 if (useconf && (q = cfg_get_strg(0, "timeout")) != 0 && *q != 0)
614 timeout = simple_strtol(q, NULL, 0);
617 prom_printf("boot: ");
622 end = beg + 100 * timeout;
624 c = prom_nbgetchar();
625 } while (c == -1 && prom_getms() <= end);
629 else if (c != '\n' && c != '\t' && c != '\r' && c != '\b' ) {
635 if (c != -1 && c != '\n' && c != '\r') {
638 } else if (c >= ' ') {
641 if ((cfg_get_flag (cbuff, "single-key")) && useconf) {
644 prom_printf("%s\n", cbuff);
649 if (c == '\n' || c == '\r') {
651 imagename = cfg_get_default();
653 prom_printf("%s", imagename);
655 prom_printf(" %s", params->args);
657 } else if (!singlekey) {
658 cmdedit(maintabfunc, 0);
660 strcpy(given_bootargs, cbuff);
661 given_bootargs_by_user = 1;
663 word_split(&imagename, ¶ms->args);
666 /* chrp gets this wrong, force it -- Cort */
667 if ( useconf && (!imagename || imagename[0] == 0 ))
668 imagename = cfg_get_default();
671 defdevice = boot.dev;
674 defdevice = cfg_get_strg(0, "device");
675 p = cfg_get_strg(0, "partition");
677 n = simple_strtol(p, &endp, 10);
678 if (endp != p && *endp == 0)
681 p = cfg_get_strg(0, "pause-message");
684 if (cfg_get_flag(0, "restricted"))
686 p = cfg_get_strg(imagename, "image");
690 defdevice = cfg_get_strg(label, "device");
691 if(!defdevice) defdevice=boot.dev;
692 p = cfg_get_strg(label, "partition");
694 n = simple_strtol(p, &endp, 10);
695 if (endp != p && *endp == 0)
698 if (cfg_get_flag(label, "restricted"))
701 if (params->args && password && restricted)
702 check_password ("To specify arguments for this image "
703 "you must enter the password.");
704 else if (password && !restricted)
705 check_password ("This image is restricted.");
707 params->args = make_params(label, params->args);
711 if (!strcmp (imagename, "help")) {
712 /* FIXME: defdevice shouldn't need to be reset all over the place */
713 if(!defdevice) defdevice = boot.dev;
715 "\nPress the tab key for a list of defined images.\n"
716 "The label marked with a \"*\" is is the default image, "
717 "press <return> to boot it.\n\n"
718 "To boot any other label simply type its name and press <return>.\n\n"
719 "To boot a kernel image which is not defined in the yaboot configuration \n"
720 "file, enter the kernel image name as [[device:][partno],]/path, where \n"
721 "\"device:\" is the OpenFirmware device path to the disk the image \n"
722 "resides on, and \"partno\" is the partition number the image resides on.\n"
723 "Note that the comma (,) is only required if you specify an OpenFirmware\n"
724 "device, if you only specify a filename you should not start it with a \",\"\n\n"
725 "If you omit \"device:\" and \"partno\" yaboot will use the values of \n"
726 "\"device=\" and \"partition=\" in yaboot.conf, right now those are set to: \n"
728 "partition=%d\n\n", defdevice, defpart);
732 if (!strcmp (imagename, "halt")) {
734 check_password ("Restricted command.");
738 if (!strcmp (imagename, "bye")) {
740 check_password ("Restricted command.");
746 if (imagename[0] == '$') {
747 /* forth command string */
749 check_password ("OpenFirmware commands are restricted.");
750 prom_interpret(imagename+1);
754 strncpy(imagepath, imagename, 1024);
756 if (!label && password)
757 check_password ("To boot a custom image you must enter the password.");
759 if (!parse_device_path(imagepath, defdevice, defpart,
760 "/vmlinux", ¶ms->kernel)) {
761 prom_printf("%s: Unable to parse\n", imagepath);
764 DEBUG_F("after parse_device_path: dev=%s part=%d file=%s\n", params->kernel.dev,
765 params->kernel.part, params->kernel.file);
768 p = cfg_get_strg(label, "initrd");
770 DEBUG_F("Parsing initrd path <%s>\n", p);
771 strncpy(initrdpath, p, 1024);
772 if (!parse_device_path(initrdpath, defdevice, defpart,
773 "/root.bin", ¶ms->rd)) {
774 prom_printf("%s: Unable to parse\n", imagepath);
778 p = cfg_get_strg(label, "sysmap");
780 DEBUG_F("Parsing sysmap path <%s>\n", p);
781 strncpy(sysmappath, p, 1024);
782 if (!parse_device_path(sysmappath, defdevice, defpart,
783 "/boot/System.map", ¶ms->sysmap)) {
784 prom_printf("%s: Unable to parse\n", imagepath);
792 /* This is derived from quik core. To be changed to first parse the headers
793 * doing lazy-loading, and then claim the memory before loading the kernel
795 * We also need to add initrd support to this whole mecanism
800 #define MAX_HEADERS 32
802 struct boot_file_t file;
804 static struct boot_param_t params;
806 unsigned long initrd_size;
808 unsigned long sysmap_size;
809 kernel_entry_t kernel_entry;
810 struct bi_record* birec;
813 void *initrd_more,*initrd_want;
814 unsigned long initrd_read;
816 loadinfo.load_loc = 0;
824 if (get_params(¶ms))
826 if (!params.kernel.file)
829 prom_printf("Please wait, loading kernel...\n");
831 memset(&file, 0, sizeof(file));
833 if (strlen(boot.file) && !strcmp(boot.file,"\\\\") && params.kernel.file[0] != '/'
834 && params.kernel.file[0] != '\\') {
835 loc=(char*)malloc(strlen(params.kernel.file)+3);
837 prom_printf ("malloc error\n");
840 strcpy(loc,boot.file);
841 strcat(loc,params.kernel.file);
842 free(params.kernel.file);
843 params.kernel.file=loc;
845 result = open_file(¶ms.kernel, &file);
846 if (result != FILE_ERR_OK) {
847 prom_printf("%s:%d,", params.kernel.dev, params.kernel.part);
848 prom_perror(result, params.kernel.file);
852 /* Read the Elf e_ident, e_type and e_machine fields to
853 * determine Elf file type
855 if (file.fs->read(&file, sizeof(Elf_Ident), &loadinfo.elf) < sizeof(Elf_Ident)) {
856 prom_printf("\nCan't read Elf e_ident/e_type/e_machine info\n");
857 file.fs->close(&file);
858 memset(&file, 0, sizeof(file));
862 if (is_elf32(&loadinfo)) {
863 if (!load_elf32(&file, &loadinfo)) {
864 file.fs->close(&file);
865 memset(&file, 0, sizeof(file));
868 prom_printf(" Elf32 kernel loaded...\n");
869 } else if (is_elf64(&loadinfo)) {
870 if (!load_elf64(&file, &loadinfo)) {
871 file.fs->close(&file);
872 memset(&file, 0, sizeof(file));
875 prom_printf(" Elf64 kernel loaded...\n");
877 prom_printf ("%s: Not a valid ELF image\n", params.kernel.file);
878 file.fs->close(&file);
879 memset(&file, 0, sizeof(file));
882 file.fs->close(&file);
883 memset(&file, 0, sizeof(file));
885 /* If sysmap, load it (only if booting a vmlinux).
887 if (flat_vmlinux && params.sysmap.file) {
888 prom_printf("Loading System.map ...\n");
889 if(strlen(boot.file) && !strcmp(boot.file,"\\\\") && params.sysmap.file[0] != '/'
890 && params.sysmap.file[0] != '\\') {
892 loc=(char*)malloc(strlen(params.sysmap.file)+3);
894 prom_printf ("malloc error\n");
897 strcpy(loc,boot.file);
898 strcat(loc,params.sysmap.file);
899 free(params.sysmap.file);
900 params.sysmap.file=loc;
903 result = open_file(¶ms.sysmap, &file);
904 if (result != FILE_ERR_OK) {
905 prom_printf("%s:%d,", params.sysmap.dev, params.sysmap.part);
906 prom_perror(result, params.sysmap.file);
909 sysmap_base = prom_claim(loadinfo.base+loadinfo.memsize, 0x100000, 0);
910 if (sysmap_base == (void *)-1) {
911 prom_printf("Claim failed for sysmap memory\n");
914 sysmap_size = file.fs->read(&file, 0xfffff, sysmap_base);
915 if (sysmap_size == 0)
918 ((char *)sysmap_base)[sysmap_size++] = 0;
920 file.fs->close(&file);
921 memset(&file, 0, sizeof(file));
924 prom_printf("System.map loaded at %p, size: %lu Kbytes\n",
925 sysmap_base, sysmap_size >> 10);
926 loadinfo.memsize += _ALIGN(0x100000, 0x1000);
928 prom_printf("System.map load failed !\n");
933 /* If ramdisk, load it (only if booting a vmlinux). For now, we
934 * can't tell the size it will be so we claim an arbitrary amount
937 if (flat_vmlinux && params.rd.file) {
938 if(strlen(boot.file) && !strcmp(boot.file,"\\\\") && params.rd.file[0] != '/'
939 && params.kernel.file[0] != '\\')
942 loc=(char*)malloc(strlen(params.rd.file)+3);
944 prom_printf ("Malloc error\n");
947 strcpy(loc,boot.file);
948 strcat(loc,params.rd.file);
949 free(params.rd.file);
952 prom_printf("Loading ramdisk...\n");
953 result = open_file(¶ms.rd, &file);
954 if (result != FILE_ERR_OK) {
955 prom_printf("%s:%d,", params.rd.dev, params.rd.part);
956 prom_perror(result, params.rd.file);
959 #define INITRD_CHUNKSIZE 0x400000
960 initrd_base = prom_claim(loadinfo.base+loadinfo.memsize, INITRD_CHUNKSIZE, 0);
961 if (initrd_base == (void *)-1) {
962 prom_printf("Claim failed for initrd memory\n");
965 initrd_size = file.fs->read(&file, INITRD_CHUNKSIZE, initrd_base);
966 if (initrd_size == 0)
968 initrd_read = initrd_size;
969 initrd_more = initrd_base;
970 while (initrd_read == INITRD_CHUNKSIZE ) { /* need to read more? */
971 initrd_want = (void *)((unsigned long)initrd_more+INITRD_CHUNKSIZE);
972 initrd_more = prom_claim(initrd_want, INITRD_CHUNKSIZE, 0);
973 if (initrd_more != initrd_want) {
974 prom_printf("Claim failed for initrd memory at %p rc=%p\n",initrd_want,initrd_more);
977 initrd_read = file.fs->read(&file, INITRD_CHUNKSIZE, initrd_more);
978 DEBUG_F(" block at %p rc=%lu\n",initrd_more,initrd_read);
979 initrd_size += initrd_read;
982 file.fs->close(&file);
983 memset(&file, 0, sizeof(file));
986 prom_printf("ramdisk loaded at %p, size: %lu Kbytes\n",
987 initrd_base, initrd_size >> 10);
989 prom_printf("ramdisk load failed !\n");
994 DEBUG_F("setting kernel args to: %s\n", params.args);
995 prom_setargs(params.args);
996 DEBUG_F("flushing icache...");
997 flush_icache_range ((long)loadinfo.base, (long)loadinfo.base+loadinfo.memsize);
1002 * Fill new boot infos (only if booting a vmlinux).
1004 * The birec is low on memory, probably inside the malloc pool,
1005 * so we don't write it earlier. At this point, we should not
1006 * use anything coming from the malloc pool.
1008 birec = (struct bi_record *)_ALIGN(loadinfo.filesize+(1<<20)-1,(1<<20));
1010 /* We make sure it's mapped. We map only 64k for now, it's
1011 * plenty enough we don't claim since this precise memory
1012 * range may already be claimed by the malloc pool.
1014 prom_map (birec, birec, 0x10000);
1015 DEBUG_F("birec at %p\n", birec);
1018 birec->tag = BI_FIRST;
1019 birec->size = sizeof(struct bi_record);
1020 birec = (struct bi_record *)((ulong)birec + birec->size);
1022 birec->tag = BI_BOOTLOADER_ID;
1023 sprintf( (char *)birec->data, "yaboot");
1024 birec->size = sizeof(struct bi_record) + strlen("yaboot") + 1;
1025 birec = (struct bi_record *)((ulong)birec + birec->size);
1027 birec->tag = BI_MACHTYPE;
1028 birec->data[0] = _machine;
1029 birec->size = sizeof(struct bi_record) + sizeof(ulong);
1030 birec = (struct bi_record *)((ulong)birec + birec->size);
1033 birec->tag = BI_SYSMAP;
1034 birec->data[0] = (ulong)sysmap_base;
1035 birec->data[1] = sysmap_size;
1036 birec->size = sizeof(struct bi_record) + sizeof(ulong)*2;
1037 birec = (struct bi_record *)((ulong)birec + birec->size);
1039 birec->tag = BI_LAST;
1040 birec->size = sizeof(struct bi_record);
1041 birec = (struct bi_record *)((ulong)birec + birec->size);
1044 /* compute the kernel's entry point. */
1045 kernel_entry = loadinfo.base + loadinfo.entry - loadinfo.load_loc;
1047 DEBUG_F("Kernel entry point = %p\n", kernel_entry);
1048 DEBUG_F("kernel: arg1 = %p,\n"
1049 " arg2 = 0x%08lx,\n"
1053 initrd_base + loadinfo.load_loc, initrd_size, prom, 0, 0);
1055 DEBUG_F("Entering kernel...\n");
1057 /* call the kernel with our stack. */
1058 kernel_entry(initrd_base + loadinfo.load_loc, initrd_size, prom, 0, 0);
1066 load_elf32(struct boot_file_t *file, loadinfo_t *loadinfo)
1069 Elf32_Ehdr *e = &(loadinfo->elf.elf32hdr);
1071 int size = sizeof(Elf32_Ehdr) - sizeof(Elf_Ident);
1072 unsigned long addr, loadaddr;
1074 /* Read the rest of the Elf header... */
1075 if ((*(file->fs->read))(file, size, &e->e_version) < size) {
1076 prom_printf("\nCan't read Elf32 image header\n");
1080 DEBUG_F("Elf32 header:\n");
1081 DEBUG_F(" e.e_type = %d\n", (int)e->e_type);
1082 DEBUG_F(" e.e_machine = %d\n", (int)e->e_machine);
1083 DEBUG_F(" e.e_version = %d\n", (int)e->e_version);
1084 DEBUG_F(" e.e_entry = 0x%08x\n", (int)e->e_entry);
1085 DEBUG_F(" e.e_phoff = 0x%08x\n", (int)e->e_phoff);
1086 DEBUG_F(" e.e_shoff = 0x%08x\n", (int)e->e_shoff);
1087 DEBUG_F(" e.e_flags = %d\n", (int)e->e_flags);
1088 DEBUG_F(" e.e_ehsize = 0x%08x\n", (int)e->e_ehsize);
1089 DEBUG_F(" e.e_phentsize = 0x%08x\n", (int)e->e_phentsize);
1090 DEBUG_F(" e.e_phnum = %d\n", (int)e->e_phnum);
1092 loadinfo->entry = e->e_entry;
1094 if (e->e_phnum > MAX_HEADERS) {
1095 prom_printf ("Can only load kernels with one program header\n");
1099 ph = (Elf32_Phdr *)malloc(sizeof(Elf32_Phdr) * e->e_phnum);
1101 prom_printf ("Malloc error\n");
1105 /* Now, we read the section header */
1106 if ((*(file->fs->seek))(file, e->e_phoff) != FILE_ERR_OK) {
1107 prom_printf ("seek error\n");
1110 if ((*(file->fs->read))(file, sizeof(Elf32_Phdr) * e->e_phnum, ph) !=
1111 sizeof(Elf32_Phdr) * e->e_phnum) {
1112 prom_printf ("read error\n");
1116 /* Scan through the program header
1117 * HACK: We must return the _memory size of the kernel image, not the
1118 * file size (because we have to leave room before other boot
1119 * infos. This code works as a side effect of the fact that
1120 * we have one section and vaddr == p_paddr
1122 loadinfo->memsize = loadinfo->filesize = loadinfo->offset = 0;
1124 for (i = 0; i < e->e_phnum; ++i, ++p) {
1125 if (p->p_type != PT_LOAD || p->p_offset == 0)
1127 if (loadinfo->memsize == 0) {
1128 loadinfo->offset = p->p_offset;
1129 loadinfo->memsize = p->p_memsz;
1130 loadinfo->filesize = p->p_filesz;
1131 loadinfo->load_loc = p->p_vaddr;
1133 loadinfo->memsize = p->p_offset + p->p_memsz - loadinfo->offset; /* XXX Bogus */
1134 loadinfo->filesize = p->p_offset + p->p_filesz - loadinfo->offset;
1138 if (loadinfo->memsize == 0) {
1139 prom_printf("Can't find a loadable segment !\n");
1143 /* leave some room (1Mb) for boot infos */
1144 loadinfo->memsize = _ALIGN(loadinfo->memsize,(1<<20)) + 0x100000;
1145 /* Claim OF memory */
1146 DEBUG_F("Before prom_claim, mem_sz: 0x%08lx\n", loadinfo->memsize);
1148 /* Determine whether we are trying to boot a vmlinux or some
1149 * other binary image (eg, zImage). We load vmlinux's at
1150 * KERNELADDR and all other binaries at their e_entry value.
1152 if (e->e_entry == KERNEL_LINK_ADDR_PPC32) {
1154 loadaddr = KERNELADDR;
1157 loadaddr = e->e_entry;
1160 /* On some systems, loadaddr may already be claimed, so try some
1161 * other nearby addresses before giving up.
1163 for(addr=loadaddr; addr <= loadaddr * 8 ;addr+=0x100000) {
1164 loadinfo->base = prom_claim((void *)addr, loadinfo->memsize, 0);
1165 if (loadinfo->base != (void *)-1) break;
1167 if (loadinfo->base == (void *)-1) {
1168 prom_printf("Claim error, can't allocate kernel memory\n");
1172 DEBUG_F("After ELF parsing, load base: %p, mem_sz: 0x%08lx\n",
1173 loadinfo->base, loadinfo->memsize);
1174 DEBUG_F(" wanted load base: 0x%08lx, mem_sz: 0x%08lx\n",
1175 loadaddr, loadinfo->memsize);
1177 /* Load the program segments... */
1179 for (i = 0; i < e->e_phnum; ++i, ++p) {
1180 unsigned long offset;
1181 if (p->p_type != PT_LOAD || p->p_offset == 0)
1184 /* Now, we skip to the image itself */
1185 if ((*(file->fs->seek))(file, p->p_offset) != FILE_ERR_OK) {
1186 prom_printf ("Seek error\n");
1187 prom_release(loadinfo->base, loadinfo->memsize);
1190 offset = p->p_vaddr - loadinfo->load_loc;
1191 if ((*(file->fs->read))(file, p->p_filesz, loadinfo->base+offset) != p->p_filesz) {
1192 prom_printf ("Read failed\n");
1193 prom_release(loadinfo->base, loadinfo->memsize);
1200 /* Return success at loading the Elf32 kernel */
1205 load_elf64(struct boot_file_t *file, loadinfo_t *loadinfo)
1208 Elf64_Ehdr *e = &(loadinfo->elf.elf64hdr);
1210 int size = sizeof(Elf64_Ehdr) - sizeof(Elf_Ident);
1211 unsigned long addr, loadaddr;
1213 /* Read the rest of the Elf header... */
1214 if ((*(file->fs->read))(file, size, &e->e_version) < size) {
1215 prom_printf("\nCan't read Elf64 image header\n");
1219 DEBUG_F("Elf64 header:\n");
1220 DEBUG_F(" e.e_type = %d\n", (int)e->e_type);
1221 DEBUG_F(" e.e_machine = %d\n", (int)e->e_machine);
1222 DEBUG_F(" e.e_version = %d\n", (int)e->e_version);
1223 DEBUG_F(" e.e_entry = 0x%016lx\n", (long)e->e_entry);
1224 DEBUG_F(" e.e_phoff = 0x%016lx\n", (long)e->e_phoff);
1225 DEBUG_F(" e.e_shoff = 0x%016lx\n", (long)e->e_shoff);
1226 DEBUG_F(" e.e_flags = %d\n", (int)e->e_flags);
1227 DEBUG_F(" e.e_ehsize = 0x%08x\n", (int)e->e_ehsize);
1228 DEBUG_F(" e.e_phentsize = 0x%08x\n", (int)e->e_phentsize);
1229 DEBUG_F(" e.e_phnum = %d\n", (int)e->e_phnum);
1231 loadinfo->entry = e->e_entry;
1233 if (e->e_phnum > MAX_HEADERS) {
1234 prom_printf ("Can only load kernels with one program header\n");
1238 ph = (Elf64_Phdr *)malloc(sizeof(Elf64_Phdr) * e->e_phnum);
1240 prom_printf ("Malloc error\n");
1244 /* Now, we read the section header */
1245 if ((*(file->fs->seek))(file, e->e_phoff) != FILE_ERR_OK) {
1246 prom_printf ("Seek error\n");
1249 if ((*(file->fs->read))(file, sizeof(Elf64_Phdr) * e->e_phnum, ph) !=
1250 sizeof(Elf64_Phdr) * e->e_phnum) {
1251 prom_printf ("Read error\n");
1255 /* Scan through the program header
1256 * HACK: We must return the _memory size of the kernel image, not the
1257 * file size (because we have to leave room before other boot
1258 * infos. This code works as a side effect of the fact that
1259 * we have one section and vaddr == p_paddr
1261 loadinfo->memsize = loadinfo->filesize = loadinfo->offset = 0;
1263 for (i = 0; i < e->e_phnum; ++i, ++p) {
1264 if (p->p_type != PT_LOAD || p->p_offset == 0)
1266 if (loadinfo->memsize == 0) {
1267 loadinfo->offset = p->p_offset;
1268 loadinfo->memsize = p->p_memsz;
1269 loadinfo->filesize = p->p_filesz;
1270 loadinfo->load_loc = p->p_vaddr;
1272 loadinfo->memsize = p->p_offset + p->p_memsz - loadinfo->offset; /* XXX Bogus */
1273 loadinfo->filesize = p->p_offset + p->p_filesz - loadinfo->offset;
1277 if (loadinfo->memsize == 0) {
1278 prom_printf("Can't find a loadable segment !\n");
1282 /* leave some room (1Mb) for boot infos */
1283 loadinfo->memsize = _ALIGN(loadinfo->memsize,(1<<20)) + 0x100000;
1284 /* Claim OF memory */
1285 DEBUG_F("Before prom_claim, mem_sz: 0x%08lx\n", loadinfo->memsize);
1287 /* Determine whether we are trying to boot a vmlinux or some
1288 * other binary image (eg, zImage). We load vmlinux's at
1289 * KERNELADDR and all other binaries at their e_entry value.
1291 if (e->e_entry == KERNEL_LINK_ADDR_PPC64) {
1293 loadaddr = KERNELADDR;
1296 loadaddr = e->e_entry;
1299 /* On some systems, loadaddr may already be claimed, so try some
1300 * other nearby addresses before giving up.
1302 for(addr=loadaddr; addr <= loadaddr * 8 ;addr+=0x100000) {
1303 loadinfo->base = prom_claim((void *)addr, loadinfo->memsize, 0);
1304 if (loadinfo->base != (void *)-1) break;
1306 if (loadinfo->base == (void *)-1) {
1307 prom_printf("Claim error, can't allocate kernel memory\n");
1311 DEBUG_F("After ELF parsing, load base: %p, mem_sz: 0x%08lx\n",
1312 loadinfo->base, loadinfo->memsize);
1313 DEBUG_F(" wanted load base: 0x%08lx, mem_sz: 0x%08lx\n",
1314 loadaddr, loadinfo->memsize);
1316 /* Load the program segments... */
1318 for (i = 0; i < e->e_phnum; ++i, ++p) {
1319 unsigned long offset;
1320 if (p->p_type != PT_LOAD || p->p_offset == 0)
1323 /* Now, we skip to the image itself */
1324 if ((*(file->fs->seek))(file, p->p_offset) != FILE_ERR_OK) {
1325 prom_printf ("Seek error\n");
1326 prom_release(loadinfo->base, loadinfo->memsize);
1329 offset = p->p_vaddr - loadinfo->load_loc;
1330 if ((*(file->fs->read))(file, p->p_filesz, loadinfo->base+offset) != p->p_filesz) {
1331 prom_printf ("Read failed\n");
1332 prom_release(loadinfo->base, loadinfo->memsize);
1339 /* Return success at loading the Elf64 kernel */
1344 is_elf32(loadinfo_t *loadinfo)
1346 Elf32_Ehdr *e = &(loadinfo->elf.elf32hdr);
1348 return (e->e_ident[EI_MAG0] == ELFMAG0 &&
1349 e->e_ident[EI_MAG1] == ELFMAG1 &&
1350 e->e_ident[EI_MAG2] == ELFMAG2 &&
1351 e->e_ident[EI_MAG3] == ELFMAG3 &&
1352 e->e_ident[EI_CLASS] == ELFCLASS32 &&
1353 e->e_ident[EI_DATA] == ELFDATA2MSB &&
1354 e->e_type == ET_EXEC &&
1355 e->e_machine == EM_PPC);
1359 is_elf64(loadinfo_t *loadinfo)
1361 Elf64_Ehdr *e = &(loadinfo->elf.elf64hdr);
1363 return (e->e_ident[EI_MAG0] == ELFMAG0 &&
1364 e->e_ident[EI_MAG1] == ELFMAG1 &&
1365 e->e_ident[EI_MAG2] == ELFMAG2 &&
1366 e->e_ident[EI_MAG3] == ELFMAG3 &&
1367 e->e_ident[EI_CLASS] == ELFCLASS64 &&
1368 e->e_ident[EI_DATA] == ELFDATA2MSB &&
1369 e->e_type == ET_EXEC &&
1370 e->e_machine == EM_PPC64);
1376 #ifdef CONFIG_SET_COLORMAP
1377 static unsigned char default_colors[] = {
1396 prom_handle scrn = PROM_INVALID_HANDLE;
1398 /* Try Apple's mac-boot screen ihandle */
1399 result = (int)call_prom_return("interpret", 1, 2,
1400 "\" _screen-ihandle\" $find if execute else 0 then", &scrn);
1401 DEBUG_F("Trying to get screen ihandle, result: %d, scrn: %p\n", result, scrn);
1403 if (scrn == 0 || scrn == PROM_INVALID_HANDLE) {
1405 /* Hrm... check to see if stdout is a display */
1406 scrn = call_prom ("instance-to-package", 1, 1, prom_stdout);
1407 DEBUG_F("instance-to-package of stdout is: %p\n", scrn);
1408 if (prom_getprop(scrn, "device_type", type, 32) > 0 && !strncmp(type, "display", 7)) {
1409 DEBUG_F("got it ! stdout is a screen\n");
1412 /* Else, we try to open the package */
1413 scrn = (prom_handle)call_prom( "open", 1, 1, "screen" );
1414 DEBUG_F("Open screen result: %p\n", scrn);
1418 if (scrn == PROM_INVALID_HANDLE) {
1419 prom_printf("No screen device found !/n");
1423 prom_set_color(scrn, i, default_colors[i*3],
1424 default_colors[i*3+1], default_colors[i*3+2]);
1426 prom_printf("\x1b[1;37m\x1b[2;40m");
1428 for (i=0;i<16; i++) {
1429 prom_printf("\x1b[%d;%dm\x1b[1;47m%s \x1b[2;40m %s\n",
1430 ansi_color_table[i].index,
1431 ansi_color_table[i].value,
1432 ansi_color_table[i].name,
1433 ansi_color_table[i].name);
1434 prom_printf("\x1b[%d;%dm\x1b[1;37m%s \x1b[2;30m %s\n",
1435 ansi_color_table[i].index,
1436 ansi_color_table[i].value+10,
1437 ansi_color_table[i].name,
1438 ansi_color_table[i].name);
1440 prom_printf("\x1b[1;37m\x1b[2;40m");
1441 #endif /* COLOR_TEST */
1447 #endif /* CONFIG_SET_COLORMAP */
1455 if (_machine == _MACH_Pmac)
1458 prom_get_chosen("bootpath", bootdevice, sizeof(bootdevice));
1459 DEBUG_F("/chosen/bootpath = %s\n", bootdevice);
1460 if (bootdevice[0] == 0) {
1461 prom_get_options("boot-device", bootdevice, sizeof(bootdevice));
1462 DEBUG_F("boot-device = %s\n", bootdevice);
1464 if (bootdevice[0] == 0) {
1465 prom_printf("Couldn't determine boot device\n");
1469 if (!parse_device_path(bootdevice, NULL, -1, "", &boot)) {
1470 prom_printf("%s: Unable to parse\n", bootdevice);
1473 DEBUG_F("After parse_device_path: dev=%s, part=%d, file=%s\n",
1474 boot.dev, boot.part, boot.file);
1476 if (strlen(boot.file)) {
1477 if (!strncmp(boot.file, "\\\\", 2))
1481 p = last = boot.file;
1491 if (strlen(boot.file))
1492 strcat(boot.file, "\\");
1495 DEBUG_F("After pmac path kludgeup: dev=%s, part=%d, file=%s\n",
1496 boot.dev, boot.part, boot.file);
1498 useconf = load_config_file(boot.dev, boot.file, boot.part);
1500 prom_printf("Welcome to yaboot version " VERSION "\n");
1501 prom_printf("Enter \"help\" to get some basic usage information\n");
1503 /* I am fed up with lusers using the wrong partition type and
1504 mailing me *when* it breaks */
1506 if (_machine == _MACH_Pmac) {
1507 char *entry = cfg_get_strg(0, "ptypewarning");
1510 warn = strcmp(entry,
1511 "I_know_the_partition_type_is_wrong_and_will_NOT_send_mail_when_booting_breaks");
1513 ptype = get_part_type(boot.dev, boot.part);
1514 if ((ptype != NULL) && (strcmp(ptype, "Apple_Bootstrap")))
1515 prom_printf("\nWARNING: Bootstrap partition type is wrong: \"%s\"\n"
1516 " type should be: \"Apple_Bootstrap\"\n\n", ptype);
1522 prom_printf("Bye.\n");
1528 * c-file-style: "k&r"