2 #define BOOTINFO_VERSION 1
3 #define NODEV (-1) /* non-existent device */
4 #define PAGE_SHIFT 12 /* LOG2(PAGE_SIZE) */
5 #define PAGE_SIZE (1<<PAGE_SHIFT) /* bytes/page */
6 #define PAGE_MASK (PAGE_SIZE-1)
10 unsigned int bi_version
;
11 const unsigned char *bi_kernelname
;
12 struct nfs_diskless
*bi_nfs_diskless
;
13 /* End of fields that are always present. */
14 #define bi_endcommon bi_n_bios_used
15 unsigned int bi_n_bios_used
;
16 unsigned long bi_bios_geom
[N_BIOS_GEOM
];
18 unsigned char bi_memsizes_valid
;
19 unsigned char bi_pad
[3];
20 unsigned long bi_basemem
;
21 unsigned long bi_extmem
;
22 unsigned long bi_symtab
;
23 unsigned long bi_esymtab
;
24 /* Note that these are in the FreeBSD headers but were not here... */
25 unsigned long bi_kernend
; /* end of kernel space */
26 unsigned long bi_envp
; /* environment */
27 unsigned long bi_modulep
; /* preloaded modules */
30 static struct bootinfo bsdinfo
;
33 static Elf32_Shdr
*shdr
; /* To support the FreeBSD kludge! */
34 static Address symtab_load
;
35 static Address symstr_load
;
36 static int symtabindex
;
37 static int symstrindex
;
41 Unknown
, Tagged
, Aout
, Elf
, Aout_FreeBSD
, Elf_FreeBSD
,
42 } image_type
= Unknown
;
44 static unsigned int off
;
48 static void elf_freebsd_probe(void)
51 if ( (estate
.e
.elf32
.e_entry
& 0xf0000000) &&
52 (estate
.e
.elf32
.e_type
== ET_EXEC
))
54 image_type
= Elf_FreeBSD
;
56 off
= -(estate
.e
.elf32
.e_entry
& 0xff000000);
57 estate
.e
.elf32
.e_entry
+= off
;
59 /* Make sure we have a null to start with... */
62 /* Clear the symbol index values... */
66 /* ...and the load addresses of the symbols */
71 static void elf_freebsd_fixup_segment(void)
73 if (image_type
== Elf_FreeBSD
) {
74 estate
.p
.phdr32
[estate
.segment
].p_paddr
+= off
;
78 static void elf_freebsd_find_segment_end(void)
80 /* Count the bytes read even for the last block
81 * as we will need to know where the last block
82 * ends in order to load the symbols correctly.
83 * (plus it could be useful elsewhere...)
84 * Note that we need to count the actual size,
85 * not just the end of the disk image size.
88 (estate
.p
.phdr32
[estate
.segment
].p_memsz
-
89 estate
.p
.phdr32
[estate
.segment
].p_filesz
);
92 static int elf_freebsd_debug_loader(unsigned int offset
)
94 /* No more segments to be loaded - time to start the
95 * nasty state machine to support the loading of
96 * FreeBSD debug symbols due to the fact that FreeBSD
97 * uses/exports the kernel's debug symbols in order
98 * to make much of the system work! Amazing (arg!)
100 * We depend on the fact that for the FreeBSD kernel,
101 * there is only one section of debug symbols and that
102 * the section is after all of the loaded sections in
103 * the file. This assumes a lot but is somewhat required
104 * to make this code not be too annoying. (Where do you
105 * load symbols when the code has not loaded yet?)
106 * Since this function is actually just a callback from
107 * the network data transfer code, we need to be able to
108 * work with the data as it comes in. There is no chance
109 * for doing a seek other than forwards.
111 * The process we use is to first load the section
112 * headers. Once they are loaded (shdr != 0) we then
113 * look for where the symbol table and symbol table
114 * strings are and setup some state that we found
115 * them and fall into processing the first one (which
116 * is the symbol table) and after that has been loaded,
117 * we try the symbol strings. Note that the order is
118 * actually required as the memory image depends on
119 * the symbol strings being loaded starting at the
120 * end of the symbol table. The kernel assumes this
121 * layout of the image.
123 * At any point, if we get to the end of the load file
124 * or the section requested is earlier in the file than
125 * the current file pointer, we just end up falling
126 * out of this and booting the kernel without this
130 /* Make sure that the next address is long aligned... */
131 /* Assumes size of long is a power of 2... */
132 estate
.curaddr
= (estate
.curaddr
+ sizeof(long) - 1) & ~(sizeof(long) - 1);
134 /* If we have not yet gotten the shdr loaded, try that */
137 estate
.toread
= estate
.e
.elf32
.e_shnum
* estate
.e
.elf32
.e_shentsize
;
138 estate
.skip
= estate
.e
.elf32
.e_shoff
- (estate
.loc
+ offset
);
142 printf("shdr *, size %lX, curaddr %lX\n",
143 estate
.toread
, estate
.curaddr
);
146 /* Start reading at the curaddr and make that the shdr */
147 shdr
= (Elf32_Shdr
*)phys_to_virt(estate
.curaddr
);
149 /* Start to read... */
155 /* We have the shdr loaded, check if we have found
156 * the indexs where the symbols are supposed to be */
157 if ((symtabindex
== -1) && (symstrindex
== -1))
160 /* Make sure that the address is page aligned... */
161 /* Symbols need to start in their own page(s)... */
162 estate
.curaddr
= (estate
.curaddr
+ 4095) & ~4095;
164 /* Need to make new indexes... */
165 for (i
=0; i
< estate
.e
.elf32
.e_shnum
; i
++)
167 if (shdr
[i
].sh_type
== SHT_SYMTAB
)
170 for (j
=0; j
< estate
.e
.elf32
.e_phnum
; j
++)
172 /* Check only for loaded sections */
173 if ((estate
.p
.phdr32
[j
].p_type
| 0x80) == (PT_LOAD
| 0x80))
175 /* Only the extra symbols */
176 if ((shdr
[i
].sh_offset
>= estate
.p
.phdr32
[j
].p_offset
) &&
177 ((shdr
[i
].sh_offset
+ shdr
[i
].sh_size
) <=
178 (estate
.p
.phdr32
[j
].p_offset
+ estate
.p
.phdr32
[j
].p_filesz
)))
186 if ((shdr
[i
].sh_offset
!= 0) && (shdr
[i
].sh_size
!= 0))
189 symstrindex
= shdr
[i
].sh_link
;
195 /* Check if we have a symbol table index and have not loaded it */
196 if ((symtab_load
== 0) && (symtabindex
>= 0))
198 /* No symbol table yet? Load it first... */
200 /* This happens to work out in a strange way.
201 * If we are past the point in the file already,
202 * we will skip a *large* number of bytes which
203 * ends up bringing us to the end of the file and
204 * an old (default) boot. Less code and lets
205 * the state machine work in a cleaner way but this
206 * is a nasty side-effect trick... */
207 estate
.skip
= shdr
[symtabindex
].sh_offset
- (estate
.loc
+ offset
);
209 /* And we need to read this many bytes... */
210 estate
.toread
= shdr
[symtabindex
].sh_size
;
215 printf("db sym, size %lX, curaddr %lX\n",
216 estate
.toread
, estate
.curaddr
);
218 /* Save where we are loading this... */
219 symtab_load
= estate
.curaddr
;
221 *((long *)phys_to_virt(estate
.curaddr
)) = estate
.toread
;
222 estate
.curaddr
+= sizeof(long);
224 /* Start to read... */
228 else if ((symstr_load
== 0) && (symstrindex
>= 0))
230 /* We have already loaded the symbol table, so
231 * now on to the symbol strings... */
234 /* Same nasty trick as above... */
235 estate
.skip
= shdr
[symstrindex
].sh_offset
- (estate
.loc
+ offset
);
237 /* And we need to read this many bytes... */
238 estate
.toread
= shdr
[symstrindex
].sh_size
;
243 printf("db str, size %lX, curaddr %lX\n",
244 estate
.toread
, estate
.curaddr
);
246 /* Save where we are loading this... */
247 symstr_load
= estate
.curaddr
;
249 *((long *)phys_to_virt(estate
.curaddr
)) = estate
.toread
;
250 estate
.curaddr
+= sizeof(long);
252 /* Start to read... */
261 static void elf_freebsd_boot(unsigned long entry
)
263 if (image_type
!= Elf_FreeBSD
)
266 memset(&bsdinfo
, 0, sizeof(bsdinfo
));
267 bsdinfo
.bi_basemem
= meminfo
.basememsize
;
268 bsdinfo
.bi_extmem
= meminfo
.memsize
;
269 bsdinfo
.bi_memsizes_valid
= 1;
270 bsdinfo
.bi_version
= BOOTINFO_VERSION
;
271 bsdinfo
.bi_kernelname
= virt_to_phys(KERNEL_BUF
);
272 bsdinfo
.bi_nfs_diskless
= NULL
;
273 bsdinfo
.bi_size
= sizeof(bsdinfo
);
274 #define RB_BOOTINFO 0x80000000 /* have `struct bootinfo *' arg */
275 if(freebsd_kernel_env
[0] != '\0'){
276 freebsd_howto
|= RB_BOOTINFO
;
277 bsdinfo
.bi_envp
= (unsigned long)freebsd_kernel_env
;
280 /* Check if we have symbols loaded, and if so,
281 * made the meta_data needed to pass those to
283 if ((symtab_load
!=0) && (symstr_load
!= 0))
287 bsdinfo
.bi_symtab
= symtab_load
;
289 /* End of symbols (long aligned...) */
290 /* Assumes size of long is a power of 2... */
291 bsdinfo
.bi_esymtab
= (symstr_load
+
293 *((long *)phys_to_virt(symstr_load
)) +
294 sizeof(long) - 1) & ~(sizeof(long) - 1);
296 /* Where we will build the meta data... */
297 t
= phys_to_virt(bsdinfo
.bi_esymtab
);
300 printf("Metadata at %lX\n",t
);
303 /* Set up the pointer to the memory... */
304 bsdinfo
.bi_modulep
= virt_to_phys(t
);
306 /* The metadata structure is an array of 32-bit
307 * words where we store some information about the
308 * system. This is critical, as FreeBSD now looks
309 * only for the metadata for the extended symbol
310 * information rather than in the bootinfo.
312 /* First, do the kernel name and the kernel type */
313 /* Note that this assumed x86 byte order... */
316 *t
++=MODINFO_NAME
; *t
++= 7; *t
++=0x6E72656B; *t
++=0x00006C65;
318 /* 'elf kernel\0\0' */
319 *t
++=MODINFO_TYPE
; *t
++=11; *t
++=0x20666C65; *t
++=0x6E72656B; *t
++ = 0x00006C65;
321 /* Now the symbol start/end - note that they are
322 * here in local/physical address - the Kernel
323 * boot process will relocate the addresses. */
324 *t
++=MODINFOMD_SSYM
| MODINFO_METADATA
; *t
++=sizeof(*t
); *t
++=bsdinfo
.bi_symtab
;
325 *t
++=MODINFOMD_ESYM
| MODINFO_METADATA
; *t
++=sizeof(*t
); *t
++=bsdinfo
.bi_esymtab
;
327 *t
++=MODINFO_END
; *t
++=0; /* end of metadata */
329 /* Since we have symbols we need to make
330 * sure that the kernel knows its own end
331 * of memory... It is not _end but after
332 * the symbols and the metadata... */
333 bsdinfo
.bi_kernend
= virt_to_phys(t
);
335 /* Signal locore.s that we have a valid bootinfo
336 * structure that was completely filled in. */
337 freebsd_howto
|= 0x80000000;
340 xstart32(entry
, freebsd_howto
, NODEV
, 0, 0, 0,
341 virt_to_phys(&bsdinfo
), 0, 0, 0);
342 longjmp(restart_etherboot
, -2);
347 static void aout_freebsd_probe(void)
350 if (((astate
.head
.a_midmag
>> 16) & 0xffff) == 0) {
351 /* Some other a.out variants have a different
352 * value, and use other alignments (e.g. 1K),
353 * not the 4K used by FreeBSD. */
354 image_type
= Aout_FreeBSD
;
356 off
= -(astate
.head
.a_entry
& 0xff000000);
357 astate
.head
.a_entry
+= off
;
361 static void aout_freebsd_boot(void)
363 if (image_type
== Aout_FreeBSD
) {
364 memset(&bsdinfo
, 0, sizeof(bsdinfo
));
365 bsdinfo
.bi_basemem
= meminfo
.basememsize
;
366 bsdinfo
.bi_extmem
= meminfo
.memsize
;
367 bsdinfo
.bi_memsizes_valid
= 1;
368 bsdinfo
.bi_version
= BOOTINFO_VERSION
;
369 bsdinfo
.bi_kernelname
= virt_to_phys(KERNEL_BUF
);
370 bsdinfo
.bi_nfs_diskless
= NULL
;
371 bsdinfo
.bi_size
= sizeof(bsdinfo
);
372 xstart32(astate
.head
.a_entry
, freebsd_howto
, NODEV
, 0, 0, 0,
373 virt_to_phys(&bsdinfo
), 0, 0, 0);
374 longjmp(restart_etherboot
, -2);