浏览代码

Place multiboot command lines in base memory; Xen won't pick them up

otherwise.  :(
tags/v0.9.3
Michael Brown 17 年前
父节点
当前提交
688bac1656
共有 1 个文件被更改,包括 69 次插入36 次删除
  1. 69
    36
      src/arch/i386/image/multiboot.c

+ 69
- 36
src/arch/i386/image/multiboot.c 查看文件

@@ -23,6 +23,7 @@
23 23
  *
24 24
  */
25 25
 
26
+#include <stdio.h>
26 27
 #include <errno.h>
27 28
 #include <assert.h>
28 29
 #include <realmode.h>
@@ -51,6 +52,16 @@ struct image_type multiboot_image_type __image_type ( PROBE_MULTIBOOT );
51 52
  */
52 53
 #define MAX_MODULES 8
53 54
 
55
+/**
56
+ * Maximum combined length of command lines
57
+ *
58
+ * Again; sorry.  Some broken OSes zero out any non-base memory that
59
+ * isn't part of the loaded module set, so we can't just use
60
+ * virt_to_phys(cmdline) to point to the command lines, even though
61
+ * this would comply with the Multiboot spec.
62
+ */
63
+#define MB_MAX_CMDLINE 512
64
+
54 65
 /** Multiboot flags that we support */
55 66
 #define MB_SUPPORTED_FLAGS ( MB_FLAG_PGALIGN | MB_FLAG_MEMMAP | \
56 67
 			     MB_FLAG_VIDMODE | MB_FLAG_RAW )
@@ -77,6 +88,13 @@ struct multiboot_header_info {
77 88
 	size_t offset;
78 89
 };
79 90
 
91
+/** Multiboot module command lines */
92
+static char __bss16_array ( mb_cmdlines, [MB_MAX_CMDLINE] );
93
+#define mb_cmdlines __use_data16 ( mb_cmdlines )
94
+
95
+/** Offset within module command lines */
96
+static unsigned int mb_cmdline_offset;
97
+
80 98
 /**
81 99
  * Build multiboot memory map
82 100
  *
@@ -118,6 +136,32 @@ static void multiboot_build_memmap ( struct image *image,
118 136
 	}
119 137
 }
120 138
 
139
+/**
140
+ * Add command line in base memory
141
+ *
142
+ * @v cmdline		Command line
143
+ * @ret physaddr	Physical address of command line
144
+ */
145
+physaddr_t multiboot_add_cmdline ( const char *cmdline ) {
146
+	char *mb_cmdline;
147
+
148
+	if ( ! cmdline )
149
+		cmdline = "";
150
+
151
+	/* Copy command line to base memory buffer */
152
+	mb_cmdline = ( mb_cmdlines + mb_cmdline_offset );
153
+	mb_cmdline_offset +=
154
+		( snprintf ( mb_cmdline,
155
+			     ( sizeof ( mb_cmdlines ) - mb_cmdline_offset ),
156
+			     "%s", cmdline ) + 1 );
157
+
158
+	/* Truncate to terminating NUL in buffer if necessary */
159
+	if ( mb_cmdline_offset > sizeof ( mb_cmdlines ) )
160
+		mb_cmdline_offset = ( sizeof ( mb_cmdlines ) - 1 );
161
+
162
+	return virt_to_phys ( mb_cmdline );
163
+}
164
+
121 165
 /**
122 166
  * Build multiboot module list
123 167
  *
@@ -135,7 +179,6 @@ multiboot_build_module_list ( struct image *image,
135 179
 	unsigned int insert;
136 180
 	physaddr_t start;
137 181
 	physaddr_t end;
138
-	char *cmdline;
139 182
 	unsigned int i;
140 183
 
141 184
 	/* Add each image as a multiboot module */
