X-Git-Url: http://git.ozlabs.org/?p=yaboot.git;a=blobdiff_plain;f=second%2Fyaboot.c;h=d7a3a20f1c0b0fccca199f4895e983e4d1dbca5e;hp=7b7bcdb208e7ba4e70d54bec88b93dd9e34eef5d;hb=6f00a510abbfaa45b580cf5f371f0168ba662d3d;hpb=678d83ff8608534ece0f1e912eddedef4f0bb67a diff --git a/second/yaboot.c b/second/yaboot.c index 7b7bcdb..d7a3a20 100644 --- a/second/yaboot.c +++ b/second/yaboot.c @@ -1,38 +1,45 @@ -/* Yaboot - secondary boot loader for Linux on ppc. - - Copyright (C) 1999 Benjamin Herrenschmidt - - portions based on poof - - Copyright (C) 1999 Marius Vollmer - - portions based on quik - - Copyright (C) 1996 Paul Mackerras. - - Because this program is derived from the corresponding file in the - silo-0.64 distribution, it is also - - Copyright (C) 1996 Pete A. Zaitcev - 1996 Maurizio Plaza - 1996 David S. Miller - 1996 Miguel de Icaza - 1996 Jakub Jelinek - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ +/* + * Yaboot - secondary boot loader for Linux on PowerPC. + * + * Copyright (C) 2001, 2002 Ethan Benson + * + * Copyright (C) 1999, 2000, 2001 Benjamin Herrenschmidt + * + * IBM CHRP support + * + * Copyright (C) 2001 Peter Bergner + * + * portions based on poof + * + * Copyright (C) 1999 Marius Vollmer + * + * portions based on quik + * + * Copyright (C) 1996 Paul Mackerras. + * + * Because this program is derived from the corresponding file in the + * silo-0.64 distribution, it is also + * + * Copyright (C) 1996 Pete A. Zaitcev + * 1996 Maurizio Plaza + * 1996 David S. Miller + * 1996 Miguel de Icaza + * 1996 Jakub Jelinek + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ #include "stdarg.h" #include "string.h" @@ -173,7 +180,7 @@ yaboot_start (unsigned long r3, unsigned long r4, unsigned long r5) /* OF seems to do it, but I'm not very confident */ memset(&__bss_start, 0, &_end - &__bss_start); - + /* Check for quik first stage bootloader (but I don't think we are * compatible with it anyway, I'll look into backporting to older OF * versions later @@ -185,7 +192,7 @@ yaboot_start (unsigned long r3, unsigned long r4, unsigned long r5) /* Initialize OF interface */ prom_init ((prom_entry) r5); - + /* Allocate some memory for malloc'ator */ malloc_base = prom_claim((void *)MALLOCADDR, MALLOCSIZE, 0); if (malloc_base == (void *)-1) { @@ -196,7 +203,7 @@ yaboot_start (unsigned long r3, unsigned long r4, unsigned long r5) malloc_init(malloc_base, MALLOCSIZE); DEBUG_F("Malloc buffer allocated at %p (%d bytes)\n", malloc_base, MALLOCSIZE); - + /* A few useless DEBUG_F's */ DEBUG_F("reloc_offset : %ld (should be 0)\n", reloc_offset()); DEBUG_F("test_bss : %d (should be 0)\n", test_bss); @@ -219,7 +226,7 @@ yaboot_start (unsigned long r3, unsigned long r4, unsigned long r5) _machine = _MACH_chrp; } } - + DEBUG_F("Running on _machine = %d\n", _machine); DEBUG_SLEEP; @@ -234,9 +241,9 @@ yaboot_start (unsigned long r3, unsigned long r4, unsigned long r5) /* Return to OF */ prom_exit(); - + return result; - + } #ifdef CONFIG_COLOR_TEXT @@ -253,13 +260,13 @@ check_color_text_ui(char *color) i++; } return -1; -} +} #endif /* CONFIG_COLOR_TEXT */ void print_message_file(char *filename) { - char *msg = NULL; + char *msg = NULL; char *p, *endp; char *defdev = boot.dev; int defpart = boot.part; @@ -277,7 +284,7 @@ void print_message_file(char *filename) if (p) { n = simple_strtol(p, &endp, 10); if (endp != p && *endp == 0) - defpart = n; + defpart = n; } strncpy(msgpath, filename, sizeof(msgpath)); @@ -381,7 +388,7 @@ load_config_file(char *device, char* path, int partition) prom_interpret(p); password = cfg_get_strg(0, "password"); - + #ifdef CONFIG_COLOR_TEXT p = cfg_get_strg(0, "fgcolor"); if (p) { @@ -400,19 +407,19 @@ load_config_file(char *device, char* path, int partition) } if (bgcolor >= 0) { char temp[64]; - sprintf(temp, "%x to background-color", bgcolor); - prom_interpret(temp); + sprintf(temp, "%x to background-color", bgcolor); + prom_interpret(temp); #if !DEBUG prom_printf("\xc"); #endif /* !DEBUG */ } if (fgcolor >= 0) { char temp[64]; - sprintf(temp, "%x to foreground-color", fgcolor); - prom_interpret(temp); + sprintf(temp, "%x to foreground-color", fgcolor); + prom_interpret(temp); } #endif /* CONFIG_COLOR_TEXT */ - + p = cfg_get_strg(0, "init-message"); if (p) prom_printf("%s\n", p); @@ -422,15 +429,15 @@ load_config_file(char *device, char* path, int partition) print_message_file(p); result = 1; - + bail: if (opened) file.fs->close(&file); - - if (result != 1 && conf_file) + + if (conf_file) free(conf_file); - + return result; } @@ -542,8 +549,9 @@ void check_password(char *str) { int i; + prom_printf("\n%s", str); for (i = 0; i < 3; i++) { - prom_printf ("\n%sassword: ", str); + prom_printf ("\nPassword: "); passwdbuff[0] = 0; cmdedit ((void (*)(void)) 0, 1); prom_printf ("\n"); @@ -551,18 +559,22 @@ void check_password(char *str) if (!strncmp (password, "$1$", 3)) { if (!check_md5_password(passwdbuff, password)) return; - } + } else if (!strcmp (password, passwdbuff)) return; #else /* !MD5 */ if (!strcmp (password, passwdbuff)) return; #endif /* USE_MD5_PASSWORDS */ - if (i < 2) - prom_printf ("Password incorrect. Please try again..."); + if (i < 2) { + prom_sleep(1); + prom_printf ("Incorrect password. Try again."); + } } - prom_printf ("Seems like you don't know the access password. Go away!\n"); - prom_sleep(3); + prom_printf(" ___________________\n< Permission denied >\n -------------------\n" + " \\ ^__^\n \\ (oo)\\_______\n (__)\\ )\\/\\\n" + " ||----w |\n || ||\n"); + prom_sleep(4); prom_interpret("reset-all"); } @@ -590,7 +602,7 @@ int get_params(struct boot_param_t* params) params->rd.part = -1; params->sysmap.part = -1; defpart = boot.part; - + cmdinit(); if (first) { @@ -694,15 +706,18 @@ int get_params(struct boot_param_t* params) restricted = 1; if (label) { if (params->args && password && restricted) - check_password ("To specify image arguments you must enter the p"); + check_password ("To specify arguments for this image " + "you must enter the password."); else if (password && !restricted) - check_password ("P"); + check_password ("This image is restricted."); } params->args = make_params(label, params->args); } } if (!strcmp (imagename, "help")) { + /* FIXME: defdevice shouldn't need to be reset all over the place */ + if(!defdevice) defdevice = boot.dev; prom_printf( "\nPress the tab key for a list of defined images.\n" "The label marked with a \"*\" is is the default image, " @@ -723,22 +738,22 @@ int get_params(struct boot_param_t* params) if (!strcmp (imagename, "halt")) { if (password) - check_password ("P"); + check_password ("Restricted command."); prom_pause(); return 0; } if (!strcmp (imagename, "bye")) { if (password) { - check_password ("P"); + check_password ("Restricted command."); return 1; } - return 1; + return 1; } if (imagename[0] == '$') { /* forth command string */ if (password) - check_password ("P"); + check_password ("OpenFirmware commands are restricted."); prom_interpret(imagename+1); return 0; } @@ -746,7 +761,7 @@ int get_params(struct boot_param_t* params) strncpy(imagepath, imagename, 1024); if (!label && password) - check_password ("To boot a custom image you must enter the p"); + check_password ("To boot a custom image you must enter the password."); if (!parse_device_path(imagepath, defdevice, defpart, "/vmlinux", ¶ms->kernel)) { @@ -804,7 +819,7 @@ yaboot_text_ui(void) loadinfo_t loadinfo; void *initrd_more,*initrd_want; unsigned long initrd_read; - + loadinfo.load_loc = 0; for (;;) { @@ -812,12 +827,12 @@ yaboot_text_ui(void) initrd_base = 0; sysmap_base = 0; sysmap_size = 0; - + if (get_params(¶ms)) return; if (!params.kernel.file) continue; - + prom_printf("Please wait, loading kernel...\n"); memset(&file, 0, sizeof(file)); @@ -891,7 +906,7 @@ yaboot_text_ui(void) free(params.sysmap.file); params.sysmap.file=loc; } - + result = open_file(¶ms.sysmap, &file); if (result != FILE_ERR_OK) { prom_printf("%s:%d,", params.sysmap.dev, params.sysmap.part); @@ -901,6 +916,7 @@ yaboot_text_ui(void) sysmap_base = prom_claim(loadinfo.base+loadinfo.memsize, 0x100000, 0); if (sysmap_base == (void *)-1) { prom_printf("Claim failed for sysmap memory\n"); + prom_pause(); sysmap_base = 0; } else { sysmap_size = file.fs->read(&file, 0xfffff, sysmap_base); @@ -948,7 +964,7 @@ yaboot_text_ui(void) prom_perror(result, params.rd.file); } else { -#define INITRD_CHUNKSIZE 0x400000 +#define INITRD_CHUNKSIZE 0x100000 initrd_base = prom_claim(loadinfo.base+loadinfo.memsize, INITRD_CHUNKSIZE, 0); if (initrd_base == (void *)-1) { prom_printf("Claim failed for initrd memory\n"); @@ -964,6 +980,7 @@ yaboot_text_ui(void) initrd_more = prom_claim(initrd_want, INITRD_CHUNKSIZE, 0); if (initrd_more != initrd_want) { prom_printf("Claim failed for initrd memory at %p rc=%p\n",initrd_want,initrd_more); + prom_pause(); break; } initrd_read = file.fs->read(&file, INITRD_CHUNKSIZE, initrd_more); @@ -990,7 +1007,7 @@ yaboot_text_ui(void) DEBUG_F(" done\n"); if (flat_vmlinux) { - /* + /* * Fill new boot infos (only if booting a vmlinux). * * The birec is low on memory, probably inside the malloc pool, @@ -1010,12 +1027,12 @@ yaboot_text_ui(void) birec->tag = BI_FIRST; birec->size = sizeof(struct bi_record); birec = (struct bi_record *)((ulong)birec + birec->size); - + birec->tag = BI_BOOTLOADER_ID; sprintf( (char *)birec->data, "yaboot"); birec->size = sizeof(struct bi_record) + strlen("yaboot") + 1; birec = (struct bi_record *)((ulong)birec + birec->size); - + birec->tag = BI_MACHTYPE; birec->data[0] = _machine; birec->size = sizeof(struct bi_record) + sizeof(ulong); @@ -1066,7 +1083,7 @@ load_elf32(struct boot_file_t *file, loadinfo_t *loadinfo) /* Read the rest of the Elf header... */ if ((*(file->fs->read))(file, size, &e->e_version) < size) { prom_printf("\nCan't read Elf32 image header\n"); - return 0; + goto bail; } DEBUG_F("Elf32 header:\n"); @@ -1085,24 +1102,24 @@ load_elf32(struct boot_file_t *file, loadinfo_t *loadinfo) if (e->e_phnum > MAX_HEADERS) { prom_printf ("Can only load kernels with one program header\n"); - return 0; + goto bail; } ph = (Elf32_Phdr *)malloc(sizeof(Elf32_Phdr) * e->e_phnum); if (!ph) { prom_printf ("Malloc error\n"); - return 0; + goto bail; } /* Now, we read the section header */ if ((*(file->fs->seek))(file, e->e_phoff) != FILE_ERR_OK) { prom_printf ("seek error\n"); - return 0; + goto bail; } if ((*(file->fs->read))(file, sizeof(Elf32_Phdr) * e->e_phnum, ph) != sizeof(Elf32_Phdr) * e->e_phnum) { prom_printf ("read error\n"); - return 0; + goto bail; } /* Scan through the program header @@ -1129,7 +1146,7 @@ load_elf32(struct boot_file_t *file, loadinfo_t *loadinfo) if (loadinfo->memsize == 0) { prom_printf("Can't find a loadable segment !\n"); - return 0; + goto bail; } /* leave some room (1Mb) for boot infos */ @@ -1146,7 +1163,7 @@ load_elf32(struct boot_file_t *file, loadinfo_t *loadinfo) loadaddr = KERNELADDR; } else { flat_vmlinux = 0; - loadaddr = e->e_entry; + loadaddr = loadinfo->load_loc; } /* On some systems, loadaddr may already be claimed, so try some @@ -1158,8 +1175,8 @@ load_elf32(struct boot_file_t *file, loadinfo_t *loadinfo) } if (loadinfo->base == (void *)-1) { prom_printf("Claim error, can't allocate kernel memory\n"); - return 0; - } + goto bail; + } DEBUG_F("After ELF parsing, load base: %p, mem_sz: 0x%08lx\n", loadinfo->base, loadinfo->memsize); @@ -1177,20 +1194,25 @@ load_elf32(struct boot_file_t *file, loadinfo_t *loadinfo) if ((*(file->fs->seek))(file, p->p_offset) != FILE_ERR_OK) { prom_printf ("Seek error\n"); prom_release(loadinfo->base, loadinfo->memsize); - return 0; + goto bail; } offset = p->p_vaddr - loadinfo->load_loc; if ((*(file->fs->read))(file, p->p_filesz, loadinfo->base+offset) != p->p_filesz) { prom_printf ("Read failed\n"); prom_release(loadinfo->base, loadinfo->memsize); - return 0; + goto bail; } } free(ph); - + /* Return success at loading the Elf32 kernel */ return 1; + +bail: + if (ph) + free(ph); + return 0; } static int @@ -1205,7 +1227,7 @@ load_elf64(struct boot_file_t *file, loadinfo_t *loadinfo) /* Read the rest of the Elf header... */ if ((*(file->fs->read))(file, size, &e->e_version) < size) { prom_printf("\nCan't read Elf64 image header\n"); - return 0; + goto bail; } DEBUG_F("Elf64 header:\n"); @@ -1224,24 +1246,24 @@ load_elf64(struct boot_file_t *file, loadinfo_t *loadinfo) if (e->e_phnum > MAX_HEADERS) { prom_printf ("Can only load kernels with one program header\n"); - return 0; + goto bail; } ph = (Elf64_Phdr *)malloc(sizeof(Elf64_Phdr) * e->e_phnum); if (!ph) { prom_printf ("Malloc error\n"); - return 0; + goto bail; } /* Now, we read the section header */ if ((*(file->fs->seek))(file, e->e_phoff) != FILE_ERR_OK) { prom_printf ("Seek error\n"); - return 0; + goto bail; } if ((*(file->fs->read))(file, sizeof(Elf64_Phdr) * e->e_phnum, ph) != sizeof(Elf64_Phdr) * e->e_phnum) { prom_printf ("Read error\n"); - return 0; + goto bail; } /* Scan through the program header @@ -1268,7 +1290,7 @@ load_elf64(struct boot_file_t *file, loadinfo_t *loadinfo) if (loadinfo->memsize == 0) { prom_printf("Can't find a loadable segment !\n"); - return 0; + goto bail; } /* leave some room (1Mb) for boot infos */ @@ -1297,8 +1319,8 @@ load_elf64(struct boot_file_t *file, loadinfo_t *loadinfo) } if (loadinfo->base == (void *)-1) { prom_printf("Claim error, can't allocate kernel memory\n"); - return 0; - } + goto bail; + } DEBUG_F("After ELF parsing, load base: %p, mem_sz: 0x%08lx\n", loadinfo->base, loadinfo->memsize); @@ -1316,20 +1338,25 @@ load_elf64(struct boot_file_t *file, loadinfo_t *loadinfo) if ((*(file->fs->seek))(file, p->p_offset) != FILE_ERR_OK) { prom_printf ("Seek error\n"); prom_release(loadinfo->base, loadinfo->memsize); - return 0; + goto bail; } offset = p->p_vaddr - loadinfo->load_loc; if ((*(file->fs->read))(file, p->p_filesz, loadinfo->base+offset) != p->p_filesz) { prom_printf ("Read failed\n"); prom_release(loadinfo->base, loadinfo->memsize); - return 0; + goto bail; } } free(ph); - + /* Return success at loading the Elf64 kernel */ return 1; + +bail: + if (ph) + free(ph); + return 0; } static int @@ -1406,7 +1433,7 @@ setup_display(void) DEBUG_F("Open screen result: %p\n", scrn); } } - + if (scrn == PROM_INVALID_HANDLE) { prom_printf("No screen device found !/n"); return; @@ -1415,7 +1442,7 @@ setup_display(void) prom_set_color(scrn, i, default_colors[i*3], default_colors[i*3+1], default_colors[i*3+2]); } - prom_printf("\x1b[1;37m\x1b[2;40m"); + prom_printf("\x1b[1;37m\x1b[2;40m"); #ifdef COLOR_TEST for (i=0;i<16; i++) { prom_printf("\x1b[%d;%dm\x1b[1;47m%s \x1b[2;40m %s\n", @@ -1429,7 +1456,7 @@ setup_display(void) ansi_color_table[i].name, ansi_color_table[i].name); } - prom_printf("\x1b[1;37m\x1b[2;40m"); + prom_printf("\x1b[1;37m\x1b[2;40m"); #endif /* COLOR_TEST */ #if !DEBUG @@ -1446,7 +1473,7 @@ yaboot_main(void) if (_machine == _MACH_Pmac) setup_display(); - + prom_get_chosen("bootpath", bootdevice, sizeof(bootdevice)); DEBUG_F("/chosen/bootpath = %s\n", bootdevice); if (bootdevice[0] == 0) { @@ -1506,16 +1533,18 @@ yaboot_main(void) if ((ptype != NULL) && (strcmp(ptype, "Apple_Bootstrap"))) prom_printf("\nWARNING: Bootstrap partition type is wrong: \"%s\"\n" " type should be: \"Apple_Bootstrap\"\n\n", ptype); + if (ptype) + free(ptype); } } yaboot_text_ui(); - + prom_printf("Bye.\n"); return 0; } -/* +/* * Local variables: * c-file-style: "k&r" * c-basic-offset: 5