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 /*
673 * Should not need to call RAW_ADDR; cur_addr is already
674 * adjusted to account for grub_scratch_mem.
675 * XXX Linux might calculate cur_addr differently.
676 */
677 if (grub_read ((char *) (cur_addr), tab_size)
678 == tab_size)
679 {
680 mbi.syms.e.addr = cur_addr;
681 shdr = (Elf32_Shdr *) mbi.syms.e.addr;
682 cur_addr += tab_size;
683
684 printf (", shtab=0x%x", cur_addr);
685
686 for (i = 0; i < mbi.syms.e.num; i++)
687 {
688 /* This section is a loaded section,
689 so we don't care. */
690 if (shdr[i].sh_addr != 0)
691 continue;
692
693 /* This section is empty, so we don't care. */
694 if (shdr[i].sh_size == 0)
695 continue;
696
697 /* Align the section to a sh_addralign bits boundary. */
698 cur_addr = ((cur_addr + shdr[i].sh_addralign) &
699 - (int) shdr[i].sh_addralign);
700
701 grub_seek (shdr[i].sh_offset);
702
703 sec_size = shdr[i].sh_size;
704
705 /*
706 * Should not need to call RAW_ADDR; cur_addr is already
707 * adjusted to account for grub_scratch_mem.
708 * XXX Linux might calculate cur_addr differently.
709 */
710 if (! (memcheck (cur_addr, sec_size)
711 && (grub_read ((char *) (cur_addr),
712 sec_size)
713 == sec_size)))
714 {
715 symtab_err = 1;
716 break;
717 }
718
719 shdr[i].sh_addr = cur_addr;
720 cur_addr += sec_size;
721 }
722 }
723 else
724 symtab_err = 1;
725
726 if (mbi.syms.e.addr < RAW_ADDR(0x10000))
727 symtab_err = 1;
728
729 if (symtab_err)
730 {
731 printf ("(bad)");
732 mbi.syms.e.num = 0;
733 mbi.syms.e.size = 0;
734 mbi.syms.e.addr = 0;
735 mbi.syms.e.shndx = 0;
736 cur_addr = 0;
737 }
738 else
739 mbi.flags |= MB_INFO_ELF_SHDR;
740 }
741 }
742 }
743
744 if (! errnum)
745 {
746 grub_printf (", entry=0x%x]\n", (unsigned) entry_addr);
747
748 /* If the entry address is physically different from that of the ELF
749 header, correct it here. */
750 if (real_entry_addr)
751 entry_addr = real_entry_addr;
752 }
753 else
754 {
755 putchar ('\n');
756 type = KERNEL_TYPE_NONE;
757 }
758
759 grub_close ();
760
761 /* Sanity check. */
762 if (suggested_type != KERNEL_TYPE_NONE && suggested_type != type)
763 {
764 errnum = ERR_EXEC_FORMAT;
765 return KERNEL_TYPE_NONE;
766 }
767
768 return type;
769 }
770
771 int
load_module(char * module,char * arg)772 load_module (char *module, char *arg)
773 {
774 int len;
775
776 /* if we are supposed to load on 4K boundaries */
777 cur_addr = (cur_addr + 0xFFF) & 0xFFFFF000;
778
779 if (!grub_open (module))
780 return 0;
781
782 len = grub_read ((char *) cur_addr, -1);
783 if (! len)
784 {
785 grub_close ();
786 return 0;
787 }
788
789 printf (" [Multiboot-module @ 0x%x, 0x%x bytes]\n", cur_addr, len);
790
791 /* these two simply need to be set if any modules are loaded at all */
792 mbi.flags |= MB_INFO_MODS;
793 mbi.mods_addr = (int) mll;
794
795 mll[mbi.mods_count].cmdline = (int) arg;
796 mll[mbi.mods_count].mod_start = cur_addr;
797 cur_addr += len;
798 mll[mbi.mods_count].mod_end = cur_addr;
799 mll[mbi.mods_count].pad = 0;
800
801 /* increment number of modules included */
802 mbi.mods_count++;
803
804 grub_close ();
805 return 1;
806 }
807
808 int
load_initrd(char * initrd)809 load_initrd (char *initrd)
810 {
811 int len;
812 unsigned long moveto;
813 unsigned long max_addr;
814 struct linux_kernel_header *lh
815 = (struct linux_kernel_header *) (cur_addr - LINUX_SETUP_MOVE_SIZE);
816
817 #ifndef NO_DECOMPRESSION
818 no_decompression = 1;
819 #endif
820
821 if (! grub_open (initrd))
822 goto fail;
823
824 len = grub_read ((char *) cur_addr, -1);
825 if (! len)
826 {
827 grub_close ();
828 goto fail;
829 }
830
831 if (linux_mem_size)
832 moveto = linux_mem_size;
833 else
834 moveto = (mbi.mem_upper + 0x400) << 10;
835
836 moveto = (moveto - len) & 0xfffff000;
837 max_addr = (lh->header == LINUX_MAGIC_SIGNATURE && lh->version >= 0x0203
838 ? lh->initrd_addr_max : LINUX_INITRD_MAX_ADDRESS);
839 if (moveto + len >= max_addr)
840 moveto = (max_addr - len) & 0xfffff000;
841
842 /* XXX: Linux 2.3.xx has a bug in the memory range check, so avoid
843 the last page.
844 XXX: Linux 2.2.xx has a bug in the memory range check, which is
845 worse than that of Linux 2.3.xx, so avoid the last 64kb. *sigh* */
846 moveto -= 0x10000;
847 memmove ((void *) RAW_ADDR (moveto), (void *) cur_addr, len);
848
849 printf (" [Linux-initrd @ 0x%x, 0x%x bytes]\n", moveto, len);
850
851 /* FIXME: Should check if the kernel supports INITRD. */
852 lh->ramdisk_image = RAW_ADDR (moveto);
853 lh->ramdisk_size = len;
854
855 grub_close ();
856
857 fail:
858
859 #ifndef NO_DECOMPRESSION
860 no_decompression = 0;
861 #endif
862
863 return ! errnum;
864 }
865
866
867 #ifdef GRUB_UTIL
868 /* Dummy function to fake the *BSD boot. */
869 static void
bsd_boot_entry(int flags,int bootdev,int sym_start,int sym_end,int mem_upper,int mem_lower)870 bsd_boot_entry (int flags, int bootdev, int sym_start, int sym_end,
871 int mem_upper, int mem_lower)
872 {
873 stop ();
874 }
875 #endif
876
877
878 /*
879 * All "*_boot" commands depend on the images being loaded into memory
880 * correctly, the variables in this file being set up correctly, and
881 * the root partition being set in the 'saved_drive' and 'saved_partition'
882 * variables.
883 */
884
885
886 void
bsd_boot(kernel_t type,int bootdev,char * arg)887 bsd_boot (kernel_t type, int bootdev, char *arg)
888 {
889 char *str;
890 int clval = 0, i;
891 struct bootinfo bi;
892
893 #ifdef GRUB_UTIL
894 entry_addr = (entry_func) bsd_boot_entry;
895 #else
896 stop_floppy ();
897 #endif
898
899 while (*(++arg) && *arg != ' ');
900 str = arg;
901 while (*str)
902 {
903 if (*str == '-')
904 {
905 while (*str && *str != ' ')
906 {
907 if (*str == 'C')
908 clval |= RB_CDROM;
909 if (*str == 'a')
910 clval |= RB_ASKNAME;
911 if (*str == 'b')
912 clval |= RB_HALT;
913 if (*str == 'c')
914 clval |= RB_CONFIG;
915 if (*str == 'd')
916 clval |= RB_KDB;
917 if (*str == 'D')
918 clval |= RB_MULTIPLE;
919 if (*str == 'g')
920 clval |= RB_GDB;
921 if (*str == 'h')
922 clval |= RB_SERIAL;
923 if (*str == 'm')
924 clval |= RB_MUTE;
925 if (*str == 'r')
926 clval |= RB_DFLTROOT;
927 if (*str == 's')
928 clval |= RB_SINGLE;
929 if (*str == 'v')
930 clval |= RB_VERBOSE;
931 str++;
932 }
933 continue;
934 }
935 str++;
936 }
937
938 if (type == KERNEL_TYPE_FREEBSD)
939 {
940 clval |= RB_BOOTINFO;
941
942 bi.bi_version = BOOTINFO_VERSION;
943
944 *arg = 0;
945 while ((--arg) > (char *) MB_CMDLINE_BUF && *arg != '/');
946 if (*arg == '/')
947 bi.bi_kernelname = arg + 1;
948 else
949 bi.bi_kernelname = 0;
950
951 bi.bi_nfs_diskless = 0;
952 bi.bi_n_bios_used = 0; /* this field is apparently unused */
953
954 for (i = 0; i < N_BIOS_GEOM; i++)
955 {
956 struct geometry geom;
957
958 /* XXX Should check the return value. */
959 get_diskinfo (i + 0x80, &geom);
960 /* FIXME: If HEADS or SECTORS is greater than 255, then this will
961 break the geometry information. That is a drawback of BSD
962 but not of GRUB. */
963 bi.bi_bios_geom[i] = (((geom.cylinders - 1) << 16)
964 + (((geom.heads - 1) & 0xff) << 8)
965 + (geom.sectors & 0xff));
966 }
967
968 bi.bi_size = sizeof (struct bootinfo);
969 bi.bi_memsizes_valid = 1;
970 bi.bi_bios_dev = saved_drive;
971 bi.bi_basemem = mbi.mem_lower;
972 bi.bi_extmem = extended_memory;
973
974 if (mbi.flags & MB_INFO_AOUT_SYMS)
975 {
976 bi.bi_symtab = mbi.syms.a.addr;
977 bi.bi_esymtab = mbi.syms.a.addr + 4
978 + mbi.syms.a.tabsize + mbi.syms.a.strsize;
979 }
980 #if 0
981 else if (mbi.flags & MB_INFO_ELF_SHDR)
982 {
983 /* FIXME: Should check if a symbol table exists and, if exists,
984 pass the table to BI. */
985 }
986 #endif
987 else
988 {
989 bi.bi_symtab = 0;
990 bi.bi_esymtab = 0;
991 }
992
993 /* call entry point */
994 (*entry_addr) (clval, bootdev, 0, 0, 0, ((int) (&bi)));
995 }
996 else
997 {
998 /*
999 * We now pass the various bootstrap parameters to the loaded
1000 * image via the argument list.
1001 *
1002 * This is the official list:
1003 *
1004 * arg0 = 8 (magic)
1005 * arg1 = boot flags
1006 * arg2 = boot device
1007 * arg3 = start of symbol table (0 if not loaded)
1008 * arg4 = end of symbol table (0 if not loaded)
1009 * arg5 = transfer address from image
1010 * arg6 = transfer address for next image pointer
1011 * arg7 = conventional memory size (640)
1012 * arg8 = extended memory size (8196)
1013 *
1014 * ...in actuality, we just pass the parameters used by the kernel.
1015 */
1016
1017 /* call entry point */
1018 unsigned long end_mark;
1019
1020 if (mbi.flags & MB_INFO_AOUT_SYMS)
1021 end_mark = (mbi.syms.a.addr + 4
1022 + mbi.syms.a.tabsize + mbi.syms.a.strsize);
1023 else
1024 /* FIXME: it should be mbi.syms.e.size. */
1025 end_mark = 0;
1026
1027 (*entry_addr) (clval, bootdev, 0, end_mark,
1028 extended_memory, mbi.mem_lower);
1029 }
1030 }
1031