aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Brown <mcb30@ipxe.org>2020-10-20 14:48:29 +0100
committerMichael Brown <mcb30@ipxe.org>2020-10-20 15:05:37 +0100
commite6f9054d13bd9bc95720ca3e8cf6c4dcf4eae018 (patch)
tree31502aa34471a294cc0707faa6aaee2a69074635
parent334f0074b1f50d522a701f79faf28dadbdc28362 (diff)
downloadipxe-e6f9054d13bd9bc95720ca3e8cf6c4dcf4eae018.zip
ipxe-e6f9054d13bd9bc95720ca3e8cf6c4dcf4eae018.tar.gz
ipxe-e6f9054d13bd9bc95720ca3e8cf6c4dcf4eae018.tar.bz2
[iscsi] Allow iSCSI device to be described using an EFI device path
Signed-off-by: Michael Brown <mcb30@ipxe.org>
-rw-r--r--src/include/ipxe/efi/efi_path.h3
-rw-r--r--src/interface/efi/efi_path.c70
-rw-r--r--src/net/tcp/iscsi.c2
3 files changed, 75 insertions, 0 deletions
diff --git a/src/include/ipxe/efi/efi_path.h b/src/include/ipxe/efi/efi_path.h
index 3921fce..3701976 100644
--- a/src/include/ipxe/efi/efi_path.h
+++ b/src/include/ipxe/efi/efi_path.h
@@ -15,6 +15,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
struct net_device;
struct uri;
+struct iscsi_session;
struct aoe_device;
struct usb_function;
@@ -25,6 +26,8 @@ extern EFI_DEVICE_PATH_PROTOCOL * efi_paths ( EFI_DEVICE_PATH_PROTOCOL *first,
... );
extern EFI_DEVICE_PATH_PROTOCOL * efi_netdev_path ( struct net_device *netdev );
extern EFI_DEVICE_PATH_PROTOCOL * efi_uri_path ( struct uri *uri );
+extern EFI_DEVICE_PATH_PROTOCOL *
+efi_iscsi_path ( struct iscsi_session *iscsi );
extern EFI_DEVICE_PATH_PROTOCOL * efi_aoe_path ( struct aoe_device *aoedev );
extern EFI_DEVICE_PATH_PROTOCOL * efi_usb_path ( struct usb_function *func );
diff --git a/src/interface/efi/efi_path.c b/src/interface/efi/efi_path.c
index 8636c96..3c14a2e 100644
--- a/src/interface/efi/efi_path.c
+++ b/src/interface/efi/efi_path.c
@@ -23,7 +23,9 @@
#include <byteswap.h>
#include <ipxe/netdevice.h>
#include <ipxe/vlan.h>
+#include <ipxe/tcpip.h>
#include <ipxe/uri.h>
+#include <ipxe/iscsi.h>
#include <ipxe/aoe.h>
#include <ipxe/usb.h>
#include <ipxe/efi/efi.h>
@@ -222,6 +224,74 @@ EFI_DEVICE_PATH_PROTOCOL * efi_uri_path ( struct uri *uri ) {
}
/**
+ * Construct EFI device path for iSCSI device
+ *
+ * @v iscsi iSCSI session
+ * @ret path EFI device path, or NULL on error
+ */
+EFI_DEVICE_PATH_PROTOCOL * efi_iscsi_path ( struct iscsi_session *iscsi ) {
+ struct sockaddr_tcpip *st_target;
+ struct net_device *netdev;
+ EFI_DEVICE_PATH_PROTOCOL *netpath;
+ EFI_DEVICE_PATH_PROTOCOL *path;
+ EFI_DEVICE_PATH_PROTOCOL *end;
+ ISCSI_DEVICE_PATH *iscsipath;
+ char *name;
+ size_t prefix_len;
+ size_t name_len;
+ size_t iscsi_len;
+ size_t len;
+
+ /* Get network device associated with target address */
+ st_target = ( ( struct sockaddr_tcpip * ) &iscsi->target_sockaddr );
+ netdev = tcpip_netdev ( st_target );
+ if ( ! netdev )
+ goto err_netdev;
+
+ /* Get network device path */
+ netpath = efi_netdev_path ( netdev );
+ if ( ! netpath )
+ goto err_netpath;
+
+ /* Calculate device path length */
+ prefix_len = efi_path_len ( netpath );
+ name_len = ( strlen ( iscsi->target_iqn ) + 1 /* NUL */ );
+ iscsi_len = ( sizeof ( *iscsipath ) + name_len );
+ len = ( prefix_len + iscsi_len + sizeof ( *end ) );
+
+ /* Allocate device path */
+ path = zalloc ( len );
+ if ( ! path )
+ goto err_alloc;
+
+ /* Construct device path */
+ memcpy ( path, netpath, prefix_len );
+ iscsipath = ( ( ( void * ) path ) + prefix_len );
+ iscsipath->Header.Type = MESSAGING_DEVICE_PATH;
+ iscsipath->Header.SubType = MSG_ISCSI_DP;
+ iscsipath->Header.Length[0] = iscsi_len;
+ iscsipath->LoginOption = ISCSI_LOGIN_OPTION_AUTHMETHOD_NON;
+ memcpy ( &iscsipath->Lun, &iscsi->lun, sizeof ( iscsipath->Lun ) );
+ name = ( ( ( void * ) iscsipath ) + sizeof ( *iscsipath ) );
+ memcpy ( name, iscsi->target_iqn, name_len );
+ end = ( ( ( void * ) name ) + name_len );
+ end->Type = END_DEVICE_PATH_TYPE;
+ end->SubType = END_ENTIRE_DEVICE_PATH_SUBTYPE;
+ end->Length[0] = sizeof ( *end );
+
+ /* Free temporary paths */
+ free ( netpath );
+
+ return path;
+
+ err_alloc:
+ free ( netpath );
+ err_netpath:
+ err_netdev:
+ return NULL;
+}
+
+/**
* Construct EFI device path for AoE device
*
* @v aoedev AoE device
diff --git a/src/net/tcp/iscsi.c b/src/net/tcp/iscsi.c
index 3a44b90..e36d561 100644
--- a/src/net/tcp/iscsi.c
+++ b/src/net/tcp/iscsi.c
@@ -46,6 +46,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <ipxe/base16.h>
#include <ipxe/base64.h>
#include <ipxe/ibft.h>
+#include <ipxe/efi/efi_path.h>
#include <ipxe/iscsi.h>
/** @file
@@ -1863,6 +1864,7 @@ static struct interface_operation iscsi_control_op[] = {
INTF_OP ( xfer_window, struct iscsi_session *, iscsi_scsi_window ),
INTF_OP ( intf_close, struct iscsi_session *, iscsi_close ),
INTF_OP ( acpi_describe, struct iscsi_session *, iscsi_describe ),
+ EFI_INTF_OP ( efi_describe, struct iscsi_session *, efi_iscsi_path ),
};
/** iSCSI SCSI command-issuing interface descriptor */