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 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 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 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 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 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