2 * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 * You can also choose to distribute this program under the terms of
20 * the Unmodified Binary Distribution Licence (as given in the file
21 * COPYING.UBDL), provided that you have satisfied its requirements.
24 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
29 * Multiboot image format
37 #include <multiboot.h>
38 #include <ipxe/uaccess.h>
39 #include <ipxe/image.h>
40 #include <ipxe/segment.h>
43 #include <ipxe/init.h>
44 #include <ipxe/features.h>
46 #include <ipxe/version.h>
48 FEATURE ( FEATURE_IMAGE, "MBOOT", DHCP_EB_FEATURE_MULTIBOOT, 1 );
51 * Maximum number of modules we will allow for
53 * If this has bitten you: sorry. I did have a perfect scheme with a
54 * dynamically allocated list of modules on the protected-mode stack,
55 * but it was incompatible with some broken OSes that can only access
56 * low memory at boot time (even though we kindly set up 4GB flat
57 * physical addressing as per the multiboot specification.
63 * Maximum combined length of command lines
65 * Again; sorry. Some broken OSes zero out any non-base memory that
66 * isn't part of the loaded module set, so we can't just use
67 * virt_to_phys(cmdline) to point to the command lines, even though
68 * this would comply with the Multiboot spec.
70 #define MB_MAX_CMDLINE 512
72 /** Multiboot flags that we support */
73 #define MB_SUPPORTED_FLAGS ( MB_FLAG_PGALIGN | MB_FLAG_MEMMAP | \
74 MB_FLAG_VIDMODE | MB_FLAG_RAW )
76 /** Compulsory feature multiboot flags */
77 #define MB_COMPULSORY_FLAGS 0x0000ffff
79 /** Optional feature multiboot flags */
80 #define MB_OPTIONAL_FLAGS 0xffff0000
83 * Multiboot flags that we don't support
85 * We only care about the compulsory feature flags (bits 0-15); we are
86 * allowed to ignore the optional feature flags.
88 #define MB_UNSUPPORTED_FLAGS ( MB_COMPULSORY_FLAGS & ~MB_SUPPORTED_FLAGS )
90 /** A multiboot header descriptor */
91 struct multiboot_header_info {
92 /** The actual multiboot header */
93 struct multiboot_header mb;
94 /** Offset of header within the multiboot image */
98 /** Multiboot module command lines */
99 static char __bss16_array ( mb_cmdlines, [MB_MAX_CMDLINE] );
100 #define mb_cmdlines __use_data16 ( mb_cmdlines )
102 /** Offset within module command lines */
103 static unsigned int mb_cmdline_offset;
106 * Build multiboot memory map
108 * @v image Multiboot image
109 * @v mbinfo Multiboot information structure
110 * @v mbmemmap Multiboot memory map
111 * @v limit Maxmimum number of memory map entries
113 static void multiboot_build_memmap ( struct image *image,
114 struct multiboot_info *mbinfo,
115 struct multiboot_memory_map *mbmemmap,
116 unsigned int limit ) {
117 struct memory_map memmap;
121 get_memmap ( &memmap );
123 /* Translate into multiboot format */
124 memset ( mbmemmap, 0, sizeof ( *mbmemmap ) );
125 for ( i = 0 ; i < memmap.count ; i++ ) {
127 DBGC ( image, "MULTIBOOT %p limit of %d memmap "
128 "entries reached\n", image, limit );
131 mbmemmap[i].size = ( sizeof ( mbmemmap[i] ) -
132 sizeof ( mbmemmap[i].size ) );
133 mbmemmap[i].base_addr = memmap.regions[i].start;
134 mbmemmap[i].length = ( memmap.regions[i].end -
135 memmap.regions[i].start );
136 mbmemmap[i].type = MBMEM_RAM;
137 mbinfo->mmap_length += sizeof ( mbmemmap[i] );
138 if ( memmap.regions[i].start == 0 )
139 mbinfo->mem_lower = ( memmap.regions[i].end / 1024 );
140 if ( memmap.regions[i].start == 0x100000 )
141 mbinfo->mem_upper = ( ( memmap.regions[i].end -
147 * Add command line in base memory
150 * @ret physaddr Physical address of command line
152 static physaddr_t multiboot_add_cmdline ( struct image *image ) {
153 char *mb_cmdline = ( mb_cmdlines + mb_cmdline_offset );
154 size_t remaining = ( sizeof ( mb_cmdlines ) - mb_cmdline_offset );
155 char *buf = mb_cmdline;
158 /* Copy image URI to base memory buffer as start of command line */
159 len = ( format_uri ( image->uri, buf, remaining ) + 1 /* NUL */ );
160 if ( len > remaining )
162 mb_cmdline_offset += len;
166 /* Copy command line to base memory buffer, if present */
167 if ( image->cmdline ) {
168 mb_cmdline_offset--; /* Strip NUL */
171 len = ( snprintf ( buf, remaining, " %s",
172 image->cmdline ) + 1 /* NUL */ );
173 if ( len > remaining )
175 mb_cmdline_offset += len;
178 return virt_to_phys ( mb_cmdline );
182 * Add multiboot modules
184 * @v image Multiboot image
185 * @v start Start address for modules
186 * @v mbinfo Multiboot information structure
187 * @v modules Multiboot module list
188 * @ret rc Return status code
190 static int multiboot_add_modules ( struct image *image, physaddr_t start,
191 struct multiboot_info *mbinfo,
192 struct multiboot_module *modules,
193 unsigned int limit ) {
194 struct image *module_image;
195 struct multiboot_module *module;
198 /* Add each image as a multiboot module */
199 for_each_image ( module_image ) {
201 if ( mbinfo->mods_count >= limit ) {
202 DBGC ( image, "MULTIBOOT %p limit of %d modules "
203 "reached\n", image, limit );
207 /* Do not include kernel image itself as a module */
208 if ( module_image == image )
211 /* Page-align the module */
212 start = ( ( start + 0xfff ) & ~0xfff );
214 /* Prepare segment */
215 if ( ( rc = prep_segment ( phys_to_user ( start ),
217 module_image->len ) ) != 0 ) {
218 DBGC ( image, "MULTIBOOT %p could not prepare module "
219 "%s: %s\n", image, module_image->name,
225 memcpy_user ( phys_to_user ( start ), 0,
226 module_image->data, 0, module_image->len );
228 /* Add module to list */
229 module = &modules[mbinfo->mods_count++];
230 module->mod_start = start;
231 module->mod_end = ( start + module_image->len );
232 module->string = multiboot_add_cmdline ( module_image );
233 module->reserved = 0;
234 DBGC ( image, "MULTIBOOT %p module %s is [%x,%x)\n",
235 image, module_image->name, module->mod_start,
237 start += module_image->len;
244 * The multiboot information structure
246 * Kept in base memory because some OSes won't find it elsewhere,
247 * along with the other structures belonging to the Multiboot
250 static struct multiboot_info __bss16 ( mbinfo );
251 #define mbinfo __use_data16 ( mbinfo )
253 /** The multiboot bootloader name */
254 static char __bss16_array ( mb_bootloader_name, [32] );
255 #define mb_bootloader_name __use_data16 ( mb_bootloader_name )
257 /** The multiboot memory map */
258 static struct multiboot_memory_map
259 __bss16_array ( mbmemmap, [MAX_MEMORY_REGIONS] );
260 #define mbmemmap __use_data16 ( mbmemmap )
262 /** The multiboot module list */
263 static struct multiboot_module __bss16_array ( mbmodules, [MAX_MODULES] );
264 #define mbmodules __use_data16 ( mbmodules )
267 * Find multiboot header
269 * @v image Multiboot file
270 * @v hdr Multiboot header descriptor to fill in
271 * @ret rc Return status code
273 static int multiboot_find_header ( struct image *image,
274 struct multiboot_header_info *hdr ) {
277 unsigned int buf_idx;
280 /* Scan through first 8kB of image file 256 bytes at a time.
281 * (Use the buffering to avoid the overhead of a
282 * copy_from_user() for every dword.)
284 for ( offset = 0 ; offset < 8192 ; offset += sizeof ( buf[0] ) ) {
285 /* Check for end of image */
286 if ( offset > image->len )
288 /* Refill buffer if applicable */
289 buf_idx = ( ( offset % sizeof ( buf ) ) / sizeof ( buf[0] ) );
290 if ( buf_idx == 0 ) {
291 copy_from_user ( buf, image->data, offset,
294 /* Check signature */
295 if ( buf[buf_idx] != MULTIBOOT_HEADER_MAGIC )
297 /* Copy header and verify checksum */
298 copy_from_user ( &hdr->mb, image->data, offset,
299 sizeof ( hdr->mb ) );
300 checksum = ( hdr->mb.magic + hdr->mb.flags +
304 /* Record offset of multiboot header and return */
305 hdr->offset = offset;
309 /* No multiboot header found */
314 * Load raw multiboot image into memory
316 * @v image Multiboot file
317 * @v hdr Multiboot header descriptor
318 * @ret entry Entry point
319 * @ret max Maximum used address
320 * @ret rc Return status code
322 static int multiboot_load_raw ( struct image *image,
323 struct multiboot_header_info *hdr,
324 physaddr_t *entry, physaddr_t *max ) {
332 if ( ! ( hdr->mb.flags & MB_FLAG_RAW ) ) {
333 DBGC ( image, "MULTIBOOT %p is not flagged as a raw image\n",
338 /* Verify and prepare segment */
339 offset = ( hdr->offset - hdr->mb.header_addr + hdr->mb.load_addr );
340 filesz = ( hdr->mb.load_end_addr ?
341 ( hdr->mb.load_end_addr - hdr->mb.load_addr ) :
342 ( image->len - offset ) );
343 memsz = ( hdr->mb.bss_end_addr ?
344 ( hdr->mb.bss_end_addr - hdr->mb.load_addr ) : filesz );
345 buffer = phys_to_user ( hdr->mb.load_addr );
346 if ( ( rc = prep_segment ( buffer, filesz, memsz ) ) != 0 ) {
347 DBGC ( image, "MULTIBOOT %p could not prepare segment: %s\n",
348 image, strerror ( rc ) );
352 /* Copy image to segment */
353 memcpy_user ( buffer, 0, image->data, offset, filesz );
355 /* Record execution entry point and maximum used address */
356 *entry = hdr->mb.entry_addr;
357 *max = ( hdr->mb.load_addr + memsz );
363 * Load ELF multiboot image into memory
365 * @v image Multiboot file
366 * @ret entry Entry point
367 * @ret max Maximum used address
368 * @ret rc Return status code
370 static int multiboot_load_elf ( struct image *image, physaddr_t *entry,
375 if ( ( rc = elf_load ( image, entry, max ) ) != 0 ) {
376 DBGC ( image, "MULTIBOOT %p ELF image failed to load: %s\n",
377 image, strerror ( rc ) );
385 * Execute multiboot image
387 * @v image Multiboot image
388 * @ret rc Return status code
390 static int multiboot_exec ( struct image *image ) {
391 struct multiboot_header_info hdr;
396 /* Locate multiboot header, if present */
397 if ( ( rc = multiboot_find_header ( image, &hdr ) ) != 0 ) {
398 DBGC ( image, "MULTIBOOT %p has no multiboot header\n",
403 /* Abort if we detect flags that we cannot support */
404 if ( hdr.mb.flags & MB_UNSUPPORTED_FLAGS ) {
405 DBGC ( image, "MULTIBOOT %p flags %08x not supported\n",
406 image, ( hdr.mb.flags & MB_UNSUPPORTED_FLAGS ) );
410 /* There is technically a bit MB_FLAG_RAW to indicate whether
411 * this is an ELF or a raw image. In practice, grub will use
412 * the ELF header if present, and Solaris relies on this
415 if ( ( ( rc = multiboot_load_elf ( image, &entry, &max ) ) != 0 ) &&
416 ( ( rc = multiboot_load_raw ( image, &hdr, &entry, &max ) ) != 0 ))
419 /* Populate multiboot information structure */
420 memset ( &mbinfo, 0, sizeof ( mbinfo ) );
421 mbinfo.flags = ( MBI_FLAG_LOADER | MBI_FLAG_MEM | MBI_FLAG_MMAP |
422 MBI_FLAG_CMDLINE | MBI_FLAG_MODS );
423 mb_cmdline_offset = 0;
424 mbinfo.cmdline = multiboot_add_cmdline ( image );
425 mbinfo.mods_addr = virt_to_phys ( mbmodules );
426 mbinfo.mmap_addr = virt_to_phys ( mbmemmap );
427 snprintf ( mb_bootloader_name, sizeof ( mb_bootloader_name ),
428 "iPXE %s", product_version );
429 mbinfo.boot_loader_name = virt_to_phys ( mb_bootloader_name );
430 if ( ( rc = multiboot_add_modules ( image, max, &mbinfo, mbmodules,
431 ( sizeof ( mbmodules ) /
432 sizeof ( mbmodules[0] ) ) ) ) !=0)
435 /* Multiboot images may not return and have no callback
436 * interface, so shut everything down prior to booting the OS.
440 /* Build memory map after unhiding bootloader memory regions as part of
441 * shutting everything down.
443 multiboot_build_memmap ( image, &mbinfo, mbmemmap,
444 ( sizeof(mbmemmap) / sizeof(mbmemmap[0]) ) );
446 /* Jump to OS with flat physical addressing */
447 DBGC ( image, "MULTIBOOT %p starting execution at %lx\n",
449 __asm__ __volatile__ ( PHYS_CODE ( "pushl %%ebp\n\t"
452 : : "a" ( MULTIBOOT_BOOTLOADER_MAGIC ),
453 "b" ( virt_to_phys ( &mbinfo ) ),
455 : "ecx", "edx", "esi", "memory" );
457 DBGC ( image, "MULTIBOOT %p returned\n", image );
459 /* It isn't safe to continue after calling shutdown() */
462 return -ECANCELED; /* -EIMPOSSIBLE, anyone? */
466 * Probe multiboot image
468 * @v image Multiboot file
469 * @ret rc Return status code
471 static int multiboot_probe ( struct image *image ) {
472 struct multiboot_header_info hdr;
475 /* Locate multiboot header, if present */
476 if ( ( rc = multiboot_find_header ( image, &hdr ) ) != 0 ) {
477 DBGC ( image, "MULTIBOOT %p has no multiboot header\n",
481 DBGC ( image, "MULTIBOOT %p found header with flags %08x\n",
482 image, hdr.mb.flags );
487 /** Multiboot image type */
488 struct image_type multiboot_image_type __image_type ( PROBE_MULTIBOOT ) = {
490 .probe = multiboot_probe,
491 .exec = multiboot_exec,