Procházet zdrojové kódy

We can now load an initrd as well as a kernel

tags/v0.9.3
Michael Brown před 17 roky
rodič
revize
a5f6408d8e
2 změnil soubory, kde provedl 95 přidání a 5 odebrání
  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 Zobrazit soubor

@@ -35,6 +35,7 @@
35 35
 #include <gpxe/segment.h>
36 36
 #include <gpxe/memmap.h>
37 37
 #include <gpxe/shutdown.h>
38
+#include <gpxe/initrd.h>
38 39
 
39 40
 struct image_type bzimage_image_type __image_type ( PROBE_NORMAL );
40 41
 
@@ -76,6 +77,10 @@ struct bzimage_exec_context {
76 77
 	unsigned int vid_mode;
77 78
 	/** Memory limit */
78 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,8 +109,8 @@ static int bzimage_parse_cmdline ( struct image *image,
104 109
 		} else {
105 110
 			exec_ctx->vid_mode = strtoul ( vga, &vga, 16 );
106 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,18 +121,21 @@ static int bzimage_parse_cmdline ( struct image *image,
116 121
 		exec_ctx->mem_limit = strtoul ( mem, &mem, 0 );
117 122
 		switch ( *mem ) {
118 123
 		case 'G':
124
+		case 'g':
119 125
 			exec_ctx->mem_limit <<= 10;
120 126
 		case 'M':
127
+		case 'm':
121 128
 			exec_ctx->mem_limit <<= 10;
122 129
 		case 'K':
130
+		case 'k':
123 131
 			exec_ctx->mem_limit <<= 10;
124 132
 			break;
125 133
 		case '\0':
126 134
 		case ' ':
127 135
 			break;
128 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 139
 			break;
132 140
 		}
133 141
 	}
@@ -159,6 +167,63 @@ static int bzimage_set_cmdline ( struct image *image,
159 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 228
  * Execute bzImage image
164 229
  *
@@ -169,8 +234,12 @@ static int bzimage_exec ( struct image *image ) {
169 234
 	struct bzimage_exec_context exec_ctx;
170 235
 	struct bzimage_header bzhdr;
171 236
 	const char *cmdline = ( image->cmdline ? image->cmdline : "" );
237
+	struct image *initrd;
172 238
 	int rc;
173 239
 
240
+	/* Initialise context */
241
+	memset ( &exec_ctx, 0, sizeof ( exec_ctx ) );
242
+
174 243
 	/* Retrieve kernel header */
175 244
 	exec_ctx.rm_kernel_seg = image->priv.ul;
176 245
 	exec_ctx.rm_kernel = real_to_user ( exec_ctx.rm_kernel_seg, 0 );
@@ -179,7 +248,11 @@ static int bzimage_exec ( struct image *image ) {
179 248
 	exec_ctx.rm_cmdline = exec_ctx.rm_heap = 
180 249
 		( bzhdr.heap_end_ptr + 0x200 );
181 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 257
 	/* Parse command line for bootloader parameters */
185 258
 	if ( ( rc = bzimage_parse_cmdline ( image, &exec_ctx, cmdline ) ) != 0)
@@ -189,8 +262,20 @@ static int bzimage_exec ( struct image *image ) {
189 262
 	if ( ( rc = bzimage_set_cmdline ( image, &exec_ctx, cmdline ) ) != 0 )
190 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 275
 	/* Update and store kernel header */
193 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 279
 	copy_to_user ( exec_ctx.rm_kernel, BZI_HDR_OFFSET, &bzhdr,
195 280
 		       sizeof ( bzhdr ) );
196 281
 
@@ -377,6 +462,9 @@ int bzimage_load ( struct image *image ) {
377 462
 	struct bzimage_header bzhdr;
378 463
 	int rc;
379 464
 
465
+	/* Initialise context */
466
+	memset ( &load_ctx, 0, sizeof ( load_ctx ) );
467
+
380 468
 	/* Load and verify header */
381 469
 	if ( ( rc = bzimage_load_header ( image, &load_ctx, &bzhdr ) ) != 0 )
382 470
 		return rc;

+ 2
- 0
src/arch/i386/include/bzimage.h Zobrazit soubor

@@ -94,6 +94,8 @@ struct bzimage_header {
94 94
 /** bzImage special video mode "ask" */
95 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 100
 /** bzImage command-line structure used by older kernels */
99 101
 struct bzimage_cmdline {

Načítá se…
Zrušit
Uložit