VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/FirmwareNew/NetworkPkg/Ip4Dxe/Ip4Config2Nv.c

Last change on this file was 105670, checked in by vboxsync, 9 months ago

Devices/EFI/FirmwareNew: Merge edk2-stable-202405 and make it build on aarch64, bugref:4643

  • Property svn:eol-style set to native
File size: 43.3 KB
Line 
1/** @file
2 Helper functions for configuring or getting the parameters relating to Ip4.
3
4Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
5SPDX-License-Identifier: BSD-2-Clause-Patent
6
7**/
8
9#include "Ip4Impl.h"
10
11CHAR16 mIp4Config2StorageName[] = L"IP4_CONFIG2_IFR_NVDATA";
12
13/**
14 Calculate the prefix length of the IPv4 subnet mask.
15
16 @param[in] SubnetMask The IPv4 subnet mask.
17
18 @return The prefix length of the subnet mask.
19 @retval 0 Other errors as indicated.
20
21**/
22UINT8
23GetSubnetMaskPrefixLength (
24 IN EFI_IPv4_ADDRESS *SubnetMask
25 )
26{
27 UINT8 Len;
28 UINT32 ReverseMask;
29
30 //
31 // The SubnetMask is in network byte order.
32 //
33 ReverseMask = SwapBytes32 (*(UINT32 *)&SubnetMask[0]);
34
35 //
36 // Reverse it.
37 //
38 ReverseMask = ~ReverseMask;
39
40 if ((ReverseMask & (ReverseMask + 1)) != 0) {
41 return 0;
42 }
43
44 Len = 0;
45
46 while (ReverseMask != 0) {
47 ReverseMask = ReverseMask >> 1;
48 Len++;
49 }
50
51 return (UINT8)(32 - Len);
52}
53
54/**
55 Convert the decimal dotted IPv4 address into the binary IPv4 address.
56
57 @param[in] Str The UNICODE string.
58 @param[out] Ip The storage to return the IPv4 address.
59
60 @retval EFI_SUCCESS The binary IP address is returned in Ip.
61 @retval EFI_INVALID_PARAMETER The IP string is malformatted.
62
63**/
64EFI_STATUS
65Ip4Config2StrToIp (
66 IN CHAR16 *Str,
67 OUT EFI_IPv4_ADDRESS *Ip
68 )
69{
70 UINTN Index;
71 UINTN Number;
72
73 Index = 0;
74
75 while (*Str != L'\0') {
76 if (Index > 3) {
77 return EFI_INVALID_PARAMETER;
78 }
79
80 Number = 0;
81 while ((*Str >= L'0') && (*Str <= L'9')) {
82 Number = Number * 10 + (*Str - L'0');
83 Str++;
84 }
85
86 if (Number > 0xFF) {
87 return EFI_INVALID_PARAMETER;
88 }
89
90 Ip->Addr[Index] = (UINT8)Number;
91
92 if ((*Str != L'\0') && (*Str != L'.')) {
93 //
94 // The current character should be either the NULL terminator or
95 // the dot delimiter.
96 //
97 return EFI_INVALID_PARAMETER;
98 }
99
100 if (*Str == L'.') {
101 //
102 // Skip the delimiter.
103 //
104 Str++;
105 }
106
107 Index++;
108 }
109
110 if (Index != 4) {
111 return EFI_INVALID_PARAMETER;
112 }
113
114 return EFI_SUCCESS;
115}
116
117/**
118 Convert the decimal dotted IPv4 addresses separated by space into the binary IPv4 address list.
119
120 @param[in] Str The UNICODE string contains IPv4 addresses.
121 @param[out] PtrIpList The storage to return the IPv4 address list.
122 @param[out] IpCount The size of the IPv4 address list.
123
124 @retval EFI_SUCCESS The binary IP address list is returned in PtrIpList.
125 @retval EFI_OUT_OF_RESOURCES Error occurs in allocating memory.
126 @retval EFI_INVALID_PARAMETER The IP string is malformatted.
127
128**/
129EFI_STATUS
130Ip4Config2StrToIpList (
131 IN CHAR16 *Str,
132 OUT EFI_IPv4_ADDRESS **PtrIpList,
133 OUT UINTN *IpCount
134 )
135{
136 UINTN BeginIndex;
137 UINTN EndIndex;
138 UINTN Index;
139 UINTN IpIndex;
140 CHAR16 *StrTemp;
141 BOOLEAN SpaceTag;
142
143 BeginIndex = 0;
144 EndIndex = BeginIndex;
145 Index = 0;
146 IpIndex = 0;
147 StrTemp = NULL;
148 SpaceTag = TRUE;
149
150 *PtrIpList = NULL;
151 *IpCount = 0;
152
153 if (Str == NULL) {
154 return EFI_SUCCESS;
155 }
156
157 //
158 // Get the number of Ip.
159 //
160 while (*(Str + Index) != L'\0') {
161 if (*(Str + Index) == L' ') {
162 SpaceTag = TRUE;
163 } else {
164 if (SpaceTag) {
165 (*IpCount)++;
166 SpaceTag = FALSE;
167 }
168 }
169
170 Index++;
171 }
172
173 if (*IpCount == 0) {
174 return EFI_SUCCESS;
175 }
176
177 //
178 // Allocate buffer for IpList.
179 //
180 *PtrIpList = AllocateZeroPool (*IpCount * sizeof (EFI_IPv4_ADDRESS));
181 if (*PtrIpList == NULL) {
182 return EFI_OUT_OF_RESOURCES;
183 }
184
185 //
186 // Get IpList from Str.
187 //
188 Index = 0;
189 while (*(Str + Index) != L'\0') {
190 if (*(Str + Index) == L' ') {
191 if (!SpaceTag) {
192 StrTemp = AllocateZeroPool ((EndIndex - BeginIndex + 1) * sizeof (CHAR16));
193 if (StrTemp == NULL) {
194 FreePool (*PtrIpList);
195 *PtrIpList = NULL;
196 *IpCount = 0;
197 return EFI_OUT_OF_RESOURCES;
198 }
199
200 CopyMem (StrTemp, Str + BeginIndex, (EndIndex - BeginIndex) * sizeof (CHAR16));
201 *(StrTemp + (EndIndex - BeginIndex)) = L'\0';
202
203 if (Ip4Config2StrToIp (StrTemp, &((*PtrIpList)[IpIndex])) != EFI_SUCCESS) {
204 FreePool (StrTemp);
205 FreePool (*PtrIpList);
206 *PtrIpList = NULL;
207 *IpCount = 0;
208 return EFI_INVALID_PARAMETER;
209 }
210
211 BeginIndex = EndIndex;
212 IpIndex++;
213
214 FreePool (StrTemp);
215 }
216
217 BeginIndex++;
218 EndIndex++;
219 SpaceTag = TRUE;
220 } else {
221 EndIndex++;
222 SpaceTag = FALSE;
223 }
224
225 Index++;
226
227 if (*(Str + Index) == L'\0') {
228 if (!SpaceTag) {
229 StrTemp = AllocateZeroPool ((EndIndex - BeginIndex + 1) * sizeof (CHAR16));
230 if (StrTemp == NULL) {
231 FreePool (*PtrIpList);
232 *PtrIpList = NULL;
233 *IpCount = 0;
234 return EFI_OUT_OF_RESOURCES;
235 }
236
237 CopyMem (StrTemp, Str + BeginIndex, (EndIndex - BeginIndex) * sizeof (CHAR16));
238 *(StrTemp + (EndIndex - BeginIndex)) = L'\0';
239
240 if (Ip4Config2StrToIp (StrTemp, &((*PtrIpList)[IpIndex])) != EFI_SUCCESS) {
241 FreePool (StrTemp);
242 FreePool (*PtrIpList);
243 *PtrIpList = NULL;
244 *IpCount = 0;
245 return EFI_INVALID_PARAMETER;
246 }
247
248 FreePool (StrTemp);
249 }
250 }
251 }
252
253 return EFI_SUCCESS;
254}
255
256/**
257 Convert the IPv4 address into a dotted string.
258
259 @param[in] Ip The IPv4 address.
260 @param[out] Str The dotted IP string.
261
262**/
263VOID
264Ip4Config2IpToStr (
265 IN EFI_IPv4_ADDRESS *Ip,
266 OUT CHAR16 *Str
267 )
268{
269 UnicodeSPrint (
270 Str,
271 2 * IP4_STR_MAX_SIZE,
272 L"%d.%d.%d.%d",
273 Ip->Addr[0],
274 Ip->Addr[1],
275 Ip->Addr[2],
276 Ip->Addr[3]
277 );
278}
279
280/**
281 Convert the IPv4 address list into string consists of several decimal
282 dotted IPv4 addresses separated by space.
283
284 @param[in] Ip The IPv4 address list.
285 @param[in] IpCount The size of IPv4 address list.
286 @param[out] Str The string contains several decimal dotted
287 IPv4 addresses separated by space.
288
289 @retval EFI_SUCCESS Operation is success.
290 @retval EFI_OUT_OF_RESOURCES Error occurs in allocating memory.
291
292**/
293EFI_STATUS
294Ip4Config2IpListToStr (
295 IN EFI_IPv4_ADDRESS *Ip,
296 IN UINTN IpCount,
297 OUT CHAR16 *Str
298 )
299{
300 UINTN Index;
301 UINTN TemIndex;
302 UINTN StrIndex;
303 CHAR16 *TempStr;
304 EFI_IPv4_ADDRESS *TempIp;
305
306 Index = 0;
307 TemIndex = 0;
308 StrIndex = 0;
309 TempStr = NULL;
310 TempIp = NULL;
311
312 for (Index = 0; Index < IpCount; Index++) {
313 TempIp = Ip + Index;
314 if (TempStr == NULL) {
315 TempStr = AllocateZeroPool (2 * IP4_STR_MAX_SIZE);
316 if (TempStr == NULL) {
317 return EFI_OUT_OF_RESOURCES;
318 }
319 }
320
321 UnicodeSPrint (
322 TempStr,
323 2 * IP4_STR_MAX_SIZE,
324 L"%d.%d.%d.%d",
325 TempIp->Addr[0],
326 TempIp->Addr[1],
327 TempIp->Addr[2],
328 TempIp->Addr[3]
329 );
330
331 for (TemIndex = 0; TemIndex < IP4_STR_MAX_SIZE; TemIndex++) {
332 if (*(TempStr + TemIndex) == L'\0') {
333 if (Index == IpCount - 1) {
334 Str[StrIndex++] = L'\0';
335 } else {
336 Str[StrIndex++] = L' ';
337 }
338
339 break;
340 } else {
341 Str[StrIndex++] = *(TempStr + TemIndex);
342 }
343 }
344 }
345
346 if (TempStr != NULL) {
347 FreePool (TempStr);
348 }
349
350 return EFI_SUCCESS;
351}
352
353/**
354 The notify function of create event when performing a manual configuration.
355
356 @param[in] Event The pointer of Event.
357 @param[in] Context The pointer of Context.
358
359**/
360VOID
361EFIAPI
362Ip4Config2ManualAddressNotify (
363 IN EFI_EVENT Event,
364 IN VOID *Context
365 )
366{
367 *((BOOLEAN *)Context) = TRUE;
368}
369
370/**
371 Convert the network configuration data into the IFR data.
372
373 @param[in] Instance The IP4 config2 instance.
374 @param[in, out] IfrNvData The IFR nv data.
375
376 @retval EFI_SUCCESS The configure parameter to IFR data was
377 set successfully.
378 @retval EFI_INVALID_PARAMETER Source instance or target IFR data is not available.
379 @retval Others Other errors as indicated.
380
381**/
382EFI_STATUS
383Ip4Config2ConvertConfigNvDataToIfrNvData (
384 IN IP4_CONFIG2_INSTANCE *Instance,
385 IN OUT IP4_CONFIG2_IFR_NVDATA *IfrNvData
386 )
387{
388 IP4_SERVICE *IpSb;
389 EFI_IP4_CONFIG2_PROTOCOL *Ip4Config2;
390 EFI_IP4_CONFIG2_INTERFACE_INFO *Ip4Info;
391 EFI_IP4_CONFIG2_POLICY Policy;
392 UINTN DataSize;
393 UINTN GatewaySize;
394 EFI_IPv4_ADDRESS GatewayAddress;
395 EFI_STATUS Status;
396 UINTN DnsSize;
397 UINTN DnsCount;
398 EFI_IPv4_ADDRESS *DnsAddress;
399
400 Status = EFI_SUCCESS;
401 Ip4Config2 = &Instance->Ip4Config2;
402 Ip4Info = NULL;
403 DnsAddress = NULL;
404 GatewaySize = sizeof (EFI_IPv4_ADDRESS);
405
406 if ((IfrNvData == NULL) || (Instance == NULL)) {
407 return EFI_INVALID_PARAMETER;
408 }
409
410 NET_CHECK_SIGNATURE (Instance, IP4_CONFIG2_INSTANCE_SIGNATURE);
411
412 IpSb = IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance);
413
414 if (IpSb->DefaultInterface->Configured) {
415 IfrNvData->Configure = 1;
416 } else {
417 IfrNvData->Configure = 0;
418 goto Exit;
419 }
420
421 //
422 // Get the Policy info.
423 //
424 DataSize = sizeof (EFI_IP4_CONFIG2_POLICY);
425 Status = Ip4Config2->GetData (
426 Ip4Config2,
427 Ip4Config2DataTypePolicy,
428 &DataSize,
429 &Policy
430 );
431 if (EFI_ERROR (Status)) {
432 goto Exit;
433 }
434
435 if (Policy == Ip4Config2PolicyStatic) {
436 IfrNvData->DhcpEnable = FALSE;
437 } else if (Policy == Ip4Config2PolicyDhcp) {
438 IfrNvData->DhcpEnable = TRUE;
439 goto Exit;
440 }
441
442 //
443 // Get the interface info.
444 //
445 DataSize = 0;
446 Status = Ip4Config2->GetData (
447 Ip4Config2,
448 Ip4Config2DataTypeInterfaceInfo,
449 &DataSize,
450 NULL
451 );
452 if (Status != EFI_BUFFER_TOO_SMALL) {
453 return Status;
454 }
455
456 Ip4Info = AllocateZeroPool (DataSize);
457 if (Ip4Info == NULL) {
458 Status = EFI_OUT_OF_RESOURCES;
459 return Status;
460 }
461
462 Status = Ip4Config2->GetData (
463 Ip4Config2,
464 Ip4Config2DataTypeInterfaceInfo,
465 &DataSize,
466 Ip4Info
467 );
468 if (EFI_ERROR (Status)) {
469 goto Exit;
470 }
471
472 //
473 // Get the Gateway info.
474 //
475 Status = Ip4Config2->GetData (
476 Ip4Config2,
477 Ip4Config2DataTypeGateway,
478 &GatewaySize,
479 &GatewayAddress
480 );
481 if (EFI_ERROR (Status)) {
482 goto Exit;
483 }
484
485 //
486 // Get the Dns info.
487 //
488 DnsSize = 0;
489 Status = Ip4Config2->GetData (
490 Ip4Config2,
491 Ip4Config2DataTypeDnsServer,
492 &DnsSize,
493 NULL
494 );
495 if ((Status != EFI_BUFFER_TOO_SMALL) && (Status != EFI_NOT_FOUND)) {
496 goto Exit;
497 }
498
499 DnsCount = (UINT32)(DnsSize / sizeof (EFI_IPv4_ADDRESS));
500
501 if (DnsSize > 0) {
502 DnsAddress = AllocateZeroPool (DnsSize);
503 if (DnsAddress == NULL) {
504 Status = EFI_OUT_OF_RESOURCES;
505 goto Exit;
506 }
507
508 Status = Ip4Config2->GetData (
509 Ip4Config2,
510 Ip4Config2DataTypeDnsServer,
511 &DnsSize,
512 DnsAddress
513 );
514 if (EFI_ERROR (Status)) {
515 goto Exit;
516 }
517 }
518
519 Ip4Config2IpToStr (&Ip4Info->StationAddress, IfrNvData->StationAddress);
520 Ip4Config2IpToStr (&Ip4Info->SubnetMask, IfrNvData->SubnetMask);
521 Ip4Config2IpToStr (&GatewayAddress, IfrNvData->GatewayAddress);
522 Status = Ip4Config2IpListToStr (DnsAddress, DnsCount, IfrNvData->DnsAddress);
523
524Exit:
525
526 if (DnsAddress != NULL) {
527 FreePool (DnsAddress);
528 }
529
530 if (Ip4Info != NULL) {
531 FreePool (Ip4Info);
532 }
533
534 return Status;
535}
536
537/**
538 Convert the IFR data into the network configuration data and set the IP
539 configure parameters for the NIC.
540
541 @param[in] IfrFormNvData The IFR NV data.
542 @param[in, out] Instance The IP4 config2 instance.
543
544 @retval EFI_SUCCESS The configure parameter for this NIC was
545 set successfully.
546 @retval EFI_INVALID_PARAMETER The address information for setting is invalid.
547 @retval Others Other errors as indicated.
548
549**/
550EFI_STATUS
551Ip4Config2ConvertIfrNvDataToConfigNvData (
552 IN IP4_CONFIG2_IFR_NVDATA *IfrFormNvData,
553 IN OUT IP4_CONFIG2_INSTANCE *Instance
554 )
555{
556 EFI_STATUS Status;
557 EFI_IP4_CONFIG2_PROTOCOL *Ip4Cfg2;
558 IP4_CONFIG2_NVDATA *Ip4NvData;
559
560 EFI_IP_ADDRESS StationAddress;
561 EFI_IP_ADDRESS SubnetMask;
562 EFI_IP_ADDRESS Gateway;
563 IP4_ADDR Ip;
564 EFI_IPv4_ADDRESS *DnsAddress;
565 UINTN DnsCount;
566 UINTN Index;
567
568 EFI_EVENT TimeoutEvent;
569 EFI_EVENT SetAddressEvent;
570 BOOLEAN IsAddressOk;
571 UINTN DataSize;
572 EFI_INPUT_KEY Key;
573
574 Status = EFI_SUCCESS;
575 Ip4Cfg2 = &Instance->Ip4Config2;
576 Ip4NvData = &Instance->Ip4NvData;
577
578 DnsCount = 0;
579 DnsAddress = NULL;
580
581 TimeoutEvent = NULL;
582 SetAddressEvent = NULL;
583
584 if ((Instance == NULL) || (IfrFormNvData == NULL)) {
585 return EFI_INVALID_PARAMETER;
586 }
587
588 if (IfrFormNvData->Configure != TRUE) {
589 if (Ip4NvData->DnsAddress != NULL) {
590 FreePool (Ip4NvData->DnsAddress);
591 Ip4NvData->DnsAddress = NULL;
592 Ip4NvData->DnsAddressCount = 0;
593 }
594
595 if (Ip4NvData->GatewayAddress != NULL) {
596 FreePool (Ip4NvData->GatewayAddress);
597 Ip4NvData->GatewayAddress = NULL;
598 Ip4NvData->GatewayAddressCount = 0;
599 }
600
601 if (Ip4NvData->ManualAddress != NULL) {
602 FreePool (Ip4NvData->ManualAddress);
603 Ip4NvData->ManualAddress = NULL;
604 Ip4NvData->ManualAddressCount = 0;
605 }
606
607 Ip4NvData->Policy = Ip4Config2PolicyDhcp;
608 Status = Ip4Cfg2->SetData (
609 Ip4Cfg2,
610 Ip4Config2DataTypePolicy,
611 sizeof (EFI_IP4_CONFIG2_POLICY),
612 &Ip4NvData->Policy
613 );
614 return EFI_SUCCESS;
615 }
616
617 if (IfrFormNvData->DhcpEnable == TRUE) {
618 Ip4NvData->Policy = Ip4Config2PolicyDhcp;
619
620 Status = Ip4Cfg2->SetData (
621 Ip4Cfg2,
622 Ip4Config2DataTypePolicy,
623 sizeof (EFI_IP4_CONFIG2_POLICY),
624 &Ip4NvData->Policy
625 );
626 if (EFI_ERROR (Status)) {
627 return Status;
628 }
629 } else {
630 //
631 // Get Ip4NvData from IfrFormNvData if it is valid.
632 //
633 Ip4NvData->Policy = Ip4Config2PolicyStatic;
634
635 Status = Ip4Config2StrToIp (IfrFormNvData->SubnetMask, &SubnetMask.v4);
636 if (EFI_ERROR (Status) || ((SubnetMask.Addr[0] != 0) && (GetSubnetMaskPrefixLength (&SubnetMask.v4) == 0))) {
637 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid Subnet Mask!", NULL);
638 return EFI_INVALID_PARAMETER;
639 }
640
641 Status = Ip4Config2StrToIp (IfrFormNvData->StationAddress, &StationAddress.v4);
642 if (EFI_ERROR (Status) ||
643 ((SubnetMask.Addr[0] != 0) && !NetIp4IsUnicast (NTOHL (StationAddress.Addr[0]), NTOHL (SubnetMask.Addr[0]))) ||
644 !Ip4StationAddressValid (NTOHL (StationAddress.Addr[0]), NTOHL (SubnetMask.Addr[0])))
645 {
646 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid IP address!", NULL);
647 return EFI_INVALID_PARAMETER;
648 }
649
650 Status = Ip4Config2StrToIp (IfrFormNvData->GatewayAddress, &Gateway.v4);
651 if (EFI_ERROR (Status) ||
652 ((Gateway.Addr[0] != 0) && (SubnetMask.Addr[0] != 0) && !NetIp4IsUnicast (NTOHL (Gateway.Addr[0]), NTOHL (SubnetMask.Addr[0]))))
653 {
654 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid Gateway!", NULL);
655 return EFI_INVALID_PARAMETER;
656 }
657
658 Status = Ip4Config2StrToIpList (IfrFormNvData->DnsAddress, &DnsAddress, &DnsCount);
659 if (!EFI_ERROR (Status) && (DnsCount > 0)) {
660 for (Index = 0; Index < DnsCount; Index++) {
661 CopyMem (&Ip, &DnsAddress[Index], sizeof (IP4_ADDR));
662 if (IP4_IS_UNSPECIFIED (NTOHL (Ip)) || IP4_IS_LOCAL_BROADCAST (NTOHL (Ip))) {
663 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid Dns Server!", NULL);
664 FreePool (DnsAddress);
665 return EFI_INVALID_PARAMETER;
666 }
667 }
668 } else {
669 if (EFI_ERROR (Status)) {
670 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid Dns Server!", NULL);
671 }
672 }
673
674 if (Ip4NvData->ManualAddress != NULL) {
675 FreePool (Ip4NvData->ManualAddress);
676 }
677
678 Ip4NvData->ManualAddressCount = 1;
679 Ip4NvData->ManualAddress = AllocateZeroPool (sizeof (EFI_IP4_CONFIG2_MANUAL_ADDRESS));
680 if (Ip4NvData->ManualAddress == NULL) {
681 if (DnsAddress != NULL) {
682 FreePool (DnsAddress);
683 }
684
685 return EFI_OUT_OF_RESOURCES;
686 }
687
688 CopyMem (&Ip4NvData->ManualAddress->Address, &StationAddress.v4, sizeof (EFI_IPv4_ADDRESS));
689 CopyMem (&Ip4NvData->ManualAddress->SubnetMask, &SubnetMask.v4, sizeof (EFI_IPv4_ADDRESS));
690
691 if (Ip4NvData->GatewayAddress != NULL) {
692 FreePool (Ip4NvData->GatewayAddress);
693 }
694
695 Ip4NvData->GatewayAddressCount = 1;
696 Ip4NvData->GatewayAddress = AllocateZeroPool (sizeof (EFI_IPv4_ADDRESS));
697 if (Ip4NvData->GatewayAddress == NULL) {
698 if (DnsAddress != NULL) {
699 FreePool (DnsAddress);
700 }
701
702 return EFI_OUT_OF_RESOURCES;
703 }
704
705 CopyMem (Ip4NvData->GatewayAddress, &Gateway.v4, sizeof (EFI_IPv4_ADDRESS));
706
707 if (Ip4NvData->DnsAddress != NULL) {
708 FreePool (Ip4NvData->DnsAddress);
709 }
710
711 Ip4NvData->DnsAddressCount = (UINT32)DnsCount;
712 Ip4NvData->DnsAddress = DnsAddress;
713
714 //
715 // Setting Ip4NvData.
716 //
717 Status = Ip4Cfg2->SetData (
718 Ip4Cfg2,
719 Ip4Config2DataTypePolicy,
720 sizeof (EFI_IP4_CONFIG2_POLICY),
721 &Ip4NvData->Policy
722 );
723 if (EFI_ERROR (Status)) {
724 return Status;
725 }
726
727 //
728 // Create events & timers for asynchronous settings.
729 //
730 Status = gBS->CreateEvent (
731 EVT_TIMER,
732 TPL_CALLBACK,
733 NULL,
734 NULL,
735 &TimeoutEvent
736 );
737 if (EFI_ERROR (Status)) {
738 return EFI_OUT_OF_RESOURCES;
739 }
740
741 Status = gBS->CreateEvent (
742 EVT_NOTIFY_SIGNAL,
743 TPL_NOTIFY,
744 Ip4Config2ManualAddressNotify,
745 &IsAddressOk,
746 &SetAddressEvent
747 );
748 if (EFI_ERROR (Status)) {
749 goto Exit;
750 }
751
752 IsAddressOk = FALSE;
753
754 Status = Ip4Cfg2->RegisterDataNotify (
755 Ip4Cfg2,
756 Ip4Config2DataTypeManualAddress,
757 SetAddressEvent
758 );
759 if (EFI_ERROR (Status)) {
760 goto Exit;
761 }
762
763 //
764 // Set ManualAddress.
765 //
766 DataSize = Ip4NvData->ManualAddressCount * sizeof (EFI_IP4_CONFIG2_MANUAL_ADDRESS);
767 Status = Ip4Cfg2->SetData (
768 Ip4Cfg2,
769 Ip4Config2DataTypeManualAddress,
770 DataSize,
771 (VOID *)Ip4NvData->ManualAddress
772 );
773
774 if (Status == EFI_NOT_READY) {
775 gBS->SetTimer (TimeoutEvent, TimerRelative, 50000000);
776 while (EFI_ERROR (gBS->CheckEvent (TimeoutEvent))) {
777 if (IsAddressOk) {
778 Status = EFI_SUCCESS;
779 break;
780 }
781 }
782 }
783
784 Ip4Cfg2->UnregisterDataNotify (
785 Ip4Cfg2,
786 Ip4Config2DataTypeManualAddress,
787 SetAddressEvent
788 );
789 if (EFI_ERROR (Status)) {
790 goto Exit;
791 }
792
793 //
794 // Set gateway.
795 //
796 DataSize = Ip4NvData->GatewayAddressCount * sizeof (EFI_IPv4_ADDRESS);
797 Status = Ip4Cfg2->SetData (
798 Ip4Cfg2,
799 Ip4Config2DataTypeGateway,
800 DataSize,
801 Ip4NvData->GatewayAddress
802 );
803 if (EFI_ERROR (Status)) {
804 goto Exit;
805 }
806
807 //
808 // Set DNS addresses.
809 //
810 if ((Ip4NvData->DnsAddressCount > 0) && (Ip4NvData->DnsAddress != NULL)) {
811 DataSize = Ip4NvData->DnsAddressCount * sizeof (EFI_IPv4_ADDRESS);
812 Status = Ip4Cfg2->SetData (
813 Ip4Cfg2,
814 Ip4Config2DataTypeDnsServer,
815 DataSize,
816 Ip4NvData->DnsAddress
817 );
818
819 if (EFI_ERROR (Status)) {
820 goto Exit;
821 }
822 }
823 }
824
825Exit:
826 if (SetAddressEvent != NULL) {
827 gBS->CloseEvent (SetAddressEvent);
828 }
829
830 if (TimeoutEvent != NULL) {
831 gBS->CloseEvent (TimeoutEvent);
832 }
833
834 return Status;
835}
836
837/**
838 This function allows the caller to request the current
839 configuration for one or more named elements. The resulting
840 string is in <ConfigAltResp> format. Any and all alternative
841 configuration strings shall also be appended to the end of the
842 current configuration string. If they are, they must appear
843 after the current configuration. They must contain the same
844 routing (GUID, NAME, PATH) as the current configuration string.
845 They must have an additional description indicating the type of
846 alternative configuration the string represents,
847 "ALTCFG=<StringToken>". That <StringToken> (when
848 converted from Hex UNICODE to binary) is a reference to a
849 string in the associated string pack.
850
851 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
852 @param[in] Request A null-terminated Unicode string in
853 <ConfigRequest> format. Note that this
854 includes the routing information as well as
855 the configurable name / value pairs. It is
856 invalid for this string to be in
857 <MultiConfigRequest> format.
858 @param[out] Progress On return, points to a character in the
859 Request string. Points to the string's null
860 terminator if request was successful. Points
861 to the most recent "&" before the first
862 failing name / value pair (or the beginning
863 of the string if the failure is in the first
864 name / value pair) if the request was not
865 successful.
866 @param[out] Results A null-terminated Unicode string in
867 <ConfigAltResp> format which has all values
868 filled in for the names in the Request string.
869 String to be allocated by the called function.
870
871 @retval EFI_SUCCESS The Results string is filled with the
872 values corresponding to all requested
873 names.
874 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the
875 parts of the results that must be
876 stored awaiting possible future
877 protocols.
878 @retval EFI_NOT_FOUND Routing data doesn't match any
879 known driver. Progress set to the
880 first character in the routing header.
881 Note: There is no requirement that the
882 driver validate the routing data. It
883 must skip the <ConfigHdr> in order to
884 process the names.
885 @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set
886 to most recent & before the
887 error or the beginning of the
888 string.
889 @retval EFI_INVALID_PARAMETER Unknown name. Progress points
890 to the & before the name in
891 question.Currently not implemented.
892**/
893EFI_STATUS
894EFIAPI
895Ip4FormExtractConfig (
896 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
897 IN CONST EFI_STRING Request,
898 OUT EFI_STRING *Progress,
899 OUT EFI_STRING *Results
900 )
901{
902 EFI_STATUS Status;
903 IP4_CONFIG2_INSTANCE *Ip4Config2Instance;
904 IP4_FORM_CALLBACK_INFO *Private;
905 IP4_CONFIG2_IFR_NVDATA *IfrFormNvData;
906 EFI_STRING ConfigRequestHdr;
907 EFI_STRING ConfigRequest;
908 BOOLEAN AllocatedRequest;
909 EFI_STRING FormResult;
910 UINTN Size;
911 UINTN BufferSize;
912
913 if ((Progress == NULL) || (Results == NULL)) {
914 return EFI_INVALID_PARAMETER;
915 }
916
917 Status = EFI_SUCCESS;
918 IfrFormNvData = NULL;
919 ConfigRequest = NULL;
920 FormResult = NULL;
921 Size = 0;
922 AllocatedRequest = FALSE;
923 ConfigRequest = Request;
924 Private = IP4_FORM_CALLBACK_INFO_FROM_CONFIG_ACCESS (This);
925 Ip4Config2Instance = IP4_CONFIG2_INSTANCE_FROM_FORM_CALLBACK (Private);
926 BufferSize = sizeof (IP4_CONFIG2_IFR_NVDATA);
927 *Progress = Request;
928
929 //
930 // Check Request data in <ConfigHdr>.
931 //
932 if ((Request == NULL) || HiiIsConfigHdrMatch (Request, &gIp4Config2NvDataGuid, mIp4Config2StorageName)) {
933 IfrFormNvData = AllocateZeroPool (sizeof (IP4_CONFIG2_IFR_NVDATA));
934 if (IfrFormNvData == NULL) {
935 return EFI_OUT_OF_RESOURCES;
936 }
937
938 Ip4Config2ConvertConfigNvDataToIfrNvData (Ip4Config2Instance, IfrFormNvData);
939
940 if ((Request == NULL) || (StrStr (Request, L"OFFSET") == NULL)) {
941 //
942 // Request has no request element, construct full request string.
943 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
944 // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
945 //
946 ConfigRequestHdr = HiiConstructConfigHdr (&gIp4Config2NvDataGuid, mIp4Config2StorageName, Private->ChildHandle);
947 Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16);
948 ConfigRequest = AllocateZeroPool (Size);
949 if (ConfigRequest == NULL) {
950 Status = EFI_OUT_OF_RESOURCES;
951 goto Failure;
952 }
953
954 AllocatedRequest = TRUE;
955
956 UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr, (UINT64)BufferSize);
957 FreePool (ConfigRequestHdr);
958 }
959
960 //
961 // Convert buffer data to <ConfigResp> by helper function BlockToConfig()
962 //
963 Status = gHiiConfigRouting->BlockToConfig (
964 gHiiConfigRouting,
965 ConfigRequest,
966 (UINT8 *)IfrFormNvData,
967 BufferSize,
968 &FormResult,
969 Progress
970 );
971
972 FreePool (IfrFormNvData);
973
974 //
975 // Free the allocated config request string.
976 //
977 if (AllocatedRequest) {
978 FreePool (ConfigRequest);
979 ConfigRequest = NULL;
980 }
981
982 if (EFI_ERROR (Status)) {
983 goto Failure;
984 }
985 }
986
987 if ((Request == NULL) || HiiIsConfigHdrMatch (Request, &gIp4Config2NvDataGuid, mIp4Config2StorageName)) {
988 *Results = FormResult;
989 } else {
990 return EFI_NOT_FOUND;
991 }
992
993Failure:
994 //
995 // Set Progress string to the original request string.
996 //
997 if (Request == NULL) {
998 *Progress = NULL;
999 } else if (StrStr (Request, L"OFFSET") == NULL) {
1000 *Progress = Request + StrLen (Request);
1001 }
1002
1003 return Status;
1004}
1005
1006/**
1007 This function applies changes in a driver's configuration.
1008 Input is a Configuration, which has the routing data for this
1009 driver followed by name / value configuration pairs. The driver
1010 must apply those pairs to its configurable storage. If the
1011 driver's configuration is stored in a linear block of data
1012 and the driver's name / value pairs are in <BlockConfig>
1013 format, it may use the ConfigToBlock helper function (above) to
1014 simplify the job. Currently not implemented.
1015
1016 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
1017 @param[in] Configuration A null-terminated Unicode string in
1018 <ConfigString> format.
1019 @param[out] Progress A pointer to a string filled in with the
1020 offset of the most recent '&' before the
1021 first failing name / value pair (or the
1022 beginning of the string if the failure
1023 is in the first name / value pair) or
1024 the terminating NULL if all was
1025 successful.
1026
1027 @retval EFI_SUCCESS The results have been distributed or are
1028 awaiting distribution.
1029 @retval EFI_OUT_OF_MEMORY Not enough memory to store the
1030 parts of the results that must be
1031 stored awaiting possible future
1032 protocols.
1033 @retval EFI_INVALID_PARAMETERS Passing in a NULL for the
1034 Results parameter would result
1035 in this type of error.
1036 @retval EFI_NOT_FOUND Target for the specified routing data
1037 was not found.
1038**/
1039EFI_STATUS
1040EFIAPI
1041Ip4FormRouteConfig (
1042 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
1043 IN CONST EFI_STRING Configuration,
1044 OUT EFI_STRING *Progress
1045 )
1046{
1047 EFI_STATUS Status;
1048 UINTN BufferSize;
1049 IP4_CONFIG2_IFR_NVDATA *IfrFormNvData;
1050 IP4_CONFIG2_INSTANCE *Ip4Config2Instance;
1051 IP4_FORM_CALLBACK_INFO *Private;
1052
1053 Status = EFI_SUCCESS;
1054 IfrFormNvData = NULL;
1055
1056 if ((Configuration == NULL) || (Progress == NULL)) {
1057 return EFI_INVALID_PARAMETER;
1058 }
1059
1060 *Progress = Configuration;
1061
1062 Private = IP4_FORM_CALLBACK_INFO_FROM_CONFIG_ACCESS (This);
1063 Ip4Config2Instance = IP4_CONFIG2_INSTANCE_FROM_FORM_CALLBACK (Private);
1064
1065 //
1066 // Check Routing data in <ConfigHdr>.
1067 //
1068 if (HiiIsConfigHdrMatch (Configuration, &gIp4Config2NvDataGuid, mIp4Config2StorageName)) {
1069 //
1070 // Convert buffer data to <ConfigResp> by helper function BlockToConfig()
1071 //
1072 IfrFormNvData = AllocateZeroPool (sizeof (IP4_CONFIG2_IFR_NVDATA));
1073 if (IfrFormNvData == NULL) {
1074 return EFI_OUT_OF_RESOURCES;
1075 }
1076
1077 BufferSize = 0;
1078
1079 Status = gHiiConfigRouting->ConfigToBlock (
1080 gHiiConfigRouting,
1081 Configuration,
1082 (UINT8 *)IfrFormNvData,
1083 &BufferSize,
1084 Progress
1085 );
1086 if (Status != EFI_BUFFER_TOO_SMALL) {
1087 return Status;
1088 }
1089
1090 Status = gHiiConfigRouting->ConfigToBlock (
1091 gHiiConfigRouting,
1092 Configuration,
1093 (UINT8 *)IfrFormNvData,
1094 &BufferSize,
1095 Progress
1096 );
1097 if (!EFI_ERROR (Status)) {
1098 Status = Ip4Config2ConvertIfrNvDataToConfigNvData (IfrFormNvData, Ip4Config2Instance);
1099 }
1100
1101 FreePool (IfrFormNvData);
1102 } else {
1103 return EFI_NOT_FOUND;
1104 }
1105
1106 return Status;
1107}
1108
1109/**
1110 This function is called to provide results data to the driver.
1111 This data consists of a unique key that is used to identify
1112 which data is either being passed back or being asked for.
1113
1114 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
1115 @param[in] Action Specifies the type of action taken by the browser.
1116 @param[in] QuestionId A unique value which is sent to the original
1117 exporting driver so that it can identify the type
1118 of data to expect. The format of the data tends to
1119 vary based on the opcode that enerated the callback.
1120 @param[in] Type The type of value for the question.
1121 @param[in] Value A pointer to the data being sent to the original
1122 exporting driver.
1123 @param[out] ActionRequest On return, points to the action requested by the
1124 callback function.
1125
1126 @retval EFI_SUCCESS The callback successfully handled the action.
1127 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the
1128 variable and its data.
1129 @retval EFI_DEVICE_ERROR The variable could not be saved.
1130 @retval EFI_UNSUPPORTED The specified Action is not supported by the
1131 callback. Currently not implemented.
1132 @retval EFI_INVALID_PARAMETERS Passing in wrong parameter.
1133 @retval Others Other errors as indicated.
1134
1135**/
1136EFI_STATUS
1137EFIAPI
1138Ip4FormCallback (
1139 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
1140 IN EFI_BROWSER_ACTION Action,
1141 IN EFI_QUESTION_ID QuestionId,
1142 IN UINT8 Type,
1143 IN EFI_IFR_TYPE_VALUE *Value,
1144 OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest
1145 )
1146{
1147 EFI_STATUS Status;
1148 IP4_CONFIG2_INSTANCE *Instance;
1149 IP4_CONFIG2_IFR_NVDATA *IfrFormNvData;
1150 IP4_FORM_CALLBACK_INFO *Private;
1151
1152 EFI_IP_ADDRESS StationAddress;
1153 EFI_IP_ADDRESS SubnetMask;
1154 EFI_IP_ADDRESS Gateway;
1155 IP4_ADDR Ip;
1156 EFI_IPv4_ADDRESS *DnsAddress;
1157 UINTN DnsCount;
1158 UINTN Index;
1159 EFI_INPUT_KEY Key;
1160
1161 IfrFormNvData = NULL;
1162 DnsCount = 0;
1163 DnsAddress = NULL;
1164
1165 if (Action == EFI_BROWSER_ACTION_CHANGED) {
1166 Private = IP4_FORM_CALLBACK_INFO_FROM_CONFIG_ACCESS (This);
1167 Instance = IP4_CONFIG2_INSTANCE_FROM_FORM_CALLBACK (Private);
1168
1169 IfrFormNvData = AllocateZeroPool (sizeof (IP4_CONFIG2_IFR_NVDATA));
1170 if (IfrFormNvData == NULL) {
1171 return EFI_OUT_OF_RESOURCES;
1172 }
1173
1174 //
1175 // Retrieve uncommitted data from Browser
1176 //
1177 if (!HiiGetBrowserData (&gIp4Config2NvDataGuid, mIp4Config2StorageName, sizeof (IP4_CONFIG2_IFR_NVDATA), (UINT8 *)IfrFormNvData)) {
1178 FreePool (IfrFormNvData);
1179 return EFI_NOT_FOUND;
1180 }
1181
1182 Status = EFI_SUCCESS;
1183
1184 switch (QuestionId) {
1185 case KEY_LOCAL_IP:
1186 Status = Ip4Config2StrToIp (IfrFormNvData->StationAddress, &StationAddress.v4);
1187 if (EFI_ERROR (Status) || IP4_IS_UNSPECIFIED (NTOHL (StationAddress.Addr[0])) || IP4_IS_LOCAL_BROADCAST (NTOHL (StationAddress.Addr[0]))) {
1188 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid IP address!", NULL);
1189 Status = EFI_INVALID_PARAMETER;
1190 }
1191
1192 break;
1193
1194 case KEY_SUBNET_MASK:
1195 Status = Ip4Config2StrToIp (IfrFormNvData->SubnetMask, &SubnetMask.v4);
1196 if (EFI_ERROR (Status) || ((SubnetMask.Addr[0] != 0) && (GetSubnetMaskPrefixLength (&SubnetMask.v4) == 0))) {
1197 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid Subnet Mask!", NULL);
1198 Status = EFI_INVALID_PARAMETER;
1199 }
1200
1201 break;
1202
1203 case KEY_GATE_WAY:
1204 Status = Ip4Config2StrToIp (IfrFormNvData->GatewayAddress, &Gateway.v4);
1205 if (EFI_ERROR (Status) || IP4_IS_LOCAL_BROADCAST (NTOHL (Gateway.Addr[0]))) {
1206 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid Gateway!", NULL);
1207 Status = EFI_INVALID_PARAMETER;
1208 }
1209
1210 break;
1211
1212 case KEY_DNS:
1213 Status = Ip4Config2StrToIpList (IfrFormNvData->DnsAddress, &DnsAddress, &DnsCount);
1214 if (!EFI_ERROR (Status) && (DnsCount > 0)) {
1215 for (Index = 0; Index < DnsCount; Index++) {
1216 CopyMem (&Ip, &DnsAddress[Index], sizeof (IP4_ADDR));
1217 if (IP4_IS_UNSPECIFIED (NTOHL (Ip)) || IP4_IS_LOCAL_BROADCAST (NTOHL (Ip))) {
1218 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid Dns Server!", NULL);
1219 Status = EFI_INVALID_PARAMETER;
1220 break;
1221 }
1222 }
1223 } else {
1224 if (EFI_ERROR (Status)) {
1225 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid Dns Server!", NULL);
1226 }
1227 }
1228
1229 if (DnsAddress != NULL) {
1230 FreePool (DnsAddress);
1231 }
1232
1233 break;
1234
1235 case KEY_SAVE_CHANGES:
1236 Status = Ip4Config2ConvertIfrNvDataToConfigNvData (IfrFormNvData, Instance);
1237 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT;
1238 break;
1239
1240 default:
1241 break;
1242 }
1243
1244 FreePool (IfrFormNvData);
1245
1246 return Status;
1247 }
1248
1249 //
1250 // All other action return unsupported.
1251 //
1252 return EFI_UNSUPPORTED;
1253}
1254
1255/**
1256 Install HII Config Access protocol for network device and allocate resource.
1257
1258 @param[in, out] Instance The IP4 config2 Instance.
1259
1260 @retval EFI_SUCCESS The HII Config Access protocol is installed.
1261 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
1262 @retval Others Other errors as indicated.
1263
1264**/
1265EFI_STATUS
1266Ip4Config2FormInit (
1267 IN OUT IP4_CONFIG2_INSTANCE *Instance
1268 )
1269{
1270 EFI_STATUS Status;
1271 IP4_SERVICE *IpSb;
1272 IP4_FORM_CALLBACK_INFO *CallbackInfo;
1273 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;
1274 VENDOR_DEVICE_PATH VendorDeviceNode;
1275 EFI_SERVICE_BINDING_PROTOCOL *MnpSb;
1276 CHAR16 *MacString;
1277 CHAR16 MenuString[128];
1278 CHAR16 PortString[128];
1279 CHAR16 *OldMenuString;
1280 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
1281
1282 IpSb = IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance);
1283 ASSERT (IpSb != NULL);
1284
1285 CallbackInfo = &Instance->CallbackInfo;
1286
1287 CallbackInfo->Signature = IP4_FORM_CALLBACK_INFO_SIGNATURE;
1288
1289 Status = gBS->HandleProtocol (
1290 IpSb->Controller,
1291 &gEfiDevicePathProtocolGuid,
1292 (VOID **)&ParentDevicePath
1293 );
1294 if (EFI_ERROR (Status)) {
1295 return Status;
1296 }
1297
1298 //
1299 // Construct device path node for EFI HII Config Access protocol,
1300 // which consists of controller physical device path and one hardware
1301 // vendor guid node.
1302 //
1303 ZeroMem (&VendorDeviceNode, sizeof (VENDOR_DEVICE_PATH));
1304 VendorDeviceNode.Header.Type = HARDWARE_DEVICE_PATH;
1305 VendorDeviceNode.Header.SubType = HW_VENDOR_DP;
1306
1307 CopyGuid (&VendorDeviceNode.Guid, &gEfiCallerIdGuid);
1308
1309 SetDevicePathNodeLength (&VendorDeviceNode.Header, sizeof (VENDOR_DEVICE_PATH));
1310 CallbackInfo->HiiVendorDevicePath = AppendDevicePathNode (
1311 ParentDevicePath,
1312 (EFI_DEVICE_PATH_PROTOCOL *)&VendorDeviceNode
1313 );
1314 if (CallbackInfo->HiiVendorDevicePath == NULL) {
1315 Status = EFI_OUT_OF_RESOURCES;
1316 goto Error;
1317 }
1318
1319 ConfigAccess = &CallbackInfo->HiiConfigAccessProtocol;
1320 ConfigAccess->ExtractConfig = Ip4FormExtractConfig;
1321 ConfigAccess->RouteConfig = Ip4FormRouteConfig;
1322 ConfigAccess->Callback = Ip4FormCallback;
1323
1324 //
1325 // Install Device Path Protocol and Config Access protocol on new handle
1326 //
1327 Status = gBS->InstallMultipleProtocolInterfaces (
1328 &CallbackInfo->ChildHandle,
1329 &gEfiDevicePathProtocolGuid,
1330 CallbackInfo->HiiVendorDevicePath,
1331 &gEfiHiiConfigAccessProtocolGuid,
1332 ConfigAccess,
1333 NULL
1334 );
1335
1336 if (!EFI_ERROR (Status)) {
1337 //
1338 // Open the Parent Handle for the child
1339 //
1340 Status = gBS->OpenProtocol (
1341 IpSb->Controller,
1342 &gEfiManagedNetworkServiceBindingProtocolGuid,
1343 (VOID **)&MnpSb,
1344 IpSb->Image,
1345 CallbackInfo->ChildHandle,
1346 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
1347 );
1348 }
1349
1350 if (EFI_ERROR (Status)) {
1351 goto Error;
1352 }
1353
1354 //
1355 // Publish our HII data
1356 //
1357 CallbackInfo->RegisteredHandle = HiiAddPackages (
1358 &gIp4Config2NvDataGuid,
1359 CallbackInfo->ChildHandle,
1360 Ip4DxeStrings,
1361 Ip4Config2Bin,
1362 NULL
1363 );
1364 if (CallbackInfo->RegisteredHandle == NULL) {
1365 Status = EFI_OUT_OF_RESOURCES;
1366 goto Error;
1367 }
1368
1369 //
1370 // Append MAC string in the menu help string and tile help string
1371 //
1372 Status = NetLibGetMacString (IpSb->Controller, IpSb->Image, &MacString);
1373 if (!EFI_ERROR (Status)) {
1374 OldMenuString = HiiGetString (
1375 CallbackInfo->RegisteredHandle,
1376 STRING_TOKEN (STR_IP4_CONFIG2_FORM_HELP),
1377 NULL
1378 );
1379 UnicodeSPrint (MenuString, 128, L"%s (MAC:%s)", OldMenuString, MacString);
1380 HiiSetString (
1381 CallbackInfo->RegisteredHandle,
1382 STRING_TOKEN (STR_IP4_CONFIG2_FORM_HELP),
1383 MenuString,
1384 NULL
1385 );
1386
1387 UnicodeSPrint (PortString, 128, L"MAC:%s", MacString);
1388 HiiSetString (
1389 CallbackInfo->RegisteredHandle,
1390 STRING_TOKEN (STR_IP4_DEVICE_FORM_HELP),
1391 PortString,
1392 NULL
1393 );
1394
1395 FreePool (MacString);
1396 FreePool (OldMenuString);
1397
1398 return EFI_SUCCESS;
1399 }
1400
1401Error:
1402 Ip4Config2FormUnload (Instance);
1403 return Status;
1404}
1405
1406/**
1407 Uninstall the HII Config Access protocol for network devices and free up the resources.
1408
1409 @param[in, out] Instance The IP4 config2 instance to unload a form.
1410
1411**/
1412VOID
1413Ip4Config2FormUnload (
1414 IN OUT IP4_CONFIG2_INSTANCE *Instance
1415 )
1416{
1417 IP4_SERVICE *IpSb;
1418 IP4_FORM_CALLBACK_INFO *CallbackInfo;
1419 IP4_CONFIG2_NVDATA *Ip4NvData;
1420
1421 IpSb = IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance);
1422 ASSERT (IpSb != NULL);
1423
1424 CallbackInfo = &Instance->CallbackInfo;
1425
1426 if (CallbackInfo->ChildHandle != NULL) {
1427 //
1428 // Close the child handle
1429 //
1430 gBS->CloseProtocol (
1431 IpSb->Controller,
1432 &gEfiManagedNetworkServiceBindingProtocolGuid,
1433 IpSb->Image,
1434 CallbackInfo->ChildHandle
1435 );
1436
1437 //
1438 // Uninstall EFI_HII_CONFIG_ACCESS_PROTOCOL
1439 //
1440 gBS->UninstallMultipleProtocolInterfaces (
1441 CallbackInfo->ChildHandle,
1442 &gEfiDevicePathProtocolGuid,
1443 CallbackInfo->HiiVendorDevicePath,
1444 &gEfiHiiConfigAccessProtocolGuid,
1445 &CallbackInfo->HiiConfigAccessProtocol,
1446 NULL
1447 );
1448 }
1449
1450 if (CallbackInfo->HiiVendorDevicePath != NULL) {
1451 FreePool (CallbackInfo->HiiVendorDevicePath);
1452 }
1453
1454 if (CallbackInfo->RegisteredHandle != NULL) {
1455 //
1456 // Remove HII package list
1457 //
1458 HiiRemovePackages (CallbackInfo->RegisteredHandle);
1459 }
1460
1461 Ip4NvData = &Instance->Ip4NvData;
1462
1463 if (Ip4NvData->ManualAddress != NULL) {
1464 FreePool (Ip4NvData->ManualAddress);
1465 }
1466
1467 if (Ip4NvData->GatewayAddress != NULL) {
1468 FreePool (Ip4NvData->GatewayAddress);
1469 }
1470
1471 if (Ip4NvData->DnsAddress != NULL) {
1472 FreePool (Ip4NvData->DnsAddress);
1473 }
1474
1475 Ip4NvData->ManualAddressCount = 0;
1476 Ip4NvData->GatewayAddressCount = 0;
1477 Ip4NvData->DnsAddressCount = 0;
1478}
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette