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