]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Library/UefiHiiLib/HiiLib.c
c6e1fe12ad2be6a96201be8ea15e37eecd9865f8
[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 - 2010, 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.
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 break;
798 }
799
800 return EFI_SUCCESS;
801 }
802
803 /**
804 This function checks VarOffset and VarWidth is in the block range.
805
806 @param BlockArray The block array is to be checked.
807 @param VarOffset Offset of var to the structure
808 @param VarWidth Width of var.
809
810 @retval TRUE This Var is in the block range.
811 @retval FALSE This Var is not in the block range.
812 **/
813 BOOLEAN
814 BlockArrayCheck (
815 IN IFR_BLOCK_DATA *BlockArray,
816 IN UINT16 VarOffset,
817 IN UINT16 VarWidth
818 )
819 {
820 LIST_ENTRY *Link;
821 IFR_BLOCK_DATA *BlockData;
822
823 //
824 // No Request Block array, all vars are got.
825 //
826 if (BlockArray == NULL) {
827 return TRUE;
828 }
829
830 //
831 // Check the input var is in the request block range.
832 //
833 for (Link = BlockArray->Entry.ForwardLink; Link != &BlockArray->Entry; Link = Link->ForwardLink) {
834 BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);
835 if ((VarOffset >= BlockData->Offset) && ((VarOffset + VarWidth) <= (BlockData->Offset + BlockData->Width))) {
836 return TRUE;
837 }
838 }
839
840 return FALSE;
841 }
842
843 /**
844 Get the value of <Number> in <BlockConfig> format, i.e. the value of OFFSET
845 or WIDTH or VALUE.
846 <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>
847
848 @param ValueString String in <BlockConfig> format and points to the
849 first character of <Number>.
850 @param ValueData The output value. Caller takes the responsibility
851 to free memory.
852 @param ValueLength Length of the <Number>, in characters.
853
854 @retval EFI_OUT_OF_RESOURCES Insufficient resources to store neccessary
855 structures.
856 @retval EFI_SUCCESS Value of <Number> is outputted in Number
857 successfully.
858
859 **/
860 EFI_STATUS
861 EFIAPI
862 InternalHiiGetValueOfNumber (
863 IN EFI_STRING ValueString,
864 OUT UINT8 **ValueData,
865 OUT UINTN *ValueLength
866 )
867 {
868 EFI_STRING StringPtr;
869 UINTN Length;
870 UINT8 *Buf;
871 UINT8 DigitUint8;
872 UINTN Index;
873 CHAR16 TemStr[2];
874
875 ASSERT (ValueString != NULL && ValueData != NULL && ValueLength != NULL);
876 ASSERT (*ValueString != L'\0');
877
878 //
879 // Get the length of value string
880 //
881 StringPtr = ValueString;
882 while (*StringPtr != L'\0' && *StringPtr != L'&') {
883 StringPtr++;
884 }
885 Length = StringPtr - ValueString;
886
887 //
888 // Allocate buffer to store the value
889 //
890 Buf = (UINT8 *) AllocateZeroPool ((Length + 1) / 2);
891 if (Buf == NULL) {
892 return EFI_OUT_OF_RESOURCES;
893 }
894
895 //
896 // Convert character one by one to the value buffer
897 //
898 ZeroMem (TemStr, sizeof (TemStr));
899 for (Index = 0; Index < Length; Index ++) {
900 TemStr[0] = ValueString[Length - Index - 1];
901 DigitUint8 = (UINT8) StrHexToUint64 (TemStr);
902 if ((Index & 1) == 0) {
903 Buf [Index/2] = DigitUint8;
904 } else {
905 Buf [Index/2] = (UINT8) ((DigitUint8 << 4) + Buf [Index/2]);
906 }
907 }
908
909 //
910 // Set the converted value and string length.
911 //
912 *ValueData = Buf;
913 *ValueLength = Length;
914 return EFI_SUCCESS;
915 }
916
917 /**
918 This internal function parses IFR data to validate current setting.
919
920 @param ConfigResp ConfigResp string contains the current setting.
921 @param HiiPackageList Point to Hii package list.
922 @param PackageListLength The length of the pacakge.
923 @param VarGuid Guid of the buffer storage.
924 @param VarName Name of the buffer storage.
925
926 @retval EFI_SUCCESS The current setting is valid.
927 @retval EFI_OUT_OF_RESOURCES The memory is not enough.
928 @retval EFI_INVALID_PARAMETER The config string or the Hii package is invalid.
929 **/
930 EFI_STATUS
931 EFIAPI
932 InternalHiiValidateCurrentSetting (
933 IN EFI_STRING ConfigResp,
934 IN EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList,
935 IN UINTN PackageListLength,
936 IN EFI_GUID *VarGuid,
937 IN CHAR16 *VarName
938 )
939 {
940 IFR_BLOCK_DATA *CurrentBlockArray;
941 IFR_BLOCK_DATA *BlockData;
942 IFR_BLOCK_DATA *NewBlockData;
943 IFR_BLOCK_DATA VarBlockData;
944 EFI_STRING StringPtr;
945 UINTN Length;
946 UINT8 *TmpBuffer;
947 UINT16 Offset;
948 UINT16 Width;
949 UINT64 VarValue;
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 if (VarValue == IfrOneOfOption->Value.u64) {
1515 //
1516 // The value is one of option value.
1517 // Set OpCode to Zero, don't need check again.
1518 //
1519 VarBlockData.OpCode = 0;
1520 }
1521 }
1522
1523 break;
1524 case EFI_IFR_END_OP:
1525 //
1526 // Decrease opcode scope for the validated opcode
1527 //
1528 if (VarBlockData.Scope > 0) {
1529 VarBlockData.Scope --;
1530 }
1531
1532 //
1533 // OneOf value doesn't belong to one of option value.
1534 //
1535 if ((VarBlockData.Scope == 0) && (VarBlockData.OpCode == EFI_IFR_ONE_OF_OP)) {
1536 Status = EFI_INVALID_PARAMETER;
1537 goto Done;
1538 }
1539 break;
1540 default:
1541 //
1542 // Increase Scope for the validated opcode
1543 //
1544 if (VarBlockData.Scope > 0) {
1545 VarBlockData.Scope = (UINT8) (VarBlockData.Scope + IfrOpHdr->Scope);
1546 }
1547 break;
1548 }
1549 //
1550 // Go to the next opcode
1551 //
1552 IfrOffset += IfrOpHdr->Length;
1553 }
1554 //
1555 // Only one form is in a package list.
1556 //
1557 break;
1558 }
1559
1560 //
1561 // Go to next package.
1562 //
1563 PackageOffset += PacakgeHeader.Length;
1564 }
1565
1566 Done:
1567 if (VarBuffer != NULL) {
1568 FreePool (VarBuffer);
1569 }
1570
1571 if (CurrentBlockArray != NULL) {
1572 //
1573 // Free Link Array CurrentBlockArray
1574 //
1575 while (!IsListEmpty (&CurrentBlockArray->Entry)) {
1576 BlockData = BASE_CR (CurrentBlockArray->Entry.ForwardLink, IFR_BLOCK_DATA, Entry);
1577 RemoveEntryList (&BlockData->Entry);
1578 FreePool (BlockData);
1579 }
1580 FreePool (CurrentBlockArray);
1581 }
1582
1583 return Status;
1584 }
1585
1586 /**
1587 This function parses the input ConfigRequest string and its matched IFR code
1588 string for setting default value and validating current setting.
1589
1590 1. For setting default action, Reset the default value specified by DefaultId
1591 to the driver configuration got by Request string.
1592 2. For validating current setting, Validate the current configuration
1593 by parsing HII form IFR opcode.
1594
1595 NULL request string support depends on the ExportConfig interface of
1596 HiiConfigRouting protocol in UEFI specification.
1597
1598 @param Request A null-terminated Unicode string in
1599 <MultiConfigRequest> format. It can be NULL.
1600 If it is NULL, all current configuration for the
1601 entirety of the current HII database will be validated.
1602 If it is NULL, all configuration for the
1603 entirety of the current HII database will be reset.
1604 @param DefaultId Specifies the type of defaults to retrieve only for setting default action.
1605 @param ActionType Action supports setting defaults and validate current setting.
1606
1607 @retval TURE Action runs successfully.
1608 @retval FALSE Action is not valid or Action can't be executed successfully..
1609 **/
1610 BOOLEAN
1611 EFIAPI
1612 InternalHiiIfrValueAction (
1613 IN CONST EFI_STRING Request, OPTIONAL
1614 IN UINT16 DefaultId,
1615 IN UINT8 ActionType
1616 )
1617 {
1618 EFI_STRING ConfigAltResp;
1619 EFI_STRING ConfigAltHdr;
1620 EFI_STRING ConfigResp;
1621 EFI_STRING Progress;
1622 EFI_STRING StringPtr;
1623 EFI_STRING StringHdr;
1624 EFI_STATUS Status;
1625 EFI_HANDLE DriverHandle;
1626 EFI_HANDLE TempDriverHandle;
1627 EFI_HII_HANDLE *HiiHandleBuffer;
1628 EFI_HII_HANDLE HiiHandle;
1629 UINT32 Index;
1630 EFI_GUID *VarGuid;
1631 EFI_STRING VarName;
1632 EFI_STRING_ID DefaultName;
1633
1634 UINT8 *PackageData;
1635 UINTN IfrOffset;
1636 EFI_IFR_OP_HEADER *IfrOpHdr;
1637 EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;
1638 UINT32 PackageOffset;
1639 UINTN PackageListLength;
1640 EFI_HII_PACKAGE_HEADER PacakgeHeader;
1641 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
1642 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
1643
1644 ConfigAltResp = NULL;
1645 ConfigResp = NULL;
1646 VarGuid = NULL;
1647 VarName = NULL;
1648 DevicePath = NULL;
1649 ConfigAltHdr = NULL;
1650 HiiHandleBuffer = NULL;
1651 Index = 0;
1652 TempDriverHandle = NULL;
1653 HiiHandle = NULL;
1654 PackageData = NULL;
1655 HiiPackageList = NULL;
1656
1657 //
1658 // Only support set default and validate setting action.
1659 //
1660 if ((ActionType != ACTION_SET_DEFAUTL_VALUE) && (ActionType != ACTION_VALIDATE_SETTING)) {
1661 return FALSE;
1662 }
1663
1664 //
1665 // Get the full requested value and deault value string.
1666 //
1667 if (Request != NULL) {
1668 Status = gHiiConfigRouting->ExtractConfig (
1669 gHiiConfigRouting,
1670 Request,
1671 &Progress,
1672 &ConfigAltResp
1673 );
1674 } else {
1675 Status = gHiiConfigRouting->ExportConfig (
1676 gHiiConfigRouting,
1677 &ConfigAltResp
1678 );
1679 }
1680
1681 if (EFI_ERROR (Status)) {
1682 return FALSE;
1683 }
1684
1685 StringPtr = ConfigAltResp;
1686
1687 while (StringPtr != L'\0') {
1688 //
1689 // 1. Find <ConfigHdr> GUID=...&NAME=...&PATH=...
1690 //
1691 StringHdr = StringPtr;
1692
1693 //
1694 // Get Guid value
1695 //
1696 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {
1697 Status = EFI_INVALID_PARAMETER;
1698 goto Done;
1699 }
1700 StringPtr += StrLen (L"GUID=");
1701 Status = InternalHiiGetBufferFromString (StringPtr, GUID_CONFIG_STRING_TYPE, (UINT8 **) &VarGuid);
1702 if (EFI_ERROR (Status)) {
1703 goto Done;
1704 }
1705
1706 //
1707 // Get Name value VarName
1708 //
1709 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&NAME=", StrLen (L"&NAME=")) != 0) {
1710 StringPtr++;
1711 }
1712 if (*StringPtr == L'\0') {
1713 Status = EFI_INVALID_PARAMETER;
1714 goto Done;
1715 }
1716 StringPtr += StrLen (L"&NAME=");
1717 Status = InternalHiiGetBufferFromString (StringPtr, NAME_CONFIG_STRING_TYPE, (UINT8 **) &VarName);
1718 if (EFI_ERROR (Status)) {
1719 goto Done;
1720 }
1721
1722 //
1723 // Get Path value DevicePath
1724 //
1725 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&PATH=", StrLen (L"&PATH=")) != 0) {
1726 StringPtr++;
1727 }
1728 if (*StringPtr == L'\0') {
1729 Status = EFI_INVALID_PARAMETER;
1730 goto Done;
1731 }
1732 StringPtr += StrLen (L"&PATH=");
1733 Status = InternalHiiGetBufferFromString (StringPtr, PATH_CONFIG_STRING_TYPE, (UINT8 **) &DevicePath);
1734 if (EFI_ERROR (Status)) {
1735 goto Done;
1736 }
1737
1738 //
1739 // Get the Driver handle by the got device path.
1740 //
1741 TempDevicePath = DevicePath;
1742 Status = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &TempDevicePath, &DriverHandle);
1743 if (EFI_ERROR (Status)) {
1744 goto Done;
1745 }
1746
1747 //
1748 // Find the matched Hii Handle for the found Driver handle
1749 //
1750 HiiHandleBuffer = HiiGetHiiHandles (NULL);
1751 if (HiiHandleBuffer == NULL) {
1752 Status = EFI_NOT_FOUND;
1753 goto Done;
1754 }
1755
1756 for (Index = 0; HiiHandleBuffer[Index] != NULL; Index ++) {
1757 gHiiDatabase->GetPackageListHandle (gHiiDatabase, HiiHandleBuffer[Index], &TempDriverHandle);
1758 if (TempDriverHandle == DriverHandle) {
1759 break;
1760 }
1761 }
1762
1763 HiiHandle = HiiHandleBuffer[Index];
1764 FreePool (HiiHandleBuffer);
1765
1766 if (HiiHandle == NULL) {
1767 //
1768 // This request string has no its Hii package.
1769 // Its default value and validating can't execute by parsing IFR data.
1770 // Directly jump into the next ConfigAltResp string for another pair Guid, Name, and Path.
1771 //
1772 Status = EFI_SUCCESS;
1773 goto NextConfigAltResp;
1774 }
1775
1776 //
1777 // 2. Get DefaultName string ID by parsing the PacakgeList
1778 //
1779
1780 //
1781 // Get HiiPackage by HiiHandle
1782 //
1783 PackageListLength = 0;
1784 HiiPackageList = NULL;
1785 Status = gHiiDatabase->ExportPackageLists (gHiiDatabase, HiiHandle, &PackageListLength, HiiPackageList);
1786
1787 //
1788 // The return status should always be EFI_BUFFER_TOO_SMALL as input buffer's size is 0.
1789 //
1790 if (Status != EFI_BUFFER_TOO_SMALL) {
1791 Status = EFI_INVALID_PARAMETER;
1792 goto Done;
1793 }
1794
1795 HiiPackageList = AllocatePool (PackageListLength);
1796 if (HiiPackageList == NULL) {
1797 Status = EFI_OUT_OF_RESOURCES;
1798 goto Done;
1799 }
1800
1801 //
1802 // Get PackageList on HiiHandle
1803 //
1804 Status = gHiiDatabase->ExportPackageLists (gHiiDatabase, HiiHandle, &PackageListLength, HiiPackageList);
1805 if (EFI_ERROR (Status)) {
1806 goto Done;
1807 }
1808
1809 //
1810 // Parse the form package and get the default name string ID.
1811 //
1812 if (ActionType == ACTION_SET_DEFAUTL_VALUE) {
1813 PackageOffset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);
1814 Status = EFI_NOT_FOUND;
1815 while (PackageOffset < PackageListLength) {
1816 CopyMem (&PacakgeHeader, (UINT8 *) HiiPackageList + PackageOffset, sizeof (PacakgeHeader));
1817
1818 //
1819 // Parse IFR opcode to get default store opcode
1820 //
1821 if (PacakgeHeader.Type == EFI_HII_PACKAGE_FORMS) {
1822 IfrOffset = sizeof (PacakgeHeader);
1823 PackageData = (UINT8 *) HiiPackageList + PackageOffset;
1824 while (IfrOffset < PacakgeHeader.Length) {
1825 IfrOpHdr = (EFI_IFR_OP_HEADER *) (PackageData + IfrOffset);
1826 //
1827 // Match DefaultId to find its DefaultName
1828 //
1829 if (IfrOpHdr->OpCode == EFI_IFR_DEFAULTSTORE_OP) {
1830 if (((EFI_IFR_DEFAULTSTORE *) IfrOpHdr)->DefaultId == DefaultId) {
1831 DefaultName = ((EFI_IFR_DEFAULTSTORE *) IfrOpHdr)->DefaultName;
1832 Status = EFI_SUCCESS;
1833 break;
1834 }
1835 }
1836 IfrOffset += IfrOpHdr->Length;
1837 }
1838 //
1839 // Only one form is in a package list.
1840 //
1841 break;
1842 }
1843
1844 //
1845 // Go to next package.
1846 //
1847 PackageOffset += PacakgeHeader.Length;
1848 }
1849
1850 //
1851 // Not found the matched default string ID
1852 //
1853 if (EFI_ERROR (Status)) {
1854 Status = EFI_SUCCESS;
1855 goto NextConfigAltResp;
1856 }
1857 }
1858
1859 //
1860 // 3. Call ConfigRouting GetAltCfg(ConfigRoute, <ConfigResponse>, Guid, Name, DevicePath, AltCfgId, AltCfgResp)
1861 // Get the default configuration string according to the found default name string ID.
1862 //
1863 Status = gHiiConfigRouting->GetAltConfig (
1864 gHiiConfigRouting,
1865 ConfigAltResp,
1866 VarGuid,
1867 VarName,
1868 DevicePath,
1869 (ActionType == ACTION_SET_DEFAUTL_VALUE) ? &DefaultName:NULL, // it can be NULL to get the current setting.
1870 &ConfigResp
1871 );
1872
1873 //
1874 // The required setting can't be found. So, it is not required to be validated and set.
1875 //
1876 if (EFI_ERROR (Status)) {
1877 Status = EFI_SUCCESS;
1878 goto NextConfigAltResp;
1879 }
1880 //
1881 // Only the ConfigHdr is found. Not any block data is found. No data is required to be validated and set.
1882 //
1883 if (StrStr (ConfigResp, L"&OFFSET=") == NULL) {
1884 goto NextConfigAltResp;
1885 }
1886
1887 //
1888 // 4. Set the default configuration information or Validate current setting by parse IFR code.
1889 // Current Setting is in ConfigResp, will be set into buffer, then check it again.
1890 //
1891 if (ActionType == ACTION_SET_DEFAUTL_VALUE) {
1892 //
1893 // Set the default configuration information.
1894 //
1895 Status = gHiiConfigRouting->RouteConfig (gHiiConfigRouting, ConfigResp, &Progress);
1896 } else {
1897 //
1898 // Current Setting is in ConfigResp, will be set into buffer, then check it again.
1899 //
1900 Status = InternalHiiValidateCurrentSetting (ConfigResp, HiiPackageList, PackageListLength, VarGuid, VarName);
1901 }
1902
1903 if (EFI_ERROR (Status)) {
1904 goto Done;
1905 }
1906
1907 NextConfigAltResp:
1908 //
1909 // Free the allocated pacakge buffer and the got ConfigResp string.
1910 //
1911 if (HiiPackageList != NULL) {
1912 FreePool (HiiPackageList);
1913 HiiPackageList = NULL;
1914 }
1915
1916 if (ConfigResp != NULL) {
1917 FreePool (ConfigResp);
1918 ConfigResp = NULL;
1919 }
1920
1921 //
1922 // Free the allocated buffer.
1923 //
1924 FreePool (VarGuid);
1925 VarGuid = NULL;
1926
1927 FreePool (VarName);
1928 VarName = NULL;
1929
1930 FreePool (DevicePath);
1931 DevicePath = NULL;
1932
1933 //
1934 // 5. Jump to next ConfigAltResp for another Guid, Name, Path.
1935 //
1936
1937 //
1938 // Get and Skip ConfigHdr
1939 //
1940 while (*StringPtr != L'\0' && *StringPtr != L'&') {
1941 StringPtr++;
1942 }
1943 if (*StringPtr == L'\0') {
1944 break;
1945 }
1946
1947 //
1948 // Construct ConfigAltHdr string "&<ConfigHdr>&ALTCFG=\0"
1949 // | 1 | StrLen (ConfigHdr) | 8 | 1 |
1950 //
1951 ConfigAltHdr = AllocateZeroPool ((1 + StringPtr - StringHdr + 8 + 1) * sizeof (CHAR16));
1952 if (ConfigAltHdr == NULL) {
1953 Status = EFI_OUT_OF_RESOURCES;
1954 goto Done;
1955 }
1956 StrCpy (ConfigAltHdr, L"&");
1957 StrnCat (ConfigAltHdr, StringHdr, StringPtr - StringHdr);
1958 StrCat (ConfigAltHdr, L"&ALTCFG=");
1959
1960 //
1961 // Skip all AltResp (AltConfigHdr ConfigBody) for the same ConfigHdr
1962 //
1963 while ((StringHdr = StrStr (StringPtr, ConfigAltHdr)) != NULL) {
1964 StringPtr = StringHdr + StrLen (ConfigAltHdr);
1965 if (*StringPtr == L'\0') {
1966 break;
1967 }
1968 }
1969
1970 //
1971 // Free the allocated ConfigAltHdr string
1972 //
1973 FreePool (ConfigAltHdr);
1974 if (*StringPtr == L'\0') {
1975 break;
1976 }
1977
1978 //
1979 // Find &GUID as the next ConfigHdr
1980 //
1981 StringPtr = StrStr (StringPtr, L"&GUID");
1982 if (StringPtr == NULL) {
1983 break;
1984 }
1985
1986 //
1987 // Skip char '&'
1988 //
1989 StringPtr ++;
1990 }
1991
1992 Done:
1993 if (VarGuid != NULL) {
1994 FreePool (VarGuid);
1995 }
1996
1997 if (VarName != NULL) {
1998 FreePool (VarName);
1999 }
2000
2001 if (DevicePath != NULL) {
2002 FreePool (DevicePath);
2003 }
2004
2005 if (ConfigResp != NULL) {
2006 FreePool (ConfigResp);
2007 }
2008
2009 if (ConfigAltResp != NULL) {
2010 FreePool (ConfigAltResp);
2011 }
2012
2013 if (HiiPackageList != NULL) {
2014 FreePool (HiiPackageList);
2015 }
2016
2017 if (EFI_ERROR (Status)) {
2018 return FALSE;
2019 }
2020
2021 return TRUE;
2022 }
2023
2024 /**
2025 Validate the current configuration by parsing HII form IFR opcode.
2026
2027 NULL request string support depends on the ExportConfig interface of
2028 HiiConfigRouting protocol in UEFI specification.
2029
2030 @param Request A null-terminated Unicode string in
2031 <MultiConfigRequest> format. It can be NULL.
2032 If it is NULL, all current configuration for the
2033 entirety of the current HII database will be validated.
2034
2035 @retval TURE Current configuration is valid.
2036 @retval FALSE Current configuration is invalid.
2037 **/
2038 BOOLEAN
2039 EFIAPI
2040 HiiValidateSettings (
2041 IN CONST EFI_STRING Request OPTIONAL
2042 )
2043 {
2044 return InternalHiiIfrValueAction (Request, 0, ACTION_VALIDATE_SETTING);
2045 }
2046
2047 /**
2048 Reset the default value specified by DefaultId to the driver
2049 configuration got by Request string.
2050
2051 NULL request string support depends on the ExportConfig interface of
2052 HiiConfigRouting protocol in UEFI specification.
2053
2054 @param Request A null-terminated Unicode string in
2055 <MultiConfigRequest> format. It can be NULL.
2056 If it is NULL, all configuration for the
2057 entirety of the current HII database will be reset.
2058 @param DefaultId Specifies the type of defaults to retrieve.
2059
2060 @retval TURE The default value is set successfully.
2061 @retval FALSE The default value can't be found and set.
2062 **/
2063 BOOLEAN
2064 EFIAPI
2065 HiiSetToDefaults (
2066 IN CONST EFI_STRING Request, OPTIONAL
2067 IN UINT16 DefaultId
2068 )
2069 {
2070 return InternalHiiIfrValueAction (Request, DefaultId, ACTION_SET_DEFAUTL_VALUE);
2071 }
2072
2073 /**
2074 Determines if two values in config strings match.
2075
2076 Compares the substring between StartSearchString and StopSearchString in
2077 FirstString to the substring between StartSearchString and StopSearchString
2078 in SecondString. If the two substrings match, then TRUE is returned. If the
2079 two substrings do not match, then FALSE is returned.
2080
2081 If FirstString is NULL, then ASSERT().
2082 If SecondString is NULL, then ASSERT().
2083 If StartSearchString is NULL, then ASSERT().
2084 If StopSearchString is NULL, then ASSERT().
2085
2086 @param FirstString Pointer to the first Null-terminated Unicode string.
2087 @param SecondString Pointer to the second Null-terminated Unicode string.
2088 @param StartSearchString Pointer to the Null-terminated Unicode string that
2089 marks the start of the value string to compare.
2090 @param StopSearchString Pointer to the Null-terminated Unicode string that
2091 marks the end of the value string to compare.
2092
2093 @retval FALSE StartSearchString is not present in FirstString.
2094 @retval FALSE StartSearchString is not present in SecondString.
2095 @retval FALSE StopSearchString is not present in FirstString.
2096 @retval FALSE StopSearchString is not present in SecondString.
2097 @retval FALSE The length of the substring in FirstString is not the
2098 same length as the substring in SecondString.
2099 @retval FALSE The value string in FirstString does not matche the
2100 value string in SecondString.
2101 @retval TRUE The value string in FirstString matches the value
2102 string in SecondString.
2103
2104 **/
2105 BOOLEAN
2106 EFIAPI
2107 InternalHiiCompareSubString (
2108 IN CHAR16 *FirstString,
2109 IN CHAR16 *SecondString,
2110 IN CHAR16 *StartSearchString,
2111 IN CHAR16 *StopSearchString
2112 )
2113 {
2114 CHAR16 *EndFirstString;
2115 CHAR16 *EndSecondString;
2116
2117 ASSERT (FirstString != NULL);
2118 ASSERT (SecondString != NULL);
2119 ASSERT (StartSearchString != NULL);
2120 ASSERT (StopSearchString != NULL);
2121
2122 FirstString = StrStr (FirstString, StartSearchString);
2123 if (FirstString == NULL) {
2124 return FALSE;
2125 }
2126
2127 SecondString = StrStr (SecondString, StartSearchString);
2128 if (SecondString == NULL) {
2129 return FALSE;
2130 }
2131
2132 EndFirstString = StrStr (FirstString, StopSearchString);
2133 if (EndFirstString == NULL) {
2134 return FALSE;
2135 }
2136
2137 EndSecondString = StrStr (SecondString, StopSearchString);
2138 if (EndSecondString == NULL) {
2139 return FALSE;
2140 }
2141
2142 if ((EndFirstString - FirstString) != (EndSecondString - SecondString)) {
2143 return FALSE;
2144 }
2145
2146 return (BOOLEAN)(StrnCmp (FirstString, SecondString, EndFirstString - FirstString) == 0);
2147 }
2148
2149 /**
2150 Determines if the routing data specified by GUID and NAME match a <ConfigHdr>.
2151
2152 If ConfigHdr is NULL, then ASSERT().
2153
2154 @param[in] ConfigHdr Either <ConfigRequest> or <ConfigResp>.
2155 @param[in] Guid GUID of the storage.
2156 @param[in] Name NAME of the storage.
2157
2158 @retval TRUE Routing information matches <ConfigHdr>.
2159 @retval FALSE Routing information does not match <ConfigHdr>.
2160
2161 **/
2162 BOOLEAN
2163 EFIAPI
2164 HiiIsConfigHdrMatch (
2165 IN CONST EFI_STRING ConfigHdr,
2166 IN CONST EFI_GUID *Guid, OPTIONAL
2167 IN CONST CHAR16 *Name OPTIONAL
2168 )
2169 {
2170 EFI_STRING CompareConfigHdr;
2171 BOOLEAN Result;
2172
2173 ASSERT (ConfigHdr != NULL);
2174
2175 //
2176 // Use Guid and Name to generate a <ConfigHdr> string
2177 //
2178 CompareConfigHdr = HiiConstructConfigHdr (Guid, Name, NULL);
2179 if (CompareConfigHdr == NULL) {
2180 return FALSE;
2181 }
2182
2183 Result = TRUE;
2184 if (Guid != NULL) {
2185 //
2186 // Compare GUID value strings
2187 //
2188 Result = InternalHiiCompareSubString (ConfigHdr, CompareConfigHdr, L"GUID=", L"&NAME=");
2189 }
2190
2191 if (Result && Name != NULL) {
2192 //
2193 // Compare NAME value strings
2194 //
2195 Result = InternalHiiCompareSubString (ConfigHdr, CompareConfigHdr, L"&NAME=", L"&PATH=");
2196 }
2197
2198 //
2199 // Free the <ConfigHdr> string
2200 //
2201 FreePool (CompareConfigHdr);
2202
2203 return Result;
2204 }
2205
2206 /**
2207 Retrieves uncommitted data from the Form Browser and converts it to a binary
2208 buffer.
2209
2210 @param[in] VariableGuid Pointer to an EFI_GUID structure. This is an optional
2211 parameter that may be NULL.
2212 @param[in] VariableName Pointer to a Null-terminated Unicode string. This
2213 is an optional parameter that may be NULL.
2214 @param[in] BufferSize Length in bytes of buffer to hold retrieved data.
2215 @param[out] Buffer Buffer of data to be updated.
2216
2217 @retval FALSE The uncommitted data could not be retrieved.
2218 @retval TRUE The uncommitted data was retrieved.
2219
2220 **/
2221 BOOLEAN
2222 EFIAPI
2223 HiiGetBrowserData (
2224 IN CONST EFI_GUID *VariableGuid, OPTIONAL
2225 IN CONST CHAR16 *VariableName, OPTIONAL
2226 IN UINTN BufferSize,
2227 OUT UINT8 *Buffer
2228 )
2229 {
2230 EFI_STRING ResultsData;
2231 UINTN Size;
2232 EFI_STRING ConfigResp;
2233 EFI_STATUS Status;
2234 CHAR16 *Progress;
2235
2236 //
2237 // Retrieve the results data from the Browser Callback
2238 //
2239 ResultsData = InternalHiiBrowserCallback (VariableGuid, VariableName, NULL);
2240 if (ResultsData == NULL) {
2241 return FALSE;
2242 }
2243
2244 //
2245 // Construct <ConfigResp> mConfigHdrTemplate L'&' ResultsData L'\0'
2246 //
2247 Size = (StrLen (mConfigHdrTemplate) + 1) * sizeof (CHAR16);
2248 Size = Size + (StrLen (ResultsData) + 1) * sizeof (CHAR16);
2249 ConfigResp = AllocateZeroPool (Size);
2250 UnicodeSPrint (ConfigResp, Size, L"%s&%s", mConfigHdrTemplate, ResultsData);
2251
2252 //
2253 // Free the allocated buffer
2254 //
2255 FreePool (ResultsData);
2256 if (ConfigResp == NULL) {
2257 return FALSE;
2258 }
2259
2260 //
2261 // Convert <ConfigResp> to a buffer
2262 //
2263 Status = gHiiConfigRouting->ConfigToBlock (
2264 gHiiConfigRouting,
2265 ConfigResp,
2266 Buffer,
2267 &BufferSize,
2268 &Progress
2269 );
2270 //
2271 // Free the allocated buffer
2272 //
2273 FreePool (ConfigResp);
2274
2275 if (EFI_ERROR (Status)) {
2276 return FALSE;
2277 }
2278
2279 return TRUE;
2280 }
2281
2282 /**
2283 Updates uncommitted data in the Form Browser.
2284
2285 If Buffer is NULL, then ASSERT().
2286
2287 @param[in] VariableGuid Pointer to an EFI_GUID structure. This is an optional
2288 parameter that may be NULL.
2289 @param[in] VariableName Pointer to a Null-terminated Unicode string. This
2290 is an optional parameter that may be NULL.
2291 @param[in] BufferSize Length, in bytes, of Buffer.
2292 @param[in] Buffer Buffer of data to commit.
2293 @param[in] RequestElement An optional field to specify which part of the
2294 buffer data will be send back to Browser. If NULL,
2295 the whole buffer of data will be committed to
2296 Browser.
2297 <RequestElement> ::= &OFFSET=<Number>&WIDTH=<Number>*
2298
2299 @retval FALSE The uncommitted data could not be updated.
2300 @retval TRUE The uncommitted data was updated.
2301
2302 **/
2303 BOOLEAN
2304 EFIAPI
2305 HiiSetBrowserData (
2306 IN CONST EFI_GUID *VariableGuid, OPTIONAL
2307 IN CONST CHAR16 *VariableName, OPTIONAL
2308 IN UINTN BufferSize,
2309 IN CONST UINT8 *Buffer,
2310 IN CONST CHAR16 *RequestElement OPTIONAL
2311 )
2312 {
2313 UINTN Size;
2314 EFI_STRING ConfigRequest;
2315 EFI_STRING ConfigResp;
2316 EFI_STRING ResultsData;
2317
2318 ASSERT (Buffer != NULL);
2319
2320 //
2321 // Construct <ConfigRequest>
2322 //
2323 if (RequestElement == NULL) {
2324 //
2325 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
2326 // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
2327 //
2328 Size = (StrLen (mConfigHdrTemplate) + 32 + 1) * sizeof (CHAR16);
2329 ConfigRequest = AllocateZeroPool (Size);
2330 UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", mConfigHdrTemplate, (UINT64)BufferSize);
2331 } else {
2332 //
2333 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
2334 // followed by <RequestElement> followed by a Null-terminator
2335 //
2336 Size = StrLen (mConfigHdrTemplate) * sizeof (CHAR16);
2337 Size = Size + (StrLen (RequestElement) + 1) * sizeof (CHAR16);
2338 ConfigRequest = AllocateZeroPool (Size);
2339 UnicodeSPrint (ConfigRequest, Size, L"%s%s", mConfigHdrTemplate, RequestElement);
2340 }
2341 if (ConfigRequest == NULL) {
2342 return FALSE;
2343 }
2344
2345 //
2346 // Convert <ConfigRequest> to <ConfigResp>
2347 //
2348 ConfigResp = InternalHiiBlockToConfig (ConfigRequest, Buffer, BufferSize);
2349 FreePool (ConfigRequest);
2350 if (ConfigResp == NULL) {
2351 return FALSE;
2352 }
2353
2354 //
2355 // Set data in the uncommitted browser state information
2356 //
2357 ResultsData = InternalHiiBrowserCallback (VariableGuid, VariableName, ConfigResp + StrLen(mConfigHdrTemplate) + 1);
2358 FreePool (ConfigResp);
2359
2360 return (BOOLEAN)(ResultsData != NULL);
2361 }
2362
2363 /////////////////////////////////////////
2364 /////////////////////////////////////////
2365 /// IFR Functions
2366 /////////////////////////////////////////
2367 /////////////////////////////////////////
2368
2369 #define HII_LIB_OPCODE_ALLOCATION_SIZE 0x200
2370
2371 typedef struct {
2372 UINT8 *Buffer;
2373 UINTN BufferSize;
2374 UINTN Position;
2375 } HII_LIB_OPCODE_BUFFER;
2376
2377 ///
2378 /// Lookup table that converts EFI_IFR_TYPE_X enum values to a width in bytes
2379 ///
2380 GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 mHiiDefaultTypeToWidth[] = {
2381 1, // EFI_IFR_TYPE_NUM_SIZE_8
2382 2, // EFI_IFR_TYPE_NUM_SIZE_16
2383 4, // EFI_IFR_TYPE_NUM_SIZE_32
2384 8, // EFI_IFR_TYPE_NUM_SIZE_64
2385 1, // EFI_IFR_TYPE_BOOLEAN
2386 3, // EFI_IFR_TYPE_TIME
2387 4, // EFI_IFR_TYPE_DATE
2388 2 // EFI_IFR_TYPE_STRING
2389 };
2390
2391 /**
2392 Allocates and returns a new OpCode Handle. OpCode Handles must be freed with
2393 HiiFreeOpCodeHandle().
2394
2395 @retval NULL There are not enough resources to allocate a new OpCode Handle.
2396 @retval Other A new OpCode handle.
2397
2398 **/
2399 VOID *
2400 EFIAPI
2401 HiiAllocateOpCodeHandle (
2402 VOID
2403 )
2404 {
2405 HII_LIB_OPCODE_BUFFER *OpCodeBuffer;
2406
2407 OpCodeBuffer = (HII_LIB_OPCODE_BUFFER *)AllocatePool (sizeof (HII_LIB_OPCODE_BUFFER));
2408 if (OpCodeBuffer == NULL) {
2409 return NULL;
2410 }
2411 OpCodeBuffer->Buffer = (UINT8 *)AllocatePool (HII_LIB_OPCODE_ALLOCATION_SIZE);
2412 if (OpCodeBuffer->Buffer == NULL) {
2413 FreePool (OpCodeBuffer);
2414 return NULL;
2415 }
2416 OpCodeBuffer->BufferSize = HII_LIB_OPCODE_ALLOCATION_SIZE;
2417 OpCodeBuffer->Position = 0;
2418 return (VOID *)OpCodeBuffer;
2419 }
2420
2421 /**
2422 Frees an OpCode Handle that was previously allocated with HiiAllocateOpCodeHandle().
2423 When an OpCode Handle is freed, all of the opcodes associated with the OpCode
2424 Handle are also freed.
2425
2426 If OpCodeHandle is NULL, then ASSERT().
2427
2428 @param[in] OpCodeHandle Handle to the buffer of opcodes.
2429
2430 **/
2431 VOID
2432 EFIAPI
2433 HiiFreeOpCodeHandle (
2434 VOID *OpCodeHandle
2435 )
2436 {
2437 HII_LIB_OPCODE_BUFFER *OpCodeBuffer;
2438
2439 ASSERT (OpCodeHandle != NULL);
2440
2441 OpCodeBuffer = (HII_LIB_OPCODE_BUFFER *)OpCodeHandle;
2442 if (OpCodeBuffer->Buffer != NULL) {
2443 FreePool (OpCodeBuffer->Buffer);
2444 }
2445 FreePool (OpCodeBuffer);
2446 }
2447
2448 /**
2449 Internal function gets the current position of opcode buffer.
2450
2451 @param[in] OpCodeHandle Handle to the buffer of opcodes.
2452
2453 @return Current position of opcode buffer.
2454 **/
2455 UINTN
2456 EFIAPI
2457 InternalHiiOpCodeHandlePosition (
2458 IN VOID *OpCodeHandle
2459 )
2460 {
2461 return ((HII_LIB_OPCODE_BUFFER *)OpCodeHandle)->Position;
2462 }
2463
2464 /**
2465 Internal function gets the start pointer of opcode buffer.
2466
2467 @param[in] OpCodeHandle Handle to the buffer of opcodes.
2468
2469 @return Pointer to the opcode buffer base.
2470 **/
2471 UINT8 *
2472 EFIAPI
2473 InternalHiiOpCodeHandleBuffer (
2474 IN VOID *OpCodeHandle
2475 )
2476 {
2477 return ((HII_LIB_OPCODE_BUFFER *)OpCodeHandle)->Buffer;
2478 }
2479
2480 /**
2481 Internal function reserves the enough buffer for current opcode.
2482 When the buffer is not enough, Opcode buffer will be extended.
2483
2484 @param[in] OpCodeHandle Handle to the buffer of opcodes.
2485 @param[in] Size Size of current opcode.
2486
2487 @return Pointer to the current opcode.
2488 **/
2489 UINT8 *
2490 EFIAPI
2491 InternalHiiGrowOpCodeHandle (
2492 IN VOID *OpCodeHandle,
2493 IN UINTN Size
2494 )
2495 {
2496 HII_LIB_OPCODE_BUFFER *OpCodeBuffer;
2497 UINT8 *Buffer;
2498
2499 ASSERT (OpCodeHandle != NULL);
2500
2501 OpCodeBuffer = (HII_LIB_OPCODE_BUFFER *)OpCodeHandle;
2502 if (OpCodeBuffer->Position + Size > OpCodeBuffer->BufferSize) {
2503 Buffer = ReallocatePool (
2504 OpCodeBuffer->BufferSize,
2505 OpCodeBuffer->BufferSize + (Size + HII_LIB_OPCODE_ALLOCATION_SIZE),
2506 OpCodeBuffer->Buffer
2507 );
2508 if (Buffer == NULL) {
2509 return NULL;
2510 }
2511 OpCodeBuffer->Buffer = Buffer;
2512 OpCodeBuffer->BufferSize += (Size + HII_LIB_OPCODE_ALLOCATION_SIZE);
2513 }
2514 Buffer = OpCodeBuffer->Buffer + OpCodeBuffer->Position;
2515 OpCodeBuffer->Position += Size;
2516 return Buffer;
2517 }
2518
2519 /**
2520 Internal function creates opcode based on the template opcode.
2521
2522 @param[in] OpCodeHandle Handle to the buffer of opcodes.
2523 @param[in] OpCodeTemplate Pointer to the template buffer of opcode.
2524 @param[in] OpCode OpCode IFR value.
2525 @param[in] OpCodeSize Size of opcode.
2526 @param[in] ExtensionSize Size of extended opcode.
2527 @param[in] Scope Scope bit of opcode.
2528
2529 @return Pointer to the current opcode with opcode data.
2530 **/
2531 UINT8 *
2532 EFIAPI
2533 InternalHiiCreateOpCodeExtended (
2534 IN VOID *OpCodeHandle,
2535 IN VOID *OpCodeTemplate,
2536 IN UINT8 OpCode,
2537 IN UINTN OpCodeSize,
2538 IN UINTN ExtensionSize,
2539 IN UINT8 Scope
2540 )
2541 {
2542 EFI_IFR_OP_HEADER *Header;
2543 UINT8 *Buffer;
2544
2545 ASSERT (OpCodeTemplate != NULL);
2546 ASSERT ((OpCodeSize + ExtensionSize) <= 0x7F);
2547
2548 Header = (EFI_IFR_OP_HEADER *)OpCodeTemplate;
2549 Header->OpCode = OpCode;
2550 Header->Scope = Scope;
2551 Header->Length = (UINT8)(OpCodeSize + ExtensionSize);
2552 Buffer = InternalHiiGrowOpCodeHandle (OpCodeHandle, Header->Length);
2553 return (UINT8 *)CopyMem (Buffer, Header, OpCodeSize);
2554 }
2555
2556 /**
2557 Internal function creates opcode based on the template opcode for the normal opcode.
2558
2559 @param[in] OpCodeHandle Handle to the buffer of opcodes.
2560 @param[in] OpCodeTemplate Pointer to the template buffer of opcode.
2561 @param[in] OpCode OpCode IFR value.
2562 @param[in] OpCodeSize Size of opcode.
2563
2564 @return Pointer to the current opcode with opcode data.
2565 **/
2566 UINT8 *
2567 EFIAPI
2568 InternalHiiCreateOpCode (
2569 IN VOID *OpCodeHandle,
2570 IN VOID *OpCodeTemplate,
2571 IN UINT8 OpCode,
2572 IN UINTN OpCodeSize
2573 )
2574 {
2575 return InternalHiiCreateOpCodeExtended (OpCodeHandle, OpCodeTemplate, OpCode, OpCodeSize, 0, 0);
2576 }
2577
2578 /**
2579 Append raw opcodes to an OpCodeHandle.
2580
2581 If OpCodeHandle is NULL, then ASSERT().
2582 If RawBuffer is NULL, then ASSERT();
2583
2584 @param[in] OpCodeHandle Handle to the buffer of opcodes.
2585 @param[in] RawBuffer Buffer of opcodes to append.
2586 @param[in] RawBufferSize The size, in bytes, of Buffer.
2587
2588 @retval NULL There is not enough space left in Buffer to add the opcode.
2589 @retval Other A pointer to the appended opcodes.
2590
2591 **/
2592 UINT8 *
2593 EFIAPI
2594 HiiCreateRawOpCodes (
2595 IN VOID *OpCodeHandle,
2596 IN UINT8 *RawBuffer,
2597 IN UINTN RawBufferSize
2598 )
2599 {
2600 UINT8 *Buffer;
2601
2602 ASSERT (RawBuffer != NULL);
2603
2604 Buffer = InternalHiiGrowOpCodeHandle (OpCodeHandle, RawBufferSize);
2605 return (UINT8 *)CopyMem (Buffer, RawBuffer, RawBufferSize);
2606 }
2607
2608 /**
2609 Append opcodes from one OpCode Handle to another OpCode handle.
2610
2611 If OpCodeHandle is NULL, then ASSERT().
2612 If RawOpCodeHandle is NULL, then ASSERT();
2613
2614 @param[in] OpCodeHandle Handle to the buffer of opcodes.
2615 @param[in] RawOpCodeHandle Handle to the buffer of opcodes.
2616
2617 @retval NULL There is not enough space left in Buffer to add the opcode.
2618 @retval Other A pointer to the appended opcodes.
2619
2620 **/
2621 UINT8 *
2622 EFIAPI
2623 InternalHiiAppendOpCodes (
2624 IN VOID *OpCodeHandle,
2625 IN VOID *RawOpCodeHandle
2626 )
2627 {
2628 HII_LIB_OPCODE_BUFFER *RawOpCodeBuffer;
2629
2630 ASSERT (RawOpCodeHandle != NULL);
2631
2632 RawOpCodeBuffer = (HII_LIB_OPCODE_BUFFER *)RawOpCodeHandle;
2633 return HiiCreateRawOpCodes (OpCodeHandle, RawOpCodeBuffer->Buffer, RawOpCodeBuffer->Position);
2634 }
2635
2636 /**
2637 Create EFI_IFR_END_OP opcode.
2638
2639 If OpCodeHandle is NULL, then ASSERT().
2640
2641 @param[in] OpCodeHandle Handle to the buffer of opcodes.
2642
2643 @retval NULL There is not enough space left in Buffer to add the opcode.
2644 @retval Other A pointer to the created opcode.
2645
2646 **/
2647 UINT8 *
2648 EFIAPI
2649 HiiCreateEndOpCode (
2650 IN VOID *OpCodeHandle
2651 )
2652 {
2653 EFI_IFR_END OpCode;
2654
2655 return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_END_OP, sizeof (OpCode));
2656 }
2657
2658 /**
2659 Create EFI_IFR_ONE_OF_OPTION_OP opcode.
2660
2661 If OpCodeHandle is NULL, then ASSERT().
2662 If Type is invalid, then ASSERT().
2663 If Flags is invalid, then ASSERT().
2664
2665 @param[in] OpCodeHandle Handle to the buffer of opcodes.
2666 @param[in] StringId StringId for the option
2667 @param[in] Flags Flags for the option
2668 @param[in] Type Type for the option
2669 @param[in] Value Value for the option
2670
2671 @retval NULL There is not enough space left in Buffer to add the opcode.
2672 @retval Other A pointer to the created opcode.
2673
2674 **/
2675 UINT8 *
2676 EFIAPI
2677 HiiCreateOneOfOptionOpCode (
2678 IN VOID *OpCodeHandle,
2679 IN UINT16 StringId,
2680 IN UINT8 Flags,
2681 IN UINT8 Type,
2682 IN UINT64 Value
2683 )
2684 {
2685 EFI_IFR_ONE_OF_OPTION OpCode;
2686
2687 ASSERT (Type < EFI_IFR_TYPE_OTHER);
2688
2689 ZeroMem (&OpCode, sizeof (OpCode));
2690 OpCode.Option = StringId;
2691 OpCode.Flags = (UINT8) (Flags & (EFI_IFR_OPTION_DEFAULT | EFI_IFR_OPTION_DEFAULT_MFG));
2692 OpCode.Type = Type;
2693 CopyMem (&OpCode.Value, &Value, mHiiDefaultTypeToWidth[Type]);
2694
2695 return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_ONE_OF_OPTION_OP, sizeof (OpCode));
2696 }
2697
2698 /**
2699 Create EFI_IFR_DEFAULT_OP opcode.
2700
2701 If OpCodeHandle is NULL, then ASSERT().
2702 If Type is invalid, then ASSERT().
2703
2704 @param[in] OpCodeHandle Handle to the buffer of opcodes.
2705 @param[in] DefaultId DefaultId for the default
2706 @param[in] Type Type for the default
2707 @param[in] Value Value for the default
2708
2709 @retval NULL There is not enough space left in Buffer to add the opcode.
2710 @retval Other A pointer to the created opcode.
2711
2712 **/
2713 UINT8 *
2714 EFIAPI
2715 HiiCreateDefaultOpCode (
2716 IN VOID *OpCodeHandle,
2717 IN UINT16 DefaultId,
2718 IN UINT8 Type,
2719 IN UINT64 Value
2720 )
2721 {
2722 EFI_IFR_DEFAULT OpCode;
2723
2724 ASSERT (Type < EFI_IFR_TYPE_OTHER);
2725
2726 ZeroMem (&OpCode, sizeof (OpCode));
2727 OpCode.Type = Type;
2728 OpCode.DefaultId = DefaultId;
2729 CopyMem (&OpCode.Value, &Value, mHiiDefaultTypeToWidth[Type]);
2730
2731 return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_DEFAULT_OP, sizeof (OpCode));
2732 }
2733
2734 /**
2735 Create EFI_IFR_GUID opcode.
2736
2737 If OpCodeHandle is NULL, then ASSERT().
2738 If Guid is NULL, then ASSERT().
2739 If OpCodeSize < sizeof (EFI_IFR_GUID), then ASSERT().
2740
2741 @param[in] OpCodeHandle Handle to the buffer of opcodes.
2742 @param[in] Guid Pointer to EFI_GUID of this guided opcode.
2743 @param[in] GuidOpCode Pointer to an EFI_IFR_GUID opcode. This is an
2744 optional parameter that may be NULL. If this
2745 parameter is NULL, then the GUID extension
2746 region of the created opcode is filled with zeros.
2747 If this parameter is not NULL, then the GUID
2748 extension region of GuidData will be copied to
2749 the GUID extension region of the created opcode.
2750 @param[in] OpCodeSize The size, in bytes, of created opcode. This value
2751 must be >= sizeof(EFI_IFR_GUID).
2752
2753 @retval NULL There is not enough space left in Buffer to add the opcode.
2754 @retval Other A pointer to the created opcode.
2755
2756 **/
2757 UINT8 *
2758 EFIAPI
2759 HiiCreateGuidOpCode (
2760 IN VOID *OpCodeHandle,
2761 IN CONST EFI_GUID *Guid,
2762 IN CONST VOID *GuidOpCode, OPTIONAL
2763 IN UINTN OpCodeSize
2764 )
2765 {
2766 EFI_IFR_GUID OpCode;
2767 EFI_IFR_GUID *OpCodePointer;
2768
2769 ASSERT (Guid != NULL);
2770 ASSERT (OpCodeSize >= sizeof (OpCode));
2771
2772 ZeroMem (&OpCode, sizeof (OpCode));
2773 CopyGuid ((EFI_GUID *)(VOID *)&OpCode.Guid, Guid);
2774
2775 OpCodePointer = (EFI_IFR_GUID *)InternalHiiCreateOpCodeExtended (
2776 OpCodeHandle,
2777 &OpCode,
2778 EFI_IFR_GUID_OP,
2779 sizeof (OpCode),
2780 OpCodeSize - sizeof (OpCode),
2781 0
2782 );
2783 if (OpCodePointer != NULL && GuidOpCode != NULL) {
2784 CopyMem (OpCodePointer + 1, (EFI_IFR_GUID *)GuidOpCode + 1, OpCodeSize - sizeof (OpCode));
2785 }
2786 return (UINT8 *)OpCodePointer;
2787 }
2788
2789 /**
2790 Create EFI_IFR_ACTION_OP opcode.
2791
2792 If OpCodeHandle is NULL, then ASSERT().
2793 If any reserved bits are set in QuestionFlags, then ASSERT().
2794
2795 @param[in] OpCodeHandle Handle to the buffer of opcodes.
2796 @param[in] QuestionId Question ID
2797 @param[in] Prompt String ID for Prompt
2798 @param[in] Help String ID for Help
2799 @param[in] QuestionFlags Flags in Question Header
2800 @param[in] QuestionConfig String ID for configuration
2801
2802 @retval NULL There is not enough space left in Buffer to add the opcode.
2803 @retval Other A pointer to the created opcode.
2804
2805 **/
2806 UINT8 *
2807 EFIAPI
2808 HiiCreateActionOpCode (
2809 IN VOID *OpCodeHandle,
2810 IN EFI_QUESTION_ID QuestionId,
2811 IN EFI_STRING_ID Prompt,
2812 IN EFI_STRING_ID Help,
2813 IN UINT8 QuestionFlags,
2814 IN EFI_STRING_ID QuestionConfig
2815 )
2816 {
2817 EFI_IFR_ACTION OpCode;
2818
2819 ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED))) == 0);
2820
2821 ZeroMem (&OpCode, sizeof (OpCode));
2822 OpCode.Question.QuestionId = QuestionId;
2823 OpCode.Question.Header.Prompt = Prompt;
2824 OpCode.Question.Header.Help = Help;
2825 OpCode.Question.Flags = QuestionFlags;
2826 OpCode.QuestionConfig = QuestionConfig;
2827
2828 return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_ACTION_OP, sizeof (OpCode));
2829 }
2830
2831 /**
2832 Create EFI_IFR_SUBTITLE_OP opcode.
2833
2834 If OpCodeHandle is NULL, then ASSERT().
2835 If any reserved bits are set in Flags, then ASSERT().
2836 If Scope > 1, then ASSERT().
2837
2838 @param[in] OpCodeHandle Handle to the buffer of opcodes.
2839 @param[in] Prompt String ID for Prompt
2840 @param[in] Help String ID for Help
2841 @param[in] Flags Subtitle opcode flags
2842 @param[in] Scope 1 if this opcpde is the beginning of a new scope.
2843 0 if this opcode is within the current scope.
2844
2845 @retval NULL There is not enough space left in Buffer to add the opcode.
2846 @retval Other A pointer to the created opcode.
2847
2848 **/
2849 UINT8 *
2850 EFIAPI
2851 HiiCreateSubTitleOpCode (
2852 IN VOID *OpCodeHandle,
2853 IN EFI_STRING_ID Prompt,
2854 IN EFI_STRING_ID Help,
2855 IN UINT8 Flags,
2856 IN UINT8 Scope
2857 )
2858 {
2859 EFI_IFR_SUBTITLE OpCode;
2860
2861 ASSERT (Scope <= 1);
2862 ASSERT ((Flags & (~(EFI_IFR_FLAGS_HORIZONTAL))) == 0);
2863
2864 ZeroMem (&OpCode, sizeof (OpCode));
2865 OpCode.Statement.Prompt = Prompt;
2866 OpCode.Statement.Help = Help;
2867 OpCode.Flags = Flags;
2868
2869 return InternalHiiCreateOpCodeExtended (
2870 OpCodeHandle,
2871 &OpCode,
2872 EFI_IFR_SUBTITLE_OP,
2873 sizeof (OpCode),
2874 0,
2875 Scope
2876 );
2877 }
2878
2879 /**
2880 Create EFI_IFR_REF_OP opcode.
2881
2882 If OpCodeHandle is NULL, then ASSERT().
2883 If any reserved bits are set in QuestionFlags, then ASSERT().
2884
2885 @param[in] OpCodeHandle Handle to the buffer of opcodes.
2886 @param[in] FormId Destination Form ID
2887 @param[in] Prompt String ID for Prompt
2888 @param[in] Help String ID for Help
2889 @param[in] QuestionFlags Flags in Question Header
2890 @param[in] QuestionId Question ID
2891
2892 @retval NULL There is not enough space left in Buffer to add the opcode.
2893 @retval Other A pointer to the created opcode.
2894
2895 **/
2896 UINT8 *
2897 EFIAPI
2898 HiiCreateGotoOpCode (
2899 IN VOID *OpCodeHandle,
2900 IN EFI_FORM_ID FormId,
2901 IN EFI_STRING_ID Prompt,
2902 IN EFI_STRING_ID Help,
2903 IN UINT8 QuestionFlags,
2904 IN EFI_QUESTION_ID QuestionId
2905 )
2906 {
2907 EFI_IFR_REF OpCode;
2908
2909 ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED))) == 0);
2910
2911 ZeroMem (&OpCode, sizeof (OpCode));
2912 OpCode.Question.Header.Prompt = Prompt;
2913 OpCode.Question.Header.Help = Help;
2914 OpCode.Question.QuestionId = QuestionId;
2915 OpCode.Question.Flags = QuestionFlags;
2916 OpCode.FormId = FormId;
2917
2918 return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_REF_OP, sizeof (OpCode));
2919 }
2920
2921 /**
2922 Create EFI_IFR_CHECKBOX_OP opcode.
2923
2924 If OpCodeHandle is NULL, then ASSERT().
2925 If any reserved bits are set in QuestionFlags, then ASSERT().
2926 If any reserved bits are set in CheckBoxFlags, then ASSERT().
2927
2928 @param[in] OpCodeHandle Handle to the buffer of opcodes.
2929 @param[in] QuestionId Question ID
2930 @param[in] VarStoreId Storage ID
2931 @param[in] VarOffset Offset in Storage
2932 @param[in] Prompt String ID for Prompt
2933 @param[in] Help String ID for Help
2934 @param[in] QuestionFlags Flags in Question Header
2935 @param[in] CheckBoxFlags Flags for checkbox opcode
2936 @param[in] DefaultsOpCodeHandle Handle for a buffer of DEFAULT opcodes. This
2937 is an optional parameter that may be NULL.
2938
2939 @retval NULL There is not enough space left in Buffer to add the opcode.
2940 @retval Other A pointer to the created opcode.
2941
2942 **/
2943 UINT8 *
2944 EFIAPI
2945 HiiCreateCheckBoxOpCode (
2946 IN VOID *OpCodeHandle,
2947 IN EFI_QUESTION_ID QuestionId,
2948 IN EFI_VARSTORE_ID VarStoreId,
2949 IN UINT16 VarOffset,
2950 IN EFI_STRING_ID Prompt,
2951 IN EFI_STRING_ID Help,
2952 IN UINT8 QuestionFlags,
2953 IN UINT8 CheckBoxFlags,
2954 IN VOID *DefaultsOpCodeHandle OPTIONAL
2955 )
2956 {
2957 EFI_IFR_CHECKBOX OpCode;
2958 UINTN Position;
2959
2960 ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED))) == 0);
2961
2962 ZeroMem (&OpCode, sizeof (OpCode));
2963 OpCode.Question.QuestionId = QuestionId;
2964 OpCode.Question.VarStoreId = VarStoreId;
2965 OpCode.Question.VarStoreInfo.VarOffset = VarOffset;
2966 OpCode.Question.Header.Prompt = Prompt;
2967 OpCode.Question.Header.Help = Help;
2968 OpCode.Question.Flags = QuestionFlags;
2969 OpCode.Flags = CheckBoxFlags;
2970
2971 if (DefaultsOpCodeHandle == NULL) {
2972 return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_CHECKBOX_OP, sizeof (OpCode));
2973 }
2974
2975 Position = InternalHiiOpCodeHandlePosition (OpCodeHandle);
2976 InternalHiiCreateOpCodeExtended (OpCodeHandle, &OpCode, EFI_IFR_CHECKBOX_OP, sizeof (OpCode), 0, 1);
2977 InternalHiiAppendOpCodes (OpCodeHandle, DefaultsOpCodeHandle);
2978 HiiCreateEndOpCode (OpCodeHandle);
2979 return InternalHiiOpCodeHandleBuffer (OpCodeHandle) + Position;
2980 }
2981
2982 /**
2983 Create EFI_IFR_NUMERIC_OP opcode.
2984
2985 If OpCodeHandle is NULL, then ASSERT().
2986 If any reserved bits are set in QuestionFlags, then ASSERT().
2987 If any reserved bits are set in NumericFlags, then ASSERT().
2988
2989 @param[in] OpCodeHandle Handle to the buffer of opcodes.
2990 @param[in] QuestionId Question ID
2991 @param[in] VarStoreId Storage ID
2992 @param[in] VarOffset Offset in Storage
2993 @param[in] Prompt String ID for Prompt
2994 @param[in] Help String ID for Help
2995 @param[in] QuestionFlags Flags in Question Header
2996 @param[in] NumericFlags Flags for numeric opcode
2997 @param[in] Minimum Numeric minimum value
2998 @param[in] Maximum Numeric maximum value
2999 @param[in] Step Numeric step for edit
3000 @param[in] DefaultsOpCodeHandle Handle for a buffer of DEFAULT opcodes. This
3001 is an optional parameter that may be NULL.
3002
3003 @retval NULL There is not enough space left in Buffer to add the opcode.
3004 @retval Other A pointer to the created opcode.
3005
3006 **/
3007 UINT8 *
3008 EFIAPI
3009 HiiCreateNumericOpCode (
3010 IN VOID *OpCodeHandle,
3011 IN EFI_QUESTION_ID QuestionId,
3012 IN EFI_VARSTORE_ID VarStoreId,
3013 IN UINT16 VarOffset,
3014 IN EFI_STRING_ID Prompt,
3015 IN EFI_STRING_ID Help,
3016 IN UINT8 QuestionFlags,
3017 IN UINT8 NumericFlags,
3018 IN UINT64 Minimum,
3019 IN UINT64 Maximum,
3020 IN UINT64 Step,
3021 IN VOID *DefaultsOpCodeHandle OPTIONAL
3022 )
3023 {
3024 EFI_IFR_NUMERIC OpCode;
3025 UINTN Position;
3026
3027 ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED))) == 0);
3028
3029 ZeroMem (&OpCode, sizeof (OpCode));
3030 OpCode.Question.QuestionId = QuestionId;
3031 OpCode.Question.VarStoreId = VarStoreId;
3032 OpCode.Question.VarStoreInfo.VarOffset = VarOffset;
3033 OpCode.Question.Header.Prompt = Prompt;
3034 OpCode.Question.Header.Help = Help;
3035 OpCode.Question.Flags = QuestionFlags;
3036 OpCode.Flags = NumericFlags;
3037
3038 switch (NumericFlags & EFI_IFR_NUMERIC_SIZE) {
3039 case EFI_IFR_NUMERIC_SIZE_1:
3040 OpCode.data.u8.MinValue = (UINT8)Minimum;
3041 OpCode.data.u8.MaxValue = (UINT8)Maximum;
3042 OpCode.data.u8.Step = (UINT8)Step;
3043 break;
3044
3045 case EFI_IFR_NUMERIC_SIZE_2:
3046 OpCode.data.u16.MinValue = (UINT16)Minimum;
3047 OpCode.data.u16.MaxValue = (UINT16)Maximum;
3048 OpCode.data.u16.Step = (UINT16)Step;
3049 break;
3050
3051 case EFI_IFR_NUMERIC_SIZE_4:
3052 OpCode.data.u32.MinValue = (UINT32)Minimum;
3053 OpCode.data.u32.MaxValue = (UINT32)Maximum;
3054 OpCode.data.u32.Step = (UINT32)Step;
3055 break;
3056
3057 case EFI_IFR_NUMERIC_SIZE_8:
3058 OpCode.data.u64.MinValue = Minimum;
3059 OpCode.data.u64.MaxValue = Maximum;
3060 OpCode.data.u64.Step = Step;
3061 break;
3062 }
3063
3064 if (DefaultsOpCodeHandle == NULL) {
3065 return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_NUMERIC_OP, sizeof (OpCode));
3066 }
3067
3068 Position = InternalHiiOpCodeHandlePosition (OpCodeHandle);
3069 InternalHiiCreateOpCodeExtended (OpCodeHandle, &OpCode, EFI_IFR_NUMERIC_OP, sizeof (OpCode), 0, 1);
3070 InternalHiiAppendOpCodes (OpCodeHandle, DefaultsOpCodeHandle);
3071 HiiCreateEndOpCode (OpCodeHandle);
3072 return InternalHiiOpCodeHandleBuffer (OpCodeHandle) + Position;
3073 }
3074
3075 /**
3076 Create EFI_IFR_STRING_OP opcode.
3077
3078 If OpCodeHandle is NULL, then ASSERT().
3079 If any reserved bits are set in QuestionFlags, then ASSERT().
3080 If any reserved bits are set in StringFlags, then ASSERT().
3081
3082 @param[in] OpCodeHandle Handle to the buffer of opcodes.
3083 @param[in] QuestionId Question ID
3084 @param[in] VarStoreId Storage ID
3085 @param[in] VarOffset Offset in Storage
3086 @param[in] Prompt String ID for Prompt
3087 @param[in] Help String ID for Help
3088 @param[in] QuestionFlags Flags in Question Header
3089 @param[in] StringFlags Flags for string opcode
3090 @param[in] MinSize String minimum length
3091 @param[in] MaxSize String maximum length
3092 @param[in] DefaultsOpCodeHandle Handle for a buffer of DEFAULT opcodes. This
3093 is an optional parameter that may be NULL.
3094
3095 @retval NULL There is not enough space left in Buffer to add the opcode.
3096 @retval Other A pointer to the created opcode.
3097
3098 **/
3099 UINT8 *
3100 EFIAPI
3101 HiiCreateStringOpCode (
3102 IN VOID *OpCodeHandle,
3103 IN EFI_QUESTION_ID QuestionId,
3104 IN EFI_VARSTORE_ID VarStoreId,
3105 IN UINT16 VarOffset,
3106 IN EFI_STRING_ID Prompt,
3107 IN EFI_STRING_ID Help,
3108 IN UINT8 QuestionFlags,
3109 IN UINT8 StringFlags,
3110 IN UINT8 MinSize,
3111 IN UINT8 MaxSize,
3112 IN VOID *DefaultsOpCodeHandle OPTIONAL
3113 )
3114 {
3115 EFI_IFR_STRING OpCode;
3116 UINTN Position;
3117
3118 ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED))) == 0);
3119
3120 ZeroMem (&OpCode, sizeof (OpCode));
3121 OpCode.Question.Header.Prompt = Prompt;
3122 OpCode.Question.Header.Help = Help;
3123 OpCode.Question.QuestionId = QuestionId;
3124 OpCode.Question.VarStoreId = VarStoreId;
3125 OpCode.Question.VarStoreInfo.VarOffset = VarOffset;
3126 OpCode.Question.Flags = QuestionFlags;
3127 OpCode.MinSize = MinSize;
3128 OpCode.MaxSize = MaxSize;
3129 OpCode.Flags = (UINT8) (StringFlags & EFI_IFR_STRING_MULTI_LINE);
3130
3131 if (DefaultsOpCodeHandle == NULL) {
3132 return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_STRING_OP, sizeof (OpCode));
3133 }
3134
3135 Position = InternalHiiOpCodeHandlePosition (OpCodeHandle);
3136 InternalHiiCreateOpCodeExtended (OpCodeHandle, &OpCode, EFI_IFR_STRING_OP, sizeof (OpCode), 0, 1);
3137 InternalHiiAppendOpCodes (OpCodeHandle, DefaultsOpCodeHandle);
3138 HiiCreateEndOpCode (OpCodeHandle);
3139 return InternalHiiOpCodeHandleBuffer (OpCodeHandle) + Position;
3140 }
3141
3142 /**
3143 Create EFI_IFR_ONE_OF_OP opcode.
3144
3145 If OpCodeHandle is NULL, then ASSERT().
3146 If any reserved bits are set in QuestionFlags, then ASSERT().
3147 If any reserved bits are set in OneOfFlags, then ASSERT().
3148
3149 @param[in] OpCodeHandle Handle to the buffer of opcodes.
3150 @param[in] QuestionId Question ID
3151 @param[in] VarStoreId Storage ID
3152 @param[in] VarOffset Offset in Storage
3153 @param[in] Prompt String ID for Prompt
3154 @param[in] Help String ID for Help
3155 @param[in] QuestionFlags Flags in Question Header
3156 @param[in] OneOfFlags Flags for oneof opcode
3157 @param[in] OptionsOpCodeHandle Handle for a buffer of ONE_OF_OPTION opcodes.
3158 @param[in] DefaultsOpCodeHandle Handle for a buffer of DEFAULT opcodes. This
3159 is an optional parameter that may be NULL.
3160
3161 @retval NULL There is not enough space left in Buffer to add the opcode.
3162 @retval Other A pointer to the created opcode.
3163
3164 **/
3165 UINT8 *
3166 EFIAPI
3167 HiiCreateOneOfOpCode (
3168 IN VOID *OpCodeHandle,
3169 IN EFI_QUESTION_ID QuestionId,
3170 IN EFI_VARSTORE_ID VarStoreId,
3171 IN UINT16 VarOffset,
3172 IN EFI_STRING_ID Prompt,
3173 IN EFI_STRING_ID Help,
3174 IN UINT8 QuestionFlags,
3175 IN UINT8 OneOfFlags,
3176 IN VOID *OptionsOpCodeHandle,
3177 IN VOID *DefaultsOpCodeHandle OPTIONAL
3178 )
3179 {
3180 EFI_IFR_ONE_OF OpCode;
3181 UINTN Position;
3182
3183 ASSERT (OptionsOpCodeHandle != NULL);
3184 ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED | EFI_IFR_FLAG_OPTIONS_ONLY))) == 0);
3185
3186 ZeroMem (&OpCode, sizeof (OpCode));
3187 OpCode.Question.Header.Prompt = Prompt;
3188 OpCode.Question.Header.Help = Help;
3189 OpCode.Question.QuestionId = QuestionId;
3190 OpCode.Question.VarStoreId = VarStoreId;
3191 OpCode.Question.VarStoreInfo.VarOffset = VarOffset;
3192 OpCode.Question.Flags = QuestionFlags;
3193 OpCode.Flags = OneOfFlags;
3194
3195 Position = InternalHiiOpCodeHandlePosition (OpCodeHandle);
3196 InternalHiiCreateOpCodeExtended (OpCodeHandle, &OpCode, EFI_IFR_ONE_OF_OP, sizeof (OpCode), 0, 1);
3197 InternalHiiAppendOpCodes (OpCodeHandle, OptionsOpCodeHandle);
3198 if (DefaultsOpCodeHandle != NULL) {
3199 InternalHiiAppendOpCodes (OpCodeHandle, DefaultsOpCodeHandle);
3200 }
3201 HiiCreateEndOpCode (OpCodeHandle);
3202 return InternalHiiOpCodeHandleBuffer (OpCodeHandle) + Position;
3203 }
3204
3205 /**
3206 Create EFI_IFR_ORDERED_LIST_OP opcode.
3207
3208 If OpCodeHandle is NULL, then ASSERT().
3209 If any reserved bits are set in QuestionFlags, then ASSERT().
3210 If any reserved bits are set in OrderedListFlags, then ASSERT().
3211
3212 @param[in] OpCodeHandle Handle to the buffer of opcodes.
3213 @param[in] QuestionId Question ID
3214 @param[in] VarStoreId Storage ID
3215 @param[in] VarOffset Offset in Storage
3216 @param[in] Prompt String ID for Prompt
3217 @param[in] Help String ID for Help
3218 @param[in] QuestionFlags Flags in Question Header
3219 @param[in] OrderedListFlags Flags for ordered list opcode
3220 @param[in] DataType Type for option value
3221 @param[in] MaxContainers Maximum count for options in this ordered list
3222 @param[in] OptionsOpCodeHandle Handle for a buffer of ONE_OF_OPTION opcodes.
3223 @param[in] DefaultsOpCodeHandle Handle for a buffer of DEFAULT opcodes. This
3224 is an optional parameter that may be NULL.
3225
3226 @retval NULL There is not enough space left in Buffer to add the opcode.
3227 @retval Other A pointer to the created opcode.
3228
3229 **/
3230 UINT8 *
3231 EFIAPI
3232 HiiCreateOrderedListOpCode (
3233 IN VOID *OpCodeHandle,
3234 IN EFI_QUESTION_ID QuestionId,
3235 IN EFI_VARSTORE_ID VarStoreId,
3236 IN UINT16 VarOffset,
3237 IN EFI_STRING_ID Prompt,
3238 IN EFI_STRING_ID Help,
3239 IN UINT8 QuestionFlags,
3240 IN UINT8 OrderedListFlags,
3241 IN UINT8 DataType,
3242 IN UINT8 MaxContainers,
3243 IN VOID *OptionsOpCodeHandle,
3244 IN VOID *DefaultsOpCodeHandle OPTIONAL
3245 )
3246 {
3247 EFI_IFR_ORDERED_LIST OpCode;
3248 UINTN Position;
3249
3250 ASSERT (OptionsOpCodeHandle != NULL);
3251 ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED | EFI_IFR_FLAG_OPTIONS_ONLY))) == 0);
3252
3253 ZeroMem (&OpCode, sizeof (OpCode));
3254 OpCode.Question.Header.Prompt = Prompt;
3255 OpCode.Question.Header.Help = Help;
3256 OpCode.Question.QuestionId = QuestionId;
3257 OpCode.Question.VarStoreId = VarStoreId;
3258 OpCode.Question.VarStoreInfo.VarOffset = VarOffset;
3259 OpCode.Question.Flags = QuestionFlags;
3260 OpCode.MaxContainers = MaxContainers;
3261 OpCode.Flags = OrderedListFlags;
3262
3263 Position = InternalHiiOpCodeHandlePosition (OpCodeHandle);
3264 InternalHiiCreateOpCodeExtended (OpCodeHandle, &OpCode, EFI_IFR_ORDERED_LIST_OP, sizeof (OpCode), 0, 1);
3265 InternalHiiAppendOpCodes (OpCodeHandle, OptionsOpCodeHandle);
3266 if (DefaultsOpCodeHandle != NULL) {
3267 InternalHiiAppendOpCodes (OpCodeHandle, DefaultsOpCodeHandle);
3268 }
3269 HiiCreateEndOpCode (OpCodeHandle);
3270 return InternalHiiOpCodeHandleBuffer (OpCodeHandle) + Position;
3271 }
3272
3273 /**
3274 Create EFI_IFR_TEXT_OP opcode.
3275
3276 If OpCodeHandle is NULL, then ASSERT().
3277
3278 @param[in] OpCodeHandle Handle to the buffer of opcodes.
3279 @param[in] Prompt String ID for Prompt.
3280 @param[in] Help String ID for Help.
3281 @param[in] TextTwo String ID for TextTwo.
3282
3283 @retval NULL There is not enough space left in Buffer to add the opcode.
3284 @retval Other A pointer to the created opcode.
3285
3286 **/
3287 UINT8 *
3288 EFIAPI
3289 HiiCreateTextOpCode (
3290 IN VOID *OpCodeHandle,
3291 IN EFI_STRING_ID Prompt,
3292 IN EFI_STRING_ID Help,
3293 IN EFI_STRING_ID TextTwo
3294 )
3295 {
3296 EFI_IFR_TEXT OpCode;
3297
3298 ZeroMem (&OpCode, sizeof (OpCode));
3299 OpCode.Statement.Prompt = Prompt;
3300 OpCode.Statement.Help = Help;
3301 OpCode.TextTwo = TextTwo;
3302
3303 return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_TEXT_OP, sizeof (OpCode));
3304 }
3305
3306 /**
3307 Create EFI_IFR_DATE_OP opcode.
3308
3309 If OpCodeHandle is NULL, then ASSERT().
3310 If any reserved bits are set in QuestionFlags, then ASSERT().
3311 If any reserved bits are set in DateFlags, then ASSERT().
3312
3313 @param[in] OpCodeHandle Handle to the buffer of opcodes.
3314 @param[in] QuestionId Question ID
3315 @param[in] VarStoreId Storage ID, optional. If DateFlags is not
3316 QF_DATE_STORAGE_NORMAL, this parameter is ignored.
3317 @param[in] VarOffset Offset in Storage, optional. If DateFlags is not
3318 QF_DATE_STORAGE_NORMAL, this parameter is ignored.
3319 @param[in] Prompt String ID for Prompt
3320 @param[in] Help String ID for Help
3321 @param[in] QuestionFlags Flags in Question Header
3322 @param[in] DateFlags Flags for date opcode
3323 @param[in] DefaultsOpCodeHandle Handle for a buffer of DEFAULT opcodes. This
3324 is an optional parameter that may be NULL.
3325
3326 @retval NULL There is not enough space left in Buffer to add the opcode.
3327 @retval Other A pointer to the created opcode.
3328
3329 **/
3330 UINT8 *
3331 EFIAPI
3332 HiiCreateDateOpCode (
3333 IN VOID *OpCodeHandle,
3334 IN EFI_QUESTION_ID QuestionId,
3335 IN EFI_VARSTORE_ID VarStoreId, OPTIONAL
3336 IN UINT16 VarOffset, OPTIONAL
3337 IN EFI_STRING_ID Prompt,
3338 IN EFI_STRING_ID Help,
3339 IN UINT8 QuestionFlags,
3340 IN UINT8 DateFlags,
3341 IN VOID *DefaultsOpCodeHandle OPTIONAL
3342 )
3343 {
3344 EFI_IFR_DATE OpCode;
3345 UINTN Position;
3346
3347 ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED))) == 0);
3348 ASSERT ((DateFlags & (~(EFI_QF_DATE_YEAR_SUPPRESS | EFI_QF_DATE_MONTH_SUPPRESS | EFI_QF_DATE_DAY_SUPPRESS | EFI_QF_DATE_STORAGE))) == 0);
3349
3350 ZeroMem (&OpCode, sizeof (OpCode));
3351 OpCode.Question.Header.Prompt = Prompt;
3352 OpCode.Question.Header.Help = Help;
3353 OpCode.Question.QuestionId = QuestionId;
3354 OpCode.Question.VarStoreId = VarStoreId;
3355 OpCode.Question.VarStoreInfo.VarOffset = VarOffset;
3356 OpCode.Question.Flags = QuestionFlags;
3357 OpCode.Flags = DateFlags;
3358
3359 if (DefaultsOpCodeHandle == NULL) {
3360 return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_DATE_OP, sizeof (OpCode));
3361 }
3362
3363 Position = InternalHiiOpCodeHandlePosition (OpCodeHandle);
3364 InternalHiiCreateOpCodeExtended (OpCodeHandle, &OpCode, EFI_IFR_DATE_OP, sizeof (OpCode), 0, 1);
3365 InternalHiiAppendOpCodes (OpCodeHandle, DefaultsOpCodeHandle);
3366 HiiCreateEndOpCode (OpCodeHandle);
3367 return InternalHiiOpCodeHandleBuffer (OpCodeHandle) + Position;
3368 }
3369
3370 /**
3371 Create EFI_IFR_TIME_OP opcode.
3372
3373 If OpCodeHandle is NULL, then ASSERT().
3374 If any reserved bits are set in QuestionFlags, then ASSERT().
3375 If any reserved bits are set in TimeFlags, then ASSERT().
3376
3377 @param[in] OpCodeHandle Handle to the buffer of opcodes.
3378 @param[in] QuestionId Question ID
3379 @param[in] VarStoreId Storage ID, optional. If TimeFlags is not
3380 QF_TIME_STORAGE_NORMAL, this parameter is ignored.
3381 @param[in] VarOffset Offset in Storage, optional. If TimeFlags is not
3382 QF_TIME_STORAGE_NORMAL, this parameter is ignored.
3383 @param[in] Prompt String ID for Prompt
3384 @param[in] Help String ID for Help
3385 @param[in] QuestionFlags Flags in Question Header
3386 @param[in] TimeFlags Flags for time opcode
3387 @param[in] DefaultsOpCodeHandle Handle for a buffer of DEFAULT opcodes. This
3388 is an optional parameter that may be NULL.
3389
3390 @retval NULL There is not enough space left in Buffer to add the opcode.
3391 @retval Other A pointer to the created opcode.
3392
3393 **/
3394 UINT8 *
3395 EFIAPI
3396 HiiCreateTimeOpCode (
3397 IN VOID *OpCodeHandle,
3398 IN EFI_QUESTION_ID QuestionId,
3399 IN EFI_VARSTORE_ID VarStoreId, OPTIONAL
3400 IN UINT16 VarOffset, OPTIONAL
3401 IN EFI_STRING_ID Prompt,
3402 IN EFI_STRING_ID Help,
3403 IN UINT8 QuestionFlags,
3404 IN UINT8 TimeFlags,
3405 IN VOID *DefaultsOpCodeHandle OPTIONAL
3406 )
3407 {
3408 EFI_IFR_TIME OpCode;
3409 UINTN Position;
3410
3411 ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED))) == 0);
3412 ASSERT ((TimeFlags & (~(QF_TIME_HOUR_SUPPRESS | QF_TIME_MINUTE_SUPPRESS | QF_TIME_SECOND_SUPPRESS | QF_TIME_STORAGE))) == 0);
3413
3414 ZeroMem (&OpCode, sizeof (OpCode));
3415 OpCode.Question.Header.Prompt = Prompt;
3416 OpCode.Question.Header.Help = Help;
3417 OpCode.Question.QuestionId = QuestionId;
3418 OpCode.Question.VarStoreId = VarStoreId;
3419 OpCode.Question.VarStoreInfo.VarOffset = VarOffset;
3420 OpCode.Question.Flags = QuestionFlags;
3421 OpCode.Flags = TimeFlags;
3422
3423 if (DefaultsOpCodeHandle == NULL) {
3424 return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_TIME_OP, sizeof (OpCode));
3425 }
3426
3427 Position = InternalHiiOpCodeHandlePosition (OpCodeHandle);
3428 InternalHiiCreateOpCodeExtended (OpCodeHandle, &OpCode, EFI_IFR_TIME_OP, sizeof (OpCode), 0, 1);
3429 InternalHiiAppendOpCodes (OpCodeHandle, DefaultsOpCodeHandle);
3430 HiiCreateEndOpCode (OpCodeHandle);
3431 return InternalHiiOpCodeHandleBuffer (OpCodeHandle) + Position;
3432 }
3433
3434 /**
3435 This is the internal worker function to update the data in
3436 a form specified by FormSetGuid, FormId and Label.
3437
3438 @param[in] FormSetGuid The optional Formset GUID.
3439 @param[in] FormId The Form ID.
3440 @param[in] Package The package header.
3441 @param[in] OpCodeBufferStart An OpCode buffer that contains the set of IFR
3442 opcodes to be inserted or replaced in the form.
3443 @param[in] OpCodeBufferEnd An OpCcode buffer that contains the IFR opcode
3444 that marks the end of a replace operation in the form.
3445 @param[out] TempPackage The resultant package.
3446
3447 @retval EFI_SUCCESS The function completes successfully.
3448 @retval EFI_NOT_FOUND The updated opcode or endopcode is not found.
3449
3450 **/
3451 EFI_STATUS
3452 EFIAPI
3453 InternalHiiUpdateFormPackageData (
3454 IN EFI_GUID *FormSetGuid, OPTIONAL
3455 IN EFI_FORM_ID FormId,
3456 IN EFI_HII_PACKAGE_HEADER *Package,
3457 IN HII_LIB_OPCODE_BUFFER *OpCodeBufferStart,
3458 IN HII_LIB_OPCODE_BUFFER *OpCodeBufferEnd, OPTIONAL
3459 OUT EFI_HII_PACKAGE_HEADER *TempPackage
3460 )
3461 {
3462 UINTN AddSize;
3463 UINT8 *BufferPos;
3464 EFI_HII_PACKAGE_HEADER PackageHeader;
3465 UINTN Offset;
3466 EFI_IFR_OP_HEADER *IfrOpHdr;
3467 EFI_IFR_OP_HEADER *UpdateIfrOpHdr;
3468 BOOLEAN GetFormSet;
3469 BOOLEAN GetForm;
3470 BOOLEAN Updated;
3471 UINTN UpdatePackageLength;
3472
3473 CopyMem (TempPackage, Package, sizeof (EFI_HII_PACKAGE_HEADER));
3474 UpdatePackageLength = sizeof (EFI_HII_PACKAGE_HEADER);
3475 BufferPos = (UINT8 *) (TempPackage + 1);
3476
3477 CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));
3478 IfrOpHdr = (EFI_IFR_OP_HEADER *)((UINT8 *) Package + sizeof (EFI_HII_PACKAGE_HEADER));
3479 Offset = sizeof (EFI_HII_PACKAGE_HEADER);
3480 GetFormSet = (BOOLEAN) ((FormSetGuid == NULL) ? TRUE : FALSE);
3481 GetForm = FALSE;
3482 Updated = FALSE;
3483
3484 while (Offset < PackageHeader.Length) {
3485 CopyMem (BufferPos, IfrOpHdr, IfrOpHdr->Length);
3486 BufferPos += IfrOpHdr->Length;
3487 UpdatePackageLength += IfrOpHdr->Length;
3488
3489 //
3490 // Find the matched FormSet and Form
3491 //
3492 if ((IfrOpHdr->OpCode == EFI_IFR_FORM_SET_OP) && (FormSetGuid != NULL)) {
3493 if (CompareGuid((GUID *)(VOID *)&((EFI_IFR_FORM_SET *) IfrOpHdr)->Guid, FormSetGuid)) {
3494 GetFormSet = TRUE;
3495 } else {
3496 GetFormSet = FALSE;
3497 }
3498 } else if (IfrOpHdr->OpCode == EFI_IFR_FORM_OP || IfrOpHdr->OpCode == EFI_IFR_FORM_MAP_OP) {
3499 if (CompareMem (&((EFI_IFR_FORM *) IfrOpHdr)->FormId, &FormId, sizeof (EFI_FORM_ID)) == 0) {
3500 GetForm = TRUE;
3501 } else {
3502 GetForm = FALSE;
3503 }
3504 }
3505
3506 //
3507 // The matched Form is found, and Update data in this form
3508 //
3509 if (GetFormSet && GetForm) {
3510 UpdateIfrOpHdr = (EFI_IFR_OP_HEADER *) OpCodeBufferStart->Buffer;
3511 if ((UpdateIfrOpHdr->Length == IfrOpHdr->Length) && \
3512 (CompareMem (IfrOpHdr, UpdateIfrOpHdr, UpdateIfrOpHdr->Length) == 0)) {
3513 //
3514 // Remove the original data when End OpCode buffer exist.
3515 //
3516 if (OpCodeBufferEnd != NULL) {
3517 Offset += IfrOpHdr->Length;
3518 IfrOpHdr = (EFI_IFR_OP_HEADER *) ((UINT8 *) (IfrOpHdr) + IfrOpHdr->Length);
3519 UpdateIfrOpHdr = (EFI_IFR_OP_HEADER *) OpCodeBufferEnd->Buffer;
3520 while (Offset < PackageHeader.Length) {
3521 //
3522 // Search the matched end opcode
3523 //
3524 if ((UpdateIfrOpHdr->Length == IfrOpHdr->Length) && \
3525 (CompareMem (IfrOpHdr, UpdateIfrOpHdr, UpdateIfrOpHdr->Length) == 0)) {
3526 break;
3527 }
3528 //
3529 // Go to the next Op-Code
3530 //
3531 Offset += IfrOpHdr->Length;
3532 IfrOpHdr = (EFI_IFR_OP_HEADER *) ((UINT8 *) (IfrOpHdr) + IfrOpHdr->Length);
3533 }
3534
3535 if (Offset >= PackageHeader.Length) {
3536 //
3537 // The end opcode is not found.
3538 //
3539 return EFI_NOT_FOUND;
3540 }
3541 }
3542
3543 //
3544 // Insert the updated data
3545 //
3546 AddSize = ((EFI_IFR_OP_HEADER *) OpCodeBufferStart->Buffer)->Length;
3547 CopyMem (BufferPos, OpCodeBufferStart->Buffer + AddSize, OpCodeBufferStart->Position - AddSize);
3548 BufferPos += OpCodeBufferStart->Position - AddSize;
3549 UpdatePackageLength += OpCodeBufferStart->Position - AddSize;
3550
3551 if (OpCodeBufferEnd != NULL) {
3552 //
3553 // Add the end opcode
3554 //
3555 CopyMem (BufferPos, IfrOpHdr, IfrOpHdr->Length);
3556 BufferPos += IfrOpHdr->Length;
3557 UpdatePackageLength += IfrOpHdr->Length;
3558 }
3559
3560 //
3561 // Copy the left package data.
3562 //
3563 Offset += IfrOpHdr->Length;
3564 CopyMem (BufferPos, (UINT8 *) Package + Offset, PackageHeader.Length - Offset);
3565 UpdatePackageLength += PackageHeader.Length - Offset;
3566
3567 //
3568 // Set update flag
3569 //
3570 Updated = TRUE;
3571 break;
3572 }
3573 }
3574
3575 //
3576 // Go to the next Op-Code
3577 //
3578 Offset += IfrOpHdr->Length;
3579 IfrOpHdr = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (IfrOpHdr) + IfrOpHdr->Length);
3580 }
3581
3582 if (!Updated) {
3583 //
3584 // The updated opcode buffer is not found.
3585 //
3586 return EFI_NOT_FOUND;
3587 }
3588 //
3589 // Update the package length.
3590 //
3591 PackageHeader.Length = (UINT32) UpdatePackageLength;
3592 CopyMem (TempPackage, &PackageHeader, sizeof (EFI_HII_PACKAGE_HEADER));
3593
3594 return EFI_SUCCESS;
3595 }
3596
3597 /**
3598 This function updates a form that has previously been registered with the HII
3599 Database. This function will perform at most one update operation.
3600
3601 The form to update is specified by Handle, FormSetGuid, and FormId. Binary
3602 comparisons of IFR opcodes are performed from the beginning of the form being
3603 updated until an IFR opcode is found that exactly matches the first IFR opcode
3604 specified by StartOpCodeHandle. The following rules are used to determine if
3605 an insert, replace, or delete operation is performed.
3606
3607 1) If no matches are found, then NULL is returned.
3608 2) If a match is found, and EndOpCodeHandle is NULL, then all of the IFR opcodes
3609 from StartOpCodeHandle except the first opcode are inserted immediately after
3610 the matching IFR opcode in the form to be updated.
3611 3) If a match is found, and EndOpCodeHandle is not NULL, then a search is made
3612 from the matching IFR opcode until an IFR opcode exactly matches the first
3613 IFR opcode specified by EndOpCodeHandle. If no match is found for the first
3614 IFR opcode specified by EndOpCodeHandle, then NULL is returned. If a match
3615 is found, then all of the IFR opcodes between the start match and the end
3616 match are deleted from the form being updated and all of the IFR opcodes
3617 from StartOpCodeHandle except the first opcode are inserted immediately after
3618 the matching start IFR opcode. If StartOpCcodeHandle only contains one
3619 IFR instruction, then the result of this operation will delete all of the IFR
3620 opcodes between the start end matches.
3621
3622 If HiiHandle is NULL, then ASSERT().
3623 If StartOpCodeHandle is NULL, then ASSERT().
3624
3625 @param[in] HiiHandle The HII Handle of the form to update.
3626 @param[in] FormSetGuid The Formset GUID of the form to update. This
3627 is an optional parameter that may be NULL.
3628 If it is NULL, all FormSet will be updated.
3629 @param[in] FormId The ID of the form to update.
3630 @param[in] StartOpCodeHandle An OpCode Handle that contains the set of IFR
3631 opcodes to be inserted or replaced in the form.
3632 The first IFR instruction in StartOpCodeHandle
3633 is used to find matching IFR opcode in the
3634 form.
3635 @param[in] EndOpCodeHandle An OpCcode Handle that contains the IFR opcode
3636 that marks the end of a replace operation in
3637 the form. This is an optional parameter that
3638 may be NULL. If it is NULL, then an the IFR
3639 opcodes specified by StartOpCodeHandle are
3640 inserted into the form.
3641
3642 @retval EFI_OUT_OF_RESOURCES No enough memory resource is allocated.
3643 @retval EFI_NOT_FOUND The following cases will return EFI_NOT_FOUND.
3644 1) The form specified by HiiHandle, FormSetGuid,
3645 and FormId could not be found in the HII Database.
3646 2) No IFR opcodes in the target form match the first
3647 IFR opcode in StartOpCodeHandle.
3648 3) EndOpCOde is not NULL, and no IFR opcodes in the
3649 target form following a matching start opcode match
3650 the first IFR opcode in EndOpCodeHandle.
3651 @retval EFI_SUCCESS The matched form is updated by StartOpcode.
3652
3653 **/
3654 EFI_STATUS
3655 EFIAPI
3656 HiiUpdateForm (
3657 IN EFI_HII_HANDLE HiiHandle,
3658 IN EFI_GUID *FormSetGuid, OPTIONAL
3659 IN EFI_FORM_ID FormId,
3660 IN VOID *StartOpCodeHandle,
3661 IN VOID *EndOpCodeHandle OPTIONAL
3662 )
3663 {
3664 EFI_STATUS Status;
3665 EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;
3666 UINT32 PackageListLength;
3667 UINT32 Offset;
3668 EFI_HII_PACKAGE_LIST_HEADER *UpdatePackageList;
3669 UINTN BufferSize;
3670 UINT8 *UpdateBufferPos;
3671 EFI_HII_PACKAGE_HEADER *Package;
3672 EFI_HII_PACKAGE_HEADER *TempPacakge;
3673 EFI_HII_PACKAGE_HEADER PackageHeader;
3674 BOOLEAN Updated;
3675 HII_LIB_OPCODE_BUFFER *OpCodeBufferStart;
3676 HII_LIB_OPCODE_BUFFER *OpCodeBufferEnd;
3677
3678 //
3679 // Input update data can't be NULL.
3680 //
3681 ASSERT (HiiHandle != NULL);
3682 ASSERT (StartOpCodeHandle != NULL);
3683 UpdatePackageList = NULL;
3684 TempPacakge = NULL;
3685 HiiPackageList = NULL;
3686
3687 //
3688 // Retrieve buffer data from Opcode Handle
3689 //
3690 OpCodeBufferStart = (HII_LIB_OPCODE_BUFFER *) StartOpCodeHandle;
3691 OpCodeBufferEnd = (HII_LIB_OPCODE_BUFFER *) EndOpCodeHandle;
3692
3693 //
3694 // Get the original package list
3695 //
3696 BufferSize = 0;
3697 HiiPackageList = NULL;
3698 Status = gHiiDatabase->ExportPackageLists (gHiiDatabase, HiiHandle, &BufferSize, HiiPackageList);
3699 //
3700 // The return status should always be EFI_BUFFER_TOO_SMALL as input buffer's size is 0.
3701 //
3702 if (Status != EFI_BUFFER_TOO_SMALL) {
3703 return Status;
3704 }
3705
3706 HiiPackageList = AllocatePool (BufferSize);
3707 if (HiiPackageList == NULL) {
3708 Status = EFI_OUT_OF_RESOURCES;
3709 goto Finish;
3710 }
3711
3712 Status = gHiiDatabase->ExportPackageLists (gHiiDatabase, HiiHandle, &BufferSize, HiiPackageList);
3713 if (EFI_ERROR (Status)) {
3714 goto Finish;
3715 }
3716
3717 //
3718 // Calculate and allocate space for retrieval of IFR data
3719 //
3720 BufferSize += OpCodeBufferStart->Position;
3721 UpdatePackageList = AllocateZeroPool (BufferSize);
3722 if (UpdatePackageList == NULL) {
3723 Status = EFI_OUT_OF_RESOURCES;
3724 goto Finish;
3725 }
3726
3727 //
3728 // Allocate temp buffer to store the temp updated package buffer
3729 //
3730 TempPacakge = AllocateZeroPool (BufferSize);
3731 if (TempPacakge == NULL) {
3732 Status = EFI_OUT_OF_RESOURCES;
3733 goto Finish;
3734 }
3735
3736 UpdateBufferPos = (UINT8 *) UpdatePackageList;
3737
3738 //
3739 // Copy the package list header
3740 //
3741 CopyMem (UpdateBufferPos, HiiPackageList, sizeof (EFI_HII_PACKAGE_LIST_HEADER));
3742 UpdateBufferPos += sizeof (EFI_HII_PACKAGE_LIST_HEADER);
3743
3744 //
3745 // Go through each package to find the matched package and update one by one
3746 //
3747 Updated = FALSE;
3748 Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);
3749 PackageListLength = ReadUnaligned32 (&HiiPackageList->PackageLength);
3750 while (Offset < PackageListLength) {
3751 Package = (EFI_HII_PACKAGE_HEADER *) (((UINT8 *) HiiPackageList) + Offset);
3752 CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));
3753 Offset += Package->Length;
3754
3755 if (Package->Type == EFI_HII_PACKAGE_FORMS) {
3756 //
3757 // Check this package is the matched package.
3758 //
3759 Status = InternalHiiUpdateFormPackageData (FormSetGuid, FormId, Package, OpCodeBufferStart, OpCodeBufferEnd, TempPacakge);
3760 //
3761 // The matched package is found. Its package buffer will be updated by the input new data.
3762 //
3763 if (!EFI_ERROR(Status)) {
3764 //
3765 // Set Update Flag
3766 //
3767 Updated = TRUE;
3768 //
3769 // Add updated package buffer
3770 //
3771 Package = TempPacakge;
3772 }
3773 }
3774
3775 //
3776 // Add pacakge buffer
3777 //
3778 CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));
3779 CopyMem (UpdateBufferPos, Package, PackageHeader.Length);
3780 UpdateBufferPos += PackageHeader.Length;
3781 }
3782
3783 if (Updated) {
3784 //
3785 // Update package list length
3786 //
3787 BufferSize = UpdateBufferPos - (UINT8 *) UpdatePackageList;
3788 WriteUnaligned32 (&UpdatePackageList->PackageLength, (UINT32) BufferSize);
3789
3790 //
3791 // Update Package to show form
3792 //
3793 Status = gHiiDatabase->UpdatePackageList (gHiiDatabase, HiiHandle, UpdatePackageList);
3794 } else {
3795 //
3796 // Not matched form is found and updated.
3797 //
3798 Status = EFI_NOT_FOUND;
3799 }
3800
3801 Finish:
3802 if (HiiPackageList != NULL) {
3803 FreePool (HiiPackageList);
3804 }
3805
3806 if (UpdatePackageList != NULL) {
3807 FreePool (UpdatePackageList);
3808 }
3809
3810 if (TempPacakge != NULL) {
3811 FreePool (TempPacakge);
3812 }
3813
3814 return Status;
3815 }