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