Browse Source

Split bzimage_load into separate functions

tags/v0.9.3
Michael Brown 17 years ago
parent
commit
3ccd7335f0
2 changed files with 202 additions and 87 deletions
  1. 183
    81
      src/arch/i386/image/bzimage.c
  2. 19
    6
      src/arch/i386/include/bzimage.h

+ 183
- 81
src/arch/i386/image/bzimage.c View File

@@ -35,18 +35,36 @@
35 35
 
36 36
 struct image_type bzimage_image_type __image_type ( PROBE_NORMAL );
37 37
 
38
+/**
39
+ * bzImage load context
40
+ */
41
+struct bzimage_load_context {
42
+	/** Real-mode kernel portion load segment address */
43
+	unsigned int rm_kernel_seg;
44
+	/** Real-mode kernel portion load address */
45
+	userptr_t rm_kernel;
46
+	/** Real-mode kernel portion file size */
47
+	size_t rm_filesz;
48
+	/** Real-mode heap top (offset from rm_kernel) */
49
+	size_t rm_heap;
50
+	/** Command line (offset from rm_kernel) */
51
+	size_t rm_cmdline;
52
+	/** Real-mode kernel portion total memory size */
53
+	size_t rm_memsz;
54
+	/** Non-real-mode kernel portion load address */
55
+	userptr_t pm_kernel;
56
+	/** Non-real-mode kernel portion file and memory size */
57
+	size_t pm_sz;
58
+};
59
+
38 60
 /**
39 61
  * bzImage execution context
40 62
  */
41
-union bzimage_exec_context {
42
-	/** Real-mode parameters */
43
-	struct {
44
-		/** Kernel real-mode data segment */
45
-		uint16_t kernel_seg;
46
-		/** Kernel real-mode stack pointer */
47
-		uint16_t stack;
48
-	} rm;
49
-	unsigned long ul;
63
+struct bzimage_exec_context {
64
+	/** Kernel real-mode data segment */
65
+	uint16_t kernel_seg;
66
+	/** Kernel real-mode stack pointer */
67
+	uint16_t stack;
50 68
 };
51 69
 
52 70
 /**
@@ -56,10 +74,13 @@ union bzimage_exec_context {
56 74
  * @ret rc		Return status code
57 75
  */
58 76
 static int bzimage_exec ( struct image *image ) {
59
-	union bzimage_exec_context context;
77
+	union {
78
+		struct bzimage_exec_context bz;
79
+		unsigned long ul;
80
+	} exec_ctx;
60 81
 
61 82
 	/* Retrieve stored execution context */
62
-	context.ul = image->priv.ul;
83
+	exec_ctx.ul = image->priv.ul;
63 84
 
64 85
 	/* Prepare for exiting */
65 86
 	shutdown();
@@ -74,9 +95,9 @@ static int bzimage_exec ( struct image *image ) {
74 95
 					   "pushw %w2\n\t"
75 96
 					   "pushw $0\n\t"
76 97
 					   "lret\n\t" )
77
-			       : : "r" ( context.rm.kernel_seg ),
78
-			           "r" ( context.rm.stack ),
79
-			           "r" ( context.rm.kernel_seg + 0x20 ) );
98
+			       : : "r" ( exec_ctx.bz.kernel_seg ),
99
+			           "r" ( exec_ctx.bz.stack ),
100
+			           "r" ( exec_ctx.bz.kernel_seg + 0x20 ) );
80 101
 
81 102
 	/* There is no way for the image to return, since we provide
82 103
 	 * no return address.
@@ -87,119 +108,200 @@ static int bzimage_exec ( struct image *image ) {
87 108
 }
88 109
 
89 110
 /**
90
- * Load bzImage image into memory
111
+ * Load and parse bzImage header
91 112
  *
92 113
  * @v image		bzImage file
114
+ * @v load_ctx		Load context
115
+ * @v bzhdr		Buffer for bzImage header
93 116
  * @ret rc		Return status code
94 117
  */
