]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Network/IScsiDxe/IScsiConfig.c
Remove the old unused ValueToString code, which has been replaced by UnicodeValueToSt...
[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
669314e5 70 \r
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
87 EFI_SIMPLE_NETWORK_PROTOCOL *Snp;\r
88 EFI_SIMPLE_NETWORK_MODE *Mode;\r
89 ISCSI_MAC_INFO *CurMacInfo;\r
90 ISCSI_MAC_INFO TempMacInfo;\r
91 CHAR16 MacString[65];\r
92 UINTN DeviceListSize;\r
93\r
94 //\r
95 // Dump all the handles the Simple Network Protocol is installed on.\r
96 //\r
97 Status = gBS->LocateHandleBuffer (\r
98 ByProtocol,\r
99 &gEfiSimpleNetworkProtocolGuid,\r
100 NULL,\r
101 &NumHandles,\r
102 &Handles\r
103 );\r
104 if (EFI_ERROR (Status)) {\r
105 return Status;\r
106 }\r
107\r
108 DataSize = 0;\r
109 Status = gRT->GetVariable (\r
110 L"iSCSIDeviceList",\r
111 &mVendorGuid,\r
112 NULL,\r
113 &DataSize,\r
114 NULL\r
115 );\r
116 if (Status == EFI_BUFFER_TOO_SMALL) {\r
e48e37fc 117 DeviceList = (ISCSI_DEVICE_LIST *) AllocatePool (DataSize);\r
6a690e23 118\r
119 gRT->GetVariable (\r
120 L"iSCSIDeviceList",\r
121 &mVendorGuid,\r
122 NULL,\r
123 &DataSize,\r
124 DeviceList\r
125 );\r
126\r
127 LastDeviceIndex = 0;\r
128\r
129 for (HandleIndex = 0; HandleIndex < NumHandles; HandleIndex++) {\r
130 gBS->HandleProtocol (Handles[HandleIndex], &gEfiSimpleNetworkProtocolGuid, (VOID **)&Snp);\r
131\r
132 Mode = Snp->Mode;\r
133\r
134 for (Index = LastDeviceIndex; Index < DeviceList->NumDevice; Index++) {\r
135 CurMacInfo = &DeviceList->MacInfo[Index];\r
136 if ((CurMacInfo->Len == Mode->HwAddressSize) &&\r
137 (NET_MAC_EQUAL (&CurMacInfo->Mac, &Mode->PermanentAddress, Mode->HwAddressSize))\r
138 ) {\r
139 //\r
140 // The previous configured NIC is still here.\r
141 //\r
142 if (Index != LastDeviceIndex) {\r
143 //\r
144 // Swap the current MAC address entry with the one indexed by\r
145 // LastDeviceIndex.\r
146 //\r
e48e37fc 147 CopyMem (&TempMacInfo, CurMacInfo, sizeof (ISCSI_MAC_INFO));\r
148 CopyMem (CurMacInfo, &DeviceList->MacInfo[LastDeviceIndex], sizeof (ISCSI_MAC_INFO));\r
149 CopyMem (&DeviceList->MacInfo[LastDeviceIndex], &TempMacInfo, sizeof (ISCSI_MAC_INFO));\r
6a690e23 150 }\r
151\r
152 LastDeviceIndex++;\r
153 }\r
154 }\r
155\r
156 if (LastDeviceIndex == DeviceList->NumDevice) {\r
157 break;\r
158 }\r
159 }\r
160\r
161 for (Index = LastDeviceIndex; Index < DeviceList->NumDevice; Index++) {\r
162 //\r
163 // delete the variables\r
164 //\r
165 CurMacInfo = &DeviceList->MacInfo[Index];\r
166 IScsiMacAddrToStr (&CurMacInfo->Mac, CurMacInfo->Len, MacString);\r
167 gRT->SetVariable (MacString, &gEfiIScsiInitiatorNameProtocolGuid, 0, 0, NULL);\r
168 gRT->SetVariable (MacString, &mIScsiCHAPAuthInfoGuid, 0, 0, NULL);\r
169 }\r
170\r
e48e37fc 171 gBS->FreePool (DeviceList);\r
6a690e23 172 } else if (Status != EFI_NOT_FOUND) {\r
e48e37fc 173 gBS->FreePool (Handles);\r
6a690e23 174 return Status;\r
175 }\r
176 //\r
177 // Construct the new iSCSI device list.\r
178 //\r
179 DeviceListSize = sizeof (ISCSI_DEVICE_LIST) + (NumHandles - 1) * sizeof (ISCSI_MAC_INFO);\r
e48e37fc 180 DeviceList = (ISCSI_DEVICE_LIST *) AllocatePool (DeviceListSize);\r
6a690e23 181 DeviceList->NumDevice = (UINT8) NumHandles;\r
182\r
183 for (Index = 0; Index < NumHandles; Index++) {\r
184 gBS->HandleProtocol (Handles[Index], &gEfiSimpleNetworkProtocolGuid, (VOID **)&Snp);\r
185 Mode = Snp->Mode;\r
186\r
187 CurMacInfo = &DeviceList->MacInfo[Index];\r
e48e37fc 188 CopyMem (&CurMacInfo->Mac, &Mode->PermanentAddress, Mode->HwAddressSize);\r
6a690e23 189 CurMacInfo->Len = (UINT8) Mode->HwAddressSize;\r
190 }\r
191\r
192 gRT->SetVariable (\r
193 L"iSCSIDeviceList",\r
194 &mVendorGuid,\r
195 ISCSI_CONFIG_VAR_ATTR,\r
196 DeviceListSize,\r
197 DeviceList\r
198 );\r
199\r
e48e37fc 200 gBS->FreePool (DeviceList);\r
356e635c 201 gBS->FreePool (Handles);\r
6a690e23 202\r
203 return Status;\r
204}\r
205\r
12618416 206/**\r
207 Get the iSCSI configuration form entry by the index of the goto opcode actived.\r
208\r
669314e5 209 @param[in] Index The 0-based index of the goto opcode actived.\r
12618416 210\r
669314e5 211 @return The iSCSI configuration form entry found.\r
12618416 212**/\r
6a690e23 213ISCSI_CONFIG_FORM_ENTRY *\r
214IScsiGetConfigFormEntryByIndex (\r
215 IN UINT32 Index\r
216 )\r
6a690e23 217{\r
218 UINT32 CurrentIndex;\r
e48e37fc 219 LIST_ENTRY *Entry;\r
6a690e23 220 ISCSI_CONFIG_FORM_ENTRY *ConfigFormEntry;\r
221\r
222 CurrentIndex = 0;\r
223 ConfigFormEntry = NULL;\r
224\r
225 NET_LIST_FOR_EACH (Entry, &mIScsiConfigFormList) {\r
226 if (CurrentIndex == Index) {\r
227 ConfigFormEntry = NET_LIST_USER_STRUCT (Entry, ISCSI_CONFIG_FORM_ENTRY, Link);\r
228 break;\r
229 }\r
230\r
231 CurrentIndex++;\r
232 }\r
233\r
234 return ConfigFormEntry;\r
235}\r
236\r
12618416 237/**\r
238 Convert the iSCSI configuration data into the IFR data.\r
239\r
c5de0d55 240 @param[in] ConfigFormEntry The iSCSI configuration form entry.\r
241 @param[out] IfrNvData The IFR nv data.\r
12618416 242**/\r
6a690e23 243VOID\r
244IScsiConvertDeviceConfigDataToIfrNvData (\r
c5de0d55 245 IN ISCSI_CONFIG_FORM_ENTRY *ConfigFormEntry,\r
246 OUT ISCSI_CONFIG_IFR_NVDATA *IfrNvData\r
6a690e23 247 )\r
6a690e23 248{\r
249 ISCSI_SESSION_CONFIG_NVDATA *SessionConfigData;\r
250 ISCSI_CHAP_AUTH_CONFIG_NVDATA *AuthConfigData;\r
251\r
252 //\r
253 // Normal session configuration parameters.\r
254 //\r
255 SessionConfigData = &ConfigFormEntry->SessionConfigData;\r
256 IfrNvData->Enabled = SessionConfigData->Enabled;\r
257\r
258 IfrNvData->InitiatorInfoFromDhcp = SessionConfigData->InitiatorInfoFromDhcp;\r
259 IfrNvData->TargetInfoFromDhcp = SessionConfigData->TargetInfoFromDhcp;\r
260 IfrNvData->TargetPort = SessionConfigData->TargetPort;\r
261\r
262 IScsiIpToStr (&SessionConfigData->LocalIp, IfrNvData->LocalIp);\r
263 IScsiIpToStr (&SessionConfigData->SubnetMask, IfrNvData->SubnetMask);\r
264 IScsiIpToStr (&SessionConfigData->Gateway, IfrNvData->Gateway);\r
265 IScsiIpToStr (&SessionConfigData->TargetIp, IfrNvData->TargetIp);\r
266\r
267 IScsiAsciiStrToUnicodeStr (SessionConfigData->TargetName, IfrNvData->TargetName);\r
268\r
269 IScsiLunToUnicodeStr (SessionConfigData->BootLun, IfrNvData->BootLun);\r
270\r
271 //\r
272 // CHAP authentication parameters.\r
273 //\r
274 AuthConfigData = &ConfigFormEntry->AuthConfigData;\r
275\r
276 IfrNvData->CHAPType = AuthConfigData->CHAPType;\r
277\r
278 IScsiAsciiStrToUnicodeStr (AuthConfigData->CHAPName, IfrNvData->CHAPName);\r
279 IScsiAsciiStrToUnicodeStr (AuthConfigData->CHAPSecret, IfrNvData->CHAPSecret);\r
280 IScsiAsciiStrToUnicodeStr (AuthConfigData->ReverseCHAPName, IfrNvData->ReverseCHAPName);\r
281 IScsiAsciiStrToUnicodeStr (AuthConfigData->ReverseCHAPSecret, IfrNvData->ReverseCHAPSecret);\r
282}\r
283\r
12618416 284/**\r
669314e5 285 This function allows the caller to request the current\r
286 configuration for one or more named elements. The resulting\r
287 string is in <ConfigAltResp> format. Any and all alternative\r
288 configuration strings shall also be appended to the end of the\r
289 current configuration string. If they are, they must appear\r
290 after the current configuration. They must contain the same\r
291 routing (GUID, NAME, PATH) as the current configuration string.\r
292 They must have an additional description indicating the type of\r
293 alternative configuration the string represents,\r
294 "ALTCFG=<StringToken>". That <StringToken> (when\r
295 converted from Hex UNICODE to binary) is a reference to a\r
296 string in the associated string pack.\r
297\r
298 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
299 @param[in] Request A null-terminated Unicode string in\r
300 <ConfigRequest> format. Note that this\r
301 includes the routing information as well as\r
302 the configurable name / value pairs. It is\r
303 invalid for this string to be in\r
304 <MultiConfigRequest> format.\r
305 @param[out] Progress On return, points to a character in the\r
306 Request string. Points to the string's null\r
307 terminator if request was successful. Points\r
308 to the most recent "&" before the first\r
309 failing name / value pair (or the beginning\r
310 of the string if the failure is in the first\r
311 name / value pair) if the request was not\r
312 successful.\r
313 @param[out] Results A null-terminated Unicode string in\r
314 <ConfigAltResp> format which has all values\r
315 filled in for the names in the Request string.\r
316 String to be allocated by the called function.\r
317\r
318 @retval EFI_SUCCESS The Results string is filled with the\r
319 values corresponding to all requested\r
320 names.\r
321 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the\r
322 parts of the results that must be\r
323 stored awaiting possible future\r
324 protocols.\r
325 @retval EFI_INVALID_PARAMETER For example, passing in a NULL\r
326 for the Request parameter\r
327 would result in this type of\r
328 error. In this case, the\r
329 Progress parameter would be\r
330 set to NULL. \r
331 @retval EFI_NOT_FOUND Routing data doesn't match any\r
332 known driver. Progress set to the\r
333 first character in the routing header.\r
334 Note: There is no requirement that the\r
335 driver validate the routing data. It\r
336 must skip the <ConfigHdr> in order to\r
337 process the names.\r
338 @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set\r
339 to most recent & before the\r
340 error or the beginning of the\r
341 string.\r
342 @retval EFI_INVALID_PARAMETER Unknown name. Progress points\r
343 to the & before the name in\r
344 question.Currently not implemented.\r
12618416 345**/\r
6a690e23 346EFI_STATUS\r
347EFIAPI\r
93e3992d 348IScsiFormExtractConfig (\r
349 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
350 IN CONST EFI_STRING Request,\r
351 OUT EFI_STRING *Progress,\r
352 OUT EFI_STRING *Results\r
6a690e23 353 )\r
6a690e23 354{\r
93e3992d 355 EFI_STATUS Status;\r
356 CHAR8 InitiatorName[ISCSI_NAME_IFR_MAX_SIZE];\r
357 UINTN BufferSize;\r
358 ISCSI_CONFIG_IFR_NVDATA *IfrNvData;\r
359 ISCSI_FORM_CALLBACK_INFO *Private;\r
360 EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;\r
6a690e23 361\r
ae79d2f9 362 if (Request == NULL || Progress == NULL || Results == NULL) {\r
669314e5 363 return EFI_INVALID_PARAMETER;\r
8d00a0f1 364 }\r
ae79d2f9 365 *Progress = Request;\r
8d00a0f1 366\r
6a690e23 367 if (!mIScsiDeviceListUpdated) {\r
368 //\r
369 // Update the device list.\r
370 //\r
371 IScsiUpdateDeviceList ();\r
372 mIScsiDeviceListUpdated = TRUE;\r
373 }\r
374\r
93e3992d 375 Private = ISCSI_FORM_CALLBACK_INFO_FROM_FORM_CALLBACK (This);\r
376 IfrNvData = AllocateZeroPool (sizeof (ISCSI_CONFIG_IFR_NVDATA));\r
377 ASSERT (IfrNvData != NULL);\r
378 if (Private->Current != NULL) {\r
379 IScsiConvertDeviceConfigDataToIfrNvData (Private->Current, IfrNvData);\r
380 }\r
6a690e23 381\r
93e3992d 382 BufferSize = ISCSI_NAME_IFR_MAX_SIZE;\r
6a690e23 383 Status = gIScsiInitiatorName.Get (&gIScsiInitiatorName, &BufferSize, InitiatorName);\r
384 if (EFI_ERROR (Status)) {\r
385 IfrNvData->InitiatorName[0] = L'\0';\r
386 } else {\r
387 IScsiAsciiStrToUnicodeStr (InitiatorName, IfrNvData->InitiatorName);\r
388 }\r
389\r
93e3992d 390 //\r
391 // Convert buffer data to <ConfigResp> by helper function BlockToConfig()\r
392 //\r
393 HiiConfigRouting = Private->ConfigRouting;\r
394 BufferSize = sizeof (ISCSI_CONFIG_IFR_NVDATA);\r
395 Status = HiiConfigRouting->BlockToConfig (\r
396 HiiConfigRouting,\r
397 Request,\r
398 (UINT8 *) IfrNvData,\r
399 BufferSize,\r
400 Results,\r
401 Progress\r
402 );\r
e48e37fc 403 gBS->FreePool (IfrNvData);\r
93e3992d 404 return Status;\r
6a690e23 405}\r
406\r
12618416 407/**\r
669314e5 408 This function applies changes in a driver's configuration.\r
409 Input is a Configuration, which has the routing data for this\r
410 driver followed by name / value configuration pairs. The driver\r
411 must apply those pairs to its configurable storage. If the\r
412 driver's configuration is stored in a linear block of data\r
55a64ae0 413 and the driver's name / value pairs are in <BlockConfig>\r
669314e5 414 format, it may use the ConfigToBlock helper function (above) to\r
415 simplify the job. Currently not implemented.\r
416\r
417 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
418 @param[in] Configuration A null-terminated Unicode string in\r
419 <ConfigString> format. \r
420 @param[out] Progress A pointer to a string filled in with the\r
421 offset of the most recent '&' before the\r
422 first failing name / value pair (or the\r
423 beginn ing of the string if the failure\r
424 is in the first name / value pair) or\r
425 the terminating NULL if all was\r
426 successful.\r
427\r
428 @retval EFI_SUCCESS The results have been distributed or are\r
429 awaiting distribution. \r
e1f1fb16 430 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the\r
669314e5 431 parts of the results that must be\r
432 stored awaiting possible future\r
433 protocols.\r
434 @retval EFI_INVALID_PARAMETERS Passing in a NULL for the\r
435 Results parameter would result\r
436 in this type of error.\r
437 @retval EFI_NOT_FOUND Target for the specified routing data\r
438 was not found.\r
12618416 439**/\r
6a690e23 440EFI_STATUS\r
441EFIAPI\r
93e3992d 442IScsiFormRouteConfig (\r
443 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
444 IN CONST EFI_STRING Configuration,\r
445 OUT EFI_STRING *Progress\r
6a690e23 446 )\r
12618416 447{\r
ae79d2f9
LG
448 if (Configuration == NULL || Progress == NULL) {\r
449 return EFI_INVALID_PARAMETER;\r
450 }\r
451\r
452 //\r
453 // Check routing data in <ConfigHdr>.\r
454 // Note: if only one Storage is used, then this checking could be skipped.\r
455 //\r
456 if (!HiiIsConfigHdrMatch (Configuration, &mVendorGuid, mVendorStorageName)) {\r
457 *Progress = Configuration;\r
458 return EFI_NOT_FOUND;\r
459 }\r
460\r
461 *Progress = Configuration + StrLen (Configuration);\r
12618416 462 return EFI_SUCCESS;\r
463}\r
6a690e23 464\r
12618416 465/**\r
669314e5 466 This function is called to provide results data to the driver.\r
467 This data consists of a unique key that is used to identify\r
468 which data is either being passed back or being asked for.\r
469\r
470 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
471 @param[in] Action Specifies the type of action taken by the browser.\r
472 @param[in] QuestionId A unique value which is sent to the original\r
473 exporting driver so that it can identify the type\r
474 of data to expect. The format of the data tends to \r
475 vary based on the opcode that enerated the callback.\r
476 @param[in] Type The type of value for the question.\r
477 @param[in] Value A pointer to the data being sent to the original\r
478 exporting driver.\r
479 @param[out] ActionRequest On return, points to the action requested by the\r
480 callback function.\r
481\r
482 @retval EFI_SUCCESS The callback successfully handled the action.\r
483 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the\r
484 variable and its data.\r
485 @retval EFI_DEVICE_ERROR The variable could not be saved.\r
486 @retval EFI_UNSUPPORTED The specified Action is not supported by the\r
487 callback.Currently not implemented.\r
488 @retval EFI_INVALID_PARAMETERS Passing in wrong parameter. \r
963dbb30 489 @retval Others Other errors as indicated. \r
12618416 490**/\r
93e3992d 491EFI_STATUS\r
492EFIAPI\r
493IScsiFormCallback (\r
494 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
f3e1569d 495 IN EFI_BROWSER_ACTION Action,\r
669314e5 496 IN EFI_QUESTION_ID QuestionId,\r
93e3992d 497 IN UINT8 Type,\r
498 IN EFI_IFR_TYPE_VALUE *Value,\r
499 OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest\r
500 )\r
6a690e23 501{\r
502 ISCSI_FORM_CALLBACK_INFO *Private;\r
503 UINTN BufferSize;\r
504 CHAR8 IScsiName[ISCSI_NAME_IFR_MAX_SIZE];\r
505 CHAR16 PortString[128];\r
506 CHAR8 Ip4String[IP4_STR_MAX_SIZE];\r
507 CHAR8 LunString[ISCSI_LUN_STR_MAX_LEN];\r
508 UINT64 Lun;\r
6c7a807a 509 EFI_STRING_ID DeviceFormTitleToken;\r
6a690e23 510 ISCSI_CONFIG_IFR_NVDATA *IfrNvData;\r
511 ISCSI_CONFIG_FORM_ENTRY *ConfigFormEntry;\r
512 EFI_IP_ADDRESS HostIp;\r
513 EFI_IP_ADDRESS SubnetMask;\r
514 EFI_IP_ADDRESS Gateway;\r
515 EFI_STATUS Status;\r
63d55bb9 516 EFI_INPUT_KEY Key;\r
6a690e23 517\r
518 Private = ISCSI_FORM_CALLBACK_INFO_FROM_FORM_CALLBACK (This);\r
93e3992d 519\r
520 //\r
521 // Retrive uncommitted data from Browser\r
522 //\r
1d451ff9
LG
523 IfrNvData = AllocateZeroPool (sizeof (ISCSI_CONFIG_IFR_NVDATA));\r
524 ASSERT (IfrNvData != NULL);\r
525 if (!HiiGetBrowserData (&mVendorGuid, mVendorStorageName, sizeof (ISCSI_CONFIG_IFR_NVDATA), (UINT8 *) IfrNvData)) {\r
526 FreePool (IfrNvData);\r
7e3bcccb 527 return EFI_NOT_FOUND;\r
93e3992d 528 }\r
7e3bcccb
LG
529 \r
530 Status = EFI_SUCCESS;\r
6a690e23 531\r
669314e5 532 switch (QuestionId) {\r
6a690e23 533 case KEY_INITIATOR_NAME:\r
534 IScsiUnicodeStrToAsciiStr (IfrNvData->InitiatorName, IScsiName);\r
535 BufferSize = AsciiStrLen (IScsiName) + 1;\r
536\r
537 Status = gIScsiInitiatorName.Set (&gIScsiInitiatorName, &BufferSize, IScsiName);\r
538 if (EFI_ERROR (Status)) {\r
63d55bb9 539 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid iSCSI Name!", NULL);\r
6a690e23 540 }\r
541\r
542 break;\r
543\r
544 case KEY_LOCAL_IP:\r
545 IScsiUnicodeStrToAsciiStr (IfrNvData->LocalIp, Ip4String);\r
546 Status = IScsiAsciiStrToIp (Ip4String, &HostIp.v4);\r
f6b7393c 547 if (EFI_ERROR (Status) || !NetIp4IsUnicast (NTOHL (HostIp.Addr[0]), 0)) {\r
63d55bb9 548 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid IP address!", NULL);\r
6a690e23 549 Status = EFI_INVALID_PARAMETER;\r
550 } else {\r
e48e37fc 551 CopyMem (&Private->Current->SessionConfigData.LocalIp, &HostIp.v4, sizeof (HostIp.v4));\r
6a690e23 552 }\r
553\r
554 break;\r
555\r
556 case KEY_SUBNET_MASK:\r
557 IScsiUnicodeStrToAsciiStr (IfrNvData->SubnetMask, Ip4String);\r
558 Status = IScsiAsciiStrToIp (Ip4String, &SubnetMask.v4);\r
559 if (EFI_ERROR (Status) || ((SubnetMask.Addr[0] != 0) && (IScsiGetSubnetMaskPrefixLength (&SubnetMask.v4) == 0))) {\r
63d55bb9 560 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid Subnet Mask!", NULL);\r
6a690e23 561 Status = EFI_INVALID_PARAMETER;\r
562 } else {\r
e48e37fc 563 CopyMem (&Private->Current->SessionConfigData.SubnetMask, &SubnetMask.v4, sizeof (SubnetMask.v4));\r
6a690e23 564 }\r
565\r
566 break;\r
567\r
568 case KEY_GATE_WAY:\r
569 IScsiUnicodeStrToAsciiStr (IfrNvData->Gateway, Ip4String);\r
570 Status = IScsiAsciiStrToIp (Ip4String, &Gateway.v4);\r
f6b7393c 571 if (EFI_ERROR (Status) || ((Gateway.Addr[0] != 0) && !NetIp4IsUnicast (NTOHL (Gateway.Addr[0]), 0))) {\r
63d55bb9 572 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid Gateway!", NULL);\r
6a690e23 573 Status = EFI_INVALID_PARAMETER;\r
574 } else {\r
e48e37fc 575 CopyMem (&Private->Current->SessionConfigData.Gateway, &Gateway.v4, sizeof (Gateway.v4));\r
6a690e23 576 }\r
577\r
578 break;\r
579\r
580 case KEY_TARGET_IP:\r
581 IScsiUnicodeStrToAsciiStr (IfrNvData->TargetIp, Ip4String);\r
582 Status = IScsiAsciiStrToIp (Ip4String, &HostIp.v4);\r
f6b7393c 583 if (EFI_ERROR (Status) || !NetIp4IsUnicast (NTOHL (HostIp.Addr[0]), 0)) {\r
63d55bb9 584 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid IP address!", NULL);\r
6a690e23 585 Status = EFI_INVALID_PARAMETER;\r
586 } else {\r
e48e37fc 587 CopyMem (&Private->Current->SessionConfigData.TargetIp, &HostIp.v4, sizeof (HostIp.v4));\r
6a690e23 588 }\r
589\r
590 break;\r
591\r
592 case KEY_TARGET_NAME:\r
593 IScsiUnicodeStrToAsciiStr (IfrNvData->TargetName, IScsiName);\r
594 Status = IScsiNormalizeName (IScsiName, AsciiStrLen (IScsiName));\r
595 if (EFI_ERROR (Status)) {\r
63d55bb9 596 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid iSCSI Name!", NULL);\r
6a690e23 597 } else {\r
598 AsciiStrCpy (Private->Current->SessionConfigData.TargetName, IScsiName);\r
599 }\r
600\r
601 break;\r
602\r
603 case KEY_DHCP_ENABLE:\r
604 if (IfrNvData->InitiatorInfoFromDhcp == 0) {\r
605 IfrNvData->TargetInfoFromDhcp = 0;\r
606 }\r
607\r
608 break;\r
609\r
610 case KEY_BOOT_LUN:\r
611 IScsiUnicodeStrToAsciiStr (IfrNvData->BootLun, LunString);\r
612 Status = IScsiAsciiStrToLun (LunString, (UINT8 *) &Lun);\r
613 if (EFI_ERROR (Status)) {\r
63d55bb9 614 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid LUN string!", NULL);\r
6a690e23 615 } else {\r
e48e37fc 616 CopyMem (Private->Current->SessionConfigData.BootLun, &Lun, sizeof (Lun));\r
6a690e23 617 }\r
618\r
619 break;\r
620\r
621 case KEY_CHAP_NAME:\r
622 IScsiUnicodeStrToAsciiStr (IfrNvData->CHAPName, Private->Current->AuthConfigData.CHAPName);\r
623 break;\r
624\r
625 case KEY_CHAP_SECRET:\r
626 IScsiUnicodeStrToAsciiStr (IfrNvData->CHAPSecret, Private->Current->AuthConfigData.CHAPSecret);\r
627 break;\r
628\r
629 case KEY_REVERSE_CHAP_NAME:\r
630 IScsiUnicodeStrToAsciiStr (IfrNvData->ReverseCHAPName, Private->Current->AuthConfigData.ReverseCHAPName);\r
631 break;\r
632\r
633 case KEY_REVERSE_CHAP_SECRET:\r
634 IScsiUnicodeStrToAsciiStr (IfrNvData->ReverseCHAPSecret, Private->Current->AuthConfigData.ReverseCHAPSecret);\r
635 break;\r
636\r
637 case KEY_SAVE_CHANGES:\r
638 //\r
639 // First, update those fields which don't have INTERACTIVE set.\r
640 //\r
641 Private->Current->SessionConfigData.Enabled = IfrNvData->Enabled;\r
642 Private->Current->SessionConfigData.InitiatorInfoFromDhcp = IfrNvData->InitiatorInfoFromDhcp;\r
643 Private->Current->SessionConfigData.TargetPort = IfrNvData->TargetPort;\r
644 if (Private->Current->SessionConfigData.TargetPort == 0) {\r
645 Private->Current->SessionConfigData.TargetPort = ISCSI_WELL_KNOWN_PORT;\r
646 }\r
647\r
648 Private->Current->SessionConfigData.TargetInfoFromDhcp = IfrNvData->TargetInfoFromDhcp;\r
649 Private->Current->AuthConfigData.CHAPType = IfrNvData->CHAPType;\r
650\r
651 //\r
652 // Only do full parameter validation if iSCSI is enabled on this device.\r
653 //\r
654 if (Private->Current->SessionConfigData.Enabled) {\r
655 //\r
656 // Validate the address configuration of the Initiator if DHCP isn't\r
657 // deployed.\r
658 //\r
659 if (!Private->Current->SessionConfigData.InitiatorInfoFromDhcp) {\r
e48e37fc 660 CopyMem (&HostIp.v4, &Private->Current->SessionConfigData.LocalIp, sizeof (HostIp.v4));\r
661 CopyMem (&SubnetMask.v4, &Private->Current->SessionConfigData.SubnetMask, sizeof (SubnetMask.v4));\r
662 CopyMem (&Gateway.v4, &Private->Current->SessionConfigData.Gateway, sizeof (Gateway.v4));\r
6a690e23 663\r
664 if ((Gateway.Addr[0] != 0)) {\r
665 if (SubnetMask.Addr[0] == 0) {\r
63d55bb9 666 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Gateway address is set but subnet mask is zero.", NULL);\r
6a690e23 667 Status = EFI_INVALID_PARAMETER;\r
668 break;\r
669 } else if (!IP4_NET_EQUAL (HostIp.Addr[0], Gateway.Addr[0], SubnetMask.Addr[0])) {\r
63d55bb9 670 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Local IP and Gateway are not in the same subnet.", NULL);\r
6a690e23 671 Status = EFI_INVALID_PARAMETER;\r
672 break;\r
673 }\r
674 }\r
675 }\r
676 //\r
677 // Validate target configuration if DHCP isn't deployed.\r
678 //\r
679 if (!Private->Current->SessionConfigData.TargetInfoFromDhcp) {\r
e48e37fc 680 CopyMem (&HostIp.v4, &Private->Current->SessionConfigData.TargetIp, sizeof (HostIp.v4));\r
f6b7393c 681 if (!NetIp4IsUnicast (NTOHL (HostIp.Addr[0]), 0)) {\r
63d55bb9 682 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Target IP is invalid!", NULL);\r
6a690e23 683 Status = EFI_INVALID_PARAMETER;\r
684 break;\r
685 }\r
686 }\r
687\r
688 if (IfrNvData->CHAPType != ISCSI_CHAP_NONE) {\r
689 if ((IfrNvData->CHAPName[0] == '\0') || (IfrNvData->CHAPSecret[0] == '\0')) {\r
63d55bb9 690 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"CHAP Name or CHAP Secret is invalid!", NULL);\r
6a690e23 691 Status = EFI_INVALID_PARAMETER;\r
692 break;\r
693 }\r
694\r
695 if ((IfrNvData->CHAPType == ISCSI_CHAP_MUTUAL) &&\r
696 ((IfrNvData->ReverseCHAPName[0] == '\0') || (IfrNvData->ReverseCHAPSecret[0] == '\0'))\r
697 ) {\r
63d55bb9 698 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Reverse CHAP Name or Reverse CHAP Secret is invalid!", NULL);\r
6a690e23 699 Status = EFI_INVALID_PARAMETER;\r
700 break;\r
701 }\r
702 }\r
703 }\r
704\r
705 BufferSize = sizeof (Private->Current->SessionConfigData);\r
706 gRT->SetVariable (\r
707 Private->Current->MacString,\r
708 &gEfiIScsiInitiatorNameProtocolGuid,\r
709 ISCSI_CONFIG_VAR_ATTR,\r
710 BufferSize,\r
711 &Private->Current->SessionConfigData\r
712 );\r
713\r
714 BufferSize = sizeof (Private->Current->AuthConfigData);\r
715 gRT->SetVariable (\r
716 Private->Current->MacString,\r
717 &mIScsiCHAPAuthInfoGuid,\r
718 ISCSI_CONFIG_VAR_ATTR,\r
719 BufferSize,\r
720 &Private->Current->AuthConfigData\r
721 );\r
93e3992d 722 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT;\r
6a690e23 723 break;\r
724\r
725 default:\r
669314e5 726 if ((QuestionId >= KEY_DEVICE_ENTRY_BASE) && (QuestionId < (mNumberOfIScsiDevices + KEY_DEVICE_ENTRY_BASE))) {\r
6a690e23 727 //\r
728 // In case goto the device configuration form, update the device form title.\r
729 //\r
669314e5 730 ConfigFormEntry = IScsiGetConfigFormEntryByIndex ((UINT32) (QuestionId - KEY_DEVICE_ENTRY_BASE));\r
6a690e23 731 ASSERT (ConfigFormEntry != NULL);\r
732\r
93e3992d 733 UnicodeSPrint (PortString, (UINTN) 128, L"Port %s", ConfigFormEntry->MacString);\r
6c7a807a 734 DeviceFormTitleToken = (EFI_STRING_ID) STR_ISCSI_DEVICE_FORM_TITLE;\r
cb7d01c0 735 HiiSetString (Private->RegisteredHandle, DeviceFormTitleToken, PortString, NULL);\r
6a690e23 736\r
737 IScsiConvertDeviceConfigDataToIfrNvData (ConfigFormEntry, IfrNvData);\r
738\r
739 Private->Current = ConfigFormEntry;\r
740 }\r
741\r
742 break;\r
743 }\r
744\r
93e3992d 745 if (!EFI_ERROR (Status)) {\r
746 //\r
747 // Pass changed uncommitted data back to Form Browser\r
748 //\r
7e3bcccb 749 HiiSetBrowserData (&mVendorGuid, mVendorStorageName, sizeof (ISCSI_CONFIG_IFR_NVDATA), (UINT8 *) IfrNvData, NULL);\r
93e3992d 750 }\r
751\r
7e3bcccb 752 FreePool (IfrNvData);\r
6a690e23 753 return Status;\r
754}\r
755\r
12618416 756/**\r
6a690e23 757 Updates the iSCSI configuration form to add/delete an entry for the iSCSI\r
758 device specified by the Controller.\r
759\r
669314e5 760 @param[in] DriverBindingHandle The driverbinding handle.\r
761 @param[in] Controller The controller handle of the iSCSI device.\r
762 @param[in] AddForm Whether to add or delete a form entry.\r
6a690e23 763\r
12618416 764 @retval EFI_SUCCESS The iSCSI configuration form is updated.\r
12618416 765 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
963dbb30 766 @retval Others Other errors as indicated.\r
12618416 767**/\r
768EFI_STATUS\r
769IScsiConfigUpdateForm (\r
770 IN EFI_HANDLE DriverBindingHandle,\r
771 IN EFI_HANDLE Controller,\r
772 IN BOOLEAN AddForm\r
773 )\r
6a690e23 774{\r
e48e37fc 775 LIST_ENTRY *Entry;\r
6a690e23 776 ISCSI_CONFIG_FORM_ENTRY *ConfigFormEntry;\r
777 BOOLEAN EntryExisted;\r
6a690e23 778 EFI_STATUS Status;\r
6a690e23 779 EFI_SIMPLE_NETWORK_PROTOCOL *Snp;\r
780 CHAR16 PortString[128];\r
781 UINT16 FormIndex;\r
782 UINTN BufferSize;\r
7e3bcccb
LG
783 VOID *StartOpCodeHandle;\r
784 VOID *EndOpCodeHandle;\r
785 EFI_IFR_GUID_LABEL *StartLabel;\r
786 EFI_IFR_GUID_LABEL *EndLabel;\r
6a690e23 787\r
788 ConfigFormEntry = NULL;\r
789 EntryExisted = FALSE;\r
790\r
791 NET_LIST_FOR_EACH (Entry, &mIScsiConfigFormList) {\r
792 ConfigFormEntry = NET_LIST_USER_STRUCT (Entry, ISCSI_CONFIG_FORM_ENTRY, Link);\r
793\r
794 if (ConfigFormEntry->Controller == Controller) {\r
795 EntryExisted = TRUE;\r
796 break;\r
797 }\r
798 }\r
799\r
800 if (AddForm) {\r
801 if (EntryExisted) {\r
802 return EFI_SUCCESS;\r
803 } else {\r
804 //\r
805 // Add a new form.\r
806 //\r
e48e37fc 807 ConfigFormEntry = (ISCSI_CONFIG_FORM_ENTRY *) AllocateZeroPool (sizeof (ISCSI_CONFIG_FORM_ENTRY));\r
6a690e23 808 if (ConfigFormEntry == NULL) {\r
809 return EFI_OUT_OF_RESOURCES;\r
810 }\r
811\r
e48e37fc 812 InitializeListHead (&ConfigFormEntry->Link);\r
6a690e23 813 ConfigFormEntry->Controller = Controller;\r
814\r
815 //\r
816 // Get the simple network protocol and convert the MAC address into\r
817 // the formatted string.\r
818 //\r
819 Status = gBS->HandleProtocol (\r
820 Controller,\r
821 &gEfiSimpleNetworkProtocolGuid,\r
822 (VOID **)&Snp\r
823 );\r
824 ASSERT (Status == EFI_SUCCESS);\r
825\r
826 IScsiMacAddrToStr (&Snp->Mode->PermanentAddress, Snp->Mode->HwAddressSize, ConfigFormEntry->MacString);\r
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
876 gBS->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
e48e37fc 1058 gBS->FreePool (mCallbackInfo);\r
6a690e23 1059\r
1060 return EFI_SUCCESS;\r
1061}\r