]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[fcp] Allow Fibre Channel device to be described using an EFI device path
authorMichael Brown <mcb30@ipxe.org>
Thu, 22 Oct 2020 13:01:27 +0000 (14:01 +0100)
committerMichael Brown <mcb30@ipxe.org>
Thu, 22 Oct 2020 13:16:55 +0000 (14:16 +0100)
Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/include/ipxe/efi/efi_path.h
src/include/ipxe/fcp.h
src/interface/efi/efi_path.c
src/net/fcp.c

index 3701976017bdaa867ab314898ee836a1f5b6ec9d..91a6c255d0c5ee3873af802b7ab7553333172a9a 100644 (file)
@@ -17,6 +17,7 @@ struct net_device;
 struct uri;
 struct iscsi_session;
 struct aoe_device;
+struct fcp_description;
 struct usb_function;
 
 extern EFI_DEVICE_PATH_PROTOCOL *
@@ -29,6 +30,7 @@ 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_fcp_path ( struct fcp_description *desc );
 extern EFI_DEVICE_PATH_PROTOCOL * efi_usb_path ( struct usb_function *func );
 
 extern EFI_DEVICE_PATH_PROTOCOL * efi_describe ( struct interface *interface );
index 853ca13f66cb2b4fcf427a9bd5e03656c764ea41..d86afab4277d2b6478ec170b438e37f2842643d7 100644 (file)
@@ -163,4 +163,12 @@ struct fcp_prli_service_parameters {
 /** Enhanced discovery supported */
 #define FCP_PRLI_ENH_DISC 0x0800
 
+/** An FCP device description */
+struct fcp_description {
+       /** Fibre Channel WWN */
+       struct fc_name wwn;
+       /** SCSI LUN */
+       struct scsi_lun lun;
+};
+
 #endif /* _IPXE_FCP_H */
index 3c14a2ee6c1b15794dc4cd9db529eefbf724c38d..76b1e4daede18af509c02a3f2f84778ce439fac3 100644 (file)
@@ -27,6 +27,7 @@
 #include <ipxe/uri.h>
 #include <ipxe/iscsi.h>
 #include <ipxe/aoe.h>
+#include <ipxe/fcp.h>
 #include <ipxe/usb.h>
 #include <ipxe/efi/efi.h>
 #include <ipxe/efi/efi_driver.h>
@@ -337,6 +338,36 @@ EFI_DEVICE_PATH_PROTOCOL * efi_aoe_path ( struct aoe_device *aoedev ) {
        return NULL;
 }
 
+/**
+ * Construct EFI device path for Fibre Channel device
+ *
+ * @v desc             FCP device description
+ * @ret path           EFI device path, or NULL on error
+ */
+EFI_DEVICE_PATH_PROTOCOL * efi_fcp_path ( struct fcp_description *desc ) {
+       struct {
+               FIBRECHANNELEX_DEVICE_PATH fc;
+               EFI_DEVICE_PATH_PROTOCOL end;
+       } __attribute__ (( packed )) *path;
+
+       /* Allocate device path */
+       path = zalloc ( sizeof ( *path ) );
+       if ( ! path )
+               return NULL;
+
+       /* Construct device path */
+       path->fc.Header.Type = MESSAGING_DEVICE_PATH;
+       path->fc.Header.SubType = MSG_FIBRECHANNELEX_DP;
+       path->fc.Header.Length[0] = sizeof ( path->fc );
+       memcpy ( path->fc.WWN, &desc->wwn, sizeof ( path->fc.WWN ) );
+       memcpy ( path->fc.Lun, &desc->lun, sizeof ( path->fc.Lun ) );
+       path->end.Type = END_DEVICE_PATH_TYPE;
+       path->end.SubType = END_ENTIRE_DEVICE_PATH_SUBTYPE;
+       path->end.Length[0] = sizeof ( path->end );
+
+       return &path->fc.Header;
+}
+
 /**
  * Construct EFI device path for USB function
  *
index d92cfdcf389116cef8ece32f948f7129a5a747de..f78f7bd9bf966b1ba5ff648b46cb669e40f98f30 100644 (file)
@@ -43,6 +43,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
 #include <ipxe/scsi.h>
 #include <ipxe/device.h>
 #include <ipxe/edd.h>
+#include <ipxe/efi/efi_path.h>
 #include <ipxe/fc.h>
 #include <ipxe/fcels.h>
 #include <ipxe/fcp.h>
@@ -158,10 +159,8 @@ struct fcp_device {
        /** List of active commands */
        struct list_head fcpcmds;
 
-       /** Fibre Channel WWN (for boot firmware table) */
-       struct fc_name wwn;
-       /** SCSI LUN (for boot firmware table) */
-       struct scsi_lun lun;
+       /** Device description (for boot firmware table) */
+       struct fcp_description desc;
 };
 
 /** An FCP command */
