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