Browse Source

[efi] Split SNP HII functionality into a separate file

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 12 years ago
parent
commit
41ea18a455
4 changed files with 508 additions and 418 deletions
  1. 68
    0
      src/include/ipxe/efi/efi_snp.h
  2. 1
    0
      src/include/ipxe/errfile.h
  3. 9
    418
      src/interface/efi/efi_snp.c
  4. 430
    0
      src/interface/efi/efi_snp_hii.c

+ 68
- 0
src/include/ipxe/efi/efi_snp.h View File

@@ -0,0 +1,68 @@
1
+#ifndef _IPXE_EFI_SNP_H
2
+#define _IPXE_EFI_SNP_H
3
+
4
+/** @file
5
+ *
6
+ * iPXE EFI SNP interface
7
+ *
8
+ */
9
+
10
+#include <ipxe/list.h>
11
+#include <ipxe/netdevice.h>
12
+#include <ipxe/efi/efi.h>
13
+#include <ipxe/efi/Protocol/SimpleNetwork.h>
14
+#include <ipxe/efi/Protocol/NetworkInterfaceIdentifier.h>
15
+#include <ipxe/efi/Protocol/DevicePath.h>
16
+#include <ipxe/efi/Protocol/HiiConfigAccess.h>
17
+#include <ipxe/efi/Protocol/HiiDatabase.h>
18
+
19
+/** An SNP device */
20
+struct efi_snp_device {
21
+	/** List of SNP devices */
22
+	struct list_head list;
23
+	/** The underlying iPXE network device */
24
+	struct net_device *netdev;
25
+	/** The underlying EFI PCI device */
26
+	struct efi_pci_device *efipci;
27
+	/** EFI device handle */
28
+	EFI_HANDLE handle;
29
+	/** The SNP structure itself */
30
+	EFI_SIMPLE_NETWORK_PROTOCOL snp;
31
+	/** The SNP "mode" (parameters) */
32
+	EFI_SIMPLE_NETWORK_MODE mode;
33
+	/** Outstanding TX packet count (via "interrupt status")
34
+	 *
35
+	 * Used in order to generate TX completions.
36
+	 */
37
+	unsigned int tx_count_interrupts;
38
+	/** Outstanding TX packet count (via "recycled tx buffers")
39
+	 *
40
+	 * Used in order to generate TX completions.
41
+	 */
42
+	unsigned int tx_count_txbufs;
43
+	/** Outstanding RX packet count (via "interrupt status") */
44
+	unsigned int rx_count_interrupts;
45
+	/** Outstanding RX packet count (via WaitForPacket event) */
46
+	unsigned int rx_count_events;
47
+	/** The network interface identifier */
48
+	EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL nii;
49
+	/** HII configuration access protocol */
50
+	EFI_HII_CONFIG_ACCESS_PROTOCOL hii;
51
+	/** HII package list */
52
+	EFI_HII_PACKAGE_LIST_HEADER *package_list;
53
+	/** HII handle */
54
+	EFI_HII_HANDLE hii_handle;
55
+	/** Device name */
56
+	wchar_t name[ sizeof ( ( ( struct net_device * ) NULL )->name ) ];
57
+	/** The device path
58
+	 *
59
+	 * This field is variable in size and must appear at the end
60
+	 * of the structure.
61
+	 */
62
+	EFI_DEVICE_PATH_PROTOCOL path;
63
+};
64
+
65
+extern int efi_snp_hii_install ( struct efi_snp_device *snpdev );
66
+extern void efi_snp_hii_uninstall ( struct efi_snp_device *snpdev );
67
+
68
+#endif /* _IPXE_EFI_SNP_H */

+ 1
- 0
src/include/ipxe/errfile.h View File

@@ -263,6 +263,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
263 263
 #define ERRFILE_validator	      ( ERRFILE_OTHER | 0x002e0000 )
264 264
 #define ERRFILE_ocsp		      ( ERRFILE_OTHER | 0x002f0000 )
265 265
 #define ERRFILE_nslookup	      ( ERRFILE_OTHER | 0x00300000 )
266
+#define ERRFILE_efi_snp_hii	      ( ERRFILE_OTHER | 0x00310000 )
266 267
 
267 268
 /** @} */
268 269
 

+ 9
- 418
src/interface/efi/efi_snp.c View File

@@ -32,65 +32,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
32 32
 #include <ipxe/efi/efi_pci.h>
33 33
 #include <ipxe/efi/efi_driver.h>
34 34
 #include <ipxe/efi/efi_strings.h>
35
-#include <ipxe/efi/efi_hii.h>
36
-#include <ipxe/efi/Protocol/SimpleNetwork.h>
37
-#include <ipxe/efi/Protocol/NetworkInterfaceIdentifier.h>
38
-#include <ipxe/efi/Protocol/DevicePath.h>
39
-#include <ipxe/efi/Protocol/HiiConfigAccess.h>
40
-#include <ipxe/efi/Protocol/HiiDatabase.h>
41
-#include <config/general.h>
42
-
43
-/** @file
44
- *
45
- * iPXE EFI SNP interface
46
- *
47
- */
48
-
49
-/** An SNP device */
50
-struct efi_snp_device {
51
-	/** List of SNP devices */
52
-	struct list_head list;
53
-	/** The underlying iPXE network device */
54
-	struct net_device *netdev;
55
-	/** The underlying EFI PCI device */
56
-	struct efi_pci_device *efipci;
57
-	/** EFI device handle */
58
-	EFI_HANDLE handle;
59
-	/** The SNP structure itself */
60
-	EFI_SIMPLE_NETWORK_PROTOCOL snp;
61
-	/** The SNP "mode" (parameters) */
62
-	EFI_SIMPLE_NETWORK_MODE mode;
63
-	/** Outstanding TX packet count (via "interrupt status")
64
-	 *
65
-	 * Used in order to generate TX completions.
66
-	 */
67
-	unsigned int tx_count_interrupts;
68
-	/** Outstanding TX packet count (via "recycled tx buffers")
69
-	 *
70
-	 * Used in order to generate TX completions.
71
-	 */
72
-	unsigned int tx_count_txbufs;
73
-	/** Outstanding RX packet count (via "interrupt status") */
74
-	unsigned int rx_count_interrupts;
75
-	/** Outstanding RX packet count (via WaitForPacket event) */
76
-	unsigned int rx_count_events;
77
-	/** The network interface identifier */
78
-	EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL nii;
79
-	/** HII configuration access protocol */
80
-	EFI_HII_CONFIG_ACCESS_PROTOCOL hii;
81
-	/** HII package list */
82
-	EFI_HII_PACKAGE_LIST_HEADER *package_list;
83
-	/** HII handle */
84
-	EFI_HII_HANDLE hii_handle;
85
-	/** Device name */
86
-	wchar_t name[ sizeof ( ( ( struct net_device * ) NULL )->name ) ];
87
-	/** The device path
88
-	 *
89
-	 * This field is variable in size and must appear at the end
90
-	 * of the structure.
91
-	 */
92
-	EFI_DEVICE_PATH_PROTOCOL path;
93
-};
35
+#include <ipxe/efi/efi_snp.h>
94 36
 
