Browse Source

Allow loading of multiple initramfs images.

tags/v0.9.3
Michael Brown 17 years ago
parent
commit
c5d9114064
1 changed files with 61 additions and 50 deletions
  1. 61
    50
      src/arch/i386/image/bzimage.c

+ 61
- 50
src/arch/i386/image/bzimage.c View File

@@ -33,7 +33,6 @@
33 33
 #include <gpxe/uaccess.h>
34 34
 #include <gpxe/image.h>
35 35
 #include <gpxe/segment.h>
36
-#include <gpxe/memmap.h>
37 36
 #include <gpxe/init.h>
38 37
 #include <gpxe/initrd.h>
39 38
 
@@ -168,58 +167,77 @@ static int bzimage_set_cmdline ( struct image *image,
168 167
 }
169 168
 
170 169
 /**
171
- * Load initrd, if any
170
+ * Load initrds, if any
172 171
  *
173 172
  * @v image		bzImage image
174 173
  * @v exec_ctx		Execution context
175 174
  * @ret rc		Return status code
176 175
  */
177 176
 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 );
177
+				 struct bzimage_exec_context *exec_ctx ) {
178
+	struct image *initrd;
179
+	size_t initrd_len;
180
+	size_t total_len = 0;
181
+	size_t offset = 0;
182
+	physaddr_t start;
181 183
 	int rc;
182 184
 
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;
185
+	/* Add up length of all initrd images */
186
+	for_each_image ( initrd ) {
187
+		if ( initrd->type != &initrd_image_type )
188
+			continue;
189
+		initrd_len = ( ( image->len + 0x0f ) & ~0x0f );
190
+		total_len += initrd_len;
191
+	}
192
+
193
+	if ( ! total_len )
194
+		return 0;
195
+
196
+	/* Find a suitable start address.  Try 1MB boundaries,
197
+	 * starting from the downloaded kernel image itself and
198
+	 * working downwards until we hit an available region.
199
+	 */
200
+	for ( start = ( user_to_phys ( image->data, 0 ) & ~0xfffff ) ; ;
201
+	      start -= 0x100000 ) {
202
+		/* Check that we're not going to overwrite the
203
+		 * kernel itself.  This check isn't totally
204
+		 * accurate, but errs on the side of caution.
205
+		 */
206
+		if ( start <= ( BZI_LOAD_HIGH_ADDR + image->len ) ) {
207
+			DBGC ( image, "bzImage %p could not find a location "
208
+			       "for initrd\n", image );
209
+			return -ENOBUFS;
217 210
 		}
211
+		/* Check that we are within the kernel's range */
212
+		if ( ( start + total_len ) > exec_ctx->mem_limit )
213
+			continue;
214
+		/* Prepare and verify segment */
215
+		if ( ( rc = prep_segment ( phys_to_user ( start ), 0,
216
+					   total_len ) ) != 0 )
217
+			continue;
218
+		/* Use this address */
219
+		break;
218 220
 	}
219 221
 
222
+	/* Construct initrd */
223
+	DBGC ( image, "bzImage %p constructing initrd at [%lx,%lx)\n",
224
+	       image, start, ( start + total_len ) );
225
+	for_each_image ( initrd ) {
226
+		if ( initrd->type != &initrd_image_type )
227
+			continue;
228
+		initrd_len = ( ( image->len + 0x0f ) & ~0x0f );
229
+		DBGC ( image, "bzImage %p has initrd %p at [%lx,%lx)\n",
230
+		       image, initrd, ( start + offset ),
231
+		       ( start + offset + initrd->len ) );
232
+		memcpy_user ( phys_to_user ( start ), offset,
233
+			      initrd->data, 0, initrd->len );
234
+		offset += initrd_len;
235
+	}
236
+	assert ( offset == total_len );
237
+
220 238
 	/* Record initrd location */
221 239
 	exec_ctx->ramdisk_image = start;
222
-	exec_ctx->ramdisk_size = initrd->len;
240
+	exec_ctx->ramdisk_size = total_len;
223 241
 
224 242
 	return 0;
225 243
 }
@@ -234,7 +252,6 @@ static int bzimage_exec ( struct image *image ) {
234 252
 	struct bzimage_exec_context exec_ctx;
235 253
 	struct bzimage_header bzhdr;
236 254
 	const char *cmdline = ( image->cmdline ? image->cmdline : "" );
237
-	struct image *initrd;
238 255
 	int rc;
239 256
 
240 257
 	/* Initialise context */
@@ -262,15 +279,9 @@ static int bzimage_exec ( struct image *image ) {
262 279
 	if ( ( rc = bzimage_set_cmdline ( image, &exec_ctx, cmdline ) ) != 0 )
263 280
 		return rc;
264 281
 
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
-	}
282
+	/* Load any initrds */
283
+	if ( ( rc = bzimage_load_initrd ( image, &exec_ctx ) ) != 0 )
284
+		return rc;
274 285
 
275 286
 	/* Update and store kernel header */
276 287
 	bzhdr.vid_mode = exec_ctx.vid_mode;

Loading…
Cancel
Save