Added kernel module for starting the usb stack at boot time. It's not activated thoug...
[cake.git] / rom / dos / internalloadseg_aos.c
blob7f850c767686a3f0a11ff8b726b31bb73fb94ab0
1 /*
2 Copyright © 1995-2007, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc:
6 Lang: english
7 */
9 #include <exec/execbase.h>
10 #include <exec/memory.h>
11 #include <dos/dosasl.h>
12 #include <dos/doshunks.h>
13 #include <dos/dosextens.h>
14 #include <proto/exec.h>
15 #include <proto/dos.h>
16 #include <proto/arossupport.h>
17 #include <aros/asmcall.h>
18 #include <aros/debug.h>
19 #include <aros/macros.h>
21 #include "dos_intern.h"
22 #include "internalloadseg.h"
24 static int read_block(BPTR file, APTR buffer, ULONG size, SIPTR * funcarray, struct DosLibrary * DOSBase);
26 struct hunk
28 ULONG size;
29 UBYTE *memory;
32 #include <proto/dos.h>
34 BPTR InternalLoadSeg_AOS(BPTR fh,
35 BPTR table,
36 SIPTR * funcarray,
37 SIPTR * stack,
38 struct MinList *seginfos,
39 struct DosLibrary * DOSBase)
41 #define ERROR(a) { *error=a; goto end; }
44 struct hunk *hunktab = NULL;
45 ULONG hunktype, count, first, last, offset, curhunk, numhunks;
46 LONG t;
47 UBYTE name_buf[255];
48 register int i;
49 BPTR last_p = 0;
50 #if DEBUG
51 static STRPTR segtypes[] = { "CODE", "DATA", "BSS", };
52 #endif
55 LONG *error=&((struct Process *)FindTask(NULL))->pr_Result2;
57 curhunk = 0; /* keep GCC quiet */
59 if (Seek(fh, 0, OFFSET_BEGINNING) < 0)
60 goto end;
62 while(!read_block(fh, &hunktype, sizeof(hunktype), funcarray, DOSBase))
64 hunktype = AROS_BE2LONG(hunktype) ;
66 switch(hunktype & 0xFFFFFF)
68 ULONG tmp, req;
70 case HUNK_SYMBOL:
71 /* The SYMBOL_HUNK looks like this:
72 ---------------------
73 | n = size of | This
74 | symbol in longs | may
75 |-------------------| be
76 | n longwords = name| repeated
77 | of symbol | any
78 |-------------------| number
79 | value (1 long) | of times
80 --------------------|
81 | 0 = end of HUNK_ |
82 | SYMBOL |
83 -------------------- */
85 D(bug("HUNK_SYMBOL (skipping)\n"));
86 while(!read_block(fh, &count, sizeof(count), funcarray, DOSBase) && count)
88 count = AROS_BE2LONG(count) ;
90 if (Seek(fh, (count+1)*4, OFFSET_CURRENT) < 0)
91 goto end;
93 break;
95 case HUNK_UNIT:
97 if (read_block(fh, &count, sizeof(count), funcarray, DOSBase))
98 goto end;
100 count = AROS_BE2LONG(count) ;
102 count *= 4;
103 if (read_block(fh, name_buf, count, funcarray, DOSBase))
104 goto end;
105 D(bug("HUNK_UNIT: \"%.*s\"\n", count, name_buf));
106 break;
108 case HUNK_HEADER:
109 D(bug("HUNK_HEADER:\n"));
110 while (1)
112 if (read_block(fh, &count, sizeof(count), funcarray, DOSBase))
113 goto end;
114 if (count == 0L)
115 break;
117 count = AROS_BE2LONG(count);
119 count *= 4;
120 if (read_block(fh, name_buf, count, funcarray, DOSBase))
121 goto end;
122 D(bug("\tlibname: \"%.*s\"\n", count, name_buf));
124 if (read_block(fh, &numhunks, sizeof(numhunks), funcarray, DOSBase))
125 goto end;
127 numhunks = AROS_BE2LONG(numhunks);
129 D(bug("\tHunk count: %ld\n", numhunks));
131 hunktab = (struct hunk *)AllocVec(sizeof(struct hunk) * numhunks,
132 MEMF_CLEAR);
133 if (hunktab == NULL)
134 ERROR(ERROR_NO_FREE_STORE);
135 if (read_block(fh, &first, sizeof(first), funcarray, DOSBase))
136 goto end;
138 first = AROS_BE2LONG(first);
140 D(bug("\tFirst hunk: %ld\n", first));
141 curhunk = 0 /* first */;
142 if (read_block(fh, &last, sizeof(last), funcarray, DOSBase))
143 goto end;
145 last = AROS_BE2LONG(last);
147 D(bug("\tLast hunk: %ld\n", last));
148 for (i = 0 /* first */; i < numhunks /* last */; i++)
150 if (read_block(fh, &count, sizeof(count), funcarray, DOSBase))
151 goto end;
153 count = AROS_BE2LONG(count);
155 tmp = count & 0xFF000000;
156 count &= 0xFFFFFF;
157 D(bug("\tHunk %d size: 0x%06lx bytes in ", i, count*4));
158 req = MEMF_CLEAR;
160 switch(tmp)
162 case HUNKF_FAST:
163 D(bug("FAST"));
164 req |= MEMF_FAST;
165 break;
167 case HUNKF_CHIP:
168 D(bug("CHIP"));
169 req |= MEMF_CHIP;
170 break;
172 case HUNKF_ADVISORY:
173 D(bug("ADVISORY"));
174 if (read_block(fh, &req, sizeof(req), funcarray, DOSBase))
175 goto end;
177 req = AROS_BE2LONG(req);
179 break;
181 default:
182 D(bug("ANY"));
183 req |= MEMF_ANY;
184 break;
187 D(bug(" memory\n"));
188 /* we need space for the code, the length of this hunk and
189 for a pointer to the next hunk
191 hunktab[i].size = count * 4 + sizeof(ULONG) + sizeof(BPTR);
192 hunktab[i].memory =(UBYTE *)
193 AROS_CALL2(void *, funcarray[1] /* AllocMem */,
194 AROS_LCA(ULONG , hunktab[i].size , D0),
195 AROS_LCA(ULONG , req , D1),
196 struct Library *, (struct Library *)SysBase);
198 if (hunktab[i].memory == NULL)
199 ERROR(ERROR_NO_FREE_STORE);
201 *((BPTR *)(hunktab[i].memory)) = (BPTR)hunktab[i].size;
202 hunktab[i].memory += sizeof(ULONG);
204 /* Link hunks
205 if this is not the first hunk that is loaded, then connect
206 it to the previous one (pointer to the field where the
207 pointer to the next hunk is located)
209 if (i > 0)
210 ((BPTR *)(hunktab[i-1].memory))[-1] = MKBADDR(hunktab[i].memory);
212 /* advance the pointer to the address where the code is to be loaded to */
213 hunktab[i].memory += sizeof(BPTR);
216 break;
218 case HUNK_CODE:
219 case HUNK_DATA:
220 case HUNK_BSS:
221 if (read_block(fh, &count, sizeof(count), funcarray, DOSBase))
222 goto end;
224 count = AROS_BE2LONG(count);
226 D(bug("HUNK_%s(%d): Length: 0x%06lx bytes in ",
227 segtypes[(hunktype & 0xFFFFFF)-HUNK_CODE], curhunk, count*4));
229 switch(hunktype & 0xFF000000)
231 case HUNKF_FAST:
232 D(bug("FAST"));
233 req = MEMF_FAST;
234 break;
236 case HUNKF_CHIP:
237 D(bug("CHIP"));
238 req = MEMF_CHIP;
239 break;
241 case HUNKF_ADVISORY:
242 D(bug("ADVISORY"));
243 if (read_block(fh, &req, sizeof(req), funcarray, DOSBase))
244 goto end;
246 req = AROS_BE2LONG(req);
248 break;
250 default:
251 D(bug("ANY"));
252 req = MEMF_ANY;
253 break;
256 D(bug(" memory\n"));
257 if ((hunktype & 0xFFFFFF) != HUNK_BSS && count)
259 if (read_block(fh, hunktab[curhunk].memory, count*4, funcarray, DOSBase))
260 goto end;
263 break;
265 case HUNK_RELOC32:
266 D(bug("HUNK_RELOC32:\n"));
267 while (1)
269 ULONG *addr;
271 if (read_block(fh, &count, sizeof(count), funcarray, DOSBase))
272 goto end;
273 if (count == 0L)
274 break;
276 count = AROS_BE2LONG(count);
278 i = count;
279 if (read_block(fh, &count, sizeof(count), funcarray, DOSBase))
280 goto end;
282 count = AROS_BE2LONG(count);
284 D(bug("\tHunk #%ld:\n", count));
285 while (i > 0)
287 if (read_block(fh, &offset, sizeof(offset), funcarray, DOSBase))
288 goto end;
290 offset = AROS_BE2LONG(offset);
292 D(bug("\t\t0x%06lx\n", offset));
293 addr = (ULONG *)(hunktab[curhunk].memory + offset);
295 *addr = AROS_BE2LONG(*addr) + (ULONG)(hunktab[count].memory);
297 --i;
300 break;
302 case HUNK_DREL32: /* For compatibility with V37 */
303 case HUNK_RELOC32SHORT:
305 ULONG Wordcount = 0;
307 while (1)
309 ULONG *addr;
310 UWORD word;
312 Wordcount++;
314 if (read_block(fh, &word, sizeof(word), funcarray, DOSBase))
315 goto end;
316 if (word == 0L)
317 break;
319 word = AROS_BE2LONG(word);
321 i = word;
322 Wordcount++;
323 if (read_block(fh, &word, sizeof(word), funcarray, DOSBase))
324 goto end;
326 word = AROS_BE2WORD(word);
328 count = word;
329 D(bug("\tHunk #%ld:\n", count));
330 while (i > 0)
332 Wordcount++;
333 /* read a 16bit number (2 bytes) */
334 if (read_block(fh, &word, sizeof(word), funcarray, DOSBase))
335 goto end;
337 word = AROS_BE2WORD(word);
339 offset = word;
340 /* offset now contains the byte offset in it`s 16 highest bits.
341 These 16 highest bits have to become the 16 lowest bits so
342 we get the word we need. */
343 //(ULONG)offset >>= ((sizeof(offset)-2)*8);
344 //D(bug("\t\t0x%06lx\n", offset));
345 addr = (ULONG *)(hunktab[curhunk].memory + offset);
347 *addr = AROS_BE2LONG(*addr) + (ULONG)(hunktab[count].memory);
349 --i;
350 } /* while (i > 0)*/
351 } /* while (1) */
353 /* if the amount of words read was odd, then skip the following
354 16-bit word */
355 if (0x1 == (Wordcount & 0x1))
356 Seek(fh, 2, OFFSET_CURRENT);
358 break;
360 case HUNK_END:
361 D(bug("HUNK_END\n"));
362 ++curhunk;
363 break;
365 case HUNK_RELOC16:
366 D(bug("HUNK_RELOC16 not implemented\n"));
367 ERROR(ERROR_BAD_HUNK);
369 case HUNK_RELOC8:
370 D(bug("HUNK_RELOC8 not implemented\n"));
371 ERROR(ERROR_BAD_HUNK);
373 case HUNK_NAME:
374 D(bug("HUNK_NAME not implemented\n"));
375 ERROR(ERROR_BAD_HUNK);
377 case HUNK_EXT:
378 D(bug("HUNK_EXT not implemented\n"));
379 ERROR(ERROR_BAD_HUNK);
381 case HUNK_DEBUG:
382 if (read_block(fh, &count, sizeof(count), funcarray, DOSBase))
383 goto end;
385 count = AROS_BE2LONG(count);
387 D(bug("HUNK_DEBUG (%x Bytes)\n",count));
388 if (Seek(fh, count * 4, OFFSET_CURRENT ) < 0 )
389 goto end;
390 break;
392 case HUNK_OVERLAY:
393 D(bug("HUNK_OVERLAY not implemented\n"));
394 ERROR(ERROR_BAD_HUNK);
396 case HUNK_BREAK:
397 D(bug("HUNK_BREAK not implemented\n"));
398 ERROR(ERROR_BAD_HUNK);
400 default:
401 D(bug("Hunk type 0x%06lx not implemented\n", hunktype & 0xFFFFFF));
402 ERROR(ERROR_BAD_HUNK);
403 } /* switch */
404 } /* while */
406 if (hunktab)
408 /* Clear caches */
409 for (t=numhunks-1 /* last */; t >= (LONG)0 /*first */; t--)
411 if (hunktab[t].size)
413 CacheClearE(hunktab[t].memory, hunktab[t].size,
414 CACRF_ClearI|CACRF_ClearD);
418 last_p = MKBADDR(hunktab[0].memory - sizeof(BPTR));
420 FreeVec(hunktab);
421 hunktab = NULL;
424 end:
425 if (hunktab != NULL)
427 for (t = 0 /* first */; t < numhunks /* last */; t++)
428 if (hunktab[t].memory != NULL)
430 AROS_CALL2NR(void, funcarray[2] /* FreeMem*/,
431 AROS_LCA(void * , hunktab[t].memory-sizeof(ULONG)-sizeof(BPTR), A1),
432 AROS_LCA(ULONG , hunktab[t].size , D0),
433 struct Library *, (struct Library *)SysBase);
436 FreeVec(hunktab);
438 return last_p;
439 } /* InternalLoadSeg */
442 static int read_block(BPTR file, APTR buffer, ULONG size, SIPTR * funcarray, struct DosLibrary * DOSBase)
444 LONG subsize;
445 UBYTE *buf=(UBYTE *)buffer;
447 while(size)
449 subsize = AROS_CALL3(LONG, funcarray[0] /* Read */,
450 AROS_LCA(BPTR , file , D1),
451 AROS_LCA(void * , buf , D2),
452 AROS_LCA(LONG , size , D3),
453 struct DosLibrary *, DOSBase);
454 if(subsize==0)
456 ((struct Process *)FindTask(NULL))->pr_Result2=ERROR_BAD_HUNK;
457 return 1;
460 if(subsize<0)
461 return 1;
462 buf +=subsize;
463 size -=subsize;
465 return 0;