|
@@ -28,20 +28,9 @@
|
28
|
28
|
#include <gpxe/uaccess.h>
|
29
|
29
|
#include <gpxe/image.h>
|
30
|
30
|
#include <gpxe/segment.h>
|
|
31
|
+#include <gpxe/memmap.h>
|
31
|
32
|
#include <gpxe/elf.h>
|
32
|
33
|
|
33
|
|
-/** Boot modules must be page aligned */
|
34
|
|
-#define MB_FLAG_PGALIGN 0x00000001
|
35
|
|
-
|
36
|
|
-/** Memory map must be provided */
|
37
|
|
-#define MB_FLAG_MEMMAP 0x00000002
|
38
|
|
-
|
39
|
|
-/** Video mode information must be provided */
|
40
|
|
-#define MB_FLAG_VIDMODE 0x00000004
|
41
|
|
-
|
42
|
|
-/** Image is a raw multiboot image (not ELF) */
|
43
|
|
-#define MB_FLAG_RAW 0x00010000
|
44
|
|
-
|
45
|
34
|
/** Multiboot flags that we support */
|
46
|
35
|
#define MB_SUPPORTED_FLAGS ( MB_FLAG_PGALIGN | MB_FLAG_MEMMAP | \
|
47
|
36
|
MB_FLAG_VIDMODE | MB_FLAG_RAW )
|
|
@@ -75,18 +64,51 @@ struct multiboot_header_info {
|
75
|
64
|
* @ret rc Return status code
|
76
|
65
|
*/
|
77
|
66
|
static int multiboot_execute ( struct image *image ) {
|
|
67
|
+ static const char *bootloader_name = "gPXE " VERSION;
|
78
|
68
|
struct multiboot_info mbinfo;
|
|
69
|
+ struct memory_map memmap;
|
|
70
|
+ struct multiboot_memory_map mbmemmap[ sizeof ( memmap.regions ) /
|
|
71
|
+ sizeof ( memmap.regions[0] ) ];
|
|
72
|
+ unsigned int i;
|
79
|
73
|
|
80
|
74
|
/* Populate multiboot information structure */
|
81
|
75
|
memset ( &mbinfo, 0, sizeof ( mbinfo ) );
|
|
76
|
+
|
|
77
|
+ /* Set boot loader name */
|
|
78
|
+ mbinfo.flags |= MBI_FLAG_LOADER;
|
|
79
|
+ mbinfo.boot_loader_name = virt_to_phys ( bootloader_name );
|
82
|
80
|
|
|
81
|
+ /* Get memory map */
|
|
82
|
+ get_memmap ( &memmap );
|
|
83
|
+ memset ( mbmemmap, 0, sizeof ( mbmemmap ) );
|
|
84
|
+ for ( i = 0 ; i < memmap.count ; i++ ) {
|
|
85
|
+ mbmemmap[i].size = sizeof ( mbmemmap[i] );
|
|
86
|
+ mbmemmap[i].base_addr = memmap.regions[i].start;
|
|
87
|
+ mbmemmap[i].length = ( memmap.regions[i].end -
|
|
88
|
+ memmap.regions[i].start );
|
|
89
|
+ mbmemmap[i].type = MBMEM_RAM;
|
|
90
|
+ mbinfo.mmap_length += sizeof ( mbmemmap[i] );
|
|
91
|
+ if ( memmap.regions[i].start == 0 )
|
|
92
|
+ mbinfo.mem_lower = memmap.regions[i].end;
|
|
93
|
+ if ( memmap.regions[i].start == 0x100000 )
|
|
94
|
+ mbinfo.mem_upper = ( memmap.regions[i].end - 0x100000);
|
|
95
|
+ }
|
|
96
|
+ mbinfo.flags |= ( MBI_FLAG_MEM | MBI_FLAG_MMAP );
|
|
97
|
+ mbinfo.mmap_addr = virt_to_phys ( &mbmemmap[0].base_addr );
|
|
98
|
+
|
|
99
|
+ /* Set command line, if present */
|
|
100
|
+ if ( image->cmdline ) {
|
|
101
|
+ mbinfo.flags |= MBI_FLAG_CMDLINE;
|
|
102
|
+ mbinfo.cmdline = virt_to_phys ( image->cmdline );
|
|
103
|
+ }
|
83
|
104
|
|
84
|
105
|
/* Jump to OS with flat physical addressing */
|
85
|
|
- __asm__ ( PHYS_CODE ( "call *%%edi\n\t" )
|
86
|
|
- : : "a" ( MULTIBOOT_BOOTLOADER_MAGIC ),
|
87
|
|
- "b" ( virt_to_phys ( &mbinfo ) ),
|
88
|
|
- "D" ( image->entry )
|
89
|
|
- : "ecx", "edx", "esi", "ebp" );
|
|
106
|
+ __asm__ __volatile__ ( PHYS_CODE ( "xchgw %%bx,%%bx\n\t"
|
|
107
|
+ "call *%%edi\n\t" )
|
|
108
|
+ : : "a" ( MULTIBOOT_BOOTLOADER_MAGIC ),
|
|
109
|
+ "b" ( virt_to_phys ( &mbinfo ) ),
|
|
110
|
+ "D" ( image->entry )
|
|
111
|
+ : "ecx", "edx", "esi", "ebp" );
|
90
|
112
|
|
91
|
113
|
return -ECANCELED;
|
92
|
114
|
}
|