| 
				
			 | 
			
			
				
				@@ -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
			 | 
			
			
				
				 } 
			 |