Explorar el Código

We can now load an initrd as well as a kernel

tags/v0.9.3
Michael Brown hace 17 años
padre
commit
a5f6408d8e
Se han modificado 2 ficheros con 95 adiciones y 5 borrados
  1. 93
    5
      src/arch/i386/image/bzimage.c
  2. 2
    0
      src/arch/i386/include/bzimage.h

+ 93
- 5
src/arch/i386/image/bzimage.c Ver fichero

35
 #include <gpxe/segment.h>
35
 #include <gpxe/segment.h>
36
 #include <gpxe/memmap.h>
36
 #include <gpxe/memmap.h>
37
 #include <gpxe/shutdown.h>
37
 #include <gpxe/shutdown.h>
38
+#include <gpxe/initrd.h>
38
 
39
 
39
 struct image_type bzimage_image_type __image_type ( PROBE_NORMAL );
40
 struct image_type bzimage_image_type __image_type ( PROBE_NORMAL );
40
 
41
 
76
 	unsigned int vid_mode;
77
 	unsigned int vid_mode;
77
 	/** Memory limit */
78
 	/** Memory limit */
78
 	uint64_t mem_limit;
79
 	uint64_t mem_limit;
80
+	/** Initrd address */
81
+	physaddr_t ramdisk_image;
82
+	/** Initrd size */
83
+	physaddr_t ramdisk_size;
79
 };
84
 };
80
 
85
 
81
 /**
86
 /**
104
 		} else {
109
 		} else {
105
 			exec_ctx->vid_mode = strtoul ( vga, &vga, 16 );
110
 			exec_ctx->vid_mode = strtoul ( vga, &vga, 16 );
106
 			if ( *vga && ( *vga != ' ' ) ) {
111
 			if ( *vga && ( *vga != ' ' ) ) {
107
-				DBGC ( image, "bzImage %p strange \"vga=\"\n",
108
-				       image );
112
+				DBGC ( image, "bzImage %p strange \"vga=\""
113
+				       "terminator '%c'\n", image, *vga );
109
 			}
114
 			}
110
 		}
115
 		}
111
 	}
116
 	}
116
 		exec_ctx->mem_limit = strtoul ( mem, &mem, 0 );
121
 		exec_ctx->mem_limit = strtoul ( mem, &mem, 0 );
117
 		switch ( *mem ) {
122
 		switch ( *mem ) {
118
 		case 'G':
123
 		case 'G':
124
+		case 'g':
119
 			exec_ctx->mem_limit <<= 10;
125
 			exec_ctx->mem_limit <<= 10;
120
 		case 'M':
126
 		case 'M':
127
+		case 'm':
121
 			exec_ctx->mem_limit <<= 10;
128
 			exec_ctx->mem_limit <<= 10;
122
 		case 'K':
129
 		case 'K':
130
+		case 'k':
123
 			exec_ctx->mem_limit <<= 10;
131
 			exec_ctx->mem_limit <<= 10;
124
 			break;
132
 			break;
125
 		case '\0':
133
 		case '\0':
126
 		case ' ':
134
 		case ' ':
127
 			break;
135
 			break;
128
 		default:
136
 		default:
129
-			DBGC ( image, "bzImage %p strange \"mem=\"\n",
130
-			       image );
137
+			DBGC ( image, "bzImage %p strange \"mem=\" "
138
+			       "terminator '%c'\n", image, *mem );
131
 			break;
139
 			break;
132
 		}
140
 		}
133
 	}
141
 	}
159
 	return 0;
167
 	return 0;
160
 }
168
 }
161
 
169
 
170
+/**
171
+ * Load initrd, if any
172
+ *
173
+ * @v image		bzImage image
174
+ * @v exec_ctx		Execution context
175
+ * @ret rc		Return status code
176
+ */
177
+static int bzimage_load_initrd ( struct image *image,
178
+				 struct bzimage_exec_context *exec_ctx,
179
+				 struct image *initrd ) {
180
+	physaddr_t start = user_to_phys ( initrd->data, 0 );
181
+	int rc;
182
+
183
+	DBGC ( image, "bzImage %p loading initrd %p (%s)\n",
184
+	       image, initrd, initrd->name );
185
+	
186
+	/* Find a suitable start address */
187
+	if ( ( start + initrd->len ) <= exec_ctx->mem_limit ) {
188
+		/* Just use initrd in situ */
189
+		DBGC ( image, "bzImage %p using initrd as [%lx,%lx)\n",
190
+		       image, start, ( start + initrd->len ) );
191
+	} else {
192
+		for ( ; ; start -= 0x100000 ) {
193
+			/* Check that we're not going to overwrite the
194
+			 * kernel itself.  This check isn't totally
195
+			 * accurate, but errs on the side of caution.
196
+			 */
197
+			if ( start <= ( BZI_LOAD_HIGH_ADDR + image->len ) ) {
198
+				DBGC ( image, "bzImage %p could not find a "
199
+				       "location for initrd\n", image );
200
+				return -ENOBUFS;
201
+			}
202
+			/* Check that we are within the kernel's range */
203
+			if ( ( start + initrd->len ) > exec_ctx->mem_limit )
204
+				continue;
205
+			/* Prepare and verify segment */
206
+			if ( ( rc = prep_segment ( phys_to_user ( start ),
207
+						   initrd->len,
208
+						   initrd->len ) ) != 0 )
209
+				continue;
210
+			/* Copy to segment */
211
+			DBGC ( image, "bzImage %p relocating initrd to "
212
+			       "[%lx,%lx)\n", image, start,
213
+			       ( start + initrd->len ) );
214
+			memcpy_user ( phys_to_user ( start ), 0,
215
+				      initrd->data, 0, initrd->len );
216
+			break;
217
+		}
218
+	}
219
+
220
+	/* Record initrd location */
221
+	exec_ctx->ramdisk_image = start;
222
+	exec_ctx->ramdisk_size = initrd->len;
223
+
224
+	return 0;
225
+}
226
+
162
 /**
227
 /**
163
  * Execute bzImage image
228
  * Execute bzImage image
164
  *
229
  *
169
 	struct bzimage_exec_context exec_ctx;
234
 	struct bzimage_exec_context exec_ctx;
170
 	struct bzimage_header bzhdr;
235
 	struct bzimage_header bzhdr;
171
 	const char *cmdline = ( image->cmdline ? image->cmdline : "" );
236
 	const char *cmdline = ( image->cmdline ? image->cmdline : "" );
237
+	struct image *initrd;
172
 	int rc;
238
 	int rc;
173
 
239
 
240
+	/* Initialise context */
241
+	memset ( &exec_ctx, 0, sizeof ( exec_ctx ) );
242
+
174
 	/* Retrieve kernel header */
