Dash:
[t2.git] / package / boot / arcload / 12_ELF64_on_M32.patch
blob7c34c44f73aaa72548b14cdb50f9552b0482ba9a
1 #! /bin/sh /usr/share/dpatch/dpatch-run
2 ## 12_ELF64_on_M32.dpatch by <jblache@debian.org>
3 ##
4 ## All lines beginning with `## DP:' are a description of the patch.
5 ## DP: Add support for loading ELF64 kernels on 32bit PROMs.
6 ## DP: (some code shamelessly stolen from arcboot)
8 @DPATCH@
9 diff -urNad arcload-0.5~/loader/main.c arcload-0.5/loader/main.c
10 --- arcload-0.5~/loader/main.c 2007-09-11 16:17:27.000000000 +0000
11 +++ arcload-0.5/loader/main.c 2007-09-11 16:18:32.000000000 +0000
12 @@ -30,6 +30,17 @@
13 // malloc pool size
14 #define ARENA 1048576
17 +typedef union {
18 + unsigned char e_ident[EI_NIDENT];
19 + Elf32_Ehdr e32;
20 + Elf64_Ehdr e64;
21 +} Elf_Ehdr;
23 +#ifdef M32
24 +INT is_elf64 = 1;
25 +#endif
27 INT checkmemmap(ULONG elf_start, ULONG elf_size)
29 MEMORYDESCRIPTOR *md;
30 @@ -84,84 +95,112 @@
31 #endif
34 -ULONG load_elf(CHAR *fname)
36 - BDEV file;
38 #ifdef M32
39 - Elf32_Ehdr hdr;
40 +Elf64_Addr load_elf32(Elf32_Ehdr *hdr, BDEV *file)
42 Elf32_Phdr ph[N_PHDR];
43 - ULONG elf_ehdr_size = sizeof(Elf32_Ehdr);
44 - ULONG elf_phdr_size = sizeof(Elf32_Phdr);
45 -#else
46 - Elf64_Ehdr hdr;
47 - Elf64_Phdr ph[N_PHDR];
48 - ULONG elf_ehdr_size = sizeof(Elf64_Ehdr);
49 - ULONG elf_phdr_size = sizeof(Elf64_Phdr);
50 -#endif
51 INT i, j, nph = 0;
52 ULONG left, pos;
53 UCHAR *ptr;
55 - /* Open */
56 - if(bopen(&file, fname)) {
57 - printf("Opening %s failed.\n\r", fname);
58 + /* Not Relocatable? */
59 + if(hdr->e_type != ET_EXEC) {
60 + printf("ELF file is not executable.\n\r");
61 + printf("Relocatable files are not supported, sorry.\n\r");
62 return 0;
65 - printf("Loading %s...\n\r", fname);
67 - /* Read ELF Header */
68 - if(bread(&file, elf_ehdr_size, &hdr)<0) {
69 - printf("Error reading ELF header.\n\r");
70 - goto close;
71 + /* Does the ELF have any Program Headers? */
72 + if(hdr->e_phnum == 0) {
73 + printf("ELF file contains no Program Headers.\n\r");
74 + return 0;
77 - /* Is is an ELF binary? */
78 - if((hdr.e_ident[0] != 0x7f) ||
79 - (hdr.e_ident[1] != 'E') ||
80 - (hdr.e_ident[2] != 'L') ||
81 - (hdr.e_ident[3] != 'F'))
82 - {
83 - printf("ELF magic invalid.\n\r");
84 - goto close;
85 + /* Save LOAD headers */
86 + for(i = 0; i < hdr->e_phnum; i++) {
87 + bseek(file, (hdr->e_phoff + (i * hdr->e_phentsize)));
88 + if(bread(file, sizeof(Elf32_Phdr), ph+nph)<0) {
89 + printf("Can't read program header %u at 0x%x!\n\r", i, hdr->e_phoff + (i * hdr->e_phentsize));
90 + return 0;
91 + }
93 + if(ph[nph].p_type != PT_LOAD)
94 + continue;
96 + nph++;
97 + if(nph>=N_PHDR) {
98 + printf("ELF file has too many LOAD headers (over N_PHDR).\n\r");
99 + return 0;
103 - /* 32 or 64 bit? */
104 -#ifdef M32
105 - if(hdr.e_ident[EI_CLASS] != ELFCLASS32) {
106 - printf("ELF file is not 32-bit.\n\r");
107 -#else
108 - if(hdr.e_ident[EI_CLASS] != ELFCLASS64) {
109 - printf("ELF file is not 64-bit.\n\r");
110 -#endif
111 - goto close;
112 + /* Was a LOAD header found? */
113 + if(!nph) {
114 + printf("ELF file contains no LOAD header.\n\r");
115 + return 0;
118 - /* Big Endian? */
119 - if(hdr.e_ident[EI_DATA] != ELFDATA2MSB) {
120 - printf("ELF file is not big-endian.\n\r");
121 - goto close;
122 + /* Realize LOAD headers */
123 + for(i = 0; i < nph; i++) {
124 + /* Check the Memory Map */
125 + if(checkmemmap(vtophys(ph[i].p_vaddr), ph[i].p_memsz)) {
126 + printf("File can't be loaded into current memory map.\n\r");
127 + return 0;
130 + /* Load the ELF into memory */
131 + printf("Reading %u bytes... ", (ULONG)ph[i].p_filesz);
132 + left = ph[i].p_filesz;
133 + pos = 0;
134 + ptr = (UCHAR *)ph[i].p_vaddr;
135 + bseek(file, ph[i].p_offset);
136 + while(left > 0) {
137 + j = ((left > READBLOCK) ? READBLOCK : left);
138 + if(bread(file, j, ptr)<0) {
139 + printf("failed at %u!\n\r", (ULONG)pos);
140 + return 0;
142 + left -= j;
143 + ptr += j;
144 + pos += j;
146 + printf("OK.\n\r");
147 + ptr = (UCHAR *)(ph[i].p_vaddr + ph[i].p_filesz);
148 + for(pos = ph[i].p_filesz; pos < ph[i].p_memsz; pos++)
149 + *(ptr++) = 0;
152 + return (Elf64_Addr) hdr->e_entry;
154 +#endif /* M32 */
156 +Elf64_Addr load_elf64(Elf64_Ehdr *hdr, BDEV *file)
158 + Elf64_Phdr ph[N_PHDR];
159 + INT i, j, nph = 0;
160 + ULONG left, pos;
161 + UCHAR *ptr;
163 /* Not Relocatable? */
164 - if(hdr.e_ident[EI_DATA] != ET_EXEC) {
165 + if(hdr->e_type != ET_EXEC) {
166 printf("ELF file is not executable.\n\r");
167 printf("Relocatable files are not supported, sorry.\n\r");
168 - goto close;
169 + return 0;
172 /* Does the ELF have any Program Headers? */
173 - if(hdr.e_phnum == 0) {
174 + if(hdr->e_phnum == 0) {
175 printf("ELF file contains no Program Headers.\n\r");
176 - goto close;
177 + return 0;
180 /* Save LOAD headers */
181 - for(i = 0; i < hdr.e_phnum; i++) {
182 - bseek(&file, (hdr.e_phoff + (i * hdr.e_phentsize)));
183 - if(bread(&file, elf_phdr_size, ph+nph)<0) {
184 - printf("Can't read program header %u at 0x%x!\n\r", i, hdr.e_phoff + (i * hdr.e_phentsize));
185 - goto close;
186 + for(i = 0; i < hdr->e_phnum; i++) {
187 + bseek(file, (hdr->e_phoff + (i * hdr->e_phentsize)));
188 + if(bread(file, sizeof(Elf64_Phdr), ph+nph)<0) {
189 + printf("Can't read program header %u at 0x%x!\n\r", i, hdr->e_phoff + (i * hdr->e_phentsize));
190 + return 0;
193 if(ph[nph].p_type != PT_LOAD)
194 @@ -170,14 +209,14 @@
195 nph++;
196 if(nph>=N_PHDR) {
197 printf("ELF file has too many LOAD headers (over N_PHDR).\n\r");
198 - goto close;
199 + return 0;
203 /* Was a LOAD header found? */
204 if(!nph) {
205 printf("ELF file contains no LOAD header.\n\r");
206 - goto close;
207 + return 0;
210 /* Realize LOAD headers */
211 @@ -185,34 +224,96 @@
212 /* Check the Memory Map */
213 if(checkmemmap(vtophys(ph[i].p_vaddr), ph[i].p_memsz)) {
214 printf("File can't be loaded into current memory map.\n\r");
215 - goto close;
216 + return 0;
219 /* Load the ELF into memory */
220 printf("Reading %u bytes... ", (ULONG)ph[i].p_filesz);
221 left = ph[i].p_filesz;
222 pos = 0;
223 +#ifdef M32
224 + ptr = (UCHAR *)(Elf32_Addr)ph[i].p_vaddr;
225 +#else
226 ptr = (UCHAR *)ph[i].p_vaddr;
227 - bseek(&file, ph[i].p_offset);
228 +#endif
229 + bseek(file, ph[i].p_offset);
230 while(left > 0) {
231 j = ((left > READBLOCK) ? READBLOCK : left);
232 - if(bread(&file, j, ptr)<0) {
233 + if(bread(file, j, ptr)<0) {
234 printf("failed at %u!\n\r", (ULONG)pos);
235 - goto close;
236 + return 0;
238 left -= j;
239 ptr += j;
240 pos += j;
242 printf("OK.\n\r");
243 +#ifdef M32
244 + ptr = (UCHAR *)(Elf32_Addr)(ph[i].p_vaddr + ph[i].p_filesz);
245 +#else
246 ptr = (UCHAR *)(ph[i].p_vaddr + ph[i].p_filesz);
247 +#endif
248 for(pos = ph[i].p_filesz; pos < ph[i].p_memsz; pos++)
249 *(ptr++) = 0;
252 + return hdr->e_entry;
255 +Elf64_Addr load_elf(CHAR *fname)
257 + BDEV file;
258 + Elf_Ehdr hdr;
259 + Elf64_Addr kentry;
261 + /* Open */
262 + if(bopen(&file, fname)) {
263 + printf("Opening %s failed.\n\r", fname);
264 + return 0;
267 + printf("Loading %s...\n\r", fname);
269 + /* Read ELF Header */
270 + if(bread(&file, sizeof(hdr), &hdr)<0) {
271 + printf("Error reading ELF header.\n\r");
272 + goto close;
275 + /* Is is an ELF binary? */
276 + if((hdr.e_ident[0] != 0x7f) ||
277 + (hdr.e_ident[1] != 'E') ||
278 + (hdr.e_ident[2] != 'L') ||
279 + (hdr.e_ident[3] != 'F'))
281 + printf("ELF magic invalid.\n\r");
282 + goto close;
285 + /* Big Endian? */
286 + if(hdr.e_ident[EI_DATA] != ELFDATA2MSB) {
287 + printf("ELF file is not big-endian.\n\r");
288 + goto close;
291 + /* 32 or 64 bit? */
292 + if(hdr.e_ident[EI_CLASS] == ELFCLASS64) {
293 + kentry = load_elf64(&hdr.e64, &file);
295 +#ifdef M32
296 + else if(hdr.e_ident[EI_CLASS] == ELFCLASS32) {
297 + is_elf64 = 0;
298 + kentry = load_elf32(&hdr.e32, &file);
300 +#endif
301 + else {
302 + printf("ELF file cannot be loaded.\n\r");
303 + goto close;
306 bclose(&file);
308 - return hdr.e_entry;
309 + return kentry;
311 /* Failed to do something, close and return */
312 close:
313 @@ -220,6 +321,7 @@
314 return 0;
318 #ifdef M64
319 unsigned fixup_trampolines_data[]={
320 0x03e00821, 0x04110001, 0x00000000, 0xdfe30014,
321 @@ -248,12 +350,31 @@
322 "Patched %u occurrences of the wrong trampoline.\n"
323 "-- WARNING --\n", stat);
325 -#endif
326 +#endif /* M64 */
328 +#ifdef M32
329 +void _start64(LONG argc, CHAR * argv[], CHAR * envp[],
330 + unsigned long long *addr)
332 + __asm__ __volatile__(
333 + ".set push\n"
334 + "\t.set mips3\n"
335 + "\t.set noreorder\n"
336 + "\t.set noat\n"
337 + "\tld $1, 0($7)\n"
338 + "\tjr $1\n"
339 + "\t nop\n"
340 + "\t.set pop");
342 +#endif /* M32 */
344 void __start(void);
345 LONG main(INT argc, CHAR **argv, CHAR **envp)
347 - ULONG entry;
348 + Elf64_Addr entry;
349 +#ifdef M32
350 + Elf32_Addr entry32 = (Elf32_Addr)entry;
351 +#endif
352 VOID (*kernel_entry)(INT argc, CHAR **argv, CHAR **envp);
354 char *system;
355 @@ -318,10 +439,25 @@
356 if(!entry)
357 return 1;
359 +#ifdef M32
360 + if(!is_elf64) {
361 + kernel_entry = (VOID(*)(INT, CHAR **, CHAR **))entry32;
363 + printf("Entering 32bit kernel.\n\r");
364 + ArcFlushAllCaches();
365 + kernel_entry(append_count, append, envp);
366 + } else {
367 + printf("Entering 64bit kernel.\n\r");
368 + ArcFlushAllCaches();
369 + _start64(append_count, append, envp, &entry);
371 +#else
372 kernel_entry = (VOID(*)(INT, CHAR **, CHAR **))entry;
374 printf("Entering kernel.\n\r");
375 + ArcFlushAllCaches();
376 kernel_entry(append_count, append, envp);
377 +#endif
378 return 0;