Browse Source

Mostly updated. Won't work yet.

tags/v0.9.3
Michael Brown 17 years ago
parent
commit
3bdbfe1f00
1 changed files with 172 additions and 199 deletions
  1. 172
    199
      src/arch/i386/image/nbi.c

+ 172
- 199
src/arch/i386/image/nbi.c View File

@@ -1,11 +1,10 @@
1
-#warning "This file is obsolete"
2
-#if 0
3
-
4
-#include "memsizes.h"
5
-#include "realmode.h"
6
-#include "gateA20.h"
7
-#include "etherboot.h"
8
-#include "errno.h"
1
+#include <errno.h>
2
+#include <assert.h>
3
+#include <realmode.h>
4
+#include <gateA20.h>
5
+#include <gpxe/uaccess.h>
6
+#include <gpxe/segment.h>
7
+#include <gpxe/image.h>
9 8
 
10 9
 /** @file
11 10
  *
@@ -22,6 +21,8 @@
22 21
  *
23 22
  */
24 23
 
24
+struct image_type nbi_image_type __image_type ( PROBE_NORMAL );
25
+
25 26
 /**
26 27
  * An NBI image header
27 28
  *
@@ -82,206 +83,185 @@ struct segheader {
82 83
 #define NBI_LOADADDR_BEFORE		0x03
83 84
 #define NBI_LAST_SEGHEADER(flags)	( (flags) & ( 1 << 2 ) )
84 85
 
86
+/* Define a type for passing info to a loaded program */
87
+struct ebinfo {
88
+	uint8_t  major, minor;  /* Version */
89
+	uint16_t flags;         /* Bit flags */
90
+};
91
+
85 92
 /** Info passed to NBI image */
86 93
 static struct ebinfo loaderinfo = {
87 94
 	VERSION_MAJOR, VERSION_MINOR,
88 95
 	0
89 96
 };
90 97
 
91
-/**
92
- * Determine whether or not this is a valid NBI image
93
- *
94
- * @v start		Address of the image
95
- * @v len		Length of the image
96
- * @v context		NBI image context
97
- * @ret	True		Image is a valid NBI image
98
- * @ret	False		Image is not a valid NBI image
99
- * @err	ENOEXEC		Image is not a valid NBI image
100
- * 
101
- * "context" is filled in with a context pointer suitable for passing to
102
- * nbi_load() and nbi_boot().
103
- *
104
- */
105
-static int nbi_probe ( physaddr_t start, off_t len, void **context ) {
106
-	static struct imgheader imgheader;
107
-
108
-	if ( (unsigned)len < sizeof ( imgheader ) ) {
109
-		DBG ( "NBI image too small\n" );
110
-		errno = ENOEXEC;
111
-		return 0;
112
-	}
113
-
114
-	copy_from_phys ( &imgheader, start, sizeof ( imgheader ) );
115
-
116
-	if ( imgheader.magic != NBI_MAGIC ) {
117
-		errno = ENOEXEC;
118
-		return 0;
119
-	}
120
-
121
-	/* Record image context */
122
-	DBG ( "NBI found valid image\n" );
123
-	*context = &imgheader;
124
-	return 1;
125
-}
126
-
127 98
 /**
128 99
  * Prepare a segment for an NBI image
129 100
  *
130
- * @v dest		Address of segment
131
- * @v imglen		Length of initialised-data portion of the segment
132
- * @v memlen		Total length of the segment
101
+ * @v image		NBI image
102
+ * @v offset		Offset within NBI image
103
+ * @v filesz		Length of initialised-data portion of the segment
104
+ * @v memsz		Total length of the segment
133 105
  * @v src		Source for initialised data
134
- * @ret True		Segment can be used
135
- * @ret False		Segment cannot be used
136
- * @err other		As returned by prep_segment()
137
- *
106
+ * @ret rc		Return status code
138 107
  */
