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