Allow selection of emulated network card.
[qemu] / hw / magic-load.c
1 #include "vl.h"
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
52
53 #define ELF_CLASS   ELFCLASS32
54 #define ELF_DATA    ELFDATA2MSB
55 #define ELF_ARCH    EM_SPARC
56
57 #include "elf.h"
58
59 #ifndef BSWAP_NEEDED
60 #define bswap_ehdr32(e) do { } while (0)
61 #define bswap_phdr32(e) do { } while (0)
62 #define bswap_shdr32(e) do { } while (0)
63 #define bswap_sym32(e) do { } while (0)
64 #ifdef TARGET_SPARC64
65 #define bswap_ehdr64(e) do { } while (0)
66 #define bswap_phdr64(e) do { } while (0)
67 #define bswap_shdr64(e) do { } while (0)
68 #define bswap_sym64(e) do { } while (0)
69 #endif
70 #endif
71
72 #define SZ              32
73 #define elf_word        uint32_t
74 #define bswapSZs        bswap32s
75 #include "elf_ops.h"
76
77 #ifdef TARGET_SPARC64
78 #undef elfhdr
79 #undef elf_phdr
80 #undef elf_shdr
81 #undef elf_sym
82 #undef elf_note
83 #undef elf_word
84 #undef bswapSZs
85 #undef SZ
86 #define elfhdr          elf64_hdr
87 #define elf_phdr        elf64_phdr
88 #define elf_note        elf64_note
89 #define elf_shdr        elf64_shdr
90 #define elf_sym         elf64_sym
91 #define elf_word        uint64_t
92 #define bswapSZs        bswap64s
93 #define SZ              64
94 #include "elf_ops.h"
95 #endif
96
97 int load_elf(const char *filename, uint8_t *addr)
98 {
99     struct elf32_hdr ehdr;
100     int retval, fd;
101     Elf32_Half machine;
102
103     fd = open(filename, O_RDONLY | O_BINARY);
104     if (fd < 0)
105         goto error;
106
107     retval = read(fd, &ehdr, sizeof(ehdr));
108     if (retval < 0)
109         goto error;
110
111     if (ehdr.e_ident[0] != 0x7f || ehdr.e_ident[1] != 'E'
112         || ehdr.e_ident[2] != 'L' || ehdr.e_ident[3] != 'F')
113         goto error;
114     machine = tswap16(ehdr.e_machine);
115     if (machine == EM_SPARC || machine == EM_SPARC32PLUS) {
116         struct elf32_phdr phdr;
117
118         bswap_ehdr32(&ehdr);
119
120         if (find_phdr32(&ehdr, fd, &phdr, PT_LOAD))
121             goto error;
122         retval = read_program32(fd, &phdr, addr, ehdr.e_entry);
123         if (retval < 0)
124             goto error;
125         load_symbols32(&ehdr, fd);
126     }
127 #ifdef TARGET_SPARC64
128     else if (machine == EM_SPARCV9) {
129         struct elf64_hdr ehdr64;
130         struct elf64_phdr phdr;
131
132         lseek(fd, 0, SEEK_SET);
133
134         retval = read(fd, &ehdr64, sizeof(ehdr64));
135         if (retval < 0)
136             goto error;
137
138         bswap_ehdr64(&ehdr64);
139
140         if (find_phdr64(&ehdr64, fd, &phdr, PT_LOAD))
141             goto error;
142         retval = read_program64(fd, &phdr, phys_ram_base + ehdr64.e_entry, ehdr64.e_entry);
143         if (retval < 0)
144             goto error;
145         load_symbols64(&ehdr64, fd);
146     }
147 #endif
148
149     close(fd);
150     return retval;
151  error:
152     close(fd);
153     return -1;
154 }
155
156 int load_aout(const char *filename, uint8_t *addr)
157 {
158     int fd, size, ret;
159     struct exec e;
160     uint32_t magic;
161
162     fd = open(filename, O_RDONLY | O_BINARY);
163     if (fd < 0)
164         return -1;
165
166     size = read(fd, &e, sizeof(e));
167     if (size < 0)
168         goto fail;
169
170     bswap_ahdr(&e);
171
172     magic = N_MAGIC(e);
173     switch (magic) {
174     case ZMAGIC:
175     case QMAGIC:
176     case OMAGIC:
177         lseek(fd, N_TXTOFF(e), SEEK_SET);
178         size = read(fd, addr, e.a_text + e.a_data);
179         if (size < 0)
180             goto fail;
181         break;
182     case NMAGIC:
183         lseek(fd, N_TXTOFF(e), SEEK_SET);
184         size = read(fd, addr, e.a_text);
185         if (size < 0)
186             goto fail;
187         ret = read(fd, addr + N_DATADDR(e), e.a_data);
188         if (ret < 0)
189             goto fail;
190         size += ret;
191         break;
192     default:
193         goto fail;
194     }
195     close(fd);
196     return size;
197  fail:
198     close(fd);
199     return -1;
200 }
201