|
@@ -29,6 +29,8 @@
|
29
|
29
|
#include <gpxe/efi/Protocol/DriverBinding.h>
|
30
|
30
|
#include <gpxe/efi/Protocol/PciIo.h>
|
31
|
31
|
#include <gpxe/efi/Protocol/SimpleNetwork.h>
|
|
32
|
+#include <gpxe/efi/Protocol/ComponentName2.h>
|
|
33
|
+#include <config/general.h>
|
32
|
34
|
|
33
|
35
|
/** @file
|
34
|
36
|
*
|
|
@@ -40,6 +42,8 @@
|
40
|
42
|
struct efi_snp_device {
|
41
|
43
|
/** The underlying gPXE network device */
|
42
|
44
|
struct net_device *netdev;
|
|
45
|
+ /** EFI device handle */
|
|
46
|
+ EFI_HANDLE handle;
|
43
|
47
|
/** The SNP structure itself */
|
44
|
48
|
EFI_SIMPLE_NETWORK_PROTOCOL snp;
|
45
|
49
|
/** The SNP "mode" (parameters) */
|
|
@@ -58,6 +62,14 @@ struct efi_snp_device {
|
58
|
62
|
unsigned int rx_count_interrupts;
|
59
|
63
|
/** Outstanding RX packet count (via WaitForPacket event) */
|
60
|
64
|
unsigned int rx_count_events;
|
|
65
|
+ /** Device name */
|
|
66
|
+ wchar_t name[ sizeof ( ( ( struct net_device * ) NULL )->name ) ];
|
|
67
|
+ /** The device path
|
|
68
|
+ *
|
|
69
|
+ * This field is variable in size and must appear at the end
|
|
70
|
+ * of the structure.
|
|
71
|
+ */
|
|
72
|
+ EFI_DEVICE_PATH_PROTOCOL path;
|
61
|
73
|
};
|
62
|
74
|
|
63
|
75
|
/** EFI simple network protocol GUID */
|
|
@@ -68,6 +80,14 @@ static EFI_GUID efi_simple_network_protocol_guid
|
68
|
80
|
static EFI_GUID efi_driver_binding_protocol_guid
|
69
|
81
|
= EFI_DRIVER_BINDING_PROTOCOL_GUID;
|
70
|
82
|
|
|
83
|
+/** EFI component name protocol GUID */
|
|
84
|
+static EFI_GUID efi_component_name2_protocol_guid
|
|
85
|
+ = EFI_COMPONENT_NAME2_PROTOCOL_GUID;
|
|
86
|
+
|
|
87
|
+/** EFI device path protocol GUID */
|
|
88
|
+static EFI_GUID efi_device_path_protocol_guid
|
|
89
|
+ = EFI_DEVICE_PATH_PROTOCOL_GUID;
|
|
90
|
+
|
71
|
91
|
/** EFI PCI I/O protocol GUID */
|
72
|
92
|
static EFI_GUID efi_pci_io_protocol_guid
|
73
|
93
|
= EFI_PCI_IO_PROTOCOL_GUID;
|
|
@@ -784,7 +804,7 @@ efi_snp_snpdev ( EFI_DRIVER_BINDING_PROTOCOL *driver, EFI_HANDLE device ) {
|
784
|
804
|
EFI_SIMPLE_NETWORK_PROTOCOL *snp;
|
785
|
805
|
void *interface;
|
786
|
806
|
} u;
|
787
|
|
- struct efi_snp_device *snpdev;
|
|
807
|
+ struct efi_snp_device *snpdev = NULL;
|
788
|
808
|
EFI_STATUS efirc;
|
789
|
809
|
|
790
|
810
|
if ( ( efirc = bs->OpenProtocol ( device,
|
|
@@ -795,12 +815,16 @@ efi_snp_snpdev ( EFI_DRIVER_BINDING_PROTOCOL *driver, EFI_HANDLE device ) {
|
795
|
815
|
EFI_OPEN_PROTOCOL_GET_PROTOCOL))!=0){
|
796
|
816
|
DBGC ( driver, "SNPDRV %p device %p could not locate SNP: "
|
797
|
817
|
"%s\n", driver, device, efi_strerror ( efirc ) );
|
798
|
|
- return NULL;
|
|
818
|
+ goto err_no_snp;
|
799
|
819
|
}
|
800
|
820
|
|
801
|
821
|
snpdev = container_of ( u.snp, struct efi_snp_device, snp );
|
802
|
822
|
DBGCP ( driver, "SNPDRV %p device %p is SNPDEV %p\n",
|
803
|
823
|
driver, device, snpdev );
|
|
824
|
+
|
|
825
|
+ bs->CloseProtocol ( device, &efi_simple_network_protocol_guid,
|
|
826
|
+ driver->DriverBindingHandle, device );
|
|
827
|
+ err_no_snp:
|
804
|
828
|
return snpdev;
|
805
|
829
|
}
|
806
|
830
|
|
|
@@ -838,15 +862,41 @@ efi_snp_driver_start ( EFI_DRIVER_BINDING_PROTOCOL *driver,
|
838
|
862
|
EFI_HANDLE device,
|
839
|
863
|
EFI_DEVICE_PATH_PROTOCOL *child ) {
|
840
|
864
|
EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
|
|
865
|
+ EFI_DEVICE_PATH_PROTOCOL *path;
|
|
866
|
+ EFI_DEVICE_PATH_PROTOCOL *subpath;
|
|
867
|
+ MAC_ADDR_DEVICE_PATH *macpath;
|
841
|
868
|
struct efi_snp_device *snpdev;
|
842
|
869
|
struct net_device *netdev;
|
|
870
|
+ size_t subpath_len;
|
|
871
|
+ size_t path_prefix_len = 0;
|
|
872
|
+ unsigned int i;
|
843
|
873
|
EFI_STATUS efirc;
|
844
|
874
|
|
845
|
875
|
DBGCP ( driver, "SNPDRV %p DRIVER_START %p (%p)\n",
|
846
|
876
|
driver, device, child );
|
847
|
877
|
|
|
878
|
+ /* Determine device path prefix length */
|
|
879
|
+ if ( ( efirc = bs->OpenProtocol ( device,
|
|
880
|
+ &efi_device_path_protocol_guid,
|
|
881
|
+ ( void * ) &path,
|
|
882
|
+ driver->DriverBindingHandle,
|
|
883
|
+ device,
|
|
884
|
+ EFI_OPEN_PROTOCOL_BY_DRIVER )) !=0 ){
|
|
885
|
+ DBGCP ( driver, "SNPDRV %p device %p has no device path\n",
|
|
886
|
+ driver, device );
|
|
887
|
+ goto err_no_device_path;
|
|
888
|
+ }
|
|
889
|
+ subpath = path;
|
|
890
|
+ while ( subpath->Type != END_DEVICE_PATH_TYPE ) {
|
|
891
|
+ subpath_len = ( ( subpath->Length[1] << 8 ) |
|
|
892
|
+ subpath->Length[0] );
|
|
893
|
+ path_prefix_len += subpath_len;
|
|
894
|
+ subpath = ( ( ( void * ) subpath ) + subpath_len );
|
|
895
|
+ }
|
|
896
|
+
|
848
|
897
|
/* Allocate the SNP device */
|
849
|
|
- snpdev = zalloc ( sizeof ( *snpdev ) );
|
|
898
|
+ snpdev = zalloc ( sizeof ( *snpdev ) + path_prefix_len +
|
|
899
|
+ sizeof ( *macpath ) );
|
850
|
900
|
if ( ! snpdev ) {
|
851
|
901
|
efirc = EFI_OUT_OF_RESOURCES;
|
852
|
902
|
goto err_alloc_snp;
|
|
@@ -886,22 +936,50 @@ efi_snp_driver_start ( EFI_DRIVER_BINDING_PROTOCOL *driver,
|
886
|
936
|
snpdev->mode.State = EfiSimpleNetworkStopped;
|
887
|
937
|
efi_snp_set_mode ( snpdev );
|
888
|
938
|
|
|
939
|
+ /* Populate the device name */
|
|
940
|
+ for ( i = 0 ; i < sizeof ( netdev->name ) ; i++ ) {
|
|
941
|
+ /* Damn Unicode names */
|
|
942
|
+ assert ( i < ( sizeof ( snpdev->name ) /
|
|
943
|
+ sizeof ( snpdev->name[0] ) ) );
|
|
944
|
+ snpdev->name[i] = netdev->name[i];
|
|
945
|
+ }
|
|
946
|
+
|
|
947
|
+ /* Populate the device path */
|
|
948
|
+ memcpy ( &snpdev->path, path, path_prefix_len );
|
|
949
|
+ macpath = ( ( ( void * ) &snpdev->path ) + path_prefix_len );
|
|
950
|
+ subpath = ( ( void * ) ( macpath + 1 ) );
|
|
951
|
+ memset ( macpath, 0, sizeof ( *macpath ) );
|
|
952
|
+ macpath->Header.Type = MESSAGING_DEVICE_PATH;
|
|
953
|
+ macpath->Header.SubType = MSG_MAC_ADDR_DP;
|
|
954
|
+ macpath->Header.Length[0] = sizeof ( *macpath );
|
|
955
|
+ memcpy ( &macpath->MacAddress, netdev->ll_addr,
|
|
956
|
+ sizeof ( macpath->MacAddress ) );
|
|
957
|
+ macpath->IfType = ntohs ( netdev->ll_protocol->ll_proto );
|
|
958
|
+ memset ( subpath, 0, sizeof ( *subpath ) );
|
|
959
|
+ subpath->Type = END_DEVICE_PATH_TYPE;
|
|
960
|
+ subpath->SubType = END_ENTIRE_DEVICE_PATH_SUBTYPE;
|
|
961
|
+ subpath->Length[0] = sizeof ( *subpath );
|
|
962
|
+
|
889
|
963
|
/* Install the SNP */
|
890
|
|
- if ( ( efirc = bs->InstallProtocolInterface ( &device,
|
891
|
|
- &efi_simple_network_protocol_guid,
|
892
|
|
- EFI_NATIVE_INTERFACE, &snpdev->snp ) ) != 0 ) {
|
893
|
|
- DBGC ( snpdev, "SNPDEV %p could not install protocol: %s\n",
|
894
|
|
- snpdev, efi_strerror ( efirc ) );
|
|
964
|
+ if ( ( efirc = bs->InstallMultipleProtocolInterfaces (
|
|
965
|
+ &snpdev->handle,
|
|
966
|
+ &efi_simple_network_protocol_guid, &snpdev->snp,
|
|
967
|
+ &efi_device_path_protocol_guid, &snpdev->path,
|
|
968
|
+ NULL ) ) != 0 ) {
|
|
969
|
+ DBGC ( snpdev, "SNPDEV %p could not install protocols: "
|
|
970
|
+ "%s\n", snpdev, efi_strerror ( efirc ) );
|
895
|
971
|
goto err_install_protocol_interface;
|
896
|
972
|
}
|
897
|
973
|
|
898
|
|
- DBGC ( snpdev, "SNPDEV %p installed for %s on device %p\n",
|
899
|
|
- snpdev, netdev->name, device );
|
|
974
|
+ DBGC ( snpdev, "SNPDEV %p installed for %s as device %p\n",
|
|
975
|
+ snpdev, netdev->name, snpdev->handle );
|
900
|
976
|
return 0;
|
901
|
977
|
|
902
|
|
- bs->UninstallProtocolInterface ( device,
|
903
|
|
- &efi_simple_network_protocol_guid,
|
904
|
|
- &snpdev->snp );
|
|
978
|
+ bs->UninstallMultipleProtocolInterfaces (
|
|
979
|
+ snpdev->handle,
|
|
980
|
+ &efi_simple_network_protocol_guid, &snpdev->snp,
|
|
981
|
+ &efi_device_path_protocol_guid, &snpdev->path,
|
|
982
|
+ NULL );
|
905
|
983
|
err_install_protocol_interface:
|
906
|
984
|
bs->CloseEvent ( snpdev->snp.WaitForPacket );
|
907
|
985
|
err_create_event:
|
|
@@ -910,6 +988,9 @@ efi_snp_driver_start ( EFI_DRIVER_BINDING_PROTOCOL *driver,
|
910
|
988
|
err_no_netdev:
|
911
|
989
|
free ( snpdev );
|
912
|
990
|
err_alloc_snp:
|
|
991
|
+ bs->CloseProtocol ( device, &efi_device_path_protocol_guid,
|
|
992
|
+ driver->DriverBindingHandle, device );
|
|
993
|
+ err_no_device_path:
|
913
|
994
|
return efirc;
|
914
|
995
|
}
|
915
|
996
|
|
|
@@ -942,12 +1023,16 @@ efi_snp_driver_stop ( EFI_DRIVER_BINDING_PROTOCOL *driver,
|
942
|
1023
|
}
|
943
|
1024
|
|
944
|
1025
|
/* Uninstall the SNP */
|
945
|
|
- bs->UninstallProtocolInterface ( device,
|
946
|
|
- &efi_simple_network_protocol_guid,
|
947
|
|
- &snpdev->snp );
|
|
1026
|
+ bs->UninstallMultipleProtocolInterfaces (
|
|
1027
|
+ snpdev->handle,
|
|
1028
|
+ &efi_simple_network_protocol_guid, &snpdev->snp,
|
|
1029
|
+ &efi_device_path_protocol_guid, &snpdev->path,
|
|
1030
|
+ NULL );
|
948
|
1031
|
bs->CloseEvent ( snpdev->snp.WaitForPacket );
|
949
|
1032
|
netdev_put ( snpdev->netdev );
|
950
|
1033
|
free ( snpdev );
|
|
1034
|
+ bs->CloseProtocol ( device, &efi_device_path_protocol_guid,
|
|
1035
|
+ driver->DriverBindingHandle, device );
|
951
|
1036
|
return 0;
|
952
|
1037
|
}
|
953
|
1038
|
|
|
@@ -961,6 +1046,50 @@ static EFI_DRIVER_BINDING_PROTOCOL efi_snp_binding = {
|
961
|
1046
|
NULL
|
962
|
1047
|
};
|
963
|
1048
|
|
|
1049
|
+/**
|
|
1050
|
+ * Look up driver name
|
|
1051
|
+ *
|
|
1052
|
+ * @v wtf Component name protocol
|
|
1053
|
+ * @v language Language to use
|
|
1054
|
+ * @v driver_name Driver name to fill in
|
|
1055
|
+ * @ret efirc EFI status code
|
|
1056
|
+ */
|
|
1057
|
+static EFI_STATUS EFIAPI
|
|
1058
|
+efi_snp_get_driver_name ( EFI_COMPONENT_NAME2_PROTOCOL *wtf __unused,
|
|
1059
|
+ CHAR8 *language __unused, CHAR16 **driver_name ) {
|
|
1060
|
+
|
|
1061
|
+ *driver_name = L"" PRODUCT_SHORT_NAME " Driver";
|
|
1062
|
+ return 0;
|
|
1063
|
+}
|
|
1064
|
+
|
|
1065
|
+/**
|
|
1066
|
+ * Look up controller name
|
|
1067
|
+ *
|
|
1068
|
+ * @v wtf Component name protocol
|
|
1069
|
+ * @v device Device
|
|
1070
|
+ * @v child Child device, or NULL
|
|
1071
|
+ * @v language Language to use
|
|
1072
|
+ * @v driver_name Device name to fill in
|
|
1073
|
+ * @ret efirc EFI status code
|
|
1074
|
+ */
|
|
1075
|
+static EFI_STATUS EFIAPI
|
|
1076
|
+efi_snp_get_controller_name ( EFI_COMPONENT_NAME2_PROTOCOL *wtf __unused,
|
|
1077
|
+ EFI_HANDLE device __unused,
|
|
1078
|
+ EFI_HANDLE child __unused,
|
|
1079
|
+ CHAR8 *language __unused,
|
|
1080
|
+ CHAR16 **controller_name __unused ) {
|
|
1081
|
+
|
|
1082
|
+ /* Just let EFI use the default Device Path Name */
|
|
1083
|
+ return EFI_UNSUPPORTED;
|
|
1084
|
+}
|
|
1085
|
+
|
|
1086
|
+/** EFI SNP component name protocol */
|
|
1087
|
+static EFI_COMPONENT_NAME2_PROTOCOL efi_snp_name = {
|
|
1088
|
+ efi_snp_get_driver_name,
|
|
1089
|
+ efi_snp_get_controller_name,
|
|
1090
|
+ "en"
|
|
1091
|
+};
|
|
1092
|
+
|
964
|
1093
|
/**
|
965
|
1094
|
* Install EFI SNP driver
|
966
|
1095
|
*
|
|
@@ -972,12 +1101,12 @@ int efi_snp_install ( void ) {
|
972
|
1101
|
EFI_STATUS efirc;
|
973
|
1102
|
|
974
|
1103
|
driver->ImageHandle = efi_image_handle;
|
975
|
|
- if ( ( efirc = bs->InstallProtocolInterface (
|
976
|
|
- &driver->DriverBindingHandle,
|
977
|
|
- &efi_driver_binding_protocol_guid,
|
978
|
|
- EFI_NATIVE_INTERFACE,
|
979
|
|
- driver ) ) != 0 ) {
|
980
|
|
- DBGC ( driver, "SNPDRV %p could not install driver binding: "
|
|
1104
|
+ if ( ( efirc = bs->InstallMultipleProtocolInterfaces (
|
|
1105
|
+ &driver->DriverBindingHandle,
|
|
1106
|
+ &efi_driver_binding_protocol_guid, driver,
|
|
1107
|
+ &efi_component_name2_protocol_guid, &efi_snp_name,
|
|
1108
|
+ NULL ) ) != 0 ) {
|
|
1109
|
+ DBGC ( driver, "SNPDRV %p could not install protocols: "
|
981
|
1110
|
"%s\n", driver, efi_strerror ( efirc ) );
|
982
|
1111
|
return EFIRC_TO_RC ( efirc );
|
983
|
1112
|
}
|