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