95 37
 /** EFI simple network protocol GUID */
96 38
 static EFI_GUID efi_simple_network_protocol_guid
@@ -759,336 +701,6 @@ static EFI_SIMPLE_NETWORK_PROTOCOL efi_snp_device_snp = {
759 701
 	.Receive	= efi_snp_receive,
760 702
 };
761 703
 
762
-/******************************************************************************
763
- *
764
- * Human Interface Infrastructure
765
- *
766
- ******************************************************************************
767
- */
768
-
769
-/** EFI configuration access protocol GUID */
770
-static EFI_GUID efi_hii_config_access_protocol_guid
771
-	= EFI_HII_CONFIG_ACCESS_PROTOCOL_GUID;
772
-
773
-/** EFI HII database protocol */
774
-static EFI_HII_DATABASE_PROTOCOL *efihii;
775
-EFI_REQUIRE_PROTOCOL ( EFI_HII_DATABASE_PROTOCOL, &efihii );
776
-
777
-/** Local base GUID used for our EFI SNP formset */
778
-#define EFI_SNP_FORMSET_GUID_BASE					\
779
-	{ 0xc4f84019, 0x6dfd, 0x4a27,					\
780
-	  { 0x9b, 0x94, 0xb7, 0x2e, 0x1f, 0xbc, 0xad, 0xca } }
781
-
782
-/** Form identifiers used for our EFI SNP HII */
783
-enum efi_snp_hii_form_id {
784
-	EFI_SNP_FORM = 0x0001,		/**< The only form */
785
-};
786
-
787
-/** String identifiers used for our EFI SNP HII */
788
-enum efi_snp_hii_string_id {
789
-	/* Language name */
790
-	EFI_SNP_LANGUAGE_NAME = 0x0001,
791
-	/* Formset */
792
-	EFI_SNP_FORMSET_TITLE, EFI_SNP_FORMSET_HELP,
793
-	/* Product name */
794
-	EFI_SNP_PRODUCT_PROMPT, EFI_SNP_PRODUCT_HELP, EFI_SNP_PRODUCT_TEXT,
795
-	/* Version */
796
-	EFI_SNP_VERSION_PROMPT, EFI_SNP_VERSION_HELP, EFI_SNP_VERSION_TEXT,
797
-	/* Driver */
798
-	EFI_SNP_DRIVER_PROMPT, EFI_SNP_DRIVER_HELP, EFI_SNP_DRIVER_TEXT,
799
-	/* Device */
800
-	EFI_SNP_DEVICE_PROMPT, EFI_SNP_DEVICE_HELP, EFI_SNP_DEVICE_TEXT,
801
-	/* End of list */
802
-	EFI_SNP_MAX_STRING_ID
803
-};
804
-
805
-/** EFI SNP formset */
806
-struct efi_snp_formset {
807
-	EFI_HII_PACKAGE_HEADER Header;
808
-	EFI_IFR_FORM_SET_TYPE(2) FormSet;
809
-	EFI_IFR_GUID_CLASS Class;
810
-	EFI_IFR_GUID_SUBCLASS SubClass;
811
-	EFI_IFR_FORM Form;
812
-	EFI_IFR_TEXT ProductText;
813
-	EFI_IFR_TEXT VersionText;
814
-	EFI_IFR_TEXT DriverText;
815
-	EFI_IFR_TEXT DeviceText;
816
-	EFI_IFR_END EndForm;
817
-	EFI_IFR_END EndFormSet;
818
-} __attribute__ (( packed )) efi_snp_formset = {
819
-	.Header = {
820
-		.Length = sizeof ( efi_snp_formset ),
821
-		.Type = EFI_HII_PACKAGE_FORMS,
822
-	},
823
-	.FormSet = EFI_IFR_FORM_SET ( EFI_SNP_FORMSET_GUID_BASE,
824
-				      EFI_SNP_FORMSET_TITLE,
825
-				      EFI_SNP_FORMSET_HELP,
826
-				      typeof ( efi_snp_formset.FormSet ),
827
-				      EFI_HII_PLATFORM_SETUP_FORMSET_GUID,
828
-				      EFI_HII_IBM_UCM_COMPLIANT_FORMSET_GUID ),
829
-	.Class = EFI_IFR_GUID_CLASS ( EFI_NETWORK_DEVICE_CLASS ),
830
-	.SubClass = EFI_IFR_GUID_SUBCLASS ( 0x03 ),
831
-	.Form = EFI_IFR_FORM ( EFI_SNP_FORM, EFI_SNP_FORMSET_TITLE ),
832
-	.ProductText = EFI_IFR_TEXT ( EFI_SNP_PRODUCT_PROMPT,
833
-				      EFI_SNP_PRODUCT_HELP,
834
-				      EFI_SNP_PRODUCT_TEXT ),
835
-	.VersionText = EFI_IFR_TEXT ( EFI_SNP_VERSION_PROMPT,
836
-				      EFI_SNP_VERSION_HELP,
837
-				      EFI_SNP_VERSION_TEXT ),
838
-	.DriverText = EFI_IFR_TEXT ( EFI_SNP_DRIVER_PROMPT,
839
-				     EFI_SNP_DRIVER_HELP,
840
-				     EFI_SNP_DRIVER_TEXT ),
841
-	.DeviceText = EFI_IFR_TEXT ( EFI_SNP_DEVICE_PROMPT,
842
-				     EFI_SNP_DEVICE_HELP,
843
-				     EFI_SNP_DEVICE_TEXT ),
844
-	.EndForm = EFI_IFR_END(),
845
-	.EndFormSet = EFI_IFR_END(),
846
-};
847
-
848
-/**
849
- * Generate EFI SNP string
850
- *
851
- * @v wbuf		Buffer
852
- * @v swlen		Size of buffer (in wide characters)
853
- * @v snpdev		SNP device
854
- * @ret wlen		Length of string (in wide characters)
855
- */
856
-static int efi_snp_string ( wchar_t *wbuf, ssize_t swlen,
857
-			    enum efi_snp_hii_string_id id,
858
-			    struct efi_snp_device *snpdev ) {
859
-	struct net_device *netdev = snpdev->netdev;
860
-	struct device *dev = netdev->dev;
861
-
862
-	switch ( id ) {
863
-	case EFI_SNP_LANGUAGE_NAME:
864
-		return efi_ssnprintf ( wbuf, swlen, "English" );
865
-	case EFI_SNP_FORMSET_TITLE:
866
-		return efi_ssnprintf ( wbuf, swlen, "%s (%s)",
867
-				       ( PRODUCT_NAME[0] ?
868
-					 PRODUCT_NAME : PRODUCT_SHORT_NAME ),
869
-				       netdev_addr ( netdev ) );
870
-	case EFI_SNP_FORMSET_HELP:
871
-		return efi_ssnprintf ( wbuf, swlen,
872
-				       "Configure " PRODUCT_SHORT_NAME );
873
-	case EFI_SNP_PRODUCT_PROMPT:
874
-		return efi_ssnprintf ( wbuf, swlen, "Name" );
875
-	case EFI_SNP_PRODUCT_HELP:
876
-		return efi_ssnprintf ( wbuf, swlen, "Firmware product name" );
877
-	case EFI_SNP_PRODUCT_TEXT:
878
-		return efi_ssnprintf ( wbuf, swlen, "%s",
879
-				       ( PRODUCT_NAME[0] ?
880
-					 PRODUCT_NAME : PRODUCT_SHORT_NAME ) );
881
-	case EFI_SNP_VERSION_PROMPT:
882
-		return efi_ssnprintf ( wbuf, swlen, "Version" );
883
-	case EFI_SNP_VERSION_HELP:
884
-		return efi_ssnprintf ( wbuf, swlen, "Firmware version" );
885
-	case EFI_SNP_VERSION_TEXT:
886
-		return efi_ssnprintf ( wbuf, swlen, VERSION );
887
-	case EFI_SNP_DRIVER_PROMPT:
888
-		return efi_ssnprintf ( wbuf, swlen, "Driver" );
889
-	case EFI_SNP_DRIVER_HELP:
890
-		return efi_ssnprintf ( wbuf, swlen, "Firmware driver" );
891
-	case EFI_SNP_DRIVER_TEXT:
892
-		return efi_ssnprintf ( wbuf, swlen, "%s", dev->driver_name );
893
-	case EFI_SNP_DEVICE_PROMPT:
894
-		return efi_ssnprintf ( wbuf, swlen, "Device" );
895
-	case EFI_SNP_DEVICE_HELP:
896
-		return efi_ssnprintf ( wbuf, swlen, "Hardware device" );
897
-	case EFI_SNP_DEVICE_TEXT:
898
-		return efi_ssnprintf ( wbuf, swlen, "%s", dev->name );
899
-	default:
900
-		assert ( 0 );
901
-		return 0;
902
-	}
903
-}
904
-
905
-/**
906
- * Generate EFI SNP string package
907
- *
908
- * @v strings		String package header buffer
909
- * @v max_len		Buffer length
910
- * @v snpdev		SNP device
911
- * @ret len		Length of string package
912
- */
913
-static int efi_snp_strings ( EFI_HII_STRING_PACKAGE_HDR *strings,
914
-			     size_t max_len, struct efi_snp_device *snpdev ) {
915
-	static const char language[] = "en-us";
916
-	void *buf = strings;
917
-	ssize_t remaining = max_len;
918
-	size_t hdrsize;
919
-	EFI_HII_SIBT_STRING_UCS2_BLOCK *string;
920
-	ssize_t wremaining;
921
-	size_t string_wlen;
922
-	unsigned int id;
923
-	EFI_HII_STRING_BLOCK *end;
924
-	size_t len;
925
-
926
-	/* Calculate header size */
927
-	hdrsize = ( offsetof ( typeof ( *strings ), Language ) +
928
-		    sizeof ( language ) );
929
-	buf += hdrsize;
930
-	remaining -= hdrsize;
931
-
932
-	/* Fill in strings */
933
-	for ( id = 1 ; id < EFI_SNP_MAX_STRING_ID ; id++ ) {
934
-		string = buf;
935
-		if ( remaining >= ( ( ssize_t ) sizeof ( string->Header ) ) )
936
-			string->Header.BlockType = EFI_HII_SIBT_STRING_UCS2;
937
-		buf += offsetof ( typeof ( *string ), StringText );
938
-		remaining -= offsetof ( typeof ( *string ), StringText );
939
-		wremaining = ( remaining /
940
-			       ( ( ssize_t ) sizeof ( string->StringText[0] )));
941
-		assert ( ! ( ( remaining <= 0 ) && ( wremaining > 0 ) ) );
942
-		string_wlen = efi_snp_string ( string->StringText, wremaining,
943
-					       id, snpdev );
944
-		buf += ( ( string_wlen + 1 /* wNUL */ ) *
945
-			 sizeof ( string->StringText[0] ) );
946
-		remaining -= ( ( string_wlen + 1 /* wNUL */ ) *
947
-			       sizeof ( string->StringText[0] ) );
948
-	}
949
-
950
-	/* Fill in end marker */
951
-	end = buf;
952
-	if ( remaining >= ( ( ssize_t ) sizeof ( *end ) ) )
953
-		end->BlockType = EFI_HII_SIBT_END;
954
-	buf += sizeof ( *end );
955
-	remaining -= sizeof ( *end );
956
-
957
-	/* Calculate overall length */
958
-	len = ( max_len - remaining );
959
-
960
-	/* Fill in string package header */
961
-	if ( strings ) {
962
-		memset ( strings, 0, sizeof ( *strings ) );
963
-		strings->Header.Length = len;
964
-		strings->Header.Type = EFI_HII_PACKAGE_STRINGS;
965
-		strings->HdrSize = hdrsize;
966
-		strings->StringInfoOffset = hdrsize;
967
-		strings->LanguageName = EFI_SNP_LANGUAGE_NAME;
968
-		memcpy ( strings->Language, language, sizeof ( language ) );
969
-	}
970
-
971
-	return len;
972
-}
973
-
974
-/**
975
- * Generate EFI SNP package list
976
- *
977
- * @v snpdev		SNP device
978
- * @ret package_list	Package list, or NULL on error
979
- *
980
- * The package list is allocated using malloc(), and must eventually
981
- * be freed by the caller.
982
- */
983
-static EFI_HII_PACKAGE_LIST_HEADER *
984
-efi_snp_package_list ( struct efi_snp_device *snpdev ) {
985
-	size_t strings_len = efi_snp_strings ( NULL, 0, snpdev );
986
-	struct {
987
-		EFI_HII_PACKAGE_LIST_HEADER header;
988
-		struct efi_snp_formset formset;
989
-		union {
990
-			EFI_HII_STRING_PACKAGE_HDR strings;
991
-			uint8_t pad[strings_len];
992
-		} __attribute__ (( packed )) strings;
993
-		EFI_HII_PACKAGE_HEADER end;
994
-	} __attribute__ (( packed )) *package_list;
995
-
996
-	/* Allocate package list */
997
-	package_list = zalloc ( sizeof ( *package_list ) );
998
-	if ( ! package_list )
999
-		return NULL;
1000
-
1001
-	/* Create a unique GUID for this package list and formset */
1002
-	efi_snp_formset.FormSet.FormSet.Guid.Data1++;
1003
-
1004
-	/* Populate package list */
1005
-	memcpy ( &package_list->header.PackageListGuid,
1006
-		 &efi_snp_formset.FormSet.FormSet.Guid,
1007
-		 sizeof ( package_list->header.PackageListGuid ) );
1008
-	package_list->header.PackageLength = sizeof ( *package_list );
1009
-	memcpy ( &package_list->formset, &efi_snp_formset,
1010
-		 sizeof ( package_list->formset ) );
1011
-	efi_snp_strings ( &package_list->strings.strings,
1012
-			  sizeof ( package_list->strings ), snpdev );
1013
-	package_list->end.Length = sizeof ( package_list->end );
1014
-	package_list->end.Type = EFI_HII_PACKAGE_END;
1015
-
1016
-	return &package_list->header;
1017
-}
1018
-
1019
-/**
1020
- * Fetch configuration
1021
- *
1022
- * @v hii		HII configuration access protocol
1023
- * @v request		Configuration to fetch
1024
- * @ret progress	Progress made through configuration to fetch
1025
- * @ret results		Query results
1026
- * @ret efirc		EFI status code
1027
- */
1028
-static EFI_STATUS EFIAPI
1029
-efi_snp_hii_extract_config ( const EFI_HII_CONFIG_ACCESS_PROTOCOL *hii,
1030
-			     EFI_STRING request, EFI_STRING *progress,
1031
-			     EFI_STRING *results __unused ) {
1032
-	struct efi_snp_device *snpdev =
1033
-		container_of ( hii, struct efi_snp_device, hii );
1034
-
1035
-	DBGC ( snpdev, "SNPDEV %p ExtractConfig\n", snpdev );
1036
-
1037
-	*progress = request;
1038
-	return EFI_INVALID_PARAMETER;
1039
-}
1040
-
1041
-/**
1042
- * Store configuration
1043
- *
1044
- * @v hii		HII configuration access protocol
1045
- * @v config		Configuration to store
1046
- * @ret progress	Progress made through configuration to store
1047
- * @ret efirc		EFI status code
1048
- */
1049
-static EFI_STATUS EFIAPI
1050
-efi_snp_hii_route_config ( const EFI_HII_CONFIG_ACCESS_PROTOCOL *hii,
1051
-			   EFI_STRING config, EFI_STRING *progress ) {
1052
-	struct efi_snp_device *snpdev =
1053
-		container_of ( hii, struct efi_snp_device, hii );
1054
-
1055
-	DBGC ( snpdev, "SNPDEV %p RouteConfig\n", snpdev );
1056
-
1057
-	*progress = config;
1058
-	return EFI_INVALID_PARAMETER;
1059
-}
1060
-
1061
-/**
1062
- * Handle form actions
1063
- *
1064
- * @v hii		HII configuration access protocol
1065
- * @v action		Form browser action
1066
- * @v question_id	Question ID
1067
- * @v type		Type of value
1068
- * @v value		Value
1069
- * @ret action_request	Action requested by driver
1070
- * @ret efirc		EFI status code
1071
- */
1072
-static EFI_STATUS EFIAPI
1073
-efi_snp_hii_callback ( const EFI_HII_CONFIG_ACCESS_PROTOCOL *hii,
1074
-		       EFI_BROWSER_ACTION action __unused,
1075
-		       EFI_QUESTION_ID question_id __unused,
1076
-		       UINT8 type __unused, EFI_IFR_TYPE_VALUE *value __unused,
1077
-		       EFI_BROWSER_ACTION_REQUEST *action_request __unused ) {
1078
-	struct efi_snp_device *snpdev =
1079
-		container_of ( hii, struct efi_snp_device, hii );
1080
-
1081
-	DBGC ( snpdev, "SNPDEV %p Callback\n", snpdev );
1082
-	return EFI_UNSUPPORTED;
1083
-}
1084
-
1085
-/** HII configuration access protocol */
1086
-static EFI_HII_CONFIG_ACCESS_PROTOCOL efi_snp_device_hii = {
1087
-	.ExtractConfig	= efi_snp_hii_extract_config,
1088
-	.RouteConfig	= efi_snp_hii_route_config,
1089
-	.Callback	= efi_snp_hii_callback,
1090
-};
1091
-
1092 704
 /******************************************************************************
1093 705
  *
1094 706
  * iPXE network driver
@@ -1182,9 +794,6 @@ static int efi_snp_probe ( struct net_device *netdev ) {
1182 794
 	strncpy ( snpdev->nii.StringId, "iPXE",
1183 795
 		  sizeof ( snpdev->nii.StringId ) );
1184 796
 
1185
-	/* Populate the HII configuration access structure */
1186
-	memcpy ( &snpdev->hii, &efi_snp_device_hii, sizeof ( snpdev->hii ) );
1187
-
1188 797
 	/* Populate the device name */
