Revision e80cfcfc hw/magic-load.c

b/hw/magic-load.c
1 1
#include "vl.h"
2 2
#include "disas.h"
3
#include "exec-all.h"
4

  
5
struct exec
6
{
7
  uint32_t a_info;   /* Use macros N_MAGIC, etc for access */
8
  uint32_t a_text;   /* length of text, in bytes */
9
  uint32_t a_data;   /* length of data, in bytes */
10
  uint32_t a_bss;    /* length of uninitialized data area, in bytes */
11
  uint32_t a_syms;   /* length of symbol table data in file, in bytes */
12
  uint32_t a_entry;  /* start address */
13
  uint32_t a_trsize; /* length of relocation info for text, in bytes */
14
  uint32_t a_drsize; /* length of relocation info for data, in bytes */
15
};
16

  
17
#ifdef BSWAP_NEEDED
18
static void bswap_ahdr(struct exec *e)
19
{
20
    bswap32s(&e->a_info);
21
    bswap32s(&e->a_text);
22
    bswap32s(&e->a_data);
23
    bswap32s(&e->a_bss);
24
    bswap32s(&e->a_syms);
25
    bswap32s(&e->a_entry);
26
    bswap32s(&e->a_trsize);
27
    bswap32s(&e->a_drsize);
28
}
29
#else
30
#define bswap_ahdr(x) do { } while (0)
31
#endif
32

  
33
#define N_MAGIC(exec) ((exec).a_info & 0xffff)
34
#define OMAGIC 0407
35
#define NMAGIC 0410
36
#define ZMAGIC 0413
37
#define QMAGIC 0314
38
#define _N_HDROFF(x) (1024 - sizeof (struct exec))
39
#define N_TXTOFF(x)							\
40
    (N_MAGIC(x) == ZMAGIC ? _N_HDROFF((x)) + sizeof (struct exec) :	\
41
     (N_MAGIC(x) == QMAGIC ? 0 : sizeof (struct exec)))
42
#define N_TXTADDR(x) (N_MAGIC(x) == QMAGIC ? TARGET_PAGE_SIZE : 0)
43
#define N_DATOFF(x) (N_TXTOFF(x) + (x).a_text)
44
#define _N_SEGMENT_ROUND(x) (((x) + TARGET_PAGE_SIZE - 1) & ~(TARGET_PAGE_SIZE - 1))
45

  
46
#define _N_TXTENDADDR(x) (N_TXTADDR(x)+(x).a_text)
47

  
48
#define N_DATADDR(x) \
49
    (N_MAGIC(x)==OMAGIC? (_N_TXTENDADDR(x)) \
50
     : (_N_SEGMENT_ROUND (_N_TXTENDADDR(x))))
51

  
3 52

  
4 53
#define ELF_CLASS   ELFCLASS32
5 54
#define ELF_DATA    ELFDATA2MSB
......
103 152
    return NULL;
