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