1189 798
 	efi_snprintf ( snpdev->name, ( sizeof ( snpdev->name ) /
1190 799
 				       sizeof ( snpdev->name[0] ) ),
@@ -1213,7 +822,6 @@ static int efi_snp_probe ( struct net_device *netdev ) {
1213 822
 			&efi_device_path_protocol_guid, &snpdev->path,
1214 823
 			&efi_nii_protocol_guid, &snpdev->nii,
1215 824
 			&efi_nii31_protocol_guid, &snpdev->nii,
1216
-			&efi_hii_config_access_protocol_guid, &snpdev->hii,
1217 825
 			NULL ) ) != 0 ) {
1218 826
 		DBGC ( snpdev, "SNPDEV %p could not install protocols: "
1219 827
 		       "%s\n", snpdev, efi_strerror ( efirc ) );
@@ -1230,23 +838,11 @@ static int efi_snp_probe ( struct net_device *netdev ) {
1230 838
 		goto err_efipci_child_add;
1231 839
 	}
1232 840
 
1233
-	/* Create HII package list */
1234
-	snpdev->package_list = efi_snp_package_list ( snpdev );
1235
-	if ( ! snpdev->package_list ) {
1236
-		DBGC ( snpdev, "SNPDEV %p could not create HII package list\n",
1237
-		       snpdev );
1238
-		rc = -ENOMEM;
1239
-		goto err_create_hii;
1240
-	}
1241
-
1242
-	/* Add HII packages */
1243
-	if ( ( efirc = efihii->NewPackageList ( efihii, snpdev->package_list,
1244
-						snpdev->handle,
1245
-						&snpdev->hii_handle ) ) != 0 ) {
1246
-		DBGC ( snpdev, "SNPDEV %p could not add HII packages: %s\n",
1247
-		       snpdev, efi_strerror ( efirc ) );
1248
-		rc = EFIRC_TO_RC ( efirc );
1249
-		goto err_register_hii;
841
+	/* Install HII */
842
+	if ( ( rc = efi_snp_hii_install ( snpdev ) ) != 0 ) {
843
+		DBGC ( snpdev, "SNPDEV %p could not install HII: %s\n",
844
+		       snpdev, strerror ( rc ) );
845
+		goto err_hii_install;
1250 846
 	}
1251 847
 
1252 848
 	/* Add to list of SNP devices */
@@ -1256,10 +852,8 @@ static int efi_snp_probe ( struct net_device *netdev ) {
1256 852
 	       snpdev, netdev->name, snpdev->handle );
1257 853
 	return 0;
1258 854
 
1259
-	efihii->RemovePackageList ( efihii, snpdev->hii_handle );
1260
- err_register_hii:
1261
-	free ( snpdev->package_list );
1262
- err_create_hii:
855
+	efi_snp_hii_uninstall ( snpdev );
856
+ err_hii_install:
1263 857
 	efipci_child_del ( efipci, snpdev->handle );
1264 858
  err_efipci_child_add:
1265 859
 	bs->UninstallMultipleProtocolInterfaces (
@@ -1268,7 +862,6 @@ static int efi_snp_probe ( struct net_device *netdev ) {
1268 862
 			&efi_device_path_protocol_guid, &snpdev->path,
1269 863
 			&efi_nii_protocol_guid, &snpdev->nii,
1270 864
 			&efi_nii31_protocol_guid, &snpdev->nii,
1271
-			&efi_hii_config_access_protocol_guid, &snpdev->hii,
1272 865
 			NULL );
1273 866
  err_install_protocol_interface:
1274 867
 	bs->CloseEvent ( snpdev->snp.WaitForPacket );
@@ -1320,8 +913,7 @@ static void efi_snp_remove ( struct net_device *netdev ) {
1320 913
 	}
1321 914
 
1322 915
 	/* Uninstall the SNP */
1323
-	efihii->RemovePackageList ( efihii, snpdev->hii_handle );
1324
-	free ( snpdev->package_list );
916
+	efi_snp_hii_uninstall ( snpdev );
1325 917
 	efipci_child_del ( snpdev->efipci, snpdev->handle );
1326 918
 	list_del ( &snpdev->list );
1327 919
 	bs->UninstallMultipleProtocolInterfaces (
@@ -1330,7 +922,6 @@ static void efi_snp_remove ( struct net_device *netdev ) {
1330 922
 			&efi_device_path_protocol_guid, &snpdev->path,
1331 923
 			&efi_nii_protocol_guid, &snpdev->nii,
1332 924
 			&efi_nii31_protocol_guid, &snpdev->nii,
1333
-			&efi_hii_config_access_protocol_guid, &snpdev->hii,
1334 925
 			NULL );
1335 926
 	bs->CloseEvent ( snpdev->snp.WaitForPacket );
1336 927
 	netdev_put ( snpdev->netdev );

+ 430
- 0
src/interface/efi/efi_snp_hii.c View File

@@ -0,0 +1,430 @@
1
+/*
2
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
3
+ *
4
+ * This program is free software; you can redistribute it and/or
5
+ * modify it under the terms of the GNU General Public License as
6
+ * published by the Free Software Foundation; either version 2 of the
7
+ * License, or any later version.
8
+ *
9
+ * This program is distributed in the hope that it will be useful, but
10
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
+ * General Public License for more details.
13
+ *
14
+ * You should have received a copy of the GNU General Public License
15
+ * along with this program; if not, write to the Free Software
16
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17
+ * 02110-1301, USA.
18
+ */
19
+
20
+FILE_LICENCE ( GPL2_OR_LATER );
21
+
22
+#include <string.h>
23
+#include <stdlib.h>
24
+#include <errno.h>
25
+#include <ipxe/device.h>
26
+#include <ipxe/netdevice.h>
27
+#include <ipxe/efi/efi.h>
28
+#include <ipxe/efi/efi_hii.h>
29
+#include <ipxe/efi/efi_snp.h>
30
+#include <ipxe/efi/efi_strings.h>
31
+#include <config/general.h>
32
+
33
+/** EFI configuration access protocol GUID */
34
+static EFI_GUID efi_hii_config_access_protocol_guid
35
+	= EFI_HII_CONFIG_ACCESS_PROTOCOL_GUID;
36
+
37
+/** EFI HII database protocol */
38
+static EFI_HII_DATABASE_PROTOCOL *efihii;
39
+EFI_REQUIRE_PROTOCOL ( EFI_HII_DATABASE_PROTOCOL, &efihii );
40
+
41
+/** Local base GUID used for our EFI SNP formset */
42
+#define EFI_SNP_FORMSET_GUID_BASE					\
43
+	{ 0xc4f84019, 0x6dfd, 0x4a27,					\
44
+	  { 0x9b, 0x94, 0xb7, 0x2e, 0x1f, 0xbc, 0xad, 0xca } }
45
+
46
+/** Form identifiers used for our EFI SNP HII */
47
+enum efi_snp_hii_form_id {
48
+	EFI_SNP_FORM = 0x0001,		/**< The only form */
49
+};
50
+
51
+/** String identifiers used for our EFI SNP HII */
52
+enum efi_snp_hii_string_id {
53
+	/* Language name */
54
+	EFI_SNP_LANGUAGE_NAME = 0x0001,
55
+	/* Formset */
56
+	EFI_SNP_FORMSET_TITLE, EFI_SNP_FORMSET_HELP,
57
+	/* Product name */
58
+	EFI_SNP_PRODUCT_PROMPT, EFI_SNP_PRODUCT_HELP, EFI_SNP_PRODUCT_TEXT,
59
+	/* Version */
60
+	EFI_SNP_VERSION_PROMPT, EFI_SNP_VERSION_HELP, EFI_SNP_VERSION_TEXT,
61
+	/* Driver */
62
+	EFI_SNP_DRIVER_PROMPT, EFI_SNP_DRIVER_HELP, EFI_SNP_DRIVER_TEXT,
63
+	/* Device */
64
+	EFI_SNP_DEVICE_PROMPT, EFI_SNP_DEVICE_HELP, EFI_SNP_DEVICE_TEXT,
65
+	/* End of list */
66
+	EFI_SNP_MAX_STRING_ID
67
+};
68
+
69
+/** EFI SNP formset */
70
+struct efi_snp_formset {
71
+	EFI_HII_PACKAGE_HEADER Header;
72
+	EFI_IFR_FORM_SET_TYPE(2) FormSet;
73
+	EFI_IFR_GUID_CLASS Class;
74
+	EFI_IFR_GUID_SUBCLASS SubClass;
75
+	EFI_IFR_FORM Form;
76
+	EFI_IFR_TEXT ProductText;
77
+	EFI_IFR_TEXT VersionText;
78
+	EFI_IFR_TEXT DriverText;
79
+	EFI_IFR_TEXT DeviceText;
80
+	EFI_IFR_END EndForm;
81
+	EFI_IFR_END EndFormSet;
82
+} __attribute__ (( packed )) efi_snp_formset = {
83
+	.Header = {
84
+		.Length = sizeof ( efi_snp_formset ),
85
+		.Type = EFI_HII_PACKAGE_FORMS,
86
+	},
87
+	.FormSet = EFI_IFR_FORM_SET ( EFI_SNP_FORMSET_GUID_BASE,
88
+				      EFI_SNP_FORMSET_TITLE,
89
+				      EFI_SNP_FORMSET_HELP,
90
+				      typeof ( efi_snp_formset.FormSet ),
91
+				      EFI_HII_PLATFORM_SETUP_FORMSET_GUID,
92
+				      EFI_HII_IBM_UCM_COMPLIANT_FORMSET_GUID ),
93
+	.Class = EFI_IFR_GUID_CLASS ( EFI_NETWORK_DEVICE_CLASS ),
94
+	.SubClass = EFI_IFR_GUID_SUBCLASS ( 0x03 ),
95
+	.Form = EFI_IFR_FORM ( EFI_SNP_FORM, EFI_SNP_FORMSET_TITLE ),
96
+	.ProductText = EFI_IFR_TEXT ( EFI_SNP_PRODUCT_PROMPT,
97
+				      EFI_SNP_PRODUCT_HELP,
98
+				      EFI_SNP_PRODUCT_TEXT ),
99
+	.VersionText = EFI_IFR_TEXT ( EFI_SNP_VERSION_PROMPT,
100
+				      EFI_SNP_VERSION_HELP,
101
+				      EFI_SNP_VERSION_TEXT ),
102
+	.DriverText = EFI_IFR_TEXT ( EFI_SNP_DRIVER_PROMPT,
103
+				     EFI_SNP_DRIVER_HELP,
104
+				     EFI_SNP_DRIVER_TEXT ),
105
+	.DeviceText = EFI_IFR_TEXT ( EFI_SNP_DEVICE_PROMPT,
106
+				     EFI_SNP_DEVICE_HELP,
107
+				     EFI_SNP_DEVICE_TEXT ),
108
+	.EndForm = EFI_IFR_END(),
109
+	.EndFormSet = EFI_IFR_END(),
110
+};
111
+
112
+/**
113
+ * Generate EFI SNP string
114
+ *
115
+ * @v wbuf		Buffer
116
+ * @v swlen		Size of buffer (in wide characters)
117
+ * @v snpdev		SNP device
118
+ * @ret wlen		Length of string (in wide characters)
119
+ */
120
+static int efi_snp_string ( wchar_t *wbuf, ssize_t swlen,
121
+			    enum efi_snp_hii_string_id id,
122
+			    struct efi_snp_device *snpdev ) {
123
+	struct net_device *netdev = snpdev->netdev;
124
+	struct device *dev = netdev->dev;
125
+
126
+	switch ( id ) {
127
+	case EFI_SNP_LANGUAGE_NAME:
128
+		return efi_ssnprintf ( wbuf, swlen, "English" );
129
+	case EFI_SNP_FORMSET_TITLE:
130
+		return efi_ssnprintf ( wbuf, swlen, "%s (%s)",
131
+				       ( PRODUCT_NAME[0] ?
132
+					 PRODUCT_NAME : PRODUCT_SHORT_NAME ),
133
+				       netdev_addr ( netdev ) );
134
+	case EFI_SNP_FORMSET_HELP:
135
+		return efi_ssnprintf ( wbuf, swlen,
136
+				       "Configure " PRODUCT_SHORT_NAME );
137
+	case EFI_SNP_PRODUCT_PROMPT:
138
+		return efi_ssnprintf ( wbuf, swlen, "Name" );
139
+	case EFI_SNP_PRODUCT_HELP:
140
+		return efi_ssnprintf ( wbuf, swlen, "Firmware product name" );
141
+	case EFI_SNP_PRODUCT_TEXT:
142
+		return efi_ssnprintf ( wbuf, swlen, "%s",
143
+				       ( PRODUCT_NAME[0] ?
144
+					 PRODUCT_NAME : PRODUCT_SHORT_NAME ) );
145
+	case EFI_SNP_VERSION_PROMPT:
146
+		return efi_ssnprintf ( wbuf, swlen, "Version" );
147
+	case EFI_SNP_VERSION_HELP:
148
+		return efi_ssnprintf ( wbuf, swlen, "Firmware version" );
149
+	case EFI_SNP_VERSION_TEXT:
150
+		return efi_ssnprintf ( wbuf, swlen, VERSION );
151
+	case EFI_SNP_DRIVER_PROMPT:
152
+		return efi_ssnprintf ( wbuf, swlen, "Driver" );
153
+	case EFI_SNP_DRIVER_HELP:
154
+		return efi_ssnprintf ( wbuf, swlen, "Firmware driver" );
155
+	case EFI_SNP_DRIVER_TEXT:
156
+		return efi_ssnprintf ( wbuf, swlen, "%s", dev->driver_name );
157
+	case EFI_SNP_DEVICE_PROMPT:
158
+		return efi_ssnprintf ( wbuf, swlen, "Device" );
159
+	case EFI_SNP_DEVICE_HELP:
160
+		return efi_ssnprintf ( wbuf, swlen, "Hardware device" );
161
+	case EFI_SNP_DEVICE_TEXT:
162
+		return efi_ssnprintf ( wbuf, swlen, "%s", dev->name );
163
+	default:
164
+		assert ( 0 );
165
+		return 0;
166
+	}
167
+}
168
+
169
+/**
170
+ * Generate EFI SNP string package
171
+ *
172
+ * @v strings		String package header buffer
173
+ * @v max_len		Buffer length
174
+ * @v snpdev		SNP device
175
+ * @ret len		Length of string package
176
+ */
177
+static int efi_snp_strings ( EFI_HII_STRING_PACKAGE_HDR *strings,
178
+			     size_t max_len, struct efi_snp_device *snpdev ) {
179
+	static const char language[] = "en-us";
180
+	void *buf = strings;
181
+	ssize_t remaining = max_len;
182
+	size_t hdrsize;
183
+	EFI_HII_SIBT_STRING_UCS2_BLOCK *string;
184
+	ssize_t wremaining;
185
+	size_t string_wlen;
186
+	unsigned int id;
187
+	EFI_HII_STRING_BLOCK *end;
188
+	size_t len;
189
+
190
+	/* Calculate header size */
191
+	hdrsize = ( offsetof ( typeof ( *strings ), Language ) +
192
+		    sizeof ( language ) );
193
+	buf += hdrsize;
194
+	remaining -= hdrsize;
195
+
196
+	/* Fill in strings */
197
+	for ( id = 1 ; id < EFI_SNP_MAX_STRING_ID ; id++ ) {
198
+		string = buf;
199
+		if ( remaining >= ( ( ssize_t ) sizeof ( string->Header ) ) )
200
+			string->Header.BlockType = EFI_HII_SIBT_STRING_UCS2;
201
+		buf += offsetof ( typeof ( *string ), StringText );
202
+		remaining -= offsetof ( typeof ( *string ), StringText );
203
+		wremaining = ( remaining /
204
+			       ( ( ssize_t ) sizeof ( string->StringText[0] )));
205
+		assert ( ! ( ( remaining <= 0 ) && ( wremaining > 0 ) ) );
206
+		string_wlen = efi_snp_string ( string->StringText, wremaining,
207
+					       id, snpdev );
208
+		buf += ( ( string_wlen + 1 /* wNUL */ ) *
209
+			 sizeof ( string->StringText[0] ) );
210
+		remaining -= ( ( string_wlen + 1 /* wNUL */ ) *
211
+			       sizeof ( string->StringText[0] ) );
212
+	}
213
+
214
+	/* Fill in end marker */
215
+	end = buf;
216
+	if ( remaining >= ( ( ssize_t ) sizeof ( *end ) ) )
217
+		end->BlockType = EFI_HII_SIBT_END;
218
+	buf += sizeof ( *end );
219
+	remaining -= sizeof ( *end );
220
+
221
+	/* Calculate overall length */
222
+	len = ( max_len - remaining );
223
+
224
+	/* Fill in string package header */
225
+	if ( strings ) {
226
+		memset ( strings, 0, sizeof ( *strings ) );
227
+		strings->Header.Length = len;
228
+		strings->Header.Type = EFI_HII_PACKAGE_STRINGS;
229
+		strings->HdrSize = hdrsize;
230
+		strings->StringInfoOffset = hdrsize;
231
+		strings->LanguageName = EFI_SNP_LANGUAGE_NAME;
232
+		memcpy ( strings->Language, language, sizeof ( language ) );
233
+	}
234
+
235
+	return len;
236
+}
237
+
238
+/**
239
+ * Generate EFI SNP package list
240
+ *
241
+ * @v snpdev		SNP device
242
+ * @ret package_list	Package list, or NULL on error
243
+ *
244
+ * The package list is allocated using malloc(), and must eventually
245
+ * be freed by the caller.
246
+ */
247
+static EFI_HII_PACKAGE_LIST_HEADER *
248
+efi_snp_package_list ( struct efi_snp_device *snpdev ) {
249
+	size_t strings_len = efi_snp_strings ( NULL, 0, snpdev );
250
+	struct {
251
+		EFI_HII_PACKAGE_LIST_HEADER header;
252
+		struct efi_snp_formset formset;
253
+		union {
254
+			EFI_HII_STRING_PACKAGE_HDR strings;
255
+			uint8_t pad[strings_len];
256
+		} __attribute__ (( packed )) strings;
257
+		EFI_HII_PACKAGE_HEADER end;
258
+	} __attribute__ (( packed )) *package_list;
259
+
260
+	/* Allocate package list */
261
+	package_list = zalloc ( sizeof ( *package_list ) );
262
+	if ( ! package_list )
263
+		return NULL;
264
+
265
+	/* Create a unique GUID for this package list and formset */
266
+	efi_snp_formset.FormSet.FormSet.Guid.Data1++;
267
+
268
+	/* Populate package list */
269
+	memcpy ( &package_list->header.PackageListGuid,
270
+		 &efi_snp_formset.FormSet.FormSet.Guid,
271
+		 sizeof ( package_list->header.PackageListGuid ) );
272
+	package_list->header.PackageLength = sizeof ( *package_list );
273
+	memcpy ( &package_list->formset, &efi_snp_formset,
274
+		 sizeof ( package_list->formset ) );
275
+	efi_snp_strings ( &package_list->strings.strings,
276
+			  sizeof ( package_list->strings ), snpdev );
277
+	package_list->end.Length = sizeof ( package_list->end );
278
+	package_list->end.Type = EFI_HII_PACKAGE_END;
279
+
280
+	return &package_list->header;
281
+}
282
+
283
+/**
284
+ * Fetch configuration
285
+ *
286
+ * @v hii		HII configuration access protocol
287
+ * @v request		Configuration to fetch
288
+ * @ret progress	Progress made through configuration to fetch
289
+ * @ret results		Query results
290
+ * @ret efirc		EFI status code
291
+ */
292
+static EFI_STATUS EFIAPI
293
+efi_snp_hii_extract_config ( const EFI_HII_CONFIG_ACCESS_PROTOCOL *hii,
294
+			     EFI_STRING request, EFI_STRING *progress,
295
+			     EFI_STRING *results __unused ) {
296
+	struct efi_snp_device *snpdev =
297
+		container_of ( hii, struct efi_snp_device, hii );
298
+
299
+	DBGC ( snpdev, "SNPDEV %p ExtractConfig \"%ls\"\n", snpdev, request );
300
+
301
+	*progress = request;
302
+	return EFI_INVALID_PARAMETER;
303
+}
304
+
305
+/**
306
+ * Store configuration
307
+ *
308
+ * @v hii		HII configuration access protocol
309
+ * @v config		Configuration to store
310
+ * @ret progress	Progress made through configuration to store
311
+ * @ret efirc		EFI status code
312
+ */
313
+static EFI_STATUS EFIAPI
314
+efi_snp_hii_route_config ( const EFI_HII_CONFIG_ACCESS_PROTOCOL *hii,
315
+			   EFI_STRING config, EFI_STRING *progress ) {
316
+	struct efi_snp_device *snpdev =
317
+		container_of ( hii, struct efi_snp_device, hii );
318
+
319
+	DBGC ( snpdev, "SNPDEV %p RouteConfig \"%ls\"\n", snpdev, config );
320
+
321
+	*progress = config;
322
+	return EFI_INVALID_PARAMETER;
323
+}
324
+
325
+/**
326
+ * Handle form actions
327
+ *
328
+ * @v hii		HII configuration access protocol
329
+ * @v action		Form browser action
330
+ * @v question_id	Question ID
331
+ * @v type		Type of value
332
+ * @v value		Value
333
+ * @ret action_request	Action requested by driver
334
+ * @ret efirc		EFI status code
335
+ */
336
+static EFI_STATUS EFIAPI
337
+efi_snp_hii_callback ( const EFI_HII_CONFIG_ACCESS_PROTOCOL *hii,
338
+		       EFI_BROWSER_ACTION action __unused,
339
+		       EFI_QUESTION_ID question_id __unused,
340
+		       UINT8 type __unused, EFI_IFR_TYPE_VALUE *value __unused,
341
+		       EFI_BROWSER_ACTION_REQUEST *action_request __unused ) {
342
+	struct efi_snp_device *snpdev =
343
+		container_of ( hii, struct efi_snp_device, hii );
344
+
345
+	DBGC ( snpdev, "SNPDEV %p Callback\n", snpdev );
346
+	return EFI_UNSUPPORTED;
347
+}
348
+
349
+/** HII configuration access protocol */
350
+static EFI_HII_CONFIG_ACCESS_PROTOCOL efi_snp_device_hii = {
351
+	.ExtractConfig	= efi_snp_hii_extract_config,
352
+	.RouteConfig	= efi_snp_hii_route_config,
353
+	.Callback	= efi_snp_hii_callback,
354
+};
355
+
356
+/**
357
+ * Install HII protocol and packages for SNP device
358
+ *
359
+ * @v snpdev		SNP device
360
+ * @ret rc		Return status code
361
+ */
362
+int efi_snp_hii_install ( struct efi_snp_device *snpdev ) {
363
+	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
364
+	int efirc;
365
+	int rc;
366
+
367
+	/* Initialise HII protocol */
368
+	memcpy ( &snpdev->hii, &efi_snp_device_hii, sizeof ( snpdev->hii ) );
369
+
370
+	/* Create HII package list */
371
+	snpdev->package_list = efi_snp_package_list ( snpdev );
372
+	if ( ! snpdev->package_list ) {
373
+		DBGC ( snpdev, "SNPDEV %p could not create HII package list\n",
374
+		       snpdev );
375
+		rc = -ENOMEM;
376
+		goto err_build_package_list;
377
+	}
378
+
379
+	/* Add HII packages */
380
+	if ( ( efirc = efihii->NewPackageList ( efihii, snpdev->package_list,
381
+						snpdev->handle,
382
+						&snpdev->hii_handle ) ) != 0 ) {
383
+		DBGC ( snpdev, "SNPDEV %p could not add HII packages: %s\n",
384
+		       snpdev, efi_strerror ( efirc ) );
385
+		rc = EFIRC_TO_RC ( efirc );
386
+		goto err_new_package_list;
387
+	}
388
+
389
+	/* Install HII protocol */
390
+	if ( ( efirc = bs->InstallMultipleProtocolInterfaces (
391
+			 &snpdev->handle,
392
+			 &efi_hii_config_access_protocol_guid, &snpdev->hii,
393
+			 NULL ) ) != 0 ) {
394
+		DBGC ( snpdev, "SNPDEV %p could not install HII protocol: %s\n",
395
+		       snpdev, efi_strerror ( efirc ) );
396
+		rc = EFIRC_TO_RC ( efirc );
397
+		goto err_install_protocol;
398
+	}
399
+
400
+	return 0;
401
+
402
+	bs->UninstallMultipleProtocolInterfaces (
403
+			snpdev->handle,
404
+			&efi_hii_config_access_protocol_guid, &snpdev->hii,
405
+			NULL );
406
+ err_install_protocol:
407
+	efihii->RemovePackageList ( efihii, snpdev->hii_handle );
408
+ err_new_package_list:
409
+	free ( snpdev->package_list );
410
+	snpdev->package_list = NULL;
411
+ err_build_package_list:
412
+	return rc;
413
+}
414
+
415
+/**
416
+ * Uninstall HII protocol and package for SNP device
417
+ *
418
+ * @v snpdev		SNP device
419
+ */
420
+void efi_snp_hii_uninstall ( struct efi_snp_device *snpdev ) {
421
+	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
422
+
423
+	bs->UninstallMultipleProtocolInterfaces (
424
+			snpdev->handle,
425
+			&efi_hii_config_access_protocol_guid, &snpdev->hii,
426
+			NULL );
427
+	efihii->RemovePackageList ( efihii, snpdev->hii_handle );
428
+	free ( snpdev->package_list );
429
+	snpdev->package_list = NULL;
430
+}

Loading…
Cancel
Save