]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Library/UefiHiiLib/HiiLib.c
Fix Bug to convert low Hex string to handle L'A' - L'F'
[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 Other A pointer to the Null-terminate Unicode <ConfigHdr> string
932
933 **/
934 EFI_STRING
935 EFIAPI
936 HiiConstructConfigHdr (
937 IN CONST EFI_GUID *Guid, OPTIONAL
938 IN CONST CHAR16 *Name, OPTIONAL
939 IN EFI_HANDLE DriverHandle
940 )
941 {
942 UINTN NameLength;
943 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
944 UINTN DevicePathSize;
945 CHAR16 *String;
946 CHAR16 *ReturnString;
947 UINTN Index;
948 UINT8 *Buffer;
949
950 //
951 // Compute the length of Name in Unicode characters.
952 // If Name is NULL, then the length is 0.
953 //
954 NameLength = 0;
955 if (Name != NULL) {
956 NameLength = StrLen (Name);
957 }
958
959 DevicePath = NULL;
960 DevicePathSize = 0;
961 //
962 // Retrieve DevicePath Protocol associated with DriverHandle
963 //
964 if (DriverHandle != NULL) {
965 DevicePath = DevicePathFromHandle (DriverHandle);
966 if (DevicePath == NULL) {
967 return NULL;
968 }
969 //
970 // Compute the size of the device path in bytes
971 //
972 DevicePathSize = GetDevicePathSize (DevicePath);
973 }
974
975 //
976 // GUID=<HexCh>32&NAME=<Char>NameLength&PATH=<HexChar>DevicePathSize <Null>
977 // | 5 | sizeof (EFI_GUID) * 2 | 6 | NameStrLen*4 | 6 | DevicePathSize * 2 | 1 |
978 //
979 String = AllocateZeroPool ((5 + sizeof (EFI_GUID) * 2 + 6 + NameLength * 4 + 6 + DevicePathSize * 2 + 1) * sizeof (CHAR16));
980 if (String == NULL) {
981 return NULL;
982 }
983
984 //
985 // Start with L"GUID="
986 //
987 ReturnString = StrCpy (String, L"GUID=");
988 String += StrLen (String);
989
990 if (Guid != NULL) {
991 //
992 // Append Guid converted to <HexCh>32
993 //
994 for (Index = 0, Buffer = (UINT8 *)Guid; Index < sizeof (EFI_GUID); Index++) {
995 String += UnicodeValueToString (String, PREFIX_ZERO | RADIX_HEX, *(Buffer++), 2);
996 }
997 }
998
999 //
1000 // Append L"&NAME="
1001 //
1002 StrCpy (String, L"&NAME=");
1003 String += StrLen (String);
1004
1005 if (Name != NULL) {
1006 //
1007 // Append Name converted to <Char>NameLength
1008 //
1009 for (; *Name != L'\0'; Name++) {
1010 String += UnicodeValueToString (String, PREFIX_ZERO | RADIX_HEX, *Name, 4);
1011 }
1012 }
1013
1014 //
1015 // Append L"&PATH="
1016 //
1017 StrCpy (String, L"&PATH=");
1018 String += StrLen (String);
1019
1020 //
1021 // Append the device path associated with DriverHandle converted to <HexChar>DevicePathSize
1022 //
1023 for (Index = 0, Buffer = (UINT8 *)DevicePath; Index < DevicePathSize; Index++) {
1024 String += UnicodeValueToString (String, PREFIX_ZERO | RADIX_HEX, *(Buffer++), 2);
1025 }
1026
1027 //
1028 // Null terminate the Unicode string
1029 //
1030 *String = L'\0';
1031
1032 //
1033 // Convert all hex digits in range [A-F] in the configuration header to [a-f]
1034 //
1035 return InternalHiiLowerConfigString (ReturnString);
1036 }
1037
1038 /**
1039 Allocates and returns a Null-terminated Unicode <ConfigAltResp> string.
1040
1041 If Guid is NULL, then ASSERT().
1042 If Name is NULL, then ASSERT().
1043 If BlockNameArray is NULL, then ASSERT().
1044
1045 @param[in] Guid GUID of the buffer storage.
1046 @param[in] Name Name of the buffer storage.
1047 @param[in] DriverHandle The DriverHandle that support a Device Path
1048 Protocol.
1049 @param[in] BufferStorage Content of the buffer storage.
1050 @param[in] BufferStorageSize Length in bytes of the buffer storage.
1051 @param[in] BlockNameArray Array generated by VFR compiler. This array
1052 contains a UINT32 value that is the length
1053 of BlockNameArray in bytes, followed by pairs
1054 of 16-bit values that are the offset and length
1055 values used to contruct a <ConfigRequest> string.
1056 @param[in] ... A variable argument list that contains pairs of 16-bit
1057 ALTCFG identifiers and pointers to DefaultValueArrays.
1058 The variable argument list is terminated by a NULL
1059 DefaultValueArray pointer. A DefaultValueArray
1060 contains a UINT32 value that is the length, in bytes,
1061 of the DefaultValueArray. The UINT32 length value
1062 is followed by a series of records that contain
1063 a 16-bit WIDTH value followed by a byte array with
1064 WIDTH entries. The records must be parsed from
1065 beginning to end until the UINT32 length limit
1066 is reached.
1067
1068 @retval NULL There are not enough resources to process the request.
1069 @retval NULL A <ConfigResp> could not be retrieved from the Config
1070 Routing Protocol.
1071 @retval Other A pointer to the Null-terminate Unicode <ConfigAltResp>
1072 string.
1073
1074 **/
1075 EFI_STRING
1076 EFIAPI
1077 HiiConstructConfigAltResp (
1078 IN CONST EFI_GUID *Guid,
1079 IN CONST CHAR16 *Name,
1080 IN EFI_HANDLE DriverHandle,
1081 IN CONST VOID *BufferStorage,
1082 IN UINTN BufferStorageSize,
1083 IN CONST VOID *BlockNameArray,
1084 ...
1085 )
1086 {
1087 UINTN Length;
1088 CHAR16 *String;
1089 CHAR16 *ConfigHdr;
1090 UINT8 *Buffer;
1091 UINT8 *BufferEnd;
1092 CHAR16 *ConfigRequest;
1093 EFI_STRING ConfigResp;
1094 EFI_STRING ConfigAltResp;
1095 VA_LIST Args;
1096 UINTN AltCfgId;
1097 UINT16 Width;
1098 UINT16 OffsetValue;
1099 UINT16 WidthValue;
1100
1101 ASSERT (Guid != NULL);
1102 ASSERT (Name != NULL);
1103 ASSERT (BlockNameArray != NULL);
1104
1105 //
1106 // Initialize local variables
1107 //
1108 ConfigHdr = NULL;
1109 ConfigRequest = NULL;
1110 ConfigResp = NULL;
1111
1112 //
1113 // Construct <ConfigHdr> : "GUID=...&NAME=...&PATH=..."
1114 //
1115 ConfigHdr = HiiConstructConfigHdr (Guid, Name, DriverHandle);
1116 if (ConfigHdr == NULL) {
1117 goto Exit;
1118 }
1119
1120 //
1121 // Compute the length of the entire request starting with <ConfigHdr> and a
1122 // Null-terminator
1123 //
1124 Length = StrLen (ConfigHdr) + 1;
1125
1126 //
1127 // Determine the size <BlockName> Offset/Width pairs
1128 //
1129 Buffer = (UINT8 *)BlockNameArray;
1130 BufferEnd = Buffer + ReadUnaligned32 ((UINT32 *)Buffer);
1131 Buffer += sizeof (UINT32);
1132
1133 //
1134 // Add <BlockName> length that is composed of one or more Offset/Width pairs
1135 //
1136 // <BlockName> ::= &OFFSET=1234&WIDTH=1234
1137 // | 8 | 4 | 7 | 4 |
1138 //
1139 Length += (((BufferEnd - Buffer) / (sizeof (UINT16) + sizeof (UINT16))) * (8 + 4 + 7 + 4));
1140
1141 //
1142 // Allocate buffer for the entire <ConfigRequest>
1143 //
1144 ConfigRequest = AllocateZeroPool (Length * sizeof (CHAR16));
1145 if (ConfigRequest == NULL) {
1146 goto Exit;
1147 }
1148 String = ConfigRequest;
1149
1150 //
1151 // Start with <ConfigHdr>
1152 //
1153 StrCpy (String, ConfigHdr);
1154 String += StrLen (String);
1155
1156 //
1157 // Loop through all the Offset/Width pairs and append them to ConfigRequest
1158 //
1159 while (Buffer < BufferEnd) {
1160 //
1161 // Append &OFFSET=XXXX&WIDTH=YYYY
1162 //
1163 OffsetValue = ReadUnaligned16 ((UINT16 *)Buffer);
1164 WidthValue = ReadUnaligned16 ((UINT16 *)(Buffer + sizeof (UINT16)));
1165 UnicodeSPrint (
1166 String,
1167 (8 + 4 + 7 + 4) * sizeof (CHAR16),
1168 L"&OFFSET=%04X&WIDTH=%04X",
1169 OffsetValue,
1170 WidthValue
1171 );
1172
1173 String += StrLen (String);
1174 Buffer += (sizeof (UINT16) + sizeof (UINT16));
1175 }
1176
1177 //
1178 // Get the <ConfigResp>
1179 //
1180 ConfigResp = InternalHiiBlockToConfig (ConfigRequest, BufferStorage, BufferStorageSize);
1181 if (ConfigResp == NULL) {
1182 goto Exit;
1183 }
1184
1185 //
1186 // Compute the length of the entire response starting with <ConfigResp> and a
1187 // Null-terminator
1188 //
1189 Length = StrLen (ConfigResp) + 1;
1190
1191 //
1192 // Add the length associated with each pair of variable argument parameters
1193 //
1194 VA_START (Args, BlockNameArray);
1195 while (TRUE) {
1196 AltCfgId = VA_ARG (Args, UINT16);
1197 Buffer = VA_ARG (Args, UINT8 *);
1198 if (Buffer == NULL) {
1199 break;
1200 }
1201
1202 //
1203 // Add length for "&<ConfigHdr>&ALTCFG=XXXX"
1204 // |1| StrLen (ConfigHdr) | 8 | 4 |
1205 //
1206 Length += (1 + StrLen (ConfigHdr) + 8 + 4);
1207
1208 BufferEnd = Buffer + ReadUnaligned32 ((UINT32 *)Buffer);
1209 Buffer += sizeof (UINT32);
1210 while (Buffer < BufferEnd) {
1211 //
1212 // Extract Width field
1213 //
1214 Width = ReadUnaligned16 ((UINT16 *)(Buffer + sizeof (UINT16)));
1215
1216 //
1217 // Add length for "&OFFSET=XXXX&WIDTH=YYYY&VALUE=zzzzzzzzzzzz"
1218 // | 8 | 4 | 7 | 4 | 7 | Width * 2 |
1219 //
1220 Length += (8 + 4 + 7 + 4 + 7 + Width * 2);
1221
1222 //
1223 // Update Buffer to the next record
1224 //
1225 Buffer += (sizeof (UINT16) + sizeof (UINT16) + Width);
1226 }
1227 }
1228 VA_END (Args);
1229
1230 //
1231 // Allocate a buffer for the entire response
1232 //
1233 ConfigAltResp = AllocateZeroPool (Length * sizeof (CHAR16));
1234 if (ConfigAltResp == NULL) {
1235 goto Exit;
1236 }
1237 String = ConfigAltResp;
1238
1239 //
1240 // Add <ConfigResp>
1241 //
1242 StrCpy (String, ConfigResp);
1243 String += StrLen (String);
1244
1245 //
1246 // Add <AltResp> for each pair of variable argument parameters
1247 //
1248 VA_START (Args, BlockNameArray);
1249 while (TRUE) {
1250 AltCfgId = VA_ARG (Args, UINT16);
1251 Buffer = VA_ARG (Args, UINT8 *);
1252 if (Buffer == NULL) {
1253 break;
1254 }
1255
1256 //
1257 // Add <AltConfigHdr> of the form "&<ConfigHdr>&ALTCFG=XXXX"
1258 // |1| StrLen (ConfigHdr) | 8 | 4 |
1259 //
1260 UnicodeSPrint (
1261 String,
1262 (1 + StrLen (ConfigHdr) + 8 + 4) * sizeof (CHAR16),
1263 L"&%s&ALTCFG=%04X",
1264 ConfigHdr,
1265 AltCfgId
1266 );
1267 String += StrLen (String);
1268
1269 //
1270 // Add <ConfigBody> ::= <ConfigElement>*
1271 //
1272 BufferEnd = Buffer + ReadUnaligned32 ((UINT32 *)Buffer);
1273 Buffer += sizeof (UINT32);
1274 while (Buffer < BufferEnd) {
1275 //
1276 // Extract Width field
1277 //
1278 Width = ReadUnaligned16 ((UINT16 *)(Buffer + sizeof (UINT16)));
1279
1280 //
1281 // Add <BlockConfig>
1282 //
1283 UnicodeSPrint (
1284 String,
1285 (8 + 4 + 7 + 4 + 7 + Width * 2) * sizeof (CHAR16),
1286 L"&OFFSET=%04X&WIDTH=%04X&VALUE=",
1287 ReadUnaligned16 ((UINT16 *)Buffer),
1288 Width
1289 );
1290 String += StrLen (String);
1291
1292 //
1293 // Update Buffer to point to the value in the current record
1294 //
1295 Buffer += (sizeof (UINT16) + sizeof (UINT16));
1296
1297 //
1298 // Convert Value to a hex string in "%x" format
1299 // NOTE: This is in the opposite byte that GUID and PATH use
1300 //
1301 for (; Width > 0; Width--) {
1302 String += UnicodeValueToString (String, PREFIX_ZERO | RADIX_HEX, Buffer[Width - 1], 2);
1303 }
1304 //
1305 // Update Buffer to the next record
1306 //
1307 Buffer += Width;
1308 }
1309 }
1310 VA_END (Args);
1311
1312 //
1313 // Convert all hex digits in range [A-F] in the configuration header to [a-f]
1314 //
1315 return InternalHiiLowerConfigString (ConfigAltResp);
1316
1317 Exit:
1318 if (ConfigHdr != NULL) {
1319 FreePool (ConfigHdr);
1320 }
1321 if (ConfigRequest != NULL) {
1322 FreePool (ConfigRequest);
1323 }
1324 if (ConfigResp != NULL) {
1325 FreePool (ConfigResp);
1326 }
1327
1328 return NULL;
1329 }
1330
1331 /**
1332 Determines if two values in config strings match.
1333
1334 Compares the substring between StartSearchString and StopSearchString in
1335 FirstString to the substring between StartSearchString and StopSearchString
1336 in SecondString. If the two substrings match, then TRUE is returned. If the
1337 two substrings do not match, then FALSE is returned.
1338
1339 If FirstString is NULL, then ASSERT().
1340 If SecondString is NULL, then ASSERT().
1341 If StartSearchString is NULL, then ASSERT().
1342 If StopSearchString is NULL, then ASSERT().
1343
1344 @param FirstString Pointer to the first Null-terminated Unicode string.
1345 @param SecondString Pointer to the second Null-terminated Unicode string.
1346 @param StartSearchString Pointer to the Null-terminated Unicode string that
1347 marks the start of the value string to compare.
1348 @param StopSearchString Pointer to the Null-terminated Unicode string that
1349 marks the end of the vakue string to compare.
1350
1351 @retval FALSE StartSearchString is not present in FirstString.
1352 @retval FALSE StartSearchString is not present in SecondString.
1353 @retval FALSE StopSearchString is not present in FirstString.
1354 @retval FALSE StopSearchString is not present in SecondString.
1355 @retval FALSE The length of the substring in FirstString is not the
1356 same length as the substring in SecondString.
1357 @retval FALSE The value string in FirstString does not matche the
1358 value string in SecondString.
1359 @retval TRUE The value string in FirstString matches the value
1360 string in SecondString.
1361
1362 **/
1363 BOOLEAN
1364 EFIAPI
1365 InternalHiiCompareSubString (
1366 IN CHAR16 *FirstString,
1367 IN CHAR16 *SecondString,
1368 IN CHAR16 *StartSearchString,
1369 IN CHAR16 *StopSearchString
1370 )
1371 {
1372 CHAR16 *EndFirstString;
1373 CHAR16 *EndSecondString;
1374
1375 ASSERT (FirstString != NULL);
1376 ASSERT (SecondString != NULL);
1377 ASSERT (StartSearchString != NULL);
1378 ASSERT (StopSearchString != NULL);
1379
1380 FirstString = StrStr (FirstString, StartSearchString);
1381 if (FirstString == NULL) {
1382 return FALSE;
1383 }
1384
1385 SecondString = StrStr (SecondString, StartSearchString);
1386 if (SecondString == NULL) {
1387 return FALSE;
1388 }
1389
1390 EndFirstString = StrStr (FirstString, StopSearchString);
1391 if (EndFirstString == NULL) {
1392 return FALSE;
1393 }
1394
1395 EndSecondString = StrStr (SecondString, StopSearchString);
1396 if (EndSecondString == NULL) {
1397 return FALSE;
1398 }
1399
1400 if ((EndFirstString - FirstString) != (EndSecondString - SecondString)) {
1401 return FALSE;
1402 }
1403
1404 return (BOOLEAN)(StrnCmp (FirstString, SecondString, EndFirstString - FirstString) == 0);
1405 }
1406
1407 /**
1408 Determines if the routing data specified by GUID and NAME match a <ConfigHdr>.
1409
1410 If ConfigHdr is NULL, then ASSERT().
1411
1412 @param[in] ConfigHdr Either <ConfigRequest> or <ConfigResp>.
1413 @param[in] Guid GUID of the storage.
1414 @param[in] Name NAME of the storage.
1415
1416 @retval TRUE Routing information matches <ConfigHdr>.
1417 @retval FALSE Routing information does not match <ConfigHdr>.
1418
1419 **/
1420 BOOLEAN
1421 EFIAPI
1422 HiiIsConfigHdrMatch (
1423 IN CONST EFI_STRING ConfigHdr,
1424 IN CONST EFI_GUID *Guid, OPTIONAL
1425 IN CONST CHAR16 *Name OPTIONAL
1426 )
1427 {
1428 EFI_STRING CompareConfigHdr;
1429 BOOLEAN Result;
1430
1431 ASSERT (ConfigHdr != NULL);
1432
1433 //
1434 // Use Guid and Name to generate a <ConfigHdr> string
1435 //
1436 CompareConfigHdr = HiiConstructConfigHdr (Guid, Name, NULL);
1437 if (CompareConfigHdr == NULL) {
1438 return FALSE;
1439 }
1440
1441 Result = TRUE;
1442 if (Guid != NULL) {
1443 //
1444 // Compare GUID value strings
1445 //
1446 Result = InternalHiiCompareSubString (ConfigHdr, CompareConfigHdr, L"GUID=", L"&NAME=");
1447 }
1448
1449 if (Result && Name != NULL) {
1450 //
1451 // Compare NAME value strings
1452 //
1453 Result = InternalHiiCompareSubString (ConfigHdr, CompareConfigHdr, L"&NAME=", L"&PATH=");
1454 }
1455
1456 //
1457 // Free the <ConfigHdr> string
1458 //
1459 FreePool (CompareConfigHdr);
1460
1461 return Result;
1462 }
1463
1464 /**
1465 Retrieves uncommited data from the Form Browser and converts it to a binary
1466 buffer. The returned buffer is allocated using AllocatePool(). The caller
1467 is responsible for freeing the returned buffer using FreePool().
1468
1469 @param[in] VariableName Pointer to a Null-terminated Unicode string. This
1470 is an optional parameter that may be NULL.
1471 @param[in] VariableGuid Pointer to an EFI_GUID structure. This is an optional
1472 parameter that may be NULL.
1473 @param[in] BufferSize Length in bytes of buffer to hold retrived data.
1474
1475 @retval NULL The uncommitted data could not be retrieved.
1476 @retval Other A pointer to a buffer containing the uncommitted data.
1477
1478 **/
1479 UINT8 *
1480 EFIAPI
1481 HiiGetBrowserData (
1482 IN CONST EFI_GUID *VariableGuid, OPTIONAL
1483 IN CONST CHAR16 *VariableName, OPTIONAL
1484 IN UINTN BlockSize
1485 )
1486 {
1487 EFI_STRING ResultsData;
1488 UINTN Size;
1489 EFI_STRING ConfigResp;
1490 UINT8 *Block;
1491
1492 //
1493 // Retrieve the results data from the Browser Callback
1494 //
1495 ResultsData = InternalHiiBrowserCallback (VariableGuid, VariableName, NULL);
1496 if (ResultsData == NULL) {
1497 return NULL;
1498 }
1499
1500 //
1501 // Construct <ConfigResp> mConfigHdrTemplate L'&' ResultsData L'\0'
1502 //
1503 Size = (StrLen (mConfigHdrTemplate) + 1) * sizeof (CHAR16);
1504 Size = Size + (StrLen (ResultsData) + 1) * sizeof (CHAR16);
1505 ConfigResp = AllocateZeroPool (Size);
1506 UnicodeSPrint (ConfigResp, Size, L"%s&%s", mConfigHdrTemplate, ResultsData);
1507
1508 //
1509 // Free the allocated buffer
1510 //
1511 FreePool (ResultsData);
1512 if (ConfigResp == NULL) {
1513 return NULL;
1514 }
1515
1516 //
1517 // Convert <ConfigResp> to a buffer
1518 //
1519 Block = InternalHiiConfigToBlock (ConfigResp, BlockSize);
1520 FreePool (ConfigResp);
1521
1522 return Block;
1523 }
1524
1525 /**
1526 Updates uncommitted data in the Form Browser.
1527
1528 If Buffer is NULL, then ASSERT().
1529
1530 @param[in] VariableName Pointer to a Null-terminated Unicode string. This
1531 is an optional parameter that may be NULL.
1532 @param[in] VariableGuid Pointer to an EFI_GUID structure. This is an optional
1533 parameter that may be NULL.
1534 @param[in] BufferSize Length, in bytes, of Buffer.
1535 @param[in] Buffer Buffer of data to commit.
1536 @param[in] RequestElement An optional field to specify which part of the
1537 buffer data will be send back to Browser. If NULL,
1538 the whole buffer of data will be committed to
1539 Browser.
1540 <RequestElement> ::= &OFFSET=<Number>&WIDTH=<Number>*
1541
1542 @retval FALSE The uncommitted data could not be updated.
1543 @retval TRUE The uncommitted data was updated.
1544
1545 **/
1546 BOOLEAN
1547 EFIAPI
1548 HiiSetBrowserData (
1549 IN CONST EFI_GUID *VariableGuid, OPTIONAL
1550 IN CONST CHAR16 *VariableName, OPTIONAL
1551 IN UINTN BufferSize,
1552 IN CONST UINT8 *Buffer,
1553 IN CONST CHAR16 *RequestElement OPTIONAL
1554 )
1555 {
1556 UINTN Size;
1557 EFI_STRING ConfigRequest;
1558 EFI_STRING ConfigResp;
1559 EFI_STRING ResultsData;
1560
1561 ASSERT (Buffer != NULL);
1562
1563 //
1564 // Construct <ConfigRequest>
1565 //
1566 if (RequestElement == NULL) {
1567 //
1568 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
1569 // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
1570 //
1571 Size = (StrLen (mConfigHdrTemplate) + 32 + 1) * sizeof (CHAR16);
1572 ConfigRequest = AllocateZeroPool (Size);
1573 UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", mConfigHdrTemplate, (UINT64)BufferSize);
1574 } else {
1575 //
1576 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
1577 // followed by <RequestElement> followed by a Null-terminator
1578 //
1579 Size = StrLen (mConfigHdrTemplate) * sizeof (CHAR16);
1580 Size = Size + (StrLen (RequestElement) + 1) * sizeof (CHAR16);
1581 ConfigRequest = AllocateZeroPool (Size);
1582 UnicodeSPrint (ConfigRequest, Size, L"%s%s", mConfigHdrTemplate, RequestElement);
1583 }
1584 if (ConfigRequest == NULL) {
1585 return FALSE;
1586 }
1587
1588 //
1589 // Convert <ConfigRequest> to <ConfigResp>
1590 //
1591 ConfigResp = InternalHiiBlockToConfig (ConfigRequest, Buffer, BufferSize);
1592 FreePool (ConfigRequest);
1593 if (ConfigResp == NULL) {
1594 return FALSE;
1595 }
1596
1597 //
1598 // Set data in the uncommitted browser state information
1599 //
1600 ResultsData = InternalHiiBrowserCallback (VariableGuid, VariableName, ConfigResp + StrLen(mConfigHdrTemplate) + 1);
1601 FreePool (ConfigResp);
1602
1603 return (BOOLEAN)(ResultsData != NULL);
1604 }
1605
1606 /////////////////////////////////////////
1607 /////////////////////////////////////////
1608 /// IFR Functions
1609 /////////////////////////////////////////
1610 /////////////////////////////////////////
1611
1612 #define HII_LIB_OPCODE_ALLOCATION_SIZE 0x200
1613
1614 typedef struct {
1615 UINT8 *Buffer;
1616 UINTN BufferSize;
1617 UINTN Position;
1618 } HII_LIB_OPCODE_BUFFER;
1619
1620 ///
1621 /// Lookup table that converts EFI_IFR_TYPE_X enum values to a width in bytes
1622 ///
1623 GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 mHiiDefaultTypeToWidth[] = {
1624 1, // EFI_IFR_TYPE_NUM_SIZE_8
1625 2, // EFI_IFR_TYPE_NUM_SIZE_16
1626 4, // EFI_IFR_TYPE_NUM_SIZE_32
1627 8, // EFI_IFR_TYPE_NUM_SIZE_64
1628 1, // EFI_IFR_TYPE_BOOLEAN
1629 3, // EFI_IFR_TYPE_TIME
1630 4, // EFI_IFR_TYPE_DATE
1631 2 // EFI_IFR_TYPE_STRING
1632 };
1633
1634 /**
1635 Allocates and returns a new OpCode Handle. OpCode Handles must be freed with
1636 HiiFreeOpCodeHandle().
1637
1638 @retval NULL There are not enough resources to allocate a new OpCode Handle.
1639 @retval Other A new OpCode handle.
1640
1641 **/
1642 VOID *
1643 EFIAPI
1644 HiiAllocateOpCodeHandle (
1645 VOID
1646 )
1647 {
1648 HII_LIB_OPCODE_BUFFER *OpCodeBuffer;
1649
1650 OpCodeBuffer = (HII_LIB_OPCODE_BUFFER *)AllocatePool (sizeof (HII_LIB_OPCODE_BUFFER));
1651 if (OpCodeBuffer == NULL) {
1652 return NULL;
1653 }
1654 OpCodeBuffer->Buffer = (UINT8 *)AllocatePool (HII_LIB_OPCODE_ALLOCATION_SIZE);
1655 if (OpCodeBuffer->Buffer == NULL) {
1656 FreePool (OpCodeBuffer);
1657 return NULL;
1658 }
1659 OpCodeBuffer->BufferSize = HII_LIB_OPCODE_ALLOCATION_SIZE;
1660 OpCodeBuffer->Position = 0;
1661 return (VOID *)OpCodeBuffer;
1662 }
1663
1664 /**
1665 Frees an OpCode Handle that was peviously allocated with HiiAllocateOpCodeHandle().
1666 When an OpCode Handle is freed, all of the opcodes associated with the OpCode
1667 Handle are also freed.
1668
1669 If OpCodeHandle is NULL, then ASSERT().
1670
1671 **/
1672 VOID
1673 EFIAPI
1674 HiiFreeOpCodeHandle (
1675 VOID *OpCodeHandle
1676 )
1677 {
1678 HII_LIB_OPCODE_BUFFER *OpCodeBuffer;
1679
1680 ASSERT (OpCodeHandle != NULL);
1681
1682 OpCodeBuffer = (HII_LIB_OPCODE_BUFFER *)OpCodeHandle;
1683 if (OpCodeBuffer->Buffer != NULL) {
1684 FreePool (OpCodeBuffer->Buffer);
1685 }
1686 FreePool (OpCodeBuffer);
1687 }
1688
1689 UINTN
1690 EFIAPI
1691 InternalHiiOpCodeHandlePosition (
1692 IN VOID *OpCodeHandle
1693 )
1694 {
1695 return ((HII_LIB_OPCODE_BUFFER *)OpCodeHandle)->Position;
1696 }
1697
1698 UINT8 *
1699 EFIAPI
1700 InternalHiiOpCodeHandleBuffer (
1701 IN VOID *OpCodeHandle
1702 )
1703 {
1704 return ((HII_LIB_OPCODE_BUFFER *)OpCodeHandle)->Buffer;
1705 }
1706
1707 UINT8 *
1708 EFIAPI
1709 InternalHiiGrowOpCodeHandle (
1710 VOID *OpCodeHandle,
1711 UINTN Size
1712 )
1713 {
1714 HII_LIB_OPCODE_BUFFER *OpCodeBuffer;
1715 UINT8 *Buffer;
1716
1717 ASSERT (OpCodeHandle != NULL);
1718
1719 OpCodeBuffer = (HII_LIB_OPCODE_BUFFER *)OpCodeHandle;
1720 if (OpCodeBuffer->Position + Size > OpCodeBuffer->BufferSize) {
1721 Buffer = ReallocatePool (
1722 OpCodeBuffer->BufferSize,
1723 OpCodeBuffer->BufferSize + (Size + HII_LIB_OPCODE_ALLOCATION_SIZE),
1724 OpCodeBuffer->Buffer
1725 );
1726 if (Buffer == NULL) {
1727 return NULL;
1728 }
1729 OpCodeBuffer->Buffer = Buffer;
1730 OpCodeBuffer->BufferSize += (Size + HII_LIB_OPCODE_ALLOCATION_SIZE);
1731 }
1732 Buffer = OpCodeBuffer->Buffer + OpCodeBuffer->Position;
1733 OpCodeBuffer->Position += Size;
1734 return Buffer;
1735 }
1736
1737 UINT8 *
1738 EFIAPI
1739 InternalHiiCreateOpCodeExtended (
1740 IN VOID *OpCodeHandle,
1741 IN VOID *OpCodeTemplate,
1742 IN UINT8 OpCode,
1743 IN UINTN OpCodeSize,
1744 IN UINTN ExtensionSize,
1745 IN UINT8 Scope
1746 )
1747 {
1748 EFI_IFR_OP_HEADER *Header;
1749 UINT8 *Buffer;
1750
1751 ASSERT (OpCodeTemplate != NULL);
1752 ASSERT ((OpCodeSize + ExtensionSize) <= 0x7F);
1753
1754 Header = (EFI_IFR_OP_HEADER *)OpCodeTemplate;
1755 Header->OpCode = OpCode;
1756 Header->Scope = Scope;
1757 Header->Length = (UINT8)(OpCodeSize + ExtensionSize);
1758 Buffer = InternalHiiGrowOpCodeHandle (OpCodeHandle, Header->Length);
1759 return (UINT8 *)CopyMem (Buffer, Header, OpCodeSize);
1760 }
1761
1762 UINT8 *
1763 EFIAPI
1764 InternalHiiCreateOpCode (
1765 IN VOID *OpCodeHandle,
1766 IN VOID *OpCodeTemplate,
1767 IN UINT8 OpCode,
1768 IN UINTN OpCodeSize
1769 )
1770 {
1771 return InternalHiiCreateOpCodeExtended (OpCodeHandle, OpCodeTemplate, OpCode, OpCodeSize, 0, 0);
1772 }
1773
1774 /**
1775 Append raw opcodes to an OpCodeHandle.
1776
1777 If OpCodeHandle is NULL, then ASSERT().
1778 If RawBuffer is NULL, then ASSERT();
1779
1780 @param[in] OpCodeHandle Handle to the buffer of opcodes.
1781 @param[in] RawBuffer Buffer of opcodes to append.
1782 @param[in] RawBufferSize The size, in bytes, of Buffer.
1783
1784 @retval NULL There is not enough space left in Buffer to add the opcode.
1785 @retval Other A pointer to the appended opcodes.
1786
1787 **/
1788 UINT8 *
1789 EFIAPI
1790 InternalHiiCreateRawOpCodes (
1791 IN VOID *OpCodeHandle,
1792 IN UINT8 *RawBuffer,
1793 IN UINTN RawBufferSize
1794 )
1795 {
1796 UINT8 *Buffer;
1797
1798 ASSERT (RawBuffer != NULL);
1799
1800 Buffer = InternalHiiGrowOpCodeHandle (OpCodeHandle, RawBufferSize);
1801 return (UINT8 *)CopyMem (Buffer, RawBuffer, RawBufferSize);
1802 }
1803
1804 /**
1805 Append opcodes from one OpCode Handle to another OpCode handle.
1806
1807 If OpCodeHandle is NULL, then ASSERT().
1808 If RawOpCodeHandle is NULL, then ASSERT();
1809
1810 @param[in] OpCodeHandle Handle to the buffer of opcodes.
1811 @param[in] RawOpCodeHandle Handle to the buffer of opcodes.
1812
1813 @retval NULL There is not enough space left in Buffer to add the opcode.
1814 @retval Other A pointer to the appended opcodes.
1815
1816 **/
1817 UINT8 *
1818 EFIAPI
1819 InternalHiiAppendOpCodes (
1820 IN VOID *OpCodeHandle,
1821 IN VOID *RawOpCodeHandle
1822 )
1823 {
1824 HII_LIB_OPCODE_BUFFER *RawOpCodeBuffer;
1825
1826 ASSERT (RawOpCodeHandle != NULL);
1827
1828 RawOpCodeBuffer = (HII_LIB_OPCODE_BUFFER *)RawOpCodeHandle;
1829 return InternalHiiCreateRawOpCodes (OpCodeHandle, RawOpCodeBuffer->Buffer, RawOpCodeBuffer->Position);
1830 }
1831
1832 /**
1833 Create EFI_IFR_END_OP opcode.
1834
1835 If OpCodeHandle is NULL, then ASSERT().
1836
1837 @param[in] OpCodeHandle Handle to the buffer of opcodes.
1838
1839 @retval NULL There is not enough space left in Buffer to add the opcode.
1840 @retval Other A pointer to the created opcode.
1841
1842 **/
1843 UINT8 *
1844 EFIAPI
1845 HiiCreateEndOpCode (
1846 IN VOID *OpCodeHandle
1847 )
1848 {
1849 EFI_IFR_END OpCode;
1850
1851 return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_END_OP, sizeof (OpCode));
1852 }
1853
1854 /**
1855 Create EFI_IFR_ONE_OF_OPTION_OP opcode.
1856
1857 If OpCodeHandle is NULL, then ASSERT().
1858 If Type is invalid, then ASSERT().
1859 If Flags is invalid, then ASSERT().
1860
1861 @param[in] OpCodeHandle Handle to the buffer of opcodes.
1862 @param[in] StringId StringId for the option
1863 @param[in] Flags Flags for the option
1864 @param[in] Type Type for the option
1865 @param[in] Value Value for the option
1866
1867 @retval NULL There is not enough space left in Buffer to add the opcode.
1868 @retval Other A pointer to the created opcode.
1869
1870 **/
1871 UINT8 *
1872 EFIAPI
1873 HiiCreateOneOfOptionOpCode (
1874 IN VOID *OpCodeHandle,
1875 IN UINT16 StringId,
1876 IN UINT8 Flags,
1877 IN UINT8 Type,
1878 IN UINT64 Value
1879 )
1880 {
1881 EFI_IFR_ONE_OF_OPTION OpCode;
1882
1883 ASSERT (Type < EFI_IFR_TYPE_OTHER);
1884
1885 ZeroMem (&OpCode, sizeof (OpCode));
1886 OpCode.Option = StringId;
1887 OpCode.Flags = (UINT8) (Flags & (EFI_IFR_OPTION_DEFAULT | EFI_IFR_OPTION_DEFAULT_MFG));
1888 OpCode.Type = Type;
1889 CopyMem (&OpCode.Value, &Value, mHiiDefaultTypeToWidth[Type]);
1890
1891 return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_ONE_OF_OPTION_OP, sizeof (OpCode));
1892 }
1893
1894 /**
1895 Create EFI_IFR_DEFAULT_OP opcode.
1896
1897 If OpCodeHandle is NULL, then ASSERT().
1898 If Type is invalid, then ASSERT().
1899
1900 @param[in] OpCodeHandle Handle to the buffer of opcodes.
1901 @param[in] DefaultId DefaultId for the default
1902 @param[in] Type Type for the default
1903 @param[in] Value Value for the default
1904
1905 @retval NULL There is not enough space left in Buffer to add the opcode.
1906 @retval Other A pointer to the created opcode.
1907
1908 **/
1909 UINT8 *
1910 EFIAPI
1911 HiiCreateDefaultOpCode (
1912 IN VOID *OpCodeHandle,
1913 IN UINT16 DefaultId,
1914 IN UINT8 Type,
1915 IN UINT64 Value
1916 )
1917 {
1918 EFI_IFR_DEFAULT OpCode;
1919
1920 ASSERT (Type < EFI_IFR_TYPE_OTHER);
1921
1922 ZeroMem (&OpCode, sizeof (OpCode));
1923 OpCode.Type = Type;
1924 OpCode.DefaultId = DefaultId;
1925 CopyMem (&OpCode.Value, &Value, mHiiDefaultTypeToWidth[Type]);
1926
1927 return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_DEFAULT_OP, sizeof (OpCode));
1928 }
1929
1930 /**
1931 Create EFI_IFR_GUID opcode.
1932
1933 If OpCodeHandle is NULL, then ASSERT().
1934 If Guid is NULL, then ASSERT().
1935 If OpCodeSize < sizeof (EFI_IFR_GUID), then ASSERT().
1936
1937 @param[in] OpCodeHandle Handle to the buffer of opcodes.
1938 @param[in] Guid Pointer to EFI_GUID of this guided opcode.
1939 @param[in] GuidOpCode Pointer to an EFI_IFR_GUID opcode. This is an
1940 optional parameter that may be NULL. If this
1941 parameter is NULL, then the GUID extension
1942 region of the created opcode is filled with zeros.
1943 If this parameter is not NULL, then the GUID
1944 extension region of GuidData will be copied to
1945 the GUID extension region of the created opcode.
1946 @param[in] OpCodeSize The size, in bytes, of created opcode. This value
1947 must be >= sizeof(EFI_IFR_GUID).
1948
1949 @retval NULL There is not enough space left in Buffer to add the opcode.
1950 @retval Other A pointer to the created opcode.
1951
1952 **/
1953 UINT8 *
1954 EFIAPI
1955 HiiCreateGuidOpCode (
1956 IN VOID *OpCodeHandle,
1957 IN CONST EFI_GUID *Guid,
1958 IN CONST VOID *GuidOpCode, OPTIONAL
1959 IN UINTN OpCodeSize
1960 )
1961 {
1962 EFI_IFR_GUID OpCode;
1963 EFI_IFR_GUID *OpCodePointer;
1964
1965 ASSERT (Guid != NULL);
1966 ASSERT (OpCodeSize >= sizeof (OpCode));
1967
1968 ZeroMem (&OpCode, sizeof (OpCode));
1969 CopyGuid ((EFI_GUID *)(VOID *)&OpCode.Guid, Guid);
1970
1971 OpCodePointer = (EFI_IFR_GUID *)InternalHiiCreateOpCodeExtended (
1972 OpCodeHandle,
1973 &OpCode,
1974 EFI_IFR_GUID_OP,
1975 sizeof (OpCode),
1976 OpCodeSize - sizeof (OpCode),
1977 0
1978 );
1979 if (OpCodePointer != NULL && GuidOpCode != NULL) {
1980 CopyMem (OpCodePointer + 1, (EFI_IFR_GUID *)GuidOpCode + 1, OpCodeSize - sizeof (OpCode));
1981 }
1982 return (UINT8 *)OpCodePointer;
1983 }
1984
1985 /**
1986 Create EFI_IFR_ACTION_OP opcode.
1987
1988 If OpCodeHandle is NULL, then ASSERT().
1989 If any reserved bits are set in QuestionFlags, then ASSERT().
1990
1991 @param[in] OpCodeHandle Handle to the buffer of opcodes.
1992 @param[in] QuestionId Question ID
1993 @param[in] Prompt String ID for Prompt
1994 @param[in] Help String ID for Help
1995 @param[in] QuestionFlags Flags in Question Header
1996 @param[in] QuestionConfig String ID for configuration
1997
1998 @retval NULL There is not enough space left in Buffer to add the opcode.
1999 @retval Other A pointer to the created opcode.
2000
2001 **/
2002 UINT8 *
2003 EFIAPI
2004 HiiCreateActionOpCode (
2005 IN VOID *OpCodeHandle,
2006 IN EFI_QUESTION_ID QuestionId,
2007 IN EFI_STRING_ID Prompt,
2008 IN EFI_STRING_ID Help,
2009 IN UINT8 QuestionFlags,
2010 IN EFI_STRING_ID QuestionConfig
2011 )
2012 {
2013 EFI_IFR_ACTION OpCode;
2014
2015 ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED | EFI_IFR_FLAG_OPTIONS_ONLY))) == 0);
2016
2017 ZeroMem (&OpCode, sizeof (OpCode));
2018 OpCode.Question.QuestionId = QuestionId;
2019 OpCode.Question.Header.Prompt = Prompt;
2020 OpCode.Question.Header.Help = Help;
2021 OpCode.Question.Flags = QuestionFlags;
2022 OpCode.QuestionConfig = QuestionConfig;
2023
2024 return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_ACTION_OP, sizeof (OpCode));
2025 }
2026
2027 /**
2028 Create EFI_IFR_SUBTITLE_OP opcode.
2029
2030 If OpCodeHandle is NULL, then ASSERT().
2031 If any reserved bits are set in Flags, then ASSERT().
2032 If Scope > 1, then ASSERT().
2033
2034 @param[in] OpCodeHandle Handle to the buffer of opcodes.
2035 @param[in] Prompt String ID for Prompt
2036 @param[in] Help String ID for Help
2037 @param[in] Flags Subtitle opcode flags
2038 @param[in] Scope 1 if this opcpde is the beginning of a new scope.
2039 0 if this opcode is within the current scope.
2040
2041 @retval NULL There is not enough space left in Buffer to add the opcode.
2042 @retval Other A pointer to the created opcode.
2043
2044 **/
2045 UINT8 *
2046 EFIAPI
2047 HiiCreateSubTitleOpCode (
2048 IN VOID *OpCodeHandle,
2049 IN EFI_STRING_ID Prompt,
2050 IN EFI_STRING_ID Help,
2051 IN UINT8 Flags,
2052 IN UINT8 Scope
2053 )
2054 {
2055 EFI_IFR_SUBTITLE OpCode;
2056
2057 ASSERT (Scope <= 1);
2058 ASSERT ((Flags & (~(EFI_IFR_FLAGS_HORIZONTAL))) == 0);
2059
2060 ZeroMem (&OpCode, sizeof (OpCode));
2061 OpCode.Statement.Prompt = Prompt;
2062 OpCode.Statement.Help = Help;
2063 OpCode.Flags = Flags;
2064
2065 return InternalHiiCreateOpCodeExtended (
2066 OpCodeHandle,
2067 &OpCode,
2068 EFI_IFR_SUBTITLE_OP,
2069 sizeof (OpCode),
2070 0,
2071 Scope
2072 );
2073 }
2074
2075 /**
2076 Create EFI_IFR_REF_OP opcode.
2077
2078 If OpCodeHandle is NULL, then ASSERT().
2079 If any reserved bits are set in QuestionFlags, then ASSERT().
2080
2081 @param[in] OpCodeHandle Handle to the buffer of opcodes.
2082 @param[in] FormId Destination Form ID
2083 @param[in] Prompt String ID for Prompt
2084 @param[in] Help String ID for Help
2085 @param[in] QuestionFlags Flags in Question Header
2086 @param[in] QuestionId Question ID
2087
2088 @retval NULL There is not enough space left in Buffer to add the opcode.
2089 @retval Other A pointer to the created opcode.
2090
2091 **/
2092 UINT8 *
2093 EFIAPI
2094 HiiCreateGotoOpCode (
2095 IN VOID *OpCodeHandle,
2096 IN EFI_FORM_ID FormId,
2097 IN EFI_STRING_ID Prompt,
2098 IN EFI_STRING_ID Help,
2099 IN UINT8 QuestionFlags,
2100 IN EFI_QUESTION_ID QuestionId
2101 )
2102 {
2103 EFI_IFR_REF OpCode;
2104
2105 ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED | EFI_IFR_FLAG_OPTIONS_ONLY))) == 0);
2106
2107 ZeroMem (&OpCode, sizeof (OpCode));
2108 OpCode.Question.Header.Prompt = Prompt;
2109 OpCode.Question.Header.Help = Help;
2110 OpCode.Question.QuestionId = QuestionId;
2111 OpCode.Question.Flags = QuestionFlags;
2112 OpCode.FormId = FormId;
2113
2114 return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_REF_OP, sizeof (OpCode));
2115 }
2116
2117 /**
2118 Create EFI_IFR_CHECKBOX_OP opcode.
2119
2120 If OpCodeHandle is NULL, then ASSERT().
2121 If any reserved bits are set in QuestionFlags, then ASSERT().
2122 If any reserved bits are set in CheckBoxFlags, then ASSERT().
2123
2124 @param[in] OpCodeHandle Handle to the buffer of opcodes.
2125 @param[in] QuestionId Question ID
2126 @param[in] VarStoreId Storage ID
2127 @param[in] VarOffset Offset in Storage
2128 @param[in] Prompt String ID for Prompt
2129 @param[in] Help String ID for Help
2130 @param[in] QuestionFlags Flags in Question Header
2131 @param[in] CheckBoxFlags Flags for checkbox opcode
2132 @param[in] DefaultsOpCodeHandle Handle for a buffer of DEFAULT opcodes. This
2133 is an optional parameter that may be NULL.
2134
2135 @retval NULL There is not enough space left in Buffer to add the opcode.
2136 @retval Other A pointer to the created opcode.
2137
2138 **/
2139 UINT8 *
2140 EFIAPI
2141 HiiCreateCheckBoxOpCode (
2142 IN VOID *OpCodeHandle,
2143 IN EFI_QUESTION_ID QuestionId,
2144 IN EFI_VARSTORE_ID VarStoreId,
2145 IN UINT16 VarOffset,
2146 IN EFI_STRING_ID Prompt,
2147 IN EFI_STRING_ID Help,
2148 IN UINT8 QuestionFlags,
2149 IN UINT8 CheckBoxFlags,
2150 IN VOID *DefaultsOpCodeHandle OPTIONAL
2151 )
2152 {
2153 EFI_IFR_CHECKBOX OpCode;
2154 UINTN Position;
2155
2156 ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED | EFI_IFR_FLAG_OPTIONS_ONLY))) == 0);
2157
2158 ZeroMem (&OpCode, sizeof (OpCode));
2159 OpCode.Question.QuestionId = QuestionId;
2160 OpCode.Question.VarStoreId = VarStoreId;
2161 OpCode.Question.VarStoreInfo.VarOffset = VarOffset;
2162 OpCode.Question.Header.Prompt = Prompt;
2163 OpCode.Question.Header.Help = Help;
2164 OpCode.Question.Flags = QuestionFlags;
2165 OpCode.Flags = CheckBoxFlags;
2166
2167 if (DefaultsOpCodeHandle == NULL) {
2168 return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_CHECKBOX_OP, sizeof (OpCode));
2169 }
2170
2171 Position = InternalHiiOpCodeHandlePosition (OpCodeHandle);
2172 InternalHiiCreateOpCodeExtended (OpCodeHandle, &OpCode, EFI_IFR_CHECKBOX_OP, sizeof (OpCode), 0, 1);
2173 InternalHiiAppendOpCodes (OpCodeHandle, DefaultsOpCodeHandle);
2174 HiiCreateEndOpCode (OpCodeHandle);
2175 return InternalHiiOpCodeHandleBuffer (OpCodeHandle) + Position;
2176 }
2177
2178 /**
2179 Create EFI_IFR_NUMERIC_OP opcode.
2180
2181 If OpCodeHandle is NULL, then ASSERT().
2182 If any reserved bits are set in QuestionFlags, then ASSERT().
2183 If any reserved bits are set in NumericFlags, then ASSERT().
2184
2185 @param[in] OpCodeHandle Handle to the buffer of opcodes.
2186 @param[in] QuestionId Question ID
2187 @param[in] VarStoreId Storage ID
2188 @param[in] VarOffset Offset in Storage
2189 @param[in] Prompt String ID for Prompt
2190 @param[in] Help String ID for Help
2191 @param[in] QuestionFlags Flags in Question Header
2192 @param[in] NumericFlags Flags for numeric opcode
2193 @param[in] Minimum Numeric minimum value
2194 @param[in] Maximum Numeric maximum value
2195 @param[in] Step Numeric step for edit
2196 @param[in] DefaultsOpCodeHandle Handle for a buffer of DEFAULT opcodes. This
2197 is an optional parameter that may be NULL.
2198
2199 @retval NULL There is not enough space left in Buffer to add the opcode.
2200 @retval Other A pointer to the created opcode.
2201
2202 **/
2203 UINT8 *
2204 EFIAPI
2205 HiiCreateNumericOpCode (
2206 IN VOID *OpCodeHandle,
2207 IN EFI_QUESTION_ID QuestionId,
2208 IN EFI_VARSTORE_ID VarStoreId,
2209 IN UINT16 VarOffset,
2210 IN EFI_STRING_ID Prompt,
2211 IN EFI_STRING_ID Help,
2212 IN UINT8 QuestionFlags,
2213 IN UINT8 NumericFlags,
2214 IN UINT64 Minimum,
2215 IN UINT64 Maximum,
2216 IN UINT64 Step,
2217 IN VOID *DefaultsOpCodeHandle OPTIONAL
2218 )
2219 {
2220 EFI_IFR_NUMERIC OpCode;
2221 UINTN Position;
2222
2223 ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED | EFI_IFR_FLAG_OPTIONS_ONLY))) == 0);
2224
2225 ZeroMem (&OpCode, sizeof (OpCode));
2226 OpCode.Question.QuestionId = QuestionId;
2227 OpCode.Question.VarStoreId = VarStoreId;
2228 OpCode.Question.VarStoreInfo.VarOffset = VarOffset;
2229 OpCode.Question.Header.Prompt = Prompt;
2230 OpCode.Question.Header.Help = Help;
2231 OpCode.Question.Flags = QuestionFlags;
2232 OpCode.Flags = NumericFlags;
2233
2234 switch (NumericFlags & EFI_IFR_NUMERIC_SIZE) {
2235 case EFI_IFR_NUMERIC_SIZE_1:
2236 OpCode.data.u8.MinValue = (UINT8)Minimum;
2237 OpCode.data.u8.MaxValue = (UINT8)Maximum;
2238 OpCode.data.u8.Step = (UINT8)Step;
2239 break;
2240
2241 case EFI_IFR_NUMERIC_SIZE_2:
2242 OpCode.data.u16.MinValue = (UINT16)Minimum;
2243 OpCode.data.u16.MaxValue = (UINT16)Maximum;
2244 OpCode.data.u16.Step = (UINT16)Step;
2245 break;
2246
2247 case EFI_IFR_NUMERIC_SIZE_4:
2248 OpCode.data.u32.MinValue = (UINT32)Minimum;
2249 OpCode.data.u32.MaxValue = (UINT32)Maximum;
2250 OpCode.data.u32.Step = (UINT32)Step;
2251 break;
2252
2253 case EFI_IFR_NUMERIC_SIZE_8:
2254 OpCode.data.u64.MinValue = Minimum;
2255 OpCode.data.u64.MaxValue = Maximum;
2256 OpCode.data.u64.Step = Step;
2257 break;
2258 }
2259
2260 if (DefaultsOpCodeHandle == NULL) {
2261 return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_NUMERIC_OP, sizeof (OpCode));
2262 }
2263
2264 Position = InternalHiiOpCodeHandlePosition (OpCodeHandle);
2265 InternalHiiCreateOpCodeExtended (OpCodeHandle, &OpCode, EFI_IFR_NUMERIC_OP, sizeof (OpCode), 0, 1);
2266 InternalHiiAppendOpCodes (OpCodeHandle, DefaultsOpCodeHandle);
2267 HiiCreateEndOpCode (OpCodeHandle);
2268 return InternalHiiOpCodeHandleBuffer (OpCodeHandle) + Position;
2269 }
2270
2271 /**
2272 Create EFI_IFR_STRING_OP opcode.
2273
2274 If OpCodeHandle is NULL, then ASSERT().
2275 If any reserved bits are set in QuestionFlags, then ASSERT().
2276 If any reserved bits are set in StringFlags, then ASSERT().
2277
2278 @param[in] OpCodeHandle Handle to the buffer of opcodes.
2279 @param[in] QuestionId Question ID
2280 @param[in] VarStoreId Storage ID
2281 @param[in] VarOffset Offset in Storage
2282 @param[in] Prompt String ID for Prompt
2283 @param[in] Help String ID for Help
2284 @param[in] QuestionFlags Flags in Question Header
2285 @param[in] StringFlags Flags for string opcode
2286 @param[in] MinSize String minimum length
2287 @param[in] MaxSize String maximum length
2288 @param[in] DefaultsOpCodeHandle Handle for a buffer of DEFAULT opcodes. This
2289 is an optional parameter that may be NULL.
2290
2291 @retval NULL There is not enough space left in Buffer to add the opcode.
2292 @retval Other A pointer to the created opcode.
2293
2294 **/
2295 UINT8 *
2296 EFIAPI
2297 HiiCreateStringOpCode (
2298 IN VOID *OpCodeHandle,
2299 IN EFI_QUESTION_ID QuestionId,
2300 IN EFI_VARSTORE_ID VarStoreId,
2301 IN UINT16 VarOffset,
2302 IN EFI_STRING_ID Prompt,
2303 IN EFI_STRING_ID Help,
2304 IN UINT8 QuestionFlags,
2305 IN UINT8 StringFlags,
2306 IN UINT8 MinSize,
2307 IN UINT8 MaxSize,
2308 IN VOID *DefaultsOpCodeHandle OPTIONAL
2309 )
2310 {
2311 EFI_IFR_STRING OpCode;
2312 UINTN Position;
2313
2314 ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED | EFI_IFR_FLAG_OPTIONS_ONLY))) == 0);
2315
2316 ZeroMem (&OpCode, sizeof (OpCode));
2317 OpCode.Question.Header.Prompt = Prompt;
2318 OpCode.Question.Header.Help = Help;
2319 OpCode.Question.QuestionId = QuestionId;
2320 OpCode.Question.VarStoreId = VarStoreId;
2321 OpCode.Question.VarStoreInfo.VarOffset = VarOffset;
2322 OpCode.Question.Flags = QuestionFlags;
2323 OpCode.MinSize = MinSize;
2324 OpCode.MaxSize = MaxSize;
2325 OpCode.Flags = (UINT8) (StringFlags & EFI_IFR_STRING_MULTI_LINE);
2326
2327 if (DefaultsOpCodeHandle == NULL) {
2328 return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_STRING_OP, sizeof (OpCode));
2329 }
2330
2331 Position = InternalHiiOpCodeHandlePosition (OpCodeHandle);
2332 InternalHiiCreateOpCodeExtended (OpCodeHandle, &OpCode, EFI_IFR_STRING_OP, sizeof (OpCode), 0, 1);
2333 InternalHiiAppendOpCodes (OpCodeHandle, DefaultsOpCodeHandle);
2334 HiiCreateEndOpCode (OpCodeHandle);
2335 return InternalHiiOpCodeHandleBuffer (OpCodeHandle) + Position;
2336 }
2337
2338 /**
2339 Create EFI_IFR_ONE_OF_OP opcode.
2340
2341 If OpCodeHandle is NULL, then ASSERT().
2342 If any reserved bits are set in QuestionFlags, then ASSERT().
2343 If any reserved bits are set in OneOfFlags, then ASSERT().
2344
2345 @param[in] OpCodeHandle Handle to the buffer of opcodes.
2346 @param[in] QuestionId Question ID
2347 @param[in] VarStoreId Storage ID
2348 @param[in] VarOffset Offset in Storage
2349 @param[in] Prompt String ID for Prompt
2350 @param[in] Help String ID for Help
2351 @param[in] QuestionFlags Flags in Question Header
2352 @param[in] OneOfFlags Flags for oneof opcode
2353 @param[in] OptionsOpCodeHandle Handle for a buffer of ONE_OF_OPTION opcodes.
2354 @param[in] DefaultsOpCodeHandle Handle for a buffer of DEFAULT opcodes. This
2355 is an optional parameter that may be NULL.
2356
2357 @retval NULL There is not enough space left in Buffer to add the opcode.
2358 @retval Other A pointer to the created opcode.
2359
2360 **/
2361 UINT8 *
2362 EFIAPI
2363 HiiCreateOneOfOpCode (
2364 IN VOID *OpCodeHandle,
2365 IN EFI_QUESTION_ID QuestionId,
2366 IN EFI_VARSTORE_ID VarStoreId,
2367 IN UINT16 VarOffset,
2368 IN EFI_STRING_ID Prompt,
2369 IN EFI_STRING_ID Help,
2370 IN UINT8 QuestionFlags,
2371 IN UINT8 OneOfFlags,
2372 IN VOID *OptionsOpCodeHandle,
2373 IN VOID *DefaultsOpCodeHandle OPTIONAL
2374 )
2375 {
2376 EFI_IFR_ONE_OF OpCode;
2377 UINTN Position;
2378
2379 ASSERT (OptionsOpCodeHandle != NULL);
2380 ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED | EFI_IFR_FLAG_OPTIONS_ONLY))) == 0);
2381
2382 ZeroMem (&OpCode, sizeof (OpCode));
2383 OpCode.Question.Header.Prompt = Prompt;
2384 OpCode.Question.Header.Help = Help;
2385 OpCode.Question.QuestionId = QuestionId;
2386 OpCode.Question.VarStoreId = VarStoreId;
2387 OpCode.Question.VarStoreInfo.VarOffset = VarOffset;
2388 OpCode.Question.Flags = QuestionFlags;
2389 OpCode.Flags = OneOfFlags;
2390
2391 Position = InternalHiiOpCodeHandlePosition (OpCodeHandle);
2392 InternalHiiCreateOpCodeExtended (OpCodeHandle, &OpCode, EFI_IFR_ONE_OF_OP, sizeof (OpCode), 0, 1);
2393 InternalHiiAppendOpCodes (OpCodeHandle, OptionsOpCodeHandle);
2394 if (DefaultsOpCodeHandle != NULL) {
2395 InternalHiiAppendOpCodes (OpCodeHandle, DefaultsOpCodeHandle);
2396 }
2397 HiiCreateEndOpCode (OpCodeHandle);
2398 return InternalHiiOpCodeHandleBuffer (OpCodeHandle) + Position;
2399 }
2400
2401 /**
2402 Create EFI_IFR_ORDERED_LIST_OP opcode.
2403
2404 If OpCodeHandle is NULL, then ASSERT().
2405 If any reserved bits are set in QuestionFlags, then ASSERT().
2406 If any reserved bits are set in OrderedListFlags, then ASSERT().
2407
2408 @param[in] OpCodeHandle Handle to the buffer of opcodes.
2409 @param[in] QuestionId Question ID
2410 @param[in] VarStoreId Storage ID
2411 @param[in] VarOffset Offset in Storage
2412 @param[in] Prompt String ID for Prompt
2413 @param[in] Help String ID for Help
2414 @param[in] QuestionFlags Flags in Question Header
2415 @param[in] OrderedListFlags Flags for ordered list opcode
2416 @param[in] DataType Type for option value
2417 @param[in] MaxContainers Maximum count for options in this ordered list
2418 @param[in] OptionsOpCodeHandle Handle for a buffer of ONE_OF_OPTION opcodes.
2419 @param[in] DefaultsOpCodeHandle Handle for a buffer of DEFAULT opcodes. This
2420 is an optional parameter that may be NULL.
2421
2422 @retval NULL There is not enough space left in Buffer to add the opcode.
2423 @retval Other A pointer to the created opcode.
2424
2425 **/
2426 UINT8 *
2427 EFIAPI
2428 HiiCreateOrderedListOpCode (
2429 IN VOID *OpCodeHandle,
2430 IN EFI_QUESTION_ID QuestionId,
2431 IN EFI_VARSTORE_ID VarStoreId,
2432 IN UINT16 VarOffset,
2433 IN EFI_STRING_ID Prompt,
2434 IN EFI_STRING_ID Help,
2435 IN UINT8 QuestionFlags,
2436 IN UINT8 OrderedListFlags,
2437 IN UINT8 DataType,
2438 IN UINT8 MaxContainers,
2439 IN VOID *OptionsOpCodeHandle,
2440 IN VOID *DefaultsOpCodeHandle OPTIONAL
2441 )
2442 {
2443 EFI_IFR_ORDERED_LIST OpCode;
2444 UINTN Position;
2445
2446 ASSERT (OptionsOpCodeHandle != NULL);
2447 ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED | EFI_IFR_FLAG_OPTIONS_ONLY))) == 0);
2448
2449 ZeroMem (&OpCode, sizeof (OpCode));
2450 OpCode.Question.Header.Prompt = Prompt;
2451 OpCode.Question.Header.Help = Help;
2452 OpCode.Question.QuestionId = QuestionId;
2453 OpCode.Question.VarStoreId = VarStoreId;
2454 OpCode.Question.VarStoreInfo.VarOffset = VarOffset;
2455 OpCode.Question.Flags = QuestionFlags;
2456 OpCode.MaxContainers = MaxContainers;
2457 OpCode.Flags = OrderedListFlags;
2458
2459 Position = InternalHiiOpCodeHandlePosition (OpCodeHandle);
2460 InternalHiiCreateOpCodeExtended (OpCodeHandle, &OpCode, EFI_IFR_ORDERED_LIST_OP, sizeof (OpCode), 0, 1);
2461 InternalHiiAppendOpCodes (OpCodeHandle, OptionsOpCodeHandle);
2462 if (DefaultsOpCodeHandle != NULL) {
2463 InternalHiiAppendOpCodes (OpCodeHandle, DefaultsOpCodeHandle);
2464 }
2465 HiiCreateEndOpCode (OpCodeHandle);
2466 return InternalHiiOpCodeHandleBuffer (OpCodeHandle) + Position;
2467 }
2468
2469 /**
2470 This is the internal worker function to update the data in
2471 a form specified by FormSetGuid, FormId and Label.
2472
2473 @param FormSetGuid The optional Formset GUID.
2474 @param FormId The Form ID.
2475 @param Package The package header.
2476
2477 @param TempPacakge The resultant package.
2478
2479 @retval EFI_SUCCESS The function completes successfully.
2480
2481 **/
2482 EFI_STATUS
2483 EFIAPI
2484 InternalHiiUpdateFormPackageData (
2485 IN EFI_GUID *FormSetGuid, OPTIONAL
2486 IN EFI_FORM_ID FormId,
2487 IN EFI_HII_PACKAGE_HEADER *Package,
2488 IN HII_LIB_OPCODE_BUFFER *OpCodeBufferStart,
2489 IN HII_LIB_OPCODE_BUFFER *OpCodeBufferEnd, OPTIONAL
2490 OUT EFI_HII_PACKAGE_HEADER *TempPackage
2491 )
2492 {
2493 UINTN AddSize;
2494 UINT8 *BufferPos;
2495 EFI_HII_PACKAGE_HEADER PackageHeader;
2496 UINTN Offset;
2497 EFI_IFR_OP_HEADER *IfrOpHdr;
2498 EFI_IFR_OP_HEADER *UpdateIfrOpHdr;
2499 BOOLEAN GetFormSet;
2500 BOOLEAN GetForm;
2501 BOOLEAN Updated;
2502 EFI_IFR_OP_HEADER *AddOpCode;
2503 UINT32 UpdatePackageLength;
2504
2505 CopyMem (TempPackage, Package, sizeof (EFI_HII_PACKAGE_HEADER));
2506 UpdatePackageLength = sizeof (EFI_HII_PACKAGE_HEADER);
2507 BufferPos = (UINT8 *) (TempPackage + 1);
2508
2509 CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));
2510 IfrOpHdr = (EFI_IFR_OP_HEADER *)((UINT8 *) Package + sizeof (EFI_HII_PACKAGE_HEADER));
2511 Offset = sizeof (EFI_HII_PACKAGE_HEADER);
2512 GetFormSet = (BOOLEAN) ((FormSetGuid == NULL) ? TRUE : FALSE);
2513 GetForm = FALSE;
2514 Updated = FALSE;
2515
2516 while (Offset < PackageHeader.Length) {
2517 CopyMem (BufferPos, IfrOpHdr, IfrOpHdr->Length);
2518 BufferPos += IfrOpHdr->Length;
2519 UpdatePackageLength += IfrOpHdr->Length;
2520
2521 //
2522 // Find the matched FormSet and Form
2523 //
2524 if ((IfrOpHdr->OpCode == EFI_IFR_FORM_SET_OP) && (FormSetGuid != NULL)) {
2525 if (CompareGuid((GUID *)(VOID *)&((EFI_IFR_FORM_SET *) IfrOpHdr)->Guid, FormSetGuid)) {
2526 GetFormSet = TRUE;
2527 } else {
2528 GetFormSet = FALSE;
2529 }
2530 } else if (IfrOpHdr->OpCode == EFI_IFR_FORM_OP) {
2531 if (CompareMem (&((EFI_IFR_FORM *) IfrOpHdr)->FormId, &FormId, sizeof (EFI_FORM_ID)) == 0) {
2532 GetForm = TRUE;
2533 } else {
2534 GetForm = FALSE;
2535 }
2536 }
2537
2538 //
2539 // The matched Form is found, and Update data in this form
2540 //
2541 if (GetFormSet && GetForm && !Updated) {
2542 UpdateIfrOpHdr = (EFI_IFR_OP_HEADER *) OpCodeBufferStart->Buffer;
2543 if ((UpdateIfrOpHdr->Length == IfrOpHdr->Length) && \
2544 (CompareMem (IfrOpHdr, UpdateIfrOpHdr, UpdateIfrOpHdr->Length) == 0)) {
2545 //
2546 // Remove the original data when End OpCode buffer exist.
2547 //
2548 if (OpCodeBufferEnd != NULL) {
2549 Offset += IfrOpHdr->Length;
2550 IfrOpHdr = (EFI_IFR_OP_HEADER *) ((UINT8 *) (IfrOpHdr) + IfrOpHdr->Length);
2551 UpdateIfrOpHdr = (EFI_IFR_OP_HEADER *) OpCodeBufferEnd->Buffer;
2552 while (Offset < PackageHeader.Length) {
2553 //
2554 // Search the matched end opcode
2555 //
2556 if ((UpdateIfrOpHdr->Length == IfrOpHdr->Length) && \
2557 (CompareMem (IfrOpHdr, UpdateIfrOpHdr, UpdateIfrOpHdr->Length) == 0)) {
2558 break;
2559 }
2560 //
2561 // Go to the next Op-Code
2562 //
2563 Offset += IfrOpHdr->Length;
2564 IfrOpHdr = (EFI_IFR_OP_HEADER *) ((UINT8 *) (IfrOpHdr) + IfrOpHdr->Length);
2565 }
2566
2567 if (Offset >= PackageHeader.Length) {
2568 //
2569 // The end opcode is not found.
2570 //
2571 return EFI_NOT_FOUND;
2572 }
2573 }
2574 //
2575 // Insert the updated data
2576 //
2577 UpdateIfrOpHdr = (EFI_IFR_OP_HEADER *) OpCodeBufferStart->Buffer;
2578 AddOpCode = (EFI_IFR_OP_HEADER *) (OpCodeBufferStart->Buffer + UpdateIfrOpHdr->Length);
2579 AddSize = UpdateIfrOpHdr->Length;
2580 while (AddSize < OpCodeBufferStart->Position) {
2581 CopyMem (BufferPos, AddOpCode, AddOpCode->Length);
2582 BufferPos += AddOpCode->Length;
2583 UpdatePackageLength += AddOpCode->Length;
2584
2585 AddOpCode = (EFI_IFR_OP_HEADER *) ((UINT8 *) (AddOpCode) + AddOpCode->Length);
2586 AddSize += AddOpCode->Length;
2587 }
2588
2589 if (OpCodeBufferEnd != NULL) {
2590 //
2591 // Add the end opcode
2592 //
2593 CopyMem (BufferPos, IfrOpHdr, IfrOpHdr->Length);
2594 BufferPos += IfrOpHdr->Length;
2595 UpdatePackageLength += IfrOpHdr->Length;
2596 }
2597 //
2598 // Set update flag
2599 //
2600 Updated = TRUE;
2601 }
2602 }
2603
2604 //
2605 // Go to the next Op-Code
2606 //
2607 Offset += IfrOpHdr->Length;
2608 IfrOpHdr = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (IfrOpHdr) + IfrOpHdr->Length);
2609 }
2610
2611 if (!Updated) {
2612 //
2613 // The updated opcode buffer is not found.
2614 //
2615 return EFI_NOT_FOUND;
2616 }
2617 //
2618 // Update the package length.
2619 //
2620 PackageHeader.Length = UpdatePackageLength;
2621 CopyMem (TempPackage, &PackageHeader, sizeof (EFI_HII_PACKAGE_HEADER));
2622
2623 return EFI_SUCCESS;
2624 }
2625
2626 /**
2627 This function updates a form that has previously been registered with the HII
2628 Database. This function will perform at most one update operation.
2629
2630 The form to update is specified by Handle, FormSetGuid, and FormId. Binary
2631 comparisons of IFR opcodes are performed from the beginning of the form being
2632 updated until an IFR opcode is found that exactly matches the first IFR opcode
2633 specifed by StartOpCodeHandle. The following rules are used to determine if
2634 an insert, replace, or delete operation is performed.
2635
2636 1) If no matches are found, then NULL is returned.
2637 2) If a match is found, and EndOpCodeHandle is NULL, then all of the IFR opcodes
2638 from StartOpcodeHandle except the first opcode are inserted immediately after
2639 the matching IFR opcode in the form beng updated.
2640 3) If a match is found, and EndOpCodeHandle is not NULL, then a search is made
2641 from the matching IFR opcode until an IFR opcode exatly matches the first
2642 IFR opcode specified by EndOpCodeHandle. If no match is found for the first
2643 IFR opcode specified by EndOpCodeHandle, then NULL is returned. If a match
2644 is found, then all of the IFR opcodes between the start match and the end
2645 match are deleted from the form being updated and all of the IFR opcodes
2646 from StartOpcodeHandle except the first opcode are inserted immediately after
2647 the matching start IFR opcode. If StartOpCcodeHandle only contains one
2648 IFR instruction, then the result of ths operation will delete all of the IFR
2649 opcodes between the start end matches.
2650
2651 If HiiHandle is NULL, then ASSERT().
2652 If StartOpCodeHandle is NULL, then ASSERT().
2653
2654 @param[in] HiiHandle The HII Handle of the form to update.
2655 @param[in] FormSetGuid The Formset GUID of the form to update. This
2656 is an optional parameter that may be NULL.
2657 If it is NULL, all FormSet will be updated.
2658 @param[in] FormId The ID of the form to update.
2659 @param[in] StartOpCodeHandle An OpCode Handle that contains the set of IFR
2660 opcodes to be inserted or replaced in the form.
2661 The first IFR instruction in StartOpCodeHandle
2662 is used to find matching IFR opcode in the
2663 form.
2664 @param[in] EndOpCodeHandle An OpCcode Handle that contains the IFR opcode
2665 that marks the end of a replace operation in
2666 the form. This is an optional parameter that
2667 may be NULL. If it is NULL, then an the IFR
2668 opcodes specified by StartOpCodeHandle are
2669 inserted into the form.
2670
2671 @retval EFI_OUT_OF_RESOURCES No enough memory resource is allocated.
2672 @retval EFI_NOT_FOUND The following cases will return EFI_NOT_FOUND.
2673 1) The form specified by HiiHandle, FormSetGuid,
2674 and FormId could not be found in the HII Database.
2675 2) No IFR opcodes in the target form match the first
2676 IFR opcode in StartOpCodeHandle.
2677 3) EndOpCOde is not NULL, and no IFR opcodes in the
2678 target form following a matching start opcode match
2679 the first IFR opcode in EndOpCodeHandle.
2680 @retval EFI_SUCCESS The matched form is updated by StartOpcode.
2681
2682 **/
2683 EFI_STATUS
2684 EFIAPI
2685 HiiUpdateForm (
2686 IN EFI_HII_HANDLE HiiHandle,
2687 IN EFI_GUID *FormSetGuid, OPTIONAL
2688 IN EFI_FORM_ID FormId,
2689 IN VOID *StartOpcodeHandle,
2690 IN VOID *EndOpcodeHandle OPTIONAL
2691 )
2692 {
2693 EFI_STATUS Status;
2694 EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;
2695 UINT32 PackageListLength;
2696 UINT32 Offset;
2697 EFI_HII_PACKAGE_LIST_HEADER *UpdatePackageList;
2698 UINTN BufferSize;
2699 UINT8 *UpdateBufferPos;
2700 EFI_HII_PACKAGE_HEADER *Package;
2701 EFI_HII_PACKAGE_HEADER *TempPacakge;
2702 EFI_HII_PACKAGE_HEADER PackageHeader;
2703 BOOLEAN Updated;
2704 HII_LIB_OPCODE_BUFFER *OpCodeBufferStart;
2705 HII_LIB_OPCODE_BUFFER *OpCodeBufferEnd;
2706
2707 //
2708 // Input update data can't be NULL.
2709 //
2710 ASSERT (HiiHandle != NULL);
2711 ASSERT (StartOpcodeHandle != NULL);
2712 UpdatePackageList = NULL;
2713 TempPacakge = NULL;
2714 HiiPackageList = NULL;
2715
2716 //
2717 // Restrive buffer data from Opcode Handle
2718 //
2719 OpCodeBufferStart = (HII_LIB_OPCODE_BUFFER *) StartOpcodeHandle;
2720 OpCodeBufferEnd = (HII_LIB_OPCODE_BUFFER *) EndOpcodeHandle;
2721
2722 //
2723 // Get the orginal package list
2724 //
2725 BufferSize = 0;
2726 HiiPackageList = NULL;
2727 Status = gHiiDatabase->ExportPackageLists (gHiiDatabase, HiiHandle, &BufferSize, HiiPackageList);
2728 //
2729 // The return status should always be EFI_BUFFER_TOO_SMALL as input buffer's size is 0.
2730 //
2731 if (Status != EFI_BUFFER_TOO_SMALL) {
2732 return Status;
2733 }
2734
2735 HiiPackageList = AllocatePool (BufferSize);
2736 if (HiiPackageList == NULL) {
2737 Status = EFI_OUT_OF_RESOURCES;
2738 goto Finish;
2739 }
2740
2741 Status = gHiiDatabase->ExportPackageLists (gHiiDatabase, HiiHandle, &BufferSize, HiiPackageList);
2742 if (EFI_ERROR (Status)) {
2743 goto Finish;
2744 }
2745
2746 //
2747 // Calculate and allocate space for retrieval of IFR data
2748 //
2749 BufferSize += OpCodeBufferStart->Position;
2750 UpdatePackageList = AllocateZeroPool (BufferSize);
2751 if (UpdatePackageList == NULL) {
2752 Status = EFI_OUT_OF_RESOURCES;
2753 goto Finish;
2754 }
2755
2756 //
2757 // Allocate temp buffer to store the temp updated package buffer
2758 //
2759 TempPacakge = AllocateZeroPool (BufferSize);
2760 if (TempPacakge == NULL) {
2761 Status = EFI_OUT_OF_RESOURCES;
2762 goto Finish;
2763 }
2764
2765 UpdateBufferPos = (UINT8 *) UpdatePackageList;
2766
2767 //
2768 // Copy the package list header
2769 //
2770 CopyMem (UpdateBufferPos, HiiPackageList, sizeof (EFI_HII_PACKAGE_LIST_HEADER));
2771 UpdateBufferPos += sizeof (EFI_HII_PACKAGE_LIST_HEADER);
2772
2773 //
2774 // Go through each package to find the matched pacakge and update one by one
2775 //
2776 Updated = FALSE;
2777 Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);
2778 PackageListLength = ReadUnaligned32 (&HiiPackageList->PackageLength);
2779 while (Offset < PackageListLength) {
2780 Package = (EFI_HII_PACKAGE_HEADER *) (((UINT8 *) HiiPackageList) + Offset);
2781 CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));
2782 Offset += Package->Length;
2783
2784 if (Package->Type == EFI_HII_PACKAGE_FORMS) {
2785 //
2786 // Check this package is the matched package.
2787 //
2788 Status = InternalHiiUpdateFormPackageData (FormSetGuid, FormId, Package, OpCodeBufferStart, OpCodeBufferEnd, TempPacakge);
2789 //
2790 // The matched package is found. Its pacakge buffer will be updated by the input new data.
2791 //
2792 if (!EFI_ERROR(Status)) {
2793 //
2794 // Set Update Flag
2795 //
2796 Updated = TRUE;
2797 //
2798 // Add updated package buffer
2799 //
2800 Package = TempPacakge;
2801 }
2802 }
2803
2804 //
2805 // Add pacakge buffer
2806 //
2807 CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));
2808 CopyMem (UpdateBufferPos, Package, PackageHeader.Length);
2809 UpdateBufferPos += PackageHeader.Length;
2810 }
2811
2812 if (Updated) {
2813 //
2814 // Update package list length
2815 //
2816 BufferSize = UpdateBufferPos - (UINT8 *) UpdatePackageList;
2817 WriteUnaligned32 (&UpdatePackageList->PackageLength, (UINT32) BufferSize);
2818
2819 //
2820 // Update Pacakge to show form
2821 //
2822 Status = gHiiDatabase->UpdatePackageList (gHiiDatabase, HiiHandle, UpdatePackageList);
2823 } else {
2824 //
2825 // Not matched form is found and updated.
2826 //
2827 Status = EFI_NOT_FOUND;
2828 }
2829
2830 Finish:
2831 if (HiiPackageList != NULL) {
2832 FreePool (HiiPackageList);
2833 }
2834
2835 if (UpdatePackageList != NULL) {
2836 FreePool (UpdatePackageList);
2837 }
2838
2839 if (TempPacakge != NULL) {
2840 FreePool (TempPacakge);
2841 }
2842
2843 return Status;
2844 }
2845
2846 /**
2847 Configure the buffer accrording to ConfigBody strings in the format of
2848 <Length:4 bytes>, <Offset: 2 bytes>, <Width:2 bytes>, <Data:n bytes>.
2849 This ConfigBody strings is generated by UEFI VfrCompiler for the default
2850 values in a Form Set. The name of the ConfigBody strings is VfrMyIfrNVDataDefault0000
2851 constructed following this rule:
2852 "Vfr" + varstore.name + "Default" + defaultstore.attributes.
2853 Check the generated C file in Output for details.
2854
2855 @param Buffer The start address of buffer.
2856 @param BufferSize The size of buffer.
2857 @param Number The number of the strings.
2858 @param ... Variable argument list for default value in <AltResp> format
2859 generated by the tool.
2860
2861 @retval EFI_BUFFER_TOO_SMALL the BufferSize is too small to operate.
2862 @retval EFI_INVALID_PARAMETER Buffer is NULL or BufferSize is 0.
2863 @retval EFI_SUCCESS Operation successful.
2864
2865 **/
2866 EFI_STATUS
2867 EFIAPI
2868 HiiIfrLibExtractDefault(
2869 IN VOID *Buffer,
2870 IN UINTN *BufferSize,
2871 UINTN Number,
2872 ...
2873 )
2874 {
2875 VA_LIST Args;
2876 UINTN Index;
2877 UINT32 TotalLen;
2878 UINT8 *BufCfgArray;
2879 UINT8 *BufferPos;
2880 UINT16 Offset;
2881 UINT16 Width;
2882 UINT8 *Value;
2883
2884 if ((Buffer == NULL) || (BufferSize == NULL)) {
2885 return EFI_INVALID_PARAMETER;
2886 }
2887
2888 Offset = 0;
2889 Width = 0;
2890 Value = NULL;
2891
2892 VA_START (Args, Number);
2893 for (Index = 0; Index < Number; Index++) {
2894 BufCfgArray = (UINT8 *) VA_ARG (Args, VOID *);
2895 TotalLen = ReadUnaligned32 ((UINT32 *)BufCfgArray);
2896 BufferPos = BufCfgArray + sizeof (UINT32);
2897
2898 while ((UINT32)(BufferPos - BufCfgArray) < TotalLen) {
2899 Offset = ReadUnaligned16 ((UINT16 *)BufferPos);
2900 BufferPos += sizeof (UINT16);
2901 Width = ReadUnaligned16 ((UINT16 *)BufferPos);
2902 BufferPos += sizeof (UINT16);
2903 Value = BufferPos;
2904 BufferPos += Width;
2905
2906 if ((UINTN)(Offset + Width) > *BufferSize) {
2907 return EFI_BUFFER_TOO_SMALL;
2908 }
2909
2910 CopyMem ((UINT8 *)Buffer + Offset, Value, Width);
2911 }
2912 }
2913 VA_END (Args);
2914
2915 *BufferSize = (UINTN)Offset;
2916
2917 return EFI_SUCCESS;
2918 }