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