Browse Source

Split bootsector execution code out into bootsector.c.

Added basic El Torito ISO image boot capability
tags/v0.9.3
Michael Brown 18 years ago
parent
commit
2cf1e33df1

+ 111
- 0
src/arch/i386/image/bootsector.c View File

@@ -0,0 +1,111 @@
1
+/*
2
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
3
+ *
4
+ * This program is free software; you can redistribute it and/or
5
+ * modify it under the terms of the GNU General Public License as
6
+ * published by the Free Software Foundation; either version 2 of the
7
+ * License, or any later version.
8
+ *
9
+ * This program is distributed in the hope that it will be useful, but
10
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
+ * General Public License for more details.
13
+ *
14
+ * You should have received a copy of the GNU General Public License
15
+ * along with this program; if not, write to the Free Software
16
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
+ */
18
+
19
+/**
20
+ * @file
21
+ *
22
+ * x86 bootsector image format
23
+ *
24
+ */
25
+
26
+#include <errno.h>
27
+#include <realmode.h>
28
+#include <biosint.h>
29
+#include <bootsector.h>
30
+
31
+/** Vector for storing original INT 18 handler
32
+ *
33
+ * We do not chain to this vector, so there is no need to place it in
34
+ * .text16.
35
+ */
36
+static struct segoff int18_vector;
37
+
38
+/** Vector for storing original INT 19 handler
39
+ *
40
+ * We do not chain to this vector, so there is no need to place it in
41
+ * .text16.
42
+ */
43
+static struct segoff int19_vector;
44
+
45
+/** Restart point for INT 18 or 19 */
46
+extern void bootsector_exec_fail ( void );
47
+
48
+/**
49
+ * Jump to preloaded bootsector
50
+ *
51
+ * @v segment		Real-mode segment
52
+ * @v offset		Real-mode offset
53
+ * @v drive		Drive number to pass to boot sector
54
+ * @ret rc		Return status code
55
+ */
56
+int call_bootsector ( unsigned int segment, unsigned int offset,
57
+		      unsigned int drive ) {
58
+	int discard_b, discard_D, discard_d;
59
+
60
+	DBG ( "Booting from boot sector at %04x:%04x\n", segment, offset );
61
+
62
+	/* Hook INTs 18 and 19 to capture failure paths */
63
+	hook_bios_interrupt ( 0x18, ( unsigned int ) bootsector_exec_fail,
64
+			      &int18_vector );
65
+	hook_bios_interrupt ( 0x19, ( unsigned int ) bootsector_exec_fail,
66
+			      &int19_vector );
67
+
68
+	/* Boot the loaded sector
69
+	 *
70
+	 * We assume that the boot sector may completely destroy our
71
+	 * real-mode stack, so we preserve everything we need in
72
+	 * static storage.
73
+	 */
74
+	__asm__ __volatile__ ( REAL_CODE ( /* Save return address off-stack */
75
+					   "popw %%cs:saved_retaddr\n\t"
76
+					   /* Save stack pointer */
77
+					   "movw %%ss, %%ax\n\t"
78
+					   "movw %%ax, %%cs:saved_ss\n\t"
79
+					   "movw %%sp, %%cs:saved_sp\n\t"
80
+					   /* Jump to boot sector */
81
+					   "pushw %%bx\n\t"
82
+					   "pushw %%di\n\t"
83
+					   "lret\n\t"
84
+					   /* Preserved variables */
85
+					   "\nsaved_ss: .word 0\n\t"
86
+					   "\nsaved_sp: .word 0\n\t"
87
+					   "\nsaved_retaddr: .word 0\n\t"
88
+					   /* Boot failure return point */
89
+					   "\nbootsector_exec_fail:\n\t"
90
+					   /* Restore stack pointer */
91
+					   "movw %%cs:saved_ss, %%ax\n\t"
92
+					   "movw %%ax, %%ss\n\t"
93
+					   "movw %%cs:saved_sp, %%sp\n\t"
94
+					   /* Return via saved address */
95
+					   "jmp *%%cs:saved_retaddr\n\t" )
96
+			       : "=b" ( discard_b ), "=D" ( discard_D ),
97
+			         "=d" ( discard_d )
98
+			       : "b" ( segment ), "D" ( offset ),
99
+			         "d" ( drive )
100
+			       : "eax", "ecx", "esi", "ebp" );
101
+
102
+	DBG ( "Booted disk returned via INT 18 or 19\n" );
103
+
104
+	/* Unhook INTs 18 and 19 */
105
+	unhook_bios_interrupt ( 0x18, ( unsigned int ) bootsector_exec_fail,
106
+				&int18_vector );
107
+	unhook_bios_interrupt ( 0x19, ( unsigned int ) bootsector_exec_fail,
108
+				&int19_vector );
109
+	
110
+	return -ECANCELED;
111
+}

