~ubuntu-branches/ubuntu/raring/ipxe/raring

« back to all changes in this revision

Viewing changes to src/arch/i386/core/aout_loader.c

  • Committer: Package Import Robot
  • Author(s): James Page
  • Date: 2012-11-14 15:47:31 UTC
  • mfrom: (1.1.3)
  • Revision ID: package-import@ubuntu.com-20121114154731-jhuy5d1h2jw75qe9
Tags: 1.0.0+git-4.d6b0b76-0ubuntu1
* New upstream snapshot:
  - d/p/iscsi*.patch: Dropped - included in snapshot.
  - Refreshed all other patches.
* d/p/enable-https.patch: Enable HTTPS support (LP: #1025239).

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* a.out */
2
 
struct exec {
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 */
11
 
};
12
 
 
13
 
struct aout_state {
14
 
        struct exec head;
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 */
20
 
};
21
 
 
22
 
static struct aout_state astate;
23
 
 
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)
26
 
{
27
 
        unsigned long start, mid, end, istart, iend;
28
 
        if (len < sizeof(astate.head)) {
29
 
                return 0;
30
 
        }
31
 
        memcpy(&astate.head, data, sizeof(astate.head));
32
 
        if ((astate.head.a_midmag & 0xffff) != 0x010BL) {
33
 
                return 0;
34
 
        }
35
 
        
36
 
        printf("(a.out");
37
 
        aout_freebsd_probe();
38
 
        printf(")... ");
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;
43
 
        istart = 4096;
44
 
        iend   = istart + (mid - start);
45
 
        if (!prep_segment(start, mid, end, istart, iend))
46
 
                return dead_download;
47
 
        astate.segment = -1;
48
 
        astate.loc = 0;
49
 
        astate.skip = 0;
50
 
        astate.toread = 0;
51
 
        return aout_download;
52
 
}
53
 
 
54
 
static sector_t aout_download(unsigned char *data, unsigned int len, int eof)
55
 
{
56
 
        unsigned int offset;    /* working offset in the current data block */
57
 
 
58
 
        offset = 0;
59
 
 
60
 
#ifdef AOUT_LYNX_KDI
61
 
        astate.segment++;
62
 
        if (astate.segment == 0) {
63
 
                astate.curaddr = 0x100000;
64
 
                astate.head.a_entry = astate.curaddr + 0x20;
65
 
        }
66
 
        memcpy(phys_to_virt(astate.curaddr), data, len);
67
 
        astate.curaddr += len;
68
 
        return 0;
69
 
#endif
70
 
 
71
 
        do {
72
 
                if (astate.segment != -1) {
73
 
                        if (astate.skip) {
74
 
                                if (astate.skip >= len - offset) {
75
 
                                        astate.skip -= len - offset;
76
 
                                        break;
77
 
                                }
78
 
                                offset += astate.skip;
79
 
                                astate.skip = 0;
80
 
                        }
81
 
 
82
 
                        if (astate.toread) {
83
 
                                if (astate.toread >= len - offset) {
84
 
                                        memcpy(phys_to_virt(astate.curaddr), data+offset,
85
 
                                                len - offset);
86
 
                                        astate.curaddr += len - offset;
87
 
                                        astate.toread -= len - offset;
88
 
                                        break;
89
 
                                }
90
 
                                memcpy(phys_to_virt(astate.curaddr), data+offset, astate.toread);
91
 
                                offset += astate.toread;
92
 
                                astate.toread = 0;
93
 
                        }
94
 
                }
95
 
 
96
 
                /* Data left, but current segment finished - look for the next
97
 
                 * segment.  This is quite simple for a.out files.  */
98
 
                astate.segment++;
99
 
                switch (astate.segment) {
100
 
                case 0:
101
 
                        /* read text */
102
 
                        astate.curaddr = astate.head.a_entry;
103
 
                        astate.skip = 4096;
104
 
                        astate.toread = astate.head.a_text;
105
 
                        break;
106
 
                case 1:
107
 
                        /* read data */
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;
114
 
                        break;
115
 
                case 2:
116
 
                        /* initialize bss and start kernel */
117
 
                        astate.curaddr = (astate.curaddr + 4095) & ~4095;
118
 
                        astate.skip = 0;
119
 
                        astate.toread = 0;
120
 
                        memset(phys_to_virt(astate.curaddr), '\0', astate.head.a_bss);
121
 
                        goto aout_startkernel;
122
 
                default:
123
 
                        break;
124
 
                }
125
 
        } while (offset < len);
126
 
 
127
 
        astate.loc += len;
128
 
 
129
 
        if (eof) {
130
 
                unsigned long entry;
131
 
 
132
 
aout_startkernel:
133
 
                entry = astate.head.a_entry;
134
 
                done(1);
135
 
 
136
 
                aout_freebsd_boot();
137
 
#ifdef AOUT_LYNX_KDI
138
 
                xstart32(entry);
139
 
#endif
140
 
                printf("unexpected a.out variant\n");
141
 
                longjmp(restart_etherboot, -2);
142
 
        }
143
 
        return 0;
144
 
}