1 /** @file 2 HII Library implementation that uses DXE protocols and services. 3 4 Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR> 5 This program and the accompanying materials 6 are licensed and made available under the terms and conditions of the BSD License 7 which accompanies this distribution. The full text of the license may be found at 8 http://opensource.org/licenses/bsd-license.php 9 10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 12 13 **/ 14 15 #include "InternalHiiLib.h" 16 17 #define GUID_CONFIG_STRING_TYPE 0x00 18 #define NAME_CONFIG_STRING_TYPE 0x01 19 #define PATH_CONFIG_STRING_TYPE 0x02 20 21 #define ACTION_SET_DEFAUTL_VALUE 0x01 22 #define ACTION_VALIDATE_SETTING 0x02 23 24 #define HII_LIB_DEFAULT_VARSTORE_SIZE 0x200 25 26 typedef struct { 27 LIST_ENTRY Entry; // Link to Block array 28 UINT16 Offset; 29 UINT16 Width; 30 UINT8 OpCode; 31 UINT8 Scope; 32 } IFR_BLOCK_DATA; 33 34 typedef struct { 35 EFI_VARSTORE_ID VarStoreId; 36 UINT16 Size; 37 } IFR_VARSTORAGE_DATA; 38 39 // 40 // <ConfigHdr> Template 41 // 42 GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR16 mConfigHdrTemplate[] = L"GUID=00000000000000000000000000000000&NAME=0000&PATH=00"; 43 44 EFI_FORM_BROWSER2_PROTOCOL *mUefiFormBrowser2 = NULL; 45 46 // 47 // Template used to mark the end of a list of packages 48 // 49 GLOBAL_REMOVE_IF_UNREFERENCED CONST EFI_HII_PACKAGE_HEADER mEndOfPakageList = { 50 sizeof (EFI_HII_PACKAGE_HEADER), 51 EFI_HII_PACKAGE_END 52 }; 53 54 /** 55 Extract Hii package list GUID for given HII handle. 56 57 If HiiHandle could not be found in the HII database, then ASSERT. 58 If Guid is NULL, then ASSERT. 59 60 @param Handle Hii handle 61 @param Guid Package list GUID 62 63 @retval EFI_SUCCESS Successfully extract GUID from Hii database. 64 65 **/ 66 EFI_STATUS 67 EFIAPI 68 InternalHiiExtractGuidFromHiiHandle ( 69 IN EFI_HII_HANDLE Handle, 70 OUT EFI_GUID *Guid 71 ) 72 { 73 EFI_STATUS Status; 74 UINTN BufferSize; 75 EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList; 76 77 ASSERT (Guid != NULL); 78 ASSERT (Handle != NULL); 79 80 // 81 // Get HII PackageList 82 // 83 BufferSize = 0; 84 HiiPackageList = NULL; 85 86 Status = gHiiDatabase->ExportPackageLists (gHiiDatabase, Handle, &BufferSize, HiiPackageList); 87 ASSERT (Status != EFI_NOT_FOUND); 88 89 if (Status == EFI_BUFFER_TOO_SMALL) { 90 HiiPackageList = AllocatePool (BufferSize); 91 ASSERT (HiiPackageList != NULL); 92 93 Status = gHiiDatabase->ExportPackageLists (gHiiDatabase, Handle, &BufferSize, HiiPackageList); 94 } 95 if (EFI_ERROR (Status)) { 96 FreePool (HiiPackageList); 97 return Status; 98 } 99 100 // 101 // Extract GUID 102 // 103 CopyGuid (Guid, &HiiPackageList->PackageListGuid); 104 105 FreePool (HiiPackageList); 106 107 return EFI_SUCCESS; 108 } 109 110 /** 111 Registers a list of packages in the HII Database and returns the HII Handle 112 associated with that registration. If an HII Handle has already been registered 113 with the same PackageListGuid and DeviceHandle, then NULL is returned. If there 114 are not enough resources to perform the registration, then NULL is returned. 115 If an empty list of packages is passed in, then NULL is returned. If the size of 116 the list of package is 0, then NULL is returned. 117 118 The variable arguments are pointers which point to package header that defined 119 by UEFI VFR compiler and StringGather tool. 120 121 #pragma pack (push, 1) 122 typedef struct { 123 UINT32 BinaryLength; 124 EFI_HII_PACKAGE_HEADER PackageHeader; 125 } EDKII_AUTOGEN_PACKAGES_HEADER; 126 #pragma pack (pop) 127 128 @param[in] PackageListGuid The GUID of the package list. 129 @param[in] DeviceHandle If not NULL, the Device Handle on which 130 an instance of DEVICE_PATH_PROTOCOL is installed. 131 This Device Handle uniquely defines the device that 132 the added packages are associated with. 133 @param[in] ... The variable argument list that contains pointers 134 to packages terminated by a NULL. 135 136 @retval NULL A HII Handle has already been registered in the HII Database with 137 the same PackageListGuid and DeviceHandle. 138 @retval NULL The HII Handle could not be created. 139 @retval NULL An empty list of packages was passed in. 140 @retval NULL All packages are empty. 141 @retval Other The HII Handle associated with the newly registered package list. 142 143 **/ 144 EFI_HII_HANDLE 145 EFIAPI 146 HiiAddPackages ( 147 IN CONST EFI_GUID *PackageListGuid, 148 IN EFI_HANDLE DeviceHandle OPTIONAL, 149 ... 150 ) 151 { 152 EFI_STATUS Status; 153 VA_LIST Args; 154 UINT32 *Package; 155 EFI_HII_PACKAGE_LIST_HEADER *PackageListHeader; 156 EFI_HII_HANDLE HiiHandle; 157 UINT32 Length; 158 UINT8 *Data; 159 160 ASSERT (PackageListGuid != NULL); 161 162 // 163 // Calculate the length of all the packages in the variable argument list 164 // 165 for (Length = 0, VA_START (Args, DeviceHandle); (Package = VA_ARG (Args, UINT32 *)) != NULL; ) { 166 Length += (ReadUnaligned32 (Package) - sizeof (UINT32)); 167 } 168 VA_END (Args); 169 170 // 171 // If there are no packages in the variable argument list or all the packages 172 // are empty, then return a NULL HII Handle 173 // 174 if (Length == 0) { 175 return NULL; 176 } 177 178 // 179 // Add the length of the Package List Header and the terminating Package Header 180 // 181 Length += sizeof (EFI_HII_PACKAGE_LIST_HEADER) + sizeof (EFI_HII_PACKAGE_HEADER); 182 183 // 184 // Allocate the storage for the entire Package List 185 // 186 PackageListHeader = AllocateZeroPool (Length); 187 188 // 189 // If the Package List can not be allocated, then return a NULL HII Handle 190 // 191 if (PackageListHeader == NULL) { 192 return NULL; 193 } 194 195 // 196 // Fill in the GUID and Length of the Package List Header 197 // 198 CopyGuid (&PackageListHeader->PackageListGuid, PackageListGuid); 199 PackageListHeader->PackageLength = Length; 200 201 // 202 // Initialize a pointer to the beginning if the Package List data 203 // 204 Data = (UINT8 *)(PackageListHeader + 1); 205 206 // 207 // Copy the data from each package in the variable argument list 208 // 209 for (VA_START (Args, DeviceHandle); (Package = VA_ARG (Args, UINT32 *)) != NULL; ) { 210 Length = ReadUnaligned32 (Package) - sizeof (UINT32); 211 CopyMem (Data, Package + 1, Length); 212 Data += Length; 213 } 214 VA_END (Args); 215 216 // 217 // Append a package of type EFI_HII_PACKAGE_END to mark the end of the package list 218 // 219 CopyMem (Data, &mEndOfPakageList, sizeof (mEndOfPakageList)); 220 221 // 222 // Register the package list with the HII Database 223 // 224 Status = gHiiDatabase->NewPackageList ( 225 gHiiDatabase, 226 PackageListHeader, 227 DeviceHandle, 228 &HiiHandle 229 ); 230 if (EFI_ERROR (Status)) { 231 HiiHandle = NULL; 232 } 233 234 // 235 // Free the allocated package list 236 // 237 FreePool (PackageListHeader); 238 239 // 240 // Return the new HII Handle 241 // 242 return HiiHandle; 243 } 244 245 /** 246 Removes a package list from the HII database. 247 248 If HiiHandle is NULL, then ASSERT. 249 If HiiHandle is not a valid EFI_HII_HANDLE in the HII database, then ASSERT. 250 251 @param[in] HiiHandle The handle that was previously registered in the HII database 252 253 **/ 254 VOID 255 EFIAPI 256 HiiRemovePackages ( 257 IN EFI_HII_HANDLE HiiHandle 258 ) 259 { 260 EFI_STATUS Status; 261 262 ASSERT (HiiHandle != NULL); 263 Status = gHiiDatabase->RemovePackageList (gHiiDatabase, HiiHandle); 264 ASSERT_EFI_ERROR (Status); 265 } 266 267 268 /** 269 Retrieves the array of all the HII Handles or the HII handles of a specific 270 package list GUID in the HII Database. 271 This array is terminated with a NULL HII Handle. 272 This function allocates the returned array using AllocatePool(). 273 The caller is responsible for freeing the array with FreePool(). 274 275 @param[in] PackageListGuid An optional parameter that is used to request 276 HII Handles associated with a specific 277 Package List GUID. If this parameter is NULL, 278 then all the HII Handles in the HII Database 279 are returned. If this parameter is not NULL, 280 then zero or more HII Handles associated with 281 PackageListGuid are returned. 282 283 @retval NULL No HII handles were found in the HII database 284 @retval NULL The array of HII Handles could not be retrieved 285 @retval Other A pointer to the NULL terminated array of HII Handles 286 287 **/ 288 EFI_HII_HANDLE * 289 EFIAPI 290 HiiGetHiiHandles ( 291 IN CONST EFI_GUID *PackageListGuid OPTIONAL 292 ) 293 { 294 EFI_STATUS Status; 295 UINTN HandleBufferLength; 296 EFI_HII_HANDLE TempHiiHandleBuffer; 297 EFI_HII_HANDLE *HiiHandleBuffer; 298 EFI_GUID Guid; 299 UINTN Index1; 300 UINTN Index2; 301 302 // 303 // Retrieve the size required for the buffer of all HII handles. 304 // 305 HandleBufferLength = 0; 306 Status = gHiiDatabase->ListPackageLists ( 307 gHiiDatabase, 308 EFI_HII_PACKAGE_TYPE_ALL, 309 NULL, 310 &HandleBufferLength, 311 &TempHiiHandleBuffer 312 ); 313 314 // 315 // If ListPackageLists() returns EFI_SUCCESS for a zero size, 316 // then there are no HII handles in the HII database. If ListPackageLists() 317 // returns an error other than EFI_BUFFER_TOO_SMALL, then there are no HII 318 // handles in the HII database. 319 // 320 if (Status != EFI_BUFFER_TOO_SMALL) { 321 // 322 // Return NULL if the size can not be retrieved, or if there are no HII 323 // handles in the HII Database 324 // 325 return NULL; 326 } 327 328 // 329 // Allocate the array of HII handles to hold all the HII Handles and a NULL terminator 330 // 331 HiiHandleBuffer = AllocateZeroPool (HandleBufferLength + sizeof (EFI_HII_HANDLE)); 332 if (HiiHandleBuffer == NULL) { 333 // 334 // Return NULL if allocation fails. 335 // 336 return NULL; 337 } 338 339 // 340 // Retrieve the array of HII Handles in the HII Database 341 // 342 Status = gHiiDatabase->ListPackageLists ( 343 gHiiDatabase, 344 EFI_HII_PACKAGE_TYPE_ALL, 345 NULL, 346 &HandleBufferLength, 347 HiiHandleBuffer 348 ); 349 if (EFI_ERROR (Status)) { 350 // 351 // Free the buffer and return NULL if the HII handles can not be retrieved. 352 // 353 FreePool (HiiHandleBuffer); 354 return NULL; 355 } 356 357 if (PackageListGuid == NULL) { 358 // 359 // Return the NULL terminated array of HII handles in the HII Database 360 // 361 return HiiHandleBuffer; 362 } else { 363 for (Index1 = 0, Index2 = 0; HiiHandleBuffer[Index1] != NULL; Index1++) { 364 Status = InternalHiiExtractGuidFromHiiHandle (HiiHandleBuffer[Index1], &Guid); 365 ASSERT_EFI_ERROR (Status); 366 if (CompareGuid (&Guid, PackageListGuid)) { 367 HiiHandleBuffer[Index2++] = HiiHandleBuffer[Index1]; 368 } 369 } 370 if (Index2 > 0) { 371 HiiHandleBuffer[Index2] = NULL; 372 return HiiHandleBuffer; 373 } else { 374 FreePool (HiiHandleBuffer); 375 return NULL; 376 } 377 } 378 } 379 380 /** 381 This function allows a caller to extract the form set opcode form the Hii Handle. 382 The returned buffer is allocated using AllocatePool().The caller is responsible 383 for freeing the allocated buffer using FreePool(). 384 385 @param Handle The HII handle. 386 @param Buffer On return, points to a pointer which point to the buffer that contain the formset opcode. 387 @param BufferSize On return, points to the length of the buffer. 388 389 @retval EFI_OUT_OF_RESOURCES No enough memory resource is allocated. 390 @retval EFI_NOT_FOUND Can't find the package data for the input Handle. 391 @retval EFI_INVALID_PARAMETER The input parameters are not correct. 392 @retval EFI_SUCCESS Get the formset opcode from the hii handle successfully. 393 394 **/ 395 EFI_STATUS 396 EFIAPI 397 HiiGetFormSetFromHiiHandle( 398 IN EFI_HII_HANDLE Handle, 399 OUT EFI_IFR_FORM_SET **Buffer, 400 OUT UINTN *BufferSize 401 ) 402 { 403 EFI_STATUS Status; 404 UINTN PackageListSize; 405 UINTN TempSize; 406 EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList; 407 UINT8 *Package; 408 UINT8 *OpCodeData; 409 UINT8 *FormSetBuffer; 410 UINT8 *TempBuffer; 411 UINT32 Offset; 412 UINT32 Offset2; 413 UINT32 PackageListLength; 414 EFI_HII_PACKAGE_HEADER PackageHeader; 415 416 TempSize = 0; 417 FormSetBuffer = NULL; 418 TempBuffer = NULL; 419 420 // 421 // Get HII PackageList 422 // 423 PackageListSize = 0; 424 HiiPackageList = NULL; 425 Status = gHiiDatabase->ExportPackageLists (gHiiDatabase, Handle, &PackageListSize, HiiPackageList); 426 if (EFI_ERROR (Status) && (Status != EFI_BUFFER_TOO_SMALL)) { 427 return Status; 428 } 429 430 HiiPackageList = AllocatePool (PackageListSize); 431 if (HiiPackageList == NULL) { 432 return EFI_OUT_OF_RESOURCES; 433 } 434 435 Status = gHiiDatabase->ExportPackageLists (gHiiDatabase, Handle, &PackageListSize, HiiPackageList); 436 ASSERT_EFI_ERROR (Status); 437 438 // 439 // Get Form package from this HII package List 440 // 441 Status = EFI_NOT_FOUND; 442 Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER); 443 PackageListLength = ReadUnaligned32 (&HiiPackageList->PackageLength); 444 445 while (Offset < PackageListLength) { 446 Package = ((UINT8 *) HiiPackageList) + Offset; 447 CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER)); 448 Offset += PackageHeader.Length; 449 450 if (PackageHeader.Type != EFI_HII_PACKAGE_FORMS) { 451 continue; 452 } 453 454 // 455 // Search FormSet Opcode in this Form Package 456 // 457 Offset2 = sizeof (EFI_HII_PACKAGE_HEADER); 458 while (Offset2 < PackageHeader.Length) { 459 OpCodeData = Package + Offset2; 460 Offset2 += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length; 461 462 if (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode != EFI_IFR_FORM_SET_OP) { 463 continue; 464 } 465 466 if (FormSetBuffer != NULL){ 467 TempBuffer = AllocateCopyPool (TempSize + ((EFI_IFR_OP_HEADER *) OpCodeData)->Length, FormSetBuffer); 468 FreePool(FormSetBuffer); 469 FormSetBuffer = NULL; 470 if (TempBuffer == NULL) { 471 Status = EFI_OUT_OF_RESOURCES; 472 goto Done; 473 } 474 CopyMem (TempBuffer + TempSize, OpCodeData, ((EFI_IFR_OP_HEADER *) OpCodeData)->Length); 475 } else { 476 TempBuffer = AllocateCopyPool (TempSize + ((EFI_IFR_OP_HEADER *) OpCodeData)->Length, OpCodeData); 477 if (TempBuffer == NULL) { 478 Status = EFI_OUT_OF_RESOURCES; 479 goto Done; 480 } 481 } 482 TempSize += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length; 483 FormSetBuffer = TempBuffer; 484 485 Status = EFI_SUCCESS; 486 // 487 //One form package has one formset, exit current form package to search other form package in the packagelist. 488 // 489 break; 490 } 491 } 492 Done: 493 FreePool (HiiPackageList); 494 495 *BufferSize = TempSize; 496 *Buffer = (EFI_IFR_FORM_SET *)FormSetBuffer; 497 498 return Status; 499 } 500 501 /** 502 Converts all hex dtring characters in range ['A'..'F'] to ['a'..'f'] for 503 hex digits that appear between a '=' and a '&' in a config string. 504 505 If ConfigString is NULL, then ASSERT(). 506 507 @param[in] ConfigString Pointer to a Null-terminated Unicode string. 508 509 @return Pointer to the Null-terminated Unicode result string. 510 511 **/ 512 EFI_STRING 513 EFIAPI 514 InternalHiiLowerConfigString ( 515 IN EFI_STRING ConfigString 516 ) 517 { 518 EFI_STRING String; 519 BOOLEAN Lower; 520 521 ASSERT (ConfigString != NULL); 522 523 // 524 // Convert all hex digits in range [A-F] in the configuration header to [a-f] 525 // 526 for (String = ConfigString, Lower = FALSE; *String != L'\0'; String++) { 527 if (*String == L'=') { 528 Lower = TRUE; 529 } else if (*String == L'&') { 530 Lower = FALSE; 531 } else if (Lower && *String >= L'A' && *String <= L'F') { 532 *String = (CHAR16) (*String - L'A' + L'a'); 533 } 534 } 535 536 return ConfigString; 537 } 538 539 /** 540 Uses the BlockToConfig() service of the Config Routing Protocol to 541 convert <ConfigRequest> and a buffer to a <ConfigResp> 542 543 If ConfigRequest is NULL, then ASSERT(). 544 If Block is NULL, then ASSERT(). 545 546 @param[in] ConfigRequest Pointer to a Null-terminated Unicode string. 547 @param[in] Block Pointer to a block of data. 548 @param[in] BlockSize The zie, in bytes, of Block. 549 550 @retval NULL The <ConfigResp> string could not be generated. 551 @retval Other Pointer to the Null-terminated Unicode <ConfigResp> string. 552 553 **/ 554 EFI_STRING 555 EFIAPI 556 InternalHiiBlockToConfig ( 557 IN CONST EFI_STRING ConfigRequest, 558 IN CONST UINT8 *Block, 559 IN UINTN BlockSize 560 ) 561 { 562 EFI_STATUS Status; 563 EFI_STRING ConfigResp; 564 CHAR16 *Progress; 565 566 ASSERT (ConfigRequest != NULL); 567 ASSERT (Block != NULL); 568 569 // 570 // Convert <ConfigRequest> to <ConfigResp> 571 // 572 Status = gHiiConfigRouting->BlockToConfig ( 573 gHiiConfigRouting, 574 ConfigRequest, 575 Block, 576 BlockSize, 577 &ConfigResp, 578 &Progress 579 ); 580 if (EFI_ERROR (Status)) { 581 return NULL; 582 } 583 return ConfigResp; 584 } 585 586 /** 587 Uses the BrowserCallback() service of the Form Browser Protocol to retrieve 588 or set uncommitted data. If sata i being retrieved, then the buffer is 589 allocated using AllocatePool(). The caller is then responsible for freeing 590 the buffer using FreePool(). 591 592 @param[in] VariableGuid Pointer to an EFI_GUID structure. This is an optional 593 parameter that may be NULL. 594 @param[in] VariableName Pointer to a Null-terminated Unicode string. This 595 is an optional parameter that may be NULL. 596 @param[in] SetResultsData If not NULL, then this parameter specified the buffer 597 of uncommited data to set. If this parameter is NULL, 598 then the caller is requesting to get the uncommited data 599 from the Form Browser. 600 601 @retval NULL The uncommitted data could not be retrieved. 602 @retval Other A pointer to a buffer containing the uncommitted data. 603 604 **/ 605 EFI_STRING 606 EFIAPI 607 InternalHiiBrowserCallback ( 608 IN CONST EFI_GUID *VariableGuid, OPTIONAL 609 IN CONST CHAR16 *VariableName, OPTIONAL 610 IN CONST EFI_STRING SetResultsData OPTIONAL 611 ) 612 { 613 EFI_STATUS Status; 614 UINTN ResultsDataSize; 615 EFI_STRING ResultsData; 616 CHAR16 TempResultsData; 617 618 // 619 // Locate protocols 620 // 621 if (mUefiFormBrowser2 == NULL) { 622 Status = gBS->LocateProtocol (&gEfiFormBrowser2ProtocolGuid, NULL, (VOID **) &mUefiFormBrowser2); 623 if (EFI_ERROR (Status) || mUefiFormBrowser2 == NULL) { 624 return NULL; 625 } 626 } 627 628 ResultsDataSize = 0; 629 630 if (SetResultsData != NULL) { 631 // 632 // Request to to set data in the uncommitted browser state information 633 // 634 ResultsData = SetResultsData; 635 } else { 636 // 637 // Retrieve the length of the buffer required ResultsData from the Browser Callback 638 // 639 Status = mUefiFormBrowser2->BrowserCallback ( 640 mUefiFormBrowser2, 641 &ResultsDataSize, 642 &TempResultsData, 643 TRUE, 644 VariableGuid, 645 VariableName 646 ); 647 648 if (!EFI_ERROR (Status)) { 649 // 650 // No Resluts Data, only allocate one char for '\0' 651 // 652 ResultsData = AllocateZeroPool (sizeof (CHAR16)); 653 return ResultsData; 654 } 655 656 if (Status != EFI_BUFFER_TOO_SMALL) { 657 return NULL; 658 } 659 660 // 661 // Allocate the ResultsData buffer 662 // 663 ResultsData = AllocateZeroPool (ResultsDataSize); 664 if (ResultsData == NULL) { 665 return NULL; 666 } 667 } 668 669 // 670 // Retrieve or set the ResultsData from the Browser Callback 671 // 672 Status = mUefiFormBrowser2->BrowserCallback ( 673 mUefiFormBrowser2, 674 &ResultsDataSize, 675 ResultsData, 676 (BOOLEAN)(SetResultsData == NULL), 677 VariableGuid, 678 VariableName 679 ); 680 if (EFI_ERROR (Status)) { 681 return NULL; 682 } 683 684 return ResultsData; 685 } 686 687 /** 688 Allocates and returns a Null-terminated Unicode <ConfigHdr> string using routing 689 information that includes a GUID, an optional Unicode string name, and a device 690 path. The string returned is allocated with AllocatePool(). The caller is 691 responsible for freeing the allocated string with FreePool(). 692 693 The format of a <ConfigHdr> is as follows: 694 695 GUID=<HexCh>32&NAME=<Char>NameLength&PATH=<HexChar>DevicePathSize<Null> 696 697 @param[in] Guid Pointer to an EFI_GUID that is the routing information 698 GUID. Each of the 16 bytes in Guid is converted to 699 a 2 Unicode character hexadecimal string. This is 700 an optional parameter that may be NULL. 701 @param[in] Name Pointer to a Null-terminated Unicode string that is 702 the routing information NAME. This is an optional 703 parameter that may be NULL. Each 16-bit Unicode 704 character in Name is converted to a 4 character Unicode 705 hexadecimal string. 706 @param[in] DriverHandle The driver handle which supports a Device Path Protocol 707 that is the routing information PATH. Each byte of 708 the Device Path associated with DriverHandle is converted 709 to a 2 Unicode character hexadecimal string. 710 711 @retval NULL DriverHandle does not support the Device Path Protocol. 712 @retval Other A pointer to the Null-terminate Unicode <ConfigHdr> string 713 714 **/ 715 EFI_STRING 716 EFIAPI 717 HiiConstructConfigHdr ( 718 IN CONST EFI_GUID *Guid, OPTIONAL 719 IN CONST CHAR16 *Name, OPTIONAL 720 IN EFI_HANDLE DriverHandle 721 ) 722 { 723 UINTN NameLength; 724 EFI_DEVICE_PATH_PROTOCOL *DevicePath; 725 UINTN DevicePathSize; 726 CHAR16 *String; 727 CHAR16 *ReturnString; 728 UINTN Index; 729 UINT8 *Buffer; 730 UINTN MaxLen; 731 732 // 733 // Compute the length of Name in Unicode characters. 734 // If Name is NULL, then the length is 0. 735 // 736 NameLength = 0; 737 if (Name != NULL) { 738 NameLength = StrLen (Name); 739 } 740 741 DevicePath = NULL; 742 DevicePathSize = 0; 743 // 744 // Retrieve DevicePath Protocol associated with DriverHandle 745 // 746 if (DriverHandle != NULL) { 747 DevicePath = DevicePathFromHandle (DriverHandle); 748 if (DevicePath == NULL) { 749 return NULL; 750 } 751 // 752 // Compute the size of the device path in bytes 753 // 754 DevicePathSize = GetDevicePathSize (DevicePath); 755 } 756 757 // 758 // GUID=<HexCh>32&NAME=<Char>NameLength&PATH=<HexChar>DevicePathSize <Null> 759 // | 5 | sizeof (EFI_GUID) * 2 | 6 | NameStrLen*4 | 6 | DevicePathSize * 2 | 1 | 760 // 761 MaxLen = 5 + sizeof (EFI_GUID) * 2 + 6 + NameLength * 4 + 6 + DevicePathSize * 2 + 1; 762 String = AllocateZeroPool (MaxLen * sizeof (CHAR16)); 763 if (String == NULL) { 764 return NULL; 765 } 766 767 // 768 // Start with L"GUID=" 769 // 770 StrCpyS (String, MaxLen, L"GUID="); 771 ReturnString = String; 772 String += StrLen (String); 773 774 if (Guid != NULL) { 775 // 776 // Append Guid converted to <HexCh>32 777 // 778 for (Index = 0, Buffer = (UINT8 *)Guid; Index < sizeof (EFI_GUID); Index++) { 779 String += UnicodeValueToString (String, PREFIX_ZERO | RADIX_HEX, *(Buffer++), 2); 780 } 781 } 782 783 // 784 // Append L"&NAME=" 785 // 786 StrCatS (ReturnString, MaxLen, L"&NAME="); 787 String += StrLen (String); 788 789 if (Name != NULL) { 790 // 791 // Append Name converted to <Char>NameLength 792 // 793 for (; *Name != L'\0'; Name++) { 794 String += UnicodeValueToString (String, PREFIX_ZERO | RADIX_HEX, *Name, 4); 795 } 796 } 797 798 // 799 // Append L"&PATH=" 800 // 801 StrCatS (ReturnString, MaxLen, L"&PATH="); 802 String += StrLen (String); 803 804 // 805 // Append the device path associated with DriverHandle converted to <HexChar>DevicePathSize 806 // 807 for (Index = 0, Buffer = (UINT8 *)DevicePath; Index < DevicePathSize; Index++) { 808 String += UnicodeValueToString (String, PREFIX_ZERO | RADIX_HEX, *(Buffer++), 2); 809 } 810 811 // 812 // Null terminate the Unicode string 813 // 814 *String = L'\0'; 815 816 // 817 // Convert all hex digits in range [A-F] in the configuration header to [a-f] 818 // 819 return InternalHiiLowerConfigString (ReturnString); 820 } 821 822 /** 823 Convert the hex UNICODE encoding string of UEFI GUID, NAME or device path 824 to binary buffer from <ConfigHdr>. 825 826 This is a internal function. 827 828 @param String UEFI configuration string. 829 @param Flag Flag specifies what type buffer will be retrieved. 830 @param Buffer Binary of Guid, Name or Device path. 831 832 @retval EFI_INVALID_PARAMETER Any incoming parameter is invalid. 833 @retval EFI_OUT_OF_RESOURCES Lake of resources to store neccesary structures. 834 @retval EFI_SUCCESS The buffer data is retrieved and translated to 835 binary format. 836 837 **/ 838 EFI_STATUS 839 InternalHiiGetBufferFromString ( 840 IN EFI_STRING String, 841 IN UINT8 Flag, 842 OUT UINT8 **Buffer 843 ) 844 { 845 UINTN Length; 846 EFI_STRING ConfigHdr; 847 CHAR16 *StringPtr; 848 UINT8 *DataBuffer; 849 CHAR16 TemStr[5]; 850 UINTN Index; 851 UINT8 DigitUint8; 852 853 if (String == NULL || Buffer == NULL) { 854 return EFI_INVALID_PARAMETER; 855 } 856 857 DataBuffer = NULL; 858 StringPtr = NULL; 859 ConfigHdr = String; 860 // 861 // The content between 'GUID', 'NAME', 'PATH' of <ConfigHdr> and '&' of next element 862 // or '\0' (end of configuration string) is the UNICODE %02x bytes encoding string. 863 // 864 for (Length = 0; *String != 0 && *String != L'&'; String++, Length++); 865 866 switch (Flag) { 867 case GUID_CONFIG_STRING_TYPE: 868 case PATH_CONFIG_STRING_TYPE: 869 // 870 // The data in <ConfigHdr> is encoded as hex UNICODE %02x bytes in the same order 871 // as the device path and Guid resides in RAM memory. 872 // Translate the data into binary. 873 // 874 DataBuffer = (UINT8 *) AllocateZeroPool ((Length + 1) / 2); 875 if (DataBuffer == NULL) { 876 return EFI_OUT_OF_RESOURCES; 877 } 878 // 879 // Convert binary byte one by one 880 // 881 ZeroMem (TemStr, sizeof (TemStr)); 882 for (Index = 0; Index < Length; Index ++) { 883 TemStr[0] = ConfigHdr[Index]; 884 DigitUint8 = (UINT8) StrHexToUint64 (TemStr); 885 if ((Index & 1) == 0) { 886 DataBuffer [Index/2] = DigitUint8; 887 } else { 888 DataBuffer [Index/2] = (UINT8) ((DataBuffer [Index/2] << 4) + DigitUint8); 889 } 890 } 891 892 *Buffer = DataBuffer; 893 break; 894 895 case NAME_CONFIG_STRING_TYPE: 896 // 897 // Convert Config String to Unicode String, e.g. "0041004200430044" => "ABCD" 898 // 899 900 // 901 // Add the tailling char L'\0' 902 // 903 DataBuffer = (UINT8 *) AllocateZeroPool ((Length/4 + 1) * sizeof (CHAR16)); 904 if (DataBuffer == NULL) { 905 return EFI_OUT_OF_RESOURCES; 906 } 907 // 908 // Convert character one by one 909 // 910 StringPtr = (CHAR16 *) DataBuffer; 911 ZeroMem (TemStr, sizeof (TemStr)); 912 for (Index = 0; Index < Length; Index += 4) { 913 StrnCpyS (TemStr, sizeof (TemStr) / sizeof (CHAR16), ConfigHdr + Index, 4); 914 StringPtr[Index/4] = (CHAR16) StrHexToUint64 (TemStr); 915 } 916 // 917 // Add tailing L'\0' character 918 // 919 StringPtr[Index/4] = L'\0'; 920 921 *Buffer = DataBuffer; 922 break; 923 924 default: 925 return EFI_INVALID_PARAMETER; 926 } 927 928 return EFI_SUCCESS; 929 } 930 931 /** 932 This function checks VarOffset and VarWidth is in the block range. 933 934 @param BlockArray The block array is to be checked. 935 @param VarOffset Offset of var to the structure 936 @param VarWidth Width of var. 937 938 @retval TRUE This Var is in the block range. 939 @retval FALSE This Var is not in the block range. 940 **/ 941 BOOLEAN 942 BlockArrayCheck ( 943 IN IFR_BLOCK_DATA *BlockArray, 944 IN UINT16 VarOffset, 945 IN UINT16 VarWidth 946 ) 947 { 948 LIST_ENTRY *Link; 949 IFR_BLOCK_DATA *BlockData; 950 951 // 952 // No Request Block array, all vars are got. 953 // 954 if (BlockArray == NULL) { 955 return TRUE; 956 } 957 958 // 959 // Check the input var is in the request block range. 960 // 961 for (Link = BlockArray->Entry.ForwardLink; Link != &BlockArray->Entry; Link = Link->ForwardLink) { 962 BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry); 963 if ((VarOffset >= BlockData->Offset) && ((VarOffset + VarWidth) <= (BlockData->Offset + BlockData->Width))) { 964 return TRUE; 965 } 966 } 967 968 return FALSE; 969 } 970 971 /** 972 Get the value of <Number> in <BlockConfig> format, i.e. the value of OFFSET 973 or WIDTH or VALUE. 974 <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number> 975 976 @param ValueString String in <BlockConfig> format and points to the 977 first character of <Number>. 978 @param ValueData The output value. Caller takes the responsibility 979 to free memory. 980 @param ValueLength Length of the <Number>, in characters. 981 982 @retval EFI_OUT_OF_RESOURCES Insufficient resources to store neccessary 983 structures. 984 @retval EFI_SUCCESS Value of <Number> is outputted in Number 985 successfully. 986 987 **/ 988 EFI_STATUS 989 EFIAPI 990 InternalHiiGetValueOfNumber ( 991 IN EFI_STRING ValueString, 992 OUT UINT8 **ValueData, 993 OUT UINTN *ValueLength 994 ) 995 { 996 EFI_STRING StringPtr; 997 UINTN Length; 998 UINT8 *Buf; 999 UINT8 DigitUint8; 1000 UINTN Index; 1001 CHAR16 TemStr[2]; 1002 1003 ASSERT (ValueString != NULL && ValueData != NULL && ValueLength != NULL); 1004 ASSERT (*ValueString != L'\0'); 1005 1006 // 1007 // Get the length of value string 1008 // 1009 StringPtr = ValueString; 1010 while (*StringPtr != L'\0' && *StringPtr != L'&') { 1011 StringPtr++; 1012 } 1013 Length = StringPtr - ValueString; 1014 1015 // 1016 // Allocate buffer to store the value 1017 // 1018 Buf = (UINT8 *) AllocateZeroPool ((Length + 1) / 2); 1019 if (Buf == NULL) { 1020 return EFI_OUT_OF_RESOURCES; 1021 } 1022 1023 // 1024 // Convert character one by one to the value buffer 1025 // 1026 ZeroMem (TemStr, sizeof (TemStr)); 1027 for (Index = 0; Index < Length; Index ++) { 1028 TemStr[0] = ValueString[Length - Index - 1]; 1029 DigitUint8 = (UINT8) StrHexToUint64 (TemStr); 1030 if ((Index & 1) == 0) { 1031 Buf [Index/2] = DigitUint8; 1032 } else { 1033 Buf [Index/2] = (UINT8) ((DigitUint8 << 4) + Buf [Index/2]); 1034 } 1035 } 1036 1037 // 1038 // Set the converted value and string length. 1039 // 1040 *ValueData = Buf; 1041 *ValueLength = Length; 1042 return EFI_SUCCESS; 1043 } 1044 1045 /** 1046 Get value from config request resp string. 1047 1048 @param ConfigElement ConfigResp string contains the current setting. 1049 @param VarName The variable name which need to get value. 1050 @param VarValue The return value. 1051 1052 @retval EFI_SUCCESS Get the value for the VarName 1053 @retval EFI_OUT_OF_RESOURCES The memory is not enough. 1054 **/ 1055 EFI_STATUS 1056 GetValueFromRequest ( 1057 IN CHAR16 *ConfigElement, 1058 IN CHAR16 *VarName, 1059 OUT UINT64 *VarValue 1060 ) 1061 { 1062 UINT8 *TmpBuffer; 1063 CHAR16 *StringPtr; 1064 UINTN Length; 1065 EFI_STATUS Status; 1066 1067 // 1068 // Find VarName related string. 1069 // 1070 StringPtr = StrStr (ConfigElement, VarName); 1071 ASSERT (StringPtr != NULL); 1072 1073 // 1074 // Skip the "VarName=" string 1075 // 1076 StringPtr += StrLen (VarName) + 1; 1077 1078 // 1079 // Get Offset 1080 // 1081 Status = InternalHiiGetValueOfNumber (StringPtr, &TmpBuffer, &Length); 1082 if (EFI_ERROR (Status)) { 1083 return Status; 1084 } 1085 1086 *VarValue = 0; 1087 CopyMem (VarValue, TmpBuffer, (((Length + 1) / 2) < sizeof (UINT64)) ? ((Length + 1) / 2) : sizeof (UINT64)); 1088 1089 FreePool (TmpBuffer); 1090 1091 return EFI_SUCCESS; 1092 } 1093 1094 /** 1095 This internal function parses IFR data to validate current setting. 1096 1097 Base on the NameValueType, if it is TRUE, RequestElement and HiiHandle is valid; 1098 else the VarBuffer and CurrentBlockArray is valid. 1099 1100 @param HiiPackageList Point to Hii package list. 1101 @param PackageListLength The length of the pacakge. 1102 @param VarGuid Guid of the buffer storage. 1103 @param VarName Name of the buffer storage. 1104 @param VarBuffer The data buffer for the storage. 1105 @param CurrentBlockArray The block array from the config Requst string. 1106 @param RequestElement The config string for this storage. 1107 @param HiiHandle The HiiHandle for this formset. 1108 @param NameValueType Whether current storage is name/value varstore or not. 1109 1110 @retval EFI_SUCCESS The current setting is valid. 1111 @retval EFI_OUT_OF_RESOURCES The memory is not enough. 1112 @retval EFI_INVALID_PARAMETER The config string or the Hii package is invalid. 1113 **/ 1114 EFI_STATUS 1115 ValidateQuestionFromVfr ( 1116 IN EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList, 1117 IN UINTN PackageListLength, 1118 IN EFI_GUID *VarGuid, 1119 IN CHAR16 *VarName, 1120 IN UINT8 *VarBuffer, 1121 IN IFR_BLOCK_DATA *CurrentBlockArray, 1122 IN CHAR16 *RequestElement, 1123 IN EFI_HII_HANDLE HiiHandle, 1124 IN BOOLEAN NameValueType 1125 ) 1126 { 1127 IFR_BLOCK_DATA VarBlockData; 1128 UINT16 Offset; 1129 UINT16 Width; 1130 UINT64 VarValue; 1131 EFI_IFR_TYPE_VALUE TmpValue; 1132 EFI_STATUS Status; 1133 EFI_HII_PACKAGE_HEADER PackageHeader; 1134 UINT32 PackageOffset; 1135 UINT8 *PackageData; 1136 UINTN IfrOffset; 1137 EFI_IFR_OP_HEADER *IfrOpHdr; 1138 EFI_IFR_VARSTORE *IfrVarStore; 1139 EFI_IFR_VARSTORE_NAME_VALUE *IfrNameValueStore; 1140 EFI_IFR_VARSTORE_EFI *IfrEfiVarStore; 1141 IFR_VARSTORAGE_DATA VarStoreData; 1142 EFI_IFR_ONE_OF *IfrOneOf; 1143 EFI_IFR_NUMERIC *IfrNumeric; 1144 EFI_IFR_ONE_OF_OPTION *IfrOneOfOption; 1145 EFI_IFR_CHECKBOX *IfrCheckBox; 1146 EFI_IFR_STRING *IfrString; 1147 CHAR8 *VarStoreName; 1148 UINTN Index; 1149 CHAR16 *QuestionName; 1150 CHAR16 *StringPtr; 1151 1152 // 1153 // Initialize the local variables. 1154 // 1155 Index = 0; 1156 VarStoreName = NULL; 1157 Status = EFI_SUCCESS; 1158 VarValue = 0; 1159 IfrVarStore = NULL; 1160 IfrNameValueStore = NULL; 1161 IfrEfiVarStore = NULL; 1162 ZeroMem (&VarStoreData, sizeof (IFR_VARSTORAGE_DATA)); 1163 ZeroMem (&VarBlockData, sizeof (VarBlockData)); 1164 1165 // 1166 // Check IFR value is in block data, then Validate Value 1167 // 1168 PackageOffset = sizeof (EFI_HII_PACKAGE_LIST_HEADER); 1169 while (PackageOffset < PackageListLength) { 1170 CopyMem (&PackageHeader, (UINT8 *) HiiPackageList + PackageOffset, sizeof (PackageHeader)); 1171 1172 // 1173 // Parse IFR opcode from the form package. 1174 // 1175 if (PackageHeader.Type == EFI_HII_PACKAGE_FORMS) { 1176 IfrOffset = sizeof (PackageHeader); 1177 PackageData = (UINT8 *) HiiPackageList + PackageOffset; 1178 while (IfrOffset < PackageHeader.Length) { 1179 IfrOpHdr = (EFI_IFR_OP_HEADER *) (PackageData + IfrOffset); 1180 // 1181 // Validate current setting to the value built in IFR opcode 1182 // 1183 switch (IfrOpHdr->OpCode) { 1184 case EFI_IFR_VARSTORE_OP: 1185 // 1186 // VarStoreId has been found. No further found. 1187 // 1188 if (VarStoreData.VarStoreId != 0) { 1189 break; 1190 } 1191 // 1192 // Find the matched VarStoreId to the input VarGuid and VarName 1193 // 1194 IfrVarStore = (EFI_IFR_VARSTORE *) IfrOpHdr; 1195 if (CompareGuid ((EFI_GUID *) (VOID *) &IfrVarStore->Guid, VarGuid)) { 1196 VarStoreName = (CHAR8 *) IfrVarStore->Name; 1197 for (Index = 0; VarStoreName[Index] != 0; Index ++) { 1198 if ((CHAR16) VarStoreName[Index] != VarName[Index]) { 1199 break; 1200 } 1201 } 1202 // 1203 // The matched VarStore is found. 1204 // 1205 if ((VarStoreName[Index] != 0) || (VarName[Index] != 0)) { 1206 IfrVarStore = NULL; 1207 } 1208 } else { 1209 IfrVarStore = NULL; 1210 } 1211 1212 if (IfrVarStore != NULL) { 1213 VarStoreData.VarStoreId = IfrVarStore->VarStoreId; 1214 VarStoreData.Size = IfrVarStore->Size; 1215 } 1216 break; 1217 case EFI_IFR_VARSTORE_NAME_VALUE_OP: 1218 // 1219 // VarStoreId has been found. No further found. 1220 // 1221 if (VarStoreData.VarStoreId != 0) { 1222 break; 1223 } 1224 // 1225 // Find the matched VarStoreId to the input VarGuid 1226 // 1227 IfrNameValueStore = (EFI_IFR_VARSTORE_NAME_VALUE *) IfrOpHdr; 1228 if (!CompareGuid ((EFI_GUID *) (VOID *) &IfrNameValueStore->Guid, VarGuid)) { 1229 IfrNameValueStore = NULL; 1230 } 1231 1232 if (IfrNameValueStore != NULL) { 1233 VarStoreData.VarStoreId = IfrNameValueStore->VarStoreId; 1234 } 1235 break; 1236 case EFI_IFR_VARSTORE_EFI_OP: 1237 // 1238 // VarStore is found. Don't need to search any more. 1239 // 1240 if (VarStoreData.VarStoreId != 0) { 1241 break; 1242 } 1243 1244 IfrEfiVarStore = (EFI_IFR_VARSTORE_EFI *) IfrOpHdr; 1245 1246 // 1247 // If the length is small than the structure, this is from old efi 1248 // varstore definition. Old efi varstore get config directly from 1249 // GetVariable function. 1250 // 1251 if (IfrOpHdr->Length < sizeof (EFI_IFR_VARSTORE_EFI)) { 1252 break; 1253 } 1254 1255 if (CompareGuid ((EFI_GUID *) (VOID *) &IfrEfiVarStore->Guid, VarGuid)) { 1256 VarStoreName = (CHAR8 *) IfrEfiVarStore->Name; 1257 for (Index = 0; VarStoreName[Index] != 0; Index ++) { 1258 if ((CHAR16) VarStoreName[Index] != VarName[Index]) { 1259 break; 1260 } 1261 } 1262 // 1263 // The matched VarStore is found. 1264 // 1265 if ((VarStoreName[Index] != 0) || (VarName[Index] != 0)) { 1266 IfrEfiVarStore = NULL; 1267 } 1268 } else { 1269 IfrEfiVarStore = NULL; 1270 } 1271 1272 if (IfrEfiVarStore != NULL) { 1273 // 1274 // Find the matched VarStore 1275 // 1276 VarStoreData.VarStoreId = IfrEfiVarStore->VarStoreId; 1277 VarStoreData.Size = IfrEfiVarStore->Size; 1278 } 1279 break; 1280 case EFI_IFR_FORM_OP: 1281 case EFI_IFR_FORM_MAP_OP: 1282 // 1283 // Check the matched VarStoreId is found. 1284 // 1285 if (VarStoreData.VarStoreId == 0) { 1286 return EFI_SUCCESS; 1287 } 1288 break; 1289 case EFI_IFR_ONE_OF_OP: 1290 // 1291 // Check whether current value is the one of option. 1292 // 1293 1294 // 1295 // OneOf question is not in IFR Form. This IFR form is not valid. 1296 // 1297 if (VarStoreData.VarStoreId == 0) { 1298 return EFI_INVALID_PARAMETER; 1299 } 1300 // 1301 // Check whether this question is for the requested varstore. 1302 // 1303 IfrOneOf = (EFI_IFR_ONE_OF *) IfrOpHdr; 1304 if (IfrOneOf->Question.VarStoreId != VarStoreData.VarStoreId) { 1305 break; 1306 } 1307 1308 if (NameValueType) { 1309 QuestionName = HiiGetString (HiiHandle, IfrOneOf->Question.VarStoreInfo.VarName, NULL); 1310 ASSERT (QuestionName != NULL); 1311 1312 if (StrStr (RequestElement, QuestionName) == NULL) { 1313 // 1314 // This question is not in the current configuration string. Skip it. 1315 // 1316 break; 1317 } 1318 1319 Status = GetValueFromRequest (RequestElement, QuestionName, &VarValue); 1320 if (EFI_ERROR (Status)) { 1321 return Status; 1322 } 1323 } else { 1324 // 1325 // Get Offset by Question header and Width by DataType Flags 1326 // 1327 Offset = IfrOneOf->Question.VarStoreInfo.VarOffset; 1328 Width = (UINT16) (1 << (IfrOneOf->Flags & EFI_IFR_NUMERIC_SIZE)); 1329 // 1330 // Check whether this question is in current block array. 1331 // 1332 if (!BlockArrayCheck (CurrentBlockArray, Offset, Width)) { 1333 // 1334 // This question is not in the current configuration string. Skip it. 1335 // 1336 break; 1337 } 1338 // 1339 // Check this var question is in the var storage 1340 // 1341 if ((Offset + Width) > VarStoreData.Size) { 1342 // 1343 // This question exceeds the var store size. 1344 // 1345 return EFI_INVALID_PARAMETER; 1346 } 1347 1348 // 1349 // Get the current value for oneof opcode 1350 // 1351 VarValue = 0; 1352 CopyMem (&VarValue, VarBuffer + Offset, Width); 1353 } 1354 // 1355 // Set Block Data, to be checked in the following Oneof option opcode. 1356 // 1357 VarBlockData.OpCode = IfrOpHdr->OpCode; 1358 VarBlockData.Scope = IfrOpHdr->Scope; 1359 break; 1360 case EFI_IFR_NUMERIC_OP: 1361 // 1362 // Check the current value is in the numeric range. 1363 // 1364 1365 // 1366 // Numeric question is not in IFR Form. This IFR form is not valid. 1367 // 1368 if (VarStoreData.VarStoreId == 0) { 1369 return EFI_INVALID_PARAMETER; 1370 } 1371 // 1372 // Check whether this question is for the requested varstore. 1373 // 1374 IfrNumeric = (EFI_IFR_NUMERIC *) IfrOpHdr; 1375 if (IfrNumeric->Question.VarStoreId != VarStoreData.VarStoreId) { 1376 break; 1377 } 1378 1379 if (NameValueType) { 1380 QuestionName = HiiGetString (HiiHandle, IfrNumeric->Question.VarStoreInfo.VarName, NULL); 1381 ASSERT (QuestionName != NULL); 1382 1383 if (StrStr (RequestElement, QuestionName) == NULL) { 1384 // 1385 // This question is not in the current configuration string. Skip it. 1386 // 1387 break; 1388 } 1389 1390 Status = GetValueFromRequest (RequestElement, QuestionName, &VarValue); 1391 if (EFI_ERROR (Status)) { 1392 return Status; 1393 } 1394 } else { 1395 // 1396 // Get Offset by Question header and Width by DataType Flags 1397 // 1398 Offset = IfrNumeric->Question.VarStoreInfo.VarOffset; 1399 Width = (UINT16) (1 << (IfrNumeric->Flags & EFI_IFR_NUMERIC_SIZE)); 1400 // 1401 // Check whether this question is in current block array. 1402 // 1403 if (!BlockArrayCheck (CurrentBlockArray, Offset, Width)) { 1404 // 1405 // This question is not in the current configuration string. Skip it. 1406 // 1407 break; 1408 } 1409 // 1410 // Check this var question is in the var storage 1411 // 1412 if ((Offset + Width) > VarStoreData.Size) { 1413 // 1414 // This question exceeds the var store size. 1415 // 1416 return EFI_INVALID_PARAMETER; 1417 } 1418 1419 // 1420 // Check the current value is in the numeric range. 1421 // 1422 VarValue = 0; 1423 CopyMem (&VarValue, VarBuffer + Offset, Width); 1424 } 1425 if ((IfrNumeric->Flags & EFI_IFR_DISPLAY) == 0) { 1426 switch (IfrNumeric->Flags & EFI_IFR_NUMERIC_SIZE) { 1427 case EFI_IFR_NUMERIC_SIZE_1: 1428 if ((INT8) VarValue < (INT8) IfrNumeric->data.u8.MinValue || (INT8) VarValue > (INT8) IfrNumeric->data.u8.MaxValue) { 1429 // 1430 // Not in the valid range. 1431 // 1432 return EFI_INVALID_PARAMETER; 1433 } 1434 break; 1435 case EFI_IFR_NUMERIC_SIZE_2: 1436 if ((INT16) VarValue < (INT16) IfrNumeric->data.u16.MinValue || (INT16) VarValue > (INT16) IfrNumeric->data.u16.MaxValue) { 1437 // 1438 // Not in the valid range. 1439 // 1440 return EFI_INVALID_PARAMETER; 1441 } 1442 break; 1443 case EFI_IFR_NUMERIC_SIZE_4: 1444 if ((INT32) VarValue < (INT32) IfrNumeric->data.u32.MinValue || (INT32) VarValue > (INT32) IfrNumeric->data.u32.MaxValue) { 1445 // 1446 // Not in the valid range. 1447 // 1448 return EFI_INVALID_PARAMETER; 1449 } 1450 break; 1451 case EFI_IFR_NUMERIC_SIZE_8: 1452 if ((INT64) VarValue < (INT64) IfrNumeric->data.u64.MinValue || (INT64) VarValue > (INT64) IfrNumeric->data.u64.MaxValue) { 1453 // 1454 // Not in the valid range. 1455 // 1456 return EFI_INVALID_PARAMETER; 1457 } 1458 break; 1459 } 1460 } else { 1461 switch (IfrNumeric->Flags & EFI_IFR_NUMERIC_SIZE) { 1462 case EFI_IFR_NUMERIC_SIZE_1: 1463 if ((UINT8) VarValue < IfrNumeric->data.u8.MinValue || (UINT8) VarValue > IfrNumeric->data.u8.MaxValue) { 1464 // 1465 // Not in the valid range. 1466 // 1467 return EFI_INVALID_PARAMETER; 1468 } 1469 break; 1470 case EFI_IFR_NUMERIC_SIZE_2: 1471 if ((UINT16) VarValue < IfrNumeric->data.u16.MinValue || (UINT16) VarValue > IfrNumeric->data.u16.MaxValue) { 1472 // 1473 // Not in the valid range. 1474 // 1475 return EFI_INVALID_PARAMETER; 1476 } 1477 break; 1478 case EFI_IFR_NUMERIC_SIZE_4: 1479 if ((UINT32) VarValue < IfrNumeric->data.u32.MinValue || (UINT32) VarValue > IfrNumeric->data.u32.MaxValue) { 1480 // 1481 // Not in the valid range. 1482 // 1483 return EFI_INVALID_PARAMETER; 1484 } 1485 break; 1486 case EFI_IFR_NUMERIC_SIZE_8: 1487 if ((UINT64) VarValue < IfrNumeric->data.u64.MinValue || (UINT64) VarValue > IfrNumeric->data.u64.MaxValue) { 1488 // 1489 // Not in the valid range. 1490 // 1491 return EFI_INVALID_PARAMETER; 1492 } 1493 break; 1494 } 1495 } 1496 break; 1497 case EFI_IFR_CHECKBOX_OP: 1498 // 1499 // Check value is BOOLEAN type, only 0 and 1 is valid. 1500 // 1501 1502 // 1503 // CheckBox question is not in IFR Form. This IFR form is not valid. 1504 // 1505 if (VarStoreData.VarStoreId == 0) { 1506 return EFI_INVALID_PARAMETER; 1507 } 1508 1509 // 1510 // Check whether this question is for the requested varstore. 1511 // 1512 IfrCheckBox = (EFI_IFR_CHECKBOX *) IfrOpHdr; 1513 if (IfrCheckBox->Question.VarStoreId != VarStoreData.VarStoreId) { 1514 break; 1515 } 1516 1517 if (NameValueType) { 1518 QuestionName = HiiGetString (HiiHandle, IfrCheckBox->Question.VarStoreInfo.VarName, NULL); 1519 ASSERT (QuestionName != NULL); 1520 1521 if (StrStr (RequestElement, QuestionName) == NULL) { 1522 // 1523 // This question is not in the current configuration string. Skip it. 1524 // 1525 break; 1526 } 1527 1528 Status = GetValueFromRequest (RequestElement, QuestionName, &VarValue); 1529 if (EFI_ERROR (Status)) { 1530 return Status; 1531 } 1532 } else { 1533 // 1534 // Get Offset by Question header 1535 // 1536 Offset = IfrCheckBox->Question.VarStoreInfo.VarOffset; 1537 Width = (UINT16) sizeof (BOOLEAN); 1538 // 1539 // Check whether this question is in current block array. 1540 // 1541 if (!BlockArrayCheck (CurrentBlockArray, Offset, Width)) { 1542 // 1543 // This question is not in the current configuration string. Skip it. 1544 // 1545 break; 1546 } 1547 // 1548 // Check this var question is in the var storage 1549 // 1550 if ((Offset + Width) > VarStoreData.Size) { 1551 // 1552 // This question exceeds the var store size. 1553 // 1554 return EFI_INVALID_PARAMETER; 1555 } 1556 // 1557 // Check the current value is in the numeric range. 1558 // 1559 VarValue = 0; 1560 CopyMem (&VarValue, VarBuffer + Offset, Width); 1561 } 1562 // 1563 // Boolean type, only 1 and 0 is valid. 1564 // 1565 if (VarValue > 1) { 1566 return EFI_INVALID_PARAMETER; 1567 } 1568 break; 1569 case EFI_IFR_STRING_OP: 1570 // 1571 // Check current string length is less than maxsize 1572 // 1573 1574 // 1575 // CheckBox question is not in IFR Form. This IFR form is not valid. 1576 // 1577 if (VarStoreData.VarStoreId == 0) { 1578 return EFI_INVALID_PARAMETER; 1579 } 1580 1581 // 1582 // Check whether this question is for the requested varstore. 1583 // 1584 IfrString = (EFI_IFR_STRING *) IfrOpHdr; 1585 if (IfrString->Question.VarStoreId != VarStoreData.VarStoreId) { 1586 break; 1587 } 1588 // 1589 // Get Width by OneOf Flags 1590 // 1591 Width = (UINT16) (IfrString->MaxSize * sizeof (UINT16)); 1592 if (NameValueType) { 1593 QuestionName = HiiGetString (HiiHandle, IfrString->Question.VarStoreInfo.VarName, NULL); 1594 ASSERT (QuestionName != NULL); 1595 1596 StringPtr = StrStr (RequestElement, QuestionName); 1597 if (StringPtr == NULL) { 1598 // 1599 // This question is not in the current configuration string. Skip it. 1600 // 1601 break; 1602 } 1603 1604 // 1605 // Skip the "=". 1606 // 1607 StringPtr += 1; 1608 1609 // 1610 // Check current string length is less than maxsize 1611 // 1612 if (StrSize (StringPtr) > Width) { 1613 return EFI_INVALID_PARAMETER; 1614 } 1615 } else { 1616 // 1617 // Get Offset/Width by Question header and OneOf Flags 1618 // 1619 Offset = IfrString->Question.VarStoreInfo.VarOffset; 1620 // 1621 // Check whether this question is in current block array. 1622 // 1623 if (!BlockArrayCheck (CurrentBlockArray, Offset, Width)) { 1624 // 1625 // This question is not in the current configuration string. Skip it. 1626 // 1627 break; 1628 } 1629 // 1630 // Check this var question is in the var storage 1631 // 1632 if ((Offset + Width) > VarStoreData.Size) { 1633 // 1634 // This question exceeds the var store size. 1635 // 1636 return EFI_INVALID_PARAMETER; 1637 } 1638 1639 // 1640 // Check current string length is less than maxsize 1641 // 1642 if (StrSize ((CHAR16 *) (VarBuffer + Offset)) > Width) { 1643 return EFI_INVALID_PARAMETER; 1644 } 1645 } 1646 break; 1647 case EFI_IFR_ONE_OF_OPTION_OP: 1648 // 1649 // Opcode Scope is zero. This one of option is not to be checked. 1650 // 1651 if (VarBlockData.Scope == 0) { 1652 break; 1653 } 1654 1655 // 1656 // Only check for OneOf and OrderList opcode 1657 // 1658 IfrOneOfOption = (EFI_IFR_ONE_OF_OPTION *) IfrOpHdr; 1659 if (VarBlockData.OpCode == EFI_IFR_ONE_OF_OP) { 1660 // 1661 // Check current value is the value of one of option. 1662 // 1663 ASSERT (IfrOneOfOption->Type <= EFI_IFR_TYPE_NUM_SIZE_64); 1664 ZeroMem (&TmpValue, sizeof (EFI_IFR_TYPE_VALUE)); 1665 CopyMem (&TmpValue, &IfrOneOfOption->Value, IfrOneOfOption->Header.Length - OFFSET_OF (EFI_IFR_ONE_OF_OPTION, Value)); 1666 if (VarValue == TmpValue.u64) { 1667 // 1668 // The value is one of option value. 1669 // Set OpCode to Zero, don't need check again. 1670 // 1671 VarBlockData.OpCode = 0; 1672 } 1673 } 1674 break; 1675 case EFI_IFR_END_OP: 1676 // 1677 // Decrease opcode scope for the validated opcode 1678 // 1679 if (VarBlockData.Scope > 0) { 1680 VarBlockData.Scope --; 1681 } 1682 1683 // 1684 // OneOf value doesn't belong to one of option value. 1685 // 1686 if ((VarBlockData.Scope == 0) && (VarBlockData.OpCode == EFI_IFR_ONE_OF_OP)) { 1687 return EFI_INVALID_PARAMETER; 1688 } 1689 break; 1690 default: 1691 // 1692 // Increase Scope for the validated opcode 1693 // 1694 if (VarBlockData.Scope > 0) { 1695 VarBlockData.Scope = (UINT8) (VarBlockData.Scope + IfrOpHdr->Scope); 1696 } 1697 break; 1698 } 1699 // 1700 // Go to the next opcode 1701 // 1702 IfrOffset += IfrOpHdr->Length; 1703 } 1704 // 1705 // Only one form is in a package list. 1706 // 1707 break; 1708 } 1709 1710 // 1711 // Go to next package. 1712 // 1713 PackageOffset += PackageHeader.Length; 1714 } 1715 1716 return EFI_SUCCESS; 1717 } 1718 1719 /** 1720 This internal function parses IFR data to validate current setting. 1721 1722 @param ConfigElement ConfigResp element string contains the current setting. 1723 @param CurrentBlockArray Current block array. 1724 @param VarBuffer Data buffer for this varstore. 1725 1726 @retval EFI_SUCCESS The current setting is valid. 1727 @retval EFI_OUT_OF_RESOURCES The memory is not enough. 1728 @retval EFI_INVALID_PARAMETER The config string or the Hii package is invalid. 1729 **/ 1730 EFI_STATUS 1731 GetBlockDataInfo ( 1732 IN CHAR16 *ConfigElement, 1733 OUT IFR_BLOCK_DATA **CurrentBlockArray, 1734 OUT UINT8 **VarBuffer 1735 ) 1736 { 1737 IFR_BLOCK_DATA *BlockData; 1738 IFR_BLOCK_DATA *NewBlockData; 1739 EFI_STRING StringPtr; 1740 UINTN Length; 1741 UINT8 *TmpBuffer; 1742 UINT16 Offset; 1743 UINT16 Width; 1744 LIST_ENTRY *Link; 1745 UINTN MaxBufferSize; 1746 EFI_STATUS Status; 1747 IFR_BLOCK_DATA *BlockArray; 1748 UINT8 *DataBuffer; 1749 1750 // 1751 // Initialize the local variables. 1752 // 1753 Status = EFI_SUCCESS; 1754 BlockData = NULL; 1755 NewBlockData = NULL; 1756 TmpBuffer = NULL; 1757 BlockArray = NULL; 1758 MaxBufferSize = HII_LIB_DEFAULT_VARSTORE_SIZE; 1759 DataBuffer = AllocateZeroPool (MaxBufferSize); 1760 if (DataBuffer == NULL) { 1761 return EFI_OUT_OF_RESOURCES; 1762 } 1763 1764 // 1765 // Init BlockArray 1766 // 1767 BlockArray = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA)); 1768 if (BlockArray == NULL) { 1769 Status = EFI_OUT_OF_RESOURCES; 1770 goto Done; 1771 } 1772 InitializeListHead (&BlockArray->Entry); 1773 1774 StringPtr = StrStr (ConfigElement, L"&OFFSET="); 1775 ASSERT (StringPtr != NULL); 1776 1777 // 1778 // Parse each <RequestElement> if exists 1779 // Only <BlockName> format is supported by this help function. 1780 // <BlockName> ::= &'OFFSET='<Number>&'WIDTH='<Number> 1781 // 1782 while (*StringPtr != 0 && StrnCmp (StringPtr, L"&OFFSET=", StrLen (L"&OFFSET=")) == 0) { 1783 // 1784 // Skip the &OFFSET= string 1785 // 1786 StringPtr += StrLen (L"&OFFSET="); 1787 1788 // 1789 // Get Offset 1790 // 1791 Status = InternalHiiGetValueOfNumber (StringPtr, &TmpBuffer, &Length); 1792 if (EFI_ERROR (Status)) { 1793 goto Done; 1794 } 1795 Offset = 0; 1796 CopyMem ( 1797 &Offset, 1798 TmpBuffer, 1799 (((Length + 1) / 2) < sizeof (UINT16)) ? ((Length + 1) / 2) : sizeof (UINT16) 1800 ); 1801 FreePool (TmpBuffer); 1802 TmpBuffer = NULL; 1803 1804 StringPtr += Length; 1805 if (StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) { 1806 Status = EFI_INVALID_PARAMETER; 1807 goto Done; 1808 } 1809 StringPtr += StrLen (L"&WIDTH="); 1810 1811 // 1812 // Get Width 1813 // 1814 Status = InternalHiiGetValueOfNumber (StringPtr, &TmpBuffer, &Length); 1815 if (EFI_ERROR (Status)) { 1816 goto Done; 1817 } 1818 Width = 0; 1819 CopyMem ( 1820 &Width, 1821 TmpBuffer, 1822 (((Length + 1) / 2) < sizeof (UINT16)) ? ((Length + 1) / 2) : sizeof (UINT16) 1823 ); 1824 FreePool (TmpBuffer); 1825 TmpBuffer = NULL; 1826 1827 StringPtr += Length; 1828 if (*StringPtr != 0 && *StringPtr != L'&') { 1829 Status = EFI_INVALID_PARAMETER; 1830 goto Done; 1831 } 1832 1833 if (StrnCmp (StringPtr, L"&VALUE=", StrLen (L"&VALUE=")) != 0) { 1834 Status = EFI_INVALID_PARAMETER; 1835 goto Done; 1836 } 1837 StringPtr += StrLen (L"&VALUE="); 1838 1839 // 1840 // Get Value 1841 // 1842 Status = InternalHiiGetValueOfNumber (StringPtr, &TmpBuffer, &Length); 1843 if (EFI_ERROR (Status)) { 1844 goto Done; 1845 } 1846 1847 StringPtr += Length; 1848 if (*StringPtr != 0 && *StringPtr != L'&') { 1849 Status = EFI_INVALID_PARAMETER; 1850 goto Done; 1851 } 1852 1853 // 1854 // Check whether VarBuffer is enough 1855 // 1856 if ((UINTN) (Offset + Width) > MaxBufferSize) { 1857 DataBuffer = ReallocatePool ( 1858 MaxBufferSize, 1859 Offset + Width + HII_LIB_DEFAULT_VARSTORE_SIZE, 1860 DataBuffer 1861 ); 1862 if (DataBuffer == NULL) { 1863 Status = EFI_OUT_OF_RESOURCES; 1864 goto Done; 1865 } 1866 MaxBufferSize = Offset + Width + HII_LIB_DEFAULT_VARSTORE_SIZE; 1867 } 1868 1869 // 1870 // Update the Block with configuration info 1871 // 1872 CopyMem (DataBuffer + Offset, TmpBuffer, Width); 1873 FreePool (TmpBuffer); 1874 TmpBuffer = NULL; 1875 1876 // 1877 // Set new Block Data 1878 // 1879 NewBlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA)); 1880 if (NewBlockData == NULL) { 1881 Status = EFI_OUT_OF_RESOURCES; 1882 goto Done; 1883 } 1884 NewBlockData->Offset = Offset; 1885 NewBlockData->Width = Width; 1886 1887 // 1888 // Insert the new block data into the block data array. 1889 // 1890 for (Link = BlockArray->Entry.ForwardLink; Link != &BlockArray->Entry; Link = Link->ForwardLink) { 1891 BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry); 1892 if (NewBlockData->Offset == BlockData->Offset) { 1893 if (NewBlockData->Width > BlockData->Width) { 1894 BlockData->Width = NewBlockData->Width; 1895 } 1896 FreePool (NewBlockData); 1897 break; 1898 } else if (NewBlockData->Offset < BlockData->Offset) { 1899 // 1900 // Insert new block data as the previous one of this link. 1901 // 1902 InsertTailList (Link, &NewBlockData->Entry); 1903 break; 1904 } 1905 } 1906 1907 // 1908 // Insert new block data into the array tail. 1909 // 1910 if (Link == &BlockArray->Entry) { 1911 InsertTailList (Link, &NewBlockData->Entry); 1912 } 1913 1914 // 1915 // If '\0', parsing is finished. 1916 // 1917 if (*StringPtr == 0) { 1918 break; 1919 } 1920 // 1921 // Go to next ConfigBlock 1922 // 1923 } 1924 1925 // 1926 // Merge the aligned block data into the single block data. 1927 // 1928 Link = BlockArray->Entry.ForwardLink; 1929 while ((Link != &BlockArray->Entry) && (Link->ForwardLink != &BlockArray->Entry)) { 1930 BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry); 1931 NewBlockData = BASE_CR (Link->ForwardLink, IFR_BLOCK_DATA, Entry); 1932 if ((NewBlockData->Offset >= BlockData->Offset) && (NewBlockData->Offset <= (BlockData->Offset + BlockData->Width))) { 1933 if ((NewBlockData->Offset + NewBlockData->Width) > (BlockData->Offset + BlockData->Width)) { 1934 BlockData->Width = (UINT16) (NewBlockData->Offset + NewBlockData->Width - BlockData->Offset); 1935 } 1936 RemoveEntryList (Link->ForwardLink); 1937 FreePool (NewBlockData); 1938 continue; 1939 } 1940 Link = Link->ForwardLink; 1941 } 1942 1943 *VarBuffer = DataBuffer; 1944 *CurrentBlockArray = BlockArray; 1945 return EFI_SUCCESS; 1946 1947 Done: 1948 if (DataBuffer != NULL) { 1949 FreePool (DataBuffer); 1950 } 1951 1952 if (BlockArray != NULL) { 1953 // 1954 // Free Link Array CurrentBlockArray 1955 // 1956 while (!IsListEmpty (&BlockArray->Entry)) { 1957 BlockData = BASE_CR (BlockArray->Entry.ForwardLink, IFR_BLOCK_DATA, Entry); 1958 RemoveEntryList (&BlockData->Entry); 1959 FreePool (BlockData); 1960 } 1961 FreePool (BlockArray); 1962 } 1963 1964 return Status; 1965 } 1966 1967 /** 1968 This internal function parses IFR data to validate current setting. 1969 1970 @param ConfigResp ConfigResp string contains the current setting. 1971 @param HiiPackageList Point to Hii package list. 1972 @param PackageListLength The length of the pacakge. 1973 @param VarGuid Guid of the buffer storage. 1974 @param VarName Name of the buffer storage. 1975 @param HiiHandle The HiiHandle for this package. 1976 1977 @retval EFI_SUCCESS The current setting is valid. 1978 @retval EFI_OUT_OF_RESOURCES The memory is not enough. 1979 @retval EFI_INVALID_PARAMETER The config string or the Hii package is invalid. 1980 **/ 1981 EFI_STATUS 1982 EFIAPI 1983 InternalHiiValidateCurrentSetting ( 1984 IN EFI_STRING ConfigResp, 1985 IN EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList, 1986 IN UINTN PackageListLength, 1987 IN EFI_GUID *VarGuid, 1988 IN CHAR16 *VarName, 1989 IN EFI_HII_HANDLE HiiHandle 1990 ) 1991 { 1992 CHAR16 *StringPtr; 1993 EFI_STATUS Status; 1994 IFR_BLOCK_DATA *CurrentBlockArray; 1995 IFR_BLOCK_DATA *BlockData; 1996 UINT8 *VarBuffer; 1997 BOOLEAN NameValueType; 1998 1999 CurrentBlockArray = NULL; 2000 VarBuffer = NULL; 2001 StringPtr = NULL; 2002 Status = EFI_SUCCESS; 2003 2004 // 2005 // If StringPtr != NULL, get the request elements. 2006 // 2007 if (StrStr (ConfigResp, L"&OFFSET=") != NULL) { 2008 Status = GetBlockDataInfo(ConfigResp, &CurrentBlockArray, &VarBuffer); 2009 if (EFI_ERROR (Status)) { 2010 return Status; 2011 } 2012 NameValueType = FALSE; 2013 } else { 2014 // 2015 // Skip header part. 2016 // 2017 StringPtr = StrStr (ConfigResp, L"PATH="); 2018 ASSERT (StringPtr != NULL); 2019 2020 if (StrStr (StringPtr, L"&") != NULL) { 2021 NameValueType = TRUE; 2022 } else { 2023 // 2024 // Not found Request element, return success. 2025 // 2026 return EFI_SUCCESS; 2027 } 2028 } 2029 2030 Status = ValidateQuestionFromVfr( 2031 HiiPackageList, 2032 PackageListLength, 2033 VarGuid, 2034 VarName, 2035 VarBuffer, 2036 CurrentBlockArray, 2037 ConfigResp, 2038 HiiHandle, 2039 NameValueType 2040 ); 2041 2042 if (VarBuffer != NULL) { 2043 FreePool (VarBuffer); 2044 } 2045 2046 if (CurrentBlockArray != NULL) { 2047 // 2048 // Free Link Array CurrentBlockArray 2049 // 2050 while (!IsListEmpty (&CurrentBlockArray->Entry)) { 2051 BlockData = BASE_CR (CurrentBlockArray->Entry.ForwardLink, IFR_BLOCK_DATA, Entry); 2052 RemoveEntryList (&BlockData->Entry); 2053 FreePool (BlockData); 2054 } 2055 FreePool (CurrentBlockArray); 2056 } 2057 2058 return Status; 2059 } 2060 2061 /** 2062 Check whether the ConfigRequest string has the request elements. 2063 For EFI_HII_VARSTORE_BUFFER type, the request has "&OFFSET=****&WIDTH=****..." format. 2064 For EFI_HII_VARSTORE_NAME_VALUE type, the request has "&NAME1**&NAME2..." format. 2065 2066 @param ConfigRequest The input config request string. 2067 2068 @retval TRUE The input include config request elements. 2069 @retval FALSE The input string not includes. 2070 2071 **/ 2072 BOOLEAN 2073 GetElementsFromRequest ( 2074 IN EFI_STRING ConfigRequest 2075 ) 2076 { 2077 EFI_STRING TmpRequest; 2078 2079 TmpRequest = StrStr (ConfigRequest, L"PATH="); 2080 ASSERT (TmpRequest != NULL); 2081 2082 if ((StrStr (TmpRequest, L"&OFFSET=") != NULL) || (StrStr (TmpRequest, L"&") != NULL)) { 2083 return TRUE; 2084 } 2085 2086 return FALSE; 2087 } 2088 2089 /** 2090 This function parses the input ConfigRequest string and its matched IFR code 2091 string for setting default value and validating current setting. 2092 2093 1. For setting default action, Reset the default value specified by DefaultId 2094 to the driver configuration got by Request string. 2095 2. For validating current setting, Validate the current configuration 2096 by parsing HII form IFR opcode. 2097 2098 NULL request string support depends on the ExportConfig interface of 2099 HiiConfigRouting protocol in UEFI specification. 2100 2101 @param Request A null-terminated Unicode string in 2102 <MultiConfigRequest> format. It can be NULL. 2103 If it is NULL, all current configuration for the 2104 entirety of the current HII database will be validated. 2105 If it is NULL, all configuration for the 2106 entirety of the current HII database will be reset. 2107 @param DefaultId Specifies the type of defaults to retrieve only for setting default action. 2108 @param ActionType Action supports setting defaults and validate current setting. 2109 2110 @retval TRUE Action runs successfully. 2111 @retval FALSE Action is not valid or Action can't be executed successfully.. 2112 **/ 2113 BOOLEAN 2114 EFIAPI 2115 InternalHiiIfrValueAction ( 2116 IN CONST EFI_STRING Request, OPTIONAL 2117 IN UINT16 DefaultId, 2118 IN UINT8 ActionType 2119 ) 2120 { 2121 EFI_STRING ConfigAltResp; 2122 EFI_STRING ConfigAltHdr; 2123 EFI_STRING ConfigResp; 2124 EFI_STRING Progress; 2125 EFI_STRING StringPtr; 2126 EFI_STRING StringHdr; 2127 EFI_STATUS Status; 2128 EFI_HANDLE DriverHandle; 2129 EFI_HANDLE TempDriverHandle; 2130 EFI_HII_HANDLE *HiiHandleBuffer; 2131 EFI_HII_HANDLE HiiHandle; 2132 UINT32 Index; 2133 EFI_GUID *VarGuid; 2134 EFI_STRING VarName; 2135 2136 EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList; 2137 UINTN PackageListLength; 2138 UINTN MaxLen; 2139 EFI_DEVICE_PATH_PROTOCOL *DevicePath; 2140 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath; 2141 2142 ConfigAltResp = NULL; 2143 ConfigResp = NULL; 2144 VarGuid = NULL; 2145 VarName = NULL; 2146 DevicePath = NULL; 2147 ConfigAltHdr = NULL; 2148 HiiHandleBuffer = NULL; 2149 Index = 0; 2150 TempDriverHandle = NULL; 2151 HiiHandle = NULL; 2152 HiiPackageList = NULL; 2153 2154 // 2155 // Only support set default and validate setting action. 2156 // 2157 if ((ActionType != ACTION_SET_DEFAUTL_VALUE) && (ActionType != ACTION_VALIDATE_SETTING)) { 2158 return FALSE; 2159 } 2160 2161 // 2162 // Get the full requested value and deault value string. 2163 // 2164 if (Request != NULL) { 2165 Status = gHiiConfigRouting->ExtractConfig ( 2166 gHiiConfigRouting, 2167 Request, 2168 &Progress, 2169 &ConfigAltResp 2170 ); 2171 } else { 2172 Status = gHiiConfigRouting->ExportConfig ( 2173 gHiiConfigRouting, 2174 &ConfigAltResp 2175 ); 2176 } 2177 2178 if (EFI_ERROR (Status)) { 2179 return FALSE; 2180 } 2181 2182 StringPtr = ConfigAltResp; 2183 ASSERT (StringPtr != NULL); 2184 2185 while (*StringPtr != L'\0') { 2186 // 2187 // 1. Find <ConfigHdr> GUID=...&NAME=...&PATH=... 2188 // 2189 StringHdr = StringPtr; 2190 2191 // 2192 // Get Guid value 2193 // 2194 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) { 2195 Status = EFI_INVALID_PARAMETER; 2196 goto Done; 2197 } 2198 StringPtr += StrLen (L"GUID="); 2199 Status = InternalHiiGetBufferFromString (StringPtr, GUID_CONFIG_STRING_TYPE, (UINT8 **) &VarGuid); 2200 if (EFI_ERROR (Status)) { 2201 goto Done; 2202 } 2203 2204 // 2205 // Get Name value VarName 2206 // 2207 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&NAME=", StrLen (L"&NAME=")) != 0) { 2208 StringPtr++; 2209 } 2210 if (*StringPtr == L'\0') { 2211 Status = EFI_INVALID_PARAMETER; 2212 goto Done; 2213 } 2214 StringPtr += StrLen (L"&NAME="); 2215 Status = InternalHiiGetBufferFromString (StringPtr, NAME_CONFIG_STRING_TYPE, (UINT8 **) &VarName); 2216 if (EFI_ERROR (Status)) { 2217 goto Done; 2218 } 2219 2220 // 2221 // Get Path value DevicePath 2222 // 2223 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&PATH=", StrLen (L"&PATH=")) != 0) { 2224 StringPtr++; 2225 } 2226 if (*StringPtr == L'\0') { 2227 Status = EFI_INVALID_PARAMETER; 2228 goto Done; 2229 } 2230 StringPtr += StrLen (L"&PATH="); 2231 Status = InternalHiiGetBufferFromString (StringPtr, PATH_CONFIG_STRING_TYPE, (UINT8 **) &DevicePath); 2232 if (EFI_ERROR (Status)) { 2233 goto Done; 2234 } 2235 2236 // 2237 // Get the Driver handle by the got device path. 2238 // 2239 TempDevicePath = DevicePath; 2240 Status = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &TempDevicePath, &DriverHandle); 2241 if (EFI_ERROR (Status)) { 2242 goto Done; 2243 } 2244 2245 // 2246 // Find the matched Hii Handle for the found Driver handle 2247 // 2248 HiiHandleBuffer = HiiGetHiiHandles (NULL); 2249 if (HiiHandleBuffer == NULL) { 2250 Status = EFI_NOT_FOUND; 2251 goto Done; 2252 } 2253 2254 for (Index = 0; HiiHandleBuffer[Index] != NULL; Index ++) { 2255 gHiiDatabase->GetPackageListHandle (gHiiDatabase, HiiHandleBuffer[Index], &TempDriverHandle); 2256 if (TempDriverHandle == DriverHandle) { 2257 break; 2258 } 2259 } 2260 2261 HiiHandle = HiiHandleBuffer[Index]; 2262 FreePool (HiiHandleBuffer); 2263 2264 if (HiiHandle == NULL) { 2265 // 2266 // This request string has no its Hii package. 2267 // Its default value and validating can't execute by parsing IFR data. 2268 // Directly jump into the next ConfigAltResp string for another pair Guid, Name, and Path. 2269 // 2270 Status = EFI_SUCCESS; 2271 goto NextConfigAltResp; 2272 } 2273 2274 // 2275 // 2. Get HiiPackage by HiiHandle 2276 // 2277 PackageListLength = 0; 2278 HiiPackageList = NULL; 2279 Status = gHiiDatabase->ExportPackageLists (gHiiDatabase, HiiHandle, &PackageListLength, HiiPackageList); 2280 2281 // 2282 // The return status should always be EFI_BUFFER_TOO_SMALL as input buffer's size is 0. 2283 // 2284 if (Status != EFI_BUFFER_TOO_SMALL) { 2285 Status = EFI_INVALID_PARAMETER; 2286 goto Done; 2287 } 2288 2289 HiiPackageList = AllocatePool (PackageListLength); 2290 if (HiiPackageList == NULL) { 2291 Status = EFI_OUT_OF_RESOURCES; 2292 goto Done; 2293 } 2294 2295 // 2296 // Get PackageList on HiiHandle 2297 // 2298 Status = gHiiDatabase->ExportPackageLists (gHiiDatabase, HiiHandle, &PackageListLength, HiiPackageList); 2299 if (EFI_ERROR (Status)) { 2300 goto Done; 2301 } 2302 2303 // 2304 // 3. Call ConfigRouting GetAltCfg(ConfigRoute, <ConfigResponse>, Guid, Name, DevicePath, AltCfgId, AltCfgResp) 2305 // Get the default configuration string according to the default ID. 2306 // 2307 Status = gHiiConfigRouting->GetAltConfig ( 2308 gHiiConfigRouting, 2309 ConfigAltResp, 2310 VarGuid, 2311 VarName, 2312 DevicePath, 2313 (ActionType == ACTION_SET_DEFAUTL_VALUE) ? &DefaultId:NULL, // it can be NULL to get the current setting. 2314 &ConfigResp 2315 ); 2316 2317 // 2318 // The required setting can't be found. So, it is not required to be validated and set. 2319 // 2320 if (EFI_ERROR (Status)) { 2321 Status = EFI_SUCCESS; 2322 goto NextConfigAltResp; 2323 } 2324 // 2325 // Only the ConfigHdr is found. Not any block data is found. No data is required to be validated and set. 2326 // 2327 if (!GetElementsFromRequest (ConfigResp)) { 2328 goto NextConfigAltResp; 2329 } 2330 2331 // 2332 // 4. Set the default configuration information or Validate current setting by parse IFR code. 2333 // Current Setting is in ConfigResp, will be set into buffer, then check it again. 2334 // 2335 if (ActionType == ACTION_SET_DEFAUTL_VALUE) { 2336 // 2337 // Set the default configuration information. 2338 // 2339 Status = gHiiConfigRouting->RouteConfig (gHiiConfigRouting, ConfigResp, &Progress); 2340 } else { 2341 // 2342 // Current Setting is in ConfigResp, will be set into buffer, then check it again. 2343 // 2344 Status = InternalHiiValidateCurrentSetting (ConfigResp, HiiPackageList, PackageListLength, VarGuid, VarName, HiiHandle); 2345 } 2346 2347 if (EFI_ERROR (Status)) { 2348 goto Done; 2349 } 2350 2351 NextConfigAltResp: 2352 // 2353 // Free the allocated pacakge buffer and the got ConfigResp string. 2354 // 2355 if (HiiPackageList != NULL) { 2356 FreePool (HiiPackageList); 2357 HiiPackageList = NULL; 2358 } 2359 2360 if (ConfigResp != NULL) { 2361 FreePool (ConfigResp); 2362 ConfigResp = NULL; 2363 } 2364 2365 // 2366 // Free the allocated buffer. 2367 // 2368 FreePool (VarGuid); 2369 VarGuid = NULL; 2370 2371 FreePool (VarName); 2372 VarName = NULL; 2373 2374 FreePool (DevicePath); 2375 DevicePath = NULL; 2376 2377 // 2378 // 5. Jump to next ConfigAltResp for another Guid, Name, Path. 2379 // 2380 2381 // 2382 // Get and Skip ConfigHdr 2383 // 2384 while (*StringPtr != L'\0' && *StringPtr != L'&') { 2385 StringPtr++; 2386 } 2387 if (*StringPtr == L'\0') { 2388 break; 2389 } 2390 2391 // 2392 // Construct ConfigAltHdr string "&<ConfigHdr>&ALTCFG=\0" 2393 // | 1 | StrLen (ConfigHdr) | 8 | 1 | 2394 // 2395 MaxLen = 1 + StringPtr - StringHdr + 8 + 1; 2396 ConfigAltHdr = AllocateZeroPool ( MaxLen * sizeof (CHAR16)); 2397 if (ConfigAltHdr == NULL) { 2398 Status = EFI_OUT_OF_RESOURCES; 2399 goto Done; 2400 } 2401 StrCpyS (ConfigAltHdr, MaxLen, L"&"); 2402 StrnCatS (ConfigAltHdr, MaxLen, StringHdr, StringPtr - StringHdr); 2403 StrCatS (ConfigAltHdr, MaxLen, L"&ALTCFG="); 2404 2405 // 2406 // Skip all AltResp (AltConfigHdr ConfigBody) for the same ConfigHdr 2407 // 2408 while ((StringHdr = StrStr (StringPtr, ConfigAltHdr)) != NULL) { 2409 StringPtr = StringHdr + StrLen (ConfigAltHdr); 2410 if (*StringPtr == L'\0') { 2411 break; 2412 } 2413 } 2414 2415 // 2416 // Free the allocated ConfigAltHdr string 2417 // 2418 FreePool (ConfigAltHdr); 2419 if (*StringPtr == L'\0') { 2420 break; 2421 } 2422 2423 // 2424 // Find &GUID as the next ConfigHdr 2425 // 2426 StringPtr = StrStr (StringPtr, L"&GUID"); 2427 if (StringPtr == NULL) { 2428 break; 2429 } 2430 2431 // 2432 // Skip char '&' 2433 // 2434 StringPtr ++; 2435 } 2436 2437 Done: 2438 if (VarGuid != NULL) { 2439 FreePool (VarGuid); 2440 } 2441 2442 if (VarName != NULL) { 2443 FreePool (VarName); 2444 } 2445 2446 if (DevicePath != NULL) { 2447 FreePool (DevicePath); 2448 } 2449 2450 if (ConfigResp != NULL) { 2451 FreePool (ConfigResp); 2452 } 2453 2454 if (ConfigAltResp != NULL) { 2455 FreePool (ConfigAltResp); 2456 } 2457 2458 if (HiiPackageList != NULL) { 2459 FreePool (HiiPackageList); 2460 } 2461 2462 if (EFI_ERROR (Status)) { 2463 return FALSE; 2464 } 2465 2466 return TRUE; 2467 } 2468 2469 /** 2470 Validate the current configuration by parsing HII form IFR opcode. 2471 2472 NULL request string support depends on the ExportConfig interface of 2473 HiiConfigRouting protocol in UEFI specification. 2474 2475 @param Request A null-terminated Unicode string in 2476 <MultiConfigRequest> format. It can be NULL. 2477 If it is NULL, all current configuration for the 2478 entirety of the current HII database will be validated. 2479 2480 @retval TRUE Current configuration is valid. 2481 @retval FALSE Current configuration is invalid. 2482 **/ 2483 BOOLEAN 2484 EFIAPI 2485 HiiValidateSettings ( 2486 IN CONST EFI_STRING Request OPTIONAL 2487 ) 2488 { 2489 return InternalHiiIfrValueAction (Request, 0, ACTION_VALIDATE_SETTING); 2490 } 2491 2492 /** 2493 Reset the default value specified by DefaultId to the driver 2494 configuration got by Request string. 2495 2496 NULL request string support depends on the ExportConfig interface of 2497 HiiConfigRouting protocol in UEFI specification. 2498 2499 @param Request A null-terminated Unicode string in 2500 <MultiConfigRequest> format. It can be NULL. 2501 If it is NULL, all configuration for the 2502 entirety of the current HII database will be reset. 2503 @param DefaultId Specifies the type of defaults to retrieve. 2504 2505 @retval TRUE The default value is set successfully. 2506 @retval FALSE The default value can't be found and set. 2507 **/ 2508 BOOLEAN 2509 EFIAPI 2510 HiiSetToDefaults ( 2511 IN CONST EFI_STRING Request, OPTIONAL 2512 IN UINT16 DefaultId 2513 ) 2514 { 2515 return InternalHiiIfrValueAction (Request, DefaultId, ACTION_SET_DEFAUTL_VALUE); 2516 } 2517 2518 /** 2519 Determines if two values in config strings match. 2520 2521 Compares the substring between StartSearchString and StopSearchString in 2522 FirstString to the substring between StartSearchString and StopSearchString 2523 in SecondString. If the two substrings match, then TRUE is returned. If the 2524 two substrings do not match, then FALSE is returned. 2525 2526 If FirstString is NULL, then ASSERT(). 2527 If SecondString is NULL, then ASSERT(). 2528 If StartSearchString is NULL, then ASSERT(). 2529 If StopSearchString is NULL, then ASSERT(). 2530 2531 @param FirstString Pointer to the first Null-terminated Unicode string. 2532 @param SecondString Pointer to the second Null-terminated Unicode string. 2533 @param StartSearchString Pointer to the Null-terminated Unicode string that 2534 marks the start of the value string to compare. 2535 @param StopSearchString Pointer to the Null-terminated Unicode string that 2536 marks the end of the value string to compare. 2537 2538 @retval FALSE StartSearchString is not present in FirstString. 2539 @retval FALSE StartSearchString is not present in SecondString. 2540 @retval FALSE StopSearchString is not present in FirstString. 2541 @retval FALSE StopSearchString is not present in SecondString. 2542 @retval FALSE The length of the substring in FirstString is not the 2543 same length as the substring in SecondString. 2544 @retval FALSE The value string in FirstString does not matche the 2545 value string in SecondString. 2546 @retval TRUE The value string in FirstString matches the value 2547 string in SecondString. 2548 2549 **/ 2550 BOOLEAN 2551 EFIAPI 2552 InternalHiiCompareSubString ( 2553 IN CHAR16 *FirstString, 2554 IN CHAR16 *SecondString, 2555 IN CHAR16 *StartSearchString, 2556 IN CHAR16 *StopSearchString 2557 ) 2558 { 2559 CHAR16 *EndFirstString; 2560 CHAR16 *EndSecondString; 2561 2562 ASSERT (FirstString != NULL); 2563 ASSERT (SecondString != NULL); 2564 ASSERT (StartSearchString != NULL); 2565 ASSERT (StopSearchString != NULL); 2566 2567 FirstString = StrStr (FirstString, StartSearchString); 2568 if (FirstString == NULL) { 2569 return FALSE; 2570 } 2571 2572 SecondString = StrStr (SecondString, StartSearchString); 2573 if (SecondString == NULL) { 2574 return FALSE; 2575 } 2576 2577 EndFirstString = StrStr (FirstString, StopSearchString); 2578 if (EndFirstString == NULL) { 2579 return FALSE; 2580 } 2581 2582 EndSecondString = StrStr (SecondString, StopSearchString); 2583 if (EndSecondString == NULL) { 2584 return FALSE; 2585 } 2586 2587 if ((EndFirstString - FirstString) != (EndSecondString - SecondString)) { 2588 return FALSE; 2589 } 2590 2591 return (BOOLEAN)(StrnCmp (FirstString, SecondString, EndFirstString - FirstString) == 0); 2592 } 2593 2594 /** 2595 Determines if the routing data specified by GUID and NAME match a <ConfigHdr>. 2596 2597 If ConfigHdr is NULL, then ASSERT(). 2598 2599 @param[in] ConfigHdr Either <ConfigRequest> or <ConfigResp>. 2600 @param[in] Guid GUID of the storage. 2601 @param[in] Name NAME of the storage. 2602 2603 @retval TRUE Routing information matches <ConfigHdr>. 2604 @retval FALSE Routing information does not match <ConfigHdr>. 2605 2606 **/ 2607 BOOLEAN 2608 EFIAPI 2609 HiiIsConfigHdrMatch ( 2610 IN CONST EFI_STRING ConfigHdr, 2611 IN CONST EFI_GUID *Guid, OPTIONAL 2612 IN CONST CHAR16 *Name OPTIONAL 2613 ) 2614 { 2615 EFI_STRING CompareConfigHdr; 2616 BOOLEAN Result; 2617 2618 ASSERT (ConfigHdr != NULL); 2619 2620 // 2621 // Use Guid and Name to generate a <ConfigHdr> string 2622 // 2623 CompareConfigHdr = HiiConstructConfigHdr (Guid, Name, NULL); 2624 if (CompareConfigHdr == NULL) { 2625 return FALSE; 2626 } 2627 2628 Result = TRUE; 2629 if (Guid != NULL) { 2630 // 2631 // Compare GUID value strings 2632 // 2633 Result = InternalHiiCompareSubString (ConfigHdr, CompareConfigHdr, L"GUID=", L"&NAME="); 2634 } 2635 2636 if (Result && Name != NULL) { 2637 // 2638 // Compare NAME value strings 2639 // 2640 Result = InternalHiiCompareSubString (ConfigHdr, CompareConfigHdr, L"&NAME=", L"&PATH="); 2641 } 2642 2643 // 2644 // Free the <ConfigHdr> string 2645 // 2646 FreePool (CompareConfigHdr); 2647 2648 return Result; 2649 } 2650 2651 /** 2652 Retrieves uncommitted data from the Form Browser and converts it to a binary 2653 buffer. 2654 2655 @param[in] VariableGuid Pointer to an EFI_GUID structure. This is an optional 2656 parameter that may be NULL. 2657 @param[in] VariableName Pointer to a Null-terminated Unicode string. This 2658 is an optional parameter that may be NULL. 2659 @param[in] BufferSize Length in bytes of buffer to hold retrieved data. 2660 @param[out] Buffer Buffer of data to be updated. 2661 2662 @retval FALSE The uncommitted data could not be retrieved. 2663 @retval TRUE The uncommitted data was retrieved. 2664 2665 **/ 2666 BOOLEAN 2667 EFIAPI 2668 HiiGetBrowserData ( 2669 IN CONST EFI_GUID *VariableGuid, OPTIONAL 2670 IN CONST CHAR16 *VariableName, OPTIONAL 2671 IN UINTN BufferSize, 2672 OUT UINT8 *Buffer 2673 ) 2674 { 2675 EFI_STRING ResultsData; 2676 UINTN Size; 2677 EFI_STRING ConfigResp; 2678 EFI_STATUS Status; 2679 CHAR16 *Progress; 2680 2681 // 2682 // Retrieve the results data from the Browser Callback 2683 // 2684 ResultsData = InternalHiiBrowserCallback (VariableGuid, VariableName, NULL); 2685 if (ResultsData == NULL) { 2686 return FALSE; 2687 } 2688 2689 // 2690 // Construct <ConfigResp> mConfigHdrTemplate L'&' ResultsData L'\0' 2691 // 2692 Size = (StrLen (mConfigHdrTemplate) + 1) * sizeof (CHAR16); 2693 Size = Size + (StrLen (ResultsData) + 1) * sizeof (CHAR16); 2694 ConfigResp = AllocateZeroPool (Size); 2695 UnicodeSPrint (ConfigResp, Size, L"%s&%s", mConfigHdrTemplate, ResultsData); 2696 2697 // 2698 // Free the allocated buffer 2699 // 2700 FreePool (ResultsData); 2701 if (ConfigResp == NULL) { 2702 return FALSE; 2703 } 2704 2705 // 2706 // Convert <ConfigResp> to a buffer 2707 // 2708 Status = gHiiConfigRouting->ConfigToBlock ( 2709 gHiiConfigRouting, 2710 ConfigResp, 2711 Buffer, 2712 &BufferSize, 2713 &Progress 2714 ); 2715 // 2716 // Free the allocated buffer 2717 // 2718 FreePool (ConfigResp); 2719 2720 if (EFI_ERROR (Status)) { 2721 return FALSE; 2722 } 2723 2724 return TRUE; 2725 } 2726 2727 /** 2728 Updates uncommitted data in the Form Browser. 2729 2730 If Buffer is NULL, then ASSERT(). 2731 2732 @param[in] VariableGuid Pointer to an EFI_GUID structure. This is an optional 2733 parameter that may be NULL. 2734 @param[in] VariableName Pointer to a Null-terminated Unicode string. This 2735 is an optional parameter that may be NULL. 2736 @param[in] BufferSize Length, in bytes, of Buffer. 2737 @param[in] Buffer Buffer of data to commit. 2738 @param[in] RequestElement An optional field to specify which part of the 2739 buffer data will be send back to Browser. If NULL, 2740 the whole buffer of data will be committed to 2741 Browser. 2742 <RequestElement> ::= &OFFSET=<Number>&WIDTH=<Number>* 2743 2744 @retval FALSE The uncommitted data could not be updated. 2745 @retval TRUE The uncommitted data was updated. 2746 2747 **/ 2748 BOOLEAN 2749 EFIAPI 2750 HiiSetBrowserData ( 2751 IN CONST EFI_GUID *VariableGuid, OPTIONAL 2752 IN CONST CHAR16 *VariableName, OPTIONAL 2753 IN UINTN BufferSize, 2754 IN CONST UINT8 *Buffer, 2755 IN CONST CHAR16 *RequestElement OPTIONAL 2756 ) 2757 { 2758 UINTN Size; 2759 EFI_STRING ConfigRequest; 2760 EFI_STRING ConfigResp; 2761 EFI_STRING ResultsData; 2762 2763 ASSERT (Buffer != NULL); 2764 2765 // 2766 // Construct <ConfigRequest> 2767 // 2768 if (RequestElement == NULL) { 2769 // 2770 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template 2771 // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator 2772 // 2773 Size = (StrLen (mConfigHdrTemplate) + 32 + 1) * sizeof (CHAR16); 2774 ConfigRequest = AllocateZeroPool (Size); 2775 UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", mConfigHdrTemplate, (UINT64)BufferSize); 2776 } else { 2777 // 2778 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template 2779 // followed by <RequestElement> followed by a Null-terminator 2780 // 2781 Size = StrLen (mConfigHdrTemplate) * sizeof (CHAR16); 2782 Size = Size + (StrLen (RequestElement) + 1) * sizeof (CHAR16); 2783 ConfigRequest = AllocateZeroPool (Size); 2784 UnicodeSPrint (ConfigRequest, Size, L"%s%s", mConfigHdrTemplate, RequestElement); 2785 } 2786 if (ConfigRequest == NULL) { 2787 return FALSE; 2788 } 2789 2790 // 2791 // Convert <ConfigRequest> to <ConfigResp> 2792 // 2793 ConfigResp = InternalHiiBlockToConfig (ConfigRequest, Buffer, BufferSize); 2794 FreePool (ConfigRequest); 2795 if (ConfigResp == NULL) { 2796 return FALSE; 2797 } 2798 2799 // 2800 // Set data in the uncommitted browser state information 2801 // 2802 ResultsData = InternalHiiBrowserCallback (VariableGuid, VariableName, ConfigResp + StrLen(mConfigHdrTemplate) + 1); 2803 FreePool (ConfigResp); 2804 2805 return (BOOLEAN)(ResultsData != NULL); 2806 } 2807 2808 ///////////////////////////////////////// 2809 ///////////////////////////////////////// 2810 /// IFR Functions 2811 ///////////////////////////////////////// 2812 ///////////////////////////////////////// 2813 2814 #define HII_LIB_OPCODE_ALLOCATION_SIZE 0x200 2815 2816 typedef struct { 2817 UINT8 *Buffer; 2818 UINTN BufferSize; 2819 UINTN Position; 2820 } HII_LIB_OPCODE_BUFFER; 2821 2822 /// 2823 /// Lookup table that converts EFI_IFR_TYPE_X enum values to a width in bytes 2824 /// 2825 GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 mHiiDefaultTypeToWidth[] = { 2826 1, // EFI_IFR_TYPE_NUM_SIZE_8 2827 2, // EFI_IFR_TYPE_NUM_SIZE_16 2828 4, // EFI_IFR_TYPE_NUM_SIZE_32 2829 8, // EFI_IFR_TYPE_NUM_SIZE_64 2830 1, // EFI_IFR_TYPE_BOOLEAN 2831 3, // EFI_IFR_TYPE_TIME 2832 4, // EFI_IFR_TYPE_DATE 2833 2 // EFI_IFR_TYPE_STRING 2834 }; 2835 2836 /** 2837 Allocates and returns a new OpCode Handle. OpCode Handles must be freed with 2838 HiiFreeOpCodeHandle(). 2839 2840 @retval NULL There are not enough resources to allocate a new OpCode Handle. 2841 @retval Other A new OpCode handle. 2842 2843 **/ 2844 VOID * 2845 EFIAPI 2846 HiiAllocateOpCodeHandle ( 2847 VOID 2848 ) 2849 { 2850 HII_LIB_OPCODE_BUFFER *OpCodeBuffer; 2851 2852 OpCodeBuffer = (HII_LIB_OPCODE_BUFFER *)AllocatePool (sizeof (HII_LIB_OPCODE_BUFFER)); 2853 if (OpCodeBuffer == NULL) { 2854 return NULL; 2855 } 2856 OpCodeBuffer->Buffer = (UINT8 *)AllocatePool (HII_LIB_OPCODE_ALLOCATION_SIZE); 2857 if (OpCodeBuffer->Buffer == NULL) { 2858 FreePool (OpCodeBuffer); 2859 return NULL; 2860 } 2861 OpCodeBuffer->BufferSize = HII_LIB_OPCODE_ALLOCATION_SIZE; 2862 OpCodeBuffer->Position = 0; 2863 return (VOID *)OpCodeBuffer; 2864 } 2865 2866 /** 2867 Frees an OpCode Handle that was previously allocated with HiiAllocateOpCodeHandle(). 2868 When an OpCode Handle is freed, all of the opcodes associated with the OpCode 2869 Handle are also freed. 2870 2871 If OpCodeHandle is NULL, then ASSERT(). 2872 2873 @param[in] OpCodeHandle Handle to the buffer of opcodes. 2874 2875 **/ 2876 VOID 2877 EFIAPI 2878 HiiFreeOpCodeHandle ( 2879 VOID *OpCodeHandle 2880 ) 2881 { 2882 HII_LIB_OPCODE_BUFFER *OpCodeBuffer; 2883 2884 ASSERT (OpCodeHandle != NULL); 2885 2886 OpCodeBuffer = (HII_LIB_OPCODE_BUFFER *)OpCodeHandle; 2887 if (OpCodeBuffer->Buffer != NULL) { 2888 FreePool (OpCodeBuffer->Buffer); 2889 } 2890 FreePool (OpCodeBuffer); 2891 } 2892 2893 /** 2894 Internal function gets the current position of opcode buffer. 2895 2896 @param[in] OpCodeHandle Handle to the buffer of opcodes. 2897 2898 @return Current position of opcode buffer. 2899 **/ 2900 UINTN 2901 EFIAPI 2902 InternalHiiOpCodeHandlePosition ( 2903 IN VOID *OpCodeHandle 2904 ) 2905 { 2906 return ((HII_LIB_OPCODE_BUFFER *)OpCodeHandle)->Position; 2907 } 2908 2909 /** 2910 Internal function gets the start pointer of opcode buffer. 2911 2912 @param[in] OpCodeHandle Handle to the buffer of opcodes. 2913 2914 @return Pointer to the opcode buffer base. 2915 **/ 2916 UINT8 * 2917 EFIAPI 2918 InternalHiiOpCodeHandleBuffer ( 2919 IN VOID *OpCodeHandle 2920 ) 2921 { 2922 return ((HII_LIB_OPCODE_BUFFER *)OpCodeHandle)->Buffer; 2923 } 2924 2925 /** 2926 Internal function reserves the enough buffer for current opcode. 2927 When the buffer is not enough, Opcode buffer will be extended. 2928 2929 @param[in] OpCodeHandle Handle to the buffer of opcodes. 2930 @param[in] Size Size of current opcode. 2931 2932 @return Pointer to the current opcode. 2933 **/ 2934 UINT8 * 2935 EFIAPI 2936 InternalHiiGrowOpCodeHandle ( 2937 IN VOID *OpCodeHandle, 2938 IN UINTN Size 2939 ) 2940 { 2941 HII_LIB_OPCODE_BUFFER *OpCodeBuffer; 2942 UINT8 *Buffer; 2943 2944 ASSERT (OpCodeHandle != NULL); 2945 2946 OpCodeBuffer = (HII_LIB_OPCODE_BUFFER *)OpCodeHandle; 2947 if (OpCodeBuffer->Position + Size > OpCodeBuffer->BufferSize) { 2948 Buffer = ReallocatePool ( 2949 OpCodeBuffer->BufferSize, 2950 OpCodeBuffer->BufferSize + (Size + HII_LIB_OPCODE_ALLOCATION_SIZE), 2951 OpCodeBuffer->Buffer 2952 ); 2953 ASSERT (Buffer != NULL); 2954 OpCodeBuffer->Buffer = Buffer; 2955 OpCodeBuffer->BufferSize += (Size + HII_LIB_OPCODE_ALLOCATION_SIZE); 2956 } 2957 Buffer = OpCodeBuffer->Buffer + OpCodeBuffer->Position; 2958 OpCodeBuffer->Position += Size; 2959 return Buffer; 2960 } 2961 2962 /** 2963 Internal function creates opcode based on the template opcode. 2964 2965 @param[in] OpCodeHandle Handle to the buffer of opcodes. 2966 @param[in] OpCodeTemplate Pointer to the template buffer of opcode. 2967 @param[in] OpCode OpCode IFR value. 2968 @param[in] OpCodeSize Size of opcode. 2969 @param[in] ExtensionSize Size of extended opcode. 2970 @param[in] Scope Scope bit of opcode. 2971 2972 @return Pointer to the current opcode with opcode data. 2973 **/ 2974 UINT8 * 2975 EFIAPI 2976 InternalHiiCreateOpCodeExtended ( 2977 IN VOID *OpCodeHandle, 2978 IN VOID *OpCodeTemplate, 2979 IN UINT8 OpCode, 2980 IN UINTN OpCodeSize, 2981 IN UINTN ExtensionSize, 2982 IN UINT8 Scope 2983 ) 2984 { 2985 EFI_IFR_OP_HEADER *Header; 2986 UINT8 *Buffer; 2987 2988 ASSERT (OpCodeTemplate != NULL); 2989 ASSERT ((OpCodeSize + ExtensionSize) <= 0x7F); 2990 2991 Header = (EFI_IFR_OP_HEADER *)OpCodeTemplate; 2992 Header->OpCode = OpCode; 2993 Header->Scope = Scope; 2994 Header->Length = (UINT8)(OpCodeSize + ExtensionSize); 2995 Buffer = InternalHiiGrowOpCodeHandle (OpCodeHandle, Header->Length); 2996 return (UINT8 *)CopyMem (Buffer, Header, OpCodeSize); 2997 } 2998 2999 /** 3000 Internal function creates opcode based on the template opcode for the normal opcode. 3001 3002 @param[in] OpCodeHandle Handle to the buffer of opcodes. 3003 @param[in] OpCodeTemplate Pointer to the template buffer of opcode. 3004 @param[in] OpCode OpCode IFR value. 3005 @param[in] OpCodeSize Size of opcode. 3006 3007 @return Pointer to the current opcode with opcode data. 3008 **/ 3009 UINT8 * 3010 EFIAPI 3011 InternalHiiCreateOpCode ( 3012 IN VOID *OpCodeHandle, 3013 IN VOID *OpCodeTemplate, 3014 IN UINT8 OpCode, 3015 IN UINTN OpCodeSize 3016 ) 3017 { 3018 return InternalHiiCreateOpCodeExtended (OpCodeHandle, OpCodeTemplate, OpCode, OpCodeSize, 0, 0); 3019 } 3020 3021 /** 3022 Append raw opcodes to an OpCodeHandle. 3023 3024 If OpCodeHandle is NULL, then ASSERT(). 3025 If RawBuffer is NULL, then ASSERT(); 3026 3027 @param[in] OpCodeHandle Handle to the buffer of opcodes. 3028 @param[in] RawBuffer Buffer of opcodes to append. 3029 @param[in] RawBufferSize The size, in bytes, of Buffer. 3030 3031 @retval NULL There is not enough space left in Buffer to add the opcode. 3032 @retval Other A pointer to the appended opcodes. 3033 3034 **/ 3035 UINT8 * 3036 EFIAPI 3037 HiiCreateRawOpCodes ( 3038 IN VOID *OpCodeHandle, 3039 IN UINT8 *RawBuffer, 3040 IN UINTN RawBufferSize 3041 ) 3042 { 3043 UINT8 *Buffer; 3044 3045 ASSERT (RawBuffer != NULL); 3046 3047 Buffer = InternalHiiGrowOpCodeHandle (OpCodeHandle, RawBufferSize); 3048 return (UINT8 *)CopyMem (Buffer, RawBuffer, RawBufferSize); 3049 } 3050 3051 /** 3052 Append opcodes from one OpCode Handle to another OpCode handle. 3053 3054 If OpCodeHandle is NULL, then ASSERT(). 3055 If RawOpCodeHandle is NULL, then ASSERT(); 3056 3057 @param[in] OpCodeHandle Handle to the buffer of opcodes. 3058 @param[in] RawOpCodeHandle Handle to the buffer of opcodes. 3059 3060 @retval NULL There is not enough space left in Buffer to add the opcode. 3061 @retval Other A pointer to the appended opcodes. 3062 3063 **/ 3064 UINT8 * 3065 EFIAPI 3066 InternalHiiAppendOpCodes ( 3067 IN VOID *OpCodeHandle, 3068 IN VOID *RawOpCodeHandle 3069 ) 3070 { 3071 HII_LIB_OPCODE_BUFFER *RawOpCodeBuffer; 3072 3073 ASSERT (RawOpCodeHandle != NULL); 3074 3075 RawOpCodeBuffer = (HII_LIB_OPCODE_BUFFER *)RawOpCodeHandle; 3076 return HiiCreateRawOpCodes (OpCodeHandle, RawOpCodeBuffer->Buffer, RawOpCodeBuffer->Position); 3077 } 3078 3079 /** 3080 Create EFI_IFR_END_OP opcode. 3081 3082 If OpCodeHandle is NULL, then ASSERT(). 3083 3084 @param[in] OpCodeHandle Handle to the buffer of opcodes. 3085 3086 @retval NULL There is not enough space left in Buffer to add the opcode. 3087 @retval Other A pointer to the created opcode. 3088 3089 **/ 3090 UINT8 * 3091 EFIAPI 3092 HiiCreateEndOpCode ( 3093 IN VOID *OpCodeHandle 3094 ) 3095 { 3096 EFI_IFR_END OpCode; 3097 3098 return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_END_OP, sizeof (OpCode)); 3099 } 3100 3101 /** 3102 Create EFI_IFR_ONE_OF_OPTION_OP opcode. 3103 3104 If OpCodeHandle is NULL, then ASSERT(). 3105 If Type is invalid, then ASSERT(). 3106 If Flags is invalid, then ASSERT(). 3107 3108 @param[in] OpCodeHandle Handle to the buffer of opcodes. 3109 @param[in] StringId StringId for the option 3110 @param[in] Flags Flags for the option 3111 @param[in] Type Type for the option 3112 @param[in] Value Value for the option 3113 3114 @retval NULL There is not enough space left in Buffer to add the opcode. 3115 @retval Other A pointer to the created opcode. 3116 3117 **/ 3118 UINT8 * 3119 EFIAPI 3120 HiiCreateOneOfOptionOpCode ( 3121 IN VOID *OpCodeHandle, 3122 IN UINT16 StringId, 3123 IN UINT8 Flags, 3124 IN UINT8 Type, 3125 IN UINT64 Value 3126 ) 3127 { 3128 EFI_IFR_ONE_OF_OPTION OpCode; 3129 3130 ASSERT (Type < EFI_IFR_TYPE_OTHER); 3131 3132 ZeroMem (&OpCode, sizeof (OpCode)); 3133 OpCode.Option = StringId; 3134 OpCode.Flags = (UINT8) (Flags & (EFI_IFR_OPTION_DEFAULT | EFI_IFR_OPTION_DEFAULT_MFG)); 3135 OpCode.Type = Type; 3136 CopyMem (&OpCode.Value, &Value, mHiiDefaultTypeToWidth[Type]); 3137 3138 return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_ONE_OF_OPTION_OP, OFFSET_OF(EFI_IFR_ONE_OF_OPTION, Value) + mHiiDefaultTypeToWidth[Type]); 3139 } 3140 3141 /** 3142 Create EFI_IFR_DEFAULT_OP opcode. 3143 3144 If OpCodeHandle is NULL, then ASSERT(). 3145 If Type is invalid, then ASSERT(). 3146 3147 @param[in] OpCodeHandle Handle to the buffer of opcodes. 3148 @param[in] DefaultId DefaultId for the default 3149 @param[in] Type Type for the default 3150 @param[in] Value Value for the default 3151 3152 @retval NULL There is not enough space left in Buffer to add the opcode. 3153 @retval Other A pointer to the created opcode. 3154 3155 **/ 3156 UINT8 * 3157 EFIAPI 3158 HiiCreateDefaultOpCode ( 3159 IN VOID *OpCodeHandle, 3160 IN UINT16 DefaultId, 3161 IN UINT8 Type, 3162 IN UINT64 Value 3163 ) 3164 { 3165 EFI_IFR_DEFAULT OpCode; 3166 3167 ASSERT (Type < EFI_IFR_TYPE_OTHER); 3168 3169 ZeroMem (&OpCode, sizeof (OpCode)); 3170 OpCode.Type = Type; 3171 OpCode.DefaultId = DefaultId; 3172 CopyMem (&OpCode.Value, &Value, mHiiDefaultTypeToWidth[Type]); 3173 3174 return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_DEFAULT_OP, OFFSET_OF(EFI_IFR_DEFAULT, Value) + mHiiDefaultTypeToWidth[Type]); 3175 } 3176 3177 /** 3178 Create EFI_IFR_GUID opcode. 3179 3180 If OpCodeHandle is NULL, then ASSERT(). 3181 If Guid is NULL, then ASSERT(). 3182 If OpCodeSize < sizeof (EFI_IFR_GUID), then ASSERT(). 3183 3184 @param[in] OpCodeHandle Handle to the buffer of opcodes. 3185 @param[in] Guid Pointer to EFI_GUID of this guided opcode. 3186 @param[in] GuidOpCode Pointer to an EFI_IFR_GUID opcode. This is an 3187 optional parameter that may be NULL. If this 3188 parameter is NULL, then the GUID extension 3189 region of the created opcode is filled with zeros. 3190 If this parameter is not NULL, then the GUID 3191 extension region of GuidData will be copied to 3192 the GUID extension region of the created opcode. 3193 @param[in] OpCodeSize The size, in bytes, of created opcode. This value 3194 must be >= sizeof(EFI_IFR_GUID). 3195 3196 @retval NULL There is not enough space left in Buffer to add the opcode. 3197 @retval Other A pointer to the created opcode. 3198 3199 **/ 3200 UINT8 * 3201 EFIAPI 3202 HiiCreateGuidOpCode ( 3203 IN VOID *OpCodeHandle, 3204 IN CONST EFI_GUID *Guid, 3205 IN CONST VOID *GuidOpCode, OPTIONAL 3206 IN UINTN OpCodeSize 3207 ) 3208 { 3209 EFI_IFR_GUID OpCode; 3210 EFI_IFR_GUID *OpCodePointer; 3211 3212 ASSERT (Guid != NULL); 3213 ASSERT (OpCodeSize >= sizeof (OpCode)); 3214 3215 ZeroMem (&OpCode, sizeof (OpCode)); 3216 CopyGuid ((EFI_GUID *)(VOID *)&OpCode.Guid, Guid); 3217 3218 OpCodePointer = (EFI_IFR_GUID *)InternalHiiCreateOpCodeExtended ( 3219 OpCodeHandle, 3220 &OpCode, 3221 EFI_IFR_GUID_OP, 3222 sizeof (OpCode), 3223 OpCodeSize - sizeof (OpCode), 3224 0 3225 ); 3226 if (OpCodePointer != NULL && GuidOpCode != NULL) { 3227 CopyMem (OpCodePointer + 1, (EFI_IFR_GUID *)GuidOpCode + 1, OpCodeSize - sizeof (OpCode)); 3228 } 3229 return (UINT8 *)OpCodePointer; 3230 } 3231 3232 /** 3233 Create EFI_IFR_ACTION_OP opcode. 3234 3235 If OpCodeHandle is NULL, then ASSERT(). 3236 If any reserved bits are set in QuestionFlags, then ASSERT(). 3237 3238 @param[in] OpCodeHandle Handle to the buffer of opcodes. 3239 @param[in] QuestionId Question ID 3240 @param[in] Prompt String ID for Prompt 3241 @param[in] Help String ID for Help 3242 @param[in] QuestionFlags Flags in Question Header 3243 @param[in] QuestionConfig String ID for configuration 3244 3245 @retval NULL There is not enough space left in Buffer to add the opcode. 3246 @retval Other A pointer to the created opcode. 3247 3248 **/ 3249 UINT8 * 3250 EFIAPI 3251 HiiCreateActionOpCode ( 3252 IN VOID *OpCodeHandle, 3253 IN EFI_QUESTION_ID QuestionId, 3254 IN EFI_STRING_ID Prompt, 3255 IN EFI_STRING_ID Help, 3256 IN UINT8 QuestionFlags, 3257 IN EFI_STRING_ID QuestionConfig 3258 ) 3259 { 3260 EFI_IFR_ACTION OpCode; 3261 3262 ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED))) == 0); 3263 3264 ZeroMem (&OpCode, sizeof (OpCode)); 3265 OpCode.Question.QuestionId = QuestionId; 3266 OpCode.Question.Header.Prompt = Prompt; 3267 OpCode.Question.Header.Help = Help; 3268 OpCode.Question.Flags = QuestionFlags; 3269 OpCode.QuestionConfig = QuestionConfig; 3270 3271 return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_ACTION_OP, sizeof (OpCode)); 3272 } 3273 3274 /** 3275 Create EFI_IFR_SUBTITLE_OP opcode. 3276 3277 If OpCodeHandle is NULL, then ASSERT(). 3278 If any reserved bits are set in Flags, then ASSERT(). 3279 If Scope > 1, then ASSERT(). 3280 3281 @param[in] OpCodeHandle Handle to the buffer of opcodes. 3282 @param[in] Prompt String ID for Prompt 3283 @param[in] Help String ID for Help 3284 @param[in] Flags Subtitle opcode flags 3285 @param[in] Scope 1 if this opcpde is the beginning of a new scope. 3286 0 if this opcode is within the current scope. 3287 3288 @retval NULL There is not enough space left in Buffer to add the opcode. 3289 @retval Other A pointer to the created opcode. 3290 3291 **/ 3292 UINT8 * 3293 EFIAPI 3294 HiiCreateSubTitleOpCode ( 3295 IN VOID *OpCodeHandle, 3296 IN EFI_STRING_ID Prompt, 3297 IN EFI_STRING_ID Help, 3298 IN UINT8 Flags, 3299 IN UINT8 Scope 3300 ) 3301 { 3302 EFI_IFR_SUBTITLE OpCode; 3303 3304 ASSERT (Scope <= 1); 3305 ASSERT ((Flags & (~(EFI_IFR_FLAGS_HORIZONTAL))) == 0); 3306 3307 ZeroMem (&OpCode, sizeof (OpCode)); 3308 OpCode.Statement.Prompt = Prompt; 3309 OpCode.Statement.Help = Help; 3310 OpCode.Flags = Flags; 3311 3312 return InternalHiiCreateOpCodeExtended ( 3313 OpCodeHandle, 3314 &OpCode, 3315 EFI_IFR_SUBTITLE_OP, 3316 sizeof (OpCode), 3317 0, 3318 Scope 3319 ); 3320 } 3321 3322 /** 3323 Create EFI_IFR_REF_OP opcode. 3324 3325 If OpCodeHandle is NULL, then ASSERT(). 3326 If any reserved bits are set in QuestionFlags, then ASSERT(). 3327 3328 @param[in] OpCodeHandle Handle to the buffer of opcodes. 3329 @param[in] FormId Destination Form ID 3330 @param[in] Prompt String ID for Prompt 3331 @param[in] Help String ID for Help 3332 @param[in] QuestionFlags Flags in Question Header 3333 @param[in] QuestionId Question ID 3334 3335 @retval NULL There is not enough space left in Buffer to add the opcode. 3336 @retval Other A pointer to the created opcode. 3337 3338 **/ 3339 UINT8 * 3340 EFIAPI 3341 HiiCreateGotoOpCode ( 3342 IN VOID *OpCodeHandle, 3343 IN EFI_FORM_ID FormId, 3344 IN EFI_STRING_ID Prompt, 3345 IN EFI_STRING_ID Help, 3346 IN UINT8 QuestionFlags, 3347 IN EFI_QUESTION_ID QuestionId 3348 ) 3349 { 3350 EFI_IFR_REF OpCode; 3351 3352 ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED))) == 0); 3353 3354 ZeroMem (&OpCode, sizeof (OpCode)); 3355 OpCode.Question.Header.Prompt = Prompt; 3356 OpCode.Question.Header.Help = Help; 3357 OpCode.Question.QuestionId = QuestionId; 3358 OpCode.Question.Flags = QuestionFlags; 3359 OpCode.FormId = FormId; 3360 3361 return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_REF_OP, sizeof (OpCode)); 3362 } 3363 3364 /** 3365 Create EFI_IFR_REF_OP, EFI_IFR_REF2_OP, EFI_IFR_REF3_OP and EFI_IFR_REF4_OP opcode. 3366 3367 When RefDevicePath is not zero, EFI_IFR_REF4 opcode will be created. 3368 When RefDevicePath is zero and RefFormSetId is not NULL, EFI_IFR_REF3 opcode will be created. 3369 When RefDevicePath is zero, RefFormSetId is NULL and RefQuestionId is not zero, EFI_IFR_REF2 opcode will be created. 3370 When RefDevicePath is zero, RefFormSetId is NULL and RefQuestionId is zero, EFI_IFR_REF opcode will be created. 3371 3372 If OpCodeHandle is NULL, then ASSERT(). 3373 If any reserved bits are set in QuestionFlags, then ASSERT(). 3374 3375 @param[in] OpCodeHandle The handle to the buffer of opcodes. 3376 @param[in] RefFormId The Destination Form ID. 3377 @param[in] Prompt The string ID for Prompt. 3378 @param[in] Help The string ID for Help. 3379 @param[in] QuestionFlags The flags in Question Header 3380 @param[in] QuestionId Question ID. 3381 @param[in] RefQuestionId The question on the form to which this link is referring. 3382 If its value is zero, then the link refers to the top of the form. 3383 @param[in] RefFormSetId The form set to which this link is referring. If its value is NULL, and RefDevicePath is 3384 zero, then the link is to the current form set. 3385 @param[in] RefDevicePath The string identifier that specifies the string containing the text representation of 3386 the device path to which the form set containing the form specified by FormId. 3387 If its value is zero, then the link refers to the current page. 3388 3389 @retval NULL There is not enough space left in Buffer to add the opcode. 3390 @retval Other A pointer to the created opcode. 3391 3392 **/ 3393 UINT8 * 3394 EFIAPI 3395 HiiCreateGotoExOpCode ( 3396 IN VOID *OpCodeHandle, 3397 IN EFI_FORM_ID RefFormId, 3398 IN EFI_STRING_ID Prompt, 3399 IN EFI_STRING_ID Help, 3400 IN UINT8 QuestionFlags, 3401 IN EFI_QUESTION_ID QuestionId, 3402 IN EFI_QUESTION_ID RefQuestionId, 3403 IN EFI_GUID *RefFormSetId, OPTIONAL 3404 IN EFI_STRING_ID RefDevicePath 3405 ) 3406 { 3407 EFI_IFR_REF4 OpCode; 3408 UINTN OpCodeSize; 3409 3410 ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED))) == 0); 3411 3412 ZeroMem (&OpCode, sizeof (OpCode)); 3413 OpCode.Question.Header.Prompt = Prompt; 3414 OpCode.Question.Header.Help = Help; 3415 OpCode.Question.QuestionId = QuestionId; 3416 OpCode.Question.Flags = QuestionFlags; 3417 OpCode.FormId = RefFormId; 3418 OpCode.QuestionId = RefQuestionId; 3419 OpCode.DevicePath = RefDevicePath; 3420 if (RefFormSetId != NULL) { 3421 CopyMem (&OpCode.FormSetId, RefFormSetId, sizeof (OpCode.FormSetId)); 3422 } 3423 3424 // 3425 // Cacluate OpCodeSize based on the input Ref value. 3426 // Try to use the small OpCode to save size. 3427 // 3428 OpCodeSize = sizeof (EFI_IFR_REF); 3429 if (RefDevicePath != 0) { 3430 OpCodeSize = sizeof (EFI_IFR_REF4); 3431 } else if (RefFormSetId != NULL) { 3432 OpCodeSize = sizeof (EFI_IFR_REF3); 3433 } else if (RefQuestionId != 0) { 3434 OpCodeSize = sizeof (EFI_IFR_REF2); 3435 } 3436 3437 return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_REF_OP, OpCodeSize); 3438 } 3439 3440 /** 3441 Create EFI_IFR_CHECKBOX_OP opcode. 3442 3443 If OpCodeHandle is NULL, then ASSERT(). 3444 If any reserved bits are set in QuestionFlags, then ASSERT(). 3445 If any reserved bits are set in CheckBoxFlags, then ASSERT(). 3446 3447 @param[in] OpCodeHandle Handle to the buffer of opcodes. 3448 @param[in] QuestionId Question ID 3449 @param[in] VarStoreId Storage ID 3450 @param[in] VarOffset Offset in Storage or String ID of the name (VarName) 3451 for this name/value pair. 3452 @param[in] Prompt String ID for Prompt 3453 @param[in] Help String ID for Help 3454 @param[in] QuestionFlags Flags in Question Header 3455 @param[in] CheckBoxFlags Flags for checkbox opcode 3456 @param[in] DefaultsOpCodeHandle Handle for a buffer of DEFAULT opcodes. This 3457 is an optional parameter that may be NULL. 3458 3459 @retval NULL There is not enough space left in Buffer to add the opcode. 3460 @retval Other A pointer to the created opcode. 3461 3462 **/ 3463 UINT8 * 3464 EFIAPI 3465 HiiCreateCheckBoxOpCode ( 3466 IN VOID *OpCodeHandle, 3467 IN EFI_QUESTION_ID QuestionId, 3468 IN EFI_VARSTORE_ID VarStoreId, 3469 IN UINT16 VarOffset, 3470 IN EFI_STRING_ID Prompt, 3471 IN EFI_STRING_ID Help, 3472 IN UINT8 QuestionFlags, 3473 IN UINT8 CheckBoxFlags, 3474 IN VOID *DefaultsOpCodeHandle OPTIONAL 3475 ) 3476 { 3477 EFI_IFR_CHECKBOX OpCode; 3478 UINTN Position; 3479 3480 ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED))) == 0); 3481 3482 ZeroMem (&OpCode, sizeof (OpCode)); 3483 OpCode.Question.QuestionId = QuestionId; 3484 OpCode.Question.VarStoreId = VarStoreId; 3485 OpCode.Question.VarStoreInfo.VarOffset = VarOffset; 3486 OpCode.Question.Header.Prompt = Prompt; 3487 OpCode.Question.Header.Help = Help; 3488 OpCode.Question.Flags = QuestionFlags; 3489 OpCode.Flags = CheckBoxFlags; 3490 3491 if (DefaultsOpCodeHandle == NULL) { 3492 return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_CHECKBOX_OP, sizeof (OpCode)); 3493 } 3494 3495 Position = InternalHiiOpCodeHandlePosition (OpCodeHandle); 3496 InternalHiiCreateOpCodeExtended (OpCodeHandle, &OpCode, EFI_IFR_CHECKBOX_OP, sizeof (OpCode), 0, 1); 3497 InternalHiiAppendOpCodes (OpCodeHandle, DefaultsOpCodeHandle); 3498 HiiCreateEndOpCode (OpCodeHandle); 3499 return InternalHiiOpCodeHandleBuffer (OpCodeHandle) + Position; 3500 } 3501 3502 /** 3503 Create EFI_IFR_NUMERIC_OP opcode. 3504 3505 If OpCodeHandle is NULL, then ASSERT(). 3506 If any reserved bits are set in QuestionFlags, then ASSERT(). 3507 If any reserved bits are set in NumericFlags, then ASSERT(). 3508 3509 @param[in] OpCodeHandle Handle to the buffer of opcodes. 3510 @param[in] QuestionId Question ID 3511 @param[in] VarStoreId Storage ID 3512 @param[in] VarOffset Offset in Storage or String ID of the name (VarName) 3513 for this name/value pair. 3514 @param[in] Prompt String ID for Prompt 3515 @param[in] Help String ID for Help 3516 @param[in] QuestionFlags Flags in Question Header 3517 @param[in] NumericFlags Flags for numeric opcode 3518 @param[in] Minimum Numeric minimum value 3519 @param[in] Maximum Numeric maximum value 3520 @param[in] Step Numeric step for edit 3521 @param[in] DefaultsOpCodeHandle Handle for a buffer of DEFAULT opcodes. This 3522 is an optional parameter that may be NULL. 3523 3524 @retval NULL There is not enough space left in Buffer to add the opcode. 3525 @retval Other A pointer to the created opcode. 3526 3527 **/ 3528 UINT8 * 3529 EFIAPI 3530 HiiCreateNumericOpCode ( 3531 IN VOID *OpCodeHandle, 3532 IN EFI_QUESTION_ID QuestionId, 3533 IN EFI_VARSTORE_ID VarStoreId, 3534 IN UINT16 VarOffset, 3535 IN EFI_STRING_ID Prompt, 3536 IN EFI_STRING_ID Help, 3537 IN UINT8 QuestionFlags, 3538 IN UINT8 NumericFlags, 3539 IN UINT64 Minimum, 3540 IN UINT64 Maximum, 3541 IN UINT64 Step, 3542 IN VOID *DefaultsOpCodeHandle OPTIONAL 3543 ) 3544 { 3545 EFI_IFR_NUMERIC OpCode; 3546 UINTN Position; 3547 UINTN Length; 3548 3549 ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED))) == 0); 3550 3551 Length = 0; 3552 ZeroMem (&OpCode, sizeof (OpCode)); 3553 OpCode.Question.QuestionId = QuestionId; 3554 OpCode.Question.VarStoreId = VarStoreId; 3555 OpCode.Question.VarStoreInfo.VarOffset = VarOffset; 3556 OpCode.Question.Header.Prompt = Prompt; 3557 OpCode.Question.Header.Help = Help; 3558 OpCode.Question.Flags = QuestionFlags; 3559 OpCode.Flags = NumericFlags; 3560 3561 switch (NumericFlags & EFI_IFR_NUMERIC_SIZE) { 3562 case EFI_IFR_NUMERIC_SIZE_1: 3563 OpCode.data.u8.MinValue = (UINT8)Minimum; 3564 OpCode.data.u8.MaxValue = (UINT8)Maximum; 3565 OpCode.data.u8.Step = (UINT8)Step; 3566 Length = 3; 3567 break; 3568 3569 case EFI_IFR_NUMERIC_SIZE_2: 3570 OpCode.data.u16.MinValue = (UINT16)Minimum; 3571 OpCode.data.u16.MaxValue = (UINT16)Maximum; 3572 OpCode.data.u16.Step = (UINT16)Step; 3573 Length = 6; 3574 break; 3575 3576 case EFI_IFR_NUMERIC_SIZE_4: 3577 OpCode.data.u32.MinValue = (UINT32)Minimum; 3578 OpCode.data.u32.MaxValue = (UINT32)Maximum; 3579 OpCode.data.u32.Step = (UINT32)Step; 3580 Length = 12; 3581 break; 3582 3583 case EFI_IFR_NUMERIC_SIZE_8: 3584 OpCode.data.u64.MinValue = Minimum; 3585 OpCode.data.u64.MaxValue = Maximum; 3586 OpCode.data.u64.Step = Step; 3587 Length = 24; 3588 break; 3589 } 3590 3591 Length += OFFSET_OF (EFI_IFR_NUMERIC, data); 3592 3593 if (DefaultsOpCodeHandle == NULL) { 3594 return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_NUMERIC_OP, Length); 3595 } 3596 3597 Position = InternalHiiOpCodeHandlePosition (OpCodeHandle); 3598 InternalHiiCreateOpCodeExtended (OpCodeHandle, &OpCode, EFI_IFR_NUMERIC_OP, Length, 0, 1); 3599 InternalHiiAppendOpCodes (OpCodeHandle, DefaultsOpCodeHandle); 3600 HiiCreateEndOpCode (OpCodeHandle); 3601 return InternalHiiOpCodeHandleBuffer (OpCodeHandle) + Position; 3602 } 3603 3604 /** 3605 Create EFI_IFR_STRING_OP opcode. 3606 3607 If OpCodeHandle is NULL, then ASSERT(). 3608 If any reserved bits are set in QuestionFlags, then ASSERT(). 3609 If any reserved bits are set in StringFlags, then ASSERT(). 3610 3611 @param[in] OpCodeHandle Handle to the buffer of opcodes. 3612 @param[in] QuestionId Question ID 3613 @param[in] VarStoreId Storage ID 3614 @param[in] VarOffset Offset in Storage or String ID of the name (VarName) 3615 for this name/value pair. 3616 @param[in] Prompt String ID for Prompt 3617 @param[in] Help String ID for Help 3618 @param[in] QuestionFlags Flags in Question Header 3619 @param[in] StringFlags Flags for string opcode 3620 @param[in] MinSize String minimum length 3621 @param[in] MaxSize String maximum length 3622 @param[in] DefaultsOpCodeHandle Handle for a buffer of DEFAULT opcodes. This 3623 is an optional parameter that may be NULL. 3624 3625 @retval NULL There is not enough space left in Buffer to add the opcode. 3626 @retval Other A pointer to the created opcode. 3627 3628 **/ 3629 UINT8 * 3630 EFIAPI 3631 HiiCreateStringOpCode ( 3632 IN VOID *OpCodeHandle, 3633 IN EFI_QUESTION_ID QuestionId, 3634 IN EFI_VARSTORE_ID VarStoreId, 3635 IN UINT16 VarOffset, 3636 IN EFI_STRING_ID Prompt, 3637 IN EFI_STRING_ID Help, 3638 IN UINT8 QuestionFlags, 3639 IN UINT8 StringFlags, 3640 IN UINT8 MinSize, 3641 IN UINT8 MaxSize, 3642 IN VOID *DefaultsOpCodeHandle OPTIONAL 3643 ) 3644 { 3645 EFI_IFR_STRING OpCode; 3646 UINTN Position; 3647 3648 ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED))) == 0); 3649 3650 ZeroMem (&OpCode, sizeof (OpCode)); 3651 OpCode.Question.Header.Prompt = Prompt; 3652 OpCode.Question.Header.Help = Help; 3653 OpCode.Question.QuestionId = QuestionId; 3654 OpCode.Question.VarStoreId = VarStoreId; 3655 OpCode.Question.VarStoreInfo.VarOffset = VarOffset; 3656 OpCode.Question.Flags = QuestionFlags; 3657 OpCode.MinSize = MinSize; 3658 OpCode.MaxSize = MaxSize; 3659 OpCode.Flags = (UINT8) (StringFlags & EFI_IFR_STRING_MULTI_LINE); 3660 3661 if (DefaultsOpCodeHandle == NULL) { 3662 return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_STRING_OP, sizeof (OpCode)); 3663 } 3664 3665 Position = InternalHiiOpCodeHandlePosition (OpCodeHandle); 3666 InternalHiiCreateOpCodeExtended (OpCodeHandle, &OpCode, EFI_IFR_STRING_OP, sizeof (OpCode), 0, 1); 3667 InternalHiiAppendOpCodes (OpCodeHandle, DefaultsOpCodeHandle); 3668 HiiCreateEndOpCode (OpCodeHandle); 3669 return InternalHiiOpCodeHandleBuffer (OpCodeHandle) + Position; 3670 } 3671 3672 /** 3673 Create EFI_IFR_ONE_OF_OP opcode. 3674 3675 If OpCodeHandle is NULL, then ASSERT(). 3676 If any reserved bits are set in QuestionFlags, then ASSERT(). 3677 If any reserved bits are set in OneOfFlags, then ASSERT(). 3678 3679 @param[in] OpCodeHandle Handle to the buffer of opcodes. 3680 @param[in] QuestionId Question ID 3681 @param[in] VarStoreId Storage ID 3682 @param[in] VarOffset Offset in Storage or String ID of the name (VarName) 3683 for this name/value pair. 3684 @param[in] Prompt String ID for Prompt 3685 @param[in] Help String ID for Help 3686 @param[in] QuestionFlags Flags in Question Header 3687 @param[in] OneOfFlags Flags for oneof opcode 3688 @param[in] OptionsOpCodeHandle Handle for a buffer of ONE_OF_OPTION opcodes. 3689 @param[in] DefaultsOpCodeHandle Handle for a buffer of DEFAULT opcodes. This 3690 is an optional parameter that may be NULL. 3691 3692 @retval NULL There is not enough space left in Buffer to add the opcode. 3693 @retval Other A pointer to the created opcode. 3694 3695 **/ 3696 UINT8 * 3697 EFIAPI 3698 HiiCreateOneOfOpCode ( 3699 IN VOID *OpCodeHandle, 3700 IN EFI_QUESTION_ID QuestionId, 3701 IN EFI_VARSTORE_ID VarStoreId, 3702 IN UINT16 VarOffset, 3703 IN EFI_STRING_ID Prompt, 3704 IN EFI_STRING_ID Help, 3705 IN UINT8 QuestionFlags, 3706 IN UINT8 OneOfFlags, 3707 IN VOID *OptionsOpCodeHandle, 3708 IN VOID *DefaultsOpCodeHandle OPTIONAL 3709 ) 3710 { 3711 EFI_IFR_ONE_OF OpCode; 3712 UINTN Position; 3713 UINTN Length; 3714 3715 ASSERT (OptionsOpCodeHandle != NULL); 3716 ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED | EFI_IFR_FLAG_OPTIONS_ONLY))) == 0); 3717 3718 ZeroMem (&OpCode, sizeof (OpCode)); 3719 OpCode.Question.Header.Prompt = Prompt; 3720 OpCode.Question.Header.Help = Help; 3721 OpCode.Question.QuestionId = QuestionId; 3722 OpCode.Question.VarStoreId = VarStoreId; 3723 OpCode.Question.VarStoreInfo.VarOffset = VarOffset; 3724 OpCode.Question.Flags = QuestionFlags; 3725 OpCode.Flags = OneOfFlags; 3726 3727 Length = OFFSET_OF (EFI_IFR_ONE_OF, data); 3728 Length += (1 << (OneOfFlags & EFI_IFR_NUMERIC_SIZE)) * 3; 3729 3730 Position = InternalHiiOpCodeHandlePosition (OpCodeHandle); 3731 InternalHiiCreateOpCodeExtended (OpCodeHandle, &OpCode, EFI_IFR_ONE_OF_OP, Length, 0, 1); 3732 InternalHiiAppendOpCodes (OpCodeHandle, OptionsOpCodeHandle); 3733 if (DefaultsOpCodeHandle != NULL) { 3734 InternalHiiAppendOpCodes (OpCodeHandle, DefaultsOpCodeHandle); 3735 } 3736 HiiCreateEndOpCode (OpCodeHandle); 3737 return InternalHiiOpCodeHandleBuffer (OpCodeHandle) + Position; 3738 } 3739 3740 /** 3741 Create EFI_IFR_ORDERED_LIST_OP opcode. 3742 3743 If OpCodeHandle is NULL, then ASSERT(). 3744 If any reserved bits are set in QuestionFlags, then ASSERT(). 3745 If any reserved bits are set in OrderedListFlags, then ASSERT(). 3746 3747 @param[in] OpCodeHandle Handle to the buffer of opcodes. 3748 @param[in] QuestionId Question ID 3749 @param[in] VarStoreId Storage ID 3750 @param[in] VarOffset Offset in Storage or String ID of the name (VarName) 3751 for this name/value pair. 3752 @param[in] Prompt String ID for Prompt 3753 @param[in] Help String ID for Help 3754 @param[in] QuestionFlags Flags in Question Header 3755 @param[in] OrderedListFlags Flags for ordered list opcode 3756 @param[in] DataType Type for option value 3757 @param[in] MaxContainers Maximum count for options in this ordered list 3758 @param[in] OptionsOpCodeHandle Handle for a buffer of ONE_OF_OPTION opcodes. 3759 @param[in] DefaultsOpCodeHandle Handle for a buffer of DEFAULT opcodes. This 3760 is an optional parameter that may be NULL. 3761 3762 @retval NULL There is not enough space left in Buffer to add the opcode. 3763 @retval Other A pointer to the created opcode. 3764 3765 **/ 3766 UINT8 * 3767 EFIAPI 3768 HiiCreateOrderedListOpCode ( 3769 IN VOID *OpCodeHandle, 3770 IN EFI_QUESTION_ID QuestionId, 3771 IN EFI_VARSTORE_ID VarStoreId, 3772 IN UINT16 VarOffset, 3773 IN EFI_STRING_ID Prompt, 3774 IN EFI_STRING_ID Help, 3775 IN UINT8 QuestionFlags, 3776 IN UINT8 OrderedListFlags, 3777 IN UINT8 DataType, 3778 IN UINT8 MaxContainers, 3779 IN VOID *OptionsOpCodeHandle, 3780 IN VOID *DefaultsOpCodeHandle OPTIONAL 3781 ) 3782 { 3783 EFI_IFR_ORDERED_LIST OpCode; 3784 UINTN Position; 3785 3786 ASSERT (OptionsOpCodeHandle != NULL); 3787 ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED | EFI_IFR_FLAG_OPTIONS_ONLY))) == 0); 3788 3789 ZeroMem (&OpCode, sizeof (OpCode)); 3790 OpCode.Question.Header.Prompt = Prompt; 3791 OpCode.Question.Header.Help = Help; 3792 OpCode.Question.QuestionId = QuestionId; 3793 OpCode.Question.VarStoreId = VarStoreId; 3794 OpCode.Question.VarStoreInfo.VarOffset = VarOffset; 3795 OpCode.Question.Flags = QuestionFlags; 3796 OpCode.MaxContainers = MaxContainers; 3797 OpCode.Flags = OrderedListFlags; 3798 3799 Position = InternalHiiOpCodeHandlePosition (OpCodeHandle); 3800 InternalHiiCreateOpCodeExtended (OpCodeHandle, &OpCode, EFI_IFR_ORDERED_LIST_OP, sizeof (OpCode), 0, 1); 3801 InternalHiiAppendOpCodes (OpCodeHandle, OptionsOpCodeHandle); 3802 if (DefaultsOpCodeHandle != NULL) { 3803 InternalHiiAppendOpCodes (OpCodeHandle, DefaultsOpCodeHandle); 3804 } 3805 HiiCreateEndOpCode (OpCodeHandle); 3806 return InternalHiiOpCodeHandleBuffer (OpCodeHandle) + Position; 3807 } 3808 3809 /** 3810 Create EFI_IFR_TEXT_OP opcode. 3811 3812 If OpCodeHandle is NULL, then ASSERT(). 3813 3814 @param[in] OpCodeHandle Handle to the buffer of opcodes. 3815 @param[in] Prompt String ID for Prompt. 3816 @param[in] Help String ID for Help. 3817 @param[in] TextTwo String ID for TextTwo. 3818 3819 @retval NULL There is not enough space left in Buffer to add the opcode. 3820 @retval Other A pointer to the created opcode. 3821 3822 **/ 3823 UINT8 * 3824 EFIAPI 3825 HiiCreateTextOpCode ( 3826 IN VOID *OpCodeHandle, 3827 IN EFI_STRING_ID Prompt, 3828 IN EFI_STRING_ID Help, 3829 IN EFI_STRING_ID TextTwo 3830 ) 3831 { 3832 EFI_IFR_TEXT OpCode; 3833 3834 ZeroMem (&OpCode, sizeof (OpCode)); 3835 OpCode.Statement.Prompt = Prompt; 3836 OpCode.Statement.Help = Help; 3837 OpCode.TextTwo = TextTwo; 3838 3839 return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_TEXT_OP, sizeof (OpCode)); 3840 } 3841 3842 /** 3843 Create EFI_IFR_DATE_OP opcode. 3844 3845 If OpCodeHandle is NULL, then ASSERT(). 3846 If any reserved bits are set in QuestionFlags, then ASSERT(). 3847 If any reserved bits are set in DateFlags, then ASSERT(). 3848 3849 @param[in] OpCodeHandle Handle to the buffer of opcodes. 3850 @param[in] QuestionId Question ID 3851 @param[in] VarStoreId Storage ID, optional. If DateFlags is not 3852 QF_DATE_STORAGE_NORMAL, this parameter is ignored. 3853 @param[in] VarOffset Offset in Storage or String ID of the name (VarName) 3854 for this name/value pair, optional. If DateFlags is not 3855 QF_DATE_STORAGE_NORMAL, this parameter is ignored. 3856 @param[in] Prompt String ID for Prompt 3857 @param[in] Help String ID for Help 3858 @param[in] QuestionFlags Flags in Question Header 3859 @param[in] DateFlags Flags for date opcode 3860 @param[in] DefaultsOpCodeHandle Handle for a buffer of DEFAULT opcodes. This 3861 is an optional parameter that may be NULL. 3862 3863 @retval NULL There is not enough space left in Buffer to add the opcode. 3864 @retval Other A pointer to the created opcode. 3865 3866 **/ 3867 UINT8 * 3868 EFIAPI 3869 HiiCreateDateOpCode ( 3870 IN VOID *OpCodeHandle, 3871 IN EFI_QUESTION_ID QuestionId, 3872 IN EFI_VARSTORE_ID VarStoreId, OPTIONAL 3873 IN UINT16 VarOffset, OPTIONAL 3874 IN EFI_STRING_ID Prompt, 3875 IN EFI_STRING_ID Help, 3876 IN UINT8 QuestionFlags, 3877 IN UINT8 DateFlags, 3878 IN VOID *DefaultsOpCodeHandle OPTIONAL 3879 ) 3880 { 3881 EFI_IFR_DATE OpCode; 3882 UINTN Position; 3883 3884 ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED))) == 0); 3885 ASSERT ((DateFlags & (~(EFI_QF_DATE_YEAR_SUPPRESS | EFI_QF_DATE_MONTH_SUPPRESS | EFI_QF_DATE_DAY_SUPPRESS | EFI_QF_DATE_STORAGE))) == 0); 3886 3887 ZeroMem (&OpCode, sizeof (OpCode)); 3888 OpCode.Question.Header.Prompt = Prompt; 3889 OpCode.Question.Header.Help = Help; 3890 OpCode.Question.QuestionId = QuestionId; 3891 OpCode.Question.VarStoreId = VarStoreId; 3892 OpCode.Question.VarStoreInfo.VarOffset = VarOffset; 3893 OpCode.Question.Flags = QuestionFlags; 3894 OpCode.Flags = DateFlags; 3895 3896 if (DefaultsOpCodeHandle == NULL) { 3897 return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_DATE_OP, sizeof (OpCode)); 3898 } 3899 3900 Position = InternalHiiOpCodeHandlePosition (OpCodeHandle); 3901 InternalHiiCreateOpCodeExtended (OpCodeHandle, &OpCode, EFI_IFR_DATE_OP, sizeof (OpCode), 0, 1); 3902 InternalHiiAppendOpCodes (OpCodeHandle, DefaultsOpCodeHandle); 3903 HiiCreateEndOpCode (OpCodeHandle); 3904 return InternalHiiOpCodeHandleBuffer (OpCodeHandle) + Position; 3905 } 3906 3907 /** 3908 Create EFI_IFR_TIME_OP opcode. 3909 3910 If OpCodeHandle is NULL, then ASSERT(). 3911 If any reserved bits are set in QuestionFlags, then ASSERT(). 3912 If any reserved bits are set in TimeFlags, then ASSERT(). 3913 3914 @param[in] OpCodeHandle Handle to the buffer of opcodes. 3915 @param[in] QuestionId Question ID 3916 @param[in] VarStoreId Storage ID, optional. If TimeFlags is not 3917 QF_TIME_STORAGE_NORMAL, this parameter is ignored. 3918 @param[in] VarOffset Offset in Storage or String ID of the name (VarName) 3919 for this name/value pair, optional. If TimeFlags is not 3920 QF_TIME_STORAGE_NORMAL, this parameter is ignored. 3921 @param[in] Prompt String ID for Prompt 3922 @param[in] Help String ID for Help 3923 @param[in] QuestionFlags Flags in Question Header 3924 @param[in] TimeFlags Flags for time opcode 3925 @param[in] DefaultsOpCodeHandle Handle for a buffer of DEFAULT opcodes. This 3926 is an optional parameter that may be NULL. 3927 3928 @retval NULL There is not enough space left in Buffer to add the opcode. 3929 @retval Other A pointer to the created opcode. 3930 3931 **/ 3932 UINT8 * 3933 EFIAPI 3934 HiiCreateTimeOpCode ( 3935 IN VOID *OpCodeHandle, 3936 IN EFI_QUESTION_ID QuestionId, 3937 IN EFI_VARSTORE_ID VarStoreId, OPTIONAL 3938 IN UINT16 VarOffset, OPTIONAL 3939 IN EFI_STRING_ID Prompt, 3940 IN EFI_STRING_ID Help, 3941 IN UINT8 QuestionFlags, 3942 IN UINT8 TimeFlags, 3943 IN VOID *DefaultsOpCodeHandle OPTIONAL 3944 ) 3945 { 3946 EFI_IFR_TIME OpCode; 3947 UINTN Position; 3948 3949 ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED))) == 0); 3950 ASSERT ((TimeFlags & (~(QF_TIME_HOUR_SUPPRESS | QF_TIME_MINUTE_SUPPRESS | QF_TIME_SECOND_SUPPRESS | QF_TIME_STORAGE))) == 0); 3951 3952 ZeroMem (&OpCode, sizeof (OpCode)); 3953 OpCode.Question.Header.Prompt = Prompt; 3954 OpCode.Question.Header.Help = Help; 3955 OpCode.Question.QuestionId = QuestionId; 3956 OpCode.Question.VarStoreId = VarStoreId; 3957 OpCode.Question.VarStoreInfo.VarOffset = VarOffset; 3958 OpCode.Question.Flags = QuestionFlags; 3959 OpCode.Flags = TimeFlags; 3960 3961 if (DefaultsOpCodeHandle == NULL) { 3962 return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_TIME_OP, sizeof (OpCode)); 3963 } 3964 3965 Position = InternalHiiOpCodeHandlePosition (OpCodeHandle); 3966 InternalHiiCreateOpCodeExtended (OpCodeHandle, &OpCode, EFI_IFR_TIME_OP, sizeof (OpCode), 0, 1); 3967 InternalHiiAppendOpCodes (OpCodeHandle, DefaultsOpCodeHandle); 3968 HiiCreateEndOpCode (OpCodeHandle); 3969 return InternalHiiOpCodeHandleBuffer (OpCodeHandle) + Position; 3970 } 3971 3972 /** 3973 This is the internal worker function to update the data in 3974 a form specified by FormSetGuid, FormId and Label. 3975 3976 @param[in] FormSetGuid The optional Formset GUID. 3977 @param[in] FormId The Form ID. 3978 @param[in] Package The package header. 3979 @param[in] OpCodeBufferStart An OpCode buffer that contains the set of IFR 3980 opcodes to be inserted or replaced in the form. 3981 @param[in] OpCodeBufferEnd An OpCcode buffer that contains the IFR opcode 3982 that marks the end of a replace operation in the form. 3983 @param[out] TempPackage The resultant package. 3984 3985 @retval EFI_SUCCESS The function completes successfully. 3986 @retval EFI_NOT_FOUND The updated opcode or endopcode is not found. 3987 3988 **/ 3989 EFI_STATUS 3990 EFIAPI 3991 InternalHiiUpdateFormPackageData ( 3992 IN EFI_GUID *FormSetGuid, OPTIONAL 3993 IN EFI_FORM_ID FormId, 3994 IN EFI_HII_PACKAGE_HEADER *Package, 3995 IN HII_LIB_OPCODE_BUFFER *OpCodeBufferStart, 3996 IN HII_LIB_OPCODE_BUFFER *OpCodeBufferEnd, OPTIONAL 3997 OUT EFI_HII_PACKAGE_HEADER *TempPackage 3998 ) 3999 { 4000 UINTN AddSize; 4001 UINT8 *BufferPos; 4002 EFI_HII_PACKAGE_HEADER PackageHeader; 4003 UINTN Offset; 4004 EFI_IFR_OP_HEADER *IfrOpHdr; 4005 EFI_IFR_OP_HEADER *UpdateIfrOpHdr; 4006 BOOLEAN GetFormSet; 4007 BOOLEAN GetForm; 4008 BOOLEAN Updated; 4009 UINTN UpdatePackageLength; 4010 4011 CopyMem (TempPackage, Package, sizeof (EFI_HII_PACKAGE_HEADER)); 4012 UpdatePackageLength = sizeof (EFI_HII_PACKAGE_HEADER); 4013 BufferPos = (UINT8 *) (TempPackage + 1); 4014 4015 CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER)); 4016 IfrOpHdr = (EFI_IFR_OP_HEADER *)((UINT8 *) Package + sizeof (EFI_HII_PACKAGE_HEADER)); 4017 Offset = sizeof (EFI_HII_PACKAGE_HEADER); 4018 GetFormSet = (BOOLEAN) ((FormSetGuid == NULL) ? TRUE : FALSE); 4019 GetForm = FALSE; 4020 Updated = FALSE; 4021 4022 while (Offset < PackageHeader.Length) { 4023 CopyMem (BufferPos, IfrOpHdr, IfrOpHdr->Length); 4024 BufferPos += IfrOpHdr->Length; 4025 UpdatePackageLength += IfrOpHdr->Length; 4026 4027 // 4028 // Find the matched FormSet and Form 4029 // 4030 if ((IfrOpHdr->OpCode == EFI_IFR_FORM_SET_OP) && (FormSetGuid != NULL)) { 4031 if (CompareGuid((GUID *)(VOID *)&((EFI_IFR_FORM_SET *) IfrOpHdr)->Guid, FormSetGuid)) { 4032 GetFormSet = TRUE; 4033 } else { 4034 GetFormSet = FALSE; 4035 } 4036 } else if (IfrOpHdr->OpCode == EFI_IFR_FORM_OP || IfrOpHdr->OpCode == EFI_IFR_FORM_MAP_OP) { 4037 if (CompareMem (&((EFI_IFR_FORM *) IfrOpHdr)->FormId, &FormId, sizeof (EFI_FORM_ID)) == 0) { 4038 GetForm = TRUE; 4039 } else { 4040 GetForm = FALSE; 4041 } 4042 } 4043 4044 // 4045 // The matched Form is found, and Update data in this form 4046 // 4047 if (GetFormSet && GetForm) { 4048 UpdateIfrOpHdr = (EFI_IFR_OP_HEADER *) OpCodeBufferStart->Buffer; 4049 if ((UpdateIfrOpHdr->Length == IfrOpHdr->Length) && \ 4050 (CompareMem (IfrOpHdr, UpdateIfrOpHdr, UpdateIfrOpHdr->Length) == 0)) { 4051 // 4052 // Remove the original data when End OpCode buffer exist. 4053 // 4054 if (OpCodeBufferEnd != NULL) { 4055 Offset += IfrOpHdr->Length; 4056 IfrOpHdr = (EFI_IFR_OP_HEADER *) ((UINT8 *) (IfrOpHdr) + IfrOpHdr->Length); 4057 UpdateIfrOpHdr = (EFI_IFR_OP_HEADER *) OpCodeBufferEnd->Buffer; 4058 while (Offset < PackageHeader.Length) { 4059 // 4060 // Search the matched end opcode 4061 // 4062 if ((UpdateIfrOpHdr->Length == IfrOpHdr->Length) && \ 4063 (CompareMem (IfrOpHdr, UpdateIfrOpHdr, UpdateIfrOpHdr->Length) == 0)) { 4064 break; 4065 } 4066 // 4067 // Go to the next Op-Code 4068 // 4069 Offset += IfrOpHdr->Length; 4070 IfrOpHdr = (EFI_IFR_OP_HEADER *) ((UINT8 *) (IfrOpHdr) + IfrOpHdr->Length); 4071 } 4072 4073 if (Offset >= PackageHeader.Length) { 4074 // 4075 // The end opcode is not found. 4076 // 4077 return EFI_NOT_FOUND; 4078 } 4079 } 4080 4081 // 4082 // Insert the updated data 4083 // 4084 AddSize = ((EFI_IFR_OP_HEADER *) OpCodeBufferStart->Buffer)->Length; 4085 CopyMem (BufferPos, OpCodeBufferStart->Buffer + AddSize, OpCodeBufferStart->Position - AddSize); 4086 BufferPos += OpCodeBufferStart->Position - AddSize; 4087 UpdatePackageLength += OpCodeBufferStart->Position - AddSize; 4088 4089 if (OpCodeBufferEnd != NULL) { 4090 // 4091 // Add the end opcode 4092 // 4093 CopyMem (BufferPos, IfrOpHdr, IfrOpHdr->Length); 4094 BufferPos += IfrOpHdr->Length; 4095 UpdatePackageLength += IfrOpHdr->Length; 4096 } 4097 4098 // 4099 // Copy the left package data. 4100 // 4101 Offset += IfrOpHdr->Length; 4102 CopyMem (BufferPos, (UINT8 *) Package + Offset, PackageHeader.Length - Offset); 4103 UpdatePackageLength += PackageHeader.Length - Offset; 4104 4105 // 4106 // Set update flag 4107 // 4108 Updated = TRUE; 4109 break; 4110 } 4111 } 4112 4113 // 4114 // Go to the next Op-Code 4115 // 4116 Offset += IfrOpHdr->Length; 4117 IfrOpHdr = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (IfrOpHdr) + IfrOpHdr->Length); 4118 } 4119 4120 if (!Updated) { 4121 // 4122 // The updated opcode buffer is not found. 4123 // 4124 return EFI_NOT_FOUND; 4125 } 4126 // 4127 // Update the package length. 4128 // 4129 PackageHeader.Length = (UINT32) UpdatePackageLength; 4130 CopyMem (TempPackage, &PackageHeader, sizeof (EFI_HII_PACKAGE_HEADER)); 4131 4132 return EFI_SUCCESS; 4133 } 4134 4135 /** 4136 This function updates a form that has previously been registered with the HII 4137 Database. This function will perform at most one update operation. 4138 4139 The form to update is specified by Handle, FormSetGuid, and FormId. Binary 4140 comparisons of IFR opcodes are performed from the beginning of the form being 4141 updated until an IFR opcode is found that exactly matches the first IFR opcode 4142 specified by StartOpCodeHandle. The following rules are used to determine if 4143 an insert, replace, or delete operation is performed. 4144 4145 1) If no matches are found, then NULL is returned. 4146 2) If a match is found, and EndOpCodeHandle is NULL, then all of the IFR opcodes 4147 from StartOpCodeHandle except the first opcode are inserted immediately after 4148 the matching IFR opcode in the form to be updated. 4149 3) If a match is found, and EndOpCodeHandle is not NULL, then a search is made 4150 from the matching IFR opcode until an IFR opcode exactly matches the first 4151 IFR opcode specified by EndOpCodeHandle. If no match is found for the first 4152 IFR opcode specified by EndOpCodeHandle, then NULL is returned. If a match 4153 is found, then all of the IFR opcodes between the start match and the end 4154 match are deleted from the form being updated and all of the IFR opcodes 4155 from StartOpCodeHandle except the first opcode are inserted immediately after 4156 the matching start IFR opcode. If StartOpCcodeHandle only contains one 4157 IFR instruction, then the result of this operation will delete all of the IFR 4158 opcodes between the start end matches. 4159 4160 If HiiHandle is NULL, then ASSERT(). 4161 If StartOpCodeHandle is NULL, then ASSERT(). 4162 4163 @param[in] HiiHandle The HII Handle of the form to update. 4164 @param[in] FormSetGuid The Formset GUID of the form to update. This 4165 is an optional parameter that may be NULL. 4166 If it is NULL, all FormSet will be updated. 4167 @param[in] FormId The ID of the form to update. 4168 @param[in] StartOpCodeHandle An OpCode Handle that contains the set of IFR 4169 opcodes to be inserted or replaced in the form. 4170 The first IFR instruction in StartOpCodeHandle 4171 is used to find matching IFR opcode in the 4172 form. 4173 @param[in] EndOpCodeHandle An OpCcode Handle that contains the IFR opcode 4174 that marks the end of a replace operation in 4175 the form. This is an optional parameter that 4176 may be NULL. If it is NULL, then an the IFR 4177 opcodes specified by StartOpCodeHandle are 4178 inserted into the form. 4179 4180 @retval EFI_OUT_OF_RESOURCES No enough memory resource is allocated. 4181 @retval EFI_NOT_FOUND The following cases will return EFI_NOT_FOUND. 4182 1) The form specified by HiiHandle, FormSetGuid, 4183 and FormId could not be found in the HII Database. 4184 2) No IFR opcodes in the target form match the first 4185 IFR opcode in StartOpCodeHandle. 4186 3) EndOpCOde is not NULL, and no IFR opcodes in the 4187 target form following a matching start opcode match 4188 the first IFR opcode in EndOpCodeHandle. 4189 @retval EFI_SUCCESS The matched form is updated by StartOpcode. 4190 4191 **/ 4192 EFI_STATUS 4193 EFIAPI 4194 HiiUpdateForm ( 4195 IN EFI_HII_HANDLE HiiHandle, 4196 IN EFI_GUID *FormSetGuid, OPTIONAL 4197 IN EFI_FORM_ID FormId, 4198 IN VOID *StartOpCodeHandle, 4199 IN VOID *EndOpCodeHandle OPTIONAL 4200 ) 4201 { 4202 EFI_STATUS Status; 4203 EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList; 4204 UINT32 PackageListLength; 4205 UINT32 Offset; 4206 EFI_HII_PACKAGE_LIST_HEADER *UpdatePackageList; 4207 UINTN BufferSize; 4208 UINT8 *UpdateBufferPos; 4209 EFI_HII_PACKAGE_HEADER *Package; 4210 EFI_HII_PACKAGE_HEADER *TempPackage; 4211 EFI_HII_PACKAGE_HEADER PackageHeader; 4212 BOOLEAN Updated; 4213 HII_LIB_OPCODE_BUFFER *OpCodeBufferStart; 4214 HII_LIB_OPCODE_BUFFER *OpCodeBufferEnd; 4215 4216 // 4217 // Input update data can't be NULL. 4218 // 4219 ASSERT (HiiHandle != NULL); 4220 ASSERT (StartOpCodeHandle != NULL); 4221 UpdatePackageList = NULL; 4222 TempPackage = NULL; 4223 HiiPackageList = NULL; 4224 4225 // 4226 // Retrieve buffer data from Opcode Handle 4227 // 4228 OpCodeBufferStart = (HII_LIB_OPCODE_BUFFER *) StartOpCodeHandle; 4229 OpCodeBufferEnd = (HII_LIB_OPCODE_BUFFER *) EndOpCodeHandle; 4230 4231 // 4232 // Get the original package list 4233 // 4234 BufferSize = 0; 4235 HiiPackageList = NULL; 4236 Status = gHiiDatabase->ExportPackageLists (gHiiDatabase, HiiHandle, &BufferSize, HiiPackageList); 4237 // 4238 // The return status should always be EFI_BUFFER_TOO_SMALL as input buffer's size is 0. 4239 // 4240 if (Status != EFI_BUFFER_TOO_SMALL) { 4241 return Status; 4242 } 4243 4244 HiiPackageList = AllocatePool (BufferSize); 4245 if (HiiPackageList == NULL) { 4246 Status = EFI_OUT_OF_RESOURCES; 4247 goto Finish; 4248 } 4249 4250 Status = gHiiDatabase->ExportPackageLists (gHiiDatabase, HiiHandle, &BufferSize, HiiPackageList); 4251 if (EFI_ERROR (Status)) { 4252 goto Finish; 4253 } 4254 4255 // 4256 // Calculate and allocate space for retrieval of IFR data 4257 // 4258 BufferSize += OpCodeBufferStart->Position; 4259 UpdatePackageList = AllocateZeroPool (BufferSize); 4260 if (UpdatePackageList == NULL) { 4261 Status = EFI_OUT_OF_RESOURCES; 4262 goto Finish; 4263 } 4264 4265 // 4266 // Allocate temp buffer to store the temp updated package buffer 4267 // 4268 TempPackage = AllocateZeroPool (BufferSize); 4269 if (TempPackage == NULL) { 4270 Status = EFI_OUT_OF_RESOURCES; 4271 goto Finish; 4272 } 4273 4274 UpdateBufferPos = (UINT8 *) UpdatePackageList; 4275 4276 // 4277 // Copy the package list header 4278 // 4279 CopyMem (UpdateBufferPos, HiiPackageList, sizeof (EFI_HII_PACKAGE_LIST_HEADER)); 4280 UpdateBufferPos += sizeof (EFI_HII_PACKAGE_LIST_HEADER); 4281 4282 // 4283 // Go through each package to find the matched package and update one by one 4284 // 4285 Updated = FALSE; 4286 Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER); 4287 PackageListLength = ReadUnaligned32 (&HiiPackageList->PackageLength); 4288 while (Offset < PackageListLength) { 4289 Package = (EFI_HII_PACKAGE_HEADER *) (((UINT8 *) HiiPackageList) + Offset); 4290 CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER)); 4291 Offset += Package->Length; 4292 4293 if (Package->Type == EFI_HII_PACKAGE_FORMS) { 4294 // 4295 // Check this package is the matched package. 4296 // 4297 Status = InternalHiiUpdateFormPackageData (FormSetGuid, FormId, Package, OpCodeBufferStart, OpCodeBufferEnd, TempPackage); 4298 // 4299 // The matched package is found. Its package buffer will be updated by the input new data. 4300 // 4301 if (!EFI_ERROR(Status)) { 4302 // 4303 // Set Update Flag 4304 // 4305 Updated = TRUE; 4306 // 4307 // Add updated package buffer 4308 // 4309 Package = TempPackage; 4310 } 4311 } 4312 4313 // 4314 // Add pacakge buffer 4315 // 4316 CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER)); 4317 CopyMem (UpdateBufferPos, Package, PackageHeader.Length); 4318 UpdateBufferPos += PackageHeader.Length; 4319 } 4320 4321 if (Updated) { 4322 // 4323 // Update package list length 4324 // 4325 BufferSize = UpdateBufferPos - (UINT8 *) UpdatePackageList; 4326 WriteUnaligned32 (&UpdatePackageList->PackageLength, (UINT32) BufferSize); 4327 4328 // 4329 // Update Package to show form 4330 // 4331 Status = gHiiDatabase->UpdatePackageList (gHiiDatabase, HiiHandle, UpdatePackageList); 4332 } else { 4333 // 4334 // Not matched form is found and updated. 4335 // 4336 Status = EFI_NOT_FOUND; 4337 } 4338 4339 Finish: 4340 if (HiiPackageList != NULL) { 4341 FreePool (HiiPackageList); 4342 } 4343 4344 if (UpdatePackageList != NULL) { 4345 FreePool (UpdatePackageList); 4346 } 4347 4348 if (TempPackage != NULL) { 4349 FreePool (TempPackage); 4350 } 4351 4352 return Status; 4353 } 4354