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);