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