Pārlūkot izejas kodu

Place multiboot tables in base memory; at least some OSes won't see it

if we don't.
tags/v0.9.3
Michael Brown 18 gadus atpakaļ
vecāks
revīzija
bcd6ca3291
1 mainītis faili ar 64 papildinājumiem un 34 dzēšanām
  1. 64
    34
      src/arch/i386/image/multiboot.c

+ 64
- 34
src/arch/i386/image/multiboot.c Parādīt failu

@@ -25,7 +25,7 @@
25 25
 
26 26
 #include <errno.h>
27 27
 #include <assert.h>
28
-#include <alloca.h>
28
+#include <realmode.h>
29 29
 #include <multiboot.h>
30 30
 #include <gpxe/uaccess.h>
31 31
 #include <gpxe/image.h>
@@ -35,6 +35,18 @@
35 35
 
36 36
 struct image_type multiboot_image_type __image_type ( PROBE_MULTIBOOT );
37 37
 
38
+/**
39
+ * Maximum number of modules we will allow for
40
+ *
41
+ * If this has bitten you: sorry.  I did have a perfect scheme with a
42
+ * dynamically allocated list of modules on the protected-mode stack,
43
+ * but it was incompatible with some broken OSes that can only access
44
+ * low memory at boot time (even though we kindly set up 4GB flat
45
+ * physical addressing as per the multiboot specification.
46
+ *
47
+ */
48
+#define MAX_MODULES 8
49
+
38 50
 /** Multiboot flags that we support */
39 51
 #define MB_SUPPORTED_FLAGS ( MB_FLAG_PGALIGN | MB_FLAG_MEMMAP | \
40 52
 			     MB_FLAG_VIDMODE | MB_FLAG_RAW )
