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