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