-/* 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"
/* 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
/* 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) {
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);
_machine = _MACH_chrp;
}
}
-
+
DEBUG_F("Running on _machine = %d\n", _machine);
DEBUG_SLEEP;
/* Return to OF */
prom_exit();
-
+
return result;
-
+
}
#ifdef CONFIG_COLOR_TEXT
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;
if (p) {
n = simple_strtol(p, &endp, 10);
if (endp != p && *endp == 0)
- defpart = n;
+ defpart = n;
}
strncpy(msgpath, filename, sizeof(msgpath));
prom_interpret(p);
password = cfg_get_strg(0, "password");
-
+
#ifdef CONFIG_COLOR_TEXT
p = cfg_get_strg(0, "fgcolor");
if (p) {
}
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);
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;
}
if (!strncmp (password, "$1$", 3)) {
if (!check_md5_password(passwdbuff, password))
return;
- }
+ }
else if (!strcmp (password, passwdbuff))
return;
#else /* !MD5 */
params->rd.part = -1;
params->sysmap.part = -1;
defpart = boot.part;
-
+
cmdinit();
if (first) {
check_password ("Restricted command.");
return 1;
}
- return 1;
+ return 1;
}
if (imagename[0] == '$') {
loadinfo_t loadinfo;
void *initrd_more,*initrd_want;
unsigned long initrd_read;
-
+
loadinfo.load_loc = 0;
for (;;) {
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));
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);
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);
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");
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);
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,
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);
/* 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 */
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
}
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);
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
/* 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 */
}
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);
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
DEBUG_F("Open screen result: %p\n", scrn);
}
}
-
+
if (scrn == PROM_INVALID_HANDLE) {
prom_printf("No screen device found !/n");
return;
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",
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
if (_machine == _MACH_Pmac)
setup_display();
-
+
prom_get_chosen("bootpath", bootdevice, sizeof(bootdevice));
DEBUG_F("/chosen/bootpath = %s\n", bootdevice);
if (bootdevice[0] == 0) {
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