Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / openbios / libopenbios / aout_load.c
1 /* a.out boot loader
2  * As we have seek, this implementation can be straightforward.
3  * 2003-07 by SONE Takeshi
4  */
5
6 #include "config.h"
7 #include "kernel/kernel.h"
8
9 #ifdef CONFIG_SPARC64
10 #define CONFIG_SPARC64_PAGE_SIZE_8KB
11 #endif
12
13 /* NextStep bootloader on SPARC32 expects the a.out header directly
14    below load-base (0x4000) */
15 #ifdef CONFIG_SPARC32
16 #define AOUT_HEADER_COPY
17 #endif 
18
19 #include "libopenbios/sys_info.h"
20 #include "libopenbios/bindings.h"
21 #include "libopenbios/aout_load.h"
22 #include "libc/diskio.h"
23 #define printf printk
24 #define debug printk
25
26 #define addr_fixup(addr) ((addr) & 0x00ffffff)
27
28 static char *image_name, *image_version;
29 static int fd;
30
31 static int 
32 check_mem_ranges(struct sys_info *info,
33                             unsigned long start,
34                             unsigned long size)
35 {
36     int j;
37     unsigned long end;
38     unsigned long prog_start, prog_end;
39     struct memrange *mem;
40
41     prog_start = virt_to_phys(&_start);
42     prog_end = virt_to_phys(&_end);
43
44     end = start + size;
45
46     if (start < prog_start && end > prog_start)
47         goto conflict;
48     if (start < prog_end && end > prog_end)
49         goto conflict;
50     mem = info->memrange;
51     for (j = 0; j < info->n_memranges; j++) {
52         if (mem[j].base <= start && mem[j].base + mem[j].size >= end)
53             break;
54     }
55     if (j >= info->n_memranges)
56         goto badseg;
57     return 1;
58
59  conflict:
60     printf("%s occupies [%#lx-%#lx]\n", program_name, prog_start, prog_end);
61
62  badseg:
63     printf("A.out file [%#lx-%#lx] doesn't fit into memory\n", start, end - 1);
64     return 0;
65 }
66
67 int 
68 is_aout(struct exec *ehdr)
69 {
70         return ((ehdr->a_info & 0xffff) == OMAGIC
71                 || (ehdr->a_info & 0xffff) == NMAGIC
72                 || (ehdr->a_info & 0xffff) == ZMAGIC
73                 || (ehdr->a_info & 0xffff) == QMAGIC);
74 }
75
76 int 
77 aout_load(struct sys_info *info, ihandle_t dev)
78 {
79     int retval = -1;
80     struct exec ehdr;
81     unsigned long start, size;
82     unsigned int offset;
83
84     image_name = image_version = NULL;
85
86     /* Mark the saved-program-state as invalid */
87     feval("0 state-valid !");
88
89     fd = open_ih(dev);
90     if (fd == -1) {
91         goto out;
92     }
93
94     for (offset = 0; offset < 16 * 512; offset += 512) {
95         seek_io(fd, offset);
96         if (read_io(fd, &ehdr, sizeof ehdr) != sizeof ehdr) {
97             debug("Can't read a.out header\n");
98             retval = LOADER_NOT_SUPPORT;
99             goto out;
100         }
101         if (is_aout(&ehdr))
102             break;
103     }
104
105     if (!is_aout(&ehdr)) {
106         debug("Not a bootable a.out image\n");
107         retval = LOADER_NOT_SUPPORT;
108         goto out;
109     }
110
111     if (ehdr.a_text == 0x30800007)
112         ehdr.a_text=64*1024;
113
114     if (N_MAGIC(ehdr) == NMAGIC) {
115         size = addr_fixup(N_DATADDR(ehdr)) + addr_fixup(ehdr.a_data);
116     } else {
117         size = addr_fixup(ehdr.a_text) + addr_fixup(ehdr.a_data);
118     }
119
120     if (size < 7680)
121         size = 7680;
122
123     fword("load-base");
124     start = POP(); // N_TXTADDR(ehdr);
125
126     if (!check_mem_ranges(info, start, size))
127         goto out;
128
129     printf("Loading a.out %s...\n", image_name ? image_name : "image");
130
131     seek_io(fd, offset + N_TXTOFF(ehdr));
132
133     if (N_MAGIC(ehdr) == NMAGIC) {
134         if ((size_t)read_io(fd, (void *)start, ehdr.a_text) != ehdr.a_text) {
135             printf("Can't read program text segment (size 0x" FMT_aout_ehdr ")\n", ehdr.a_text);
136             goto out;
137         }
138         if ((size_t)read_io(fd, (void *)(start + N_DATADDR(ehdr)), ehdr.a_data) != ehdr.a_data) {
139             printf("Can't read program data segment (size 0x" FMT_aout_ehdr ")\n", ehdr.a_data);
140             goto out;
141         }
142     } else {
143         if ((size_t)read_io(fd, (void *)start, size) != size) {
144             printf("Can't read program (size 0x" FMT_sizet ")\n", size);
145             goto out;
146         }
147     }
148
149     debug("Loaded %lu bytes\n", size);
150     debug("entry point is %#lx\n", start);
151
152 #ifdef AOUT_HEADER_COPY
153     // Copy the a.out header just before start
154     memcpy((char *)(start - 0x20), &ehdr, 0x20);
155 #endif
156
157     // Initialise saved-program-state
158     PUSH(addr_fixup(start));
159     feval("saved-program-state >sps.entry !");
160     PUSH(size);
161     feval("saved-program-state >sps.file-size !");
162     feval("aout saved-program-state >sps.file-type !");
163
164     feval("-1 state-valid !");
165
166 out:
167     close_io(fd);
168     return retval;
169 }
170
171 void 
172 aout_init_program(void)
173 {
174         // Currently not implemented
175         feval("0 state-valid !");
176 }