]> git.proxmox.com Git - mirror_edk2.git/blob - NetworkPkg/Ip4Dxe/Ip4Config2Nv.c
NetworkPkg: Apply uncrustify changes
[mirror_edk2.git] / NetworkPkg / Ip4Dxe / Ip4Config2Nv.c
1 /** @file
2 Helper functions for configuring or getting the parameters relating to Ip4.
3
4 Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6
7 **/
8
9 #include "Ip4Impl.h"
10
11 CHAR16 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 **/
22 UINT8
23 GetSubnetMaskPrefixLength (
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 **/
64 EFI_STATUS
65 Ip4Config2StrToIp (
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 **/
129 EFI_STATUS
130 Ip4Config2StrToIpList (
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 **/
263 VOID
264 Ip4Config2IpToStr (
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 **/
293 EFI_STATUS
294 Ip4Config2IpListToStr (
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 **/
360 VOID
361 EFIAPI
362 Ip4Config2ManualAddressNotify (
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 **/
382 EFI_STATUS
383 Ip4Config2ConvertConfigNvDataToIfrNvData (
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
524 Exit:
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 **/
550 EFI_STATUS
551 Ip4Config2ConvertIfrNvDataToConfigNvData (
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 return EFI_SUCCESS;
590 }
591
592 if (IfrFormNvData->DhcpEnable == TRUE) {
593 Ip4NvData->Policy = Ip4Config2PolicyDhcp;
594
595 Status = Ip4Cfg2->SetData (
596 Ip4Cfg2,
597 Ip4Config2DataTypePolicy,
598 sizeof (EFI_IP4_CONFIG2_POLICY),
599 &Ip4NvData->Policy
600 );
601 if (EFI_ERROR (Status)) {
602 return Status;
603 }
604 } else {
605 //
606 // Get Ip4NvData from IfrFormNvData if it is valid.
607 //
608 Ip4NvData->Policy = Ip4Config2PolicyStatic;
609
610 Status = Ip4Config2StrToIp (IfrFormNvData->SubnetMask, &SubnetMask.v4);
611 if (EFI_ERROR (Status) || ((SubnetMask.Addr[0] != 0) && (GetSubnetMaskPrefixLength (&SubnetMask.v4) == 0))) {
612 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid Subnet Mask!", NULL);
613 return EFI_INVALID_PARAMETER;
614 }
615
616 Status = Ip4Config2StrToIp (IfrFormNvData->StationAddress, &StationAddress.v4);
617 if (EFI_ERROR (Status) ||
618 ((SubnetMask.Addr[0] != 0) && !NetIp4IsUnicast (NTOHL (StationAddress.Addr[0]), NTOHL (SubnetMask.Addr[0]))) ||
619 !Ip4StationAddressValid (NTOHL (StationAddress.Addr[0]), NTOHL (SubnetMask.Addr[0])))
620 {
621 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid IP address!", NULL);
622 return EFI_INVALID_PARAMETER;
623 }
624
625 Status = Ip4Config2StrToIp (IfrFormNvData->GatewayAddress, &Gateway.v4);
626 if (EFI_ERROR (Status) ||
627 ((Gateway.Addr[0] != 0) && (SubnetMask.Addr[0] != 0) && !NetIp4IsUnicast (NTOHL (Gateway.Addr[0]), NTOHL (SubnetMask.Addr[0]))))
628 {
629 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid Gateway!", NULL);
630 return EFI_INVALID_PARAMETER;
631 }
632
633 Status = Ip4Config2StrToIpList (IfrFormNvData->DnsAddress, &DnsAddress, &DnsCount);
634 if (!EFI_ERROR (Status) && (DnsCount > 0)) {
635 for (Index = 0; Index < DnsCount; Index++) {
636 CopyMem (&Ip, &DnsAddress[Index], sizeof (IP4_ADDR));
637 if (IP4_IS_UNSPECIFIED (NTOHL (Ip)) || IP4_IS_LOCAL_BROADCAST (NTOHL (Ip))) {
638 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid Dns Server!", NULL);
639 FreePool (DnsAddress);
640 return EFI_INVALID_PARAMETER;
641 }
642 }
643 } else {
644 if (EFI_ERROR (Status)) {
645 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid Dns Server!", NULL);
646 }
647 }
648
649 if (Ip4NvData->ManualAddress != NULL) {
650 FreePool (Ip4NvData->ManualAddress);
651 }
652
653 Ip4NvData->ManualAddressCount = 1;
654 Ip4NvData->ManualAddress = AllocateZeroPool (sizeof (EFI_IP4_CONFIG2_MANUAL_ADDRESS));
655 if (Ip4NvData->ManualAddress == NULL) {
656 if (DnsAddress != NULL) {
657 FreePool (DnsAddress);
658 }
659
660 return EFI_OUT_OF_RESOURCES;
661 }
662
663 CopyMem (&Ip4NvData->ManualAddress->Address, &StationAddress.v4, sizeof (EFI_IPv4_ADDRESS));
664 CopyMem (&Ip4NvData->ManualAddress->SubnetMask, &SubnetMask.v4, sizeof (EFI_IPv4_ADDRESS));
665
666 if (Ip4NvData->GatewayAddress != NULL) {
667 FreePool (Ip4NvData->GatewayAddress);
668 }
669
670 Ip4NvData->GatewayAddressCount = 1;
671 Ip4NvData->GatewayAddress = AllocateZeroPool (sizeof (EFI_IPv4_ADDRESS));
672 if (Ip4NvData->GatewayAddress == NULL) {
673 if (DnsAddress != NULL) {
674 FreePool (DnsAddress);
675 }
676
677 return EFI_OUT_OF_RESOURCES;
678 }
679
680 CopyMem (Ip4NvData->GatewayAddress, &Gateway.v4, sizeof (EFI_IPv4_ADDRESS));
681
682 if (Ip4NvData->DnsAddress != NULL) {
683 FreePool (Ip4NvData->DnsAddress);
684 }
685
686 Ip4NvData->DnsAddressCount = (UINT32)DnsCount;
687 Ip4NvData->DnsAddress = DnsAddress;
688
689 //
690 // Setting Ip4NvData.
691 //
692 Status = Ip4Cfg2->SetData (
693 Ip4Cfg2,
694 Ip4Config2DataTypePolicy,
695 sizeof (EFI_IP4_CONFIG2_POLICY),
696 &Ip4NvData->Policy
697 );
698 if (EFI_ERROR (Status)) {
699 return Status;
700 }
701
702 //
703 // Create events & timers for asynchronous settings.
704 //
705 Status = gBS->CreateEvent (
706 EVT_TIMER,
707 TPL_CALLBACK,
708 NULL,
709 NULL,
710 &TimeoutEvent
711 );
712 if (EFI_ERROR (Status)) {
713 return EFI_OUT_OF_RESOURCES;
714 }
715
716 Status = gBS->CreateEvent (
717 EVT_NOTIFY_SIGNAL,
718 TPL_NOTIFY,
719 Ip4Config2ManualAddressNotify,
720 &IsAddressOk,
721 &SetAddressEvent
722 );
723 if (EFI_ERROR (Status)) {
724 goto Exit;
725 }
726
727 IsAddressOk = FALSE;
728
729 Status = Ip4Cfg2->RegisterDataNotify (
730 Ip4Cfg2,
731 Ip4Config2DataTypeManualAddress,
732 SetAddressEvent
733 );
734 if (EFI_ERROR (Status)) {
735 goto Exit;
736 }
737
738 //
739 // Set ManualAddress.
740 //
741 DataSize = Ip4NvData->ManualAddressCount * sizeof (EFI_IP4_CONFIG2_MANUAL_ADDRESS);
742 Status = Ip4Cfg2->SetData (
743 Ip4Cfg2,
744 Ip4Config2DataTypeManualAddress,
745 DataSize,
746 (VOID *)Ip4NvData->ManualAddress
747 );
748
749 if (Status == EFI_NOT_READY) {
750 gBS->SetTimer (TimeoutEvent, TimerRelative, 50000000);
751 while (EFI_ERROR (gBS->CheckEvent (TimeoutEvent))) {
752 if (IsAddressOk) {
753 Status = EFI_SUCCESS;
754 break;
755 }
756 }
757 }
758
759 Ip4Cfg2->UnregisterDataNotify (
760 Ip4Cfg2,
761 Ip4Config2DataTypeManualAddress,
762 SetAddressEvent
763 );
764 if (EFI_ERROR (Status)) {
765 goto Exit;
766 }
767
768 //
769 // Set gateway.
770 //
771 DataSize = Ip4NvData->GatewayAddressCount * sizeof (EFI_IPv4_ADDRESS);
772 Status = Ip4Cfg2->SetData (
773 Ip4Cfg2,
774 Ip4Config2DataTypeGateway,
775 DataSize,
776 Ip4NvData->GatewayAddress
777 );
778 if (EFI_ERROR (Status)) {
779 goto Exit;
780 }
781
782 //
783 // Set DNS addresses.
784 //
785 if ((Ip4NvData->DnsAddressCount > 0) && (Ip4NvData->DnsAddress != NULL)) {
786 DataSize = Ip4NvData->DnsAddressCount * sizeof (EFI_IPv4_ADDRESS);
787 Status = Ip4Cfg2->SetData (
788 Ip4Cfg2,
789 Ip4Config2DataTypeDnsServer,
790 DataSize,
791 Ip4NvData->DnsAddress
792 );
793
794 if (EFI_ERROR (Status)) {
795 goto Exit;
796 }
797 }
798 }
799
800 Exit:
801 if (SetAddressEvent != NULL) {
802 gBS->CloseEvent (SetAddressEvent);
803 }
804
805 if (TimeoutEvent != NULL) {
806 gBS->CloseEvent (TimeoutEvent);
807 }
808
809 return Status;
810 }
811
812 /**
813 This function allows the caller to request the current
814 configuration for one or more named elements. The resulting
815 string is in <ConfigAltResp> format. Any and all alternative
816 configuration strings shall also be appended to the end of the
817 current configuration string. If they are, they must appear
818 after the current configuration. They must contain the same
819 routing (GUID, NAME, PATH) as the current configuration string.
820 They must have an additional description indicating the type of
821 alternative configuration the string represents,
822 "ALTCFG=<StringToken>". That <StringToken> (when
823 converted from Hex UNICODE to binary) is a reference to a
824 string in the associated string pack.
825
826 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
827 @param[in] Request A null-terminated Unicode string in
828 <ConfigRequest> format. Note that this
829 includes the routing information as well as
830 the configurable name / value pairs. It is
831 invalid for this string to be in
832 <MultiConfigRequest> format.
833 @param[out] Progress On return, points to a character in the
834 Request string. Points to the string's null
835 terminator if request was successful. Points
836 to the most recent "&" before the first
837 failing name / value pair (or the beginning
838 of the string if the failure is in the first
839 name / value pair) if the request was not
840 successful.
841 @param[out] Results A null-terminated Unicode string in
842 <ConfigAltResp> format which has all values
843 filled in for the names in the Request string.
844 String to be allocated by the called function.
845
846 @retval EFI_SUCCESS The Results string is filled with the
847 values corresponding to all requested
848 names.
849 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the
850 parts of the results that must be
851 stored awaiting possible future
852 protocols.
853 @retval EFI_NOT_FOUND Routing data doesn't match any
854 known driver. Progress set to the
855 first character in the routing header.
856 Note: There is no requirement that the
857 driver validate the routing data. It
858 must skip the <ConfigHdr> in order to
859 process the names.
860 @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set
861 to most recent & before the
862 error or the beginning of the
863 string.
864 @retval EFI_INVALID_PARAMETER Unknown name. Progress points
865 to the & before the name in
866 question.Currently not implemented.
867 **/
868 EFI_STATUS
869 EFIAPI
870 Ip4FormExtractConfig (
871 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
872 IN CONST EFI_STRING Request,
873 OUT EFI_STRING *Progress,
874 OUT EFI_STRING *Results
875 )
876 {
877 EFI_STATUS Status;
878 IP4_CONFIG2_INSTANCE *Ip4Config2Instance;
879 IP4_FORM_CALLBACK_INFO *Private;
880 IP4_CONFIG2_IFR_NVDATA *IfrFormNvData;
881 EFI_STRING ConfigRequestHdr;
882 EFI_STRING ConfigRequest;
883 BOOLEAN AllocatedRequest;
884 EFI_STRING FormResult;
885 UINTN Size;
886 UINTN BufferSize;
887
888 if ((Progress == NULL) || (Results == NULL)) {
889 return EFI_INVALID_PARAMETER;
890 }
891
892 Status = EFI_SUCCESS;
893 IfrFormNvData = NULL;
894 ConfigRequest = NULL;
895 FormResult = NULL;
896 Size = 0;
897 AllocatedRequest = FALSE;
898 ConfigRequest = Request;
899 Private = IP4_FORM_CALLBACK_INFO_FROM_CONFIG_ACCESS (This);
900 Ip4Config2Instance = IP4_CONFIG2_INSTANCE_FROM_FORM_CALLBACK (Private);
901 BufferSize = sizeof (IP4_CONFIG2_IFR_NVDATA);
902 *Progress = Request;
903
904 //
905 // Check Request data in <ConfigHdr>.
906 //
907 if ((Request == NULL) || HiiIsConfigHdrMatch (Request, &gIp4Config2NvDataGuid, mIp4Config2StorageName)) {
908 IfrFormNvData = AllocateZeroPool (sizeof (IP4_CONFIG2_IFR_NVDATA));
909 if (IfrFormNvData == NULL) {
910 return EFI_OUT_OF_RESOURCES;
911 }
912
913 Ip4Config2ConvertConfigNvDataToIfrNvData (Ip4Config2Instance, IfrFormNvData);
914
915 if ((Request == NULL) || (StrStr (Request, L"OFFSET") == NULL)) {
916 //
917 // Request has no request element, construct full request string.
918 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
919 // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
920 //
921 ConfigRequestHdr = HiiConstructConfigHdr (&gIp4Config2NvDataGuid, mIp4Config2StorageName, Private->ChildHandle);
922 Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16);
923 ConfigRequest = AllocateZeroPool (Size);
924 if (ConfigRequest == NULL) {
925 Status = EFI_OUT_OF_RESOURCES;
926 goto Failure;
927 }
928
929 AllocatedRequest = TRUE;
930
931 UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr, (UINT64)BufferSize);
932 FreePool (ConfigRequestHdr);
933 }
934
935 //
936 // Convert buffer data to <ConfigResp> by helper function BlockToConfig()
937 //
938 Status = gHiiConfigRouting->BlockToConfig (
939 gHiiConfigRouting,
940 ConfigRequest,
941 (UINT8 *)IfrFormNvData,
942 BufferSize,
943 &FormResult,
944 Progress
945 );
946
947 FreePool (IfrFormNvData);
948
949 //
950 // Free the allocated config request string.
951 //
952 if (AllocatedRequest) {
953 FreePool (ConfigRequest);
954 ConfigRequest = NULL;
955 }
956
957 if (EFI_ERROR (Status)) {
958 goto Failure;
959 }
960 }
961
962 if ((Request == NULL) || HiiIsConfigHdrMatch (Request, &gIp4Config2NvDataGuid, mIp4Config2StorageName)) {
963 *Results = FormResult;
964 } else {
965 return EFI_NOT_FOUND;
966 }
967
968 Failure:
969 //
970 // Set Progress string to the original request string.
971 //
972 if (Request == NULL) {
973 *Progress = NULL;
974 } else if (StrStr (Request, L"OFFSET") == NULL) {
975 *Progress = Request + StrLen (Request);
976 }
977
978 return Status;
979 }
980
981 /**
982 This function applies changes in a driver's configuration.
983 Input is a Configuration, which has the routing data for this
984 driver followed by name / value configuration pairs. The driver
985 must apply those pairs to its configurable storage. If the
986 driver's configuration is stored in a linear block of data
987 and the driver's name / value pairs are in <BlockConfig>
988 format, it may use the ConfigToBlock helper function (above) to
989 simplify the job. Currently not implemented.
990
991 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
992 @param[in] Configuration A null-terminated Unicode string in
993 <ConfigString> format.
994 @param[out] Progress A pointer to a string filled in with the
995 offset of the most recent '&' before the
996 first failing name / value pair (or the
997 beginning of the string if the failure
998 is in the first name / value pair) or
999 the terminating NULL if all was
1000 successful.
1001
1002 @retval EFI_SUCCESS The results have been distributed or are
1003 awaiting distribution.
1004 @retval EFI_OUT_OF_MEMORY Not enough memory to store the
1005 parts of the results that must be
1006 stored awaiting possible future
1007 protocols.
1008 @retval EFI_INVALID_PARAMETERS Passing in a NULL for the
1009 Results parameter would result
1010 in this type of error.
1011 @retval EFI_NOT_FOUND Target for the specified routing data
1012 was not found.
1013 **/
1014 EFI_STATUS
1015 EFIAPI
1016 Ip4FormRouteConfig (
1017 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
1018 IN CONST EFI_STRING Configuration,
1019 OUT EFI_STRING *Progress
1020 )
1021 {
1022 EFI_STATUS Status;
1023 UINTN BufferSize;
1024 IP4_CONFIG2_IFR_NVDATA *IfrFormNvData;
1025 IP4_CONFIG2_INSTANCE *Ip4Config2Instance;
1026 IP4_FORM_CALLBACK_INFO *Private;
1027
1028 Status = EFI_SUCCESS;
1029 IfrFormNvData = NULL;
1030
1031 if ((Configuration == NULL) || (Progress == NULL)) {
1032 return EFI_INVALID_PARAMETER;
1033 }
1034
1035 *Progress = Configuration;
1036
1037 Private = IP4_FORM_CALLBACK_INFO_FROM_CONFIG_ACCESS (This);
1038 Ip4Config2Instance = IP4_CONFIG2_INSTANCE_FROM_FORM_CALLBACK (Private);
1039
1040 //
1041 // Check Routing data in <ConfigHdr>.
1042 //
1043 if (HiiIsConfigHdrMatch (Configuration, &gIp4Config2NvDataGuid, mIp4Config2StorageName)) {
1044 //
1045 // Convert buffer data to <ConfigResp> by helper function BlockToConfig()
1046 //
1047 IfrFormNvData = AllocateZeroPool (sizeof (IP4_CONFIG2_IFR_NVDATA));
1048 if (IfrFormNvData == NULL) {
1049 return EFI_OUT_OF_RESOURCES;
1050 }
1051
1052 BufferSize = 0;
1053
1054 Status = gHiiConfigRouting->ConfigToBlock (
1055 gHiiConfigRouting,
1056 Configuration,
1057 (UINT8 *)IfrFormNvData,
1058 &BufferSize,
1059 Progress
1060 );
1061 if (Status != EFI_BUFFER_TOO_SMALL) {
1062 return Status;
1063 }
1064
1065 Status = gHiiConfigRouting->ConfigToBlock (
1066 gHiiConfigRouting,
1067 Configuration,
1068 (UINT8 *)IfrFormNvData,
1069 &BufferSize,
1070 Progress
1071 );
1072 if (!EFI_ERROR (Status)) {
1073 Status = Ip4Config2ConvertIfrNvDataToConfigNvData (IfrFormNvData, Ip4Config2Instance);
1074 }
1075
1076 FreePool (IfrFormNvData);
1077 } else {
1078 return EFI_NOT_FOUND;
1079 }
1080
1081 return Status;
1082 }
1083
1084 /**
1085 This function is called to provide results data to the driver.
1086 This data consists of a unique key that is used to identify
1087 which data is either being passed back or being asked for.
1088
1089 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
1090 @param[in] Action Specifies the type of action taken by the browser.
1091 @param[in] QuestionId A unique value which is sent to the original
1092 exporting driver so that it can identify the type
1093 of data to expect. The format of the data tends to
1094 vary based on the opcode that enerated the callback.
1095 @param[in] Type The type of value for the question.
1096 @param[in] Value A pointer to the data being sent to the original
1097 exporting driver.
1098 @param[out] ActionRequest On return, points to the action requested by the
1099 callback function.
1100
1101 @retval EFI_SUCCESS The callback successfully handled the action.
1102 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the
1103 variable and its data.
1104 @retval EFI_DEVICE_ERROR The variable could not be saved.
1105 @retval EFI_UNSUPPORTED The specified Action is not supported by the
1106 callback. Currently not implemented.
1107 @retval EFI_INVALID_PARAMETERS Passing in wrong parameter.
1108 @retval Others Other errors as indicated.
1109
1110 **/
1111 EFI_STATUS
1112 EFIAPI
1113 Ip4FormCallback (
1114 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
1115 IN EFI_BROWSER_ACTION Action,
1116 IN EFI_QUESTION_ID QuestionId,
1117 IN UINT8 Type,
1118 IN EFI_IFR_TYPE_VALUE *Value,
1119 OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest
1120 )
1121 {
1122 EFI_STATUS Status;
1123 IP4_CONFIG2_INSTANCE *Instance;
1124 IP4_CONFIG2_IFR_NVDATA *IfrFormNvData;
1125 IP4_FORM_CALLBACK_INFO *Private;
1126
1127 EFI_IP_ADDRESS StationAddress;
1128 EFI_IP_ADDRESS SubnetMask;
1129 EFI_IP_ADDRESS Gateway;
1130 IP4_ADDR Ip;
1131 EFI_IPv4_ADDRESS *DnsAddress;
1132 UINTN DnsCount;
1133 UINTN Index;
1134 EFI_INPUT_KEY Key;
1135
1136 IfrFormNvData = NULL;
1137 DnsCount = 0;
1138 DnsAddress = NULL;
1139
1140 if (Action == EFI_BROWSER_ACTION_CHANGED) {
1141 Private = IP4_FORM_CALLBACK_INFO_FROM_CONFIG_ACCESS (This);
1142 Instance = IP4_CONFIG2_INSTANCE_FROM_FORM_CALLBACK (Private);
1143
1144 IfrFormNvData = AllocateZeroPool (sizeof (IP4_CONFIG2_IFR_NVDATA));
1145 if (IfrFormNvData == NULL) {
1146 return EFI_OUT_OF_RESOURCES;
1147 }
1148
1149 //
1150 // Retrieve uncommitted data from Browser
1151 //
1152 if (!HiiGetBrowserData (&gIp4Config2NvDataGuid, mIp4Config2StorageName, sizeof (IP4_CONFIG2_IFR_NVDATA), (UINT8 *)IfrFormNvData)) {
1153 FreePool (IfrFormNvData);
1154 return EFI_NOT_FOUND;
1155 }
1156
1157 Status = EFI_SUCCESS;
1158
1159 switch (QuestionId) {
1160 case KEY_LOCAL_IP:
1161 Status = Ip4Config2StrToIp (IfrFormNvData->StationAddress, &StationAddress.v4);
1162 if (EFI_ERROR (Status) || IP4_IS_UNSPECIFIED (NTOHL (StationAddress.Addr[0])) || IP4_IS_LOCAL_BROADCAST (NTOHL (StationAddress.Addr[0]))) {
1163 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid IP address!", NULL);
1164 Status = EFI_INVALID_PARAMETER;
1165 }
1166
1167 break;
1168
1169 case KEY_SUBNET_MASK:
1170 Status = Ip4Config2StrToIp (IfrFormNvData->SubnetMask, &SubnetMask.v4);
1171 if (EFI_ERROR (Status) || ((SubnetMask.Addr[0] != 0) && (GetSubnetMaskPrefixLength (&SubnetMask.v4) == 0))) {
1172 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid Subnet Mask!", NULL);
1173 Status = EFI_INVALID_PARAMETER;
1174 }
1175
1176 break;
1177
1178 case KEY_GATE_WAY:
1179 Status = Ip4Config2StrToIp (IfrFormNvData->GatewayAddress, &Gateway.v4);
1180 if (EFI_ERROR (Status) || IP4_IS_LOCAL_BROADCAST (NTOHL (Gateway.Addr[0]))) {
1181 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid Gateway!", NULL);
1182 Status = EFI_INVALID_PARAMETER;
1183 }
1184
1185 break;
1186
1187 case KEY_DNS:
1188 Status = Ip4Config2StrToIpList (IfrFormNvData->DnsAddress, &DnsAddress, &DnsCount);
1189 if (!EFI_ERROR (Status) && (DnsCount > 0)) {
1190 for (Index = 0; Index < DnsCount; Index++) {
1191 CopyMem (&Ip, &DnsAddress[Index], sizeof (IP4_ADDR));
1192 if (IP4_IS_UNSPECIFIED (NTOHL (Ip)) || IP4_IS_LOCAL_BROADCAST (NTOHL (Ip))) {
1193 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid Dns Server!", NULL);
1194 Status = EFI_INVALID_PARAMETER;
1195 break;
1196 }
1197 }
1198 } else {
1199 if (EFI_ERROR (Status)) {
1200 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid Dns Server!", NULL);
1201 }
1202 }
1203
1204 if (DnsAddress != NULL) {
1205 FreePool (DnsAddress);
1206 }
1207
1208 break;
1209
1210 case KEY_SAVE_CHANGES:
1211 Status = Ip4Config2ConvertIfrNvDataToConfigNvData (IfrFormNvData, Instance);
1212 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT;
1213 break;
1214
1215 default:
1216 break;
1217 }
1218
1219 FreePool (IfrFormNvData);
1220
1221 return Status;
1222 }
1223
1224 //
1225 // All other action return unsupported.
1226 //
1227 return EFI_UNSUPPORTED;
1228 }
1229
1230 /**
1231 Install HII Config Access protocol for network device and allocate resource.
1232
1233 @param[in, out] Instance The IP4 config2 Instance.
1234
1235 @retval EFI_SUCCESS The HII Config Access protocol is installed.
1236 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
1237 @retval Others Other errors as indicated.
1238
1239 **/
1240 EFI_STATUS
1241 Ip4Config2FormInit (
1242 IN OUT IP4_CONFIG2_INSTANCE *Instance
1243 )
1244 {
1245 EFI_STATUS Status;
1246 IP4_SERVICE *IpSb;
1247 IP4_FORM_CALLBACK_INFO *CallbackInfo;
1248 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;
1249 VENDOR_DEVICE_PATH VendorDeviceNode;
1250 EFI_SERVICE_BINDING_PROTOCOL *MnpSb;
1251 CHAR16 *MacString;
1252 CHAR16 MenuString[128];
1253 CHAR16 PortString[128];
1254 CHAR16 *OldMenuString;
1255 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
1256
1257 IpSb = IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance);
1258 ASSERT (IpSb != NULL);
1259
1260 CallbackInfo = &Instance->CallbackInfo;
1261
1262 CallbackInfo->Signature = IP4_FORM_CALLBACK_INFO_SIGNATURE;
1263
1264 Status = gBS->HandleProtocol (
1265 IpSb->Controller,
1266 &gEfiDevicePathProtocolGuid,
1267 (VOID **)&ParentDevicePath
1268 );
1269 if (EFI_ERROR (Status)) {
1270 return Status;
1271 }
1272
1273 //
1274 // Construct device path node for EFI HII Config Access protocol,
1275 // which consists of controller physical device path and one hardware
1276 // vendor guid node.
1277 //
1278 ZeroMem (&VendorDeviceNode, sizeof (VENDOR_DEVICE_PATH));
1279 VendorDeviceNode.Header.Type = HARDWARE_DEVICE_PATH;
1280 VendorDeviceNode.Header.SubType = HW_VENDOR_DP;
1281
1282 CopyGuid (&VendorDeviceNode.Guid, &gEfiCallerIdGuid);
1283
1284 SetDevicePathNodeLength (&VendorDeviceNode.Header, sizeof (VENDOR_DEVICE_PATH));
1285 CallbackInfo->HiiVendorDevicePath = AppendDevicePathNode (
1286 ParentDevicePath,
1287 (EFI_DEVICE_PATH_PROTOCOL *)&VendorDeviceNode
1288 );
1289 if (CallbackInfo->HiiVendorDevicePath == NULL) {
1290 Status = EFI_OUT_OF_RESOURCES;
1291 goto Error;
1292 }
1293
1294 ConfigAccess = &CallbackInfo->HiiConfigAccessProtocol;
1295 ConfigAccess->ExtractConfig = Ip4FormExtractConfig;
1296 ConfigAccess->RouteConfig = Ip4FormRouteConfig;
1297 ConfigAccess->Callback = Ip4FormCallback;
1298
1299 //
1300 // Install Device Path Protocol and Config Access protocol on new handle
1301 //
1302 Status = gBS->InstallMultipleProtocolInterfaces (
1303 &CallbackInfo->ChildHandle,
1304 &gEfiDevicePathProtocolGuid,
1305 CallbackInfo->HiiVendorDevicePath,
1306 &gEfiHiiConfigAccessProtocolGuid,
1307 ConfigAccess,
1308 NULL
1309 );
1310
1311 if (!EFI_ERROR (Status)) {
1312 //
1313 // Open the Parent Handle for the child
1314 //
1315 Status = gBS->OpenProtocol (
1316 IpSb->Controller,
1317 &gEfiManagedNetworkServiceBindingProtocolGuid,
1318 (VOID **)&MnpSb,
1319 IpSb->Image,
1320 CallbackInfo->ChildHandle,
1321 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
1322 );
1323 }
1324
1325 if (EFI_ERROR (Status)) {
1326 goto Error;
1327 }
1328
1329 //
1330 // Publish our HII data
1331 //
1332 CallbackInfo->RegisteredHandle = HiiAddPackages (
1333 &gIp4Config2NvDataGuid,
1334 CallbackInfo->ChildHandle,
1335 Ip4DxeStrings,
1336 Ip4Config2Bin,
1337 NULL
1338 );
1339 if (CallbackInfo->RegisteredHandle == NULL) {
1340 Status = EFI_OUT_OF_RESOURCES;
1341 goto Error;
1342 }
1343
1344 //
1345 // Append MAC string in the menu help string and tile help string
1346 //
1347 Status = NetLibGetMacString (IpSb->Controller, IpSb->Image, &MacString);
1348 if (!EFI_ERROR (Status)) {
1349 OldMenuString = HiiGetString (
1350 CallbackInfo->RegisteredHandle,
1351 STRING_TOKEN (STR_IP4_CONFIG2_FORM_HELP),
1352 NULL
1353 );
1354 UnicodeSPrint (MenuString, 128, L"%s (MAC:%s)", OldMenuString, MacString);
1355 HiiSetString (
1356 CallbackInfo->RegisteredHandle,
1357 STRING_TOKEN (STR_IP4_CONFIG2_FORM_HELP),
1358 MenuString,
1359 NULL
1360 );
1361
1362 UnicodeSPrint (PortString, 128, L"MAC:%s", MacString);
1363 HiiSetString (
1364 CallbackInfo->RegisteredHandle,
1365 STRING_TOKEN (STR_IP4_DEVICE_FORM_HELP),
1366 PortString,
1367 NULL
1368 );
1369
1370 FreePool (MacString);
1371 FreePool (OldMenuString);
1372
1373 return EFI_SUCCESS;
1374 }
1375
1376 Error:
1377 Ip4Config2FormUnload (Instance);
1378 return Status;
1379 }
1380
1381 /**
1382 Uninstall the HII Config Access protocol for network devices and free up the resources.
1383
1384 @param[in, out] Instance The IP4 config2 instance to unload a form.
1385
1386 **/
1387 VOID
1388 Ip4Config2FormUnload (
1389 IN OUT IP4_CONFIG2_INSTANCE *Instance
1390 )
1391 {
1392 IP4_SERVICE *IpSb;
1393 IP4_FORM_CALLBACK_INFO *CallbackInfo;
1394 IP4_CONFIG2_NVDATA *Ip4NvData;
1395
1396 IpSb = IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance);
1397 ASSERT (IpSb != NULL);
1398
1399 CallbackInfo = &Instance->CallbackInfo;
1400
1401 if (CallbackInfo->ChildHandle != NULL) {
1402 //
1403 // Close the child handle
1404 //
1405 gBS->CloseProtocol (
1406 IpSb->Controller,
1407 &gEfiManagedNetworkServiceBindingProtocolGuid,
1408 IpSb->Image,
1409 CallbackInfo->ChildHandle
1410 );
1411
1412 //
1413 // Uninstall EFI_HII_CONFIG_ACCESS_PROTOCOL
1414 //
1415 gBS->UninstallMultipleProtocolInterfaces (
1416 CallbackInfo->ChildHandle,
1417 &gEfiDevicePathProtocolGuid,
1418 CallbackInfo->HiiVendorDevicePath,
1419 &gEfiHiiConfigAccessProtocolGuid,
1420 &CallbackInfo->HiiConfigAccessProtocol,
1421 NULL
1422 );
1423 }
1424
1425 if (CallbackInfo->HiiVendorDevicePath != NULL) {
1426 FreePool (CallbackInfo->HiiVendorDevicePath);
1427 }
1428
1429 if (CallbackInfo->RegisteredHandle != NULL) {
1430 //
1431 // Remove HII package list
1432 //
1433 HiiRemovePackages (CallbackInfo->RegisteredHandle);
1434 }
1435
1436 Ip4NvData = &Instance->Ip4NvData;
1437
1438 if (Ip4NvData->ManualAddress != NULL) {
1439 FreePool (Ip4NvData->ManualAddress);
1440 }
1441
1442 if (Ip4NvData->GatewayAddress != NULL) {
1443 FreePool (Ip4NvData->GatewayAddress);
1444 }
1445
1446 if (Ip4NvData->DnsAddress != NULL) {
1447 FreePool (Ip4NvData->DnsAddress);
1448 }
1449
1450 Ip4NvData->ManualAddressCount = 0;
1451 Ip4NvData->GatewayAddressCount = 0;
1452 Ip4NvData->DnsAddressCount = 0;
1453 }