]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Library/UefiHiiLib/HiiLib.c
997e36aeb11dea84f00a94147259591f560de8d1
[mirror_edk2.git] / MdeModulePkg / Library / UefiHiiLib / HiiLib.c
1 /** @file
2 HII Library implementation that uses DXE protocols and services.
3
4 Copyright (c) 2006 - 2008, Intel Corporation<BR>
5 All rights reserved. This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13 **/
14
15 #include "InternalHiiLib.h"
16
17 //
18 // <ConfigHdr> Template
19 //
20 GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR16 mConfigHdrTemplate[] = L"GUID=00000000000000000000000000000000&NAME=0000&PATH=00";
21
22 //
23 // Form Browser2 Protocol
24 //
25 EFI_FORM_BROWSER2_PROTOCOL *mUefiFormBrowser2 = NULL;
26
27 /**
28 This funciton build the package list based on the package number,
29 the GUID of the package list and the list of pointer which point to
30 package header that defined by UEFI VFR compiler and StringGather
31 tool.
32
33 #pragma pack (push, 1)
34 typedef struct {
35 UINT32 BinaryLength;
36 EFI_HII_PACKAGE_HEADER PackageHeader;
37 } EDKII_AUTOGEN_PACKAGES_HEADER;
38 #pragma pack (pop)
39
40 If there is not enough resource for the new package list,
41 the function will ASSERT.
42
43 @param NumberOfPackages The number of packages be
44 @param GuidId The GUID for the package list to be generated.
45 @param Marker The variable argument list. Each entry represent a specific package header that is
46 generated by VFR compiler and StrGather tool. The first 4 bytes is a UINT32 value
47 that indicate the overall length of the package.
48
49 @return The pointer to the package list header.
50
51 **/
52 EFI_HII_PACKAGE_LIST_HEADER *
53 InternalHiiLibPreparePackages (
54 IN UINTN NumberOfPackages,
55 IN CONST EFI_GUID *GuidId,
56 IN VA_LIST Marker
57 )
58 {
59 EFI_HII_PACKAGE_LIST_HEADER *PackageListHeader;
60 UINT8 *PackageListData;
61 UINT32 PackageListLength;
62 UINT32 PackageLength;
63 EFI_HII_PACKAGE_HEADER PackageHeader;
64 UINT8 *PackageArray;
65 UINTN Index;
66 VA_LIST MarkerBackup;
67
68 PackageListLength = sizeof (EFI_HII_PACKAGE_LIST_HEADER);
69
70 MarkerBackup = Marker;
71
72 //
73 // Count the length of the final package list.
74 //
75 for (Index = 0; Index < NumberOfPackages; Index++) {
76 CopyMem (&PackageLength, VA_ARG (Marker, VOID *), sizeof (UINT32));
77 //
78 // Do not count the BinaryLength field.
79 //
80 PackageListLength += (PackageLength - sizeof (UINT32));
81 }
82
83 //
84 // Include the length of EFI_HII_PACKAGE_END
85 //
86 PackageListLength += sizeof (EFI_HII_PACKAGE_HEADER);
87 PackageListHeader = AllocateZeroPool (PackageListLength);
88 ASSERT (PackageListHeader != NULL);
89
90 CopyGuid (&PackageListHeader->PackageListGuid, GuidId);
91 PackageListHeader->PackageLength = PackageListLength;
92
93 PackageListData = ((UINT8 *) PackageListHeader) + sizeof (EFI_HII_PACKAGE_LIST_HEADER);
94
95 Marker = MarkerBackup;
96 //
97 // Prepare the final package list.
98 //
99 for (Index = 0; Index < NumberOfPackages; Index++) {
100 PackageArray = (UINT8 *) VA_ARG (Marker, VOID *);
101 //
102 // CopyMem is used for UINT32 to cover the unaligned address access.
103 //
104 CopyMem (&PackageLength, PackageArray, sizeof (UINT32));
105 PackageLength -= sizeof (UINT32);
106 PackageArray += sizeof (UINT32);
107 CopyMem (PackageListData, PackageArray, PackageLength);
108 PackageListData += PackageLength;
109 }
110
111 //
112 // Append EFI_HII_PACKAGE_END
113 //
114 PackageHeader.Type = EFI_HII_PACKAGE_END;
115 PackageHeader.Length = sizeof (EFI_HII_PACKAGE_HEADER);
116 CopyMem (PackageListData, &PackageHeader, PackageHeader.Length);
117
118 return PackageListHeader;
119 }
120
121 /**
122 Assemble EFI_HII_PACKAGE_LIST according to the passed in packages.
123
124 If GuidId is NULL, then ASSERT.
125 If not enough resource to complete the operation, then ASSERT.
126
127 @param NumberOfPackages Number of packages.
128 @param GuidId Package GUID.
129 @param ... Variable argument list for packages to be assembled.
130
131 @return Pointer of EFI_HII_PACKAGE_LIST_HEADER.
132
133 **/
134 EFI_HII_PACKAGE_LIST_HEADER *
135 EFIAPI
136 HiiLibPreparePackageList (
137 IN UINTN NumberOfPackages,
138 IN CONST EFI_GUID *GuidId,
139 ...
140 )
141 {
142 EFI_HII_PACKAGE_LIST_HEADER *PackageListHeader;
143 VA_LIST Marker;
144
145 ASSERT (GuidId != NULL);
146
147 VA_START (Marker, GuidId);
148 PackageListHeader = InternalHiiLibPreparePackages (NumberOfPackages, GuidId, Marker);
149 VA_END (Marker);
150
151 return PackageListHeader;
152 }
153
154
155 /**
156 This function allocates pool for an EFI_HII_PACKAGE_LIST structure
157 with additional space that is big enough to host all packages described by the variable
158 argument list of package pointers. The allocated structure is initialized using NumberOfPackages,
159 GuidId, and the variable length argument list of package pointers.
160
161 Then, EFI_HII_PACKAGE_LIST will be register to the default System HII Database. The
162 Handle to the newly registered Package List is returned through HiiHandle.
163
164 If HiiHandle is NULL, then ASSERT.
165
166 @param NumberOfPackages The number of HII packages to register.
167 @param GuidId Package List GUID ID.
168 @param DriverHandle Optional. If not NULL, the DriverHandle on which an instance of DEVICE_PATH_PROTOCOL is installed.
169 This DriverHandle uniquely defines the device that the added packages are associated with.
170 @param HiiHandle On output, the HiiHandle is update with the handle which can be used to retrieve the Package
171 List later. If the functions failed to add the package to the default HII database, this value will
172 be set to NULL.
173 @param ... The variable argument list describing all HII Package.
174
175 @return EFI_SUCCESS If the packages are successfully added to the default HII database.
176 @return EFI_OUT_OF_RESOURCE Not enough resource to complete the operation.
177
178 **/
179 EFI_STATUS
180 EFIAPI
181 HiiLibAddPackages (
182 IN UINTN NumberOfPackages,
183 IN CONST EFI_GUID *GuidId,
184 IN EFI_HANDLE DriverHandle, OPTIONAL
185 OUT EFI_HII_HANDLE *HiiHandle,
186 ...
187 )
188 {
189 VA_LIST Args;
190 EFI_HII_PACKAGE_LIST_HEADER *PackageListHeader;
191 EFI_STATUS Status;
192
193 ASSERT (HiiHandle != NULL);
194
195 VA_START (Args, HiiHandle);
196 PackageListHeader = InternalHiiLibPreparePackages (NumberOfPackages, GuidId, Args);
197
198 Status = gHiiDatabase->NewPackageList (gHiiDatabase, PackageListHeader, DriverHandle, HiiHandle);
199 if (HiiHandle != NULL) {
200 if (EFI_ERROR (Status)) {
201 *HiiHandle = NULL;
202 }
203 }
204
205 FreePool (PackageListHeader);
206 VA_END (Args);
207
208 return Status;
209 }
210
211 /**
212 Removes a package list from the default HII database.
213
214 If HiiHandle is NULL, then ASSERT.
215 If HiiHandle is not a valid EFI_HII_HANDLE in the default HII database, then ASSERT.
216
217 @param HiiHandle The handle that was previously registered to the data base that is requested for removal.
218 List later.
219
220 **/
221 VOID
222 EFIAPI
223 HiiLibRemovePackages (
224 IN EFI_HII_HANDLE HiiHandle
225 )
226 {
227 EFI_STATUS Status;
228 ASSERT (IsHiiHandleRegistered (HiiHandle));
229
230 Status = gHiiDatabase->RemovePackageList (gHiiDatabase, HiiHandle);
231 ASSERT_EFI_ERROR (Status);
232 }
233
234
235 /**
236 Determines the handles that are currently active in the database.
237 It's the caller's responsibility to free handle buffer.
238
239 If HandleBufferLength is NULL, then ASSERT.
240 If HiiHandleBuffer is NULL, then ASSERT.
241
242 @param HandleBufferLength On input, a pointer to the length of the handle
243 buffer. On output, the length of the handle buffer
244 that is required for the handles found.
245 @param HiiHandleBuffer Pointer to an array of Hii Handles returned.
246
247 @retval EFI_SUCCESS Get an array of Hii Handles successfully.
248
249 **/
250 EFI_STATUS
251 EFIAPI
252 HiiLibGetHiiHandles (
253 IN OUT UINTN *HandleBufferLength,
254 OUT EFI_HII_HANDLE **HiiHandleBuffer
255 )
256 {
257 EFI_STATUS Status;
258
259 ASSERT (HandleBufferLength != NULL);
260 ASSERT (HiiHandleBuffer != NULL);
261
262 *HandleBufferLength = 0;
263 *HiiHandleBuffer = NULL;
264
265 //
266 // Try to find the actual buffer size for HiiHandle Buffer.
267 //
268 Status = gHiiDatabase->ListPackageLists (
269 gHiiDatabase,
270 EFI_HII_PACKAGE_TYPE_ALL,
271 NULL,
272 HandleBufferLength,
273 *HiiHandleBuffer
274 );
275
276 if (Status == EFI_BUFFER_TOO_SMALL) {
277 *HiiHandleBuffer = AllocateZeroPool (*HandleBufferLength);
278 ASSERT (*HiiHandleBuffer != NULL);
279 Status = gHiiDatabase->ListPackageLists (
280 gHiiDatabase,
281 EFI_HII_PACKAGE_TYPE_ALL,
282 NULL,
283 HandleBufferLength,
284 *HiiHandleBuffer
285 );
286
287 if (EFI_ERROR (Status)) {
288 FreePool (*HiiHandleBuffer);
289 *HiiHandleBuffer = NULL;
290 }
291 }
292
293 return Status;
294 }
295
296 /**
297 Extract Hii package list GUID for given HII handle.
298
299 If HiiHandle could not be found in the default HII database, then ASSERT.
300 If Guid is NULL, then ASSERT.
301
302 @param Handle Hii handle
303 @param Guid Package list GUID
304
305 @retval EFI_SUCCESS Successfully extract GUID from Hii database.
306
307 **/
308 EFI_STATUS
309 EFIAPI
310 HiiLibExtractGuidFromHiiHandle (
311 IN EFI_HII_HANDLE Handle,
312 OUT EFI_GUID *Guid
313 )
314 {
315 EFI_STATUS Status;
316 UINTN BufferSize;
317 EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;
318
319 ASSERT (Guid != NULL);
320 ASSERT (IsHiiHandleRegistered (Handle));
321
322 //
323 // Get HII PackageList
324 //
325 BufferSize = 0;
326 HiiPackageList = NULL;
327
328 Status = gHiiDatabase->ExportPackageLists (gHiiDatabase, Handle, &BufferSize, HiiPackageList);
329 ASSERT (Status != EFI_NOT_FOUND);
330
331 if (Status == EFI_BUFFER_TOO_SMALL) {
332 HiiPackageList = AllocatePool (BufferSize);
333 ASSERT (HiiPackageList != NULL);
334
335 Status = gHiiDatabase->ExportPackageLists (gHiiDatabase, Handle, &BufferSize, HiiPackageList);
336 }
337 if (EFI_ERROR (Status)) {
338 FreePool (HiiPackageList);
339 return Status;
340 }
341
342 //
343 // Extract GUID
344 //
345 CopyGuid (Guid, &HiiPackageList->PackageListGuid);
346
347 FreePool (HiiPackageList);
348
349 return EFI_SUCCESS;
350 }
351
352 /**
353 Find HII Handle in the default HII database associated with given Device Path.
354
355 If DevicePath is NULL, then ASSERT.
356
357 @param DevicePath Device Path associated with the HII package list
358 handle.
359
360 @retval Handle HII package list Handle associated with the Device
361 Path.
362 @retval NULL Hii Package list handle is not found.
363
364 **/
365 EFI_HII_HANDLE
366 EFIAPI
367 HiiLibDevicePathToHiiHandle (
368 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
369 )
370 {
371 EFI_STATUS Status;
372 EFI_DEVICE_PATH_PROTOCOL *TmpDevicePath;
373 UINTN BufferSize;
374 UINTN HandleCount;
375 UINTN Index;
376 EFI_HANDLE *Handles;
377 EFI_HANDLE Handle;
378 UINTN Size;
379 EFI_HANDLE DriverHandle;
380 EFI_HII_HANDLE *HiiHandles;
381 EFI_HII_HANDLE HiiHandle;
382
383 ASSERT (DevicePath != NULL);
384
385 //
386 // Locate Device Path Protocol handle buffer
387 //
388 Status = gBS->LocateHandleBuffer (
389 ByProtocol,
390 &gEfiDevicePathProtocolGuid,
391 NULL,
392 &HandleCount,
393 &Handles
394 );
395 if (EFI_ERROR (Status)) {
396 return NULL;
397 }
398
399 //
400 // Search Driver Handle by Device Path
401 //
402 DriverHandle = NULL;
403 BufferSize = GetDevicePathSize (DevicePath);
404 for(Index = 0; Index < HandleCount; Index++) {
405 Handle = Handles[Index];
406 gBS->HandleProtocol (Handle, &gEfiDevicePathProtocolGuid, (VOID **) &TmpDevicePath);
407
408 //
409 // Check whether DevicePath match
410 //
411 Size = GetDevicePathSize (TmpDevicePath);
412 if ((Size == BufferSize) && CompareMem (DevicePath, TmpDevicePath, Size) == 0) {
413 DriverHandle = Handle;
414 break;
415 }
416 }
417 FreePool (Handles);
418
419 if (DriverHandle == NULL) {
420 return NULL;
421 }
422
423 //
424 // Retrieve all Hii Handles from HII database
425 //
426 BufferSize = 0x1000;
427 HiiHandles = AllocatePool (BufferSize);
428 ASSERT (HiiHandles != NULL);
429 Status = gHiiDatabase->ListPackageLists (
430 gHiiDatabase,
431 EFI_HII_PACKAGE_TYPE_ALL,
432 NULL,
433 &BufferSize,
434 HiiHandles
435 );
436 if (Status == EFI_BUFFER_TOO_SMALL) {
437 FreePool (HiiHandles);
438 HiiHandles = AllocatePool (BufferSize);
439 ASSERT (HiiHandles != NULL);
440
441 Status = gHiiDatabase->ListPackageLists (
442 gHiiDatabase,
443 EFI_HII_PACKAGE_TYPE_ALL,
444 NULL,
445 &BufferSize,
446 HiiHandles
447 );
448 }
449
450 if (EFI_ERROR (Status)) {
451 FreePool (HiiHandles);
452 return NULL;
453 }
454
455 //
456 // Search Hii Handle by Driver Handle
457 //
458 HiiHandle = NULL;
459 HandleCount = BufferSize / sizeof (EFI_HII_HANDLE);
460 for (Index = 0; Index < HandleCount; Index++) {
461 Status = gHiiDatabase->GetPackageListHandle (
462 gHiiDatabase,
463 HiiHandles[Index],
464 &Handle
465 );
466 if (!EFI_ERROR (Status) && (Handle == DriverHandle)) {
467 HiiHandle = HiiHandles[Index];
468 break;
469 }
470 }
471
472 FreePool (HiiHandles);
473 return HiiHandle;
474 }
475
476 /**
477 Exports the contents of one or all package lists in the HII database into a buffer.
478
479 If Handle is not NULL and not a valid EFI_HII_HANDLE registered in the database,
480 then ASSERT.
481 If PackageListHeader is NULL, then ASSERT.
482 If PackageListSize is NULL, then ASSERT.
483
484 @param Handle The HII Handle.
485 @param PackageListHeader A pointer to a buffer that will contain the results of
486 the export function.
487 @param PackageListSize On output, the length of the buffer that is required for the exported data.
488
489 @retval EFI_SUCCESS Package exported.
490
491 @retval EFI_OUT_OF_RESOURCES Not enought memory to complete the operations.
492
493 **/
494 EFI_STATUS
495 EFIAPI
496 HiiLibExportPackageLists (
497 IN EFI_HII_HANDLE Handle,
498 OUT EFI_HII_PACKAGE_LIST_HEADER **PackageListHeader,
499 OUT UINTN *PackageListSize
500 )
501 {
502 EFI_STATUS Status;
503 UINTN Size;
504 EFI_HII_PACKAGE_LIST_HEADER *PackageListHdr;
505
506 ASSERT (PackageListSize != NULL);
507 ASSERT (PackageListHeader != NULL);
508
509 if (Handle != NULL) {
510 ASSERT (IsHiiHandleRegistered (Handle));
511 }
512
513 Size = 0;
514 PackageListHdr = NULL;
515 Status = gHiiDatabase->ExportPackageLists (
516 gHiiDatabase,
517 Handle,
518 &Size,
519 PackageListHdr
520 );
521 ASSERT_EFI_ERROR (Status != EFI_BUFFER_TOO_SMALL);
522
523 if (Status == EFI_BUFFER_TOO_SMALL) {
524 PackageListHdr = AllocateZeroPool (Size);
525
526 if (PackageListHeader == NULL) {
527 return EFI_OUT_OF_RESOURCES;
528 } else {
529 Status = gHiiDatabase->ExportPackageLists (
530 gHiiDatabase,
531 Handle,
532 &Size,
533 PackageListHdr
534 );
535 }
536 }
537
538 if (!EFI_ERROR (Status)) {
539 *PackageListHeader = PackageListHdr;
540 *PackageListSize = Size;
541 } else {
542 FreePool (PackageListHdr);
543 }
544
545 return Status;
546 }
547
548 /**
549
550 This function returns a list of the package handles of the
551 specified type that are currently active in the HII database. The
552 pseudo-type EFI_HII_PACKAGE_TYPE_ALL will cause all package
553 handles to be listed.
554
555 If HandleBufferLength is NULL, then ASSERT.
556 If HandleBuffer is NULL, the ASSERT.
557 If PackageType is EFI_HII_PACKAGE_TYPE_GUID and PackageGuid is
558 NULL, then ASSERT.
559 If PackageType is not EFI_HII_PACKAGE_TYPE_GUID and PackageGuid is not
560 NULL, then ASSERT.
561
562
563 @param PackageType Specifies the package type of the packages
564 to list or EFI_HII_PACKAGE_TYPE_ALL for
565 all packages to be listed.
566
567 @param PackageGuid If PackageType is
568 EFI_HII_PACKAGE_TYPE_GUID, then this is
569 the pointer to the GUID which must match
570 the Guid field of
571 EFI_HII_PACKAGE_GUID_HEADER. Otherwise, it
572 must be NULL.
573
574 @param HandleBufferLength On output, the length of the handle buffer
575 that is required for the handles found.
576
577 @param HandleBuffer On output, an array of EFI_HII_HANDLE instances returned.
578 The caller is responcible to free this pointer allocated.
579
580 @retval EFI_SUCCESS The matching handles are outputed successfully.
581 HandleBufferLength is updated with the actual length.
582 @retval EFI_OUT_OF_RESOURCES Not enough resource to complete the operation.
583 @retval EFI_NOT_FOUND No matching handle could not be found in database.
584 **/
585 EFI_STATUS
586 EFIAPI
587 HiiLibListPackageLists (
588 IN UINT8 PackageType,
589 IN CONST EFI_GUID *PackageGuid,
590 IN OUT UINTN *HandleBufferLength,
591 OUT EFI_HII_HANDLE **HandleBuffer
592 )
593 {
594 EFI_STATUS Status;
595
596 ASSERT (HandleBufferLength != NULL);
597 ASSERT (HandleBuffer != NULL);
598
599 *HandleBufferLength = 0;
600 *HandleBuffer = NULL;
601
602 if (PackageType == EFI_HII_PACKAGE_TYPE_GUID) {
603 ASSERT (PackageGuid != NULL);
604 } else {
605 ASSERT (PackageGuid == NULL);
606 }
607
608 Status = gHiiDatabase->ListPackageLists (
609 gHiiDatabase,
610 PackageType,
611 PackageGuid,
612 HandleBufferLength,
613 *HandleBuffer
614 );
615 if (EFI_ERROR (Status) && (Status != EFI_BUFFER_TOO_SMALL)) {
616 //
617 // No packages is registered to UEFI HII Database, just return.
618 //
619 //
620 return Status;
621 }
622
623 *HandleBuffer = AllocateZeroPool (*HandleBufferLength);
624
625 if (*HandleBuffer == NULL) {
626 return EFI_OUT_OF_RESOURCES;
627 }
628
629 return gHiiDatabase->ListPackageLists (
630 gHiiDatabase,
631 PackageType,
632 PackageGuid,
633 HandleBufferLength,
634 *HandleBuffer
635 );
636
637 }
638 /**
639 This function check if the Hii Handle is a valid handle registered
640 in the HII database.
641
642 @param HiiHandle The HII Handle.
643
644 @retval TRUE If it is a valid HII handle.
645 @retval FALSE If it is a invalid HII handle.
646 **/
647 BOOLEAN
648 IsHiiHandleRegistered (
649 EFI_HII_HANDLE HiiHandle
650 )
651 {
652 EFI_STATUS Status;
653 UINTN BufferSize;
654 EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;
655
656 ASSERT (HiiHandle != NULL);
657
658 HiiPackageList = NULL;
659 BufferSize = 0;
660
661 Status = gHiiDatabase->ExportPackageLists (
662 gHiiDatabase,
663 HiiHandle,
664 &BufferSize,
665 HiiPackageList
666 );
667
668 return (BOOLEAN) (Status == EFI_BUFFER_TOO_SMALL);
669 }
670
671
672 /**
673 Converts all hex dtring characters in range ['A'..'F'] to ['a'..'f'] for
674 hex digits that appear between a '=' and a '&' in a config string.
675
676 If String is NULL, then ASSERT().
677
678 @param[in] String Pointer to a Null-terminated Unicode string.
679
680 @return Pointer to the Null-terminated Unicode result string.
681
682 **/
683 EFI_STRING
684 EFIAPI
685 InternalHiiLowerConfigString (
686 IN EFI_STRING ConfigString
687 )
688 {
689 EFI_STRING String;
690 BOOLEAN Lower;
691
692 ASSERT (ConfigString != NULL);
693
694 //
695 // Convert all hex digits in range [A-F] in the configuration header to [a-f]
696 //
697 for (String = ConfigString, Lower = FALSE; *String != L'\0'; String++) {
698 if (*String == L'=') {
699 Lower = TRUE;
700 } else if (*String == L'&') {
701 Lower = FALSE;
702 } else if (Lower && *String > L'A' && *String <= L'F') {
703 *String = (CHAR16) (*String - L'A' + L'a');
704 }
705 }
706
707 return ConfigString;
708 }
709
710 /**
711 Uses the BlockToConfig() service of the Config Routing Protocol to
712 convert <ConfigRequest> and a buffer to a <ConfigResp>
713
714 If ConfigRequest is NULL, then ASSERT().
715 If Block is NULL, then ASSERT().
716
717 @param[in] ConfigRequest Pointer to a Null-terminated Unicode string.
718 @param[in] Block Pointer to a block of data.
719 @param[in] BlockSize The zie, in bytes, of Block.
720
721 @retval NULL The <ConfigResp> string could not be generated.
722 @retval Other Pointer to the Null-terminated Unicode <ConfigResp> string.
723
724 **/
725 EFI_STRING
726 EFIAPI
727 InternalHiiBlockToConfig (
728 IN CONST EFI_STRING ConfigRequest,
729 IN CONST UINT8 *Block,
730 IN UINTN BlockSize
731 )
732 {
733 EFI_STATUS Status;
734 EFI_STRING ConfigResp;
735 CHAR16 *Progress;
736
737 ASSERT (ConfigRequest != NULL);
738 ASSERT (Block != NULL);
739
740 //
741 // Convert <ConfigRequest> to <ConfigResp>
742 //
743 Status = gHiiConfigRouting->BlockToConfig (
744 gHiiConfigRouting,
745 ConfigRequest,
746 Block,
747 BlockSize,
748 &ConfigResp,
749 &Progress
750 );
751 if (EFI_ERROR (Status)) {
752 return NULL;
753 }
754 return ConfigResp;
755 }
756
757 /**
758 Uses the ConfigToBlock() service of the Config Routing Protocol to
759 convert <ConfigResp> to a block. The block is allocated using
760 AllocatePool(). The caller is responsible for freeing the block
761 using FreePool().
762
763 If ConfigResp is NULL, then ASSERT().
764
765 @param[in] ConfigResp Pointer to a Null-terminated Unicode string.
766 @param[in] BufferSize Length in bytes of buffer to hold retrived data.
767
768 @retval NULL The block could not be generated..
769 @retval Other Pointer to the allocated block.
770
771 **/
772 UINT8 *
773 EFIAPI
774 InternalHiiConfigToBlock (
775 IN EFI_STRING ConfigResp,
776 IN UINTN BlockSize
777 )
778 {
779 EFI_STATUS Status;
780 CHAR16 *Progress;
781 UINT8 *Block;
782
783 ASSERT (ConfigResp != NULL);
784
785 //
786 // Allocate a buffer to hold the <ConfigResp> conversion
787 //
788 Block = AllocateZeroPool (BlockSize);
789 if (Block == NULL) {
790 return NULL;
791 }
792
793 //
794 // Convert <ConfigResp> to a buffer
795 //
796 Status = gHiiConfigRouting->ConfigToBlock (
797 gHiiConfigRouting,
798 ConfigResp,
799 Block,
800 &BlockSize,
801 &Progress
802 );
803 if (EFI_ERROR (Status)) {
804 FreePool (Block);
805 return NULL;
806 }
807
808 //
809 // Return converted buffer
810 //
811 return Block;
812 }
813
814 /**
815 Uses the BrowserCallback() service of the Form Browser Protocol to retrieve
816 or set uncommitted data. If sata i being retrieved, then the buffer is
817 allocated using AllocatePool(). The caller is then responsible for freeing
818 the buffer using FreePool().
819
820 @param[in] VariableName Pointer to a Null-terminated Unicode string. This
821 is an optional parameter that may be NULL.
822 @param[in] VariableGuid Pointer to an EFI_GUID structure. This is an optional
823 parameter that may be NULL.
824 @param[in] SetResultsData If not NULL, then this parameter specified the buffer
825 of uncommited data to set. If this parameter is NULL,
826 then the caller is requesting to get the uncommited data
827 from the Form Browser.
828
829 @retval NULL The uncommitted data could not be retrieved.
830 @retval Other A pointer to a buffer containing the uncommitted data.
831
832 **/
833 EFI_STRING
834 EFIAPI
835 InternalHiiBrowserCallback (
836 IN CONST EFI_GUID *VariableGuid, OPTIONAL
837 IN CONST CHAR16 *VariableName, OPTIONAL
838 IN CONST EFI_STRING SetResultsData OPTIONAL
839 )
840 {
841 EFI_STATUS Status;
842 UINTN ResultsDataSize;
843 EFI_STRING ResultsData;
844 CHAR16 TempResultsData;
845
846 //
847 // Locate protocols
848 //
849 if (mUefiFormBrowser2 == NULL) {
850 Status = gBS->LocateProtocol (&gEfiFormBrowser2ProtocolGuid, NULL, (VOID **) &mUefiFormBrowser2);
851 if (EFI_ERROR (Status) || mUefiFormBrowser2 == NULL) {
852 return NULL;
853 }
854 }
855
856 ResultsDataSize = 0;
857
858 if (SetResultsData != NULL) {
859 //
860 // Request to to set data in the uncommitted browser state information
861 //
862 ResultsData = SetResultsData;
863 } else {
864 //
865 // Retrieve the length of the buffer required ResultsData from the Browser Callback
866 //
867 Status = mUefiFormBrowser2->BrowserCallback (
868 mUefiFormBrowser2,
869 &ResultsDataSize,
870 &TempResultsData,
871 TRUE,
872 VariableGuid,
873 VariableName
874 );
875 if (Status != EFI_BUFFER_TOO_SMALL) {
876 return NULL;
877 }
878
879 //
880 // Allocate the ResultsData buffer
881 //
882 ResultsData = AllocateZeroPool (ResultsDataSize);
883 if (ResultsData == NULL) {
884 return NULL;
885 }
886 }
887
888 //
889 // Retrieve or set the ResultsData from the Browser Callback
890 //
891 Status = mUefiFormBrowser2->BrowserCallback (
892 mUefiFormBrowser2,
893 &ResultsDataSize,
894 ResultsData,
895 (BOOLEAN)(SetResultsData == NULL),
896 VariableGuid,
897 VariableName
898 );
899 if (EFI_ERROR (Status)) {
900 return NULL;
901 }
902
903 return ResultsData;
904 }
905
906 /**
907 Allocates and returns a Null-terminated Unicode <ConfigHdr> string using routing
908 information that includes a GUID, an optional Unicode string name, and a device
909 path. The string returned is allocated with AllocatePool(). The caller is
910 responsible for freeing the allocated string with FreePool().
911
912 The format of a <ConfigHdr> is as follows:
913
914 GUID=<HexCh>32&NAME=<Char>NameLength&PATH=<HexChar>DevicePathSize<Null>
915
916 @param[in] Guid Pointer to an EFI_GUID that is the routing information
917 GUID. Each of the 16 bytes in Guid is converted to
918 a 2 Unicode character hexidecimal string. This is
919 an optional parameter that may be NULL.
920 @param[in] Name Pointer to a Null-terminated Unicode string that is
921 the routing information NAME. This is an optional
922 parameter that may be NULL. Each 16-bit Unicode
923 character in Name is converted to a 4 character Unicode
924 hexidecimal string.
925 @param[in] DriverHandle The driver handle which supports a Device Path Protocol
926 that is the routing information PATH. Each byte of
927 the Device Path associated with DriverHandle is converted
928 to a 2 Unicode character hexidecimal string.
929
930 @retval NULL DriverHandle does not support the Device Path Protocol.
931 @retval NULL DriverHandle does not support the Device Path Protocol.
932 @retval Other A pointer to the Null-terminate Unicode <ConfigHdr> string
933
934 **/
935 EFI_STRING
936 EFIAPI
937 HiiConstructConfigHdr (
938 IN CONST EFI_GUID *Guid, OPTIONAL
939 IN CONST CHAR16 *Name, OPTIONAL
940 IN EFI_HANDLE DriverHandle
941 )
942 {
943 UINTN NameLength;
944 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
945 UINTN DevicePathSize;
946 CHAR16 *String;
947 CHAR16 *ReturnString;
948 UINTN Index;
949 UINT8 *Buffer;
950
951 //
952 // Compute the length of Name in Unicode characters.
953 // If Name is NULL, then the length is 0.
954 //
955 NameLength = 0;
956 if (Name != NULL) {
957 NameLength = StrLen (Name);
958 }
959
960 //
961 // Retrieve DevicePath Protocol associated with DriverHandle
962 //
963 DevicePath = DevicePathFromHandle (DriverHandle);
964 if (DevicePath == NULL) {
965 return NULL;
966 }
967
968 //
969 // Compute the size of the device path in bytes
970 //
971 DevicePathSize = GetDevicePathSize (DevicePath);
972
973 //
974 // GUID=<HexCh>32&NAME=<Char>NameLength&PATH=<HexChar>DevicePathSize <Null>
975 // | 5 | sizeof (EFI_GUID) * 2 | 6 | NameStrLen*4 | 6 | DevicePathSize * 2 | 1 |
976 //
977 String = AllocateZeroPool ((5 + sizeof (EFI_GUID) * 2 + 6 + NameLength * 4 + 6 + DevicePathSize * 2 + 1) * sizeof (CHAR16));
978 if (String == NULL) {
979 return NULL;
980 }
981
982 //
983 // Start with L"GUID="
984 //
985 ReturnString = StrCpy (String, L"GUID=");
986 String += StrLen (String);
987
988 if (Guid != NULL) {
989 //
990 // Append Guid converted to <HexCh>32
991 //
992 for (Index = 0, Buffer = (UINT8 *)Guid; Index < sizeof (EFI_GUID); Index++) {
993 String += UnicodeValueToString (String, PREFIX_ZERO | RADIX_HEX, *(Buffer++), 2);
994 }
995 }
996
997 //
998 // Append L"&NAME="
999 //
1000 StrCpy (String, L"&NAME=");
1001 String += StrLen (String);
1002
1003 if (Name != NULL) {
1004 //
1005 // Append Name converted to <Char>NameLength
1006 //
1007 for (; *Name != L'\0'; Name++) {
1008 String += UnicodeValueToString (String, PREFIX_ZERO | RADIX_HEX, *Name, 4);
1009 }
1010 }
1011
1012 //
1013 // Append L"&PATH="
1014 //
1015 StrCpy (String, L"&PATH=");
1016 String += StrLen (String);
1017
1018 //
1019 // Append the device path associated with DriverHandle converted to <HexChar>DevicePathSize
1020 //
1021 for (Index = 0, Buffer = (UINT8 *)DevicePath; Index < DevicePathSize; Index++) {
1022 String += UnicodeValueToString (String, PREFIX_ZERO | RADIX_HEX, *(Buffer++), 2);
1023 }
1024
1025 //
1026 // Null terminate the Unicode string
1027 //
1028 *String = L'\0';
1029
1030 //
1031 // Convert all hex digits in range [A-F] in the configuration header to [a-f]
1032 //
1033 return InternalHiiLowerConfigString (ReturnString);
1034 }
1035
1036 /**
1037 Allocates and returns a Null-terminated Unicode <ConfigAltResp> string.
1038
1039 If Guid is NULL, then ASSERT().
1040 If Name is NULL, then ASSERT().
1041 If BlockNameArray is NULL, then ASSERT().
1042
1043 @param[in] Guid GUID of the buffer storage.
1044 @param[in] Name Name of the buffer storage.
1045 @param[in] DriverHandle The DriverHandle that support a Device Path
1046 Protocol.
1047 @param[in] BufferStorage Content of the buffer storage.
1048 @param[in] BufferStorageSize Length in bytes of the buffer storage.
1049 @param[in] BlockNameArray Array generated by VFR compiler. This array
1050 contains a UINT32 value that is the length
1051 of BlockNameArray in bytes, followed by pairs
1052 of 16-bit values that are the offset and length
1053 values used to contruct a <ConfigRequest> string.
1054 @param[in] ... A variable argument list that contains pairs of 16-bit
1055 ALTCFG identifiers and pointers to DefaultValueArrays.
1056 The variable argument list is terminated by a NULL
1057 DefaultValueArray pointer. A DefaultValueArray
1058 contains a UINT32 value that is the length, in bytes,
1059 of the DefaultValueArray. The UINT32 length value
1060 is followed by a series of records that contain
1061 a 16-bit WIDTH value followed by a byte array with
1062 WIDTH entries. The records must be parsed from
1063 beginning to end until the UINT32 length limit
1064 is reached.
1065
1066 @retval NULL There are not enough resources to process the request.
1067 @retval NULL A <ConfigResp> could not be retrieved from the Config
1068 Routing Protocol.
1069 @retval Other A pointer to the Null-terminate Unicode <ConfigAltResp>
1070 string.
1071
1072 **/
1073 EFI_STRING
1074 EFIAPI
1075 HiiConstructConfigAltResp (
1076 IN CONST EFI_GUID *Guid,
1077 IN CONST CHAR16 *Name,
1078 IN EFI_HANDLE DriverHandle,
1079 IN CONST VOID *BufferStorage,
1080 IN UINTN BufferStorageSize,
1081 IN CONST VOID *BlockNameArray,
1082 ...
1083 )
1084 {
1085 UINTN Length;
1086 CHAR16 *String;
1087 CHAR16 *ConfigHdr;
1088 UINT8 *Buffer;
1089 UINT8 *BufferEnd;
1090 CHAR16 *ConfigRequest;
1091 EFI_STRING ConfigResp;
1092 EFI_STRING ConfigAltResp;
1093 VA_LIST Args;
1094 UINTN AltCfgId;
1095 UINT16 Width;
1096 UINT16 OffsetValue;
1097 UINT16 WidthValue;
1098
1099 ASSERT (Guid != NULL);
1100 ASSERT (Name != NULL);
1101 ASSERT (BlockNameArray != NULL);
1102
1103 //
1104 // Initialize local variables
1105 //
1106 ConfigHdr = NULL;
1107 ConfigRequest = NULL;
1108 ConfigResp = NULL;
1109
1110 //
1111 // Construct <ConfigHdr> : "GUID=...&NAME=...&PATH=..."
1112 //
1113 ConfigHdr = HiiConstructConfigHdr (Guid, Name, DriverHandle);
1114 if (ConfigHdr == NULL) {
1115 goto Exit;
1116 }
1117
1118 //
1119 // Compute the length of the entire request starting with <ConfigHdr> and a
1120 // Null-terminator
1121 //
1122 Length = StrLen (ConfigHdr) + 1;
1123
1124 //
1125 // Determine the size <BlockName> Offset/Width pairs
1126 //
1127 Buffer = (UINT8 *)BlockNameArray;
1128 BufferEnd = Buffer + ReadUnaligned32 ((UINT32 *)Buffer);
1129 Buffer += sizeof (UINT32);
1130
1131 //
1132 // Add <BlockName> length that is composed of one or more Offset/Width pairs
1133 //
1134 // <BlockName> ::= &OFFSET=1234&WIDTH=1234
1135 // | 8 | 4 | 7 | 4 |
1136 //
1137 Length += (((BufferEnd - Buffer) / (sizeof (UINT16) + sizeof (UINT16))) * (8 + 4 + 7 + 4));
1138
1139 //
1140 // Allocate buffer for the entire <ConfigRequest>
1141 //
1142 ConfigRequest = AllocateZeroPool (Length * sizeof (CHAR16));
1143 if (ConfigRequest == NULL) {
1144 goto Exit;
1145 }
1146 String = ConfigRequest;
1147
1148 //
1149 // Start with <ConfigHdr>
1150 //
1151 StrCpy (String, ConfigHdr);
1152 String += StrLen (String);
1153
1154 //
1155 // Loop through all the Offset/Width pairs and append them to ConfigRequest
1156 //
1157 while (Buffer < BufferEnd) {
1158 //
1159 // Append &OFFSET=XXXX&WIDTH=YYYY
1160 //
1161 OffsetValue = ReadUnaligned16 ((UINT16 *)Buffer);
1162 WidthValue = ReadUnaligned16 ((UINT16 *)(Buffer + sizeof (UINT16)));
1163 UnicodeSPrint (
1164 String,
1165 (8 + 4 + 7 + 4) * sizeof (CHAR16),
1166 L"&OFFSET=%04X&WIDTH=%04X",
1167 OffsetValue,
1168 WidthValue
1169 );
1170
1171 String += StrLen (String);
1172 Buffer += (sizeof (UINT16) + sizeof (UINT16));
1173 }
1174
1175 //
1176 // Get the <ConfigResp>
1177 //
1178 ConfigResp = InternalHiiBlockToConfig (ConfigRequest, BufferStorage, BufferStorageSize);
1179 if (ConfigResp == NULL) {
1180 goto Exit;
1181 }
1182
1183 //
1184 // Compute the length of the entire response starting with <ConfigResp> and a
1185 // Null-terminator
1186 //
1187 Length = StrLen (ConfigResp) + 1;
1188
1189 //
1190 // Add the length associated with each pair of variable argument parameters
1191 //
1192 VA_START (Args, BlockNameArray);
1193 while (TRUE) {
1194 AltCfgId = VA_ARG (Args, UINT16);
1195 Buffer = VA_ARG (Args, UINT8 *);
1196 if (Buffer == NULL) {
1197 break;
1198 }
1199
1200 //
1201 // Add length for "&<ConfigHdr>&ALTCFG=XXXX"
1202 // |1| StrLen (ConfigHdr) | 8 | 4 |
1203 //
1204 Length += (1 + StrLen (ConfigHdr) + 8 + 4);
1205
1206 BufferEnd = Buffer + ReadUnaligned32 ((UINT32 *)Buffer);
1207 Buffer += sizeof (UINT32);
1208 while (Buffer < BufferEnd) {
1209 //
1210 // Extract Width field
1211 //
1212 Width = ReadUnaligned16 ((UINT16 *)(Buffer + sizeof (UINT16)));
1213
1214 //
1215 // Add length for "&OFFSET=XXXX&WIDTH=YYYY&VALUE=zzzzzzzzzzzz"
1216 // | 8 | 4 | 7 | 4 | 7 | Width * 2 |
1217 //
1218 Length += (8 + 4 + 7 + 4 + 7 + Width * 2);
1219
1220 //
1221 // Update Buffer to the next record
1222 //
1223 Buffer += (sizeof (UINT16) + sizeof (UINT16) + Width);
1224 }
1225 }
1226 VA_END (Args);
1227
1228 //
1229 // Allocate a buffer for the entire response
1230 //
1231 ConfigAltResp = AllocateZeroPool (Length * sizeof (CHAR16));
1232 if (ConfigAltResp == NULL) {
1233 goto Exit;
1234 }
1235 String = ConfigAltResp;
1236
1237 //
1238 // Add <ConfigResp>
1239 //
1240 StrCpy (String, ConfigResp);
1241 String += StrLen (String);
1242
1243 //
1244 // Add <AltResp> for each pair of variable argument parameters
1245 //
1246 VA_START (Args, BlockNameArray);
1247 while (TRUE) {
1248 AltCfgId = VA_ARG (Args, UINT16);
1249 Buffer = VA_ARG (Args, UINT8 *);
1250 if (Buffer == NULL) {
1251 break;
1252 }
1253
1254 //
1255 // Add <AltConfigHdr> of the form "&<ConfigHdr>&ALTCFG=XXXX"
1256 // |1| StrLen (ConfigHdr) | 8 | 4 |
1257 //
1258 UnicodeSPrint (
1259 String,
1260 (1 + StrLen (ConfigHdr) + 8 + 4) * sizeof (CHAR16),
1261 L"&%s&ALTCFG=%04X",
1262 ConfigHdr,
1263 AltCfgId
1264 );
1265 String += StrLen (String);
1266
1267 //
1268 // Add <ConfigBody> ::= <ConfigElement>*
1269 //
1270 BufferEnd = Buffer + ReadUnaligned32 ((UINT32 *)Buffer);
1271 Buffer += sizeof (UINT32);
1272 while (Buffer < BufferEnd) {
1273 //
1274 // Extract Width field
1275 //
1276 Width = ReadUnaligned16 ((UINT16 *)(Buffer + sizeof (UINT16)));
1277
1278 //
1279 // Add <BlockConfig>
1280 //
1281 UnicodeSPrint (
1282 String,
1283 (8 + 4 + 7 + 4 + 7 + Width * 2) * sizeof (CHAR16),
1284 L"&OFFSET=%04X&WIDTH=%04X&VALUE=",
1285 ReadUnaligned16 ((UINT16 *)Buffer),
1286 Width
1287 );
1288 String += StrLen (String);
1289
1290 //
1291 // Update Buffer to point to the value in the current record
1292 //
1293 Buffer += (sizeof (UINT16) + sizeof (UINT16));
1294
1295 //
1296 // Convert Value to a hex string in "%x" format
1297 // NOTE: This is in the opposite byte that GUID and PATH use
1298 //
1299 for (; Width > 0; Width--) {
1300 String += UnicodeValueToString (String, PREFIX_ZERO | RADIX_HEX, Buffer[Width - 1], 2);
1301 }
1302 //
1303 // Update Buffer to the next record
1304 //
1305 Buffer += Width;
1306 }
1307 }
1308 VA_END (Args);
1309
1310 //
1311 // Convert all hex digits in range [A-F] in the configuration header to [a-f]
1312 //
1313 return InternalHiiLowerConfigString (ConfigAltResp);
1314
1315 Exit:
1316 if (ConfigHdr != NULL) {
1317 FreePool (ConfigHdr);
1318 }
1319 if (ConfigRequest != NULL) {
1320 FreePool (ConfigRequest);
1321 }
1322 if (ConfigResp != NULL) {
1323 FreePool (ConfigResp);
1324 }
1325
1326 return NULL;
1327 }
1328
1329 /**
1330 Determines if two values in config strings match.
1331
1332 Compares the substring between StartSearchString and StopSearchString in
1333 FirstString to the substring between StartSearchString and StopSearchString
1334 in SecondString. If the two substrings match, then TRUE is returned. If the
1335 two substrings do not match, then FALSE is returned.
1336
1337 If FirstString is NULL, then ASSERT().
1338 If SecondString is NULL, then ASSERT().
1339 If StartSearchString is NULL, then ASSERT().
1340 If StopSearchString is NULL, then ASSERT().
1341
1342 @param FirstString Pointer to the first Null-terminated Unicode string.
1343 @param SecondString Pointer to the second Null-terminated Unicode string.
1344 @param StartSearchString Pointer to the Null-terminated Unicode string that
1345 marks the start of the value string to compare.
1346 @param StopSearchString Pointer to the Null-terminated Unicode string that
1347 marks the end of the vakue string to compare.
1348
1349 @retval FALSE StartSearchString is not present in FirstString.
1350 @retval FALSE StartSearchString is not present in SecondString.
1351 @retval FALSE StopSearchString is not present in FirstString.
1352 @retval FALSE StopSearchString is not present in SecondString.
1353 @retval FALSE The length of the substring in FirstString is not the
1354 same length as the substring in SecondString.
1355 @retval FALSE The value string in FirstString does not matche the
1356 value string in SecondString.
1357 @retval TRUE The value string in FirstString matches the value
1358 string in SecondString.
1359
1360 **/
1361 BOOLEAN
1362 EFIAPI
1363 InternalHiiCompareSubString (
1364 IN CHAR16 *FirstString,
1365 IN CHAR16 *SecondString,
1366 IN CHAR16 *StartSearchString,
1367 IN CHAR16 *StopSearchString
1368 )
1369 {
1370 CHAR16 *EndFirstString;
1371 CHAR16 *EndSecondString;
1372
1373 ASSERT (FirstString != NULL);
1374 ASSERT (SecondString != NULL);
1375 ASSERT (StartSearchString != NULL);
1376 ASSERT (StopSearchString != NULL);
1377
1378 FirstString = StrStr (FirstString, StartSearchString);
1379 if (FirstString == NULL) {
1380 return FALSE;
1381 }
1382
1383 SecondString = StrStr (SecondString, StartSearchString);
1384 if (SecondString == NULL) {
1385 return FALSE;
1386 }
1387
1388 EndFirstString = StrStr (FirstString, StopSearchString);
1389 if (EndFirstString == NULL) {
1390 return FALSE;
1391 }
1392
1393 EndSecondString = StrStr (SecondString, StopSearchString);
1394 if (EndSecondString == NULL) {
1395 return FALSE;
1396 }
1397
1398 if ((EndFirstString - FirstString) != (EndSecondString - SecondString)) {
1399 return FALSE;
1400 }
1401
1402 return (BOOLEAN)(StrnCmp (FirstString, SecondString, EndFirstString - FirstString) == 0);
1403 }
1404
1405 /**
1406 Determines if the routing data specified by GUID and NAME match a <ConfigHdr>.
1407
1408 If ConfigHdr is NULL, then ASSERT().
1409
1410 @param[in] ConfigHdr Either <ConfigRequest> or <ConfigResp>.
1411 @param[in] Guid GUID of the storage.
1412 @param[in] Name NAME of the storage.
1413
1414 @retval TRUE Routing information matches <ConfigHdr>.
1415 @retval FALSE Routing information does not match <ConfigHdr>.
1416
1417 **/
1418 BOOLEAN
1419 EFIAPI
1420 HiiIsConfigHdrMatch (
1421 IN CONST EFI_STRING ConfigHdr,
1422 IN CONST EFI_GUID *Guid, OPTIONAL
1423 IN CONST CHAR16 *Name OPTIONAL
1424 )
1425 {
1426 EFI_STRING CompareConfigHdr;
1427 BOOLEAN Result;
1428
1429 ASSERT (ConfigHdr != NULL);
1430
1431 //
1432 // Use Guid and Name to generate a <ConfigHdr> string
1433 //
1434 CompareConfigHdr = HiiConstructConfigHdr (Guid, Name, NULL);
1435 if (CompareConfigHdr == NULL) {
1436 return FALSE;
1437 }
1438
1439 Result = TRUE;
1440 if (Guid != NULL) {
1441 //
1442 // Compare GUID value strings
1443 //
1444 Result = InternalHiiCompareSubString (ConfigHdr, CompareConfigHdr, L"GUID=", L"&NAME=");
1445 }
1446
1447 if (Result && Name != NULL) {
1448 //
1449 // Compare NAME value strings
1450 //
1451 Result = InternalHiiCompareSubString (ConfigHdr, CompareConfigHdr, L"&NAME=", L"&PATH=");
1452 }
1453
1454 //
1455 // Free the <ConfigHdr> string
1456 //
1457 FreePool (CompareConfigHdr);
1458
1459 return Result;
1460 }
1461
1462 /**
1463 Retrieves uncommited data from the Form Browser and converts it to a binary
1464 buffer. The returned buffer is allocated using AllocatePool(). The caller
1465 is responsible for freeing the returned buffer using FreePool().
1466
1467 @param[in] VariableName Pointer to a Null-terminated Unicode string. This
1468 is an optional parameter that may be NULL.
1469 @param[in] VariableGuid Pointer to an EFI_GUID structure. This is an optional
1470 parameter that may be NULL.
1471 @param[in] BufferSize Length in bytes of buffer to hold retrived data.
1472
1473 @retval NULL The uncommitted data could not be retrieved.
1474 @retval Other A pointer to a buffer containing the uncommitted data.
1475
1476 **/
1477 UINT8 *
1478 EFIAPI
1479 HiiGetBrowserData (
1480 IN CONST EFI_GUID *VariableGuid, OPTIONAL
1481 IN CONST CHAR16 *VariableName, OPTIONAL
1482 IN UINTN BlockSize
1483 )
1484 {
1485 EFI_STRING ResultsData;
1486 UINTN Size;
1487 EFI_STRING ConfigResp;
1488 UINT8 *Block;
1489
1490 //
1491 // Retrieve the results data from the Browser Callback
1492 //
1493 ResultsData = InternalHiiBrowserCallback (VariableGuid, VariableName, NULL);
1494 if (ResultsData == NULL) {
1495 return NULL;
1496 }
1497
1498 //
1499 // Construct <ConfigResp> mConfigHdrTemplate L'&' ResultsData L'\0'
1500 //
1501 Size = (StrLen (mConfigHdrTemplate) + 1) * sizeof (CHAR16);
1502 Size = Size + (StrLen (ResultsData) + 1) * sizeof (CHAR16);
1503 ConfigResp = AllocateZeroPool (Size);
1504 UnicodeSPrint (ConfigResp, Size, L"%s&%s", mConfigHdrTemplate, ResultsData);
1505
1506 //
1507 // Free the allocated buffer
1508 //
1509 FreePool (ResultsData);
1510 if (ConfigResp == NULL) {
1511 return NULL;
1512 }
1513
1514 //
1515 // Convert <ConfigResp> to a buffer
1516 //
1517 Block = InternalHiiConfigToBlock (ConfigResp, BlockSize);
1518 FreePool (ConfigResp);
1519
1520 return Block;
1521 }
1522
1523 /**
1524 Updates uncommitted data in the Form Browser.
1525
1526 If Buffer is NULL, then ASSERT().
1527
1528 @param[in] VariableName Pointer to a Null-terminated Unicode string. This
1529 is an optional parameter that may be NULL.
1530 @param[in] VariableGuid Pointer to an EFI_GUID structure. This is an optional
1531 parameter that may be NULL.
1532 @param[in] BufferSize Length, in bytes, of Buffer.
1533 @param[in] Buffer Buffer of data to commit.
1534 @param[in] RequestElement An optional field to specify which part of the
1535 buffer data will be send back to Browser. If NULL,
1536 the whole buffer of data will be committed to
1537 Browser.
1538 <RequestElement> ::= &OFFSET=<Number>&WIDTH=<Number>*
1539
1540 @retval FALSE The uncommitted data could not be updated.
1541 @retval TRUE The uncommitted data was updated.
1542
1543 **/
1544 BOOLEAN
1545 EFIAPI
1546 HiiSetBrowserData (
1547 IN CONST EFI_GUID *VariableGuid, OPTIONAL
1548 IN CONST CHAR16 *VariableName, OPTIONAL
1549 IN UINTN BufferSize,
1550 IN CONST UINT8 *Buffer,
1551 IN CONST CHAR16 *RequestElement OPTIONAL
1552 )
1553 {
1554 UINTN Size;
1555 EFI_STRING ConfigRequest;
1556 EFI_STRING ConfigResp;
1557 EFI_STRING ResultsData;
1558
1559 ASSERT (Buffer != NULL);
1560
1561 //
1562 // Construct <ConfigRequest>
1563 //
1564 if (RequestElement == NULL) {
1565 //
1566 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
1567 // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
1568 //
1569 Size = (StrLen (mConfigHdrTemplate) + 32 + 1) * sizeof (CHAR16);
1570 ConfigRequest = AllocateZeroPool (Size);
1571 UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", mConfigHdrTemplate, (UINT64)BufferSize);
1572 } else {
1573 //
1574 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
1575 // followed by <RequestElement> followed by a Null-terminator
1576 //
1577 Size = StrLen (mConfigHdrTemplate) * sizeof (CHAR16);
1578 Size = Size + (StrLen (RequestElement) + 1) * sizeof (CHAR16);
1579 ConfigRequest = AllocateZeroPool (Size);
1580 UnicodeSPrint (ConfigRequest, Size, L"%s%s", mConfigHdrTemplate, RequestElement);
1581 }
1582 if (ConfigRequest == NULL) {
1583 return FALSE;
1584 }
1585
1586 //
1587 // Convert <ConfigRequest> to <ConfigResp>
1588 //
1589 ConfigResp = InternalHiiBlockToConfig (ConfigRequest, Buffer, BufferSize);
1590 FreePool (ConfigRequest);
1591 if (ConfigResp == NULL) {
1592 return FALSE;
1593 }
1594
1595 //
1596 // Set data in the uncommitted browser state information
1597 //
1598 ResultsData = InternalHiiBrowserCallback (VariableGuid, VariableName, ConfigResp + StrLen(mConfigHdrTemplate) + 1);
1599 FreePool (ConfigResp);
1600
1601 return (BOOLEAN)(ResultsData != NULL);
1602 }
1603
1604 /////////////////////////////////////////
1605 /////////////////////////////////////////
1606 /// IFR Functions
1607 /////////////////////////////////////////
1608 /////////////////////////////////////////
1609
1610 #define HII_LIB_OPCODE_ALLOCATION_SIZE 0x200
1611
1612 typedef struct {
1613 UINT8 *Buffer;
1614 UINTN BufferSize;
1615 UINTN Position;
1616 } HII_LIB_OPCODE_BUFFER;
1617
1618 ///
1619 /// Lookup table that converts EFI_IFR_TYPE_X enum values to a width in bytes
1620 ///
1621 GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 mHiiDefaultTypeToWidth[] = {
1622 1, // EFI_IFR_TYPE_NUM_SIZE_8
1623 2, // EFI_IFR_TYPE_NUM_SIZE_16
1624 4, // EFI_IFR_TYPE_NUM_SIZE_32
1625 8, // EFI_IFR_TYPE_NUM_SIZE_64
1626 1, // EFI_IFR_TYPE_BOOLEAN
1627 3, // EFI_IFR_TYPE_TIME
1628 4, // EFI_IFR_TYPE_DATE
1629 2 // EFI_IFR_TYPE_STRING
1630 };
1631
1632 /**
1633 Allocates and returns a new OpCode Handle. OpCode Handles must be freed with
1634 HiiFreeOpCodeHandle().
1635
1636 @retval NULL There are not enough resources to allocate a new OpCode Handle.
1637 @retval Other A new OpCode handle.
1638
1639 **/
1640 VOID *
1641 EFIAPI
1642 HiiAllocateOpCodeHandle (
1643 VOID
1644 )
1645 {
1646 HII_LIB_OPCODE_BUFFER *OpCodeBuffer;
1647
1648 OpCodeBuffer = (HII_LIB_OPCODE_BUFFER *)AllocatePool (sizeof (HII_LIB_OPCODE_BUFFER));
1649 if (OpCodeBuffer == NULL) {
1650 return NULL;
1651 }
1652 OpCodeBuffer->Buffer = (UINT8 *)AllocatePool (HII_LIB_OPCODE_ALLOCATION_SIZE);
1653 if (OpCodeBuffer->Buffer == NULL) {
1654 FreePool (OpCodeBuffer);
1655 return NULL;
1656 }
1657 OpCodeBuffer->BufferSize = HII_LIB_OPCODE_ALLOCATION_SIZE;
1658 OpCodeBuffer->Position = 0;
1659 return (VOID *)OpCodeBuffer;
1660 }
1661
1662 /**
1663 Frees an OpCode Handle that was peviously allocated with HiiAllocateOpCodeHandle().
1664 When an OpCode Handle is freed, all of the opcodes associated with the OpCode
1665 Handle are also freed.
1666
1667 If OpCodeHandle is NULL, then ASSERT().
1668
1669 **/
1670 VOID
1671 EFIAPI
1672 HiiFreeOpCodeHandle (
1673 VOID *OpCodeHandle
1674 )
1675 {
1676 HII_LIB_OPCODE_BUFFER *OpCodeBuffer;
1677
1678 ASSERT (OpCodeHandle != NULL);
1679
1680 OpCodeBuffer = (HII_LIB_OPCODE_BUFFER *)OpCodeHandle;
1681 if (OpCodeBuffer->Buffer != NULL) {
1682 FreePool (OpCodeBuffer->Buffer);
1683 }
1684 FreePool (OpCodeBuffer);
1685 }
1686
1687 UINTN
1688 EFIAPI
1689 InternalHiiOpCodeHandlePosition (
1690 IN VOID *OpCodeHandle
1691 )
1692 {
1693 return ((HII_LIB_OPCODE_BUFFER *)OpCodeHandle)->Position;
1694 }
1695
1696 UINT8 *
1697 EFIAPI
1698 InternalHiiOpCodeHandleBuffer (
1699 IN VOID *OpCodeHandle
1700 )
1701 {
1702 return ((HII_LIB_OPCODE_BUFFER *)OpCodeHandle)->Buffer;
1703 }
1704
1705 UINT8 *
1706 EFIAPI
1707 InternalHiiGrowOpCodeHandle (
1708 VOID *OpCodeHandle,
1709 UINTN Size
1710 )
1711 {
1712 HII_LIB_OPCODE_BUFFER *OpCodeBuffer;
1713 UINT8 *Buffer;
1714
1715 ASSERT (OpCodeHandle != NULL);
1716
1717 OpCodeBuffer = (HII_LIB_OPCODE_BUFFER *)OpCodeHandle;
1718 if (OpCodeBuffer->Position + Size > OpCodeBuffer->BufferSize) {
1719 Buffer = ReallocatePool (
1720 OpCodeBuffer->BufferSize,
1721 OpCodeBuffer->BufferSize + (Size + HII_LIB_OPCODE_ALLOCATION_SIZE),
1722 OpCodeBuffer->Buffer
1723 );
1724 if (Buffer == NULL) {
1725 return NULL;
1726 }
1727 OpCodeBuffer->Buffer = Buffer;
1728 OpCodeBuffer->BufferSize += (Size + HII_LIB_OPCODE_ALLOCATION_SIZE);
1729 }
1730 Buffer = OpCodeBuffer->Buffer + OpCodeBuffer->Position;
1731 OpCodeBuffer->Position += Size;
1732 return Buffer;
1733 }
1734
1735 UINT8 *
1736 EFIAPI
1737 InternalHiiCreateOpCodeExtended (
1738 IN VOID *OpCodeHandle,
1739 IN VOID *OpCodeTemplate,
1740 IN UINT8 OpCode,
1741 IN UINTN OpCodeSize,
1742 IN UINTN ExtensionSize,
1743 IN UINT8 Scope
1744 )
1745 {
1746 EFI_IFR_OP_HEADER *Header;
1747 UINT8 *Buffer;
1748
1749 ASSERT (OpCodeTemplate != NULL);
1750 ASSERT ((OpCodeSize + ExtensionSize) <= 0x7F);
1751
1752 Header = (EFI_IFR_OP_HEADER *)OpCodeTemplate;
1753 Header->OpCode = OpCode;
1754 Header->Scope = Scope;
1755 Header->Length = (UINT8)(OpCodeSize + ExtensionSize);
1756 Buffer = InternalHiiGrowOpCodeHandle (OpCodeHandle, Header->Length);
1757 return (UINT8 *)CopyMem (Buffer, Header, OpCodeSize);
1758 }
1759
1760 UINT8 *
1761 EFIAPI
1762 InternalHiiCreateOpCode (
1763 IN VOID *OpCodeHandle,
1764 IN VOID *OpCodeTemplate,
1765 IN UINT8 OpCode,
1766 IN UINTN OpCodeSize
1767 )
1768 {
1769 return InternalHiiCreateOpCodeExtended (OpCodeHandle, OpCodeTemplate, OpCode, OpCodeSize, 0, 0);
1770 }
1771
1772 /**
1773 Append raw opcodes to an OpCodeHandle.
1774
1775 If OpCodeHandle is NULL, then ASSERT().
1776 If RawBuffer is NULL, then ASSERT();
1777
1778 @param[in] OpCodeHandle Handle to the buffer of opcodes.
1779 @param[in] RawBuffer Buffer of opcodes to append.
1780 @param[in] RawBufferSize The size, in bytes, of Buffer.
1781
1782 @retval NULL There is not enough space left in Buffer to add the opcode.
1783 @retval Other A pointer to the appended opcodes.
1784
1785 **/
1786 UINT8 *
1787 EFIAPI
1788 InternalHiiCreateRawOpCodes (
1789 IN VOID *OpCodeHandle,
1790 IN UINT8 *RawBuffer,
1791 IN UINTN RawBufferSize
1792 )
1793 {
1794 UINT8 *Buffer;
1795
1796 ASSERT (RawBuffer != NULL);
1797
1798 Buffer = InternalHiiGrowOpCodeHandle (OpCodeHandle, RawBufferSize);
1799 return (UINT8 *)CopyMem (Buffer, RawBuffer, RawBufferSize);
1800 }
1801
1802 /**
1803 Append opcodes from one OpCode Handle to another OpCode handle.
1804
1805 If OpCodeHandle is NULL, then ASSERT().
1806 If RawOpCodeHandle is NULL, then ASSERT();
1807
1808 @param[in] OpCodeHandle Handle to the buffer of opcodes.
1809 @param[in] RawOpCodeHandle Handle to the buffer of opcodes.
1810
1811 @retval NULL There is not enough space left in Buffer to add the opcode.
1812 @retval Other A pointer to the appended opcodes.
1813
1814 **/
1815 UINT8 *
1816 EFIAPI
1817 InternalHiiAppendOpCodes (
1818 IN VOID *OpCodeHandle,
1819 IN VOID *RawOpCodeHandle
1820 )
1821 {
1822 HII_LIB_OPCODE_BUFFER *RawOpCodeBuffer;
1823
1824 ASSERT (RawOpCodeHandle != NULL);
1825
1826 RawOpCodeBuffer = (HII_LIB_OPCODE_BUFFER *)RawOpCodeHandle;
1827 return InternalHiiCreateRawOpCodes (OpCodeHandle, RawOpCodeBuffer->Buffer, RawOpCodeBuffer->Position);
1828 }
1829
1830 /**
1831 Create EFI_IFR_END_OP opcode.
1832
1833 If OpCodeHandle is NULL, then ASSERT().
1834
1835 @param[in] OpCodeHandle Handle to the buffer of opcodes.
1836
1837 @retval NULL There is not enough space left in Buffer to add the opcode.
1838 @retval Other A pointer to the created opcode.
1839
1840 **/
1841 UINT8 *
1842 EFIAPI
1843 HiiCreateEndOpCode (
1844 IN VOID *OpCodeHandle
1845 )
1846 {
1847 EFI_IFR_END OpCode;
1848
1849 return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_END_OP, sizeof (OpCode));
1850 }
1851
1852 /**
1853 Create EFI_IFR_ONE_OF_OPTION_OP opcode.
1854
1855 If OpCodeHandle is NULL, then ASSERT().
1856 If Type is invalid, then ASSERT().
1857 If Flags is invalid, then ASSERT().
1858
1859 @param[in] OpCodeHandle Handle to the buffer of opcodes.
1860 @param[in] StringId StringId for the option
1861 @param[in] Flags Flags for the option
1862 @param[in] Type Type for the option
1863 @param[in] Value Value for the option
1864
1865 @retval NULL There is not enough space left in Buffer to add the opcode.
1866 @retval Other A pointer to the created opcode.
1867
1868 **/
1869 UINT8 *
1870 EFIAPI
1871 HiiCreateOneOfOptionOpCode (
1872 IN VOID *OpCodeHandle,
1873 IN UINT16 StringId,
1874 IN UINT8 Flags,
1875 IN UINT8 Type,
1876 IN UINT64 Value
1877 )
1878 {
1879 EFI_IFR_ONE_OF_OPTION OpCode;
1880
1881 ASSERT (Type < EFI_IFR_TYPE_OTHER);
1882
1883 ZeroMem (&OpCode, sizeof (OpCode));
1884 OpCode.Option = StringId;
1885 OpCode.Flags = (UINT8) (Flags & (EFI_IFR_OPTION_DEFAULT | EFI_IFR_OPTION_DEFAULT_MFG));
1886 OpCode.Type = Type;
1887 CopyMem (&OpCode.Value, &Value, mHiiDefaultTypeToWidth[Type]);
1888
1889 return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_ONE_OF_OPTION_OP, sizeof (OpCode));
1890 }
1891
1892 /**
1893 Create EFI_IFR_DEFAULT_OP opcode.
1894
1895 If OpCodeHandle is NULL, then ASSERT().
1896 If Type is invalid, then ASSERT().
1897
1898 @param[in] OpCodeHandle Handle to the buffer of opcodes.
1899 @param[in] DefaultId DefaultId for the default
1900 @param[in] Type Type for the default
1901 @param[in] Value Value for the default
1902
1903 @retval NULL There is not enough space left in Buffer to add the opcode.
1904 @retval Other A pointer to the created opcode.
1905
1906 **/
1907 UINT8 *
1908 EFIAPI
1909 HiiCreateDefaultOpCode (
1910 IN VOID *OpCodeHandle,
1911 IN UINT16 DefaultId,
1912 IN UINT8 Type,
1913 IN UINT64 Value
1914 )
1915 {
1916 EFI_IFR_DEFAULT OpCode;
1917
1918 ASSERT (Type < EFI_IFR_TYPE_OTHER);
1919
1920 ZeroMem (&OpCode, sizeof (OpCode));
1921 OpCode.Type = Type;
1922 OpCode.DefaultId = DefaultId;
1923 CopyMem (&OpCode.Value, &Value, mHiiDefaultTypeToWidth[Type]);
1924
1925 return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_DEFAULT_OP, sizeof (OpCode));
1926 }
1927
1928 /**
1929 Create EFI_IFR_GUID opcode.
1930
1931 If OpCodeHandle is NULL, then ASSERT().
1932 If Guid is NULL, then ASSERT().
1933 If OpCodeSize < sizeof (EFI_IFR_GUID), then ASSERT().
1934
1935 @param[in] OpCodeHandle Handle to the buffer of opcodes.
1936 @param[in] Guid Pointer to EFI_GUID of this guided opcode.
1937 @param[in] GuidOpCode Pointer to an EFI_IFR_GUID opcode. This is an
1938 optional parameter that may be NULL. If this
1939 parameter is NULL, then the GUID extension
1940 region of the created opcode is filled with zeros.
1941 If this parameter is not NULL, then the GUID
1942 extension region of GuidData will be copied to
1943 the GUID extension region of the created opcode.
1944 @param[in] OpCodeSize The size, in bytes, of created opcode. This value
1945 must be >= sizeof(EFI_IFR_GUID).
1946
1947 @retval NULL There is not enough space left in Buffer to add the opcode.
1948 @retval Other A pointer to the created opcode.
1949
1950 **/
1951 UINT8 *
1952 EFIAPI
1953 HiiCreateGuidOpCode (
1954 IN VOID *OpCodeHandle,
1955 IN CONST EFI_GUID *Guid,
1956 IN CONST VOID *GuidOpCode, OPTIONAL
1957 IN UINTN OpCodeSize
1958 )
1959 {
1960 EFI_IFR_GUID OpCode;
1961 EFI_IFR_GUID *OpCodePointer;
1962
1963 ASSERT (Guid != NULL);
1964 ASSERT (OpCodeSize >= sizeof (OpCode));
1965
1966 ZeroMem (&OpCode, sizeof (OpCode));
1967 CopyGuid ((EFI_GUID *)(VOID *)&OpCode.Guid, Guid);
1968
1969 OpCodePointer = (EFI_IFR_GUID *)InternalHiiCreateOpCodeExtended (
1970 OpCodeHandle,
1971 &OpCode,
1972 EFI_IFR_GUID_OP,
1973 sizeof (OpCode),
1974 OpCodeSize - sizeof (OpCode),
1975 0
1976 );
1977 if (OpCodePointer != NULL && GuidOpCode != NULL) {
1978 CopyMem (OpCodePointer + 1, (EFI_IFR_GUID *)GuidOpCode + 1, OpCodeSize - sizeof (OpCode));
1979 }
1980 return (UINT8 *)OpCodePointer;
1981 }
1982
1983 /**
1984 Create EFI_IFR_ACTION_OP opcode.
1985
1986 If OpCodeHandle is NULL, then ASSERT().
1987 If any reserved bits are set in QuestionFlags, then ASSERT().
1988
1989 @param[in] OpCodeHandle Handle to the buffer of opcodes.
1990 @param[in] QuestionId Question ID
1991 @param[in] Prompt String ID for Prompt
1992 @param[in] Help String ID for Help
1993 @param[in] QuestionFlags Flags in Question Header
1994 @param[in] QuestionConfig String ID for configuration
1995
1996 @retval NULL There is not enough space left in Buffer to add the opcode.
1997 @retval Other A pointer to the created opcode.
1998
1999 **/
2000 UINT8 *
2001 EFIAPI
2002 HiiCreateActionOpCode (
2003 IN VOID *OpCodeHandle,
2004 IN EFI_QUESTION_ID QuestionId,
2005 IN EFI_STRING_ID Prompt,
2006 IN EFI_STRING_ID Help,
2007 IN UINT8 QuestionFlags,
2008 IN EFI_STRING_ID QuestionConfig
2009 )
2010 {
2011 EFI_IFR_ACTION OpCode;
2012
2013 ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED | EFI_IFR_FLAG_OPTIONS_ONLY))) == 0);
2014
2015 ZeroMem (&OpCode, sizeof (OpCode));
2016 OpCode.Question.QuestionId = QuestionId;
2017 OpCode.Question.Header.Prompt = Prompt;
2018 OpCode.Question.Header.Help = Help;
2019 OpCode.Question.Flags = QuestionFlags;
2020 OpCode.QuestionConfig = QuestionConfig;
2021
2022 return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_ACTION_OP, sizeof (OpCode));
2023 }
2024
2025 /**
2026 Create EFI_IFR_SUBTITLE_OP opcode.
2027
2028 If OpCodeHandle is NULL, then ASSERT().
2029 If any reserved bits are set in Flags, then ASSERT().
2030 If Scope > 1, then ASSERT().
2031
2032 @param[in] OpCodeHandle Handle to the buffer of opcodes.
2033 @param[in] Prompt String ID for Prompt
2034 @param[in] Help String ID for Help
2035 @param[in] Flags Subtitle opcode flags
2036 @param[in] Scope 1 if this opcpde is the beginning of a new scope.
2037 0 if this opcode is within the current scope.
2038
2039 @retval NULL There is not enough space left in Buffer to add the opcode.
2040 @retval Other A pointer to the created opcode.
2041
2042 **/
2043 UINT8 *
2044 EFIAPI
2045 HiiCreateSubTitleOpCode (
2046 IN VOID *OpCodeHandle,
2047 IN EFI_STRING_ID Prompt,
2048 IN EFI_STRING_ID Help,
2049 IN UINT8 Flags,
2050 IN UINT8 Scope
2051 )
2052 {
2053 EFI_IFR_SUBTITLE OpCode;
2054
2055 ASSERT (Scope <= 1);
2056 ASSERT ((Flags & (~(EFI_IFR_FLAGS_HORIZONTAL))) == 0);
2057
2058 ZeroMem (&OpCode, sizeof (OpCode));
2059 OpCode.Statement.Prompt = Prompt;
2060 OpCode.Statement.Help = Help;
2061 OpCode.Flags = Flags;
2062
2063 return InternalHiiCreateOpCodeExtended (
2064 OpCodeHandle,
2065 &OpCode,
2066 EFI_IFR_SUBTITLE_OP,
2067 sizeof (OpCode),
2068 0,
2069 Scope
2070 );
2071 }
2072
2073 /**
2074 Create EFI_IFR_REF_OP opcode.
2075
2076 If OpCodeHandle is NULL, then ASSERT().
2077 If any reserved bits are set in QuestionFlags, then ASSERT().
2078
2079 @param[in] OpCodeHandle Handle to the buffer of opcodes.
2080 @param[in] FormId Destination Form ID
2081 @param[in] Prompt String ID for Prompt
2082 @param[in] Help String ID for Help
2083 @param[in] QuestionFlags Flags in Question Header
2084 @param[in] QuestionId Question ID
2085
2086 @retval NULL There is not enough space left in Buffer to add the opcode.
2087 @retval Other A pointer to the created opcode.
2088
2089 **/
2090 UINT8 *
2091 EFIAPI
2092 HiiCreateGotoOpCode (
2093 IN VOID *OpCodeHandle,
2094 IN EFI_FORM_ID FormId,
2095 IN EFI_STRING_ID Prompt,
2096 IN EFI_STRING_ID Help,
2097 IN UINT8 QuestionFlags,
2098 IN EFI_QUESTION_ID QuestionId
2099 )
2100 {
2101 EFI_IFR_REF OpCode;
2102
2103 ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED | EFI_IFR_FLAG_OPTIONS_ONLY))) == 0);
2104
2105 ZeroMem (&OpCode, sizeof (OpCode));
2106 OpCode.Question.Header.Prompt = Prompt;
2107 OpCode.Question.Header.Help = Help;
2108 OpCode.Question.QuestionId = QuestionId;
2109 OpCode.Question.Flags = QuestionFlags;
2110 OpCode.FormId = FormId;
2111
2112 return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_REF_OP, sizeof (OpCode));
2113 }
2114
2115 /**
2116 Create EFI_IFR_CHECKBOX_OP opcode.
2117
2118 If OpCodeHandle is NULL, then ASSERT().
2119 If any reserved bits are set in QuestionFlags, then ASSERT().
2120 If any reserved bits are set in CheckBoxFlags, then ASSERT().
2121
2122 @param[in] OpCodeHandle Handle to the buffer of opcodes.
2123 @param[in] QuestionId Question ID
2124 @param[in] VarStoreId Storage ID
2125 @param[in] VarOffset Offset in Storage
2126 @param[in] Prompt String ID for Prompt
2127 @param[in] Help String ID for Help
2128 @param[in] QuestionFlags Flags in Question Header
2129 @param[in] CheckBoxFlags Flags for checkbox opcode
2130 @param[in] DefaultsOpCodeHandle Handle for a buffer of DEFAULT opcodes. This
2131 is an optional parameter that may be NULL.
2132
2133 @retval NULL There is not enough space left in Buffer to add the opcode.
2134 @retval Other A pointer to the created opcode.
2135
2136 **/
2137 UINT8 *
2138 EFIAPI
2139 HiiCreateCheckBoxOpCode (
2140 IN VOID *OpCodeHandle,
2141 IN EFI_QUESTION_ID QuestionId,
2142 IN EFI_VARSTORE_ID VarStoreId,
2143 IN UINT16 VarOffset,
2144 IN EFI_STRING_ID Prompt,
2145 IN EFI_STRING_ID Help,
2146 IN UINT8 QuestionFlags,
2147 IN UINT8 CheckBoxFlags,
2148 IN VOID *DefaultsOpCodeHandle OPTIONAL
2149 )
2150 {
2151 EFI_IFR_CHECKBOX OpCode;
2152 UINTN Position;
2153
2154 ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED | EFI_IFR_FLAG_OPTIONS_ONLY))) == 0);
2155
2156 ZeroMem (&OpCode, sizeof (OpCode));
2157 OpCode.Question.QuestionId = QuestionId;
2158 OpCode.Question.VarStoreId = VarStoreId;
2159 OpCode.Question.VarStoreInfo.VarOffset = VarOffset;
2160 OpCode.Question.Header.Prompt = Prompt;
2161 OpCode.Question.Header.Help = Help;
2162 OpCode.Question.Flags = QuestionFlags;
2163 OpCode.Flags = CheckBoxFlags;
2164
2165 if (DefaultsOpCodeHandle == NULL) {
2166 return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_CHECKBOX_OP, sizeof (OpCode));
2167 }
2168
2169 Position = InternalHiiOpCodeHandlePosition (OpCodeHandle);
2170 InternalHiiCreateOpCodeExtended (OpCodeHandle, &OpCode, EFI_IFR_CHECKBOX_OP, sizeof (OpCode), 0, 1);
2171 InternalHiiAppendOpCodes (OpCodeHandle, DefaultsOpCodeHandle);
2172 HiiCreateEndOpCode (OpCodeHandle);
2173 return InternalHiiOpCodeHandleBuffer (OpCodeHandle) + Position;
2174 }
2175
2176 /**
2177 Create EFI_IFR_NUMERIC_OP opcode.
2178
2179 If OpCodeHandle is NULL, then ASSERT().
2180 If any reserved bits are set in QuestionFlags, then ASSERT().
2181 If any reserved bits are set in NumericFlags, then ASSERT().
2182
2183 @param[in] OpCodeHandle Handle to the buffer of opcodes.
2184 @param[in] QuestionId Question ID
2185 @param[in] VarStoreId Storage ID
2186 @param[in] VarOffset Offset in Storage
2187 @param[in] Prompt String ID for Prompt
2188 @param[in] Help String ID for Help
2189 @param[in] QuestionFlags Flags in Question Header
2190 @param[in] NumericFlags Flags for numeric opcode
2191 @param[in] Minimum Numeric minimum value
2192 @param[in] Maximum Numeric maximum value
2193 @param[in] Step Numeric step for edit
2194 @param[in] DefaultsOpCodeHandle Handle for a buffer of DEFAULT opcodes. This
2195 is an optional parameter that may be NULL.
2196
2197 @retval NULL There is not enough space left in Buffer to add the opcode.
2198 @retval Other A pointer to the created opcode.
2199
2200 **/
2201 UINT8 *
2202 EFIAPI
2203 HiiCreateNumericOpCode (
2204 IN VOID *OpCodeHandle,
2205 IN EFI_QUESTION_ID QuestionId,
2206 IN EFI_VARSTORE_ID VarStoreId,
2207 IN UINT16 VarOffset,
2208 IN EFI_STRING_ID Prompt,
2209 IN EFI_STRING_ID Help,
2210 IN UINT8 QuestionFlags,
2211 IN UINT8 NumericFlags,
2212 IN UINT64 Minimum,
2213 IN UINT64 Maximum,
2214 IN UINT64 Step,
2215 IN VOID *DefaultsOpCodeHandle OPTIONAL
2216 )
2217 {
2218 EFI_IFR_NUMERIC OpCode;
2219 UINTN Position;
2220
2221 ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED | EFI_IFR_FLAG_OPTIONS_ONLY))) == 0);
2222
2223 ZeroMem (&OpCode, sizeof (OpCode));
2224 OpCode.Question.QuestionId = QuestionId;
2225 OpCode.Question.VarStoreId = VarStoreId;
2226 OpCode.Question.VarStoreInfo.VarOffset = VarOffset;
2227 OpCode.Question.Header.Prompt = Prompt;
2228 OpCode.Question.Header.Help = Help;
2229 OpCode.Question.Flags = QuestionFlags;
2230 OpCode.Flags = NumericFlags;
2231
2232 switch (NumericFlags & EFI_IFR_NUMERIC_SIZE) {
2233 case EFI_IFR_NUMERIC_SIZE_1:
2234 OpCode.data.u8.MinValue = (UINT8)Minimum;
2235 OpCode.data.u8.MaxValue = (UINT8)Maximum;
2236 OpCode.data.u8.Step = (UINT8)Step;
2237 break;
2238
2239 case EFI_IFR_NUMERIC_SIZE_2:
2240 OpCode.data.u16.MinValue = (UINT16)Minimum;
2241 OpCode.data.u16.MaxValue = (UINT16)Maximum;
2242 OpCode.data.u16.Step = (UINT16)Step;
2243 break;
2244
2245 case EFI_IFR_NUMERIC_SIZE_4:
2246 OpCode.data.u32.MinValue = (UINT32)Minimum;
2247 OpCode.data.u32.MaxValue = (UINT32)Maximum;
2248 OpCode.data.u32.Step = (UINT32)Step;
2249 break;
2250
2251 case EFI_IFR_NUMERIC_SIZE_8:
2252 OpCode.data.u64.MinValue = Minimum;
2253 OpCode.data.u64.MaxValue = Maximum;
2254 OpCode.data.u64.Step = Step;
2255 break;
2256 }
2257
2258 if (DefaultsOpCodeHandle == NULL) {
2259 return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_NUMERIC_OP, sizeof (OpCode));
2260 }
2261
2262 Position = InternalHiiOpCodeHandlePosition (OpCodeHandle);
2263 InternalHiiCreateOpCodeExtended (OpCodeHandle, &OpCode, EFI_IFR_NUMERIC_OP, sizeof (OpCode), 0, 1);
2264 InternalHiiAppendOpCodes (OpCodeHandle, DefaultsOpCodeHandle);
2265 HiiCreateEndOpCode (OpCodeHandle);
2266 return InternalHiiOpCodeHandleBuffer (OpCodeHandle) + Position;
2267 }
2268
2269 /**
2270 Create EFI_IFR_STRING_OP opcode.
2271
2272 If OpCodeHandle is NULL, then ASSERT().
2273 If any reserved bits are set in QuestionFlags, then ASSERT().
2274 If any reserved bits are set in StringFlags, then ASSERT().
2275
2276 @param[in] OpCodeHandle Handle to the buffer of opcodes.
2277 @param[in] QuestionId Question ID
2278 @param[in] VarStoreId Storage ID
2279 @param[in] VarOffset Offset in Storage
2280 @param[in] Prompt String ID for Prompt
2281 @param[in] Help String ID for Help
2282 @param[in] QuestionFlags Flags in Question Header
2283 @param[in] StringFlags Flags for string opcode
2284 @param[in] MinSize String minimum length
2285 @param[in] MaxSize String maximum length
2286 @param[in] DefaultsOpCodeHandle Handle for a buffer of DEFAULT opcodes. This
2287 is an optional parameter that may be NULL.
2288
2289 @retval NULL There is not enough space left in Buffer to add the opcode.
2290 @retval Other A pointer to the created opcode.
2291
2292 **/
2293 UINT8 *
2294 EFIAPI
2295 HiiCreateStringOpCode (
2296 IN VOID *OpCodeHandle,
2297 IN EFI_QUESTION_ID QuestionId,
2298 IN EFI_VARSTORE_ID VarStoreId,
2299 IN UINT16 VarOffset,
2300 IN EFI_STRING_ID Prompt,
2301 IN EFI_STRING_ID Help,
2302 IN UINT8 QuestionFlags,
2303 IN UINT8 StringFlags,
2304 IN UINT8 MinSize,
2305 IN UINT8 MaxSize,
2306 IN VOID *DefaultsOpCodeHandle OPTIONAL
2307 )
2308 {
2309 EFI_IFR_STRING OpCode;
2310 UINTN Position;
2311
2312 ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED | EFI_IFR_FLAG_OPTIONS_ONLY))) == 0);
2313
2314 ZeroMem (&OpCode, sizeof (OpCode));
2315 OpCode.Question.Header.Prompt = Prompt;
2316 OpCode.Question.Header.Help = Help;
2317 OpCode.Question.QuestionId = QuestionId;
2318 OpCode.Question.VarStoreId = VarStoreId;
2319 OpCode.Question.VarStoreInfo.VarOffset = VarOffset;
2320 OpCode.Question.Flags = QuestionFlags;
2321 OpCode.MinSize = MinSize;
2322 OpCode.MaxSize = MaxSize;
2323 OpCode.Flags = (UINT8) (StringFlags & EFI_IFR_STRING_MULTI_LINE);
2324
2325 if (DefaultsOpCodeHandle == NULL) {
2326 return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_STRING_OP, sizeof (OpCode));
2327 }
2328
2329 Position = InternalHiiOpCodeHandlePosition (OpCodeHandle);
2330 InternalHiiCreateOpCodeExtended (OpCodeHandle, &OpCode, EFI_IFR_STRING_OP, sizeof (OpCode), 0, 1);
2331 InternalHiiAppendOpCodes (OpCodeHandle, DefaultsOpCodeHandle);
2332 HiiCreateEndOpCode (OpCodeHandle);
2333 return InternalHiiOpCodeHandleBuffer (OpCodeHandle) + Position;
2334 }
2335
2336 /**
2337 Create EFI_IFR_ONE_OF_OP opcode.
2338
2339 If OpCodeHandle is NULL, then ASSERT().
2340 If any reserved bits are set in QuestionFlags, then ASSERT().
2341 If any reserved bits are set in OneOfFlags, then ASSERT().
2342
2343 @param[in] OpCodeHandle Handle to the buffer of opcodes.
2344 @param[in] QuestionId Question ID
2345 @param[in] VarStoreId Storage ID
2346 @param[in] VarOffset Offset in Storage
2347 @param[in] Prompt String ID for Prompt
2348 @param[in] Help String ID for Help
2349 @param[in] QuestionFlags Flags in Question Header
2350 @param[in] OneOfFlags Flags for oneof opcode
2351 @param[in] OptionsOpCodeHandle Handle for a buffer of ONE_OF_OPTION opcodes.
2352 @param[in] DefaultsOpCodeHandle Handle for a buffer of DEFAULT opcodes. This
2353 is an optional parameter that may be NULL.
2354
2355 @retval NULL There is not enough space left in Buffer to add the opcode.
2356 @retval Other A pointer to the created opcode.
2357
2358 **/
2359 UINT8 *
2360 EFIAPI
2361 HiiCreateOneOfOpCode (
2362 IN VOID *OpCodeHandle,
2363 IN EFI_QUESTION_ID QuestionId,
2364 IN EFI_VARSTORE_ID VarStoreId,
2365 IN UINT16 VarOffset,
2366 IN EFI_STRING_ID Prompt,
2367 IN EFI_STRING_ID Help,
2368 IN UINT8 QuestionFlags,
2369 IN UINT8 OneOfFlags,
2370 IN VOID *OptionsOpCodeHandle,
2371 IN VOID *DefaultsOpCodeHandle OPTIONAL
2372 )
2373 {
2374 EFI_IFR_ONE_OF OpCode;
2375 UINTN Position;
2376
2377 ASSERT (OptionsOpCodeHandle != NULL);
2378 ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED | EFI_IFR_FLAG_OPTIONS_ONLY))) == 0);
2379
2380 ZeroMem (&OpCode, sizeof (OpCode));
2381 OpCode.Question.Header.Prompt = Prompt;
2382 OpCode.Question.Header.Help = Help;
2383 OpCode.Question.QuestionId = QuestionId;
2384 OpCode.Question.VarStoreId = VarStoreId;
2385 OpCode.Question.VarStoreInfo.VarOffset = VarOffset;
2386 OpCode.Question.Flags = QuestionFlags;
2387 OpCode.Flags = OneOfFlags;
2388
2389 Position = InternalHiiOpCodeHandlePosition (OpCodeHandle);
2390 InternalHiiCreateOpCodeExtended (OpCodeHandle, &OpCode, EFI_IFR_ONE_OF_OP, sizeof (OpCode), 0, 1);
2391 InternalHiiAppendOpCodes (OpCodeHandle, OptionsOpCodeHandle);
2392 if (DefaultsOpCodeHandle != NULL) {
2393 InternalHiiAppendOpCodes (OpCodeHandle, DefaultsOpCodeHandle);
2394 }
2395 HiiCreateEndOpCode (OpCodeHandle);
2396 return InternalHiiOpCodeHandleBuffer (OpCodeHandle) + Position;
2397 }
2398
2399 /**
2400 Create EFI_IFR_ORDERED_LIST_OP opcode.
2401
2402 If OpCodeHandle is NULL, then ASSERT().
2403 If any reserved bits are set in QuestionFlags, then ASSERT().
2404 If any reserved bits are set in OrderedListFlags, then ASSERT().
2405
2406 @param[in] OpCodeHandle Handle to the buffer of opcodes.
2407 @param[in] QuestionId Question ID
2408 @param[in] VarStoreId Storage ID
2409 @param[in] VarOffset Offset in Storage
2410 @param[in] Prompt String ID for Prompt
2411 @param[in] Help String ID for Help
2412 @param[in] QuestionFlags Flags in Question Header
2413 @param[in] OrderedListFlags Flags for ordered list opcode
2414 @param[in] DataType Type for option value
2415 @param[in] MaxContainers Maximum count for options in this ordered list
2416 @param[in] OptionsOpCodeHandle Handle for a buffer of ONE_OF_OPTION opcodes.
2417 @param[in] DefaultsOpCodeHandle Handle for a buffer of DEFAULT opcodes. This
2418 is an optional parameter that may be NULL.
2419
2420 @retval NULL There is not enough space left in Buffer to add the opcode.
2421 @retval Other A pointer to the created opcode.
2422
2423 **/
2424 UINT8 *
2425 EFIAPI
2426 HiiCreateOrderedListOpCode (
2427 IN VOID *OpCodeHandle,
2428 IN EFI_QUESTION_ID QuestionId,
2429 IN EFI_VARSTORE_ID VarStoreId,
2430 IN UINT16 VarOffset,
2431 IN EFI_STRING_ID Prompt,
2432 IN EFI_STRING_ID Help,
2433 IN UINT8 QuestionFlags,
2434 IN UINT8 OrderedListFlags,
2435 IN UINT8 DataType,
2436 IN UINT8 MaxContainers,
2437 IN VOID *OptionsOpCodeHandle,
2438 IN VOID *DefaultsOpCodeHandle OPTIONAL
2439 )
2440 {
2441 EFI_IFR_ORDERED_LIST OpCode;
2442 UINTN Position;
2443
2444 ASSERT (OptionsOpCodeHandle != NULL);
2445 ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED | EFI_IFR_FLAG_OPTIONS_ONLY))) == 0);
2446
2447 ZeroMem (&OpCode, sizeof (OpCode));
2448 OpCode.Question.Header.Prompt = Prompt;
2449 OpCode.Question.Header.Help = Help;
2450 OpCode.Question.QuestionId = QuestionId;
2451 OpCode.Question.VarStoreId = VarStoreId;
2452 OpCode.Question.VarStoreInfo.VarOffset = VarOffset;
2453 OpCode.Question.Flags = QuestionFlags;
2454 OpCode.MaxContainers = MaxContainers;
2455 OpCode.Flags = OrderedListFlags;
2456
2457 Position = InternalHiiOpCodeHandlePosition (OpCodeHandle);
2458 InternalHiiCreateOpCodeExtended (OpCodeHandle, &OpCode, EFI_IFR_ORDERED_LIST_OP, sizeof (OpCode), 0, 1);
2459 InternalHiiAppendOpCodes (OpCodeHandle, OptionsOpCodeHandle);
2460 if (DefaultsOpCodeHandle != NULL) {
2461 InternalHiiAppendOpCodes (OpCodeHandle, DefaultsOpCodeHandle);
2462 }
2463 HiiCreateEndOpCode (OpCodeHandle);
2464 return InternalHiiOpCodeHandleBuffer (OpCodeHandle) + Position;
2465 }
2466
2467 /**
2468 This is the internal worker function to update the data in
2469 a form specified by FormSetGuid, FormId and Label.
2470
2471 @param FormSetGuid The optional Formset GUID.
2472 @param FormId The Form ID.
2473 @param Package The package header.
2474
2475 @param TempPacakge The resultant package.
2476
2477 @retval EFI_SUCCESS The function completes successfully.
2478
2479 **/
2480 EFI_STATUS
2481 EFIAPI
2482 InternalHiiUpdateFormPackageData (
2483 IN EFI_GUID *FormSetGuid, OPTIONAL
2484 IN EFI_FORM_ID FormId,
2485 IN EFI_HII_PACKAGE_HEADER *Package,
2486 IN HII_LIB_OPCODE_BUFFER *OpCodeBufferStart,
2487 IN HII_LIB_OPCODE_BUFFER *OpCodeBufferEnd, OPTIONAL
2488 OUT EFI_HII_PACKAGE_HEADER *TempPackage
2489 )
2490 {
2491 UINTN AddSize;
2492 UINT8 *BufferPos;
2493 EFI_HII_PACKAGE_HEADER PackageHeader;
2494 UINTN Offset;
2495 EFI_IFR_OP_HEADER *IfrOpHdr;
2496 EFI_IFR_OP_HEADER *UpdateIfrOpHdr;
2497 BOOLEAN GetFormSet;
2498 BOOLEAN GetForm;
2499 BOOLEAN Updated;
2500 EFI_IFR_OP_HEADER *AddOpCode;
2501 UINT32 UpdatePackageLength;
2502
2503 CopyMem (TempPackage, Package, sizeof (EFI_HII_PACKAGE_HEADER));
2504 UpdatePackageLength = sizeof (EFI_HII_PACKAGE_HEADER);
2505 BufferPos = (UINT8 *) (TempPackage + 1);
2506
2507 CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));
2508 IfrOpHdr = (EFI_IFR_OP_HEADER *)((UINT8 *) Package + sizeof (EFI_HII_PACKAGE_HEADER));
2509 Offset = sizeof (EFI_HII_PACKAGE_HEADER);
2510 GetFormSet = (BOOLEAN) ((FormSetGuid == NULL) ? TRUE : FALSE);
2511 GetForm = FALSE;
2512 Updated = FALSE;
2513
2514 while (Offset < PackageHeader.Length) {
2515 CopyMem (BufferPos, IfrOpHdr, IfrOpHdr->Length);
2516 BufferPos += IfrOpHdr->Length;
2517 UpdatePackageLength += IfrOpHdr->Length;
2518
2519 //
2520 // Find the matched FormSet and Form
2521 //
2522 if ((IfrOpHdr->OpCode == EFI_IFR_FORM_SET_OP) && (FormSetGuid != NULL)) {
2523 if (CompareGuid((GUID *)(VOID *)&((EFI_IFR_FORM_SET *) IfrOpHdr)->Guid, FormSetGuid)) {
2524 GetFormSet = TRUE;
2525 } else {
2526 GetFormSet = FALSE;
2527 }
2528 } else if (IfrOpHdr->OpCode == EFI_IFR_FORM_OP) {
2529 if (CompareMem (&((EFI_IFR_FORM *) IfrOpHdr)->FormId, &FormId, sizeof (EFI_FORM_ID)) == 0) {
2530 GetForm = TRUE;
2531 } else {
2532 GetForm = FALSE;
2533 }
2534 }
2535
2536 //
2537 // The matched Form is found, and Update data in this form
2538 //
2539 if (GetFormSet && GetForm && !Updated) {
2540 UpdateIfrOpHdr = (EFI_IFR_OP_HEADER *) OpCodeBufferStart->Buffer;
2541 if ((UpdateIfrOpHdr->Length == IfrOpHdr->Length) && \
2542 (CompareMem (IfrOpHdr, UpdateIfrOpHdr, UpdateIfrOpHdr->Length) == 0)) {
2543 //
2544 // Remove the original data when End OpCode buffer exist.
2545 //
2546 if (OpCodeBufferEnd != NULL) {
2547 Offset += IfrOpHdr->Length;
2548 IfrOpHdr = (EFI_IFR_OP_HEADER *) ((UINT8 *) (IfrOpHdr) + IfrOpHdr->Length);
2549 UpdateIfrOpHdr = (EFI_IFR_OP_HEADER *) OpCodeBufferEnd->Buffer;
2550 while (Offset < PackageHeader.Length) {
2551 //
2552 // Search the matched end opcode
2553 //
2554 if ((UpdateIfrOpHdr->Length == IfrOpHdr->Length) && \
2555 (CompareMem (IfrOpHdr, UpdateIfrOpHdr, UpdateIfrOpHdr->Length) == 0)) {
2556 break;
2557 }
2558 //
2559 // Go to the next Op-Code
2560 //
2561 Offset += IfrOpHdr->Length;
2562 IfrOpHdr = (EFI_IFR_OP_HEADER *) ((UINT8 *) (IfrOpHdr) + IfrOpHdr->Length);
2563 }
2564
2565 if (Offset >= PackageHeader.Length) {
2566 //
2567 // The end opcode is not found.
2568 //
2569 return EFI_NOT_FOUND;
2570 }
2571 }
2572 //
2573 // Insert the updated data
2574 //
2575 UpdateIfrOpHdr = (EFI_IFR_OP_HEADER *) OpCodeBufferStart->Buffer;
2576 AddOpCode = (EFI_IFR_OP_HEADER *) (OpCodeBufferStart->Buffer + UpdateIfrOpHdr->Length);
2577 AddSize = UpdateIfrOpHdr->Length;
2578 while (AddSize < OpCodeBufferStart->Position) {
2579 CopyMem (BufferPos, AddOpCode, AddOpCode->Length);
2580 BufferPos += AddOpCode->Length;
2581 UpdatePackageLength += AddOpCode->Length;
2582
2583 AddOpCode = (EFI_IFR_OP_HEADER *) ((UINT8 *) (AddOpCode) + AddOpCode->Length);
2584 AddSize += AddOpCode->Length;
2585 }
2586
2587 if (OpCodeBufferEnd != NULL) {
2588 //
2589 // Add the end opcode
2590 //
2591 CopyMem (BufferPos, IfrOpHdr, IfrOpHdr->Length);
2592 BufferPos += IfrOpHdr->Length;
2593 UpdatePackageLength += IfrOpHdr->Length;
2594 }
2595 //
2596 // Set update flag
2597 //
2598 Updated = TRUE;
2599 }
2600 }
2601
2602 //
2603 // Go to the next Op-Code
2604 //
2605 Offset += IfrOpHdr->Length;
2606 IfrOpHdr = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (IfrOpHdr) + IfrOpHdr->Length);
2607 }
2608
2609 if (!Updated) {
2610 //
2611 // The updated opcode buffer is not found.
2612 //
2613 return EFI_NOT_FOUND;
2614 }
2615 //
2616 // Update the package length.
2617 //
2618 PackageHeader.Length = UpdatePackageLength;
2619 CopyMem (TempPackage, &PackageHeader, sizeof (EFI_HII_PACKAGE_HEADER));
2620
2621 return EFI_SUCCESS;
2622 }
2623
2624 /**
2625 This function updates a form that has previously been registered with the HII
2626 Database. This function will perform at most one update operation.
2627
2628 The form to update is specified by Handle, FormSetGuid, and FormId. Binary
2629 comparisons of IFR opcodes are performed from the beginning of the form being
2630 updated until an IFR opcode is found that exactly matches the first IFR opcode
2631 specifed by StartOpCodeHandle. The following rules are used to determine if
2632 an insert, replace, or delete operation is performed.
2633
2634 1) If no matches are found, then NULL is returned.
2635 2) If a match is found, and EndOpCodeHandle is NULL, then all of the IFR opcodes
2636 from StartOpcodeHandle except the first opcode are inserted immediately after
2637 the matching IFR opcode in the form beng updated.
2638 3) If a match is found, and EndOpCodeHandle is not NULL, then a search is made
2639 from the matching IFR opcode until an IFR opcode exatly matches the first
2640 IFR opcode specified by EndOpCodeHandle. If no match is found for the first
2641 IFR opcode specified by EndOpCodeHandle, then NULL is returned. If a match
2642 is found, then all of the IFR opcodes between the start match and the end
2643 match are deleted from the form being updated and all of the IFR opcodes
2644 from StartOpcodeHandle except the first opcode are inserted immediately after
2645 the matching start IFR opcode. If StartOpCcodeHandle only contains one
2646 IFR instruction, then the result of ths operation will delete all of the IFR
2647 opcodes between the start end matches.
2648
2649 If HiiHandle is NULL, then ASSERT().
2650 If StartOpCodeHandle is NULL, then ASSERT().
2651
2652 @param[in] HiiHandle The HII Handle of the form to update.
2653 @param[in] FormSetGuid The Formset GUID of the form to update. This
2654 is an optional parameter that may be NULL.
2655 If it is NULL, all FormSet will be updated.
2656 @param[in] FormId The ID of the form to update.
2657 @param[in] StartOpCodeHandle An OpCode Handle that contains the set of IFR
2658 opcodes to be inserted or replaced in the form.
2659 The first IFR instruction in StartOpCodeHandle
2660 is used to find matching IFR opcode in the
2661 form.
2662 @param[in] EndOpCodeHandle An OpCcode Handle that contains the IFR opcode
2663 that marks the end of a replace operation in
2664 the form. This is an optional parameter that
2665 may be NULL. If it is NULL, then an the IFR
2666 opcodes specified by StartOpCodeHandle are
2667 inserted into the form.
2668
2669 @retval EFI_OUT_OF_RESOURCES No enough memory resource is allocated.
2670 @retval EFI_NOT_FOUND The following cases will return EFI_NOT_FOUND.
2671 1) The form specified by HiiHandle, FormSetGuid,
2672 and FormId could not be found in the HII Database.
2673 2) No IFR opcodes in the target form match the first
2674 IFR opcode in StartOpCodeHandle.
2675 3) EndOpCOde is not NULL, and no IFR opcodes in the
2676 target form following a matching start opcode match
2677 the first IFR opcode in EndOpCodeHandle.
2678 @retval EFI_SUCCESS The matched form is updated by StartOpcode.
2679
2680 **/
2681 EFI_STATUS
2682 EFIAPI
2683 HiiUpdateForm (
2684 IN EFI_HII_HANDLE HiiHandle,
2685 IN EFI_GUID *FormSetGuid, OPTIONAL
2686 IN EFI_FORM_ID FormId,
2687 IN VOID *StartOpcodeHandle,
2688 IN VOID *EndOpcodeHandle OPTIONAL
2689 )
2690 {
2691 EFI_STATUS Status;
2692 EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;
2693 UINT32 PackageListLength;
2694 UINT32 Offset;
2695 EFI_HII_PACKAGE_LIST_HEADER *UpdatePackageList;
2696 UINTN BufferSize;
2697 UINT8 *UpdateBufferPos;
2698 EFI_HII_PACKAGE_HEADER *Package;
2699 EFI_HII_PACKAGE_HEADER *TempPacakge;
2700 EFI_HII_PACKAGE_HEADER PackageHeader;
2701 BOOLEAN Updated;
2702 HII_LIB_OPCODE_BUFFER *OpCodeBufferStart;
2703 HII_LIB_OPCODE_BUFFER *OpCodeBufferEnd;
2704
2705 //
2706 // Input update data can't be NULL.
2707 //
2708 ASSERT (HiiHandle != NULL);
2709 ASSERT (StartOpcodeHandle != NULL);
2710 UpdatePackageList = NULL;
2711 TempPacakge = NULL;
2712 HiiPackageList = NULL;
2713
2714 //
2715 // Restrive buffer data from Opcode Handle
2716 //
2717 OpCodeBufferStart = (HII_LIB_OPCODE_BUFFER *) StartOpcodeHandle;
2718 OpCodeBufferEnd = (HII_LIB_OPCODE_BUFFER *) EndOpcodeHandle;
2719
2720 //
2721 // Get the orginal package list
2722 //
2723 BufferSize = 0;
2724 HiiPackageList = NULL;
2725 Status = gHiiDatabase->ExportPackageLists (gHiiDatabase, HiiHandle, &BufferSize, HiiPackageList);
2726 //
2727 // The return status should always be EFI_BUFFER_TOO_SMALL as input buffer's size is 0.
2728 //
2729 if (Status != EFI_BUFFER_TOO_SMALL) {
2730 return Status;
2731 }
2732
2733 HiiPackageList = AllocatePool (BufferSize);
2734 if (HiiPackageList == NULL) {
2735 Status = EFI_OUT_OF_RESOURCES;
2736 goto Finish;
2737 }
2738
2739 Status = gHiiDatabase->ExportPackageLists (gHiiDatabase, HiiHandle, &BufferSize, HiiPackageList);
2740 if (EFI_ERROR (Status)) {
2741 goto Finish;
2742 }
2743
2744 //
2745 // Calculate and allocate space for retrieval of IFR data
2746 //
2747 BufferSize += OpCodeBufferStart->Position;
2748 UpdatePackageList = AllocateZeroPool (BufferSize);
2749 if (UpdatePackageList == NULL) {
2750 Status = EFI_OUT_OF_RESOURCES;
2751 goto Finish;
2752 }
2753
2754 //
2755 // Allocate temp buffer to store the temp updated package buffer
2756 //
2757 TempPacakge = AllocateZeroPool (BufferSize);
2758 if (TempPacakge == NULL) {
2759 Status = EFI_OUT_OF_RESOURCES;
2760 goto Finish;
2761 }
2762
2763 UpdateBufferPos = (UINT8 *) UpdatePackageList;
2764
2765 //
2766 // Copy the package list header
2767 //
2768 CopyMem (UpdateBufferPos, HiiPackageList, sizeof (EFI_HII_PACKAGE_LIST_HEADER));
2769 UpdateBufferPos += sizeof (EFI_HII_PACKAGE_LIST_HEADER);
2770
2771 //
2772 // Go through each package to find the matched pacakge and update one by one
2773 //
2774 Updated = FALSE;
2775 Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);
2776 PackageListLength = ReadUnaligned32 (&HiiPackageList->PackageLength);
2777 while (Offset < PackageListLength) {
2778 Package = (EFI_HII_PACKAGE_HEADER *) (((UINT8 *) HiiPackageList) + Offset);
2779 CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));
2780 Offset += Package->Length;
2781
2782 if (Package->Type == EFI_HII_PACKAGE_FORMS) {
2783 //
2784 // Check this package is the matched package.
2785 //
2786 Status = InternalHiiUpdateFormPackageData (FormSetGuid, FormId, Package, OpCodeBufferStart, OpCodeBufferEnd, TempPacakge);
2787 //
2788 // The matched package is found. Its pacakge buffer will be updated by the input new data.
2789 //
2790 if (!EFI_ERROR(Status)) {
2791 //
2792 // Set Update Flag
2793 //
2794 Updated = TRUE;
2795 //
2796 // Add updated package buffer
2797 //
2798 Package = TempPacakge;
2799 }
2800 }
2801
2802 //
2803 // Add pacakge buffer
2804 //
2805 CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));
2806 CopyMem (UpdateBufferPos, Package, PackageHeader.Length);
2807 UpdateBufferPos += PackageHeader.Length;
2808 }
2809
2810 if (Updated) {
2811 //
2812 // Update package list length
2813 //
2814 BufferSize = UpdateBufferPos - (UINT8 *) UpdatePackageList;
2815 WriteUnaligned32 (&UpdatePackageList->PackageLength, (UINT32) BufferSize);
2816
2817 //
2818 // Update Pacakge to show form
2819 //
2820 Status = gHiiDatabase->UpdatePackageList (gHiiDatabase, HiiHandle, UpdatePackageList);
2821 } else {
2822 //
2823 // Not matched form is found and updated.
2824 //
2825 Status = EFI_NOT_FOUND;
2826 }
2827
2828 Finish:
2829 if (HiiPackageList != NULL) {
2830 FreePool (HiiPackageList);
2831 }
2832
2833 if (UpdatePackageList != NULL) {
2834 FreePool (UpdatePackageList);
2835 }
2836
2837 if (TempPacakge != NULL) {
2838 FreePool (TempPacakge);
2839 }
2840
2841 return Status;
2842 }
2843
2844 /**
2845 Configure the buffer accrording to ConfigBody strings in the format of
2846 <Length:4 bytes>, <Offset: 2 bytes>, <Width:2 bytes>, <Data:n bytes>.
2847 This ConfigBody strings is generated by UEFI VfrCompiler for the default
2848 values in a Form Set. The name of the ConfigBody strings is VfrMyIfrNVDataDefault0000
2849 constructed following this rule:
2850 "Vfr" + varstore.name + "Default" + defaultstore.attributes.
2851 Check the generated C file in Output for details.
2852
2853 @param Buffer The start address of buffer.
2854 @param BufferSize The size of buffer.
2855 @param Number The number of the strings.
2856 @param ... Variable argument list for default value in <AltResp> format
2857 generated by the tool.
2858
2859 @retval EFI_BUFFER_TOO_SMALL the BufferSize is too small to operate.
2860 @retval EFI_INVALID_PARAMETER Buffer is NULL or BufferSize is 0.
2861 @retval EFI_SUCCESS Operation successful.
2862
2863 **/
2864 EFI_STATUS
2865 EFIAPI
2866 HiiIfrLibExtractDefault(
2867 IN VOID *Buffer,
2868 IN UINTN *BufferSize,
2869 UINTN Number,
2870 ...
2871 )
2872 {
2873 VA_LIST Args;
2874 UINTN Index;
2875 UINT32 TotalLen;
2876 UINT8 *BufCfgArray;
2877 UINT8 *BufferPos;
2878 UINT16 Offset;
2879 UINT16 Width;
2880 UINT8 *Value;
2881
2882 if ((Buffer == NULL) || (BufferSize == NULL)) {
2883 return EFI_INVALID_PARAMETER;
2884 }
2885
2886 Offset = 0;
2887 Width = 0;
2888 Value = NULL;
2889
2890 VA_START (Args, Number);
2891 for (Index = 0; Index < Number; Index++) {
2892 BufCfgArray = (UINT8 *) VA_ARG (Args, VOID *);
2893 TotalLen = ReadUnaligned32 ((UINT32 *)BufCfgArray);
2894 BufferPos = BufCfgArray + sizeof (UINT32);
2895
2896 while ((UINT32)(BufferPos - BufCfgArray) < TotalLen) {
2897 Offset = ReadUnaligned16 ((UINT16 *)BufferPos);
2898 BufferPos += sizeof (UINT16);
2899 Width = ReadUnaligned16 ((UINT16 *)BufferPos);
2900 BufferPos += sizeof (UINT16);
2901 Value = BufferPos;
2902 BufferPos += Width;
2903
2904 if ((UINTN)(Offset + Width) > *BufferSize) {
2905 return EFI_BUFFER_TOO_SMALL;
2906 }
2907
2908 CopyMem ((UINT8 *)Buffer + Offset, Value, Width);
2909 }
2910 }
2911 VA_END (Args);
2912
2913 *BufferSize = (UINTN)Offset;
2914
2915 return EFI_SUCCESS;
2916 }