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