1 /* boot.c - load and bootstrap a kernel */
2 /*
3 * GRUB -- GRand Unified Bootloader
4 * Copyright (C) 1999,2000,2001,2002,2003,2004 Free Software Foundation, Inc.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21
22 #include "shared.h"
23
24 #include "freebsd.h"
25 #include "imgact_aout.h"
26 #include "i386-elf.h"
27
28 static int cur_addr;
29 entry_func entry_addr;
30 static struct mod_list mll[99];
31 static int linux_mem_size;
32
33 /*
34 * The next two functions, 'load_image' and 'load_module', are the building
35 * blocks of the multiboot loader component. They handle essentially all
36 * of the gory details of loading in a bootable image and the modules.
37 */
38
39 kernel_t
load_image(char * kernel,char * arg,kernel_t suggested_type,unsigned long load_flags)40 load_image (char *kernel, char *arg, kernel_t suggested_type,
41 unsigned long load_flags)
42 {
43 int len, i, exec_type = 0, align_4k = 1;
44 entry_func real_entry_addr = 0;
45 kernel_t type = KERNEL_TYPE_NONE;
46 unsigned long flags = 0, text_len = 0, data_len = 0, bss_len = 0;
47 char *str = 0, *str2 = 0;
48 struct linux_kernel_header *lh;
49 union
50 {
51 struct multiboot_header *mb;
52 struct exec *aout;
53 Elf32_Ehdr *elf;
54 }
55 pu;
56 /* presuming that MULTIBOOT_SEARCH is large enough to encompass an
57 executable header */
58 unsigned char buffer[MULTIBOOT_SEARCH];
59
60 /* sets the header pointer to point to the beginning of the
61 buffer by default */
62 pu.aout = (struct exec *) buffer;
63
64 if (!grub_open (kernel))
65 return KERNEL_TYPE_NONE;
66
67 if (!(len = grub_read (buffer, MULTIBOOT_SEARCH)) || len < 32)
68 {
69 grub_close ();
70
71 if (!errnum)
72 errnum = ERR_EXEC_FORMAT;
73
74 return KERNEL_TYPE_NONE;
75 }
76
77 for (i = 0; i < len; i++)
78 {
79 if (MULTIBOOT_FOUND ((int) (buffer + i), len - i))
80 {
81 flags = ((struct multiboot_header *) (buffer + i))->flags;
82 if (flags & MULTIBOOT_UNSUPPORTED)
83 {
84 grub_close ();
85 errnum = ERR_BOOT_FEATURES;
86 return KERNEL_TYPE_NONE;
87 }
88 type = KERNEL_TYPE_MULTIBOOT;
89 str2 = "Multiboot";
90 break;
91 }
92 }
93
94 /* Use BUFFER as a linux kernel header, if the image is Linux zImage
95 or bzImage. */
96 lh = (struct linux_kernel_header *) buffer;
97
98 /* ELF loading supported if multiboot, FreeBSD and NetBSD. */
99 if ((type == KERNEL_TYPE_MULTIBOOT
100 || pu.elf->e_ident[EI_OSABI] == ELFOSABI_FREEBSD
101 || grub_strcmp (pu.elf->e_ident + EI_BRAND, "FreeBSD") == 0
102 || suggested_type == KERNEL_TYPE_NETBSD)
103 && len > sizeof (Elf32_Ehdr)
104 && BOOTABLE_I386_ELF ((*((Elf32_Ehdr *) buffer))))
105 {
106 if (type == KERNEL_TYPE_MULTIBOOT)
107 entry_addr = (entry_func) pu.elf->e_entry;
108 else
109 entry_addr = (entry_func) (pu.elf->e_entry & 0xFFFFFF);
110
111 if (entry_addr < (entry_func) 0x100000)
112 errnum = ERR_BELOW_1MB;
113
114 /* don't want to deal with ELF program header at some random
115 place in the file -- this generally won't happen */
116 if (pu.elf->e_phoff == 0 || pu.elf->e_phnum == 0
117 || ((pu.elf->e_phoff + (pu.elf->e_phentsize * pu.elf->e_phnum))
118 >= len))
119 errnum = ERR_EXEC_FORMAT;
120 str = "elf";
121
122 if (type == KERNEL_TYPE_NONE)
123 {
124 /* At the moment, there is no way to identify a NetBSD ELF
125 kernel, so rely on the suggested type by the user. */
126 if (suggested_type == KERNEL_TYPE_NETBSD)
127 {
128 str2 = "NetBSD";
129 type = suggested_type;
130 }
131 else
132 {
133 str2 = "FreeBSD";
134 type = KERNEL_TYPE_FREEBSD;
135 }
136 }
137 }
138 else if (flags & MULTIBOOT_AOUT_KLUDGE)
139 {
140 pu.mb = (struct multiboot_header *) (buffer + i);
141 entry_addr = (entry_func) pu.mb->entry_addr;
142 cur_addr = pu.mb->load_addr;
143 /* first offset into file */
144 grub_seek (i - (pu.mb->header_addr - cur_addr));
145
146 /* If the load end address is zero, load the whole contents. */
147 if (! pu.mb->load_end_addr)
148 pu.mb->load_end_addr = cur_addr + filemax;
149
150 text_len = pu.mb->load_end_addr - cur_addr;
151 data_len = 0;
152
153 /* If the bss end address is zero, assume that there is no bss area. */
154 if (! pu.mb->bss_end_addr)
155 pu.mb->bss_end_addr = pu.mb->load_end_addr;
156
157 bss_len = pu.mb->bss_end_addr - pu.mb->load_end_addr;
158
159 if (pu.mb->header_addr < pu.mb->load_addr
160 || pu.mb->load_end_addr <= pu.mb->load_addr
161 || pu.mb->bss_end_addr < pu.mb->load_end_addr
162 || (pu.mb->header_addr - pu.mb->load_addr) > i)
163 errnum = ERR_EXEC_FORMAT;
164
165 if (cur_addr < 0x100000)
166 errnum = ERR_BELOW_1MB;
167
168 pu.aout = (struct exec *) buffer;
169 exec_type = 2;
170 str = "kludge";
171 }
172 else if (len > sizeof (struct exec) && !N_BADMAG ((*(pu.aout))))
173 {
174 entry_addr = (entry_func) pu.aout->a_entry;
175
176 if (type == KERNEL_TYPE_NONE)
177 {
178 /*
179 * If it doesn't have a Multiboot header, then presume
180 * it is either a FreeBSD or NetBSD executable. If so,
181 * then use a magic number of normal ordering, ZMAGIC to
182 * determine if it is FreeBSD.
183 *
184 * This is all because freebsd and netbsd seem to require
185 * masking out some address bits... differently for each
186 * one... plus of course we need to know which booting
187 * method to use.
188 */
189 entry_addr = (entry_func) ((int) entry_addr & 0xFFFFFF);
190
191 if (buffer[0] == 0xb && buffer[1] == 1)
192 {
193 type = KERNEL_TYPE_FREEBSD;
194 cur_addr = (int) entry_addr;
195 str2 = "FreeBSD";
196 }
197 else
198 {
199 type = KERNEL_TYPE_NETBSD;
200 cur_addr = (int) entry_addr & 0xF00000;
201 if (N_GETMAGIC ((*(pu.aout))) != NMAGIC)
202 align_4k = 0;
203 str2 = "NetBSD";
204 }
205 }
206
207 /* first offset into file */
208 grub_seek (N_TXTOFF (*(pu.aout)));
209 text_len = pu.aout->a_text;
210 data_len = pu.aout->a_data;
211 bss_len = pu.aout->a_bss;
212
213 if (cur_addr < 0x100000)
214 errnum = ERR_BELOW_1MB;
215
216 exec_type = 1;
217 str = "a.out";
218 }
219 else if (lh->boot_flag == BOOTSEC_SIGNATURE
220 && lh->setup_sects <= LINUX_MAX_SETUP_SECTS)
221 {
222 int big_linux = 0;
223 int setup_sects = lh->setup_sects;
224
225 if (lh->header == LINUX_MAGIC_SIGNATURE && lh->version >= 0x0200)
226 {
227 big_linux = (lh->loadflags & LINUX_FLAG_BIG_KERNEL);
228 lh->type_of_loader = LINUX_BOOT_LOADER_TYPE;
229
230 /* Put the real mode part at as a high location as possible. */
231 linux_data_real_addr
232 = (char *) ((mbi.mem_lower << 10) - LINUX_SETUP_MOVE_SIZE);
233 /* But it must not exceed the traditional area. */
234 if (linux_data_real_addr > (char *) LINUX_OLD_REAL_MODE_ADDR)
235 linux_data_real_addr = (char *) LINUX_OLD_REAL_MODE_ADDR;
236
237 if (lh->version >= 0x0201)
238 {
239 lh->heap_end_ptr = LINUX_HEAP_END_OFFSET;
240 lh->loadflags |= LINUX_FLAG_CAN_USE_HEAP;
241 }
242
243 if (lh->version >= 0x0202)
244 lh->cmd_line_ptr = linux_data_real_addr + LINUX_CL_OFFSET;
245 else
246 {
247 lh->cl_magic = LINUX_CL_MAGIC;
248 lh->cl_offset = LINUX_CL_OFFSET;
249 lh->setup_move_size = LINUX_SETUP_MOVE_SIZE;
250 }
251 }
252 else
253 {
254 /* Your kernel is quite old... */
255 lh->cl_magic = LINUX_CL_MAGIC;
256 lh->cl_offset = LINUX_CL_OFFSET;
257
258 setup_sects = LINUX_DEFAULT_SETUP_SECTS;
259
260 linux_data_real_addr = (char *) LINUX_OLD_REAL_MODE_ADDR;
261 }
262
263 /* If SETUP_SECTS is not set, set it to the default (4). */
264 if (! setup_sects)
265 setup_sects = LINUX_DEFAULT_SETUP_SECTS;
266
267 data_len = setup_sects << 9;
268 text_len = filemax - data_len - SECTOR_SIZE;
269
270 linux_data_tmp_addr = (char *) LINUX_BZIMAGE_ADDR + text_len;
271
272 if (! big_linux
273 && text_len > linux_data_real_addr - (char *) LINUX_ZIMAGE_ADDR)
274 {
275 grub_printf (" linux 'zImage' kernel too big, try 'make bzImage'\n");
276 errnum = ERR_WONT_FIT;
277 }
278 else if (linux_data_real_addr + LINUX_SETUP_MOVE_SIZE
279 > RAW_ADDR ((char *) (mbi.mem_lower << 10)))
280 errnum = ERR_WONT_FIT;
281 else
282 {
283 grub_printf (" [Linux-%s, setup=0x%x, size=0x%x]\n",
284 (big_linux ? "bzImage" : "zImage"), data_len, text_len);
285
286 /* Video mode selection support. What a mess! */
287 /* NOTE: Even the word "mess" is not still enough to
288 represent how wrong and bad the Linux video support is,
289 but I don't want to hear complaints from Linux fanatics
290 any more. -okuji */
291 {
292 char *vga;
293
294 /* Find the substring "vga=". */
295 vga = grub_strstr (arg, "vga=");
296 if (vga)
297 {
298 char *value = vga + 4;
299 int vid_mode;
300
301 /* Handle special strings. */
302 if (substring ("normal", value) < 1)
303 vid_mode = LINUX_VID_MODE_NORMAL;
304 else if (substring ("ext", value) < 1)
305 vid_mode = LINUX_VID_MODE_EXTENDED;
306 else if (substring ("ask", value) < 1)
307 vid_mode = LINUX_VID_MODE_ASK;
308 else if (safe_parse_maxint (&value, &vid_mode))
309 ;
310 else
311 {
312 /* ERRNUM is already set inside the function
313 safe_parse_maxint. */
314 grub_close ();
315 return KERNEL_TYPE_NONE;
316 }
317
318 lh->vid_mode = vid_mode;
319 }
320 }
321
322 /* Check the mem= option to limit memory used for initrd. */
323 {
324 char *mem;
325
326 mem = grub_strstr (arg, "mem=");
327 if (mem)
328 {
329 char *value = mem + 4;
330
331 safe_parse_maxint (&value, &linux_mem_size);
332 switch (errnum)
333 {
334 case ERR_NUMBER_OVERFLOW:
335 /* If an overflow occurs, use the maximum address for
336 initrd instead. This is good, because MAXINT is
337 greater than LINUX_INITRD_MAX_ADDRESS. */
338 linux_mem_size = LINUX_INITRD_MAX_ADDRESS;
339 errnum = ERR_NONE;
340 break;
341
342 case ERR_NONE:
343 {
344 int shift = 0;
345
346 switch (grub_tolower (*value))
347 {
348 case 'g':
349 shift += 10;
350 case 'm':
351 shift += 10;
352 case 'k':
353 shift += 10;
354 default:
355 break;
356 }
357
358 /* Check an overflow. */
359 if (linux_mem_size > (MAXINT >> shift))
360 linux_mem_size = LINUX_INITRD_MAX_ADDRESS;
361 else
362 linux_mem_size <<= shift;
363 }
364 break;
365
366 default:
367 linux_mem_size = 0;
368 errnum = ERR_NONE;
369 break;
370 }
371 }
372 else
373 linux_mem_size = 0;
374 }
375
376 /* It is possible that DATA_LEN + SECTOR_SIZE is greater than
377 MULTIBOOT_SEARCH, so the data may have been read partially. */
378 if (data_len + SECTOR_SIZE <= MULTIBOOT_SEARCH)
379 grub_memmove (linux_data_tmp_addr, buffer,
380 data_len + SECTOR_SIZE);
381 else
382 {
383 grub_memmove (linux_data_tmp_addr, buffer, MULTIBOOT_SEARCH);
384 grub_read (linux_data_tmp_addr + MULTIBOOT_SEARCH,
385 data_len + SECTOR_SIZE - MULTIBOOT_SEARCH);
386 }
387
388 if (lh->header != LINUX_MAGIC_SIGNATURE ||
389 lh->version < 0x0200)
390 /* Clear the heap space. */
391 grub_memset (linux_data_tmp_addr + ((setup_sects + 1) << 9),
392 0,
393 (64 - setup_sects - 1) << 9);
394
395 /* Copy command-line plus memory hack to staging area.
396 NOTE: Linux has a bug that it doesn't handle multiple spaces
397 between two options and a space after a "mem=" option isn't
398 removed correctly so the arguments to init could be like
399 {"init", "", "", NULL}. This affects some not-very-clever
400 shells. Thus, the code below does a trick to avoid the bug.
401 That is, copy "mem=XXX" to the end of the command-line, and
402 avoid to copy spaces unnecessarily. Hell. */
403 {
404 char *src = skip_to (0, arg);
405 char *dest = linux_data_tmp_addr + LINUX_CL_OFFSET;
406
407 while (dest < linux_data_tmp_addr + LINUX_CL_END_OFFSET && *src)
408 *(dest++) = *(src++);
409
410 /* Old Linux kernels have problems determining the amount of
411 the available memory. To work around this problem, we add
412 the "mem" option to the kernel command line. This has its
413 own drawbacks because newer kernels can determine the
414 memory map more accurately. Boot protocol 2.03, which
415 appeared in Linux 2.4.18, provides a pointer to the kernel
416 version string, so we could check it. But since kernel
417 2.4.18 and newer are known to detect memory reliably, boot
418 protocol 2.03 already implies that the kernel is new
419 enough. The "mem" option is added if neither of the
420 following conditions is met:
421 1) The "mem" option is already present.
422 2) The "kernel" command is used with "--no-mem-option".
423 3) GNU GRUB is configured not to pass the "mem" option.
424 4) The kernel supports boot protocol 2.03 or newer. */
425 if (! grub_strstr (arg, "mem=")
426 && ! (load_flags & KERNEL_LOAD_NO_MEM_OPTION)
427 && lh->version < 0x0203 /* kernel version < 2.4.18 */
428 && dest + 15 < linux_data_tmp_addr + LINUX_CL_END_OFFSET)
429 {
430 *dest++ = ' ';
431 *dest++ = 'm';
432 *dest++ = 'e';
433 *dest++ = 'm';
434 *dest++ = '=';
435
436 dest = convert_to_ascii (dest, 'u', (extended_memory + 0x400));
437 *dest++ = 'K';
438 }
439
440 *dest = 0;
441 }
442
443 /* offset into file */
444 grub_seek (data_len + SECTOR_SIZE);
445
446 cur_addr = (int) linux_data_tmp_addr + LINUX_SETUP_MOVE_SIZE;
447 grub_read ((char *) LINUX_BZIMAGE_ADDR, text_len);
448
449 if (errnum == ERR_NONE)
450 {
451 grub_close ();
452
453 /* Sanity check. */
454 if (suggested_type != KERNEL_TYPE_NONE
455 && ((big_linux && suggested_type != KERNEL_TYPE_BIG_LINUX)
456 || (! big_linux && suggested_type != KERNEL_TYPE_LINUX)))
457 {
458 errnum = ERR_EXEC_FORMAT;
459 return KERNEL_TYPE_NONE;
460 }
461
462 /* Ugly hack. */
463 linux_text_len = text_len;
464
465 return big_linux ? KERNEL_TYPE_BIG_LINUX : KERNEL_TYPE_LINUX;
466 }
467 }
468 }
469 else /* no recognizable format */
470 errnum = ERR_EXEC_FORMAT;
471
472 /* return if error */
473 if (errnum)
474 {
475 grub_close ();
476 return KERNEL_TYPE_NONE;
477 }
478
479 /* fill the multiboot info structure */
480 mbi.cmdline = (int) arg;
481 mbi.mods_count = 0;
482 mbi.mods_addr = 0;
483 mbi.boot_device = (current_drive << 24) | current_partition;
484 mbi.flags &= ~(MB_INFO_MODS | MB_INFO_AOUT_SYMS | MB_INFO_ELF_SHDR);
485 mbi.syms.a.tabsize = 0;
486 mbi.syms.a.strsize = 0;
487 mbi.syms.a.addr = 0;
488 mbi.syms.a.pad = 0;
489
490 printf (" [%s-%s", str2, str);
491
492 str = "";
493
494 if (exec_type) /* can be loaded like a.out */
495 {
496 if (flags & MULTIBOOT_AOUT_KLUDGE)
497 str = "-and-data";
498
499 printf (", loadaddr=0x%x, text%s=0x%x", cur_addr, str, text_len);
500
501 /* read text, then read data */
502 if (grub_read ((char *) RAW_ADDR (cur_addr), text_len) == text_len)
503 {
504 cur_addr += text_len;
505
506 if (!(flags & MULTIBOOT_AOUT_KLUDGE))
507 {
508 /* we have to align to a 4K boundary */
509 if (align_4k)
510 cur_addr = (cur_addr + 0xFFF) & 0xFFFFF000;
511 else
512 printf (", C");
513
514 printf (", data=0x%x", data_len);
515
516 if ((grub_read ((char *) RAW_ADDR (cur_addr), data_len)
517 != data_len)
518 && !errnum)
519 errnum = ERR_EXEC_FORMAT;
520 cur_addr += data_len;
521 }
522
523 if (!errnum)
524 {
525 memset ((char *) RAW_ADDR (cur_addr), 0, bss_len);
526 cur_addr += bss_len;
527
528 printf (", bss=0x%x", bss_len);
529 }
530 }
531 else if (!errnum)
532 errnum = ERR_EXEC_FORMAT;
533
534 if (!errnum && pu.aout->a_syms
535 && pu.aout->a_syms < (filemax - filepos))
536 {
537 int symtab_err, orig_addr = cur_addr;
538
539 /* we should align to a 4K boundary here for good measure */
540 if (align_4k)
541 cur_addr = (cur_addr + 0xFFF) & 0xFFFFF000;
542
543 mbi.syms.a.addr = cur_addr;
544
545 *((int *) RAW_ADDR (cur_addr)) = pu.aout->a_syms;
546 cur_addr += sizeof (int);
547
548 printf (", symtab=0x%x", pu.aout->a_syms);
549
550 if (grub_read ((char *) RAW_ADDR (cur_addr), pu.aout->a_syms)
551 == pu.aout->a_syms)
552 {
553 cur_addr += pu.aout->a_syms;
554 mbi.syms.a.tabsize = pu.aout->a_syms;
555
556 if (grub_read ((char *) &i, sizeof (int)) == sizeof (int))
557 {
558 *((int *) RAW_ADDR (cur_addr)) = i;
559 cur_addr += sizeof (int);
560
561 mbi.syms.a.strsize = i;
562
563 i -= sizeof (int);
564
565 printf (", strtab=0x%x", i);
566
567 symtab_err = (grub_read ((char *) RAW_ADDR (cur_addr), i)
568 != i);
569 cur_addr += i;
570 }
571 else
572 symtab_err = 1;
573 }
574 else
575 symtab_err = 1;
576
577 if (symtab_err)
578 {
579 printf ("(bad)");
580 cur_addr = orig_addr;
581 mbi.syms.a.tabsize = 0;
582 mbi.syms.a.strsize = 0;
583 mbi.syms.a.addr = 0;
584 }
585 else
586 mbi.flags |= MB_INFO_AOUT_SYMS;
587 }
588 }
589 else
590 /* ELF executable */
591 {
592 unsigned loaded = 0, memaddr, memsiz, filesiz;
593 Elf32_Phdr *phdr;
594
595 /* reset this to zero for now */
596 cur_addr = 0;
597
598 /* scan for program segments */
599 for (i = 0; i < pu.elf->e_phnum; i++)
600 {
601 phdr = (Elf32_Phdr *)
602 (pu.elf->e_phoff + ((int) buffer)
603 + (pu.elf->e_phentsize * i));
604 if (phdr->p_type == PT_LOAD)
605 {
606 /* offset into file */
607 grub_seek (phdr->p_offset);
608 filesiz = phdr->p_filesz;
609
610 if (type == KERNEL_TYPE_FREEBSD || type == KERNEL_TYPE_NETBSD)
611 memaddr = RAW_ADDR (phdr->p_paddr & 0xFFFFFF);
612 else
613 memaddr = RAW_ADDR (phdr->p_paddr);
614
615 memsiz = phdr->p_memsz;
616 if (memaddr < RAW_ADDR (0x100000))
617 errnum = ERR_BELOW_1MB;
618
619 /* If the memory range contains the entry address, get the
620 physical address here. */
621 if (type == KERNEL_TYPE_MULTIBOOT
622 && (unsigned) entry_addr >= phdr->p_vaddr
623 && (unsigned) entry_addr < phdr->p_vaddr + memsiz)
624 real_entry_addr = (entry_func) ((unsigned) entry_addr
625 + memaddr - phdr->p_vaddr);
626
627 /* make sure we only load what we're supposed to! */
628 if (filesiz > memsiz)
629 filesiz = memsiz;
630 /* mark memory as used */
631 if (cur_addr < memaddr + memsiz)
632 cur_addr = memaddr + memsiz;
633 printf (", <0x%x:0x%x:0x%x>", memaddr, filesiz,
634 memsiz - filesiz);
635 /* increment number of segments */
636 loaded++;
637
638 /* load the segment */
639 if (memcheck (memaddr, memsiz)
640 && grub_read ((char *) memaddr, filesiz) == filesiz)
641 {
642 if (memsiz > filesiz)
643 memset ((char *) (memaddr + filesiz), 0, memsiz - filesiz);
644 }
645 else
646 break;
647 }
648 }
649
650 if (! errnum)
651 {
652 if (! loaded)
653 errnum = ERR_EXEC_FORMAT;
654 else
655 {
656 /* Load ELF symbols. */
657 Elf32_Shdr *shdr = NULL;
658 int tab_size, sec_size;
659 int symtab_err = 0;
660
661 mbi.syms.e.num = pu.elf->e_shnum;
662 mbi.syms.e.size = pu.elf->e_shentsize;
663 mbi.syms.e.shndx = pu.elf->e_shstrndx;
664
665 /* We should align to a 4K boundary here for good measure. */
666 if (align_4k)
667 cur_addr = (cur_addr + 0xFFF) & 0xFFFFF000;
668
669 tab_size = pu.elf->e_shentsize * pu.elf->e_shnum;
670
671 grub_seek (pu.elf->e_shoff);
672 if (grub_read ((char *) RAW_ADDR (cur_addr), tab_size)
673 == tab_size)
674 {
675 mbi.syms.e.addr = cur_addr;
676 shdr = (Elf32_Shdr *) mbi.syms.e.addr;
677 cur_addr += tab_size;
678
679 printf (", shtab=0x%x", cur_addr);
680
681 for (i = 0; i < mbi.syms.e.num; i++)
682 {
683 /* This section is a loaded section,
684 so we don't care. */
685 if (shdr[i].sh_addr != 0)
686 continue;
687
688 /* This section is empty, so we don't care. */
689 if (shdr[i].sh_size == 0)
690 continue;
691
692 /* Align the section to a sh_addralign bits boundary. */
693 cur_addr = ((cur_addr + shdr[i].sh_addralign) &
694 - (int) shdr[i].sh_addralign);
695
696 grub_seek (shdr[i].sh_offset);
697
698 sec_size = shdr[i].sh_size;
699
700 if (! (memcheck (cur_addr, sec_size)
701 && (grub_read ((char *) RAW_ADDR (cur_addr),
702 sec_size)
703 == sec_size)))
704 {
705 symtab_err = 1;
706 break;
707 }
708
709 shdr[i].sh_addr = cur_addr;
710 cur_addr += sec_size;
711 }
712 }
713 else
714 symtab_err = 1;
715
716 if (mbi.syms.e.addr < RAW_ADDR(0x10000))
717 symtab_err = 1;
718
719 if (symtab_err)
720 {
721 printf ("(bad)");
722 mbi.syms.e.num = 0;
723 mbi.syms.e.size = 0;
724 mbi.syms.e.addr = 0;
725 mbi.syms.e.shndx = 0;
726 cur_addr = 0;
727 }
728 else
729 mbi.flags |= MB_INFO_ELF_SHDR;
730 }
731 }
732 }
733
734 if (! errnum)
735 {
736 grub_printf (", entry=0x%x]\n", (unsigned) entry_addr);
737
738 /* If the entry address is physically different from that of the ELF
739 header, correct it here. */
740 if (real_entry_addr)
741 entry_addr = real_entry_addr;
742 }
743 else
744 {
745 putchar ('\n');
746 type = KERNEL_TYPE_NONE;
747 }
748
749 grub_close ();
750
751 /* Sanity check. */
752 if (suggested_type != KERNEL_TYPE_NONE && suggested_type != type)
753 {
754 errnum = ERR_EXEC_FORMAT;
755 return KERNEL_TYPE_NONE;
756 }
757
758 return type;
759 }
760
761 int
load_module(char * module,char * arg)762 load_module (char *module, char *arg)
763 {
764 int len;
765
766 /* if we are supposed to load on 4K boundaries */
767 cur_addr = (cur_addr + 0xFFF) & 0xFFFFF000;
768
769 if (!grub_open (module))
770 return 0;
771
772 len = grub_read ((char *) cur_addr, -1);
773 if (! len)
774 {
775 grub_close ();
776 return 0;
777 }
778
779 printf (" [Multiboot-module @ 0x%x, 0x%x bytes]\n", cur_addr, len);
780
781 /* these two simply need to be set if any modules are loaded at all */
782 mbi.flags |= MB_INFO_MODS;
783 mbi.mods_addr = (int) mll;
784
785 mll[mbi.mods_count].cmdline = (int) arg;
786 mll[mbi.mods_count].mod_start = cur_addr;
787 cur_addr += len;
788 mll[mbi.mods_count].mod_end = cur_addr;
789 mll[mbi.mods_count].pad = 0;
790
791 /* increment number of modules included */
792 mbi.mods_count++;
793
794 grub_close ();
795 return 1;
796 }
797
798 int
load_initrd(char * initrd)799 load_initrd (char *initrd)
800 {
801 int len;
802 unsigned long moveto;
803 unsigned long max_addr;
804 struct linux_kernel_header *lh
805 = (struct linux_kernel_header *) (cur_addr - LINUX_SETUP_MOVE_SIZE);
806
807 #ifndef NO_DECOMPRESSION
808 no_decompression = 1;
809 #endif
810
811 if (! grub_open (initrd))
812 goto fail;
813
814 len = grub_read ((char *) cur_addr, -1);
815 if (! len)
816 {
817 grub_close ();
818 goto fail;
819 }
820
821 if (linux_mem_size)
822 moveto = linux_mem_size;
823 else
824 moveto = (mbi.mem_upper + 0x400) << 10;
825
826 moveto = (moveto - len) & 0xfffff000;
827 max_addr = (lh->header == LINUX_MAGIC_SIGNATURE && lh->version >= 0x0203
828 ? lh->initrd_addr_max : LINUX_INITRD_MAX_ADDRESS);
829 if (moveto + len >= max_addr)
830 moveto = (max_addr - len) & 0xfffff000;
831
832 /* XXX: Linux 2.3.xx has a bug in the memory range check, so avoid
833 the last page.
834 XXX: Linux 2.2.xx has a bug in the memory range check, which is
835 worse than that of Linux 2.3.xx, so avoid the last 64kb. *sigh* */
836 moveto -= 0x10000;
837 memmove ((void *) RAW_ADDR (moveto), (void *) cur_addr, len);
838
839 printf (" [Linux-initrd @ 0x%x, 0x%x bytes]\n", moveto, len);
840
841 /* FIXME: Should check if the kernel supports INITRD. */
842 lh->ramdisk_image = RAW_ADDR (moveto);
843 lh->ramdisk_size = len;
844
845 grub_close ();
846
847 fail:
848
849 #ifndef NO_DECOMPRESSION
850 no_decompression = 0;
851 #endif
852
853 return ! errnum;
854 }
855
856
857 #ifdef GRUB_UTIL
858 /* Dummy function to fake the *BSD boot. */
859 static void
bsd_boot_entry(int flags,int bootdev,int sym_start,int sym_end,int mem_upper,int mem_lower)860 bsd_boot_entry (int flags, int bootdev, int sym_start, int sym_end,
861 int mem_upper, int mem_lower)
862 {
863 stop ();
864 }
865 #endif
866
867
868 /*
869 * All "*_boot" commands depend on the images being loaded into memory
870 * correctly, the variables in this file being set up correctly, and
871 * the root partition being set in the 'saved_drive' and 'saved_partition'
872 * variables.
873 */
874
875
876 void
bsd_boot(kernel_t type,int bootdev,char * arg)877 bsd_boot (kernel_t type, int bootdev, char *arg)
878 {
879 char *str;
880 int clval = 0, i;
881 struct bootinfo bi;
882
883 #ifdef GRUB_UTIL
884 entry_addr = (entry_func) bsd_boot_entry;
885 #else
886 stop_floppy ();
887 #endif
888
889 while (*(++arg) && *arg != ' ');
890 str = arg;
891 while (*str)
892 {
893 if (*str == '-')
894 {
895 while (*str && *str != ' ')
896 {
897 if (*str == 'C')
898 clval |= RB_CDROM;
899 if (*str == 'a')
900 clval |= RB_ASKNAME;
901 if (*str == 'b')
902 clval |= RB_HALT;
903 if (*str == 'c')
904 clval |= RB_CONFIG;
905 if (*str == 'd')
906 clval |= RB_KDB;
907 if (*str == 'D')
908 clval |= RB_MULTIPLE;
909 if (*str == 'g')
910 clval |= RB_GDB;
911 if (*str == 'h')
912 clval |= RB_SERIAL;
913 if (*str == 'm')
914 clval |= RB_MUTE;
915 if (*str == 'r')
916 clval |= RB_DFLTROOT;
917 if (*str == 's')
918 clval |= RB_SINGLE;
919 if (*str == 'v')
920 clval |= RB_VERBOSE;
921 str++;
922 }
923 continue;
924 }
925 str++;
926 }
927
928 if (type == KERNEL_TYPE_FREEBSD)
929 {
930 clval |= RB_BOOTINFO;
931
932 bi.bi_version = BOOTINFO_VERSION;
933
934 *arg = 0;
935 while ((--arg) > (char *) MB_CMDLINE_BUF && *arg != '/');
936 if (*arg == '/')
937 bi.bi_kernelname = arg + 1;
938 else
939 bi.bi_kernelname = 0;
940
941 bi.bi_nfs_diskless = 0;
942 bi.bi_n_bios_used = 0; /* this field is apparently unused */
943
944 for (i = 0; i < N_BIOS_GEOM; i++)
945 {
946 struct geometry geom;
947
948 /* XXX Should check the return value. */
949 get_diskinfo (i + 0x80, &geom);
950 /* FIXME: If HEADS or SECTORS is greater than 255, then this will
951 break the geometry information. That is a drawback of BSD
952 but not of GRUB. */
953 bi.bi_bios_geom[i] = (((geom.cylinders - 1) << 16)
954 + (((geom.heads - 1) & 0xff) << 8)
955 + (geom.sectors & 0xff));
956 }
957
958 bi.bi_size = sizeof (struct bootinfo);
959 bi.bi_memsizes_valid = 1;
960 bi.bi_bios_dev = saved_drive;
961 bi.bi_basemem = mbi.mem_lower;
962 bi.bi_extmem = extended_memory;
963
964 if (mbi.flags & MB_INFO_AOUT_SYMS)
965 {
966 bi.bi_symtab = mbi.syms.a.addr;
967 bi.bi_esymtab = mbi.syms.a.addr + 4
968 + mbi.syms.a.tabsize + mbi.syms.a.strsize;
969 }
970 #if 0
971 else if (mbi.flags & MB_INFO_ELF_SHDR)
972 {
973 /* FIXME: Should check if a symbol table exists and, if exists,
974 pass the table to BI. */
975 }
976 #endif
977 else
978 {
979 bi.bi_symtab = 0;
980 bi.bi_esymtab = 0;
981 }
982
983 /* call entry point */
984 (*entry_addr) (clval, bootdev, 0, 0, 0, ((int) (&bi)));
985 }
986 else
987 {
988 /*
989 * We now pass the various bootstrap parameters to the loaded
990 * image via the argument list.
991 *
992 * This is the official list:
993 *
994 * arg0 = 8 (magic)
995 * arg1 = boot flags
996 * arg2 = boot device
997 * arg3 = start of symbol table (0 if not loaded)
998 * arg4 = end of symbol table (0 if not loaded)
999 * arg5 = transfer address from image
1000 * arg6 = transfer address for next image pointer
1001 * arg7 = conventional memory size (640)
1002 * arg8 = extended memory size (8196)
1003 *
1004 * ...in actuality, we just pass the parameters used by the kernel.
1005 */
1006
1007 /* call entry point */
1008 unsigned long end_mark;
1009
1010 if (mbi.flags & MB_INFO_AOUT_SYMS)
1011 end_mark = (mbi.syms.a.addr + 4
1012 + mbi.syms.a.tabsize + mbi.syms.a.strsize);
1013 else
1014 /* FIXME: it should be mbi.syms.e.size. */
1015 end_mark = 0;
1016
1017 (*entry_addr) (clval, bootdev, 0, end_mark,
1018 extended_memory, mbi.mem_lower);
1019 }
1020 }
1021