ia64/xen-unstable

view tools/ioemu/hw/magic-load.c @ 6946:e703abaf6e3d

Add behaviour to the remove methods to remove the transaction's path itself. This allows us to write Remove(path) to remove the specified path rather than having to slice the path ourselves.
author emellor@ewan
date Sun Sep 18 14:42:13 2005 +0100 (2005-09-18)
parents 8e5fc5fe636c
children fcb7e5616102
line source
1 #include "vl.h"
2 #include "disas.h"
4 #define ELF_CLASS ELFCLASS32
5 #define ELF_DATA ELFDATA2MSB
6 #define ELF_ARCH EM_SPARC
8 #include "elf.h"
10 #ifdef BSWAP_NEEDED
11 static void bswap_ehdr(Elf32_Ehdr *ehdr)
12 {
13 bswap16s(&ehdr->e_type); /* Object file type */
14 bswap16s(&ehdr->e_machine); /* Architecture */
15 bswap32s(&ehdr->e_version); /* Object file version */
16 bswap32s(&ehdr->e_entry); /* Entry point virtual address */
17 bswap32s(&ehdr->e_phoff); /* Program header table file offset */
18 bswap32s(&ehdr->e_shoff); /* Section header table file offset */
19 bswap32s(&ehdr->e_flags); /* Processor-specific flags */
20 bswap16s(&ehdr->e_ehsize); /* ELF header size in bytes */
21 bswap16s(&ehdr->e_phentsize); /* Program header table entry size */
22 bswap16s(&ehdr->e_phnum); /* Program header table entry count */
23 bswap16s(&ehdr->e_shentsize); /* Section header table entry size */
24 bswap16s(&ehdr->e_shnum); /* Section header table entry count */
25 bswap16s(&ehdr->e_shstrndx); /* Section header string table index */
26 }
28 static void bswap_phdr(Elf32_Phdr *phdr)
29 {
30 bswap32s(&phdr->p_type); /* Segment type */
31 bswap32s(&phdr->p_offset); /* Segment file offset */
32 bswap32s(&phdr->p_vaddr); /* Segment virtual address */
33 bswap32s(&phdr->p_paddr); /* Segment physical address */
34 bswap32s(&phdr->p_filesz); /* Segment size in file */
35 bswap32s(&phdr->p_memsz); /* Segment size in memory */
36 bswap32s(&phdr->p_flags); /* Segment flags */
37 bswap32s(&phdr->p_align); /* Segment alignment */
38 }
40 static void bswap_shdr(Elf32_Shdr *shdr)
41 {
42 bswap32s(&shdr->sh_name);
43 bswap32s(&shdr->sh_type);
44 bswap32s(&shdr->sh_flags);
45 bswap32s(&shdr->sh_addr);
46 bswap32s(&shdr->sh_offset);
47 bswap32s(&shdr->sh_size);
48 bswap32s(&shdr->sh_link);
49 bswap32s(&shdr->sh_info);
50 bswap32s(&shdr->sh_addralign);
51 bswap32s(&shdr->sh_entsize);
52 }
54 static void bswap_sym(Elf32_Sym *sym)
55 {
56 bswap32s(&sym->st_name);
57 bswap32s(&sym->st_value);
58 bswap32s(&sym->st_size);
59 bswap16s(&sym->st_shndx);
60 }
61 #else
62 #define bswap_ehdr(e) do { } while (0)
63 #define bswap_phdr(e) do { } while (0)
64 #define bswap_shdr(e) do { } while (0)
65 #define bswap_sym(e) do { } while (0)
66 #endif
68 static int find_phdr(struct elfhdr *ehdr, int fd, struct elf_phdr *phdr, uint32_t type)
69 {
70 int i, retval;
72 retval = lseek(fd, ehdr->e_phoff, SEEK_SET);
73 if (retval < 0)
74 return -1;
76 for (i = 0; i < ehdr->e_phnum; i++) {
77 retval = read(fd, phdr, sizeof(*phdr));
78 if (retval < 0)
79 return -1;
80 bswap_phdr(phdr);
81 if (phdr->p_type == type)
82 return 0;
83 }
84 return -1;
85 }
87 static void *find_shdr(struct elfhdr *ehdr, int fd, struct elf_shdr *shdr, uint32_t type)
88 {
89 int i, retval;
91 retval = lseek(fd, ehdr->e_shoff, SEEK_SET);
92 if (retval < 0)
93 return NULL;
95 for (i = 0; i < ehdr->e_shnum; i++) {
96 retval = read(fd, shdr, sizeof(*shdr));
97 if (retval < 0)
98 return NULL;
99 bswap_shdr(shdr);
100 if (shdr->sh_type == type)
101 return qemu_malloc(shdr->sh_size);
102 }
103 return NULL;
104 }
106 static int find_strtab(struct elfhdr *ehdr, int fd, struct elf_shdr *shdr, struct elf_shdr *symtab)
107 {
108 int retval;
110 retval = lseek(fd, ehdr->e_shoff + sizeof(struct elf_shdr) * symtab->sh_link, SEEK_SET);
111 if (retval < 0)
112 return -1;
114 retval = read(fd, shdr, sizeof(*shdr));
115 if (retval < 0)
116 return -1;
117 bswap_shdr(shdr);
118 if (shdr->sh_type == SHT_STRTAB)
119 return qemu_malloc(shdr->sh_size);;
120 return 0;
121 }
123 static int read_program(int fd, struct elf_phdr *phdr, void *dst)
124 {
125 int retval;
126 retval = lseek(fd, 0x4000, SEEK_SET);
127 if (retval < 0)
128 return -1;
129 return read(fd, dst, phdr->p_filesz);
130 }
132 static int read_section(int fd, struct elf_shdr *s, void *dst)
133 {
134 int retval;
136 retval = lseek(fd, s->sh_offset, SEEK_SET);
137 if (retval < 0)
138 return -1;
139 retval = read(fd, dst, s->sh_size);
140 if (retval < 0)
141 return -1;
142 return 0;
143 }
145 static void *process_section(struct elfhdr *ehdr, int fd, struct elf_shdr *shdr, uint32_t type)
146 {
147 void *dst;
149 dst = find_shdr(ehdr, fd, shdr, type);
150 if (!dst)
151 goto error;
153 if (read_section(fd, shdr, dst))
154 goto error;
155 return dst;
156 error:
157 qemu_free(dst);
158 return NULL;
159 }
161 static void *process_strtab(struct elfhdr *ehdr, int fd, struct elf_shdr *shdr, struct elf_shdr *symtab)
162 {
163 void *dst;
165 dst = find_strtab(ehdr, fd, shdr, symtab);
166 if (!dst)
167 goto error;
169 if (read_section(fd, shdr, dst))
170 goto error;
171 return dst;
172 error:
173 qemu_free(dst);
174 return NULL;
175 }
177 static void load_symbols(struct elfhdr *ehdr, int fd)
178 {
179 struct elf_shdr symtab, strtab;
180 struct elf_sym *syms;
181 int nsyms, i;
182 char *str;
184 /* Symbol table */
185 syms = process_section(ehdr, fd, &symtab, SHT_SYMTAB);
186 if (!syms)
187 return;
189 nsyms = symtab.sh_size / sizeof(struct elf_sym);
190 for (i = 0; i < nsyms; i++)
191 bswap_sym(&syms[i]);
193 /* String table */
194 str = process_strtab(ehdr, fd, &strtab, &symtab);
195 if (!str)
196 goto error_freesyms;
198 /* Commit */
199 if (disas_symtab)
200 qemu_free(disas_symtab); /* XXX Merge with old symbols? */
201 if (disas_strtab)
202 qemu_free(disas_strtab);
203 disas_symtab = syms;
204 disas_num_syms = nsyms;
205 disas_strtab = str;
206 return;
207 error_freesyms:
208 qemu_free(syms);
209 return;
210 }
212 int load_elf(const char * filename, uint8_t *addr)
213 {
214 struct elfhdr ehdr;
215 struct elf_phdr phdr;
216 int retval, fd;
218 fd = open(filename, O_RDONLY | O_BINARY);
219 if (fd < 0)
220 goto error;
222 retval = read(fd, &ehdr, sizeof(ehdr));
223 if (retval < 0)
224 goto error;
226 bswap_ehdr(&ehdr);
228 if (ehdr.e_ident[0] != 0x7f || ehdr.e_ident[1] != 'E'
229 || ehdr.e_ident[2] != 'L' || ehdr.e_ident[3] != 'F'
230 || ehdr.e_machine != EM_SPARC)
231 goto error;
233 if (find_phdr(&ehdr, fd, &phdr, PT_LOAD))
234 goto error;
235 retval = read_program(fd, &phdr, addr);
236 if (retval < 0)
237 goto error;
239 load_symbols(&ehdr, fd);
241 close(fd);
242 return retval;
243 error:
244 close(fd);
245 return -1;
246 }
248 int load_kernel(const char *filename, uint8_t *addr)
249 {
250 int fd, size;
252 fd = open(filename, O_RDONLY | O_BINARY);
253 if (fd < 0)
254 return -1;
255 /* load 32 bit code */
256 size = read(fd, addr, 16 * 1024 * 1024);
257 if (size < 0)
258 goto fail;
259 close(fd);
260 return size;
261 fail:
262 close(fd);
263 return -1;
264 }
266 typedef struct MAGICState {
267 uint32_t addr;
268 uint32_t saved_addr;
269 int magic_state;
270 char saved_kfn[1024];
271 } MAGICState;
273 static uint32_t magic_mem_readl(void *opaque, target_phys_addr_t addr)
274 {
275 int ret;
276 MAGICState *s = opaque;
278 if (s->magic_state == 0) {
279 ret = load_elf(s->saved_kfn, (uint8_t *)s->saved_addr);
280 if (ret < 0)
281 ret = load_kernel(s->saved_kfn, (uint8_t *)s->saved_addr);
282 if (ret < 0) {
283 fprintf(stderr, "qemu: could not load kernel '%s'\n",
284 s->saved_kfn);
285 }
286 s->magic_state = 1; /* No more magic */
287 tb_flush();
288 return bswap32(ret);
289 }
290 return 0;
291 }
293 static void magic_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
294 {
295 }
298 static CPUReadMemoryFunc *magic_mem_read[3] = {
299 magic_mem_readl,
300 magic_mem_readl,
301 magic_mem_readl,
302 };
304 static CPUWriteMemoryFunc *magic_mem_write[3] = {
305 magic_mem_writel,
306 magic_mem_writel,
307 magic_mem_writel,
308 };
310 void magic_init(const char *kfn, int kloadaddr, uint32_t addr)
311 {
312 int magic_io_memory;
313 MAGICState *s;
315 s = qemu_mallocz(sizeof(MAGICState));
316 if (!s)
317 return;
319 strcpy(s->saved_kfn, kfn);
320 s->saved_addr = kloadaddr;
321 s->magic_state = 0;
322 s->addr = addr;
323 magic_io_memory = cpu_register_io_memory(0, magic_mem_read, magic_mem_write, s);
324 cpu_register_physical_memory(addr, 4, magic_io_memory);
325 }