diff options
author | Michael Brown <mcb30@ipxe.org> | 2020-10-20 14:48:29 +0100 |
---|---|---|
committer | Michael Brown <mcb30@ipxe.org> | 2020-10-20 15:05:37 +0100 |
commit | e6f9054d13bd9bc95720ca3e8cf6c4dcf4eae018 (patch) | |
tree | 31502aa34471a294cc0707faa6aaee2a69074635 | |
parent | 334f0074b1f50d522a701f79faf28dadbdc28362 (diff) | |
download | ipxe-e6f9054d13bd9bc95720ca3e8cf6c4dcf4eae018.tar.gz |
[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.h | 3 | ||||
-rw-r--r-- | src/interface/efi/efi_path.c | 70 | ||||
-rw-r--r-- | src/net/tcp/iscsi.c | 2 |
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 3921fcee2..370197601 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 8636c965b..3c14a2ee6 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 3a44b90f0..e36d5619d 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 */ |