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