|
@@ -29,351 +29,71 @@ Modifications: Ken Yap (for Etherboot/16)
|
29
|
29
|
* your option) any later version.
|
30
|
30
|
*/
|
31
|
31
|
|
32
|
|
-#include "etherboot.h"
|
|
32
|
+#include "io.h"
|
|
33
|
+#include "heap.h"
|
33
|
34
|
#include "memsizes.h"
|
34
|
35
|
|
35
|
|
-#ifdef KEEP_IT_REAL
|
|
36
|
+/* Linker symbols */
|
|
37
|
+extern char _text[];
|
|
38
|
+extern char _end[];
|
36
|
39
|
|
37
|
|
-#warning "All download mechanisms are broken under KEEP_IT_REAL"
|
38
|
|
-
|
39
|
|
-os_download_t probe_image(unsigned char *data, unsigned int len) {
|
40
|
|
- return 0;
|
41
|
|
-}
|
42
|
|
-
|
43
|
|
-int load_block(unsigned char *data, unsigned int block, unsigned int len, int eof) {
|
44
|
|
- return 1;
|
45
|
|
-}
|
46
|
|
-
|
47
|
|
-#else /* KEEP_IT_REAL */
|
48
|
|
-
|
49
|
|
-
|
50
|
|
-struct os_entry_regs os_regs;
|
51
|
|
-
|
52
|
|
-static struct ebinfo loaderinfo = {
|
53
|
|
- VERSION_MAJOR, VERSION_MINOR,
|
54
|
|
- 0
|
55
|
|
-};
|
56
|
|
-
|
57
|
|
-#define LOAD_DEBUG 0
|
58
|
|
-
|
59
|
|
-static int prep_segment(unsigned long start, unsigned long mid, unsigned long end,
|
60
|
|
- unsigned long istart, unsigned long iend);
|
61
|
|
-static unsigned long find_segment(unsigned long size, unsigned long align);
|
62
|
|
-static sector_t dead_download ( unsigned char *data, unsigned int len, int eof);
|
63
|
|
-static void done(int do_cleanup);
|
64
|
|
-
|
65
|
|
-#if defined(IMAGE_FREEBSD) && defined(ELF_IMAGE)
|
66
|
|
-static void elf_freebsd_probe(void);
|
67
|
|
-static void elf_freebsd_fixup_segment(void);
|
68
|
|
-static void elf_freebsd_find_segment_end(void);
|
69
|
|
-static int elf_freebsd_debug_loader(unsigned int offset);
|
70
|
|
-static void elf_freebsd_boot(unsigned long entry);
|
71
|
|
-#else
|
72
|
|
-#define elf_freebsd_probe() do {} while(0)
|
73
|
|
-#define elf_freebsd_fixup_segment() do {} while(0)
|
74
|
|
-#define elf_freebsd_find_segment_end() do {} while(0)
|
75
|
|
-#define elf_freebsd_debug_loader(off) (0)
|
76
|
|
-#define elf_freebsd_boot(entry) do {} while(0)
|
77
|
|
-#endif
|
78
|
|
-#if defined(IMAGE_FREEBSD) && defined(AOUT_IMAGE)
|
79
|
|
-static void aout_freebsd_probe(void);
|
80
|
|
-static void aout_freebsd_boot(void);
|
81
|
|
-#else
|
82
|
|
-#define aout_freebsd_probe() do {} while(0)
|
83
|
|
-#define aout_freebsd_boot() do {} while(0)
|
84
|
|
-#endif
|
85
|
|
-
|
86
|
|
-/**************************************************************************
|
87
|
|
-dead_download - Restart etherboot if probe image fails
|
88
|
|
-**************************************************************************/
|
89
|
|
-static sector_t dead_download ( unsigned char *data __unused, unsigned int len __unused, int eof __unused) {
|
90
|
|
- longjmp(restart_etherboot, -2);
|
91
|
|
-}
|
92
|
|
-
|
93
|
|
-#ifdef IMAGE_MULTIBOOT
|
94
|
|
-#include "../arch/i386/core/multiboot_loader.c"
|
95
|
|
-#else
|
96
|
|
-#define multiboot_probe(data, len) do {} while(0)
|
97
|
|
-#define multiboot_boot(entry) do {} while(0)
|
98
|
|
-#endif
|
99
|
|
-
|
100
|
|
-
|
101
|
|
-#ifdef WINCE_IMAGE
|
102
|
|
-#include "../arch/i386/core/wince_loader.c"
|
103
|
|
-#endif
|
104
|
|
-
|
105
|
|
-#ifdef AOUT_IMAGE
|
106
|
|
-#include "../arch/i386/core/aout_loader.c"
|
107
|
|
-#endif
|
108
|
|
-
|
109
|
|
-#ifdef TAGGED_IMAGE
|
110
|
|
-#include "../arch/i386/core/tagged_loader.c"
|
111
|
|
-#endif
|
112
|
|
-
|
113
|
|
-#if defined(ELF_IMAGE) || defined(ELF64_IMAGE)
|
114
|
|
-#include "elf_loader.c"
|
115
|
|
-#endif
|
116
|
|
-
|
117
|
|
-#if defined(COFF_IMAGE)
|
118
|
|
-#include "../arch/e1/core/coff_loader.c"
|
119
|
|
-#endif
|
120
|
|
-
|
121
|
|
-#ifdef IMAGE_FREEBSD
|
122
|
|
-#include "../arch/i386/core/freebsd_loader.c"
|
123
|
|
-#endif
|
124
|
|
-
|
125
|
|
-#ifdef PXE_IMAGE
|
126
|
|
-#include "../arch/i386/core/pxe_loader.c"
|
127
|
|
-#endif
|
128
|
|
-
|
129
|
|
-#ifdef RAW_IMAGE
|
130
|
|
-#include "../arch/armnommu/core/raw_loader.c"
|
131
|
|
-#endif
|
132
|
|
-
|
133
|
|
-static void done(int do_cleanup)
|
134
|
|
-{
|
135
|
|
-#ifdef SIZEINDICATOR
|
136
|
|
- printf("K ");
|
137
|
|
-#endif
|
138
|
|
- printf("done\n");
|
139
|
|
- /* We may not want to do the cleanup: when booting a PXE
|
140
|
|
- * image, for example, we need to leave the network card
|
141
|
|
- * enabled, and it helps debugging if the serial console
|
142
|
|
- * remains enabled. The call the cleanup() will be triggered
|
143
|
|
- * when the PXE stack is shut down.
|
144
|
|
- */
|
145
|
|
- if ( do_cleanup ) {
|
146
|
|
- cleanup();
|
147
|
|
- /* arch_on_exit(0); */
|
148
|
|
- }
|
149
|
|
-}
|
150
|
|
-
|
151
|
|
-static int prep_segment(unsigned long start, unsigned long mid, unsigned long end,
|
152
|
|
- unsigned long istart __unused, unsigned long iend __unused)
|
153
|
|
-{
|
|
40
|
+int prep_segment ( physaddr_t start, physaddr_t mid, physaddr_t end ) {
|
154
|
41
|
unsigned fit, i;
|
155
|
42
|
|
156
|
|
-#if LOAD_DEBUG
|
157
|
|
- printf ( "\nAbout to prepare segment [%lX,%lX)\n", start, end );
|
158
|
|
- sleep ( 3 );
|
159
|
|
-#endif
|
|
43
|
+ DBG ( "OSLOADER preparing segment [%lX,%lX)\n", start, end );
|
160
|
44
|
|
161
|
|
- if (mid > end) {
|
162
|
|
- printf("filesz > memsz\n");
|
|
45
|
+ if ( mid > end ) {
|
|
46
|
+ DBG ( "OSLOADER got filesz > memsz\n" );
|
163
|
47
|
return 0;
|
164
|
48
|
}
|
165
|
|
- if ((end > virt_to_phys(_text)) &&
|
166
|
|
- (start < virt_to_phys(_end))) {
|
167
|
|
- printf("segment [%lX, %lX) overlaps etherboot [%lX, %lX)\n",
|
168
|
|
- start, end,
|
169
|
|
- virt_to_phys(_text), virt_to_phys(_end)
|
170
|
|
- );
|
|
49
|
+
|
|
50
|
+ /* Check for overlap with Etherboot runtime image */
|
|
51
|
+ if ( ( end > virt_to_phys ( _text ) ) &&
|
|
52
|
+ ( start < virt_to_phys ( _end ) ) ) {
|
|
53
|
+ DBG ( "OSLOADER got segment [%lX, %lX) "
|
|
54
|
+ "overlapping etherboot [%lX, %lX)\n",
|
|
55
|
+ start, end,
|
|
56
|
+ virt_to_phys ( _text ), virt_to_phys ( _end ) );
|
171
|
57
|
return 0;
|
172
|
58
|
}
|
173
|
|
- if ((end > heap_ptr) && (start < heap_bot)) {
|
174
|
|
- printf("segment [%lX, %lX) overlaps heap [%lX, %lX)\n",
|
175
|
|
- start, end,
|
176
|
|
- heap_ptr, heap_bot
|
177
|
|
- );
|
|
59
|
+
|
|
60
|
+ /* Check for overlap with used portion of heap. Since the
|
|
61
|
+ * heap code just finds the biggest available memory area, we
|
|
62
|
+ * check only against the used heap area, rather than the
|
|
63
|
+ * whole heap area.
|
|
64
|
+ */
|
|
65
|
+ if ( ( end > heap_ptr ) && ( start < heap_end ) ) {
|
|
66
|
+ DBG ( "OSLOADER got segment [%lX, %lX) "
|
|
67
|
+ "overlapping used heap [%lX, %lX)\n",
|
|
68
|
+ start, end, heap_ptr, heap_end );
|
178
|
69
|
return 0;
|
179
|
70
|
}
|
|
71
|
+
|
|
72
|
+ /* Check that block fits entirely inside a single memory region */
|
180
|
73
|
fit = 0;
|
181
|
|
- for(i = 0; i < meminfo.map_count; i++) {
|
|
74
|
+ for ( i = 0 ; i < meminfo.map_count ; i++ ) {
|
182
|
75
|
unsigned long long r_start, r_end;
|
|
76
|
+
|
183
|
77
|
if (meminfo.map[i].type != E820_RAM)
|
184
|
78
|
continue;
|
|
79
|
+
|
185
|
80
|
r_start = meminfo.map[i].addr;
|
186
|
81
|
r_end = r_start + meminfo.map[i].size;
|
187
|
|
- if ((start >= r_start) && (end <= r_end)) {
|
|
82
|
+ if ( ( start >= r_start ) && ( end <= r_end ) ) {
|
188
|
83
|
fit = 1;
|
189
|
84
|
break;
|
190
|
85
|
}
|
191
|
86
|
}
|
192
|
|
- if (!fit) {
|
193
|
|
- printf("\nsegment [%lX,%lX) does not fit in any memory region\n",
|
194
|
|
- start, end);
|
195
|
|
-#if LOAD_DEBUG
|
196
|
|
- printf("Memory regions(%d):\n", meminfo.map_count);
|
197
|
|
- for(i = 0; i < meminfo.map_count; i++) {
|
198
|
|
- unsigned long long r_start, r_end;
|
199
|
|
- if (meminfo.map[i].type != E820_RAM)
|
200
|
|
- continue;
|
201
|
|
- r_start = meminfo.map[i].addr;
|
202
|
|
- r_end = r_start + meminfo.map[i].size;
|
203
|
|
- printf("[%X%X, %X%X) type %d\n",
|
204
|
|
- (unsigned long)(r_start >> 32),
|
205
|
|
- (unsigned long)r_start,
|
206
|
|
- (unsigned long)(r_end >> 32),
|
207
|
|
- (unsigned long)r_end,
|
208
|
|
- meminfo.map[i].type);
|
209
|
|
- }
|
210
|
|
-#endif
|
|
87
|
+ if ( ! fit ) {
|
|
88
|
+ DBG ( "OSLOADER got segment [%lX,%lX) "
|
|
89
|
+ "which does not fit in any memory region\n",
|
|
90
|
+ start, end );
|
211
|
91
|
return 0;
|
212
|
92
|
}
|
213
|
|
-#if LOAD_DEBUG
|
214
|
|
- /* Zap the whole lot. Do this so that if we're treading on
|
215
|
|
- * anything, it shows up now, when the debug message is
|
216
|
|
- * visible, rather than when we're partway through downloading
|
217
|
|
- * the file.
|
218
|
|
- *
|
219
|
|
- * If you see an entire screen full of exclamation marks, then
|
220
|
|
- * you've almost certainly written all over the display RAM.
|
221
|
|
- * This is likely to happen if the status of the A20 line gets
|
222
|
|
- * screwed up. Of course, if this happens, it's a good bet
|
223
|
|
- * that you've also trashed the whole of low memory, so expect
|
224
|
|
- * interesting things to happen...
|
225
|
|
- */
|
226
|
|
- memset(phys_to_virt(start), '!', mid - start);
|
227
|
|
-#endif
|
228
|
|
- /* Zero the bss */
|
229
|
|
- if (end > mid) {
|
230
|
|
- memset(phys_to_virt(mid), 0, end - mid);
|
231
|
|
- }
|
232
|
|
- return 1;
|
233
|
|
-}
|
234
|
|
-
|
235
|
|
-static unsigned long find_segment(unsigned long size, unsigned long align)
|
236
|
|
-{
|
237
|
|
- unsigned i;
|
238
|
|
- /* Verify I have a power of 2 alignment */
|
239
|
|
- if (align & (align - 1)) {
|
240
|
|
- return ULONG_MAX;
|
241
|
|
- }
|
242
|
|
- for(i = 0; i < meminfo.map_count; i++) {
|
243
|
|
- unsigned long r_start, r_end;
|
244
|
|
- if (meminfo.map[i].type != E820_RAM)
|
245
|
|
- continue;
|
246
|
|
- if ((meminfo.map[i].addr + meminfo.map[i].size) > ULONG_MAX) {
|
247
|
|
- continue;
|
248
|
|
- }
|
249
|
|
- r_start = meminfo.map[i].addr;
|
250
|
|
- r_end = r_start + meminfo.map[i].size;
|
251
|
|
- /* Don't allow the segment to overlap etherboot */
|
252
|
|
- if ((r_end > virt_to_phys(_text)) && (r_start < virt_to_phys(_text))) {
|
253
|
|
- r_end = virt_to_phys(_text);
|
254
|
|
- }
|
255
|
|
- if ((r_start > virt_to_phys(_text)) && (r_start < virt_to_phys(_end))) {
|
256
|
|
- r_start = virt_to_phys(_end);
|
257
|
|
- }
|
258
|
|
- /* Don't allow the segment to overlap the heap */
|
259
|
|
- if ((r_end > heap_ptr) && (r_start < heap_ptr)) {
|
260
|
|
- r_end = heap_ptr;
|
261
|
|
- }
|
262
|
|
- if ((r_start > heap_ptr) && (r_start < heap_bot)) {
|
263
|
|
- r_start = heap_ptr;
|
264
|
|
- }
|
265
|
|
- r_start = (r_start + align - 1) & ~(align - 1);
|
266
|
|
- if ((r_end >= r_start) && ((r_end - r_start) >= size)) {
|
267
|
|
- return r_start;
|
268
|
|
- }
|
269
|
|
- }
|
270
|
|
- /* I did not find anything :( */
|
271
|
|
- return ULONG_MAX;
|
272
|
|
-}
|
273
|
93
|
|
274
|
|
-/**************************************************************************
|
275
|
|
-PROBE_IMAGE - Detect image file type
|
276
|
|
-**************************************************************************/
|
277
|
|
-os_download_t probe_image(unsigned char *data, unsigned int len)
|
278
|
|
-{
|
279
|
|
- os_download_t os_download = 0;
|
280
|
|
-
|
281
|
|
-#ifdef AOUT_IMAGE
|
282
|
|
- if (!os_download) os_download = aout_probe(data, len);
|
283
|
|
-#endif
|
284
|
|
-#ifdef ELF_IMAGE
|
285
|
|
- if (!os_download) os_download = elf32_probe(data, len);
|
286
|
|
-#endif
|
287
|
|
-#ifdef ELF64_IMAGE
|
288
|
|
- if (!os_download) os_download = elf64_probe(data, len);
|
289
|
|
-#endif
|
290
|
|
-#ifdef COFF_IMAGE
|
291
|
|
- if (!os_download) os_download = coff_probe(data, len);
|
292
|
|
-#endif
|
293
|
|
-#ifdef WINCE_IMAGE
|
294
|
|
- if (!os_download) os_download = wince_probe(data, len);
|
295
|
|
-#endif
|
296
|
|
-#ifdef TAGGED_IMAGE
|
297
|
|
- if (!os_download) os_download = tagged_probe(data, len);
|
298
|
|
-#endif
|
299
|
|
-/* PXE_IMAGE must always be last */
|
300
|
|
-#ifdef PXE_IMAGE
|
301
|
|
- if (!os_download) os_download = pxe_probe(data, len);
|
302
|
|
-#endif
|
303
|
|
-#ifdef RAW_IMAGE
|
304
|
|
- if (!os_download) os_download = raw_probe(data, len);
|
305
|
|
-#endif
|
306
|
|
-
|
307
|
|
- return os_download;
|
308
|
|
-}
|
309
|
|
-
|
310
|
|
-/**************************************************************************
|
311
|
|
-LOAD_BLOCK - Try to load file
|
312
|
|
-**************************************************************************/
|
313
|
|
-int load_block(unsigned char *data, unsigned int block, unsigned int len, int eof)
|
314
|
|
-{
|
315
|
|
- static os_download_t os_download;
|
316
|
|
- static sector_t skip_sectors;
|
317
|
|
- static unsigned int skip_bytes;
|
318
|
|
-#ifdef SIZEINDICATOR
|
319
|
|
- static int rlen = 0;
|
320
|
|
-
|
321
|
|
- if (block == 1)
|
322
|
|
- {
|
323
|
|
- rlen=len;
|
324
|
|
- printf("XXXX");
|
325
|
|
- }
|
326
|
|
- if (!(block % 4) || eof) {
|
327
|
|
- int size;
|
328
|
|
- size = ((block-1) * rlen + len) / 1024;
|
329
|
|
-
|
330
|
|
- putchar('\b');
|
331
|
|
- putchar('\b');
|
332
|
|
- putchar('\b');
|
333
|
|
- putchar('\b');
|
334
|
|
-
|
335
|
|
- putchar('0' + (size/1000)%10);
|
336
|
|
- putchar('0' + (size/100)%10);
|
337
|
|
- putchar('0' + (size/10)%10);
|
338
|
|
- putchar('0' + (size/1)%10);
|
339
|
|
- }
|
340
|
|
-#else
|
341
|
|
- putchar ( '.' );
|
342
|
|
-#endif
|
343
|
|
- if (block == 1)
|
344
|
|
- {
|
345
|
|
- skip_sectors = 0;
|
346
|
|
- skip_bytes = 0;
|
347
|
|
- os_download = probe_image(data, len);
|
348
|
|
- if (!os_download) {
|
349
|
|
- printf("error: not a valid image\n");
|
350
|
|
-#if 0
|
351
|
|
- printf("block: %d len: %d\n", block, len);
|
352
|
|
- printf("%hhx %hhx %hhx %hhx %hhx %hhx %hhx %hhx %hhx\n",
|
353
|
|
- data[0], data[1], data[2], data[3],
|
354
|
|
- data[4], data[5], data[6], data[7]);
|
355
|
|
-#endif
|
356
|
|
- return 0;
|
357
|
|
- }
|
358
|
|
- } /* end of block zero processing */
|
|
94
|
+ /* Zero the bss */
|
|
95
|
+ memset ( phys_to_virt ( mid ), 0, end - mid );
|
359
|
96
|
|
360
|
|
- /* Either len is greater or the skip is greater */
|
361
|
|
- if ((skip_sectors > (len >> 9)) ||
|
362
|
|
- ((skip_sectors == (len >> 9)) && (skip_bytes >= (len & 0x1ff)))) {
|
363
|
|
- /* If I don't have enough bytes borrow them from skip_sectors */
|
364
|
|
- if (skip_bytes < len) {
|
365
|
|
- skip_sectors -= (len - skip_bytes + 511) >> 9;
|
366
|
|
- skip_bytes += (len - skip_bytes + 511) & ~0x1ff;
|
367
|
|
- }
|
368
|
|
- skip_bytes -= len;
|
369
|
|
- }
|
370
|
|
- else {
|
371
|
|
- len -= (skip_sectors << 9) + skip_bytes;
|
372
|
|
- data += (skip_sectors << 9) + skip_bytes;
|
373
|
|
- }
|
374
|
|
- skip_sectors = os_download(data, len, eof);
|
375
|
|
- skip_bytes = 0;
|
376
|
|
-
|
377
|
97
|
return 1;
|
378
|
98
|
}
|
379
|
99
|
|
|
@@ -382,5 +102,3 @@ int load_block(unsigned char *data, unsigned int block, unsigned int len, int eo
|
382
|
102
|
* c-basic-offset: 8
|
383
|
103
|
* End:
|
384
|
104
|
*/
|
385
|
|
-
|
386
|
|
-#endif /* KEEP_IT_REAL */
|