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