2 Copyright © 1995-2007, The AROS Development Team. All rights reserved.
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
);
32 #include <proto/dos.h>
34 BPTR
InternalLoadSeg_AOS(BPTR fh
,
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
;
51 static STRPTR segtypes
[] = { "CODE", "DATA", "BSS", };
55 LONG
*error
=&((struct Process
*)FindTask(NULL
))->pr_Result2
;
57 curhunk
= 0; /* keep GCC quiet */
59 if (Seek(fh
, 0, OFFSET_BEGINNING
) < 0)
62 while(!read_block(fh
, &hunktype
, sizeof(hunktype
), funcarray
, DOSBase
))
64 hunktype
= AROS_BE2LONG(hunktype
) ;
66 switch(hunktype
& 0xFFFFFF)
71 /* The SYMBOL_HUNK looks like this:
74 | symbol in longs | may
75 |-------------------| be
76 | n longwords = name| repeated
78 |-------------------| number
79 | value (1 long) | of times
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)
97 if (read_block(fh
, &count
, sizeof(count
), funcarray
, DOSBase
))
100 count
= AROS_BE2LONG(count
) ;
103 if (read_block(fh
, name_buf
, count
, funcarray
, DOSBase
))
105 D(bug("HUNK_UNIT: \"%.*s\"\n", count
, name_buf
));
109 D(bug("HUNK_HEADER:\n"));
112 if (read_block(fh
, &count
, sizeof(count
), funcarray
, DOSBase
))
117 count
= AROS_BE2LONG(count
);
120 if (read_block(fh
, name_buf
, count
, funcarray
, DOSBase
))
122 D(bug("\tlibname: \"%.*s\"\n", count
, name_buf
));
124 if (read_block(fh
, &numhunks
, sizeof(numhunks
), funcarray
, DOSBase
))
127 numhunks
= AROS_BE2LONG(numhunks
);
129 D(bug("\tHunk count: %ld\n", numhunks
));
131 hunktab
= (struct hunk
*)AllocVec(sizeof(struct hunk
) * numhunks
,
134 ERROR(ERROR_NO_FREE_STORE
);
135 if (read_block(fh
, &first
, sizeof(first
), funcarray
, DOSBase
))
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
))
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
))
153 count
= AROS_BE2LONG(count
);
155 tmp
= count
& 0xFF000000;
157 D(bug("\tHunk %d size: 0x%06lx bytes in ", i
, count
*4));
174 if (read_block(fh
, &req
, sizeof(req
), funcarray
, DOSBase
))
177 req
= AROS_BE2LONG(req
);
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
);
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)
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
);
221 if (read_block(fh
, &count
, sizeof(count
), funcarray
, DOSBase
))
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)
243 if (read_block(fh
, &req
, sizeof(req
), funcarray
, DOSBase
))
246 req
= AROS_BE2LONG(req
);
257 if ((hunktype
& 0xFFFFFF) != HUNK_BSS
&& count
)
259 if (read_block(fh
, hunktab
[curhunk
].memory
, count
*4, funcarray
, DOSBase
))
266 D(bug("HUNK_RELOC32:\n"));
271 if (read_block(fh
, &count
, sizeof(count
), funcarray
, DOSBase
))
276 count
= AROS_BE2LONG(count
);
279 if (read_block(fh
, &count
, sizeof(count
), funcarray
, DOSBase
))
282 count
= AROS_BE2LONG(count
);
284 D(bug("\tHunk #%ld:\n", count
));
287 if (read_block(fh
, &offset
, sizeof(offset
), funcarray
, DOSBase
))
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
);
302 case HUNK_DREL32
: /* For compatibility with V37 */
303 case HUNK_RELOC32SHORT
:
314 if (read_block(fh
, &word
, sizeof(word
), funcarray
, DOSBase
))
319 word
= AROS_BE2LONG(word
);
323 if (read_block(fh
, &word
, sizeof(word
), funcarray
, DOSBase
))
326 word
= AROS_BE2WORD(word
);
329 D(bug("\tHunk #%ld:\n", count
));
333 /* read a 16bit number (2 bytes) */
334 if (read_block(fh
, &word
, sizeof(word
), funcarray
, DOSBase
))
337 word
= AROS_BE2WORD(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
);
353 /* if the amount of words read was odd, then skip the following
355 if (0x1 == (Wordcount
& 0x1))
356 Seek(fh
, 2, OFFSET_CURRENT
);
361 D(bug("HUNK_END\n"));
366 D(bug("HUNK_RELOC16 not implemented\n"));
367 ERROR(ERROR_BAD_HUNK
);
370 D(bug("HUNK_RELOC8 not implemented\n"));
371 ERROR(ERROR_BAD_HUNK
);
374 D(bug("HUNK_NAME not implemented\n"));
375 ERROR(ERROR_BAD_HUNK
);
378 D(bug("HUNK_EXT not implemented\n"));
379 ERROR(ERROR_BAD_HUNK
);
382 if (read_block(fh
, &count
, sizeof(count
), funcarray
, DOSBase
))
385 count
= AROS_BE2LONG(count
);
387 D(bug("HUNK_DEBUG (%x Bytes)\n",count
));
388 if (Seek(fh
, count
* 4, OFFSET_CURRENT
) < 0 )
393 D(bug("HUNK_OVERLAY not implemented\n"));
394 ERROR(ERROR_BAD_HUNK
);
397 D(bug("HUNK_BREAK not implemented\n"));
398 ERROR(ERROR_BAD_HUNK
);
401 D(bug("Hunk type 0x%06lx not implemented\n", hunktype
& 0xFFFFFF));
402 ERROR(ERROR_BAD_HUNK
);
409 for (t
=numhunks
-1 /* last */; t
>= (LONG
)0 /*first */; t
--)
413 CacheClearE(hunktab
[t
].memory
, hunktab
[t
].size
,
414 CACRF_ClearI
|CACRF_ClearD
);
418 last_p
= MKBADDR(hunktab
[0].memory
- sizeof(BPTR
));
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
);
439 } /* InternalLoadSeg */
442 static int read_block(BPTR file
, APTR buffer
, ULONG size
, SIPTR
* funcarray
, struct DosLibrary
* DOSBase
)
445 UBYTE
*buf
=(UBYTE
*)buffer
;
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
);
456 ((struct Process
*)FindTask(NULL
))->pr_Result2
=ERROR_BAD_HUNK
;