|
@@ -183,7 +183,7 @@ efi_snp_start ( EFI_SIMPLE_NETWORK_PROTOCOL *snp ) {
|
183
|
183
|
struct efi_snp_device *snpdev =
|
184
|
184
|
container_of ( snp, struct efi_snp_device, snp );
|
185
|
185
|
|
186
|
|
- DBGC2 ( snpdev, "SNPDEV %p START\n", snpdev );
|
|
186
|
+ DBGC ( snpdev, "SNPDEV %p START\n", snpdev );
|
187
|
187
|
|
188
|
188
|
/* Fail if net device is currently claimed for use by iPXE */
|
189
|
189
|
if ( efi_snp_claimed )
|
|
@@ -205,7 +205,7 @@ efi_snp_stop ( EFI_SIMPLE_NETWORK_PROTOCOL *snp ) {
|
205
|
205
|
struct efi_snp_device *snpdev =
|
206
|
206
|
container_of ( snp, struct efi_snp_device, snp );
|
207
|
207
|
|
208
|
|
- DBGC2 ( snpdev, "SNPDEV %p STOP\n", snpdev );
|
|
208
|
+ DBGC ( snpdev, "SNPDEV %p STOP\n", snpdev );
|
209
|
209
|
|
210
|
210
|
/* Fail if net device is currently claimed for use by iPXE */
|
211
|
211
|
if ( efi_snp_claimed )
|
|
@@ -213,6 +213,7 @@ efi_snp_stop ( EFI_SIMPLE_NETWORK_PROTOCOL *snp ) {
|
213
|
213
|
|
214
|
214
|
snpdev->started = 0;
|
215
|
215
|
efi_snp_set_state ( snpdev );
|
|
216
|
+
|
216
|
217
|
return 0;
|
217
|
218
|
}
|
218
|
219
|
|
|
@@ -231,9 +232,9 @@ efi_snp_initialize ( EFI_SIMPLE_NETWORK_PROTOCOL *snp,
|
231
|
232
|
container_of ( snp, struct efi_snp_device, snp );
|
232
|
233
|
int rc;
|
233
|
234
|
|
234
|
|
- DBGC2 ( snpdev, "SNPDEV %p INITIALIZE (%ld extra RX, %ld extra TX)\n",
|
235
|
|
- snpdev, ( ( unsigned long ) extra_rx_bufsize ),
|
236
|
|
- ( ( unsigned long ) extra_tx_bufsize ) );
|
|
235
|
+ DBGC ( snpdev, "SNPDEV %p INITIALIZE (%ld extra RX, %ld extra TX)\n",
|
|
236
|
+ snpdev, ( ( unsigned long ) extra_rx_bufsize ),
|
|
237
|
+ ( ( unsigned long ) extra_tx_bufsize ) );
|
237
|
238
|
|
238
|
239
|
/* Fail if net device is currently claimed for use by iPXE */
|
239
|
240
|
if ( efi_snp_claimed )
|
|
@@ -262,8 +263,8 @@ efi_snp_reset ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, BOOLEAN ext_verify ) {
|
262
|
263
|
container_of ( snp, struct efi_snp_device, snp );
|
263
|
264
|
int rc;
|
264
|
265
|
|
265
|
|
- DBGC2 ( snpdev, "SNPDEV %p RESET (%s extended verification)\n",
|
266
|
|
- snpdev, ( ext_verify ? "with" : "without" ) );
|
|
266
|
+ DBGC ( snpdev, "SNPDEV %p RESET (%s extended verification)\n",
|
|
267
|
+ snpdev, ( ext_verify ? "with" : "without" ) );
|
267
|
268
|
|
268
|
269
|
/* Fail if net device is currently claimed for use by iPXE */
|
269
|
270
|
if ( efi_snp_claimed )
|
|
@@ -294,7 +295,7 @@ efi_snp_shutdown ( EFI_SIMPLE_NETWORK_PROTOCOL *snp ) {
|
294
|
295
|
struct efi_snp_device *snpdev =
|
295
|
296
|
container_of ( snp, struct efi_snp_device, snp );
|
296
|
297
|
|
297
|
|
- DBGC2 ( snpdev, "SNPDEV %p SHUTDOWN\n", snpdev );
|
|
298
|
+ DBGC ( snpdev, "SNPDEV %p SHUTDOWN\n", snpdev );
|
298
|
299
|
|
299
|
300
|
/* Fail if net device is currently claimed for use by iPXE */
|
300
|
301
|
if ( efi_snp_claimed )
|
|
@@ -326,9 +327,9 @@ efi_snp_receive_filters ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, UINT32 enable,
|
326
|
327
|
container_of ( snp, struct efi_snp_device, snp );
|
327
|
328
|
unsigned int i;
|
328
|
329
|
|
329
|
|
- DBGC2 ( snpdev, "SNPDEV %p RECEIVE_FILTERS %08x&~%08x%s %ld mcast\n",
|
330
|
|
- snpdev, enable, disable, ( mcast_reset ? " reset" : "" ),
|
331
|
|
- ( ( unsigned long ) mcast_count ) );
|
|
330
|
+ DBGC ( snpdev, "SNPDEV %p RECEIVE_FILTERS %08x&~%08x%s %ld mcast\n",
|
|
331
|
+ snpdev, enable, disable, ( mcast_reset ? " reset" : "" ),
|
|
332
|
+ ( ( unsigned long ) mcast_count ) );
|
332
|
333
|
for ( i = 0 ; i < mcast_count ; i++ ) {
|
333
|
334
|
DBGC2_HDA ( snpdev, i, &mcast[i],
|
334
|
335
|
snpdev->netdev->ll_protocol->ll_addr_len );
|
|
@@ -359,8 +360,8 @@ efi_snp_station_address ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, BOOLEAN reset,
|
359
|
360
|
container_of ( snp, struct efi_snp_device, snp );
|
360
|
361
|
struct ll_protocol *ll_protocol = snpdev->netdev->ll_protocol;
|
361
|
362
|
|
362
|
|
- DBGC2 ( snpdev, "SNPDEV %p STATION_ADDRESS %s\n", snpdev,
|
363
|
|
- ( reset ? "reset" : ll_protocol->ntoa ( new ) ) );
|
|
363
|
+ DBGC ( snpdev, "SNPDEV %p STATION_ADDRESS %s\n", snpdev,
|
|
364
|
+ ( reset ? "reset" : ll_protocol->ntoa ( new ) ) );
|
364
|
365
|
|
365
|
366
|
/* Fail if net device is currently claimed for use by iPXE */
|
366
|
367
|
if ( efi_snp_claimed )
|
|
@@ -396,8 +397,8 @@ efi_snp_statistics ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, BOOLEAN reset,
|
396
|
397
|
container_of ( snp, struct efi_snp_device, snp );
|
397
|
398
|
EFI_NETWORK_STATISTICS stats_buf;
|
398
|
399
|
|
399
|
|
- DBGC2 ( snpdev, "SNPDEV %p STATISTICS%s", snpdev,
|
400
|
|
- ( reset ? " reset" : "" ) );
|
|
400
|
+ DBGC ( snpdev, "SNPDEV %p STATISTICS%s", snpdev,
|
|
401
|
+ ( reset ? " reset" : "" ) );
|
401
|
402
|
|
402
|
403
|
/* Fail if net device is currently claimed for use by iPXE */
|
403
|
404
|
if ( efi_snp_claimed )
|
|
@@ -449,7 +450,7 @@ efi_snp_mcast_ip_to_mac ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, BOOLEAN ipv6,
|
449
|
450
|
|
450
|
451
|
ip_str = ( ipv6 ? "(IPv6)" /* FIXME when we have inet6_ntoa() */ :
|
451
|
452
|
inet_ntoa ( *( ( struct in_addr * ) ip ) ) );
|
452
|
|
- DBGC2 ( snpdev, "SNPDEV %p MCAST_IP_TO_MAC %s\n", snpdev, ip_str );
|
|
453
|
+ DBGC ( snpdev, "SNPDEV %p MCAST_IP_TO_MAC %s\n", snpdev, ip_str );
|
453
|
454
|
|
454
|
455
|
/* Fail if net device is currently claimed for use by iPXE */
|
455
|
456
|
if ( efi_snp_claimed )
|
|
@@ -482,9 +483,9 @@ efi_snp_nvdata ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, BOOLEAN read,
|
482
|
483
|
struct efi_snp_device *snpdev =
|
483
|
484
|
container_of ( snp, struct efi_snp_device, snp );
|
484
|
485
|
|
485
|
|
- DBGC2 ( snpdev, "SNPDEV %p NVDATA %s %lx+%lx\n", snpdev,
|
486
|
|
- ( read ? "read" : "write" ), ( ( unsigned long ) offset ),
|
487
|
|
- ( ( unsigned long ) len ) );
|
|
486
|
+ DBGC ( snpdev, "SNPDEV %p NVDATA %s %lx+%lx\n", snpdev,
|
|
487
|
+ ( read ? "read" : "write" ), ( ( unsigned long ) offset ),
|
|
488
|
+ ( ( unsigned long ) len ) );
|
488
|
489
|
if ( ! read )
|
489
|
490
|
DBGC2_HDA ( snpdev, offset, data, len );
|
490
|
491
|
|
|
@@ -802,6 +803,608 @@ static EFI_SIMPLE_NETWORK_PROTOCOL efi_snp_device_snp = {
|
802
|
803
|
.Receive = efi_snp_receive,
|
803
|
804
|
};
|
804
|
805
|
|
|
806
|
+/******************************************************************************
|
|
807
|
+ *
|
|
808
|
+ * UNDI protocol
|
|
809
|
+ *
|
|
810
|
+ ******************************************************************************
|
|
811
|
+ */
|
|
812
|
+
|
|
813
|
+/** Union type for command parameter blocks */
|
|
814
|
+typedef union {
|
|
815
|
+ PXE_CPB_STATION_ADDRESS station_address;
|
|
816
|
+ PXE_CPB_FILL_HEADER fill_header;
|
|
817
|
+ PXE_CPB_FILL_HEADER_FRAGMENTED fill_header_fragmented;
|
|
818
|
+ PXE_CPB_TRANSMIT transmit;
|
|
819
|
+ PXE_CPB_RECEIVE receive;
|
|
820
|
+} PXE_CPB_ANY;
|
|
821
|
+
|
|
822
|
+/** Union type for data blocks */
|
|
823
|
+typedef union {
|
|
824
|
+ PXE_DB_GET_INIT_INFO get_init_info;
|
|
825
|
+ PXE_DB_STATION_ADDRESS station_address;
|
|
826
|
+ PXE_DB_GET_STATUS get_status;
|
|
827
|
+ PXE_DB_RECEIVE receive;
|
|
828
|
+} PXE_DB_ANY;
|
|
829
|
+
|
|
830
|
+/**
|
|
831
|
+ * Calculate UNDI byte checksum
|
|
832
|
+ *
|
|
833
|
+ * @v data Data
|
|
834
|
+ * @v len Length of data
|
|
835
|
+ * @ret sum Checksum
|
|
836
|
+ */
|
|
837
|
+static uint8_t efi_undi_checksum ( void *data, size_t len ) {
|
|
838
|
+ uint8_t *bytes = data;
|
|
839
|
+ uint8_t sum = 0;
|
|
840
|
+
|
|
841
|
+ while ( len-- )
|
|
842
|
+ sum += *bytes++;
|
|
843
|
+ return sum;
|
|
844
|
+}
|
|
845
|
+
|
|
846
|
+/**
|
|
847
|
+ * Get UNDI SNP device interface number
|
|
848
|
+ *
|
|
849
|
+ * @v snpdev SNP device
|
|
850
|
+ * @ret ifnum UNDI interface number
|
|
851
|
+ */
|
|
852
|
+static unsigned int efi_undi_ifnum ( struct efi_snp_device *snpdev ) {
|
|
853
|
+
|
|
854
|
+ /* iPXE network device indexes are one-based (leaving zero
|
|
855
|
+ * meaning "unspecified"). UNDI interface numbers are
|
|
856
|
+ * zero-based.
|
|
857
|
+ */
|
|
858
|
+ return ( snpdev->netdev->index - 1 );
|
|
859
|
+}
|
|
860
|
+
|
|
861
|
+/**
|
|
862
|
+ * Identify UNDI SNP device
|
|
863
|
+ *
|
|
864
|
+ * @v ifnum Interface number
|
|
865
|
+ * @ret snpdev SNP device, or NULL if not found
|
|
866
|
+ */
|
|
867
|
+static struct efi_snp_device * efi_undi_snpdev ( unsigned int ifnum ) {
|
|
868
|
+ struct efi_snp_device *snpdev;
|
|
869
|
+
|
|
870
|
+ list_for_each_entry ( snpdev, &efi_snp_devices, list ) {
|
|
871
|
+ if ( efi_undi_ifnum ( snpdev ) == ifnum )
|
|
872
|
+ return snpdev;
|
|
873
|
+ }
|
|
874
|
+ return NULL;
|
|
875
|
+}
|
|
876
|
+
|
|
877
|
+/**
|
|
878
|
+ * Convert EFI status code to UNDI status code
|
|
879
|
+ *
|
|
880
|
+ * @v efirc EFI status code
|
|
881
|
+ * @ret statcode UNDI status code
|
|
882
|
+ */
|
|
883
|
+static PXE_STATCODE efi_undi_statcode ( EFI_STATUS efirc ) {
|
|
884
|
+
|
|
885
|
+ switch ( efirc ) {
|
|
886
|
+ case EFI_INVALID_PARAMETER: return PXE_STATCODE_INVALID_PARAMETER;
|
|
887
|
+ case EFI_UNSUPPORTED: return PXE_STATCODE_UNSUPPORTED;
|
|
888
|
+ case EFI_OUT_OF_RESOURCES: return PXE_STATCODE_BUFFER_FULL;
|
|
889
|
+ case EFI_PROTOCOL_ERROR: return PXE_STATCODE_DEVICE_FAILURE;
|
|
890
|
+ case EFI_NOT_READY: return PXE_STATCODE_NO_DATA;
|
|
891
|
+ default:
|
|
892
|
+ return PXE_STATCODE_INVALID_CDB;
|
|
893
|
+ }
|
|
894
|
+}
|
|
895
|
+
|
|
896
|
+/**
|
|
897
|
+ * Get state
|
|
898
|
+ *
|
|
899
|
+ * @v snpdev SNP device
|
|
900
|
+ * @v cdb Command description block
|
|
901
|
+ * @ret efirc EFI status code
|
|
902
|
+ */
|
|
903
|
+static EFI_STATUS efi_undi_get_state ( struct efi_snp_device *snpdev,
|
|
904
|
+ PXE_CDB *cdb ) {
|
|
905
|
+ EFI_SIMPLE_NETWORK_MODE *mode = &snpdev->mode;
|
|
906
|
+
|
|
907
|
+ DBGC ( snpdev, "UNDI %p GET STATE\n", snpdev );
|
|
908
|
+
|
|
909
|
+ /* Return current state */
|
|
910
|
+ if ( mode->State == EfiSimpleNetworkInitialized ) {
|
|
911
|
+ cdb->StatFlags |= PXE_STATFLAGS_GET_STATE_INITIALIZED;
|
|
912
|
+ } else if ( mode->State == EfiSimpleNetworkStarted ) {
|
|
913
|
+ cdb->StatFlags |= PXE_STATFLAGS_GET_STATE_STARTED;
|
|
914
|
+ } else {
|
|
915
|
+ cdb->StatFlags |= PXE_STATFLAGS_GET_STATE_STOPPED;
|
|
916
|
+ }
|
|
917
|
+
|
|
918
|
+ return 0;
|
|
919
|
+}
|
|
920
|
+
|
|
921
|
+/**
|
|
922
|
+ * Start
|
|
923
|
+ *
|
|
924
|
+ * @v snpdev SNP device
|
|
925
|
+ * @ret efirc EFI status code
|
|
926
|
+ */
|
|
927
|
+static EFI_STATUS efi_undi_start ( struct efi_snp_device *snpdev ) {
|
|
928
|
+ EFI_STATUS efirc;
|
|
929
|
+
|
|
930
|
+ DBGC ( snpdev, "UNDI %p START\n", snpdev );
|
|
931
|
+
|
|
932
|
+ /* Start SNP device */
|
|
933
|
+ if ( ( efirc = efi_snp_start ( &snpdev->snp ) ) != 0 )
|
|
934
|
+ return efirc;
|
|
935
|
+
|
|
936
|
+ return 0;
|
|
937
|
+}
|
|
938
|
+
|
|
939
|
+/**
|
|
940
|
+ * Stop
|
|
941
|
+ *
|
|
942
|
+ * @v snpdev SNP device
|
|
943
|
+ * @ret efirc EFI status code
|
|
944
|
+ */
|
|
945
|
+static EFI_STATUS efi_undi_stop ( struct efi_snp_device *snpdev ) {
|
|
946
|
+ EFI_STATUS efirc;
|
|
947
|
+
|
|
948
|
+ DBGC ( snpdev, "UNDI %p STOP\n", snpdev );
|
|
949
|
+
|
|
950
|
+ /* Stop SNP device */
|
|
951
|
+ if ( ( efirc = efi_snp_stop ( &snpdev->snp ) ) != 0 )
|
|
952
|
+ return efirc;
|
|
953
|
+
|
|
954
|
+ return 0;
|
|
955
|
+}
|
|
956
|
+
|
|
957
|
+/**
|
|
958
|
+ * Get initialisation information
|
|
959
|
+ *
|
|
960
|
+ * @v snpdev SNP device
|
|
961
|
+ * @v cdb Command description block
|
|
962
|
+ * @v db Data block
|
|
963
|
+ * @ret efirc EFI status code
|
|
964
|
+ */
|
|
965
|
+static EFI_STATUS efi_undi_get_init_info ( struct efi_snp_device *snpdev,
|
|
966
|
+ PXE_CDB *cdb,
|
|
967
|
+ PXE_DB_GET_INIT_INFO *db ) {
|
|
968
|
+ struct net_device *netdev = snpdev->netdev;
|
|
969
|
+ struct ll_protocol *ll_protocol = netdev->ll_protocol;
|
|
970
|
+
|
|
971
|
+ DBGC ( snpdev, "UNDI %p GET INIT INFO\n", snpdev );
|
|
972
|
+
|
|
973
|
+ /* Populate structure */
|
|
974
|
+ memset ( db, 0, sizeof ( *db ) );
|
|
975
|
+ db->FrameDataLen = ( netdev->max_pkt_len - ll_protocol->ll_header_len );
|
|
976
|
+ db->MediaHeaderLen = ll_protocol->ll_header_len;
|
|
977
|
+ db->HWaddrLen = ll_protocol->ll_addr_len;
|
|
978
|
+ db->IFtype = ntohs ( ll_protocol->ll_proto );
|
|
979
|
+ cdb->StatFlags |= ( PXE_STATFLAGS_CABLE_DETECT_SUPPORTED |
|
|
980
|
+ PXE_STATFLAGS_GET_STATUS_NO_MEDIA_SUPPORTED );
|
|
981
|
+
|
|
982
|
+ return 0;
|
|
983
|
+}
|
|
984
|
+
|
|
985
|
+/**
|
|
986
|
+ * Initialise
|
|
987
|
+ *
|
|
988
|
+ * @v snpdev SNP device
|
|
989
|
+ * @v cdb Command description block
|
|
990
|
+ * @v efirc EFI status code
|
|
991
|
+ */
|
|
992
|
+static EFI_STATUS efi_undi_initialize ( struct efi_snp_device *snpdev,
|
|
993
|
+ PXE_CDB *cdb ) {
|
|
994
|
+ struct net_device *netdev = snpdev->netdev;
|
|
995
|
+ EFI_STATUS efirc;
|
|
996
|
+
|
|
997
|
+ DBGC ( snpdev, "UNDI %p INITIALIZE\n", snpdev );
|
|
998
|
+
|
|
999
|
+ /* Reset SNP device */
|
|
1000
|
+ if ( ( efirc = efi_snp_initialize ( &snpdev->snp, 0, 0 ) ) != 0 )
|
|
1001
|
+ return efirc;
|
|
1002
|
+
|
|
1003
|
+ /* Report link state */
|
|
1004
|
+ if ( ! netdev_link_ok ( netdev ) )
|
|
1005
|
+ cdb->StatFlags |= PXE_STATFLAGS_INITIALIZED_NO_MEDIA;
|
|
1006
|
+
|
|
1007
|
+ return 0;
|
|
1008
|
+}
|
|
1009
|
+
|
|
1010
|
+/**
|
|
1011
|
+ * Reset
|
|
1012
|
+ *
|
|
1013
|
+ * @v snpdev SNP device
|
|
1014
|
+ * @v efirc EFI status code
|
|
1015
|
+ */
|
|
1016
|
+static EFI_STATUS efi_undi_reset ( struct efi_snp_device *snpdev ) {
|
|
1017
|
+ EFI_STATUS efirc;
|
|
1018
|
+
|
|
1019
|
+ DBGC ( snpdev, "UNDI %p RESET\n", snpdev );
|
|
1020
|
+
|
|
1021
|
+ /* Reset SNP device */
|
|
1022
|
+ if ( ( efirc = efi_snp_reset ( &snpdev->snp, 0 ) ) != 0 )
|
|
1023
|
+ return efirc;
|
|
1024
|
+
|
|
1025
|
+ return 0;
|
|
1026
|
+}
|
|
1027
|
+
|
|
1028
|
+/**
|
|
1029
|
+ * Shutdown
|
|
1030
|
+ *
|
|
1031
|
+ * @v snpdev SNP device
|
|
1032
|
+ * @v efirc EFI status code
|
|
1033
|
+ */
|
|
1034
|
+static EFI_STATUS efi_undi_shutdown ( struct efi_snp_device *snpdev ) {
|
|
1035
|
+ EFI_STATUS efirc;
|
|
1036
|
+
|
|
1037
|
+ DBGC ( snpdev, "UNDI %p SHUTDOWN\n", snpdev );
|
|
1038
|
+
|
|
1039
|
+ /* Reset SNP device */
|
|
1040
|
+ if ( ( efirc = efi_snp_shutdown ( &snpdev->snp ) ) != 0 )
|
|
1041
|
+ return efirc;
|
|
1042
|
+
|
|
1043
|
+ return 0;
|
|
1044
|
+}
|
|
1045
|
+
|
|
1046
|
+/**
|
|
1047
|
+ * Get/set receive filters
|
|
1048
|
+ *
|
|
1049
|
+ * @v snpdev SNP device
|
|
1050
|
+ * @v cdb Command description block
|
|
1051
|
+ * @v efirc EFI status code
|
|
1052
|
+ */
|
|
1053
|
+static EFI_STATUS efi_undi_receive_filters ( struct efi_snp_device *snpdev,
|
|
1054
|
+ PXE_CDB *cdb ) {
|
|
1055
|
+
|
|
1056
|
+ DBGC ( snpdev, "UNDI %p RECEIVE FILTERS\n", snpdev );
|
|
1057
|
+
|
|
1058
|
+ /* Mark everything as supported */
|
|
1059
|
+ cdb->StatFlags |= ( PXE_STATFLAGS_RECEIVE_FILTER_UNICAST |
|
|
1060
|
+ PXE_STATFLAGS_RECEIVE_FILTER_BROADCAST |
|
|
1061
|
+ PXE_STATFLAGS_RECEIVE_FILTER_PROMISCUOUS |
|
|
1062
|
+ PXE_STATFLAGS_RECEIVE_FILTER_ALL_MULTICAST );
|
|
1063
|
+
|
|
1064
|
+ return 0;
|
|
1065
|
+}
|
|
1066
|
+
|
|
1067
|
+/**
|
|
1068
|
+ * Get/set station address
|
|
1069
|
+ *
|
|
1070
|
+ * @v snpdev SNP device
|
|
1071
|
+ * @v cdb Command description block
|
|
1072
|
+ * @v cpb Command parameter block
|
|
1073
|
+ * @v efirc EFI status code
|
|
1074
|
+ */
|
|
1075
|
+static EFI_STATUS efi_undi_station_address ( struct efi_snp_device *snpdev,
|
|
1076
|
+ PXE_CDB *cdb,
|
|
1077
|
+ PXE_CPB_STATION_ADDRESS *cpb,
|
|
1078
|
+ PXE_DB_STATION_ADDRESS *db ) {
|
|
1079
|
+ struct net_device *netdev = snpdev->netdev;
|
|
1080
|
+ struct ll_protocol *ll_protocol = netdev->ll_protocol;
|
|
1081
|
+ void *mac;
|
|
1082
|
+ int reset;
|
|
1083
|
+ EFI_STATUS efirc;
|
|
1084
|
+
|
|
1085
|
+ DBGC ( snpdev, "UNDI %p STATION ADDRESS\n", snpdev );
|
|
1086
|
+
|
|
1087
|
+ /* Update address if applicable */
|
|
1088
|
+ reset = ( cdb->OpFlags & PXE_OPFLAGS_STATION_ADDRESS_RESET );
|
|
1089
|
+ mac = ( cpb ? &cpb->StationAddr : NULL );
|
|
1090
|
+ if ( ( reset || mac ) &&
|
|
1091
|
+ ( ( efirc = efi_snp_station_address ( &snpdev->snp, reset,
|
|
1092
|
+ mac ) ) != 0 ) )
|
|
1093
|
+ return efirc;
|
|
1094
|
+
|
|
1095
|
+ /* Fill in current addresses, if applicable */
|
|
1096
|
+ if ( db ) {
|
|
1097
|
+ memset ( db, 0, sizeof ( *db ) );
|
|
1098
|
+ memcpy ( &db->StationAddr, netdev->ll_addr,
|
|
1099
|
+ ll_protocol->ll_addr_len );
|
|
1100
|
+ memcpy ( &db->BroadcastAddr, netdev->ll_broadcast,
|
|
1101
|
+ ll_protocol->ll_addr_len );
|
|
1102
|
+ memcpy ( &db->PermanentAddr, netdev->hw_addr,
|
|
1103
|
+ ll_protocol->hw_addr_len );
|
|
1104
|
+ }
|
|
1105
|
+
|
|
1106
|
+ return 0;
|
|
1107
|
+}
|
|
1108
|
+
|
|
1109
|
+/**
|
|
1110
|
+ * Get interrupt status
|
|
1111
|
+ *
|
|
1112
|
+ * @v snpdev SNP device
|
|
1113
|
+ * @v cdb Command description block
|
|
1114
|
+ * @v db Data block
|
|
1115
|
+ * @v efirc EFI status code
|
|
1116
|
+ */
|
|
1117
|
+static EFI_STATUS efi_undi_get_status ( struct efi_snp_device *snpdev,
|
|
1118
|
+ PXE_CDB *cdb, PXE_DB_GET_STATUS *db ) {
|
|
1119
|
+ UINT32 interrupts;
|
|
1120
|
+ VOID *txbuf;
|
|
1121
|
+ struct io_buffer *rxbuf;
|
|
1122
|
+ EFI_STATUS efirc;
|
|
1123
|
+
|
|
1124
|
+ DBGC2 ( snpdev, "UNDI %p GET STATUS\n", snpdev );
|
|
1125
|
+
|
|
1126
|
+ /* Get status */
|
|
1127
|
+ if ( ( efirc = efi_snp_get_status ( &snpdev->snp, &interrupts,
|
|
1128
|
+ &txbuf ) ) != 0 )
|
|
1129
|
+ return efirc;
|
|
1130
|
+
|
|
1131
|
+ /* Report status */
|
|
1132
|
+ memset ( db, 0, sizeof ( *db ) );
|
|
1133
|
+ if ( interrupts & EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT )
|
|
1134
|
+ cdb->StatFlags |= PXE_STATFLAGS_GET_STATUS_RECEIVE;
|
|
1135
|
+ if ( interrupts & EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT )
|
|
1136
|
+ cdb->StatFlags |= PXE_STATFLAGS_GET_STATUS_TRANSMIT;
|
|
1137
|
+ if ( txbuf ) {
|
|
1138
|
+ db->TxBuffer[0] = ( ( intptr_t ) txbuf );
|
|
1139
|
+ } else {
|
|
1140
|
+ cdb->StatFlags |= PXE_STATFLAGS_GET_STATUS_NO_TXBUFS_WRITTEN;
|
|
1141
|
+ /* The specification states clearly that UNDI drivers
|
|
1142
|
+ * should set TXBUF_QUEUE_EMPTY if all completed
|
|
1143
|
+ * buffer addresses are written into the returned data
|
|
1144
|
+ * block. However, SnpDxe chooses to interpret
|
|
1145
|
+ * TXBUF_QUEUE_EMPTY as a synonym for
|
|
1146
|
+ * NO_TXBUFS_WRITTEN, thereby rendering it entirely
|
|
1147
|
+ * pointless. Work around this UEFI stupidity, as per
|
|
1148
|
+ * usual.
|
|
1149
|
+ */
|
|
1150
|
+ if ( snpdev->tx_prod == snpdev->tx_cons )
|
|
1151
|
+ cdb->StatFlags |=
|
|
1152
|
+ PXE_STATFLAGS_GET_STATUS_TXBUF_QUEUE_EMPTY;
|
|
1153
|
+ }
|
|
1154
|
+ rxbuf = list_first_entry ( &snpdev->rx, struct io_buffer, list );
|
|
1155
|
+ if ( rxbuf )
|
|
1156
|
+ db->RxFrameLen = iob_len ( rxbuf );
|
|
1157
|
+ if ( ! netdev_link_ok ( snpdev->netdev ) )
|
|
1158
|
+ cdb->StatFlags |= PXE_STATFLAGS_GET_STATUS_NO_MEDIA;
|
|
1159
|
+
|
|
1160
|
+ return 0;
|
|
1161
|
+}
|
|
1162
|
+
|
|
1163
|
+/**
|
|
1164
|
+ * Fill header
|
|
1165
|
+ *
|
|
1166
|
+ * @v snpdev SNP device
|
|
1167
|
+ * @v cdb Command description block
|
|
1168
|
+ * @v cpb Command parameter block
|
|
1169
|
+ * @v efirc EFI status code
|
|
1170
|
+ */
|
|
1171
|
+static EFI_STATUS efi_undi_fill_header ( struct efi_snp_device *snpdev,
|
|
1172
|
+ PXE_CDB *cdb, PXE_CPB_ANY *cpb ) {
|
|
1173
|
+ struct net_device *netdev = snpdev->netdev;
|
|
1174
|
+ struct ll_protocol *ll_protocol = netdev->ll_protocol;
|
|
1175
|
+ PXE_CPB_FILL_HEADER *whole = &cpb->fill_header;
|
|
1176
|
+ PXE_CPB_FILL_HEADER_FRAGMENTED *fragged = &cpb->fill_header_fragmented;
|
|
1177
|
+ VOID *data;
|
|
1178
|
+ void *dest;
|
|
1179
|
+ void *src;
|
|
1180
|
+ uint16_t proto;
|
|
1181
|
+ struct io_buffer iobuf;
|
|
1182
|
+ int rc;
|
|
1183
|
+
|
|
1184
|
+ /* SnpDxe will (pointlessly) use PXE_CPB_FILL_HEADER_FRAGMENTED
|
|
1185
|
+ * even though we choose to explicitly not claim support for
|
|
1186
|
+ * fragments via PXE_ROMID_IMP_FRAG_SUPPORTED.
|
|
1187
|
+ */
|
|
1188
|
+ if ( cdb->OpFlags & PXE_OPFLAGS_FILL_HEADER_FRAGMENTED ) {
|
|
1189
|
+ data = ( ( void * ) ( intptr_t ) fragged->FragDesc[0].FragAddr);
|
|
1190
|
+ dest = &fragged->DestAddr;
|
|
1191
|
+ src = &fragged->SrcAddr;
|
|
1192
|
+ proto = fragged->Protocol;
|
|
1193
|
+ } else {
|
|
1194
|
+ data = ( ( void * ) ( intptr_t ) whole->MediaHeader );
|
|
1195
|
+ dest = &whole->DestAddr;
|
|
1196
|
+ src = &whole->SrcAddr;
|
|
1197
|
+ proto = whole->Protocol;
|
|
1198
|
+ }
|
|
1199
|
+
|
|
1200
|
+ /* Construct link-layer header */
|
|
1201
|
+ iob_populate ( &iobuf, data, 0, ll_protocol->ll_header_len );
|
|
1202
|
+ iob_reserve ( &iobuf, ll_protocol->ll_header_len );
|
|
1203
|
+ if ( ( rc = ll_protocol->push ( netdev, &iobuf, dest, src,
|
|
1204
|
+ proto ) ) != 0 )
|
|
1205
|
+ return EFIRC ( rc );
|
|
1206
|
+
|
|
1207
|
+ return 0;
|
|
1208
|
+}
|
|
1209
|
+
|
|
1210
|
+/**
|
|
1211
|
+ * Transmit
|
|
1212
|
+ *
|
|
1213
|
+ * @v snpdev SNP device
|
|
1214
|
+ * @v cpb Command parameter block
|
|
1215
|
+ * @v efirc EFI status code
|
|
1216
|
+ */
|
|
1217
|
+static EFI_STATUS efi_undi_transmit ( struct efi_snp_device *snpdev,
|
|
1218
|
+ PXE_CPB_TRANSMIT *cpb ) {
|
|
1219
|
+ VOID *data = ( ( void * ) ( intptr_t ) cpb->FrameAddr );
|
|
1220
|
+ EFI_STATUS efirc;
|
|
1221
|
+
|
|
1222
|
+ DBGC2 ( snpdev, "UNDI %p TRANSMIT\n", snpdev );
|
|
1223
|
+
|
|
1224
|
+ /* Transmit packet */
|
|
1225
|
+ if ( ( efirc = efi_snp_transmit ( &snpdev->snp, 0, cpb->DataLen,
|
|
1226
|
+ data, NULL, NULL, NULL ) ) != 0 )
|
|
1227
|
+ return efirc;
|
|
1228
|
+
|
|
1229
|
+ return 0;
|
|
1230
|
+}
|
|
1231
|
+
|
|
1232
|
+/**
|
|
1233
|
+ * Receive
|
|
1234
|
+ *
|
|
1235
|
+ * @v snpdev SNP device
|
|
1236
|
+ * @v cpb Command parameter block
|
|
1237
|
+ * @v efirc EFI status code
|
|
1238
|
+ */
|
|
1239
|
+static EFI_STATUS efi_undi_receive ( struct efi_snp_device *snpdev,
|
|
1240
|
+ PXE_CPB_RECEIVE *cpb,
|
|
1241
|
+ PXE_DB_RECEIVE *db ) {
|
|
1242
|
+ struct net_device *netdev = snpdev->netdev;
|
|
1243
|
+ struct ll_protocol *ll_protocol = netdev->ll_protocol;
|
|
1244
|
+ VOID *data = ( ( void * ) ( intptr_t ) cpb->BufferAddr );
|
|
1245
|
+ UINTN hdr_len;
|
|
1246
|
+ UINTN len = cpb->BufferLen;
|
|
1247
|
+ EFI_MAC_ADDRESS src;
|
|
1248
|
+ EFI_MAC_ADDRESS dest;
|
|
1249
|
+ UINT16 proto;
|
|
1250
|
+ EFI_STATUS efirc;
|
|
1251
|
+
|
|
1252
|
+ DBGC2 ( snpdev, "UNDI %p RECEIVE\n", snpdev );
|
|
1253
|
+
|
|
1254
|
+ /* Receive packet */
|
|
1255
|
+ if ( ( efirc = efi_snp_receive ( &snpdev->snp, &hdr_len, &len, data,
|
|
1256
|
+ &src, &dest, &proto ) ) != 0 )
|
|
1257
|
+ return efirc;
|
|
1258
|
+
|
|
1259
|
+ /* Describe frame */
|
|
1260
|
+ memset ( db, 0, sizeof ( *db ) );
|
|
1261
|
+ memcpy ( &db->SrcAddr, &src, ll_protocol->ll_addr_len );
|
|
1262
|
+ memcpy ( &db->DestAddr, &dest, ll_protocol->ll_addr_len );
|
|
1263
|
+ db->FrameLen = len;
|
|
1264
|
+ db->Protocol = proto;
|
|
1265
|
+ db->MediaHeaderLen = ll_protocol->ll_header_len;
|
|
1266
|
+ db->Type = PXE_FRAME_TYPE_PROMISCUOUS;
|
|
1267
|
+
|
|
1268
|
+ return 0;
|
|
1269
|
+}
|
|
1270
|
+
|
|
1271
|
+/** UNDI entry point */
|
|
1272
|
+static EFIAPI VOID efi_undi_issue ( UINT64 cdb_phys ) {
|
|
1273
|
+ PXE_CDB *cdb = ( ( void * ) ( intptr_t ) cdb_phys );
|
|
1274
|
+ PXE_CPB_ANY *cpb = ( ( void * ) ( intptr_t ) cdb->CPBaddr );
|
|
1275
|
+ PXE_DB_ANY *db = ( ( void * ) ( intptr_t ) cdb->DBaddr );
|
|
1276
|
+ struct efi_snp_device *snpdev;
|
|
1277
|
+ EFI_STATUS efirc;
|
|
1278
|
+
|
|
1279
|
+ /* Identify device */
|
|
1280
|
+ snpdev = efi_undi_snpdev ( cdb->IFnum );
|
|
1281
|
+ if ( ! snpdev ) {
|
|
1282
|
+ DBGC ( cdb, "UNDI invalid interface number %d\n", cdb->IFnum );
|
|
1283
|
+ cdb->StatCode = PXE_STATCODE_INVALID_CDB;
|
|
1284
|
+ cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
|
|
1285
|
+ return;
|
|
1286
|
+ }
|
|
1287
|
+
|
|
1288
|
+ /* Fail if net device is currently claimed for use by iPXE */
|
|
1289
|
+ if ( efi_snp_claimed ) {
|
|
1290
|
+ cdb->StatCode = PXE_STATCODE_BUSY;
|
|
1291
|
+ cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
|
|
1292
|
+ return;
|
|
1293
|
+ }
|
|
1294
|
+
|
|
1295
|
+ /* Handle opcode */
|
|
1296
|
+ cdb->StatCode = PXE_STATCODE_SUCCESS;
|
|
1297
|
+ cdb->StatFlags = PXE_STATFLAGS_COMMAND_COMPLETE;
|
|
1298
|
+ switch ( cdb->OpCode ) {
|
|
1299
|
+
|
|
1300
|
+ case PXE_OPCODE_GET_STATE:
|
|
1301
|
+ efirc = efi_undi_get_state ( snpdev, cdb );
|
|
1302
|
+ break;
|
|
1303
|
+
|
|
1304
|
+ case PXE_OPCODE_START:
|
|
1305
|
+ efirc = efi_undi_start ( snpdev );
|
|
1306
|
+ break;
|
|
1307
|
+
|
|
1308
|
+ case PXE_OPCODE_STOP:
|
|
1309
|
+ efirc = efi_undi_stop ( snpdev );
|
|
1310
|
+ break;
|
|
1311
|
+
|
|
1312
|
+ case PXE_OPCODE_GET_INIT_INFO:
|
|
1313
|
+ efirc = efi_undi_get_init_info ( snpdev, cdb,
|
|
1314
|
+ &db->get_init_info );
|
|
1315
|
+ break;
|
|
1316
|
+
|
|
1317
|
+ case PXE_OPCODE_INITIALIZE:
|
|
1318
|
+ efirc = efi_undi_initialize ( snpdev, cdb );
|
|
1319
|
+ break;
|
|
1320
|
+
|
|
1321
|
+ case PXE_OPCODE_RESET:
|
|
1322
|
+ efirc = efi_undi_reset ( snpdev );
|
|
1323
|
+ break;
|
|
1324
|
+
|
|
1325
|
+ case PXE_OPCODE_SHUTDOWN:
|
|
1326
|
+ efirc = efi_undi_shutdown ( snpdev );
|
|
1327
|
+ break;
|
|
1328
|
+
|
|
1329
|
+ case PXE_OPCODE_RECEIVE_FILTERS:
|
|
1330
|
+ efirc = efi_undi_receive_filters ( snpdev, cdb );
|
|
1331
|
+ break;
|
|
1332
|
+
|
|
1333
|
+ case PXE_OPCODE_STATION_ADDRESS:
|
|
1334
|
+ efirc = efi_undi_station_address ( snpdev, cdb,
|
|
1335
|
+ &cpb->station_address,
|
|
1336
|
+ &db->station_address );
|
|
1337
|
+ break;
|
|
1338
|
+
|
|
1339
|
+ case PXE_OPCODE_GET_STATUS:
|
|
1340
|
+ efirc = efi_undi_get_status ( snpdev, cdb, &db->get_status );
|
|
1341
|
+ break;
|
|
1342
|
+
|
|
1343
|
+ case PXE_OPCODE_FILL_HEADER:
|
|
1344
|
+ efirc = efi_undi_fill_header ( snpdev, cdb, cpb );
|
|
1345
|
+ break;
|
|
1346
|
+
|
|
1347
|
+ case PXE_OPCODE_TRANSMIT:
|
|
1348
|
+ efirc = efi_undi_transmit ( snpdev, &cpb->transmit );
|
|
1349
|
+ break;
|
|
1350
|
+
|
|
1351
|
+ case PXE_OPCODE_RECEIVE:
|
|
1352
|
+ efirc = efi_undi_receive ( snpdev, &cpb->receive,
|
|
1353
|
+ &db->receive );
|
|
1354
|
+ break;
|
|
1355
|
+
|
|
1356
|
+ default:
|
|
1357
|
+ DBGC ( snpdev, "UNDI %p unsupported opcode %#04x\n",
|
|
1358
|
+ snpdev, cdb->OpCode );
|
|
1359
|
+ efirc = EFI_UNSUPPORTED;
|
|
1360
|
+ break;
|
|
1361
|
+ }
|
|
1362
|
+
|
|
1363
|
+ /* Convert EFI status code to UNDI status code */
|
|
1364
|
+ if ( efirc != 0 ) {
|
|
1365
|
+ cdb->StatFlags &= ~PXE_STATFLAGS_STATUS_MASK;
|
|
1366
|
+ cdb->StatFlags |= PXE_STATFLAGS_COMMAND_FAILED;
|
|
1367
|
+ cdb->StatCode = efi_undi_statcode ( efirc );
|
|
1368
|
+ }
|
|
1369
|
+}
|
|
1370
|
+
|
|
1371
|
+/** UNDI interface
|
|
1372
|
+ *
|
|
1373
|
+ * Must be aligned on a 16-byte boundary, for no particularly good
|
|
1374
|
+ * reason.
|
|
1375
|
+ */
|
|
1376
|
+static PXE_SW_UNDI efi_snp_undi __attribute__ (( aligned ( 16 ) )) = {
|
|
1377
|
+ .Signature = PXE_ROMID_SIGNATURE,
|
|
1378
|
+ .Len = sizeof ( efi_snp_undi ),
|
|
1379
|
+ .Rev = PXE_ROMID_REV,
|
|
1380
|
+ .MajorVer = PXE_ROMID_MAJORVER,
|
|
1381
|
+ .MinorVer = PXE_ROMID_MINORVER,
|
|
1382
|
+ .Implementation = ( PXE_ROMID_IMP_SW_VIRT_ADDR |
|
|
1383
|
+ PXE_ROMID_IMP_STATION_ADDR_SETTABLE |
|
|
1384
|
+ PXE_ROMID_IMP_PROMISCUOUS_MULTICAST_RX_SUPPORTED |
|
|
1385
|
+ PXE_ROMID_IMP_PROMISCUOUS_RX_SUPPORTED |
|
|
1386
|
+ PXE_ROMID_IMP_BROADCAST_RX_SUPPORTED |
|
|
1387
|
+ PXE_ROMID_IMP_TX_COMPLETE_INT_SUPPORTED |
|
|
1388
|
+ PXE_ROMID_IMP_PACKET_RX_INT_SUPPORTED ),
|
|
1389
|
+ /* SnpDxe checks that BusCnt is non-zero. It makes no further
|
|
1390
|
+ * use of BusCnt, and never looks as BusType[]. As with much
|
|
1391
|
+ * of the EDK2 code, this check seems to serve no purpose
|
|
1392
|
+ * whatsoever but must nonetheless be humoured.
|
|
1393
|
+ */
|
|
1394
|
+ .BusCnt = 1,
|
|
1395
|
+ .BusType[0] = PXE_BUSTYPE ( 'i', 'P', 'X', 'E' ),
|
|
1396
|
+};
|
|
1397
|
+
|
|
1398
|
+/** Network Identification Interface (NII) */
|
|
1399
|
+static EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL efi_snp_device_nii = {
|
|
1400
|
+ .Revision = EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_REVISION,
|
|
1401
|
+ .StringId = "UNDI",
|
|
1402
|
+ .Type = EfiNetworkInterfaceUndi,
|
|
1403
|
+ .MajorVer = 3,
|
|
1404
|
+ .MinorVer = 1,
|
|
1405
|
+ .Ipv6Supported = TRUE, /* This is a raw packet interface, FFS! */
|
|
1406
|
+};
|
|
1407
|
+
|
805
|
1408
|
/******************************************************************************
|
806
|
1409
|
*
|
807
|
1410
|
* Component name protocol
|
|
@@ -939,6 +1542,8 @@ static int efi_snp_probe ( struct net_device *netdev ) {
|
939
|
1542
|
EFI_DEVICE_PATH_PROTOCOL *path_end;
|
940
|
1543
|
MAC_ADDR_DEVICE_PATH *macpath;
|
941
|
1544
|
size_t path_prefix_len = 0;
|
|
1545
|
+ unsigned int ifcnt;
|
|
1546
|
+ void *interface;
|
942
|
1547
|
EFI_STATUS efirc;
|
943
|
1548
|
int rc;
|
944
|
1549
|
|
|
@@ -986,10 +1591,17 @@ static int efi_snp_probe ( struct net_device *netdev ) {
|
986
|
1591
|
efi_snp_set_mode ( snpdev );
|
987
|
1592
|
|
988
|
1593
|
/* Populate the NII structure */
|
989
|
|
- snpdev->nii.Revision =
|
990
|
|
- EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_REVISION;
|
991
|
|
- strncpy ( snpdev->nii.StringId, "iPXE",
|
992
|
|
- sizeof ( snpdev->nii.StringId ) );
|
|
1594
|
+ memcpy ( &snpdev->nii, &efi_snp_device_nii, sizeof ( snpdev->nii ) );
|
|
1595
|
+ snpdev->nii.Id = ( ( intptr_t ) &efi_snp_undi );
|
|
1596
|
+ snpdev->nii.IfNum = efi_undi_ifnum ( snpdev );
|
|
1597
|
+ efi_snp_undi.EntryPoint = ( ( intptr_t ) efi_undi_issue );
|
|
1598
|
+ ifcnt = ( ( efi_snp_undi.IFcntExt << 8 ) | efi_snp_undi.IFcnt );
|
|
1599
|
+ if ( ifcnt < snpdev->nii.IfNum )
|
|
1600
|
+ ifcnt = snpdev->nii.IfNum;
|
|
1601
|
+ efi_snp_undi.IFcnt = ( ifcnt & 0xff );
|
|
1602
|
+ efi_snp_undi.IFcntExt = ( ifcnt >> 8 );
|
|
1603
|
+ efi_snp_undi.Fudge -= efi_undi_checksum ( &efi_snp_undi,
|
|
1604
|
+ sizeof ( efi_snp_undi ) );
|
993
|
1605
|
|
994
|
1606
|
/* Populate the component name structure */
|
995
|
1607
|
efi_snprintf ( snpdev->driver_name,
|
|
@@ -1056,6 +1668,37 @@ static int efi_snp_probe ( struct net_device *netdev ) {
|
1056
|
1668
|
goto err_install_protocol_interface;
|
1057
|
1669
|
}
|
1058
|
1670
|
|
|
1671
|
+ /* SnpDxe will repeatedly start up and shut down our NII/UNDI
|
|
1672
|
+ * interface (in order to obtain the MAC address) before
|
|
1673
|
+ * discovering that it cannot install another SNP on the same
|
|
1674
|
+ * handle. This causes the underlying network device to be
|
|
1675
|
+ * unexpectedly closed.
|
|
1676
|
+ *
|
|
1677
|
+ * Prevent this by opening our own NII (and NII31) protocol
|
|
1678
|
+ * instances to prevent SnpDxe from attempting to bind to
|
|
1679
|
+ * them.
|
|
1680
|
+ */
|
|
1681
|
+ if ( ( efirc = bs->OpenProtocol ( snpdev->handle,
|
|
1682
|
+ &efi_nii_protocol_guid, &interface,
|
|
1683
|
+ efi_image_handle, snpdev->handle,
|
|
1684
|
+ ( EFI_OPEN_PROTOCOL_BY_DRIVER |
|
|
1685
|
+ EFI_OPEN_PROTOCOL_EXCLUSIVE )))!=0){
|
|
1686
|
+ rc = -EEFI ( efirc );
|
|
1687
|
+ DBGC ( snpdev, "SNPDEV %p could not open NII protocol: %s\n",
|
|
1688
|
+ snpdev, strerror ( rc ) );
|
|
1689
|
+ goto err_open_nii;
|
|
1690
|
+ }
|
|
1691
|
+ if ( ( efirc = bs->OpenProtocol ( snpdev->handle,
|
|
1692
|
+ &efi_nii31_protocol_guid, &interface,
|
|
1693
|
+ efi_image_handle, snpdev->handle,
|
|
1694
|
+ ( EFI_OPEN_PROTOCOL_BY_DRIVER |
|
|
1695
|
+ EFI_OPEN_PROTOCOL_EXCLUSIVE )))!=0){
|
|
1696
|
+ rc = -EEFI ( efirc );
|
|
1697
|
+ DBGC ( snpdev, "SNPDEV %p could not open NII31 protocol: %s\n",
|
|
1698
|
+ snpdev, strerror ( rc ) );
|
|
1699
|
+ goto err_open_nii31;
|
|
1700
|
+ }
|
|
1701
|
+
|
1059
|
1702
|
/* Add as child of EFI parent device */
|
1060
|
1703
|
if ( ( rc = efi_child_add ( efidev->device, snpdev->handle ) ) != 0 ) {
|
1061
|
1704
|
DBGC ( snpdev, "SNPDEV %p could not become child of %s: %s\n",
|
|
@@ -1090,6 +1733,12 @@ static int efi_snp_probe ( struct net_device *netdev ) {
|
1090
|
1733
|
efi_snp_hii_uninstall ( snpdev );
|
1091
|
1734
|
efi_child_del ( efidev->device, snpdev->handle );
|
1092
|
1735
|
err_efi_child_add:
|
|
1736
|
+ bs->CloseProtocol ( snpdev->handle, &efi_nii_protocol_guid,
|
|
1737
|
+ efi_image_handle, snpdev->handle );
|
|
1738
|
+ err_open_nii:
|
|
1739
|
+ bs->CloseProtocol ( snpdev->handle, &efi_nii31_protocol_guid,
|
|
1740
|
+ efi_image_handle, snpdev->handle );
|
|
1741
|
+ err_open_nii31:
|
1093
|
1742
|
bs->UninstallMultipleProtocolInterfaces (
|
1094
|
1743
|
snpdev->handle,
|
1095
|
1744
|
&efi_simple_network_protocol_guid, &snpdev->snp,
|
|
@@ -1158,6 +1807,10 @@ static void efi_snp_remove ( struct net_device *netdev ) {
|
1158
|
1807
|
if ( snpdev->package_list )
|
1159
|
1808
|
efi_snp_hii_uninstall ( snpdev );
|
1160
|
1809
|
efi_child_del ( snpdev->efidev->device, snpdev->handle );
|
|
1810
|
+ bs->CloseProtocol ( snpdev->handle, &efi_nii_protocol_guid,
|
|
1811
|
+ efi_image_handle, snpdev->handle );
|
|
1812
|
+ bs->CloseProtocol ( snpdev->handle, &efi_nii31_protocol_guid,
|
|
1813
|
+ efi_image_handle, snpdev->handle );
|
1161
|
1814
|
bs->UninstallMultipleProtocolInterfaces (
|
1162
|
1815
|
snpdev->handle,
|
1163
|
1816
|
&efi_simple_network_protocol_guid, &snpdev->snp,
|