+ 334
- 0
src/arch/i386/image/eltorito.c View File

@@ -0,0 +1,334 @@
1
+/*
2
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
3
+ *
4
+ * This program is free software; you can redistribute it and/or
5
+ * modify it under the terms of the GNU General Public License as
6
+ * published by the Free Software Foundation; either version 2 of the
7
+ * License, or any later version.
8
+ *
9
+ * This program is distributed in the hope that it will be useful, but
10
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
+ * General Public License for more details.
13
+ *
14
+ * You should have received a copy of the GNU General Public License
15
+ * along with this program; if not, write to the Free Software
16
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
+ */
18
+
19
+/**
20
+ * @file
21
+ *
22
+ * El Torito bootable ISO image format
23
+ *
24
+ */
25
+
26
+#include <stdint.h>
27
+#include <errno.h>
28
+#include <assert.h>
29
+#include <realmode.h>
30
+#include <bootsector.h>
31
+#include <int13.h>
32
+#include <gpxe/uaccess.h>
33
+#include <gpxe/image.h>
34
+#include <gpxe/segment.h>
35
+#include <gpxe/ramdisk.h>
36
+#include <gpxe/shutdown.h>
37
+
38
+#define ISO9660_BLKSIZE 2048
39
+#define ELTORITO_VOL_DESC_OFFSET ( 17 * ISO9660_BLKSIZE )
40
+
41
+/** An El Torito Boot Record Volume Descriptor */
42
+struct eltorito_vol_desc {
43
+	/** Boot record indicator; must be 0 */
44
+	uint8_t record_indicator;
45
+	/** ISO-9660 identifier; must be "CD001" */
46
+	uint8_t iso9660_id[5];
47
+	/** Version, must be 1 */
48
+	uint8_t version;
49
+	/** Boot system indicator; must be "EL TORITO SPECIFICATION" */
50
+	uint8_t system_indicator[32];
51
+	/** Unused */
52
+	uint8_t unused[32];
53
+	/** Boot catalog sector */
54
+	uint32_t sector;
55
+} __attribute__ (( packed ));
56
+
57
+/** An El Torito Boot Catalog Validation Entry */
58
+struct eltorito_validation_entry {
59
+	/** Header ID; must be 1 */
60
+	uint8_t header_id;
61
+	/** Platform ID
62
+	 *
63
+	 * 0 = 80x86
64
+	 * 1 = PowerPC
65
+	 * 2 = Mac
66
+	 */
67
+	uint8_t platform_id;
68
+	/** Reserved */
69
+	uint16_t reserved;
70
+	/** ID string */
71
+	uint8_t id_string[24];
72
+	/** Checksum word */
73
+	uint16_t checksum;
74
+	/** Signature; must be 0xaa55 */
75
+	uint16_t signature;
76
+} __attribute__ (( packed ));
77
+
78
+/** A bootable entry in the El Torito Boot Catalog */
79
+struct eltorito_boot_entry {
80
+	/** Boot indicator
81
+	 *
82
+	 * Must be @c ELTORITO_BOOTABLE for a bootable ISO image
83
+	 */
84
+	uint8_t indicator;
85
+	/** Media type
86
+	 *
87
+	 */
88
+	uint8_t media_type;
89
+	/** Load segment */
90
+	uint16_t load_segment;
91
+	/** System type */
92
+	uint8_t filesystem;
93
+	/** Unused */
94
+	uint8_t reserved_a;
95
+	/** Sector count */
96
+	uint16_t length;
97
+	/** Starting sector */
98
+	uint32_t start;
99
+	/** Unused */
100
+	uint8_t reserved_b[20];
101
+} __attribute__ (( packed ));
102
+
103
+/** Boot indicator for a bootable ISO image */
104
+#define ELTORITO_BOOTABLE 0x88
105
+
106
+/** El Torito media types */
107
+enum eltorito_media_type {
108
+	/** No emulation */
109
+	ELTORITO_NO_EMULATION = 0,
110
+};
111
+
112
+struct image_type eltorito_image_type __image_type ( PROBE_NORMAL );
113
+
114
+/**
115
+ * Calculate 16-bit word checksum
116
+ *
117
+ * @v data		Data to checksum
118
+ * @v len		Length (in bytes, must be even)
119
+ * @ret sum		Checksum
120
+ */
121
+static unsigned int word_checksum ( void *data, size_t len ) {
122
+	uint16_t *words;
123
+	uint16_t sum = 0;
124
+
125
+	for ( words = data ; len ; words++, len -= 2 ) {
126
+		sum += *words;
127
+	}
128
+	return sum;
129
+}
130
+
131
+/**
132
+ * Execute El Torito image
133
+ *
134
+ * @v image		El Torito image
135
+ * @ret rc		Return status code
136
+ */
137
+static int eltorito_exec ( struct image *image ) {
138
+	struct ramdisk ramdisk;
139
+	struct int13_drive int13_drive;
140
+	unsigned int load_segment = image->priv.ul;
141
+	unsigned int load_offset = ( load_segment ? 0 : 0x7c00 );
142
+	int rc;
143
+
144
+	memset ( &ramdisk, 0, sizeof ( ramdisk ) );
145
+	init_ramdisk ( &ramdisk, image->data, image->len, ISO9660_BLKSIZE );
146
+	
147
+	memset ( &int13_drive, 0, sizeof ( int13_drive ) );
148
+	int13_drive.blockdev = &ramdisk.blockdev;
149
+	register_int13_drive ( &int13_drive );
150
+
151
+	if ( ( rc = call_bootsector ( load_segment, load_offset, 
152
+				      int13_drive.drive ) ) != 0 ) {
153
+		DBGC ( image, "ElTorito %p boot failed: %s\n",
154
+		       image, strerror ( rc ) );
155
+		goto err;
156
+	}
157
+	
158
+	rc = -ECANCELED; /* -EIMPOSSIBLE */
159
+ err:
160
+	unregister_int13_drive ( &int13_drive );
161
+	return rc;
162
+}
163
+
164
+/**
165
+ * Read and verify El Torito Boot Record Volume Descriptor
166
+ *
167
+ * @v image		El Torito file
168
+ * @ret catalog_offset	Offset of Boot Catalog
169
+ * @ret rc		Return status code
170
+ */
171
+static int eltorito_read_voldesc ( struct image *image,
172
+				   unsigned long *catalog_offset ) {
173
+	static const struct eltorito_vol_desc vol_desc_signature = {
174
+		.record_indicator = 0,
175
+		.iso9660_id = "CD001",
176
+		.version = 1,
177
+		.system_indicator = "EL TORITO SPECIFICATION",
178
+	};
179
+	struct eltorito_vol_desc vol_desc;
180
+
181
+	/* Sanity check */
182
+	if ( image->len < ( ELTORITO_VOL_DESC_OFFSET + ISO9660_BLKSIZE ) ) {
183
+		DBGC ( image, "ElTorito %p too short\n", image );
184
+		return -ENOEXEC;
185
+	}
186
+
187
+	/* Read and verify Boot Record Volume Descriptor */
188
+	copy_from_user ( &vol_desc, image->data, ELTORITO_VOL_DESC_OFFSET,
189
+			 sizeof ( vol_desc ) );
190
+	if ( memcmp ( &vol_desc, &vol_desc_signature,
191
+		      offsetof ( typeof ( vol_desc ), sector ) ) != 0 ) {
192
+		DBGC ( image, "ElTorito %p invalid Boot Record Volume "
193
+		       "Descriptor\n", image );
194
+		return -ENOEXEC;
195
+	}
196
+	*catalog_offset = ( vol_desc.sector * ISO9660_BLKSIZE );
197
+
198
+	DBGC ( image, "ElTorito %p boot catalog at offset %#lx\n",
199
+	       image, *catalog_offset );
200
+
201
+	return 0;
202
+}
203
+
204
+/**
205
+ * Read and verify El Torito Boot Catalog
206
+ *
207
+ * @v image		El Torito file
208
+ * @v catalog_offset	Offset of Boot Catalog
209
+ * @ret boot_entry	El Torito boot entry
210
+ * @ret rc		Return status code
211
+ */
212
+static int eltorito_read_catalog ( struct image *image,
213
+				   unsigned long catalog_offset,
214
+				   struct eltorito_boot_entry *boot_entry ) {
215
+	struct eltorito_validation_entry validation_entry;
216
+
217
+	/* Sanity check */
218
+	if ( image->len < ( catalog_offset + ISO9660_BLKSIZE ) ) {
219
+		DBGC ( image, "ElTorito %p bad boot catalog offset %#lx\n",
220
+		       image, catalog_offset );
221
+		return -ENOEXEC;
222
+	}
223
+
224
+	/* Read and verify the Validation Entry of the Boot Catalog */
225
+	copy_from_user ( &validation_entry, image->data, catalog_offset,
226
+			 sizeof ( validation_entry ) );
227
+	if ( word_checksum ( &validation_entry,
228
+			     sizeof ( validation_entry ) ) != 0 ) {
229
+		DBGC ( image, "ElTorito %p bad Validation Entry checksum\n",
230
+		       image );
231
+		return -ENOEXEC;
232
+	}
233
+
234
+	/* Read and verify the Initial/Default entry */
235
+	copy_from_user ( boot_entry, image->data,
236
+			 ( catalog_offset + sizeof ( validation_entry ) ),
237
+			 sizeof ( *boot_entry ) );
238
+	if ( boot_entry->indicator != ELTORITO_BOOTABLE ) {
239
+		DBGC ( image, "ElTorito %p not bootable\n", image );
240
+		return -ENOEXEC;
241
+	}
242
+	if ( boot_entry->media_type != ELTORITO_NO_EMULATION ) {
243
+		DBGC ( image, "ElTorito %p cannot support media type %d\n",
244
+		       image, boot_entry->media_type );
245
+		return -ENOTSUP;
246
+	}
247
+
248
+	DBGC ( image, "ElTorito %p media type %d segment %04x\n",
249
+	       image, boot_entry->media_type, boot_entry->load_segment );
250
+
251
+	return 0;
252
+}
253
+
254
+/**
255
+ * Load El Torito virtual disk image into memory
256
+ *
257
+ * @v image		El Torito file
258
+ * @v boot_entry	El Torito boot entry
259
+ * @ret rc		Return status code
260
+ */
261
+static int eltorito_load_disk ( struct image *image,
262
+				struct eltorito_boot_entry *boot_entry ) {
263
+	unsigned long start = ( boot_entry->start * ISO9660_BLKSIZE );
264
+	unsigned long length = ( boot_entry->length * ISO9660_BLKSIZE );
265
+	unsigned int load_segment;
266
+	userptr_t buffer;
267
+	int rc;
268
+
269
+	/* Sanity check */
270
+	if ( image->len < ( start + length ) ) {
271
+		DBGC ( image, "ElTorito %p virtual disk lies outside image\n",
272
+		       image );
273
+		return -ENOEXEC;
274
+	}
275
+	DBGC ( image, "ElTorito %p virtual disk at %#lx+%#lx\n",
276
+	       image, start, length );
277
+
278
+	/* Calculate load address */
279
+	load_segment = boot_entry->load_segment;
280
+	buffer = real_to_user ( load_segment, ( load_segment ? 0 : 0x7c00 ) );
281
+
282
+	/* Verify and prepare segment */
283
+	if ( ( rc = prep_segment ( buffer, length, length ) ) != 0 ) {
284
+		DBGC ( image, "ElTorito %p could not prepare segment: %s\n",
285
+		       image, strerror ( rc ) );
286
+		return rc;
287
+	}
288
+
289
+	/* Copy image to segment */
290
+	memcpy_user ( buffer, 0, image->data, start, length );
291
+
292
+	return 0;
293
+}
294
+
295
+/**
296
+ * Load El Torito image into memory
297
+ *
298
+ * @v image		El Torito file
299
+ * @ret rc		Return status code
300
+ */
301
+int eltorito_load ( struct image *image ) {
302
+	struct eltorito_boot_entry boot_entry;
303
+	unsigned long bootcat_offset;
304
+	int rc;
305
+
306
+	/* Read Boot Record Volume Descriptor, if present */
307
+	if ( ( rc = eltorito_read_voldesc ( image, &bootcat_offset ) ) != 0 )
308
+		return rc;
309
+
310
+	/* This is an El Torito image, valid or otherwise */
311
+	if ( ! image->type )
312
+		image->type = &eltorito_image_type;
313
+
314
+	/* Read Boot Catalog */
315
+	if ( ( rc = eltorito_read_catalog ( image, bootcat_offset,
316
+					    &boot_entry ) ) != 0 )
317
+		return rc;
318
+
319
+	/* Load Virtual Disk image */
320
+	if ( ( rc = eltorito_load_disk ( image, &boot_entry ) ) != 0 )
321
+		return rc;
322
+
323
+	/* Record load segment in image private data field */
324
+	image->priv.ul = boot_entry.load_segment;
325
+
326
+	return 0;
327
+}
328
+
329
+/** El Torito image type */
330
+struct image_type eltorito_image_type __image_type ( PROBE_NORMAL ) = {
331
+	.name = "El Torito",
332
+	.load = eltorito_load,
333
+	.exec = eltorito_exec,
334
+};

