-/* 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"
char *password = NULL;
struct boot_fspec_t boot;
int _machine = _MACH_Pmac;
+int flat_vmlinux;
#ifdef CONFIG_COLOR_TEXT
}
/* Build the path to the file */
- if (path)
- strcpy(conf_path, path);
- else if ( _machine == _MACH_chrp )
+ if (_machine == _MACH_chrp)
strcpy(conf_path, "/etc/");
+ else if (path && *path)
+ strcpy(conf_path, path);
else
conf_path[0] = 0;
strcat(conf_path, CONFIG_FILE_NAME);
if (opened)
file.fs->close(&file);
- if (result != 1 && conf_file)
+ if (conf_file)
free(conf_file);
return result;
{
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");
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");
}
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, "
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;
if (imagename[0] == '$') {
/* forth command string */
if (password)
- check_password ("P");
+ check_password ("OpenFirmware commands are restricted.");
prom_interpret(imagename+1);
return 0;
}
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)) {
file.fs->close(&file);
memset(&file, 0, sizeof(file));
- /* If sysmap, load it.
+ /* If sysmap, load it (only if booting a vmlinux).
*/
- if (params.sysmap.file) {
+ if (flat_vmlinux && params.sysmap.file) {
prom_printf("Loading System.map ...\n");
if(strlen(boot.file) && !strcmp(boot.file,"\\\\") && params.sysmap.file[0] != '/'
&& params.sysmap.file[0] != '\\') {
}
}
- /* If ramdisk, load it. For now, we can't tell the size it will be
- * so we claim an arbitrary amount of 4Mb
+ /* If ramdisk, load it (only if booting a vmlinux). For now, we
+ * can't tell the size it will be so we claim an arbitrary amount
+ * of 4Mb.
*/
- if (params.rd.file) {
+ if (flat_vmlinux && params.rd.file) {
if(strlen(boot.file) && !strcmp(boot.file,"\\\\") && params.rd.file[0] != '/'
&& params.kernel.file[0] != '\\')
{
flush_icache_range ((long)loadinfo.base, (long)loadinfo.base+loadinfo.memsize);
DEBUG_F(" done\n");
-/*
- * Fill mew boot infos
- *
- * The birec is low on memory, probably inside the malloc pool, so
- * we don't write it earlier. At this point, we should not use anything
- * coming from the malloc pool
- */
- birec = (struct bi_record *)_ALIGN(loadinfo.filesize+(1<<20)-1,(1<<20));
-
-/* We make sure it's mapped. We map only 64k for now, it's plenty enough
- * we don't claim since this precise memory range may already be claimed
- * by the malloc pool
- */
- prom_map (birec, birec, 0x10000);
- DEBUG_F("birec at %p\n", birec);
- DEBUG_SLEEP;
-
- birec->tag = BI_FIRST;
- birec->size = sizeof(struct bi_record);
- birec = (struct bi_record *)((unsigned long)birec + birec->size);
+ if (flat_vmlinux) {
+ /*
+ * Fill new boot infos (only if booting a vmlinux).
+ *
+ * The birec is low on memory, probably inside the malloc pool,
+ * so we don't write it earlier. At this point, we should not
+ * use anything coming from the malloc pool.
+ */
+ birec = (struct bi_record *)_ALIGN(loadinfo.filesize+(1<<20)-1,(1<<20));
+
+ /* We make sure it's mapped. We map only 64k for now, it's
+ * plenty enough we don't claim since this precise memory
+ * range may already be claimed by the malloc pool.
+ */
+ prom_map (birec, birec, 0x10000);
+ DEBUG_F("birec at %p\n", birec);
+ DEBUG_SLEEP;
+
+ 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 *)((unsigned long)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(unsigned long);
- birec = (struct bi_record *)((unsigned long)birec + birec->size);
-
- if (sysmap_base) {
- birec->tag = BI_SYSMAP;
- birec->data[0] = (unsigned long)sysmap_base;
- birec->data[1] = sysmap_size;
- birec->size = sizeof(struct bi_record) + sizeof(unsigned long)*2;
- birec = (struct bi_record *)((unsigned long)birec + birec->size);
- }
- birec->tag = BI_LAST;
- birec->size = sizeof(struct bi_record);
- birec = (struct bi_record *)((unsigned long)birec + birec->size);
+ birec->tag = BI_MACHTYPE;
+ birec->data[0] = _machine;
+ birec->size = sizeof(struct bi_record) + sizeof(ulong);
+ birec = (struct bi_record *)((ulong)birec + birec->size);
+
+ if (sysmap_base) {
+ birec->tag = BI_SYSMAP;
+ birec->data[0] = (ulong)sysmap_base;
+ birec->data[1] = sysmap_size;
+ birec->size = sizeof(struct bi_record) + sizeof(ulong)*2;
+ birec = (struct bi_record *)((ulong)birec + birec->size);
+ }
+ birec->tag = BI_LAST;
+ birec->size = sizeof(struct bi_record);
+ birec = (struct bi_record *)((ulong)birec + birec->size);
+ }
/* compute the kernel's entry point. */
kernel_entry = loadinfo.base + loadinfo.entry - loadinfo.load_loc;
/* 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");
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
if (loadinfo->memsize == 0) {
prom_printf("Can't find a loadable segment !\n");
- return 0;
+ goto bail;
}
/* leave some room (1Mb) for boot infos */
/* Claim OF memory */
DEBUG_F("Before prom_claim, mem_sz: 0x%08lx\n", loadinfo->memsize);
+ /* Determine whether we are trying to boot a vmlinux or some
+ * other binary image (eg, zImage). We load vmlinux's at
+ * KERNELADDR and all other binaries at their e_entry value.
+ */
+ if (e->e_entry == KERNEL_LINK_ADDR_PPC32) {
+ flat_vmlinux = 1;
+ loadaddr = KERNELADDR;
+ } else {
+ flat_vmlinux = 0;
+ loadaddr = loadinfo->load_loc;
+ }
+
/* On some systems, loadaddr may already be claimed, so try some
* other nearby addresses before giving up.
*/
- loadaddr = (e->e_entry == KERNEL_LINK_ADDR_PPC32 ||
- e->e_entry == 0) ? KERNELADDR : e->e_entry;
for(addr=loadaddr; addr <= loadaddr * 8 ;addr+=0x100000) {
loadinfo->base = prom_claim((void *)addr, loadinfo->memsize, 0);
if (loadinfo->base != (void *)-1) break;
}
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",
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;
}
}
/* Return success at loading the Elf32 kernel */
return 1;
+
+bail:
+ if (ph)
+ free(ph);
+ return 0;
}
static int
/* 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");
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
if (loadinfo->memsize == 0) {
prom_printf("Can't find a loadable segment !\n");
- return 0;
+ goto bail;
}
/* leave some room (1Mb) for boot infos */
/* Claim OF memory */
DEBUG_F("Before prom_claim, mem_sz: 0x%08lx\n", loadinfo->memsize);
+ /* Determine whether we are trying to boot a vmlinux or some
+ * other binary image (eg, zImage). We load vmlinux's at
+ * KERNELADDR and all other binaries at their e_entry value.
+ */
+ if (e->e_entry == KERNEL_LINK_ADDR_PPC64) {
+ flat_vmlinux = 1;
+ loadaddr = KERNELADDR;
+ } else {
+ flat_vmlinux = 0;
+ loadaddr = e->e_entry;
+ }
+
/* On some systems, loadaddr may already be claimed, so try some
* other nearby addresses before giving up.
*/
- loadaddr = (e->e_entry == KERNEL_LINK_ADDR_PPC64) ? KERNELADDR : e->e_entry;
for(addr=loadaddr; addr <= loadaddr * 8 ;addr+=0x100000) {
loadinfo->base = prom_claim((void *)addr, loadinfo->memsize, 0);
if (loadinfo->base != (void *)-1) break;
}
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",
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;
}
}
/* Return success at loading the Elf64 kernel */
return 1;
+
+bail:
+ if (ph)
+ free(ph);
+ return 0;
}
static int
prom_get_chosen("bootpath", bootdevice, sizeof(bootdevice));
DEBUG_F("/chosen/bootpath = %s\n", bootdevice);
- if (bootdevice[0] == 0)
+ if (bootdevice[0] == 0) {
prom_get_options("boot-device", bootdevice, sizeof(bootdevice));
+ DEBUG_F("boot-device = %s\n", bootdevice);
+ }
if (bootdevice[0] == 0) {
prom_printf("Couldn't determine boot device\n");
return -1;
}
- if (!parse_device_path(bootdevice, (_machine == _MACH_Pmac) ? "hd" : "disc",
- -1, "", &boot)) {
+ if (!parse_device_path(bootdevice, NULL, -1, "", &boot)) {
prom_printf("%s: Unable to parse\n", bootdevice);
return -1;
}
strcat(boot.file, "\\");
}
}
- DEBUG_F("After path fixup: dev=%s, part=%d, file=%s\n",
+ DEBUG_F("After pmac path kludgeup: dev=%s, part=%d, file=%s\n",
boot.dev, boot.part, boot.file);
useconf = load_config_file(boot.dev, boot.file, boot.part);
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;
}