3 unsigned long a_midmag
; /* flags<<26 | mid<<16 | magic */
4 unsigned long a_text
; /* text segment size */
5 unsigned long a_data
; /* initialized data size */
6 unsigned long a_bss
; /* uninitialized data size */
7 unsigned long a_syms
; /* symbol table size */
8 unsigned long a_entry
; /* entry point */
9 unsigned long a_trsize
; /* text relocation size */
10 unsigned long a_drsize
; /* data relocation size */
15 unsigned long curaddr
;
16 int segment
; /* current segment number, -1 for none */
17 unsigned long loc
; /* start offset of current block */
18 unsigned long skip
; /* padding to be skipped to current segment */
19 unsigned long toread
; /* remaining data to be read in the segment */
22 static struct aout_state astate
;
24 static sector_t
aout_download(unsigned char *data
, unsigned int len
, int eof
);
25 static inline os_download_t
aout_probe(unsigned char *data
, unsigned int len
)
27 unsigned long start
, mid
, end
, istart
, iend
;
28 if (len
< sizeof(astate
.head
)) {
31 memcpy(&astate
.head
, data
, sizeof(astate
.head
));
32 if ((astate
.head
.a_midmag
& 0xffff) != 0x010BL
) {
39 /* Check the aout image */
40 start
= astate
.head
.a_entry
;
41 mid
= (((start
+ astate
.head
.a_text
) + 4095) & ~4095) + astate
.head
.a_data
;
42 end
= ((mid
+ 4095) & ~4095) + astate
.head
.a_bss
;
44 iend
= istart
+ (mid
- start
);
45 if (!prep_segment(start
, mid
, end
, istart
, iend
))
54 static sector_t
aout_download(unsigned char *data
, unsigned int len
, int eof
)
56 unsigned int offset
; /* working offset in the current data block */
62 if (astate
.segment
== 0) {
63 astate
.curaddr
= 0x100000;
64 astate
.head
.a_entry
= astate
.curaddr
+ 0x20;
66 memcpy(phys_to_virt(astate
.curaddr
), data
, len
);
67 astate
.curaddr
+= len
;
72 if (astate
.segment
!= -1) {
74 if (astate
.skip
>= len
- offset
) {
75 astate
.skip
-= len
- offset
;
78 offset
+= astate
.skip
;
83 if (astate
.toread
>= len
- offset
) {
84 memcpy(phys_to_virt(astate
.curaddr
), data
+offset
,
86 astate
.curaddr
+= len
- offset
;
87 astate
.toread
-= len
- offset
;
90 memcpy(phys_to_virt(astate
.curaddr
), data
+offset
, astate
.toread
);
91 offset
+= astate
.toread
;
96 /* Data left, but current segment finished - look for the next
97 * segment. This is quite simple for a.out files. */
99 switch (astate
.segment
) {
102 astate
.curaddr
= astate
.head
.a_entry
;
104 astate
.toread
= astate
.head
.a_text
;
108 /* skip and curaddr may be wrong, but I couldn't find
109 * examples where this failed. There is no reasonable
110 * documentation for a.out available. */
111 astate
.skip
= ((astate
.curaddr
+ 4095) & ~4095) - astate
.curaddr
;
112 astate
.curaddr
= (astate
.curaddr
+ 4095) & ~4095;
113 astate
.toread
= astate
.head
.a_data
;
116 /* initialize bss and start kernel */
117 astate
.curaddr
= (astate
.curaddr
+ 4095) & ~4095;
120 memset(phys_to_virt(astate
.curaddr
), '\0', astate
.head
.a_bss
);
121 goto aout_startkernel
;
125 } while (offset
< len
);
133 entry
= astate
.head
.a_entry
;
140 printf("unexpected a.out variant\n");
141 longjmp(restart_etherboot
, -2);