• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* bootinfo */
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)
7 #define N_BIOS_GEOM     8
8 
9 struct bootinfo {
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];
17         unsigned int            bi_size;
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 */
28 };
29 
30 static struct bootinfo bsdinfo;
31 
32 #ifdef ELF_IMAGE
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;
38 #endif
39 
40 static enum {
41 	Unknown, Tagged, Aout, Elf, Aout_FreeBSD, Elf_FreeBSD,
42 } image_type = Unknown;
43 
44 static unsigned int off;
45 
46 
47 #ifdef ELF_IMAGE
elf_freebsd_probe(void)48 static void elf_freebsd_probe(void)
49 {
50 	image_type = Elf;
51 	if (	(estate.e.elf32.e_entry & 0xf0000000) &&
52 		(estate.e.elf32.e_type == ET_EXEC))
53 	{
54 		image_type = Elf_FreeBSD;
55 		printf("/FreeBSD");
56 		off = -(estate.e.elf32.e_entry & 0xff000000);
57 		estate.e.elf32.e_entry += off;
58 	}
59 	/* Make sure we have a null to start with... */
60 	shdr = 0;
61 
62 	/* Clear the symbol index values... */
63 	symtabindex = -1;
64 	symstrindex = -1;
65 
66 	/* ...and the load addresses of the symbols  */
67 	symtab_load = 0;
68 	symstr_load = 0;
69 }
70 
elf_freebsd_fixup_segment(void)71 static void elf_freebsd_fixup_segment(void)
72 {
73 	if (image_type == Elf_FreeBSD) {
74 		estate.p.phdr32[estate.segment].p_paddr += off;
75 	}
76 }
77 
elf_freebsd_find_segment_end(void)78 static void elf_freebsd_find_segment_end(void)
79 {
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.
86 	 */
87 	estate.curaddr +=
88 		(estate.p.phdr32[estate.segment].p_memsz -
89 		estate.p.phdr32[estate.segment].p_filesz);
90 }
91 
elf_freebsd_debug_loader(unsigned int offset)92 static int elf_freebsd_debug_loader(unsigned int offset)
93 {
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!)
99 	 *
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.
110 	 *
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.
122 	 *
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
127 	 * information.
128 	 */
129 
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);
133 
134 	/* If we have not yet gotten the shdr loaded, try that */
135 	if (shdr == 0)
136 	{
137 		estate.toread = estate.e.elf32.e_shnum * estate.e.elf32.e_shentsize;
138 		estate.skip = estate.e.elf32.e_shoff - (estate.loc + offset);
139 		if (estate.toread)
140 		{
141 #if ELF_DEBUG
142 			printf("shdr *, size %lX, curaddr %lX\n",
143 				estate.toread, estate.curaddr);
144 #endif
145 
146 			/* Start reading at the curaddr and make that the shdr */
147 			shdr = (Elf32_Shdr *)phys_to_virt(estate.curaddr);
148 
149 			/* Start to read... */
150 			return 1;
151 		}
152 	}
153 	else
154 	{
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))
158 		{
159 			int i;
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;
163 
164 			/* Need to make new indexes... */
165 			for (i=0; i < estate.e.elf32.e_shnum; i++)
166 			{
167 				if (shdr[i].sh_type == SHT_SYMTAB)
168 				{
169 					int j;
170 					for (j=0; j < estate.e.elf32.e_phnum; j++)
171 					{
172 						/* Check only for loaded sections */
173 						if ((estate.p.phdr32[j].p_type | 0x80) == (PT_LOAD | 0x80))
174 						{
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)))
179 							{
180 								shdr[i].sh_offset=0;
181 								shdr[i].sh_size=0;
182 								break;
183 							}
184 						}
185 					}
186 					if ((shdr[i].sh_offset != 0) && (shdr[i].sh_size != 0))
187 					{
188 						symtabindex = i;
189 						symstrindex = shdr[i].sh_link;
190 					}
191 				}
192 			}
193 		}
194 
195 		/* Check if we have a symbol table index and have not loaded it */
196 		if ((symtab_load == 0) && (symtabindex >= 0))
197 		{
198 			/* No symbol table yet?  Load it first... */
199 
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);
208 
209 			/* And we need to read this many bytes... */
210 			estate.toread = shdr[symtabindex].sh_size;
211 
212 			if (estate.toread)
213 			{
214 #if ELF_DEBUG
215 				printf("db sym, size %lX, curaddr %lX\n",
216 					estate.toread, estate.curaddr);
217 #endif
218 				/* Save where we are loading this... */
219 				symtab_load = estate.curaddr;
220 
221 				*((long *)phys_to_virt(estate.curaddr)) = estate.toread;
222 				estate.curaddr += sizeof(long);
223 
224 				/* Start to read... */
225 				return 1;
226 			}
227 		}
228 		else if ((symstr_load == 0) && (symstrindex >= 0))
229 		{
230 			/* We have already loaded the symbol table, so
231 			 * now on to the symbol strings... */
232 
233 
234 			/* Same nasty trick as above... */
235 			estate.skip = shdr[symstrindex].sh_offset - (estate.loc + offset);
236 
237 			/* And we need to read this many bytes... */
238 			estate.toread = shdr[symstrindex].sh_size;
239 
240 			if (estate.toread)
241 			{
242 #if ELF_DEBUG
243 				printf("db str, size %lX, curaddr %lX\n",
244 					estate.toread, estate.curaddr);
245 #endif
246 				/* Save where we are loading this... */
247 				symstr_load = estate.curaddr;
248 
249 				*((long *)phys_to_virt(estate.curaddr)) = estate.toread;
250 				estate.curaddr += sizeof(long);
251 
252 				/* Start to read... */
253 				return 1;
254 			}
255 		}
256 	}
257 	/* all done */
258 	return 0;
259 }
260 
elf_freebsd_boot(unsigned long entry)261 static void elf_freebsd_boot(unsigned long entry)
262 {
263 	if (image_type != Elf_FreeBSD)
264 		return;
265 
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;
278 	}
279 
280 	/* Check if we have symbols loaded, and if so,
281 	 * made the meta_data needed to pass those to
282 	 * the kernel. */
283 	if ((symtab_load !=0) && (symstr_load != 0))
284 	{
285 		unsigned long *t;
286 
287 		bsdinfo.bi_symtab = symtab_load;
288 
289 		/* End of symbols (long aligned...) */
290 		/* Assumes size of long is a power of 2... */
291 		bsdinfo.bi_esymtab = (symstr_load +
292 			sizeof(long) +
293 			*((long *)phys_to_virt(symstr_load)) +
294 			sizeof(long) - 1) & ~(sizeof(long) - 1);
295 
296 		/* Where we will build the meta data... */
297 		t = phys_to_virt(bsdinfo.bi_esymtab);
298 
299 #if ELF_DEBUG
300 		printf("Metadata at %lX\n",t);
301 #endif
302 
303 		/* Set up the pointer to the memory... */
304 		bsdinfo.bi_modulep = virt_to_phys(t);
305 
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.
311 		 */
312 		/* First, do the kernel name and the kernel type */
313 		/* Note that this assumed x86 byte order... */
314 
315 		/* 'kernel\0\0' */
316 		*t++=MODINFO_NAME; *t++= 7; *t++=0x6E72656B; *t++=0x00006C65;
317 
318 		/* 'elf kernel\0\0' */
319 		*t++=MODINFO_TYPE; *t++=11; *t++=0x20666C65; *t++=0x6E72656B; *t++ = 0x00006C65;
320 
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;
326 
327 		*t++=MODINFO_END; *t++=0; /* end of metadata */
328 
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);
334 
335 		/* Signal locore.s that we have a valid bootinfo
336 		 * structure that was completely filled in. */
337 		freebsd_howto |= 0x80000000;
338 	}
339 
340 	xstart32(entry, freebsd_howto, NODEV, 0, 0, 0,
341 		virt_to_phys(&bsdinfo), 0, 0, 0);
342 	longjmp(restart_etherboot, -2);
343 }
344 #endif
345 
346 #ifdef AOUT_IMAGE
aout_freebsd_probe(void)347 static void aout_freebsd_probe(void)
348 {
349 	image_type = Aout;
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;
355 		printf("/FreeBSD");
356 		off = -(astate.head.a_entry & 0xff000000);
357 		astate.head.a_entry += off;
358 	}
359 }
360 
aout_freebsd_boot(void)361 static void aout_freebsd_boot(void)
362 {
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);
375 	}
376 }
377 #endif
378