Browse Source

[efi] Provide component name protocol and device path protocol interfaces

Include a minimal component name protocol so that the driver name
shows up as something other than "<UNKNOWN>" in the driver list, and a
device path protocol so that the network interface shows up as a
separate device in the device list, rather than being attached
directly to the PCI device.

Incidentally, the EFI component name protocol reaches new depths for
signal-to-noise ratio in program code.  A typical instance within the
EFI development kit will use an additional 300 lines of code to
provide slightly less functionality than GNU gettext achieves with
three additional characters.
tags/v0.9.7
Michael Brown 15 years ago
parent
commit
cced04ef3b
2 changed files with 325 additions and 22 deletions
  1. 174
    0
      src/include/gpxe/efi/Protocol/ComponentName2.h
  2. 151
    22
      src/interface/efi/efi_snp.c

+ 174
- 0
src/include/gpxe/efi/Protocol/ComponentName2.h View File

@@ -0,0 +1,174 @@
1
+/** @file
2
+  UEFI Component Name 2 Protocol as defined in the UEFI 2.1 specification.
3
+  This protocol is used to retrieve user readable names of drivers
4
+  and controllers managed by UEFI Drivers.
5
+
6
+  Copyright (c) 2006 - 2008, Intel Corporation
7
+  All rights reserved. This program and the accompanying materials
8
+  are licensed and made available under the terms and conditions of the BSD License
9
+  which accompanies this distribution.  The full text of the license may be found at
10
+  http://opensource.org/licenses/bsd-license.php
11
+
12
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
14
+
15
+**/
16
+
17
+#ifndef __EFI_COMPONENT_NAME2_H__
18
+#define __EFI_COMPONENT_NAME2_H__
19
+
20
+///
21
+/// Global ID for the Component Name Protocol
22
+///
23
+#define EFI_COMPONENT_NAME2_PROTOCOL_GUID \
24
+  {0x6a7a5cff, 0xe8d9, 0x4f70, { 0xba, 0xda, 0x75, 0xab, 0x30, 0x25, 0xce, 0x14 } }
25
+
26
+typedef struct _EFI_COMPONENT_NAME2_PROTOCOL  EFI_COMPONENT_NAME2_PROTOCOL;
27
+
28
+
29
+/**
30
+  Retrieves a Unicode string that is the user readable name of
31
+  the EFI Driver.
32
+
33
+  @param  This       A pointer to the
34
+                     EFI_COMPONENT_NAME2_PROTOCOL instance.
35
+
36
+  @param  Language   A pointer to a Null-terminated ASCII string
37
+                     array indicating the language. This is the
38
+                     language of the driver name that the caller
39
+                     is requesting, and it must match one of the
40
+                     languages specified in SupportedLanguages.
41
+                     The number of languages supported by a
42
+                     driver is up to the driver writer. Language
43
+                     is specified in RFC 3066 language code
44
+                     format.
45
+
46
+  @param  DriverName A pointer to the Unicode string to return.
47
+                     This Unicode string is the name of the
48
+                     driver specified by This in the language
49
+                     specified by Language.
50
+
51
+  @retval EFI_SUCCESS           The Unicode string for the
52
+                                Driver specified by This and the
53
+                                language specified by Language
54
+                                was returned in DriverName.
55
+
56
+  @retval EFI_INVALID_PARAMETER Language is NULL.
57
+
58
+  @retval EFI_INVALID_PARAMETER DriverName is NULL.
59
+
60
+  @retval EFI_UNSUPPORTED       The driver specified by This
61
+                                does not support the language
62
+                                specified by Language.
63
+
64
+**/
65
+typedef
66
+EFI_STATUS
67
+(EFIAPI *EFI_COMPONENT_NAME2_GET_DRIVER_NAME)(
68
+  IN EFI_COMPONENT_NAME2_PROTOCOL          *This,
69
+  IN  CHAR8                                *Language,
70
+  OUT CHAR16                               **DriverName
71
+  );
72
+
73
+
74
+/**
75
+  Retrieves a Unicode string that is the user readable name of
76
+  the controller that is being managed by an EFI Driver.
77
+
78
+  @param  This             A pointer to the
79
+                           EFI_COMPONENT_NAME2_PROTOCOL instance.
80
+
81
+  @param  ControllerHandle The handle of a controller that the
82
+                           driver specified by This is managing.
83
+                           This handle specifies the controller
84
+                           whose name is to be returned.
85
+
86
+  @param ChildHandle      The handle of the child controller to
87
+                           retrieve the name of.  This is an
88
+                           optional parameter that may be NULL.
89
+                           It will be NULL for device drivers.
90
+                           It will also be NULL for a bus
91
+                           drivers that wish to retrieve the
92
+                           name of the bus controller.  It will
93
+                           not be NULL for a bus driver that
94
+                           wishes to retrieve the name of a
95
+                           child controller.
96
+
97
+  @param  Language         A pointer to a Null-terminated ASCII
98
+                           string array indicating the language.
99
+                           This is the language of the driver
100
+                           name that the caller is requesting,
101
+                           and it must match one of the
102
+                           languages specified in
103
+                           SupportedLanguages. The number of
104
+                           languages supported by a driver is up
105
+                           to the driver writer. Language is
106
+                           specified in RFC 3066 language code
107
+                           format.
108
+
109
+  @param  ControllerName   A pointer to the Unicode string to
110
+                           return.  This Unicode string is the
111
+                           name of the controller specified by
112
+                           ControllerHandle and ChildHandle in
113
+                           the language specified by Language
114
+                           from the point of view of the driver
115
+                           specified by This.
116
+
117
+  @retval EFI_SUCCESS           The Unicode string for the user
118
+                                readable name in the language
119
+                                specified by Language for the
120
+                                driver specified by This was
121
+                                returned in DriverName.
122
+
123
+  @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid
124
+                                EFI_HANDLE.
125
+
126
+  @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it
127
+                                is not a valid EFI_HANDLE.
128
+
129
+  @retval EFI_INVALID_PARAMETER Language is NULL.
130
+
131
+  @retval EFI_INVALID_PARAMETER ControllerName is NULL.
132
+
133
+  @retval EFI_UNSUPPORTED       The driver specified by This is
134
+                                not currently managing the
135
+                                controller specified by
136
+                                ControllerHandle and
137
+                                ChildHandle.
138
+
139
+  @retval EFI_UNSUPPORTED       The driver specified by This
140
+                                does not support the language
141
+                                specified by Language.
142
+
143
+**/
144
+typedef
145
+EFI_STATUS
146
+(EFIAPI *EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME)(
147
+  IN EFI_COMPONENT_NAME2_PROTOCOL *This,
148
+  IN  EFI_HANDLE                  ControllerHandle,
149
+  IN  EFI_HANDLE                  ChildHandle        OPTIONAL,
150
+  IN  CHAR8                       *Language,
151
+  OUT CHAR16                      **ControllerName
152
+  );
153
+
154
+///
155
+/// This protocol is used to retrieve user readable names of drivers
156
+/// and controllers managed by UEFI Drivers.
157
+///
158
+struct _EFI_COMPONENT_NAME2_PROTOCOL {
159
+  EFI_COMPONENT_NAME2_GET_DRIVER_NAME      GetDriverName;
160
+  EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME  GetControllerName;
161
+
162
+  ///
163
+  /// A Null-terminated ASCII string array that contains one or more
164
+  /// supported language codes. This is the list of language codes that
165
+  /// this protocol supports. The number of languages supported by a
166
+  /// driver is up to the driver writer. SupportedLanguages is
167
+  /// specified in RFC 3066 format.
168
+  ///
169
+  CHAR8                                    *SupportedLanguages;
170
+};
171
+
172
+extern EFI_GUID gEfiComponentName2ProtocolGuid;
173
+
174
+#endif

+ 151
- 22
src/interface/efi/efi_snp.c View File

@@ -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
 	}

Loading…
Cancel
Save