+ 12
- 0
src/arch/i386/include/bootsector.h View File

@@ -0,0 +1,12 @@
1
+#ifndef _BOOTSECTOR_H
2
+#define _BOOTSECTOR_H
3
+
4
+/** @file
5
+ *
6
+ * x86 bootsector image format
7
+ */
8
+
9
+extern int call_bootsector ( unsigned int segment, unsigned int offset,
10
+			     unsigned int drive );
11
+
12
+#endif /* _BOOTSECTOR_H */

+ 2
- 0
src/arch/i386/include/int13.h View File

@@ -37,6 +37,8 @@ struct block_device;
37 37
 #define INT13_EXTENDED_WRITE		0x43
38 38
 /** Get extended drive parameters */
39 39
 #define INT13_GET_EXTENDED_PARAMETERS	0x48
40
+/** Get CD-ROM status / terminate emulation */
41
+#define INT13_CDROM_STATUS_TERMINATE	0x4b
40 42
 
41 43
 /** @} */
42 44
 

+ 58
- 69
src/arch/i386/interface/pcbios/int13.c View File

@@ -26,6 +26,7 @@
26 26
 #include <realmode.h>
27 27
 #include <bios.h>
28 28
 #include <biosint.h>
29
+#include <bootsector.h>
29 30
 #include <int13.h>