@@ -151,44 +194,35 @@ multiboot_build_module_list ( struct image *image,
151 194
 		if ( module_image == image )
152 195
 			continue;
153 196
 
154
-		/* If we don't have a data structure to populate, just count */
155
-		if ( modules ) {
156
-			
157
-			/* At least some OSes expect the multiboot
158
-			 * modules to be in ascending order, so we
159
-			 * have to support it.
160
-			 */
161
-			start = user_to_phys ( module_image->data, 0 );
162
-			end = user_to_phys ( module_image->data,
163
-					     module_image->len );
164
-			for ( insert = 0 ; insert < count ; insert++ ) {
165
-				if ( start < modules[insert].mod_start )
166
-					break;
167
-			}
168
-			module = &modules[insert];
169
-			memmove ( ( module + 1 ), module,
170
-				  ( ( count - insert ) * sizeof ( *module ) ));
171
-			module->mod_start = start;
172
-			module->mod_end = end;
173
-			cmdline = ( module_image->cmdline ?
174
-				    module_image->cmdline : "" );
175
-			module->string = virt_to_phys ( cmdline );
176
-			module->reserved = 0;
177
-			
178
-			/* We promise to page-align modules */
179
-			assert ( ( module->mod_start & 0xfff ) == 0 );
197
+		/* At least some OSes expect the multiboot modules to
198
+		 * be in ascending order, so we have to support it.
199
+		 */
200
+		start = user_to_phys ( module_image->data, 0 );
201
+		end = user_to_phys ( module_image->data, module_image->len );
202
+		for ( insert = 0 ; insert < count ; insert++ ) {
203
+			if ( start < modules[insert].mod_start )
204
+				break;
180 205
 		}
206
+		module = &modules[insert];
207
+		memmove ( ( module + 1 ), module,
208
+			  ( ( count - insert ) * sizeof ( *module ) ) );
209
+		module->mod_start = start;
210
+		module->mod_end = end;
211
+		module->string =
212
+			multiboot_add_cmdline ( module_image->cmdline );
213
+		module->reserved = 0;
214
+		
215
+		/* We promise to page-align modules */
216
+		assert ( ( module->mod_start & 0xfff ) == 0 );
181 217
 
182 218
 		count++;
183 219
 	}
184 220
 
185 221
 	/* Dump module configuration */
186
-	if ( modules ) {
187
-		for ( i = 0 ; i < count ; i++ ) {
188
-			DBGC ( image, "MULTIBOOT %p module %d is [%lx,%lx)\n",
189
-			       image, i, modules[i].mod_start,
190
-			       modules[i].mod_end );
191
-		}
222
+	for ( i = 0 ; i < count ; i++ ) {
223
+		DBGC ( image, "MULTIBOOT %p module %d is [%lx,%lx)\n",
224
+		       image, i, modules[i].mod_start,
225
+		       modules[i].mod_end );
192 226
 	}
193 227
 
194 228
 	return count;
@@ -225,7 +259,6 @@ static struct multiboot_module __bss16_array ( mbmodules, [MAX_MODULES] );
225 259
  */
226 260
 static int multiboot_exec ( struct image *image ) {
227 261
 	physaddr_t entry = image->priv.phys;
228
-	char *cmdline;
229 262
 
230 263
 	/* Populate multiboot information structure */
231 264
 	memset ( &mbinfo, 0, sizeof ( mbinfo ) );
@@ -233,8 +266,8 @@ static int multiboot_exec ( struct image *image ) {
233 266
 			 MBI_FLAG_CMDLINE | MBI_FLAG_MODS );
234 267
 	multiboot_build_memmap ( image, &mbinfo, mbmemmap,
235 268
 				 ( sizeof(mbmemmap) / sizeof(mbmemmap[0]) ) );
236
-	cmdline = ( image->cmdline ? image->cmdline : "" );
237
-	mbinfo.cmdline = virt_to_phys ( cmdline );
269
+	mb_cmdline_offset = 0;
270
+	mbinfo.cmdline = multiboot_add_cmdline ( image->cmdline );
238 271
 	mbinfo.mods_count = multiboot_build_module_list ( image, mbmodules,
239 272
 				( sizeof(mbmodules) / sizeof(mbmodules[0]) ) );
240 273
 	mbinfo.mods_addr = virt_to_phys ( mbmodules );

正在加载...
取消
保存