Selaa lähdekoodia

[block] Replace gPXE block-device API with an iPXE asynchronous interface

The block device interface used in gPXE predates the invention of even
the old gPXE data-transfer interface, let alone the current iPXE
generic asynchronous interface mechanism.  Bring this old code up to
date, with the following benefits:

 o  Block device commands can be cancelled by the requestor.  The INT 13
    layer uses this to provide a global timeout on all INT 13 calls,
    with the result that an unexpected passive failure mode (such as
    an iSCSI target ACKing the request but never sending a response)
    will lead to a timeout that gets reported back to the INT 13 user,
    rather than simply freezing the system.

 o  INT 13,00 (reset drive) is now able to reset the underlying block
    device.  INT 13 users, such as DOS, that use INT 13,00 as a method
    for error recovery now have a chance of recovering.

 o  All block device commands are tagged, with a numerical tag that
    will show up in debugging output and in packet captures; this will
    allow easier interpretation of bug reports that include both
    sources of information.

 o  The extremely ugly hacks used to generate the boot firmware tables
    have been eradicated and replaced with a generic acpi_describe()
    method (exploiting the ability of iPXE interfaces to pass through
    methods to an underlying interface).  The ACPI tables are now
    built in a shared data block within .bss16, rather than each
    requiring dedicated space in .data16.

 o  The architecture-independent concept of a SAN device has been
    exposed to the iPXE core through the sanboot API, which provides
    calls to hook, unhook, boot, and describe SAN devices.  This
    allows for much more flexible usage patterns (such as hooking an
    empty SAN device and then running an OS installer via TFTP).

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 13 vuotta sitten
vanhempi
commit
220495f8bf
47 muutettua tiedostoa jossa 4774 lisäystä ja 2997 poistoa
  1. 0
    336
      src/arch/i386/image/eltorito.c
  2. 0
    3
      src/arch/i386/include/bits/eltorito.h
  3. 14
    0
      src/arch/i386/include/bits/sanboot.h
  4. 4
    57
      src/arch/i386/include/int13.h
  5. 0
    37
      src/arch/i386/include/ipxe/abft.h
  6. 18
    0
      src/arch/i386/include/ipxe/bios_sanboot.h
  7. 0
    125
      src/arch/i386/include/ipxe/sbft.h
  8. 0
    62
      src/arch/i386/interface/pcbios/abft.c
  9. 0
    78
      src/arch/i386/interface/pcbios/aoeboot.c
  10. 0
    73
      src/arch/i386/interface/pcbios/ib_srpboot.c
  11. 696
    194
      src/arch/i386/interface/pcbios/int13.c
  12. 0
    75
      src/arch/i386/interface/pcbios/iscsiboot.c
  13. 0
    26
      src/arch/i386/interface/pcbios/keepsan.c
  14. 0
    105
      src/arch/i386/interface/pcbios/sbft.c
  15. 12
    0
      src/arch/x86_64/include/bits/sanboot.h
  16. 1
    1
      src/config/config.c
  17. 1
    1
      src/config/config_ethernet.c
  18. 1
    1
      src/config/config_infiniband.c
  19. 1
    0
      src/config/defaults/efi.h
  20. 1
    0
      src/config/defaults/linux.h
  21. 1
    0
      src/config/defaults/pcbios.h
  22. 16
    0
      src/config/sanboot.h
  23. 43
    0
      src/core/acpi.c
  24. 138
    0
      src/core/blockdev.c
  25. 44
    0
      src/core/null_sanboot.c
  26. 577
    106
      src/drivers/block/ata.c
  27. 139
    119
      src/drivers/block/ibft.c
  28. 0
    97
      src/drivers/block/ramdisk.c
  29. 641
    237
      src/drivers/block/scsi.c
  30. 553
    277
      src/drivers/block/srp.c
  31. 21
    1
      src/include/ipxe/acpi.h
  32. 24
    43
      src/include/ipxe/aoe.h
  33. 40
    45
      src/include/ipxe/ata.h
  34. 36
    34
      src/include/ipxe/blockdev.h
  35. 3
    0
      src/include/ipxe/errfile.h
  36. 27
    48
      src/include/ipxe/ib_srp.h
  37. 8
    39
      src/include/ipxe/ibft.h
  38. 25
    46
      src/include/ipxe/iscsi.h
  39. 18
    0
      src/include/ipxe/null_sanboot.h
  40. 0
    24
      src/include/ipxe/ramdisk.h
  41. 82
    9
      src/include/ipxe/sanboot.h
  42. 57
    43
      src/include/ipxe/scsi.h
  43. 77
    116
      src/include/ipxe/srp.h
  44. 850
    290
      src/net/aoe.c
  45. 260
    85
      src/net/infiniband/ib_srp.c
  46. 283
    156
      src/net/tcp/iscsi.c
  47. 62
    8
      src/usr/autoboot.c

+ 0
- 336
src/arch/i386/image/eltorito.c Näytä tiedosto

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

+ 0
- 3
src/arch/i386/include/bits/eltorito.h Näytä tiedosto

@@ -1,3 +0,0 @@
1
-#ifndef ELTORITO_PLATFORM
2
-#define ELTORITO_PLATFORM ELTORITO_PLATFORM_X86
3
-#endif /* ELTORITO_PLATFORM */

+ 14
- 0
src/arch/i386/include/bits/sanboot.h Näytä tiedosto

@@ -0,0 +1,14 @@
1
+#ifndef _BITS_SANBOOT_H
2
+#define _BITS_SANBOOT_H
3
+
4
+/** @file
5
+ *
6
+ * i386-specific sanboot API implementations
7
+ *
8
+ */
9
+
10
+FILE_LICENCE ( GPL2_OR_LATER );
11
+
12
+#include <ipxe/bios_sanboot.h>
13
+
14
+#endif /* _BITS_SANBOOT_H */

+ 4
- 57
src/arch/i386/include/int13.h Näytä tiedosto

@@ -13,8 +13,6 @@ FILE_LICENCE ( GPL2_OR_LATER );
13 13
 #include <ipxe/list.h>
14 14
 #include <realmode.h>
15 15
 
16
-struct block_device;
17
-
18 16
 /**
19 17
  * @defgroup int13ops INT 13 operation codes
20 18
  * @{
@@ -56,6 +54,8 @@ struct block_device;
56 54
 #define INT13_STATUS_INVALID		0x01
57 55
 /** Read error */
58 56
 #define INT13_STATUS_READ_ERROR		0x04
57
+/** Reset failed */
58
+#define INT13_STATUS_RESET_FAILED	0x05
59 59
 /** Write error */
60 60
 #define INT13_STATUS_WRITE_ERROR	0xcc
61 61
 
@@ -64,57 +64,6 @@ struct block_device;
64 64
 /** Block size for non-extended INT 13 calls */
65 65
 #define INT13_BLKSIZE 512
66 66
 
67
-/** An INT 13 emulated drive */
68
-struct int13_drive {
69
-	/** List of all registered drives */
70
-	struct list_head list;
71
-
72
-	/** Underlying block device */
73
-	struct block_device *blockdev;
74
-
75
-	/** BIOS in-use drive number (0x80-0xff) */
76
-	unsigned int drive;
77
-	/** BIOS natural drive number (0x80-0xff)
78
-	 *
79
-	 * This is the drive number that would have been assigned by
80
-	 * 'naturally' appending the drive to the end of the BIOS
81
-	 * drive list.
82
-	 *
83
-	 * If the emulated drive replaces a preexisting drive, this is
84
-	 * the drive number that the preexisting drive gets remapped
85
-	 * to.
86
-	 */
87
-	unsigned int natural_drive;
88
-
89
-	/** Number of cylinders
90
-	 *
91
-	 * The cylinder number field in an INT 13 call is ten bits
92
-	 * wide, giving a maximum of 1024 cylinders.  Conventionally,
93
-	 * when the 7.8GB limit of a CHS address is exceeded, it is
94
-	 * the number of cylinders that is increased beyond the
95
-	 * addressable limit.
96
-	 */
97
-	unsigned int cylinders;
98
-	/** Number of heads
99
-	 *
100
-	 * The head number field in an INT 13 call is eight bits wide,
101
-	 * giving a maximum of 256 heads.  However, apparently all
102
-	 * versions of MS-DOS up to and including Win95 fail with 256
103
-	 * heads, so the maximum encountered in practice is 255.
104
-	 */
105
-	unsigned int heads;
106
-	/** Number of sectors per track
107
-	 *
108
-	 * The sector number field in an INT 13 call is six bits wide,
109
-	 * giving a maximum of 63 sectors, since sector numbering
110
-	 * (unlike head and cylinder numbering) starts at 1, not 0.
111
-	 */
112
-	unsigned int sectors_per_track;
113
-
114
-	/** Status of last operation */
115
-	int last_status;
116
-};
117
-
118 67
 /** An INT 13 disk address packet */
119 68
 struct int13_disk_address {
120 69
 	/** Size of the packet, in bytes */
@@ -147,7 +96,6 @@ struct int13_disk_parameters {
147 96
 	uint64_t sectors;
148 97
 	/** Bytes per sector */
149 98
 	uint16_t sector_size;
150
-	
151 99
 } __attribute__ (( packed ));
152 100
 
153 101
 /**
@@ -285,8 +233,7 @@ struct master_boot_record {
285 233
 	uint16_t signature;
286 234
 } __attribute__ (( packed ));
287 235
 
288
-extern void register_int13_drive ( struct int13_drive *drive );
289
-extern void unregister_int13_drive ( struct int13_drive *drive );
290
-extern int int13_boot ( unsigned int drive );
236
+/** Use natural BIOS drive number */
237
+#define INT13_USE_NATURAL_DRIVE 0xff
291 238
 
292 239
 #endif /* INT13_H */

+ 0
- 37
src/arch/i386/include/ipxe/abft.h Näytä tiedosto

@@ -1,37 +0,0 @@
1
-#ifndef _IPXE_ABFT_H
2
-#define _IPXE_ABFT_H
3
-
4
-/** @file
5
- *
6
- * AoE boot firmware table
7
- *
8
- */
9
-
10
-FILE_LICENCE ( GPL2_OR_LATER );
11
-
12
-#include <stdint.h>
13
-#include <ipxe/acpi.h>
14
-#include <ipxe/if_ether.h>
15
-
16
-/** AoE boot firmware table signature */
17
-#define ABFT_SIG "aBFT"
18
-
19
-/**
20
- * AoE Boot Firmware Table (aBFT)
21
- */
22
-struct abft_table {
23
-	/** ACPI header */
24
-	struct acpi_description_header acpi;
25
-	/** AoE shelf */
26
-	uint16_t shelf;
27
-	/** AoE slot */
28
-	uint8_t slot;
29
-	/** Reserved */
30
-	uint8_t reserved_a;
31
-	/** MAC address */
32
-	uint8_t mac[ETH_ALEN];
33
-} __attribute__ (( packed ));
34
-
35
-extern void abft_fill_data ( struct aoe_session *aoe );
36
-
37
-#endif /* _IPXE_ABFT_H */

+ 18
- 0
src/arch/i386/include/ipxe/bios_sanboot.h Näytä tiedosto

@@ -0,0 +1,18 @@
1
+#ifndef _IPXE_BIOS_SANBOOT_H
2
+#define _IPXE_BIOS_SANBOOT_H
3
+
4
+/** @file
5
+ *
6
+ * Standard PC-BIOS sanboot interface
7
+ *
8
+ */
9
+
10
+FILE_LICENCE ( GPL2_OR_LATER );
11
+
12
+#ifdef SANBOOT_PCBIOS
13
+#define SANBOOT_PREFIX_pcbios
14
+#else
15
+#define SANBOOT_PREFIX_pcbios __pcbios_
16
+#endif
17
+
18
+#endif /* _IPXE_BIOS_SANBOOT_H */

+ 0
- 125
src/arch/i386/include/ipxe/sbft.h Näytä tiedosto

@@ -1,125 +0,0 @@
1
-#ifndef _IPXE_SBFT_H
2
-#define _IPXE_SBFT_H
3
-
4
-/*
5
- * Copyright (C) 2009 Fen Systems Ltd <mbrown@fensystems.co.uk>.
6
- * All rights reserved.
7
- *
8
- * Redistribution and use in source and binary forms, with or without
9
- * modification, are permitted provided that the following conditions
10
- * are met:
11
- *
12
- *   Redistributions of source code must retain the above copyright
13
- *   notice, this list of conditions and the following disclaimer.
14
- *
15
- *   Redistributions in binary form must reproduce the above copyright
16
- *   notice, this list of conditions and the following disclaimer in
17
- *   the documentation and/or other materials provided with the
18
- *   distribution.
19
- *
20
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24
- * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
25
- * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
31
- * OF THE POSSIBILITY OF SUCH DAMAGE.
32
- */
33
-
34
-FILE_LICENCE ( BSD2 );
35
-
36
-/** @file
37
- *
38
- * SRP boot firmware table
39
- *
40
- * The working draft specification for the SRP boot firmware table can
41
- * be found at
42
- *
43
- *   http://ipxe.org/wiki/srp/sbft
44
- *
45
- */
46
-
47
-#include <stdint.h>
48
-#include <ipxe/acpi.h>
49
-#include <ipxe/scsi.h>
50
-#include <ipxe/srp.h>
51
-#include <ipxe/ib_srp.h>
52
-
53
-/** SRP Boot Firmware Table signature */
54
-#define SBFT_SIG "sBFT"
55
-
56
-/** An offset from the start of the sBFT */
57
-typedef uint16_t sbft_off_t;
58
-
59
-/**
60
- * SRP Boot Firmware Table
61
- */
62
-struct sbft_table {
63
-	/** ACPI header */
64
-	struct acpi_description_header acpi;
65
-	/** Offset to SCSI subtable */
66
-	sbft_off_t scsi_offset;
67
-	/** Offset to SRP subtable */
68
-	sbft_off_t srp_offset;
69
-	/** Offset to IB subtable, if present */
70
-	sbft_off_t ib_offset;
71
-	/** Reserved */
72
-	uint8_t reserved[6];
73
-} __attribute__ (( packed ));
74
-
75
-/**
76
- * sBFT SCSI subtable
77
- */
78
-struct sbft_scsi_subtable {
79
-	/** LUN */
80
-	struct scsi_lun lun;
81
-} __attribute__ (( packed ));
82
-
83
-/**
84
- * sBFT SRP subtable
85
- */
86
-struct sbft_srp_subtable {
87
-	/** Initiator and target ports */
88
-	struct srp_port_ids port_ids;
89
-} __attribute__ (( packed ));
90
-
91
-/**
92
- * sBFT IB subtable
93
- */
94
-struct sbft_ib_subtable {
95
-	/** Source GID */
96
-	struct ib_gid sgid;
97
-	/** Destination GID */
98
-	struct ib_gid dgid;
99
-	/** Service ID */
100
-	struct ib_gid_half service_id;
101
-	/** Partition key */
102
-	uint16_t pkey;
103
-	/** Reserved */
104
-	uint8_t reserved[6];
105
-} __attribute__ (( packed ));
106
-
107
-/**
108
- * An sBFT created by iPXE
109
- */
110
-struct ipxe_sbft {
111
-	/** The table header */
112
-	struct sbft_table table;
113
-	/** The SCSI subtable */
114
-	struct sbft_scsi_subtable scsi;
115
-	/** The SRP subtable */
116
-	struct sbft_srp_subtable srp;
117
-	/** The IB subtable */
118
-	struct sbft_ib_subtable ib;
119
-} __attribute__ (( packed, aligned ( 16 ) ));
120
-
121
-struct srp_device;
122
-
123
-extern int sbft_fill_data ( struct srp_device *srp );
124
-
125
-#endif /* _IPXE_SBFT_H */

+ 0
- 62
src/arch/i386/interface/pcbios/abft.c Näytä tiedosto

@@ -1,62 +0,0 @@
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
-FILE_LICENCE ( GPL2_OR_LATER );
20
-
21
-#include <realmode.h>
22
-#include <ipxe/aoe.h>
23
-#include <ipxe/netdevice.h>
24
-#include <ipxe/abft.h>
25
-
26
-/** @file
27
- *
28
- * AoE Boot Firmware Table
29
- *
30
- */
31
-
32
-#define abftab __use_data16 ( abftab )
33
-/** The aBFT used by iPXE */
34
-struct abft_table __data16 ( abftab ) __attribute__ (( aligned ( 16 ) )) = {
35
-	/* ACPI header */
36
-	.acpi = {
37
-		.signature = ABFT_SIG,
38
-		.length = sizeof ( abftab ),
39
-		.revision = 1,
40
-		.oem_id = "FENSYS",
41
-		.oem_table_id = "iPXE",
42
-	},
43
-};
44
-
45
-/**
46
- * Fill in all variable portions of aBFT
47
- *
48
- * @v aoe		AoE session
49
- */
50
-void abft_fill_data ( struct aoe_session *aoe ) {
51
-
52
-	/* Fill in boot parameters */
53
-	abftab.shelf = aoe->major;
54
-	abftab.slot = aoe->minor;
55
-	memcpy ( abftab.mac, aoe->netdev->ll_addr, sizeof ( abftab.mac ) );
56
-
57
-	/* Update checksum */
58
-	acpi_fix_checksum ( &abftab.acpi );
59
-
60
-	DBG ( "AoE boot firmware table:\n" );
61
-	DBG_HD ( &abftab, sizeof ( abftab ) );
62
-}

+ 0
- 78
src/arch/i386/interface/pcbios/aoeboot.c Näytä tiedosto

@@ -1,78 +0,0 @@
1
-#include <stdint.h>
2
-#include <string.h>
3
-#include <stdlib.h>
4
-#include <stdio.h>
5
-#include <errno.h>
6
-#include <ipxe/aoe.h>
7
-#include <ipxe/ata.h>
8
-#include <ipxe/netdevice.h>
9
-#include <ipxe/sanboot.h>
10
-#include <ipxe/abft.h>
11
-#include <int13.h>
12
-
13
-FILE_LICENCE ( GPL2_OR_LATER );
14
-
15
-static int aoeboot ( const char *root_path ) {
16
-	struct ata_device *ata;
17
-	struct int13_drive *drive;
18
-	int rc;
19
-
20
-	ata = zalloc ( sizeof ( *ata ) );
21
-	if ( ! ata ) {
22
-		rc = -ENOMEM;
23
-		goto err_alloc_ata;
24
-	}
25
-	drive = zalloc ( sizeof ( *drive ) );
26
-	if ( ! drive ) {
27
-		rc = -ENOMEM;
28
-		goto err_alloc_drive;
29
-	}
30
-
31
-	/* FIXME: ugly, ugly hack */
32
-	struct net_device *netdev = last_opened_netdev();
33
-
34
-	if ( ( rc = aoe_attach ( ata, netdev, root_path ) ) != 0 ) {
35
-		printf ( "Could not attach AoE device: %s\n",
36
-			 strerror ( rc ) );
37
-		goto err_attach;
38
-	}
39
-	if ( ( rc = init_atadev ( ata ) ) != 0 ) {
40
-		printf ( "Could not initialise AoE device: %s\n",
41
-			 strerror ( rc ) );
42
-		goto err_init;
43
-	}
44
-
45
-	/* FIXME: ugly, ugly hack */
46
-	struct aoe_session *aoe =
47
-		container_of ( ata->backend, struct aoe_session, refcnt );
48
-	abft_fill_data ( aoe );
49
-
50
-	drive->blockdev = &ata->blockdev;
51
-
52
-	register_int13_drive ( drive );
53
-	printf ( "Registered as BIOS drive %#02x\n", drive->drive );
54
-	printf ( "Booting from BIOS drive %#02x\n", drive->drive );
55
-	rc = int13_boot ( drive->drive );
56
-	printf ( "Boot failed\n" );
57
-
58
-	/* Leave drive registered, if instructed to do so */
59
-	if ( keep_san() )
60
-		return rc;
61
-
62
-	printf ( "Unregistering BIOS drive %#02x\n", drive->drive );
63
-	unregister_int13_drive ( drive );
64
-
65
- err_init:
66
-	aoe_detach ( ata );
67
- err_attach:
68
-	free ( drive );
69
- err_alloc_drive:
70
-	free ( ata );
71
- err_alloc_ata:
72
-	return rc;
73
-}
74
-
75
-struct sanboot_protocol aoe_sanboot_protocol __sanboot_protocol = {
76
-	.prefix = "aoe:",
77
-	.boot = aoeboot,
78
-};

+ 0
- 73
src/arch/i386/interface/pcbios/ib_srpboot.c Näytä tiedosto

@@ -1,73 +0,0 @@
1
-#include <stdint.h>
2
-#include <string.h>
3
-#include <stdlib.h>
4
-#include <stdio.h>
5
-#include <errno.h>
6
-#include <ipxe/sanboot.h>
7
-#include <int13.h>
8
-#include <ipxe/srp.h>
9
-#include <ipxe/sbft.h>
10
-
11
-FILE_LICENCE ( GPL2_OR_LATER );
12
-
13
-static int ib_srpboot ( const char *root_path ) {
14
-	struct scsi_device *scsi;
15
-	struct int13_drive *drive;
16
-	int rc;
17
-
18
-	scsi = zalloc ( sizeof ( *scsi ) );
19
-	if ( ! scsi ) {
20
-		rc = -ENOMEM;
21
-		goto err_alloc_scsi;
22
-	}
23
-	drive = zalloc ( sizeof ( *drive ) );
24
-	if ( ! drive ) {
25
-		rc = -ENOMEM;
26
-		goto err_alloc_drive;
27
-	}
28
-
29
-	if ( ( rc = srp_attach ( scsi, root_path ) ) != 0 ) {
30
-		printf ( "Could not attach IB_SRP device: %s\n",
31
-			 strerror ( rc ) );
32
-		goto err_attach;
33
-	}
34
-	if ( ( rc = init_scsidev ( scsi ) ) != 0 ) {
35
-		printf ( "Could not initialise IB_SRP device: %s\n",
36
-			 strerror ( rc ) );
37
-		goto err_init;
38
-	}
39
-
40
-	drive->blockdev = &scsi->blockdev;
41
-
42
-	/* FIXME: ugly, ugly hack */
43
-	struct srp_device *srp =
44
-		container_of ( scsi->backend, struct srp_device, refcnt );
45
-	sbft_fill_data ( srp );
46
-
47
-	register_int13_drive ( drive );
48
-	printf ( "Registered as BIOS drive %#02x\n", drive->drive );
49
-	printf ( "Booting from BIOS drive %#02x\n", drive->drive );
50
-	rc = int13_boot ( drive->drive );
51
-	printf ( "Boot failed\n" );
52
-
53
-	/* Leave drive registered, if instructed to do so */
54
-	if ( keep_san() )
55
-		return rc;
56
-
57
-	printf ( "Unregistering BIOS drive %#02x\n", drive->drive );
58
-	unregister_int13_drive ( drive );
59
-
60
- err_init:
61
-	srp_detach ( scsi );
62
- err_attach:
63
-	free ( drive );
64
- err_alloc_drive:
65
-	free ( scsi );
66
- err_alloc_scsi:
67
-	return rc;
68
-}
69
-
70
-struct sanboot_protocol ib_srp_sanboot_protocol __sanboot_protocol = {
71
-	.prefix = "ib_srp:",
72
-	.boot = ib_srpboot,
73
-};

+ 696
- 194
src/arch/i386/interface/pcbios/int13.c
File diff suppressed because it is too large
Näytä tiedosto


+ 0
- 75
src/arch/i386/interface/pcbios/iscsiboot.c Näytä tiedosto

@@ -1,75 +0,0 @@
1
-#include <stdint.h>
2
-#include <string.h>
3
-#include <stdlib.h>
4
-#include <stdio.h>
5
-#include <errno.h>
6
-#include <ipxe/iscsi.h>
7
-#include <ipxe/netdevice.h>
8
-#include <ipxe/ibft.h>
9
-#include <ipxe/sanboot.h>
10
-#include <int13.h>
11
-
12
-FILE_LICENCE ( GPL2_OR_LATER );
13
-
14
-static int iscsiboot ( const char *root_path ) {
15
-	struct scsi_device *scsi;
16
-	struct int13_drive *drive;
17
-	int rc;
18
-
19
-	scsi = zalloc ( sizeof ( *scsi ) );
20
-	if ( ! scsi ) {
21
-		rc = -ENOMEM;
22
-		goto err_alloc_scsi;
23
-	}
24
-	drive = zalloc ( sizeof ( *drive ) );
25
-	if ( ! drive ) {
26
-		rc = -ENOMEM;
27
-		goto err_alloc_drive;
28
-	}
29
-
30
-	if ( ( rc = iscsi_attach ( scsi, root_path ) ) != 0 ) {
31
-		printf ( "Could not attach iSCSI device: %s\n",
32
-			 strerror ( rc ) );
33
-		goto err_attach;
34
-	}
35
-	if ( ( rc = init_scsidev ( scsi ) ) != 0 ) {
36
-		printf ( "Could not initialise iSCSI device: %s\n",
37
-			 strerror ( rc ) );
38
-		goto err_init;
39
-	}
40
-
41
-	drive->blockdev = &scsi->blockdev;
42
-
43
-	/* FIXME: ugly, ugly hack */
44
-	struct net_device *netdev = last_opened_netdev();
45
-	struct iscsi_session *iscsi =
46
-		container_of ( scsi->backend, struct iscsi_session, refcnt );
47
-	ibft_fill_data ( netdev, iscsi );
48
-
49
-	register_int13_drive ( drive );
50
-	printf ( "Registered as BIOS drive %#02x\n", drive->drive );
51
-	printf ( "Booting from BIOS drive %#02x\n", drive->drive );
52
-	rc = int13_boot ( drive->drive );
53
-	printf ( "Boot failed\n" );
54
-
55
-	/* Leave drive registered, if instructed to do so */
56
-	if ( keep_san() )
57
-		return rc;
58
-
59
-	printf ( "Unregistering BIOS drive %#02x\n", drive->drive );
60
-	unregister_int13_drive ( drive );
61
-
62
- err_init:
63
-	iscsi_detach ( scsi );
64
- err_attach:
65
-	free ( drive );
66
- err_alloc_drive:
67
-	free ( scsi );
68
- err_alloc_scsi:
69
-	return rc;
70
-}
71
-
72
-struct sanboot_protocol iscsi_sanboot_protocol __sanboot_protocol = {
73
-	.prefix = "iscsi:",
74
-	.boot = iscsiboot,
75
-};

+ 0
- 26
src/arch/i386/interface/pcbios/keepsan.c Näytä tiedosto

@@ -1,26 +0,0 @@
1
-#include <stdint.h>
2
-#include <stdio.h>
3
-#include <ipxe/settings.h>
4
-#include <ipxe/dhcp.h>
5
-#include <ipxe/init.h>
6
-#include <ipxe/sanboot.h>
7
-#include <usr/autoboot.h>
8
-
9
-struct setting keep_san_setting __setting = {
10
-	.name = "keep-san",
11
-	.description = "Preserve SAN connection",
12
-	.tag = DHCP_EB_KEEP_SAN,
13
-	.type = &setting_type_int8,
14
-};
15
-
16
-int keep_san ( void ) {
17
-	int keep_san;
18
-
19
-	keep_san = fetch_intz_setting ( NULL, &keep_san_setting );
20
-	if ( ! keep_san )
21
-		return 0;
22
-
23
-	printf ( "Preserving connection to SAN disk\n" );
24
-	shutdown_exit_flags |= SHUTDOWN_KEEP_DEVICES;
25
-	return 1;
26
-}

+ 0
- 105
src/arch/i386/interface/pcbios/sbft.c Näytä tiedosto

@@ -1,105 +0,0 @@
1
-/*
2
- * Copyright (C) 2009 Fen Systems Ltd <mbrown@fensystems.co.uk>.
3
- * All rights reserved.
4
- *
5
- * Redistribution and use in source and binary forms, with or without
6
- * modification, are permitted provided that the following conditions
7
- * are met:
8
- *
9
- *   Redistributions of source code must retain the above copyright
10
- *   notice, this list of conditions and the following disclaimer.
11
- *
12
- *   Redistributions in binary form must reproduce the above copyright
13
- *   notice, this list of conditions and the following disclaimer in
14
- *   the documentation and/or other materials provided with the
15
- *   distribution.
16
- *
17
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
20
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
21
- * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
22
- * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
28
- * OF THE POSSIBILITY OF SUCH DAMAGE.
29
- */
30
-
31
-FILE_LICENCE ( BSD2 );
32
-
33
-/** @file
34
- *
35
- * SRP boot firmware table
36
- *
37
- */
38
-
39
-#include <assert.h>
40
-#include <realmode.h>
41
-#include <ipxe/srp.h>
42
-#include <ipxe/ib_srp.h>
43
-#include <ipxe/acpi.h>
44
-#include <ipxe/sbft.h>
45
-
46
-#define sbftab __use_data16 ( sbftab )
47
-/** The sBFT used by iPXE */
48
-struct ipxe_sbft __data16 ( sbftab ) = {
49
-	/* Table header */
50
-	.table = {
51
-		/* ACPI header */
52
-		.acpi = {
53
-			.signature = SBFT_SIG,
54
-			.length = sizeof ( sbftab ),
55
-			.revision = 1,
56
-			.oem_id = "FENSYS",
57
-			.oem_table_id = "iPXE",
58
-		},
59
-		.scsi_offset = offsetof ( typeof ( sbftab ), scsi ),
60
-		.srp_offset = offsetof ( typeof ( sbftab ), srp ),
61
-		.ib_offset = offsetof ( typeof ( sbftab ), ib ),
62
-	},
63
-};
64
-
65
-/**
66
- * Fill in all variable portions of sBFT
67
- *
68
- * @v srp		SRP device
69
- * @ret rc		Return status code
70
- */
71
-int sbft_fill_data ( struct srp_device *srp ) {
72
-	struct sbft_scsi_subtable *sbft_scsi = &sbftab.scsi;
73
-	struct sbft_srp_subtable *sbft_srp = &sbftab.srp;
74
-	struct sbft_ib_subtable *sbft_ib = &sbftab.ib;
75
-	struct ib_srp_parameters *ib_params;
76
-	struct segoff rm_sbftab = {
77
-		.segment = rm_ds,
78
-		.offset = __from_data16 ( &sbftab ),
79
-	};
80
-
81
-	/* Fill in the SCSI subtable */
82
-	memcpy ( &sbft_scsi->lun, &srp->lun, sizeof ( sbft_scsi->lun ) );
83
-
84
-	/* Fill in the SRP subtable */
85
-	memcpy ( &sbft_srp->port_ids, &srp->port_ids,
86
-		 sizeof ( sbft_srp->port_ids ) );
87
-
88
-	/* Fill in the IB subtable */
89
-	assert ( srp->transport == &ib_srp_transport );
90
-	ib_params = ib_srp_params ( srp );
91
-	memcpy ( &sbft_ib->sgid, &ib_params->sgid, sizeof ( sbft_ib->sgid ) );
92
-	memcpy ( &sbft_ib->dgid, &ib_params->dgid, sizeof ( sbft_ib->dgid ) );
93
-	memcpy ( &sbft_ib->service_id, &ib_params->service_id,
94
-		 sizeof ( sbft_ib->service_id ) );
95
-	sbft_ib->pkey = ib_params->pkey;
96
-
97
-	/* Update checksum */
98
-	acpi_fix_checksum ( &sbftab.table.acpi );
99
-
100
-	DBGC ( &sbftab, "SRP Boot Firmware Table at %04x:%04x:\n",
101
-	       rm_sbftab.segment, rm_sbftab.offset );
102
-	DBGC_HDA ( &sbftab, rm_sbftab, &sbftab, sizeof ( sbftab ) );
103
-
104
-	return 0;
105
-}

+ 12
- 0
src/arch/x86_64/include/bits/sanboot.h Näytä tiedosto

@@ -0,0 +1,12 @@
1
+#ifndef _BITS_SANBOOT_H
2
+#define _BITS_SANBOOT_H
3
+
4
+/** @file
5
+ *
6
+ * x86_64-specific sanboot API implementations
7
+ *
8
+ */
9
+
10
+FILE_LICENCE ( GPL2_OR_LATER );
11
+
12
+#endif /* _BITS_SANBOOT_H */

+ 1
- 1
src/config/config.c Näytä tiedosto

@@ -133,7 +133,7 @@ REQUIRE_OBJECT ( slam );
133 133
  *
134 134
  */
135 135
 #ifdef SANBOOT_PROTO_ISCSI
136
-REQUIRE_OBJECT ( iscsiboot );
136
+REQUIRE_OBJECT ( iscsi );
137 137
 #endif
138 138
 
139 139
 /*

+ 1
- 1
src/config/config_ethernet.c Näytä tiedosto

@@ -19,5 +19,5 @@ FILE_LICENCE ( GPL2_OR_LATER );
19 19
  * Drag in Ethernet-specific protocols
20 20
  */
21 21
 #ifdef SANBOOT_PROTO_AOE
22
-REQUIRE_OBJECT ( aoeboot );
22
+REQUIRE_OBJECT ( aoe );
23 23
 #endif

+ 1
- 1
src/config/config_infiniband.c Näytä tiedosto

@@ -19,5 +19,5 @@ FILE_LICENCE ( GPL2_OR_LATER );
19 19
  * Drag in Infiniband-specific protocols
20 20
  */
21 21
 #ifdef SANBOOT_PROTO_IB_SRP
22
-REQUIRE_OBJECT ( ib_srpboot );
22
+REQUIRE_OBJECT ( ib_srp );
23 23
 #endif

+ 1
- 0
src/config/defaults/efi.h Näytä tiedosto

@@ -15,6 +15,7 @@
15 15
 #define NAP_EFIX86
16 16
 #define UMALLOC_EFI
17 17
 #define SMBIOS_EFI
18
+#define SANBOOT_NULL
18 19
 
19 20
 #define	IMAGE_EFI		/* EFI image support */
20 21
 #define	IMAGE_SCRIPT		/* iPXE script image support */

+ 1
- 0
src/config/defaults/linux.h Näytä tiedosto

@@ -13,6 +13,7 @@
13 13
 #define UMALLOC_LINUX
14 14
 #define NAP_LINUX
15 15
 #define SMBIOS_LINUX
16
+#define SANBOOT_NULL
16 17
 
17 18
 #define DRIVERS_LINUX
18 19
 

+ 1
- 0
src/config/defaults/pcbios.h Näytä tiedosto

@@ -17,6 +17,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
17 17
 #define NAP_PCBIOS
18 18
 #define UMALLOC_MEMTOP
19 19
 #define SMBIOS_PCBIOS
20
+#define SANBOOT_PCBIOS
20 21
 
21 22
 #define	IMAGE_ELF		/* ELF image support */
22 23
 #define	IMAGE_MULTIBOOT		/* MultiBoot image support */

+ 16
- 0
src/config/sanboot.h Näytä tiedosto

@@ -0,0 +1,16 @@
1
+#ifndef CONFIG_SANBOOT_H
2
+#define CONFIG_SANBOOT_H
3
+
4
+/** @file
5
+ *
6
+ * sanboot API configuration
7
+ *
8
+ */
9
+
10
+FILE_LICENCE ( GPL2_OR_LATER );
11
+
12
+#include <config/defaults.h>
13
+
14
+#include <config/local/sanboot.h>
15
+
16
+#endif /* CONFIG_SANBOOT_H */

+ 43
- 0
src/core/acpi.c Näytä tiedosto

@@ -18,7 +18,9 @@
18 18
 
19 19
 FILE_LICENCE ( GPL2_OR_LATER );
20 20
 
21
+#include <errno.h>
21 22
 #include <ipxe/acpi.h>
23
+#include <ipxe/interface.h>
22 24
 
23 25
 /** @file
24 26
  *
@@ -26,6 +28,13 @@ FILE_LICENCE ( GPL2_OR_LATER );
26 28
  *
27 29
  */
28 30
 
31
+/******************************************************************************
32
+ *
33
+ * Utility functions
34
+ *
35
+ ******************************************************************************
36
+ */
37
+
29 38
 /**
30 39
  * Fix up ACPI table checksum
31 40
  *
@@ -40,3 +49,37 @@ void acpi_fix_checksum ( struct acpi_description_header *acpi ) {
40 49
 	}
41 50
 	acpi->checksum -= sum;
42 51
 }
52
+
53
+/******************************************************************************
54
+ *
55
+ * Interface methods
56
+ *
57
+ ******************************************************************************
58
+ */
59
+
60
+/**
61
+ * Describe object in an ACPI table
62
+ *
63
+ * @v intf		Interface
64
+ * @v acpi		ACPI table
65
+ * @v len		Length of ACPI table
66
+ * @ret rc		Return status code
67
+ */
68
+int acpi_describe ( struct interface *intf,
69
+		    struct acpi_description_header *acpi, size_t len ) {
70
+	struct interface *dest;
71
+	acpi_describe_TYPE ( void * ) *op =
72
+		intf_get_dest_op ( intf, acpi_describe, &dest );
73
+	void *object = intf_object ( dest );
74
+	int rc;
75
+
76
+	if ( op ) {
77
+		rc = op ( object, acpi, len );
78
+	} else {
79
+		/* Default is to fail to describe */
80
+		rc = -EOPNOTSUPP;
81
+	}
82
+
83
+	intf_put ( dest );
84
+	return rc;
85
+}

+ 138
- 0
src/core/blockdev.c Näytä tiedosto

@@ -0,0 +1,138 @@
1
+/*
2
+ * Copyright (C) 2010 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
+FILE_LICENCE ( GPL2_OR_LATER );
20
+
21
+#include <errno.h>
22
+#include <ipxe/interface.h>
23
+#include <ipxe/blockdev.h>
24
+
25
+/** @file
26
+ *
27
+ * Block devices
28
+ *
29
+ */
30
+
31
+/**
32
+ * Read from block device
33
+ *
34
+ * @v control		Control interface
35
+ * @v data		Data interface
36
+ * @v lba		Starting logical block address
37
+ * @v count		Number of logical blocks
38
+ * @v buffer		Data buffer
39
+ * @v len		Length of data buffer
40
+ * @ret rc		Return status code
41
+ */
42
+int block_read ( struct interface *control, struct interface *data,
43
+		 uint64_t lba, unsigned int count,
44
+		 userptr_t buffer, size_t len ) {
45
+	struct interface *dest;
46
+	block_read_TYPE ( void * ) *op =
47
+		intf_get_dest_op ( control, block_read, &dest );
48
+	void *object = intf_object ( dest );
49
+	int rc;
50
+
51
+	if ( op ) {
52
+		rc = op ( object, data, lba, count, buffer, len );
53
+	} else {
54
+		/* Default is to fail to issue the command */
55
+		rc = -EOPNOTSUPP;
56
+	}
57
+
58
+	intf_put ( dest );
59
+	return rc;
60
+}
61
+
62
+/**
63
+ * Write to block device
64
+ *
65
+ * @v control		Control interface
66
+ * @v data		Data interface
67
+ * @v lba		Starting logical block address
68
+ * @v count		Number of logical blocks
69
+ * @v buffer		Data buffer
70
+ * @v len		Length of data buffer
71
+ * @ret rc		Return status code
72
+ */
73
+int block_write ( struct interface *control, struct interface *data,
74
+		  uint64_t lba, unsigned int count,
75
+		  userptr_t buffer, size_t len ) {
76
+	struct interface *dest;
77
+	block_write_TYPE ( void * ) *op =
78
+		intf_get_dest_op ( control, block_write, &dest );
79
+	void *object = intf_object ( dest );
80
+	int rc;
81
+
82
+	if ( op ) {
83
+		rc = op ( object, data, lba, count, buffer, len );
84
+	} else {
85
+		/* Default is to fail to issue the command */
86
+		rc = -EOPNOTSUPP;
87
+	}
88
+
89
+	intf_put ( dest );
90
+	return rc;
91
+}
92
+
93
+/**
94
+ * Read block device capacity
95
+ *
96
+ * @v control		Control interface
97
+ * @v data		Data interface
98
+ * @ret rc		Return status code
99
+ */
100
+int block_read_capacity ( struct interface *control, struct interface *data ) {
101
+	struct interface *dest;
102
+	block_read_capacity_TYPE ( void * ) *op =
103
+		intf_get_dest_op ( control, block_read_capacity, &dest );
104
+	void *object = intf_object ( dest );
105
+	int rc;
106
+
107
+	if ( op ) {
108
+		rc = op ( object, data );
109
+	} else {
110
+		/* Default is to fail to issue the command */
111
+		rc = -EOPNOTSUPP;
112
+	}
113
+
114
+	intf_put ( dest );
115
+	return rc;
116
+}
117
+
118
+/**
119
+ * Report block device capacity
120
+ *
121
+ * @v intf		Interface
122
+ * @v capacity		Block device capacity
123
+ */
124
+void block_capacity ( struct interface *intf,
125
+		      struct block_device_capacity *capacity ) {
126
+	struct interface *dest;
127
+	block_capacity_TYPE ( void * ) *op =
128
+		intf_get_dest_op ( intf, block_capacity, &dest );
129
+	void *object = intf_object ( dest );
130
+
131
+	if ( op ) {
132
+		op ( object, capacity );
133
+	} else {
134
+		/* Default is to do nothing */
135
+	}
136
+
137
+	intf_put ( dest );
138
+}

+ 44
- 0
src/core/null_sanboot.c Näytä tiedosto

@@ -0,0 +1,44 @@
1
+/*
2
+ * Copyright (C) 2010 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
+FILE_LICENCE ( GPL2_OR_LATER );
20
+
21
+#include <errno.h>
22
+#include <ipxe/sanboot.h>
23
+
24
+static int null_san_hook ( struct uri *uri __unused,
25
+			   unsigned int drive __unused ) {
26
+	return -EOPNOTSUPP;
27
+}
28
+
29
+static void null_san_unhook ( unsigned int drive __unused ) {
30
+	/* Do nothing */
31
+}
32
+
33
+static int null_san_boot ( unsigned int drive __unused ) {
34
+	return -EOPNOTSUPP;
35
+}
36
+
37
+static int null_san_describe ( unsigned int drive __unused ) {
38
+	return -EOPNOTSUPP;
39
+}
40
+
41
+PROVIDE_SANBOOT ( null, san_hook, null_san_hook );
42
+PROVIDE_SANBOOT ( null, san_unhook, null_san_unhook );
43
+PROVIDE_SANBOOT ( null, san_boot, null_san_boot );
44
+PROVIDE_SANBOOT ( null, san_describe, null_san_describe );

