]> git.proxmox.com Git - mirror_edk2.git/blob - NetworkPkg/Ip6Dxe/Ip6ConfigNv.c
Update IPv6 configuration UI: 1) keep addresses blank when enter ‘Advanced Configurat...
[mirror_edk2.git] / NetworkPkg / Ip6Dxe / Ip6ConfigNv.c
1 /** @file
2 Helper functions for configuring or obtaining the parameters relating to IP6.
3
4 Copyright (c) 2010 - 2013, Intel Corporation. All rights reserved.<BR>
5
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php.
10
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13
14 **/
15
16 #include "Ip6Impl.h"
17
18 CHAR16 mIp6ConfigStorageName[] = L"IP6_CONFIG_IFR_NVDATA";
19
20 /**
21 The notify function of create event when performing a manual configuration.
22
23 @param[in] Event The pointer of Event.
24 @param[in] Context The pointer of Context.
25
26 **/
27 VOID
28 EFIAPI
29 Ip6ConfigManualAddressNotify (
30 IN EFI_EVENT Event,
31 IN VOID *Context
32 )
33 {
34 *((BOOLEAN *) Context) = TRUE;
35 }
36
37 /**
38 Get the configuration data for the EFI IPv6 network stack running on the
39 communication. It is a help function to the call EfiIp6ConfigGetData().
40
41 @param[in] Ip6Config The pointer to the EFI_IP6_CONFIG_PROTOCOL instance.
42 @param[in] DataType The type of data to get.
43 @param[out] DataSize The size of buffer required in bytes.
44 @param[out] Data The data buffer in which the configuration data is returned. The
45 type of the data buffer associated with the DataType.
46 It is the caller's responsibility to free the resource.
47
48 @retval EFI_SUCCESS The specified configuration data was obtained successfully.
49 @retval EFI_INVALID_PARAMETER One or more of the followings are TRUE:
50 - Ip6Config is NULL or invalid.
51 - DataSize is NULL.
52 - Data is NULL.
53 @retval EFI_OUT_OF_RESOURCES Fail to perform the operation due to lack of resources.
54 @retval EFI_NOT_READY The specified configuration data is not ready due to an
55 asynchronous configuration process already in progress.
56 @retval EFI_NOT_FOUND The specified configuration data was not found.
57
58 **/
59 EFI_STATUS
60 Ip6ConfigNvGetData (
61 IN EFI_IP6_CONFIG_PROTOCOL *Ip6Config,
62 IN EFI_IP6_CONFIG_DATA_TYPE DataType,
63 OUT UINTN *DataSize,
64 OUT VOID **Data
65 )
66 {
67 UINTN BufferSize;
68 VOID *Buffer;
69 EFI_STATUS Status;
70
71 if ((Ip6Config == NULL) || (Data == NULL) || (DataSize == NULL)) {
72 return EFI_INVALID_PARAMETER;
73 }
74
75 BufferSize = 0;
76 Status = Ip6Config->GetData (
77 Ip6Config,
78 DataType,
79 &BufferSize,
80 NULL
81 );
82 if (Status != EFI_BUFFER_TOO_SMALL) {
83 return Status;
84 }
85
86 Buffer = AllocateZeroPool (BufferSize);
87 if (Buffer == NULL) {
88 return EFI_OUT_OF_RESOURCES;
89 }
90
91 Status = Ip6Config->GetData (
92 Ip6Config,
93 DataType,
94 &BufferSize,
95 Buffer
96 );
97 if (EFI_ERROR (Status)) {
98 FreePool (Buffer);
99 return Status;
100 }
101
102 *DataSize = BufferSize;
103 *Data = Buffer;
104
105 return EFI_SUCCESS;
106 }
107
108 /**
109 Free all nodes in IP6_ADDRESS_INFO_ENTRY in the list array specified
110 with ListHead.
111
112 @param[in] ListHead The head of the list array in IP6_ADDRESS_INFO_ENTRY.
113
114 **/
115 VOID
116 Ip6FreeAddressInfoList (
117 IN LIST_ENTRY *ListHead
118 )
119 {
120 IP6_ADDRESS_INFO_ENTRY *Node;
121 LIST_ENTRY *Entry;
122 LIST_ENTRY *NextEntry;
123
124 NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, ListHead) {
125 Node = NET_LIST_USER_STRUCT (Entry, IP6_ADDRESS_INFO_ENTRY, Link);
126 RemoveEntryList (&Node->Link);
127 FreePool (Node);
128 }
129 }
130
131 /**
132 Convert the IPv6 address into a formatted string.
133
134 @param[in] Ip6 The IPv6 address.
135 @param[out] Str The formatted IP string.
136
137 **/
138 VOID
139 Ip6ToStr (
140 IN EFI_IPv6_ADDRESS *Ip6,
141 OUT CHAR16 *Str
142 )
143 {
144 UINTN Index;
145 BOOLEAN Short;
146 UINTN Number;
147 CHAR16 FormatString[8];
148
149 Short = FALSE;
150
151 for (Index = 0; Index < 15; Index = Index + 2) {
152 if (!Short &&
153 Index % 2 == 0 &&
154 Ip6->Addr[Index] == 0 &&
155 Ip6->Addr[Index + 1] == 0
156 ) {
157 //
158 // Deal with the case of ::.
159 //
160 if (Index == 0) {
161 *Str = L':';
162 *(Str + 1) = L':';
163 Str = Str + 2;
164 } else {
165 *Str = L':';
166 Str = Str + 1;
167 }
168
169 while ((Index < 15) && (Ip6->Addr[Index] == 0) && (Ip6->Addr[Index + 1] == 0)) {
170 Index = Index + 2;
171 }
172
173 Short = TRUE;
174
175 if (Index == 16) {
176 //
177 // :: is at the end of the address.
178 //
179 *Str = L'\0';
180 break;
181 }
182 }
183
184 ASSERT (Index < 15);
185
186 if (Ip6->Addr[Index] == 0) {
187 Number = UnicodeSPrint (Str, 2 * IP6_STR_MAX_SIZE, L"%x:", (UINTN) Ip6->Addr[Index + 1]);
188 } else {
189 if (Ip6->Addr[Index + 1] < 0x10) {
190 CopyMem (FormatString, L"%x0%x:", StrSize (L"%x0%x:"));
191 } else {
192 CopyMem (FormatString, L"%x%x:", StrSize (L"%x%x:"));
193 }
194
195 Number = UnicodeSPrint (
196 Str,
197 2 * IP6_STR_MAX_SIZE,
198 (CONST CHAR16 *) FormatString,
199 (UINTN) Ip6->Addr[Index],
200 (UINTN) Ip6->Addr[Index + 1]
201 );
202 }
203
204 Str = Str + Number;
205
206 if (Index + 2 == 16) {
207 *Str = L'\0';
208 if (*(Str - 1) == L':') {
209 *(Str - 1) = L'\0';
210 }
211 }
212 }
213 }
214
215 /**
216 Convert EFI_IP6_CONFIG_INTERFACE_ID to string format.
217
218 @param[out] String The buffer to store the converted string.
219 @param[in] IfId The pointer of EFI_IP6_CONFIG_INTERFACE_ID.
220
221 @retval EFI_SUCCESS The string converted successfully.
222 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
223
224 **/
225 EFI_STATUS
226 Ip6ConvertInterfaceIdToString (
227 OUT CHAR16 *String,
228 IN EFI_IP6_CONFIG_INTERFACE_ID *IfId
229 )
230 {
231 UINT8 Index;
232 UINTN Number;
233
234 if ((String == NULL) || (IfId == NULL)) {
235 return EFI_INVALID_PARAMETER;
236 }
237
238 for (Index = 0; Index < 8; Index++) {
239 Number = UnicodeSPrint (
240 String,
241 2 * INTERFACE_ID_STR_STORAGE,
242 L"%x:",
243 (UINTN) IfId->Id[Index]
244 );
245 String = String + Number;
246 }
247
248 *(String - 1) = '\0';
249
250 return EFI_SUCCESS;
251 }
252
253 /**
254 Parse InterfaceId in string format and convert it to EFI_IP6_CONFIG_INTERFACE_ID.
255
256 @param[in] String The buffer of the string to be parsed.
257 @param[out] IfId The pointer of EFI_IP6_CONFIG_INTERFACE_ID.
258
259 @retval EFI_SUCCESS The operation finished successfully.
260 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
261
262 **/
263 EFI_STATUS
264 Ip6ParseInterfaceIdFromString (
265 IN CONST CHAR16 *String,
266 OUT EFI_IP6_CONFIG_INTERFACE_ID *IfId
267 )
268 {
269 UINT8 Index;
270 CHAR16 *IfIdStr;
271 CHAR16 *TempStr;
272 UINTN NodeVal;
273
274 if ((String == NULL) || (IfId == NULL)) {
275 return EFI_INVALID_PARAMETER;
276 }
277
278 IfIdStr = (CHAR16 *) String;
279
280 ZeroMem (IfId, sizeof (EFI_IP6_CONFIG_INTERFACE_ID));
281
282 for (Index = 0; Index < 8; Index++) {
283 TempStr = IfIdStr;
284
285 while ((*IfIdStr != L'\0') && (*IfIdStr != L':')) {
286 IfIdStr++;
287 }
288
289 //
290 // The InterfaceId format is X:X:X:X, the number of X should not exceed 8.
291 // If the number of X is less than 8, zero is appended to the InterfaceId.
292 //
293 if ((*IfIdStr == ':') && (Index == 7)) {
294 return EFI_INVALID_PARAMETER;
295 }
296
297 //
298 // Convert the string to interface id. AsciiStrHexToUintn stops at the
299 // first character that is not a valid hex character, ':' or '\0' here.
300 //
301 NodeVal = StrHexToUintn (TempStr);
302 if (NodeVal > 0xFF) {
303 return EFI_INVALID_PARAMETER;
304 }
305
306 IfId->Id[Index] = (UINT8) NodeVal;
307
308 IfIdStr++;
309 }
310
311 return EFI_SUCCESS;
312 }
313
314 /**
315 Create Hii Extend Label OpCode as the start opcode and end opcode. It is
316 a help function.
317
318 @param[in] StartLabelNumber The number of start label.
319 @param[out] StartOpCodeHandle Points to the start opcode handle.
320 @param[out] StartLabel Points to the created start opcode.
321 @param[out] EndOpCodeHandle Points to the end opcode handle.
322 @param[out] EndLabel Points to the created end opcode.
323
324 @retval EFI_OUT_OF_RESOURCES Does not have sufficient resources to finish this
325 operation.
326 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
327 @retval EFI_SUCCESS The operation completed successfully.
328
329 **/
330 EFI_STATUS
331 Ip6CreateOpCode (
332 IN UINT16 StartLabelNumber,
333 OUT VOID **StartOpCodeHandle,
334 OUT EFI_IFR_GUID_LABEL **StartLabel,
335 OUT VOID **EndOpCodeHandle,
336 OUT EFI_IFR_GUID_LABEL **EndLabel
337 )
338 {
339 EFI_STATUS Status;
340 EFI_IFR_GUID_LABEL *InternalStartLabel;
341 EFI_IFR_GUID_LABEL *InternalEndLabel;
342
343 if (StartOpCodeHandle == NULL || StartLabel == NULL || EndOpCodeHandle == NULL || EndLabel == NULL) {
344 return EFI_INVALID_PARAMETER;
345 }
346
347 *StartOpCodeHandle = NULL;
348 *EndOpCodeHandle = NULL;
349 Status = EFI_OUT_OF_RESOURCES;
350
351 //
352 // Initialize the container for dynamic opcodes.
353 //
354 *StartOpCodeHandle = HiiAllocateOpCodeHandle ();
355 if (*StartOpCodeHandle == NULL) {
356 return Status;
357 }
358
359 *EndOpCodeHandle = HiiAllocateOpCodeHandle ();
360 if (*EndOpCodeHandle == NULL) {
361 goto Exit;
362 }
363
364 //
365 // Create Hii Extend Label OpCode as the start opcode.
366 //
367 InternalStartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (
368 *StartOpCodeHandle,
369 &gEfiIfrTianoGuid,
370 NULL,
371 sizeof (EFI_IFR_GUID_LABEL)
372 );
373 if (InternalStartLabel == NULL) {
374 goto Exit;
375 }
376
377 InternalStartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
378 InternalStartLabel->Number = StartLabelNumber;
379
380 //
381 // Create Hii Extend Label OpCode as the end opcode.
382 //
383 InternalEndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (
384 *EndOpCodeHandle,
385 &gEfiIfrTianoGuid,
386 NULL,
387 sizeof (EFI_IFR_GUID_LABEL)
388 );
389 if (InternalEndLabel == NULL) {
390 goto Exit;
391 }
392
393 InternalEndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
394 InternalEndLabel->Number = LABEL_END;
395
396 *StartLabel = InternalStartLabel;
397 *EndLabel = InternalEndLabel;
398
399 return EFI_SUCCESS;
400
401 Exit:
402
403 if (*StartOpCodeHandle != NULL) {
404 HiiFreeOpCodeHandle (*StartOpCodeHandle);
405 }
406
407 if (*EndOpCodeHandle != NULL) {
408 HiiFreeOpCodeHandle (*EndOpCodeHandle);
409 }
410
411 return Status;
412 }
413
414 /**
415 This function converts the different format of address list to string format and
416 then generates the corresponding text opcode to illustarate the address info in
417 IP6 configuration page. Currently, the following formats are supported:
418 EFI_IP6_ADDRESS_INFO AddressType: Ip6ConfigNvHostAddress;
419 EFI_IPv6_ADDRESS AddressType: Ip6ConfigNvGatewayAddress and Ip6ConfigNvDnsAddress;
420 EFI_IP6_ROUTE_TABLE AddressType: Ip6ConfigNvRouteTable.
421
422 @param[in, out] String The pointer to the buffer to store the converted
423 string.
424 @param[in] HiiHandle A handle that was previously registered in the
425 HII Database.
426 @param[in] AddressType The address type.
427 @param[in] AddressInfo Pointer to the address list.
428 @param[in] AddressCount The address count of the address list.
429
430 @retval EFI_SUCCESS The operation finished successfully.
431 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
432 @retval EFI_UNSUPPORTED The AddressType is not supported.
433
434
435 **/
436 EFI_STATUS
437 Ip6ConvertAddressListToString (
438 IN OUT CHAR16 *String,
439 IN EFI_HII_HANDLE HiiHandle,
440 IN IP6_CONFIG_NV_ADDRESS_TYPE AddressType,
441 IN VOID *AddressInfo,
442 IN UINTN AddressCount
443 )
444 {
445 UINTN Index;
446 UINTN Number;
447 CHAR16 *TempStr;
448 EFI_STATUS Status;
449 VOID *StartOpCodeHandle;
450 EFI_IFR_GUID_LABEL *StartLabel;
451 VOID *EndOpCodeHandle;
452 EFI_IFR_GUID_LABEL *EndLabel;
453 UINT16 StartLabelNumber;
454 EFI_STRING_ID TextTwo;
455 UINT8 *AddressHead;
456 UINT8 PrefixLength;
457 EFI_IPv6_ADDRESS *Address;
458
459 if ((String == NULL) || (HiiHandle == NULL) || (AddressInfo == NULL)) {
460 return EFI_INVALID_PARAMETER;
461 }
462
463 if (AddressType == Ip6ConfigNvHostAddress) {
464 StartLabelNumber = HOST_ADDRESS_LABEL;
465 } else if (AddressType == Ip6ConfigNvGatewayAddress) {
466 StartLabelNumber = GATEWAY_ADDRESS_LABEL;
467 } else if (AddressType == Ip6ConfigNvDnsAddress) {
468 StartLabelNumber = DNS_ADDRESS_LABEL;
469 } else if (AddressType == Ip6ConfigNvRouteTable) {
470 StartLabelNumber = ROUTE_TABLE_LABEL;
471 } else {
472 ASSERT (FALSE);
473 return EFI_UNSUPPORTED;
474 }
475
476 Status = Ip6CreateOpCode (
477 StartLabelNumber,
478 &StartOpCodeHandle,
479 &StartLabel,
480 &EndOpCodeHandle,
481 &EndLabel
482 );
483 if (EFI_ERROR (Status)) {
484 return Status;
485 }
486
487 AddressHead = (UINT8 *) AddressInfo;
488
489 for (Index = 0; Index < AddressCount; Index++) {
490 if (AddressType == Ip6ConfigNvHostAddress) {
491 AddressInfo = AddressHead + sizeof (EFI_IP6_ADDRESS_INFO) * Index;
492 Address = &((EFI_IP6_ADDRESS_INFO *) AddressInfo)->Address;
493 } else if (AddressType == Ip6ConfigNvRouteTable) {
494 AddressInfo = AddressHead + sizeof (EFI_IP6_ROUTE_TABLE) * Index;
495 Address = &((EFI_IP6_ROUTE_TABLE *) AddressInfo)->Destination;
496 } else {
497 AddressInfo = AddressHead + sizeof (EFI_IPv6_ADDRESS) * Index;
498 Address = AddressInfo;
499 }
500
501 //
502 // Convert the IP address info to string.
503 //
504 Ip6ToStr (Address, String);
505 TempStr = String + StrLen (String);
506
507 if ((AddressType == Ip6ConfigNvHostAddress) || (AddressType == Ip6ConfigNvRouteTable)) {
508 if (AddressType == Ip6ConfigNvHostAddress) {
509 PrefixLength = ((EFI_IP6_ADDRESS_INFO *) AddressInfo)->PrefixLength;
510 } else {
511 PrefixLength = ((EFI_IP6_ROUTE_TABLE *) AddressInfo)->PrefixLength;
512 }
513
514 //
515 // Append the prefix length to the string.
516 //
517 *TempStr = L'/';
518 TempStr++;
519 Number = UnicodeSPrint (TempStr, 6, L"%d", PrefixLength);
520 TempStr = TempStr + Number;
521 }
522
523 if (AddressType == Ip6ConfigNvRouteTable) {
524 //
525 // Append " >> " to the string.
526 //
527 Number = UnicodeSPrint (TempStr, 8, L" >> ");
528 TempStr = TempStr + Number;
529
530 //
531 // Append the gateway address to the string.
532 //
533 Ip6ToStr (&((EFI_IP6_ROUTE_TABLE *) AddressInfo)->Gateway, TempStr);
534 TempStr = TempStr + StrLen (TempStr);
535 }
536
537 //
538 // Generate a text opcode and update the UI.
539 //
540 TextTwo = HiiSetString (HiiHandle, 0, String, NULL);
541 if (TextTwo == 0) {
542 Status = EFI_INVALID_PARAMETER;
543 goto Exit;
544 }
545
546 HiiCreateTextOpCode (StartOpCodeHandle, STR_NULL, STR_NULL, TextTwo);
547
548 String = TempStr;
549 *String = IP6_ADDRESS_DELIMITER;
550 String++;
551 }
552
553 *(String - 1) = '\0';
554
555 Status = HiiUpdateForm (
556 HiiHandle, // HII handle
557 &gIp6ConfigNvDataGuid, // Formset GUID
558 FORMID_MAIN_FORM, // Form ID
559 StartOpCodeHandle, // Label for where to insert opcodes
560 EndOpCodeHandle // Replace data
561 );
562
563 Exit:
564 HiiFreeOpCodeHandle (StartOpCodeHandle);
565 HiiFreeOpCodeHandle (EndOpCodeHandle);
566
567 return Status;
568 }
569
570 /**
571 Parse address list in string format and convert it to a list array of node in
572 IP6_ADDRESS_INFO_ENTRY.
573
574 @param[in] String The buffer to string to be parsed.
575 @param[out] ListHead The list head of array.
576 @param[out] AddressCount The number of list nodes in the array.
577
578 @retval EFI_SUCCESS The operation finished successfully.
579 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
580 @retval EFI_OUT_OF_RESOURCES Failed to perform the operation due to lack of resource.
581
582 **/
583 EFI_STATUS
584 Ip6ParseAddressListFromString (
585 IN CONST CHAR16 *String,
586 OUT LIST_ENTRY *ListHead,
587 OUT UINT32 *AddressCount
588 )
589 {
590 EFI_STATUS Status;
591 CHAR16 *LocalString;
592 CHAR16 *Temp;
593 CHAR16 *TempStr;
594 EFI_IP6_ADDRESS_INFO AddressInfo;
595 IP6_ADDRESS_INFO_ENTRY *Node;
596 BOOLEAN Last;
597 UINT32 Count;
598
599 if ((String == NULL) || (ListHead == NULL) || (AddressCount == NULL)) {
600 return EFI_INVALID_PARAMETER;
601 }
602
603 LocalString = (CHAR16 *) AllocateCopyPool (StrSize (String), String);
604 if (LocalString == NULL) {
605 return EFI_OUT_OF_RESOURCES;
606 }
607
608 //
609 // Clean the original address list.
610 //
611 Ip6FreeAddressInfoList (ListHead);
612
613 Temp = LocalString;
614 Last = FALSE;
615 Count = 0;
616
617 while (*LocalString != L'\0') {
618 TempStr = LocalString;
619 while ((*LocalString != L'\0') && (*LocalString != IP6_ADDRESS_DELIMITER)) {
620 LocalString++;
621 }
622
623 if (*LocalString == L'\0') {
624 Last = TRUE;
625 }
626
627 *LocalString = L'\0';
628
629 Status = NetLibStrToIp6andPrefix (TempStr, &AddressInfo.Address, &AddressInfo.PrefixLength);
630 if (EFI_ERROR (Status)) {
631 goto Error;
632 }
633
634 if (AddressInfo.PrefixLength == 0xFF) {
635 AddressInfo.PrefixLength = 0;
636 }
637
638 if (!NetIp6IsValidUnicast (&AddressInfo.Address)) {
639 Status = EFI_INVALID_PARAMETER;
640 goto Error;
641 }
642
643 Node = AllocatePool (sizeof (IP6_ADDRESS_INFO_ENTRY));
644 if (Node == NULL) {
645 Status = EFI_OUT_OF_RESOURCES;
646 goto Error;
647 }
648
649 CopyMem (&Node->AddrInfo, &AddressInfo, sizeof (EFI_IP6_ADDRESS_INFO));
650 InsertTailList (ListHead, &Node->Link);
651 Count++;
652
653 if (Last) {
654 break;
655 }
656
657 LocalString++;
658 }
659
660 FreePool (Temp);
661 *AddressCount = Count;
662 return EFI_SUCCESS;
663
664 Error:
665 Ip6FreeAddressInfoList (ListHead);
666 FreePool (Temp);
667 return Status;
668 }
669
670 /**
671 This function converts the interface info to string and draws it to the IP6 UI.
672 The interface information includes interface name, interface type, hardware
673 address and route table information.
674
675 @param[in] IfInfo The pointer of EFI_IP6_CONFIG_INTERFACE_INFO.
676 @param[in] HiiHandle The handle that was previously registered in the
677 HII Database.
678 @param[in, out] IfrNvData Points to IP6_CONFIG_IFR_NVDATA.
679
680 @retval EFI_SUCCESS The operation finished successfully.
681 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
682 @retval EFI_OUT_OF_RESOURCES The operation failed due to lack of resources.
683
684 **/
685 EFI_STATUS
686 Ip6ConvertInterfaceInfoToString (
687 IN EFI_IP6_CONFIG_INTERFACE_INFO *IfInfo,
688 IN EFI_HII_HANDLE HiiHandle,
689 IN OUT IP6_CONFIG_IFR_NVDATA *IfrNvData
690 )
691 {
692 UINT32 Index;
693 UINTN Number;
694 CHAR16 *String;
695 CHAR16 PortString[ADDRESS_STR_MAX_SIZE];
696 CHAR16 FormatString[8];
697 EFI_STRING_ID StringId;
698 EFI_STATUS Status;
699
700 if ((IfInfo == NULL) || (HiiHandle == NULL) || (IfrNvData == NULL)) {
701 return EFI_INVALID_PARAMETER;
702 }
703
704 //
705 // Print the interface name.
706 //
707 StringId = HiiSetString (
708 HiiHandle,
709 STRING_TOKEN (STR_IP6_INTERFACE_NAME_CONTENT),
710 IfInfo->Name,
711 NULL
712 );
713 if (StringId == 0) {
714 return EFI_OUT_OF_RESOURCES;
715 }
716
717 //
718 // Print the interface type.
719 //
720 if (IfInfo->IfType == Ip6InterfaceTypeEthernet) {
721 StrCpy (PortString, IP6_ETHERNET);
722 } else if (IfInfo->IfType == Ip6InterfaceTypeExperimentalEthernet) {
723 StrCpy (PortString, IP6_EXPERIMENTAL_ETHERNET);
724 } else {
725 //
726 // Refer to RFC1700, chapter Number Hardware Type.
727 //
728 UnicodeSPrint (PortString, 6, L"%d", IfInfo->IfType);
729 }
730
731 StringId = HiiSetString (
732 HiiHandle,
733 STRING_TOKEN (STR_IP6_INTERFACE_TYPE_CONTENT),
734 PortString,
735 NULL
736 );
737 if (StringId == 0) {
738 return EFI_OUT_OF_RESOURCES;
739 }
740
741 //
742 // Convert the hardware address.
743 //
744 String = PortString;
745 ASSERT (IfInfo->HwAddressSize <= 32);
746
747 for (Index = 0; Index < IfInfo->HwAddressSize; Index++) {
748
749 if (IfInfo->HwAddress.Addr[Index] < 0x10) {
750 StrCpy (FormatString, L"0%x-");
751 } else {
752 StrCpy (FormatString, L"%x-");
753 }
754
755 Number = UnicodeSPrint (
756 String,
757 8,
758 (CONST CHAR16 *) FormatString,
759 (UINTN) IfInfo->HwAddress.Addr[Index]
760 );
761 String = String + Number;
762 }
763
764 if (Index != 0) {
765 ASSERT (String > PortString);
766 String--;
767 *String = '\0';
768 }
769
770 //
771 // Print the hardware address.
772 //
773 StringId = HiiSetString (
774 HiiHandle,
775 STRING_TOKEN (STR_IP6_MAC_ADDRESS_CONTENT),
776 PortString,
777 NULL
778 );
779 if (StringId == 0) {
780 return EFI_OUT_OF_RESOURCES;
781 }
782
783 //
784 // Print the route table information.
785 //
786 Status = Ip6ConvertAddressListToString (
787 PortString,
788 HiiHandle,
789 Ip6ConfigNvRouteTable,
790 IfInfo->RouteTable,
791 IfInfo->RouteCount
792 );
793 return Status;
794 }
795
796 /**
797 Build the address info list from list array of node in IP6_ADDRESS_INFO_ENTRY.
798
799 @param[in] Instance Points to IP6 config instance data.
800 @param[in] AddressType The address type.
801 @param[out] AddressInfo The pointer to the buffer to store the address list.
802 @param[out] AddressSize The address size of the address list.
803
804 @retval EFI_SUCCESS The operation finished successfully.
805 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
806 @retval EFI_UNSUPPORTED The AddressType is not supported.
807
808 **/
809 EFI_STATUS
810 Ip6BuildNvAddressInfo (
811 IN IP6_CONFIG_INSTANCE *Instance,
812 IN IP6_CONFIG_NV_ADDRESS_TYPE AddressType,
813 OUT VOID **AddressInfo,
814 OUT UINTN *AddressSize
815 )
816 {
817 IP6_CONFIG_NVDATA *Ip6NvData;
818 LIST_ENTRY *Entry;
819 LIST_ENTRY *ListHead;
820 IP6_ADDRESS_INFO_ENTRY *Node;
821 VOID *AddressList;
822 VOID *TmpStr;
823 UINTN DataSize;
824 EFI_IPv6_ADDRESS *Ip6Address;
825 EFI_IP6_CONFIG_MANUAL_ADDRESS *ManualAddress;
826
827 if ((Instance == NULL) || (AddressInfo == NULL) || (AddressSize == NULL)) {
828 return EFI_INVALID_PARAMETER;
829 }
830
831 NET_CHECK_SIGNATURE (Instance, IP6_CONFIG_INSTANCE_SIGNATURE);
832
833 Ip6NvData = &Instance->Ip6NvData;
834
835 if (AddressType == Ip6ConfigNvHostAddress) {
836 ListHead = &Ip6NvData->ManualAddress;
837 DataSize = sizeof (EFI_IP6_CONFIG_MANUAL_ADDRESS) * Ip6NvData->ManualAddressCount;
838 } else if (AddressType == Ip6ConfigNvGatewayAddress) {
839 ListHead = &Ip6NvData->GatewayAddress;
840 DataSize = sizeof (EFI_IPv6_ADDRESS) * Ip6NvData->GatewayAddressCount;
841 } else if (AddressType == Ip6ConfigNvDnsAddress) {
842 ListHead = &Ip6NvData->DnsAddress;
843 DataSize = sizeof (EFI_IPv6_ADDRESS) * Ip6NvData->DnsAddressCount;
844 } else {
845 return EFI_UNSUPPORTED;
846 }
847
848 AddressList = AllocateZeroPool (DataSize);
849 if (AddressList == NULL) {
850 return EFI_OUT_OF_RESOURCES;
851 }
852
853 TmpStr = AddressList;
854
855 NET_LIST_FOR_EACH (Entry, ListHead) {
856 Node = NET_LIST_USER_STRUCT (Entry, IP6_ADDRESS_INFO_ENTRY, Link);
857 if (AddressType == Ip6ConfigNvHostAddress) {
858 ManualAddress = (EFI_IP6_CONFIG_MANUAL_ADDRESS *) AddressList;
859 IP6_COPY_ADDRESS (&ManualAddress->Address, &Node->AddrInfo.Address);
860 ManualAddress->PrefixLength = Node->AddrInfo.PrefixLength;
861 AddressList = (UINT8 *) AddressList + sizeof (EFI_IP6_CONFIG_MANUAL_ADDRESS);
862 } else {
863 Ip6Address = (EFI_IPv6_ADDRESS *) AddressList;
864 IP6_COPY_ADDRESS (Ip6Address, &Node->AddrInfo.Address);
865 AddressList = (UINT8 *) AddressList + sizeof (EFI_IPv6_ADDRESS);
866 }
867 }
868
869 *AddressInfo = TmpStr;
870 *AddressSize = DataSize;
871 return EFI_SUCCESS;
872 }
873
874 /**
875 Convert the IP6 configuration data into the IFR data.
876
877 @param[in, out] IfrNvData The IFR NV data.
878 @param[in] Instance The IP6 config instance data.
879
880 @retval EFI_SUCCESS The operation finished successfully.
881 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
882 @retval EFI_UNSUPPORTED The policy is not supported in the current implementation.
883 @retval Others Other errors as indicated.
884
885 **/
886 EFI_STATUS
887 Ip6ConvertConfigNvDataToIfrNvData (
888 IN OUT IP6_CONFIG_IFR_NVDATA *IfrNvData,
889 IN IP6_CONFIG_INSTANCE *Instance
890 )
891 {
892 IP6_CONFIG_NVDATA *Ip6NvData;
893 EFI_IP6_CONFIG_PROTOCOL *Ip6Config;
894 UINTN DataSize;
895 VOID *Data;
896 EFI_STATUS Status;
897 EFI_IP6_CONFIG_POLICY Policy;
898 EFI_IP6_CONFIG_DUP_ADDR_DETECT_TRANSMITS DadXmits;
899 EFI_HII_HANDLE HiiHandle;
900
901 if ((IfrNvData == NULL) || (Instance == NULL)) {
902 return EFI_INVALID_PARAMETER;
903 }
904
905 NET_CHECK_SIGNATURE (Instance, IP6_CONFIG_INSTANCE_SIGNATURE);
906
907 Ip6Config = &Instance->Ip6Config;
908 Ip6NvData = &Instance->Ip6NvData;
909 Data = NULL;
910 DataSize = 0;
911 HiiHandle = Instance->CallbackInfo.RegisteredHandle;
912
913 //
914 // Get the current interface info.
915 //
916 Status = Ip6ConfigNvGetData (
917 Ip6Config,
918 Ip6ConfigDataTypeInterfaceInfo,
919 &DataSize,
920 (VOID **) &Data
921 );
922 if (EFI_ERROR (Status)) {
923 goto Exit;
924 }
925
926 //
927 // Convert the interface info to string and print.
928 //
929 Status = Ip6ConvertInterfaceInfoToString (
930 (EFI_IP6_CONFIG_INTERFACE_INFO *) Data,
931 HiiHandle,
932 IfrNvData
933 );
934 if (EFI_ERROR (Status)) {
935 goto Exit;
936 }
937
938 //
939 // Get the interface id.
940 //
941 DataSize = sizeof (EFI_IP6_CONFIG_INTERFACE_ID);
942 ZeroMem (&Ip6NvData->InterfaceId, DataSize);
943 Status = Ip6Config->GetData (
944 Ip6Config,
945 Ip6ConfigDataTypeAltInterfaceId,
946 &DataSize,
947 &Ip6NvData->InterfaceId
948 );
949 if (EFI_ERROR (Status)) {
950 goto Exit;
951 }
952
953 Ip6ConvertInterfaceIdToString (IfrNvData->InterfaceId, &Ip6NvData->InterfaceId);
954
955 //
956 // Get current policy.
957 //
958 DataSize = sizeof (EFI_IP6_CONFIG_POLICY);
959 Status = Ip6Config->GetData (
960 Ip6Config,
961 Ip6ConfigDataTypePolicy,
962 &DataSize,
963 &Policy
964 );
965
966 if (EFI_ERROR (Status)) {
967 goto Exit;
968 }
969
970 if (Policy == Ip6ConfigPolicyManual) {
971 IfrNvData->Policy = IP6_POLICY_MANUAL;
972 } else if (Policy == Ip6ConfigPolicyAutomatic) {
973 IfrNvData->Policy = IP6_POLICY_AUTO;
974 } else {
975 ASSERT (FALSE);
976 Status = EFI_UNSUPPORTED;
977 goto Exit;
978 }
979
980 //
981 // Get Duplicate Address Detection Transmits count.
982 //
983 DataSize = sizeof (EFI_IP6_CONFIG_DUP_ADDR_DETECT_TRANSMITS);
984 Status = Ip6Config->GetData (
985 Ip6Config,
986 Ip6ConfigDataTypeDupAddrDetectTransmits,
987 &DataSize,
988 &DadXmits
989 );
990
991 if (EFI_ERROR (Status)) {
992 goto Exit;
993 }
994
995 IfrNvData->DadTransmitCount = DadXmits.DupAddrDetectTransmits;
996
997 Exit:
998 if (Data != NULL) {
999 FreePool (Data);
1000 }
1001
1002 return Status;
1003 }
1004
1005 /**
1006 Convert IFR data into IP6 configuration data. The policy, alternative interface
1007 ID, and DAD transmit counts, and will be saved.
1008
1009 @param[in] IfrNvData The IFR NV data.
1010 @param[in, out] Instance The IP6 config instance data.
1011
1012 @retval EFI_SUCCESS The operation finished successfully.
1013 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
1014 @retval Others Other errors as indicated.
1015
1016 **/
1017 EFI_STATUS
1018 Ip6ConvertIfrNvDataToConfigNvDataGeneral (
1019 IN IP6_CONFIG_IFR_NVDATA *IfrNvData,
1020 IN OUT IP6_CONFIG_INSTANCE *Instance
1021 )
1022 {
1023 IP6_CONFIG_NVDATA *Ip6NvData;
1024 EFI_IP6_CONFIG_PROTOCOL *Ip6Config;
1025 EFI_STATUS Status;
1026
1027 if ((IfrNvData == NULL) || (Instance == NULL)) {
1028 return EFI_INVALID_PARAMETER;
1029 }
1030
1031 NET_CHECK_SIGNATURE (Instance, IP6_CONFIG_INSTANCE_SIGNATURE);
1032 Ip6NvData = &Instance->Ip6NvData;
1033 Ip6Config = &Instance->Ip6Config;
1034
1035 //
1036 // Update those fields which don't have INTERACTIVE attribute.
1037 //
1038 if (IfrNvData->Policy == IP6_POLICY_AUTO) {
1039 Ip6NvData->Policy = Ip6ConfigPolicyAutomatic;
1040 } else if (IfrNvData->Policy == IP6_POLICY_MANUAL) {
1041 Ip6NvData->Policy = Ip6ConfigPolicyManual;
1042 }
1043
1044 Ip6NvData->DadTransmitCount.DupAddrDetectTransmits = IfrNvData->DadTransmitCount;
1045
1046 //
1047 // Set the configured policy.
1048 //
1049 Status = Ip6Config->SetData (
1050 Ip6Config,
1051 Ip6ConfigDataTypePolicy,
1052 sizeof (EFI_IP6_CONFIG_POLICY),
1053 &Ip6NvData->Policy
1054 );
1055 if (EFI_ERROR (Status)) {
1056 return Status;
1057 }
1058
1059 //
1060 // Set the duplicate address detection transmits count.
1061 //
1062 Status = Ip6Config->SetData (
1063 Ip6Config,
1064 Ip6ConfigDataTypeDupAddrDetectTransmits,
1065 sizeof (EFI_IP6_CONFIG_DUP_ADDR_DETECT_TRANSMITS),
1066 &Ip6NvData->DadTransmitCount
1067 );
1068 if (EFI_ERROR (Status)) {
1069 return Status;
1070 }
1071
1072 //
1073 // Set the alternative interface ID
1074 //
1075 Status = Ip6Config->SetData (
1076 Ip6Config,
1077 Ip6ConfigDataTypeAltInterfaceId,
1078 sizeof (EFI_IP6_CONFIG_INTERFACE_ID),
1079 &Ip6NvData->InterfaceId
1080 );
1081 if (EFI_ERROR (Status)) {
1082 return Status;
1083 }
1084
1085 return EFI_SUCCESS;
1086 }
1087
1088 /**
1089 Convert IFR data into IP6 configuration data. The policy, configured
1090 manual address, gateway address, and DNS server address will be saved.
1091
1092 @param[in] IfrNvData The IFR NV data.
1093 @param[in, out] Instance The IP6 config instance data.
1094
1095 @retval EFI_SUCCESS The operation finished successfully.
1096 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
1097 @retval Others Other errors as indicated.
1098
1099 **/
1100 EFI_STATUS
1101 Ip6ConvertIfrNvDataToConfigNvDataAdvanced (
1102 IN IP6_CONFIG_IFR_NVDATA *IfrNvData,
1103 IN OUT IP6_CONFIG_INSTANCE *Instance
1104 )
1105 {
1106 IP6_CONFIG_NVDATA *Ip6NvData;
1107 EFI_IP6_CONFIG_PROTOCOL *Ip6Config;
1108 EFI_STATUS Status;
1109 EFI_IP6_CONFIG_MANUAL_ADDRESS *ManualAddress;
1110 EFI_IPv6_ADDRESS *Address;
1111 BOOLEAN IsAddressOk;
1112 EFI_EVENT SetAddressEvent;
1113 EFI_EVENT TimeoutEvent;
1114 UINTN DataSize;
1115
1116 if ((IfrNvData == NULL) || (Instance == NULL)) {
1117 return EFI_INVALID_PARAMETER;
1118 }
1119
1120 if (IfrNvData->Policy == IP6_POLICY_AUTO) {
1121 return EFI_SUCCESS;
1122 }
1123
1124 NET_CHECK_SIGNATURE (Instance, IP6_CONFIG_INSTANCE_SIGNATURE);
1125 Ip6NvData = &Instance->Ip6NvData;
1126 Ip6Config = &Instance->Ip6Config;
1127
1128 //
1129 // Update those fields which don't have INTERACTIVE attribute.
1130 //
1131 Ip6NvData->Policy = Ip6ConfigPolicyManual;
1132
1133 //
1134 // Set the configured policy.
1135 //
1136 Status = Ip6Config->SetData (
1137 Ip6Config,
1138 Ip6ConfigDataTypePolicy,
1139 sizeof (EFI_IP6_CONFIG_POLICY),
1140 &Ip6NvData->Policy
1141 );
1142 if (EFI_ERROR (Status)) {
1143 return Status;
1144 }
1145
1146 //
1147 // Create events & timers for asynchronous settings.
1148 //
1149 SetAddressEvent = NULL;
1150 TimeoutEvent = NULL;
1151 ManualAddress = NULL;
1152 Address = NULL;
1153
1154 Status = gBS->CreateEvent (
1155 EVT_NOTIFY_SIGNAL,
1156 TPL_NOTIFY,
1157 Ip6ConfigManualAddressNotify,
1158 &IsAddressOk,
1159 &SetAddressEvent
1160 );
1161 if (EFI_ERROR (Status)) {
1162 goto Exit;
1163 }
1164
1165 Status = gBS->CreateEvent (
1166 EVT_TIMER,
1167 TPL_CALLBACK,
1168 NULL,
1169 NULL,
1170 &TimeoutEvent
1171 );
1172 if (EFI_ERROR (Status)) {
1173 goto Exit;
1174 }
1175
1176 //
1177 // Set the manual address list. This is an asynchronous process.
1178 //
1179 if (!IsListEmpty (&Ip6NvData->ManualAddress) && (Ip6NvData->ManualAddressCount != 0)) {
1180 Status = Ip6BuildNvAddressInfo (
1181 Instance,
1182 Ip6ConfigNvHostAddress,
1183 (VOID **) &ManualAddress,
1184 &DataSize
1185 );
1186 if (EFI_ERROR (Status)) {
1187 goto Exit;
1188 }
1189
1190 IsAddressOk = FALSE;
1191
1192 Status = Ip6Config->RegisterDataNotify (
1193 Ip6Config,
1194 Ip6ConfigDataTypeManualAddress,
1195 SetAddressEvent
1196 );
1197 if (EFI_ERROR (Status)) {
1198 goto Exit;
1199 }
1200
1201 Status = Ip6Config->SetData (
1202 Ip6Config,
1203 Ip6ConfigDataTypeManualAddress,
1204 DataSize,
1205 (VOID *) ManualAddress
1206 );
1207 if (Status == EFI_NOT_READY) {
1208 gBS->SetTimer (TimeoutEvent, TimerRelative, 50000000);
1209 while (EFI_ERROR (gBS->CheckEvent (TimeoutEvent))) {
1210 if (IsAddressOk) {
1211 Status = EFI_SUCCESS;
1212 }
1213 break;
1214 }
1215 }
1216
1217 Status = Ip6Config->UnregisterDataNotify (
1218 Ip6Config,
1219 Ip6ConfigDataTypeManualAddress,
1220 SetAddressEvent
1221 );
1222 if (EFI_ERROR (Status)) {
1223 goto Exit;
1224 }
1225 }
1226
1227 //
1228 // Set gateway address list.
1229 //
1230 if (!IsListEmpty (&Ip6NvData->GatewayAddress) && (Ip6NvData->GatewayAddressCount != 0)) {
1231 Status = Ip6BuildNvAddressInfo (
1232 Instance,
1233 Ip6ConfigNvGatewayAddress,
1234 (VOID **) &Address,
1235 &DataSize
1236 );
1237 if (EFI_ERROR (Status)) {
1238 goto Exit;
1239 }
1240
1241 Status = Ip6Config->SetData (
1242 Ip6Config,
1243 Ip6ConfigDataTypeGateway,
1244 DataSize,
1245 (VOID *) Address
1246 );
1247 if (EFI_ERROR (Status)) {
1248 goto Exit;
1249 }
1250
1251 FreePool (Address);
1252 Address = NULL;
1253 }
1254
1255 //
1256 // Set DNS server address list.
1257 //
1258 if (!IsListEmpty (&Ip6NvData->DnsAddress) && (Ip6NvData->DnsAddressCount != 0)) {
1259 Status = Ip6BuildNvAddressInfo (
1260 Instance,
1261 Ip6ConfigNvDnsAddress,
1262 (VOID **) &Address,
1263 &DataSize
1264 );
1265 if (EFI_ERROR (Status)) {
1266 goto Exit;
1267 }
1268
1269 Status = Ip6Config->SetData (
1270 Ip6Config,
1271 Ip6ConfigDataTypeDnsServer,
1272 DataSize,
1273 (VOID *) Address
1274 );
1275 if (EFI_ERROR (Status)) {
1276 goto Exit;
1277 }
1278 }
1279
1280 Status = EFI_SUCCESS;
1281
1282 Exit:
1283 if (SetAddressEvent != NULL) {
1284 gBS->CloseEvent (SetAddressEvent);
1285 }
1286
1287 if (TimeoutEvent != NULL) {
1288 gBS->CloseEvent (TimeoutEvent);
1289 }
1290
1291 if (ManualAddress != NULL) {
1292 FreePool (ManualAddress);
1293 }
1294
1295 if (Address != NULL) {
1296 FreePool (Address);
1297 }
1298
1299 return Status;
1300 }
1301
1302
1303 /**
1304 This function allows the caller to request the current
1305 configuration for one or more named elements. The resulting
1306 string is in <ConfigAltResp> format. Any and all alternative
1307 configuration strings shall also be appended to the end of the
1308 current configuration string. If they are, they must appear
1309 after the current configuration. They must contain the same
1310 routing (GUID, NAME, PATH) as the current configuration string.
1311 They must have an additional description indicating the type of
1312 alternative configuration the string represents,
1313 "ALTCFG=<StringToken>". That <StringToken> (when
1314 converted from Hex UNICODE to binary) is a reference to a
1315 string in the associated string pack.
1316
1317 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
1318 @param[in] Request A null-terminated Unicode string in
1319 <ConfigRequest> format. Note that this
1320 includes the routing information as well as
1321 the configurable name / value pairs. It is
1322 invalid for this string to be in
1323 <MultiConfigRequest> format.
1324 @param[out] Progress On return, points to a character in the
1325 Request string. Points to the string's null
1326 terminator if request was successful. Points
1327 to the most recent "&" before the first
1328 failing name / value pair (or the beginning
1329 of the string if the failure is in the first
1330 name / value pair) if the request was not
1331 successful.
1332 @param[out] Results A null-terminated Unicode string in
1333 <ConfigAltResp> format which has all values
1334 filled in for the names in the Request string.
1335 String to be allocated by the called function.
1336
1337 @retval EFI_SUCCESS The Results string is filled with the
1338 values corresponding to all requested
1339 names.
1340 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the
1341 parts of the results that must be
1342 stored awaiting possible future
1343 protocols.
1344 @retval EFI_INVALID_PARAMETER For example, passing in a NULL
1345 for the Request parameter
1346 would result in this type of
1347 error. In this case, the
1348 Progress parameter would be
1349 set to NULL.
1350 @retval EFI_NOT_FOUND Routing data doesn't match any
1351 known driver. Progress set to the
1352 first character in the routing header.
1353 Note: There is no requirement that the
1354 driver validate the routing data. It
1355 must skip the <ConfigHdr> in order to
1356 process the names.
1357 @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set
1358 to most recent & before the
1359 error or the beginning of the
1360 string.
1361 @retval EFI_INVALID_PARAMETER Unknown name. Progress points
1362 to the & before the name in
1363 question. Currently not implemented.
1364 **/
1365 EFI_STATUS
1366 EFIAPI
1367 Ip6FormExtractConfig (
1368 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
1369 IN CONST EFI_STRING Request,
1370 OUT EFI_STRING *Progress,
1371 OUT EFI_STRING *Results
1372 )
1373 {
1374
1375 EFI_STATUS Status;
1376 IP6_FORM_CALLBACK_INFO *Private;
1377 IP6_CONFIG_INSTANCE *Ip6ConfigInstance;
1378 IP6_CONFIG_IFR_NVDATA *IfrNvData;
1379 EFI_STRING ConfigRequestHdr;
1380 EFI_STRING ConfigRequest;
1381 BOOLEAN AllocatedRequest;
1382 UINTN Size;
1383 UINTN BufferSize;
1384
1385 if (This == NULL || Progress == NULL || Results == NULL) {
1386 return EFI_INVALID_PARAMETER;
1387 }
1388
1389 *Progress = Request;
1390 if ((Request != NULL) &&
1391 !HiiIsConfigHdrMatch (Request, &gIp6ConfigNvDataGuid, mIp6ConfigStorageName)) {
1392 return EFI_NOT_FOUND;
1393 }
1394
1395 ConfigRequestHdr = NULL;
1396 ConfigRequest = NULL;
1397 AllocatedRequest = FALSE;
1398 Size = 0;
1399
1400 Private = IP6_FORM_CALLBACK_INFO_FROM_CONFIG_ACCESS (This);
1401 Ip6ConfigInstance = IP6_CONFIG_INSTANCE_FROM_FORM_CALLBACK (Private);
1402 BufferSize = sizeof (IP6_CONFIG_IFR_NVDATA);
1403
1404 IfrNvData = (IP6_CONFIG_IFR_NVDATA *) AllocateZeroPool (BufferSize);
1405 if (IfrNvData == NULL) {
1406 return EFI_OUT_OF_RESOURCES;
1407 }
1408
1409 Status = Ip6ConvertConfigNvDataToIfrNvData (IfrNvData, Ip6ConfigInstance);
1410 if (EFI_ERROR (Status)) {
1411 goto Exit;
1412 }
1413
1414 ConfigRequest = Request;
1415 if ((Request == NULL) || (StrStr (Request, L"OFFSET") == NULL)) {
1416 //
1417 // Request has no request element, construct full request string.
1418 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
1419 // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator.
1420 //
1421 ConfigRequestHdr = HiiConstructConfigHdr (
1422 &gIp6ConfigNvDataGuid,
1423 mIp6ConfigStorageName,
1424 Private->ChildHandle
1425 );
1426 Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16);
1427 ConfigRequest = AllocateZeroPool (Size);
1428 ASSERT (ConfigRequest != NULL);
1429 AllocatedRequest = TRUE;
1430 UnicodeSPrint (
1431 ConfigRequest,
1432 Size,
1433 L"%s&OFFSET=0&WIDTH=%016LX",
1434 ConfigRequestHdr,
1435 (UINT64) BufferSize
1436 );
1437 FreePool (ConfigRequestHdr);
1438 }
1439
1440 //
1441 // Convert buffer data to <ConfigResp> by helper function BlockToConfig()
1442 //
1443 Status = gHiiConfigRouting->BlockToConfig (
1444 gHiiConfigRouting,
1445 ConfigRequest,
1446 (UINT8 *) IfrNvData,
1447 BufferSize,
1448 Results,
1449 Progress
1450 );
1451
1452 Exit:
1453 FreePool (IfrNvData);
1454 //
1455 // Free the allocated config request string.
1456 //
1457 if (AllocatedRequest) {
1458 FreePool (ConfigRequest);
1459 ConfigRequest = NULL;
1460 }
1461 //
1462 // Set Progress string to the original request string.
1463 //
1464 if (Request == NULL) {
1465 *Progress = NULL;
1466 } else if (StrStr (Request, L"OFFSET") == NULL) {
1467 *Progress = Request + StrLen (Request);
1468 }
1469
1470 return Status;
1471 }
1472
1473 /**
1474 This function applies changes in a driver's configuration.
1475 Input is a Configuration, which has the routing data for this
1476 driver followed by name / value configuration pairs. The driver
1477 must apply those pairs to its configurable storage. If the
1478 driver's configuration is stored in a linear block of data
1479 and the driver's name / value pairs are in <BlockConfig>
1480 format, it may use the ConfigToBlock helper function (above) to
1481 simplify the job. Currently not implemented.
1482
1483 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
1484 @param[in] Configuration A null-terminated Unicode string in
1485 <ConfigString> format.
1486 @param[out] Progress A pointer to a string filled in with the
1487 offset of the most recent '&' before the
1488 first failing name / value pair (or the
1489 beginn ing of the string if the failure
1490 is in the first name / value pair) or
1491 the terminating NULL if all was
1492 successful.
1493
1494 @retval EFI_SUCCESS The results have been distributed or are
1495 awaiting distribution.
1496 @retval EFI_OUT_OF_MEMORY Not enough memory to store the
1497 parts of the results that must be
1498 stored awaiting possible future
1499 protocols.
1500 @retval EFI_INVALID_PARAMETERS Passing in a NULL for the
1501 Results parameter would result
1502 in this type of error.
1503 @retval EFI_NOT_FOUND Target for the specified routing data
1504 was not found.
1505 **/
1506 EFI_STATUS
1507 EFIAPI
1508 Ip6FormRouteConfig (
1509 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
1510 IN CONST EFI_STRING Configuration,
1511 OUT EFI_STRING *Progress
1512 )
1513 {
1514 if (This == NULL || Configuration == NULL || Progress == NULL) {
1515 return EFI_INVALID_PARAMETER;
1516 }
1517
1518 //
1519 // Check routing data in <ConfigHdr>.
1520 // Note: if only one Storage is used, then this checking could be skipped.
1521 //
1522 if (!HiiIsConfigHdrMatch (Configuration, &gIp6ConfigNvDataGuid, mIp6ConfigStorageName)) {
1523 *Progress = Configuration;
1524 return EFI_NOT_FOUND;
1525 }
1526
1527 *Progress = Configuration + StrLen (Configuration);
1528
1529 return EFI_SUCCESS;
1530 }
1531
1532 /**
1533 Display host addresses, route table, DNS addresses and gateway addresses in
1534 "IPv6 Current Setting" page.
1535
1536 @param[in] Instance The IP6 config instance data.
1537
1538 @retval EFI_SUCCESS The operation finished successfully.
1539 @retval Others Other errors as indicated.
1540
1541 **/
1542 EFI_STATUS
1543 Ip6GetCurrentSetting (
1544 IN IP6_CONFIG_INSTANCE *Instance
1545 )
1546 {
1547 EFI_IP6_CONFIG_PROTOCOL *Ip6Config;
1548 EFI_HII_HANDLE HiiHandle;
1549 EFI_IP6_CONFIG_INTERFACE_INFO *Data;
1550 UINTN DataSize;
1551 EFI_STATUS Status;
1552 CHAR16 PortString[ADDRESS_STR_MAX_SIZE];
1553 EFI_IP6_CONFIG_INTERFACE_INFO *IfInfo;
1554
1555
1556 Ip6Config = &Instance->Ip6Config;
1557 HiiHandle = Instance->CallbackInfo.RegisteredHandle;
1558 Data = NULL;
1559
1560 //
1561 // Get current interface info.
1562 //
1563 Status = Ip6ConfigNvGetData (
1564 Ip6Config,
1565 Ip6ConfigDataTypeInterfaceInfo,
1566 &DataSize,
1567 (VOID **) &Data
1568 );
1569 if (EFI_ERROR (Status)) {
1570 return Status;
1571 }
1572
1573 //
1574 // Generate dynamic text opcode for host address and draw it.
1575 //
1576 IfInfo = (EFI_IP6_CONFIG_INTERFACE_INFO *) Data;
1577 Status = Ip6ConvertAddressListToString (
1578 PortString,
1579 HiiHandle,
1580 Ip6ConfigNvHostAddress,
1581 IfInfo->AddressInfo,
1582 IfInfo->AddressInfoCount
1583 );
1584 if (EFI_ERROR (Status)) {
1585 FreePool (Data);
1586 return Status;
1587 }
1588
1589 //
1590 // Generate the dynamic text opcode for route table and draw it.
1591 //
1592 Status = Ip6ConvertAddressListToString (
1593 PortString,
1594 HiiHandle,
1595 Ip6ConfigNvRouteTable,
1596 IfInfo->RouteTable,
1597 IfInfo->RouteCount
1598 );
1599 if (EFI_ERROR (Status)) {
1600 FreePool (Data);
1601 return Status;
1602 }
1603
1604 //
1605 // Get DNS server list.
1606 //
1607 FreePool (Data);
1608 DataSize = 0;
1609 Data = NULL;
1610 Status = Ip6ConfigNvGetData (
1611 Ip6Config,
1612 Ip6ConfigDataTypeDnsServer,
1613 &DataSize,
1614 (VOID **) &Data
1615 );
1616 if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
1617 if (Data != NULL) {
1618 FreePool (Data);
1619 }
1620 return Status;
1621 }
1622
1623 if (DataSize > 0) {
1624 //
1625 // Generate the dynamic text opcode for DNS server and draw it.
1626 //
1627 Status = Ip6ConvertAddressListToString (
1628 PortString,
1629 HiiHandle,
1630 Ip6ConfigNvDnsAddress,
1631 Data,
1632 DataSize / sizeof (EFI_IPv6_ADDRESS)
1633 );
1634 if (EFI_ERROR (Status)) {
1635 FreePool (Data);
1636 return Status;
1637 }
1638 }
1639
1640 //
1641 // Get gateway adderss list.
1642 //
1643 if (Data != NULL) {
1644 FreePool (Data);
1645 }
1646
1647 DataSize = 0;
1648 Data = NULL;
1649 Status = Ip6ConfigNvGetData (
1650 Ip6Config,
1651 Ip6ConfigDataTypeGateway,
1652 &DataSize,
1653 (VOID **) &Data
1654 );
1655 if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
1656 if (Data != NULL) {
1657 FreePool (Data);
1658 }
1659 return Status;
1660 }
1661
1662 if (DataSize > 0) {
1663 //
1664 // Generate the dynamic text opcode for gateway and draw it.
1665 //
1666 Status = Ip6ConvertAddressListToString (
1667 PortString,
1668 HiiHandle,
1669 Ip6ConfigNvGatewayAddress,
1670 Data,
1671 DataSize / sizeof (EFI_IPv6_ADDRESS)
1672 );
1673 if (EFI_ERROR (Status)) {
1674 FreePool (Data);
1675 return Status;
1676 }
1677 }
1678
1679 if (Data != NULL) {
1680 FreePool (Data);
1681 }
1682
1683 return EFI_SUCCESS;
1684 }
1685
1686 /**
1687 This function is called to provide results data to the driver.
1688 This data consists of a unique key that is used to identify
1689 which data is either being passed back or being asked for.
1690
1691 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
1692 @param[in] Action Specifies the type of action taken by the browser.
1693 @param[in] QuestionId A unique value which is sent to the original
1694 exporting driver so that it can identify the type
1695 of data to expect. The format of the data tends to
1696 vary based on the opcode that generated the callback.
1697 @param[in] Type The type of value for the question.
1698 @param[in] Value A pointer to the data being sent to the original
1699 exporting driver.
1700 @param[out] ActionRequest On return, points to the action requested by the
1701 callback function.
1702
1703 @retval EFI_SUCCESS The callback successfully handled the action.
1704 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the
1705 variable and its data.
1706 @retval EFI_DEVICE_ERROR The variable could not be saved.
1707 @retval EFI_UNSUPPORTED The specified Action is not supported by the
1708 callback. Currently not implemented.
1709 @retval EFI_INVALID_PARAMETER Passed in the wrong parameter.
1710 @retval Others Other errors as indicated.
1711
1712 **/
1713 EFI_STATUS
1714 EFIAPI
1715 Ip6FormCallback (
1716 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
1717 IN EFI_BROWSER_ACTION Action,
1718 IN EFI_QUESTION_ID QuestionId,
1719 IN UINT8 Type,
1720 IN EFI_IFR_TYPE_VALUE *Value,
1721 OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest
1722 )
1723 {
1724 IP6_FORM_CALLBACK_INFO *Private;
1725 UINTN BufferSize;
1726 IP6_CONFIG_IFR_NVDATA *IfrNvData;
1727 EFI_STATUS Status;
1728 EFI_INPUT_KEY Key;
1729 IP6_CONFIG_INSTANCE *Instance;
1730 IP6_CONFIG_NVDATA *Ip6NvData;
1731
1732 if (This == NULL) {
1733 return EFI_INVALID_PARAMETER;
1734 }
1735
1736 Private = IP6_FORM_CALLBACK_INFO_FROM_CONFIG_ACCESS (This);
1737 Instance = IP6_CONFIG_INSTANCE_FROM_FORM_CALLBACK (Private);
1738 Ip6NvData = &Instance->Ip6NvData;
1739
1740 if ((Action == EFI_BROWSER_ACTION_FORM_OPEN) || (Action == EFI_BROWSER_ACTION_FORM_CLOSE)){
1741 return EFI_SUCCESS;
1742 }
1743
1744 if (Action != EFI_BROWSER_ACTION_CHANGING && Action != EFI_BROWSER_ACTION_CHANGED) {
1745 return EFI_UNSUPPORTED;
1746 }
1747
1748 if ((Value == NULL) || (ActionRequest == NULL)) {
1749 return EFI_INVALID_PARAMETER;
1750 }
1751
1752 //
1753 // Retrieve uncommitted data from Browser
1754 //
1755
1756 BufferSize = sizeof (IP6_CONFIG_IFR_NVDATA);
1757 IfrNvData = AllocateZeroPool (BufferSize);
1758 if (IfrNvData == NULL) {
1759 return EFI_OUT_OF_RESOURCES;
1760 }
1761
1762 Status = EFI_SUCCESS;
1763
1764 HiiGetBrowserData (NULL, NULL, BufferSize, (UINT8 *) IfrNvData);
1765
1766 if (Action == EFI_BROWSER_ACTION_CHANGING) {
1767 switch (QuestionId) {
1768 case KEY_GET_CURRENT_SETTING:
1769 Status = Ip6GetCurrentSetting (Instance);
1770 break;
1771
1772 default:
1773 break;
1774 }
1775 } else if (Action == EFI_BROWSER_ACTION_CHANGED) {
1776 switch (QuestionId) {
1777 case KEY_SAVE_CONFIG_CHANGES:
1778 Status = Ip6ConvertIfrNvDataToConfigNvDataAdvanced (IfrNvData, Instance);
1779 if (EFI_ERROR (Status)) {
1780 break;
1781 }
1782
1783 Status = Ip6GetCurrentSetting (Instance);
1784
1785 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT;
1786 break;
1787
1788 case KEY_IGNORE_CONFIG_CHANGES:
1789 Ip6FreeAddressInfoList (&Ip6NvData->ManualAddress);
1790 Ip6FreeAddressInfoList (&Ip6NvData->GatewayAddress);
1791 Ip6FreeAddressInfoList (&Ip6NvData->DnsAddress);
1792
1793 Ip6NvData->ManualAddressCount = 0;
1794 Ip6NvData->GatewayAddressCount = 0;
1795 Ip6NvData->DnsAddressCount = 0;
1796
1797 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT;
1798 break;
1799
1800 case KEY_SAVE_CHANGES:
1801 Status = Ip6ConvertIfrNvDataToConfigNvDataGeneral (IfrNvData, Instance);
1802 if (EFI_ERROR (Status)) {
1803 break;
1804 }
1805 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT;
1806 break;
1807
1808 case KEY_INTERFACE_ID:
1809 Status = Ip6ParseInterfaceIdFromString (IfrNvData->InterfaceId, &Ip6NvData->InterfaceId);
1810 if (EFI_ERROR (Status)) {
1811 CreatePopUp (
1812 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
1813 &Key,
1814 L"Invalid Interface ID!",
1815 NULL
1816 );
1817 }
1818
1819 break;
1820
1821 case KEY_MANUAL_ADDRESS:
1822 Status = Ip6ParseAddressListFromString (
1823 IfrNvData->ManualAddress,
1824 &Ip6NvData->ManualAddress,
1825 &Ip6NvData->ManualAddressCount
1826 );
1827 if (EFI_ERROR (Status)) {
1828 CreatePopUp (
1829 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
1830 &Key,
1831 L"Invalid Host Addresses!",
1832 NULL
1833 );
1834 }
1835
1836 break;
1837
1838 case KEY_GATEWAY_ADDRESS:
1839 Status = Ip6ParseAddressListFromString (
1840 IfrNvData->GatewayAddress,
1841 &Ip6NvData->GatewayAddress,
1842 &Ip6NvData->GatewayAddressCount
1843 );
1844 if (EFI_ERROR (Status)) {
1845 CreatePopUp (
1846 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
1847 &Key,
1848 L"Invalid Gateway Addresses!",
1849 NULL
1850 );
1851 }
1852
1853 break;
1854
1855 case KEY_DNS_ADDRESS:
1856 Status = Ip6ParseAddressListFromString (
1857 IfrNvData->DnsAddress,
1858 &Ip6NvData->DnsAddress,
1859 &Ip6NvData->DnsAddressCount
1860 );
1861 if (EFI_ERROR (Status)) {
1862 CreatePopUp (
1863 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
1864 &Key,
1865 L"Invalid DNS Addresses!",
1866 NULL
1867 );
1868 }
1869
1870 break;
1871
1872 default:
1873 break;
1874 }
1875 }
1876
1877 if (!EFI_ERROR (Status)) {
1878 //
1879 // Pass changed uncommitted data back to Form Browser.
1880 //
1881 BufferSize = sizeof (IP6_CONFIG_IFR_NVDATA);
1882 HiiSetBrowserData (NULL, NULL, BufferSize, (UINT8 *) IfrNvData, NULL);
1883 }
1884
1885 FreePool (IfrNvData);
1886 return Status;
1887 }
1888
1889 /**
1890 Install HII Config Access protocol for network device and allocate resources.
1891
1892 @param[in, out] Instance The IP6_CONFIG_INSTANCE to create a form.
1893
1894 @retval EFI_SUCCESS The HII Config Access protocol is installed.
1895 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
1896 @retval Others Other errors as indicated.
1897
1898 **/
1899 EFI_STATUS
1900 Ip6ConfigFormInit (
1901 IN OUT IP6_CONFIG_INSTANCE *Instance
1902 )
1903 {
1904 EFI_STATUS Status;
1905 IP6_SERVICE *IpSb;
1906 IP6_FORM_CALLBACK_INFO *CallbackInfo;
1907 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;
1908 VENDOR_DEVICE_PATH VendorDeviceNode;
1909 EFI_SERVICE_BINDING_PROTOCOL *MnpSb;
1910 CHAR16 *MacString;
1911 CHAR16 MenuString[128];
1912 CHAR16 PortString[128];
1913 CHAR16 *OldMenuString;
1914 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
1915
1916 IpSb = IP6_SERVICE_FROM_IP6_CONFIG_INSTANCE (Instance);
1917 ASSERT (IpSb != NULL);
1918
1919 Status = gBS->HandleProtocol (
1920 IpSb->Controller,
1921 &gEfiDevicePathProtocolGuid,
1922 (VOID **) &ParentDevicePath
1923 );
1924 if (EFI_ERROR (Status)) {
1925 return Status;
1926 }
1927
1928 CallbackInfo = &Instance->CallbackInfo;
1929 CallbackInfo->Signature = IP6_FORM_CALLBACK_INFO_SIGNATURE;
1930
1931 //
1932 // Construct device path node for EFI HII Config Access protocol,
1933 // which consists of controller physical device path and one hardware
1934 // vendor guid node.
1935 //
1936 ZeroMem (&VendorDeviceNode, sizeof (VENDOR_DEVICE_PATH));
1937 VendorDeviceNode.Header.Type = HARDWARE_DEVICE_PATH;
1938 VendorDeviceNode.Header.SubType = HW_VENDOR_DP;
1939
1940 CopyGuid (&VendorDeviceNode.Guid, &gEfiCallerIdGuid);
1941
1942 SetDevicePathNodeLength (&VendorDeviceNode.Header, sizeof (VENDOR_DEVICE_PATH));
1943 CallbackInfo->HiiVendorDevicePath = AppendDevicePathNode (
1944 ParentDevicePath,
1945 (EFI_DEVICE_PATH_PROTOCOL *) &VendorDeviceNode
1946 );
1947 if (CallbackInfo->HiiVendorDevicePath == NULL) {
1948 Status = EFI_OUT_OF_RESOURCES;
1949 goto Error;
1950 }
1951
1952 ConfigAccess = &CallbackInfo->HiiConfigAccess;
1953 ConfigAccess->ExtractConfig = Ip6FormExtractConfig;
1954 ConfigAccess->RouteConfig = Ip6FormRouteConfig;
1955 ConfigAccess->Callback = Ip6FormCallback;
1956
1957 //
1958 // Install Device Path Protocol and Config Access protocol on new handle
1959 //
1960 Status = gBS->InstallMultipleProtocolInterfaces (
1961 &CallbackInfo->ChildHandle,
1962 &gEfiDevicePathProtocolGuid,
1963 CallbackInfo->HiiVendorDevicePath,
1964 &gEfiHiiConfigAccessProtocolGuid,
1965 ConfigAccess,
1966 NULL
1967 );
1968 if (!EFI_ERROR (Status)) {
1969 //
1970 // Open the Parent Handle for the child
1971 //
1972 Status = gBS->OpenProtocol (
1973 IpSb->Controller,
1974 &gEfiManagedNetworkServiceBindingProtocolGuid,
1975 (VOID **) &MnpSb,
1976 IpSb->Image,
1977 CallbackInfo->ChildHandle,
1978 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
1979 );
1980 }
1981
1982 if (EFI_ERROR (Status)) {
1983 goto Error;
1984 }
1985
1986 //
1987 // Publish our HII data
1988 //
1989 CallbackInfo->RegisteredHandle = HiiAddPackages (
1990 &gIp6ConfigNvDataGuid,
1991 CallbackInfo->ChildHandle,
1992 Ip6DxeStrings,
1993 Ip6ConfigBin,
1994 NULL
1995 );
1996 if (CallbackInfo->RegisteredHandle == NULL) {
1997 Status = EFI_OUT_OF_RESOURCES;
1998 goto Error;
1999 }
2000
2001 //
2002 // Append MAC string in the menu help string and tile help string
2003 //
2004 Status = NetLibGetMacString (IpSb->Controller, IpSb->Image, &MacString);
2005 if (!EFI_ERROR (Status)) {
2006 OldMenuString = HiiGetString (
2007 CallbackInfo->RegisteredHandle,
2008 STRING_TOKEN (STR_IP6_CONFIG_FORM_HELP),
2009 NULL)
2010 ;
2011 UnicodeSPrint (MenuString, 128, L"%s (MAC:%s)", OldMenuString, MacString);
2012 HiiSetString (
2013 CallbackInfo->RegisteredHandle,
2014 STRING_TOKEN (STR_IP6_CONFIG_FORM_HELP),
2015 MenuString,
2016 NULL
2017 );
2018 UnicodeSPrint (PortString, 128, L"MAC:%s", MacString);
2019 HiiSetString (
2020 CallbackInfo->RegisteredHandle,
2021 STRING_TOKEN (STR_IP6_DEVICE_FORM_HELP),
2022 PortString,
2023 NULL
2024 );
2025
2026 FreePool (MacString);
2027 FreePool (OldMenuString);
2028
2029 InitializeListHead (&Instance->Ip6NvData.ManualAddress);
2030 InitializeListHead (&Instance->Ip6NvData.GatewayAddress);
2031 InitializeListHead (&Instance->Ip6NvData.DnsAddress);
2032
2033 return EFI_SUCCESS;
2034 }
2035
2036 Error:
2037 Ip6ConfigFormUnload (Instance);
2038 return Status;
2039 }
2040
2041 /**
2042 Uninstall the HII Config Access protocol for network devices and free up the resources.
2043
2044 @param[in, out] Instance The IP6_CONFIG_INSTANCE to unload a form.
2045
2046 **/
2047 VOID
2048 Ip6ConfigFormUnload (
2049 IN OUT IP6_CONFIG_INSTANCE *Instance
2050 )
2051 {
2052 IP6_SERVICE *IpSb;
2053 IP6_FORM_CALLBACK_INFO *CallbackInfo;
2054 IP6_CONFIG_NVDATA *Ip6NvData;
2055
2056 IpSb = IP6_SERVICE_FROM_IP6_CONFIG_INSTANCE (Instance);
2057 ASSERT (IpSb != NULL);
2058
2059 CallbackInfo = &Instance->CallbackInfo;
2060
2061 if (CallbackInfo->ChildHandle != NULL) {
2062
2063 //
2064 // Close the child handle
2065 //
2066 gBS->CloseProtocol (
2067 IpSb->Controller,
2068 &gEfiManagedNetworkServiceBindingProtocolGuid,
2069 IpSb->Image,
2070 CallbackInfo->ChildHandle
2071 );
2072 //
2073 // Uninstall EFI_HII_CONFIG_ACCESS_PROTOCOL
2074 //
2075 gBS->UninstallMultipleProtocolInterfaces (
2076 CallbackInfo->ChildHandle,
2077 &gEfiDevicePathProtocolGuid,
2078 CallbackInfo->HiiVendorDevicePath,
2079 &gEfiHiiConfigAccessProtocolGuid,
2080 &CallbackInfo->HiiConfigAccess,
2081 NULL
2082 );
2083 }
2084
2085 if (CallbackInfo->HiiVendorDevicePath != NULL) {
2086 FreePool (CallbackInfo->HiiVendorDevicePath);
2087 }
2088
2089 if (CallbackInfo->RegisteredHandle != NULL) {
2090 //
2091 // Remove HII package list
2092 //
2093 HiiRemovePackages (CallbackInfo->RegisteredHandle);
2094 }
2095
2096 Ip6NvData = &Instance->Ip6NvData;
2097
2098 Ip6FreeAddressInfoList (&Ip6NvData->ManualAddress);
2099 Ip6FreeAddressInfoList (&Ip6NvData->GatewayAddress);
2100 Ip6FreeAddressInfoList (&Ip6NvData->DnsAddress);
2101
2102 Ip6NvData->ManualAddressCount = 0;
2103 Ip6NvData->GatewayAddressCount = 0;
2104 Ip6NvData->DnsAddressCount = 0;
2105 }