2 * Creation Date: <2004/08/28 18:38:22 greg>
3 * Time-stamp: <2004/08/28 18:38:22 greg>
7 * Copyright (C) 2004 Greg Watson
9 * Based on MOL specific code which is
10 * Copyright (C) 2002, 2003, 2004 Samuel Rydh (samuel@ibrium.se)
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation
20 #include "libopenbios/bindings.h"
21 #include "libopenbios/elfload.h"
22 #include "arch/common/nvram.h"
23 #include "libc/diskio.h"
24 #include "libc/vsprintf.h"
25 #include "pearpc/pearpc.h"
26 #include "libopenbios/ofmem.h"
29 transfer_control_to_elf( unsigned long entry )
31 extern void call_elf( unsigned long entry );
32 printk("Starting ELF image at 0x%08lX\n", entry);
36 fatal_error("call_elf returned unexpectedly\n");
40 load_elf_rom( unsigned long *entry, int fd )
42 int i, lszz_offs, elf_offs;
48 printk("Loading '%s'\n", get_file_path(fd));
50 /* the ELF-image (usually) starts at offset 0x4000 */
51 if( (elf_offs=find_elf(fd)) < 0 ) {
52 printk("----> %s is not an ELF image\n", buf );
55 if( !(phdr=elf_readhdrs(fd, elf_offs, &ehdr)) )
56 fatal_error("elf_readhdrs failed\n");
58 *entry = ehdr.e_entry;
60 /* load segments. Compressed ROM-image assumed to be located immediately
61 * after the last segment */
63 for( i=0; i<ehdr.e_phnum; i++ ) {
64 /* p_memsz, p_flags */
65 s = MIN( phdr[i].p_filesz, phdr[i].p_memsz );
66 seek_io( fd, elf_offs + phdr[i].p_offset );
68 /* printk("filesz: %08lX memsz: %08lX p_offset: %08lX p_vaddr %08lX\n",
69 phdr[i].p_filesz, phdr[i].p_memsz, phdr[i].p_offset,
72 if( phdr[i].p_vaddr != phdr[i].p_paddr )
73 printk("WARNING: ELF segment virtual addr != physical addr\n");
74 lszz_offs = MAX( lszz_offs, elf_offs + phdr[i].p_offset + phdr[i].p_filesz );
77 if( ofmem_claim( phdr[i].p_vaddr, phdr[i].p_memsz, 0 ) == -1 )
78 fatal_error("Claim failed!\n");
80 addr = (char*)phdr[i].p_vaddr;
81 if( read_io(fd, addr, s) != s )
82 fatal_error("read failed\n");
85 /* patch CODE segment */
86 if( *entry >= phdr[i].p_vaddr && *entry < phdr[i].p_vaddr + s ) {
87 patch_newworld_rom( (char*)phdr[i].p_vaddr, s );
88 newworld_timer_hack( (char*)phdr[i].p_vaddr, s );
91 flush_icache_range( addr, addr+s );
93 /*printk("ELF ROM-section loaded at %08lX (size %08lX)\n",
94 (unsigned long)phdr[i].p_vaddr, (unsigned long)phdr[i].p_memsz );*/
102 encode_bootpath( const char *spec, const char *args )
104 phandle_t chosen_ph = find_dev("/chosen");
105 set_property( chosen_ph, "bootpath", spec, strlen(spec)+1 );
106 set_property( chosen_ph, "bootargs", args, strlen(args)+1 );
109 /************************************************************************/
111 /************************************************************************/
114 pearpc_startup( void )
116 const char *paths[] = { "hd:0,\\zImage.chrp", NULL };
117 const char *args[] = { "root=/dev/hda2 console=ttyS0,115200", NULL };
121 for( i=0; paths[i]; i++ ) {
122 if( (fd=open_io(paths[i])) == -1 )
124 (void) load_elf_rom( &entry, fd );
126 encode_bootpath( paths[i], args[i] );
129 transfer_control_to_elf( entry );
130 /* won't come here */
132 printk("*** Boot failure! No secondary bootloader specified ***\n");
136 /************************************************************************/
138 /************************************************************************/
143 fword("update-chosen");