243
 	/* Retrieve kernel header */
175
 	exec_ctx.rm_kernel_seg = image->priv.ul;
244
 	exec_ctx.rm_kernel_seg = image->priv.ul;
176
 	exec_ctx.rm_kernel = real_to_user ( exec_ctx.rm_kernel_seg, 0 );
245
 	exec_ctx.rm_kernel = real_to_user ( exec_ctx.rm_kernel_seg, 0 );
179
 	exec_ctx.rm_cmdline = exec_ctx.rm_heap = 
248
 	exec_ctx.rm_cmdline = exec_ctx.rm_heap = 
180
 		( bzhdr.heap_end_ptr + 0x200 );
249
 		( bzhdr.heap_end_ptr + 0x200 );
181
 	exec_ctx.vid_mode = bzhdr.vid_mode;
250
 	exec_ctx.vid_mode = bzhdr.vid_mode;
182
-	exec_ctx.mem_limit = 0;
251
+	if ( bzhdr.version >= 0x0203 ) {
252
+		exec_ctx.mem_limit = ( bzhdr.initrd_addr_max + 1 );
253
+	} else {
254
+		exec_ctx.mem_limit = ( BZI_INITRD_MAX + 1 );
255
+	}
183
 
256
 
184
 	/* Parse command line for bootloader parameters */
257
 	/* Parse command line for bootloader parameters */
185
 	if ( ( rc = bzimage_parse_cmdline ( image, &exec_ctx, cmdline ) ) != 0)
258
 	if ( ( rc = bzimage_parse_cmdline ( image, &exec_ctx, cmdline ) ) != 0)
189
 	if ( ( rc = bzimage_set_cmdline ( image, &exec_ctx, cmdline ) ) != 0 )
262
 	if ( ( rc = bzimage_set_cmdline ( image, &exec_ctx, cmdline ) ) != 0 )
190
 		return rc;
263
 		return rc;
191
 
264
 
265
+	/* Load an initrd, if one exists */
266
+	for_each_image ( initrd ) {
267
+		if ( initrd->type == &initrd_image_type ) {
268
+			if ( ( rc = bzimage_load_initrd ( image, &exec_ctx,
269
+							  initrd ) ) != 0 )
270
+				return rc;
271
+			break;
272
+		}
273
+	}
274
+
192
 	/* Update and store kernel header */
275
 	/* Update and store kernel header */
193
 	bzhdr.vid_mode = exec_ctx.vid_mode;
276
 	bzhdr.vid_mode = exec_ctx.vid_mode;
277
+	bzhdr.ramdisk_image = exec_ctx.ramdisk_image;
278
+	bzhdr.ramdisk_size = exec_ctx.ramdisk_size;
194
 	copy_to_user ( exec_ctx.rm_kernel, BZI_HDR_OFFSET, &bzhdr,
279
 	copy_to_user ( exec_ctx.rm_kernel, BZI_HDR_OFFSET, &bzhdr,
195
 		       sizeof ( bzhdr ) );
280
 		       sizeof ( bzhdr ) );
196
 
281
 
377
 	struct bzimage_header bzhdr;
462
 	struct bzimage_header bzhdr;
378
 	int rc;
463
 	int rc;
379
 
464
 
465
+	/* Initialise context */
466
+	memset ( &load_ctx, 0, sizeof ( load_ctx ) );
467
+
380
 	/* Load and verify header */
468
 	/* Load and verify header */
381
 	if ( ( rc = bzimage_load_header ( image, &load_ctx, &bzhdr ) ) != 0 )
469
 	if ( ( rc = bzimage_load_header ( image, &load_ctx, &bzhdr ) ) != 0 )
382
 		return rc;
470
 		return rc;

+ 2
- 0
src/arch/i386/include/bzimage.h Ver fichero

94
 /** bzImage special video mode "ask" */
94
 /** bzImage special video mode "ask" */
95
 #define BZI_VID_MODE_ASK 0xfffd
95
 #define BZI_VID_MODE_ASK 0xfffd
96
 
96
 
97
+/** bzImage maximum initrd address for versions < 2.03 */
98
+#define BZI_INITRD_MAX 0x37ffffff
97
 
99
 
98
 /** bzImage command-line structure used by older kernels */
100
 /** bzImage command-line structure used by older kernels */
99
 struct bzimage_cmdline {
101
 struct bzimage_cmdline {

Loading…
Cancelar
Guardar