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