]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Network/IScsiDxe/IScsiConfig.c
1) Update SetPeiServicesTablePointer's prototype add CONST modifier.
[mirror_edk2.git] / MdeModulePkg / Universal / Network / IScsiDxe / IScsiConfig.c
1 /** @file
2 Helper functions for configuring or getting the parameters relating to ISCSI
3
4 Copyright (c) 2004 - 2008, Intel Corporation
5 All rights reserved. This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13 Module Name:
14
15 IScsiConfig.c
16
17 Abstract:
18
19 Helper functions for configuring or getting the parameters relating to ISCSI
20
21 **/
22
23 #include "IScsiImpl.h"
24
25 EFI_GUID mVendorGuid = ISCSI_CONFIG_GUID;
26 BOOLEAN mIScsiDeviceListUpdated = FALSE;
27 UINTN mNumberOfIScsiDevices = 0;
28 ISCSI_FORM_CALLBACK_INFO *mCallbackInfo = NULL;
29
30 LIST_ENTRY mIScsiConfigFormList = {
31 &mIScsiConfigFormList,
32 &mIScsiConfigFormList
33 };
34
35 /**
36 Convert the IPv4 address into a dotted string.
37
38 @param Ip[in] The IPv4 address.
39
40 @param Str[out] The dotted IP string.
41
42 @retval None.
43
44 **/
45 STATIC
46 VOID
47 IScsiIpToStr (
48 IN EFI_IPv4_ADDRESS *Ip,
49 OUT CHAR16 *Str
50 )
51 {
52 UnicodeSPrint ( Str, 2 * IP4_STR_MAX_SIZE, L"%d.%d.%d.%d", Ip->Addr[0], Ip->Addr[1], Ip->Addr[2], Ip->Addr[3]);
53 }
54
55 /**
56 Pop up an invalid notify which displays the message in Warning.
57
58 @param Warning[in] The warning message.
59
60 @retval None.
61
62 **/
63 VOID
64 PopUpInvalidNotify (
65 IN CHAR16 *Warning
66 )
67 {
68 EFI_INPUT_KEY Key;
69
70 IfrLibCreatePopUp (1, &Key, Warning);
71 }
72
73 /**
74 Update the list of iSCSI devices the iSCSI driver is controlling.
75
76 @param None.
77
78 @retval None.
79
80 **/
81 EFI_STATUS
82 IScsiUpdateDeviceList (
83 VOID
84 )
85 {
86 EFI_STATUS Status;
87 ISCSI_DEVICE_LIST *DeviceList;
88 UINTN DataSize;
89 UINTN NumHandles;
90 EFI_HANDLE *Handles;
91 UINTN HandleIndex;
92 UINTN Index;
93 UINTN LastDeviceIndex;
94 EFI_SIMPLE_NETWORK_PROTOCOL *Snp;
95 EFI_SIMPLE_NETWORK_MODE *Mode;
96 ISCSI_MAC_INFO *CurMacInfo;
97 ISCSI_MAC_INFO TempMacInfo;
98 CHAR16 MacString[65];
99 UINTN DeviceListSize;
100
101 //
102 // Dump all the handles the Simple Network Protocol is installed on.
103 //
104 Status = gBS->LocateHandleBuffer (
105 ByProtocol,
106 &gEfiSimpleNetworkProtocolGuid,
107 NULL,
108 &NumHandles,
109 &Handles
110 );
111 if (EFI_ERROR (Status)) {
112 return Status;
113 }
114
115 DataSize = 0;
116 Status = gRT->GetVariable (
117 L"iSCSIDeviceList",
118 &mVendorGuid,
119 NULL,
120 &DataSize,
121 NULL
122 );
123 if (Status == EFI_BUFFER_TOO_SMALL) {
124 DeviceList = (ISCSI_DEVICE_LIST *) AllocatePool (DataSize);
125
126 gRT->GetVariable (
127 L"iSCSIDeviceList",
128 &mVendorGuid,
129 NULL,
130 &DataSize,
131 DeviceList
132 );
133
134 LastDeviceIndex = 0;
135
136 for (HandleIndex = 0; HandleIndex < NumHandles; HandleIndex++) {
137 gBS->HandleProtocol (Handles[HandleIndex], &gEfiSimpleNetworkProtocolGuid, (VOID **)&Snp);
138
139 Mode = Snp->Mode;
140
141 for (Index = LastDeviceIndex; Index < DeviceList->NumDevice; Index++) {
142 CurMacInfo = &DeviceList->MacInfo[Index];
143 if ((CurMacInfo->Len == Mode->HwAddressSize) &&
144 (NET_MAC_EQUAL (&CurMacInfo->Mac, &Mode->PermanentAddress, Mode->HwAddressSize))
145 ) {
146 //
147 // The previous configured NIC is still here.
148 //
149 if (Index != LastDeviceIndex) {
150 //
151 // Swap the current MAC address entry with the one indexed by
152 // LastDeviceIndex.
153 //
154 CopyMem (&TempMacInfo, CurMacInfo, sizeof (ISCSI_MAC_INFO));
155 CopyMem (CurMacInfo, &DeviceList->MacInfo[LastDeviceIndex], sizeof (ISCSI_MAC_INFO));
156 CopyMem (&DeviceList->MacInfo[LastDeviceIndex], &TempMacInfo, sizeof (ISCSI_MAC_INFO));
157 }
158
159 LastDeviceIndex++;
160 }
161 }
162
163 if (LastDeviceIndex == DeviceList->NumDevice) {
164 break;
165 }
166 }
167
168 for (Index = LastDeviceIndex; Index < DeviceList->NumDevice; Index++) {
169 //
170 // delete the variables
171 //
172 CurMacInfo = &DeviceList->MacInfo[Index];
173 IScsiMacAddrToStr (&CurMacInfo->Mac, CurMacInfo->Len, MacString);
174 gRT->SetVariable (MacString, &gEfiIScsiInitiatorNameProtocolGuid, 0, 0, NULL);
175 gRT->SetVariable (MacString, &mIScsiCHAPAuthInfoGuid, 0, 0, NULL);
176 }
177
178 gBS->FreePool (DeviceList);
179 } else if (Status != EFI_NOT_FOUND) {
180 gBS->FreePool (Handles);
181 return Status;
182 }
183 //
184 // Construct the new iSCSI device list.
185 //
186 DeviceListSize = sizeof (ISCSI_DEVICE_LIST) + (NumHandles - 1) * sizeof (ISCSI_MAC_INFO);
187 DeviceList = (ISCSI_DEVICE_LIST *) AllocatePool (DeviceListSize);
188 DeviceList->NumDevice = (UINT8) NumHandles;
189
190 for (Index = 0; Index < NumHandles; Index++) {
191 gBS->HandleProtocol (Handles[Index], &gEfiSimpleNetworkProtocolGuid, (VOID **)&Snp);
192 Mode = Snp->Mode;
193
194 CurMacInfo = &DeviceList->MacInfo[Index];
195 CopyMem (&CurMacInfo->Mac, &Mode->PermanentAddress, Mode->HwAddressSize);
196 CurMacInfo->Len = (UINT8) Mode->HwAddressSize;
197 }
198
199 gRT->SetVariable (
200 L"iSCSIDeviceList",
201 &mVendorGuid,
202 ISCSI_CONFIG_VAR_ATTR,
203 DeviceListSize,
204 DeviceList
205 );
206
207 gBS->FreePool (DeviceList);
208 gBS->FreePool (Handles);
209
210 return Status;
211 }
212
213 /**
214 Get the iSCSI configuration form entry by the index of the goto opcode actived.
215
216 @param Index[in] The 0-based index of the goto opcode actived.
217
218 @retval The iSCSI configuration form entry found.
219
220 **/
221 STATIC
222 ISCSI_CONFIG_FORM_ENTRY *
223 IScsiGetConfigFormEntryByIndex (
224 IN UINT32 Index
225 )
226 {
227 UINT32 CurrentIndex;
228 LIST_ENTRY *Entry;
229 ISCSI_CONFIG_FORM_ENTRY *ConfigFormEntry;
230
231 CurrentIndex = 0;
232 ConfigFormEntry = NULL;
233
234 NET_LIST_FOR_EACH (Entry, &mIScsiConfigFormList) {
235 if (CurrentIndex == Index) {
236 ConfigFormEntry = NET_LIST_USER_STRUCT (Entry, ISCSI_CONFIG_FORM_ENTRY, Link);
237 break;
238 }
239
240 CurrentIndex++;
241 }
242
243 return ConfigFormEntry;
244 }
245
246 /**
247 Convert the iSCSI configuration data into the IFR data.
248
249 @param ConfigFormEntry[in] The iSCSI configuration form entry.
250
251 @param IfrNvData[in] The IFR nv data.
252
253 @retval None.
254
255 **/
256 STATIC
257 VOID
258 IScsiConvertDeviceConfigDataToIfrNvData (
259 IN ISCSI_CONFIG_FORM_ENTRY *ConfigFormEntry,
260 IN ISCSI_CONFIG_IFR_NVDATA *IfrNvData
261 )
262 {
263 ISCSI_SESSION_CONFIG_NVDATA *SessionConfigData;
264 ISCSI_CHAP_AUTH_CONFIG_NVDATA *AuthConfigData;
265
266 //
267 // Normal session configuration parameters.
268 //
269 SessionConfigData = &ConfigFormEntry->SessionConfigData;
270 IfrNvData->Enabled = SessionConfigData->Enabled;
271
272 IfrNvData->InitiatorInfoFromDhcp = SessionConfigData->InitiatorInfoFromDhcp;
273 IfrNvData->TargetInfoFromDhcp = SessionConfigData->TargetInfoFromDhcp;
274 IfrNvData->TargetPort = SessionConfigData->TargetPort;
275
276 IScsiIpToStr (&SessionConfigData->LocalIp, IfrNvData->LocalIp);
277 IScsiIpToStr (&SessionConfigData->SubnetMask, IfrNvData->SubnetMask);
278 IScsiIpToStr (&SessionConfigData->Gateway, IfrNvData->Gateway);
279 IScsiIpToStr (&SessionConfigData->TargetIp, IfrNvData->TargetIp);
280
281 IScsiAsciiStrToUnicodeStr (SessionConfigData->TargetName, IfrNvData->TargetName);
282
283 IScsiLunToUnicodeStr (SessionConfigData->BootLun, IfrNvData->BootLun);
284
285 //
286 // CHAP authentication parameters.
287 //
288 AuthConfigData = &ConfigFormEntry->AuthConfigData;
289
290 IfrNvData->CHAPType = AuthConfigData->CHAPType;
291
292 IScsiAsciiStrToUnicodeStr (AuthConfigData->CHAPName, IfrNvData->CHAPName);
293 IScsiAsciiStrToUnicodeStr (AuthConfigData->CHAPSecret, IfrNvData->CHAPSecret);
294 IScsiAsciiStrToUnicodeStr (AuthConfigData->ReverseCHAPName, IfrNvData->ReverseCHAPName);
295 IScsiAsciiStrToUnicodeStr (AuthConfigData->ReverseCHAPSecret, IfrNvData->ReverseCHAPSecret);
296 }
297
298 /**
299 This function allows a caller to extract the current configuration for one
300 or more named elements from the target driver.
301
302 @param This[in] Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
303
304 @param Request[in] A null-terminated Unicode string in <ConfigRequest> format.
305
306 @param Progress[out] On return, points to a character in the Request string.
307 Points to the string's null terminator if request was successful.
308 Points to the most recent '&' before the first failing name/value
309 pair (or the beginning of the string if the failure is in the
310 first name/value pair) if the request was not successful.
311
312 @param Results[out] A null-terminated Unicode string in <ConfigAltResp> format which
313 has all values filled in for the names in the Request string.
314 String to be allocated by the called function.
315
316 @retval EFI_SUCCESS The Results is filled with the requested values.
317
318 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results.
319
320 @retval EFI_INVALID_PARAMETER Request is NULL, illegal syntax, or unknown name.
321
322 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this driver.
323
324 **/
325 EFI_STATUS
326 EFIAPI
327 IScsiFormExtractConfig (
328 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
329 IN CONST EFI_STRING Request,
330 OUT EFI_STRING *Progress,
331 OUT EFI_STRING *Results
332 )
333 {
334 EFI_STATUS Status;
335 CHAR8 InitiatorName[ISCSI_NAME_IFR_MAX_SIZE];
336 UINTN BufferSize;
337 ISCSI_CONFIG_IFR_NVDATA *IfrNvData;
338 ISCSI_FORM_CALLBACK_INFO *Private;
339 EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;
340
341 if (!mIScsiDeviceListUpdated) {
342 //
343 // Update the device list.
344 //
345 IScsiUpdateDeviceList ();
346 mIScsiDeviceListUpdated = TRUE;
347 }
348
349 Private = ISCSI_FORM_CALLBACK_INFO_FROM_FORM_CALLBACK (This);
350 IfrNvData = AllocateZeroPool (sizeof (ISCSI_CONFIG_IFR_NVDATA));
351 ASSERT (IfrNvData != NULL);
352 if (Private->Current != NULL) {
353 IScsiConvertDeviceConfigDataToIfrNvData (Private->Current, IfrNvData);
354 }
355
356 BufferSize = ISCSI_NAME_IFR_MAX_SIZE;
357 Status = gIScsiInitiatorName.Get (&gIScsiInitiatorName, &BufferSize, InitiatorName);
358 if (EFI_ERROR (Status)) {
359 IfrNvData->InitiatorName[0] = L'\0';
360 } else {
361 IScsiAsciiStrToUnicodeStr (InitiatorName, IfrNvData->InitiatorName);
362 }
363
364 //
365 // Convert buffer data to <ConfigResp> by helper function BlockToConfig()
366 //
367 HiiConfigRouting = Private->ConfigRouting;
368 BufferSize = sizeof (ISCSI_CONFIG_IFR_NVDATA);
369 Status = HiiConfigRouting->BlockToConfig (
370 HiiConfigRouting,
371 Request,
372 (UINT8 *) IfrNvData,
373 BufferSize,
374 Results,
375 Progress
376 );
377 gBS->FreePool (IfrNvData);
378 return Status;
379 }
380
381 /**
382 This function processes the results of changes in configuration.
383
384 @param This[in] Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
385
386 @param Configuration[in] A null-terminated Unicode string in <ConfigResp> format.
387
388 @param Progress[out] A pointer to a string filled in with the offset of the most
389 recent '&' before the first failing name/value pair (or the
390 beginning of the string if the failure is in the first
391 name/value pair) or the terminating NULL if all was successful.
392
393 @retval EFI_SUCCESS The Results is processed successfully.
394
395 @retval EFI_INVALID_PARAMETER Configuration is NULL.
396
397 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this driver.
398
399 **/
400 EFI_STATUS
401 EFIAPI
402 IScsiFormRouteConfig (
403 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
404 IN CONST EFI_STRING Configuration,
405 OUT EFI_STRING *Progress
406 )
407 {
408 return EFI_SUCCESS;
409 }
410
411 /**
412 This function processes the results of changes in configuration.
413
414 @param This[in] Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
415
416 @param Action[in] Specifies the type of action taken by the browser.
417
418 @param QuestionId[in] A unique value which is sent to the original exporting driver
419 so that it can identify the type of data to expect.
420
421 @param Type[in] The type of value for the question.
422
423 @param Value[in] A pointer to the data being sent to the original exporting driver.
424
425 @param ActionRequest[out] On return, points to the action requested by the callback function.
426
427 @retval EFI_SUCCESS The callback successfully handled the action.
428
429 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the variable and its data.
430
431 @retval EFI_DEVICE_ERROR The variable could not be saved.
432
433 @retval EFI_UNSUPPORTED The specified Action is not supported by the callback.
434
435 **/
436 EFI_STATUS
437 EFIAPI
438 IScsiFormCallback (
439 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
440 IN EFI_BROWSER_ACTION Action,
441 IN EFI_QUESTION_ID KeyValue,
442 IN UINT8 Type,
443 IN EFI_IFR_TYPE_VALUE *Value,
444 OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest
445 )
446 {
447 ISCSI_FORM_CALLBACK_INFO *Private;
448 UINTN BufferSize;
449 CHAR8 IScsiName[ISCSI_NAME_IFR_MAX_SIZE];
450 CHAR16 PortString[128];
451 CHAR8 Ip4String[IP4_STR_MAX_SIZE];
452 CHAR8 LunString[ISCSI_LUN_STR_MAX_LEN];
453 UINT64 Lun;
454 EFI_STRING_ID DeviceFormTitleToken;
455 ISCSI_CONFIG_IFR_NVDATA *IfrNvData;
456 ISCSI_CONFIG_FORM_ENTRY *ConfigFormEntry;
457 EFI_IP_ADDRESS HostIp;
458 EFI_IP_ADDRESS SubnetMask;
459 EFI_IP_ADDRESS Gateway;
460 EFI_STATUS Status;
461
462 Private = ISCSI_FORM_CALLBACK_INFO_FROM_FORM_CALLBACK (This);
463
464 //
465 // Retrive uncommitted data from Browser
466 //
467 BufferSize = sizeof (ISCSI_CONFIG_IFR_NVDATA);
468 IfrNvData = AllocateZeroPool (BufferSize);
469 ASSERT (IfrNvData != NULL);
470 Status = GetBrowserData (NULL, NULL, &BufferSize, (UINT8 *) IfrNvData);
471 if (EFI_ERROR (Status)) {
472 gBS->FreePool (IfrNvData);
473 return Status;
474 }
475
476 switch (KeyValue) {
477 case KEY_INITIATOR_NAME:
478 IScsiUnicodeStrToAsciiStr (IfrNvData->InitiatorName, IScsiName);
479 BufferSize = AsciiStrLen (IScsiName) + 1;
480
481 Status = gIScsiInitiatorName.Set (&gIScsiInitiatorName, &BufferSize, IScsiName);
482 if (EFI_ERROR (Status)) {
483 PopUpInvalidNotify (L"Invalid iSCSI Name!");
484 }
485
486 break;
487
488 case KEY_LOCAL_IP:
489 IScsiUnicodeStrToAsciiStr (IfrNvData->LocalIp, Ip4String);
490 Status = IScsiAsciiStrToIp (Ip4String, &HostIp.v4);
491 if (EFI_ERROR (Status) || !Ip4IsUnicast (NTOHL (HostIp.Addr[0]), 0)) {
492 PopUpInvalidNotify (L"Invalid IP address!");
493 Status = EFI_INVALID_PARAMETER;
494 } else {
495 CopyMem (&Private->Current->SessionConfigData.LocalIp, &HostIp.v4, sizeof (HostIp.v4));
496 }
497
498 break;
499
500 case KEY_SUBNET_MASK:
501 IScsiUnicodeStrToAsciiStr (IfrNvData->SubnetMask, Ip4String);
502 Status = IScsiAsciiStrToIp (Ip4String, &SubnetMask.v4);
503 if (EFI_ERROR (Status) || ((SubnetMask.Addr[0] != 0) && (IScsiGetSubnetMaskPrefixLength (&SubnetMask.v4) == 0))) {
504 PopUpInvalidNotify (L"Invalid Subnet Mask!");
505 Status = EFI_INVALID_PARAMETER;
506 } else {
507 CopyMem (&Private->Current->SessionConfigData.SubnetMask, &SubnetMask.v4, sizeof (SubnetMask.v4));
508 }
509
510 break;
511
512 case KEY_GATE_WAY:
513 IScsiUnicodeStrToAsciiStr (IfrNvData->Gateway, Ip4String);
514 Status = IScsiAsciiStrToIp (Ip4String, &Gateway.v4);
515 if (EFI_ERROR (Status) || ((Gateway.Addr[0] != 0) && !Ip4IsUnicast (NTOHL (Gateway.Addr[0]), 0))) {
516 PopUpInvalidNotify (L"Invalid Gateway!");
517 Status = EFI_INVALID_PARAMETER;
518 } else {
519 CopyMem (&Private->Current->SessionConfigData.Gateway, &Gateway.v4, sizeof (Gateway.v4));
520 }
521
522 break;
523
524 case KEY_TARGET_IP:
525 IScsiUnicodeStrToAsciiStr (IfrNvData->TargetIp, Ip4String);
526 Status = IScsiAsciiStrToIp (Ip4String, &HostIp.v4);
527 if (EFI_ERROR (Status) || !Ip4IsUnicast (NTOHL (HostIp.Addr[0]), 0)) {
528 PopUpInvalidNotify (L"Invalid IP address!");
529 Status = EFI_INVALID_PARAMETER;
530 } else {
531 CopyMem (&Private->Current->SessionConfigData.TargetIp, &HostIp.v4, sizeof (HostIp.v4));
532 }
533
534 break;
535
536 case KEY_TARGET_NAME:
537 IScsiUnicodeStrToAsciiStr (IfrNvData->TargetName, IScsiName);
538 Status = IScsiNormalizeName (IScsiName, AsciiStrLen (IScsiName));
539 if (EFI_ERROR (Status)) {
540 PopUpInvalidNotify (L"Invalid iSCSI Name!");
541 } else {
542 AsciiStrCpy (Private->Current->SessionConfigData.TargetName, IScsiName);
543 }
544
545 break;
546
547 case KEY_DHCP_ENABLE:
548 if (IfrNvData->InitiatorInfoFromDhcp == 0) {
549 IfrNvData->TargetInfoFromDhcp = 0;
550 }
551
552 break;
553
554 case KEY_BOOT_LUN:
555 IScsiUnicodeStrToAsciiStr (IfrNvData->BootLun, LunString);
556 Status = IScsiAsciiStrToLun (LunString, (UINT8 *) &Lun);
557 if (EFI_ERROR (Status)) {
558 PopUpInvalidNotify (L"Invalid LUN string!");
559 } else {
560 CopyMem (Private->Current->SessionConfigData.BootLun, &Lun, sizeof (Lun));
561 }
562
563 break;
564
565 case KEY_CHAP_NAME:
566 IScsiUnicodeStrToAsciiStr (IfrNvData->CHAPName, Private->Current->AuthConfigData.CHAPName);
567 break;
568
569 case KEY_CHAP_SECRET:
570 IScsiUnicodeStrToAsciiStr (IfrNvData->CHAPSecret, Private->Current->AuthConfigData.CHAPSecret);
571 break;
572
573 case KEY_REVERSE_CHAP_NAME:
574 IScsiUnicodeStrToAsciiStr (IfrNvData->ReverseCHAPName, Private->Current->AuthConfigData.ReverseCHAPName);
575 break;
576
577 case KEY_REVERSE_CHAP_SECRET:
578 IScsiUnicodeStrToAsciiStr (IfrNvData->ReverseCHAPSecret, Private->Current->AuthConfigData.ReverseCHAPSecret);
579 break;
580
581 case KEY_SAVE_CHANGES:
582 //
583 // First, update those fields which don't have INTERACTIVE set.
584 //
585 Private->Current->SessionConfigData.Enabled = IfrNvData->Enabled;
586 Private->Current->SessionConfigData.InitiatorInfoFromDhcp = IfrNvData->InitiatorInfoFromDhcp;
587 Private->Current->SessionConfigData.TargetPort = IfrNvData->TargetPort;
588 if (Private->Current->SessionConfigData.TargetPort == 0) {
589 Private->Current->SessionConfigData.TargetPort = ISCSI_WELL_KNOWN_PORT;
590 }
591
592 Private->Current->SessionConfigData.TargetInfoFromDhcp = IfrNvData->TargetInfoFromDhcp;
593 Private->Current->AuthConfigData.CHAPType = IfrNvData->CHAPType;
594
595 //
596 // Only do full parameter validation if iSCSI is enabled on this device.
597 //
598 if (Private->Current->SessionConfigData.Enabled) {
599 //
600 // Validate the address configuration of the Initiator if DHCP isn't
601 // deployed.
602 //
603 if (!Private->Current->SessionConfigData.InitiatorInfoFromDhcp) {
604 CopyMem (&HostIp.v4, &Private->Current->SessionConfigData.LocalIp, sizeof (HostIp.v4));
605 CopyMem (&SubnetMask.v4, &Private->Current->SessionConfigData.SubnetMask, sizeof (SubnetMask.v4));
606 CopyMem (&Gateway.v4, &Private->Current->SessionConfigData.Gateway, sizeof (Gateway.v4));
607
608 if ((Gateway.Addr[0] != 0)) {
609 if (SubnetMask.Addr[0] == 0) {
610 PopUpInvalidNotify (L"Gateway address is set but subnet mask is zero.");
611 Status = EFI_INVALID_PARAMETER;
612 break;
613 } else if (!IP4_NET_EQUAL (HostIp.Addr[0], Gateway.Addr[0], SubnetMask.Addr[0])) {
614 PopUpInvalidNotify (L"Local IP and Gateway are not in the same subnet.");
615 Status = EFI_INVALID_PARAMETER;
616 break;
617 }
618 }
619 }
620 //
621 // Validate target configuration if DHCP isn't deployed.
622 //
623 if (!Private->Current->SessionConfigData.TargetInfoFromDhcp) {
624 CopyMem (&HostIp.v4, &Private->Current->SessionConfigData.TargetIp, sizeof (HostIp.v4));
625 if (!Ip4IsUnicast (NTOHL (HostIp.Addr[0]), 0)) {
626 PopUpInvalidNotify (L"Target IP is invalid!");
627 Status = EFI_INVALID_PARAMETER;
628 break;
629 }
630 }
631
632 if (IfrNvData->CHAPType != ISCSI_CHAP_NONE) {
633 if ((IfrNvData->CHAPName[0] == '\0') || (IfrNvData->CHAPSecret[0] == '\0')) {
634 PopUpInvalidNotify (L"CHAP Name or CHAP Secret is invalid!");
635 Status = EFI_INVALID_PARAMETER;
636 break;
637 }
638
639 if ((IfrNvData->CHAPType == ISCSI_CHAP_MUTUAL) &&
640 ((IfrNvData->ReverseCHAPName[0] == '\0') || (IfrNvData->ReverseCHAPSecret[0] == '\0'))
641 ) {
642 PopUpInvalidNotify (L"Reverse CHAP Name or Reverse CHAP Secret is invalid!");
643 Status = EFI_INVALID_PARAMETER;
644 break;
645 }
646 }
647 }
648
649 BufferSize = sizeof (Private->Current->SessionConfigData);
650 gRT->SetVariable (
651 Private->Current->MacString,
652 &gEfiIScsiInitiatorNameProtocolGuid,
653 ISCSI_CONFIG_VAR_ATTR,
654 BufferSize,
655 &Private->Current->SessionConfigData
656 );
657
658 BufferSize = sizeof (Private->Current->AuthConfigData);
659 gRT->SetVariable (
660 Private->Current->MacString,
661 &mIScsiCHAPAuthInfoGuid,
662 ISCSI_CONFIG_VAR_ATTR,
663 BufferSize,
664 &Private->Current->AuthConfigData
665 );
666 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT;
667 break;
668
669 default:
670 if ((KeyValue >= KEY_DEVICE_ENTRY_BASE) && (KeyValue < (mNumberOfIScsiDevices + KEY_DEVICE_ENTRY_BASE))) {
671 //
672 // In case goto the device configuration form, update the device form title.
673 //
674 ConfigFormEntry = IScsiGetConfigFormEntryByIndex ((UINT32) (KeyValue - KEY_DEVICE_ENTRY_BASE));
675 ASSERT (ConfigFormEntry != NULL);
676
677 UnicodeSPrint (PortString, (UINTN) 128, L"Port %s", ConfigFormEntry->MacString);
678 DeviceFormTitleToken = (EFI_STRING_ID) STR_ISCSI_DEVICE_FORM_TITLE;
679 HiiLibSetString (Private->RegisteredHandle, DeviceFormTitleToken, PortString);
680
681 IScsiConvertDeviceConfigDataToIfrNvData (ConfigFormEntry, IfrNvData);
682
683 Private->Current = ConfigFormEntry;
684 }
685
686 break;
687 }
688
689 if (!EFI_ERROR (Status)) {
690 //
691 // Pass changed uncommitted data back to Form Browser
692 //
693 BufferSize = sizeof (ISCSI_CONFIG_IFR_NVDATA);
694 Status = SetBrowserData (NULL, NULL, BufferSize, (UINT8 *) IfrNvData, NULL);
695 }
696
697 gBS->FreePool (IfrNvData);
698 return Status;
699 }
700
701 /**
702 Updates the iSCSI configuration form to add/delete an entry for the iSCSI
703 device specified by the Controller.
704
705 @param DriverBindingHandle[in] The driverbinding handle.
706
707 @param Controller[in] The controller handle of the iSCSI device.
708
709 @param AddForm[in] Whether to add or delete a form entry.
710
711 @retval EFI_SUCCESS The iSCSI configuration form is updated.
712
713 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
714
715 **/
716 EFI_STATUS
717 IScsiConfigUpdateForm (
718 IN EFI_HANDLE DriverBindingHandle,
719 IN EFI_HANDLE Controller,
720 IN BOOLEAN AddForm
721 )
722 {
723 LIST_ENTRY *Entry;
724 ISCSI_CONFIG_FORM_ENTRY *ConfigFormEntry;
725 BOOLEAN EntryExisted;
726 EFI_STATUS Status;
727 EFI_HII_UPDATE_DATA UpdateData;
728 EFI_SIMPLE_NETWORK_PROTOCOL *Snp;
729 CHAR16 PortString[128];
730 UINT16 FormIndex;
731 UINTN BufferSize;
732
733
734 ConfigFormEntry = NULL;
735 EntryExisted = FALSE;
736
737 NET_LIST_FOR_EACH (Entry, &mIScsiConfigFormList) {
738 ConfigFormEntry = NET_LIST_USER_STRUCT (Entry, ISCSI_CONFIG_FORM_ENTRY, Link);
739
740 if (ConfigFormEntry->Controller == Controller) {
741 EntryExisted = TRUE;
742 break;
743 }
744 }
745
746 if (AddForm) {
747 if (EntryExisted) {
748 return EFI_SUCCESS;
749 } else {
750 //
751 // Add a new form.
752 //
753 ConfigFormEntry = (ISCSI_CONFIG_FORM_ENTRY *) AllocateZeroPool (sizeof (ISCSI_CONFIG_FORM_ENTRY));
754 if (ConfigFormEntry == NULL) {
755 return EFI_OUT_OF_RESOURCES;
756 }
757
758 InitializeListHead (&ConfigFormEntry->Link);
759 ConfigFormEntry->Controller = Controller;
760
761 //
762 // Get the simple network protocol and convert the MAC address into
763 // the formatted string.
764 //
765 Status = gBS->HandleProtocol (
766 Controller,
767 &gEfiSimpleNetworkProtocolGuid,
768 (VOID **)&Snp
769 );
770 ASSERT (Status == EFI_SUCCESS);
771
772 IScsiMacAddrToStr (&Snp->Mode->PermanentAddress, Snp->Mode->HwAddressSize, ConfigFormEntry->MacString);
773
774 //
775 // Get the normal session configuration data.
776 //
777 BufferSize = sizeof (ConfigFormEntry->SessionConfigData);
778 Status = gRT->GetVariable (
779 ConfigFormEntry->MacString,
780 &gEfiIScsiInitiatorNameProtocolGuid,
781 NULL,
782 &BufferSize,
783 &ConfigFormEntry->SessionConfigData
784 );
785 if (EFI_ERROR (Status)) {
786 ZeroMem (&ConfigFormEntry->SessionConfigData, sizeof (ConfigFormEntry->SessionConfigData));
787 }
788 //
789 // Get the CHAP authentication configuration data.
790 //
791 BufferSize = sizeof (ConfigFormEntry->AuthConfigData);
792 Status = gRT->GetVariable (
793 ConfigFormEntry->MacString,
794 &mIScsiCHAPAuthInfoGuid,
795 NULL,
796 &BufferSize,
797 &ConfigFormEntry->AuthConfigData
798 );
799 if (EFI_ERROR (Status)) {
800 ZeroMem (&ConfigFormEntry->AuthConfigData, sizeof (ConfigFormEntry->AuthConfigData));
801 }
802 //
803 // Compose the Port string and create a new EFI_STRING_ID.
804 //
805 UnicodeSPrint (PortString, 128, L"Port %s", ConfigFormEntry->MacString);
806 HiiLibNewString (mCallbackInfo->RegisteredHandle, &ConfigFormEntry->PortTitleToken, PortString);
807
808 //
809 // Compose the help string of this port and create a new EFI_STRING_ID.
810 //
811 UnicodeSPrint (PortString, 128, L"Set the iSCSI parameters on port %s", ConfigFormEntry->MacString);
812 HiiLibNewString (mCallbackInfo->RegisteredHandle, &ConfigFormEntry->PortTitleHelpToken, PortString);
813
814 InsertTailList (&mIScsiConfigFormList, &ConfigFormEntry->Link);
815 mNumberOfIScsiDevices++;
816 }
817 } else {
818 ASSERT (EntryExisted);
819
820 mNumberOfIScsiDevices--;
821 RemoveEntryList (&ConfigFormEntry->Link);
822 gBS->FreePool (ConfigFormEntry);
823 }
824 //
825 // Allocate space for creation of Buffer
826 //
827 UpdateData.BufferSize = 0x1000;
828 UpdateData.Data = AllocateZeroPool (0x1000);
829 UpdateData.Offset = 0;
830
831 FormIndex = 0;
832 NET_LIST_FOR_EACH (Entry, &mIScsiConfigFormList) {
833 ConfigFormEntry = NET_LIST_USER_STRUCT (Entry, ISCSI_CONFIG_FORM_ENTRY, Link);
834
835 CreateGotoOpCode (
836 FORMID_DEVICE_FORM,
837 ConfigFormEntry->PortTitleToken,
838 ConfigFormEntry->PortTitleHelpToken,
839 EFI_IFR_FLAG_CALLBACK,
840 (UINT16)(KEY_DEVICE_ENTRY_BASE + FormIndex),
841 &UpdateData
842 );
843
844 FormIndex++;
845 }
846
847 IfrLibUpdateForm (
848 mCallbackInfo->RegisteredHandle,
849 &mVendorGuid,
850 FORMID_MAIN_FORM,
851 DEVICE_ENTRY_LABEL,
852 FALSE,
853 &UpdateData
854 );
855
856 gBS->FreePool (UpdateData.Data);
857
858 return EFI_SUCCESS;
859 }
860
861 /**
862 Initialize the iSCSI configuration form.
863
864 @param DriverBindingHandle[in] The iSCSI driverbinding handle.
865
866 @retval EFI_SUCCESS The iSCSI configuration form is initialized.
867
868 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
869
870 **/
871 EFI_STATUS
872 IScsiConfigFormInit (
873 IN EFI_HANDLE DriverBindingHandle
874 )
875 {
876 EFI_STATUS Status;
877 EFI_HII_DATABASE_PROTOCOL *HiiDatabase;
878 EFI_HII_PACKAGE_LIST_HEADER *PackageList;
879 ISCSI_FORM_CALLBACK_INFO *CallbackInfo;
880
881 Status = gBS->LocateProtocol (&gEfiHiiDatabaseProtocolGuid, NULL, (VOID **)&HiiDatabase);
882 if (EFI_ERROR (Status)) {
883 return Status;
884 }
885
886 CallbackInfo = (ISCSI_FORM_CALLBACK_INFO *) AllocatePool (sizeof (ISCSI_FORM_CALLBACK_INFO));
887 if (CallbackInfo == NULL) {
888 return EFI_OUT_OF_RESOURCES;
889 }
890
891 CallbackInfo->Signature = ISCSI_FORM_CALLBACK_INFO_SIGNATURE;
892 CallbackInfo->HiiDatabase = HiiDatabase;
893 CallbackInfo->Current = NULL;
894
895 CallbackInfo->ConfigAccess.ExtractConfig = IScsiFormExtractConfig;
896 CallbackInfo->ConfigAccess.RouteConfig = IScsiFormRouteConfig;
897 CallbackInfo->ConfigAccess.Callback = IScsiFormCallback;
898
899 Status = gBS->LocateProtocol (&gEfiHiiConfigRoutingProtocolGuid, NULL, (VOID **)&CallbackInfo->ConfigRouting);
900 if (EFI_ERROR (Status)) {
901 FreePool(CallbackInfo);
902 return Status;
903 }
904
905 //
906 // Create driver handle used by HII database
907 //
908 Status = HiiLibCreateHiiDriverHandle (&CallbackInfo->DriverHandle);
909 if (EFI_ERROR (Status)) {
910 FreePool(CallbackInfo);
911 return Status;
912 }
913
914 //
915 // Install Config Access protocol to driver handle
916 //
917 Status = gBS->InstallProtocolInterface (
918 &CallbackInfo->DriverHandle,
919 &gEfiHiiConfigAccessProtocolGuid,
920 EFI_NATIVE_INTERFACE,
921 &CallbackInfo->ConfigAccess
922 );
923 ASSERT_EFI_ERROR (Status);
924
925 //
926 // Publish our HII data
927 //
928 PackageList = HiiLibPreparePackageList (2, &mVendorGuid, IScsiDxeStrings, IScsiConfigDxeBin);
929 ASSERT (PackageList != NULL);
930
931 Status = HiiDatabase->NewPackageList (
932 HiiDatabase,
933 PackageList,
934 CallbackInfo->DriverHandle,
935 &CallbackInfo->RegisteredHandle
936 );
937 FreePool (PackageList);
938 if (EFI_ERROR (Status)) {
939 FreePool(CallbackInfo);
940 return Status;
941 }
942
943 mCallbackInfo = CallbackInfo;
944
945 return Status;
946 }
947
948 /**
949 Unload the iSCSI configuration form, this includes: delete all the iSCSI
950 device configuration entries, uninstall the form callback protocol and
951 free the resources used.
952
953 @param DriverBindingHandle[in] The iSCSI driverbinding handle.
954
955 @retval EFI_SUCCESS The iSCSI configuration form is unloaded.
956
957 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
958
959 **/
960 EFI_STATUS
961 IScsiConfigFormUnload (
962 IN EFI_HANDLE DriverBindingHandle
963 )
964 {
965 ISCSI_CONFIG_FORM_ENTRY *ConfigFormEntry;
966
967 while (!IsListEmpty (&mIScsiConfigFormList)) {
968 //
969 // Uninstall the device forms as the iSCSI driver instance may fail to
970 // control the controller but still install the device configuration form.
971 // In such case, upon driver unloading, the driver instance's driverbinding.
972 // stop () won't be called, so we have to take this chance here to uninstall
973 // the device form.
974 //
975 ConfigFormEntry = NET_LIST_USER_STRUCT (mIScsiConfigFormList.ForwardLink, ISCSI_CONFIG_FORM_ENTRY, Link);
976 IScsiConfigUpdateForm (DriverBindingHandle, ConfigFormEntry->Controller, FALSE);
977 }
978
979 //
980 // Remove HII package list
981 //
982 mCallbackInfo->HiiDatabase->RemovePackageList (
983 mCallbackInfo->HiiDatabase,
984 mCallbackInfo->RegisteredHandle
985 );
986
987 //
988 // Uninstall EFI_HII_CONFIG_ACCESS_PROTOCOL
989 //
990 gBS->UninstallProtocolInterface (
991 mCallbackInfo->DriverHandle,
992 &gEfiHiiConfigAccessProtocolGuid,
993 &mCallbackInfo->ConfigAccess
994 );
995 HiiLibDestroyHiiDriverHandle (mCallbackInfo->DriverHandle);
996
997 gBS->FreePool (mCallbackInfo);
998
999 return EFI_SUCCESS;
1000 }