]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Network/IScsiDxe/IScsiConfig.c
Update the copyright notice format
[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
e5eed7d3
HT
4Copyright (c) 2004 - 2010, Intel Corporation. All rights reserved.<BR>\r
5This program and the accompanying materials\r
7a444476 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
59aefb7e
LG
363 EFI_STRING ConfigRequestHdr;\r
364 EFI_STRING ConfigRequest;\r
365 BOOLEAN AllocatedRequest;\r
366 UINTN Size;\r
6a690e23 367\r
59aefb7e 368 if (Progress == NULL || Results == NULL) {\r
669314e5 369 return EFI_INVALID_PARAMETER;\r
8d00a0f1 370 }\r
59aefb7e 371\r
ae79d2f9 372 *Progress = Request;\r
59aefb7e
LG
373 if ((Request != NULL) && !HiiIsConfigHdrMatch (Request, &mVendorGuid, mVendorStorageName)) {\r
374 return EFI_NOT_FOUND;\r
375 }\r
376\r
377 ConfigRequestHdr = NULL;\r
378 ConfigRequest = NULL;\r
379 AllocatedRequest = FALSE;\r
380 Size = 0;\r
8d00a0f1 381\r
6a690e23 382 if (!mIScsiDeviceListUpdated) {\r
383 //\r
384 // Update the device list.\r
385 //\r
386 IScsiUpdateDeviceList ();\r
387 mIScsiDeviceListUpdated = TRUE;\r
388 }\r
389\r
93e3992d 390 Private = ISCSI_FORM_CALLBACK_INFO_FROM_FORM_CALLBACK (This);\r
391 IfrNvData = AllocateZeroPool (sizeof (ISCSI_CONFIG_IFR_NVDATA));\r
392 ASSERT (IfrNvData != NULL);\r
393 if (Private->Current != NULL) {\r
394 IScsiConvertDeviceConfigDataToIfrNvData (Private->Current, IfrNvData);\r
395 }\r
6a690e23 396\r
93e3992d 397 BufferSize = ISCSI_NAME_IFR_MAX_SIZE;\r
6a690e23 398 Status = gIScsiInitiatorName.Get (&gIScsiInitiatorName, &BufferSize, InitiatorName);\r
399 if (EFI_ERROR (Status)) {\r
400 IfrNvData->InitiatorName[0] = L'\0';\r
401 } else {\r
402 IScsiAsciiStrToUnicodeStr (InitiatorName, IfrNvData->InitiatorName);\r
403 }\r
404\r
93e3992d 405 //\r
406 // Convert buffer data to <ConfigResp> by helper function BlockToConfig()\r
407 //\r
408 HiiConfigRouting = Private->ConfigRouting;\r
409 BufferSize = sizeof (ISCSI_CONFIG_IFR_NVDATA);\r
59aefb7e
LG
410 ConfigRequest = Request;\r
411 if ((Request == NULL) || (StrStr (Request, L"OFFSET") == NULL)) {\r
412 //\r
413 // Request has no request element, construct full request string.\r
414 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template\r
415 // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator\r
416 //\r
417 ConfigRequestHdr = HiiConstructConfigHdr (&mVendorGuid, mVendorStorageName, Private->DriverHandle);\r
418 Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16);\r
419 ConfigRequest = AllocateZeroPool (Size);\r
420 ASSERT (ConfigRequest != NULL);\r
421 AllocatedRequest = TRUE;\r
422 UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr, (UINT64)BufferSize);\r
423 FreePool (ConfigRequestHdr);\r
424 }\r
93e3992d 425 Status = HiiConfigRouting->BlockToConfig (\r
426 HiiConfigRouting,\r
59aefb7e 427 ConfigRequest,\r
93e3992d 428 (UINT8 *) IfrNvData,\r
429 BufferSize,\r
430 Results,\r
431 Progress\r
432 );\r
766c7483 433 FreePool (IfrNvData);\r
59aefb7e
LG
434 //\r
435 // Free the allocated config request string.\r
436 //\r
437 if (AllocatedRequest) {\r
438 FreePool (ConfigRequest);\r
439 ConfigRequest = NULL;\r
440 }\r
441\r
442 //\r
443 // Set Progress string to the original request string.\r
444 //\r
445 if (Request == NULL) {\r
446 *Progress = NULL;\r
447 } else if (StrStr (Request, L"OFFSET") == NULL) {\r
448 *Progress = Request + StrLen (Request);\r
449 }\r
450\r
93e3992d 451 return Status;\r
6a690e23 452}\r
453\r
12618416 454/**\r
669314e5 455 This function applies changes in a driver's configuration.\r
456 Input is a Configuration, which has the routing data for this\r
457 driver followed by name / value configuration pairs. The driver\r
458 must apply those pairs to its configurable storage. If the\r
459 driver's configuration is stored in a linear block of data\r
55a64ae0 460 and the driver's name / value pairs are in <BlockConfig>\r
669314e5 461 format, it may use the ConfigToBlock helper function (above) to\r
462 simplify the job. Currently not implemented.\r
463\r
464 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
465 @param[in] Configuration A null-terminated Unicode string in\r
466 <ConfigString> format. \r
467 @param[out] Progress A pointer to a string filled in with the\r
468 offset of the most recent '&' before the\r
469 first failing name / value pair (or the\r
470 beginn ing of the string if the failure\r
471 is in the first name / value pair) or\r
472 the terminating NULL if all was\r
473 successful.\r
474\r
475 @retval EFI_SUCCESS The results have been distributed or are\r
476 awaiting distribution. \r
e1f1fb16 477 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the\r
669314e5 478 parts of the results that must be\r
479 stored awaiting possible future\r
480 protocols.\r
481 @retval EFI_INVALID_PARAMETERS Passing in a NULL for the\r
482 Results parameter would result\r
483 in this type of error.\r
484 @retval EFI_NOT_FOUND Target for the specified routing data\r
485 was not found.\r
12618416 486**/\r
6a690e23 487EFI_STATUS\r
488EFIAPI\r
93e3992d 489IScsiFormRouteConfig (\r
490 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
491 IN CONST EFI_STRING Configuration,\r
492 OUT EFI_STRING *Progress\r
6a690e23 493 )\r
12618416 494{\r
ae79d2f9
LG
495 if (Configuration == NULL || Progress == NULL) {\r
496 return EFI_INVALID_PARAMETER;\r
497 }\r
498\r
499 //\r
500 // Check routing data in <ConfigHdr>.\r
501 // Note: if only one Storage is used, then this checking could be skipped.\r
502 //\r
503 if (!HiiIsConfigHdrMatch (Configuration, &mVendorGuid, mVendorStorageName)) {\r
504 *Progress = Configuration;\r
505 return EFI_NOT_FOUND;\r
506 }\r
507\r
508 *Progress = Configuration + StrLen (Configuration);\r
12618416 509 return EFI_SUCCESS;\r
510}\r
6a690e23 511\r
12618416 512/**\r
669314e5 513 This function is called to provide results data to the driver.\r
514 This data consists of a unique key that is used to identify\r
515 which data is either being passed back or being asked for.\r
516\r
517 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
518 @param[in] Action Specifies the type of action taken by the browser.\r
519 @param[in] QuestionId A unique value which is sent to the original\r
520 exporting driver so that it can identify the type\r
521 of data to expect. The format of the data tends to \r
522 vary based on the opcode that enerated the callback.\r
523 @param[in] Type The type of value for the question.\r
524 @param[in] Value A pointer to the data being sent to the original\r
525 exporting driver.\r
526 @param[out] ActionRequest On return, points to the action requested by the\r
527 callback function.\r
528\r
529 @retval EFI_SUCCESS The callback successfully handled the action.\r
530 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the\r
531 variable and its data.\r
532 @retval EFI_DEVICE_ERROR The variable could not be saved.\r
533 @retval EFI_UNSUPPORTED The specified Action is not supported by the\r
534 callback.Currently not implemented.\r
535 @retval EFI_INVALID_PARAMETERS Passing in wrong parameter. \r
963dbb30 536 @retval Others Other errors as indicated. \r
12618416 537**/\r
93e3992d 538EFI_STATUS\r
539EFIAPI\r
540IScsiFormCallback (\r
541 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
f3e1569d 542 IN EFI_BROWSER_ACTION Action,\r
669314e5 543 IN EFI_QUESTION_ID QuestionId,\r
93e3992d 544 IN UINT8 Type,\r
545 IN EFI_IFR_TYPE_VALUE *Value,\r
546 OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest\r
547 )\r
6a690e23 548{\r
549 ISCSI_FORM_CALLBACK_INFO *Private;\r
550 UINTN BufferSize;\r
551 CHAR8 IScsiName[ISCSI_NAME_IFR_MAX_SIZE];\r
552 CHAR16 PortString[128];\r
553 CHAR8 Ip4String[IP4_STR_MAX_SIZE];\r
554 CHAR8 LunString[ISCSI_LUN_STR_MAX_LEN];\r
555 UINT64 Lun;\r
6c7a807a 556 EFI_STRING_ID DeviceFormTitleToken;\r
6a690e23 557 ISCSI_CONFIG_IFR_NVDATA *IfrNvData;\r
558 ISCSI_CONFIG_FORM_ENTRY *ConfigFormEntry;\r
559 EFI_IP_ADDRESS HostIp;\r
560 EFI_IP_ADDRESS SubnetMask;\r
561 EFI_IP_ADDRESS Gateway;\r
562 EFI_STATUS Status;\r
63d55bb9 563 EFI_INPUT_KEY Key;\r
6a690e23 564\r
565 Private = ISCSI_FORM_CALLBACK_INFO_FROM_FORM_CALLBACK (This);\r
93e3992d 566\r
567 //\r
568 // Retrive uncommitted data from Browser\r
569 //\r
1d451ff9
LG
570 IfrNvData = AllocateZeroPool (sizeof (ISCSI_CONFIG_IFR_NVDATA));\r
571 ASSERT (IfrNvData != NULL);\r
572 if (!HiiGetBrowserData (&mVendorGuid, mVendorStorageName, sizeof (ISCSI_CONFIG_IFR_NVDATA), (UINT8 *) IfrNvData)) {\r
573 FreePool (IfrNvData);\r
7e3bcccb 574 return EFI_NOT_FOUND;\r
93e3992d 575 }\r
7e3bcccb
LG
576 \r
577 Status = EFI_SUCCESS;\r
6a690e23 578\r
669314e5 579 switch (QuestionId) {\r
6a690e23 580 case KEY_INITIATOR_NAME:\r
581 IScsiUnicodeStrToAsciiStr (IfrNvData->InitiatorName, IScsiName);\r
582 BufferSize = AsciiStrLen (IScsiName) + 1;\r
583\r
584 Status = gIScsiInitiatorName.Set (&gIScsiInitiatorName, &BufferSize, IScsiName);\r
585 if (EFI_ERROR (Status)) {\r
63d55bb9 586 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid iSCSI Name!", NULL);\r
6a690e23 587 }\r
588\r
589 break;\r
590\r
591 case KEY_LOCAL_IP:\r
592 IScsiUnicodeStrToAsciiStr (IfrNvData->LocalIp, Ip4String);\r
593 Status = IScsiAsciiStrToIp (Ip4String, &HostIp.v4);\r
f6b7393c 594 if (EFI_ERROR (Status) || !NetIp4IsUnicast (NTOHL (HostIp.Addr[0]), 0)) {\r
63d55bb9 595 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid IP address!", NULL);\r
6a690e23 596 Status = EFI_INVALID_PARAMETER;\r
597 } else {\r
e48e37fc 598 CopyMem (&Private->Current->SessionConfigData.LocalIp, &HostIp.v4, sizeof (HostIp.v4));\r
6a690e23 599 }\r
600\r
601 break;\r
602\r
603 case KEY_SUBNET_MASK:\r
604 IScsiUnicodeStrToAsciiStr (IfrNvData->SubnetMask, Ip4String);\r
605 Status = IScsiAsciiStrToIp (Ip4String, &SubnetMask.v4);\r
606 if (EFI_ERROR (Status) || ((SubnetMask.Addr[0] != 0) && (IScsiGetSubnetMaskPrefixLength (&SubnetMask.v4) == 0))) {\r
63d55bb9 607 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid Subnet Mask!", NULL);\r
6a690e23 608 Status = EFI_INVALID_PARAMETER;\r
609 } else {\r
e48e37fc 610 CopyMem (&Private->Current->SessionConfigData.SubnetMask, &SubnetMask.v4, sizeof (SubnetMask.v4));\r
6a690e23 611 }\r
612\r
613 break;\r
614\r
615 case KEY_GATE_WAY:\r
616 IScsiUnicodeStrToAsciiStr (IfrNvData->Gateway, Ip4String);\r
617 Status = IScsiAsciiStrToIp (Ip4String, &Gateway.v4);\r
f6b7393c 618 if (EFI_ERROR (Status) || ((Gateway.Addr[0] != 0) && !NetIp4IsUnicast (NTOHL (Gateway.Addr[0]), 0))) {\r
63d55bb9 619 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid Gateway!", NULL);\r
6a690e23 620 Status = EFI_INVALID_PARAMETER;\r
621 } else {\r
e48e37fc 622 CopyMem (&Private->Current->SessionConfigData.Gateway, &Gateway.v4, sizeof (Gateway.v4));\r
6a690e23 623 }\r
624\r
625 break;\r
626\r
627 case KEY_TARGET_IP:\r
628 IScsiUnicodeStrToAsciiStr (IfrNvData->TargetIp, Ip4String);\r
629 Status = IScsiAsciiStrToIp (Ip4String, &HostIp.v4);\r
f6b7393c 630 if (EFI_ERROR (Status) || !NetIp4IsUnicast (NTOHL (HostIp.Addr[0]), 0)) {\r
63d55bb9 631 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid IP address!", NULL);\r
6a690e23 632 Status = EFI_INVALID_PARAMETER;\r
633 } else {\r
e48e37fc 634 CopyMem (&Private->Current->SessionConfigData.TargetIp, &HostIp.v4, sizeof (HostIp.v4));\r
6a690e23 635 }\r
636\r
637 break;\r
638\r
639 case KEY_TARGET_NAME:\r
640 IScsiUnicodeStrToAsciiStr (IfrNvData->TargetName, IScsiName);\r
641 Status = IScsiNormalizeName (IScsiName, AsciiStrLen (IScsiName));\r
642 if (EFI_ERROR (Status)) {\r
63d55bb9 643 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid iSCSI Name!", NULL);\r
6a690e23 644 } else {\r
645 AsciiStrCpy (Private->Current->SessionConfigData.TargetName, IScsiName);\r
646 }\r
647\r
648 break;\r
649\r
650 case KEY_DHCP_ENABLE:\r
651 if (IfrNvData->InitiatorInfoFromDhcp == 0) {\r
652 IfrNvData->TargetInfoFromDhcp = 0;\r
653 }\r
654\r
655 break;\r
656\r
657 case KEY_BOOT_LUN:\r
658 IScsiUnicodeStrToAsciiStr (IfrNvData->BootLun, LunString);\r
659 Status = IScsiAsciiStrToLun (LunString, (UINT8 *) &Lun);\r
660 if (EFI_ERROR (Status)) {\r
63d55bb9 661 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid LUN string!", NULL);\r
6a690e23 662 } else {\r
e48e37fc 663 CopyMem (Private->Current->SessionConfigData.BootLun, &Lun, sizeof (Lun));\r
6a690e23 664 }\r
665\r
666 break;\r
667\r
668 case KEY_CHAP_NAME:\r
669 IScsiUnicodeStrToAsciiStr (IfrNvData->CHAPName, Private->Current->AuthConfigData.CHAPName);\r
670 break;\r
671\r
672 case KEY_CHAP_SECRET:\r
673 IScsiUnicodeStrToAsciiStr (IfrNvData->CHAPSecret, Private->Current->AuthConfigData.CHAPSecret);\r
674 break;\r
675\r
676 case KEY_REVERSE_CHAP_NAME:\r
677 IScsiUnicodeStrToAsciiStr (IfrNvData->ReverseCHAPName, Private->Current->AuthConfigData.ReverseCHAPName);\r
678 break;\r
679\r
680 case KEY_REVERSE_CHAP_SECRET:\r
681 IScsiUnicodeStrToAsciiStr (IfrNvData->ReverseCHAPSecret, Private->Current->AuthConfigData.ReverseCHAPSecret);\r
682 break;\r
683\r
684 case KEY_SAVE_CHANGES:\r
685 //\r
686 // First, update those fields which don't have INTERACTIVE set.\r
687 //\r
688 Private->Current->SessionConfigData.Enabled = IfrNvData->Enabled;\r
689 Private->Current->SessionConfigData.InitiatorInfoFromDhcp = IfrNvData->InitiatorInfoFromDhcp;\r
690 Private->Current->SessionConfigData.TargetPort = IfrNvData->TargetPort;\r
691 if (Private->Current->SessionConfigData.TargetPort == 0) {\r
692 Private->Current->SessionConfigData.TargetPort = ISCSI_WELL_KNOWN_PORT;\r
693 }\r
694\r
695 Private->Current->SessionConfigData.TargetInfoFromDhcp = IfrNvData->TargetInfoFromDhcp;\r
696 Private->Current->AuthConfigData.CHAPType = IfrNvData->CHAPType;\r
697\r
698 //\r
699 // Only do full parameter validation if iSCSI is enabled on this device.\r
700 //\r
701 if (Private->Current->SessionConfigData.Enabled) {\r
702 //\r
703 // Validate the address configuration of the Initiator if DHCP isn't\r
704 // deployed.\r
705 //\r
706 if (!Private->Current->SessionConfigData.InitiatorInfoFromDhcp) {\r
e48e37fc 707 CopyMem (&HostIp.v4, &Private->Current->SessionConfigData.LocalIp, sizeof (HostIp.v4));\r
708 CopyMem (&SubnetMask.v4, &Private->Current->SessionConfigData.SubnetMask, sizeof (SubnetMask.v4));\r
709 CopyMem (&Gateway.v4, &Private->Current->SessionConfigData.Gateway, sizeof (Gateway.v4));\r
6a690e23 710\r
711 if ((Gateway.Addr[0] != 0)) {\r
712 if (SubnetMask.Addr[0] == 0) {\r
63d55bb9 713 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Gateway address is set but subnet mask is zero.", NULL);\r
6a690e23 714 Status = EFI_INVALID_PARAMETER;\r
715 break;\r
716 } else if (!IP4_NET_EQUAL (HostIp.Addr[0], Gateway.Addr[0], SubnetMask.Addr[0])) {\r
63d55bb9 717 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Local IP and Gateway are not in the same subnet.", NULL);\r
6a690e23 718 Status = EFI_INVALID_PARAMETER;\r
719 break;\r
720 }\r
721 }\r
722 }\r
723 //\r
724 // Validate target configuration if DHCP isn't deployed.\r
725 //\r
726 if (!Private->Current->SessionConfigData.TargetInfoFromDhcp) {\r
e48e37fc 727 CopyMem (&HostIp.v4, &Private->Current->SessionConfigData.TargetIp, sizeof (HostIp.v4));\r
f6b7393c 728 if (!NetIp4IsUnicast (NTOHL (HostIp.Addr[0]), 0)) {\r
63d55bb9 729 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Target IP is invalid!", NULL);\r
6a690e23 730 Status = EFI_INVALID_PARAMETER;\r
731 break;\r
732 }\r
733 }\r
734\r
735 if (IfrNvData->CHAPType != ISCSI_CHAP_NONE) {\r
736 if ((IfrNvData->CHAPName[0] == '\0') || (IfrNvData->CHAPSecret[0] == '\0')) {\r
63d55bb9 737 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"CHAP Name or CHAP Secret is invalid!", NULL);\r
6a690e23 738 Status = EFI_INVALID_PARAMETER;\r
739 break;\r
740 }\r
741\r
742 if ((IfrNvData->CHAPType == ISCSI_CHAP_MUTUAL) &&\r
743 ((IfrNvData->ReverseCHAPName[0] == '\0') || (IfrNvData->ReverseCHAPSecret[0] == '\0'))\r
744 ) {\r
63d55bb9 745 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Reverse CHAP Name or Reverse CHAP Secret is invalid!", NULL);\r
6a690e23 746 Status = EFI_INVALID_PARAMETER;\r
747 break;\r
748 }\r
749 }\r
750 }\r
751\r
752 BufferSize = sizeof (Private->Current->SessionConfigData);\r
753 gRT->SetVariable (\r
754 Private->Current->MacString,\r
755 &gEfiIScsiInitiatorNameProtocolGuid,\r
756 ISCSI_CONFIG_VAR_ATTR,\r
757 BufferSize,\r
758 &Private->Current->SessionConfigData\r
759 );\r
760\r
761 BufferSize = sizeof (Private->Current->AuthConfigData);\r
762 gRT->SetVariable (\r
763 Private->Current->MacString,\r
764 &mIScsiCHAPAuthInfoGuid,\r
765 ISCSI_CONFIG_VAR_ATTR,\r
766 BufferSize,\r
767 &Private->Current->AuthConfigData\r
768 );\r
93e3992d 769 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT;\r
6a690e23 770 break;\r
771\r
772 default:\r
669314e5 773 if ((QuestionId >= KEY_DEVICE_ENTRY_BASE) && (QuestionId < (mNumberOfIScsiDevices + KEY_DEVICE_ENTRY_BASE))) {\r
6a690e23 774 //\r
775 // In case goto the device configuration form, update the device form title.\r
776 //\r
669314e5 777 ConfigFormEntry = IScsiGetConfigFormEntryByIndex ((UINT32) (QuestionId - KEY_DEVICE_ENTRY_BASE));\r
6a690e23 778 ASSERT (ConfigFormEntry != NULL);\r
779\r
93e3992d 780 UnicodeSPrint (PortString, (UINTN) 128, L"Port %s", ConfigFormEntry->MacString);\r
6c7a807a 781 DeviceFormTitleToken = (EFI_STRING_ID) STR_ISCSI_DEVICE_FORM_TITLE;\r
cb7d01c0 782 HiiSetString (Private->RegisteredHandle, DeviceFormTitleToken, PortString, NULL);\r
6a690e23 783\r
784 IScsiConvertDeviceConfigDataToIfrNvData (ConfigFormEntry, IfrNvData);\r
785\r
786 Private->Current = ConfigFormEntry;\r
787 }\r
788\r
789 break;\r
790 }\r
791\r
93e3992d 792 if (!EFI_ERROR (Status)) {\r
793 //\r
794 // Pass changed uncommitted data back to Form Browser\r
795 //\r
7e3bcccb 796 HiiSetBrowserData (&mVendorGuid, mVendorStorageName, sizeof (ISCSI_CONFIG_IFR_NVDATA), (UINT8 *) IfrNvData, NULL);\r
93e3992d 797 }\r
798\r
7e3bcccb 799 FreePool (IfrNvData);\r
6a690e23 800 return Status;\r
801}\r
802\r
12618416 803/**\r
6a690e23 804 Updates the iSCSI configuration form to add/delete an entry for the iSCSI\r
805 device specified by the Controller.\r
806\r
669314e5 807 @param[in] DriverBindingHandle The driverbinding handle.\r
808 @param[in] Controller The controller handle of the iSCSI device.\r
809 @param[in] AddForm Whether to add or delete a form entry.\r
6a690e23 810\r
12618416 811 @retval EFI_SUCCESS The iSCSI configuration form is updated.\r
12618416 812 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
963dbb30 813 @retval Others Other errors as indicated.\r
12618416 814**/\r
815EFI_STATUS\r
816IScsiConfigUpdateForm (\r
817 IN EFI_HANDLE DriverBindingHandle,\r
818 IN EFI_HANDLE Controller,\r
819 IN BOOLEAN AddForm\r
820 )\r
6a690e23 821{\r
e48e37fc 822 LIST_ENTRY *Entry;\r
6a690e23 823 ISCSI_CONFIG_FORM_ENTRY *ConfigFormEntry;\r
824 BOOLEAN EntryExisted;\r
6a690e23 825 EFI_STATUS Status;\r
779ae357 826 EFI_MAC_ADDRESS MacAddress;\r
827 UINTN HwAddressSize;\r
828 UINT16 VlanId;\r
6a690e23 829 CHAR16 PortString[128];\r
830 UINT16 FormIndex;\r
831 UINTN BufferSize;\r
7e3bcccb
LG
832 VOID *StartOpCodeHandle;\r
833 VOID *EndOpCodeHandle;\r
834 EFI_IFR_GUID_LABEL *StartLabel;\r
835 EFI_IFR_GUID_LABEL *EndLabel;\r
6a690e23 836\r
837 ConfigFormEntry = NULL;\r
838 EntryExisted = FALSE;\r
839\r
840 NET_LIST_FOR_EACH (Entry, &mIScsiConfigFormList) {\r
841 ConfigFormEntry = NET_LIST_USER_STRUCT (Entry, ISCSI_CONFIG_FORM_ENTRY, Link);\r
842\r
843 if (ConfigFormEntry->Controller == Controller) {\r
844 EntryExisted = TRUE;\r
845 break;\r
846 }\r
847 }\r
848\r
849 if (AddForm) {\r
850 if (EntryExisted) {\r
851 return EFI_SUCCESS;\r
852 } else {\r
853 //\r
854 // Add a new form.\r
855 //\r
e48e37fc 856 ConfigFormEntry = (ISCSI_CONFIG_FORM_ENTRY *) AllocateZeroPool (sizeof (ISCSI_CONFIG_FORM_ENTRY));\r
6a690e23 857 if (ConfigFormEntry == NULL) {\r
858 return EFI_OUT_OF_RESOURCES;\r
859 }\r
860\r
e48e37fc 861 InitializeListHead (&ConfigFormEntry->Link);\r
6a690e23 862 ConfigFormEntry->Controller = Controller;\r
863\r
864 //\r
779ae357 865 // Get the MAC address and convert it into the formatted string.\r
6a690e23 866 //\r
779ae357 867 Status = NetLibGetMacAddress (Controller, &MacAddress, &HwAddressSize);\r
6a690e23 868 ASSERT (Status == EFI_SUCCESS);\r
779ae357 869 VlanId = NetLibGetVlanId (Controller);\r
6a690e23 870\r
779ae357 871 IScsiMacAddrToStr (&MacAddress, (UINT32) HwAddressSize, VlanId, ConfigFormEntry->MacString);\r
6a690e23 872\r
873 //\r
874 // Get the normal session configuration data.\r
875 //\r
876 BufferSize = sizeof (ConfigFormEntry->SessionConfigData);\r
877 Status = gRT->GetVariable (\r
878 ConfigFormEntry->MacString,\r
879 &gEfiIScsiInitiatorNameProtocolGuid,\r
880 NULL,\r
881 &BufferSize,\r
882 &ConfigFormEntry->SessionConfigData\r
883 );\r
884 if (EFI_ERROR (Status)) {\r
e48e37fc 885 ZeroMem (&ConfigFormEntry->SessionConfigData, sizeof (ConfigFormEntry->SessionConfigData));\r
6a690e23 886 }\r
887 //\r
888 // Get the CHAP authentication configuration data.\r
889 //\r
890 BufferSize = sizeof (ConfigFormEntry->AuthConfigData);\r
891 Status = gRT->GetVariable (\r
892 ConfigFormEntry->MacString,\r
893 &mIScsiCHAPAuthInfoGuid,\r
894 NULL,\r
895 &BufferSize,\r
896 &ConfigFormEntry->AuthConfigData\r
897 );\r
898 if (EFI_ERROR (Status)) {\r
e48e37fc 899 ZeroMem (&ConfigFormEntry->AuthConfigData, sizeof (ConfigFormEntry->AuthConfigData));\r
6a690e23 900 }\r
901 //\r
6c7a807a 902 // Compose the Port string and create a new EFI_STRING_ID.\r
6a690e23 903 //\r
904 UnicodeSPrint (PortString, 128, L"Port %s", ConfigFormEntry->MacString);\r
cb7d01c0 905 ConfigFormEntry->PortTitleToken = HiiSetString (mCallbackInfo->RegisteredHandle, 0, PortString, NULL);\r
6a690e23 906\r
907 //\r
6c7a807a 908 // Compose the help string of this port and create a new EFI_STRING_ID.\r
6a690e23 909 //\r
910 UnicodeSPrint (PortString, 128, L"Set the iSCSI parameters on port %s", ConfigFormEntry->MacString);\r
cb7d01c0 911 ConfigFormEntry->PortTitleHelpToken = HiiSetString (mCallbackInfo->RegisteredHandle, 0, PortString, NULL);\r
6a690e23 912\r
e48e37fc 913 InsertTailList (&mIScsiConfigFormList, &ConfigFormEntry->Link);\r
6a690e23 914 mNumberOfIScsiDevices++;\r
915 }\r
916 } else {\r
917 ASSERT (EntryExisted);\r
918\r
919 mNumberOfIScsiDevices--;\r
e48e37fc 920 RemoveEntryList (&ConfigFormEntry->Link);\r
766c7483 921 FreePool (ConfigFormEntry);\r
6a690e23 922 }\r
923 //\r
924 // Allocate space for creation of Buffer\r
925 //\r
7e3bcccb
LG
926\r
927 //\r
928 // Init OpCode Handle\r
929 //\r
930 StartOpCodeHandle = HiiAllocateOpCodeHandle ();\r
931 ASSERT (StartOpCodeHandle != NULL);\r
932\r
933 EndOpCodeHandle = HiiAllocateOpCodeHandle ();\r
934 ASSERT (EndOpCodeHandle != NULL);\r
935\r
936 //\r
937 // Create Hii Extend Label OpCode as the start opcode\r
938 //\r
939 StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));\r
940 StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
941 StartLabel->Number = DEVICE_ENTRY_LABEL;\r
942\r
943 //\r
944 // Create Hii Extend Label OpCode as the end opcode\r
945 //\r
946 EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (EndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));\r
947 EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
948 EndLabel->Number = LABEL_END;\r
6a690e23 949\r
93e3992d 950 FormIndex = 0;\r
6a690e23 951 NET_LIST_FOR_EACH (Entry, &mIScsiConfigFormList) {\r
952 ConfigFormEntry = NET_LIST_USER_STRUCT (Entry, ISCSI_CONFIG_FORM_ENTRY, Link);\r
953\r
7e3bcccb
LG
954 HiiCreateGotoOpCode (\r
955 StartOpCodeHandle, // Container for dynamic created opcodes\r
956 FORMID_DEVICE_FORM, // Target Form ID\r
957 ConfigFormEntry->PortTitleToken, // Prompt text\r
958 ConfigFormEntry->PortTitleHelpToken, // Help text\r
959 EFI_IFR_FLAG_CALLBACK, // Question flag\r
960 (UINT16)(KEY_DEVICE_ENTRY_BASE + FormIndex) // Question ID\r
6a690e23 961 );\r
962\r
6a690e23 963 FormIndex++;\r
964 }\r
965\r
7e3bcccb 966 HiiUpdateForm (\r
93e3992d 967 mCallbackInfo->RegisteredHandle,\r
968 &mVendorGuid,\r
969 FORMID_MAIN_FORM,\r
7e3bcccb
LG
970 StartOpCodeHandle, // Label DEVICE_ENTRY_LABEL\r
971 EndOpCodeHandle // LABEL_END\r
93e3992d 972 );\r
973\r
7e3bcccb
LG
974 HiiFreeOpCodeHandle (StartOpCodeHandle);\r
975 HiiFreeOpCodeHandle (EndOpCodeHandle);\r
6a690e23 976\r
977 return EFI_SUCCESS;\r
978}\r
979\r
12618416 980/**\r
6a690e23 981 Initialize the iSCSI configuration form.\r
982\r
669314e5 983 @param[in] DriverBindingHandle The iSCSI driverbinding handle.\r
6a690e23 984\r
669314e5 985 @retval EFI_SUCCESS The iSCSI configuration form is initialized.\r
986 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
963dbb30 987 @retval Others Other errors as indicated.\r
12618416 988**/\r
989EFI_STATUS\r
990IScsiConfigFormInit (\r
963dbb30 991 VOID\r
12618416 992 )\r
6a690e23 993{\r
93e3992d 994 EFI_STATUS Status;\r
995 EFI_HII_DATABASE_PROTOCOL *HiiDatabase;\r
93e3992d 996 ISCSI_FORM_CALLBACK_INFO *CallbackInfo;\r
997\r
69b0882d 998 Status = gBS->LocateProtocol (&gEfiHiiDatabaseProtocolGuid, NULL, (VOID **)&HiiDatabase);\r
6a690e23 999 if (EFI_ERROR (Status)) {\r
93e3992d 1000 return Status;\r
6a690e23 1001 }\r
1002\r
f6f910dd 1003 CallbackInfo = (ISCSI_FORM_CALLBACK_INFO *) AllocateZeroPool (sizeof (ISCSI_FORM_CALLBACK_INFO));\r
6a690e23 1004 if (CallbackInfo == NULL) {\r
1005 return EFI_OUT_OF_RESOURCES;\r
1006 }\r
1007\r
f2a94e25 1008 CallbackInfo->Signature = ISCSI_FORM_CALLBACK_INFO_SIGNATURE;\r
93e3992d 1009 CallbackInfo->HiiDatabase = HiiDatabase;\r
f2a94e25 1010 CallbackInfo->Current = NULL;\r
6a690e23 1011\r
93e3992d 1012 CallbackInfo->ConfigAccess.ExtractConfig = IScsiFormExtractConfig;\r
1013 CallbackInfo->ConfigAccess.RouteConfig = IScsiFormRouteConfig;\r
1014 CallbackInfo->ConfigAccess.Callback = IScsiFormCallback;\r
6a690e23 1015\r
69b0882d 1016 Status = gBS->LocateProtocol (&gEfiHiiConfigRoutingProtocolGuid, NULL, (VOID **)&CallbackInfo->ConfigRouting);\r
93e3992d 1017 if (EFI_ERROR (Status)) {\r
f2a94e25 1018 FreePool(CallbackInfo);\r
93e3992d 1019 return Status;\r
1020 }\r
1021\r
1022 //\r
f6f910dd 1023 // Install Device Path Protocol and Config Access protocol to driver handle\r
93e3992d 1024 //\r
f6f910dd 1025 Status = gBS->InstallMultipleProtocolInterfaces (\r
93e3992d 1026 &CallbackInfo->DriverHandle,\r
f6f910dd 1027 &gEfiDevicePathProtocolGuid,\r
1028 &mIScsiHiiVendorDevicePath,\r
93e3992d 1029 &gEfiHiiConfigAccessProtocolGuid,\r
f6f910dd 1030 &CallbackInfo->ConfigAccess,\r
1031 NULL\r
6a690e23 1032 );\r
6a690e23 1033 ASSERT_EFI_ERROR (Status);\r
93e3992d 1034 \r
6a690e23 1035 //\r
93e3992d 1036 // Publish our HII data\r
6a690e23 1037 //\r
cb7d01c0 1038 CallbackInfo->RegisteredHandle = HiiAddPackages (\r
1039 &mVendorGuid,\r
1040 CallbackInfo->DriverHandle,\r
1041 IScsiDxeStrings,\r
1042 IScsiConfigDxeBin,\r
1043 NULL\r
1044 );\r
1045 if (CallbackInfo->RegisteredHandle == NULL) {\r
f2a94e25 1046 FreePool(CallbackInfo);\r
cb7d01c0 1047 return EFI_OUT_OF_RESOURCES;\r
6a690e23 1048 }\r
1049\r
93e3992d 1050 mCallbackInfo = CallbackInfo;\r
6a690e23 1051\r
1052 return Status;\r
1053}\r
1054\r
12618416 1055/**\r
6a690e23 1056 Unload the iSCSI configuration form, this includes: delete all the iSCSI\r
1057 device configuration entries, uninstall the form callback protocol and\r
1058 free the resources used.\r
1059\r
669314e5 1060 @param[in] DriverBindingHandle The iSCSI driverbinding handle.\r
1061 \r
12618416 1062 @retval EFI_SUCCESS The iSCSI configuration form is unloaded.\r
12618416 1063 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
12618416 1064**/\r
1065EFI_STATUS\r
1066IScsiConfigFormUnload (\r
1067 IN EFI_HANDLE DriverBindingHandle\r
1068 )\r
6a690e23 1069{\r
1070 ISCSI_CONFIG_FORM_ENTRY *ConfigFormEntry;\r
6a690e23 1071\r
e48e37fc 1072 while (!IsListEmpty (&mIScsiConfigFormList)) {\r
6a690e23 1073 //\r
1074 // Uninstall the device forms as the iSCSI driver instance may fail to\r
1075 // control the controller but still install the device configuration form.\r
1076 // In such case, upon driver unloading, the driver instance's driverbinding.\r
1077 // stop () won't be called, so we have to take this chance here to uninstall\r
1078 // the device form.\r
1079 //\r
1080 ConfigFormEntry = NET_LIST_USER_STRUCT (mIScsiConfigFormList.ForwardLink, ISCSI_CONFIG_FORM_ENTRY, Link);\r
1081 IScsiConfigUpdateForm (DriverBindingHandle, ConfigFormEntry->Controller, FALSE);\r
1082 }\r
1083\r
6a690e23 1084 //\r
93e3992d 1085 // Remove HII package list\r
6a690e23 1086 //\r
93e3992d 1087 mCallbackInfo->HiiDatabase->RemovePackageList (\r
1088 mCallbackInfo->HiiDatabase,\r
1089 mCallbackInfo->RegisteredHandle\r
1090 );\r
6a690e23 1091\r
1092 //\r
93e3992d 1093 // Uninstall EFI_HII_CONFIG_ACCESS_PROTOCOL\r
6a690e23 1094 //\r
f6f910dd 1095 gBS->UninstallMultipleProtocolInterfaces (\r
1096 mCallbackInfo->DriverHandle,\r
1097 &gEfiDevicePathProtocolGuid,\r
1098 &mIScsiHiiVendorDevicePath,\r
1099 &gEfiHiiConfigAccessProtocolGuid,\r
1100 &mCallbackInfo->ConfigAccess,\r
1101 NULL\r
1102 );\r
766c7483 1103 FreePool (mCallbackInfo);\r
6a690e23 1104\r
1105 return EFI_SUCCESS;\r
1106}\r