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