30 31
 
31 32
 /** @file
@@ -44,23 +45,6 @@ static struct segoff __text16 ( int13_vector );
44 45
 /** Assembly wrapper */
45 46
 extern void int13_wrapper ( void );
46 47
 
47
-/** Vector for storing original INT 18 handler
48
- *
49
- * We do not chain to this vector, so there is no need to place it in
50
- * .text16.
51
- */
52
-static struct segoff int18_vector;
53
-
54
-/** Vector for storing original INT 19 handler
55
- *
56
- * We do not chain to this vector, so there is no need to place it in
57
- * .text16.
58
- */
59
-static struct segoff int19_vector;
60
-
61
-/** Restart point for INT 18 or 19 */
62
-extern void int13_exec_fail ( void );
63
-
64 48
 /** List of registered emulated drives */
65 49
 static LIST_HEAD ( drives );
66 50
 
@@ -114,6 +98,13 @@ static int int13_rw_sectors ( struct int13_drive *drive,
114 98
 	unsigned int count;
115 99
 	userptr_t buffer;
116 100
 
101
+	/* Validate blocksize */
102
+	if ( blockdev->blksize != INT13_BLKSIZE ) {
103
+		DBG ( "Invalid blocksize (%zd) for non-extended read/write\n",
104
+		      blockdev->blksize );
105
+		return -INT13_STATUS_INVALID;
106
+	}
107
+	
117 108
 	/* Calculate parameters */
118 109
 	cylinder = ( ( ( ix86->regs.cl & 0xc0 ) << 2 ) | ix86->regs.ch );
119 110
 	assert ( cylinder < drive->cylinders );
@@ -129,13 +120,6 @@ static int int13_rw_sectors ( struct int13_drive *drive,
129 120
 	DBG ( "C/H/S %d/%d/%d = LBA %#lx <-> %04x:%04x (count %d)\n", cylinder,
130 121
 	      head, sector, lba, ix86->segs.es, ix86->regs.bx, count );
131 122
 
132
-	/* Validate blocksize */
133
-	if ( blockdev->blksize != INT13_BLKSIZE ) {
134
-		DBG ( "Invalid blocksize (%zd) for non-extended read/write\n",
135
-		      blockdev->blksize );
136
-		return -INT13_STATUS_INVALID;
137
-	}
138
-	
139 123
 	/* Read from / write to block device */
140 124
 	if ( io ( blockdev, lba, count, buffer ) != 0 )
141 125
 		return -INT13_STATUS_READ_ERROR;
@@ -333,6 +317,38 @@ static int int13_get_extended_parameters ( struct int13_drive *drive,
333 317
 	return 0;
334 318
 }
335 319
 
320
+struct int13_cdrom_specification {
321
+	/** Size of packet in bytes */
322
+	uint8_t size;
323
+	/** Boot media type */
324
+	uint8_t media_type;
325
+	/** Drive number */
326
+	uint8_t drive;
327
+};
328
+
329
+/**
330
+ * INT 13, 4b - Get CD-ROM status / terminate emulation
331
+ *
332
+ * @v drive		Emulated drive
333
+ * @v ds:si		El Torito specification packet to fill in
334
+ * @ret status		Status code
335
+ */
336
+static int int13_cdrom_status_terminate ( struct int13_drive *drive,
337
+					  struct i386_all_regs *ix86 ) {
338
+	struct int13_cdrom_specification specification;
339
+
340
+	DBG ( "Get CD-ROM emulation parameters to %04x:%04x\n",
341
+	      ix86->segs.ds, ix86->regs.di );
342
+
343
+	memset ( &specification, 0, sizeof ( specification ) );
344
+	specification.size = sizeof ( specification );
345
+	specification.drive = drive->drive;
346
+
347
+	copy_to_real ( ix86->segs.ds, ix86->regs.si, &specification,
348
+		       sizeof ( specification ) );
349
+	return 0;
350
+}
351
+
336 352
 /**
337 353
  * INT 13 handler
338 354
  *
@@ -346,7 +362,7 @@ static void int13 ( struct i386_all_regs *ix86 ) {
346 362
 		if ( drive->drive != ix86->regs.dl )
347 363
 			continue;
348 364
 		
349
-		DBG ( "INT 13,%02x (%02x): ", command, drive->drive );
365
+		DBG ( "INT 13,%04x (%02x): ", ix86->regs.ax, drive->drive );
350 366
 
351 367
 		switch ( command ) {
352 368
 		case INT13_RESET:
@@ -379,6 +395,9 @@ static void int13 ( struct i386_all_regs *ix86 ) {
379 395
 		case INT13_GET_EXTENDED_PARAMETERS:
380 396
 			status = int13_get_extended_parameters ( drive, ix86 );
381 397
 			break;
398
+		case INT13_CDROM_STATUS_TERMINATE:
399
+			status = int13_cdrom_status_terminate ( drive, ix86 );
400
+			break;
382 401
 		default:
383 402
 			DBG ( "*** Unrecognised INT 13 ***\n" );
384 403
 			status = -INT13_STATUS_INVALID;
@@ -398,6 +417,8 @@ static void int13 ( struct i386_all_regs *ix86 ) {
398 417
 
399 418
 		/* Set OF to indicate to wrapper not to chain this call */
400 419
 		ix86->flags |= OF;
420
+
421
+		break;
401 422
 	}
402 423
 }
