Add qemu 2.4.0
[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
20 FILE_LICENCE ( GPL2_OR_LATER );
21
22 /**
23  * @file
24  *
25  * Multiboot image format
26  *
27  */
28
29 #include <stdio.h>
30 #include <errno.h>
31 #include <assert.h>
32 #include <realmode.h>
33 #include <multiboot.h>
34 #include <ipxe/uaccess.h>
35 #include <ipxe/image.h>
36 #include <ipxe/segment.h>
37 #include <ipxe/io.h>
38 #include <ipxe/elf.h>
39 #include <ipxe/init.h>
40 #include <ipxe/features.h>
41 #include <ipxe/uri.h>
42 #include <ipxe/version.h>
43
44 FEATURE ( FEATURE_IMAGE, "MBOOT", DHCP_EB_FEATURE_MULTIBOOT, 1 );
45
46 /**
47  * Maximum number of modules we will allow for
48  *
49  * If this has bitten you: sorry.  I did have a perfect scheme with a
50  * dynamically allocated list of modules on the protected-mode stack,
51  * but it was incompatible with some broken OSes that can only access
52  * low memory at boot time (even though we kindly set up 4GB flat
53  * physical addressing as per the multiboot specification.
54  *
55  */
56 #define MAX_MODULES 8
57
58 /**
59  * Maximum combined length of command lines
60  *
61  * Again; sorry.  Some broken OSes zero out any non-base memory that
62  * isn't part of the loaded module set, so we can't just use
63  * virt_to_phys(cmdline) to point to the command lines, even though
64  * this would comply with the Multiboot spec.
65  */
66 #define MB_MAX_CMDLINE 512
67
68 /** Multiboot flags that we support */
69 #define MB_SUPPORTED_FLAGS ( MB_FLAG_PGALIGN | MB_FLAG_MEMMAP | \
70                              MB_FLAG_VIDMODE | MB_FLAG_RAW )
71
72 /** Compulsory feature multiboot flags */
73 #define MB_COMPULSORY_FLAGS 0x0000ffff
74
75 /** Optional feature multiboot flags */
76 #define MB_OPTIONAL_FLAGS 0xffff0000
77
78 /**
79  * Multiboot flags that we don't support
80  *
81  * We only care about the compulsory feature flags (bits 0-15); we are
82  * allowed to ignore the optional feature flags.
83  */
84 #define MB_UNSUPPORTED_FLAGS ( MB_COMPULSORY_FLAGS & ~MB_SUPPORTED_FLAGS )
85
86 /** A multiboot header descriptor */
87 struct multiboot_header_info {
88         /** The actual multiboot header */
89         struct multiboot_header mb;
90         /** Offset of header within the multiboot image */
91         size_t offset;
92 };
93
94 /** Multiboot module command lines */
95 static char __bss16_array ( mb_cmdlines, [MB_MAX_CMDLINE] );
96 #define mb_cmdlines __use_data16 ( mb_cmdlines )
97
98 /** Offset within module command lines */
99 static unsigned int mb_cmdline_offset;
100
101 /**
102  * Build multiboot memory map
103  *
104  * @v image             Multiboot image
105  * @v mbinfo            Multiboot information structure
106  * @v mbmemmap          Multiboot memory map
107  * @v limit             Maxmimum number of memory map entries
108  */
109 static void multiboot_build_memmap ( struct image *image,
110                                      struct multiboot_info *mbinfo,
111                                      struct multiboot_memory_map *mbmemmap,
112                                      unsigned int limit ) {
113         struct memory_map memmap;
114         unsigned int i;
115
116         /* Get memory map */
117         get_memmap ( &memmap );
118
119         /* Translate into multiboot format */
120         memset ( mbmemmap, 0, sizeof ( *mbmemmap ) );
121         for ( i = 0 ; i < memmap.count ; i++ ) {
122                 if ( i >= limit ) {
123                         DBGC ( image, "MULTIBOOT %p limit of %d memmap "
124                                "entries reached\n", image, limit );
125                         break;
126                 }
127                 mbmemmap[i].size = ( sizeof ( mbmemmap[i] ) -
128                                      sizeof ( mbmemmap[i].size ) );
129                 mbmemmap[i].base_addr = memmap.regions[i].start;
130                 mbmemmap[i].length = ( memmap.regions[i].end -
131                                        memmap.regions[i].start );
132                 mbmemmap[i].type = MBMEM_RAM;
133                 mbinfo->mmap_length += sizeof ( mbmemmap[i] );
134                 if ( memmap.regions[i].start == 0 )
135                         mbinfo->mem_lower = ( memmap.regions[i].end / 1024 );
136                 if ( memmap.regions[i].start == 0x100000 )
137                         mbinfo->mem_upper = ( ( memmap.regions[i].end -
138                                                 0x100000 ) / 1024 );
139         }
140 }
141
142 /**
143  * Add command line in base memory
144  *
145  * @v image             Image
146  * @ret physaddr        Physical address of command line
147  */
148 static physaddr_t multiboot_add_cmdline ( struct image *image ) {
149         char *mb_cmdline = ( mb_cmdlines + mb_cmdline_offset );
150         size_t remaining = ( sizeof ( mb_cmdlines ) - mb_cmdline_offset );
151         char *buf = mb_cmdline;
152         size_t len;
153
154         /* Copy image URI to base memory buffer as start of command line */
155         len = ( format_uri ( image->uri, buf, remaining ) + 1 /* NUL */ );
156         if ( len > remaining )
157                 len = remaining;
158         mb_cmdline_offset += len;
159         buf += len;
160         remaining -= len;
161
162         /* Copy command line to base memory buffer, if present */
163         if ( image->cmdline ) {
164                 mb_cmdline_offset--; /* Strip NUL */
165                 buf--;
166                 remaining++;
167                 len = ( snprintf ( buf, remaining, " %s",
168                                    image->cmdline ) + 1 /* NUL */ );
169                 if ( len > remaining )
170                         len = remaining;
171                 mb_cmdline_offset += len;
172         }
173
174         return virt_to_phys ( mb_cmdline );
175 }
176
177 /**
178  * Add multiboot modules
179  *
180  * @v image             Multiboot image
181  * @v start             Start address for modules
182  * @v mbinfo            Multiboot information structure
183  * @v modules           Multiboot module list
184  * @ret rc              Return status code
185  */
186 static int multiboot_add_modules ( struct image *image, physaddr_t start,
187                                    struct multiboot_info *mbinfo,
188                                    struct multiboot_module *modules,
189                                    unsigned int limit ) {
190         struct image *module_image;
191         struct multiboot_module *module;
192         int rc;
193
194         /* Add each image as a multiboot module */
195         for_each_image ( module_image ) {
196
197                 if ( mbinfo->mods_count >= limit ) {
198                         DBGC ( image, "MULTIBOOT %p limit of %d modules "
199                                "reached\n", image, limit );
200                         break;
201                 }
202
203                 /* Do not include kernel image itself as a module */
204                 if ( module_image == image )
205                         continue;
206
207                 /* Page-align the module */
208                 start = ( ( start + 0xfff ) & ~0xfff );
209
210                 /* Prepare segment */
211                 if ( ( rc = prep_segment ( phys_to_user ( start ),
212                                            module_image->len,
213                                            module_image->len ) ) != 0 ) {
214                         DBGC ( image, "MULTIBOOT %p could not prepare module "
215                                "%s: %s\n", image, module_image->name,
216                                strerror ( rc ) );
217                         return rc;
218                 }
219
220                 /* Copy module */
221                 memcpy_user ( phys_to_user ( start ), 0,
222                               module_image->data, 0, module_image->len );
223
224                 /* Add module to list */
225                 module = &modules[mbinfo->mods_count++];
226                 module->mod_start = start;
227                 module->mod_end = ( start + module_image->len );
228                 module->string = multiboot_add_cmdline ( module_image );
229                 module->reserved = 0;
230                 DBGC ( image, "MULTIBOOT %p module %s is [%x,%x)\n",
231                        image, module_image->name, module->mod_start,
232                        module->mod_end );
233                 start += module_image->len;
234         }
235
236         return 0;
237 }
238
239 /**
240  * The multiboot information structure
241  *
242  * Kept in base memory because some OSes won't find it elsewhere,
243  * along with the other structures belonging to the Multiboot
244  * information table.
245  */
246 static struct multiboot_info __bss16 ( mbinfo );
247 #define mbinfo __use_data16 ( mbinfo )
248
249 /** The multiboot bootloader name */
250 static char __bss16_array ( mb_bootloader_name, [32] );
251 #define mb_bootloader_name __use_data16 ( mb_bootloader_name )
252
253 /** The multiboot memory map */
254 static struct multiboot_memory_map
255         __bss16_array ( mbmemmap, [MAX_MEMORY_REGIONS] );
256 #define mbmemmap __use_data16 ( mbmemmap )
257
258 /** The multiboot module list */
259 static struct multiboot_module __bss16_array ( mbmodules, [MAX_MODULES] );
260 #define mbmodules __use_data16 ( mbmodules )
261
262 /**
263  * Find multiboot header
264  *
265  * @v image             Multiboot file
266  * @v hdr               Multiboot header descriptor to fill in
267  * @ret rc              Return status code
268  */
269 static int multiboot_find_header ( struct image *image,
270                                    struct multiboot_header_info *hdr ) {
271         uint32_t buf[64];
272         size_t offset;
273         unsigned int buf_idx;
274         uint32_t checksum;
275
276         /* Scan through first 8kB of image file 256 bytes at a time.
277          * (Use the buffering to avoid the overhead of a
278          * copy_from_user() for every dword.)
279          */
280         for ( offset = 0 ; offset < 8192 ; offset += sizeof ( buf[0] ) ) {
281                 /* Check for end of image */
282                 if ( offset > image->len )
283                         break;
284                 /* Refill buffer if applicable */
285                 buf_idx = ( ( offset % sizeof ( buf ) ) / sizeof ( buf[0] ) );
286                 if ( buf_idx == 0 ) {
287                         copy_from_user ( buf, image->data, offset,
288                                          sizeof ( buf ) );
289                 }
290                 /* Check signature */
291                 if ( buf[buf_idx] != MULTIBOOT_HEADER_MAGIC )
292                         continue;
293                 /* Copy header and verify checksum */
294                 copy_from_user ( &hdr->mb, image->data, offset,
295                                  sizeof ( hdr->mb ) );
296                 checksum = ( hdr->mb.magic + hdr->mb.flags +
297                              hdr->mb.checksum );
298                 if ( checksum != 0 )
299                         continue;
300                 /* Record offset of multiboot header and return */
301                 hdr->offset = offset;
302                 return 0;
303         }
304
305         /* No multiboot header found */
306         return -ENOEXEC;
307 }
308
309 /**
310  * Load raw multiboot image into memory
311  *
312  * @v image             Multiboot file
313  * @v hdr               Multiboot header descriptor
314  * @ret entry           Entry point
315  * @ret max             Maximum used address
316  * @ret rc              Return status code
317  */
318 static int multiboot_load_raw ( struct image *image,
319                                 struct multiboot_header_info *hdr,
320                                 physaddr_t *entry, physaddr_t *max ) {
321         size_t offset;
322         size_t filesz;
323         size_t memsz;
324         userptr_t buffer;
325         int rc;
326
327         /* Sanity check */
328         if ( ! ( hdr->mb.flags & MB_FLAG_RAW ) ) {
329                 DBGC ( image, "MULTIBOOT %p is not flagged as a raw image\n",
330                        image );
331                 return -EINVAL;
332         }
333
334         /* Verify and prepare segment */
335         offset = ( hdr->offset - hdr->mb.header_addr + hdr->mb.load_addr );
336         filesz = ( hdr->mb.load_end_addr ?
337                    ( hdr->mb.load_end_addr - hdr->mb.load_addr ) :
338                    ( image->len - offset ) );
339         memsz = ( hdr->mb.bss_end_addr ?
340                   ( hdr->mb.bss_end_addr - hdr->mb.load_addr ) : filesz );
341         buffer = phys_to_user ( hdr->mb.load_addr );
342         if ( ( rc = prep_segment ( buffer, filesz, memsz ) ) != 0 ) {
343                 DBGC ( image, "MULTIBOOT %p could not prepare segment: %s\n",
344                        image, strerror ( rc ) );
345                 return rc;
346         }
347
348         /* Copy image to segment */
349         memcpy_user ( buffer, 0, image->data, offset, filesz );
350
351         /* Record execution entry point and maximum used address */
352         *entry = hdr->mb.entry_addr;
353         *max = ( hdr->mb.load_addr + memsz );
354
355         return 0;
356 }
357
358 /**
359  * Load ELF multiboot image into memory
360  *
361  * @v image             Multiboot file
362  * @ret entry           Entry point
363  * @ret max             Maximum used address
364  * @ret rc              Return status code
365  */
366 static int multiboot_load_elf ( struct image *image, physaddr_t *entry,
367                                 physaddr_t *max ) {
368         int rc;
369
370         /* Load ELF image*/
371         if ( ( rc = elf_load ( image, entry, max ) ) != 0 ) {
372                 DBGC ( image, "MULTIBOOT %p ELF image failed to load: %s\n",
373                        image, strerror ( rc ) );
374                 return rc;
375         }
376
377         return 0;
378 }
379
380 /**
381  * Execute multiboot image
382  *
383  * @v image             Multiboot image
384  * @ret rc              Return status code
385  */
386 static int multiboot_exec ( struct image *image ) {
387         struct multiboot_header_info hdr;
388         physaddr_t entry;
389         physaddr_t max;
390         int rc;
391
392         /* Locate multiboot header, if present */
393         if ( ( rc = multiboot_find_header ( image, &hdr ) ) != 0 ) {
394                 DBGC ( image, "MULTIBOOT %p has no multiboot header\n",
395                        image );
396                 return rc;
397         }
398
399         /* Abort if we detect flags that we cannot support */
400         if ( hdr.mb.flags & MB_UNSUPPORTED_FLAGS ) {
401                 DBGC ( image, "MULTIBOOT %p flags %08x not supported\n",
402                        image, ( hdr.mb.flags & MB_UNSUPPORTED_FLAGS ) );
403                 return -ENOTSUP;
404         }
405
406         /* There is technically a bit MB_FLAG_RAW to indicate whether
407          * this is an ELF or a raw image.  In practice, grub will use
408          * the ELF header if present, and Solaris relies on this
409          * behaviour.
410          */
411         if ( ( ( rc = multiboot_load_elf ( image, &entry, &max ) ) != 0 ) &&
412              ( ( rc = multiboot_load_raw ( image, &hdr, &entry, &max ) ) != 0 ))
413                 return rc;
414
415         /* Populate multiboot information structure */
416         memset ( &mbinfo, 0, sizeof ( mbinfo ) );
417         mbinfo.flags = ( MBI_FLAG_LOADER | MBI_FLAG_MEM | MBI_FLAG_MMAP |
418                          MBI_FLAG_CMDLINE | MBI_FLAG_MODS );
419         mb_cmdline_offset = 0;
420         mbinfo.cmdline = multiboot_add_cmdline ( image );
421         mbinfo.mods_addr = virt_to_phys ( mbmodules );
422         mbinfo.mmap_addr = virt_to_phys ( mbmemmap );
423         snprintf ( mb_bootloader_name, sizeof ( mb_bootloader_name ),
424                    "iPXE %s", product_version );
425         mbinfo.boot_loader_name = virt_to_phys ( mb_bootloader_name );
426         if ( ( rc = multiboot_add_modules ( image, max, &mbinfo, mbmodules,
427                                             ( sizeof ( mbmodules ) /
428                                               sizeof ( mbmodules[0] ) ) ) ) !=0)
429                 return rc;
430
431         /* Multiboot images may not return and have no callback
432          * interface, so shut everything down prior to booting the OS.
433          */
434         shutdown_boot();
435
436         /* Build memory map after unhiding bootloader memory regions as part of
437          * shutting everything down.
438          */
439         multiboot_build_memmap ( image, &mbinfo, mbmemmap,
440                                  ( sizeof(mbmemmap) / sizeof(mbmemmap[0]) ) );
441
442         /* Jump to OS with flat physical addressing */
443         DBGC ( image, "MULTIBOOT %p starting execution at %lx\n",
444                image, entry );
445         __asm__ __volatile__ ( PHYS_CODE ( "pushl %%ebp\n\t"
446                                            "call *%%edi\n\t"
447                                            "popl %%ebp\n\t" )
448                                : : "a" ( MULTIBOOT_BOOTLOADER_MAGIC ),
449                                    "b" ( virt_to_phys ( &mbinfo ) ),
450                                    "D" ( entry )
451                                : "ecx", "edx", "esi", "memory" );
452
453         DBGC ( image, "MULTIBOOT %p returned\n", image );
454
455         /* It isn't safe to continue after calling shutdown() */
456         while ( 1 ) {}
457
458         return -ECANCELED;  /* -EIMPOSSIBLE, anyone? */
459 }
460
461 /**
462  * Probe multiboot image
463  *
464  * @v image             Multiboot file
465  * @ret rc              Return status code
466  */
467 static int multiboot_probe ( struct image *image ) {
468         struct multiboot_header_info hdr;
469         int rc;
470
471         /* Locate multiboot header, if present */
472         if ( ( rc = multiboot_find_header ( image, &hdr ) ) != 0 ) {
473                 DBGC ( image, "MULTIBOOT %p has no multiboot header\n",
474                        image );
475                 return rc;
476         }
477         DBGC ( image, "MULTIBOOT %p found header with flags %08x\n",
478                image, hdr.mb.flags );
479
480         return 0;
481 }
482
483 /** Multiboot image type */
484 struct image_type multiboot_image_type __image_type ( PROBE_MULTIBOOT ) = {
485         .name = "Multiboot",
486         .probe = multiboot_probe,
487         .exec = multiboot_exec,
488 };