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