403 424
 
@@ -453,6 +474,10 @@ static void guess_int13_geometry ( struct int13_drive *drive ) {
453 474
 	unsigned long blocks_per_cyl;
454 475
 	unsigned int i;
455 476
 
477
+	/* Don't even try when the blksize is invalid for C/H/S access */
478
+	if ( drive->blockdev->blksize != INT13_BLKSIZE )
479
+		return;
480
+
456 481
 	/* Scan through partition table and modify guesses for heads
457 482
 	 * and sectors_per_track if we find any used partitions.
458 483
 	 */
@@ -564,6 +589,7 @@ void unregister_int13_drive ( struct int13_drive *drive ) {
564 589
 int int13_boot ( unsigned int drive ) {
565 590
 	int status, signature;
566 591
 	int discard_c, discard_d;
592
+	int rc;
567 593
 
568 594
 	DBG ( "Booting from INT 13 drive %02x\n", drive );
569 595
 
@@ -593,48 +619,11 @@ int int13_boot ( unsigned int drive ) {
593 619
 		return -ENOEXEC;
594 620
 	}
595 621
 
596
-	/* Hook INTs 18 and 19 to capture failure paths */
597
-	hook_bios_interrupt ( 0x18, ( unsigned int ) int13_exec_fail,
598
-			      &int18_vector );
599
-	hook_bios_interrupt ( 0x19, ( unsigned int ) int13_exec_fail,
600
-			      &int19_vector );
601
-
602
-	/* Boot the loaded sector
603
-	 *
604
-	 * We assume that the boot sector may completely destroy our
605
-	 * real-mode stack, so we preserve everything we need in
606
-	 * static storage.
607
-	 */
608
-	__asm__ __volatile__ ( REAL_CODE ( /* Save return address off-stack */
609
-					   "popw %%cs:int13_saved_retaddr\n\t"
610
-					   /* Save stack pointer */
611
-					   "movw %%ss, %%ax\n\t"
612
-					   "movw %%ax, %%cs:int13_saved_ss\n\t"
613
-					   "movw %%sp, %%cs:int13_saved_sp\n\t"
614
-					   /* Jump to boot sector */
615
-					   "ljmp $0, $0x7c00\n\t"
616
-					   /* Preserved variables */
617
-					   "\nint13_saved_ss: .word 0\n\t"
618
-					   "\nint13_saved_sp: .word 0\n\t"
619
-					   "\nint13_saved_retaddr: .word 0\n\t"
620
-					   /* Boot failure return point */
621
-					   "\nint13_exec_fail:\n\t"
622
-					   /* Restore stack pointer */
623
-					   "movw %%cs:int13_saved_ss, %%ax\n\t"
624
-					   "movw %%ax, %%ss\n\t"
625
-					   "movw %%cs:int13_saved_sp, %%sp\n\t"
626
-					   /* Return via saved address */
627
-					   "jmp *%%cs:int13_saved_retaddr\n\t")
628
-			       : "=d" ( discard_d ) : "d" ( drive )
629
-			       : "eax", "ebx", "ecx", "esi", "edi", "ebp" );
630
-
631
-	DBG ( "Booted disk returned via INT 18 or 19\n" );
632
-
633
-	/* Unhook INTs 18 and 19 */
634
-	unhook_bios_interrupt ( 0x18, ( unsigned int ) int13_exec_fail,
635
-				&int18_vector );
636
-	unhook_bios_interrupt ( 0x19, ( unsigned int ) int13_exec_fail,
637
-				&int19_vector );
638
-	
639
-	return -ECANCELED;
622
+	/* Jump to boot sector */
623
+	if ( ( rc = call_bootsector ( 0x0, 0x7c00, drive ) ) != 0 ) {
624
+		DBG ( "INT 13 drive %02x boot returned\n", drive );
625
+		return rc;
626
+	}
627
+
628
+	return -ECANCELED; /* -EIMPOSSIBLE */
640 629
 }

+ 3
- 0
src/core/config.c View File

@@ -143,6 +143,9 @@ REQUIRE_OBJECT ( script );
143 143
 #ifdef IMAGE_BZIMAGE
144 144
 REQUIRE_OBJECT ( bzimage );
145 145
 #endif
146
+#ifdef IMAGE_ELTORITO
147
+REQUIRE_OBJECT ( eltorito );
148
+#endif
146 149
 
147 150
 /*
148 151
  * Drag in all requested commands

+ 91
- 0
src/drivers/block/ramdisk.c View File

@@ -0,0 +1,91 @@
1
+/*
2
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
3
+ *
4
+ * This program is free software; you can redistribute it and/or
5
+ * modify it under the terms of the GNU General Public License as
6
+ * published by the Free Software Foundation; either version 2 of the
7
+ * License, or any later version.
8
+ *
9
+ * This program is distributed in the hope that it will be useful, but
10
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
+ * General Public License for more details.
13
+ *
14
+ * You should have received a copy of the GNU General Public License
15
+ * along with this program; if not, write to the Free Software
16
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
+ */
18
+
19
+#include <gpxe/blockdev.h>
20
+#include <gpxe/ramdisk.h>
21
+
22
+/**
23
+ * @file
24
+ *
25
+ * RAM disks
26
+ *
27
+ */
28
+
29
+static inline __attribute__ (( always_inline )) struct ramdisk *
30
+block_to_ramdisk ( struct block_device *blockdev ) {
31
+	return container_of ( blockdev, struct ramdisk, blockdev );
32
+}
33
+
34
+/**
35
+ * Read block
36
+ *
37
+ * @v blockdev		Block device
38
+ * @v block		Block number
39
+ * @v count		Block count
40
+ * @v buffer		Data buffer
41
+ * @ret rc		Return status code
42
+ */
43
+static int ramdisk_read ( struct block_device *blockdev, uint64_t block,
44
+			  unsigned long count, userptr_t buffer ) {
45
+	struct ramdisk *ramdisk = block_to_ramdisk ( blockdev );
46
+	unsigned long offset = ( block * blockdev->blksize );
47
+	unsigned long length = ( count * blockdev->blksize );
48
+
49
+	DBGC ( ramdisk, "RAMDISK %p reading [%lx,%lx)\n",
50
+	       ramdisk, offset, length );
51
+
52
+	memcpy_user ( buffer, 0, ramdisk->data, offset, length );
53
+	return 0;
54
+}
55
+
56
+/**
57
+ * Write block
58
+ *
59
+ * @v blockdev		Block device
60
+ * @v block		Block number
61
+ * @v count		Block count
62
+ * @v buffer		Data buffer
63
+ * @ret rc		Return status code
64
+ */
65
+static int ramdisk_write ( struct block_device *blockdev, uint64_t block,
66
+			   unsigned long count, userptr_t buffer ) {
67
+	struct ramdisk *ramdisk = block_to_ramdisk ( blockdev );
68
+	unsigned long offset = ( block * blockdev->blksize );
69
+	unsigned long length = ( count * blockdev->blksize );
70
+
71
+	DBGC ( ramdisk, "RAMDISK %p writing [%lx,%lx)\n",
72
+	       ramdisk, offset, length );
73
+
74
+	memcpy_user ( ramdisk->data, offset, buffer, 0, length );
75
+	return 0;
76
+}
77
+
78
+int init_ramdisk ( struct ramdisk *ramdisk, userptr_t data, size_t len,
79
+		   unsigned int blksize ) {
80
+	
81
+	if ( ! blksize )
82
+		blksize = 512;
83
+
84
+	ramdisk->data = data;
85
+	ramdisk->blockdev.read = ramdisk_read;
86
+	ramdisk->blockdev.write = ramdisk_write;
87
+	ramdisk->blockdev.blksize = blksize;
88
+	ramdisk->blockdev.blocks = ( len / blksize );
89
+
90
+	return 0;
91
+}

Loading…
Cancel
Save