95
-int bzimage_load ( struct image *image ) {
96
-	struct bzimage_header bzhdr;
97
-	union bzimage_exec_context context;
98
-	unsigned int rm_kernel_seg = 0x1000; /* place RM kernel at 1000:0000 */
99
-	userptr_t rm_kernel = real_to_user ( rm_kernel_seg, 0 );
100
-	userptr_t pm_kernel;
101
-	size_t rm_filesz;
102
-	size_t rm_memsz;
103
-	size_t pm_filesz;
104
-	size_t pm_memsz;
105
-	size_t rm_heap_end;
106
-	size_t rm_cmdline;
107
-	int rc;
118
+static int bzimage_load_header ( struct image *image,
119
+				 struct bzimage_load_context *load_ctx,
120
+				 struct bzimage_header *bzhdr ) {
108 121
 
109 122
 	/* Sanity check */
110
-	if ( image->len < ( BZI_HDR_OFFSET + sizeof ( bzhdr ) ) ) {
123
+	if ( image->len < ( BZI_HDR_OFFSET + sizeof ( *bzhdr ) ) ) {
111 124
 		DBGC ( image, "bzImage %p too short for kernel header\n",
112 125
 		       image );
113 126
 		return -ENOEXEC;
114 127
 	}
115 128
 
116 129
 	/* Read and verify header */
117
-	copy_from_user ( &bzhdr, image->data, BZI_HDR_OFFSET,
118
-			 sizeof ( bzhdr ) );
119
-	if ( bzhdr.header != BZI_SIGNATURE ) {
120
-		DBGC ( image, "bzImage %p not a bzImage\n", image );
130
+	copy_from_user ( bzhdr, image->data, BZI_HDR_OFFSET,
131
+			 sizeof ( *bzhdr ) );
132
+	if ( bzhdr->header != BZI_SIGNATURE ) {
133
+		DBGC ( image, "bzImage %p bad signature\n", image );
121 134
 		return -ENOEXEC;
122 135
 	}
123 136
 
124
-	/* This is a bzImage image, valid or otherwise */
125
-	if ( ! image->type )
126
-		image->type = &bzimage_image_type;
127
-
128 137
 	/* We don't support ancient kernels */
129
-	if ( bzhdr.version < 0x0200 ) {
138
+	if ( bzhdr->version < 0x0200 ) {
130 139
 		DBGC ( image, "bzImage %p version %04x not supported\n",
131
-		       image, bzhdr.version );
140
+		       image, bzhdr->version );
132 141
 		return -ENOTSUP;
133 142
 	}
134
-	DBGC ( image, "bzImage %p version %04x\n", image, bzhdr.version );
135 143
 
136
-	/* Check size of base memory portions */
137
-	rm_filesz = ( ( bzhdr.setup_sects ? bzhdr.setup_sects : 4 ) + 1 ) << 9;
138
-	if ( rm_filesz > image->len ) {
144
+	/* Calculate load address and size of real-mode portion */
145
+	load_ctx->rm_kernel_seg = 0x1000; /* place RM kernel at 1000:0000 */
146
+	load_ctx->rm_kernel = real_to_user ( load_ctx->rm_kernel_seg, 0 );
147
+	load_ctx->rm_filesz = load_ctx->rm_memsz =
148
+		( ( bzhdr->setup_sects ? bzhdr->setup_sects : 4 ) + 1 ) << 9;
149
+	if ( load_ctx->rm_filesz > image->len ) {
139 150
 		DBGC ( image, "bzImage %p too short for %zd byte of setup\n",
140
-		       image, rm_filesz );
151
+		       image, load_ctx->rm_filesz );
141 152
 		return -ENOEXEC;
142 153
 	}
143
-	rm_memsz = rm_filesz;
154
+
155
+	/* Calculate load address and size of non-real-mode portion */
156
+	load_ctx->pm_kernel = ( ( bzhdr->loadflags & BZI_LOAD_HIGH ) ?
157
+				phys_to_user ( BZI_LOAD_HIGH_ADDR ) :
158
+				phys_to_user ( BZI_LOAD_LOW_ADDR ) );
159
+	load_ctx->pm_sz = ( image->len - load_ctx->rm_filesz );
160
+
161
+	DBGC ( image, "bzImage %p version %04x RM %#zx bytes PM %#zx bytes\n",
162
+	       image, bzhdr->version, load_ctx->rm_filesz, load_ctx->pm_sz );
163
+	return 0;
164
+}
165
+
166
+/**
167
+ * Load real-mode portion of bzImage
168
+ *
169
+ * @v image		bzImage file
170
+ * @v load_ctx		Load context
171
+ * @v cmdline		Kernel command line
172
+ * @ret rc		Return status code
173
+ */
174
+static int bzimage_load_real ( struct image *image,
175
+			       struct bzimage_load_context *load_ctx,
176
+			       const char *cmdline ) {
177
+	size_t cmdline_len = ( strlen ( cmdline ) + 1 );
178
+	int rc;
144 179
 
145 180
 	/* Allow space for the stack and heap */
146
-	rm_memsz += BZI_STACK_SIZE;
147
-	rm_heap_end = rm_memsz;
181
+	load_ctx->rm_memsz += BZI_STACK_SIZE;
182
+	load_ctx->rm_heap = load_ctx->rm_memsz;
148 183
 
149 184
 	/* Allow space for the command line, if one exists */
150
-	rm_cmdline = rm_memsz;
151
-	if ( image->cmdline )
152
-		rm_memsz += ( strlen ( image->cmdline ) + 1 );
185
+	load_ctx->rm_cmdline = load_ctx->rm_memsz;
186
+	load_ctx->rm_memsz += cmdline_len;
153 187
 
154 188
 	/* Prepare, verify, and load the real-mode segment */
155
-	if ( ( rc = prep_segment ( rm_kernel, rm_filesz, rm_memsz ) ) != 0 ) {
189
+	if ( ( rc = prep_segment ( load_ctx->rm_kernel, load_ctx->rm_filesz,
190
+				   load_ctx->rm_memsz ) ) != 0 ) {
156 191
 		DBGC ( image, "bzImage %p could not prepare RM segment: %s\n",
157 192
 		       image, strerror ( rc ) );
158 193
 		return rc;
159 194
 	}
160
-	memcpy_user ( rm_kernel, 0, image->data, 0, rm_filesz );
195
+	memcpy_user ( load_ctx->rm_kernel, 0, image->data, 0,
196
+		      load_ctx->rm_filesz );
197
+
198
+	/* Copy command line */
199
+	copy_to_user ( load_ctx->rm_kernel, load_ctx->rm_cmdline,
200
+		       cmdline, cmdline_len );
201
+
202
+	return 0;
203
+}
161 204
 
162
-	/* Prepare, verify and load the rest of the kernel */
163
-	pm_kernel = ( ( bzhdr.loadflags & BZI_LOAD_HIGH ) ?
164
-		      phys_to_user ( 0x100000 ) : phys_to_user ( 0x10000 ) );
165
-	pm_filesz = pm_memsz = ( image->len - rm_filesz );
166
-	if ( ( rc = prep_segment ( pm_kernel, pm_filesz, pm_memsz ) ) != 0 ) {
205
+/**
206
+ * Load non-real-mode portion of bzImage
207
+ *
208
+ * @v image		bzImage file
209
+ * @v load_ctx		Load context
210
+ * @ret rc		Return status code
211
+ */
212
+static int bzimage_load_non_real ( struct image *image,
213
+				   struct bzimage_load_context *load_ctx ) {
214
+	int rc;
215
+
216
+	/* Prepare, verify and load the non-real-mode segment */
217
+	if ( ( rc = prep_segment ( load_ctx->pm_kernel, load_ctx->pm_sz,
218
+				   load_ctx->pm_sz ) ) != 0 ) {
167 219
 		DBGC ( image, "bzImage %p could not prepare PM segment: %s\n",
168 220
 		       image, strerror ( rc ) );
169 221
 		return rc;
170 222
 	}
171
-	memcpy_user ( pm_kernel, 0, image->data, rm_filesz, pm_filesz );
223
+	memcpy_user ( load_ctx->pm_kernel, 0, image->data, load_ctx->rm_filesz,
224
+		      load_ctx->pm_sz );
225
+
226
+	return 0;
227
+}
172 228
 
173
-	/* Copy down the command line, if it exists */
174
-	if ( image->cmdline ) {
175
-		copy_to_user ( rm_kernel, rm_cmdline, image->cmdline,
176
-			       strlen ( image->cmdline ) + 1 );
177
-	}
229
+
230
+/**
231
+ * Update and store bzImage header
232
+ *
233
+ * @v image		bzImage file
234
+ * @v load_ctx		Load context
235
+ * @v bzhdr		Original bzImage header
236
+ * @ret rc		Return status code
237
+ */
238
+static int bzimage_write_header ( struct image *image __unused,
239
+				  struct bzimage_load_context *load_ctx,
240
+				  struct bzimage_header *bzhdr ) {
241
+	struct bzimage_cmdline cmdline;
178 242
 
179 243
 	/* Update the header and copy it into the loaded kernel */
180
-	bzhdr.type_of_loader = BZI_LOADER_TYPE_ETHERBOOT;
181
-	if ( bzhdr.version >= 0x0201 ) {
182
-		bzhdr.heap_end_ptr = ( rm_heap_end - 0x200 );
183
-		bzhdr.loadflags |= BZI_CAN_USE_HEAP;
244
+	bzhdr->type_of_loader = BZI_LOADER_TYPE_ETHERBOOT;
245
+	if ( bzhdr->version >= 0x0201 ) {
246
+		bzhdr->heap_end_ptr = ( load_ctx->rm_heap - 0x200 );
247
+		bzhdr->loadflags |= BZI_CAN_USE_HEAP;
184 248
 	}
185
-	if ( bzhdr.version >= 0x0202 ) {
186
-		bzhdr.cmd_line_ptr = user_to_phys ( rm_kernel, rm_cmdline );
249
+	if ( bzhdr->version >= 0x0202 ) {
250
+		bzhdr->cmd_line_ptr = user_to_phys ( load_ctx->rm_kernel,
251
+						     load_ctx->rm_cmdline );
187 252
 	} else {
188
-		uint16_t cmd_line_magic = BZI_CMD_LINE_MAGIC;
189
-		uint16_t cmd_line_offset = rm_cmdline;
190
-
191
-		put_real ( cmd_line_magic, rm_kernel_seg,
192
-			   BZI_CMD_LINE_MAGIC_OFFSET );
193
-		put_real ( cmd_line_offset, rm_kernel_seg,
194
-			   BZI_CMD_LINE_OFFSET_OFFSET );
195
-		bzhdr.setup_move_size = rm_memsz;
253
+		cmdline.magic = BZI_CMDLINE_MAGIC;
254
+		cmdline.offset = load_ctx->rm_cmdline;
255
+		copy_to_user ( load_ctx->rm_kernel, BZI_CMDLINE_OFFSET,
256
+			       &cmdline, sizeof ( cmdline ) );
257
+		bzhdr->setup_move_size = load_ctx->rm_memsz;
196 258
 	}
197
-	copy_to_user ( rm_kernel, BZI_HDR_OFFSET, &bzhdr, sizeof ( bzhdr ) );
259
+	copy_to_user ( load_ctx->rm_kernel, BZI_HDR_OFFSET,
260
+		       bzhdr, sizeof ( *bzhdr ) );
261
+
262
+	return 0;
263
+}
264
+
265
+/**
266
+ * Load bzImage image into memory
267
+ *
268
+ * @v image		bzImage file
269
+ * @ret rc		Return status code
270
+ */
271
+int bzimage_load ( struct image *image ) {
272
+	struct bzimage_header bzhdr;
273
+	struct bzimage_load_context load_ctx;
274
+	union {
275
+		struct bzimage_exec_context bz;
276
+		unsigned long ul;
277
+	} exec_ctx;
278
+	const char *cmdline = ( image->cmdline ? image->cmdline : "" );
279
+	int rc;
280
+
281
+	/* Load and verify header */
282
+	if ( ( rc = bzimage_load_header ( image, &load_ctx, &bzhdr ) ) != 0 )
283
+		return rc;
284
+
285
+	/* This is a bzImage image, valid or otherwise */
286
+	if ( ! image->type )
287
+		image->type = &bzimage_image_type;
288
+
289
+	/* Load real-mode portion */
290
+	if ( ( rc = bzimage_load_real ( image, &load_ctx, cmdline ) ) != 0 )
291
+		return rc;
292
+
293
+	/* Load non-real-mode portion */
294
+	if ( ( rc = bzimage_load_non_real ( image, &load_ctx ) ) != 0 )
295
+		return rc;
296
+
297
+	/* Update and write out header */
298
+	if ( ( rc = bzimage_write_header ( image, &load_ctx, &bzhdr ) ) != 0 )
299
+		return rc;
198 300
 
199 301
 	/* Record execution context in image private data field */
200
-	context.rm.kernel_seg = rm_kernel_seg;
201
-	context.rm.stack = rm_heap_end;
202
-	image->priv.ul = context.ul;
302
+	exec_ctx.bz.kernel_seg = load_ctx.rm_kernel_seg;
303
+	exec_ctx.bz.stack = load_ctx.rm_heap;
304
+	image->priv.ul = exec_ctx.ul;
203 305
 
204 306
 	return 0;
205 307
 }

+ 19
- 6
src/arch/i386/include/bzimage.h View File

@@ -76,17 +76,30 @@ struct bzimage_header {
76 76
 /** bzImage "load high" flag */
77 77
 #define BZI_LOAD_HIGH 0x01
78 78
 
79
+/** Load address for high-loaded kernels */
80
+#define BZI_LOAD_HIGH_ADDR 0x100000
81
+
82
+/** Load address for low-loaded kernels */
83
+#define BZI_LOAD_LOW_ADDR 0x10000
84
+
79 85
 /** bzImage "kernel can use heap" flag */
80 86
 #define BZI_CAN_USE_HEAP 0x80
81 87
 
82
-/** bzImage command line present magic marker value */
83
-#define BZI_CMD_LINE_MAGIC 0xa33f
84 88
 
85
-/** bzImage command line present magic marker offset */
86
-#define BZI_CMD_LINE_MAGIC_OFFSET 0x20
89
+/** bzImage command-line structure used by older kernels */
90
+struct bzimage_cmdline {
91
+	/** Magic signature */
92
+	uint16_t magic;
93
+	/** Offset to command line */
94
+	uint16_t offset;
95
+} __attribute__ (( packed ));
96
+
97
+/** Offset of bzImage command-line structure within kernel image */
98
+#define BZI_CMDLINE_OFFSET 0x20
99
+
100
+/** bzImage command line present magic marker value */
101
+#define BZI_CMDLINE_MAGIC 0xa33f
87 102
 
88
-/** bzImage command line offset offset */
89
-#define BZI_CMD_LINE_OFFSET_OFFSET 0x22
90 103
 
91 104
 /** Amount of stack space to provide */
92 105
 #define BZI_STACK_SIZE 0x1000

Loading…
Cancel
Save