@@ -864,9 +863,9 @@ static int fcpdev_edd_describe ( struct fcp_device *fcpdev,
        } lun;
 
        type->type = cpu_to_le64 ( EDD_INTF_TYPE_FIBRE );
-       memcpy ( &wwn.fc, &fcpdev->wwn, sizeof ( wwn.fc ) );
+       memcpy ( &wwn.fc, &fcpdev->desc.wwn, sizeof ( wwn.fc ) );
        path->fibre.wwn = be64_to_cpu ( wwn.u64 );
-       memcpy ( &lun.scsi, &fcpdev->lun, sizeof ( lun.scsi ) );
+       memcpy ( &lun.scsi, &fcpdev->desc.lun, sizeof ( lun.scsi ) );
        path->fibre.lun = be64_to_cpu ( lun.u64 );
        return 0;
 }
@@ -893,6 +892,18 @@ static struct device * fcpdev_identify_device ( struct fcp_device *fcpdev ) {
        return identify_device ( &fcpdev->user.ulp->peer->port->transport );
 }
 
+/**
+ * Describe as an EFI device path
+ *
+ * @v fcp              FCP device
+ * @ret path           EFI device path, or NULL on error
+ */
+static EFI_DEVICE_PATH_PROTOCOL *
+fcpdev_efi_describe ( struct fcp_device *fcpdev ) {
+
+       return efi_fcp_path ( &fcpdev->desc );
+}
+
 /** FCP device SCSI interface operations */
 static struct interface_operation fcpdev_scsi_op[] = {
        INTF_OP ( scsi_command, struct fcp_device *, fcpdev_scsi_command ),
@@ -901,6 +912,7 @@ static struct interface_operation fcpdev_scsi_op[] = {
        INTF_OP ( edd_describe, struct fcp_device *, fcpdev_edd_describe ),
        INTF_OP ( identify_device, struct fcp_device *,
                  fcpdev_identify_device ),
+       EFI_INTF_OP ( efi_describe, struct fcp_device *, fcpdev_efi_describe ),
 };
 
 /** FCP device SCSI interface descriptor */
@@ -965,8 +977,8 @@ static int fcpdev_open ( struct interface *parent, struct fc_name *wwn,
        fc_ulp_attach ( ulp, &fcpdev->user );
 
        /* Preserve parameters required for boot firmware table */
-       memcpy ( &fcpdev->wwn, wwn, sizeof ( fcpdev->wwn ) );
-       memcpy ( &fcpdev->lun, lun, sizeof ( fcpdev->lun ) );
+       memcpy ( &fcpdev->desc.wwn, wwn, sizeof ( fcpdev->desc.wwn ) );
+       memcpy ( &fcpdev->desc.lun, lun, sizeof ( fcpdev->desc.lun ) );
 
        /* Attach SCSI device to parent interface */
        if ( ( rc = scsi_open ( parent, &fcpdev->scsi, lun ) ) != 0 ) {