@@ -66,9 +78,11 @@ struct multiboot_header_info {
66 78
  *
67 79
  * @v mbinfo		Multiboot information structure
68 80
  * @v mbmemmap		Multiboot memory map
81
+ * @v limit		Maxmimum number of memory map entries
69 82
  */
70 83
 static void multiboot_build_memmap ( struct multiboot_info *mbinfo,
71
-				     struct multiboot_memory_map *mbmemmap ) {
84
+				     struct multiboot_memory_map *mbmemmap,
85
+				     unsigned int limit ) {
72 86
 	struct memory_map memmap;
73 87
 	unsigned int i;
74 88
 
@@ -78,6 +92,11 @@ static void multiboot_build_memmap ( struct multiboot_info *mbinfo,
78 92
 	/* Translate into multiboot format */
79 93
 	memset ( mbmemmap, 0, sizeof ( *mbmemmap ) );
80 94
 	for ( i = 0 ; i < memmap.count ; i++ ) {
95
+		if ( i >= limit ) {
96
+			DBG ( "Multiboot limit of %d memmap entries reached\n",
97
+			      limit );
98
+			break;
99
+		}
81 100
 		mbmemmap[i].size = ( sizeof ( mbmemmap[i] ) -
82 101
 				     sizeof ( mbmemmap[i].size ) );
83 102
 		mbmemmap[i].base_addr = memmap.regions[i].start;
@@ -102,7 +121,8 @@ static void multiboot_build_memmap ( struct multiboot_info *mbinfo,
102 121
  */
103 122
 static unsigned int
104 123
 multiboot_build_module_list ( struct image *image,
105
-			      struct multiboot_module *modules ) {
124
+			      struct multiboot_module *modules,
125
+			      unsigned int limit ) {
106 126
 	struct image *module_image;
107 127
 	struct multiboot_module *module;
108 128
 	unsigned int count = 0;
@@ -114,6 +134,12 @@ multiboot_build_module_list ( struct image *image,
114 134
 	/* Add each image as a multiboot module */
115 135
 	for_each_image ( module_image ) {
116 136
 
137
+		if ( count >= limit ) {
138
+			DBG ( "Multiboot limit of %d modules reached\n",
139
+			      limit );
140
+			break;
141
+		}
142
+
117 143
 		/* Do not include kernel image itself as a module */
118 144
 		if ( module_image == image )
119 145
 			continue;
@@ -158,6 +184,29 @@ multiboot_build_module_list ( struct image *image,
158 184
 	return count;
159 185
 }
160 186
 
187
+/**
188
+ * The multiboot information structure
189
+ *
190
+ * Kept in base memory because some OSes won't find it elsewhere,
191
+ * along with the other structures belonging to the Multiboot
192
+ * information table.
193
+ */
194
+static struct multiboot_info __data16 ( mbinfo );
195
+#define mbinfo __use_data16 ( mbinfo )
196
+
197
+/** The multiboot bootloader name */
198
+static const char * __data16 ( mb_bootloader_name ) = "gPXE " VERSION;
199
+#define mb_bootloader_name __use_data16 ( mb_bootloader_name )
200
+
201
+/** The multiboot memory map */
202
+static struct multiboot_memory_map
203
+	__data16_array ( mbmemmap, [MAX_MEMORY_REGIONS] );
204
+#define mbmemmap __use_data16 ( mbmemmap )
205
+
206
+/** The multiboot module list */
207
+static struct multiboot_module __data16_array ( mbmodules, [MAX_MODULES] );
208
+#define mbmodules __use_data16 ( mbmodules )
209
+
161 210
 /**
162 211
  * Execute multiboot image
163 212
  *
@@ -165,45 +214,26 @@ multiboot_build_module_list ( struct image *image,
165 214
  * @ret rc		Return status code
166 215
  */
167 216
 static int multiboot_exec ( struct image *image ) {
168
-	static const char *bootloader_name = "gPXE " VERSION;
169
-	struct multiboot_info mbinfo;
170
-	struct multiboot_memory_map mbmemmap[MAX_MEMORY_REGIONS];
171
-	struct multiboot_module *modules;
172
-	unsigned int num_modules;
173 217
 
174 218
 	/* Populate multiboot information structure */
175 219
 	memset ( &mbinfo, 0, sizeof ( mbinfo ) );
176
-
177
-	/* Set boot loader name */
178
-	mbinfo.boot_loader_name = virt_to_phys ( bootloader_name );
179
-	mbinfo.flags |= MBI_FLAG_LOADER;
180
-	
181
-	/* Build memory map */
182
-	multiboot_build_memmap ( &mbinfo, mbmemmap );
183
-	mbinfo.mmap_addr = virt_to_phys ( mbmemmap );
184
-	mbinfo.flags |= ( MBI_FLAG_MEM | MBI_FLAG_MMAP );
185
-
186
-	/* Set command line */
220
+	mbinfo.flags = ( MBI_FLAG_LOADER | MBI_FLAG_MEM | MBI_FLAG_MMAP |
221
+			 MBI_FLAG_CMDLINE | MBI_FLAG_MODS );
222
+	multiboot_build_memmap ( &mbinfo, mbmemmap,
223
+				 ( sizeof(mbmemmap) / sizeof(mbmemmap[0]) ) );
187 224
 	mbinfo.cmdline = virt_to_phys ( image->cmdline );
188
-	mbinfo.flags |= MBI_FLAG_CMDLINE;
189
-
190
-	/* Construct module list */
191
-	num_modules = multiboot_build_module_list ( image, NULL );
192
-	modules = alloca ( num_modules * sizeof ( *modules ) );
193
-	multiboot_build_module_list ( image, modules );
194
-	mbinfo.mods_count = num_modules;
195
-	mbinfo.mods_addr = virt_to_phys ( modules );
196
-	mbinfo.flags |= MBI_FLAG_MODS;
197
-
225
+	mbinfo.mods_count = multiboot_build_module_list ( image, mbmodules,
226
+				( sizeof(mbmodules) / sizeof(mbmodules[0]) ) );
227
+	mbinfo.mods_addr = virt_to_phys ( mbmodules );
228
+	mbinfo.mmap_addr = virt_to_phys ( mbmemmap );
229
+	mbinfo.boot_loader_name = virt_to_phys ( mb_bootloader_name );
230
+	
198 231
 	/* Jump to OS with flat physical addressing */
199
-	__asm__ __volatile__ ( PHYS_CODE ( /* Preserve %ebp for alloca() */
200
-					   "pushl %%ebp\n\t"
201
-					   "call *%%edi\n\t"
202
-					   "popl %%ebp\n\t" )
232
+	__asm__ __volatile__ ( PHYS_CODE ( "call *%%edi\n\t" )
203 233
 			       : : "a" ( MULTIBOOT_BOOTLOADER_MAGIC ),
204 234
 			           "b" ( virt_to_phys ( &mbinfo ) ),
205 235
 			           "D" ( image->entry )
206
-			       : "ecx", "edx", "esi", "memory" );
236
+			       : "ecx", "edx", "esi", "ebp", "memory" );
207 237
 
208 238
 	return -ECANCELED;
209 239
 }

Notiek ielāde…
Atcelt
Saglabāt