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