+ 577
- 106
src/drivers/block/ata.c Näytä tiedosto

@@ -19,12 +19,14 @@
19 19
 FILE_LICENCE ( GPL2_OR_LATER );
20 20
 
21 21
 #include <stddef.h>
22
+#include <stdlib.h>
22 23
 #include <string.h>
23 24
 #include <assert.h>
24 25
 #include <errno.h>
25 26
 #include <byteswap.h>
27
+#include <ipxe/list.h>
28
+#include <ipxe/interface.h>
26 29
 #include <ipxe/blockdev.h>
27
-#include <ipxe/process.h>
28 30
 #include <ipxe/ata.h>
29 31
 
30 32
 /** @file
@@ -33,156 +35,625 @@ FILE_LICENCE ( GPL2_OR_LATER );
33 35
  *
34 36
  */
35 37
 
36
-static inline __attribute__ (( always_inline )) struct ata_device *
37
-block_to_ata ( struct block_device *blockdev ) {
38
-	return container_of ( blockdev, struct ata_device, blockdev );
39
-}
38
+/******************************************************************************
39
+ *
40
+ * Interface methods
41
+ *
42
+ ******************************************************************************
43
+ */
40 44
 
41 45
 /**
42 46
  * Issue ATA command
43 47
  *
44
- * @v ata		ATA device
48
+ * @v control		ATA control interface
49
+ * @v data		ATA data interface
45 50
  * @v command		ATA command
46
- * @ret rc		Return status code
51
+ * @ret tag		Command tag, or negative error
47 52
  */
