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