139
-static int nbi_prepare_segment ( physaddr_t dest, off_t imglen, off_t memlen,
140
-				 physaddr_t src __unused ) {
141
-	DBG ( "NBI preparing segment [%x,%x) (imglen %d memlen %d)\n",
142
-	      dest, dest + memlen, imglen, memlen );
143
-	return prep_segment ( dest, dest + imglen, dest + memlen );
108
+static int nbi_prepare_segment ( struct image *image, size_t offset __unused,
109
+				 userptr_t dest, size_t filesz, size_t memsz ){
110
+	int rc;
111
+
112
+	if ( ( rc = prep_segment ( dest, filesz, memsz ) ) != 0 ) {
113
+		DBGC ( image, "NBI %p could not prepare segment: %s\n",
114
+		       image, strerror ( rc ) );
115
+		return rc;
116
+	}
117
+
118
+	return 0;
144 119
 }
145 120
 
146 121
 /**
147 122
  * Load a segment for an NBI image
148 123
  *
149
- * @v dest		Address of segment
150
- * @v imglen		Length of initialised-data portion of the segment
151
- * @v memlen		Total length of the segment
124
+ * @v image		NBI image
125
+ * @v offset		Offset within NBI image
126
+ * @v filesz		Length of initialised-data portion of the segment
127
+ * @v memsz		Total length of the segment
152 128
  * @v src		Source for initialised data
153
- * @ret True		Always
154
- *
129
+ * @ret rc		Return status code
155 130
  */
156
-static int nbi_load_segment ( physaddr_t dest, off_t imglen,
157
-			      off_t memlen __unused, physaddr_t src ) {
158
-	DBG ( "NBI loading segment [%x,%x)\n", dest, dest + imglen );
159
-	copy_phys_to_phys ( dest, src, imglen );
160
-	return 1;
131
+static int nbi_load_segment ( struct image *image, size_t offset,
132
+			      userptr_t dest, size_t filesz,
133
+			      size_t memsz __unused ) {
134
+	memcpy_user ( dest, 0, image->data, offset, filesz );
135
+	return 0;
161 136
 }
162 137
 
163 138
 /**
164 139
  * Process segments of an NBI image
165 140
  *
166
- * @v start		Address of the image
167
- * @v len		Length of the image
141
+ * @v image		NBI image
168 142
  * @v imgheader		Image header information
169 143
  * @v process		Function to call for each segment
170
- * @ret True		All segments were processed successfully
171
- * @ret False		An error occurred processing a segment
172
- * @err ENOEXEC		Image is not a valid NBI image
173
- * @err other		As returned by the "process" function
174
- *
144
+ * @ret rc		Return status code
175 145
  */
176
-static int nbi_process_segments ( physaddr_t start, off_t len,
146
+static int nbi_process_segments ( struct image *image,
177 147
 				  struct imgheader *imgheader,
178
-				  int ( * process ) ( physaddr_t dest,
179
-						      off_t imglen,
180
-						      off_t memlen,
181
-						      physaddr_t src ) ) {
148
+				  int ( * process ) ( struct image *image,
149
+						      size_t offset,
150
+						      userptr_t dest,
151
+						      size_t filesz,
152
+						      size_t memsz ) ) {
182 153
 	struct segheader sh;
183
-	off_t offset = 0;
184
-	off_t sh_off;
185
-	physaddr_t dest;
186
-	off_t dest_imglen, dest_memlen;
154
+	size_t offset = 0;
155
+	size_t sh_off;
156
+	userptr_t dest;
157
+	size_t filesz;
158
+	size_t memsz;
159
+	int rc;
187 160
 	
188
-	/* Copy header to target location */
189
-	dest = ( ( imgheader->location.segment << 4 ) +
190
-		 imgheader->location.offset );
191
-	dest_imglen = dest_memlen = NBI_HEADER_LENGTH;
192
-	if ( ! process ( dest, dest_imglen, dest_memlen, start + offset ) )
193
-		return 0;
194
-	offset += dest_imglen;
161
+	/* Copy image header to target location */
162
+	dest = real_to_user ( imgheader->location.segment,
163
+			      imgheader->location.offset );
164
+	filesz = memsz = NBI_HEADER_LENGTH;
165
+	if ( ( rc = process ( image, offset, dest, filesz, memsz ) ) != 0 )
166
+		return rc;
167
+	offset += filesz;
195 168
 
196 169
 	/* Process segments in turn */
197 170
 	sh_off = NBI_LENGTH ( imgheader->length );
198 171
 	do {
199 172
 		/* Read segment header */
200
-		copy_from_phys ( &sh, start + sh_off, sizeof ( sh ) );
173
+		copy_from_user ( &sh, image->data, sh_off, sizeof ( sh ) );
201 174
 		if ( sh.length == 0 ) {
202 175
 			/* Avoid infinite loop? */
203
-			DBG ( "NBI invalid segheader length 0\n" );
204
-			errno = ENOEXEC;
205
-			return 0;
176
+			DBGC ( image, "NBI %p invalid segheader length 0\n",
177
+			       image );
178
+			return -ENOEXEC;
206 179
 		}
207 180
 		
208 181
 		/* Calculate segment load address */
209 182
 		switch ( NBI_LOADADDR_FLAGS ( sh.flags ) ) {
210 183
 		case NBI_LOADADDR_ABS:
211
-			dest = sh.loadaddr;
184
+			dest = phys_to_user ( sh.loadaddr );
212 185
 			break;
213 186
 		case NBI_LOADADDR_AFTER:
214
-			dest = dest + dest_memlen + sh.loadaddr;
187
+			dest = userptr_add ( dest, memsz + sh.loadaddr );
215 188
 			break;
216 189
 		case NBI_LOADADDR_BEFORE:
217
-			dest = dest - sh.loadaddr;
190
+			dest = userptr_add ( dest, -sh.loadaddr );
218 191
 			break;
219 192
 		case NBI_LOADADDR_END:
220 193
 			/* Not correct according to the spec, but
221 194
 			 * maintains backwards compatibility with
222 195
 			 * previous versions of Etherboot.
223 196
 			 */
224
-			dest = ( meminfo.memsize * 1024 + 0x100000UL )
225
-				- sh.loadaddr;
197
+			dest = phys_to_user ( ( extmemsize() + 1024 ) * 1024
198
+					      - sh.loadaddr );
226 199
 			break;
227 200
 		default:
228 201
 			/* Cannot be reached */
229
-			DBG ( "NBI can't count up to three!\n" );
202
+			assert ( 0 );
230 203
 		}
231 204
 
232 205
 		/* Process this segment */
233
-		dest_imglen = sh.imglength;
234
-		dest_memlen = sh.memlength;
235
-		if ( ! process ( dest, dest_imglen, dest_memlen,
236
-				 start + offset ) )
237
-			return 0;
238
-		offset += dest_imglen;
206
+		filesz = sh.imglength;
207
+		memsz = sh.memlength;
208
+		if ( ( offset + filesz ) > image->len ) {
209
+			DBGC ( image, "NBI %p segment outside file\n", image );
210
+			return -ENOEXEC;
211
+		}
212
+		if ( ( rc = process ( image, offset, dest,
213
+				      filesz, memsz ) ) != 0 ) {
214
+			return rc;
215
+		}
216
+		offset += filesz;
239 217
 
240 218
 		/* Next segheader */
241 219
 		sh_off += NBI_LENGTH ( sh.length );
242 220
 		if ( sh_off >= NBI_HEADER_LENGTH ) {
243
-			DBG ( "NBI header overflow\n" );
244
-			errno = ENOEXEC;
245
-			return 0;
221
+			DBGC ( image, "NBI %p header overflow\n", image );
222
+			return -ENOEXEC;
246 223
 		}
247 224
 
248 225
 	} while ( ! NBI_LAST_SEGHEADER ( sh.flags ) );
249 226
 
250
-	if ( offset != len ) {
251
-		DBG ( "NBI length mismatch (file %d, metadata %d)\n",
252
-		      len, offset );
253
-		errno = ENOEXEC;
254
-		return 0;
227
+	if ( offset != image->len ) {
228
+		DBGC ( image, "NBI %p length wrong (file %d, metadata %d)\n",
229
+		       image, image->len, offset );
230
+		return -ENOEXEC;
255 231
 	}
256 232
 
257
-	return 1;
233
+	return 0;
258 234
 }
259 235
 
260 236
 /**
261 237
  * Load an NBI image into memory
262 238
  *
263
- * @v start		Address of image
264
- * @v len		Length of image
265
- * @v context		NBI context (as returned by nbi_probe())
266
- * @ret True		Image loaded into memory
267
- * @ret False		Image not loaded into memory
268
- * @err ENOEXEC		Image is not a valid NBI image
269
- * @err other		As returned by nbi_process_segments()
270
- * @err other		As returned by nbi_prepare_segment()
271
- * @err other		As returned by nbi_load_segment()
272
- *
239
+ * @v image		NBI image
240
+ * @ret rc		Return status code
273 241
  */
274
-static int nbi_load ( physaddr_t start, off_t len, void *context ) {
275
-	struct imgheader *imgheader = context;
242
+int nbi_load ( struct image *image ) {
243
+	struct imgheader imgheader;
244
+	int rc;
276 245
 
277 246
 	/* If we don't have enough data give up */
278
-	if ( len < NBI_HEADER_LENGTH ) {
279
-		errno = ENOEXEC;
280
-		return 0;
247
+	if ( image->len < NBI_HEADER_LENGTH ) {
248
+		DBGC ( image, "NBI %p too short for an NBI image\n", image );
249
+		return -ENOEXEC;
250
+	}
251
+
252
+	/* Check image header */
253
+	copy_from_user ( &imgheader, image->data, 0, sizeof ( imgheader ) );
254
+	if ( imgheader.magic != NBI_MAGIC ) {
255
+		DBGC ( image, "NBI %p has no NBI signature\n", image );
256
+		return -ENOEXEC;
281 257
 	}
282
-	
283
-	DBG ( "NBI placing header at %hx:%hx\n",
284
-	      imgheader->location.segment, imgheader->location.offset );
258
+
259
+	/* This is an NBI image, valid or otherwise */
260
+	if ( ! image->type )
261
+		image->type = &nbi_image_type;
262
+
263
+	DBGC ( image, "NBI %p placing header at %hx:%hx\n", image,
264
+	       imgheader.location.segment, imgheader.location.offset );
285 265
 
286 266
 	/* NBI files can have overlaps between segments; the bss of
287 267
 	 * one segment may overlap the initialised data of another.  I
@@ -290,14 +270,14 @@ static int nbi_load ( physaddr_t start, off_t len, void *context ) {
290 270
 	 * passes: first to initialise the segments, then to copy the
291 271
 	 * data.  This avoids zeroing out already-copied data.
292 272
 	 */
293
-	if ( ! nbi_process_segments ( start, len, imgheader,
294
-				      nbi_prepare_segment ) )
295
-		return 0;
296
-	if ( ! nbi_process_segments ( start, len, imgheader,
297
-				      nbi_load_segment ) )
298
-		return 0;
299
-
300
-	return 1;
273
+	if ( ( rc = nbi_process_segments ( image, &imgheader,
274
+					   nbi_prepare_segment ) ) != 0 )
275
+		return rc;
276
+	if ( ( rc = nbi_process_segments ( image, &imgheader,
277
+					   nbi_load_segment ) ) != 0 )
278
+		return rc;
279
+
280
+	return 0;
301 281
 }
302 282
 
303 283
 /**
@@ -309,40 +289,34 @@ static int nbi_load ( physaddr_t start, off_t len, void *context ) {
309 289
  * @err ECANCELED	NBI program returned
310 290
  *
311 291
  */
312
-static int nbi_boot16 ( struct imgheader *imgheader ) {
313
-	uint16_t basemem_bootp;
292
+static int nbi_boot16 ( struct image *image, struct imgheader *imgheader ) {
314 293
 	int discard_D, discard_S, discard_b;
315 294
 
316
-	DBG ( "NBI executing 16-bit image at %hx:%hx\n",
317
-	      imgheader->execaddr.segoff.segment,
318
-	      imgheader->execaddr.segoff.offset );
295
+	DBGC ( image, "NBI %p executing 16-bit image at %04x:%04x\n", image,
296
+	       imgheader->execaddr.segoff.segment,
297
+	       imgheader->execaddr.segoff.offset );
319 298
 
320 299
 	gateA20_unset();
321 300
 
322
-	basemem_bootp = BASEMEM_PARAMETER_INIT ( bootp_data );
323
-	REAL_EXEC ( rm_xstart16,
324
-		    "pushw %%ds\n\t"	/* far pointer to bootp data copy */
325
-		    "pushw %%bx\n\t"
326
-		    "pushl %%esi\n\t"	/* location */
327
-		    "pushw %%cs\n\t"	/* lcall execaddr */
328
-		    "call 1f\n\t"
329
-		    "jmp 2f\n\t"
330
-		    "\n1:\n\t"
331
-		    "pushl %%edi\n\t"
332
-		    "lret\n\t"
333
-		    "\n2:\n\t"
334
-		    "addw $8,%%sp\n\t",	/* pop location and bootp ptr */
335
-		    3,
336
-		    OUT_CONSTRAINTS ( "=D" ( discard_D ), "=S" ( discard_S ),
337
-				      "=b" ( discard_b ) ),
338
-		    IN_CONSTRAINTS ( "D" ( imgheader->execaddr.segoff ),
339
-				     "S" ( imgheader->location ),
340
-				     "b" ( basemem_bootp ) ),
341
-		    CLOBBER ( "eax", "ecx", "edx", "ebp" ) );
342
-	BASEMEM_PARAMETER_DONE ( bootp_data );
301
+#warning "Should be providing bootp data"
302
+	__asm__ __volatile__ (
303
+		REAL_CODE ( "pushw %%ds\n\t"	/* far pointer to bootp data */
304
+			    "pushw %%bx\n\t"
305
+			    "pushl %%esi\n\t"	/* location */
306
+			    "pushw %%cs\n\t"	/* lcall execaddr */
307
+			    "call 1f\n\t"
308
+			    "jmp 2f\n\t"
309
+			    "\n1:\n\t"
310
+			    "pushl %%edi\n\t"
311
+			    "lret\n\t"
312
+			    "\n2:\n\t"
313
+			    "addw $8,%%sp\n\t"	/* clean up stack */ )
314
+		: "=D" ( discard_D ), "=S" ( discard_S ), "=b" ( discard_b )
315
+		: "D" ( imgheader->execaddr.segoff ),
316
+		  "S" ( imgheader->location ), "b" ( 0 /* bootp data */ )
317
+		: "eax", "ecx", "edx", "ebp" );
343 318
 	
344
-	errno = ECANCELED;
345
-	return 0;
319
+	return -ECANCELED;
346 320
 }
347 321
 
348 322
 /**
@@ -359,57 +333,56 @@ static int nbi_boot16 ( struct imgheader *imgheader ) {
359 333
  * have returned.
360 334
  *
361 335
  */
362
-static int nbi_boot32 ( struct imgheader *imgheader ) {
363
-	int rc = 0;
336
+static int nbi_boot32 ( struct image *image, struct imgheader *imgheader ) {
337
+	int rc;
364 338
 
365
-	DBG ( "NBI executing 32-bit image at %x\n",
366
-	      imgheader->execaddr.linear );
339
+	DBGC ( image, "NBI %p executing 32-bit image at %lx\n",
340
+	       image, imgheader->execaddr.linear );
367 341
 
368 342
 	/* no gateA20_unset for PM call */
369
-	errno = ENOERR;
343
+
344
+#warning "Should be providing bootp data"
345
+#warning "xstart32 no longer exists"
346
+#if 0
370 347
 	rc = xstart32 ( imgheader->execaddr.linear,
371 348
 			virt_to_phys ( &loaderinfo ),
372 349
 			( ( imgheader->location.segment << 4 ) +
373 350
 			  imgheader->location.offset ),
374
-			virt_to_phys ( &bootp_data ) );
375
-	printf ( "Secondary program returned %d\n", rc );
351
+			0 /* bootp data */ );
352
+#endif
353
+
354
+	DBGC ( image, "NBI %p returned %d\n", image, rc );
355
+
376 356
 	if ( ! NBI_PROGRAM_RETURNS ( imgheader->flags ) ) {
377 357
 		/* We shouldn't have returned */
378
-		errno = ECANCELED;
379
-		rc = 0;
358
+		rc = -ECANCELED;
380 359
 	}
381 360
 
382 361
 	return rc;
383 362
 }
384 363
 
385 364
 /**
386
- * Boot a loaded NBI image
387
- *
388
- * @v context		NBI context (as returned by nbi_probe())
389
- * @ret Never		NBI program booted successfully
390
- * @ret False		NBI program should not have returned
391
- * @ret other		As returned by NBI program
392
- * @err ECANCELED	NBI program should not have returned
393
- *
394
- * See also nbi_boot16() and nbi_boot32().
365
+ * Execute a loaded NBI image
395 366
  *
367
+ * @v image		NBI image
368
+ * @ret rc		Return status code
396 369
  */
397
-static int nbi_boot ( void *context ) {
398
-	struct imgheader *imgheader = context;
370
+static int nbi_exec ( struct image *image ) {
371
+	struct imgheader imgheader;
399 372
 
400
-	if ( NBI_LINEAR_EXEC_ADDR ( imgheader->flags ) ) {
401
-		return nbi_boot32 ( imgheader );
373
+	copy_from_user ( &imgheader, phys_to_user ( image->entry ), 0,
374
+			 sizeof ( imgheader ) );
375
+
376
+	if ( NBI_LINEAR_EXEC_ADDR ( imgheader.flags ) ) {
377
+		return nbi_boot32 ( image, &imgheader );
402 378
 	} else {
403
-		return nbi_boot16 ( imgheader );
379
+		return nbi_boot16 ( image, &imgheader );
404 380
 	}
405 381
 }
406 382
 
407
-/** Declaration of the NBI image format */
408
-struct image nbi_image __image = {
409
-	.name	= "NBI",
410
-	.probe	= nbi_probe,
411
-	.load	= nbi_load,
412
-	.boot	= nbi_boot,
383
+/** NBI image type */
384
+struct image_type nbi_image_type __image_type ( PROBE_NORMAL ) = {
385
+	.name = "NBI",
386
+	.load = nbi_load,
387
+	.exec = nbi_exec,
413 388
 };
414
-
415
-#endif

Loading…
Cancel
Save