boot.c revision 1
1N/A * GRUB -- GRand Unified Bootloader 1N/A * Copyright (C) 1999,2000,2001,2002,2003,2004 Free Software Foundation, Inc. 1N/A * This program is free software; you can redistribute it and/or modify 1N/A * it under the terms of the GNU General Public License as published by 1N/A * the Free Software Foundation; either version 2 of the License, or 1N/A * (at your option) any later version. 1N/A * This program is distributed in the hope that it will be useful, 1N/A * but WITHOUT ANY WARRANTY; without even the implied warranty of 1N/A * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1N/A * GNU General Public License for more details. 1N/A * You should have received a copy of the GNU General Public License 1N/A * along with this program; if not, write to the Free Software 1N/A * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 1N/A * The next two functions, 'load_image' and 'load_module', are the building 1N/A * blocks of the multiboot loader component. They handle essentially all 1N/A * of the gory details of loading in a bootable image and the modules. 1N/A /* presuming that MULTIBOOT_SEARCH is large enough to encompass an 1N/A executable header */ 1N/A /* sets the header pointer to point to the beginning of the 1N/A buffer by default */ 1N/A /* Use BUFFER as a linux kernel header, if the image is Linux zImage 1N/A /* ELF loading supported if multiboot, FreeBSD and NetBSD. */ 1N/A /* don't want to deal with ELF program header at some random 1N/A place in the file -- this generally won't happen */ 1N/A /* At the moment, there is no way to identify a NetBSD ELF 1N/A kernel, so rely on the suggested type by the user. */ 1N/A /* first offset into file */ 1N/A /* If the load end address is zero, load the whole contents. */ 1N/A /* If the bss end address is zero, assume that there is no bss area. */ 1N/A * If it doesn't have a Multiboot header, then presume 1N/A * it is either a FreeBSD or NetBSD executable. If so, 1N/A * then use a magic number of normal ordering, ZMAGIC to 1N/A * determine if it is FreeBSD. 1N/A * This is all because freebsd and netbsd seem to require 1N/A * masking out some address bits... differently for each 1N/A * one... plus of course we need to know which booting 1N/A /* first offset into file */ 1N/A /* Put the real mode part at as a high location as possible. */ 1N/A /* But it must not exceed the traditional area. */ 1N/A /* Your kernel is quite old... */ 1N/A /* If SETUP_SECTS is not set, set it to the default (4). */ 1N/A /* Video mode selection support. What a mess! */ 1N/A /* NOTE: Even the word "mess" is not still enough to 1N/A represent how wrong and bad the Linux video support is, 1N/A but I don't want to hear complaints from Linux fanatics 1N/A /* Find the substring "vga=". */ 1N/A /* Handle special strings. */ 1N/A /* ERRNUM is already set inside the function 1N/A safe_parse_maxint. */ 1N/A /* Check the mem= option to limit memory used for initrd. */ 1N/A /* If an overflow occurs, use the maximum address for 1N/A initrd instead. This is good, because MAXINT is 1N/A greater than LINUX_INITRD_MAX_ADDRESS. */ 1N/A /* Check an overflow. */ 1N/A /* It is possible that DATA_LEN + SECTOR_SIZE is greater than 1N/A MULTIBOOT_SEARCH, so the data may have been read partially. */ 1N/A /* Clear the heap space. */ 1N/A /* Copy command-line plus memory hack to staging area. 1N/A NOTE: Linux has a bug that it doesn't handle multiple spaces 1N/A between two options and a space after a "mem=" option isn't 1N/A removed correctly so the arguments to init could be like 1N/A {"init", "", "", NULL}. This affects some not-very-clever 1N/A shells. Thus, the code below does a trick to avoid the bug. 1N/A That is, copy "mem=XXX" to the end of the command-line, and 1N/A avoid to copy spaces unnecessarily. Hell. */ 1N/A /* Old Linux kernels have problems determining the amount of 1N/A the available memory. To work around this problem, we add 1N/A the "mem" option to the kernel command line. This has its 1N/A own drawbacks because newer kernels can determine the 1N/A memory map more accurately. Boot protocol 2.03, which 1N/A appeared in Linux 2.4.18, provides a pointer to the kernel 1N/A version string, so we could check it. But since kernel 1N/A 2.4.18 and newer are known to detect memory reliably, boot 1N/A protocol 2.03 already implies that the kernel is new 1N/A enough. The "mem" option is added if neither of the 1N/A following conditions is met: 1N/A 1) The "mem" option is already present. 1N/A 2) The "kernel" command is used with "--no-mem-option". 1N/A 3) GNU GRUB is configured not to pass the "mem" option. 1N/A 4) The kernel supports boot protocol 2.03 or newer. */ 1N/A /* offset into file */ 1N/A else /* no recognizable format */ 1N/A /* return if error */ 1N/A /* fill the multiboot info structure */ 1N/A /* read text, then read data */ 1N/A /* we have to align to a 4K boundary */ 1N/A /* we should align to a 4K boundary here for good measure */ 1N/A /* ELF executable */ 1N/A /* reset this to zero for now */ 1N/A /* scan for program segments */ 1N/A /* offset into file */ 1N/A /* If the memory range contains the entry address, get the 1N/A physical address here. */ 1N/A /* make sure we only load what we're supposed to! */ 1N/A /* mark memory as used */ 1N/A /* increment number of segments */ 1N/A /* load the segment */ 1N/A /* Load ELF symbols. */ 1N/A /* We should align to a 4K boundary here for good measure. */ 1N/A * Should not need to call RAW_ADDR; cur_addr is already 1N/A * adjusted to account for grub_scratch_mem. 1N/A * XXX Linux might calculate cur_addr differently. 1N/A /* This section is a loaded section, 1N/A so we don't care. */ 1N/A /* This section is empty, so we don't care. */ 1N/A /* Align the section to a sh_addralign bits boundary. */ 1N/A * Should not need to call RAW_ADDR; cur_addr is already 1N/A * adjusted to account for grub_scratch_mem. 1N/A * XXX Linux might calculate cur_addr differently. 1N/A /* If the entry address is physically different from that of the ELF 1N/A header, correct it here. */ 1N/A /* if we are supposed to load on 4K boundaries */ 1N/A /* these two simply need to be set if any modules are loaded at all */ 1N/A /* increment number of modules included */ 1N/A /* XXX: Linux 2.3.xx has a bug in the memory range check, so avoid 1N/A XXX: Linux 2.2.xx has a bug in the memory range check, which is 1N/A worse than that of Linux 2.3.xx, so avoid the last 64kb. *sigh* */ 1N/A /* FIXME: Should check if the kernel supports INITRD. */ 1N/A/* Dummy function to fake the *BSD boot. */ 1N/A * All "*_boot" commands depend on the images being loaded into memory 1N/A * correctly, the variables in this file being set up correctly, and 1N/A * the root partition being set in the 'saved_drive' and 'saved_partition' 1N/A /* XXX Should check the return value. */ 1N/A /* FIXME: If HEADS or SECTORS is greater than 255, then this will 1N/A break the geometry information. That is a drawback of BSD 1N/A /* FIXME: Should check if a symbol table exists and, if exists, 1N/A pass the table to BI. */ 1N/A /* call entry point */ 1N/A * We now pass the various bootstrap parameters to the loaded 1N/A * image via the argument list. 1N/A * This is the official list: 1N/A * arg2 = boot device 1N/A * arg3 = start of symbol table (0 if not loaded) 1N/A * arg4 = end of symbol table (0 if not loaded) 1N/A * arg5 = transfer address from image 1N/A * arg6 = transfer address for next image pointer 1N/A * arg7 = conventional memory size (640) 1N/A * arg8 = extended memory size (8196) 1N/A * ...in actuality, we just pass the parameters used by the kernel. 1N/A /* call entry point */