Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / openbios / arch / ppc / pearpc / main.c
1 /*
2  *   Creation Date: <2004/08/28 18:38:22 greg>
3  *   Time-stamp: <2004/08/28 18:38:22 greg>
4  *
5  *      <main.c>
6  *
7  *   Copyright (C) 2004 Greg Watson
8  *
9  *   Based on MOL specific code which is
10  *   Copyright (C) 2002, 2003, 2004 Samuel Rydh (samuel@ibrium.se)
11  *
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
15  *
16  */
17
18
19 #include "config.h"
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"
27
28 static void
29 transfer_control_to_elf( unsigned long entry )
30 {
31         extern void call_elf( unsigned long entry );
32         printk("Starting ELF image at 0x%08lX\n", entry);
33         call_elf( 0x400000 );
34         //call_elf( entry );
35
36         fatal_error("call_elf returned unexpectedly\n");
37 }
38
39 static int
40 load_elf_rom( unsigned long *entry, int fd )
41 {
42         int i, lszz_offs, elf_offs;
43         char buf[128], *addr;
44         Elf_ehdr ehdr;
45         Elf_phdr *phdr;
46         size_t s;
47
48         printk("Loading '%s'\n", get_file_path(fd));
49
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 );
53                 exit(1);
54         }
55         if( !(phdr=elf_readhdrs(fd, elf_offs, &ehdr)) )
56                 fatal_error("elf_readhdrs failed\n");
57
58         *entry = ehdr.e_entry;
59
60         /* load segments. Compressed ROM-image assumed to be located immediately
61          * after the last segment */
62         lszz_offs = elf_offs;
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 );
67
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,
70                    phdr[i].p_vaddr ); */
71
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 );
75                 if( !s )
76                         continue;
77                 if( ofmem_claim( phdr[i].p_vaddr, phdr[i].p_memsz, 0 ) == -1 )
78                         fatal_error("Claim failed!\n");
79
80                 addr = (char*)phdr[i].p_vaddr;
81                 if( read_io(fd, addr, s) != s )
82                         fatal_error("read failed\n");
83
84 #if 0
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 );
89                 }
90 #endif
91                 flush_icache_range( addr, addr+s );
92
93                 /*printk("ELF ROM-section loaded at %08lX (size %08lX)\n",
94                    (unsigned long)phdr[i].p_vaddr, (unsigned long)phdr[i].p_memsz );*/
95         }
96         free( phdr );
97         return lszz_offs;
98 }
99
100
101 static void
102 encode_bootpath( const char *spec, const char *args )
103 {
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 );
107 }
108
109 /************************************************************************/
110 /*      pearpc booting                                                  */
111 /************************************************************************/
112
113 static void
114 pearpc_startup( void )
115 {
116         const char *paths[] = { "hd:0,\\zImage.chrp", NULL };
117         const char *args[] = { "root=/dev/hda2 console=ttyS0,115200", NULL };
118         unsigned long entry;
119         int i, fd;
120
121         for( i=0; paths[i]; i++ ) {
122                 if( (fd=open_io(paths[i])) == -1 )
123                         continue;
124                 (void) load_elf_rom( &entry, fd );
125                 close_io( fd );
126                 encode_bootpath( paths[i], args[i] );
127
128                 update_nvram();
129                 transfer_control_to_elf( entry );
130                 /* won't come here */
131         }
132         printk("*** Boot failure! No secondary bootloader specified ***\n");
133 }
134
135
136 /************************************************************************/
137 /*      entry                                                           */
138 /************************************************************************/
139
140 void
141 boot( void )
142 {
143         fword("update-chosen");
144         pearpc_startup();
145 }