48
-static inline __attribute__ (( always_inline )) int
49
-ata_command ( struct ata_device *ata, struct ata_command *command ) {
50
-	int rc;
53
+int ata_command ( struct interface *control, struct interface *data,
54
+		  struct ata_cmd *command ) {
55
+	struct interface *dest;
56
+	ata_command_TYPE ( void * ) *op =
57
+		intf_get_dest_op ( control, ata_command, &dest );
58
+	void *object = intf_object ( dest );
59
+	int tag;
60
+
61
+	if ( op ) {
62
+		tag = op ( object, data, command );
63
+	} else {
64
+		/* Default is to fail to issue the command */
65
+		tag = -EOPNOTSUPP;
66
+	}
67
+
68
+	intf_put ( dest );
69
+	return tag;
70
+}
71
+
72
+/******************************************************************************
73
+ *
74
+ * ATA devices and commands
75
+ *
76
+ ******************************************************************************
77
+ */
78
+
79
+/** List of all ATA commands */
80
+static LIST_HEAD ( ata_commands );
81
+
82
+/** An ATA device */
83
+struct ata_device {
84
+	/** Reference count */
85
+	struct refcnt refcnt;
86
+	/** Block control interface */
87
+	struct interface block;
88
+	/** ATA control interface */
89
+	struct interface ata;
90
+
91
+	/** Device number
92
+	 *
93
+	 * Must be ATA_DEV_MASTER or ATA_DEV_SLAVE.
94
+	 */
95
+	unsigned int device;
96
+	/** Maximum number of blocks per single transfer */
97
+	unsigned int max_count;
98
+	/** Device uses LBA48 extended addressing */
99
+	int lba48;
100
+};
101
+
102
+/** An ATA command */
103
+struct ata_command {
104
+	/** Reference count */
105
+	struct refcnt refcnt;
106
+	/** ATA device */
107
+	struct ata_device *atadev;
108
+	/** List of ATA commands */
109
+	struct list_head list;
110
+
111
+	/** Block data interface */
112
+	struct interface block;
113
+	/** ATA data interface */
114
+	struct interface ata;
115
+
116
+	/** Command type */
117
+	struct ata_command_type *type;
118
+	/** Command tag */
119
+	uint32_t tag;
120
+
121
+	/** Private data */
122
+	uint8_t priv[0];
123
+};
124
+
125
+/** An ATA command type */
126
+struct ata_command_type {
127
+	/** Name */
128
+	const char *name;
129
+	/** Additional working space */
130
+	size_t priv_len;
131
+	/** Command for non-LBA48-capable devices */
132
+	uint8_t cmd_lba;
133
+	/** Command for LBA48-capable devices */
134
+	uint8_t cmd_lba48;
135
+	/**
136
+	 * Calculate data-in buffer
137
+	 *
138
+	 * @v atacmd		ATA command
139
+	 * @v buffer		Available buffer
140
+	 * @v len		Available buffer length
141
+	 * @ret data_in		Data-in buffer
142
+	 * @ret data_in_len	Data-in buffer length
143
+	 */
144
+	void ( * data_in ) ( struct ata_command *atacmd, userptr_t buffer,
145
+			     size_t len, userptr_t *data_in,
146
+			     size_t *data_in_len );
147
+	/**
148
+	 * Calculate data-out buffer
149
+	 *
150
+	 *
151
+	 * @v atacmd		ATA command
152
+	 * @v buffer		Available buffer
153
+	 * @v len		Available buffer length
154
+	 * @ret data_out	Data-out buffer
155
+	 * @ret data_out_len	Data-out buffer length
156
+	 */
157
+	void ( * data_out ) ( struct ata_command *atacmd, userptr_t buffer,
158
+			      size_t len, userptr_t *data_out,
159
+			      size_t *data_out_len );
160
+	/**
161
+	 * Handle ATA command completion
162
+	 *
163
+	 * @v atacmd		ATA command
164
+	 * @v rc		Reason for completion
165
+	 */
166
+	void ( * done ) ( struct ata_command *atacmd, int rc );
167
+};
168
+
169
+/**
170
+ * Get reference to ATA device
171
+ *
172
+ * @v atadev		ATA device
173
+ * @ret atadev		ATA device
174
+ */
175
+static inline __attribute__ (( always_inline )) struct ata_device *
176
+atadev_get ( struct ata_device *atadev ) {
177
+	ref_get ( &atadev->refcnt );
178
+	return atadev;
179
+}
180
+
181
+/**
182
+ * Drop reference to ATA device
183
+ *
184
+ * @v atadev		ATA device
185
+ */
186
+static inline __attribute__ (( always_inline )) void
187
+atadev_put ( struct ata_device *atadev ) {
188
+	ref_put ( &atadev->refcnt );
189
+}
190
+
191
+/**
192
+ * Get reference to ATA command
193
+ *
194
+ * @v atacmd		ATA command
195
+ * @ret atacmd		ATA command
196
+ */
197
+static inline __attribute__ (( always_inline )) struct ata_command *
198
+atacmd_get ( struct ata_command *atacmd ) {
199
+	ref_get ( &atacmd->refcnt );
200
+	return atacmd;
201
+}
202
+
203
+/**
204
+ * Drop reference to ATA command
205
+ *
206
+ * @v atacmd		ATA command
207
+ */
208
+static inline __attribute__ (( always_inline )) void
209
+atacmd_put ( struct ata_command *atacmd ) {
210
+	ref_put ( &atacmd->refcnt );
211
+}
212
+
213
+/**
214
+ * Get ATA command private data
215
+ *
216
+ * @v atacmd		ATA command
217
+ * @ret priv		Private data
218
+ */
219
+static inline __attribute__ (( always_inline )) void *
220
+atacmd_priv ( struct ata_command *atacmd ) {
221
+	return atacmd->priv;
222
+}
223
+
224
+/**
225
+ * Free ATA command
226
+ *
227
+ * @v refcnt		Reference count
228
+ */
229
+static void atacmd_free ( struct refcnt *refcnt ) {
230
+	struct ata_command *atacmd =
231
+		container_of ( refcnt, struct ata_command, refcnt );
232
+
233
+	/* Remove from list of commands */
234
+	list_del ( &atacmd->list );
235
+	atadev_put ( atacmd->atadev );
236
+
237
+	/* Free command */
238
+	free ( atacmd );
239
+}
240
+
241
+/**
242
+ * Close ATA command
243
+ *
244
+ * @v atacmd		ATA command
245
+ * @v rc		Reason for close
246
+ */
247
+static void atacmd_close ( struct ata_command *atacmd, int rc ) {
248
+	struct ata_device *atadev = atacmd->atadev;
249
+
250
+	if ( rc != 0 ) {
251
+		DBGC ( atadev, "ATA %p tag %08x closed: %s\n",
252
+		       atadev, atacmd->tag, strerror ( rc ) );
253
+	}
254
+
255
+	/* Shut down interfaces */
256
+	intf_shutdown ( &atacmd->ata, rc );
257
+	intf_shutdown ( &atacmd->block, rc );
258
+}
259
+
260
+/**
261
+ * Handle ATA command completion
262
+ *
263
+ * @v atacmd		ATA command
264
+ * @v rc		Reason for close
265
+ */
266
+static void atacmd_done ( struct ata_command *atacmd, int rc ) {
267
+
268
+	/* Hand over to the command completion handler */
269
+	atacmd->type->done ( atacmd, rc );
270
+}
271
+
272
+/**
273
+ * Use provided data buffer for ATA command
274
+ *
275
+ * @v atacmd		ATA command
276
+ * @v buffer		Available buffer
277
+ * @v len		Available buffer length
278
+ * @ret data		Data buffer
279
+ * @ret data_len	Data buffer length
280
+ */
281
+static void atacmd_data_buffer ( struct ata_command *atacmd __unused,
282
+				 userptr_t buffer, size_t len,
283
+				 userptr_t *data, size_t *data_len ) {
284
+	*data = buffer;
285
+	*data_len = len;
286
+}
51 287
 
52
-	DBG ( "ATA cmd %02x dev %02x LBA%s %llx count %04x\n",
53
-	      command->cb.cmd_stat, command->cb.device,
54
-	      ( command->cb.lba48 ? "48" : "" ),
55
-	      ( unsigned long long ) command->cb.lba.native,
56
-	      command->cb.count.native );
288
+/**
289
+ * Use no data buffer for ATA command
290
+ *
291
+ * @v atacmd		ATA command
292
+ * @v buffer		Available buffer
293
+ * @v len		Available buffer length
294
+ * @ret data		Data buffer
295
+ * @ret data_len	Data buffer length
296
+ */
297
+static void atacmd_data_none ( struct ata_command *atacmd __unused,
298
+			       userptr_t buffer __unused, size_t len __unused,
299
+			       userptr_t *data __unused,
300
+			       size_t *data_len __unused ) {
301
+	/* Nothing to do */
302
+}
303
+
304
+/**
305
+ * Use private data buffer for ATA command
306
+ *
307
+ * @v atacmd		ATA command
308
+ * @v buffer		Available buffer
309
+ * @v len		Available buffer length
310
+ * @ret data		Data buffer
311
+ * @ret data_len	Data buffer length
312
+ */
313
+static void atacmd_data_priv ( struct ata_command *atacmd,
314
+			       userptr_t buffer __unused, size_t len __unused,
315
+			       userptr_t *data, size_t *data_len ) {
316
+	*data = virt_to_user ( atacmd_priv ( atacmd ) );
317
+	*data_len = atacmd->type->priv_len;
318
+}
319
+
320
+/** ATA READ command type */
321
+static struct ata_command_type atacmd_read = {
322
+	.name = "READ",
323
+	.cmd_lba = ATA_CMD_READ,
324
+	.cmd_lba48 = ATA_CMD_READ_EXT,
325
+	.data_in = atacmd_data_buffer,
326
+	.data_out = atacmd_data_none,
327
+	.done = atacmd_close,
328
+};
329
+
330
+/** ATA WRITE command type */
331
+static struct ata_command_type atacmd_write = {
332
+	.name = "WRITE",
333
+	.cmd_lba = ATA_CMD_WRITE,
334
+	.cmd_lba48 = ATA_CMD_WRITE_EXT,
335
+	.data_in = atacmd_data_none,
336
+	.data_out = atacmd_data_buffer,
337
+	.done = atacmd_close,
338
+};
339
+
340
+/** ATA IDENTIFY private data */
341
+struct ata_identify_private {
342
+	/** Identity data */
343
+	struct ata_identity identity;
344
+};
345
+
346
+/**
347
+ * Return ATA model string (for debugging)
348
+ *
349
+ * @v identify		ATA identity data
350
+ * @ret model		Model string
351
+ */
352
+static const char * ata_model ( struct ata_identity *identity ) {
353
+	static union {
354
+		uint16_t words[ sizeof ( identity->model ) / 2 ];
355
+		char text[ sizeof ( identity->model ) + 1 /* NUL */ ];
356
+	} buf;
357
+	unsigned int i;
57 358
 
58
-	/* Flag command as in-progress */
59
-	command->rc = -EINPROGRESS;
359
+	for ( i = 0 ; i < ( sizeof ( identity->model ) / 2 ) ; i++ )
360
+		buf.words[i] = bswap_16 ( identity->model[i] );
60 361
 
61
-	/* Issue ATA command */
62
-	if ( ( rc = ata->command ( ata, command ) ) != 0 ) {
63
-		/* Something went wrong with the issuing mechanism */
64
-		DBG ( "ATA could not issue command: %s\n", strerror ( rc ) );
65
-		return rc;
362
+	return buf.text;
363
+}
364
+
365
+/**
366
+ * Handle ATA IDENTIFY command completion
367
+ *
368
+ * @v atacmd		ATA command
369
+ * @v rc		Reason for completion
370
+ */
371
+static void atacmd_identify_done ( struct ata_command *atacmd, int rc ) {
372
+	struct ata_device *atadev = atacmd->atadev;
373
+	struct ata_identify_private *priv = atacmd_priv ( atacmd );
374
+	struct ata_identity *identity = &priv->identity;
375
+	struct block_device_capacity capacity;
376
+
377
+	/* Close if command failed */
378
+	if ( rc != 0 ) {
379
+		atacmd_close ( atacmd, rc );
380
+		return;
66 381
 	}
67 382
 
68
-	/* Wait for command to complete */
69
-	while ( command->rc == -EINPROGRESS )
70
-		step();
71
-	if ( ( rc = command->rc ) != 0 ) {
72
-		/* Something went wrong with the command execution */
73
-		DBG ( "ATA command failed: %s\n", strerror ( rc ) );
74
-		return rc;
383
+	/* Extract capacity */
384
+	if ( identity->supports_lba48 & cpu_to_le16 ( ATA_SUPPORTS_LBA48 ) ) {
385
+		atadev->lba48 = 1;
386
+		capacity.blocks = le64_to_cpu ( identity->lba48_sectors );
387
+	} else {
388
+		capacity.blocks = le32_to_cpu ( identity->lba_sectors );
75 389
 	}
390
+	capacity.blksize = ATA_SECTOR_SIZE;
391
+	capacity.max_count = atadev->max_count;
392
+	DBGC ( atadev, "ATA %p is a %s\n", atadev, ata_model ( identity ) );
393
+	DBGC ( atadev, "ATA %p has %#llx blocks (%ld MB) and uses %s\n",
394
+	       atadev, capacity.blocks,
395
+	       ( ( signed long ) ( capacity.blocks >> 11 ) ),
396
+	       ( atadev->lba48 ? "LBA48" : "LBA" ) );
76 397
 
77
-	return 0;
398
+	/* Return capacity to caller */
399
+	block_capacity ( &atacmd->block, &capacity );
400
+
401
+	/* Close command */
402
+	atacmd_close ( atacmd, 0 );
78 403
 }
79 404
 
405
+/** ATA IDENTITY command type */
406
+static struct ata_command_type atacmd_identify = {
407
+	.name = "IDENTIFY",
408
+	.priv_len = sizeof ( struct ata_identify_private ),
409
+	.cmd_lba = ATA_CMD_IDENTIFY,
410
+	.cmd_lba48 = ATA_CMD_IDENTIFY,
411
+	.data_in = atacmd_data_priv,
412
+	.data_out = atacmd_data_none,
413
+	.done = atacmd_identify_done,
414
+};
415
+
416
+/** ATA command block interface operations */
417
+static struct interface_operation atacmd_block_op[] = {
418
+	INTF_OP ( intf_close, struct ata_command *, atacmd_close ),
419
+};
420
+
421
+/** ATA command block interface descriptor */
422
+static struct interface_descriptor atacmd_block_desc =
423
+	INTF_DESC_PASSTHRU ( struct ata_command, block,
424
+			     atacmd_block_op, ata );
425
+
426
+/** ATA command ATA interface operations */
427
+static struct interface_operation atacmd_ata_op[] = {
428
+	INTF_OP ( intf_close, struct ata_command *, atacmd_done ),
429
+};
430
+
431
+/** ATA command ATA interface descriptor */
432
+static struct interface_descriptor atacmd_ata_desc =
433
+	INTF_DESC_PASSTHRU ( struct ata_command, ata,
434
+			     atacmd_ata_op, block );
435
+
80 436
 /**
81
- * Read block from ATA device
437
+ * Create ATA command
82 438
  *
83
- * @v blockdev		Block device
84
- * @v block		LBA block number
85
- * @v count		Block count
439
+ * @v atadev		ATA device
440
+ * @v block		Block data interface
441
+ * @v type		ATA command type
442
+ * @v lba		Starting logical block address
443
+ * @v count		Number of blocks to transfer
86 444
  * @v buffer		Data buffer
445
+ * @v len		Length of data buffer
87 446
  * @ret rc		Return status code
88 447
  */
89
-static int ata_read ( struct block_device *blockdev, uint64_t block,
90
-		      unsigned long count, userptr_t buffer ) {
91
-	struct ata_device *ata = block_to_ata ( blockdev );
92
-	struct ata_command command;
448
+static int atadev_command ( struct ata_device *atadev,
449
+			    struct interface *block,
450
+			    struct ata_command_type *type,
451
+			    uint64_t lba, unsigned int count,
452
+			    userptr_t buffer, size_t len ) {
453
+	struct ata_command *atacmd;
454
+	struct ata_cmd command;
455
+	int tag;
456
+	int rc;
457
+
458
+	/* Allocate and initialise structure */
459
+	atacmd = zalloc ( sizeof ( *atacmd ) + type->priv_len );
460
+	if ( ! atacmd ) {
461
+		rc = -ENOMEM;
462
+		goto err_zalloc;
463
+	}
464
+	ref_init ( &atacmd->refcnt, atacmd_free );
465
+	intf_init ( &atacmd->block, &atacmd_block_desc, &atacmd->refcnt );
466
+	intf_init ( &atacmd->ata, &atacmd_ata_desc,
467
+		    &atacmd->refcnt );
468
+	atacmd->atadev = atadev_get ( atadev );
469
+	list_add ( &atacmd->list, &ata_commands );
470
+	atacmd->type = type;
93 471
 
472
+	/* Sanity check */
473
+	if ( len != ( count * ATA_SECTOR_SIZE ) ) {
474
+		DBGC ( atadev, "ATA %p tag %08x buffer length mismatch (count "
475
+		       "%d len %zd)\n", atadev, atacmd->tag, count, len );
476
+		rc = -EINVAL;
477
+		goto err_len;
478
+	}
479
+
480
+	/* Construct command */
94 481
 	memset ( &command, 0, sizeof ( command ) );
95
-	command.cb.lba.native = block;
482
+	command.cb.lba.native = lba;
96 483
 	command.cb.count.native = count;
97
-	command.cb.device = ( ata->device | ATA_DEV_OBSOLETE | ATA_DEV_LBA );
98
-	command.cb.lba48 = ata->lba48;
99
-	if ( ! ata->lba48 )
484
+	command.cb.device = ( atadev->device | ATA_DEV_OBSOLETE | ATA_DEV_LBA );
485
+	command.cb.lba48 = atadev->lba48;
486
+	if ( ! atadev->lba48 )
100 487
 		command.cb.device |= command.cb.lba.bytes.low_prev;
101
-	command.cb.cmd_stat = ( ata->lba48 ? ATA_CMD_READ_EXT : ATA_CMD_READ );
102
-	command.data_in = buffer;
103
-	return ata_command ( ata, &command );
488
+	command.cb.cmd_stat =
489
+		( atadev->lba48 ? type->cmd_lba48 : type->cmd_lba );
490
+	type->data_in ( atacmd, buffer, len,
491
+			&command.data_in, &command.data_in_len );
492
+	type->data_out ( atacmd, buffer, len,
493
+			 &command.data_out, &command.data_out_len );
494
+
495
+	/* Issue command */
496
+	if ( ( tag = ata_command ( &atadev->ata, &atacmd->ata,
497
+				   &command ) ) < 0 ) {
498
+		rc = tag;
499
+		DBGC ( atadev, "ATA %p tag %08x could not issue command: %s\n",
500
+		       atadev, atacmd->tag, strerror ( rc ) );
501
+		goto err_command;
502
+	}
503
+	atacmd->tag = tag;
504
+
505
+	DBGC2 ( atadev, "ATA %p tag %08x %s cmd %02x dev %02x LBA%s %08llx "
506
+		"count %04x\n", atadev, atacmd->tag, atacmd->type->name,
507
+		command.cb.cmd_stat, command.cb.device,
508
+		( command.cb.lba48 ? "48" : "" ),
509
+		( unsigned long long ) command.cb.lba.native,
510
+		command.cb.count.native );
511
+
512
+	/* Attach to parent interface, mortalise self, and return */
513
+	intf_plug_plug ( &atacmd->block, block );
514
+	ref_put ( &atacmd->refcnt );
515
+	return 0;
516
+
517
+ err_command:
518
+ err_len:
519
+	atacmd_close ( atacmd, rc );
520
+	ref_put ( &atacmd->refcnt );
521
+ err_zalloc:
522
+	return rc;
104 523
 }
105 524
 
106 525
 /**
107
- * Write block to ATA device
526
+ * Issue ATA block read
108 527
  *
109
- * @v blockdev		Block device
110
- * @v block		LBA block number
111
- * @v count		Block count
528
+ * @v atadev		ATA device
529
+ * @v block		Block data interface
530
+ * @v lba		Starting logical block address
531
+ * @v count		Number of blocks to transfer
112 532
  * @v buffer		Data buffer
533
+ * @v len		Length of data buffer
113 534
  * @ret rc		Return status code
535
+
114 536
  */
115
-static int ata_write ( struct block_device *blockdev, uint64_t block,
116
-		       unsigned long count, userptr_t buffer ) {
117
-	struct ata_device *ata = block_to_ata ( blockdev );
118
-	struct ata_command command;
119
-	
120
-	memset ( &command, 0, sizeof ( command ) );
121
-	command.cb.lba.native = block;
122
-	command.cb.count.native = count;
123
-	command.cb.device = ( ata->device | ATA_DEV_OBSOLETE | ATA_DEV_LBA );
124
-	command.cb.lba48 = ata->lba48;
125
-	if ( ! ata->lba48 )
126
-		command.cb.device |= command.cb.lba.bytes.low_prev;
127
-	command.cb.cmd_stat = ( ata->lba48 ?
128
-				ATA_CMD_WRITE_EXT : ATA_CMD_WRITE );
129
-	command.data_out = buffer;
130
-	return ata_command ( ata, &command );
537
+static int atadev_read ( struct ata_device *atadev,
538
+			 struct interface *block,
539
+			 uint64_t lba, unsigned int count,
540
+			 userptr_t buffer, size_t len ) {
541
+	return atadev_command ( atadev, block, &atacmd_read,
542
+				lba, count, buffer, len );
131 543
 }
132 544
 
133 545
 /**
134
- * Identify ATA device
546
+ * Issue ATA block write
135 547
  *
136
- * @v blockdev		Block device
548
+ * @v atadev		ATA device
549
+ * @v block		Block data interface
550
+ * @v lba		Starting logical block address
551
+ * @v count		Number of blocks to transfer
552
+ * @v buffer		Data buffer
553
+ * @v len		Length of data buffer
137 554
  * @ret rc		Return status code
138 555
  */
139
-static int ata_identify ( struct block_device *blockdev ) {
140
-	struct ata_device *ata = block_to_ata ( blockdev );
141
-	struct ata_command command;
142
-	struct ata_identity identity;
143
-	int rc;
556
+static int atadev_write ( struct ata_device *atadev,
557
+			  struct interface *block,
558
+			  uint64_t lba, unsigned int count,
559
+			  userptr_t buffer, size_t len ) {
560
+	return atadev_command ( atadev, block, &atacmd_write,
561
+				lba, count, buffer, len );
562
+}
144 563
 
145
-	/* Issue IDENTIFY */
146
-	memset ( &command, 0, sizeof ( command ) );
147
-	command.cb.count.native = 1;
148
-	command.cb.device = ( ata->device | ATA_DEV_OBSOLETE | ATA_DEV_LBA );
149
-	command.cb.cmd_stat = ATA_CMD_IDENTIFY;
150
-	command.data_in = virt_to_user ( &identity );
151
-	linker_assert ( sizeof ( identity ) == ATA_SECTOR_SIZE,
152
-			__ata_identity_bad_size__ );
153
-	if ( ( rc = ata_command ( ata, &command ) ) != 0 )
154
-		return rc;
155
-
156
-	/* Fill in block device parameters */
157
-	blockdev->blksize = ATA_SECTOR_SIZE;
158
-	if ( identity.supports_lba48 & cpu_to_le16 ( ATA_SUPPORTS_LBA48 ) ) {
159
-		ata->lba48 = 1;
160
-		blockdev->blocks = le64_to_cpu ( identity.lba48_sectors );
161
-	} else {
162
-		blockdev->blocks = le32_to_cpu ( identity.lba_sectors );
564
+/**
565
+ * Read ATA device capacity
566
+ *
567
+ * @v atadev		ATA device
568
+ * @v block		Block data interface
569
+ * @ret rc		Return status code
570
+ */
571
+static int atadev_read_capacity ( struct ata_device *atadev,
572
+				  struct interface *block ) {
573
+	struct ata_identity *identity;
574
+
575
+	assert ( atacmd_identify.priv_len == sizeof ( *identity ) );
576
+	assert ( atacmd_identify.priv_len == ATA_SECTOR_SIZE );
577
+	return atadev_command ( atadev, block, &atacmd_identify,
578
+				0, 1, UNULL, ATA_SECTOR_SIZE );
579
+}
580
+
581
+/**
582
+ * Close ATA device
583
+ *
584
+ * @v atadev		ATA device
585
+ * @v rc		Reason for close
586
+ */
587
+static void atadev_close ( struct ata_device *atadev, int rc ) {
588
+	struct ata_command *atacmd;
589
+	struct ata_command *tmp;
590
+
591
+	/* Shut down interfaces */
592
+	intf_shutdown ( &atadev->block, rc );
593
+	intf_shutdown ( &atadev->ata, rc );
594
+
595
+	/* Shut down any remaining commands */
596
+	list_for_each_entry_safe ( atacmd, tmp, &ata_commands, list ) {
597
+		if ( atacmd->atadev != atadev )
598
+			continue;
599
+		atacmd_get ( atacmd );
600
+		atacmd_close ( atacmd, rc );
601
+		atacmd_put ( atacmd );
163 602
 	}
164
-	return 0;
165 603
 }
166 604
 
167
-static struct block_device_operations ata_operations = {
168
-	.read	= ata_read,
169
-	.write	= ata_write
605
+/** ATA device block interface operations */
606
+static struct interface_operation atadev_block_op[] = {
607
+	INTF_OP ( block_read, struct ata_device *, atadev_read ),
608
+	INTF_OP ( block_write, struct ata_device *, atadev_write ),
609
+	INTF_OP ( block_read_capacity, struct ata_device *,
610
+		  atadev_read_capacity ),
611
+	INTF_OP ( intf_close, struct ata_device *, atadev_close ),
170 612
 };
171 613
 
614
+/** ATA device block interface descriptor */
615
+static struct interface_descriptor atadev_block_desc =
616
+	INTF_DESC_PASSTHRU ( struct ata_device, block,
617
+			     atadev_block_op, ata );
618
+
619
+/** ATA device ATA interface operations */
620
+static struct interface_operation atadev_ata_op[] = {
621
+	INTF_OP ( intf_close, struct ata_device *, atadev_close ),
622
+};
623
+
624
+/** ATA device ATA interface descriptor */
625
+static struct interface_descriptor atadev_ata_desc =
626
+	INTF_DESC_PASSTHRU ( struct ata_device, ata,
627
+			     atadev_ata_op, block );
628
+
172 629
 /**
173
- * Initialise ATA device
630
+ * Open ATA device
174 631
  *
175
- * @v ata		ATA device
632
+ * @v block		Block control interface
633
+ * @v ata		ATA control interface
634
+ * @v device		ATA device number
635
+ * @v max_count		Maximum number of blocks per single transfer
176 636
  * @ret rc		Return status code
177
- *
178
- * Initialises an ATA device.  The ata_device::command field and the
179
- * @c ATA_FL_SLAVE portion of the ata_device::flags field must already
180
- * be filled in.  This function will configure ata_device::blockdev,
181
- * including issuing an IDENTIFY DEVICE call to determine the block
182
- * size and total device size.
183 637
  */
184
-int init_atadev ( struct ata_device *ata ) {
185
-	/** Fill in read and write methods, and get device capacity */
186
-	ata->blockdev.op = &ata_operations;
187
-	return ata_identify ( &ata->blockdev );
638
+int ata_open ( struct interface *block, struct interface *ata,
639
+	       unsigned int device, unsigned int max_count ) {
640
+	struct ata_device *atadev;
641
+
642
+	/* Allocate and initialise structure */
643
+	atadev = zalloc ( sizeof ( *atadev ) );
644
+	if ( ! atadev )
645
+		return -ENOMEM;
646
+	ref_init ( &atadev->refcnt, NULL );
647
+	intf_init ( &atadev->block, &atadev_block_desc, &atadev->refcnt );
648
+	intf_init ( &atadev->ata, &atadev_ata_desc, &atadev->refcnt );
649
+	atadev->device = device;
650
+	atadev->max_count = max_count;
651
+
652
+	/* Attach to ATA and parent and interfaces, mortalise self,
653
+	 * and return
654
+	 */
655
+	intf_plug_plug ( &atadev->ata, ata );
656
+	intf_plug_plug ( &atadev->block, block );
657
+	ref_put ( &atadev->refcnt );
658
+	return 0;
188 659
 }

src/arch/i386/interface/pcbios/ibft.c → src/drivers/block/ibft.c Näytä tiedosto

@@ -32,7 +32,6 @@ FILE_LICENCE ( BSD2 );
32 32
 #include <string.h>
33 33
 #include <errno.h>
34 34
 #include <byteswap.h>
35
-#include <realmode.h>
36 35
 #include <ipxe/pci.h>
37 36
 #include <ipxe/acpi.h>
38 37
 #include <ipxe/in.h>
@@ -53,62 +52,36 @@ FILE_LICENCE ( BSD2 );
53 52
  *
54 53
  */
55 54
 
56
-#define ibftab __use_data16 ( ibftab )
57
-/** The iBFT used by iPXE */
58
-struct ipxe_ibft __data16 ( ibftab ) = {
59
-	/* Table header */
60
-	.table = {
61
-		/* ACPI header */
62
-		.acpi = {
63
-			.signature = IBFT_SIG,
64
-			.length = sizeof ( ibftab ),
65
-			.revision = 1,
66
-			.oem_id = "FENSYS",
67
-			.oem_table_id = "iPXE",
68
-		},
69
-		/* Control block */
70
-		.control = {
71
-			.header = {
72
-				.structure_id = IBFT_STRUCTURE_ID_CONTROL,
73
-				.version = 1,
74
-				.length = sizeof ( ibftab.table.control ),
75
-				.flags = 0,
76
-			},
77
-			.initiator = offsetof ( typeof ( ibftab ), initiator ),
78
-			.nic_0 = offsetof ( typeof ( ibftab ), nic ),
79
-			.target_0 = offsetof ( typeof ( ibftab ), target ),
80
-		},
81
-	},
82
-	/* iSCSI initiator information */
83
-	.initiator = {
84
-		.header = {
85
-			.structure_id = IBFT_STRUCTURE_ID_INITIATOR,
86
-			.version = 1,
87
-			.length = sizeof ( ibftab.initiator ),
88
-			.flags = ( IBFT_FL_INITIATOR_BLOCK_VALID |
89
-				   IBFT_FL_INITIATOR_FIRMWARE_BOOT_SELECTED ),
90
-		},
91
-	},
92
-	/* NIC information */
93
-	.nic = {
94
-		.header = {
95
-			.structure_id = IBFT_STRUCTURE_ID_NIC,
96
-			.version = 1,
97
-			.length = sizeof ( ibftab.nic ),
98
-			.flags = ( IBFT_FL_NIC_BLOCK_VALID |
99
-				   IBFT_FL_NIC_FIRMWARE_BOOT_SELECTED ),
100
-		},
101
-	},
102
-	/* iSCSI target information */
103
-	.target = {
104
-		.header = {
105
-			.structure_id = IBFT_STRUCTURE_ID_TARGET,
106
-			.version = 1,
107
-			.length = sizeof ( ibftab.target ),
108
-			.flags = ( IBFT_FL_TARGET_BLOCK_VALID |
109
-				   IBFT_FL_TARGET_FIRMWARE_BOOT_SELECTED ),
110
-		},
111
-	},
55
+/**
56
+ * An iBFT created by iPXE
57
+ *
58
+ */
59
+struct ipxe_ibft {
60
+	/** The fixed section */
61
+	struct ibft_table table;
62
+	/** The Initiator section */
63
+	struct ibft_initiator initiator __attribute__ (( aligned ( 16 ) ));
64
+	/** The NIC section */
65
+	struct ibft_nic nic __attribute__ (( aligned ( 16 ) ));
66
+	/** The Target section */
67
+	struct ibft_target target __attribute__ (( aligned ( 16 ) ));
68
+	/** Strings block */
69
+	char strings[0];
70
+} __attribute__ (( packed, aligned ( 16 ) ));
71
+
72
+/**
73
+ * iSCSI string block descriptor
74
+ *
75
+ * This is an internal structure that we use to keep track of the
76
+ * allocation of string data.
77
+ */
78
+struct ibft_strings {
79
+	/** The iBFT containing these strings */
80
+	struct ibft_table *table;
81
+	/** Offset of first free byte within iBFT */
82
+	size_t offset;
83
+	/** Total length of the iBFT */
84
+	size_t len;
112 85
 };
113 86
 
114 87
 /**
@@ -132,9 +105,9 @@ static void ibft_set_ipaddr ( struct ibft_ipaddr *ipaddr, struct in_addr in ) {
132 105
  * @v setting		Configuration setting
133 106
  * @v tag		DHCP option tag
134 107
  */
135
-static void ibft_set_ipaddr_option ( struct ibft_ipaddr *ipaddr,
136
-				     struct setting *setting ) {
137
-	struct in_addr in = { 0 };
108
+static void ibft_set_ipaddr_setting ( struct ibft_ipaddr *ipaddr,
109
+				      struct setting *setting ) {
110
+	struct in_addr in;
138 111
 	fetch_ipv4_setting ( NULL, setting, &in );
139 112
 	ibft_set_ipaddr ( ipaddr, in );
140 113
 }
@@ -156,22 +129,19 @@ static const char * ibft_ipaddr ( struct ibft_ipaddr *ipaddr ) {
156 129
  * @v strings		iBFT string block descriptor
157 130
  * @v string		String field to fill in
158 131
  * @v len		Length of string to allocate (excluding NUL)
159
- * @ret rc		Return status code
132
+ * @ret dest		String destination, or NULL
160 133
  */
161
-static int ibft_alloc_string ( struct ibft_string_block *strings,
162
-			       struct ibft_string *string, size_t len ) {
163
-	char *dest;
164
-	unsigned int remaining;
134
+static char * ibft_alloc_string ( struct ibft_strings *strings,
135
+				  struct ibft_string *string, size_t len ) {
165 136
 
166
-	dest = ( ( ( char * ) strings->table ) + strings->offset );
167
-	remaining = ( strings->table->acpi.length - strings->offset );
168
-	if ( len >= remaining )
169
-		return -ENOMEM;
137
+	if ( ( strings->offset + len ) >= strings->len )
138
+		return NULL;
170 139
 
171
-	string->offset = strings->offset;
172
-	string->length = len;
140
+	string->offset = cpu_to_le16 ( strings->offset );
141
+	string->len = cpu_to_le16 ( len );
173 142
 	strings->offset += ( len + 1 );
174
-	return 0;
143
+
144
+	return ( ( ( char * ) strings->table ) + string->offset );
175 145
 }
176 146
 
177 147
 /**
@@ -182,18 +152,16 @@ static int ibft_alloc_string ( struct ibft_string_block *strings,
182 152
  * @v data		String to fill in, or NULL
183 153
  * @ret rc		Return status code
184 154
  */
185
-static int ibft_set_string ( struct ibft_string_block *strings,
155
+static int ibft_set_string ( struct ibft_strings *strings,
186 156
 			     struct ibft_string *string, const char *data ) {
187 157
 	char *dest;
188
-	int rc;
189 158
 
190 159
 	if ( ! data )
191 160
 		return 0;
192 161
 
193
-	if ( ( rc = ibft_alloc_string ( strings, string,
194
-					strlen ( data ) ) ) != 0 )
195
-		return rc;
196
-	dest = ( ( ( char * ) strings->table ) + string->offset );
162
+	dest = ibft_alloc_string ( strings, string, strlen ( data ) );
163
+	if ( ! dest )
164
+		return -ENOBUFS;
197 165
 	strcpy ( dest, data );
198 166
 
199 167
 	return 0;
@@ -207,24 +175,24 @@ static int ibft_set_string ( struct ibft_string_block *strings,
207 175
  * @v setting		Configuration setting
208 176
  * @ret rc		Return status code
209 177
  */
210
-static int ibft_set_string_option ( struct ibft_string_block *strings,
211
-				    struct ibft_string *string,
212
-				    struct setting *setting ) {
178
+static int ibft_set_string_setting ( struct ibft_strings *strings,
179
+				     struct ibft_string *string,
180
+				     struct setting *setting ) {
213 181
 	int len;
214 182
 	char *dest;
215
-	int rc;
216 183
 
217 184
 	len = fetch_setting_len ( NULL, setting );
218 185
 	if ( len < 0 ) {
219 186
 		string->offset = 0;
220
-		string->length = 0;
187
+		string->len = 0;
221 188
 		return 0;
222 189
 	}
223 190
 
224
-	if ( ( rc = ibft_alloc_string ( strings, string, len ) ) != 0 )
225
-		return rc;
226
-	dest = ( ( ( char * ) strings->table ) + string->offset );
191
+	dest = ibft_alloc_string ( strings, string, len );
192
+	if ( ! dest )
193
+		return -ENOBUFS;
227 194
 	fetch_string_setting ( NULL, setting, dest, ( len + 1 ) );
195
+
228 196
 	return 0;
229 197
 }
230 198
 
@@ -235,7 +203,7 @@ static int ibft_set_string_option ( struct ibft_string_block *strings,
235 203
  * @v string		String field
236 204
  * @ret data		String content (or "<empty>")
237 205
  */
238
-static const char * ibft_string ( struct ibft_string_block *strings,
206
+static const char * ibft_string ( struct ibft_strings *strings,
239 207
 				  struct ibft_string *string ) {
240 208
 	return ( string->offset ?
241 209
 		 ( ( ( char * ) strings->table ) + string->offset ) : NULL );
@@ -250,22 +218,29 @@ static const char * ibft_string ( struct ibft_string_block *strings,
250 218
  * @ret rc		Return status code
251 219
  */
252 220
 static int ibft_fill_nic ( struct ibft_nic *nic,
253
-			   struct ibft_string_block *strings,
221
+			   struct ibft_strings *strings,
254 222
 			   struct net_device *netdev ) {
255 223
 	struct ll_protocol *ll_protocol = netdev->ll_protocol;
256 224
 	struct in_addr netmask_addr = { 0 };
257 225
 	unsigned int netmask_count = 0;
258 226
 	int rc;
259 227
 
260
-	/* Extract values from DHCP configuration */
261
-	ibft_set_ipaddr_option ( &nic->ip_address, &ip_setting );
228
+	/* Fill in common header */
229
+	nic->header.structure_id = IBFT_STRUCTURE_ID_NIC;
230
+	nic->header.version = 1;
231
+	nic->header.length = cpu_to_le16 ( sizeof ( *nic ) );
232
+	nic->header.flags = ( IBFT_FL_NIC_BLOCK_VALID |
233
+			      IBFT_FL_NIC_FIRMWARE_BOOT_SELECTED );
234
+
235
+	/* Extract values from configuration settings */
236
+	ibft_set_ipaddr_setting ( &nic->ip_address, &ip_setting );
262 237
 	DBG ( "iBFT NIC IP = %s\n", ibft_ipaddr ( &nic->ip_address ) );
263
-	ibft_set_ipaddr_option ( &nic->gateway, &gateway_setting );
238
+	ibft_set_ipaddr_setting ( &nic->gateway, &gateway_setting );
264 239
 	DBG ( "iBFT NIC gateway = %s\n", ibft_ipaddr ( &nic->gateway ) );
265
-	ibft_set_ipaddr_option ( &nic->dns[0], &dns_setting );
240
+	ibft_set_ipaddr_setting ( &nic->dns[0], &dns_setting );
266 241
 	DBG ( "iBFT NIC DNS = %s\n", ibft_ipaddr ( &nic->dns[0] ) );
267
-	if ( ( rc = ibft_set_string_option ( strings, &nic->hostname,
268
-					     &hostname_setting ) ) != 0 )
242
+	if ( ( rc = ibft_set_string_setting ( strings, &nic->hostname,
243
+					      &hostname_setting ) ) != 0 )
269 244
 		return rc;
270 245
 	DBG ( "iBFT NIC hostname = %s\n",
271 246
 	      ibft_string ( strings, &nic->hostname ) );
@@ -287,8 +262,8 @@ static int ibft_fill_nic ( struct ibft_nic *nic,
287 262
 		return rc;
288 263
 	}
289 264
 	DBG ( "iBFT NIC MAC = %s\n", eth_ntoa ( nic->mac_address ) );
290
-	nic->pci_bus_dev_func = netdev->dev->desc.location;
291
-	DBG ( "iBFT NIC PCI = %04x\n", nic->pci_bus_dev_func );
265
+	nic->pci_bus_dev_func = cpu_to_le16 ( netdev->dev->desc.location );
266
+	DBG ( "iBFT NIC PCI = %04x\n", le16_to_cpu ( nic->pci_bus_dev_func ) );
292 267
 
293 268
 	return 0;
294 269
 }
@@ -301,10 +276,18 @@ static int ibft_fill_nic ( struct ibft_nic *nic,
301 276
  * @ret rc		Return status code
302 277
  */
303 278
 static int ibft_fill_initiator ( struct ibft_initiator *initiator,
304
-				 struct ibft_string_block *strings ) {
279
+				 struct ibft_strings *strings ) {
305 280
 	const char *initiator_iqn = iscsi_initiator_iqn();
306 281
 	int rc;
307 282
 
283
+	/* Fill in common header */
284
+	initiator->header.structure_id = IBFT_STRUCTURE_ID_INITIATOR;
285
+	initiator->header.version = 1;
286
+	initiator->header.length = cpu_to_le16 ( sizeof ( *initiator ) );
287
+	initiator->header.flags = ( IBFT_FL_INITIATOR_BLOCK_VALID |
288
+				    IBFT_FL_INITIATOR_FIRMWARE_BOOT_SELECTED );
289
+
290
+	/* Fill in hostname */
308 291
 	if ( ( rc = ibft_set_string ( strings, &initiator->initiator_name,
309 292
 				      initiator_iqn ) ) != 0 )
310 293
 		return rc;
@@ -323,7 +306,7 @@ static int ibft_fill_initiator ( struct ibft_initiator *initiator,
323 306
  * @ret rc		Return status code
324 307
  */
325 308
 static int ibft_fill_target_chap ( struct ibft_target *target,
326
-				   struct ibft_string_block *strings,
309
+				   struct ibft_strings *strings,
327 310
 				   struct iscsi_session *iscsi ) {
328 311
 	int rc;
329 312
 
@@ -356,7 +339,7 @@ static int ibft_fill_target_chap ( struct ibft_target *target,
356 339
  * @ret rc		Return status code
357 340
  */
358 341
 static int ibft_fill_target_reverse_chap ( struct ibft_target *target,
359
-					   struct ibft_string_block *strings,
342
+					   struct ibft_strings *strings,
360 343
 					   struct iscsi_session *iscsi ) {
361 344
 	int rc;
362 345
 
@@ -391,17 +374,27 @@ static int ibft_fill_target_reverse_chap ( struct ibft_target *target,
391 374
  * @ret rc		Return status code
392 375
  */
393 376
 static int ibft_fill_target ( struct ibft_target *target,
394
-			      struct ibft_string_block *strings,
377
+			      struct ibft_strings *strings,
395 378
 			      struct iscsi_session *iscsi ) {
396 379
 	struct sockaddr_in *sin_target =
397 380
 		( struct sockaddr_in * ) &iscsi->target_sockaddr;
398 381
 	int rc;
399 382
 
383
+	/* Fill in common header */
384
+	target->header.structure_id = IBFT_STRUCTURE_ID_TARGET;
385
+	target->header.version = 1;
386
+	target->header.length = cpu_to_le16 ( sizeof ( *target ) );
387
+	target->header.flags = ( IBFT_FL_TARGET_BLOCK_VALID |
388
+				 IBFT_FL_TARGET_FIRMWARE_BOOT_SELECTED );
389
+
400 390
 	/* Fill in Target values */
401 391
 	ibft_set_ipaddr ( &target->ip_address, sin_target->sin_addr );
402 392
 	DBG ( "iBFT target IP = %s\n", ibft_ipaddr ( &target->ip_address ) );
403
-	target->socket = ntohs ( sin_target->sin_port );
393
+	target->socket = cpu_to_le16 ( ntohs ( sin_target->sin_port ) );
404 394
 	DBG ( "iBFT target port = %d\n", target->socket );
395
+	memcpy ( &target->boot_lun, &iscsi->lun, sizeof ( target->boot_lun ) );
396
+	DBG ( "iBFT target boot LUN = " SCSI_LUN_FORMAT "\n",
397
+	      SCSI_LUN_DATA ( target->boot_lun ) );
405 398
 	if ( ( rc = ibft_set_string ( strings, &target->target_name,
406 399
 				      iscsi->target_iqn ) ) != 0 )
407 400
 		return rc;
@@ -417,35 +410,62 @@ static int ibft_fill_target ( struct ibft_target *target,
417 410
 }
418 411
 
419 412
 /**
420
- * Fill in all variable portions of iBFT
413
+ * Fill in iBFT
421 414
  *
422
- * @v netdev		Network device
423
- * @v initiator_iqn	Initiator IQN
424
- * @v st_target		Target socket address
425
- * @v target_iqn	Target IQN
415
+ * @v iscsi		iSCSI session
416
+ * @v acpi		ACPI table
417
+ * @v len		Length of ACPI table
426 418
  * @ret rc		Return status code
427
- *
428 419
  */
429
-int ibft_fill_data ( struct net_device *netdev,
430
-		     struct iscsi_session *iscsi ) {
431
-	struct ibft_string_block strings = {
432
-		.table = &ibftab.table,
433
-		.offset = offsetof ( typeof ( ibftab ), strings ),
420
+int ibft_describe ( struct iscsi_session *iscsi,
421
+		    struct acpi_description_header *acpi,
422
+		    size_t len ) {
423
+	struct ipxe_ibft *ibft =
424
+		container_of ( acpi, struct ipxe_ibft, table.acpi );
425
+	struct ibft_strings strings = {
426
+		.table = &ibft->table,
427
+		.offset = offsetof ( typeof ( *ibft ), strings ),
428
+		.len = len,
434 429
 	};
430
+	struct net_device *netdev;
435 431
 	int rc;
436 432
 
437
-	/* Fill in NIC, Initiator and Target portions */
438
-	if ( ( rc = ibft_fill_nic ( &ibftab.nic, &strings, netdev ) ) != 0 )
433
+	/* Ugly hack.  Now that we have a generic interface mechanism
434
+	 * that can support ioctls, we can potentially eliminate this.
435
+	 */
436
+	netdev = last_opened_netdev();
437
+	if ( ! netdev ) {
438
+		DBGC ( iscsi, "iSCSI %p cannot guess network device\n",
439
+		       iscsi );
440
+		return -ENODEV;
441
+	}
442
+
443
+	/* Fill in ACPI header */
444
+	ibft->table.acpi.signature = cpu_to_le32 ( IBFT_SIG );
445
+	ibft->table.acpi.length = cpu_to_le32 ( len );
446
+	ibft->table.acpi.revision = 1;
447
+
448
+	/* Fill in Control block */
449
+	ibft->table.control.header.structure_id = IBFT_STRUCTURE_ID_CONTROL;
450
+	ibft->table.control.header.version = 1;
451
+	ibft->table.control.header.length =
452
+		cpu_to_le16 ( sizeof ( ibft->table.control ) );
453
+	ibft->table.control.initiator =
454
+		cpu_to_le16 ( offsetof ( typeof ( *ibft ), initiator ) );
455
+	ibft->table.control.nic_0 =
456
+		cpu_to_le16 ( offsetof ( typeof ( *ibft ), nic ) );
457
+	ibft->table.control.target_0 =
458
+		cpu_to_le16 ( offsetof ( typeof ( *ibft ), target ) );
459
+
460
+	/* Fill in NIC, Initiator and Target blocks */
461
+	if ( ( rc = ibft_fill_nic ( &ibft->nic, &strings, netdev ) ) != 0 )
439 462
 		return rc;
440
-	if ( ( rc = ibft_fill_initiator ( &ibftab.initiator,
463
+	if ( ( rc = ibft_fill_initiator ( &ibft->initiator,
441 464
 					  &strings ) ) != 0 )
442 465
 		return rc;
443
-	if ( ( rc = ibft_fill_target ( &ibftab.target, &strings,
466
+	if ( ( rc = ibft_fill_target ( &ibft->target, &strings,
444 467
 				       iscsi ) ) != 0 )
445 468
 		return rc;
446 469
 
447
-	/* Update checksum */
448
-	acpi_fix_checksum ( &ibftab.table.acpi );
449
-
450 470
 	return 0;
451 471
 }

+ 0
- 97
src/drivers/block/ramdisk.c Näytä tiedosto

@@ -1,97 +0,0 @@
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
-FILE_LICENCE ( GPL2_OR_LATER );
20
-
21
-#include <ipxe/blockdev.h>
22
-#include <ipxe/ramdisk.h>
23
-
24
-/**
25
- * @file
26
- *
27
- * RAM disks
28
- *
29
- */
30
-
31
-static inline __attribute__ (( always_inline )) struct ramdisk *
32
-block_to_ramdisk ( struct block_device *blockdev ) {
33
-	return container_of ( blockdev, struct ramdisk, blockdev );
34
-}
35
-
36
-/**
37
- * Read block
38
- *
39
- * @v blockdev		Block device
40
- * @v block		Block number
41
- * @v count		Block count
42
- * @v buffer		Data buffer
43
- * @ret rc		Return status code
44
- */
45
-static int ramdisk_read ( struct block_device *blockdev, uint64_t block,
46
-			  unsigned long count, userptr_t buffer ) {
47
-	struct ramdisk *ramdisk = block_to_ramdisk ( blockdev );
48
-	unsigned long offset = ( block * blockdev->blksize );
49
-	unsigned long length = ( count * blockdev->blksize );
50
-
51
-	DBGC ( ramdisk, "RAMDISK %p reading [%lx,%lx)\n",
52
-	       ramdisk, offset, length );
53
-
54
-	memcpy_user ( buffer, 0, ramdisk->data, offset, length );
55
-	return 0;
56
-}
57
-
58
-/**
59
- * Write block
60
- *
61
- * @v blockdev		Block device
62
- * @v block		Block number
63
- * @v count		Block count
64
- * @v buffer		Data buffer
65
- * @ret rc		Return status code
66
- */
67
-static int ramdisk_write ( struct block_device *blockdev, uint64_t block,
68
-			   unsigned long count, userptr_t buffer ) {
69
-	struct ramdisk *ramdisk = block_to_ramdisk ( blockdev );
70
-	unsigned long offset = ( block * blockdev->blksize );
71
-	unsigned long length = ( count * blockdev->blksize );
72
-
73
-	DBGC ( ramdisk, "RAMDISK %p writing [%lx,%lx)\n",
74
-	       ramdisk, offset, length );
75
-
76
-	memcpy_user ( ramdisk->data, offset, buffer, 0, length );
77
-	return 0;
78
-}
79
-
80
-static struct block_device_operations ramdisk_operations = {
81
-	.read	= ramdisk_read,
82
-	.write	= ramdisk_write
83
-};
84
-
85
-int init_ramdisk ( struct ramdisk *ramdisk, userptr_t data, size_t len,
86
-		   unsigned int blksize ) {
87
-	
88
-	if ( ! blksize )
89
-		blksize = 512;
90
-
91
-	ramdisk->data = data;
92
-	ramdisk->blockdev.op = &ramdisk_operations;
93
-	ramdisk->blockdev.blksize = blksize;
94
-	ramdisk->blockdev.blocks = ( len / blksize );
95
-
96
-	return 0;
97
-}

+ 641
- 237
src/drivers/block/scsi.c Näytä tiedosto

@@ -23,8 +23,8 @@ FILE_LICENCE ( GPL2_OR_LATER );
23 23
 #include <string.h>
24 24
 #include <byteswap.h>
25 25
 #include <errno.h>
26
+#include <ipxe/list.h>
26 27
 #include <ipxe/blockdev.h>
27
-#include <ipxe/process.h>
28 28
 #include <ipxe/scsi.h>
29 29
 
30 30
 /** @file
@@ -33,334 +33,738 @@ FILE_LICENCE ( GPL2_OR_LATER );
33 33
  *
34 34
  */
35 35
 
36
-/** Maximum number of dummy "read capacity (10)" operations
36
+/** Maximum number of command retries */
37
+#define SCSICMD_MAX_RETRIES 10
38
+
39
+/******************************************************************************
40
+ *
41
+ * Utility functions
37 42
  *
38
- * These are issued at connection setup to draw out various useless
39
- * power-on messages.
43
+ ******************************************************************************
40 44
  */
41
-#define SCSI_MAX_DUMMY_READ_CAP 10
42
-
43
-static inline __attribute__ (( always_inline )) struct scsi_device *
44
-block_to_scsi ( struct block_device *blockdev ) {
45
-	return container_of ( blockdev, struct scsi_device, blockdev );
46
-}
47 45
 
48 46
 /**
49
- * Handle SCSI command with no backing device
47
+ * Parse SCSI LUN
50 48
  *
51
- * @v scsi		SCSI device
52
- * @v command		SCSI command
49
+ * @v lun_string	LUN string representation
50
+ * @v lun		LUN to fill in
53 51
  * @ret rc		Return status code
54 52
  */
55
-int scsi_detached_command ( struct scsi_device *scsi __unused,
56
-			    struct scsi_command *command __unused ) {
57
-	return -ENODEV;
53
+int scsi_parse_lun ( const char *lun_string, struct scsi_lun *lun ) {
54
+	char *p;
55
+	int i;
56
+
57
+	memset ( lun, 0, sizeof ( *lun ) );
58
+	if ( lun_string ) {
59
+		p = ( char * ) lun_string;
60
+		for ( i = 0 ; i < 4 ; i++ ) {
61
+			lun->u16[i] = htons ( strtoul ( p, &p, 16 ) );
62
+			if ( *p == '\0' )
63
+				break;
64
+			if ( *p != '-' )
65
+				return -EINVAL;
66
+			p++;
67
+		}
68
+		if ( *p )
69
+			return -EINVAL;
70
+	}
71
+
72
+	return 0;
58 73
 }
59 74
 
75
+/******************************************************************************
76
+ *
77
+ * Interface methods
78
+ *
79
+ ******************************************************************************
80
+ */
81
+
60 82
 /**
61 83
  * Issue SCSI command
62 84
  *
63
- * @v scsi		SCSI device
85
+ * @v control		SCSI control interface
86
+ * @v data		SCSI data interface
64 87
  * @v command		SCSI command
65
- * @ret rc		Return status code
88
+ * @ret tag		Command tag, or negative error
66 89
  */
67
-static int scsi_command ( struct scsi_device *scsi,
68
-			  struct scsi_command *command ) {
69
-	int rc;
90
+int scsi_command ( struct interface *control, struct interface *data,
91
+		   struct scsi_cmd *command ) {
92
+	struct interface *dest;
93
+	scsi_command_TYPE ( void * ) *op =
94
+		intf_get_dest_op ( control, scsi_command, &dest );
95
+	void *object = intf_object ( dest );
96
+	int tap;
97
+
98
+	if ( op ) {
99
+		tap = op ( object, data, command );
100
+	} else {
101
+		/* Default is to fail to issue the command */
102
+		tap = -EOPNOTSUPP;
103
+	}
70 104
 
71
-	DBGC2 ( scsi, "SCSI %p " SCSI_CDB_FORMAT "\n",
72
-		scsi, SCSI_CDB_DATA ( command->cdb ) );
105
+	intf_put ( dest );
106
+	return tap;
107
+}
73 108
 
74
-	/* Clear sense response code before issuing command */
75
-	command->sense_response = 0;
109
+/**
110
+ * Report SCSI response
111
+ *
112
+ * @v interface		SCSI command interface
113
+ * @v response		SCSI response
114
+ */
115
+void scsi_response ( struct interface *intf, struct scsi_rsp *response ) {
116
+	struct interface *dest;
117
+	scsi_response_TYPE ( void * ) *op =
118
+		intf_get_dest_op ( intf, scsi_response, &dest );
119
+	void *object = intf_object ( dest );
120
+
121
+	if ( op ) {
122
+		op ( object, response );
123
+	} else {
124
+		/* Default is to ignore the response */
125
+	}
76 126
 
77
-	/* Flag command as in-progress */
78
-	command->rc = -EINPROGRESS;
127
+	intf_put ( dest );
128
+}
79 129
 
80
-	/* Issue SCSI command */
81
-	if ( ( rc = scsi->command ( scsi, command ) ) != 0 ) {
82
-		/* Something went wrong with the issuing mechanism */
83
-		DBGC ( scsi, "SCSI %p " SCSI_CDB_FORMAT " err %s\n",
84
-		       scsi, SCSI_CDB_DATA ( command->cdb ), strerror ( rc ) );
85
-		return rc;
86
-	}
130
+/******************************************************************************
131
+ *
132
+ * SCSI devices and commands
133
+ *
134
+ ******************************************************************************
135
+ */
87 136
 
88
-	/* Wait for command to complete */
89
-	while ( command->rc == -EINPROGRESS )
90
-		step();
91
-	if ( ( rc = command->rc ) != 0 ) {
92
-		/* Something went wrong with the command execution */
93
-		DBGC ( scsi, "SCSI %p " SCSI_CDB_FORMAT " err %s\n",
94
-		       scsi, SCSI_CDB_DATA ( command->cdb ), strerror ( rc ) );
95
-		return rc;
96
-	}
137
+/** A SCSI device */
138
+struct scsi_device {
139
+	/** Reference count */
140
+	struct refcnt refcnt;
141
+	/** Block control interface */
142
+	struct interface block;
143
+	/** SCSI control interface */
144
+	struct interface scsi;
97 145
 
98
-	/* Check for SCSI errors */
99
-	if ( command->status != 0 ) {
100
-		DBGC ( scsi, "SCSI %p " SCSI_CDB_FORMAT " status %02x sense "
101
-		       "%02x\n", scsi, SCSI_CDB_DATA ( command->cdb ),
102
-		       command->status, command->sense_response );
103
-		return -EIO;
104
-	}
146
+	/** SCSI LUN */
147
+	struct scsi_lun lun;
105 148
 
106
-	return 0;
149
+	/** List of commands */
150
+	struct list_head cmds;
151
+};
152
+
153
+/** A SCSI command */
154
+struct scsi_command {
155
+	/** Reference count */
156
+	struct refcnt refcnt;
157
+	/** SCSI device */
158
+	struct scsi_device *scsidev;
159
+	/** List of SCSI commands */
160
+	struct list_head list;
161
+
162
+	/** Block data interface */
163
+	struct interface block;
164
+	/** SCSI data interface */
165
+	struct interface scsi;
166
+
167
+	/** Command type */
168
+	struct scsi_command_type *type;
169
+	/** Starting logical block address */
170
+	uint64_t lba;
171
+	/** Number of blocks */
172
+	unsigned int count;
173
+	/** Data buffer */
174
+	userptr_t buffer;
175
+	/** Length of data buffer */
176
+	size_t len;
177
+	/** Command tag */
178
+	uint32_t tag;
179
+
180
+	/** Retry count */
181
+	unsigned int retries;
182
+
183
+	/** Private data */
184
+	uint8_t priv[0];
185
+};
186
+
187
+/** A SCSI command type */
188
+struct scsi_command_type {
189
+	/** Name */
190
+	const char *name;
191
+	/** Additional working space */
192
+	size_t priv_len;
193
+	/**
194
+	 * Construct SCSI command IU
195
+	 *
196
+	 * @v scsicmd		SCSI command
197
+	 * @v command		SCSI command IU
198
+	 */
199
+	void ( * cmd ) ( struct scsi_command *scsicmd,
200
+			 struct scsi_cmd *command );
201
+	/**
202
+	 * Handle SCSI command completion
203
+	 *
204
+	 * @v scsicmd		SCSI command
205
+	 * @v rc		Reason for completion
206
+	 */
207
+	void ( * done ) ( struct scsi_command *scsicmd, int rc );
208
+};
209
+
210
+/**
211
+ * Get reference to SCSI device
212
+ *
213
+ * @v scsidev		SCSI device
214
+ * @ret scsidev		SCSI device
215
+ */
216
+static inline __attribute__ (( always_inline )) struct scsi_device *
217
+scsidev_get ( struct scsi_device *scsidev ) {
218
+	ref_get ( &scsidev->refcnt );
219
+	return scsidev;
107 220
 }
108 221
 
109 222
 /**
110
- * Read block from SCSI device using READ (10)
223
+ * Drop reference to SCSI device
111 224
  *
112
- * @v blockdev		Block device
113
- * @v block		LBA block number
114
- * @v count		Block count
115
- * @v buffer		Data buffer
116
- * @ret rc		Return status code
225
+ * @v scsidev		SCSI device
117 226
  */
118
-static int scsi_read_10 ( struct block_device *blockdev, uint64_t block,
119
-			  unsigned long count, userptr_t buffer ) {
120
-	struct scsi_device *scsi = block_to_scsi ( blockdev );
121
-	struct scsi_command command;
122
-	struct scsi_cdb_read_10 *cdb = &command.cdb.read10;
227
+static inline __attribute__ (( always_inline )) void
228
+scsidev_put ( struct scsi_device *scsidev ) {
229
+	ref_put ( &scsidev->refcnt );
230
+}
123 231
 
124
-	/* Issue READ (10) */
125
-	memset ( &command, 0, sizeof ( command ) );
126
-	cdb->opcode = SCSI_OPCODE_READ_10;
127
-	cdb->lba = cpu_to_be32 ( block );
128
-	cdb->len = cpu_to_be16 ( count );
129
-	command.data_in = buffer;
130
-	command.data_in_len = ( count * blockdev->blksize );
131
-	return scsi_command ( scsi, &command );
232
+/**
233
+ * Get reference to SCSI command
234
+ *
235
+ * @v scsicmd		SCSI command
236
+ * @ret scsicmd		SCSI command
237
+ */
238
+static inline __attribute__ (( always_inline )) struct scsi_command *
239
+scsicmd_get ( struct scsi_command *scsicmd ) {
240
+	ref_get ( &scsicmd->refcnt );
241
+	return scsicmd;
132 242
 }
133 243
 
134 244
 /**
135
- * Read block from SCSI device using READ (16)
245
+ * Drop reference to SCSI command
136 246
  *
137
- * @v blockdev		Block device
138
- * @v block		LBA block number
139
- * @v count		Block count
140
- * @v buffer		Data buffer
141
- * @ret rc		Return status code
247
+ * @v scsicmd		SCSI command
142 248
  */
143
-static int scsi_read_16 ( struct block_device *blockdev, uint64_t block,
144
-			  unsigned long count, userptr_t buffer ) {
145
-	struct scsi_device *scsi = block_to_scsi ( blockdev );
146
-	struct scsi_command command;
147
-	struct scsi_cdb_read_16 *cdb = &command.cdb.read16;
249
+static inline __attribute__ (( always_inline )) void
250
+scsicmd_put ( struct scsi_command *scsicmd ) {
251
+	ref_put ( &scsicmd->refcnt );
252
+}
148 253
 
149
-	/* Issue READ (16) */
150
-	memset ( &command, 0, sizeof ( command ) );
151
-	cdb->opcode = SCSI_OPCODE_READ_16;
152
-	cdb->lba = cpu_to_be64 ( block );
153
-	cdb->len = cpu_to_be32 ( count );
154
-	command.data_in = buffer;
155
-	command.data_in_len = ( count * blockdev->blksize );
156
-	return scsi_command ( scsi, &command );
254
+/**
255
+ * Get SCSI command private data
256
+ *
257
+ * @v scsicmd		SCSI command
258
+ * @ret priv		Private data
259
+ */
260
+static inline __attribute__ (( always_inline )) void *
261
+scsicmd_priv ( struct scsi_command *scsicmd ) {
262
+	return scsicmd->priv;
157 263
 }
158 264
 
159 265
 /**
160
- * Write block to SCSI device using WRITE (10)
266
+ * Free SCSI command
161 267
  *
162
- * @v blockdev		Block device
163
- * @v block		LBA block number
164
- * @v count		Block count
165
- * @v buffer		Data buffer
166
- * @ret rc		Return status code
268
+ * @v refcnt		Reference count
167 269
  */
168
-static int scsi_write_10 ( struct block_device *blockdev, uint64_t block,
169
-			   unsigned long count, userptr_t buffer ) {
170
-	struct scsi_device *scsi = block_to_scsi ( blockdev );
171
-	struct scsi_command command;
172
-	struct scsi_cdb_write_10 *cdb = &command.cdb.write10;
270
+static void scsicmd_free ( struct refcnt *refcnt ) {
271
+	struct scsi_command *scsicmd =
272
+		container_of ( refcnt, struct scsi_command, refcnt );
173 273
 
174
-	/* Issue WRITE (10) */
175
-	memset ( &command, 0, sizeof ( command ) );
176
-	cdb->opcode = SCSI_OPCODE_WRITE_10;
177
-	cdb->lba = cpu_to_be32 ( block );
178
-	cdb->len = cpu_to_be16 ( count );
179
-	command.data_out = buffer;
180
-	command.data_out_len = ( count * blockdev->blksize );
181
-	return scsi_command ( scsi, &command );
274
+	/* Remove from list of commands */
275
+	list_del ( &scsicmd->list );
276
+	scsidev_put ( scsicmd->scsidev );
277
+
278
+	/* Free command */
279
+	free ( scsicmd );
182 280
 }
183 281
 
184 282
 /**
185
- * Write block to SCSI device using WRITE (16)
283
+ * Close SCSI command
186 284
  *
187
- * @v blockdev		Block device
188
- * @v block		LBA block number
189
- * @v count		Block count
190
- * @v buffer		Data buffer
191
- * @ret rc		Return status code
285
+ * @v scsicmd		SCSI command
286
+ * @v rc		Reason for close
192 287
  */
193
-static int scsi_write_16 ( struct block_device *blockdev, uint64_t block,
194
-			   unsigned long count, userptr_t buffer ) {
195
-	struct scsi_device *scsi = block_to_scsi ( blockdev );
196
-	struct scsi_command command;
197
-	struct scsi_cdb_write_16 *cdb = &command.cdb.write16;
288
+static void scsicmd_close ( struct scsi_command *scsicmd, int rc ) {
289
+	struct scsi_device *scsidev = scsicmd->scsidev;
198 290
 
199
-	/* Issue WRITE (16) */
200
-	memset ( &command, 0, sizeof ( command ) );
201
-	cdb->opcode = SCSI_OPCODE_WRITE_16;
202
-	cdb->lba = cpu_to_be64 ( block );
203
-	cdb->len = cpu_to_be32 ( count );
204
-	command.data_out = buffer;
205
-	command.data_out_len = ( count * blockdev->blksize );
206
-	return scsi_command ( scsi, &command );
291
+	if ( rc != 0 ) {
292
+		DBGC ( scsidev, "SCSI %p tag %08x closed: %s\n",
293
+		       scsidev, scsicmd->tag, strerror ( rc ) );
294
+	}
295
+
296
+	/* Shut down interfaces */
297
+	intf_shutdown ( &scsicmd->scsi, rc );
298
+	intf_shutdown ( &scsicmd->block, rc );
207 299
 }
208 300
 
209 301
 /**
210
- * Read capacity of SCSI device via READ CAPACITY (10)
302
+ * Construct and issue SCSI command
211 303
  *
212
- * @v blockdev		Block device
213 304
  * @ret rc		Return status code
214 305
  */
215
-static int scsi_read_capacity_10 ( struct block_device *blockdev ) {
216
-	struct scsi_device *scsi = block_to_scsi ( blockdev );
217
-	struct scsi_command command;
218
-	struct scsi_cdb_read_capacity_10 *cdb = &command.cdb.readcap10;
219
-	struct scsi_capacity_10 capacity;
306
+static int scsicmd_command ( struct scsi_command *scsicmd ) {
307
+	struct scsi_device *scsidev = scsicmd->scsidev;
308
+	struct scsi_cmd command;
309
+	int tag;
220 310
 	int rc;
221 311
 
222
-	/* Issue READ CAPACITY (10) */
312
+	/* Construct command */
223 313
 	memset ( &command, 0, sizeof ( command ) );
224
-	cdb->opcode = SCSI_OPCODE_READ_CAPACITY_10;
225
-	command.data_in = virt_to_user ( &capacity );
226
-	command.data_in_len = sizeof ( capacity );
227
-
228
-	if ( ( rc = scsi_command ( scsi, &command ) ) != 0 )
314
+	memcpy ( &command.lun, &scsidev->lun, sizeof ( command.lun ) );
315
+	scsicmd->type->cmd ( scsicmd, &command );
316
+
317
+	/* Issue command */
318
+	if ( ( tag = scsi_command ( &scsidev->scsi, &scsicmd->scsi,
319
+				    &command ) ) < 0 ) {
320
+		rc = tag;
321
+		DBGC ( scsidev, "SCSI %p could not issue command: %s\n",
322
+		       scsidev, strerror ( rc ) );
229 323
 		return rc;
324
+	}
230 325
 
231
-	/* Fill in block device fields */
232
-	blockdev->blksize = be32_to_cpu ( capacity.blksize );
233
-	blockdev->blocks = ( be32_to_cpu ( capacity.lba ) + 1 );
326
+	/* Record tag */
327
+	if ( scsicmd->tag ) {
328
+		DBGC ( scsidev, "SCSI %p tag %08x is now tag %08x\n",
329
+		       scsidev, scsicmd->tag, tag );
330
+	}
331
+	scsicmd->tag = tag;
332
+	DBGC2 ( scsidev, "SCSI %p tag %08x %s " SCSI_CDB_FORMAT "\n",
333
+		scsidev, scsicmd->tag, scsicmd->type->name,
334
+		SCSI_CDB_DATA ( command.cdb ) );
234 335
 
235 336
 	return 0;
236 337
 }
237 338
 
238 339
 /**
239
- * Read capacity of SCSI device via READ CAPACITY (16)
340
+ * Handle SCSI command completion
240 341
  *
241
- * @v blockdev		Block device
242
- * @ret rc		Return status code
342
+ * @v scsicmd		SCSI command
343
+ * @v rc		Reason for close
243 344
  */
244
-static int scsi_read_capacity_16 ( struct block_device *blockdev ) {
245
-	struct scsi_device *scsi = block_to_scsi ( blockdev );
246
-	struct scsi_command command;
247
-	struct scsi_cdb_read_capacity_16 *cdb = &command.cdb.readcap16;
248
-	struct scsi_capacity_16 capacity;
249
-	int rc;
345
+static void scsicmd_done ( struct scsi_command *scsicmd, int rc ) {
346
+	struct scsi_device *scsidev = scsicmd->scsidev;
250 347
 
251
-	/* Issue READ CAPACITY (16) */
252
-	memset ( &command, 0, sizeof ( command ) );
253
-	cdb->opcode = SCSI_OPCODE_SERVICE_ACTION_IN;
254
-	cdb->service_action = SCSI_SERVICE_ACTION_READ_CAPACITY_16;
255
-	cdb->len = cpu_to_be32 ( sizeof ( capacity ) );
256
-	command.data_in = virt_to_user ( &capacity );
257
-	command.data_in_len = sizeof ( capacity );
348
+	/* Restart SCSI interface */
349
+	intf_restart ( &scsicmd->scsi, rc );
258 350
 
259
-	if ( ( rc = scsi_command ( scsi, &command ) ) != 0 )
260
-		return rc;
351
+	/* SCSI targets have an annoying habit of returning occasional
352
+	 * pointless "error" messages such as "power-on occurred", so
353
+	 * we have to be prepared to retry commands.
354
+	 */
355
+	if ( ( rc != 0 ) && ( scsicmd->retries++ < SCSICMD_MAX_RETRIES ) ) {
356
+		/* Retry command */
357
+		DBGC ( scsidev, "SCSI %p tag %08x failed: %s\n",
358
+		       scsidev, scsicmd->tag, strerror ( rc ) );
359
+		DBGC ( scsidev, "SCSI %p tag %08x retrying (retry %d)\n",
360
+		       scsidev, scsicmd->tag, scsicmd->retries );
361
+		if ( ( rc = scsicmd_command ( scsicmd ) ) == 0 )
362
+			return;
363
+	}
261 364
 
262
-	/* Fill in block device fields */
263
-	blockdev->blksize = be32_to_cpu ( capacity.blksize );
264
-	blockdev->blocks = ( be64_to_cpu ( capacity.lba ) + 1 );
265
-	return 0;
365
+	/* If we didn't (successfully) reissue the command, hand over
366
+	 * to the command completion handler.
367
+	 */
368
+	scsicmd->type->done ( scsicmd, rc );
266 369
 }
267 370
 
268
-static struct block_device_operations scsi_operations_16 = {
269
-	.read	= scsi_read_16,
270
-	.write	= scsi_write_16,
271
-};
371
+/**
372
+ * Handle SCSI response
373
+ *
374
+ * @v scsicmd		SCSI command
375
+ * @v response		SCSI response
376
+ */
377
+static void scsicmd_response ( struct scsi_command *scsicmd,
378
+			       struct scsi_rsp *response ) {
379
+	struct scsi_device *scsidev = scsicmd->scsidev;
380
+	size_t overrun;
381
+	size_t underrun;
382
+
383
+	if ( response->status == 0 ) {
384
+		scsicmd_done ( scsicmd, 0 );
385
+	} else {
386
+		DBGC ( scsidev, "SCSI %p tag %08x status %02x",
387
+		       scsidev, scsicmd->tag, response->status );
388
+		if ( response->overrun > 0 ) {
389
+			overrun = response->overrun;
390
+			DBGC ( scsidev, " overrun +%zd", overrun );
391
+		} else if ( response->overrun < 0 ) {
392
+			underrun = -(response->overrun);
393
+			DBGC ( scsidev, " underrun -%zd", underrun );
394
+		}
395
+		DBGC ( scsidev, " sense %02x:%02x:%08x\n",
396
+		       response->sense.code, response->sense.key,
397
+		       ntohl ( response->sense.info ) );
398
+		scsicmd_done ( scsicmd, -EIO );
399
+	}
400
+}
272 401
 
273
-static struct block_device_operations scsi_operations_10 = {
274
-	.read	= scsi_read_10,
275
-	.write	= scsi_write_10,
402
+/**
403
+ * Construct SCSI READ command
404
+ *
405
+ * @v scsicmd		SCSI command
406
+ * @v command		SCSI command IU
407
+ */
408
+static void scsicmd_read_cmd ( struct scsi_command *scsicmd,
409
+			       struct scsi_cmd *command ) {
410
+
411
+	if ( ( scsicmd->lba + scsicmd->count ) > SCSI_MAX_BLOCK_10 ) {
412
+		/* Use READ (16) */
413
+		command->cdb.read16.opcode = SCSI_OPCODE_READ_16;
414
+		command->cdb.read16.lba = cpu_to_be64 ( scsicmd->lba );
415
+		command->cdb.read16.len = cpu_to_be32 ( scsicmd->count );
416
+	} else {
417
+		/* Use READ (10) */
418
+		command->cdb.read10.opcode = SCSI_OPCODE_READ_10;
419
+		command->cdb.read10.lba = cpu_to_be32 ( scsicmd->lba );
420
+		command->cdb.read10.len = cpu_to_be16 ( scsicmd->count );
421
+	}
422
+	command->data_in = scsicmd->buffer;
423
+	command->data_in_len = scsicmd->len;
424
+}
425
+
426
+/** SCSI READ command type */
427
+static struct scsi_command_type scsicmd_read = {
428
+	.name = "READ",
429
+	.cmd = scsicmd_read_cmd,
430
+	.done = scsicmd_close,
276 431
 };
277 432
 
278 433
 /**
279
- * Initialise SCSI device
434
+ * Construct SCSI WRITE command
280 435
  *
281
- * @v scsi		SCSI device
282
- * @ret rc		Return status code
283
- *
284
- * Initialises a SCSI device.  The scsi_device::command and
285
- * scsi_device::lun fields must already be filled in.  This function
286
- * will configure scsi_device::blockdev, including issuing a READ
287
- * CAPACITY call to determine the block size and total device size.
436
+ * @v scsicmd		SCSI command
437
+ * @v command		SCSI command IU
288 438
  */
289
-int init_scsidev ( struct scsi_device *scsi ) {
290
-	unsigned int i;
291
-	int rc;
439
+static void scsicmd_write_cmd ( struct scsi_command *scsicmd,
440
+				struct scsi_cmd *command ) {
441
+
442
+	if ( ( scsicmd->lba + scsicmd->count ) > SCSI_MAX_BLOCK_10 ) {
443
+		/* Use WRITE (16) */
444
+		command->cdb.write16.opcode = SCSI_OPCODE_WRITE_16;
445
+		command->cdb.write16.lba = cpu_to_be64 ( scsicmd->lba );
446
+		command->cdb.write16.len = cpu_to_be32 ( scsicmd->count );
447
+	} else {
448
+		/* Use WRITE (10) */
449
+		command->cdb.write10.opcode = SCSI_OPCODE_WRITE_10;
450
+		command->cdb.write10.lba = cpu_to_be32 ( scsicmd->lba );
451
+		command->cdb.write10.len = cpu_to_be16 ( scsicmd->count );
452
+	}
453
+	command->data_out = scsicmd->buffer;
454
+	command->data_out_len = scsicmd->len;
455
+}
292 456
 
293
-	/* Issue some theoretically extraneous READ CAPACITY (10)
294
-	 * commands, solely in order to draw out the "CHECK CONDITION
295
-	 * (power-on occurred)", "CHECK CONDITION (reported LUNs data
296
-	 * has changed)" etc. that some dumb targets insist on sending
297
-	 * as an error at start of day.  The precise command that we
298
-	 * use is unimportant; we just need to provide the target with
299
-	 * an opportunity to send its responses.
300
-	 */
301
-	for ( i = 0 ; i < SCSI_MAX_DUMMY_READ_CAP ; i++ ) {
302
-		if ( ( rc = scsi_read_capacity_10 ( &scsi->blockdev ) ) == 0 )
303
-			break;
304
-		DBGC ( scsi, "SCSI %p ignoring start-of-day error (#%d)\n",
305
-		       scsi, ( i + 1 ) );
457
+/** SCSI WRITE command type */
458
+static struct scsi_command_type scsicmd_write = {
459
+	.name = "WRITE",
460
+	.cmd = scsicmd_write_cmd,
461
+	.done = scsicmd_close,
462
+};
463
+
464
+/** SCSI READ CAPACITY private data */
465
+struct scsi_read_capacity_private {
466
+	/** Use READ CAPACITY (16) */
467
+	int use16;
468
+	/** Data buffer for READ CAPACITY commands */
469
+	union {
470
+		/** Data buffer for READ CAPACITY (10) */
471
+		struct scsi_capacity_10 capacity10;
472
+		/** Data buffer for READ CAPACITY (16) */
473
+		struct scsi_capacity_16 capacity16;
474
+	} capacity;
475
+};
476
+
477
+/**
478
+ * Construct SCSI READ CAPACITY command
479
+ *
480
+ * @v scsicmd		SCSI command
481
+ * @v command		SCSI command IU
482
+ */
483
+static void scsicmd_read_capacity_cmd ( struct scsi_command *scsicmd,
484
+					struct scsi_cmd *command ) {
485
+	struct scsi_read_capacity_private *priv = scsicmd_priv ( scsicmd );
486
+	struct scsi_cdb_read_capacity_16 *readcap16 = &command->cdb.readcap16;
487
+	struct scsi_cdb_read_capacity_10 *readcap10 = &command->cdb.readcap10;
488
+	struct scsi_capacity_16 *capacity16 = &priv->capacity.capacity16;
489
+	struct scsi_capacity_10 *capacity10 = &priv->capacity.capacity10;
490
+
491
+	if ( priv->use16 ) {
492
+		/* Use READ CAPACITY (16) */
493
+		readcap16->opcode = SCSI_OPCODE_SERVICE_ACTION_IN;
494
+		readcap16->service_action =
495
+			SCSI_SERVICE_ACTION_READ_CAPACITY_16;
496
+		readcap16->len = cpu_to_be32 ( sizeof ( *capacity16 ) );
497
+		command->data_in = virt_to_user ( capacity16 );
498
+		command->data_in_len = sizeof ( *capacity16 );
499
+	} else {
500
+		/* Use READ CAPACITY (10) */
501
+		readcap10->opcode = SCSI_OPCODE_READ_CAPACITY_10;
502
+		command->data_in = virt_to_user ( capacity10 );
503
+		command->data_in_len = sizeof ( *capacity10 );
306 504
 	}
505
+}
307 506
 
308
-	/* Try READ CAPACITY (10), which is a mandatory command, first. */
309
-	scsi->blockdev.op = &scsi_operations_10;
310
-	if ( ( rc = scsi_read_capacity_10 ( &scsi->blockdev ) ) != 0 ) {
311
-		DBGC ( scsi, "SCSI %p could not READ CAPACITY (10): %s\n",
312
-		       scsi, strerror ( rc ) );
313
-		return rc;
507
+/**
508
+ * Handle SCSI READ CAPACITY command completion
509
+ *
510
+ * @v scsicmd		SCSI command
511
+ * @v rc		Reason for completion
512
+ */
513
+static void scsicmd_read_capacity_done ( struct scsi_command *scsicmd,
514
+					 int rc ) {
515
+	struct scsi_read_capacity_private *priv = scsicmd_priv ( scsicmd );
516
+	struct scsi_capacity_16 *capacity16 = &priv->capacity.capacity16;
517
+	struct scsi_capacity_10 *capacity10 = &priv->capacity.capacity10;
518
+	struct block_device_capacity capacity;
519
+
520
+	/* Close if command failed */
521
+	if ( rc != 0 ) {
522
+		scsicmd_close ( scsicmd, rc );
523
+		return;
314 524
 	}
315 525
 
316
-	/* If capacity range was exceeded (i.e. capacity.lba was
317
-	 * 0xffffffff, meaning that blockdev->blocks is now zero), use
318
-	 * READ CAPACITY (16) instead.  READ CAPACITY (16) is not
319
-	 * mandatory, so we can't just use it straight off.
320
-	 */
321
-	if ( scsi->blockdev.blocks == 0 ) {
322
-		scsi->blockdev.op = &scsi_operations_16;
323
-		if ( ( rc = scsi_read_capacity_16 ( &scsi->blockdev ) ) != 0 ){
324
-			DBGC ( scsi, "SCSI %p could not READ CAPACITY (16): "
325
-			       "%s\n", scsi, strerror ( rc ) );
326
-			return rc;
526
+	/* Extract capacity */
527
+	if ( priv->use16 ) {
528
+		capacity.blocks = ( be64_to_cpu ( capacity16->lba ) + 1 );
529
+		capacity.blksize = be32_to_cpu ( capacity16->blksize );
530
+	} else {
531
+		capacity.blocks = ( be32_to_cpu ( capacity10->lba ) + 1 );
532
+		capacity.blksize = be32_to_cpu ( capacity10->blksize );
533
+
534
+		/* If capacity range was exceeded (i.e. capacity.lba
535
+		 * was 0xffffffff, meaning that blockdev->blocks is
536
+		 * now zero), use READ CAPACITY (16) instead.  READ
537
+		 * CAPACITY (16) is not mandatory, so we can't just
538
+		 * use it straight off.
539
+		 */
540
+		if ( capacity.blocks == 0 ) {
541
+			priv->use16 = 1;
542
+			if ( ( rc = scsicmd_command ( scsicmd ) ) != 0 ) {
543
+				scsicmd_close ( scsicmd, rc );
544
+				return;
545
+			}
546
+			return;
327 547
 		}
328 548
 	}
549
+	capacity.max_count = -1U;
550
+
551
+	/* Return capacity to caller */
552
+	block_capacity ( &scsicmd->block, &capacity );
553
+
554
+	/* Close command */
555
+	scsicmd_close ( scsicmd, 0 );
556
+}
557
+
558
+/** SCSI READ CAPACITY command type */
559
+static struct scsi_command_type scsicmd_read_capacity = {
560
+	.name = "READ CAPACITY",
561
+	.priv_len = sizeof ( struct scsi_read_capacity_private ),
562
+	.cmd = scsicmd_read_capacity_cmd,
563
+	.done = scsicmd_read_capacity_done,
564
+};
565
+
566
+/** SCSI command block interface operations */
567
+static struct interface_operation scsicmd_block_op[] = {
568
+	INTF_OP ( intf_close, struct scsi_command *, scsicmd_close ),
569
+};
570
+
571
+/** SCSI command block interface descriptor */
572
+static struct interface_descriptor scsicmd_block_desc =
573
+	INTF_DESC_PASSTHRU ( struct scsi_command, block,
574
+			     scsicmd_block_op, scsi );
575
+
576
+/** SCSI command SCSI interface operations */
577
+static struct interface_operation scsicmd_scsi_op[] = {
578
+	INTF_OP ( intf_close, struct scsi_command *, scsicmd_done ),
579
+	INTF_OP ( scsi_response, struct scsi_command *, scsicmd_response ),
580
+};
329 581
 
330
-	DBGC ( scsi, "SCSI %p using READ/WRITE (%d) commands\n", scsi,
331
-	       ( ( scsi->blockdev.op == &scsi_operations_10 ) ? 10 : 16 ) );
332
-	DBGC ( scsi, "SCSI %p capacity is %ld MB (%#llx blocks)\n", scsi,
333
-	       ( ( unsigned long ) ( scsi->blockdev.blocks >> 11 ) ),
334
-	       scsi->blockdev.blocks );
582
+/** SCSI command SCSI interface descriptor */
583
+static struct interface_descriptor scsicmd_scsi_desc =
584
+	INTF_DESC_PASSTHRU ( struct scsi_command, scsi,
585
+			     scsicmd_scsi_op, block );
335 586
 
587
+/**
588
+ * Create SCSI command
589
+ *
590
+ * @v scsidev		SCSI device
591
+ * @v block		Block data interface
592
+ * @v type		SCSI command type
593
+ * @v lba		Starting logical block address
594
+ * @v count		Number of blocks to transfer
595
+ * @v buffer		Data buffer
596
+ * @v len		Length of data buffer
597
+ * @ret rc		Return status code
598
+ */
599
+static int scsidev_command ( struct scsi_device *scsidev,
600
+			     struct interface *block,
601
+			     struct scsi_command_type *type,
602
+			     uint64_t lba, unsigned int count,
603
+			     userptr_t buffer, size_t len ) {
604
+	struct scsi_command *scsicmd;
605
+	int rc;
606
+
607
+	/* Allocate and initialise structure */
608
+	scsicmd = zalloc ( sizeof ( *scsicmd ) + type->priv_len );
609
+	if ( ! scsicmd ) {
610
+		rc = -ENOMEM;
611
+		goto err_zalloc;
612
+	}
613
+	ref_init ( &scsicmd->refcnt, scsicmd_free );
614
+	intf_init ( &scsicmd->block, &scsicmd_block_desc, &scsicmd->refcnt );
615
+	intf_init ( &scsicmd->scsi, &scsicmd_scsi_desc,
616
+		    &scsicmd->refcnt );
617
+	scsicmd->scsidev = scsidev_get ( scsidev );
618
+	list_add ( &scsicmd->list, &scsidev->cmds );
619
+	scsicmd->type = type;
620
+	scsicmd->lba = lba;
621
+	scsicmd->count = count;
622
+	scsicmd->buffer = buffer;
623
+	scsicmd->len = len;
624
+
625
+	/* Issue SCSI command */
626
+	if ( ( rc = scsicmd_command ( scsicmd ) ) != 0 )
627
+		goto err_command;
628
+
629
+	/* Attach to parent interface, mortalise self, and return */
630
+	intf_plug_plug ( &scsicmd->block, block );
631
+	ref_put ( &scsicmd->refcnt );
336 632
 	return 0;
633
+
634
+ err_command:
635
+	scsicmd_close ( scsicmd, rc );
636
+	ref_put ( &scsicmd->refcnt );
637
+ err_zalloc:
638
+	return rc;
337 639
 }
338 640
 
339 641
 /**
340
- * Parse SCSI LUN
642
+ * Issue SCSI block read
341 643
  *
342
- * @v lun_string	LUN string representation
343
- * @v lun		LUN to fill in
644
+ * @v scsidev		SCSI device
645
+ * @v block		Block data interface
646
+ * @v lba		Starting logical block address
647
+ * @v count		Number of blocks to transfer
648
+ * @v buffer		Data buffer
649
+ * @v len		Length of data buffer
344 650
  * @ret rc		Return status code
651
+
345 652
  */
346
-int scsi_parse_lun ( const char *lun_string, struct scsi_lun *lun ) {
347
-	char *p;
348
-	int i;
653
+static int scsidev_read ( struct scsi_device *scsidev,
654
+			  struct interface *block,
655
+			  uint64_t lba, unsigned int count,
656
+			  userptr_t buffer, size_t len ) {
657
+	return scsidev_command ( scsidev, block, &scsicmd_read,
658
+				 lba, count, buffer, len );
659
+}
349 660
 
350
-	memset ( lun, 0, sizeof ( *lun ) );
351
-	if ( lun_string ) {
352
-		p = ( char * ) lun_string;
353
-		for ( i = 0 ; i < 4 ; i++ ) {
354
-			lun->u16[i] = htons ( strtoul ( p, &p, 16 ) );
355
-			if ( *p == '\0' )
356
-				break;
357
-			if ( *p != '-' )
358
-				return -EINVAL;
359
-			p++;
360
-		}
361
-		if ( *p )
362
-			return -EINVAL;
661
+/**
662
+ * Issue SCSI block write
663
+ *
664
+ * @v scsidev		SCSI device
665
+ * @v block		Block data interface
666
+ * @v lba		Starting logical block address
667
+ * @v count		Number of blocks to transfer
668
+ * @v buffer		Data buffer
669
+ * @v len		Length of data buffer
670
+ * @ret rc		Return status code
671
+ */
672
+static int scsidev_write ( struct scsi_device *scsidev,
673
+			   struct interface *block,
674
+			   uint64_t lba, unsigned int count,
675
+			   userptr_t buffer, size_t len ) {
676
+	return scsidev_command ( scsidev, block, &scsicmd_write,
677
+				 lba, count, buffer, len );
678
+}
679
+
680
+/**
681
+ * Read SCSI device capacity
682
+ *
683
+ * @v scsidev		SCSI device
684
+ * @v block		Block data interface
685
+ * @ret rc		Return status code
686
+ */
687
+static int scsidev_read_capacity ( struct scsi_device *scsidev,
688
+				   struct interface *block ) {
689
+	return scsidev_command ( scsidev, block, &scsicmd_read_capacity,
690
+				 0, 0, UNULL, 0 );
691
+}
692
+
693
+/**
694
+ * Close SCSI device
695
+ *
696
+ * @v scsidev		SCSI device
697
+ * @v rc		Reason for close
698
+ */
699
+static void scsidev_close ( struct scsi_device *scsidev, int rc ) {
700
+	struct scsi_command *scsicmd;
701
+	struct scsi_command *tmp;
702
+
703
+	/* Shut down interfaces */
704
+	intf_shutdown ( &scsidev->block, rc );
705
+	intf_shutdown ( &scsidev->scsi, rc );
706
+
707
+	/* Shut down any remaining commands */
708
+	list_for_each_entry_safe ( scsicmd, tmp, &scsidev->cmds, list ) {
709
+		scsicmd_get ( scsicmd );
710
+		scsicmd_close ( scsicmd, rc );
711
+		scsicmd_put ( scsicmd );
363 712
 	}
713
+}
714
+
715
+/** SCSI device block interface operations */
716
+static struct interface_operation scsidev_block_op[] = {
717
+	INTF_OP ( block_read, struct scsi_device *, scsidev_read ),
718
+	INTF_OP ( block_write, struct scsi_device *, scsidev_write ),
719
+	INTF_OP ( block_read_capacity, struct scsi_device *,
720
+		  scsidev_read_capacity ),
721
+	INTF_OP ( intf_close, struct scsi_device *, scsidev_close ),
722
+};
723
+
724
+/** SCSI device block interface descriptor */
725
+static struct interface_descriptor scsidev_block_desc =
726
+	INTF_DESC_PASSTHRU ( struct scsi_device, block,
727
+			     scsidev_block_op, scsi );
728
+
729
+/** SCSI device SCSI interface operations */
730
+static struct interface_operation scsidev_scsi_op[] = {
731
+	INTF_OP ( intf_close, struct scsi_device *, scsidev_close ),
732
+};
364 733
 
734
+/** SCSI device SCSI interface descriptor */
735
+static struct interface_descriptor scsidev_scsi_desc =
736
+	INTF_DESC_PASSTHRU ( struct scsi_device, scsi,
737
+			     scsidev_scsi_op, block );
738
+
739
+/**
740
+ * Open SCSI device
741
+ *
742
+ * @v block		Block control interface
743
+ * @v scsi		SCSI control interface
744
+ * @v lun		SCSI LUN
745
+ * @ret rc		Return status code
746
+ */
747
+int scsi_open ( struct interface *block, struct interface *scsi,
748
+		struct scsi_lun *lun ) {
749
+	struct scsi_device *scsidev;
750
+
751
+	/* Allocate and initialise structure */
752
+	scsidev = zalloc ( sizeof ( *scsidev ) );
753
+	if ( ! scsidev )
754
+		return -ENOMEM;
755
+	ref_init ( &scsidev->refcnt, NULL );
756
+	intf_init ( &scsidev->block, &scsidev_block_desc, &scsidev->refcnt );
757
+	intf_init ( &scsidev->scsi, &scsidev_scsi_desc, &scsidev->refcnt );
758
+	INIT_LIST_HEAD ( &scsidev->cmds );
759
+	memcpy ( &scsidev->lun, lun, sizeof ( scsidev->lun ) );
760
+	DBGC ( scsidev, "SCSI %p created for LUN " SCSI_LUN_FORMAT "\n",
761
+	       scsidev, SCSI_LUN_DATA ( scsidev->lun ) );
762
+
763
+	/* Attach to SCSI and parent and interfaces, mortalise self,
764
+	 * and return
765
+	 */
766
+	intf_plug_plug ( &scsidev->scsi, scsi );
767
+	intf_plug_plug ( &scsidev->block, block );
768
+	ref_put ( &scsidev->refcnt );
365 769
 	return 0;
366 770
 }

+ 553
- 277
src/drivers/block/srp.c
File diff suppressed because it is too large
Näytä tiedosto


+ 21
- 1
src/include/ipxe/acpi.h Näytä tiedosto

@@ -10,6 +10,7 @@
10 10
 FILE_LICENCE ( GPL2_OR_LATER );
11 11
 
12 12
 #include <stdint.h>
13
+#include <ipxe/interface.h>
13 14
 
14 15
 /**
15 16
  * An ACPI description header
@@ -19,7 +20,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
19 20
  */
20 21
 struct acpi_description_header {
21 22
 	/** ACPI signature (4 ASCII characters) */
22
-	char signature[4];
23
+	uint32_t signature;
23 24
 	/** Length of table, in bytes, including header */
24 25
 	uint32_t length;
25 26
 	/** ACPI Specification minor version number */
@@ -38,6 +39,25 @@ struct acpi_description_header {
38 39
 	uint32_t asl_compiler_revision;
39 40
 } __attribute__ (( packed ));
40 41
 
42
+/**
43
+ * Build ACPI signature
44
+ *
45
+ * @v a			First character of ACPI signature
46
+ * @v b			Second character of ACPI signature
47
+ * @v c			Third character of ACPI signature
48
+ * @v d			Fourth character of ACPI signature
49
+ * @ret signature	ACPI signature
50
+ */
51
+#define ACPI_SIGNATURE( a, b, c, d ) \
52
+	( ( (a) << 0 ) | ( (b) << 8 ) | ( (c) << 16 ) | ( (d) << 24 ) )
53
+
54
+extern int acpi_describe ( struct interface *interface,
55
+			   struct acpi_description_header *acpi, size_t len );
56
+#define acpi_describe_TYPE( object_type )				\
57
+	typeof ( int ( object_type,					\
58
+		       struct acpi_description_header *acpi,		\
59
+		       size_t len ) )
60
+
41 61
 extern void acpi_fix_checksum ( struct acpi_description_header *acpi );
42 62
 
43 63
 #endif /* _IPXE_ACPI_H */

+ 24
- 43
src/include/ipxe/aoe.h Näytä tiedosto

@@ -14,10 +14,11 @@ FILE_LICENCE ( GPL2_OR_LATER );
14 14
 #include <ipxe/if_ether.h>
15 15
 #include <ipxe/retry.h>
16 16
 #include <ipxe/ata.h>
17
+#include <ipxe/acpi.h>
17 18
 
18 19
 /** An AoE config command */
19 20
 struct aoecfg {
20
-	/** AoE Queue depth */
21
+	/** AoE queue depth */
21 22
 	uint16_t bufcnt;
22 23
 	/** ATA target firmware version */
23 24
 	uint16_t fwver;
@@ -78,7 +79,7 @@ struct aoehdr {
78 79
 	/** Tag, in network byte order */
79 80
 	uint32_t tag;
80 81
 	/** Payload */
81
-	union aoecmd cmd[0];
82
+	union aoecmd payload[0];
82 83
 } __attribute__ (( packed ));
83 84
 
84 85
 #define AOE_VERSION	0x10	/**< Version 1 */
@@ -93,58 +94,38 @@ struct aoehdr {
93 94
 #define AOE_CMD_ATA	0x00	/**< Issue ATA command */
94 95
 #define AOE_CMD_CONFIG	0x01	/**< Query Config Information */
95 96
 
96
-#define AOE_TAG_MAGIC	0xebeb0000
97
-
98 97
 #define AOE_ERR_BAD_COMMAND	1 /**< Unrecognised command code */
99 98
 #define AOE_ERR_BAD_PARAMETER	2 /**< Bad argument parameter */
100 99
 #define AOE_ERR_UNAVAILABLE	3 /**< Device unavailable */
101 100
 #define AOE_ERR_CONFIG_EXISTS	4 /**< Config string present */
102 101
 #define AOE_ERR_BAD_VERSION	5 /**< Unsupported version */
103 102
 
104
-/** An AoE session */
105
-struct aoe_session {
106
-	/** Reference counter */
107
-	struct refcnt refcnt;
108
-
109
-	/** List of all AoE sessions */
110
-	struct list_head list;
111
-
112
-	/** Network device */
113
-	struct net_device *netdev;
114
-
115
-	/** Major number */
116
-	uint16_t major;
117
-	/** Minor number */
118
-	uint8_t minor;
119
-	/** Target MAC address */
120
-	uint8_t target[ETH_ALEN];
121
-
122
-	/** Tag for current AoE command */
123
-	uint32_t tag;
124
-
125
-	/** Current AOE command */
126
-	uint8_t aoe_cmd_type;
127
-	/** Current ATA command */
128
-	struct ata_command *command;
129
-	/** Overall status of current ATA command */
130
-	unsigned int status;
131
-	/** Byte offset within command's data buffer */
132
-	unsigned int command_offset;
133
-	/** Return status code for command */
134
-	int rc;
135
-
136
-	/** Retransmission timer */
137
-	struct retry_timer timer;
138
-};
139
-
140 103
 #define AOE_STATUS_ERR_MASK	0x0f /**< Error portion of status code */ 
141 104
 #define AOE_STATUS_PENDING	0x80 /**< Command pending */
142 105
 
106
+/** AoE tag magic marker */
107
+#define AOE_TAG_MAGIC 0x18ae0000
108
+
143 109
 /** Maximum number of sectors per packet */
144 110
 #define AOE_MAX_COUNT 2
145 111
 
146
-extern void aoe_detach ( struct ata_device *ata );
147
-extern int aoe_attach ( struct ata_device *ata, struct net_device *netdev,
148
-			const char *root_path );
112
+/** AoE boot firmware table signature */
113
+#define ABFT_SIG ACPI_SIGNATURE ( 'a', 'B', 'F', 'T' )
114
+
115
+/**
116
+ * AoE Boot Firmware Table (aBFT)
117
+ */
118
+struct abft_table {
119
+	/** ACPI header */
120
+	struct acpi_description_header acpi;
121
+	/** AoE shelf */
122
+	uint16_t shelf;
123
+	/** AoE slot */
124
+	uint8_t slot;
125
+	/** Reserved */
126
+	uint8_t reserved_a;
127
+	/** MAC address */
128
+	uint8_t mac[ETH_ALEN];
129
+} __attribute__ (( packed ));
149 130
 
150 131
 #endif /* _IPXE_AOE_H */

+ 40
- 45
src/include/ipxe/ata.h Näytä tiedosto

@@ -2,9 +2,8 @@
2 2
 #define _IPXE_ATA_H
3 3
 
4 4
 #include <stdint.h>
5
-#include <ipxe/blockdev.h>
6 5
 #include <ipxe/uaccess.h>
7
-#include <ipxe/refcnt.h>
6
+#include <ipxe/interface.h>
8 7
 
9 8
 /** @file
10 9
  *
@@ -104,7 +103,7 @@ struct ata_cb {
104 103
 	uint8_t device;
105 104
 	/** Command/status register */
106 105
 	uint8_t cmd_stat;
107
-	/** LBA48 addressing flag */
106
+	/** Use LBA48 extended addressing */
108 107
 	int lba48;
109 108
 };
110 109
 
@@ -138,25 +137,8 @@ struct ata_cb {
138 137
 /** "Identify" command */
139 138
 #define ATA_CMD_IDENTIFY 0xec
140 139
 
141
-/** An ATA command */
142
-struct ata_command {
143
-	/** ATA command block */
144
-	struct ata_cb cb;
145
-	/** Data-out buffer (may be NULL)
146
-	 *
147
-	 * If non-NULL, this buffer must be ata_command::cb::count
148
-	 * sectors in size.
149
-	 */
150
-	userptr_t data_out;
151
-	/** Data-in buffer (may be NULL)
152
-	 *
153
-	 * If non-NULL, this buffer must be ata_command::cb::count
154
-	 * sectors in size.
155
-	 */
156
-	userptr_t data_in;
157
-	/** Command status code */
158
-	int rc;
159
-};
140
+/** Command completed in error */
141
+#define ATA_STAT_ERR 0x01
160 142
 
161 143
 /**
162 144
  * Structure returned by ATA IDENTIFY command
@@ -165,13 +147,15 @@ struct ata_command {
165 147
  * so we implement only a few fields.
166 148
  */
167 149
 struct ata_identity {
168
-	uint16_t ignore_a[60]; /* words 0-59 */
150
+	uint16_t ignore_a[27]; /* words 0-26 */
151
+	uint16_t model[20]; /* words 27-46 */
152
+	uint16_t ignore_b[13]; /* words 47-59 */
169 153
 	uint32_t lba_sectors; /* words 60-61 */
170
-	uint16_t ignore_b[21]; /* words 62-82 */
154
+	uint16_t ignore_c[21]; /* words 62-82 */
171 155
 	uint16_t supports_lba48; /* word 83 */
172
-	uint16_t ignore_c[16]; /* words 84-99 */
156
+	uint16_t ignore_d[16]; /* words 84-99 */
173 157
 	uint64_t lba48_sectors; /* words 100-103 */
174
-	uint16_t ignore_d[152]; /* words 104-255 */
158
+	uint16_t ignore_e[152]; /* words 104-255 */
175 159
 };
176 160
 
177 161
 /** Supports LBA48 flag */
@@ -180,30 +164,41 @@ struct ata_identity {
180 164
 /** ATA sector size */
181 165
 #define ATA_SECTOR_SIZE 512
182 166
 
183
-/** An ATA device */
184
-struct ata_device {
185
-	/** Block device interface */
186
-	struct block_device blockdev;
187
-	/** Device number
167
+/** An ATA command information unit */
168
+struct ata_cmd {
169
+	/** ATA command block */
170
+	struct ata_cb cb;
171
+	/** Data-out buffer (may be NULL)
188 172
 	 *
189
-	 * Must be ATA_DEV_MASTER or ATA_DEV_SLAVE.
173
+	 * If non-NULL, this buffer must be ata_command::cb::count
174
+	 * sectors in size.
190 175
 	 */
191
-	int device;
192
-	/** LBA48 extended addressing */
193
-	int lba48;
194
-	/**
195
-	 * Issue ATA command
176
+	userptr_t data_out;
177
+	/** Data-out buffer length
196 178
 	 *
197
-	 * @v ata		ATA device
198
-	 * @v command		ATA command
199
-	 * @ret rc		Return status code
179
+	 * Must be zero if @c data_out is NULL
200 180
 	 */
201
-	int ( * command ) ( struct ata_device *ata,
202
-			    struct ata_command *command );
203
-	/** Backing device */
204
-	struct refcnt *backend;
181
+	size_t data_out_len;
182
+	/** Data-in buffer (may be NULL)
183
+	 *
184
+	 * If non-NULL, this buffer must be ata_command::cb::count
185
+	 * sectors in size.
186
+	 */
187
+	userptr_t data_in;
188
+	/** Data-in buffer length
189
+	 *
190
+	 * Must be zero if @c data_in is NULL
191
+	 */
192
+	size_t data_in_len;
205 193
 };
206 194
 
207
-extern int init_atadev ( struct ata_device *ata );
195
+extern int ata_command ( struct interface *control, struct interface *data,
196
+			 struct ata_cmd *command );
197
+#define ata_command_TYPE( object_type )					\
198
+	typeof ( int ( object_type, struct interface *data,		\
199
+		       struct ata_cmd *command ) )
200
+
201
+extern int ata_open ( struct interface *block, struct interface *ata,
202
+		      unsigned int device, unsigned int max_count );
208 203
 
209 204
 #endif /* _IPXE_ATA_H */

+ 36
- 34
src/include/ipxe/blockdev.h Näytä tiedosto

@@ -10,44 +10,46 @@
10 10
 
11 11
 FILE_LICENCE ( GPL2_OR_LATER );
12 12
 
13
+#include <stdint.h>
13 14
 #include <ipxe/uaccess.h>
15
+#include <ipxe/interface.h>
14 16
 
15
-struct block_device;
16
-
17
-/** Block device operations */
18
-struct block_device_operations {
19
-	/**
20
-	 * Read block
21
-	 *
22
-	 * @v blockdev	Block device
23
-	 * @v block	Block number
24
-	 * @v count	Block count
25
-	 * @v buffer	Data buffer
26
-	 * @ret rc	Return status code
27
-	 */
28
-	int ( * read ) ( struct block_device *blockdev, uint64_t block,
29
-			 unsigned long count, userptr_t buffer );
30
-	/**
31
-	 * Write block
32
-	 *
33
-	 * @v blockdev	Block device
34
-	 * @v block	Block number
35
-	 * @v count	Block count
36
-	 * @v buffer	Data buffer
37
-	 * @ret rc	Return status code
38
-	 */
39
-	int ( * write ) ( struct block_device *blockdev, uint64_t block,
40
-			  unsigned long count, userptr_t buffer );
41
-};
42
-
43
-/** A block device */
44
-struct block_device {
45
-	/** Block device operations */
46
-	struct block_device_operations *op;
47
-	/** Block size */
48
-	size_t blksize;
17
+/** Block device capacity */
18
+struct block_device_capacity {
49 19
 	/** Total number of blocks */
50 20
 	uint64_t blocks;
21
+	/** Block size */
22
+	size_t blksize;
23
+	/** Maximum number of blocks per single transfer */
24
+	unsigned int max_count;
51 25
 };
52 26
 
27
+extern int block_read ( struct interface *control, struct interface *data,
28
+			uint64_t lba, unsigned int count,
29
+			userptr_t buffer, size_t len );
30
+#define block_read_TYPE( object_type )					\
31
+	typeof ( int ( object_type, struct interface *data,		\
32
+		       uint64_t lba, unsigned int count,		\
33
+		       userptr_t buffer, size_t len ) )
34
+
35
+extern int block_write ( struct interface *control, struct interface *data,
36
+			 uint64_t lba, unsigned int count,
37
+			 userptr_t buffer, size_t len );
38
+#define block_write_TYPE( object_type )					\
39
+	typeof ( int ( object_type, struct interface *data,		\
40
+		       uint64_t lba, unsigned int count,		\
41
+		       userptr_t buffer, size_t len ) )
42
+
43
+extern int block_read_capacity ( struct interface *control,
44
+				 struct interface *data );
45
+#define block_read_capacity_TYPE( object_type )				\
46
+	typeof ( int ( object_type, struct interface *data ) )
47
+
48
+extern void block_capacity ( struct interface *intf,
49
+			     struct block_device_capacity *capacity );
50
+#define block_capacity_TYPE( object_type )				\
51
+	typeof ( void ( object_type,					\
52
+			struct block_device_capacity *capacity ) )
53
+
54
+
53 55
 #endif /* _IPXE_BLOCKDEV_H */

+ 3
- 0
src/include/ipxe/errfile.h Näytä tiedosto

@@ -55,6 +55,9 @@ FILE_LICENCE ( GPL2_OR_LATER );
55 55
 #define ERRFILE_bitmap		       ( ERRFILE_CORE | 0x000f0000 )
56 56
 #define ERRFILE_base64		       ( ERRFILE_CORE | 0x00100000 )
57 57
 #define ERRFILE_base16		       ( ERRFILE_CORE | 0x00110000 )
58
+#define ERRFILE_blockdev	       ( ERRFILE_CORE | 0x00120000 )
59
+#define ERRFILE_acpi		       ( ERRFILE_CORE | 0x00130000 )
60
+#define ERRFILE_null_sanboot	       ( ERRFILE_CORE | 0x00140000 )
58 61
 
59 62
 #define ERRFILE_eisa		     ( ERRFILE_DRIVER | 0x00000000 )
60 63
 #define ERRFILE_isa		     ( ERRFILE_DRIVER | 0x00010000 )

+ 27
- 48
src/include/ipxe/ib_srp.h Näytä tiedosto

@@ -14,45 +14,35 @@ FILE_LICENCE ( BSD2 );
14 14
 #include <ipxe/srp.h>
15 15
 
16 16
 /** SRP initiator port identifier for Infiniband */
17
-struct ib_srp_initiator_port_id {
18
-	/** Identifier extension */
19
-	struct ib_gid_half id_ext;
20
-	/** IB channel adapter GUID */
21
-	struct ib_gid_half hca_guid;
22
-} __attribute__ (( packed ));
17
+union ib_srp_initiator_port_id {
18
+	/** SRP version of port identifier */
19
+	union srp_port_id srp;
20
+	/** Infiniband version of port identifier */
21
+	struct {
22
+		/** Identifier extension */
23
+		struct ib_gid_half id_ext;
24
+		/** IB channel adapter GUID */
25
+		struct ib_gid_half hca_guid;
26
+	} __attribute__ (( packed )) ib;
27
+};
23 28
 
24 29
 /** SRP target port identifier for Infiniband */
25
-struct ib_srp_target_port_id {
26
-	/** Identifier extension */
27
-	struct ib_gid_half id_ext;
28
-	/** I/O controller GUID */
29
-	struct ib_gid_half ioc_guid;
30
-} __attribute__ (( packed ));
31
-
32
-/**
33
- * Get Infiniband-specific initiator port ID
34
- *
35
- * @v port_ids		SRP port IDs
36
- * @ret initiator_port_id  Infiniband-specific initiator port ID
37
- */
38
-static inline __always_inline struct ib_srp_initiator_port_id *
39
-ib_srp_initiator_port_id ( struct srp_port_ids *port_ids ) {
40
-	return ( ( struct ib_srp_initiator_port_id * ) &port_ids->initiator );
41
-}
30
+union ib_srp_target_port_id {
31
+	/** SRP version of port identifier */
32
+	union srp_port_id srp;
33
+	/** Infiniband version of port identifier */
34
+	struct {
35
+		/** Identifier extension */
36
+		struct ib_gid_half id_ext;
37
+		/** I/O controller GUID */
38
+		struct ib_gid_half ioc_guid;
39
+	} __attribute__ (( packed )) ib;
40
+};
42 41
 
43 42
 /**
44
- * Get Infiniband-specific target port ID
45
- *
46
- * @v port_ids		SRP port IDs
47
- * @ret target_port_id	Infiniband-specific target port ID
43
+ * sBFT Infiniband subtable
48 44
  */
49
-static inline __always_inline struct ib_srp_target_port_id *
50
-ib_srp_target_port_id ( struct srp_port_ids *port_ids ) {
51
-	return ( ( struct ib_srp_target_port_id * ) &port_ids->target );
52
-}
53
-
54
-/** Infiniband-specific SRP parameters */
55
-struct ib_srp_parameters {
45
+struct sbft_ib_subtable {
56 46
 	/** Source GID */
57 47
 	struct ib_gid sgid;
58 48
 	/** Destination GID */
@@ -61,19 +51,8 @@ struct ib_srp_parameters {
61 51
 	struct ib_gid_half service_id;
62 52
 	/** Partition key */
63 53
 	uint16_t pkey;
64
-};
65
-
66
-/**
67
- * Get Infiniband-specific transport parameters
68
- *
69
- * @v srp		SRP device
70
- * @ret ib_params	Infiniband-specific transport parameters
71
- */
72
-static inline __always_inline struct ib_srp_parameters *
73
-ib_srp_params ( struct srp_device *srp ) {
74
-	return srp_transport_priv ( srp );
75
-}
76
-
77
-extern struct srp_transport_type ib_srp_transport;
54
+	/** Reserved */
55
+	uint8_t reserved[6];
56
+} __attribute__ (( packed ));
78 57
 
79 58
 #endif /* _IPXE_IB_SRP_H */

src/arch/i386/include/ipxe/ibft.h → src/include/ipxe/ibft.h Näytä tiedosto

@@ -43,10 +43,11 @@ FILE_LICENCE ( BSD2 );
43 43
 
44 44
 #include <stdint.h>
45 45
 #include <ipxe/acpi.h>
46
+#include <ipxe/scsi.h>
46 47
 #include <ipxe/in.h>
47 48
 
48 49
 /** iSCSI Boot Firmware Table signature */
49
-#define IBFT_SIG "iBFT"
50
+#define IBFT_SIG ACPI_SIGNATURE ( 'i', 'B', 'F', 'T' )
50 51
 
51 52
 /** An offset from the start of the iBFT */
52 53
 typedef uint16_t ibft_off_t;
@@ -57,7 +58,7 @@ typedef uint16_t ibft_size_t;
57 58
 /** A string within the iBFT */
58 59
 struct ibft_string {
59 60
 	/** Length of string */
60
-	ibft_size_t length;
61
+	ibft_size_t len;
61 62
 	/** Offset to string */
62 63
 	ibft_off_t offset;
63 64
 } __attribute__ (( packed ));
@@ -208,7 +209,7 @@ struct ibft_target {
208 209
 	/** TCP port */
209 210
 	uint16_t socket;
210 211
 	/** Boot LUN */
211
-	uint64_t boot_lun;
212
+	struct scsi_lun boot_lun;
212 213
 	/** CHAP type
213 214
 	 *
214 215
 	 * This is an IBFT_CHAP_XXX constant.
@@ -260,43 +261,11 @@ struct ibft_table {
260 261
 	struct ibft_control control;
261 262
 } __attribute__ (( packed ));
262 263
 
263
-/**
264
- * iSCSI string block descriptor
265
- *
266
- * This is an internal structure that we use to keep track of the
267
- * allocation of string data.
268
- */
269
-struct ibft_string_block {
270
-	/** The iBFT containing these strings */
271
-	struct ibft_table *table;
272
-	/** Offset of first free byte within iBFT */
273
-	unsigned int offset;
274
-};
275
-
276
-/** Amount of space reserved for strings in a iPXE iBFT */
277
-#define IBFT_STRINGS_SIZE 384
278
-
279
-/**
280
- * An iBFT created by iPXE
281
- *
282
- */
283
-struct ipxe_ibft {
284
-	/** The fixed section */
285
-	struct ibft_table table;
286
-	/** The Initiator section */
287
-	struct ibft_initiator initiator __attribute__ (( aligned ( 16 ) ));
288
-	/** The NIC section */
289
-	struct ibft_nic nic __attribute__ (( aligned ( 16 ) ));
290
-	/** The Target section */
291
-	struct ibft_target target __attribute__ (( aligned ( 16 ) ));
292
-	/** Strings block */
293
-	char strings[IBFT_STRINGS_SIZE];
294
-} __attribute__ (( packed, aligned ( 16 ) ));
295
-
296
-struct net_device;
297 264
 struct iscsi_session;
265
+struct net_device;
298 266
 
299
-extern int ibft_fill_data ( struct net_device *netdev,
300
-			    struct iscsi_session *iscsi );
267
+extern int ibft_describe ( struct iscsi_session *iscsi,
268
+			   struct acpi_description_header *acpi,
269
+			   size_t len );
301 270
 
302 271
 #endif /* _IPXE_IBFT_H */

+ 25
- 46
src/include/ipxe/iscsi.h Näytä tiedosto

@@ -90,6 +90,9 @@ struct iscsi_bhs_common {
90 90
 /** Final PDU of a sequence */
91 91
 #define ISCSI_FLAG_FINAL 0x80
92 92
 
93
+/** iSCSI tag magic marker */
94
+#define ISCSI_TAG_MAGIC 0x18ae0000
95
+
93 96
 /**
94 97
  * iSCSI basic header segment common request fields
95 98
  *
@@ -307,8 +310,10 @@ struct iscsi_bhs_scsi_response {
307 310
 	uint32_t maxcmdsn;
308 311
 	/** Expected data sequence number */
309 312
 	uint32_t expdatasn;
310
-	/** Reserved */
311
-	uint8_t reserved_b[8];
313
+	/** Bidirectional read residual count */
314
+	uint32_t bidi_residual_count;
315
+	/** Residual count */
316
+	uint32_t residual_count;
312 317
 };
313 318
 
314 319
 /** SCSI response opcode */
@@ -320,13 +325,11 @@ struct iscsi_bhs_scsi_response {
320 325
 /** SCSI target failure */
321 326
 #define ISCSI_RESPONSE_TARGET_FAILURE 0x01
322 327
 
323
-/** SCSI sense response code offset
324
- *
325
- * The SCSI response may contain unsolicited sense data in the data
326
- * segment.  If it does, this is the offset to the sense response code
327
- * byte, which is the only byte we care about.
328
- */
329
-#define ISCSI_SENSE_RESPONSE_CODE_OFFSET 2
328
+/** Data overflow occurred */
329
+#define ISCSI_RESPONSE_FLAG_OVERFLOW 0x20
330
+
331
+/** Data underflow occurred */
332
+#define ISCSI_RESPONSE_FLAG_UNDERFLOW 0x40
330 333
 
331 334
 /**
332 335
  * iSCSI data-in basic header segment
@@ -497,6 +500,10 @@ struct iscsi_session {
497 500
 	/** Reference counter */
498 501
 	struct refcnt refcnt;
499 502
 
503
+	/** SCSI command-issuing interface */
504
+	struct interface control;
505
+	/** SCSI command interface */
506
+	struct interface data;
500 507
 	/** Transport-layer socket */
501 508
 	struct interface socket;
502 509
 
@@ -506,10 +513,6 @@ struct iscsi_session {
506 513
 	unsigned int target_port;
507 514
 	/** Target IQN */
508 515
 	char *target_iqn;
509
-	/** Logical Unit Number (LUN) */
510
-	struct scsi_lun lun;
511
-	/** Target socket address (recorded only for iBFT) */
512
-	struct sockaddr target_sockaddr;
513 516
 
514 517
 	/** Session status
515 518
 	 *
@@ -517,12 +520,6 @@ struct iscsi_session {
517 520
 	 * constants.
518 521
 	 */
519 522
 	int status;
520
-	/** Retry count
521
-	 *
522
-	 * Number of times that the connection has been retried.
523
-	 * Reset upon a successful connection.
524
-	 */
525
-	int retry_count;
526 523
 
527 524
 	/** Initiator username (if any) */
528 525
 	char *initiator_username;
@@ -542,12 +539,6 @@ struct iscsi_session {
542 539
 	/** CHAP response (used for both initiator and target auth) */
543 540
 	struct chap_response chap;
544 541
 
545
-	/** Target session identifying handle
546
-	 *
547
-	 * This is assigned by the target when we first log in, and
548
-	 * must be reused on subsequent login attempts.
549
-	 */
550
-	uint16_t tsih;
551 542
 	/** Initiator task tag
552 543
 	 *
553 544
 	 * This is the tag of the current command.  It is incremented
@@ -560,15 +551,13 @@ struct iscsi_session {
560 551
 	 * response to an R2T.
561 552
 	 */
562 553
 	uint32_t ttt;
563
-	/**
564
-	 * Transfer offset
554
+	/** Transfer offset
565 555
 	 *
566 556
 	 * This is the offset for an in-progress sequence of data-out
567 557
 	 * PDUs in response to an R2T.
568 558
 	 */
569 559
 	uint32_t transfer_offset;
570
-	/**
571
-	 * Transfer length
560
+	/** Transfer length
572 561
 	 *
573 562
 	 * This is the length for an in-progress sequence of data-out
574 563
 	 * PDUs in response to an R2T.
@@ -609,18 +598,13 @@ struct iscsi_session {
609 598
 	/** Buffer for received data (not always used) */
610 599
 	void *rx_buffer;
611 600
 
612
-	/** Current SCSI command
613
-	 *
614
-	 * Set to NULL when command is complete.
615
-	 */
616
-	struct scsi_command *command;
617
-	/** Instant return code
618
-	 *
619
-	 * Set to a non-zero value if all requests should return
620
-	 * immediately.  This can be used to e.g. avoid retrying
621
-	 * logins that are doomed to fail authentication.
622
-	 */
623
-	int instant_rc;
601
+	/** Current SCSI command, if any */
602
+	struct scsi_cmd *command;
603
+
604
+	/** Target socket address (for boot firmware table) */
605
+	struct sockaddr target_sockaddr;
606
+	/** SCSI LUN (for boot firmware table) */
607
+	struct scsi_lun lun;
624 608
 };
625 609
 
626 610
 /** iSCSI session is currently in the security negotiation phase */
@@ -668,11 +652,6 @@ struct iscsi_session {
668 652
 /** Target authenticated itself correctly */
669 653
 #define ISCSI_STATUS_AUTH_REVERSE_OK 0x00040000
670 654
 
671
-/** Maximum number of retries at connecting */
672
-#define ISCSI_MAX_RETRIES 2
673
-
674
-extern int iscsi_attach ( struct scsi_device *scsi, const char *root_path );
675
-extern void iscsi_detach ( struct scsi_device *scsi );
676 655
 extern const char * iscsi_initiator_iqn ( void );
677 656
 
678 657
 #endif /* _IPXE_ISCSI_H */

+ 18
- 0
src/include/ipxe/null_sanboot.h Näytä tiedosto

@@ -0,0 +1,18 @@
1
+#ifndef _IPXE_NULL_SANBOOT_H
2
+#define _IPXE_NULL_SANBOOT_H
3
+
4
+/** @file
5
+ *
6
+ * Standard do-nothing sanboot interface
7
+ *
8
+ */
9
+
10
+FILE_LICENCE ( GPL2_OR_LATER );
11
+
12
+#ifdef SANBOOT_NULL
13
+#define SANBOOT_PREFIX_null
14
+#else
15
+#define SANBOOT_PREFIX_null __null_
16
+#endif
17
+
18
+#endif /* _IPXE_NULL_SANBOOT_H */

+ 0
- 24
src/include/ipxe/ramdisk.h Näytä tiedosto

@@ -1,24 +0,0 @@
1
-#ifndef _IPXE_RAMDISK_H
2
-#define _IPXE_RAMDISK_H
3
-
4
-/**
5
- * @file
6
- *
7
- * RAM disks
8
- *
9
- */
10
-
11
-FILE_LICENCE ( GPL2_OR_LATER );
12
-
13
-#include <ipxe/uaccess.h>
14
-#include <ipxe/blockdev.h>
15
-
16
-struct ramdisk {
17
-	struct block_device blockdev;
18
-	userptr_t data;
19
-};
20
-
21
-extern int init_ramdisk ( struct ramdisk *ramdisk, userptr_t data, size_t len,
22
-			  unsigned int blksize );
23
-
24
-#endif /* _IPXE_RAMDISK_H */

+ 82
- 9
src/include/ipxe/sanboot.h Näytä tiedosto

@@ -1,20 +1,93 @@
1 1
 #ifndef _IPXE_SANBOOT_H
2 2
 #define _IPXE_SANBOOT_H
3 3
 
4
+/** @file
5
+ *
6
+ * iPXE sanboot API
7
+ *
8
+ * The sanboot API provides methods for hooking, unhooking,
9
+ * describing, and booting from SAN devices.
10
+ *
11
+ * The standard methods (readl()/writel() etc.) do not strictly check
12
+ * the type of the address parameter; this is because traditional
13
+ * usage does not necessarily provide the correct pointer type.  For
14
+ * example, code written for ISA devices at fixed I/O addresses (such
15
+ * as the keyboard controller) tend to use plain integer constants for
16
+ * the address parameter.
17
+ */
18
+
4 19
 FILE_LICENCE ( GPL2_OR_LATER );
5 20
 
6
-#include <ipxe/tables.h>
21
+#include <ipxe/api.h>
22
+#include <config/sanboot.h>
23
+
24
+struct uri;
25
+
26
+/**
27
+ * Calculate static inline sanboot API function name
28
+ *
29
+ * @v _prefix		Subsystem prefix
30
+ * @v _api_func		API function
31
+ * @ret _subsys_func	Subsystem API function
32
+ */
33
+#define SANBOOT_INLINE( _subsys, _api_func ) \
34
+	SINGLE_API_INLINE ( SANBOOT_PREFIX_ ## _subsys, _api_func )
35
+
36
+/**
37
+ * Provide a sanboot API implementation
38
+ *
39
+ * @v _prefix		Subsystem prefix
40
+ * @v _api_func		API function
41
+ * @v _func		Implementing function
42
+ */
43
+#define PROVIDE_SANBOOT( _subsys, _api_func, _func ) \
44
+	PROVIDE_SINGLE_API ( SANBOOT_PREFIX_ ## _subsys, _api_func, _func )
45
+
46
+/**
47
+ * Provide a static inline sanboot API implementation
48
+ *
49
+ * @v _prefix		Subsystem prefix
50
+ * @v _api_func		API function
51
+ */
52
+#define PROVIDE_SANBOOT_INLINE( _subsys, _api_func ) \
53
+	PROVIDE_SINGLE_API_INLINE ( SANBOOT_PREFIX_ ## _subsys, _api_func )
54
+
55
+/* Include all architecture-independent sanboot API headers */
56
+#include <ipxe/null_sanboot.h>
57
+
58
+/* Include all architecture-dependent sanboot API headers */
59
+#include <bits/sanboot.h>
7 60
 
8
-struct sanboot_protocol {
9
-	const char *prefix;
10
-	int ( * boot ) ( const char *root_path );
11
-};
61
+/**
62
+ * Hook SAN device
63
+ *
64
+ * @v uri		URI
65
+ * @v drive		Requested drive number
66
+ * @ret drive		Assigned drive number, or negative error
67
+ */
68
+int san_hook ( struct uri *uri, unsigned int drive );
12 69
 
13
-#define SANBOOT_PROTOCOLS \
14
-	__table ( struct sanboot_protocol, "sanboot_protocols" )
70
+/**
71
+ * Unhook SAN device
72
+ *
73
+ * @v drive		Drive number
74
+ */
75
+void san_unhook ( unsigned int drive );
15 76
 
16
-#define __sanboot_protocol __table_entry ( SANBOOT_PROTOCOLS, 01 )
77
+/**
78
+ * Attempt to boot from a SAN device
79
+ *
80
+ * @v drive		Drive number
81
+ * @ret rc		Return status code
82
+ */
83
+int san_boot ( unsigned int drive );
17 84
 
18
-extern int keep_san ( void );
85
+/**
86
+ * Describe SAN device for SAN-booted operating system
87
+ *
88
+ * @v drive		Drive number
89
+ * @ret rc		Return status code
90
+ */
91
+int san_describe ( unsigned int drive );
19 92
 
20 93
 #endif /* _IPXE_SANBOOT_H */

+ 57
- 43
src/include/ipxe/scsi.h Näytä tiedosto

@@ -2,9 +2,8 @@
2 2
 #define _IPXE_SCSI_H
3 3
 
4 4
 #include <stdint.h>
5
-#include <ipxe/blockdev.h>
6 5
 #include <ipxe/uaccess.h>
7
-#include <ipxe/refcnt.h>
6
+#include <ipxe/interface.h>
8 7
 
9 8
 /** @file
10 9
  *
@@ -14,6 +13,9 @@
14 13
 
15 14
 FILE_LICENCE ( GPL2_OR_LATER );
16 15
 
16
+/** Maximum block for READ/WRITE (10) commands */
17
+#define SCSI_MAX_BLOCK_10 0xffffffffULL
18
+
17 19
 /**
18 20
  * @defgroup scsiops SCSI operation codes
19 21
  * @{
@@ -214,8 +216,27 @@ union scsi_cdb {
214 216
 
215 217
 /** @} */
216 218
 
217
-/** A SCSI command */
218
-struct scsi_command {
219
+/** A SCSI LUN
220
+ *
221
+ * This is a four-level LUN as specified by SAM-2, in big-endian
222
+ * order.
223
+ */
224
+struct scsi_lun {
225
+	uint16_t u16[4];
226
+}  __attribute__ (( packed ));
227
+
228
+/** printf() format for dumping a scsi_lun */
229
+#define SCSI_LUN_FORMAT "%04x-%04x-%04x-%04x"
230
+
231
+/** printf() parameters for dumping a scsi_lun */
232
+#define SCSI_LUN_DATA(lun)						  \
233
+	ntohs ( (lun).u16[0] ), ntohs ( (lun).u16[1] ),			  \
234
+	ntohs ( (lun).u16[2] ), ntohs ( (lun).u16[3] )
235
+
236
+/** A SCSI command information unit */
237
+struct scsi_cmd {
238
+	/** LUN */
239
+	struct scsi_lun lun;
219 240
 	/** CDB for this command */
220 241
 	union scsi_cdb cdb;
221 242
 	/** Data-out buffer (may be NULL) */
@@ -232,50 +253,43 @@ struct scsi_command {
232 253
 	 * Must be zero if @c data_in is NULL
233 254
 	 */
234 255
 	size_t data_in_len;
235
-	/** SCSI status code */
236
-	uint8_t status;
237
-	/** SCSI sense response code */
238
-	uint8_t sense_response;
239
-	/** Command status code */
240
-	int rc;
241 256
 };
242 257
 
243
-/** A SCSI LUN
244
- *
245
- * This is a four-level LUN as specified by SAM-2, in big-endian
246
- * order.
247
- */
248
-struct scsi_lun {
249
-	uint16_t u16[4];
250
-}  __attribute__ (( packed ));
258
+/** SCSI sense data */
259
+struct scsi_sns {
260
+	/** Response code */
261
+	uint8_t code;
262
+	/** Reserved */
263
+	uint8_t reserved;
264
+	/** Sense key */
265
+	uint8_t key;
266
+	/** Information */
267
+	uint32_t info;
268
+};
251 269
 
252
-/** A SCSI device */
253
-struct scsi_device {
254
-	/** Block device interface */
255
-	struct block_device blockdev;
256
-	/**
257
-	 * Issue SCSI command
258
-	 *
259
-	 * @v scsi		SCSI device
260
-	 * @v command		SCSI command
261
-	 * @ret rc		Return status code
262
-	 *
263
-	 * Note that a successful return status code indicates only
264
-	 * that the SCSI command was issued.  The caller must check
265
-	 * the status field in the command structure to see when the
266
-	 * command completes and whether, for example, the device
267
-	 * returned CHECK CONDITION or some other non-success status
268
-	 * code.
269
-	 */
270
-	int ( * command ) ( struct scsi_device *scsi,
271
-			    struct scsi_command *command );
272
-	/** Backing device */
273
-	struct refcnt *backend;
270
+/** A SCSI response information unit */
271
+struct scsi_rsp {
272
+	/** SCSI status code */
273
+	uint8_t status;
274
+	/** Data overrun (or negative underrun) */
275
+	ssize_t overrun;
276
+	/** Autosense data (if any) */
277
+	struct scsi_sns sense;
274 278
 };
275 279
 
276
-extern int scsi_detached_command ( struct scsi_device *scsi,
277
-				   struct scsi_command *command );
278
-extern int init_scsidev ( struct scsi_device *scsi );
279 280
 extern int scsi_parse_lun ( const char *lun_string, struct scsi_lun *lun );
280 281
 
282
+extern int scsi_command ( struct interface *control, struct interface *data,
283
+			  struct scsi_cmd *command );
284
+#define scsi_command_TYPE( object_type )				\
285
+	typeof ( int ( object_type, struct interface *data,		\
286
+		       struct scsi_cmd *command ) )
287
+
288
+extern void scsi_response ( struct interface *intf, struct scsi_rsp *response );
289
+#define scsi_response_TYPE( object_type ) \
290
+	typeof ( void ( object_type, struct scsi_rsp *response ) )
291
+
292
+extern int scsi_open ( struct interface *block, struct interface *scsi,
293
+		       struct scsi_lun *lun );
294
+
281 295
 #endif /* _IPXE_SCSI_H */

+ 77
- 116
src/include/ipxe/srp.h Näytä tiedosto

@@ -14,6 +14,7 @@ FILE_LICENCE ( BSD2 );
14 14
 #include <ipxe/iobuf.h>
15 15
 #include <ipxe/xfer.h>
16 16
 #include <ipxe/scsi.h>
17
+#include <ipxe/acpi.h>
17 18
 
18 19
 /*****************************************************************************
19 20
  *
@@ -23,21 +24,18 @@ FILE_LICENCE ( BSD2 );
23 24
  */
24 25
 
25 26
 /** An SRP information unit tag */
26
-struct srp_tag {
27
+union srp_tag {
28
+	uint8_t bytes[8];
27 29
 	uint32_t dwords[2];
28 30
 } __attribute__ (( packed ));
29 31
 
32
+/** SRP tag magic marker */
33
+#define SRP_TAG_MAGIC 0x69505845
34
+
30 35
 /** An SRP port ID */
31
-struct srp_port_id {
36
+union srp_port_id {
32 37
 	uint8_t bytes[16];
33
-} __attribute__ (( packed ));
34
-
35
-/** An SRP port ID pair */
36
-struct srp_port_ids {
37
-	/** Initiator port ID */
38
-	struct srp_port_id initiator;
39
-	/** Target port ID */
40
-	struct srp_port_id target;
38
+	uint32_t dwords[4];
41 39
 } __attribute__ (( packed ));
42 40
 
43 41
 /** SRP information unit common fields */
@@ -47,7 +45,7 @@ struct srp_common {
47 45
 	/** Reserved */
48 46
 	uint8_t reserved0[7];
49 47
 	/** Tag */
50
-	struct srp_tag tag;
48
+	union srp_tag tag;
51 49
 } __attribute__ (( packed ));
52 50
 
53 51
 /*****************************************************************************
@@ -67,7 +65,7 @@ struct srp_login_req {
67 65
 	/** Reserved */
68 66
 	uint8_t reserved0[7];
69 67
 	/** Tag */
70
-	struct srp_tag tag;
68
+	union srp_tag tag;
71 69
 	/** Requested maximum initiator to target IU length */
72 70
 	uint32_t max_i_t_iu_len;
73 71
 	/** Reserved */
@@ -87,8 +85,10 @@ struct srp_login_req {
87 85
 	uint8_t flags;
88 86
 	/** Reserved */
89 87
 	uint8_t reserved2[5];
90
-	/** Initiator and target port identifiers */
91
-	struct srp_port_ids port_ids;
88
+	/** Initiator port identifier */
89
+	union srp_port_id initiator;
90
+	/** Target port identifier */
91
+	union srp_port_id target;
92 92
 } __attribute__ (( packed ));
93 93
 
94 94
 /** Type of an SRP login request */
@@ -137,7 +137,7 @@ struct srp_login_rsp {
137 137
 	/** Request limit delta */
138 138
 	uint32_t request_limit_delta;
139 139
 	/** Tag */
140
-	struct srp_tag tag;
140
+	union srp_tag tag;
141 141
 	/** Maximum initiator to target IU length */
142 142
 	uint32_t max_i_t_iu_len;
143 143
 	/** Maximum target to initiator IU length */
@@ -205,7 +205,7 @@ struct srp_login_rej {
205 205
 	 */
206 206
 	uint32_t reason;
207 207
 	/** Tag */
208
-	struct srp_tag tag;
208
+	union srp_tag tag;
209 209
 	/** Reserved */
210 210
 	uint8_t reserved1[8];
211 211
 	/** Supported buffer formats
@@ -265,7 +265,7 @@ struct srp_i_logout {
265 265
 	/** Reserved */
266 266
 	uint8_t reserved0[7];
267 267
 	/** Tag */
268
-	struct srp_tag tag;
268
+	union srp_tag tag;
269 269
 } __attribute__ (( packed ));
270 270
 
271 271
 /** Type of an SRP initiator logout request */
@@ -299,7 +299,7 @@ struct srp_t_logout {
299 299
 	 */
300 300
 	uint32_t reason;
301 301
 	/** Tag */
302
-	struct srp_tag tag;
302
+	union srp_tag tag;
303 303
 } __attribute__ (( packed ));
304 304
 
305 305
 /** Type of an SRP target logout request */
@@ -355,7 +355,7 @@ struct srp_tsk_mgmt {
355 355
 	/** Reserved */
356 356
 	uint8_t reserved0[6];
357 357
 	/** Tag */
358
-	struct srp_tag tag;
358
+	union srp_tag tag;
359 359
 	/** Reserved */
360 360
 	uint8_t reserved1[4];
361 361
 	/** Logical unit number */
@@ -370,7 +370,7 @@ struct srp_tsk_mgmt {
370 370
 	/** Reserved */
371 371
 	uint8_t reserved3[1];
372 372
 	/** Tag of task to be managed */
373
-	struct srp_tag managed_tag;
373
+	union srp_tag managed_tag;
374 374
 	/** Reserved */
375 375
 	uint8_t reserved4[8];
376 376
 } __attribute__ (( packed ));
@@ -432,7 +432,7 @@ struct srp_cmd {
432 432
 	/** Data-in buffer descriptor count */
433 433
 	uint8_t data_in_buffer_count;
434 434
 	/** Tag */
435
-	struct srp_tag tag;
435
+	union srp_tag tag;
436 436
 	/** Reserved */
437 437
 	uint8_t reserved1[4];
438 438
 	/** Logical unit number */
@@ -526,7 +526,7 @@ struct srp_rsp {
526 526
 	/** Request limit delta */
527 527
 	uint32_t request_limit_delta;
528 528
 	/** Tag */
529
-	struct srp_tag tag;
529
+	union srp_tag tag;
530 530
 	/** Reserved */
531 531
 	uint8_t reserved1[2];
532 532
 	/** Valid fields
@@ -580,9 +580,9 @@ struct srp_rsp {
580 580
  * @v rsp			SCSI response
581 581
  * @ret response_data		Response data, or NULL if not present
582 582
  */
583
-static inline void * srp_rsp_response_data ( struct srp_rsp *rsp ) {
583
+static inline const void * srp_rsp_response_data ( const struct srp_rsp *rsp ) {
584 584
 	return ( ( rsp->valid & SRP_RSP_VALID_RSPVALID ) ?
585
-		 ( ( ( void * ) rsp ) + sizeof ( *rsp ) ) : NULL );
585
+		 ( ( ( const void * ) rsp ) + sizeof ( *rsp ) ) : NULL );
586 586
 }
587 587
 
588 588
 /**
@@ -591,7 +591,7 @@ static inline void * srp_rsp_response_data ( struct srp_rsp *rsp ) {
591 591
  * @v rsp			SCSI response
592 592
  * @ret response_data_len	Response data length
593 593
  */
594
-static inline size_t srp_rsp_response_data_len ( struct srp_rsp *rsp ) {
594
+static inline size_t srp_rsp_response_data_len ( const struct srp_rsp *rsp ) {
595 595
 	return ( ( rsp->valid & SRP_RSP_VALID_RSPVALID ) ?
596 596
 		 ntohl ( rsp->response_data_len ) : 0 );
597 597
 }
@@ -602,9 +602,9 @@ static inline size_t srp_rsp_response_data_len ( struct srp_rsp *rsp ) {
602 602
  * @v rsp			SCSI response
603 603
  * @ret sense_data		Sense data, or NULL if not present
604 604
  */
605
-static inline void * srp_rsp_sense_data ( struct srp_rsp *rsp ) {
605
+static inline const void * srp_rsp_sense_data ( const struct srp_rsp *rsp ) {
606 606
 	return ( ( rsp->valid & SRP_RSP_VALID_SNSVALID ) ?
607
-		 ( ( ( void * ) rsp ) + sizeof ( *rsp ) +
607
+		 ( ( ( const void * ) rsp ) + sizeof ( *rsp ) +
608 608
 		   srp_rsp_response_data_len ( rsp ) ) : NULL );
609 609
 }
610 610
 
@@ -614,7 +614,7 @@ static inline void * srp_rsp_sense_data ( struct srp_rsp *rsp ) {
614 614
  * @v rsp			SCSI response
615 615
  * @ret sense_data_len		Sense data length
616 616
  */
617
-static inline size_t srp_rsp_sense_data_len ( struct srp_rsp *rsp ) {
617
+static inline size_t srp_rsp_sense_data_len ( const struct srp_rsp *rsp ) {
618 618
 	return ( ( rsp->valid & SRP_RSP_VALID_SNSVALID ) ?
619 619
 		 ntohl ( rsp->sense_data_len ) : 0 );
620 620
 }
@@ -644,7 +644,7 @@ struct srp_cred_req {
644 644
 	/** Request limit delta */
645 645
 	uint32_t request_limit_delta;
646 646
 	/** Tag */
647
-	struct srp_tag tag;
647
+	union srp_tag tag;
648 648
 } __attribute__ (( packed ));
649 649
 
650 650
 /** Type of an SRP credit request */
@@ -670,7 +670,7 @@ struct srp_cred_rsp {
670 670
 	/** Reserved */
671 671
 	uint8_t reserved0[7];
672 672
 	/** Tag */
673
-	struct srp_tag tag;
673
+	union srp_tag tag;
674 674
 } __attribute__ (( packed ));
675 675
 
676 676
 /** Type of an SRP credit response */
@@ -701,7 +701,7 @@ struct srp_aer_req {
701 701
 	/** Request limit delta */
702 702
 	uint32_t request_limit_delta;
703 703
 	/** Tag */
704
-	struct srp_tag tag;
704
+	union srp_tag tag;
705 705
 	/** Reserved */
706 706
 	uint8_t reserved1[4];
707 707
 	/** Logical unit number */
@@ -757,7 +757,7 @@ struct srp_aer_rsp {
757 757
 	/** Reserved */
758 758
 	uint8_t reserved0[7];
759 759
 	/** Tag */
760
-	struct srp_tag tag;
760
+	union srp_tag tag;
761 761
 } __attribute__ (( packed ));
762 762
 
763 763
 /** Type of an SRP asynchronous event response */
@@ -765,104 +765,65 @@ struct srp_aer_rsp {
765 765
 
766 766
 /*****************************************************************************
767 767
  *
768
- * Information units
769
- *
770
- *****************************************************************************
771
- */
772
-
773
-/** Maximum length of any initiator-to-target IU that we will send
768
+ * SRP boot firmware table
774 769
  *
775
- * The longest IU is a SRP_CMD with no additional CDB and two direct
776
- * data buffer descriptors, which comes to 80 bytes.
777
- */
778
-#define SRP_MAX_I_T_IU_LEN 80
779
-
780
-/*****************************************************************************
770
+ * The working draft specification for the SRP boot firmware table can
771
+ * be found at
781 772
  *
782
- * SRP device
773
+ *   http://ipxe.org/wiki/srp/sbft
783 774
  *
784 775
  *****************************************************************************
785 776
  */
786 777
 
787
-struct srp_device;
778
+/** SRP Boot Firmware Table signature */
779
+#define SBFT_SIG ACPI_SIGNATURE ( 's', 'B', 'F', 'T' )
788 780
 
789
-/** An SRP transport type */
790
-struct srp_transport_type {
791
-	/** Length of transport private data */
792
-	size_t priv_len;
793
-	/** Parse root path
794
-	 *
795
-	 * @v srp		SRP device
796
-	 * @v root_path		Root path
797
-	 * @ret 		Return status code
798
-	 */
799
-	int ( * parse_root_path ) ( struct srp_device *srp,
800
-				    const char *root_path );
801
-	/** Connect SRP session
802
-	 *
803
-	 * @v srp		SRP device
804
-	 * @ret rc		Return status code
805
-	 *
806
-	 * This method should open the underlying socket.
807
-	 */
808
-	int ( * connect ) ( struct srp_device *srp );
809
-};
781
+/** An offset from the start of the sBFT */
782
+typedef uint16_t sbft_off_t;
810 783
 
811
-/** An SRP device */
812
-struct srp_device {
813
-	/** Reference count */
814
-	struct refcnt refcnt;
784
+/**
785
+ * SRP Boot Firmware Table
786
+ */
787
+struct sbft_table {
788
+	/** ACPI header */
789
+	struct acpi_description_header acpi;
790
+	/** Offset to SCSI subtable */
791
+	sbft_off_t scsi_offset;
792
+	/** Offset to SRP subtable */
793
+	sbft_off_t srp_offset;
794
+	/** Offset to IB subtable, if present */
795
+	sbft_off_t ib_offset;
796
+	/** Reserved */
797
+	uint8_t reserved[6];
798
+} __attribute__ (( packed ));
815 799
 
816
-	/** Initiator and target port IDs */
817
-	struct srp_port_ids port_ids;
818
-	/** Logical unit number */
800
+/**
801
+ * sBFT SCSI subtable
802
+ */
803
+struct sbft_scsi_subtable {
804
+	/** LUN */
819 805
 	struct scsi_lun lun;
820
-	/** Memory handle */
821
-	uint32_t memory_handle;
822
-
823
-	/** Current state
824
-	 *
825
-	 * This is the bitwise-OR of zero or more @c SRP_STATE_XXX
826
-	 * flags.
827
-	 */
828
-	unsigned int state;
829
-	/** Retry counter */
830
-	unsigned int retry_count;
831
-	/** Current SCSI command */
832
-	struct scsi_command *command;
833
-
834
-	/** Underlying data transfer interface */
835
-	struct interface socket;
836
-
837
-	/** Transport type */
838
-	struct srp_transport_type *transport;
839
-	/** Transport private data */
840
-	char transport_priv[0];
841
-};
806
+} __attribute__ (( packed ));
842 807
 
843 808
 /**
844
- * Get SRP transport private data
845
- *
846
- * @v srp		SRP device
847
- * @ret priv		SRP transport private data
809
+ * sBFT SRP subtable
848 810
  */
849
-static inline __always_inline void *
850
-srp_transport_priv ( struct srp_device *srp ) {
851
-	return ( ( void * ) srp->transport_priv );
852
-}
853
-
854
-/** SRP state flags */
855
-enum srp_state {
856
-	/** Underlying socket is open */
857
-	SRP_STATE_SOCKET_OPEN = 0x0001,
858
-	/** Session is logged in */
859
-	SRP_STATE_LOGGED_IN = 0x0002,
860
-};
811
+struct sbft_srp_subtable {
812
+	/** Initiator port identifier */
813
+	union srp_port_id initiator;
814
+	/** Target port identifier */
815
+	union srp_port_id target;
816
+} __attribute__ (( packed ));
861 817
 
862
-/** Maximum number of SRP retry attempts */
863
-#define SRP_MAX_RETRIES 3
818
+/*****************************************************************************
819
+ *
820
+ * SRP devices
821
+ *
822
+ *****************************************************************************
823
+ */
864 824
 
865
-extern int srp_attach ( struct scsi_device *scsi, const char *root_path );
866
-extern void srp_detach ( struct scsi_device *scsi );
825
+extern int srp_open ( struct interface *block, struct interface *socket,
826
+		      union srp_port_id *initiator, union srp_port_id *target,
827
+		      uint32_t memory_handle, struct scsi_lun *lun );
867 828
 
868 829
 #endif /* _IPXE_SRP_H */

+ 850
- 290
src/net/aoe.c
File diff suppressed because it is too large
Näytä tiedosto


+ 260
- 85
src/net/infiniband/ib_srp.c Näytä tiedosto

@@ -32,7 +32,11 @@ FILE_LICENCE ( BSD2 );
32 32
 
33 33
 #include <stdlib.h>
34 34
 #include <errno.h>
35
+#include <ipxe/interface.h>
36
+#include <ipxe/uri.h>
37
+#include <ipxe/open.h>
35 38
 #include <ipxe/base16.h>
39
+#include <ipxe/acpi.h>
36 40
 #include <ipxe/srp.h>
37 41
 #include <ipxe/infiniband.h>
38 42
 #include <ipxe/ib_cmrc.h>
@@ -56,6 +60,192 @@ FILE_LICENCE ( BSD2 );
56 60
 #define EINFO_EINVAL_RP_TOO_SHORT __einfo_uniqify \
57 61
 	( EINFO_EINVAL, 0x04, "Root path too short" )
58 62
 
63
+/******************************************************************************
64
+ *
65
+ * IB SRP devices
66
+ *
67
+ ******************************************************************************
68
+ */
69
+
70
+/** An Infiniband SRP device */
71
+struct ib_srp_device {
72
+	/** Reference count */
73
+	struct refcnt refcnt;
74
+
75
+	/** SRP transport interface */
76
+	struct interface srp;
77
+	/** CMRC interface */
78
+	struct interface cmrc;
79
+
80
+	/** Infiniband device */
81
+	struct ib_device *ibdev;
82
+
83
+	/** Destination GID (for boot firmware table) */
84
+	struct ib_gid dgid;
85
+	/** Service ID (for boot firmware table) */
86
+	struct ib_gid_half service_id;
87
+};
88
+
89
+/**
90
+ * Free IB SRP device
91
+ *
92
+ * @v refcnt		Reference count
93
+ */
94
+static void ib_srp_free ( struct refcnt *refcnt ) {
95
+	struct ib_srp_device *ib_srp =
96
+		container_of ( refcnt, struct ib_srp_device, refcnt );
97
+
98
+	ibdev_put ( ib_srp->ibdev );
99
+	free ( ib_srp );
100
+}
101
+
102
+/**
103
+ * Close IB SRP device
104
+ *
105
+ * @v ib_srp		IB SRP device
106
+ * @v rc		Reason for close
107
+ */
108
+static void ib_srp_close ( struct ib_srp_device *ib_srp, int rc ) {
109
+
110
+	/* Shut down interfaces */
111
+	intf_shutdown ( &ib_srp->cmrc, rc );
112
+	intf_shutdown ( &ib_srp->srp, rc );
113
+}
114
+
115
+/**
116
+ * Describe IB SRP device in an ACPI table
117
+ *
118
+ * @v srpdev		SRP device
119
+ * @v acpi		ACPI table
120
+ * @v len		Length of ACPI table
121
+ * @ret rc		Return status code
122
+ */
123
+static int ib_srp_describe ( struct ib_srp_device *ib_srp,
124
+			     struct acpi_description_header *acpi,
125
+			     size_t len ) {
126
+	struct ib_device *ibdev = ib_srp->ibdev;
127
+	struct sbft_table *sbft =
128
+		container_of ( acpi, struct sbft_table, acpi );
129
+	struct sbft_ib_subtable *ib_sbft;
130
+	size_t used;
131
+
132
+	/* Sanity check */
133
+	if ( acpi->signature != SBFT_SIG )
134
+		return -EINVAL;
135
+
136
+	/* Append IB subtable to existing table */
137
+	used = le32_to_cpu ( sbft->acpi.length );
138
+	sbft->ib_offset = cpu_to_le16 ( used );
139
+	ib_sbft = ( ( ( void * ) sbft ) + used );
140
+	used += sizeof ( *ib_sbft );
141
+	if ( used > len )
142
+		return -ENOBUFS;
143
+	sbft->acpi.length = cpu_to_le32 ( used );
144
+
145
+	/* Populate subtable */
146
+	memcpy ( &ib_sbft->sgid, &ibdev->gid, sizeof ( ib_sbft->sgid ) );
147
+	memcpy ( &ib_sbft->dgid, &ib_srp->dgid, sizeof ( ib_sbft->dgid ) );
148
+	memcpy ( &ib_sbft->service_id, &ib_srp->service_id,
149
+		 sizeof ( ib_sbft->service_id ) );
150
+	ib_sbft->pkey = cpu_to_le16 ( ibdev->pkey );
151
+
152
+	return 0;
153
+}
154
+
155
+/** IB SRP CMRC interface operations */
156
+static struct interface_operation ib_srp_cmrc_op[] = {
157
+	INTF_OP ( intf_close, struct ib_srp_device *, ib_srp_close ),
158
+};
159
+
160
+/** IB SRP CMRC interface descriptor */
161
+static struct interface_descriptor ib_srp_cmrc_desc =
162
+	INTF_DESC_PASSTHRU ( struct ib_srp_device, cmrc, ib_srp_cmrc_op, srp );
163
+
164
+/** IB SRP SRP interface operations */
165
+static struct interface_operation ib_srp_srp_op[] = {
166
+	INTF_OP ( acpi_describe, struct ib_srp_device *, ib_srp_describe ),
167
+	INTF_OP ( intf_close, struct ib_srp_device *, ib_srp_close ),
168
+};
169
+
170
+/** IB SRP SRP interface descriptor */
171
+static struct interface_descriptor ib_srp_srp_desc =
172
+	INTF_DESC_PASSTHRU ( struct ib_srp_device, srp, ib_srp_srp_op, cmrc );
173
+
174
+/**
175
+ * Open IB SRP device
176
+ *
177
+ * @v block		Block control interface
178
+ * @v ibdev		Infiniband device
179
+ * @v dgid		Destination GID
180
+ * @v service_id	Service ID
181
+ * @v initiator		Initiator port ID
182
+ * @v target		Target port ID
183
+ * @v lun		SCSI LUN
184
+ * @ret rc		Return status code
185
+ */
186
+static int ib_srp_open ( struct interface *block, struct ib_device *ibdev,
187
+			 struct ib_gid *dgid, struct ib_gid_half *service_id,
188
+			 union srp_port_id *initiator,
189
+			 union srp_port_id *target, struct scsi_lun *lun ) {
190
+	struct ib_srp_device *ib_srp;
191
+	int rc;
192
+
193
+	/* Allocate and initialise structure */
194
+	ib_srp = zalloc ( sizeof ( *ib_srp ) );
195
+	if ( ! ib_srp ) {
196
+		rc = -ENOMEM;
197
+		goto err_zalloc;
198
+	}
199
+	ref_init ( &ib_srp->refcnt, ib_srp_free );
200
+	intf_init ( &ib_srp->srp, &ib_srp_srp_desc, &ib_srp->refcnt );
201
+	intf_init ( &ib_srp->cmrc, &ib_srp_cmrc_desc, &ib_srp->refcnt );
202
+	ib_srp->ibdev = ibdev_get ( ibdev );
203
+	DBGC ( ib_srp, "IBSRP %p created for %08x%08x%08x%08x:%08x%08x\n",
204
+	       ib_srp, ntohl ( dgid->u.dwords[0] ),
205
+	       ntohl ( dgid->u.dwords[1] ), ntohl ( dgid->u.dwords[2] ),
206
+	       ntohl ( dgid->u.dwords[3] ), ntohl ( service_id->u.dwords[0] ),
207
+	       ntohl ( service_id->u.dwords[1] ) );
208
+
209
+	/* Preserve parameters required for boot firmware table */
210
+	memcpy ( &ib_srp->dgid, dgid, sizeof ( ib_srp->dgid ) );
211
+	memcpy ( &ib_srp->service_id, service_id,
212
+		 sizeof ( ib_srp->service_id ) );
213
+
214
+	/* Open CMRC socket */
215
+	if ( ( rc = ib_cmrc_open ( &ib_srp->cmrc, ibdev, dgid,
216
+				   service_id ) ) != 0 ) {
217
+		DBGC ( ib_srp, "IBSRP %p could not open CMRC socket: %s\n",
218
+		       ib_srp, strerror ( rc ) );
219
+		goto err_cmrc_open;
220
+	}
221
+
222
+	/* Attach SRP device to parent interface */
223
+	if ( ( rc = srp_open ( block, &ib_srp->srp, initiator, target,
224
+			       ibdev->rdma_key, lun ) ) != 0 ) {
225
+		DBGC ( ib_srp, "IBSRP %p could not create SRP device: %s\n",
226
+		       ib_srp, strerror ( rc ) );
227
+		goto err_srp_open;
228
+	}
229
+
230
+	/* Mortalise self and return */
231
+	ref_put ( &ib_srp->refcnt );
232
+	return 0;
233
+
234
+ err_srp_open:
235
+ err_cmrc_open:
236
+	ib_srp_close ( ib_srp, rc );
237
+	ref_put ( &ib_srp->refcnt );
238
+ err_zalloc:
239
+	return rc;
240
+}
241
+
242
+/******************************************************************************
243
+ *
244
+ * IB SRP URIs
245
+ *
246
+ ******************************************************************************
247
+ */
248
+
59 249
 /** IB SRP parse flags */
60 250
 enum ib_srp_parse_flags {
61 251
 	IB_SRP_PARSE_REQUIRED = 0x0000,
@@ -65,12 +255,20 @@ enum ib_srp_parse_flags {
65 255
 
66 256
 /** IB SRP root path parameters */
67 257
 struct ib_srp_root_path {
258
+	/** Source GID */
259
+	struct ib_gid sgid;
260
+	/** Initiator port ID */
261
+	union ib_srp_initiator_port_id initiator;
262
+	/** Destination GID */
263
+	struct ib_gid dgid;
264
+	/** Partition key */
265
+	uint16_t pkey;
266
+	/** Service ID */
267
+	struct ib_gid_half service_id;
68 268
 	/** SCSI LUN */
69
-	struct scsi_lun *lun;
70
-	/** SRP port IDs */
71
-	struct srp_port_ids *port_ids;
72
-	/** IB SRP parameters */
73
-	struct ib_srp_parameters *ib;
269
+	struct scsi_lun lun;
270
+	/** Target port ID */
271
+	union ib_srp_target_port_id target;
74 272
 };
75 273
 
76 274
 /**
@@ -99,7 +297,6 @@ static int ib_srp_parse_byte_string ( const char *rp_comp, uint8_t *bytes,
99 297
 	decoded_size = base16_decode ( rp_comp, bytes );
100 298
 	if ( decoded_size < 0 )
101 299
 		return decoded_size;
102
-	assert ( decoded_size == size );
103 300
 
104 301
 	return 0;
105 302
 }
@@ -125,19 +322,6 @@ static int ib_srp_parse_integer ( const char *rp_comp, int default_value ) {
125 322
 	return value;
126 323
 }
127 324
 
128
-/**
129
- * Parse IB SRP root path literal component
130
- *
131
- * @v rp_comp		Root path component string
132
- * @v rp		IB SRP root path
133
- * @ret rc		Return status code
134
- */
135
-static int ib_srp_parse_literal ( const char *rp_comp __unused,
136
-				  struct ib_srp_root_path *rp __unused ) {
137
-	/* Ignore */
138
-	return 0;
139
-}
140
-
141 325
 /**
142 326
  * Parse IB SRP root path source GID
143 327
  *
@@ -151,10 +335,10 @@ static int ib_srp_parse_sgid ( const char *rp_comp,
151 335
 
152 336
 	/* Default to the GID of the last opened Infiniband device */
153 337
 	if ( ( ibdev = last_opened_ibdev() ) != NULL )
154
-		memcpy ( &rp->ib->sgid, &ibdev->gid, sizeof ( rp->ib->sgid ) );
338
+		memcpy ( &rp->sgid, &ibdev->gid, sizeof ( rp->sgid ) );
155 339
 
156
-	return ib_srp_parse_byte_string ( rp_comp, rp->ib->sgid.u.bytes,
157
-					  ( sizeof ( rp->ib->sgid ) |
340
+	return ib_srp_parse_byte_string ( rp_comp, rp->sgid.u.bytes,
341
+					  ( sizeof ( rp->sgid ) |
158 342
 					    IB_SRP_PARSE_OPTIONAL ) );
159 343
 }
160 344
 
@@ -167,11 +351,10 @@ static int ib_srp_parse_sgid ( const char *rp_comp,
167 351
  */
168 352
 static int ib_srp_parse_initiator_id_ext ( const char *rp_comp,
169 353
 					   struct ib_srp_root_path *rp ) {
170
-	struct ib_srp_initiator_port_id *port_id =
171
-		ib_srp_initiator_port_id ( rp->port_ids );
354
+	union ib_srp_initiator_port_id *port_id = &rp->initiator;
172 355
 
173
-	return ib_srp_parse_byte_string ( rp_comp, port_id->id_ext.u.bytes,
174
-					  ( sizeof ( port_id->id_ext ) |
356
+	return ib_srp_parse_byte_string ( rp_comp, port_id->ib.id_ext.u.bytes,
357
+					  ( sizeof ( port_id->ib.id_ext ) |
175 358
 					    IB_SRP_PARSE_OPTIONAL ) );
176 359
 }
177 360
 
@@ -184,15 +367,14 @@ static int ib_srp_parse_initiator_id_ext ( const char *rp_comp,
184 367
  */
185 368
 static int ib_srp_parse_initiator_hca_guid ( const char *rp_comp,
186 369
 					     struct ib_srp_root_path *rp ) {
187
-	struct ib_srp_initiator_port_id *port_id =
188
-		ib_srp_initiator_port_id ( rp->port_ids );
370
+	union ib_srp_initiator_port_id *port_id = &rp->initiator;
189 371
 
190 372
 	/* Default to the GUID portion of the source GID */
191
-	memcpy ( &port_id->hca_guid, &rp->ib->sgid.u.half[1],
192
-		 sizeof ( port_id->hca_guid ) );
373
+	memcpy ( &port_id->ib.hca_guid, &rp->sgid.u.half[1],
374
+		 sizeof ( port_id->ib.hca_guid ) );
193 375
 
194
-	return ib_srp_parse_byte_string ( rp_comp, port_id->hca_guid.u.bytes,
195
-					  ( sizeof ( port_id->hca_guid ) |
376
+	return ib_srp_parse_byte_string ( rp_comp, port_id->ib.hca_guid.u.bytes,
377
+					  ( sizeof ( port_id->ib.hca_guid ) |
196 378
 					    IB_SRP_PARSE_OPTIONAL ) );
197 379
 }
198 380
 
@@ -205,8 +387,8 @@ static int ib_srp_parse_initiator_hca_guid ( const char *rp_comp,
205 387
  */
206 388
 static int ib_srp_parse_dgid ( const char *rp_comp,
207 389
 			       struct ib_srp_root_path *rp ) {
208
-	return ib_srp_parse_byte_string ( rp_comp, rp->ib->dgid.u.bytes,
209
-					  ( sizeof ( rp->ib->dgid ) |
390
+	return ib_srp_parse_byte_string ( rp_comp, rp->dgid.u.bytes,
391
+					  ( sizeof ( rp->dgid ) |
210 392
 					    IB_SRP_PARSE_REQUIRED ) );
211 393
 }
212 394
 
@@ -223,7 +405,7 @@ static int ib_srp_parse_pkey ( const char *rp_comp,
223 405
 
224 406
 	if ( ( pkey = ib_srp_parse_integer ( rp_comp, IB_PKEY_DEFAULT ) ) < 0 )
225 407
 		return pkey;
226
-	rp->ib->pkey = pkey;
408
+	rp->pkey = pkey;
227 409
 	return 0;
228 410
 }
229 411
 
@@ -236,8 +418,8 @@ static int ib_srp_parse_pkey ( const char *rp_comp,
236 418
  */
237 419
 static int ib_srp_parse_service_id ( const char *rp_comp,
238 420
 				     struct ib_srp_root_path *rp ) {
239
-	return ib_srp_parse_byte_string ( rp_comp, rp->ib->service_id.u.bytes,
240
-					  ( sizeof ( rp->ib->service_id ) |
421
+	return ib_srp_parse_byte_string ( rp_comp, rp->service_id.u.bytes,
422
+					  ( sizeof ( rp->service_id ) |
241 423
 					    IB_SRP_PARSE_REQUIRED ) );
242 424
 }
243 425
 
@@ -250,7 +432,7 @@ static int ib_srp_parse_service_id ( const char *rp_comp,
250 432
  */
251 433
 static int ib_srp_parse_lun ( const char *rp_comp,
252 434
 			      struct ib_srp_root_path *rp ) {
253
-	return scsi_parse_lun ( rp_comp, rp->lun );
435
+	return scsi_parse_lun ( rp_comp, &rp->lun );
254 436
 }
255 437
 
256 438
 /**
@@ -262,11 +444,10 @@ static int ib_srp_parse_lun ( const char *rp_comp,
262 444
  */
263 445
 static int ib_srp_parse_target_id_ext ( const char *rp_comp,
264 446
 					struct ib_srp_root_path *rp ) {
265
-	struct ib_srp_target_port_id *port_id =
266
-		ib_srp_target_port_id ( rp->port_ids );
447
+	union ib_srp_target_port_id *port_id = &rp->target;
267 448
 
268
-	return ib_srp_parse_byte_string ( rp_comp, port_id->id_ext.u.bytes,
269
-					  ( sizeof ( port_id->id_ext ) |
449
+	return ib_srp_parse_byte_string ( rp_comp, port_id->ib.id_ext.u.bytes,
450
+					  ( sizeof ( port_id->ib.id_ext ) |
270 451
 					    IB_SRP_PARSE_REQUIRED ) );
271 452
 }
272 453
 
@@ -279,11 +460,10 @@ static int ib_srp_parse_target_id_ext ( const char *rp_comp,
279 460
  */
280 461
 static int ib_srp_parse_target_ioc_guid ( const char *rp_comp,
281 462
 					  struct ib_srp_root_path *rp ) {
282
-	struct ib_srp_target_port_id *port_id =
283
-		ib_srp_target_port_id ( rp->port_ids );
463
+	union ib_srp_target_port_id *port_id = &rp->target;
284 464
 
285
-	return ib_srp_parse_byte_string ( rp_comp, port_id->ioc_guid.u.bytes,
286
-					  ( sizeof ( port_id->ioc_guid ) |
465
+	return ib_srp_parse_byte_string ( rp_comp, port_id->ib.ioc_guid.u.bytes,
466
+					  ( sizeof ( port_id->ib.ioc_guid ) |
287 467
 					    IB_SRP_PARSE_REQUIRED ) );
288 468
 }
289 469
 
@@ -301,7 +481,6 @@ struct ib_srp_root_path_parser {
301 481
 
302 482
 /** IB SRP root path components */
303 483
 static struct ib_srp_root_path_parser ib_srp_rp_parser[] = {
304
-	{ ib_srp_parse_literal },
305 484
 	{ ib_srp_parse_sgid },
306 485
 	{ ib_srp_parse_initiator_id_ext },
307 486
 	{ ib_srp_parse_initiator_hca_guid },
@@ -320,18 +499,13 @@ static struct ib_srp_root_path_parser ib_srp_rp_parser[] = {
320 499
 /**
321 500
  * Parse IB SRP root path
322 501
  *
323
- * @v srp		SRP device
324
- * @v rp_string		Root path
502
+ * @v rp_string		Root path string
503
+ * @v rp		IB SRP root path
325 504
  * @ret rc		Return status code
326 505
  */
327
-static int ib_srp_parse_root_path ( struct srp_device *srp,
328
-				    const char *rp_string ) {
329
-	struct ib_srp_parameters *ib_params = ib_srp_params ( srp );
330
-	struct ib_srp_root_path rp = {
331
-		.lun = &srp->lun,
332
-		.port_ids = &srp->port_ids,
333
-		.ib = ib_params,
334
-	};
506
+static int ib_srp_parse_root_path ( const char *rp_string,
507
+				    struct ib_srp_root_path *rp ) {
508
+	struct ib_srp_root_path_parser *parser;
335 509
 	char rp_string_copy[ strlen ( rp_string ) + 1 ];
336 510
 	char *rp_comp[IB_SRP_NUM_RP_COMPONENTS];
337 511
 	char *rp_string_tmp = rp_string_copy;
@@ -346,8 +520,8 @@ static int ib_srp_parse_root_path ( struct srp_device *srp,
346 520
 			break;
347 521
 		for ( ; *rp_string_tmp != ':' ; rp_string_tmp++ ) {
348 522
 			if ( ! *rp_string_tmp ) {
349
-				DBGC ( srp, "SRP %p root path \"%s\" too "
350
-				       "short\n", srp, rp_string );
523
+				DBG ( "IBSRP root path \"%s\" too short\n",
524
+				      rp_string );
351 525
 				return -EINVAL_RP_TOO_SHORT;
352 526
 			}
353 527
 		}
@@ -356,11 +530,11 @@ static int ib_srp_parse_root_path ( struct srp_device *srp,
356 530
 
357 531
 	/* Parse root path components */
358 532
 	for ( i = 0 ; i < IB_SRP_NUM_RP_COMPONENTS ; i++ ) {
359
-		if ( ( rc = ib_srp_rp_parser[i].parse ( rp_comp[i],
360
-							&rp ) ) != 0 ) {
361
-			DBGC ( srp, "SRP %p could not parse \"%s\" in root "
362
-			       "path \"%s\": %s\n", srp, rp_comp[i],
363
-			       rp_string, strerror ( rc ) );
533
+		parser = &ib_srp_rp_parser[i];
534
+		if ( ( rc = parser->parse ( rp_comp[i], rp ) ) != 0 ) {
535
+			DBG ( "IBSRP could not parse \"%s\" in root path "
536
+			      "\"%s\": %s\n", rp_comp[i], rp_string,
537
+			      strerror ( rc ) );
364 538
 			return rc;
365 539
 		}
366 540
 	}
@@ -369,41 +543,42 @@ static int ib_srp_parse_root_path ( struct srp_device *srp,
369 543
 }
370 544
 
371 545
 /**
372
- * Connect IB SRP session
546
+ * Open IB SRP URI
373 547
  *
374
- * @v srp		SRP device
548
+ * @v parent		Parent interface
549
+ * @v uri		URI
375 550
  * @ret rc		Return status code
376 551
  */
377
-static int ib_srp_connect ( struct srp_device *srp ) {
378
-	struct ib_srp_parameters *ib_params = ib_srp_params ( srp );
552
+static int ib_srp_open_uri ( struct interface *parent, struct uri *uri ) {
553
+	struct ib_srp_root_path rp;
379 554
 	struct ib_device *ibdev;
380 555
 	int rc;
381 556
 
557
+	/* Parse URI */
558
+	if ( ! uri->opaque )
559
+		return -EINVAL;
560
+	memset ( &rp, 0, sizeof ( rp ) );
561
+	if ( ( rc = ib_srp_parse_root_path ( uri->opaque, &rp ) ) != 0 )
562
+		return rc;
563
+
382 564
 	/* Identify Infiniband device */
383
-	ibdev = find_ibdev ( &ib_params->sgid );
565
+	ibdev = find_ibdev ( &rp.sgid );
384 566
 	if ( ! ibdev ) {
385
-		DBGC ( srp, "SRP %p could not identify Infiniband device\n",
386
-		       srp );
567
+		DBG ( "IBSRP could not identify Infiniband device\n" );
387 568
 		return -ENODEV;
388 569
 	}
389 570
 
390
-	/* Configure remaining SRP parameters */
391
-	srp->memory_handle = ibdev->rdma_key;
392
-
393
-	/* Open CMRC socket */
394
-	if ( ( rc = ib_cmrc_open ( &srp->socket, ibdev, &ib_params->dgid,
395
-				   &ib_params->service_id ) ) != 0 ) {
396
-		DBGC ( srp, "SRP %p could not open CMRC socket: %s\n",
397
-		       srp, strerror ( rc ) );
571
+	/* Open IB SRP device */
572
+	if ( ( rc = ib_srp_open ( parent, ibdev, &rp.dgid, &rp.service_id,
573
+				  &rp.initiator.srp, &rp.target.srp,
574
+				  &rp.lun ) ) != 0 )
398 575
 		return rc;
399
-	}
400 576
 
401 577
 	return 0;
402 578
 }
403 579
 
404
-/** IB SRP transport type */
405
-struct srp_transport_type ib_srp_transport = {
406
-	.priv_len = sizeof ( struct ib_srp_parameters ),
407
-	.parse_root_path = ib_srp_parse_root_path,
408
-	.connect = ib_srp_connect,
580
+/** IB SRP URI opener */
581
+struct uri_opener ib_srp_uri_opener __uri_opener = {
582
+	.scheme = "ib_srp",
583
+	.open = ib_srp_open_uri,
409 584
 };

+ 283
- 156
src/net/tcp/iscsi.c Näytä tiedosto

@@ -28,6 +28,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
28 28
 #include <ipxe/vsprintf.h>
29 29
 #include <ipxe/socket.h>
30 30
 #include <ipxe/iobuf.h>
31
+#include <ipxe/uri.h>
31 32
 #include <ipxe/xfer.h>
32 33
 #include <ipxe/open.h>
33 34
 #include <ipxe/scsi.h>
@@ -38,6 +39,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
38 39
 #include <ipxe/features.h>
39 40
 #include <ipxe/base16.h>
40 41
 #include <ipxe/base64.h>
42
+#include <ipxe/ibft.h>
41 43
 #include <ipxe/iscsi.h>
42 44
 
43 45
 /** @file
@@ -127,6 +129,36 @@ static void iscsi_rx_buffered_data_done ( struct iscsi_session *iscsi ) {
127 129
 	iscsi->rx_buffer = NULL;
128 130
 }
129 131
 
132
+/**
133
+ * Receive PDU data into buffer
134
+ *
135
+ * @v iscsi		iSCSI session
136
+ * @v data		Data to receive
137
+ * @v len		Length of data
138
+ * @ret rc		Return status code
139
+ *
140
+ * This can be used when the RX PDU type handler wishes to buffer up
141
+ * all received data and process the PDU as a single unit.  The caller
142
+ * is repsonsible for calling iscsi_rx_buffered_data_done() after
143
+ * processing the data.
144
+ */
145
+static int iscsi_rx_buffered_data ( struct iscsi_session *iscsi,
146
+				    const void *data, size_t len ) {
147
+
148
+	/* Allocate buffer on first call */
149
+	if ( ! iscsi->rx_buffer ) {
150
+		iscsi->rx_buffer = malloc ( iscsi->rx_len );
151
+		if ( ! iscsi->rx_buffer )
152
+			return -ENOMEM;
153
+	}
154
+
155
+	/* Copy data to buffer */
156
+	assert ( ( iscsi->rx_offset + len ) <= iscsi->rx_len );
157
+	memcpy ( ( iscsi->rx_buffer + iscsi->rx_offset ), data, len );
158
+
159
+	return 0;
160
+}
161
+
130 162
 /**
131 163
  * Free iSCSI session
132 164
  *
@@ -144,9 +176,44 @@ static void iscsi_free ( struct refcnt *refcnt ) {
144 176
 	free ( iscsi->target_password );
145 177
 	chap_finish ( &iscsi->chap );
146 178
 	iscsi_rx_buffered_data_done ( iscsi );
179
+	free ( iscsi->command );
147 180
 	free ( iscsi );
148 181
 }
149 182
 
183
+/**
184
+ * Shut down iSCSI interface
185
+ *
186
+ * @v iscsi		iSCSI session
187
+ * @v rc		Reason for close
188
+ */
189
+static void iscsi_close ( struct iscsi_session *iscsi, int rc ) {
190
+
191
+	/* A TCP graceful close is still an error from our point of view */
192
+	if ( rc == 0 )
193
+		rc = -ECONNRESET;
194
+
195
+	DBGC ( iscsi, "iSCSI %p closed: %s\n", iscsi, strerror ( rc ) );
196
+
197
+	/* Stop transmission process */
198
+	process_del ( &iscsi->process );
199
+
200
+	/* Shut down interfaces */
201
+	intf_shutdown ( &iscsi->socket, rc );
202
+	intf_shutdown ( &iscsi->control, rc );
203
+	intf_shutdown ( &iscsi->data, rc );
204
+}
205
+
206
+/**
207
+ * Assign new iSCSI initiator task tag
208
+ *
209
+ * @v iscsi		iSCSI session
210
+ */
211
+static void iscsi_new_itt ( struct iscsi_session *iscsi ) {
212
+	static uint16_t itt_idx;
213
+
214
+	iscsi->itt = ( ISCSI_TAG_MAGIC | (++itt_idx) );
215
+}
216
+
150 217
 /**
151 218
  * Open iSCSI transport-layer connection
152 219
  *
@@ -180,7 +247,7 @@ static int iscsi_open_connection ( struct iscsi_session *iscsi ) {
180 247
 		iscsi->status |= ISCSI_STATUS_AUTH_REVERSE_REQUIRED;
181 248
 
182 249
 	/* Assign fresh initiator task tag */
183
-	iscsi->itt++;
250
+	iscsi_new_itt ( iscsi );
184 251
 
185 252
 	/* Initiate login */
186 253
 	iscsi_start_login ( iscsi );
@@ -220,21 +287,34 @@ static void iscsi_close_connection ( struct iscsi_session *iscsi, int rc ) {
220 287
  *
221 288
  * @v iscsi		iSCSI session
222 289
  * @v rc		Return status code
290
+ * @v rsp		SCSI response, if any
223 291
  *
224 292
  * Note that iscsi_scsi_done() will not close the connection, and must
225 293
  * therefore be called only when the internal state machines are in an
226 294
  * appropriate state, otherwise bad things may happen on the next call
227
- * to iscsi_issue().  The general rule is to call iscsi_scsi_done()
228
- * only at the end of receiving a PDU; at this point the TX and RX
229
- * engines should both be idle.
295
+ * to iscsi_scsi_command().  The general rule is to call
296
+ * iscsi_scsi_done() only at the end of receiving a PDU; at this point
297
+ * the TX and RX engines should both be idle.
230 298
  */
231
-static void iscsi_scsi_done ( struct iscsi_session *iscsi, int rc ) {
299
+static void iscsi_scsi_done ( struct iscsi_session *iscsi, int rc,
300
+			      struct scsi_rsp *rsp ) {
301
+	uint32_t itt = iscsi->itt;
232 302
 
233 303
 	assert ( iscsi->tx_state == ISCSI_TX_IDLE );
234
-	assert ( iscsi->command != NULL );
235 304
 
236
-	iscsi->command->rc = rc;
305
+	/* Clear command */
306
+	free ( iscsi->command );
237 307
 	iscsi->command = NULL;
308
+
309
+	/* Send SCSI response, if any */
310
+	scsi_response ( &iscsi->data, rsp );
311
+
312
+	/* Close SCSI command, if this is still the same command.  (It
313
+	 * is possible that the command interface has already been
314
+	 * closed as a result of the SCSI response we sent.)
315
+	 */
316
+	if ( iscsi->itt == itt )
317
+		intf_restart ( &iscsi->data, rc );
238 318
 }
239 319
 
240 320
 /****************************************************************************
@@ -268,8 +348,9 @@ static void iscsi_start_command ( struct iscsi_session *iscsi ) {
268 348
 	if ( iscsi->command->data_out )
269 349
 		command->flags |= ISCSI_COMMAND_FLAG_WRITE;
270 350
 	/* lengths left as zero */
271
-	command->lun = iscsi->lun;
272
-	command->itt = htonl ( ++iscsi->itt );
351
+	memcpy ( &command->lun, &iscsi->command->lun,
352
+		 sizeof ( command->lun ) );
353
+	command->itt = htonl ( iscsi->itt );
273 354
 	command->exp_len = htonl ( iscsi->command->data_in_len |
274 355
 				   iscsi->command->data_out_len );
275 356
 	command->cmdsn = htonl ( iscsi->cmdsn );
@@ -297,28 +378,39 @@ static int iscsi_rx_scsi_response ( struct iscsi_session *iscsi,
297 378
 				    size_t remaining ) {
298 379
 	struct iscsi_bhs_scsi_response *response
299 380
 		= &iscsi->rx_bhs.scsi_response;
300
-	int sense_offset;
381
+	struct scsi_rsp rsp;
382
+	uint32_t residual_count;
383
+	int rc;
301 384
 
302
-	/* Capture the sense response code as it floats past, if present */
303
-	sense_offset = ISCSI_SENSE_RESPONSE_CODE_OFFSET - iscsi->rx_offset;
304
-	if ( ( sense_offset >= 0 ) && len ) {
305
-		iscsi->command->sense_response =
306
-			* ( ( char * ) data + sense_offset );
385
+	/* Buffer up the PDU data */
386
+	if ( ( rc = iscsi_rx_buffered_data ( iscsi, data, len ) ) != 0 ) {
387
+		DBGC ( iscsi, "iSCSI %p could not buffer login response: %s\n",
388
+		       iscsi, strerror ( rc ) );
389
+		return rc;
307 390
 	}
308
-
309
-	/* Wait for whole SCSI response to arrive */
310 391
 	if ( remaining )
311 392
 		return 0;
312
-	
313
-	/* Record SCSI status code */
314
-	iscsi->command->status = response->status;
393
+
394
+	/* Parse SCSI response and discard buffer */
395
+	memset ( &rsp, 0, sizeof ( rsp ) );
396
+	rsp.status = response->status;
397
+	residual_count = ntohl ( response->residual_count );
398
+	if ( response->flags & ISCSI_DATA_FLAG_OVERFLOW ) {
399
+		rsp.overrun = residual_count;
400
+	} else if ( response->flags & ISCSI_DATA_FLAG_UNDERFLOW ) {
401
+		rsp.overrun = -(residual_count);
402
+	}
403
+	if ( ISCSI_DATA_LEN ( response->lengths ) )
404
+		memcpy ( &rsp.sense, ( iscsi->rx_buffer + 2 ),
405
+			 sizeof ( rsp.sense ) );
406
+	iscsi_rx_buffered_data_done ( iscsi );
315 407
 
316 408
 	/* Check for errors */
317 409
 	if ( response->response != ISCSI_RESPONSE_COMMAND_COMPLETE )
318 410
 		return -EIO;
319 411
 
320 412
 	/* Mark as completed */
321
-	iscsi_scsi_done ( iscsi, 0 );
413
+	iscsi_scsi_done ( iscsi, 0, &rsp );
322 414
 	return 0;
323 415
 }
324 416
 
@@ -352,9 +444,8 @@ static int iscsi_rx_data_in ( struct iscsi_session *iscsi,
352 444
 	if ( data_in->flags & ISCSI_DATA_FLAG_STATUS ) {
353 445
 		assert ( ( offset + len ) == iscsi->command->data_in_len );
354 446
 		assert ( data_in->flags & ISCSI_FLAG_FINAL );
355
-		iscsi->command->status = data_in->status;
356 447
 		/* iSCSI cannot return an error status via a data-in */
357
-		iscsi_scsi_done ( iscsi, 0 );
448
+		iscsi_scsi_done ( iscsi, 0, NULL );
358 449
 	}
359 450
 
360 451
 	return 0;
@@ -412,7 +503,7 @@ static void iscsi_start_data_out ( struct iscsi_session *iscsi,
412 503
 	if ( len == remaining )
413 504
 		data_out->flags = ( ISCSI_FLAG_FINAL );
414 505
 	ISCSI_SET_LENGTHS ( data_out->lengths, 0, len );
415
-	data_out->lun = iscsi->lun;
506
+	data_out->lun = iscsi->command->lun;
416 507
 	data_out->itt = htonl ( iscsi->itt );
417 508
 	data_out->ttt = htonl ( iscsi->ttt );
418 509
 	data_out->expstatsn = htonl ( iscsi->statsn + 1 );
@@ -592,6 +683,19 @@ static void iscsi_start_login ( struct iscsi_session *iscsi ) {
592 683
 	struct iscsi_bhs_login_request *request = &iscsi->tx_bhs.login_request;
593 684
 	int len;
594 685
 
686
+	switch ( iscsi->status & ISCSI_LOGIN_CSG_MASK ) {
687
+	case ISCSI_LOGIN_CSG_SECURITY_NEGOTIATION:
688
+		DBGC ( iscsi, "iSCSI %p entering security negotiation\n",
689
+		       iscsi );
690
+		break;
691
+	case ISCSI_LOGIN_CSG_OPERATIONAL_NEGOTIATION:
692
+		DBGC ( iscsi, "iSCSI %p entering operational negotiation\n",
693
+		       iscsi );
694
+		break;
695
+	default:
696
+		assert ( 0 );
697
+	}
698
+
595 699
 	/* Construct BHS and initiate transmission */
596 700
 	iscsi_start_tx ( iscsi );
597 701
 	request->opcode = ( ISCSI_OPCODE_LOGIN_REQUEST |
@@ -604,7 +708,7 @@ static void iscsi_start_login ( struct iscsi_session *iscsi ) {
604 708
 	request->isid_iana_en = htonl ( ISCSI_ISID_IANA |
605 709
 					IANA_EN_FEN_SYSTEMS );
606 710
 	/* isid_iana_qual left as zero */
607
-	request->tsih = htons ( iscsi->tsih );
711
+	/* tsih left as zero */
608 712
 	request->itt = htonl ( iscsi->itt );
609 713
 	/* cid left as zero */
610 714
 	request->cmdsn = htonl ( iscsi->cmdsn );
@@ -1011,36 +1115,6 @@ static int iscsi_handle_strings ( struct iscsi_session *iscsi,
1011 1115
 	return 0;
1012 1116
 }
1013 1117
 
1014
-/**
1015
- * Receive PDU data into buffer
1016
- *
1017
- * @v iscsi		iSCSI session
1018
- * @v data		Data to receive
1019
- * @v len		Length of data
1020
- * @ret rc		Return status code
1021
- *
1022
- * This can be used when the RX PDU type handler wishes to buffer up
1023
- * all received data and process the PDU as a single unit.  The caller
1024
- * is repsonsible for calling iscsi_rx_buffered_data_done() after
1025
- * processing the data.
1026
- */
1027
-static int iscsi_rx_buffered_data ( struct iscsi_session *iscsi,
1028
-				    const void *data, size_t len ) {
1029
-
1030
-	/* Allocate buffer on first call */
1031
-	if ( ! iscsi->rx_buffer ) {
1032
-		iscsi->rx_buffer = malloc ( iscsi->rx_len );
1033
-		if ( ! iscsi->rx_buffer )
1034
-			return -ENOMEM;
1035
-	}
1036
-
1037
-	/* Copy data to buffer */
1038
-	assert ( ( iscsi->rx_offset + len ) <= iscsi->rx_len );
1039
-	memcpy ( ( iscsi->rx_buffer + iscsi->rx_offset ), data, len );
1040
-
1041
-	return 0;
1042
-}
1043
-
1044 1118
 /**
1045 1119
  * Convert iSCSI response status to return status code
1046 1120
  *
@@ -1119,7 +1193,6 @@ static int iscsi_rx_login_response ( struct iscsi_session *iscsi,
1119 1193
 		       response->status_class, response->status_detail );
1120 1194
 		rc = iscsi_status_to_rc ( response->status_class,
1121 1195
 					  response->status_detail );
1122
-		iscsi->instant_rc = rc;
1123 1196
 		return rc;
1124 1197
 	}
1125 1198
 
@@ -1160,14 +1233,9 @@ static int iscsi_rx_login_response ( struct iscsi_session *iscsi,
1160 1233
 		return -EPROTO;
1161 1234
 	}
1162 1235
 
1163
-	/* Reset retry count */
1164
-	iscsi->retry_count = 0;
1165
-
1166
-	/* Record TSIH for future reference */
1167
-	iscsi->tsih = ntohl ( response->tsih );
1168
-	
1169
-	/* Send the actual SCSI command */
1170
-	iscsi_start_command ( iscsi );
1236
+	/* Notify SCSI layer of window change */
1237
+	DBGC ( iscsi, "iSCSI %p entering full feature phase\n", iscsi );
1238
+	xfer_window_changed ( &iscsi->control );
1171 1239
 
1172 1240
 	return 0;
1173 1241
 }
@@ -1187,13 +1255,18 @@ static int iscsi_rx_login_response ( struct iscsi_session *iscsi,
1187 1255
  * be in transit at any one time.
1188 1256
  */
1189 1257
 static void iscsi_start_tx ( struct iscsi_session *iscsi ) {
1258
+
1190 1259
 	assert ( iscsi->tx_state == ISCSI_TX_IDLE );
1260
+	assert ( ! process_running ( &iscsi->process ) );
1191 1261
 	
1192 1262
 	/* Initialise TX BHS */
1193 1263
 	memset ( &iscsi->tx_bhs, 0, sizeof ( iscsi->tx_bhs ) );
1194 1264
 
1195 1265
 	/* Flag TX engine to start transmitting */
1196 1266
 	iscsi->tx_state = ISCSI_TX_BHS;
1267
+
1268
+	/* Start transmission process */
1269
+	process_add ( &iscsi->process );
1197 1270
 }
1198 1271
 
1199 1272
 /**
@@ -1273,6 +1346,9 @@ static int iscsi_tx_data_padding ( struct iscsi_session *iscsi ) {
1273 1346
 static void iscsi_tx_done ( struct iscsi_session *iscsi ) {
1274 1347
 	struct iscsi_bhs_common *common = &iscsi->tx_bhs.common;
1275 1348
 
1349
+	/* Stop transmission process */
1350
+	process_del ( &iscsi->process );
1351
+
1276 1352
 	switch ( common->opcode & ISCSI_OPCODE_MASK ) {
1277 1353
 	case ISCSI_OPCODE_DATA_OUT:
1278 1354
 		iscsi_data_out_done ( iscsi );
@@ -1305,9 +1381,6 @@ static void iscsi_tx_step ( struct process *process ) {
1305 1381
 	/* Select fragment to transmit */
1306 1382
 	while ( 1 ) {
1307 1383
 		switch ( iscsi->tx_state ) {
1308
-		case ISCSI_TX_IDLE:
1309
-			/* Stop processing */
1310
-			return;
1311 1384
 		case ISCSI_TX_BHS:
1312 1385
 			tx = iscsi_tx_bhs;
1313 1386
 			tx_len = sizeof ( iscsi->tx_bhs );
@@ -1328,6 +1401,10 @@ static void iscsi_tx_step ( struct process *process ) {
1328 1401
 			tx_len = ISCSI_DATA_PAD_LEN ( common->lengths );
1329 1402
 			next_state = ISCSI_TX_IDLE;
1330 1403
 			break;
1404
+		case ISCSI_TX_IDLE:
1405
+			/* Stop processing */
1406
+			iscsi_tx_done ( iscsi );
1407
+			return;
1331 1408
 		default:
1332 1409
 			assert ( 0 );
1333 1410
 			return;
@@ -1343,13 +1420,13 @@ static void iscsi_tx_step ( struct process *process ) {
1343 1420
 		if ( ( rc = tx ( iscsi ) ) != 0 ) {
1344 1421
 			DBGC ( iscsi, "iSCSI %p could not transmit: %s\n",
1345 1422
 			       iscsi, strerror ( rc ) );
1423
+			/* Transmission errors are fatal */
1424
+			iscsi_close ( iscsi, rc );
1346 1425
 			return;
1347 1426
 		}
1348 1427
 
1349 1428
 		/* Move to next state */
1350 1429
 		iscsi->tx_state = next_state;
1351
-		if ( next_state == ISCSI_TX_IDLE )
1352
-			iscsi_tx_done ( iscsi );
1353 1430
 	}
1354 1431
 }
1355 1432
 
@@ -1495,8 +1572,6 @@ static int iscsi_socket_deliver ( struct iscsi_session *iscsi,
1495 1572
 				 remaining ) ) != 0 ) {
1496 1573
 			DBGC ( iscsi, "iSCSI %p could not process received "
1497 1574
 			       "data: %s\n", iscsi, strerror ( rc ) );
1498
-			iscsi_close_connection ( iscsi, rc );
1499
-			iscsi_scsi_done ( iscsi, rc );
1500 1575
 			goto done;
1501 1576
 		}
1502 1577
 
@@ -1518,39 +1593,12 @@ static int iscsi_socket_deliver ( struct iscsi_session *iscsi,
1518 1593
  done:
1519 1594
 	/* Free I/O buffer */
1520 1595
 	free_iob ( iobuf );
1521
-	return rc;
1522
-}
1523
-
1524
-/**
1525
- * Handle stream connection closure
1526
- *
1527
- * @v iscsi		iSCSI session
1528
- * @v rc		Reason for close
1529
- *
1530
- */
1531
-static void iscsi_socket_close ( struct iscsi_session *iscsi, int rc ) {
1532
-
1533
-	/* Even a graceful close counts as an error for iSCSI */
1534
-	if ( ! rc )
1535
-		rc = -ECONNRESET;
1536 1596
 
1537
-	/* Close session cleanly */
1538
-	iscsi_close_connection ( iscsi, rc );
1597
+	/* Destroy session on error */
1598
+	if ( rc != 0 )
1599
+		iscsi_close ( iscsi, rc );
1539 1600
 
1540
-	/* Retry connection if within the retry limit, otherwise fail */
1541
-	if ( ++iscsi->retry_count <= ISCSI_MAX_RETRIES ) {
1542
-		DBGC ( iscsi, "iSCSI %p retrying connection (retry #%d)\n",
1543
-		       iscsi, iscsi->retry_count );
1544
-		if ( ( rc = iscsi_open_connection ( iscsi ) ) != 0 ) {
1545
-			DBGC ( iscsi, "iSCSI %p could not reconnect: %s\n",
1546
-			       iscsi, strerror ( rc ) );
1547
-			iscsi_scsi_done ( iscsi, rc );
1548
-		}
1549
-	} else {
1550
-		DBGC ( iscsi, "iSCSI %p retry count exceeded\n", iscsi );
1551
-		iscsi->instant_rc = rc;
1552
-		iscsi_scsi_done ( iscsi, rc );
1553
-	}
1601
+	return rc;
1554 1602
 }
1555 1603
 
1556 1604
 /**
@@ -1582,13 +1630,12 @@ static int iscsi_vredirect ( struct iscsi_session *iscsi, int type,
1582 1630
 
1583 1631
 	return xfer_vreopen ( &iscsi->socket, type, args );
1584 1632
 }
1585
-			     
1586 1633
 
1587 1634
 /** iSCSI socket interface operations */
1588 1635
 static struct interface_operation iscsi_socket_operations[] = {
1589 1636
 	INTF_OP ( xfer_deliver, struct iscsi_session *, iscsi_socket_deliver ),
1590 1637
 	INTF_OP ( xfer_vredirect, struct iscsi_session *, iscsi_vredirect ),
1591
-	INTF_OP ( intf_close, struct iscsi_session *, iscsi_socket_close ),
1638
+	INTF_OP ( intf_close, struct iscsi_session *, iscsi_close ),
1592 1639
 };
1593 1640
 
1594 1641
 /** iSCSI socket interface descriptor */
@@ -1602,54 +1649,100 @@ static struct interface_descriptor iscsi_socket_desc =
1602 1649
  */
1603 1650
 
1604 1651
 /**
1605
- * Issue SCSI command
1652
+ * Check iSCSI flow-control window
1606 1653
  *
1607
- * @v scsi		SCSI device
1608
- * @v command		SCSI command
1609
- * @ret rc		Return status code
1654
+ * @v iscsi		iSCSI session
1655
+ * @ret len		Length of window
1610 1656
  */
1611
-static int iscsi_command ( struct scsi_device *scsi,
1612
-			   struct scsi_command *command ) {
1613
-	struct iscsi_session *iscsi =
1614
-		container_of ( scsi->backend, struct iscsi_session, refcnt );
1615
-	int rc;
1657
+static size_t iscsi_scsi_window ( struct iscsi_session *iscsi ) {
1616 1658
 
1617
-	/* Abort immediately if we have a recorded permanent failure */
1618
-	if ( iscsi->instant_rc )
1619
-		return iscsi->instant_rc;
1659
+	if ( ( ( iscsi->status & ISCSI_STATUS_PHASE_MASK ) ==
1660
+	       ISCSI_STATUS_FULL_FEATURE_PHASE ) &&
1661
+	     ( iscsi->command == NULL ) ) {
1662
+		/* We cannot handle concurrent commands */
1663
+		return 1;
1664
+	} else {
1665
+		return 0;
1666
+	}
1667
+}
1620 1668
 
1621
-	/* Record SCSI command */
1622
-	iscsi->command = command;
1669
+/**
1670
+ * Issue iSCSI SCSI command
1671
+ *
1672
+ * @v iscsi		iSCSI session
1673
+ * @v parent		Parent interface
1674
+ * @v command		SCSI command
1675
+ * @ret tag		Command tag, or negative error
1676
+ */
1677
+static int iscsi_scsi_command ( struct iscsi_session *iscsi,
1678
+				struct interface *parent,
1679
+				struct scsi_cmd *command ) {
1623 1680
 
1624
-	/* Issue command or open connection as appropriate */
1625
-	if ( iscsi->status ) {
1626
-		iscsi_start_command ( iscsi );
1627
-	} else {
1628
-		if ( ( rc = iscsi_open_connection ( iscsi ) ) != 0 ) {
1629
-			iscsi->command = NULL;
1630
-			return rc;
1631
-		}
1681
+	/* This iSCSI implementation cannot handle multiple concurrent
1682
+	 * commands or commands arriving before login is complete.
1683
+	 */
1684
+	if ( iscsi_scsi_window ( iscsi ) == 0 ) {
1685
+		DBGC ( iscsi, "iSCSI %p cannot handle concurrent commands\n",
1686
+		       iscsi );
1687
+		return -EOPNOTSUPP;
1632 1688
 	}
1633 1689
 
1634
-	return 0;
1690
+	/* Store command */
1691
+	iscsi->command = malloc ( sizeof ( *command ) );
1692
+	if ( ! iscsi->command )
1693
+		return -ENOMEM;
1694
+	memcpy ( iscsi->command, command, sizeof ( *command ) );
1695
+
1696
+	/* Assign new ITT */
1697
+	iscsi_new_itt ( iscsi );
1698
+
1699
+	/* Start sending command */
1700
+	iscsi_start_command ( iscsi );
1701
+
1702
+	/* Attach to parent interface and return */
1703
+	intf_plug_plug ( &iscsi->data, parent );
1704
+	return iscsi->itt;
1635 1705
 }
1636 1706
 
1707
+/** iSCSI SCSI command-issuing interface operations */
1708
+static struct interface_operation iscsi_control_op[] = {
1709
+	INTF_OP ( scsi_command, struct iscsi_session *, iscsi_scsi_command ),
1710
+	INTF_OP ( xfer_window, struct iscsi_session *, iscsi_scsi_window ),
1711
+	INTF_OP ( intf_close, struct iscsi_session *, iscsi_close ),
1712
+	INTF_OP ( acpi_describe, struct iscsi_session *, ibft_describe ),
1713
+};
1714
+
1715
+/** iSCSI SCSI command-issuing interface descriptor */
1716
+static struct interface_descriptor iscsi_control_desc =
1717
+	INTF_DESC ( struct iscsi_session, control, iscsi_control_op );
1718
+
1637 1719
 /**
1638
- * Shut down iSCSI interface
1720
+ * Close iSCSI command
1639 1721
  *
1640
- * @v scsi		SCSI device
1722
+ * @v iscsi		iSCSI session
1723
+ * @v rc		Reason for close
1641 1724
  */
1642
-void iscsi_detach ( struct scsi_device *scsi ) {
1643
-	struct iscsi_session *iscsi =
1644
-		container_of ( scsi->backend, struct iscsi_session, refcnt );
1725
+static void iscsi_command_close ( struct iscsi_session *iscsi, int rc ) {
1645 1726
 
1646
-	iscsi_close_connection ( iscsi, 0 );
1647
-	process_del ( &iscsi->process );
1648
-	scsi->command = scsi_detached_command;
1649
-	ref_put ( scsi->backend );
1650
-	scsi->backend = NULL;
1727
+	/* Restart interface */
1728
+	intf_restart ( &iscsi->data, rc );
1729
+
1730
+	/* Treat unsolicited command closures mid-command as fatal,
1731
+	 * because we have no code to handle partially-completed PDUs.
1732
+	 */
1733
+	if ( iscsi->command != NULL )
1734
+		iscsi_close ( iscsi, ( ( rc == 0 ) ? -ECANCELED : rc ) );
1651 1735
 }
1652 1736
 
1737
+/** iSCSI SCSI command interface operations */
1738
+static struct interface_operation iscsi_data_op[] = {
1739
+	INTF_OP ( intf_close, struct iscsi_session *, iscsi_command_close ),
1740
+};
1741
+
1742
+/** iSCSI SCSI command interface descriptor */
1743
+static struct interface_descriptor iscsi_data_desc =
1744
+	INTF_DESC ( struct iscsi_session, data, iscsi_data_op );
1745
+
1653 1746
 /****************************************************************************
1654 1747
  *
1655 1748
  * Instantiator
@@ -1658,8 +1751,7 @@ void iscsi_detach ( struct scsi_device *scsi ) {
1658 1751
 
1659 1752
 /** iSCSI root path components (as per RFC4173) */
1660 1753
 enum iscsi_root_path_component {
1661
-	RP_LITERAL = 0,
1662
-	RP_SERVERNAME,
1754
+	RP_SERVERNAME = 0,
1663 1755
 	RP_PROTOCOL,
1664 1756
 	RP_PORT,
1665 1757
 	RP_LUN,
@@ -1779,60 +1871,95 @@ static int iscsi_set_auth ( struct iscsi_session *iscsi,
1779 1871
 }
1780 1872
 
1781 1873
 /**
1782
- * Attach iSCSI interface
1874
+ * Open iSCSI URI
1783 1875
  *
1784
- * @v scsi		SCSI device
1785
- * @v root_path		iSCSI root path (as per RFC4173)
1876
+ * @v parent		Parent interface
1877
+ * @v uri		URI
1786 1878
  * @ret rc		Return status code
1787 1879
  */
1788
-int iscsi_attach ( struct scsi_device *scsi, const char *root_path ) {
1880
+static int iscsi_open ( struct interface *parent, struct uri *uri ) {
1789 1881
 	struct iscsi_session *iscsi;
1790 1882
 	int rc;
1791 1883
 
1884
+	/* Sanity check */
1885
+	if ( ! uri->opaque ) {
1886
+		rc = -EINVAL;
1887
+		goto err_sanity_uri;
1888
+	}
1889
+
1792 1890
 	/* Allocate and initialise structure */
1793 1891
 	iscsi = zalloc ( sizeof ( *iscsi ) );
1794
-	if ( ! iscsi )
1795
-		return -ENOMEM;
1892
+	if ( ! iscsi ) {
1893
+		rc = -ENOMEM;
1894
+		goto err_zalloc;
1895
+	}
1796 1896
 	ref_init ( &iscsi->refcnt, iscsi_free );
1897
+	intf_init ( &iscsi->control, &iscsi_control_desc, &iscsi->refcnt );
1898
+	intf_init ( &iscsi->data, &iscsi_data_desc, &iscsi->refcnt );
1797 1899
 	intf_init ( &iscsi->socket, &iscsi_socket_desc, &iscsi->refcnt );
1798
-	process_init ( &iscsi->process, iscsi_tx_step, &iscsi->refcnt );
1900
+	process_init_stopped ( &iscsi->process, iscsi_tx_step,
1901
+			       &iscsi->refcnt );
1799 1902
 
1800 1903
 	/* Parse root path */
1801
-	if ( ( rc = iscsi_parse_root_path ( iscsi, root_path ) ) != 0 )
1802
-		goto err;
1904
+	if ( ( rc = iscsi_parse_root_path ( iscsi, uri->opaque ) ) != 0 )
1905
+		goto err_parse_root_path;
1803 1906
 	/* Set fields not specified by root path */
1804 1907
 	if ( ( rc = iscsi_set_auth ( iscsi,
1805 1908
 				     iscsi_initiator_username,
1806 1909
 				     iscsi_initiator_password,
1807 1910
 				     iscsi_target_username,
1808 1911
 				     iscsi_target_password ) ) != 0 )
1809
-		goto err;
1912
+		goto err_set_auth;
1810 1913
 
1811 1914
 	/* Sanity checks */
1812 1915
 	if ( ! iscsi->target_address ) {
1813 1916
 		DBGC ( iscsi, "iSCSI %p does not yet support discovery\n",
1814 1917
 		       iscsi );
1815 1918
 		rc = -ENOTSUP_DISCOVERY;
1816
-		goto err;
1919
+		goto err_sanity_address;
1817 1920
 	}
1818 1921
 	if ( ! iscsi->target_iqn ) {
1819 1922
 		DBGC ( iscsi, "iSCSI %p no target address supplied in %s\n",
1820
-		       iscsi, root_path );
1923
+		       iscsi, uri->opaque );
1821 1924
 		rc = -EINVAL;
1822
-		goto err;
1925
+		goto err_sanity_iqn;
1823 1926
 	}
1824 1927
 
1825
-	/* Attach parent interface, mortalise self, and return */
1826
-	scsi->backend = ref_get ( &iscsi->refcnt );
1827
-	scsi->command = iscsi_command;
1928
+	/* Open socket */
1929
+	if ( ( rc = iscsi_open_connection ( iscsi ) ) != 0 )
1930
+		goto err_open_connection;
1931
+
1932
+	/* Attach SCSI device to parent interface */
1933
+	if ( ( rc = scsi_open ( parent, &iscsi->control,
1934
+				&iscsi->lun ) ) != 0 ) {
1935
+		DBGC ( iscsi, "iSCSI %p could not create SCSI device: %s\n",
1936
+		       iscsi, strerror ( rc ) );
1937
+		goto err_scsi_open;
1938
+	}
1939
+
1940
+	/* Mortalise self, and return */
1828 1941
 	ref_put ( &iscsi->refcnt );
1829 1942
 	return 0;
1830 1943
 	
1831
- err:
1944
+ err_scsi_open:
1945
+ err_open_connection:
1946
+ err_sanity_iqn:
1947
+ err_sanity_address:
1948
+ err_set_auth:
1949
+ err_parse_root_path:
1950
+	iscsi_close ( iscsi, rc );
1832 1951
 	ref_put ( &iscsi->refcnt );
1952
+ err_zalloc:
1953
+ err_sanity_uri:
1833 1954
 	return rc;
1834 1955
 }
1835 1956
 
1957
+/** iSCSI URI opener */
1958
+struct uri_opener iscsi_uri_opener __uri_opener = {
1959
+	.scheme = "iscsi",
1960
+	.open = iscsi_open,
1961
+};
1962
+
1836 1963
 /****************************************************************************
1837 1964
  *
1838 1965
  * Settings

+ 62
- 8
src/usr/autoboot.c Näytä tiedosto

@@ -27,6 +27,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
27 27
 #include <ipxe/image.h>
28 28
 #include <ipxe/sanboot.h>
29 29
 #include <ipxe/uri.h>
30
+#include <ipxe/init.h>
30 31
 #include <usr/ifmgmt.h>
31 32
 #include <usr/route.h>
32 33
 #include <usr/dhcpmgmt.h>
@@ -109,6 +110,14 @@ int boot_next_server_and_filename ( struct in_addr next_server,
109 110
 	return rc;
110 111
 }
111 112
 
113
+/** The "keep-san" setting */
114
+struct setting keep_san_setting __setting = {
115
+	.name = "keep-san",
116
+	.description = "Preserve SAN connection",
117
+	.tag = DHCP_EB_KEEP_SAN,
118
+	.type = &setting_type_int8,
119
+};
120
+
112 121
 /**
113 122
  * Boot using root path
114 123
  *
@@ -116,17 +125,62 @@ int boot_next_server_and_filename ( struct in_addr next_server,
116 125
  * @ret rc		Return status code
117 126
  */
118 127
 int boot_root_path ( const char *root_path ) {
119
-	struct sanboot_protocol *sanboot;
128
+	struct uri *uri;
129
+	int drive;
130
+	int rc;
120 131
 
121
-	/* Quick hack */
122
-	for_each_table_entry ( sanboot, SANBOOT_PROTOCOLS ) {
123
-		if ( strncmp ( root_path, sanboot->prefix,
124
-			       strlen ( sanboot->prefix ) ) == 0 ) {
125
-			return sanboot->boot ( root_path );
126
-		}
132
+	/* Parse URI */
133
+	uri = parse_uri ( root_path );
134
+	if ( ! uri ) {
135
+		printf ( "Could not parse \"%s\"\n", root_path );
136
+		rc = -ENOMEM;
137
+		goto err_parse_uri;
127 138
 	}
128 139
 
129
-	return -ENOTSUP;
140
+	/* Hook SAN device */
141
+	if ( ( drive = san_hook ( uri, 0 ) ) < 0 ) {
142
+		rc = drive;
143
+		printf ( "Could not open SAN device: %s\n",
144
+			 strerror ( rc ) );
145
+		goto err_open;
146
+	}
147
+	printf ( "Registered as SAN device %#02x\n", drive );
148
+
149
+	/* Describe SAN device */
150
+	if ( ( rc = san_describe ( drive ) ) != 0 ) {
151
+		printf ( "Could not describe SAN device %#02x: %s\n",
152
+			 drive, strerror ( rc ) );
153
+		goto err_describe;
154
+	}
155
+
156
+	printf ( "Booting from SAN device %#02x\n", drive );
157
+	rc = san_boot ( drive );
158
+	printf ( "Boot from SAN device %#02x failed: %s\n",
159
+		 drive, strerror ( rc ) );
160
+
161
+	/* Leave drive registered, if instructed to do so */
162
+	if ( fetch_intz_setting ( NULL, &keep_san_setting ) != 0 ) {
163
+		printf ( "Preserving connection to SAN device %#02x\n",
164
+			 drive );
165
+		shutdown_exit_flags |= SHUTDOWN_KEEP_DEVICES;
166
+		goto err_keep_san;
167
+	}
168
+
169
+	/* Unhook SAN deivce */
170
+	printf ( "Unregistering SAN device %#02x\n", drive );
171
+	san_unhook ( drive );
172
+
173
+	/* Drop URI reference */
174
+	uri_put ( uri );
175
+
176
+	return 0;
177
+
178
+ err_keep_san:
179
+ err_describe:
180
+ err_open:
181
+	uri_put ( uri );
182
+ err_parse_uri:
183
+	return rc;
130 184
 }
131 185
 
132 186
 /**

Loading…
Peruuta
Tallenna