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