1 /** @file
2   UEFI Component Name(2) protocol implementation for iSCSI.
3 
4 Copyright (c) 2004 - 2015, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution.  The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9 
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12 
13 **/
14 
15 #include "IScsiImpl.h"
16 
17 //
18 // EFI Component Name Protocol
19 //
20 GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gIScsiComponentName = {
21   IScsiComponentNameGetDriverName,
22   IScsiComponentNameGetControllerName,
23   "eng"
24 };
25 
26 //
27 // EFI Component Name 2 Protocol
28 //
29 GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gIScsiComponentName2 = {
30   (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) IScsiComponentNameGetDriverName,
31   (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) IScsiComponentNameGetControllerName,
32   "en"
33 };
34 
35 GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE     mIScsiDriverNameTable[] = {
36   {
37     "eng;en",
38     L"iSCSI Driver"
39   },
40   {
41     NULL,
42     NULL
43   }
44 };
45 
46 GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE  *gIScsiControllerNameTable = NULL;
47 
48 /**
49   Retrieves a Unicode string that is the user readable name of the driver.
50 
51   This function retrieves the user readable name of a driver in the form of a
52   Unicode string. If the driver specified by This has a user readable name in
53   the language specified by Language, then a pointer to the driver name is
54   returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
55   by This does not support the language specified by Language,
56   then EFI_UNSUPPORTED is returned.
57 
58   @param[in]  This              A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
59                                 EFI_COMPONENT_NAME_PROTOCOL instance.
60 
61   @param[in]  Language          A pointer to a Null-terminated ASCII string
62                                 array indicating the language. This is the
63                                 language of the driver name that the caller is
64                                 requesting, and it must match one of the
65                                 languages specified in SupportedLanguages. The
66                                 number of languages supported by a driver is up
67                                 to the driver writer. Language is specified
68                                 in RFC 4646 or ISO 639-2 language code format.
69 
70   @param[out]  DriverName       A pointer to the Unicode string to return.
71                                 This Unicode string is the name of the
72                                 driver specified by This in the language
73                                 specified by Language.
74 
75   @retval EFI_SUCCESS           The Unicode string for the Driver specified by
76                                 This and the language specified by Language was
77                                 returned in DriverName.
78 
79   @retval EFI_INVALID_PARAMETER Language is NULL.
80 
81   @retval EFI_INVALID_PARAMETER DriverName is NULL.
82 
83   @retval EFI_UNSUPPORTED       The driver specified by This does not support
84                                 the language specified by Language.
85 
86 **/
87 EFI_STATUS
88 EFIAPI
IScsiComponentNameGetDriverName(IN EFI_COMPONENT_NAME_PROTOCOL * This,IN CHAR8 * Language,OUT CHAR16 ** DriverName)89 IScsiComponentNameGetDriverName (
90   IN  EFI_COMPONENT_NAME_PROTOCOL   *This,
91   IN  CHAR8                         *Language,
92   OUT CHAR16                        **DriverName
93   )
94 {
95   return LookupUnicodeString2 (
96            Language,
97            This->SupportedLanguages,
98            mIScsiDriverNameTable,
99            DriverName,
100            (BOOLEAN) (This == &gIScsiComponentName)
101            );
102 }
103 
104 /**
105   Update the component name for the iSCSI instance.
106 
107   @param[in]  IScsiExtScsiPassThru  A pointer to the EFI_EXT_SCSI_PASS_THRU_PROTOCOL instance.
108   @param[in]  Ipv6Flag              TRUE if IP6 network stack is used.
109 
110   @retval EFI_SUCCESS               Update the ControllerNameTable of this instance successfully.
111   @retval EFI_INVALID_PARAMETER     The input parameter is invalid.
112   @retval EFI_UNSUPPORTED           Can't get the corresponding NIC info from the Controller handle.
113 
114 **/
115 EFI_STATUS
UpdateName(IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL * IScsiExtScsiPassThru,IN BOOLEAN Ipv6Flag)116 UpdateName (
117   IN   EFI_EXT_SCSI_PASS_THRU_PROTOCOL *IScsiExtScsiPassThru,
118   IN   BOOLEAN     Ipv6Flag
119   )
120 {
121   EFI_STATUS                       Status;
122   CHAR16                           HandleName[80];
123   ISCSI_DRIVER_DATA                *Private;
124   UINT8                            NicIndex;
125 
126   if (IScsiExtScsiPassThru == NULL) {
127     return EFI_INVALID_PARAMETER;
128   }
129 
130   Private  = ISCSI_DRIVER_DATA_FROM_EXT_SCSI_PASS_THRU (IScsiExtScsiPassThru);
131   NicIndex = Private->Session->ConfigData->NicIndex;
132 
133   UnicodeSPrint (
134     HandleName,
135     sizeof (HandleName),
136     L"iSCSI (%s, NicIndex=%d)",
137     Ipv6Flag ? L"IPv6" : L"IPv4",
138     NicIndex
139   );
140 
141   if (gIScsiControllerNameTable != NULL) {
142     FreeUnicodeStringTable (gIScsiControllerNameTable);
143     gIScsiControllerNameTable = NULL;
144   }
145 
146   Status = AddUnicodeString2 (
147              "eng",
148              gIScsiComponentName.SupportedLanguages,
149              &gIScsiControllerNameTable,
150              HandleName,
151              TRUE
152              );
153   if (EFI_ERROR (Status)) {
154     return Status;
155   }
156 
157   return AddUnicodeString2 (
158            "en",
159            gIScsiComponentName2.SupportedLanguages,
160            &gIScsiControllerNameTable,
161            HandleName,
162            FALSE
163            );
164 }
165 
166 /**
167   Retrieves a Unicode string that is the user readable name of the controller
168   that is being managed by a driver.
169 
170   This function retrieves the user readable name of the controller specified by
171   ControllerHandle and ChildHandle in the form of a Unicode string. If the
172   driver specified by This has a user readable name in the language specified by
173   Language, then a pointer to the controller name is returned in ControllerName,
174   and EFI_SUCCESS is returned.  If the driver specified by This is not currently
175   managing the controller specified by ControllerHandle and ChildHandle,
176   then EFI_UNSUPPORTED is returned.  If the driver specified by This does not
177   support the language specified by Language, then EFI_UNSUPPORTED is returned.
178 
179   @param[in]  This              A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
180                                 EFI_COMPONENT_NAME_PROTOCOL instance.
181 
182   @param[in]  ControllerHandle  The handle of a controller that the driver
183                                 specified by This is managing.  This handle
184                                 specifies the controller whose name is to be
185                                 returned.
186 
187   @param[in]  ChildHandle       The handle of the child controller to retrieve
188                                 the name of.  This is an optional parameter that
189                                 may be NULL.  It will be NULL for device
190                                 drivers.  It will also be NULL for a bus drivers
191                                 that wish to retrieve the name of the bus
192                                 controller.  It will not be NULL for a bus
193                                 driver that wishes to retrieve the name of a
194                                 child controller.
195 
196   @param[in]  Language          A pointer to a Null-terminated ASCII string
197                                 array indicating the language.  This is the
198                                 language of the driver name that the caller is
199                                 requesting, and it must match one of the
200                                 languages specified in SupportedLanguages. The
201                                 number of languages supported by a driver is up
202                                 to the driver writer. Language is specified in
203                                 RFC 4646 or ISO 639-2 language code format.
204 
205   @param[out]  ControllerName   A pointer to the Unicode string to return.
206                                 This Unicode string is the name of the
207                                 controller specified by ControllerHandle and
208                                 ChildHandle in the language specified by
209                                 Language, from the point of view of the driver
210                                 specified by This.
211 
212   @retval EFI_SUCCESS           The Unicode string for the user readable name in
213                                 the language specified by Language for the
214                                 driver specified by This was returned in
215                                 DriverName.
216 
217   @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.
218 
219   @retval EFI_INVALID_PARAMETER ChildHandle is not NULL, and it is not a valid
220                                 EFI_HANDLE.
221 
222   @retval EFI_INVALID_PARAMETER Language is NULL.
223 
224   @retval EFI_INVALID_PARAMETER ControllerName is NULL.
225 
226   @retval EFI_UNSUPPORTED       The driver specified by This is not currently
227                                 managing the controller specified by
228                                 ControllerHandle and ChildHandle.
229 
230   @retval EFI_UNSUPPORTED       The driver specified by This does not support
231                                 the language specified by Language.
232 
233 **/
234 EFI_STATUS
235 EFIAPI
IScsiComponentNameGetControllerName(IN EFI_COMPONENT_NAME_PROTOCOL * This,IN EFI_HANDLE ControllerHandle,IN EFI_HANDLE ChildHandle OPTIONAL,IN CHAR8 * Language,OUT CHAR16 ** ControllerName)236 IScsiComponentNameGetControllerName (
237   IN  EFI_COMPONENT_NAME_PROTOCOL   *This,
238   IN  EFI_HANDLE                    ControllerHandle,
239   IN  EFI_HANDLE                    ChildHandle        OPTIONAL,
240   IN  CHAR8                         *Language,
241   OUT CHAR16                        **ControllerName
242   )
243 {
244   EFI_STATUS                      Status;
245 
246   EFI_HANDLE                      IScsiController;
247   BOOLEAN                         Ipv6Flag;
248   EFI_GUID                        *IScsiPrivateGuid;
249   ISCSI_PRIVATE_PROTOCOL          *IScsiIdentifier;
250 
251   EFI_EXT_SCSI_PASS_THRU_PROTOCOL *IScsiExtScsiPassThru;
252 
253   if (ControllerHandle == NULL) {
254     return EFI_UNSUPPORTED;
255   }
256 
257   //
258   // Get the handle of the controller we are controling.
259   //
260   IScsiController = NetLibGetNicHandle (ControllerHandle, &gEfiTcp4ProtocolGuid);
261   if (IScsiController != NULL) {
262     IScsiPrivateGuid = &gIScsiV4PrivateGuid;
263     Ipv6Flag = FALSE;
264   } else {
265     IScsiController = NetLibGetNicHandle (ControllerHandle, &gEfiTcp6ProtocolGuid);
266     if (IScsiController != NULL) {
267       IScsiPrivateGuid = &gIScsiV6PrivateGuid;
268       Ipv6Flag = TRUE;
269     } else {
270       return EFI_UNSUPPORTED;
271     }
272   }
273 
274   Status = gBS->OpenProtocol (
275                   IScsiController,
276                   IScsiPrivateGuid,
277                   (VOID **) &IScsiIdentifier,
278                   NULL,
279                   NULL,
280                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
281                   );
282   if (EFI_ERROR (Status)) {
283     return Status;
284   }
285 
286   if(ChildHandle != NULL) {
287     if(!Ipv6Flag) {
288       //
289       // Make sure this driver produced ChildHandle
290       //
291       Status = EfiTestChildHandle (
292                  ControllerHandle,
293                  ChildHandle,
294                  &gEfiTcp4ProtocolGuid
295                  );
296       if (EFI_ERROR (Status)) {
297         return Status;
298       }
299     } else {
300       //
301       // Make sure this driver produced ChildHandle
302       //
303       Status = EfiTestChildHandle (
304                  ControllerHandle,
305                  ChildHandle,
306                  &gEfiTcp6ProtocolGuid
307                  );
308       if (EFI_ERROR (Status)) {
309         return Status;
310       }
311     }
312 
313     //
314     // Retrieve an instance of a produced protocol from ChildHandle
315     //
316     Status = gBS->OpenProtocol (
317                     ChildHandle,
318                     &gEfiExtScsiPassThruProtocolGuid,
319                    (VOID **)&IScsiExtScsiPassThru,
320                     NULL,
321                     NULL,
322                     EFI_OPEN_PROTOCOL_GET_PROTOCOL
323                     );
324     if (EFI_ERROR (Status)) {
325       return Status;
326     }
327 
328     //
329     // Update the component name for this child handle.
330     //
331     Status = UpdateName (IScsiExtScsiPassThru, Ipv6Flag);
332     if (EFI_ERROR (Status)) {
333       return Status;
334     }
335   }
336 
337   return LookupUnicodeString2 (
338            Language,
339            This->SupportedLanguages,
340            gIScsiControllerNameTable,
341            ControllerName,
342            (BOOLEAN)(This == &gIScsiComponentName)
343            );
344 }
345