These changes are the raw update to qemu-2.6.
[kvmfornfv.git] / qemu / roms / ipxe / src / arch / i386 / image / multiboot.c
1 /*
2  * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
3  *
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.
8  *
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.
13  *
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
17  * 02110-1301, USA.
18  *
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.
22  */
23
24 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25
26 /**
27  * @file
28  *
29  * Multiboot image format
30  *
31  */
32
33 #include <stdio.h>
34 #include <errno.h>
35 #include <assert.h>
36 #include <realmode.h>
37 #include <multiboot.h>
38 #include <ipxe/uaccess.h>
39 #include <ipxe/image.h>
40 #include <ipxe/segment.h>
41 #include <ipxe/io.h>
42 #include <ipxe/elf.h>
43 #include <ipxe/init.h>
44 #include <ipxe/features.h>
45 #include <ipxe/uri.h>
46 #include <ipxe/version.h>
47
48 FEATURE ( FEATURE_IMAGE, "MBOOT", DHCP_EB_FEATURE_MULTIBOOT, 1 );
49
50 /**
51  * Maximum number of modules we will allow for
52  *
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.
58  *
59  */
60 #define MAX_MODULES 8
61
62 /**
63  * Maximum combined length of command lines
64  *
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.
69  */
70 #define MB_MAX_CMDLINE 512
71
72 /** Multiboot flags that we support */
73 #define MB_SUPPORTED_FLAGS ( MB_FLAG_PGALIGN | MB_FLAG_MEMMAP | \
74                              MB_FLAG_VIDMODE | MB_FLAG_RAW )
75
76 /** Compulsory feature multiboot flags */
77 #define MB_COMPULSORY_FLAGS 0x0000ffff
78
79 /** Optional feature multiboot flags */
80 #define MB_OPTIONAL_FLAGS 0xffff0000
81
82 /**
83  * Multiboot flags that we don't support
84  *
85  * We only care about the compulsory feature flags (bits 0-15); we are
86  * allowed to ignore the optional feature flags.
87  */
88 #define MB_UNSUPPORTED_FLAGS ( MB_COMPULSORY_FLAGS & ~MB_SUPPORTED_FLAGS )
89
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 */
95         size_t offset;
96 };
97
98 /** Multiboot module command lines */
99 static char __bss16_array ( mb_cmdlines, [MB_MAX_CMDLINE] );
100 #define mb_cmdlines __use_data16 ( mb_cmdlines )
101
102 /** Offset within module command lines */
103 static unsigned int mb_cmdline_offset;
104
105 /**
106  * Build multiboot memory map
107  *
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
112  */
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;
118         unsigned int i;
119
120         /* Get memory map */
121         get_memmap ( &memmap );
122
123         /* Translate into multiboot format */
124         memset ( mbmemmap, 0, sizeof ( *mbmemmap ) );
125         for ( i = 0 ; i < memmap.count ; i++ ) {
126                 if ( i >= limit ) {
127                         DBGC ( image, "MULTIBOOT %p limit of %d memmap "
128                                "entries reached\n", image, limit );
129                         break;
130                 }
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 -
142                                                 0x100000 ) / 1024 );
143         }
144 }
145
146 /**
147  * Add command line in base memory
148  *
149  * @v image             Image
150  * @ret physaddr        Physical address of command line
151  */
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;
156         size_t len;
157
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 )
161                 len = remaining;
162         mb_cmdline_offset += len;
163         buf += len;
164         remaining -= len;
165
166         /* Copy command line to base memory buffer, if present */
167         if ( image->cmdline ) {
168                 mb_cmdline_offset--; /* Strip NUL */
169                 buf--;
170                 remaining++;
171                 len = ( snprintf ( buf, remaining, " %s",
172                                    image->cmdline ) + 1 /* NUL */ );
173                 if ( len > remaining )
174                         len = remaining;
175                 mb_cmdline_offset += len;
176         }
177
178         return virt_to_phys ( mb_cmdline );
179 }
180
181 /**
182  * Add multiboot modules
183  *
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
189  */
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;
196         int rc;
197
198         /* Add each image as a multiboot module */
199         for_each_image ( module_image ) {
200
201                 if ( mbinfo->mods_count >= limit ) {
202                         DBGC ( image, "MULTIBOOT %p limit of %d modules "
203                                "reached\n", image, limit );
204                         break;
205                 }
206
207                 /* Do not include kernel image itself as a module */
208                 if ( module_image == image )
209                         continue;
210
211                 /* Page-align the module */
212                 start = ( ( start + 0xfff ) & ~0xfff );
213
214                 /* Prepare segment */
215                 if ( ( rc = prep_segment ( phys_to_user ( start ),
216                                            module_image->len,
217                                            module_image->len ) ) != 0 ) {
218                         DBGC ( image, "MULTIBOOT %p could not prepare module "
219                                "%s: %s\n", image, module_image->name,
220                                strerror ( rc ) );
221                         return rc;
222                 }
223
224                 /* Copy module */
225                 memcpy_user ( phys_to_user ( start ), 0,
226                               module_image->data, 0, module_image->len );
227
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,
236                        module->mod_end );
237                 start += module_image->len;
238         }
239
240         return 0;
241 }
242
243 /**
244  * The multiboot information structure
245  *
246  * Kept in base memory because some OSes won't find it elsewhere,
247  * along with the other structures belonging to the Multiboot
248  * information table.
249  */
250 static struct multiboot_info __bss16 ( mbinfo );
251 #define mbinfo __use_data16 ( mbinfo )
252
253 /** The multiboot bootloader name */
254 static char __bss16_array ( mb_bootloader_name, [32] );
255 #define mb_bootloader_name __use_data16 ( mb_bootloader_name )
256
257 /** The multiboot memory map */
258 static struct multiboot_memory_map
259         __bss16_array ( mbmemmap, [MAX_MEMORY_REGIONS] );
260 #define mbmemmap __use_data16 ( mbmemmap )
261
262 /** The multiboot module list */
263 static struct multiboot_module __bss16_array ( mbmodules, [MAX_MODULES] );
264 #define mbmodules __use_data16 ( mbmodules )
265
266 /**
267  * Find multiboot header
268  *
269  * @v image             Multiboot file
270  * @v hdr               Multiboot header descriptor to fill in
271  * @ret rc              Return status code
272  */
273 static int multiboot_find_header ( struct image *image,
274                                    struct multiboot_header_info *hdr ) {
275         uint32_t buf[64];
276         size_t offset;
277         unsigned int buf_idx;
278         uint32_t checksum;
279
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.)
283          */
284         for ( offset = 0 ; offset < 8192 ; offset += sizeof ( buf[0] ) ) {
285                 /* Check for end of image */
286                 if ( offset > image->len )
287                         break;
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,
292                                          sizeof ( buf ) );
293                 }
294                 /* Check signature */
295                 if ( buf[buf_idx] != MULTIBOOT_HEADER_MAGIC )
296                         continue;
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 +
301                              hdr->mb.checksum );
302                 if ( checksum != 0 )
303                         continue;
304                 /* Record offset of multiboot header and return */
305                 hdr->offset = offset;
306                 return 0;
307         }
308
309         /* No multiboot header found */
310         return -ENOEXEC;
311 }
312
313 /**
314  * Load raw multiboot image into memory
315  *
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
321  */
322 static int multiboot_load_raw ( struct image *image,
323                                 struct multiboot_header_info *hdr,
324                                 physaddr_t *entry, physaddr_t *max ) {
325         size_t offset;
326         size_t filesz;
327         size_t memsz;
328         userptr_t buffer;
329         int rc;
330
331         /* Sanity check */
332         if ( ! ( hdr->mb.flags & MB_FLAG_RAW ) ) {
333                 DBGC ( image, "MULTIBOOT %p is not flagged as a raw image\n",
334                        image );
335                 return -EINVAL;
336         }
337
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 ) );
349                 return rc;
350         }
351
352         /* Copy image to segment */
353         memcpy_user ( buffer, 0, image->data, offset, filesz );
354
355         /* Record execution entry point and maximum used address */
356         *entry = hdr->mb.entry_addr;
357         *max = ( hdr->mb.load_addr + memsz );
358
359         return 0;
360 }
361
362 /**
363  * Load ELF multiboot image into memory
364  *
365  * @v image             Multiboot file
366  * @ret entry           Entry point
367  * @ret max             Maximum used address
368  * @ret rc              Return status code
369  */
370 static int multiboot_load_elf ( struct image *image, physaddr_t *entry,
371                                 physaddr_t *max ) {
372         int rc;
373
374         /* Load ELF image*/
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 ) );
378                 return rc;
379         }
380
381         return 0;
382 }
383
384 /**
385  * Execute multiboot image
386  *
387  * @v image             Multiboot image
388  * @ret rc              Return status code
389  */
390 static int multiboot_exec ( struct image *image ) {
391         struct multiboot_header_info hdr;
392         physaddr_t entry;
393         physaddr_t max;
394         int rc;
395
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",
399                        image );
400                 return rc;
401         }
402
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 ) );
407                 return -ENOTSUP;
408         }
409
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
413          * behaviour.
414          */
415         if ( ( ( rc = multiboot_load_elf ( image, &entry, &max ) ) != 0 ) &&
416              ( ( rc = multiboot_load_raw ( image, &hdr, &entry, &max ) ) != 0 ))
417                 return rc;
418
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)
433                 return rc;
434
435         /* Multiboot images may not return and have no callback
436          * interface, so shut everything down prior to booting the OS.
437          */
438         shutdown_boot();
439
440         /* Build memory map after unhiding bootloader memory regions as part of
441          * shutting everything down.
442          */
443         multiboot_build_memmap ( image, &mbinfo, mbmemmap,
444                                  ( sizeof(mbmemmap) / sizeof(mbmemmap[0]) ) );
445
446         /* Jump to OS with flat physical addressing */
447         DBGC ( image, "MULTIBOOT %p starting execution at %lx\n",
448                image, entry );
449         __asm__ __volatile__ ( PHYS_CODE ( "pushl %%ebp\n\t"
450                                            "call *%%edi\n\t"
451                                            "popl %%ebp\n\t" )
452                                : : "a" ( MULTIBOOT_BOOTLOADER_MAGIC ),
453                                    "b" ( virt_to_phys ( &mbinfo ) ),
454                                    "D" ( entry )
455                                : "ecx", "edx", "esi", "memory" );
456
457         DBGC ( image, "MULTIBOOT %p returned\n", image );
458
459         /* It isn't safe to continue after calling shutdown() */
460         while ( 1 ) {}
461
462         return -ECANCELED;  /* -EIMPOSSIBLE, anyone? */
463 }
464
465 /**
466  * Probe multiboot image
467  *
468  * @v image             Multiboot file
469  * @ret rc              Return status code
470  */
471 static int multiboot_probe ( struct image *image ) {
472         struct multiboot_header_info hdr;
473         int rc;
474
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",
478                        image );
479                 return rc;
480         }
481         DBGC ( image, "MULTIBOOT %p found header with flags %08x\n",
482                image, hdr.mb.flags );
483
484         return 0;
485 }
486
487 /** Multiboot image type */
488 struct image_type multiboot_image_type __image_type ( PROBE_MULTIBOOT ) = {
489         .name = "Multiboot",
490         .probe = multiboot_probe,
491         .exec = multiboot_exec,
492 };