]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Network/IScsiDxe/IScsiConfig.c
update file header
[mirror_edk2.git] / MdeModulePkg / Universal / Network / IScsiDxe / IScsiConfig.c
CommitLineData
12618416 1/** @file\r
669314e5 2 Helper functions for configuring or getting the parameters relating to ISCSI.\r
6a690e23 3\r
669314e5 4Copyright (c) 2004 - 2008, Intel Corporation.<BR>\r
7a444476 5All rights reserved. This program and the accompanying materials\r
6are licensed and made available under the terms and conditions of the BSD License\r
7which accompanies this distribution. The full text of the license may be found at\r
8http://opensource.org/licenses/bsd-license.php\r
9\r
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
6a690e23 12\r
12618416 13**/\r
6a690e23 14\r
15#include "IScsiImpl.h"\r
16\r
f2a94e25 17EFI_GUID mVendorGuid = ISCSI_CONFIG_GUID;\r
18BOOLEAN mIScsiDeviceListUpdated = FALSE;\r
19UINTN mNumberOfIScsiDevices = 0;\r
20ISCSI_FORM_CALLBACK_INFO *mCallbackInfo = NULL;\r
6a690e23 21\r
e48e37fc 22LIST_ENTRY mIScsiConfigFormList = {\r
6a690e23 23 &mIScsiConfigFormList,\r
24 &mIScsiConfigFormList\r
25};\r
26\r
12618416 27/**\r
28 Convert the IPv4 address into a dotted string.\r
29\r
669314e5 30 @param[in] Ip The IPv4 address.\r
31 @param[out] Str The dotted IP string.\r
12618416 32**/\r
6a690e23 33VOID\r
34IScsiIpToStr (\r
35 IN EFI_IPv4_ADDRESS *Ip,\r
36 OUT CHAR16 *Str\r
37 )\r
6a690e23 38{\r
39 UnicodeSPrint ( Str, 2 * IP4_STR_MAX_SIZE, L"%d.%d.%d.%d", Ip->Addr[0], Ip->Addr[1], Ip->Addr[2], Ip->Addr[3]);\r
40}\r
41\r
12618416 42/**\r
6a690e23 43 Pop up an invalid notify which displays the message in Warning.\r
44\r
669314e5 45 @param[in] Warning The warning message.\r
12618416 46**/\r
47VOID\r
48PopUpInvalidNotify (\r
49 IN CHAR16 *Warning\r
50 )\r
6a690e23 51{\r
6a690e23 52 EFI_INPUT_KEY Key;\r
6a690e23 53\r
93e3992d 54 IfrLibCreatePopUp (1, &Key, Warning);\r
6a690e23 55}\r
56\r
12618416 57/**\r
6a690e23 58 Update the list of iSCSI devices the iSCSI driver is controlling.\r
669314e5 59 \r
60 @retval EFI_SUCCESS The callback successfully handled the action.\r
61 @retval Others Some unexpected errors happened. \r
12618416 62**/\r
63EFI_STATUS\r
64IScsiUpdateDeviceList (\r
65 VOID\r
66 )\r
6a690e23 67{\r
68 EFI_STATUS Status;\r
69 ISCSI_DEVICE_LIST *DeviceList;\r
70 UINTN DataSize;\r
71 UINTN NumHandles;\r
72 EFI_HANDLE *Handles;\r
73 UINTN HandleIndex;\r
74 UINTN Index;\r
75 UINTN LastDeviceIndex;\r
76 EFI_SIMPLE_NETWORK_PROTOCOL *Snp;\r
77 EFI_SIMPLE_NETWORK_MODE *Mode;\r
78 ISCSI_MAC_INFO *CurMacInfo;\r
79 ISCSI_MAC_INFO TempMacInfo;\r
80 CHAR16 MacString[65];\r
81 UINTN DeviceListSize;\r
82\r
83 //\r
84 // Dump all the handles the Simple Network Protocol is installed on.\r
85 //\r
86 Status = gBS->LocateHandleBuffer (\r
87 ByProtocol,\r
88 &gEfiSimpleNetworkProtocolGuid,\r
89 NULL,\r
90 &NumHandles,\r
91 &Handles\r
92 );\r
93 if (EFI_ERROR (Status)) {\r
94 return Status;\r
95 }\r
96\r
97 DataSize = 0;\r
98 Status = gRT->GetVariable (\r
99 L"iSCSIDeviceList",\r
100 &mVendorGuid,\r
101 NULL,\r
102 &DataSize,\r
103 NULL\r
104 );\r
105 if (Status == EFI_BUFFER_TOO_SMALL) {\r
e48e37fc 106 DeviceList = (ISCSI_DEVICE_LIST *) AllocatePool (DataSize);\r
6a690e23 107\r
108 gRT->GetVariable (\r
109 L"iSCSIDeviceList",\r
110 &mVendorGuid,\r
111 NULL,\r
112 &DataSize,\r
113 DeviceList\r
114 );\r
115\r
116 LastDeviceIndex = 0;\r
117\r
118 for (HandleIndex = 0; HandleIndex < NumHandles; HandleIndex++) {\r
119 gBS->HandleProtocol (Handles[HandleIndex], &gEfiSimpleNetworkProtocolGuid, (VOID **)&Snp);\r
120\r
121 Mode = Snp->Mode;\r
122\r
123 for (Index = LastDeviceIndex; Index < DeviceList->NumDevice; Index++) {\r
124 CurMacInfo = &DeviceList->MacInfo[Index];\r
125 if ((CurMacInfo->Len == Mode->HwAddressSize) &&\r
126 (NET_MAC_EQUAL (&CurMacInfo->Mac, &Mode->PermanentAddress, Mode->HwAddressSize))\r
127 ) {\r
128 //\r
129 // The previous configured NIC is still here.\r
130 //\r
131 if (Index != LastDeviceIndex) {\r
132 //\r
133 // Swap the current MAC address entry with the one indexed by\r
134 // LastDeviceIndex.\r
135 //\r
e48e37fc 136 CopyMem (&TempMacInfo, CurMacInfo, sizeof (ISCSI_MAC_INFO));\r
137 CopyMem (CurMacInfo, &DeviceList->MacInfo[LastDeviceIndex], sizeof (ISCSI_MAC_INFO));\r
138 CopyMem (&DeviceList->MacInfo[LastDeviceIndex], &TempMacInfo, sizeof (ISCSI_MAC_INFO));\r
6a690e23 139 }\r
140\r
141 LastDeviceIndex++;\r
142 }\r
143 }\r
144\r
145 if (LastDeviceIndex == DeviceList->NumDevice) {\r
146 break;\r
147 }\r
148 }\r
149\r
150 for (Index = LastDeviceIndex; Index < DeviceList->NumDevice; Index++) {\r
151 //\r
152 // delete the variables\r
153 //\r
154 CurMacInfo = &DeviceList->MacInfo[Index];\r
155 IScsiMacAddrToStr (&CurMacInfo->Mac, CurMacInfo->Len, MacString);\r
156 gRT->SetVariable (MacString, &gEfiIScsiInitiatorNameProtocolGuid, 0, 0, NULL);\r
157 gRT->SetVariable (MacString, &mIScsiCHAPAuthInfoGuid, 0, 0, NULL);\r
158 }\r
159\r
e48e37fc 160 gBS->FreePool (DeviceList);\r
6a690e23 161 } else if (Status != EFI_NOT_FOUND) {\r
e48e37fc 162 gBS->FreePool (Handles);\r
6a690e23 163 return Status;\r
164 }\r
165 //\r
166 // Construct the new iSCSI device list.\r
167 //\r
168 DeviceListSize = sizeof (ISCSI_DEVICE_LIST) + (NumHandles - 1) * sizeof (ISCSI_MAC_INFO);\r
e48e37fc 169 DeviceList = (ISCSI_DEVICE_LIST *) AllocatePool (DeviceListSize);\r
6a690e23 170 DeviceList->NumDevice = (UINT8) NumHandles;\r
171\r
172 for (Index = 0; Index < NumHandles; Index++) {\r
173 gBS->HandleProtocol (Handles[Index], &gEfiSimpleNetworkProtocolGuid, (VOID **)&Snp);\r
174 Mode = Snp->Mode;\r
175\r
176 CurMacInfo = &DeviceList->MacInfo[Index];\r
e48e37fc 177 CopyMem (&CurMacInfo->Mac, &Mode->PermanentAddress, Mode->HwAddressSize);\r
6a690e23 178 CurMacInfo->Len = (UINT8) Mode->HwAddressSize;\r
179 }\r
180\r
181 gRT->SetVariable (\r
182 L"iSCSIDeviceList",\r
183 &mVendorGuid,\r
184 ISCSI_CONFIG_VAR_ATTR,\r
185 DeviceListSize,\r
186 DeviceList\r
187 );\r
188\r
e48e37fc 189 gBS->FreePool (DeviceList);\r
356e635c 190 gBS->FreePool (Handles);\r
6a690e23 191\r
192 return Status;\r
193}\r
194\r
12618416 195/**\r
196 Get the iSCSI configuration form entry by the index of the goto opcode actived.\r
197\r
669314e5 198 @param[in] Index The 0-based index of the goto opcode actived.\r
12618416 199\r
669314e5 200 @return The iSCSI configuration form entry found.\r
12618416 201**/\r
6a690e23 202ISCSI_CONFIG_FORM_ENTRY *\r
203IScsiGetConfigFormEntryByIndex (\r
204 IN UINT32 Index\r
205 )\r
6a690e23 206{\r
207 UINT32 CurrentIndex;\r
e48e37fc 208 LIST_ENTRY *Entry;\r
6a690e23 209 ISCSI_CONFIG_FORM_ENTRY *ConfigFormEntry;\r
210\r
211 CurrentIndex = 0;\r
212 ConfigFormEntry = NULL;\r
213\r
214 NET_LIST_FOR_EACH (Entry, &mIScsiConfigFormList) {\r
215 if (CurrentIndex == Index) {\r
216 ConfigFormEntry = NET_LIST_USER_STRUCT (Entry, ISCSI_CONFIG_FORM_ENTRY, Link);\r
217 break;\r
218 }\r
219\r
220 CurrentIndex++;\r
221 }\r
222\r
223 return ConfigFormEntry;\r
224}\r
225\r
12618416 226/**\r
227 Convert the iSCSI configuration data into the IFR data.\r
228\r
669314e5 229 @param[in] ConfigFormEntry The iSCSI configuration form entry.\r
230 @param[in] IfrNvData The IFR nv data.\r
12618416 231**/\r
6a690e23 232VOID\r
233IScsiConvertDeviceConfigDataToIfrNvData (\r
234 IN ISCSI_CONFIG_FORM_ENTRY *ConfigFormEntry,\r
235 IN ISCSI_CONFIG_IFR_NVDATA *IfrNvData\r
236 )\r
6a690e23 237{\r
238 ISCSI_SESSION_CONFIG_NVDATA *SessionConfigData;\r
239 ISCSI_CHAP_AUTH_CONFIG_NVDATA *AuthConfigData;\r
240\r
241 //\r
242 // Normal session configuration parameters.\r
243 //\r
244 SessionConfigData = &ConfigFormEntry->SessionConfigData;\r
245 IfrNvData->Enabled = SessionConfigData->Enabled;\r
246\r
247 IfrNvData->InitiatorInfoFromDhcp = SessionConfigData->InitiatorInfoFromDhcp;\r
248 IfrNvData->TargetInfoFromDhcp = SessionConfigData->TargetInfoFromDhcp;\r
249 IfrNvData->TargetPort = SessionConfigData->TargetPort;\r
250\r
251 IScsiIpToStr (&SessionConfigData->LocalIp, IfrNvData->LocalIp);\r
252 IScsiIpToStr (&SessionConfigData->SubnetMask, IfrNvData->SubnetMask);\r
253 IScsiIpToStr (&SessionConfigData->Gateway, IfrNvData->Gateway);\r
254 IScsiIpToStr (&SessionConfigData->TargetIp, IfrNvData->TargetIp);\r
255\r
256 IScsiAsciiStrToUnicodeStr (SessionConfigData->TargetName, IfrNvData->TargetName);\r
257\r
258 IScsiLunToUnicodeStr (SessionConfigData->BootLun, IfrNvData->BootLun);\r
259\r
260 //\r
261 // CHAP authentication parameters.\r
262 //\r
263 AuthConfigData = &ConfigFormEntry->AuthConfigData;\r
264\r
265 IfrNvData->CHAPType = AuthConfigData->CHAPType;\r
266\r
267 IScsiAsciiStrToUnicodeStr (AuthConfigData->CHAPName, IfrNvData->CHAPName);\r
268 IScsiAsciiStrToUnicodeStr (AuthConfigData->CHAPSecret, IfrNvData->CHAPSecret);\r
269 IScsiAsciiStrToUnicodeStr (AuthConfigData->ReverseCHAPName, IfrNvData->ReverseCHAPName);\r
270 IScsiAsciiStrToUnicodeStr (AuthConfigData->ReverseCHAPSecret, IfrNvData->ReverseCHAPSecret);\r
271}\r
272\r
12618416 273/**\r
669314e5 274 This function allows the caller to request the current\r
275 configuration for one or more named elements. The resulting\r
276 string is in <ConfigAltResp> format. Any and all alternative\r
277 configuration strings shall also be appended to the end of the\r
278 current configuration string. If they are, they must appear\r
279 after the current configuration. They must contain the same\r
280 routing (GUID, NAME, PATH) as the current configuration string.\r
281 They must have an additional description indicating the type of\r
282 alternative configuration the string represents,\r
283 "ALTCFG=<StringToken>". That <StringToken> (when\r
284 converted from Hex UNICODE to binary) is a reference to a\r
285 string in the associated string pack.\r
286\r
287 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
288 @param[in] Request A null-terminated Unicode string in\r
289 <ConfigRequest> format. Note that this\r
290 includes the routing information as well as\r
291 the configurable name / value pairs. It is\r
292 invalid for this string to be in\r
293 <MultiConfigRequest> format.\r
294 @param[out] Progress On return, points to a character in the\r
295 Request string. Points to the string's null\r
296 terminator if request was successful. Points\r
297 to the most recent "&" before the first\r
298 failing name / value pair (or the beginning\r
299 of the string if the failure is in the first\r
300 name / value pair) if the request was not\r
301 successful.\r
302 @param[out] Results A null-terminated Unicode string in\r
303 <ConfigAltResp> format which has all values\r
304 filled in for the names in the Request string.\r
305 String to be allocated by the called function.\r
306\r
307 @retval EFI_SUCCESS The Results string is filled with the\r
308 values corresponding to all requested\r
309 names.\r
310 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the\r
311 parts of the results that must be\r
312 stored awaiting possible future\r
313 protocols.\r
314 @retval EFI_INVALID_PARAMETER For example, passing in a NULL\r
315 for the Request parameter\r
316 would result in this type of\r
317 error. In this case, the\r
318 Progress parameter would be\r
319 set to NULL. \r
320 @retval EFI_NOT_FOUND Routing data doesn't match any\r
321 known driver. Progress set to the\r
322 first character in the routing header.\r
323 Note: There is no requirement that the\r
324 driver validate the routing data. It\r
325 must skip the <ConfigHdr> in order to\r
326 process the names.\r
327 @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set\r
328 to most recent & before the\r
329 error or the beginning of the\r
330 string.\r
331 @retval EFI_INVALID_PARAMETER Unknown name. Progress points\r
332 to the & before the name in\r
333 question.Currently not implemented.\r
12618416 334**/\r
6a690e23 335EFI_STATUS\r
336EFIAPI\r
93e3992d 337IScsiFormExtractConfig (\r
338 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
339 IN CONST EFI_STRING Request,\r
340 OUT EFI_STRING *Progress,\r
341 OUT EFI_STRING *Results\r
6a690e23 342 )\r
6a690e23 343{\r
93e3992d 344 EFI_STATUS Status;\r
345 CHAR8 InitiatorName[ISCSI_NAME_IFR_MAX_SIZE];\r
346 UINTN BufferSize;\r
347 ISCSI_CONFIG_IFR_NVDATA *IfrNvData;\r
348 ISCSI_FORM_CALLBACK_INFO *Private;\r
349 EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;\r
6a690e23 350\r
8d00a0f1 351 if (Request == NULL) {\r
669314e5 352 return EFI_INVALID_PARAMETER;\r
8d00a0f1 353 }\r
354\r
6a690e23 355 if (!mIScsiDeviceListUpdated) {\r
356 //\r
357 // Update the device list.\r
358 //\r
359 IScsiUpdateDeviceList ();\r
360 mIScsiDeviceListUpdated = TRUE;\r
361 }\r
362\r
93e3992d 363 Private = ISCSI_FORM_CALLBACK_INFO_FROM_FORM_CALLBACK (This);\r
364 IfrNvData = AllocateZeroPool (sizeof (ISCSI_CONFIG_IFR_NVDATA));\r
365 ASSERT (IfrNvData != NULL);\r
366 if (Private->Current != NULL) {\r
367 IScsiConvertDeviceConfigDataToIfrNvData (Private->Current, IfrNvData);\r
368 }\r
6a690e23 369\r
93e3992d 370 BufferSize = ISCSI_NAME_IFR_MAX_SIZE;\r
6a690e23 371 Status = gIScsiInitiatorName.Get (&gIScsiInitiatorName, &BufferSize, InitiatorName);\r
372 if (EFI_ERROR (Status)) {\r
373 IfrNvData->InitiatorName[0] = L'\0';\r
374 } else {\r
375 IScsiAsciiStrToUnicodeStr (InitiatorName, IfrNvData->InitiatorName);\r
376 }\r
377\r
93e3992d 378 //\r
379 // Convert buffer data to <ConfigResp> by helper function BlockToConfig()\r
380 //\r
381 HiiConfigRouting = Private->ConfigRouting;\r
382 BufferSize = sizeof (ISCSI_CONFIG_IFR_NVDATA);\r
383 Status = HiiConfigRouting->BlockToConfig (\r
384 HiiConfigRouting,\r
385 Request,\r
386 (UINT8 *) IfrNvData,\r
387 BufferSize,\r
388 Results,\r
389 Progress\r
390 );\r
e48e37fc 391 gBS->FreePool (IfrNvData);\r
93e3992d 392 return Status;\r
6a690e23 393}\r
394\r
12618416 395/**\r
669314e5 396 This function applies changes in a driver's configuration.\r
397 Input is a Configuration, which has the routing data for this\r
398 driver followed by name / value configuration pairs. The driver\r
399 must apply those pairs to its configurable storage. If the\r
400 driver's configuration is stored in a linear block of data\r
401 and the driver????s name / value pairs are in <BlockConfig>\r
402 format, it may use the ConfigToBlock helper function (above) to\r
403 simplify the job. Currently not implemented.\r
404\r
405 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
406 @param[in] Configuration A null-terminated Unicode string in\r
407 <ConfigString> format. \r
408 @param[out] Progress A pointer to a string filled in with the\r
409 offset of the most recent '&' before the\r
410 first failing name / value pair (or the\r
411 beginn ing of the string if the failure\r
412 is in the first name / value pair) or\r
413 the terminating NULL if all was\r
414 successful.\r
415\r
416 @retval EFI_SUCCESS The results have been distributed or are\r
417 awaiting distribution. \r
418 @retval EFI_OUT_OF_MEMORY Not enough memory to store the\r
419 parts of the results that must be\r
420 stored awaiting possible future\r
421 protocols.\r
422 @retval EFI_INVALID_PARAMETERS Passing in a NULL for the\r
423 Results parameter would result\r
424 in this type of error.\r
425 @retval EFI_NOT_FOUND Target for the specified routing data\r
426 was not found.\r
12618416 427**/\r
6a690e23 428EFI_STATUS\r
429EFIAPI\r
93e3992d 430IScsiFormRouteConfig (\r
431 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
432 IN CONST EFI_STRING Configuration,\r
433 OUT EFI_STRING *Progress\r
6a690e23 434 )\r
12618416 435{\r
436 return EFI_SUCCESS;\r
437}\r
6a690e23 438\r
12618416 439/**\r
669314e5 440 This function is called to provide results data to the driver.\r
441 This data consists of a unique key that is used to identify\r
442 which data is either being passed back or being asked for.\r
443\r
444 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
445 @param[in] Action Specifies the type of action taken by the browser.\r
446 @param[in] QuestionId A unique value which is sent to the original\r
447 exporting driver so that it can identify the type\r
448 of data to expect. The format of the data tends to \r
449 vary based on the opcode that enerated the callback.\r
450 @param[in] Type The type of value for the question.\r
451 @param[in] Value A pointer to the data being sent to the original\r
452 exporting driver.\r
453 @param[out] ActionRequest On return, points to the action requested by the\r
454 callback function.\r
455\r
456 @retval EFI_SUCCESS The callback successfully handled the action.\r
457 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the\r
458 variable and its data.\r
459 @retval EFI_DEVICE_ERROR The variable could not be saved.\r
460 @retval EFI_UNSUPPORTED The specified Action is not supported by the\r
461 callback.Currently not implemented.\r
462 @retval EFI_INVALID_PARAMETERS Passing in wrong parameter. \r
463 @retval Others Some unexpected error happened. \r
12618416 464**/\r
93e3992d 465EFI_STATUS\r
466EFIAPI\r
467IScsiFormCallback (\r
468 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
469 IN EFI_BROWSER_ACTION Action,\r
669314e5 470 IN EFI_QUESTION_ID QuestionId,\r
93e3992d 471 IN UINT8 Type,\r
472 IN EFI_IFR_TYPE_VALUE *Value,\r
473 OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest\r
474 )\r
6a690e23 475{\r
476 ISCSI_FORM_CALLBACK_INFO *Private;\r
477 UINTN BufferSize;\r
478 CHAR8 IScsiName[ISCSI_NAME_IFR_MAX_SIZE];\r
479 CHAR16 PortString[128];\r
480 CHAR8 Ip4String[IP4_STR_MAX_SIZE];\r
481 CHAR8 LunString[ISCSI_LUN_STR_MAX_LEN];\r
482 UINT64 Lun;\r
6c7a807a 483 EFI_STRING_ID DeviceFormTitleToken;\r
6a690e23 484 ISCSI_CONFIG_IFR_NVDATA *IfrNvData;\r
485 ISCSI_CONFIG_FORM_ENTRY *ConfigFormEntry;\r
486 EFI_IP_ADDRESS HostIp;\r
487 EFI_IP_ADDRESS SubnetMask;\r
488 EFI_IP_ADDRESS Gateway;\r
489 EFI_STATUS Status;\r
490\r
491 Private = ISCSI_FORM_CALLBACK_INFO_FROM_FORM_CALLBACK (This);\r
93e3992d 492\r
493 //\r
494 // Retrive uncommitted data from Browser\r
495 //\r
496 BufferSize = sizeof (ISCSI_CONFIG_IFR_NVDATA);\r
497 IfrNvData = AllocateZeroPool (BufferSize);\r
498 ASSERT (IfrNvData != NULL);\r
499 Status = GetBrowserData (NULL, NULL, &BufferSize, (UINT8 *) IfrNvData);\r
500 if (EFI_ERROR (Status)) {\r
501 gBS->FreePool (IfrNvData);\r
502 return Status;\r
503 }\r
6a690e23 504\r
669314e5 505 switch (QuestionId) {\r
6a690e23 506 case KEY_INITIATOR_NAME:\r
507 IScsiUnicodeStrToAsciiStr (IfrNvData->InitiatorName, IScsiName);\r
508 BufferSize = AsciiStrLen (IScsiName) + 1;\r
509\r
510 Status = gIScsiInitiatorName.Set (&gIScsiInitiatorName, &BufferSize, IScsiName);\r
511 if (EFI_ERROR (Status)) {\r
512 PopUpInvalidNotify (L"Invalid iSCSI Name!");\r
513 }\r
514\r
515 break;\r
516\r
517 case KEY_LOCAL_IP:\r
518 IScsiUnicodeStrToAsciiStr (IfrNvData->LocalIp, Ip4String);\r
519 Status = IScsiAsciiStrToIp (Ip4String, &HostIp.v4);\r
520 if (EFI_ERROR (Status) || !Ip4IsUnicast (NTOHL (HostIp.Addr[0]), 0)) {\r
521 PopUpInvalidNotify (L"Invalid IP address!");\r
522 Status = EFI_INVALID_PARAMETER;\r
523 } else {\r
e48e37fc 524 CopyMem (&Private->Current->SessionConfigData.LocalIp, &HostIp.v4, sizeof (HostIp.v4));\r
6a690e23 525 }\r
526\r
527 break;\r
528\r
529 case KEY_SUBNET_MASK:\r
530 IScsiUnicodeStrToAsciiStr (IfrNvData->SubnetMask, Ip4String);\r
531 Status = IScsiAsciiStrToIp (Ip4String, &SubnetMask.v4);\r
532 if (EFI_ERROR (Status) || ((SubnetMask.Addr[0] != 0) && (IScsiGetSubnetMaskPrefixLength (&SubnetMask.v4) == 0))) {\r
533 PopUpInvalidNotify (L"Invalid Subnet Mask!");\r
534 Status = EFI_INVALID_PARAMETER;\r
535 } else {\r
e48e37fc 536 CopyMem (&Private->Current->SessionConfigData.SubnetMask, &SubnetMask.v4, sizeof (SubnetMask.v4));\r
6a690e23 537 }\r
538\r
539 break;\r
540\r
541 case KEY_GATE_WAY:\r
542 IScsiUnicodeStrToAsciiStr (IfrNvData->Gateway, Ip4String);\r
543 Status = IScsiAsciiStrToIp (Ip4String, &Gateway.v4);\r
544 if (EFI_ERROR (Status) || ((Gateway.Addr[0] != 0) && !Ip4IsUnicast (NTOHL (Gateway.Addr[0]), 0))) {\r
545 PopUpInvalidNotify (L"Invalid Gateway!");\r
546 Status = EFI_INVALID_PARAMETER;\r
547 } else {\r
e48e37fc 548 CopyMem (&Private->Current->SessionConfigData.Gateway, &Gateway.v4, sizeof (Gateway.v4));\r
6a690e23 549 }\r
550\r
551 break;\r
552\r
553 case KEY_TARGET_IP:\r
554 IScsiUnicodeStrToAsciiStr (IfrNvData->TargetIp, Ip4String);\r
555 Status = IScsiAsciiStrToIp (Ip4String, &HostIp.v4);\r
556 if (EFI_ERROR (Status) || !Ip4IsUnicast (NTOHL (HostIp.Addr[0]), 0)) {\r
557 PopUpInvalidNotify (L"Invalid IP address!");\r
558 Status = EFI_INVALID_PARAMETER;\r
559 } else {\r
e48e37fc 560 CopyMem (&Private->Current->SessionConfigData.TargetIp, &HostIp.v4, sizeof (HostIp.v4));\r
6a690e23 561 }\r
562\r
563 break;\r
564\r
565 case KEY_TARGET_NAME:\r
566 IScsiUnicodeStrToAsciiStr (IfrNvData->TargetName, IScsiName);\r
567 Status = IScsiNormalizeName (IScsiName, AsciiStrLen (IScsiName));\r
568 if (EFI_ERROR (Status)) {\r
569 PopUpInvalidNotify (L"Invalid iSCSI Name!");\r
570 } else {\r
571 AsciiStrCpy (Private->Current->SessionConfigData.TargetName, IScsiName);\r
572 }\r
573\r
574 break;\r
575\r
576 case KEY_DHCP_ENABLE:\r
577 if (IfrNvData->InitiatorInfoFromDhcp == 0) {\r
578 IfrNvData->TargetInfoFromDhcp = 0;\r
579 }\r
580\r
581 break;\r
582\r
583 case KEY_BOOT_LUN:\r
584 IScsiUnicodeStrToAsciiStr (IfrNvData->BootLun, LunString);\r
585 Status = IScsiAsciiStrToLun (LunString, (UINT8 *) &Lun);\r
586 if (EFI_ERROR (Status)) {\r
587 PopUpInvalidNotify (L"Invalid LUN string!");\r
588 } else {\r
e48e37fc 589 CopyMem (Private->Current->SessionConfigData.BootLun, &Lun, sizeof (Lun));\r
6a690e23 590 }\r
591\r
592 break;\r
593\r
594 case KEY_CHAP_NAME:\r
595 IScsiUnicodeStrToAsciiStr (IfrNvData->CHAPName, Private->Current->AuthConfigData.CHAPName);\r
596 break;\r
597\r
598 case KEY_CHAP_SECRET:\r
599 IScsiUnicodeStrToAsciiStr (IfrNvData->CHAPSecret, Private->Current->AuthConfigData.CHAPSecret);\r
600 break;\r
601\r
602 case KEY_REVERSE_CHAP_NAME:\r
603 IScsiUnicodeStrToAsciiStr (IfrNvData->ReverseCHAPName, Private->Current->AuthConfigData.ReverseCHAPName);\r
604 break;\r
605\r
606 case KEY_REVERSE_CHAP_SECRET:\r
607 IScsiUnicodeStrToAsciiStr (IfrNvData->ReverseCHAPSecret, Private->Current->AuthConfigData.ReverseCHAPSecret);\r
608 break;\r
609\r
610 case KEY_SAVE_CHANGES:\r
611 //\r
612 // First, update those fields which don't have INTERACTIVE set.\r
613 //\r
614 Private->Current->SessionConfigData.Enabled = IfrNvData->Enabled;\r
615 Private->Current->SessionConfigData.InitiatorInfoFromDhcp = IfrNvData->InitiatorInfoFromDhcp;\r
616 Private->Current->SessionConfigData.TargetPort = IfrNvData->TargetPort;\r
617 if (Private->Current->SessionConfigData.TargetPort == 0) {\r
618 Private->Current->SessionConfigData.TargetPort = ISCSI_WELL_KNOWN_PORT;\r
619 }\r
620\r
621 Private->Current->SessionConfigData.TargetInfoFromDhcp = IfrNvData->TargetInfoFromDhcp;\r
622 Private->Current->AuthConfigData.CHAPType = IfrNvData->CHAPType;\r
623\r
624 //\r
625 // Only do full parameter validation if iSCSI is enabled on this device.\r
626 //\r
627 if (Private->Current->SessionConfigData.Enabled) {\r
628 //\r
629 // Validate the address configuration of the Initiator if DHCP isn't\r
630 // deployed.\r
631 //\r
632 if (!Private->Current->SessionConfigData.InitiatorInfoFromDhcp) {\r
e48e37fc 633 CopyMem (&HostIp.v4, &Private->Current->SessionConfigData.LocalIp, sizeof (HostIp.v4));\r
634 CopyMem (&SubnetMask.v4, &Private->Current->SessionConfigData.SubnetMask, sizeof (SubnetMask.v4));\r
635 CopyMem (&Gateway.v4, &Private->Current->SessionConfigData.Gateway, sizeof (Gateway.v4));\r
6a690e23 636\r
637 if ((Gateway.Addr[0] != 0)) {\r
638 if (SubnetMask.Addr[0] == 0) {\r
639 PopUpInvalidNotify (L"Gateway address is set but subnet mask is zero.");\r
640 Status = EFI_INVALID_PARAMETER;\r
641 break;\r
642 } else if (!IP4_NET_EQUAL (HostIp.Addr[0], Gateway.Addr[0], SubnetMask.Addr[0])) {\r
643 PopUpInvalidNotify (L"Local IP and Gateway are not in the same subnet.");\r
644 Status = EFI_INVALID_PARAMETER;\r
645 break;\r
646 }\r
647 }\r
648 }\r
649 //\r
650 // Validate target configuration if DHCP isn't deployed.\r
651 //\r
652 if (!Private->Current->SessionConfigData.TargetInfoFromDhcp) {\r
e48e37fc 653 CopyMem (&HostIp.v4, &Private->Current->SessionConfigData.TargetIp, sizeof (HostIp.v4));\r
6a690e23 654 if (!Ip4IsUnicast (NTOHL (HostIp.Addr[0]), 0)) {\r
655 PopUpInvalidNotify (L"Target IP is invalid!");\r
656 Status = EFI_INVALID_PARAMETER;\r
657 break;\r
658 }\r
659 }\r
660\r
661 if (IfrNvData->CHAPType != ISCSI_CHAP_NONE) {\r
662 if ((IfrNvData->CHAPName[0] == '\0') || (IfrNvData->CHAPSecret[0] == '\0')) {\r
663 PopUpInvalidNotify (L"CHAP Name or CHAP Secret is invalid!");\r
664 Status = EFI_INVALID_PARAMETER;\r
665 break;\r
666 }\r
667\r
668 if ((IfrNvData->CHAPType == ISCSI_CHAP_MUTUAL) &&\r
669 ((IfrNvData->ReverseCHAPName[0] == '\0') || (IfrNvData->ReverseCHAPSecret[0] == '\0'))\r
670 ) {\r
671 PopUpInvalidNotify (L"Reverse CHAP Name or Reverse CHAP Secret is invalid!");\r
672 Status = EFI_INVALID_PARAMETER;\r
673 break;\r
674 }\r
675 }\r
676 }\r
677\r
678 BufferSize = sizeof (Private->Current->SessionConfigData);\r
679 gRT->SetVariable (\r
680 Private->Current->MacString,\r
681 &gEfiIScsiInitiatorNameProtocolGuid,\r
682 ISCSI_CONFIG_VAR_ATTR,\r
683 BufferSize,\r
684 &Private->Current->SessionConfigData\r
685 );\r
686\r
687 BufferSize = sizeof (Private->Current->AuthConfigData);\r
688 gRT->SetVariable (\r
689 Private->Current->MacString,\r
690 &mIScsiCHAPAuthInfoGuid,\r
691 ISCSI_CONFIG_VAR_ATTR,\r
692 BufferSize,\r
693 &Private->Current->AuthConfigData\r
694 );\r
93e3992d 695 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT;\r
6a690e23 696 break;\r
697\r
698 default:\r
669314e5 699 if ((QuestionId >= KEY_DEVICE_ENTRY_BASE) && (QuestionId < (mNumberOfIScsiDevices + KEY_DEVICE_ENTRY_BASE))) {\r
6a690e23 700 //\r
701 // In case goto the device configuration form, update the device form title.\r
702 //\r
669314e5 703 ConfigFormEntry = IScsiGetConfigFormEntryByIndex ((UINT32) (QuestionId - KEY_DEVICE_ENTRY_BASE));\r
6a690e23 704 ASSERT (ConfigFormEntry != NULL);\r
705\r
93e3992d 706 UnicodeSPrint (PortString, (UINTN) 128, L"Port %s", ConfigFormEntry->MacString);\r
6c7a807a 707 DeviceFormTitleToken = (EFI_STRING_ID) STR_ISCSI_DEVICE_FORM_TITLE;\r
9226efe5 708 HiiLibSetString (Private->RegisteredHandle, DeviceFormTitleToken, PortString);\r
6a690e23 709\r
710 IScsiConvertDeviceConfigDataToIfrNvData (ConfigFormEntry, IfrNvData);\r
711\r
712 Private->Current = ConfigFormEntry;\r
713 }\r
714\r
715 break;\r
716 }\r
717\r
93e3992d 718 if (!EFI_ERROR (Status)) {\r
719 //\r
720 // Pass changed uncommitted data back to Form Browser\r
721 //\r
722 BufferSize = sizeof (ISCSI_CONFIG_IFR_NVDATA);\r
723 Status = SetBrowserData (NULL, NULL, BufferSize, (UINT8 *) IfrNvData, NULL);\r
724 }\r
725\r
e48e37fc 726 gBS->FreePool (IfrNvData);\r
6a690e23 727 return Status;\r
728}\r
729\r
12618416 730/**\r
6a690e23 731 Updates the iSCSI configuration form to add/delete an entry for the iSCSI\r
732 device specified by the Controller.\r
733\r
669314e5 734 @param[in] DriverBindingHandle The driverbinding handle.\r
735 @param[in] Controller The controller handle of the iSCSI device.\r
736 @param[in] AddForm Whether to add or delete a form entry.\r
6a690e23 737\r
12618416 738 @retval EFI_SUCCESS The iSCSI configuration form is updated.\r
12618416 739 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
669314e5 740 @retval Others Some unexpected errors happened.\r
12618416 741**/\r
742EFI_STATUS\r
743IScsiConfigUpdateForm (\r
744 IN EFI_HANDLE DriverBindingHandle,\r
745 IN EFI_HANDLE Controller,\r
746 IN BOOLEAN AddForm\r
747 )\r
6a690e23 748{\r
e48e37fc 749 LIST_ENTRY *Entry;\r
6a690e23 750 ISCSI_CONFIG_FORM_ENTRY *ConfigFormEntry;\r
751 BOOLEAN EntryExisted;\r
6a690e23 752 EFI_STATUS Status;\r
93e3992d 753 EFI_HII_UPDATE_DATA UpdateData;\r
6a690e23 754 EFI_SIMPLE_NETWORK_PROTOCOL *Snp;\r
755 CHAR16 PortString[128];\r
756 UINT16 FormIndex;\r
757 UINTN BufferSize;\r
758\r
6a690e23 759\r
760 ConfigFormEntry = NULL;\r
761 EntryExisted = FALSE;\r
762\r
763 NET_LIST_FOR_EACH (Entry, &mIScsiConfigFormList) {\r
764 ConfigFormEntry = NET_LIST_USER_STRUCT (Entry, ISCSI_CONFIG_FORM_ENTRY, Link);\r
765\r
766 if (ConfigFormEntry->Controller == Controller) {\r
767 EntryExisted = TRUE;\r
768 break;\r
769 }\r
770 }\r
771\r
772 if (AddForm) {\r
773 if (EntryExisted) {\r
774 return EFI_SUCCESS;\r
775 } else {\r
776 //\r
777 // Add a new form.\r
778 //\r
e48e37fc 779 ConfigFormEntry = (ISCSI_CONFIG_FORM_ENTRY *) AllocateZeroPool (sizeof (ISCSI_CONFIG_FORM_ENTRY));\r
6a690e23 780 if (ConfigFormEntry == NULL) {\r
781 return EFI_OUT_OF_RESOURCES;\r
782 }\r
783\r
e48e37fc 784 InitializeListHead (&ConfigFormEntry->Link);\r
6a690e23 785 ConfigFormEntry->Controller = Controller;\r
786\r
787 //\r
788 // Get the simple network protocol and convert the MAC address into\r
789 // the formatted string.\r
790 //\r
791 Status = gBS->HandleProtocol (\r
792 Controller,\r
793 &gEfiSimpleNetworkProtocolGuid,\r
794 (VOID **)&Snp\r
795 );\r
796 ASSERT (Status == EFI_SUCCESS);\r
797\r
798 IScsiMacAddrToStr (&Snp->Mode->PermanentAddress, Snp->Mode->HwAddressSize, ConfigFormEntry->MacString);\r
799\r
800 //\r
801 // Get the normal session configuration data.\r
802 //\r
803 BufferSize = sizeof (ConfigFormEntry->SessionConfigData);\r
804 Status = gRT->GetVariable (\r
805 ConfigFormEntry->MacString,\r
806 &gEfiIScsiInitiatorNameProtocolGuid,\r
807 NULL,\r
808 &BufferSize,\r
809 &ConfigFormEntry->SessionConfigData\r
810 );\r
811 if (EFI_ERROR (Status)) {\r
e48e37fc 812 ZeroMem (&ConfigFormEntry->SessionConfigData, sizeof (ConfigFormEntry->SessionConfigData));\r
6a690e23 813 }\r
814 //\r
815 // Get the CHAP authentication configuration data.\r
816 //\r
817 BufferSize = sizeof (ConfigFormEntry->AuthConfigData);\r
818 Status = gRT->GetVariable (\r
819 ConfigFormEntry->MacString,\r
820 &mIScsiCHAPAuthInfoGuid,\r
821 NULL,\r
822 &BufferSize,\r
823 &ConfigFormEntry->AuthConfigData\r
824 );\r
825 if (EFI_ERROR (Status)) {\r
e48e37fc 826 ZeroMem (&ConfigFormEntry->AuthConfigData, sizeof (ConfigFormEntry->AuthConfigData));\r
6a690e23 827 }\r
828 //\r
6c7a807a 829 // Compose the Port string and create a new EFI_STRING_ID.\r
6a690e23 830 //\r
831 UnicodeSPrint (PortString, 128, L"Port %s", ConfigFormEntry->MacString);\r
9226efe5 832 HiiLibNewString (mCallbackInfo->RegisteredHandle, &ConfigFormEntry->PortTitleToken, PortString);\r
6a690e23 833\r
834 //\r
6c7a807a 835 // Compose the help string of this port and create a new EFI_STRING_ID.\r
6a690e23 836 //\r
837 UnicodeSPrint (PortString, 128, L"Set the iSCSI parameters on port %s", ConfigFormEntry->MacString);\r
9226efe5 838 HiiLibNewString (mCallbackInfo->RegisteredHandle, &ConfigFormEntry->PortTitleHelpToken, PortString);\r
6a690e23 839\r
e48e37fc 840 InsertTailList (&mIScsiConfigFormList, &ConfigFormEntry->Link);\r
6a690e23 841 mNumberOfIScsiDevices++;\r
842 }\r
843 } else {\r
844 ASSERT (EntryExisted);\r
845\r
846 mNumberOfIScsiDevices--;\r
e48e37fc 847 RemoveEntryList (&ConfigFormEntry->Link);\r
848 gBS->FreePool (ConfigFormEntry);\r
6a690e23 849 }\r
850 //\r
851 // Allocate space for creation of Buffer\r
852 //\r
93e3992d 853 UpdateData.BufferSize = 0x1000;\r
e48e37fc 854 UpdateData.Data = AllocateZeroPool (0x1000);\r
93e3992d 855 UpdateData.Offset = 0;\r
6a690e23 856\r
93e3992d 857 FormIndex = 0;\r
6a690e23 858 NET_LIST_FOR_EACH (Entry, &mIScsiConfigFormList) {\r
859 ConfigFormEntry = NET_LIST_USER_STRUCT (Entry, ISCSI_CONFIG_FORM_ENTRY, Link);\r
860\r
861 CreateGotoOpCode (\r
862 FORMID_DEVICE_FORM,\r
863 ConfigFormEntry->PortTitleToken,\r
864 ConfigFormEntry->PortTitleHelpToken,\r
93e3992d 865 EFI_IFR_FLAG_CALLBACK,\r
69b0882d 866 (UINT16)(KEY_DEVICE_ENTRY_BASE + FormIndex),\r
93e3992d 867 &UpdateData\r
6a690e23 868 );\r
869\r
6a690e23 870 FormIndex++;\r
871 }\r
872\r
93e3992d 873 IfrLibUpdateForm (\r
874 mCallbackInfo->RegisteredHandle,\r
875 &mVendorGuid,\r
876 FORMID_MAIN_FORM,\r
877 DEVICE_ENTRY_LABEL,\r
878 FALSE,\r
879 &UpdateData\r
880 );\r
881\r
e48e37fc 882 gBS->FreePool (UpdateData.Data);\r
6a690e23 883\r
884 return EFI_SUCCESS;\r
885}\r
886\r
12618416 887/**\r
6a690e23 888 Initialize the iSCSI configuration form.\r
889\r
669314e5 890 @param[in] DriverBindingHandle The iSCSI driverbinding handle.\r
6a690e23 891\r
669314e5 892 @retval EFI_SUCCESS The iSCSI configuration form is initialized.\r
893 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
894 @retval Others Some unexpected error happened.\r
12618416 895**/\r
896EFI_STATUS\r
897IScsiConfigFormInit (\r
898 IN EFI_HANDLE DriverBindingHandle\r
899 )\r
6a690e23 900{\r
93e3992d 901 EFI_STATUS Status;\r
902 EFI_HII_DATABASE_PROTOCOL *HiiDatabase;\r
903 EFI_HII_PACKAGE_LIST_HEADER *PackageList;\r
904 ISCSI_FORM_CALLBACK_INFO *CallbackInfo;\r
905\r
69b0882d 906 Status = gBS->LocateProtocol (&gEfiHiiDatabaseProtocolGuid, NULL, (VOID **)&HiiDatabase);\r
6a690e23 907 if (EFI_ERROR (Status)) {\r
93e3992d 908 return Status;\r
6a690e23 909 }\r
910\r
e48e37fc 911 CallbackInfo = (ISCSI_FORM_CALLBACK_INFO *) AllocatePool (sizeof (ISCSI_FORM_CALLBACK_INFO));\r
6a690e23 912 if (CallbackInfo == NULL) {\r
913 return EFI_OUT_OF_RESOURCES;\r
914 }\r
915\r
f2a94e25 916 CallbackInfo->Signature = ISCSI_FORM_CALLBACK_INFO_SIGNATURE;\r
93e3992d 917 CallbackInfo->HiiDatabase = HiiDatabase;\r
f2a94e25 918 CallbackInfo->Current = NULL;\r
6a690e23 919\r
93e3992d 920 CallbackInfo->ConfigAccess.ExtractConfig = IScsiFormExtractConfig;\r
921 CallbackInfo->ConfigAccess.RouteConfig = IScsiFormRouteConfig;\r
922 CallbackInfo->ConfigAccess.Callback = IScsiFormCallback;\r
6a690e23 923\r
69b0882d 924 Status = gBS->LocateProtocol (&gEfiHiiConfigRoutingProtocolGuid, NULL, (VOID **)&CallbackInfo->ConfigRouting);\r
93e3992d 925 if (EFI_ERROR (Status)) {\r
f2a94e25 926 FreePool(CallbackInfo);\r
93e3992d 927 return Status;\r
928 }\r
929\r
930 //\r
931 // Create driver handle used by HII database\r
932 //\r
933 Status = HiiLibCreateHiiDriverHandle (&CallbackInfo->DriverHandle);\r
934 if (EFI_ERROR (Status)) {\r
f2a94e25 935 FreePool(CallbackInfo);\r
93e3992d 936 return Status;\r
937 }\r
938 \r
6a690e23 939 //\r
93e3992d 940 // Install Config Access protocol to driver handle\r
6a690e23 941 //\r
942 Status = gBS->InstallProtocolInterface (\r
93e3992d 943 &CallbackInfo->DriverHandle,\r
944 &gEfiHiiConfigAccessProtocolGuid,\r
6a690e23 945 EFI_NATIVE_INTERFACE,\r
93e3992d 946 &CallbackInfo->ConfigAccess\r
6a690e23 947 );\r
6a690e23 948 ASSERT_EFI_ERROR (Status);\r
93e3992d 949 \r
6a690e23 950 //\r
93e3992d 951 // Publish our HII data\r
6a690e23 952 //\r
9226efe5 953 PackageList = HiiLibPreparePackageList (2, &mVendorGuid, IScsiDxeStrings, IScsiConfigDxeBin);\r
93e3992d 954 ASSERT (PackageList != NULL);\r
955 \r
956 Status = HiiDatabase->NewPackageList (\r
957 HiiDatabase,\r
958 PackageList,\r
959 CallbackInfo->DriverHandle,\r
960 &CallbackInfo->RegisteredHandle\r
961 );\r
f2a94e25 962 FreePool (PackageList);\r
93e3992d 963 if (EFI_ERROR (Status)) {\r
f2a94e25 964 FreePool(CallbackInfo);\r
93e3992d 965 return Status;\r
6a690e23 966 }\r
967\r
93e3992d 968 mCallbackInfo = CallbackInfo;\r
6a690e23 969\r
970 return Status;\r
971}\r
972\r
12618416 973/**\r
6a690e23 974 Unload the iSCSI configuration form, this includes: delete all the iSCSI\r
975 device configuration entries, uninstall the form callback protocol and\r
976 free the resources used.\r
977\r
669314e5 978 @param[in] DriverBindingHandle The iSCSI driverbinding handle.\r
979 \r
12618416 980 @retval EFI_SUCCESS The iSCSI configuration form is unloaded.\r
12618416 981 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
12618416 982**/\r
983EFI_STATUS\r
984IScsiConfigFormUnload (\r
985 IN EFI_HANDLE DriverBindingHandle\r
986 )\r
6a690e23 987{\r
988 ISCSI_CONFIG_FORM_ENTRY *ConfigFormEntry;\r
6a690e23 989\r
e48e37fc 990 while (!IsListEmpty (&mIScsiConfigFormList)) {\r
6a690e23 991 //\r
992 // Uninstall the device forms as the iSCSI driver instance may fail to\r
993 // control the controller but still install the device configuration form.\r
994 // In such case, upon driver unloading, the driver instance's driverbinding.\r
995 // stop () won't be called, so we have to take this chance here to uninstall\r
996 // the device form.\r
997 //\r
998 ConfigFormEntry = NET_LIST_USER_STRUCT (mIScsiConfigFormList.ForwardLink, ISCSI_CONFIG_FORM_ENTRY, Link);\r
999 IScsiConfigUpdateForm (DriverBindingHandle, ConfigFormEntry->Controller, FALSE);\r
1000 }\r
1001\r
6a690e23 1002 //\r
93e3992d 1003 // Remove HII package list\r
6a690e23 1004 //\r
93e3992d 1005 mCallbackInfo->HiiDatabase->RemovePackageList (\r
1006 mCallbackInfo->HiiDatabase,\r
1007 mCallbackInfo->RegisteredHandle\r
1008 );\r
6a690e23 1009\r
1010 //\r
93e3992d 1011 // Uninstall EFI_HII_CONFIG_ACCESS_PROTOCOL\r
6a690e23 1012 //\r
1013 gBS->UninstallProtocolInterface (\r
93e3992d 1014 mCallbackInfo->DriverHandle,\r
1015 &gEfiHiiConfigAccessProtocolGuid,\r
1016 &mCallbackInfo->ConfigAccess\r
6a690e23 1017 );\r
93e3992d 1018 HiiLibDestroyHiiDriverHandle (mCallbackInfo->DriverHandle);\r
6a690e23 1019\r
e48e37fc 1020 gBS->FreePool (mCallbackInfo);\r
6a690e23 1021\r
1022 return EFI_SUCCESS;\r
1023}\r