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