b383488ffa4592d4480da58a5043032c2ef0bb82
[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 - 2011, 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 address,
673 address info, and route table information. The address information is also used as the
674 content of manual addresses in IP6 UI.
675
676 @param[in] IfInfo The pointer of EFI_IP6_CONFIG_INTERFACE_INFO.
677 @param[in] HiiHandle The handle that was previously registered in the
678 HII Database.
679 @param[in, out] IfrNvData Points to IP6_CONFIG_IFR_NVDATA.
680
681 @retval EFI_SUCCESS The operation finished successfully.
682 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
683 @retval EFI_OUT_OF_RESOURCES The operation failed due to lack of resources.
684
685 **/
686 EFI_STATUS
687 Ip6ConvertInterfaceInfoToString (
688 IN EFI_IP6_CONFIG_INTERFACE_INFO *IfInfo,
689 IN EFI_HII_HANDLE HiiHandle,
690 IN OUT IP6_CONFIG_IFR_NVDATA *IfrNvData
691 )
692 {
693 UINT32 Index;
694 UINTN Number;
695 CHAR16 *String;
696 CHAR16 *LinkLocalStr;
697 CHAR16 PortString[ADDRESS_STR_MAX_SIZE];
698 CHAR16 FormatString[8];
699 EFI_STRING_ID StringId;
700 EFI_STATUS Status;
701
702 if ((IfInfo == NULL) || (HiiHandle == NULL) || (IfrNvData == NULL)) {
703 return EFI_INVALID_PARAMETER;
704 }
705
706 //
707 // Print the interface name.
708 //
709 StringId = HiiSetString (
710 HiiHandle,
711 STRING_TOKEN (STR_IP6_INTERFACE_NAME_CONTENT),
712 IfInfo->Name,
713 NULL
714 );
715 if (StringId == 0) {
716 return EFI_OUT_OF_RESOURCES;
717 }
718
719 //
720 // Print the interface type.
721 //
722 if (IfInfo->IfType == Ip6InterfaceTypeEthernet) {
723 StrCpy (PortString, IP6_ETHERNET);
724 } else if (IfInfo->IfType == Ip6InterfaceTypeExperimentalEthernet) {
725 StrCpy (PortString, IP6_EXPERIMENTAL_ETHERNET);
726 } else {
727 //
728 // Refer to RFC1700, chapter Number Hardware Type.
729 //
730 UnicodeSPrint (PortString, 6, L"%d", IfInfo->IfType);
731 }
732
733 StringId = HiiSetString (
734 HiiHandle,
735 STRING_TOKEN (STR_IP6_INTERFACE_TYPE_CONTENT),
736 PortString,
737 NULL
738 );
739 if (StringId == 0) {
740 return EFI_OUT_OF_RESOURCES;
741 }
742
743 //
744 // Convert the hardware address.
745 //
746 String = PortString;
747 ASSERT (IfInfo->HwAddressSize <= 32);
748
749 for (Index = 0; Index < IfInfo->HwAddressSize; Index++) {
750
751 if (IfInfo->HwAddress.Addr[Index] < 0x10) {
752 StrCpy (FormatString, L"0%x-");
753 } else {
754 StrCpy (FormatString, L"%x-");
755 }
756
757 Number = UnicodeSPrint (
758 String,
759 8,
760 (CONST CHAR16 *) FormatString,
761 (UINTN) IfInfo->HwAddress.Addr[Index]
762 );
763 String = String + Number;
764 }
765
766 if (Index != 0) {
767 ASSERT (String > PortString);
768 String--;
769 *String = '\0';
770 }
771
772 //
773 // Print the hardware address.
774 //
775 StringId = HiiSetString (
776 HiiHandle,
777 STRING_TOKEN (STR_IP6_MAC_ADDRESS_CONTENT),
778 PortString,
779 NULL
780 );
781 if (StringId == 0) {
782 return EFI_OUT_OF_RESOURCES;
783 }
784
785 //
786 // Print the host address Information.
787 //
788 Status = Ip6ConvertAddressListToString (
789 PortString,
790 HiiHandle,
791 Ip6ConfigNvHostAddress,
792 IfInfo->AddressInfo,
793 IfInfo->AddressInfoCount
794 );
795 if (EFI_ERROR (Status)) {
796 return Status;
797 }
798
799 //
800 // Copy the Host Address Info to manual address field.
801 // Do not copy the link local address.
802 //
803 LinkLocalStr = StrStr (PortString, IP6_LINK_LOCAL_PREFIX);
804 if (LinkLocalStr != NULL) {
805 Number = LinkLocalStr - PortString;
806 if (Number > 0) {
807 CopyMem (IfrNvData->ManualAddress, PortString, Number * sizeof (CHAR16));
808 }
809
810 while ((*LinkLocalStr != L' ') && (*LinkLocalStr != L'\0')) {
811 LinkLocalStr++;
812 }
813
814 if (*LinkLocalStr != L'\0') {
815 LinkLocalStr++;
816 StrCat (IfrNvData->ManualAddress, LinkLocalStr);
817 }
818 } else {
819 StrCpy (IfrNvData->ManualAddress, PortString);
820 }
821
822 //
823 // Print the route table information.
824 //
825 Status = Ip6ConvertAddressListToString (
826 PortString,
827 HiiHandle,
828 Ip6ConfigNvRouteTable,
829 IfInfo->RouteTable,
830 IfInfo->RouteCount
831 );
832 return Status;
833 }
834
835 /**
836 Build the address info list from list array of node in IP6_ADDRESS_INFO_ENTRY.
837
838 @param[in] Instance Points to IP6 config instance data.
839 @param[in] AddressType The address type.
840 @param[out] AddressInfo The pointer to the buffer to store the address list.
841 @param[out] AddressSize The address size of the address list.
842
843 @retval EFI_SUCCESS The operation finished successfully.
844 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
845 @retval EFI_UNSUPPORTED The AddressType is not supported.
846
847 **/
848 EFI_STATUS
849 Ip6BuildNvAddressInfo (
850 IN IP6_CONFIG_INSTANCE *Instance,
851 IN IP6_CONFIG_NV_ADDRESS_TYPE AddressType,
852 OUT VOID **AddressInfo,
853 OUT UINTN *AddressSize
854 )
855 {
856 IP6_CONFIG_NVDATA *Ip6NvData;
857 LIST_ENTRY *Entry;
858 LIST_ENTRY *ListHead;
859 IP6_ADDRESS_INFO_ENTRY *Node;
860 VOID *AddressList;
861 VOID *TmpStr;
862 UINTN DataSize;
863 EFI_IPv6_ADDRESS *Ip6Address;
864 EFI_IP6_CONFIG_MANUAL_ADDRESS *ManualAddress;
865
866 if ((Instance == NULL) || (AddressInfo == NULL) || (AddressSize == NULL)) {
867 return EFI_INVALID_PARAMETER;
868 }
869
870 NET_CHECK_SIGNATURE (Instance, IP6_CONFIG_INSTANCE_SIGNATURE);
871
872 Ip6NvData = &Instance->Ip6NvData;
873
874 if (AddressType == Ip6ConfigNvHostAddress) {
875 ListHead = &Ip6NvData->ManualAddress;
876 DataSize = sizeof (EFI_IP6_CONFIG_MANUAL_ADDRESS) * Ip6NvData->ManualAddressCount;
877 } else if (AddressType == Ip6ConfigNvGatewayAddress) {
878 ListHead = &Ip6NvData->GatewayAddress;
879 DataSize = sizeof (EFI_IPv6_ADDRESS) * Ip6NvData->GatewayAddressCount;
880 } else if (AddressType == Ip6ConfigNvDnsAddress) {
881 ListHead = &Ip6NvData->DnsAddress;
882 DataSize = sizeof (EFI_IPv6_ADDRESS) * Ip6NvData->DnsAddressCount;
883 } else {
884 return EFI_UNSUPPORTED;
885 }
886
887 AddressList = AllocateZeroPool (DataSize);
888 if (AddressList == NULL) {
889 return EFI_OUT_OF_RESOURCES;
890 }
891
892 TmpStr = AddressList;
893
894 NET_LIST_FOR_EACH (Entry, ListHead) {
895 Node = NET_LIST_USER_STRUCT (Entry, IP6_ADDRESS_INFO_ENTRY, Link);
896 if (AddressType == Ip6ConfigNvHostAddress) {
897 ManualAddress = (EFI_IP6_CONFIG_MANUAL_ADDRESS *) AddressList;
898 IP6_COPY_ADDRESS (&ManualAddress->Address, &Node->AddrInfo.Address);
899 ManualAddress->PrefixLength = Node->AddrInfo.PrefixLength;
900 AddressList = (UINT8 *) AddressList + sizeof (EFI_IP6_CONFIG_MANUAL_ADDRESS);
901 } else {
902 Ip6Address = (EFI_IPv6_ADDRESS *) AddressList;
903 IP6_COPY_ADDRESS (Ip6Address, &Node->AddrInfo.Address);
904 AddressList = (UINT8 *) AddressList + sizeof (EFI_IPv6_ADDRESS);
905 }
906 }
907
908 *AddressInfo = TmpStr;
909 *AddressSize = DataSize;
910 return EFI_SUCCESS;
911 }
912
913 /**
914 Convert the IP6 configuration data into the IFR data.
915
916 @param[in, out] IfrNvData The IFR NV data.
917 @param[in] Instance The IP6 config instance data.
918
919 @retval EFI_SUCCESS The operation finished successfully.
920 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
921 @retval EFI_UNSUPPORTED The policy is not supported in the current implementation.
922 @retval Others Other errors as indicated.
923
924 **/
925 EFI_STATUS
926 Ip6ConvertConfigNvDataToIfrNvData (
927 IN OUT IP6_CONFIG_IFR_NVDATA *IfrNvData,
928 IN IP6_CONFIG_INSTANCE *Instance
929 )
930 {
931 EFI_IP6_CONFIG_PROTOCOL *Ip6Config;
932 UINTN DataSize;
933 VOID *Data;
934 EFI_STATUS Status;
935 EFI_IP6_CONFIG_INTERFACE_ID InterfaceId;
936 EFI_IP6_CONFIG_POLICY Policy;
937 EFI_IP6_CONFIG_DUP_ADDR_DETECT_TRANSMITS DadXmits;
938 EFI_HII_HANDLE HiiHandle;
939
940 if ((IfrNvData == NULL) || (Instance == NULL)) {
941 return EFI_INVALID_PARAMETER;
942 }
943
944 NET_CHECK_SIGNATURE (Instance, IP6_CONFIG_INSTANCE_SIGNATURE);
945
946 Ip6Config = &Instance->Ip6Config;
947 Data = NULL;
948 DataSize = 0;
949 HiiHandle = Instance->CallbackInfo.RegisteredHandle;
950
951 //
952 // Get the current interface info.
953 //
954 Status = Ip6ConfigNvGetData (
955 Ip6Config,
956 Ip6ConfigDataTypeInterfaceInfo,
957 &DataSize,
958 (VOID **) &Data
959 );
960 if (EFI_ERROR (Status)) {
961 goto Exit;
962 }
963
964 //
965 // Convert the interface info to string and print.
966 //
967 Status = Ip6ConvertInterfaceInfoToString (
968 (EFI_IP6_CONFIG_INTERFACE_INFO *) Data,
969 HiiHandle,
970 IfrNvData
971 );
972 if (EFI_ERROR (Status)) {
973 goto Exit;
974 }
975
976 //
977 // Get the interface id.
978 //
979 DataSize = sizeof (EFI_IP6_CONFIG_INTERFACE_ID);
980 ZeroMem (&InterfaceId, DataSize);
981 Status = Ip6Config->GetData (
982 Ip6Config,
983 Ip6ConfigDataTypeAltInterfaceId,
984 &DataSize,
985 &InterfaceId
986 );
987 if (EFI_ERROR (Status)) {
988 goto Exit;
989 }
990
991 Ip6ConvertInterfaceIdToString (IfrNvData->InterfaceId, &InterfaceId);
992
993 //
994 // Get current policy.
995 //
996 DataSize = sizeof (EFI_IP6_CONFIG_POLICY);
997 Status = Ip6Config->GetData (
998 Ip6Config,
999 Ip6ConfigDataTypePolicy,
1000 &DataSize,
1001 &Policy
1002 );
1003
1004 if (EFI_ERROR (Status)) {
1005 goto Exit;
1006 }
1007
1008 if (Policy == Ip6ConfigPolicyManual) {
1009 IfrNvData->Policy = IP6_POLICY_MANUAL;
1010 } else if (Policy == Ip6ConfigPolicyAutomatic) {
1011 IfrNvData->Policy = IP6_POLICY_AUTO;
1012 } else {
1013 ASSERT (FALSE);
1014 Status = EFI_UNSUPPORTED;
1015 goto Exit;
1016 }
1017
1018 //
1019 // Get Duplicate Address Detection Transmits count.
1020 //
1021 DataSize = sizeof (EFI_IP6_CONFIG_DUP_ADDR_DETECT_TRANSMITS);
1022 Status = Ip6Config->GetData (
1023 Ip6Config,
1024 Ip6ConfigDataTypeDupAddrDetectTransmits,
1025 &DataSize,
1026 &DadXmits
1027 );
1028
1029 if (EFI_ERROR (Status)) {
1030 goto Exit;
1031 }
1032
1033 IfrNvData->DadTransmitCount = DadXmits.DupAddrDetectTransmits;
1034
1035 //
1036 // Get DNS server list.
1037 //
1038 FreePool (Data);
1039 Data = NULL;
1040 DataSize = 0;
1041 Status = Ip6ConfigNvGetData (
1042 Ip6Config,
1043 Ip6ConfigDataTypeDnsServer,
1044 &DataSize,
1045 (VOID **) &Data
1046 );
1047
1048 if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
1049 goto Exit;
1050 }
1051
1052 if (DataSize > 0) {
1053 //
1054 // Convert the DNS server address to string and draw it to UI.
1055 //
1056 Status = Ip6ConvertAddressListToString (
1057 IfrNvData->DnsAddress,
1058 HiiHandle,
1059 Ip6ConfigNvDnsAddress,
1060 Data,
1061 DataSize / sizeof (EFI_IPv6_ADDRESS)
1062 );
1063 if (EFI_ERROR (Status)) {
1064 goto Exit;
1065 }
1066
1067 FreePool (Data);
1068 Data = NULL;
1069 }
1070
1071 //
1072 // Get gateway adderss list.
1073 //
1074 DataSize = 0;
1075 Status = Ip6ConfigNvGetData (
1076 Ip6Config,
1077 Ip6ConfigDataTypeGateway,
1078 &DataSize,
1079 (VOID **) &Data
1080 );
1081
1082 if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
1083 goto Exit;
1084 }
1085
1086 if (DataSize > 0) {
1087 //
1088 // Convert the gateway address to string and draw it to UI.
1089 //
1090 Status = Ip6ConvertAddressListToString (
1091 IfrNvData->GatewayAddress,
1092 HiiHandle,
1093 Ip6ConfigNvGatewayAddress,
1094 Data,
1095 DataSize / sizeof (EFI_IPv6_ADDRESS)
1096 );
1097 if (EFI_ERROR (Status)) {
1098 goto Exit;
1099 }
1100 }
1101
1102 Status = EFI_SUCCESS;
1103
1104 Exit:
1105 if (Data != NULL) {
1106 FreePool (Data);
1107 }
1108
1109 return Status;
1110 }
1111
1112 /**
1113 Convert IFR data into IP6 configuration data. The policy, alternative interface
1114 ID, and DAD transmit counts, and will be saved. If under manual policy, the configured
1115 manual address, gateway address, and DNS server address will be saved.
1116
1117 @param[in] IfrNvData The IFR NV data.
1118 @param[in, out] Instance The IP6 config instance data.
1119
1120 @retval EFI_SUCCESS The operation finished successfully.
1121 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
1122 @retval Others Other errors as indicated.
1123
1124 **/
1125 EFI_STATUS
1126 Ip6ConvertIfrNvDataToConfigNvData (
1127 IN IP6_CONFIG_IFR_NVDATA *IfrNvData,
1128 IN OUT IP6_CONFIG_INSTANCE *Instance
1129 )
1130 {
1131 IP6_CONFIG_NVDATA *Ip6NvData;
1132 EFI_IP6_CONFIG_PROTOCOL *Ip6Config;
1133 EFI_STATUS Status;
1134 EFI_IP6_CONFIG_MANUAL_ADDRESS *ManualAddress;
1135 EFI_IPv6_ADDRESS *Address;
1136 BOOLEAN IsAddressOk;
1137 EFI_EVENT SetAddressEvent;
1138 EFI_EVENT TimeoutEvent;
1139 UINTN DataSize;
1140
1141 if ((IfrNvData == NULL) || (Instance == NULL)) {
1142 return EFI_INVALID_PARAMETER;
1143 }
1144
1145 NET_CHECK_SIGNATURE (Instance, IP6_CONFIG_INSTANCE_SIGNATURE);
1146 Ip6NvData = &Instance->Ip6NvData;
1147 Ip6Config = &Instance->Ip6Config;
1148
1149 //
1150 // Update those fields which don't have INTERACTIVE attribute.
1151 //
1152 if (IfrNvData->Policy == IP6_POLICY_AUTO) {
1153 Ip6NvData->Policy = Ip6ConfigPolicyAutomatic;
1154 } else if (IfrNvData->Policy == IP6_POLICY_MANUAL) {
1155 Ip6NvData->Policy = Ip6ConfigPolicyManual;
1156 }
1157
1158 Ip6NvData->DadTransmitCount.DupAddrDetectTransmits = IfrNvData->DadTransmitCount;
1159
1160 //
1161 // Set the configured policy.
1162 //
1163 Status = Ip6Config->SetData (
1164 Ip6Config,
1165 Ip6ConfigDataTypePolicy,
1166 sizeof (EFI_IP6_CONFIG_POLICY),
1167 &Ip6NvData->Policy
1168 );
1169 if (EFI_ERROR (Status)) {
1170 return Status;
1171 }
1172
1173 //
1174 // Set the duplicate address detection transmits count.
1175 //
1176 Status = Ip6Config->SetData (
1177 Ip6Config,
1178 Ip6ConfigDataTypeDupAddrDetectTransmits,
1179 sizeof (EFI_IP6_CONFIG_DUP_ADDR_DETECT_TRANSMITS),
1180 &Ip6NvData->DadTransmitCount
1181 );
1182 if (EFI_ERROR (Status)) {
1183 return Status;
1184 }
1185
1186 //
1187 // Set the alternative interface ID
1188 //
1189 Status = Ip6Config->SetData (
1190 Ip6Config,
1191 Ip6ConfigDataTypeAltInterfaceId,
1192 sizeof (EFI_IP6_CONFIG_INTERFACE_ID),
1193 &Ip6NvData->InterfaceId
1194 );
1195 if (EFI_ERROR (Status)) {
1196 return Status;
1197 }
1198
1199
1200 if (Ip6NvData->Policy == Ip6ConfigPolicyAutomatic) {
1201 return EFI_SUCCESS;
1202 }
1203
1204 //
1205 // Create events & timers for asynchronous settings.
1206 //
1207 SetAddressEvent = NULL;
1208 TimeoutEvent = NULL;
1209 ManualAddress = NULL;
1210 Address = NULL;
1211
1212 Status = gBS->CreateEvent (
1213 EVT_NOTIFY_SIGNAL,
1214 TPL_NOTIFY,
1215 Ip6ConfigManualAddressNotify,
1216 &IsAddressOk,
1217 &SetAddressEvent
1218 );
1219 if (EFI_ERROR (Status)) {
1220 goto Exit;
1221 }
1222
1223 Status = gBS->CreateEvent (
1224 EVT_TIMER,
1225 TPL_CALLBACK,
1226 NULL,
1227 NULL,
1228 &TimeoutEvent
1229 );
1230 if (EFI_ERROR (Status)) {
1231 goto Exit;
1232 }
1233
1234 //
1235 // Set the manual address list. This is an asynchronous process.
1236 //
1237 if (!IsListEmpty (&Ip6NvData->ManualAddress) && (Ip6NvData->ManualAddressCount != 0)) {
1238 Status = Ip6BuildNvAddressInfo (
1239 Instance,
1240 Ip6ConfigNvHostAddress,
1241 (VOID **) &ManualAddress,
1242 &DataSize
1243 );
1244 if (EFI_ERROR (Status)) {
1245 goto Exit;
1246 }
1247
1248 IsAddressOk = FALSE;
1249
1250 Status = Ip6Config->RegisterDataNotify (
1251 Ip6Config,
1252 Ip6ConfigDataTypeManualAddress,
1253 SetAddressEvent
1254 );
1255 if (EFI_ERROR (Status)) {
1256 goto Exit;
1257 }
1258
1259 Status = Ip6Config->SetData (
1260 Ip6Config,
1261 Ip6ConfigDataTypeManualAddress,
1262 DataSize,
1263 (VOID *) ManualAddress
1264 );
1265 if (Status == EFI_NOT_READY) {
1266 gBS->SetTimer (TimeoutEvent, TimerRelative, 50000000);
1267 while (EFI_ERROR (gBS->CheckEvent (TimeoutEvent))) {
1268 if (IsAddressOk) {
1269 Status = EFI_SUCCESS;
1270 }
1271 break;
1272 }
1273 }
1274
1275 Status = Ip6Config->UnregisterDataNotify (
1276 Ip6Config,
1277 Ip6ConfigDataTypeManualAddress,
1278 SetAddressEvent
1279 );
1280 if (EFI_ERROR (Status)) {
1281 goto Exit;
1282 }
1283 }
1284
1285 //
1286 // Set gateway address list.
1287 //
1288 if (!IsListEmpty (&Ip6NvData->GatewayAddress) && (Ip6NvData->GatewayAddressCount != 0)) {
1289 Status = Ip6BuildNvAddressInfo (
1290 Instance,
1291 Ip6ConfigNvGatewayAddress,
1292 (VOID **) &Address,
1293 &DataSize
1294 );
1295 if (EFI_ERROR (Status)) {
1296 goto Exit;
1297 }
1298
1299 Status = Ip6Config->SetData (
1300 Ip6Config,
1301 Ip6ConfigDataTypeGateway,
1302 DataSize,
1303 (VOID *) Address
1304 );
1305 if (EFI_ERROR (Status)) {
1306 goto Exit;
1307 }
1308
1309 FreePool (Address);
1310 Address = NULL;
1311 }
1312
1313 //
1314 // Set DNS server address list.
1315 //
1316 if (!IsListEmpty (&Ip6NvData->DnsAddress) && (Ip6NvData->DnsAddressCount != 0)) {
1317 Status = Ip6BuildNvAddressInfo (
1318 Instance,
1319 Ip6ConfigNvDnsAddress,
1320 (VOID **) &Address,
1321 &DataSize
1322 );
1323 if (EFI_ERROR (Status)) {
1324 goto Exit;
1325 }
1326
1327 Status = Ip6Config->SetData (
1328 Ip6Config,
1329 Ip6ConfigDataTypeDnsServer,
1330 DataSize,
1331 (VOID *) Address
1332 );
1333 if (EFI_ERROR (Status)) {
1334 goto Exit;
1335 }
1336 }
1337
1338 Status = EFI_SUCCESS;
1339
1340 Exit:
1341 if (SetAddressEvent != NULL) {
1342 gBS->CloseEvent (SetAddressEvent);
1343 }
1344
1345 if (TimeoutEvent != NULL) {
1346 gBS->CloseEvent (TimeoutEvent);
1347 }
1348
1349 if (ManualAddress != NULL) {
1350 FreePool (ManualAddress);
1351 }
1352
1353 if (Address != NULL) {
1354 FreePool (Address);
1355 }
1356
1357 return Status;
1358 }
1359
1360 /**
1361 This function allows the caller to request the current
1362 configuration for one or more named elements. The resulting
1363 string is in <ConfigAltResp> format. Any and all alternative
1364 configuration strings shall also be appended to the end of the
1365 current configuration string. If they are, they must appear
1366 after the current configuration. They must contain the same
1367 routing (GUID, NAME, PATH) as the current configuration string.
1368 They must have an additional description indicating the type of
1369 alternative configuration the string represents,
1370 "ALTCFG=<StringToken>". That <StringToken> (when
1371 converted from Hex UNICODE to binary) is a reference to a
1372 string in the associated string pack.
1373
1374 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
1375 @param[in] Request A null-terminated Unicode string in
1376 <ConfigRequest> format. Note that this
1377 includes the routing information as well as
1378 the configurable name / value pairs. It is
1379 invalid for this string to be in
1380 <MultiConfigRequest> format.
1381 @param[out] Progress On return, points to a character in the
1382 Request string. Points to the string's null
1383 terminator if request was successful. Points
1384 to the most recent "&" before the first
1385 failing name / value pair (or the beginning
1386 of the string if the failure is in the first
1387 name / value pair) if the request was not
1388 successful.
1389 @param[out] Results A null-terminated Unicode string in
1390 <ConfigAltResp> format which has all values
1391 filled in for the names in the Request string.
1392 String to be allocated by the called function.
1393
1394 @retval EFI_SUCCESS The Results string is filled with the
1395 values corresponding to all requested
1396 names.
1397 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the
1398 parts of the results that must be
1399 stored awaiting possible future
1400 protocols.
1401 @retval EFI_INVALID_PARAMETER For example, passing in a NULL
1402 for the Request parameter
1403 would result in this type of
1404 error. In this case, the
1405 Progress parameter would be
1406 set to NULL.
1407 @retval EFI_NOT_FOUND Routing data doesn't match any
1408 known driver. Progress set to the
1409 first character in the routing header.
1410 Note: There is no requirement that the
1411 driver validate the routing data. It
1412 must skip the <ConfigHdr> in order to
1413 process the names.
1414 @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set
1415 to most recent & before the
1416 error or the beginning of the
1417 string.
1418 @retval EFI_INVALID_PARAMETER Unknown name. Progress points
1419 to the & before the name in
1420 question. Currently not implemented.
1421 **/
1422 EFI_STATUS
1423 EFIAPI
1424 Ip6FormExtractConfig (
1425 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
1426 IN CONST EFI_STRING Request,
1427 OUT EFI_STRING *Progress,
1428 OUT EFI_STRING *Results
1429 )
1430 {
1431
1432 EFI_STATUS Status;
1433 IP6_FORM_CALLBACK_INFO *Private;
1434 IP6_CONFIG_INSTANCE *Ip6ConfigInstance;
1435 IP6_CONFIG_IFR_NVDATA *IfrNvData;
1436 EFI_STRING ConfigRequestHdr;
1437 EFI_STRING ConfigRequest;
1438 BOOLEAN AllocatedRequest;
1439 UINTN Size;
1440 UINTN BufferSize;
1441
1442 if (This == NULL || Progress == NULL || Results == NULL) {
1443 return EFI_INVALID_PARAMETER;
1444 }
1445
1446 *Progress = Request;
1447 if ((Request != NULL) &&
1448 !HiiIsConfigHdrMatch (Request, &gIp6ConfigNvDataGuid, mIp6ConfigStorageName)) {
1449 return EFI_NOT_FOUND;
1450 }
1451
1452 ConfigRequestHdr = NULL;
1453 ConfigRequest = NULL;
1454 AllocatedRequest = FALSE;
1455 Size = 0;
1456
1457 Private = IP6_FORM_CALLBACK_INFO_FROM_CONFIG_ACCESS (This);
1458 Ip6ConfigInstance = IP6_CONFIG_INSTANCE_FROM_FORM_CALLBACK (Private);
1459 BufferSize = sizeof (IP6_CONFIG_IFR_NVDATA);
1460
1461 IfrNvData = (IP6_CONFIG_IFR_NVDATA *) AllocateZeroPool (BufferSize);
1462 if (IfrNvData == NULL) {
1463 return EFI_OUT_OF_RESOURCES;
1464 }
1465
1466 Status = Ip6ConvertConfigNvDataToIfrNvData (IfrNvData, Ip6ConfigInstance);
1467 if (EFI_ERROR (Status)) {
1468 goto Exit;
1469 }
1470
1471 ConfigRequest = Request;
1472 if ((Request == NULL) || (StrStr (Request, L"OFFSET") == NULL)) {
1473 //
1474 // Request has no request element, construct full request string.
1475 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
1476 // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator.
1477 //
1478 ConfigRequestHdr = HiiConstructConfigHdr (
1479 &gIp6ConfigNvDataGuid,
1480 mIp6ConfigStorageName,
1481 Private->ChildHandle
1482 );
1483 Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16);
1484 ConfigRequest = AllocateZeroPool (Size);
1485 ASSERT (ConfigRequest != NULL);
1486 AllocatedRequest = TRUE;
1487 UnicodeSPrint (
1488 ConfigRequest,
1489 Size,
1490 L"%s&OFFSET=0&WIDTH=%016LX",
1491 ConfigRequestHdr,
1492 (UINT64) BufferSize
1493 );
1494 FreePool (ConfigRequestHdr);
1495 }
1496
1497 //
1498 // Convert buffer data to <ConfigResp> by helper function BlockToConfig()
1499 //
1500 Status = gHiiConfigRouting->BlockToConfig (
1501 gHiiConfigRouting,
1502 ConfigRequest,
1503 (UINT8 *) IfrNvData,
1504 BufferSize,
1505 Results,
1506 Progress
1507 );
1508
1509 Exit:
1510 FreePool (IfrNvData);
1511 //
1512 // Free the allocated config request string.
1513 //
1514 if (AllocatedRequest) {
1515 FreePool (ConfigRequest);
1516 ConfigRequest = NULL;
1517 }
1518 //
1519 // Set Progress string to the original request string.
1520 //
1521 if (Request == NULL) {
1522 *Progress = NULL;
1523 } else if (StrStr (Request, L"OFFSET") == NULL) {
1524 *Progress = Request + StrLen (Request);
1525 }
1526
1527 return Status;
1528 }
1529
1530 /**
1531 This function applies changes in a driver's configuration.
1532 Input is a Configuration, which has the routing data for this
1533 driver followed by name / value configuration pairs. The driver
1534 must apply those pairs to its configurable storage. If the
1535 driver's configuration is stored in a linear block of data
1536 and the driver's name / value pairs are in <BlockConfig>
1537 format, it may use the ConfigToBlock helper function (above) to
1538 simplify the job. Currently not implemented.
1539
1540 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
1541 @param[in] Configuration A null-terminated Unicode string in
1542 <ConfigString> format.
1543 @param[out] Progress A pointer to a string filled in with the
1544 offset of the most recent '&' before the
1545 first failing name / value pair (or the
1546 beginn ing of the string if the failure
1547 is in the first name / value pair) or
1548 the terminating NULL if all was
1549 successful.
1550
1551 @retval EFI_SUCCESS The results have been distributed or are
1552 awaiting distribution.
1553 @retval EFI_OUT_OF_MEMORY Not enough memory to store the
1554 parts of the results that must be
1555 stored awaiting possible future
1556 protocols.
1557 @retval EFI_INVALID_PARAMETERS Passing in a NULL for the
1558 Results parameter would result
1559 in this type of error.
1560 @retval EFI_NOT_FOUND Target for the specified routing data
1561 was not found.
1562 **/
1563 EFI_STATUS
1564 EFIAPI
1565 Ip6FormRouteConfig (
1566 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
1567 IN CONST EFI_STRING Configuration,
1568 OUT EFI_STRING *Progress
1569 )
1570 {
1571 if (This == NULL || Configuration == NULL || Progress == NULL) {
1572 return EFI_INVALID_PARAMETER;
1573 }
1574
1575 //
1576 // Check routing data in <ConfigHdr>.
1577 // Note: if only one Storage is used, then this checking could be skipped.
1578 //
1579 if (!HiiIsConfigHdrMatch (Configuration, &gIp6ConfigNvDataGuid, mIp6ConfigStorageName)) {
1580 *Progress = Configuration;
1581 return EFI_NOT_FOUND;
1582 }
1583
1584 *Progress = Configuration + StrLen (Configuration);
1585
1586 return EFI_SUCCESS;
1587 }
1588
1589 /**
1590 This function is called to provide results data to the driver.
1591 This data consists of a unique key that is used to identify
1592 which data is either being passed back or being asked for.
1593
1594 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
1595 @param[in] Action Specifies the type of action taken by the browser.
1596 @param[in] QuestionId A unique value which is sent to the original
1597 exporting driver so that it can identify the type
1598 of data to expect. The format of the data tends to
1599 vary based on the opcode that generated the callback.
1600 @param[in] Type The type of value for the question.
1601 @param[in] Value A pointer to the data being sent to the original
1602 exporting driver.
1603 @param[out] ActionRequest On return, points to the action requested by the
1604 callback function.
1605
1606 @retval EFI_SUCCESS The callback successfully handled the action.
1607 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the
1608 variable and its data.
1609 @retval EFI_DEVICE_ERROR The variable could not be saved.
1610 @retval EFI_UNSUPPORTED The specified Action is not supported by the
1611 callback. Currently not implemented.
1612 @retval EFI_INVALID_PARAMETER Passed in the wrong parameter.
1613 @retval Others Other errors as indicated.
1614
1615 **/
1616 EFI_STATUS
1617 EFIAPI
1618 Ip6FormCallback (
1619 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
1620 IN EFI_BROWSER_ACTION Action,
1621 IN EFI_QUESTION_ID QuestionId,
1622 IN UINT8 Type,
1623 IN EFI_IFR_TYPE_VALUE *Value,
1624 OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest
1625 )
1626 {
1627 IP6_FORM_CALLBACK_INFO *Private;
1628 UINTN BufferSize;
1629 IP6_CONFIG_IFR_NVDATA *IfrNvData;
1630 IP6_CONFIG_IFR_NVDATA OldIfrNvData;
1631 EFI_STATUS Status;
1632 EFI_INPUT_KEY Key;
1633 IP6_CONFIG_INSTANCE *Instance;
1634 IP6_CONFIG_NVDATA *Ip6NvData;
1635 EFI_IP6_CONFIG_PROTOCOL *Ip6Config;
1636 EFI_IP6_CONFIG_INTERFACE_INFO *Data;
1637 UINTN DataSize;
1638 CHAR16 PortString[ADDRESS_STR_MAX_SIZE];
1639 EFI_HII_HANDLE HiiHandle;
1640 EFI_IP6_CONFIG_INTERFACE_INFO *IfInfo;
1641
1642 if (This == NULL) {
1643 return EFI_INVALID_PARAMETER;
1644 }
1645
1646 Private = IP6_FORM_CALLBACK_INFO_FROM_CONFIG_ACCESS (This);
1647 Instance = IP6_CONFIG_INSTANCE_FROM_FORM_CALLBACK (Private);
1648 Ip6NvData = &Instance->Ip6NvData;
1649
1650 if ((Action == EFI_BROWSER_ACTION_FORM_OPEN) || (Action == EFI_BROWSER_ACTION_FORM_CLOSE)){
1651 return EFI_SUCCESS;
1652 }
1653
1654 if (Action != EFI_BROWSER_ACTION_CHANGING) {
1655 return EFI_UNSUPPORTED;
1656 }
1657
1658 if ((Value == NULL) || (ActionRequest == NULL)) {
1659 return EFI_INVALID_PARAMETER;
1660 }
1661
1662 //
1663 // Retrieve uncommitted data from Browser
1664 //
1665
1666 BufferSize = sizeof (IP6_CONFIG_IFR_NVDATA);
1667 IfrNvData = AllocateZeroPool (BufferSize);
1668 if (IfrNvData == NULL) {
1669 return EFI_OUT_OF_RESOURCES;
1670 }
1671
1672 Status = EFI_SUCCESS;
1673
1674 ZeroMem (&OldIfrNvData, BufferSize);
1675
1676 HiiGetBrowserData (NULL, NULL, BufferSize, (UINT8 *) IfrNvData);
1677
1678 CopyMem (&OldIfrNvData, IfrNvData, BufferSize);
1679
1680 switch (QuestionId) {
1681 case KEY_INTERFACE_ID:
1682 Status = Ip6ParseInterfaceIdFromString (IfrNvData->InterfaceId, &Ip6NvData->InterfaceId);
1683 if (EFI_ERROR (Status)) {
1684 CreatePopUp (
1685 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
1686 &Key,
1687 L"Invalid Interface ID!",
1688 NULL
1689 );
1690 }
1691
1692 break;
1693
1694 case KEY_MANUAL_ADDRESS:
1695 Status = Ip6ParseAddressListFromString (
1696 IfrNvData->ManualAddress,
1697 &Ip6NvData->ManualAddress,
1698 &Ip6NvData->ManualAddressCount
1699 );
1700 if (EFI_ERROR (Status)) {
1701 CreatePopUp (
1702 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
1703 &Key,
1704 L"Invalid Host Addresses!",
1705 NULL
1706 );
1707 }
1708
1709 break;
1710
1711 case KEY_GATEWAY_ADDRESS:
1712 Status = Ip6ParseAddressListFromString (
1713 IfrNvData->GatewayAddress,
1714 &Ip6NvData->GatewayAddress,
1715 &Ip6NvData->GatewayAddressCount
1716 );
1717 if (EFI_ERROR (Status)) {
1718 CreatePopUp (
1719 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
1720 &Key,
1721 L"Invalid Gateway Addresses!",
1722 NULL
1723 );
1724 }
1725
1726 break;
1727
1728 case KEY_DNS_ADDRESS:
1729 Status = Ip6ParseAddressListFromString (
1730 IfrNvData->DnsAddress,
1731 &Ip6NvData->DnsAddress,
1732 &Ip6NvData->DnsAddressCount
1733 );
1734 if (EFI_ERROR (Status)) {
1735 CreatePopUp (
1736 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
1737 &Key,
1738 L"Invalid DNS Addresses!",
1739 NULL
1740 );
1741 }
1742
1743 break;
1744
1745 case KEY_SAVE_CONFIG_CHANGES:
1746 CopyMem (&OldIfrNvData, IfrNvData, sizeof (IP6_CONFIG_IFR_NVDATA));
1747 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;
1748 break;
1749
1750 case KEY_IGNORE_CONFIG_CHANGES:
1751 CopyMem (IfrNvData, &OldIfrNvData, sizeof (IP6_CONFIG_IFR_NVDATA));
1752 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD;
1753 break;
1754
1755 case KEY_SAVE_CHANGES:
1756 Status = Ip6ConvertIfrNvDataToConfigNvData (IfrNvData, Instance);
1757 if (EFI_ERROR (Status)) {
1758 break;
1759 }
1760
1761 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT;
1762 break;
1763
1764 case KEY_GET_CURRENT_SETTING:
1765 Ip6Config = &Instance->Ip6Config;
1766 HiiHandle = Instance->CallbackInfo.RegisteredHandle;
1767 Data = NULL;
1768
1769 //
1770 // Get current interface info.
1771 //
1772 Status = Ip6ConfigNvGetData (
1773 Ip6Config,
1774 Ip6ConfigDataTypeInterfaceInfo,
1775 &DataSize,
1776 (VOID **) &Data
1777 );
1778 if (EFI_ERROR (Status)) {
1779 return Status;
1780 }
1781
1782 //
1783 // Generate dynamic text opcode for host address and draw it.
1784 //
1785 IfInfo = (EFI_IP6_CONFIG_INTERFACE_INFO *) Data;
1786 Status = Ip6ConvertAddressListToString (
1787 PortString,
1788 HiiHandle,
1789 Ip6ConfigNvHostAddress,
1790 IfInfo->AddressInfo,
1791 IfInfo->AddressInfoCount
1792 );
1793 if (EFI_ERROR (Status)) {
1794 FreePool (Data);
1795 return Status;
1796 }
1797
1798 //
1799 // Generate the dynamic text opcode for route table and draw it.
1800 //
1801 Status = Ip6ConvertAddressListToString (
1802 PortString,
1803 HiiHandle,
1804 Ip6ConfigNvRouteTable,
1805 IfInfo->RouteTable,
1806 IfInfo->RouteCount
1807 );
1808 if (EFI_ERROR (Status)) {
1809 FreePool (Data);
1810 return Status;
1811 }
1812
1813 //
1814 // Get DNS server list.
1815 //
1816 FreePool (Data);
1817 DataSize = 0;
1818 Data = NULL;
1819 Status = Ip6ConfigNvGetData (
1820 Ip6Config,
1821 Ip6ConfigDataTypeDnsServer,
1822 &DataSize,
1823 (VOID **) &Data
1824 );
1825 if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
1826 if (Data != NULL) {
1827 FreePool (Data);
1828 }
1829 return Status;
1830 }
1831
1832 if (DataSize > 0) {
1833 //
1834 // Generate the dynamic text opcode for DNS server and draw it.
1835 //
1836 Status = Ip6ConvertAddressListToString (
1837 PortString,
1838 HiiHandle,
1839 Ip6ConfigNvDnsAddress,
1840 Data,
1841 DataSize / sizeof (EFI_IPv6_ADDRESS)
1842 );
1843 if (EFI_ERROR (Status)) {
1844 FreePool (Data);
1845 return Status;
1846 }
1847 }
1848
1849 //
1850 // Get gateway adderss list.
1851 //
1852 if (Data != NULL) {
1853 FreePool (Data);
1854 }
1855
1856 DataSize = 0;
1857 Data = NULL;
1858 Status = Ip6ConfigNvGetData (
1859 Ip6Config,
1860 Ip6ConfigDataTypeGateway,
1861 &DataSize,
1862 (VOID **) &Data
1863 );
1864 if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
1865 if (Data != NULL) {
1866 FreePool (Data);
1867 }
1868 return Status;
1869 }
1870
1871 if (DataSize > 0) {
1872 //
1873 // Generate the dynamic text opcode for gateway and draw it.
1874 //
1875 Status = Ip6ConvertAddressListToString (
1876 PortString,
1877 HiiHandle,
1878 Ip6ConfigNvGatewayAddress,
1879 Data,
1880 DataSize / sizeof (EFI_IPv6_ADDRESS)
1881 );
1882 if (EFI_ERROR (Status)) {
1883 FreePool (Data);
1884 return Status;
1885 }
1886 }
1887
1888 if (Data != NULL) {
1889 FreePool (Data);
1890 }
1891
1892 Status = EFI_SUCCESS;
1893
1894 break;
1895
1896 default:
1897 break;
1898 }
1899
1900 if (!EFI_ERROR (Status)) {
1901 //
1902 // Pass changed uncommitted data back to Form Browser.
1903 //
1904 BufferSize = sizeof (IP6_CONFIG_IFR_NVDATA);
1905 HiiSetBrowserData (NULL, NULL, BufferSize, (UINT8 *) IfrNvData, NULL);
1906 }
1907
1908 FreePool (IfrNvData);
1909 return Status;
1910 }
1911
1912 /**
1913 Install HII Config Access protocol for network device and allocate resources.
1914
1915 @param[in, out] Instance The IP6_CONFIG_INSTANCE to create a form.
1916
1917 @retval EFI_SUCCESS The HII Config Access protocol is installed.
1918 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
1919 @retval Others Other errors as indicated.
1920
1921 **/
1922 EFI_STATUS
1923 Ip6ConfigFormInit (
1924 IN OUT IP6_CONFIG_INSTANCE *Instance
1925 )
1926 {
1927 EFI_STATUS Status;
1928 IP6_SERVICE *IpSb;
1929 IP6_FORM_CALLBACK_INFO *CallbackInfo;
1930 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;
1931 VENDOR_DEVICE_PATH VendorDeviceNode;
1932 EFI_SERVICE_BINDING_PROTOCOL *MnpSb;
1933 CHAR16 *MacString;
1934 CHAR16 MenuString[128];
1935 CHAR16 PortString[128];
1936 CHAR16 *OldMenuString;
1937 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
1938
1939 IpSb = IP6_SERVICE_FROM_IP6_CONFIG_INSTANCE (Instance);
1940 ASSERT (IpSb != NULL);
1941
1942 Status = gBS->HandleProtocol (
1943 IpSb->Controller,
1944 &gEfiDevicePathProtocolGuid,
1945 (VOID **) &ParentDevicePath
1946 );
1947 if (EFI_ERROR (Status)) {
1948 return Status;
1949 }
1950
1951 CallbackInfo = &Instance->CallbackInfo;
1952 CallbackInfo->Signature = IP6_FORM_CALLBACK_INFO_SIGNATURE;
1953
1954 //
1955 // Construct device path node for EFI HII Config Access protocol,
1956 // which consists of controller physical device path and one hardware
1957 // vendor guid node.
1958 //
1959 ZeroMem (&VendorDeviceNode, sizeof (VENDOR_DEVICE_PATH));
1960 VendorDeviceNode.Header.Type = HARDWARE_DEVICE_PATH;
1961 VendorDeviceNode.Header.SubType = HW_VENDOR_DP;
1962
1963 CopyGuid (&VendorDeviceNode.Guid, &gEfiCallerIdGuid);
1964
1965 SetDevicePathNodeLength (&VendorDeviceNode.Header, sizeof (VENDOR_DEVICE_PATH));
1966 CallbackInfo->HiiVendorDevicePath = AppendDevicePathNode (
1967 ParentDevicePath,
1968 (EFI_DEVICE_PATH_PROTOCOL *) &VendorDeviceNode
1969 );
1970 if (CallbackInfo->HiiVendorDevicePath == NULL) {
1971 Status = EFI_OUT_OF_RESOURCES;
1972 goto Error;
1973 }
1974
1975 ConfigAccess = &CallbackInfo->HiiConfigAccess;
1976 ConfigAccess->ExtractConfig = Ip6FormExtractConfig;
1977 ConfigAccess->RouteConfig = Ip6FormRouteConfig;
1978 ConfigAccess->Callback = Ip6FormCallback;
1979
1980 //
1981 // Install Device Path Protocol and Config Access protocol on new handle
1982 //
1983 Status = gBS->InstallMultipleProtocolInterfaces (
1984 &CallbackInfo->ChildHandle,
1985 &gEfiDevicePathProtocolGuid,
1986 CallbackInfo->HiiVendorDevicePath,
1987 &gEfiHiiConfigAccessProtocolGuid,
1988 ConfigAccess,
1989 NULL
1990 );
1991 if (!EFI_ERROR (Status)) {
1992 //
1993 // Open the Parent Handle for the child
1994 //
1995 Status = gBS->OpenProtocol (
1996 IpSb->Controller,
1997 &gEfiManagedNetworkServiceBindingProtocolGuid,
1998 (VOID **) &MnpSb,
1999 IpSb->Image,
2000 CallbackInfo->ChildHandle,
2001 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
2002 );
2003 }
2004
2005 if (EFI_ERROR (Status)) {
2006 goto Error;
2007 }
2008
2009 //
2010 // Publish our HII data
2011 //
2012 CallbackInfo->RegisteredHandle = HiiAddPackages (
2013 &gIp6ConfigNvDataGuid,
2014 CallbackInfo->ChildHandle,
2015 Ip6DxeStrings,
2016 Ip6ConfigBin,
2017 NULL
2018 );
2019 if (CallbackInfo->RegisteredHandle == NULL) {
2020 Status = EFI_OUT_OF_RESOURCES;
2021 goto Error;
2022 }
2023
2024 //
2025 // Append MAC string in the menu help string and tile help string
2026 //
2027 Status = NetLibGetMacString (IpSb->Controller, IpSb->Image, &MacString);
2028 if (!EFI_ERROR (Status)) {
2029 OldMenuString = HiiGetString (
2030 CallbackInfo->RegisteredHandle,
2031 STRING_TOKEN (STR_IP6_CONFIG_FORM_HELP),
2032 NULL)
2033 ;
2034 UnicodeSPrint (MenuString, 128, L"%s (MAC:%s)", OldMenuString, MacString);
2035 HiiSetString (
2036 CallbackInfo->RegisteredHandle,
2037 STRING_TOKEN (STR_IP6_CONFIG_FORM_HELP),
2038 MenuString,
2039 NULL
2040 );
2041 UnicodeSPrint (PortString, 128, L"MAC:%s", MacString);
2042 HiiSetString (
2043 CallbackInfo->RegisteredHandle,
2044 STRING_TOKEN (STR_IP6_DEVICE_FORM_HELP),
2045 PortString,
2046 NULL
2047 );
2048
2049 FreePool (MacString);
2050 FreePool (OldMenuString);
2051
2052 InitializeListHead (&Instance->Ip6NvData.ManualAddress);
2053 InitializeListHead (&Instance->Ip6NvData.GatewayAddress);
2054 InitializeListHead (&Instance->Ip6NvData.DnsAddress);
2055
2056 return EFI_SUCCESS;
2057 }
2058
2059 Error:
2060 Ip6ConfigFormUnload (Instance);
2061 return Status;
2062 }
2063
2064 /**
2065 Uninstall the HII Config Access protocol for network devices and free up the resources.
2066
2067 @param[in, out] Instance The IP6_CONFIG_INSTANCE to unload a form.
2068
2069 **/
2070 VOID
2071 Ip6ConfigFormUnload (
2072 IN OUT IP6_CONFIG_INSTANCE *Instance
2073 )
2074 {
2075 IP6_SERVICE *IpSb;
2076 IP6_FORM_CALLBACK_INFO *CallbackInfo;
2077 IP6_CONFIG_NVDATA *Ip6NvData;
2078
2079 IpSb = IP6_SERVICE_FROM_IP6_CONFIG_INSTANCE (Instance);
2080 ASSERT (IpSb != NULL);
2081
2082 CallbackInfo = &Instance->CallbackInfo;
2083
2084 if (CallbackInfo->ChildHandle != NULL) {
2085
2086 //
2087 // Close the child handle
2088 //
2089 gBS->CloseProtocol (
2090 IpSb->Controller,
2091 &gEfiManagedNetworkServiceBindingProtocolGuid,
2092 IpSb->Image,
2093 CallbackInfo->ChildHandle
2094 );
2095 //
2096 // Uninstall EFI_HII_CONFIG_ACCESS_PROTOCOL
2097 //
2098 gBS->UninstallMultipleProtocolInterfaces (
2099 CallbackInfo->ChildHandle,
2100 &gEfiDevicePathProtocolGuid,
2101 CallbackInfo->HiiVendorDevicePath,
2102 &gEfiHiiConfigAccessProtocolGuid,
2103 &CallbackInfo->HiiConfigAccess,
2104 NULL
2105 );
2106 }
2107
2108 if (CallbackInfo->HiiVendorDevicePath != NULL) {
2109 FreePool (CallbackInfo->HiiVendorDevicePath);
2110 }
2111
2112 if (CallbackInfo->RegisteredHandle != NULL) {
2113 //
2114 // Remove HII package list
2115 //
2116 HiiRemovePackages (CallbackInfo->RegisteredHandle);
2117 }
2118
2119 Ip6NvData = &Instance->Ip6NvData;
2120
2121 Ip6FreeAddressInfoList (&Ip6NvData->ManualAddress);
2122 Ip6FreeAddressInfoList (&Ip6NvData->GatewayAddress);
2123 Ip6FreeAddressInfoList (&Ip6NvData->DnsAddress);
2124
2125 Ip6NvData->ManualAddressCount = 0;
2126 Ip6NvData->GatewayAddressCount = 0;
2127 Ip6NvData->DnsAddressCount = 0;
2128 }