]> git.proxmox.com Git - mirror_edk2.git/blob - NetworkPkg/Ip6Dxe/Ip6ConfigNv.c
update the comments.
[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, 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) {
1653 //
1654 // Update main Form when main Form is opened.
1655 // This will be done only in FORM_OPEN CallBack of question with KEY_INTERFACE_ID from main Form.
1656 //
1657 if (QuestionId != KEY_INTERFACE_ID) {
1658 return EFI_SUCCESS;
1659 }
1660
1661 Ip6Config = &Instance->Ip6Config;
1662 HiiHandle = Instance->CallbackInfo.RegisteredHandle;
1663
1664 //
1665 // Get the current interface info.
1666 //
1667 Status = Ip6ConfigNvGetData (
1668 Ip6Config,
1669 Ip6ConfigDataTypeInterfaceInfo,
1670 &DataSize,
1671 (VOID **) &Data
1672 );
1673 if (EFI_ERROR (Status)) {
1674 goto Exit;
1675 }
1676
1677 //
1678 // Generate the dynamic text opcode for host address and draw it.
1679 //
1680 IfInfo = (EFI_IP6_CONFIG_INTERFACE_INFO *) Data;
1681 Status = Ip6ConvertAddressListToString (
1682 PortString,
1683 HiiHandle,
1684 Ip6ConfigNvHostAddress,
1685 IfInfo->AddressInfo,
1686 IfInfo->AddressInfoCount
1687 );
1688 if (EFI_ERROR (Status)) {
1689 goto Exit;
1690 }
1691
1692 //
1693 // Generate the dynamic text opcode for route table and draw it.
1694 //
1695 Status = Ip6ConvertAddressListToString (
1696 PortString,
1697 HiiHandle,
1698 Ip6ConfigNvRouteTable,
1699 IfInfo->RouteTable,
1700 IfInfo->RouteCount
1701 );
1702 if (EFI_ERROR (Status)) {
1703 goto Exit;
1704 }
1705
1706 //
1707 // Get DNS server list.
1708 //
1709 DataSize = 0;
1710 Status = Ip6ConfigNvGetData (
1711 Ip6Config,
1712 Ip6ConfigDataTypeDnsServer,
1713 &DataSize,
1714 (VOID **) &Data
1715 );
1716 if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
1717 goto Exit;
1718 }
1719
1720 if (DataSize > 0) {
1721 //
1722 // Generate the dynamic text opcode for DNS server and draw it.
1723 //
1724 Status = Ip6ConvertAddressListToString (
1725 PortString,
1726 HiiHandle,
1727 Ip6ConfigNvDnsAddress,
1728 Data,
1729 DataSize / sizeof (EFI_IPv6_ADDRESS)
1730 );
1731 if (EFI_ERROR (Status)) {
1732 goto Exit;
1733 }
1734 }
1735
1736 //
1737 // Get gateway adderss list.
1738 //
1739 DataSize = 0;
1740 Status = Ip6ConfigNvGetData (
1741 Ip6Config,
1742 Ip6ConfigDataTypeGateway,
1743 &DataSize,
1744 (VOID **) &Data
1745 );
1746 if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
1747 goto Exit;
1748 }
1749
1750 if (DataSize > 0) {
1751 //
1752 // Generate the dynamic text opcode for gateway and draw it.
1753 //
1754 Status = Ip6ConvertAddressListToString (
1755 PortString,
1756 HiiHandle,
1757 Ip6ConfigNvGatewayAddress,
1758 Data,
1759 DataSize / sizeof (EFI_IPv6_ADDRESS)
1760 );
1761 if (EFI_ERROR (Status)) {
1762 goto Exit;
1763 }
1764 }
1765
1766 Exit:
1767 FreePool (Data);
1768 return Status;
1769 }
1770
1771 if (Action == EFI_BROWSER_ACTION_FORM_CLOSE) {
1772 //
1773 // Do nothing for UEFI FORM_CLOSE action
1774 //
1775 return EFI_SUCCESS;
1776 }
1777
1778 if ((Value == NULL) || (ActionRequest == NULL)) {
1779 return EFI_INVALID_PARAMETER;
1780 }
1781
1782 //
1783 // Retrieve uncommitted data from Browser
1784 //
1785
1786 BufferSize = sizeof (IP6_CONFIG_IFR_NVDATA);
1787 IfrNvData = AllocateZeroPool (BufferSize);
1788 if (IfrNvData == NULL) {
1789 return EFI_OUT_OF_RESOURCES;
1790 }
1791
1792 Status = EFI_SUCCESS;
1793
1794 ZeroMem (&OldIfrNvData, BufferSize);
1795
1796 HiiGetBrowserData (NULL, NULL, BufferSize, (UINT8 *) IfrNvData);
1797
1798 CopyMem (&OldIfrNvData, IfrNvData, BufferSize);
1799
1800 switch (QuestionId) {
1801 case KEY_INTERFACE_ID:
1802 Status = Ip6ParseInterfaceIdFromString (IfrNvData->InterfaceId, &Ip6NvData->InterfaceId);
1803 if (EFI_ERROR (Status)) {
1804 CreatePopUp (
1805 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
1806 &Key,
1807 L"Invalid Interface ID!",
1808 NULL
1809 );
1810 }
1811
1812 break;
1813
1814 case KEY_MANUAL_ADDRESS:
1815 Status = Ip6ParseAddressListFromString (
1816 IfrNvData->ManualAddress,
1817 &Ip6NvData->ManualAddress,
1818 &Ip6NvData->ManualAddressCount
1819 );
1820 if (EFI_ERROR (Status)) {
1821 CreatePopUp (
1822 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
1823 &Key,
1824 L"Invalid Host Addresses!",
1825 NULL
1826 );
1827 }
1828
1829 break;
1830
1831 case KEY_GATEWAY_ADDRESS:
1832 Status = Ip6ParseAddressListFromString (
1833 IfrNvData->GatewayAddress,
1834 &Ip6NvData->GatewayAddress,
1835 &Ip6NvData->GatewayAddressCount
1836 );
1837 if (EFI_ERROR (Status)) {
1838 CreatePopUp (
1839 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
1840 &Key,
1841 L"Invalid Gateway Addresses!",
1842 NULL
1843 );
1844 }
1845
1846 break;
1847
1848 case KEY_DNS_ADDRESS:
1849 Status = Ip6ParseAddressListFromString (
1850 IfrNvData->DnsAddress,
1851 &Ip6NvData->DnsAddress,
1852 &Ip6NvData->DnsAddressCount
1853 );
1854 if (EFI_ERROR (Status)) {
1855 CreatePopUp (
1856 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
1857 &Key,
1858 L"Invalid DNS Addresses!",
1859 NULL
1860 );
1861 }
1862
1863 break;
1864
1865 case KEY_SAVE_CONFIG_CHANGES:
1866 CopyMem (&OldIfrNvData, IfrNvData, sizeof (IP6_CONFIG_IFR_NVDATA));
1867 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT;
1868 break;
1869
1870 case KEY_IGNORE_CONFIG_CHANGES:
1871 CopyMem (IfrNvData, &OldIfrNvData, sizeof (IP6_CONFIG_IFR_NVDATA));
1872 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT;
1873 break;
1874
1875 case KEY_SAVE_CHANGES:
1876 Status = Ip6ConvertIfrNvDataToConfigNvData (IfrNvData, Instance);
1877 if (EFI_ERROR (Status)) {
1878 break;
1879 }
1880
1881 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;
1882 break;
1883
1884 default:
1885 break;
1886 }
1887
1888 if (!EFI_ERROR (Status)) {
1889 //
1890 // Pass changed uncommitted data back to Form Browser.
1891 //
1892 BufferSize = sizeof (IP6_CONFIG_IFR_NVDATA);
1893 HiiSetBrowserData (NULL, NULL, BufferSize, (UINT8 *) IfrNvData, NULL);
1894 }
1895
1896 FreePool (IfrNvData);
1897 return Status;
1898 }
1899
1900 /**
1901 Install HII Config Access protocol for network device and allocate resources.
1902
1903 @param[in, out] Instance The IP6_CONFIG_INSTANCE to create a form.
1904
1905 @retval EFI_SUCCESS The HII Config Access protocol is installed.
1906 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
1907 @retval Others Other errors as indicated.
1908
1909 **/
1910 EFI_STATUS
1911 Ip6ConfigFormInit (
1912 IN OUT IP6_CONFIG_INSTANCE *Instance
1913 )
1914 {
1915 EFI_STATUS Status;
1916 IP6_SERVICE *IpSb;
1917 IP6_FORM_CALLBACK_INFO *CallbackInfo;
1918 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;
1919 VENDOR_DEVICE_PATH VendorDeviceNode;
1920 EFI_SERVICE_BINDING_PROTOCOL *MnpSb;
1921 CHAR16 *MacString;
1922 CHAR16 MenuString[128];
1923 CHAR16 PortString[128];
1924 CHAR16 *OldMenuString;
1925 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
1926
1927 IpSb = IP6_SERVICE_FROM_IP6_CONFIG_INSTANCE (Instance);
1928 ASSERT (IpSb != NULL);
1929
1930 Status = gBS->HandleProtocol (
1931 IpSb->Controller,
1932 &gEfiDevicePathProtocolGuid,
1933 (VOID **) &ParentDevicePath
1934 );
1935 if (EFI_ERROR (Status)) {
1936 return Status;
1937 }
1938
1939 CallbackInfo = &Instance->CallbackInfo;
1940 CallbackInfo->Signature = IP6_FORM_CALLBACK_INFO_SIGNATURE;
1941
1942 //
1943 // Construct device path node for EFI HII Config Access protocol,
1944 // which consists of controller physical device path and one hardware
1945 // vendor guid node.
1946 //
1947 ZeroMem (&VendorDeviceNode, sizeof (VENDOR_DEVICE_PATH));
1948 VendorDeviceNode.Header.Type = HARDWARE_DEVICE_PATH;
1949 VendorDeviceNode.Header.SubType = HW_VENDOR_DP;
1950
1951 CopyGuid (&VendorDeviceNode.Guid, &mIp6HiiVendorDevicePathGuid);
1952
1953 SetDevicePathNodeLength (&VendorDeviceNode.Header, sizeof (VENDOR_DEVICE_PATH));
1954 CallbackInfo->HiiVendorDevicePath = AppendDevicePathNode (
1955 ParentDevicePath,
1956 (EFI_DEVICE_PATH_PROTOCOL *) &VendorDeviceNode
1957 );
1958 if (CallbackInfo->HiiVendorDevicePath == NULL) {
1959 Status = EFI_OUT_OF_RESOURCES;
1960 goto Error;
1961 }
1962
1963 ConfigAccess = &CallbackInfo->HiiConfigAccess;
1964 ConfigAccess->ExtractConfig = Ip6FormExtractConfig;
1965 ConfigAccess->RouteConfig = Ip6FormRouteConfig;
1966 ConfigAccess->Callback = Ip6FormCallback;
1967
1968 //
1969 // Install Device Path Protocol and Config Access protocol on new handle
1970 //
1971 Status = gBS->InstallMultipleProtocolInterfaces (
1972 &CallbackInfo->ChildHandle,
1973 &gEfiDevicePathProtocolGuid,
1974 CallbackInfo->HiiVendorDevicePath,
1975 &gEfiHiiConfigAccessProtocolGuid,
1976 ConfigAccess,
1977 NULL
1978 );
1979 if (!EFI_ERROR (Status)) {
1980 //
1981 // Open the Parent Handle for the child
1982 //
1983 Status = gBS->OpenProtocol (
1984 IpSb->Controller,
1985 &gEfiManagedNetworkServiceBindingProtocolGuid,
1986 (VOID **) &MnpSb,
1987 IpSb->Image,
1988 CallbackInfo->ChildHandle,
1989 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
1990 );
1991 }
1992
1993 if (EFI_ERROR (Status)) {
1994 goto Error;
1995 }
1996
1997 //
1998 // Publish our HII data
1999 //
2000 CallbackInfo->RegisteredHandle = HiiAddPackages (
2001 &mIp6ConfigNvDataGuid,
2002 CallbackInfo->ChildHandle,
2003 Ip6DxeStrings,
2004 Ip6ConfigBin,
2005 NULL
2006 );
2007 if (CallbackInfo->RegisteredHandle == NULL) {
2008 Status = EFI_OUT_OF_RESOURCES;
2009 goto Error;
2010 }
2011
2012 //
2013 // Append MAC string in the menu help string and tile help string
2014 //
2015 Status = NetLibGetMacString (IpSb->Controller, IpSb->Image, &MacString);
2016 if (!EFI_ERROR (Status)) {
2017 OldMenuString = HiiGetString (
2018 CallbackInfo->RegisteredHandle,
2019 STRING_TOKEN (STR_IP6_CONFIG_FORM_HELP),
2020 NULL)
2021 ;
2022 UnicodeSPrint (MenuString, 128, L"%s (MAC:%s)", OldMenuString, MacString);
2023 HiiSetString (
2024 CallbackInfo->RegisteredHandle,
2025 STRING_TOKEN (STR_IP6_CONFIG_FORM_HELP),
2026 MenuString,
2027 NULL
2028 );
2029 UnicodeSPrint (PortString, 128, L"MAC:%s", MacString);
2030 HiiSetString (
2031 CallbackInfo->RegisteredHandle,
2032 STRING_TOKEN (STR_IP6_DEVICE_FORM_HELP),
2033 PortString,
2034 NULL
2035 );
2036
2037 FreePool (MacString);
2038 FreePool (OldMenuString);
2039
2040 InitializeListHead (&Instance->Ip6NvData.ManualAddress);
2041 InitializeListHead (&Instance->Ip6NvData.GatewayAddress);
2042 InitializeListHead (&Instance->Ip6NvData.DnsAddress);
2043
2044 return EFI_SUCCESS;
2045 }
2046
2047 Error:
2048 Ip6ConfigFormUnload (Instance);
2049 return Status;
2050 }
2051
2052 /**
2053 Uninstall the HII Config Access protocol for network devices and free up the resources.
2054
2055 @param[in, out] Instance The IP6_CONFIG_INSTANCE to unload a form.
2056
2057 **/
2058 VOID
2059 Ip6ConfigFormUnload (
2060 IN OUT IP6_CONFIG_INSTANCE *Instance
2061 )
2062 {
2063 IP6_SERVICE *IpSb;
2064 IP6_FORM_CALLBACK_INFO *CallbackInfo;
2065 IP6_CONFIG_NVDATA *Ip6NvData;
2066
2067 IpSb = IP6_SERVICE_FROM_IP6_CONFIG_INSTANCE (Instance);
2068 ASSERT (IpSb != NULL);
2069
2070 CallbackInfo = &Instance->CallbackInfo;
2071
2072 if (CallbackInfo->ChildHandle != NULL) {
2073
2074 //
2075 // Close the child handle
2076 //
2077 gBS->CloseProtocol (
2078 IpSb->Controller,
2079 &gEfiManagedNetworkServiceBindingProtocolGuid,
2080 IpSb->Image,
2081 CallbackInfo->ChildHandle
2082 );
2083 //
2084 // Uninstall EFI_HII_CONFIG_ACCESS_PROTOCOL
2085 //
2086 gBS->UninstallMultipleProtocolInterfaces (
2087 CallbackInfo->ChildHandle,
2088 &gEfiDevicePathProtocolGuid,
2089 CallbackInfo->HiiVendorDevicePath,
2090 &gEfiHiiConfigAccessProtocolGuid,
2091 &CallbackInfo->HiiConfigAccess,
2092 NULL
2093 );
2094 }
2095
2096 if (CallbackInfo->HiiVendorDevicePath != NULL) {
2097 FreePool (CallbackInfo->HiiVendorDevicePath);
2098 }
2099
2100 if (CallbackInfo->RegisteredHandle != NULL) {
2101 //
2102 // Remove HII package list
2103 //
2104 HiiRemovePackages (CallbackInfo->RegisteredHandle);
2105 }
2106
2107 Ip6NvData = &Instance->Ip6NvData;
2108
2109 Ip6FreeAddressInfoList (&Ip6NvData->ManualAddress);
2110 Ip6FreeAddressInfoList (&Ip6NvData->GatewayAddress);
2111 Ip6FreeAddressInfoList (&Ip6NvData->DnsAddress);
2112
2113 Ip6NvData->ManualAddressCount = 0;
2114 Ip6NvData->GatewayAddressCount = 0;
2115 Ip6NvData->DnsAddressCount = 0;
2116 }