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