104 153
}
105 154

  
106
static int find_strtab(struct elfhdr *ehdr, int fd, struct elf_shdr *shdr, struct elf_shdr *symtab)
155
static void *find_strtab(struct elfhdr *ehdr, int fd, struct elf_shdr *shdr, struct elf_shdr *symtab)
107 156
{
108 157
    int retval;
109 158

  
110 159
    retval = lseek(fd, ehdr->e_shoff + sizeof(struct elf_shdr) * symtab->sh_link, SEEK_SET);
111 160
    if (retval < 0)
112
	return -1;
161
	return NULL;
113 162

  
114 163
    retval = read(fd, shdr, sizeof(*shdr));
115 164
    if (retval < 0)
116
	return -1;
165
	return NULL;
117 166
    bswap_shdr(shdr);
118 167
    if (shdr->sh_type == SHT_STRTAB)
119 168
	return qemu_malloc(shdr->sh_size);;
120
    return 0;
169
    return NULL;
121 170
}
122 171

  
123
static int read_program(int fd, struct elf_phdr *phdr, void *dst)
172
static int read_program(int fd, struct elf_phdr *phdr, void *dst, uint32_t entry)
124 173
{
125 174
    int retval;
126
    retval = lseek(fd, 0x4000, SEEK_SET);
175
    retval = lseek(fd, phdr->p_offset + entry - phdr->p_vaddr, SEEK_SET);
127 176
    if (retval < 0)
128 177
	return -1;
129 178
    return read(fd, dst, phdr->p_filesz);
......
178 227
{
179 228
    struct elf_shdr symtab, strtab;
180 229
    struct elf_sym *syms;
230
    struct syminfo *s;
181 231
    int nsyms, i;
182 232
    char *str;
183 233

  
......
196 246
	goto error_freesyms;
197 247

  
198 248
    /* 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;
249
    s = qemu_mallocz(sizeof(*s));
250
    s->disas_symtab = syms;
251
    s->disas_num_syms = nsyms;
252
    s->disas_strtab = str;
253
    s->next = syminfos;
254
    syminfos = s;
206 255
    return;
207 256
 error_freesyms:
208 257
    qemu_free(syms);
209 258
    return;
210 259
}
211 260

  
212
int load_elf(const char * filename, uint8_t *addr)
261
int load_elf(const char *filename, uint8_t *addr)
213 262
{
214 263
    struct elfhdr ehdr;
215 264
    struct elf_phdr phdr;
......
227 276

  
228 277
    if (ehdr.e_ident[0] != 0x7f || ehdr.e_ident[1] != 'E'
229 278
	|| ehdr.e_ident[2] != 'L' || ehdr.e_ident[3] != 'F'
230
	|| ehdr.e_machine != EM_SPARC)
279
	|| (ehdr.e_machine != EM_SPARC
280
	    && ehdr.e_machine != EM_SPARC32PLUS))
231 281
	goto error;
232 282

  
233 283
    if (find_phdr(&ehdr, fd, &phdr, PT_LOAD))
234 284
	goto error;
235
    retval = read_program(fd, &phdr, addr);
285
    retval = read_program(fd, &phdr, addr, ehdr.e_entry);
236 286
    if (retval < 0)
237 287
	goto error;
238 288

  
......
245 295
    return -1;
246 296
}
247 297

  
248
int load_kernel(const char *filename, uint8_t *addr)
298
int load_aout(const char *filename, uint8_t *addr)
249 299
{
250
    int fd, size;
300
    int fd, size, ret;
301
    struct exec e;
302
    uint32_t magic;
251 303

  
252 304
    fd = open(filename, O_RDONLY | O_BINARY);
253 305
    if (fd < 0)
254 306
        return -1;
255
    /* load 32 bit code */
256
    size = read(fd, addr, 16 * 1024 * 1024);
307

  
308
    size = read(fd, &e, sizeof(e));
257 309
    if (size < 0)
258 310
        goto fail;
311

  
312
    bswap_ahdr(&e);
313

  
314
    magic = N_MAGIC(e);
315
    switch (magic) {
316
    case ZMAGIC:
317
    case QMAGIC:
318
    case OMAGIC:
319
	lseek(fd, N_TXTOFF(e), SEEK_SET);
320
	size = read(fd, addr, e.a_text + e.a_data);
321
	if (size < 0)
322
	    goto fail;
323
	break;
324
    case NMAGIC:
325
	lseek(fd, N_TXTOFF(e), SEEK_SET);
326
	size = read(fd, addr, e.a_text);
327
	if (size < 0)
328
	    goto fail;
329
	ret = read(fd, addr + N_DATADDR(e), e.a_data);
330
	if (ret < 0)
331
	    goto fail;
332
	size += ret;
333
	break;
334
    default:
335
	goto fail;
336
    }
259 337
    close(fd);
260 338
    return size;
261 339
 fail:
......
263 341
    return -1;
264 342
}
265 343

  
266
typedef struct MAGICState {
267
    uint32_t addr;
268
    uint32_t saved_addr;
269
    int magic_state;
270
    char saved_kfn[1024];
271
} MAGICState;
272

  
273
static uint32_t magic_mem_readl(void *opaque, target_phys_addr_t addr)
274
{
275
    int ret;
276
    MAGICState *s = opaque;
277

  
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
}
292

  
293
static void magic_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
294
{
295
}
296

  
297

  
298
static CPUReadMemoryFunc *magic_mem_read[3] = {
299
    magic_mem_readl,
300
    magic_mem_readl,
301
    magic_mem_readl,
302
};
303

  
304
static CPUWriteMemoryFunc *magic_mem_write[3] = {
305
    magic_mem_writel,
306
    magic_mem_writel,
307
    magic_mem_writel,
308
};
309

  
310
void magic_init(const char *kfn, int kloadaddr, uint32_t addr)
311
{
312
    int magic_io_memory;
313
    MAGICState *s;
314

  
315
    s = qemu_mallocz(sizeof(MAGICState));
316
    if (!s)
317
        return;
318

  
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
}
326

  

Also available in: Unified diff