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