]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Library/UefiHiiLib/HiiLib.c
IntelFrameworkModulePkg: Replace [Ascii|Unicode]ValueToString
[mirror_edk2.git] / MdeModulePkg / Library / UefiHiiLib / HiiLib.c
CommitLineData
08e4b3cf 1/** @file\r
2 HII Library implementation that uses DXE protocols and services.\r
3\r
ae9026dd 4 Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>\r
cd5ebaa0 5 This program and the accompanying materials\r
08e4b3cf 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 "InternalHiiLib.h"\r
16\r
84f9a9ec
LG
17#define GUID_CONFIG_STRING_TYPE 0x00\r
18#define NAME_CONFIG_STRING_TYPE 0x01\r
19#define PATH_CONFIG_STRING_TYPE 0x02\r
20\r
21#define ACTION_SET_DEFAUTL_VALUE 0x01\r
22#define ACTION_VALIDATE_SETTING 0x02\r
23\r
24#define HII_LIB_DEFAULT_VARSTORE_SIZE 0x200\r
25\r
26typedef struct {\r
27 LIST_ENTRY Entry; // Link to Block array\r
28 UINT16 Offset;\r
29 UINT16 Width;\r
30 UINT8 OpCode;\r
31 UINT8 Scope;\r
32} IFR_BLOCK_DATA;\r
33\r
82e8c138
ED
34typedef struct {\r
35 EFI_VARSTORE_ID VarStoreId;\r
36 UINT16 Size;\r
37} IFR_VARSTORAGE_DATA;\r
38\r
7e3bcccb
LG
39//\r
40// <ConfigHdr> Template\r
41//\r
42GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR16 mConfigHdrTemplate[] = L"GUID=00000000000000000000000000000000&NAME=0000&PATH=00";\r
08e4b3cf 43\r
cb7d01c0 44EFI_FORM_BROWSER2_PROTOCOL *mUefiFormBrowser2 = NULL;\r
45\r
7e3bcccb 46//\r
cb7d01c0 47// Template used to mark the end of a list of packages \r
7e3bcccb 48//\r
cb7d01c0 49GLOBAL_REMOVE_IF_UNREFERENCED CONST EFI_HII_PACKAGE_HEADER mEndOfPakageList = {\r
50 sizeof (EFI_HII_PACKAGE_HEADER),\r
51 EFI_HII_PACKAGE_END\r
52};\r
08e4b3cf 53\r
84f9a9ec
LG
54/**\r
55 Extract Hii package list GUID for given HII handle.\r
56\r
57 If HiiHandle could not be found in the HII database, then ASSERT.\r
58 If Guid is NULL, then ASSERT.\r
59\r
60 @param Handle Hii handle\r
61 @param Guid Package list GUID\r
62\r
63 @retval EFI_SUCCESS Successfully extract GUID from Hii database.\r
64\r
65**/\r
66EFI_STATUS\r
67EFIAPI\r
68InternalHiiExtractGuidFromHiiHandle (\r
69 IN EFI_HII_HANDLE Handle,\r
70 OUT EFI_GUID *Guid\r
71 )\r
72{\r
73 EFI_STATUS Status;\r
74 UINTN BufferSize;\r
75 EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;\r
76\r
77 ASSERT (Guid != NULL);\r
78 ASSERT (Handle != NULL);\r
79\r
80 //\r
81 // Get HII PackageList\r
82 //\r
83 BufferSize = 0;\r
84 HiiPackageList = NULL;\r
85\r
86 Status = gHiiDatabase->ExportPackageLists (gHiiDatabase, Handle, &BufferSize, HiiPackageList);\r
87 ASSERT (Status != EFI_NOT_FOUND);\r
88 \r
89 if (Status == EFI_BUFFER_TOO_SMALL) {\r
90 HiiPackageList = AllocatePool (BufferSize);\r
91 ASSERT (HiiPackageList != NULL);\r
92\r
93 Status = gHiiDatabase->ExportPackageLists (gHiiDatabase, Handle, &BufferSize, HiiPackageList);\r
94 }\r
95 if (EFI_ERROR (Status)) {\r
96 FreePool (HiiPackageList);\r
97 return Status;\r
98 }\r
99\r
100 //\r
101 // Extract GUID\r
102 //\r
103 CopyGuid (Guid, &HiiPackageList->PackageListGuid);\r
104\r
105 FreePool (HiiPackageList);\r
106\r
107 return EFI_SUCCESS;\r
108}\r
109\r
08e4b3cf 110/**\r
cb7d01c0 111 Registers a list of packages in the HII Database and returns the HII Handle\r
112 associated with that registration. If an HII Handle has already been registered\r
aa2614b7 113 with the same PackageListGuid and DeviceHandle, then NULL is returned. If there\r
114 are not enough resources to perform the registration, then NULL is returned.\r
115 If an empty list of packages is passed in, then NULL is returned. If the size of\r
116 the list of package is 0, then NULL is returned.\r
cb7d01c0 117\r
118 The variable arguments are pointers which point to package header that defined \r
119 by UEFI VFR compiler and StringGather tool.\r
08e4b3cf 120\r
121 #pragma pack (push, 1)\r
122 typedef struct {\r
123 UINT32 BinaryLength;\r
124 EFI_HII_PACKAGE_HEADER PackageHeader;\r
125 } EDKII_AUTOGEN_PACKAGES_HEADER;\r
126 #pragma pack (pop)\r
cb7d01c0 127 \r
128 @param[in] PackageListGuid The GUID of the package list.\r
129 @param[in] DeviceHandle If not NULL, the Device Handle on which \r
130 an instance of DEVICE_PATH_PROTOCOL is installed.\r
131 This Device Handle uniquely defines the device that \r
132 the added packages are associated with.\r
133 @param[in] ... The variable argument list that contains pointers \r
134 to packages terminated by a NULL.\r
135\r
136 @retval NULL A HII Handle has already been registered in the HII Database with\r
9c6595dc 137 the same PackageListGuid and DeviceHandle.\r
cb7d01c0 138 @retval NULL The HII Handle could not be created.\r
139 @retval NULL An empty list of packages was passed in.\r
140 @retval NULL All packages are empty.\r
141 @retval Other The HII Handle associated with the newly registered package list.\r
08e4b3cf 142\r
143**/\r
cb7d01c0 144EFI_HII_HANDLE\r
145EFIAPI\r
146HiiAddPackages (\r
147 IN CONST EFI_GUID *PackageListGuid,\r
148 IN EFI_HANDLE DeviceHandle OPTIONAL,\r
149 ...\r
08e4b3cf 150 )\r
151{\r
cb7d01c0 152 EFI_STATUS Status;\r
cb7d01c0 153 VA_LIST Args;\r
154 UINT32 *Package;\r
155 EFI_HII_PACKAGE_LIST_HEADER *PackageListHeader;\r
156 EFI_HII_HANDLE HiiHandle;\r
157 UINT32 Length;\r
158 UINT8 *Data;\r
08e4b3cf 159\r
cb7d01c0 160 ASSERT (PackageListGuid != NULL);\r
08e4b3cf 161\r
08e4b3cf 162 //\r
cb7d01c0 163 // Calculate the length of all the packages in the variable argument list\r
08e4b3cf 164 //\r
cb7d01c0 165 for (Length = 0, VA_START (Args, DeviceHandle); (Package = VA_ARG (Args, UINT32 *)) != NULL; ) {\r
166 Length += (ReadUnaligned32 (Package) - sizeof (UINT32));\r
167 }\r
168 VA_END (Args);\r
08e4b3cf 169\r
08e4b3cf 170 //\r
cb7d01c0 171 // If there are no packages in the variable argument list or all the packages \r
172 // are empty, then return a NULL HII Handle\r
08e4b3cf 173 //\r
cb7d01c0 174 if (Length == 0) {\r
175 return NULL;\r
08e4b3cf 176 }\r
177\r
178 //\r
cb7d01c0 179 // Add the length of the Package List Header and the terminating Package Header \r
08e4b3cf 180 //\r
cb7d01c0 181 Length += sizeof (EFI_HII_PACKAGE_LIST_HEADER) + sizeof (EFI_HII_PACKAGE_HEADER);\r
08e4b3cf 182\r
cb7d01c0 183 //\r
184 // Allocate the storage for the entire Package List\r
185 //\r
186 PackageListHeader = AllocateZeroPool (Length);\r
08e4b3cf 187\r
cb7d01c0 188 //\r
aa2614b7 189 // If the Package List can not be allocated, then return a NULL HII Handle\r
cb7d01c0 190 //\r
191 if (PackageListHeader == NULL) {\r
192 return NULL;\r
193 }\r
08e4b3cf 194\r
cb7d01c0 195 //\r
196 // Fill in the GUID and Length of the Package List Header\r
197 //\r
198 CopyGuid (&PackageListHeader->PackageListGuid, PackageListGuid);\r
199 PackageListHeader->PackageLength = Length;\r
08e4b3cf 200\r
cb7d01c0 201 //\r
202 // Initialize a pointer to the beginning if the Package List data\r
203 //\r
204 Data = (UINT8 *)(PackageListHeader + 1);\r
08e4b3cf 205\r
cb7d01c0 206 //\r
207 // Copy the data from each package in the variable argument list\r
208 //\r
209 for (VA_START (Args, DeviceHandle); (Package = VA_ARG (Args, UINT32 *)) != NULL; ) {\r
210 Length = ReadUnaligned32 (Package) - sizeof (UINT32);\r
211 CopyMem (Data, Package + 1, Length);\r
212 Data += Length;\r
213 }\r
214 VA_END (Args);\r
08e4b3cf 215\r
cb7d01c0 216 //\r
217 // Append a package of type EFI_HII_PACKAGE_END to mark the end of the package list\r
218 //\r
219 CopyMem (Data, &mEndOfPakageList, sizeof (mEndOfPakageList));\r
08e4b3cf 220\r
cb7d01c0 221 //\r
222 // Register the package list with the HII Database\r
223 //\r
224 Status = gHiiDatabase->NewPackageList (\r
225 gHiiDatabase, \r
226 PackageListHeader, \r
227 DeviceHandle, \r
228 &HiiHandle\r
229 );\r
230 if (EFI_ERROR (Status)) {\r
231 HiiHandle = NULL;\r
08e4b3cf 232 }\r
233\r
cb7d01c0 234 //\r
235 // Free the allocated package list\r
236 //\r
08e4b3cf 237 FreePool (PackageListHeader);\r
cb7d01c0 238\r
239 //\r
240 // Return the new HII Handle\r
241 //\r
242 return HiiHandle;\r
08e4b3cf 243}\r
244\r
245/**\r
cb7d01c0 246 Removes a package list from the HII database.\r
08e4b3cf 247\r
248 If HiiHandle is NULL, then ASSERT.\r
cb7d01c0 249 If HiiHandle is not a valid EFI_HII_HANDLE in the HII database, then ASSERT.\r
08e4b3cf 250\r
cb7d01c0 251 @param[in] HiiHandle The handle that was previously registered in the HII database\r
08e4b3cf 252\r
253**/\r
254VOID\r
255EFIAPI\r
cb7d01c0 256HiiRemovePackages (\r
08e4b3cf 257 IN EFI_HII_HANDLE HiiHandle\r
258 )\r
259{\r
260 EFI_STATUS Status;\r
08e4b3cf 261\r
cb7d01c0 262 ASSERT (HiiHandle != NULL);\r
7e3bcccb 263 Status = gHiiDatabase->RemovePackageList (gHiiDatabase, HiiHandle);\r
08e4b3cf 264 ASSERT_EFI_ERROR (Status);\r
265}\r
266\r
267\r
268/**\r
7992c0b0 269 Retrieves the array of all the HII Handles or the HII handles of a specific\r
270 package list GUID in the HII Database.\r
cb7d01c0 271 This array is terminated with a NULL HII Handle.\r
272 This function allocates the returned array using AllocatePool().\r
273 The caller is responsible for freeing the array with FreePool().\r
274\r
275 @param[in] PackageListGuid An optional parameter that is used to request \r
7992c0b0 276 HII Handles associated with a specific\r
277 Package List GUID. If this parameter is NULL,\r
cb7d01c0 278 then all the HII Handles in the HII Database\r
7992c0b0 279 are returned. If this parameter is not NULL,\r
280 then zero or more HII Handles associated with \r
281 PackageListGuid are returned.\r
cb7d01c0 282\r
283 @retval NULL No HII handles were found in the HII database\r
284 @retval NULL The array of HII Handles could not be retrieved\r
285 @retval Other A pointer to the NULL terminated array of HII Handles\r
08e4b3cf 286\r
287**/\r
cb7d01c0 288EFI_HII_HANDLE *\r
08e4b3cf 289EFIAPI\r
cb7d01c0 290HiiGetHiiHandles (\r
291 IN CONST EFI_GUID *PackageListGuid OPTIONAL\r
08e4b3cf 292 )\r
293{\r
cb7d01c0 294 EFI_STATUS Status;\r
295 UINTN HandleBufferLength;\r
296 EFI_HII_HANDLE TempHiiHandleBuffer;\r
297 EFI_HII_HANDLE *HiiHandleBuffer;\r
298 EFI_GUID Guid;\r
7992c0b0 299 UINTN Index1;\r
300 UINTN Index2;\r
cb7d01c0 301\r
302 //\r
303 // Retrieve the size required for the buffer of all HII handles.\r
304 //\r
305 HandleBufferLength = 0;\r
306 Status = gHiiDatabase->ListPackageLists (\r
307 gHiiDatabase,\r
308 EFI_HII_PACKAGE_TYPE_ALL,\r
309 NULL,\r
310 &HandleBufferLength,\r
311 &TempHiiHandleBuffer\r
312 );\r
08e4b3cf 313\r
cb7d01c0 314 //\r
315 // If ListPackageLists() returns EFI_SUCCESS for a zero size, \r
316 // then there are no HII handles in the HII database. If ListPackageLists() \r
317 // returns an error other than EFI_BUFFER_TOO_SMALL, then there are no HII \r
318 // handles in the HII database.\r
319 //\r
320 if (Status != EFI_BUFFER_TOO_SMALL) {\r
321 //\r
322 // Return NULL if the size can not be retrieved, or if there are no HII \r
323 // handles in the HII Database\r
324 //\r
325 return NULL;\r
326 }\r
08e4b3cf 327\r
cb7d01c0 328 //\r
329 // Allocate the array of HII handles to hold all the HII Handles and a NULL terminator\r
330 //\r
331 HiiHandleBuffer = AllocateZeroPool (HandleBufferLength + sizeof (EFI_HII_HANDLE));\r
332 if (HiiHandleBuffer == NULL) {\r
333 //\r
334 // Return NULL if allocation fails.\r
335 //\r
336 return NULL;\r
337 }\r
08e4b3cf 338\r
339 //\r
cb7d01c0 340 // Retrieve the array of HII Handles in the HII Database\r
08e4b3cf 341 //\r
7e3bcccb 342 Status = gHiiDatabase->ListPackageLists (\r
cb7d01c0 343 gHiiDatabase,\r
344 EFI_HII_PACKAGE_TYPE_ALL,\r
345 NULL,\r
346 &HandleBufferLength,\r
347 HiiHandleBuffer\r
348 );\r
349 if (EFI_ERROR (Status)) {\r
350 //\r
351 // Free the buffer and return NULL if the HII handles can not be retrieved.\r
352 //\r
353 FreePool (HiiHandleBuffer);\r
354 return NULL;\r
fa7b3168 355 }\r
08e4b3cf 356\r
cb7d01c0 357 if (PackageListGuid == NULL) {\r
358 //\r
359 // Return the NULL terminated array of HII handles in the HII Database\r
360 //\r
361 return HiiHandleBuffer;\r
362 } else {\r
7992c0b0 363 for (Index1 = 0, Index2 = 0; HiiHandleBuffer[Index1] != NULL; Index1++) {\r
364 Status = InternalHiiExtractGuidFromHiiHandle (HiiHandleBuffer[Index1], &Guid);\r
cb7d01c0 365 ASSERT_EFI_ERROR (Status);\r
366 if (CompareGuid (&Guid, PackageListGuid)) {\r
7992c0b0 367 HiiHandleBuffer[Index2++] = HiiHandleBuffer[Index1]; \r
cb7d01c0 368 }\r
369 }\r
7992c0b0 370 if (Index2 > 0) {\r
371 HiiHandleBuffer[Index2] = NULL;\r
372 return HiiHandleBuffer;\r
373 } else {\r
374 FreePool (HiiHandleBuffer);\r
375 return NULL;\r
376 }\r
cb7d01c0 377 }\r
08e4b3cf 378}\r
379\r
8a458283
DB
380/**\r
381 This function allows a caller to extract the form set opcode form the Hii Handle.\r
382 The returned buffer is allocated using AllocatePool().The caller is responsible \r
383 for freeing the allocated buffer using FreePool().\r
384\r
385 @param Handle The HII handle.\r
3b28e744 386 @param Buffer On return, points to a pointer which point to the buffer that contain the formset opcode.\r
8a458283
DB
387 @param BufferSize On return, points to the length of the buffer.\r
388\r
389 @retval EFI_OUT_OF_RESOURCES No enough memory resource is allocated.\r
390 @retval EFI_NOT_FOUND Can't find the package data for the input Handle.\r
391 @retval EFI_INVALID_PARAMETER The input parameters are not correct.\r
3b28e744 392 @retval EFI_SUCCESS Get the formset opcode from the hii handle successfully.\r
8a458283
DB
393\r
394**/\r
395EFI_STATUS\r
396EFIAPI\r
397HiiGetFormSetFromHiiHandle(\r
398 IN EFI_HII_HANDLE Handle,\r
399 OUT EFI_IFR_FORM_SET **Buffer,\r
400 OUT UINTN *BufferSize\r
401 )\r
402{\r
403 EFI_STATUS Status;\r
404 UINTN PackageListSize;\r
405 UINTN TempSize;\r
406 EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;\r
407 UINT8 *Package;\r
408 UINT8 *OpCodeData;\r
d6cc284e
DB
409 UINT8 *FormSetBuffer;\r
410 UINT8 *TempBuffer;\r
8a458283
DB
411 UINT32 Offset;\r
412 UINT32 Offset2;\r
413 UINT32 PackageListLength;\r
414 EFI_HII_PACKAGE_HEADER PackageHeader;\r
415\r
416 TempSize = 0;\r
417 FormSetBuffer = NULL;\r
418 TempBuffer = NULL;\r
419\r
420 //\r
421 // Get HII PackageList\r
422 //\r
423 PackageListSize = 0;\r
424 HiiPackageList = NULL;\r
425 Status = gHiiDatabase->ExportPackageLists (gHiiDatabase, Handle, &PackageListSize, HiiPackageList);\r
426 if (EFI_ERROR (Status) && (Status != EFI_BUFFER_TOO_SMALL)) {\r
427 return Status;\r
428 }\r
429\r
430 HiiPackageList = AllocatePool (PackageListSize);\r
431 if (HiiPackageList == NULL) {\r
432 return EFI_OUT_OF_RESOURCES;\r
433 }\r
434\r
435 Status = gHiiDatabase->ExportPackageLists (gHiiDatabase, Handle, &PackageListSize, HiiPackageList);\r
436 ASSERT_EFI_ERROR (Status);\r
437\r
438 //\r
439 // Get Form package from this HII package List\r
440 //\r
441 Status = EFI_NOT_FOUND;\r
442 Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);\r
443 PackageListLength = ReadUnaligned32 (&HiiPackageList->PackageLength);\r
444\r
445 while (Offset < PackageListLength) {\r
446 Package = ((UINT8 *) HiiPackageList) + Offset;\r
447 CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));\r
448 Offset += PackageHeader.Length;\r
449\r
450 if (PackageHeader.Type != EFI_HII_PACKAGE_FORMS) {\r
451 continue;\r
452 }\r
453\r
454 //\r
455 // Search FormSet Opcode in this Form Package\r
456 //\r
457 Offset2 = sizeof (EFI_HII_PACKAGE_HEADER);\r
458 while (Offset2 < PackageHeader.Length) {\r
459 OpCodeData = Package + Offset2;\r
460 Offset2 += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;\r
461\r
462 if (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode != EFI_IFR_FORM_SET_OP) {\r
463 continue;\r
464 }\r
465\r
466 if (FormSetBuffer != NULL){\r
467 TempBuffer = AllocateCopyPool (TempSize + ((EFI_IFR_OP_HEADER *) OpCodeData)->Length, FormSetBuffer);\r
8a458283 468 FreePool(FormSetBuffer);\r
ae9026dd
BD
469 FormSetBuffer = NULL;\r
470 if (TempBuffer == NULL) {\r
471 Status = EFI_OUT_OF_RESOURCES;\r
472 goto Done;\r
473 }\r
474 CopyMem (TempBuffer + TempSize, OpCodeData, ((EFI_IFR_OP_HEADER *) OpCodeData)->Length);\r
8a458283
DB
475 } else {\r
476 TempBuffer = AllocateCopyPool (TempSize + ((EFI_IFR_OP_HEADER *) OpCodeData)->Length, OpCodeData);\r
ae9026dd
BD
477 if (TempBuffer == NULL) {\r
478 Status = EFI_OUT_OF_RESOURCES;\r
479 goto Done;\r
480 }\r
8a458283
DB
481 }\r
482 TempSize += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;\r
483 FormSetBuffer = TempBuffer;\r
484\r
485 Status = EFI_SUCCESS;\r
486 //\r
487 //One form package has one formset, exit current form package to search other form package in the packagelist.\r
488 //\r
489 break;\r
490 }\r
491 }\r
ae9026dd 492Done:\r
8a458283
DB
493 FreePool (HiiPackageList);\r
494\r
495 *BufferSize = TempSize;\r
d6cc284e 496 *Buffer = (EFI_IFR_FORM_SET *)FormSetBuffer;\r
8a458283
DB
497\r
498 return Status;\r
499}\r
500\r
7e3bcccb
LG
501/**\r
502 Converts all hex dtring characters in range ['A'..'F'] to ['a'..'f'] for \r
503 hex digits that appear between a '=' and a '&' in a config string.\r
504\r
84213069 505 If ConfigString is NULL, then ASSERT().\r
7e3bcccb 506\r
84213069 507 @param[in] ConfigString Pointer to a Null-terminated Unicode string.\r
7e3bcccb
LG
508\r
509 @return Pointer to the Null-terminated Unicode result string.\r
510\r
511**/\r
512EFI_STRING\r
513EFIAPI\r
514InternalHiiLowerConfigString (\r
515 IN EFI_STRING ConfigString\r
516 )\r
517{\r
518 EFI_STRING String;\r
519 BOOLEAN Lower;\r
520\r
521 ASSERT (ConfigString != NULL);\r
522\r
523 //\r
524 // Convert all hex digits in range [A-F] in the configuration header to [a-f]\r
525 //\r
526 for (String = ConfigString, Lower = FALSE; *String != L'\0'; String++) {\r
527 if (*String == L'=') {\r
528 Lower = TRUE;\r
529 } else if (*String == L'&') {\r
530 Lower = FALSE;\r
3e3f86e0 531 } else if (Lower && *String >= L'A' && *String <= L'F') {\r
5c1ebff6 532 *String = (CHAR16) (*String - L'A' + L'a');\r
7e3bcccb
LG
533 }\r
534 }\r
535\r
536 return ConfigString;\r
537}\r
538\r
539/**\r
540 Uses the BlockToConfig() service of the Config Routing Protocol to \r
541 convert <ConfigRequest> and a buffer to a <ConfigResp>\r
542\r
543 If ConfigRequest is NULL, then ASSERT().\r
544 If Block is NULL, then ASSERT().\r
545\r
546 @param[in] ConfigRequest Pointer to a Null-terminated Unicode string.\r
547 @param[in] Block Pointer to a block of data.\r
548 @param[in] BlockSize The zie, in bytes, of Block.\r
549\r
550 @retval NULL The <ConfigResp> string could not be generated.\r
551 @retval Other Pointer to the Null-terminated Unicode <ConfigResp> string.\r
552\r
553**/\r
554EFI_STRING\r
555EFIAPI\r
556InternalHiiBlockToConfig (\r
557 IN CONST EFI_STRING ConfigRequest,\r
558 IN CONST UINT8 *Block,\r
559 IN UINTN BlockSize\r
560 )\r
561{\r
562 EFI_STATUS Status;\r
563 EFI_STRING ConfigResp;\r
564 CHAR16 *Progress;\r
565\r
566 ASSERT (ConfigRequest != NULL);\r
567 ASSERT (Block != NULL);\r
568\r
569 //\r
570 // Convert <ConfigRequest> to <ConfigResp>\r
571 //\r
572 Status = gHiiConfigRouting->BlockToConfig (\r
573 gHiiConfigRouting,\r
574 ConfigRequest,\r
575 Block,\r
576 BlockSize,\r
577 &ConfigResp,\r
578 &Progress\r
579 );\r
580 if (EFI_ERROR (Status)) {\r
581 return NULL;\r
582 }\r
583 return ConfigResp;\r
584}\r
585\r
7e3bcccb
LG
586/**\r
587 Uses the BrowserCallback() service of the Form Browser Protocol to retrieve \r
588 or set uncommitted data. If sata i being retrieved, then the buffer is \r
589 allocated using AllocatePool(). The caller is then responsible for freeing \r
590 the buffer using FreePool().\r
591\r
7e3bcccb
LG
592 @param[in] VariableGuid Pointer to an EFI_GUID structure. This is an optional \r
593 parameter that may be NULL.\r
84213069
LG
594 @param[in] VariableName Pointer to a Null-terminated Unicode string. This \r
595 is an optional parameter that may be NULL.\r
7e3bcccb
LG
596 @param[in] SetResultsData If not NULL, then this parameter specified the buffer\r
597 of uncommited data to set. If this parameter is NULL,\r
598 then the caller is requesting to get the uncommited data\r
599 from the Form Browser.\r
600\r
601 @retval NULL The uncommitted data could not be retrieved.\r
602 @retval Other A pointer to a buffer containing the uncommitted data.\r
603\r
604**/\r
605EFI_STRING\r
606EFIAPI\r
607InternalHiiBrowserCallback (\r
608 IN CONST EFI_GUID *VariableGuid, OPTIONAL\r
609 IN CONST CHAR16 *VariableName, OPTIONAL\r
610 IN CONST EFI_STRING SetResultsData OPTIONAL\r
611 )\r
612{\r
613 EFI_STATUS Status;\r
614 UINTN ResultsDataSize;\r
615 EFI_STRING ResultsData;\r
616 CHAR16 TempResultsData;\r
617\r
618 //\r
619 // Locate protocols\r
620 //\r
3c7449e4
LG
621 if (mUefiFormBrowser2 == NULL) {\r
622 Status = gBS->LocateProtocol (&gEfiFormBrowser2ProtocolGuid, NULL, (VOID **) &mUefiFormBrowser2);\r
623 if (EFI_ERROR (Status) || mUefiFormBrowser2 == NULL) {\r
7e3bcccb
LG
624 return NULL;\r
625 }\r
626 }\r
627\r
628 ResultsDataSize = 0;\r
629\r
630 if (SetResultsData != NULL) {\r
631 //\r
632 // Request to to set data in the uncommitted browser state information\r
633 //\r
634 ResultsData = SetResultsData;\r
635 } else {\r
636 //\r
637 // Retrieve the length of the buffer required ResultsData from the Browser Callback\r
638 //\r
3c7449e4
LG
639 Status = mUefiFormBrowser2->BrowserCallback (\r
640 mUefiFormBrowser2,\r
7e3bcccb
LG
641 &ResultsDataSize,\r
642 &TempResultsData,\r
643 TRUE,\r
644 VariableGuid,\r
645 VariableName\r
646 );\r
6412128a
LG
647 \r
648 if (!EFI_ERROR (Status)) {\r
649 //\r
650 // No Resluts Data, only allocate one char for '\0'\r
651 //\r
652 ResultsData = AllocateZeroPool (sizeof (CHAR16));\r
653 return ResultsData;\r
654 }\r
655\r
7e3bcccb
LG
656 if (Status != EFI_BUFFER_TOO_SMALL) {\r
657 return NULL;\r
658 }\r
659\r
660 //\r
661 // Allocate the ResultsData buffer\r
662 //\r
663 ResultsData = AllocateZeroPool (ResultsDataSize);\r
664 if (ResultsData == NULL) {\r
665 return NULL;\r
666 }\r
667 }\r
668\r
669 //\r
670 // Retrieve or set the ResultsData from the Browser Callback\r
671 //\r
3c7449e4
LG
672 Status = mUefiFormBrowser2->BrowserCallback (\r
673 mUefiFormBrowser2,\r
7e3bcccb
LG
674 &ResultsDataSize,\r
675 ResultsData,\r
676 (BOOLEAN)(SetResultsData == NULL),\r
677 VariableGuid,\r
678 VariableName\r
679 );\r
680 if (EFI_ERROR (Status)) {\r
681 return NULL;\r
682 }\r
683\r
684 return ResultsData;\r
685}\r
686\r
687/**\r
688 Allocates and returns a Null-terminated Unicode <ConfigHdr> string using routing \r
689 information that includes a GUID, an optional Unicode string name, and a device\r
690 path. The string returned is allocated with AllocatePool(). The caller is \r
691 responsible for freeing the allocated string with FreePool().\r
692 \r
693 The format of a <ConfigHdr> is as follows:\r
694\r
695 GUID=<HexCh>32&NAME=<Char>NameLength&PATH=<HexChar>DevicePathSize<Null>\r
696\r
697 @param[in] Guid Pointer to an EFI_GUID that is the routing information\r
698 GUID. Each of the 16 bytes in Guid is converted to \r
3b28e744 699 a 2 Unicode character hexadecimal string. This is\r
7e3bcccb
LG
700 an optional parameter that may be NULL.\r
701 @param[in] Name Pointer to a Null-terminated Unicode string that is \r
702 the routing information NAME. This is an optional \r
703 parameter that may be NULL. Each 16-bit Unicode \r
704 character in Name is converted to a 4 character Unicode \r
3b28e744 705 hexadecimal string.\r
7e3bcccb
LG
706 @param[in] DriverHandle The driver handle which supports a Device Path Protocol\r
707 that is the routing information PATH. Each byte of\r
708 the Device Path associated with DriverHandle is converted\r
3b28e744 709 to a 2 Unicode character hexadecimal string.\r
7e3bcccb 710\r
7e3bcccb
LG
711 @retval NULL DriverHandle does not support the Device Path Protocol.\r
712 @retval Other A pointer to the Null-terminate Unicode <ConfigHdr> string\r
713\r
714**/\r
715EFI_STRING\r
716EFIAPI\r
717HiiConstructConfigHdr (\r
718 IN CONST EFI_GUID *Guid, OPTIONAL\r
719 IN CONST CHAR16 *Name, OPTIONAL\r
720 IN EFI_HANDLE DriverHandle\r
721 )\r
722{\r
723 UINTN NameLength;\r
724 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
725 UINTN DevicePathSize;\r
726 CHAR16 *String;\r
727 CHAR16 *ReturnString;\r
728 UINTN Index;\r
729 UINT8 *Buffer;\r
5ad66ec6 730 UINTN MaxLen;\r
7e3bcccb
LG
731\r
732 //\r
733 // Compute the length of Name in Unicode characters. \r
734 // If Name is NULL, then the length is 0.\r
735 //\r
736 NameLength = 0;\r
737 if (Name != NULL) {\r
738 NameLength = StrLen (Name);\r
739 }\r
740\r
3e3f86e0
LG
741 DevicePath = NULL;\r
742 DevicePathSize = 0;\r
7e3bcccb
LG
743 //\r
744 // Retrieve DevicePath Protocol associated with DriverHandle\r
745 //\r
3e3f86e0
LG
746 if (DriverHandle != NULL) {\r
747 DevicePath = DevicePathFromHandle (DriverHandle);\r
748 if (DevicePath == NULL) {\r
749 return NULL;\r
750 }\r
751 //\r
752 // Compute the size of the device path in bytes\r
753 //\r
754 DevicePathSize = GetDevicePathSize (DevicePath);\r
7e3bcccb
LG
755 }\r
756\r
7e3bcccb
LG
757 //\r
758 // GUID=<HexCh>32&NAME=<Char>NameLength&PATH=<HexChar>DevicePathSize <Null>\r
759 // | 5 | sizeof (EFI_GUID) * 2 | 6 | NameStrLen*4 | 6 | DevicePathSize * 2 | 1 |\r
760 //\r
5ad66ec6
DB
761 MaxLen = 5 + sizeof (EFI_GUID) * 2 + 6 + NameLength * 4 + 6 + DevicePathSize * 2 + 1;\r
762 String = AllocateZeroPool (MaxLen * sizeof (CHAR16));\r
7e3bcccb
LG
763 if (String == NULL) {\r
764 return NULL;\r
765 }\r
766\r
767 //\r
768 // Start with L"GUID="\r
769 //\r
5ad66ec6
DB
770 StrCpyS (String, MaxLen, L"GUID=");\r
771 ReturnString = String;\r
7e3bcccb
LG
772 String += StrLen (String);\r
773\r
774 if (Guid != NULL) {\r
775 //\r
776 // Append Guid converted to <HexCh>32\r
777 //\r
778 for (Index = 0, Buffer = (UINT8 *)Guid; Index < sizeof (EFI_GUID); Index++) {\r
779 String += UnicodeValueToString (String, PREFIX_ZERO | RADIX_HEX, *(Buffer++), 2);\r
780 }\r
781 }\r
782 \r
783 //\r
784 // Append L"&NAME="\r
785 //\r
2d3e4cd1 786 StrCatS (ReturnString, MaxLen, L"&NAME=");\r
7e3bcccb
LG
787 String += StrLen (String);\r
788\r
789 if (Name != NULL) {\r
790 //\r
791 // Append Name converted to <Char>NameLength\r
792 //\r
793 for (; *Name != L'\0'; Name++) {\r
794 String += UnicodeValueToString (String, PREFIX_ZERO | RADIX_HEX, *Name, 4);\r
795 }\r
796 }\r
797\r
798 //\r
799 // Append L"&PATH="\r
800 //\r
2d3e4cd1 801 StrCatS (ReturnString, MaxLen, L"&PATH=");\r
7e3bcccb
LG
802 String += StrLen (String);\r
803\r
804 //\r
805 // Append the device path associated with DriverHandle converted to <HexChar>DevicePathSize\r
806 //\r
807 for (Index = 0, Buffer = (UINT8 *)DevicePath; Index < DevicePathSize; Index++) {\r
808 String += UnicodeValueToString (String, PREFIX_ZERO | RADIX_HEX, *(Buffer++), 2);\r
809 }\r
810\r
811 //\r
812 // Null terminate the Unicode string\r
813 //\r
814 *String = L'\0';\r
815\r
816 //\r
817 // Convert all hex digits in range [A-F] in the configuration header to [a-f]\r
818 //\r
819 return InternalHiiLowerConfigString (ReturnString);\r
820}\r
821\r
84f9a9ec
LG
822/**\r
823 Convert the hex UNICODE encoding string of UEFI GUID, NAME or device path \r
824 to binary buffer from <ConfigHdr>.\r
825\r
826 This is a internal function.\r
827\r
828 @param String UEFI configuration string.\r
829 @param Flag Flag specifies what type buffer will be retrieved.\r
830 @param Buffer Binary of Guid, Name or Device path.\r
831\r
832 @retval EFI_INVALID_PARAMETER Any incoming parameter is invalid.\r
833 @retval EFI_OUT_OF_RESOURCES Lake of resources to store neccesary structures.\r
834 @retval EFI_SUCCESS The buffer data is retrieved and translated to\r
835 binary format.\r
836\r
837**/\r
838EFI_STATUS\r
839InternalHiiGetBufferFromString (\r
840 IN EFI_STRING String,\r
841 IN UINT8 Flag,\r
842 OUT UINT8 **Buffer\r
843 )\r
844{\r
845 UINTN Length;\r
846 EFI_STRING ConfigHdr;\r
847 CHAR16 *StringPtr;\r
848 UINT8 *DataBuffer;\r
849 CHAR16 TemStr[5];\r
850 UINTN Index;\r
851 UINT8 DigitUint8;\r
852\r
853 if (String == NULL || Buffer == NULL) {\r
854 return EFI_INVALID_PARAMETER;\r
855 }\r
856 \r
857 DataBuffer = NULL;\r
858 StringPtr = NULL;\r
859 ConfigHdr = String;\r
860 //\r
861 // The content between 'GUID', 'NAME', 'PATH' of <ConfigHdr> and '&' of next element\r
862 // or '\0' (end of configuration string) is the UNICODE %02x bytes encoding string.\r
863 //\r
864 for (Length = 0; *String != 0 && *String != L'&'; String++, Length++);\r
865\r
866 switch (Flag) {\r
867 case GUID_CONFIG_STRING_TYPE:\r
868 case PATH_CONFIG_STRING_TYPE:\r
869 //\r
870 // The data in <ConfigHdr> is encoded as hex UNICODE %02x bytes in the same order\r
871 // as the device path and Guid resides in RAM memory.\r
872 // Translate the data into binary.\r
873 //\r
874 DataBuffer = (UINT8 *) AllocateZeroPool ((Length + 1) / 2);\r
875 if (DataBuffer == NULL) {\r
876 return EFI_OUT_OF_RESOURCES;\r
877 }\r
878 //\r
879 // Convert binary byte one by one\r
880 //\r
881 ZeroMem (TemStr, sizeof (TemStr));\r
882 for (Index = 0; Index < Length; Index ++) {\r
883 TemStr[0] = ConfigHdr[Index];\r
884 DigitUint8 = (UINT8) StrHexToUint64 (TemStr);\r
885 if ((Index & 1) == 0) {\r
886 DataBuffer [Index/2] = DigitUint8;\r
887 } else {\r
888 DataBuffer [Index/2] = (UINT8) ((DataBuffer [Index/2] << 4) + DigitUint8);\r
889 }\r
890 }\r
891 \r
892 *Buffer = DataBuffer;\r
893 break;\r
894\r
895 case NAME_CONFIG_STRING_TYPE:\r
896 //\r
897 // Convert Config String to Unicode String, e.g. "0041004200430044" => "ABCD"\r
898 // \r
899\r
900 //\r
901 // Add the tailling char L'\0'\r
902 //\r
903 DataBuffer = (UINT8 *) AllocateZeroPool ((Length/4 + 1) * sizeof (CHAR16));\r
904 if (DataBuffer == NULL) {\r
905 return EFI_OUT_OF_RESOURCES;\r
906 }\r
907 //\r
908 // Convert character one by one\r
909 //\r
910 StringPtr = (CHAR16 *) DataBuffer;\r
911 ZeroMem (TemStr, sizeof (TemStr));\r
912 for (Index = 0; Index < Length; Index += 4) {\r
5ad66ec6 913 StrnCpyS (TemStr, sizeof (TemStr) / sizeof (CHAR16), ConfigHdr + Index, 4);\r
84f9a9ec
LG
914 StringPtr[Index/4] = (CHAR16) StrHexToUint64 (TemStr);\r
915 }\r
916 //\r
917 // Add tailing L'\0' character\r
918 //\r
919 StringPtr[Index/4] = L'\0';\r
920\r
921 *Buffer = DataBuffer;\r
922 break;\r
923\r
924 default:\r
925 return EFI_INVALID_PARAMETER;\r
84f9a9ec
LG
926 }\r
927\r
928 return EFI_SUCCESS;\r
929}\r
930\r
931/**\r
932 This function checks VarOffset and VarWidth is in the block range.\r
933\r
934 @param BlockArray The block array is to be checked. \r
935 @param VarOffset Offset of var to the structure\r
936 @param VarWidth Width of var.\r
937 \r
938 @retval TRUE This Var is in the block range.\r
939 @retval FALSE This Var is not in the block range.\r
940**/\r
941BOOLEAN\r
942BlockArrayCheck (\r
943 IN IFR_BLOCK_DATA *BlockArray,\r
944 IN UINT16 VarOffset,\r
945 IN UINT16 VarWidth\r
946 )\r
947{\r
948 LIST_ENTRY *Link;\r
949 IFR_BLOCK_DATA *BlockData;\r
950 \r
951 //\r
952 // No Request Block array, all vars are got.\r
953 //\r
954 if (BlockArray == NULL) {\r
955 return TRUE;\r
956 }\r
957 \r
958 //\r
959 // Check the input var is in the request block range.\r
960 //\r
961 for (Link = BlockArray->Entry.ForwardLink; Link != &BlockArray->Entry; Link = Link->ForwardLink) {\r
962 BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);\r
963 if ((VarOffset >= BlockData->Offset) && ((VarOffset + VarWidth) <= (BlockData->Offset + BlockData->Width))) {\r
964 return TRUE;\r
965 }\r
966 }\r
967\r
968 return FALSE;\r
969}\r
970\r
971/**\r
972 Get the value of <Number> in <BlockConfig> format, i.e. the value of OFFSET\r
973 or WIDTH or VALUE.\r
974 <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>\r
975\r
976 @param ValueString String in <BlockConfig> format and points to the\r
977 first character of <Number>.\r
978 @param ValueData The output value. Caller takes the responsibility\r
979 to free memory.\r
980 @param ValueLength Length of the <Number>, in characters.\r
981\r
982 @retval EFI_OUT_OF_RESOURCES Insufficient resources to store neccessary\r
983 structures.\r
984 @retval EFI_SUCCESS Value of <Number> is outputted in Number\r
985 successfully.\r
986\r
987**/\r
988EFI_STATUS\r
989EFIAPI\r
990InternalHiiGetValueOfNumber (\r
991 IN EFI_STRING ValueString,\r
992 OUT UINT8 **ValueData,\r
993 OUT UINTN *ValueLength\r
994 )\r
995{\r
996 EFI_STRING StringPtr;\r
997 UINTN Length;\r
998 UINT8 *Buf;\r
999 UINT8 DigitUint8;\r
1000 UINTN Index;\r
1001 CHAR16 TemStr[2];\r
1002\r
1003 ASSERT (ValueString != NULL && ValueData != NULL && ValueLength != NULL);\r
1004 ASSERT (*ValueString != L'\0');\r
1005\r
1006 //\r
1007 // Get the length of value string\r
1008 //\r
1009 StringPtr = ValueString;\r
1010 while (*StringPtr != L'\0' && *StringPtr != L'&') {\r
1011 StringPtr++;\r
1012 }\r
1013 Length = StringPtr - ValueString;\r
1014 \r
1015 //\r
1016 // Allocate buffer to store the value\r
1017 //\r
1018 Buf = (UINT8 *) AllocateZeroPool ((Length + 1) / 2);\r
1019 if (Buf == NULL) {\r
1020 return EFI_OUT_OF_RESOURCES;\r
1021 }\r
1022 \r
1023 //\r
1024 // Convert character one by one to the value buffer\r
1025 //\r
1026 ZeroMem (TemStr, sizeof (TemStr));\r
1027 for (Index = 0; Index < Length; Index ++) {\r
1028 TemStr[0] = ValueString[Length - Index - 1];\r
1029 DigitUint8 = (UINT8) StrHexToUint64 (TemStr);\r
1030 if ((Index & 1) == 0) {\r
1031 Buf [Index/2] = DigitUint8;\r
1032 } else {\r
1033 Buf [Index/2] = (UINT8) ((DigitUint8 << 4) + Buf [Index/2]);\r
1034 }\r
1035 }\r
1036 \r
1037 //\r
1038 // Set the converted value and string length.\r
1039 //\r
1040 *ValueData = Buf;\r
1041 *ValueLength = Length;\r
1042 return EFI_SUCCESS;\r
1043}\r
1044\r
82e8c138
ED
1045/**\r
1046 Get value from config request resp string.\r
1047\r
1048 @param ConfigElement ConfigResp string contains the current setting.\r
1049 @param VarName The variable name which need to get value.\r
1050 @param VarValue The return value.\r
1051 \r
1052 @retval EFI_SUCCESS Get the value for the VarName\r
1053 @retval EFI_OUT_OF_RESOURCES The memory is not enough.\r
1054**/\r
1055EFI_STATUS\r
1056GetValueFromRequest (\r
1057 IN CHAR16 *ConfigElement,\r
1058 IN CHAR16 *VarName,\r
1059 OUT UINT64 *VarValue\r
1060 )\r
1061{\r
1062 UINT8 *TmpBuffer;\r
1063 CHAR16 *StringPtr;\r
1064 UINTN Length;\r
1065 EFI_STATUS Status;\r
1066\r
1067 //\r
1068 // Find VarName related string.\r
1069 //\r
1070 StringPtr = StrStr (ConfigElement, VarName);\r
1071 ASSERT (StringPtr != NULL);\r
1072\r
1073 //\r
1074 // Skip the "VarName=" string\r
1075 //\r
1076 StringPtr += StrLen (VarName) + 1;\r
1077\r
1078 //\r
1079 // Get Offset\r
1080 //\r
1081 Status = InternalHiiGetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
1082 if (EFI_ERROR (Status)) {\r
1083 return Status;\r
1084 }\r
1085\r
1086 *VarValue = 0;\r
1087 CopyMem (VarValue, TmpBuffer, (((Length + 1) / 2) < sizeof (UINT64)) ? ((Length + 1) / 2) : sizeof (UINT64));\r
1088\r
1089 FreePool (TmpBuffer);\r
1090\r
1091 return EFI_SUCCESS;\r
1092}\r
1093\r
84f9a9ec 1094/**\r
8567300a
LG
1095 This internal function parses IFR data to validate current setting.\r
1096\r
82e8c138
ED
1097 Base on the NameValueType, if it is TRUE, RequestElement and HiiHandle is valid;\r
1098 else the VarBuffer and CurrentBlockArray is valid.\r
1099\r
8567300a
LG
1100 @param HiiPackageList Point to Hii package list.\r
1101 @param PackageListLength The length of the pacakge.\r
1102 @param VarGuid Guid of the buffer storage.\r
1103 @param VarName Name of the buffer storage.\r
82e8c138
ED
1104 @param VarBuffer The data buffer for the storage.\r
1105 @param CurrentBlockArray The block array from the config Requst string.\r
1106 @param RequestElement The config string for this storage.\r
1107 @param HiiHandle The HiiHandle for this formset.\r
1108 @param NameValueType Whether current storage is name/value varstore or not.\r
84f9a9ec 1109 \r
8567300a
LG
1110 @retval EFI_SUCCESS The current setting is valid.\r
1111 @retval EFI_OUT_OF_RESOURCES The memory is not enough.\r
1112 @retval EFI_INVALID_PARAMETER The config string or the Hii package is invalid.\r
84f9a9ec
LG
1113**/\r
1114EFI_STATUS\r
82e8c138 1115ValidateQuestionFromVfr (\r
84f9a9ec
LG
1116 IN EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList,\r
1117 IN UINTN PackageListLength,\r
1118 IN EFI_GUID *VarGuid,\r
82e8c138
ED
1119 IN CHAR16 *VarName,\r
1120 IN UINT8 *VarBuffer,\r
1121 IN IFR_BLOCK_DATA *CurrentBlockArray,\r
1122 IN CHAR16 *RequestElement,\r
1123 IN EFI_HII_HANDLE HiiHandle,\r
1124 IN BOOLEAN NameValueType\r
40ae09a2
ED
1125 )\r
1126{\r
1127 IFR_BLOCK_DATA VarBlockData;\r
40ae09a2
ED
1128 UINT16 Offset;\r
1129 UINT16 Width;\r
1130 UINT64 VarValue;\r
fda93fc4 1131 EFI_IFR_TYPE_VALUE TmpValue;\r
84f9a9ec 1132 EFI_STATUS Status;\r
3b28e744 1133 EFI_HII_PACKAGE_HEADER PackageHeader;\r
84f9a9ec
LG
1134 UINT32 PackageOffset;\r
1135 UINT8 *PackageData;\r
1136 UINTN IfrOffset;\r
1137 EFI_IFR_OP_HEADER *IfrOpHdr;\r
1138 EFI_IFR_VARSTORE *IfrVarStore;\r
82e8c138
ED
1139 EFI_IFR_VARSTORE_NAME_VALUE *IfrNameValueStore;\r
1140 EFI_IFR_VARSTORE_EFI *IfrEfiVarStore;\r
1141 IFR_VARSTORAGE_DATA VarStoreData;\r
84f9a9ec
LG
1142 EFI_IFR_ONE_OF *IfrOneOf;\r
1143 EFI_IFR_NUMERIC *IfrNumeric;\r
1144 EFI_IFR_ONE_OF_OPTION *IfrOneOfOption;\r
1145 EFI_IFR_CHECKBOX *IfrCheckBox;\r
1146 EFI_IFR_STRING *IfrString;\r
1147 CHAR8 *VarStoreName;\r
1148 UINTN Index;\r
82e8c138
ED
1149 CHAR16 *QuestionName;\r
1150 CHAR16 *StringPtr;\r
84f9a9ec 1151\r
84f9a9ec
LG
1152 //\r
1153 // Initialize the local variables.\r
1154 //\r
40ae09a2
ED
1155 Index = 0;\r
1156 VarStoreName = NULL;\r
1157 Status = EFI_SUCCESS;\r
40ae09a2
ED
1158 VarValue = 0;\r
1159 IfrVarStore = NULL;\r
1160 IfrNameValueStore = NULL;\r
82e8c138
ED
1161 IfrEfiVarStore = NULL;\r
1162 ZeroMem (&VarStoreData, sizeof (IFR_VARSTORAGE_DATA));\r
1163 ZeroMem (&VarBlockData, sizeof (VarBlockData));\r
84f9a9ec
LG
1164\r
1165 //\r
82e8c138 1166 // Check IFR value is in block data, then Validate Value\r
84f9a9ec 1167 //\r
84f9a9ec
LG
1168 PackageOffset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);\r
1169 while (PackageOffset < PackageListLength) {\r
3b28e744 1170 CopyMem (&PackageHeader, (UINT8 *) HiiPackageList + PackageOffset, sizeof (PackageHeader));\r
82e8c138 1171\r
84f9a9ec
LG
1172 //\r
1173 // Parse IFR opcode from the form package.\r
1174 //\r
3b28e744
GL
1175 if (PackageHeader.Type == EFI_HII_PACKAGE_FORMS) {\r
1176 IfrOffset = sizeof (PackageHeader);\r
84f9a9ec 1177 PackageData = (UINT8 *) HiiPackageList + PackageOffset;\r
3b28e744 1178 while (IfrOffset < PackageHeader.Length) {\r
84f9a9ec
LG
1179 IfrOpHdr = (EFI_IFR_OP_HEADER *) (PackageData + IfrOffset);\r
1180 //\r
1181 // Validate current setting to the value built in IFR opcode\r
1182 //\r
1183 switch (IfrOpHdr->OpCode) {\r
82e8c138 1184 case EFI_IFR_VARSTORE_OP:\r
84f9a9ec
LG
1185 //\r
1186 // VarStoreId has been found. No further found.\r
1187 //\r
82e8c138 1188 if (VarStoreData.VarStoreId != 0) {\r
84f9a9ec
LG
1189 break;\r
1190 }\r
1191 //\r
1192 // Find the matched VarStoreId to the input VarGuid and VarName\r
8567300a 1193 //\r
84f9a9ec
LG
1194 IfrVarStore = (EFI_IFR_VARSTORE *) IfrOpHdr;\r
1195 if (CompareGuid ((EFI_GUID *) (VOID *) &IfrVarStore->Guid, VarGuid)) {\r
1196 VarStoreName = (CHAR8 *) IfrVarStore->Name;\r
1197 for (Index = 0; VarStoreName[Index] != 0; Index ++) {\r
1198 if ((CHAR16) VarStoreName[Index] != VarName[Index]) {\r
1199 break;\r
1200 }\r
1201 }\r
1202 //\r
1203 // The matched VarStore is found.\r
1204 //\r
1205 if ((VarStoreName[Index] != 0) || (VarName[Index] != 0)) {\r
1206 IfrVarStore = NULL;\r
1207 }\r
1208 } else {\r
1209 IfrVarStore = NULL;\r
1210 }\r
82e8c138
ED
1211\r
1212 if (IfrVarStore != NULL) {\r
1213 VarStoreData.VarStoreId = IfrVarStore->VarStoreId;\r
1214 VarStoreData.Size = IfrVarStore->Size;\r
1215 }\r
84f9a9ec 1216 break;\r
82e8c138 1217 case EFI_IFR_VARSTORE_NAME_VALUE_OP:\r
84f9a9ec 1218 //\r
82e8c138 1219 // VarStoreId has been found. No further found.\r
84f9a9ec 1220 //\r
82e8c138
ED
1221 if (VarStoreData.VarStoreId != 0) {\r
1222 break;\r
84f9a9ec 1223 }\r
84f9a9ec 1224 //\r
82e8c138 1225 // Find the matched VarStoreId to the input VarGuid\r
84f9a9ec 1226 //\r
82e8c138
ED
1227 IfrNameValueStore = (EFI_IFR_VARSTORE_NAME_VALUE *) IfrOpHdr;\r
1228 if (!CompareGuid ((EFI_GUID *) (VOID *) &IfrNameValueStore->Guid, VarGuid)) {\r
1229 IfrNameValueStore = NULL;\r
1230 }\r
84f9a9ec 1231\r
82e8c138
ED
1232 if (IfrNameValueStore != NULL) {\r
1233 VarStoreData.VarStoreId = IfrNameValueStore->VarStoreId;\r
8567300a 1234 }\r
82e8c138
ED
1235 break;\r
1236 case EFI_IFR_VARSTORE_EFI_OP:\r
84f9a9ec 1237 //\r
82e8c138
ED
1238 // VarStore is found. Don't need to search any more.\r
1239 //\r
1240 if (VarStoreData.VarStoreId != 0) {\r
84f9a9ec
LG
1241 break;\r
1242 }\r
82e8c138
ED
1243\r
1244 IfrEfiVarStore = (EFI_IFR_VARSTORE_EFI *) IfrOpHdr;\r
1245\r
84f9a9ec 1246 //\r
82e8c138
ED
1247 // If the length is small than the structure, this is from old efi \r
1248 // varstore definition. Old efi varstore get config directly from \r
1249 // GetVariable function.\r
84f9a9ec 1250 //\r
82e8c138 1251 if (IfrOpHdr->Length < sizeof (EFI_IFR_VARSTORE_EFI)) {\r
84f9a9ec
LG
1252 break;\r
1253 }\r
82e8c138
ED
1254\r
1255 if (CompareGuid ((EFI_GUID *) (VOID *) &IfrEfiVarStore->Guid, VarGuid)) {\r
1256 VarStoreName = (CHAR8 *) IfrEfiVarStore->Name;\r
1257 for (Index = 0; VarStoreName[Index] != 0; Index ++) {\r
1258 if ((CHAR16) VarStoreName[Index] != VarName[Index]) {\r
1259 break;\r
1260 }\r
1261 }\r
84f9a9ec 1262 //\r
82e8c138 1263 // The matched VarStore is found.\r
84f9a9ec 1264 //\r
82e8c138
ED
1265 if ((VarStoreName[Index] != 0) || (VarName[Index] != 0)) {\r
1266 IfrEfiVarStore = NULL;\r
1267 }\r
1268 } else {\r
1269 IfrEfiVarStore = NULL;\r
84f9a9ec
LG
1270 }\r
1271\r
82e8c138
ED
1272 if (IfrEfiVarStore != NULL) {\r
1273 //\r
1274 // Find the matched VarStore\r
1275 //\r
1276 VarStoreData.VarStoreId = IfrEfiVarStore->VarStoreId;\r
1277 VarStoreData.Size = IfrEfiVarStore->Size;\r
1278 }\r
1279 break;\r
1280 case EFI_IFR_FORM_OP:\r
1281 case EFI_IFR_FORM_MAP_OP:\r
1282 //\r
1283 // Check the matched VarStoreId is found.\r
1284 //\r
1285 if (VarStoreData.VarStoreId == 0) {\r
1286 return EFI_SUCCESS;\r
1287 }\r
1288 break;\r
1289 case EFI_IFR_ONE_OF_OP:\r
1290 //\r
1291 // Check whether current value is the one of option.\r
1292 //\r
1293\r
1294 //\r
1295 // OneOf question is not in IFR Form. This IFR form is not valid. \r
84f9a9ec 1296 //\r
82e8c138
ED
1297 if (VarStoreData.VarStoreId == 0) {\r
1298 return EFI_INVALID_PARAMETER;\r
1299 }\r
1300 // \r
1301 // Check whether this question is for the requested varstore.\r
84f9a9ec 1302 //\r
82e8c138
ED
1303 IfrOneOf = (EFI_IFR_ONE_OF *) IfrOpHdr;\r
1304 if (IfrOneOf->Question.VarStoreId != VarStoreData.VarStoreId) {\r
1305 break;\r
1306 }\r
1307\r
1308 if (NameValueType) {\r
1309 QuestionName = HiiGetString (HiiHandle, IfrOneOf->Question.VarStoreInfo.VarName, NULL);\r
1310 ASSERT (QuestionName != NULL);\r
1311\r
1312 if (StrStr (RequestElement, QuestionName) == NULL) {\r
1313 //\r
1314 // This question is not in the current configuration string. Skip it.\r
1315 //\r
1316 break;\r
1317 }\r
1318\r
1319 Status = GetValueFromRequest (RequestElement, QuestionName, &VarValue);\r
1320 if (EFI_ERROR (Status)) {\r
1321 return Status;\r
1322 }\r
1323 } else {\r
1324 //\r
1325 // Get Offset by Question header and Width by DataType Flags\r
1326 //\r
1327 Offset = IfrOneOf->Question.VarStoreInfo.VarOffset;\r
1328 Width = (UINT16) (1 << (IfrOneOf->Flags & EFI_IFR_NUMERIC_SIZE));\r
1329 //\r
1330 // Check whether this question is in current block array.\r
1331 //\r
1332 if (!BlockArrayCheck (CurrentBlockArray, Offset, Width)) {\r
1333 //\r
1334 // This question is not in the current configuration string. Skip it.\r
1335 //\r
1336 break;\r
1337 }\r
1338 //\r
1339 // Check this var question is in the var storage \r
1340 //\r
1341 if ((Offset + Width) > VarStoreData.Size) {\r
1342 //\r
1343 // This question exceeds the var store size. \r
1344 //\r
1345 return EFI_INVALID_PARAMETER;\r
1346 }\r
1347\r
1348 //\r
1349 // Get the current value for oneof opcode\r
1350 //\r
1351 VarValue = 0;\r
1352 CopyMem (&VarValue, VarBuffer + Offset, Width);\r
1353 }\r
84f9a9ec
LG
1354 //\r
1355 // Set Block Data, to be checked in the following Oneof option opcode.\r
1356 //\r
84f9a9ec
LG
1357 VarBlockData.OpCode = IfrOpHdr->OpCode;\r
1358 VarBlockData.Scope = IfrOpHdr->Scope;\r
1359 break;\r
1360 case EFI_IFR_NUMERIC_OP:\r
1361 //\r
1362 // Check the current value is in the numeric range.\r
1363 //\r
1364\r
8567300a
LG
1365 //\r
1366 // Numeric question is not in IFR Form. This IFR form is not valid. \r
1367 //\r
82e8c138
ED
1368 if (VarStoreData.VarStoreId == 0) {\r
1369 return EFI_INVALID_PARAMETER;\r
8567300a 1370 }\r
84f9a9ec
LG
1371 //\r
1372 // Check whether this question is for the requested varstore.\r
1373 //\r
1374 IfrNumeric = (EFI_IFR_NUMERIC *) IfrOpHdr;\r
82e8c138 1375 if (IfrNumeric->Question.VarStoreId != VarStoreData.VarStoreId) {\r
84f9a9ec
LG
1376 break;\r
1377 }\r
82e8c138
ED
1378\r
1379 if (NameValueType) {\r
1380 QuestionName = HiiGetString (HiiHandle, IfrNumeric->Question.VarStoreInfo.VarName, NULL);\r
1381 ASSERT (QuestionName != NULL);\r
1382\r
1383 if (StrStr (RequestElement, QuestionName) == NULL) {\r
1384 //\r
1385 // This question is not in the current configuration string. Skip it.\r
1386 //\r
1387 break;\r
1388 }\r
1389 \r
1390 Status = GetValueFromRequest (RequestElement, QuestionName, &VarValue);\r
1391 if (EFI_ERROR (Status)) {\r
1392 return Status;\r
1393 }\r
1394 } else {\r
84f9a9ec 1395 //\r
82e8c138 1396 // Get Offset by Question header and Width by DataType Flags\r
84f9a9ec 1397 //\r
82e8c138
ED
1398 Offset = IfrNumeric->Question.VarStoreInfo.VarOffset;\r
1399 Width = (UINT16) (1 << (IfrNumeric->Flags & EFI_IFR_NUMERIC_SIZE));\r
84f9a9ec 1400 //\r
82e8c138 1401 // Check whether this question is in current block array.\r
84f9a9ec 1402 //\r
82e8c138
ED
1403 if (!BlockArrayCheck (CurrentBlockArray, Offset, Width)) {\r
1404 //\r
1405 // This question is not in the current configuration string. Skip it.\r
1406 //\r
1407 break;\r
1408 }\r
1409 //\r
1410 // Check this var question is in the var storage \r
1411 //\r
1412 if ((Offset + Width) > VarStoreData.Size) {\r
1413 //\r
1414 // This question exceeds the var store size. \r
1415 //\r
1416 return EFI_INVALID_PARAMETER;\r
1417 }\r
84f9a9ec 1418\r
82e8c138
ED
1419 //\r
1420 // Check the current value is in the numeric range.\r
1421 //\r
1422 VarValue = 0;\r
1423 CopyMem (&VarValue, VarBuffer + Offset, Width);\r
1424 }\r
afc9bf79
ED
1425 if ((IfrNumeric->Flags & EFI_IFR_DISPLAY) == 0) {\r
1426 switch (IfrNumeric->Flags & EFI_IFR_NUMERIC_SIZE) {\r
1427 case EFI_IFR_NUMERIC_SIZE_1:\r
1428 if ((INT8) VarValue < (INT8) IfrNumeric->data.u8.MinValue || (INT8) VarValue > (INT8) IfrNumeric->data.u8.MaxValue) {\r
1429 //\r
1430 // Not in the valid range.\r
1431 //\r
1432 return EFI_INVALID_PARAMETER;\r
1433 }\r
1434 break;\r
1435 case EFI_IFR_NUMERIC_SIZE_2:\r
1436 if ((INT16) VarValue < (INT16) IfrNumeric->data.u16.MinValue || (INT16) VarValue > (INT16) IfrNumeric->data.u16.MaxValue) {\r
1437 //\r
1438 // Not in the valid range.\r
1439 //\r
1440 return EFI_INVALID_PARAMETER;\r
1441 }\r
1442 break;\r
1443 case EFI_IFR_NUMERIC_SIZE_4:\r
1444 if ((INT32) VarValue < (INT32) IfrNumeric->data.u32.MinValue || (INT32) VarValue > (INT32) IfrNumeric->data.u32.MaxValue) {\r
1445 //\r
1446 // Not in the valid range.\r
1447 //\r
1448 return EFI_INVALID_PARAMETER;\r
1449 }\r
1450 break;\r
1451 case EFI_IFR_NUMERIC_SIZE_8:\r
1452 if ((INT64) VarValue < (INT64) IfrNumeric->data.u64.MinValue || (INT64) VarValue > (INT64) IfrNumeric->data.u64.MaxValue) {\r
1453 //\r
1454 // Not in the valid range.\r
1455 //\r
1456 return EFI_INVALID_PARAMETER;\r
1457 }\r
1458 break;\r
84f9a9ec 1459 }\r
afc9bf79
ED
1460 } else {\r
1461 switch (IfrNumeric->Flags & EFI_IFR_NUMERIC_SIZE) {\r
1462 case EFI_IFR_NUMERIC_SIZE_1:\r
1463 if ((UINT8) VarValue < IfrNumeric->data.u8.MinValue || (UINT8) VarValue > IfrNumeric->data.u8.MaxValue) {\r
1464 //\r
1465 // Not in the valid range.\r
1466 //\r
1467 return EFI_INVALID_PARAMETER;\r
1468 }\r
1469 break;\r
1470 case EFI_IFR_NUMERIC_SIZE_2:\r
1471 if ((UINT16) VarValue < IfrNumeric->data.u16.MinValue || (UINT16) VarValue > IfrNumeric->data.u16.MaxValue) {\r
1472 //\r
1473 // Not in the valid range.\r
1474 //\r
1475 return EFI_INVALID_PARAMETER;\r
1476 }\r
1477 break;\r
1478 case EFI_IFR_NUMERIC_SIZE_4:\r
1479 if ((UINT32) VarValue < IfrNumeric->data.u32.MinValue || (UINT32) VarValue > IfrNumeric->data.u32.MaxValue) {\r
1480 //\r
1481 // Not in the valid range.\r
1482 //\r
1483 return EFI_INVALID_PARAMETER;\r
1484 }\r
1485 break;\r
1486 case EFI_IFR_NUMERIC_SIZE_8:\r
1487 if ((UINT64) VarValue < IfrNumeric->data.u64.MinValue || (UINT64) VarValue > IfrNumeric->data.u64.MaxValue) {\r
1488 //\r
1489 // Not in the valid range.\r
1490 //\r
1491 return EFI_INVALID_PARAMETER;\r
1492 }\r
1493 break;\r
84f9a9ec 1494 }\r
84f9a9ec 1495 }\r
84f9a9ec
LG
1496 break;\r
1497 case EFI_IFR_CHECKBOX_OP:\r
1498 //\r
1499 // Check value is BOOLEAN type, only 0 and 1 is valid.\r
1500 //\r
1501\r
8567300a
LG
1502 //\r
1503 // CheckBox question is not in IFR Form. This IFR form is not valid. \r
1504 //\r
82e8c138
ED
1505 if (VarStoreData.VarStoreId == 0) {\r
1506 return EFI_INVALID_PARAMETER;\r
8567300a
LG
1507 }\r
1508\r
84f9a9ec
LG
1509 //\r
1510 // Check whether this question is for the requested varstore.\r
1511 //\r
1512 IfrCheckBox = (EFI_IFR_CHECKBOX *) IfrOpHdr;\r
82e8c138 1513 if (IfrCheckBox->Question.VarStoreId != VarStoreData.VarStoreId) {\r
84f9a9ec
LG
1514 break;\r
1515 }\r
82e8c138
ED
1516\r
1517 if (NameValueType) {\r
1518 QuestionName = HiiGetString (HiiHandle, IfrCheckBox->Question.VarStoreInfo.VarName, NULL);\r
1519 ASSERT (QuestionName != NULL);\r
1520\r
1521 if (StrStr (RequestElement, QuestionName) == NULL) {\r
1522 //\r
1523 // This question is not in the current configuration string. Skip it.\r
1524 //\r
1525 break;\r
1526 }\r
1527 \r
1528 Status = GetValueFromRequest (RequestElement, QuestionName, &VarValue);\r
1529 if (EFI_ERROR (Status)) {\r
1530 return Status;\r
1531 }\r
1532 } else {\r
84f9a9ec 1533 //\r
82e8c138 1534 // Get Offset by Question header\r
84f9a9ec 1535 //\r
82e8c138
ED
1536 Offset = IfrCheckBox->Question.VarStoreInfo.VarOffset;\r
1537 Width = (UINT16) sizeof (BOOLEAN);\r
84f9a9ec 1538 //\r
82e8c138 1539 // Check whether this question is in current block array.\r
84f9a9ec 1540 //\r
82e8c138
ED
1541 if (!BlockArrayCheck (CurrentBlockArray, Offset, Width)) {\r
1542 //\r
1543 // This question is not in the current configuration string. Skip it.\r
1544 //\r
1545 break;\r
1546 }\r
1547 //\r
1548 // Check this var question is in the var storage \r
1549 //\r
1550 if ((Offset + Width) > VarStoreData.Size) {\r
1551 //\r
1552 // This question exceeds the var store size. \r
1553 //\r
1554 return EFI_INVALID_PARAMETER;\r
1555 }\r
1556 //\r
1557 // Check the current value is in the numeric range.\r
1558 //\r
1559 VarValue = 0;\r
1560 CopyMem (&VarValue, VarBuffer + Offset, Width);\r
84f9a9ec 1561 }\r
84f9a9ec
LG
1562 //\r
1563 // Boolean type, only 1 and 0 is valid.\r
1564 //\r
82e8c138
ED
1565 if (VarValue > 1) {\r
1566 return EFI_INVALID_PARAMETER;\r
84f9a9ec 1567 }\r
84f9a9ec
LG
1568 break;\r
1569 case EFI_IFR_STRING_OP:\r
1570 //\r
1571 // Check current string length is less than maxsize\r
1572 //\r
1573\r
8567300a
LG
1574 //\r
1575 // CheckBox question is not in IFR Form. This IFR form is not valid. \r
1576 //\r
82e8c138
ED
1577 if (VarStoreData.VarStoreId == 0) {\r
1578 return EFI_INVALID_PARAMETER;\r
8567300a
LG
1579 }\r
1580\r
84f9a9ec
LG
1581 //\r
1582 // Check whether this question is for the requested varstore.\r
1583 //\r
1584 IfrString = (EFI_IFR_STRING *) IfrOpHdr;\r
82e8c138 1585 if (IfrString->Question.VarStoreId != VarStoreData.VarStoreId) {\r
84f9a9ec
LG
1586 break;\r
1587 }\r
84f9a9ec 1588 //\r
82e8c138 1589 // Get Width by OneOf Flags\r
84f9a9ec 1590 //\r
84f9a9ec 1591 Width = (UINT16) (IfrString->MaxSize * sizeof (UINT16));\r
82e8c138
ED
1592 if (NameValueType) {\r
1593 QuestionName = HiiGetString (HiiHandle, IfrString->Question.VarStoreInfo.VarName, NULL);\r
1594 ASSERT (QuestionName != NULL);\r
1595\r
1596 StringPtr = StrStr (RequestElement, QuestionName);\r
1597 if (StringPtr == NULL) {\r
1598 //\r
1599 // This question is not in the current configuration string. Skip it.\r
1600 //\r
1601 break;\r
1602 }\r
1603\r
84f9a9ec 1604 //\r
82e8c138
ED
1605 // Skip the "=".\r
1606 // \r
1607 StringPtr += 1;\r
1608 \r
84f9a9ec 1609 //\r
82e8c138 1610 // Check current string length is less than maxsize\r
84f9a9ec 1611 //\r
82e8c138
ED
1612 if (StrSize (StringPtr) > Width) {\r
1613 return EFI_INVALID_PARAMETER;\r
1614 }\r
1615 } else {\r
84f9a9ec 1616 //\r
82e8c138
ED
1617 // Get Offset/Width by Question header and OneOf Flags\r
1618 //\r
1619 Offset = IfrString->Question.VarStoreInfo.VarOffset;\r
1620 //\r
1621 // Check whether this question is in current block array.\r
1622 //\r
1623 if (!BlockArrayCheck (CurrentBlockArray, Offset, Width)) {\r
1624 //\r
1625 // This question is not in the current configuration string. Skip it.\r
1626 //\r
1627 break;\r
1628 }\r
1629 //\r
1630 // Check this var question is in the var storage \r
1631 //\r
1632 if ((Offset + Width) > VarStoreData.Size) {\r
1633 //\r
1634 // This question exceeds the var store size. \r
1635 //\r
1636 return EFI_INVALID_PARAMETER;\r
1637 }\r
1638\r
1639 //\r
1640 // Check current string length is less than maxsize\r
1641 //\r
1642 if (StrSize ((CHAR16 *) (VarBuffer + Offset)) > Width) {\r
1643 return EFI_INVALID_PARAMETER;\r
1644 }\r
84f9a9ec
LG
1645 }\r
1646 break;\r
1647 case EFI_IFR_ONE_OF_OPTION_OP:\r
1648 //\r
1649 // Opcode Scope is zero. This one of option is not to be checked. \r
1650 //\r
1651 if (VarBlockData.Scope == 0) {\r
1652 break;\r
1653 }\r
1654\r
1655 //\r
1656 // Only check for OneOf and OrderList opcode\r
1657 //\r
1658 IfrOneOfOption = (EFI_IFR_ONE_OF_OPTION *) IfrOpHdr;\r
1659 if (VarBlockData.OpCode == EFI_IFR_ONE_OF_OP) {\r
1660 //\r
1661 // Check current value is the value of one of option.\r
1662 //\r
5ecab660 1663 ASSERT (IfrOneOfOption->Type <= EFI_IFR_TYPE_NUM_SIZE_64);\r
fda93fc4 1664 ZeroMem (&TmpValue, sizeof (EFI_IFR_TYPE_VALUE));\r
a7f87053 1665 CopyMem (&TmpValue, &IfrOneOfOption->Value, IfrOneOfOption->Header.Length - OFFSET_OF (EFI_IFR_ONE_OF_OPTION, Value));\r
fda93fc4 1666 if (VarValue == TmpValue.u64) {\r
84f9a9ec
LG
1667 //\r
1668 // The value is one of option value.\r
1669 // Set OpCode to Zero, don't need check again.\r
1670 //\r
1671 VarBlockData.OpCode = 0;\r
1672 }\r
1673 }\r
84f9a9ec
LG
1674 break;\r
1675 case EFI_IFR_END_OP:\r
1676 //\r
1677 // Decrease opcode scope for the validated opcode\r
1678 //\r
1679 if (VarBlockData.Scope > 0) {\r
1680 VarBlockData.Scope --;\r
1681 }\r
1682\r
1683 //\r
1684 // OneOf value doesn't belong to one of option value. \r
1685 //\r
62b658dd 1686 if ((VarBlockData.Scope == 0) && (VarBlockData.OpCode == EFI_IFR_ONE_OF_OP)) {\r
82e8c138 1687 return EFI_INVALID_PARAMETER;\r
84f9a9ec
LG
1688 }\r
1689 break;\r
1690 default:\r
1691 //\r
1692 // Increase Scope for the validated opcode\r
1693 //\r
1694 if (VarBlockData.Scope > 0) {\r
1695 VarBlockData.Scope = (UINT8) (VarBlockData.Scope + IfrOpHdr->Scope);\r
1696 }\r
1697 break;\r
1698 }\r
1699 //\r
1700 // Go to the next opcode\r
1701 //\r
1702 IfrOffset += IfrOpHdr->Length;\r
1703 }\r
1704 //\r
1705 // Only one form is in a package list.\r
1706 //\r
1707 break;\r
1708 }\r
82e8c138 1709\r
84f9a9ec
LG
1710 //\r
1711 // Go to next package.\r
1712 //\r
3b28e744 1713 PackageOffset += PackageHeader.Length;\r
84f9a9ec
LG
1714 }\r
1715\r
82e8c138
ED
1716 return EFI_SUCCESS;\r
1717}\r
1718\r
1719/**\r
1720 This internal function parses IFR data to validate current setting.\r
1721\r
1722 @param ConfigElement ConfigResp element string contains the current setting.\r
1723 @param CurrentBlockArray Current block array.\r
1724 @param VarBuffer Data buffer for this varstore.\r
1725 \r
1726 @retval EFI_SUCCESS The current setting is valid.\r
1727 @retval EFI_OUT_OF_RESOURCES The memory is not enough.\r
1728 @retval EFI_INVALID_PARAMETER The config string or the Hii package is invalid.\r
1729**/\r
1730EFI_STATUS\r
1731GetBlockDataInfo (\r
1732 IN CHAR16 *ConfigElement,\r
1733 OUT IFR_BLOCK_DATA **CurrentBlockArray,\r
1734 OUT UINT8 **VarBuffer\r
1735 )\r
1736{\r
1737 IFR_BLOCK_DATA *BlockData;\r
1738 IFR_BLOCK_DATA *NewBlockData;\r
1739 EFI_STRING StringPtr;\r
1740 UINTN Length;\r
1741 UINT8 *TmpBuffer;\r
1742 UINT16 Offset;\r
1743 UINT16 Width;\r
40ae09a2
ED
1744 LIST_ENTRY *Link;\r
1745 UINTN MaxBufferSize;\r
1746 EFI_STATUS Status;\r
40ae09a2
ED
1747 IFR_BLOCK_DATA *BlockArray;\r
1748 UINT8 *DataBuffer;\r
1749 \r
1750 //\r
1751 // Initialize the local variables.\r
1752 //\r
40ae09a2
ED
1753 Status = EFI_SUCCESS;\r
1754 BlockData = NULL;\r
1755 NewBlockData = NULL;\r
82e8c138
ED
1756 TmpBuffer = NULL;\r
1757 BlockArray = NULL;\r
1758 MaxBufferSize = HII_LIB_DEFAULT_VARSTORE_SIZE;\r
1759 DataBuffer = AllocateZeroPool (MaxBufferSize);\r
1760 if (DataBuffer == NULL) {\r
1761 return EFI_OUT_OF_RESOURCES;\r
1762 }\r
1763\r
1764 //\r
1765 // Init BlockArray\r
1766 //\r
1767 BlockArray = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));\r
1768 if (BlockArray == NULL) {\r
1769 Status = EFI_OUT_OF_RESOURCES;\r
1770 goto Done;\r
1771 }\r
1772 InitializeListHead (&BlockArray->Entry);\r
1773\r
1774 StringPtr = StrStr (ConfigElement, L"&OFFSET=");\r
1775 ASSERT (StringPtr != NULL);\r
1776\r
1777 //\r
1778 // Parse each <RequestElement> if exists\r
1779 // Only <BlockName> format is supported by this help function.\r
1780 // <BlockName> ::= &'OFFSET='<Number>&'WIDTH='<Number>\r
1781 //\r
1782 while (*StringPtr != 0 && StrnCmp (StringPtr, L"&OFFSET=", StrLen (L"&OFFSET=")) == 0) {\r
1783 //\r
1784 // Skip the &OFFSET= string\r
1785 // \r
1786 StringPtr += StrLen (L"&OFFSET=");\r
1787\r
1788 //\r
1789 // Get Offset\r
1790 //\r
1791 Status = InternalHiiGetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
1792 if (EFI_ERROR (Status)) {\r
1793 goto Done;\r
1794 }\r
1795 Offset = 0;\r
1796 CopyMem (\r
1797 &Offset,\r
1798 TmpBuffer,\r
1799 (((Length + 1) / 2) < sizeof (UINT16)) ? ((Length + 1) / 2) : sizeof (UINT16)\r
1800 );\r
1801 FreePool (TmpBuffer);\r
1802 TmpBuffer = NULL;\r
1803\r
1804 StringPtr += Length;\r
1805 if (StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {\r
1806 Status = EFI_INVALID_PARAMETER;\r
1807 goto Done;\r
1808 }\r
1809 StringPtr += StrLen (L"&WIDTH=");\r
1810\r
1811 //\r
1812 // Get Width\r
1813 //\r
1814 Status = InternalHiiGetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
1815 if (EFI_ERROR (Status)) {\r
1816 goto Done;\r
1817 }\r
1818 Width = 0;\r
1819 CopyMem (\r
1820 &Width,\r
1821 TmpBuffer,\r
1822 (((Length + 1) / 2) < sizeof (UINT16)) ? ((Length + 1) / 2) : sizeof (UINT16)\r
1823 );\r
1824 FreePool (TmpBuffer);\r
1825 TmpBuffer = NULL;\r
1826\r
1827 StringPtr += Length;\r
1828 if (*StringPtr != 0 && *StringPtr != L'&') {\r
1829 Status = EFI_INVALID_PARAMETER;\r
1830 goto Done;\r
1831 }\r
1832\r
1833 if (StrnCmp (StringPtr, L"&VALUE=", StrLen (L"&VALUE=")) != 0) {\r
1834 Status = EFI_INVALID_PARAMETER;\r
1835 goto Done;\r
1836 }\r
1837 StringPtr += StrLen (L"&VALUE=");\r
1838\r
1839 //\r
1840 // Get Value\r
1841 //\r
1842 Status = InternalHiiGetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
1843 if (EFI_ERROR (Status)) {\r
1844 goto Done;\r
1845 }\r
1846\r
1847 StringPtr += Length;\r
1848 if (*StringPtr != 0 && *StringPtr != L'&') {\r
1849 Status = EFI_INVALID_PARAMETER;\r
1850 goto Done;\r
1851 }\r
1852\r
1853 //\r
1854 // Check whether VarBuffer is enough\r
1855 //\r
1856 if ((UINTN) (Offset + Width) > MaxBufferSize) {\r
1857 DataBuffer = ReallocatePool (\r
1858 MaxBufferSize,\r
1859 Offset + Width + HII_LIB_DEFAULT_VARSTORE_SIZE,\r
1860 DataBuffer\r
1861 );\r
1862 if (DataBuffer == NULL) {\r
1863 Status = EFI_OUT_OF_RESOURCES;\r
1864 goto Done;\r
1865 }\r
1866 MaxBufferSize = Offset + Width + HII_LIB_DEFAULT_VARSTORE_SIZE;\r
1867 }\r
1868\r
1869 //\r
1870 // Update the Block with configuration info\r
1871 //\r
1872 CopyMem (DataBuffer + Offset, TmpBuffer, Width);\r
1873 FreePool (TmpBuffer);\r
1874 TmpBuffer = NULL;\r
1875\r
1876 //\r
1877 // Set new Block Data\r
1878 //\r
1879 NewBlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));\r
1880 if (NewBlockData == NULL) {\r
1881 Status = EFI_OUT_OF_RESOURCES;\r
1882 goto Done;\r
1883 }\r
1884 NewBlockData->Offset = Offset;\r
1885 NewBlockData->Width = Width;\r
1886\r
1887 //\r
1888 // Insert the new block data into the block data array.\r
1889 //\r
1890 for (Link = BlockArray->Entry.ForwardLink; Link != &BlockArray->Entry; Link = Link->ForwardLink) {\r
1891 BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);\r
1892 if (NewBlockData->Offset == BlockData->Offset) {\r
1893 if (NewBlockData->Width > BlockData->Width) {\r
1894 BlockData->Width = NewBlockData->Width;\r
1895 }\r
1896 FreePool (NewBlockData);\r
1897 break;\r
1898 } else if (NewBlockData->Offset < BlockData->Offset) {\r
1899 //\r
1900 // Insert new block data as the previous one of this link.\r
1901 //\r
1902 InsertTailList (Link, &NewBlockData->Entry);\r
1903 break;\r
1904 }\r
1905 }\r
1906\r
1907 //\r
1908 // Insert new block data into the array tail.\r
1909 //\r
1910 if (Link == &BlockArray->Entry) {\r
1911 InsertTailList (Link, &NewBlockData->Entry);\r
1912 }\r
1913\r
1914 //\r
1915 // If '\0', parsing is finished. \r
1916 //\r
1917 if (*StringPtr == 0) {\r
1918 break;\r
1919 }\r
1920 //\r
1921 // Go to next ConfigBlock \r
1922 //\r
1923 }\r
1924\r
1925 //\r
1926 // Merge the aligned block data into the single block data.\r
1927 //\r
1928 Link = BlockArray->Entry.ForwardLink;\r
1929 while ((Link != &BlockArray->Entry) && (Link->ForwardLink != &BlockArray->Entry)) {\r
1930 BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);\r
1931 NewBlockData = BASE_CR (Link->ForwardLink, IFR_BLOCK_DATA, Entry);\r
1932 if ((NewBlockData->Offset >= BlockData->Offset) && (NewBlockData->Offset <= (BlockData->Offset + BlockData->Width))) {\r
1933 if ((NewBlockData->Offset + NewBlockData->Width) > (BlockData->Offset + BlockData->Width)) {\r
1934 BlockData->Width = (UINT16) (NewBlockData->Offset + NewBlockData->Width - BlockData->Offset);\r
1935 }\r
1936 RemoveEntryList (Link->ForwardLink);\r
1937 FreePool (NewBlockData);\r
1938 continue;\r
1939 }\r
1940 Link = Link->ForwardLink;\r
1941 }\r
1942\r
1943 *VarBuffer = DataBuffer;\r
1944 *CurrentBlockArray = BlockArray;\r
1945 return EFI_SUCCESS;\r
1946\r
84f9a9ec 1947Done:\r
82e8c138
ED
1948 if (DataBuffer != NULL) {\r
1949 FreePool (DataBuffer);\r
1950 }\r
1951 \r
1952 if (BlockArray != NULL) {\r
1953 //\r
1954 // Free Link Array CurrentBlockArray\r
1955 //\r
1956 while (!IsListEmpty (&BlockArray->Entry)) {\r
1957 BlockData = BASE_CR (BlockArray->Entry.ForwardLink, IFR_BLOCK_DATA, Entry);\r
1958 RemoveEntryList (&BlockData->Entry);\r
1959 FreePool (BlockData);\r
1960 }\r
1961 FreePool (BlockArray);\r
1962 }\r
1963\r
1964 return Status;\r
1965}\r
1966\r
1967/**\r
1968 This internal function parses IFR data to validate current setting.\r
1969\r
1970 @param ConfigResp ConfigResp string contains the current setting.\r
1971 @param HiiPackageList Point to Hii package list.\r
1972 @param PackageListLength The length of the pacakge.\r
1973 @param VarGuid Guid of the buffer storage.\r
1974 @param VarName Name of the buffer storage.\r
1975 @param HiiHandle The HiiHandle for this package.\r
1976 \r
1977 @retval EFI_SUCCESS The current setting is valid.\r
1978 @retval EFI_OUT_OF_RESOURCES The memory is not enough.\r
1979 @retval EFI_INVALID_PARAMETER The config string or the Hii package is invalid.\r
1980**/\r
1981EFI_STATUS\r
1982EFIAPI\r
1983InternalHiiValidateCurrentSetting (\r
1984 IN EFI_STRING ConfigResp,\r
1985 IN EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList,\r
1986 IN UINTN PackageListLength,\r
1987 IN EFI_GUID *VarGuid,\r
1988 IN CHAR16 *VarName,\r
1989 IN EFI_HII_HANDLE HiiHandle\r
1990 )\r
1991{\r
1992 CHAR16 *StringPtr;\r
1993 EFI_STATUS Status;\r
1994 IFR_BLOCK_DATA *CurrentBlockArray;\r
1995 IFR_BLOCK_DATA *BlockData;\r
1996 UINT8 *VarBuffer;\r
1997 BOOLEAN NameValueType;\r
1998\r
1999 CurrentBlockArray = NULL;\r
2000 VarBuffer = NULL;\r
2001 StringPtr = NULL;\r
2002 Status = EFI_SUCCESS;\r
2003\r
2004 //\r
2005 // If StringPtr != NULL, get the request elements.\r
2006 //\r
2007 if (StrStr (ConfigResp, L"&OFFSET=") != NULL) {\r
2008 Status = GetBlockDataInfo(ConfigResp, &CurrentBlockArray, &VarBuffer);\r
2009 if (EFI_ERROR (Status)) {\r
2010 return Status;\r
2011 }\r
2012 NameValueType = FALSE;\r
2013 } else {\r
2014 //\r
2015 // Skip header part.\r
2016 //\r
2017 StringPtr = StrStr (ConfigResp, L"PATH=");\r
2018 ASSERT (StringPtr != NULL);\r
2019\r
2020 if (StrStr (StringPtr, L"&") != NULL) {\r
2021 NameValueType = TRUE;\r
2022 } else {\r
2023 //\r
2024 // Not found Request element, return success.\r
2025 //\r
2026 return EFI_SUCCESS;\r
2027 }\r
2028 }\r
2029\r
2030 Status = ValidateQuestionFromVfr(\r
2031 HiiPackageList,\r
2032 PackageListLength,\r
2033 VarGuid,\r
2034 VarName,\r
2035 VarBuffer,\r
2036 CurrentBlockArray,\r
2037 ConfigResp,\r
2038 HiiHandle,\r
2039 NameValueType\r
2040 );\r
2041\r
84f9a9ec
LG
2042 if (VarBuffer != NULL) {\r
2043 FreePool (VarBuffer);\r
2044 }\r
2045 \r
2046 if (CurrentBlockArray != NULL) {\r
2047 //\r
2048 // Free Link Array CurrentBlockArray\r
2049 //\r
2050 while (!IsListEmpty (&CurrentBlockArray->Entry)) {\r
2051 BlockData = BASE_CR (CurrentBlockArray->Entry.ForwardLink, IFR_BLOCK_DATA, Entry);\r
2052 RemoveEntryList (&BlockData->Entry);\r
2053 FreePool (BlockData);\r
2054 }\r
82e8c138 2055 FreePool (CurrentBlockArray);\r
84f9a9ec
LG
2056 }\r
2057\r
2058 return Status;\r
2059}\r
2060\r
82e8c138
ED
2061/**\r
2062 Check whether the ConfigRequest string has the request elements.\r
2063 For EFI_HII_VARSTORE_BUFFER type, the request has "&OFFSET=****&WIDTH=****..." format.\r
2064 For EFI_HII_VARSTORE_NAME_VALUE type, the request has "&NAME1**&NAME2..." format.\r
2065\r
2066 @param ConfigRequest The input config request string.\r
2067\r
2068 @retval TRUE The input include config request elements.\r
2069 @retval FALSE The input string not includes.\r
2070 \r
2071**/\r
2072BOOLEAN\r
2073GetElementsFromRequest (\r
2074 IN EFI_STRING ConfigRequest\r
2075 )\r
2076{\r
2077 EFI_STRING TmpRequest;\r
2078\r
2079 TmpRequest = StrStr (ConfigRequest, L"PATH=");\r
2080 ASSERT (TmpRequest != NULL);\r
2081\r
2082 if ((StrStr (TmpRequest, L"&OFFSET=") != NULL) || (StrStr (TmpRequest, L"&") != NULL)) {\r
2083 return TRUE;\r
2084 }\r
2085\r
2086 return FALSE;\r
2087}\r
2088\r
84f9a9ec 2089/**\r
8567300a
LG
2090 This function parses the input ConfigRequest string and its matched IFR code\r
2091 string for setting default value and validating current setting.\r
2092\r
84f9a9ec
LG
2093 1. For setting default action, Reset the default value specified by DefaultId \r
2094 to the driver configuration got by Request string.\r
2095 2. For validating current setting, Validate the current configuration \r
2096 by parsing HII form IFR opcode.\r
2097\r
2098 NULL request string support depends on the ExportConfig interface of\r
2099 HiiConfigRouting protocol in UEFI specification.\r
2100 \r
2101 @param Request A null-terminated Unicode string in \r
2102 <MultiConfigRequest> format. It can be NULL.\r
2103 If it is NULL, all current configuration for the\r
2104 entirety of the current HII database will be validated.\r
2105 If it is NULL, all configuration for the\r
2106 entirety of the current HII database will be reset.\r
2107 @param DefaultId Specifies the type of defaults to retrieve only for setting default action.\r
2108 @param ActionType Action supports setting defaults and validate current setting.\r
2109 \r
3b28e744 2110 @retval TRUE Action runs successfully.\r
84f9a9ec
LG
2111 @retval FALSE Action is not valid or Action can't be executed successfully..\r
2112**/\r
2113BOOLEAN\r
2114EFIAPI\r
2115InternalHiiIfrValueAction (\r
2116 IN CONST EFI_STRING Request, OPTIONAL\r
76c24251 2117 IN UINT16 DefaultId,\r
84f9a9ec
LG
2118 IN UINT8 ActionType\r
2119 )\r
2120{\r
2121 EFI_STRING ConfigAltResp;\r
2122 EFI_STRING ConfigAltHdr;\r
2123 EFI_STRING ConfigResp;\r
2124 EFI_STRING Progress;\r
2125 EFI_STRING StringPtr;\r
2126 EFI_STRING StringHdr;\r
2127 EFI_STATUS Status;\r
2128 EFI_HANDLE DriverHandle;\r
2129 EFI_HANDLE TempDriverHandle;\r
2130 EFI_HII_HANDLE *HiiHandleBuffer;\r
2131 EFI_HII_HANDLE HiiHandle;\r
2132 UINT32 Index;\r
2133 EFI_GUID *VarGuid;\r
2134 EFI_STRING VarName;\r
84f9a9ec 2135\r
84f9a9ec 2136 EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;\r
84f9a9ec 2137 UINTN PackageListLength;\r
5ad66ec6 2138 UINTN MaxLen;\r
84f9a9ec
LG
2139 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
2140 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;\r
7538d536 2141\r
84f9a9ec
LG
2142 ConfigAltResp = NULL;\r
2143 ConfigResp = NULL;\r
2144 VarGuid = NULL;\r
2145 VarName = NULL;\r
2146 DevicePath = NULL;\r
2147 ConfigAltHdr = NULL;\r
2148 HiiHandleBuffer = NULL;\r
2149 Index = 0;\r
2150 TempDriverHandle = NULL;\r
2151 HiiHandle = NULL;\r
84f9a9ec
LG
2152 HiiPackageList = NULL;\r
2153 \r
2154 //\r
2155 // Only support set default and validate setting action.\r
2156 //\r
2157 if ((ActionType != ACTION_SET_DEFAUTL_VALUE) && (ActionType != ACTION_VALIDATE_SETTING)) {\r
2158 return FALSE;\r
2159 }\r
2160\r
2161 //\r
2162 // Get the full requested value and deault value string.\r
2163 //\r
2164 if (Request != NULL) {\r
2165 Status = gHiiConfigRouting->ExtractConfig (\r
2166 gHiiConfigRouting,\r
2167 Request,\r
2168 &Progress,\r
2169 &ConfigAltResp\r
2170 );\r
2171 } else {\r
2172 Status = gHiiConfigRouting->ExportConfig (\r
2173 gHiiConfigRouting,\r
2174 &ConfigAltResp\r
2175 );\r
2176 }\r
2177 \r
2178 if (EFI_ERROR (Status)) {\r
2179 return FALSE;\r
2180 }\r
2181 \r
2182 StringPtr = ConfigAltResp;\r
2183 \r
2184 while (StringPtr != L'\0') {\r
2185 //\r
2186 // 1. Find <ConfigHdr> GUID=...&NAME=...&PATH=...\r
2187 //\r
2188 StringHdr = StringPtr;\r
2189\r
2190 //\r
2191 // Get Guid value\r
2192 //\r
2193 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
2194 Status = EFI_INVALID_PARAMETER;\r
2195 goto Done;\r
2196 }\r
2197 StringPtr += StrLen (L"GUID=");\r
2198 Status = InternalHiiGetBufferFromString (StringPtr, GUID_CONFIG_STRING_TYPE, (UINT8 **) &VarGuid);\r
2199 if (EFI_ERROR (Status)) {\r
2200 goto Done;\r
2201 }\r
2202\r
2203 //\r
2204 // Get Name value VarName\r
2205 //\r
2206 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&NAME=", StrLen (L"&NAME=")) != 0) {\r
2207 StringPtr++;\r
2208 }\r
2209 if (*StringPtr == L'\0') {\r
2210 Status = EFI_INVALID_PARAMETER;\r
2211 goto Done;\r
2212 }\r
2213 StringPtr += StrLen (L"&NAME=");\r
2214 Status = InternalHiiGetBufferFromString (StringPtr, NAME_CONFIG_STRING_TYPE, (UINT8 **) &VarName);\r
2215 if (EFI_ERROR (Status)) {\r
2216 goto Done;\r
2217 }\r
2218 \r
2219 //\r
2220 // Get Path value DevicePath\r
2221 //\r
2222 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&PATH=", StrLen (L"&PATH=")) != 0) {\r
2223 StringPtr++;\r
2224 }\r
2225 if (*StringPtr == L'\0') {\r
2226 Status = EFI_INVALID_PARAMETER;\r
2227 goto Done;\r
2228 }\r
2229 StringPtr += StrLen (L"&PATH=");\r
2230 Status = InternalHiiGetBufferFromString (StringPtr, PATH_CONFIG_STRING_TYPE, (UINT8 **) &DevicePath);\r
2231 if (EFI_ERROR (Status)) {\r
2232 goto Done;\r
2233 }\r
2234\r
2235 //\r
2236 // Get the Driver handle by the got device path.\r
2237 //\r
2238 TempDevicePath = DevicePath;\r
2239 Status = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &TempDevicePath, &DriverHandle);\r
2240 if (EFI_ERROR (Status)) {\r
2241 goto Done;\r
2242 }\r
2243 \r
2244 //\r
2245 // Find the matched Hii Handle for the found Driver handle\r
2246 //\r
2247 HiiHandleBuffer = HiiGetHiiHandles (NULL);\r
2248 if (HiiHandleBuffer == NULL) {\r
2249 Status = EFI_NOT_FOUND;\r
2250 goto Done;\r
2251 }\r
2252\r
2253 for (Index = 0; HiiHandleBuffer[Index] != NULL; Index ++) {\r
2254 gHiiDatabase->GetPackageListHandle (gHiiDatabase, HiiHandleBuffer[Index], &TempDriverHandle);\r
2255 if (TempDriverHandle == DriverHandle) {\r
2256 break;\r
2257 }\r
2258 }\r
2259\r
2260 HiiHandle = HiiHandleBuffer[Index];\r
2261 FreePool (HiiHandleBuffer);\r
2262\r
2263 if (HiiHandle == NULL) {\r
2264 //\r
2265 // This request string has no its Hii package.\r
2266 // Its default value and validating can't execute by parsing IFR data.\r
2267 // Directly jump into the next ConfigAltResp string for another pair Guid, Name, and Path. \r
2268 //\r
82e8c138 2269 Status = EFI_SUCCESS;\r
84f9a9ec
LG
2270 goto NextConfigAltResp;\r
2271 }\r
84f9a9ec
LG
2272\r
2273 //\r
81b618fe 2274 // 2. Get HiiPackage by HiiHandle\r
84f9a9ec
LG
2275 //\r
2276 PackageListLength = 0;\r
2277 HiiPackageList = NULL;\r
2278 Status = gHiiDatabase->ExportPackageLists (gHiiDatabase, HiiHandle, &PackageListLength, HiiPackageList);\r
2279 \r
2280 //\r
2281 // The return status should always be EFI_BUFFER_TOO_SMALL as input buffer's size is 0.\r
2282 //\r
2283 if (Status != EFI_BUFFER_TOO_SMALL) {\r
2284 Status = EFI_INVALID_PARAMETER;\r
2285 goto Done;\r
2286 }\r
2287 \r
2288 HiiPackageList = AllocatePool (PackageListLength);\r
2289 if (HiiPackageList == NULL) {\r
2290 Status = EFI_OUT_OF_RESOURCES;\r
2291 goto Done;\r
2292 }\r
2293 \r
2294 //\r
2295 // Get PackageList on HiiHandle\r
2296 //\r
2297 Status = gHiiDatabase->ExportPackageLists (gHiiDatabase, HiiHandle, &PackageListLength, HiiPackageList);\r
2298 if (EFI_ERROR (Status)) {\r
2299 goto Done;\r
2300 }\r
2301 \r
84f9a9ec
LG
2302 //\r
2303 // 3. Call ConfigRouting GetAltCfg(ConfigRoute, <ConfigResponse>, Guid, Name, DevicePath, AltCfgId, AltCfgResp)\r
81b618fe 2304 // Get the default configuration string according to the default ID.\r
84f9a9ec
LG
2305 //\r
2306 Status = gHiiConfigRouting->GetAltConfig (\r
2307 gHiiConfigRouting,\r
2308 ConfigAltResp,\r
2309 VarGuid,\r
2310 VarName,\r
2311 DevicePath,\r
81b618fe 2312 (ActionType == ACTION_SET_DEFAUTL_VALUE) ? &DefaultId:NULL, // it can be NULL to get the current setting.\r
84f9a9ec
LG
2313 &ConfigResp\r
2314 );\r
1f1cb2f2
LG
2315 \r
2316 //\r
2317 // The required setting can't be found. So, it is not required to be validated and set.\r
2318 //\r
84f9a9ec 2319 if (EFI_ERROR (Status)) {\r
76c24251
LG
2320 Status = EFI_SUCCESS;\r
2321 goto NextConfigAltResp;\r
84f9a9ec 2322 }\r
1f1cb2f2
LG
2323 //\r
2324 // Only the ConfigHdr is found. Not any block data is found. No data is required to be validated and set.\r
2325 //\r
82e8c138 2326 if (!GetElementsFromRequest (ConfigResp)) {\r
1f1cb2f2
LG
2327 goto NextConfigAltResp;\r
2328 }\r
84f9a9ec
LG
2329 \r
2330 //\r
2331 // 4. Set the default configuration information or Validate current setting by parse IFR code.\r
2332 // Current Setting is in ConfigResp, will be set into buffer, then check it again.\r
2333 //\r
2334 if (ActionType == ACTION_SET_DEFAUTL_VALUE) {\r
2335 //\r
2336 // Set the default configuration information.\r
2337 //\r
2338 Status = gHiiConfigRouting->RouteConfig (gHiiConfigRouting, ConfigResp, &Progress);\r
2339 } else {\r
2340 //\r
2341 // Current Setting is in ConfigResp, will be set into buffer, then check it again.\r
2342 //\r
82e8c138 2343 Status = InternalHiiValidateCurrentSetting (ConfigResp, HiiPackageList, PackageListLength, VarGuid, VarName, HiiHandle);\r
84f9a9ec
LG
2344 }\r
2345\r
2346 if (EFI_ERROR (Status)) {\r
2347 goto Done;\r
2348 }\r
2349\r
76c24251 2350NextConfigAltResp:\r
84f9a9ec
LG
2351 //\r
2352 // Free the allocated pacakge buffer and the got ConfigResp string.\r
2353 //\r
2354 if (HiiPackageList != NULL) {\r
2355 FreePool (HiiPackageList);\r
2356 HiiPackageList = NULL;\r
2357 }\r
76c24251 2358 \r
82e8c138
ED
2359 if (ConfigResp != NULL) {\r
2360 FreePool (ConfigResp);\r
2361 ConfigResp = NULL;\r
2362 }\r
84f9a9ec 2363\r
84f9a9ec
LG
2364 //\r
2365 // Free the allocated buffer.\r
2366 //\r
2367 FreePool (VarGuid);\r
2368 VarGuid = NULL;\r
2369 \r
2370 FreePool (VarName);\r
2371 VarName = NULL;\r
2372 \r
2373 FreePool (DevicePath);\r
2374 DevicePath = NULL;\r
2375\r
2376 //\r
2377 // 5. Jump to next ConfigAltResp for another Guid, Name, Path.\r
2378 //\r
2379\r
2380 //\r
2381 // Get and Skip ConfigHdr\r
2382 //\r
2383 while (*StringPtr != L'\0' && *StringPtr != L'&') {\r
2384 StringPtr++;\r
2385 }\r
2386 if (*StringPtr == L'\0') {\r
2387 break;\r
2388 }\r
2389 \r
2390 //\r
2391 // Construct ConfigAltHdr string "&<ConfigHdr>&ALTCFG=\0" \r
2392 // | 1 | StrLen (ConfigHdr) | 8 | 1 |\r
2393 //\r
5ad66ec6
DB
2394 MaxLen = 1 + StringPtr - StringHdr + 8 + 1;\r
2395 ConfigAltHdr = AllocateZeroPool ( MaxLen * sizeof (CHAR16));\r
84f9a9ec
LG
2396 if (ConfigAltHdr == NULL) {\r
2397 Status = EFI_OUT_OF_RESOURCES;\r
2398 goto Done;\r
2399 }\r
5ad66ec6
DB
2400 StrCpyS (ConfigAltHdr, MaxLen, L"&");\r
2401 StrnCatS (ConfigAltHdr, MaxLen, StringHdr, StringPtr - StringHdr);\r
2402 StrCatS (ConfigAltHdr, MaxLen, L"&ALTCFG=");\r
84f9a9ec
LG
2403 \r
2404 //\r
2405 // Skip all AltResp (AltConfigHdr ConfigBody) for the same ConfigHdr\r
2406 //\r
2407 while ((StringHdr = StrStr (StringPtr, ConfigAltHdr)) != NULL) {\r
2408 StringPtr = StringHdr + StrLen (ConfigAltHdr);\r
2409 if (*StringPtr == L'\0') {\r
2410 break;\r
2411 }\r
2412 }\r
2413 \r
2414 //\r
2415 // Free the allocated ConfigAltHdr string\r
2416 //\r
2417 FreePool (ConfigAltHdr);\r
2418 if (*StringPtr == L'\0') {\r
2419 break;\r
2420 }\r
2421 \r
2422 //\r
2423 // Find &GUID as the next ConfigHdr\r
2424 //\r
2425 StringPtr = StrStr (StringPtr, L"&GUID");\r
2426 if (StringPtr == NULL) {\r
2427 break;\r
2428 }\r
2429\r
2430 //\r
2431 // Skip char '&'\r
2432 //\r
2433 StringPtr ++;\r
2434 }\r
2435 \r
2436Done:\r
2437 if (VarGuid != NULL) {\r
2438 FreePool (VarGuid);\r
2439 }\r
2440\r
2441 if (VarName != NULL) {\r
2442 FreePool (VarName);\r
2443 }\r
2444\r
2445 if (DevicePath != NULL) {\r
2446 FreePool (DevicePath);\r
2447 }\r
2448\r
2449 if (ConfigResp != NULL) {\r
2450 FreePool (ConfigResp);\r
2451 }\r
2452\r
2453 if (ConfigAltResp != NULL) {\r
2454 FreePool (ConfigAltResp);\r
2455 }\r
2456 \r
2457 if (HiiPackageList != NULL) {\r
2458 FreePool (HiiPackageList);\r
2459 }\r
2460 \r
2461 if (EFI_ERROR (Status)) {\r
2462 return FALSE;\r
2463 }\r
2464\r
2465 return TRUE;\r
2466}\r
2467\r
2468/**\r
2469 Validate the current configuration by parsing HII form IFR opcode.\r
2470\r
4e069e8b 2471 NULL request string support depends on the ExportConfig interface of\r
84f9a9ec
LG
2472 HiiConfigRouting protocol in UEFI specification.\r
2473 \r
2474 @param Request A null-terminated Unicode string in \r
2475 <MultiConfigRequest> format. It can be NULL.\r
2476 If it is NULL, all current configuration for the\r
2477 entirety of the current HII database will be validated.\r
2478 \r
9035e118 2479 @retval TRUE Current configuration is valid.\r
84f9a9ec
LG
2480 @retval FALSE Current configuration is invalid.\r
2481**/\r
2482BOOLEAN\r
2483EFIAPI \r
2484HiiValidateSettings (\r
2485 IN CONST EFI_STRING Request OPTIONAL\r
2486 )\r
2487{\r
2488 return InternalHiiIfrValueAction (Request, 0, ACTION_VALIDATE_SETTING);\r
2489}\r
2490\r
2491/**\r
2492 Reset the default value specified by DefaultId to the driver\r
2493 configuration got by Request string. \r
2494\r
2495 NULL request string support depends on the ExportConfig interface of\r
2496 HiiConfigRouting protocol in UEFI specification.\r
2497 \r
2498 @param Request A null-terminated Unicode string in \r
2499 <MultiConfigRequest> format. It can be NULL.\r
2500 If it is NULL, all configuration for the\r
2501 entirety of the current HII database will be reset.\r
2502 @param DefaultId Specifies the type of defaults to retrieve.\r
2503 \r
3b28e744 2504 @retval TRUE The default value is set successfully.\r
84f9a9ec
LG
2505 @retval FALSE The default value can't be found and set.\r
2506**/\r
2507BOOLEAN\r
2508EFIAPI\r
2509HiiSetToDefaults (\r
2510 IN CONST EFI_STRING Request, OPTIONAL\r
2511 IN UINT16 DefaultId\r
2512 )\r
2513{\r
2514 return InternalHiiIfrValueAction (Request, DefaultId, ACTION_SET_DEFAUTL_VALUE);\r
2515}\r
2516\r
7e3bcccb
LG
2517/**\r
2518 Determines if two values in config strings match.\r
2519\r
2520 Compares the substring between StartSearchString and StopSearchString in \r
2521 FirstString to the substring between StartSearchString and StopSearchString \r
2522 in SecondString. If the two substrings match, then TRUE is returned. If the\r
2523 two substrings do not match, then FALSE is returned.\r
2524\r
2525 If FirstString is NULL, then ASSERT().\r
2526 If SecondString is NULL, then ASSERT().\r
2527 If StartSearchString is NULL, then ASSERT().\r
2528 If StopSearchString is NULL, then ASSERT().\r
2529\r
2530 @param FirstString Pointer to the first Null-terminated Unicode string.\r
2531 @param SecondString Pointer to the second Null-terminated Unicode string.\r
2532 @param StartSearchString Pointer to the Null-terminated Unicode string that \r
2533 marks the start of the value string to compare.\r
2534 @param StopSearchString Pointer to the Null-terminated Unicode string that \r
84213069 2535 marks the end of the value string to compare.\r
7e3bcccb
LG
2536\r
2537 @retval FALSE StartSearchString is not present in FirstString. \r
2538 @retval FALSE StartSearchString is not present in SecondString.\r
2539 @retval FALSE StopSearchString is not present in FirstString. \r
2540 @retval FALSE StopSearchString is not present in SecondString.\r
2541 @retval FALSE The length of the substring in FirstString is not the \r
2542 same length as the substring in SecondString.\r
2543 @retval FALSE The value string in FirstString does not matche the \r
2544 value string in SecondString.\r
2545 @retval TRUE The value string in FirstString matches the value \r
2546 string in SecondString.\r
2547\r
2548**/\r
2549BOOLEAN\r
2550EFIAPI\r
2551InternalHiiCompareSubString (\r
2552 IN CHAR16 *FirstString,\r
2553 IN CHAR16 *SecondString,\r
2554 IN CHAR16 *StartSearchString,\r
2555 IN CHAR16 *StopSearchString\r
2556 )\r
2557{\r
2558 CHAR16 *EndFirstString;\r
2559 CHAR16 *EndSecondString;\r
2560\r
2561 ASSERT (FirstString != NULL);\r
2562 ASSERT (SecondString != NULL);\r
2563 ASSERT (StartSearchString != NULL);\r
2564 ASSERT (StopSearchString != NULL);\r
2565\r
2566 FirstString = StrStr (FirstString, StartSearchString);\r
2567 if (FirstString == NULL) {\r
2568 return FALSE;\r
2569 }\r
2570\r
2571 SecondString = StrStr (SecondString, StartSearchString);\r
2572 if (SecondString == NULL) {\r
2573 return FALSE;\r
2574 }\r
2575\r
2576 EndFirstString = StrStr (FirstString, StopSearchString);\r
2577 if (EndFirstString == NULL) {\r
2578 return FALSE;\r
2579 }\r
2580\r
2581 EndSecondString = StrStr (SecondString, StopSearchString);\r
2582 if (EndSecondString == NULL) {\r
2583 return FALSE;\r
2584 }\r
2585\r
2586 if ((EndFirstString - FirstString) != (EndSecondString - SecondString)) {\r
2587 return FALSE;\r
2588 }\r
2589\r
2590 return (BOOLEAN)(StrnCmp (FirstString, SecondString, EndFirstString - FirstString) == 0);\r
2591}\r
2592\r
2593/**\r
2594 Determines if the routing data specified by GUID and NAME match a <ConfigHdr>.\r
2595\r
2596 If ConfigHdr is NULL, then ASSERT().\r
2597\r
2598 @param[in] ConfigHdr Either <ConfigRequest> or <ConfigResp>.\r
2599 @param[in] Guid GUID of the storage.\r
2600 @param[in] Name NAME of the storage.\r
2601\r
2602 @retval TRUE Routing information matches <ConfigHdr>.\r
2603 @retval FALSE Routing information does not match <ConfigHdr>.\r
2604\r
2605**/\r
2606BOOLEAN\r
2607EFIAPI\r
2608HiiIsConfigHdrMatch (\r
2609 IN CONST EFI_STRING ConfigHdr,\r
2610 IN CONST EFI_GUID *Guid, OPTIONAL\r
2611 IN CONST CHAR16 *Name OPTIONAL\r
2612 )\r
2613{\r
2614 EFI_STRING CompareConfigHdr;\r
2615 BOOLEAN Result;\r
2616\r
2617 ASSERT (ConfigHdr != NULL);\r
2618\r
2619 //\r
2620 // Use Guid and Name to generate a <ConfigHdr> string\r
2621 //\r
2622 CompareConfigHdr = HiiConstructConfigHdr (Guid, Name, NULL);\r
2623 if (CompareConfigHdr == NULL) {\r
2624 return FALSE;\r
2625 }\r
2626\r
2627 Result = TRUE;\r
2628 if (Guid != NULL) {\r
2629 //\r
2630 // Compare GUID value strings\r
2631 //\r
2632 Result = InternalHiiCompareSubString (ConfigHdr, CompareConfigHdr, L"GUID=", L"&NAME=");\r
2633 }\r
2634\r
2635 if (Result && Name != NULL) {\r
2636 //\r
2637 // Compare NAME value strings\r
2638 //\r
2639 Result = InternalHiiCompareSubString (ConfigHdr, CompareConfigHdr, L"&NAME=", L"&PATH=");\r
2640 }\r
2641\r
2642 //\r
2643 // Free the <ConfigHdr> string\r
2644 //\r
2645 FreePool (CompareConfigHdr);\r
2646\r
2647 return Result;\r
2648}\r
2649\r
2650/**\r
84213069 2651 Retrieves uncommitted data from the Form Browser and converts it to a binary\r
1d451ff9 2652 buffer.\r
7e3bcccb 2653\r
1d451ff9
LG
2654 @param[in] VariableGuid Pointer to an EFI_GUID structure. This is an optional \r
2655 parameter that may be NULL.\r
84213069
LG
2656 @param[in] VariableName Pointer to a Null-terminated Unicode string. This \r
2657 is an optional parameter that may be NULL.\r
2658 @param[in] BufferSize Length in bytes of buffer to hold retrieved data. \r
2659 @param[out] Buffer Buffer of data to be updated.\r
7e3bcccb 2660\r
1d451ff9
LG
2661 @retval FALSE The uncommitted data could not be retrieved.\r
2662 @retval TRUE The uncommitted data was retrieved.\r
7e3bcccb
LG
2663\r
2664**/\r
1d451ff9 2665BOOLEAN\r
7e3bcccb
LG
2666EFIAPI\r
2667HiiGetBrowserData (\r
2668 IN CONST EFI_GUID *VariableGuid, OPTIONAL\r
2669 IN CONST CHAR16 *VariableName, OPTIONAL\r
84213069
LG
2670 IN UINTN BufferSize,\r
2671 OUT UINT8 *Buffer\r
7e3bcccb
LG
2672 )\r
2673{\r
2674 EFI_STRING ResultsData;\r
2675 UINTN Size;\r
2676 EFI_STRING ConfigResp;\r
1d451ff9
LG
2677 EFI_STATUS Status;\r
2678 CHAR16 *Progress;\r
7e3bcccb
LG
2679\r
2680 //\r
2681 // Retrieve the results data from the Browser Callback\r
2682 //\r
2683 ResultsData = InternalHiiBrowserCallback (VariableGuid, VariableName, NULL);\r
2684 if (ResultsData == NULL) {\r
1d451ff9 2685 return FALSE;\r
7e3bcccb
LG
2686 }\r
2687\r
2688 //\r
5c1ebff6 2689 // Construct <ConfigResp> mConfigHdrTemplate L'&' ResultsData L'\0'\r
7e3bcccb 2690 //\r
5c1ebff6
LG
2691 Size = (StrLen (mConfigHdrTemplate) + 1) * sizeof (CHAR16);\r
2692 Size = Size + (StrLen (ResultsData) + 1) * sizeof (CHAR16);\r
7e3bcccb
LG
2693 ConfigResp = AllocateZeroPool (Size);\r
2694 UnicodeSPrint (ConfigResp, Size, L"%s&%s", mConfigHdrTemplate, ResultsData);\r
2695 \r
2696 //\r
2697 // Free the allocated buffer\r
2698 //\r
2699 FreePool (ResultsData);\r
2700 if (ConfigResp == NULL) {\r
1d451ff9 2701 return FALSE;\r
7e3bcccb
LG
2702 }\r
2703\r
2704 //\r
2705 // Convert <ConfigResp> to a buffer\r
2706 //\r
1d451ff9
LG
2707 Status = gHiiConfigRouting->ConfigToBlock (\r
2708 gHiiConfigRouting,\r
2709 ConfigResp,\r
84213069
LG
2710 Buffer,\r
2711 &BufferSize,\r
1d451ff9
LG
2712 &Progress\r
2713 );\r
2714 //\r
2715 // Free the allocated buffer\r
2716 //\r
7e3bcccb
LG
2717 FreePool (ConfigResp);\r
2718\r
1d451ff9
LG
2719 if (EFI_ERROR (Status)) {\r
2720 return FALSE;\r
2721 }\r
2722\r
2723 return TRUE;\r
7e3bcccb
LG
2724}\r
2725\r
2726/**\r
2727 Updates uncommitted data in the Form Browser.\r
2728\r
2729 If Buffer is NULL, then ASSERT().\r
2730\r
7e3bcccb
LG
2731 @param[in] VariableGuid Pointer to an EFI_GUID structure. This is an optional\r
2732 parameter that may be NULL.\r
84213069
LG
2733 @param[in] VariableName Pointer to a Null-terminated Unicode string. This\r
2734 is an optional parameter that may be NULL.\r
7e3bcccb
LG
2735 @param[in] BufferSize Length, in bytes, of Buffer.\r
2736 @param[in] Buffer Buffer of data to commit.\r
2737 @param[in] RequestElement An optional field to specify which part of the\r
2738 buffer data will be send back to Browser. If NULL,\r
2739 the whole buffer of data will be committed to\r
2740 Browser. \r
2741 <RequestElement> ::= &OFFSET=<Number>&WIDTH=<Number>*\r
2742\r
2743 @retval FALSE The uncommitted data could not be updated.\r
2744 @retval TRUE The uncommitted data was updated.\r
2745\r
2746**/\r
2747BOOLEAN\r
2748EFIAPI\r
2749HiiSetBrowserData (\r
2750 IN CONST EFI_GUID *VariableGuid, OPTIONAL\r
2751 IN CONST CHAR16 *VariableName, OPTIONAL\r
2752 IN UINTN BufferSize,\r
2753 IN CONST UINT8 *Buffer,\r
2754 IN CONST CHAR16 *RequestElement OPTIONAL\r
2755 )\r
2756{\r
2757 UINTN Size;\r
2758 EFI_STRING ConfigRequest;\r
2759 EFI_STRING ConfigResp;\r
2760 EFI_STRING ResultsData;\r
2761\r
2762 ASSERT (Buffer != NULL);\r
2763\r
2764 //\r
2765 // Construct <ConfigRequest>\r
2766 //\r
2767 if (RequestElement == NULL) {\r
2768 //\r
2769 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template \r
2770 // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator\r
2771 //\r
2772 Size = (StrLen (mConfigHdrTemplate) + 32 + 1) * sizeof (CHAR16);\r
2773 ConfigRequest = AllocateZeroPool (Size);\r
2774 UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", mConfigHdrTemplate, (UINT64)BufferSize);\r
2775 } else {\r
2776 //\r
2777 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template \r
2778 // followed by <RequestElement> followed by a Null-terminator\r
2779 //\r
5c1ebff6
LG
2780 Size = StrLen (mConfigHdrTemplate) * sizeof (CHAR16);\r
2781 Size = Size + (StrLen (RequestElement) + 1) * sizeof (CHAR16);\r
7e3bcccb
LG
2782 ConfigRequest = AllocateZeroPool (Size);\r
2783 UnicodeSPrint (ConfigRequest, Size, L"%s%s", mConfigHdrTemplate, RequestElement);\r
2784 }\r
2785 if (ConfigRequest == NULL) {\r
2786 return FALSE;\r
2787 }\r
2788\r
2789 //\r
2790 // Convert <ConfigRequest> to <ConfigResp>\r
2791 //\r
2792 ConfigResp = InternalHiiBlockToConfig (ConfigRequest, Buffer, BufferSize);\r
2793 FreePool (ConfigRequest);\r
2794 if (ConfigResp == NULL) {\r
2795 return FALSE;\r
2796 }\r
2797\r
2798 //\r
2799 // Set data in the uncommitted browser state information\r
2800 //\r
2801 ResultsData = InternalHiiBrowserCallback (VariableGuid, VariableName, ConfigResp + StrLen(mConfigHdrTemplate) + 1);\r
2802 FreePool (ConfigResp);\r
2803\r
2804 return (BOOLEAN)(ResultsData != NULL);\r
2805}\r
2806\r
2807/////////////////////////////////////////\r
2808/////////////////////////////////////////\r
2809/// IFR Functions\r
2810/////////////////////////////////////////\r
2811/////////////////////////////////////////\r
2812\r
2813#define HII_LIB_OPCODE_ALLOCATION_SIZE 0x200\r
2814\r
2815typedef struct {\r
2816 UINT8 *Buffer;\r
2817 UINTN BufferSize;\r
2818 UINTN Position;\r
2819} HII_LIB_OPCODE_BUFFER;\r
2820\r
2821///\r
2822/// Lookup table that converts EFI_IFR_TYPE_X enum values to a width in bytes\r
2823///\r
2824GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 mHiiDefaultTypeToWidth[] = {\r
2825 1, // EFI_IFR_TYPE_NUM_SIZE_8\r
2826 2, // EFI_IFR_TYPE_NUM_SIZE_16\r
2827 4, // EFI_IFR_TYPE_NUM_SIZE_32\r
2828 8, // EFI_IFR_TYPE_NUM_SIZE_64\r
2829 1, // EFI_IFR_TYPE_BOOLEAN\r
2830 3, // EFI_IFR_TYPE_TIME\r
2831 4, // EFI_IFR_TYPE_DATE\r
2832 2 // EFI_IFR_TYPE_STRING\r
2833};\r
2834\r
2835/**\r
2836 Allocates and returns a new OpCode Handle. OpCode Handles must be freed with \r
2837 HiiFreeOpCodeHandle().\r
2838\r
2839 @retval NULL There are not enough resources to allocate a new OpCode Handle.\r
2840 @retval Other A new OpCode handle.\r
2841\r
2842**/\r
2843VOID *\r
2844EFIAPI\r
2845HiiAllocateOpCodeHandle (\r
2846 VOID\r
2847 )\r
2848{\r
2849 HII_LIB_OPCODE_BUFFER *OpCodeBuffer;\r
2850\r
2851 OpCodeBuffer = (HII_LIB_OPCODE_BUFFER *)AllocatePool (sizeof (HII_LIB_OPCODE_BUFFER));\r
2852 if (OpCodeBuffer == NULL) {\r
2853 return NULL;\r
2854 }\r
2855 OpCodeBuffer->Buffer = (UINT8 *)AllocatePool (HII_LIB_OPCODE_ALLOCATION_SIZE);\r
2856 if (OpCodeBuffer->Buffer == NULL) {\r
2857 FreePool (OpCodeBuffer);\r
2858 return NULL;\r
2859 }\r
2860 OpCodeBuffer->BufferSize = HII_LIB_OPCODE_ALLOCATION_SIZE;\r
2861 OpCodeBuffer->Position = 0;\r
2862 return (VOID *)OpCodeBuffer;\r
2863}\r
2864\r
2865/**\r
84213069 2866 Frees an OpCode Handle that was previously allocated with HiiAllocateOpCodeHandle().\r
7e3bcccb
LG
2867 When an OpCode Handle is freed, all of the opcodes associated with the OpCode\r
2868 Handle are also freed.\r
2869\r
2870 If OpCodeHandle is NULL, then ASSERT().\r
2871\r
84213069
LG
2872 @param[in] OpCodeHandle Handle to the buffer of opcodes.\r
2873\r
7e3bcccb
LG
2874**/\r
2875VOID\r
2876EFIAPI\r
2877HiiFreeOpCodeHandle (\r
2878 VOID *OpCodeHandle\r
2879 )\r
2880{\r
2881 HII_LIB_OPCODE_BUFFER *OpCodeBuffer;\r
2882\r
2883 ASSERT (OpCodeHandle != NULL);\r
2884\r
2885 OpCodeBuffer = (HII_LIB_OPCODE_BUFFER *)OpCodeHandle;\r
2886 if (OpCodeBuffer->Buffer != NULL) {\r
2887 FreePool (OpCodeBuffer->Buffer);\r
2888 }\r
2889 FreePool (OpCodeBuffer);\r
2890}\r
2891\r
84213069
LG
2892/**\r
2893 Internal function gets the current position of opcode buffer.\r
2894 \r
2895 @param[in] OpCodeHandle Handle to the buffer of opcodes.\r
2896\r
2897 @return Current position of opcode buffer.\r
2898**/\r
7e3bcccb
LG
2899UINTN\r
2900EFIAPI\r
2901InternalHiiOpCodeHandlePosition (\r
2902 IN VOID *OpCodeHandle\r
2903 )\r
2904{\r
2905 return ((HII_LIB_OPCODE_BUFFER *)OpCodeHandle)->Position;\r
2906}\r
2907\r
84213069
LG
2908/**\r
2909 Internal function gets the start pointer of opcode buffer.\r
2910 \r
2911 @param[in] OpCodeHandle Handle to the buffer of opcodes.\r
2912\r
2913 @return Pointer to the opcode buffer base.\r
2914**/\r
7e3bcccb
LG
2915UINT8 *\r
2916EFIAPI\r
2917InternalHiiOpCodeHandleBuffer (\r
2918 IN VOID *OpCodeHandle\r
2919 )\r
2920{\r
2921 return ((HII_LIB_OPCODE_BUFFER *)OpCodeHandle)->Buffer;\r
2922}\r
2923\r
84213069
LG
2924/**\r
2925 Internal function reserves the enough buffer for current opcode.\r
2926 When the buffer is not enough, Opcode buffer will be extended.\r
2927 \r
2928 @param[in] OpCodeHandle Handle to the buffer of opcodes.\r
2929 @param[in] Size Size of current opcode.\r
2930\r
2931 @return Pointer to the current opcode.\r
2932**/\r
7e3bcccb
LG
2933UINT8 *\r
2934EFIAPI\r
2935InternalHiiGrowOpCodeHandle (\r
84213069
LG
2936 IN VOID *OpCodeHandle,\r
2937 IN UINTN Size\r
7e3bcccb
LG
2938 )\r
2939{\r
2940 HII_LIB_OPCODE_BUFFER *OpCodeBuffer;\r
2941 UINT8 *Buffer;\r
2942\r
2943 ASSERT (OpCodeHandle != NULL);\r
2944\r
2945 OpCodeBuffer = (HII_LIB_OPCODE_BUFFER *)OpCodeHandle;\r
2946 if (OpCodeBuffer->Position + Size > OpCodeBuffer->BufferSize) {\r
2947 Buffer = ReallocatePool (\r
2948 OpCodeBuffer->BufferSize, \r
2949 OpCodeBuffer->BufferSize + (Size + HII_LIB_OPCODE_ALLOCATION_SIZE),\r
2950 OpCodeBuffer->Buffer\r
2951 );\r
02a758cb 2952 ASSERT (Buffer != NULL);\r
7e3bcccb
LG
2953 OpCodeBuffer->Buffer = Buffer;\r
2954 OpCodeBuffer->BufferSize += (Size + HII_LIB_OPCODE_ALLOCATION_SIZE);\r
2955 }\r
2956 Buffer = OpCodeBuffer->Buffer + OpCodeBuffer->Position;\r
2957 OpCodeBuffer->Position += Size;\r
2958 return Buffer;\r
2959}\r
2960\r
84213069
LG
2961/**\r
2962 Internal function creates opcode based on the template opcode.\r
2963 \r
2964 @param[in] OpCodeHandle Handle to the buffer of opcodes.\r
2965 @param[in] OpCodeTemplate Pointer to the template buffer of opcode.\r
2966 @param[in] OpCode OpCode IFR value.\r
2967 @param[in] OpCodeSize Size of opcode.\r
2968 @param[in] ExtensionSize Size of extended opcode.\r
2969 @param[in] Scope Scope bit of opcode.\r
2970\r
2971 @return Pointer to the current opcode with opcode data.\r
2972**/\r
7e3bcccb
LG
2973UINT8 *\r
2974EFIAPI\r
2975InternalHiiCreateOpCodeExtended (\r
2976 IN VOID *OpCodeHandle,\r
2977 IN VOID *OpCodeTemplate,\r
2978 IN UINT8 OpCode,\r
2979 IN UINTN OpCodeSize,\r
2980 IN UINTN ExtensionSize,\r
2981 IN UINT8 Scope\r
2982 )\r
2983{\r
2984 EFI_IFR_OP_HEADER *Header;\r
2985 UINT8 *Buffer;\r
2986\r
2987 ASSERT (OpCodeTemplate != NULL);\r
2988 ASSERT ((OpCodeSize + ExtensionSize) <= 0x7F);\r
2989\r
2990 Header = (EFI_IFR_OP_HEADER *)OpCodeTemplate;\r
2991 Header->OpCode = OpCode;\r
2992 Header->Scope = Scope;\r
2993 Header->Length = (UINT8)(OpCodeSize + ExtensionSize);\r
2994 Buffer = InternalHiiGrowOpCodeHandle (OpCodeHandle, Header->Length);\r
2995 return (UINT8 *)CopyMem (Buffer, Header, OpCodeSize);\r
2996}\r
2997\r
84213069
LG
2998/**\r
2999 Internal function creates opcode based on the template opcode for the normal opcode.\r
3000 \r
3001 @param[in] OpCodeHandle Handle to the buffer of opcodes.\r
3002 @param[in] OpCodeTemplate Pointer to the template buffer of opcode.\r
3003 @param[in] OpCode OpCode IFR value.\r
3004 @param[in] OpCodeSize Size of opcode.\r
3005\r
3006 @return Pointer to the current opcode with opcode data.\r
3007**/\r
7e3bcccb
LG
3008UINT8 *\r
3009EFIAPI\r
3010InternalHiiCreateOpCode (\r
3011 IN VOID *OpCodeHandle,\r
3012 IN VOID *OpCodeTemplate,\r
3013 IN UINT8 OpCode,\r
3014 IN UINTN OpCodeSize\r
3015 )\r
3016{\r
3017 return InternalHiiCreateOpCodeExtended (OpCodeHandle, OpCodeTemplate, OpCode, OpCodeSize, 0, 0);\r
3018}\r
3019\r
3020/**\r
3021 Append raw opcodes to an OpCodeHandle.\r
3022\r
3023 If OpCodeHandle is NULL, then ASSERT().\r
3024 If RawBuffer is NULL, then ASSERT();\r
3025\r
3026 @param[in] OpCodeHandle Handle to the buffer of opcodes.\r
3027 @param[in] RawBuffer Buffer of opcodes to append.\r
3028 @param[in] RawBufferSize The size, in bytes, of Buffer.\r
3029\r
3030 @retval NULL There is not enough space left in Buffer to add the opcode.\r
3031 @retval Other A pointer to the appended opcodes.\r
3032\r
3033**/\r
3034UINT8 *\r
3035EFIAPI\r
278663ab 3036HiiCreateRawOpCodes (\r
7e3bcccb
LG
3037 IN VOID *OpCodeHandle,\r
3038 IN UINT8 *RawBuffer,\r
3039 IN UINTN RawBufferSize\r
3040 )\r
3041{\r
3042 UINT8 *Buffer;\r
3043\r
3044 ASSERT (RawBuffer != NULL);\r
3045\r
3046 Buffer = InternalHiiGrowOpCodeHandle (OpCodeHandle, RawBufferSize);\r
3047 return (UINT8 *)CopyMem (Buffer, RawBuffer, RawBufferSize);\r
3048}\r
3049\r
3050/**\r
3051 Append opcodes from one OpCode Handle to another OpCode handle.\r
3052\r
3053 If OpCodeHandle is NULL, then ASSERT().\r
3054 If RawOpCodeHandle is NULL, then ASSERT();\r
3055\r
3056 @param[in] OpCodeHandle Handle to the buffer of opcodes.\r
3057 @param[in] RawOpCodeHandle Handle to the buffer of opcodes.\r
3058\r
3059 @retval NULL There is not enough space left in Buffer to add the opcode.\r
3060 @retval Other A pointer to the appended opcodes.\r
3061\r
3062**/\r
3063UINT8 *\r
3064EFIAPI\r
3065InternalHiiAppendOpCodes (\r
3066 IN VOID *OpCodeHandle,\r
3067 IN VOID *RawOpCodeHandle\r
3068 )\r
3069{\r
3070 HII_LIB_OPCODE_BUFFER *RawOpCodeBuffer;\r
3071\r
3072 ASSERT (RawOpCodeHandle != NULL);\r
3073\r
3074 RawOpCodeBuffer = (HII_LIB_OPCODE_BUFFER *)RawOpCodeHandle;\r
278663ab 3075 return HiiCreateRawOpCodes (OpCodeHandle, RawOpCodeBuffer->Buffer, RawOpCodeBuffer->Position);\r
7e3bcccb
LG
3076}\r
3077\r
3078/**\r
3079 Create EFI_IFR_END_OP opcode.\r
3080\r
3081 If OpCodeHandle is NULL, then ASSERT().\r
3082\r
3083 @param[in] OpCodeHandle Handle to the buffer of opcodes.\r
3084\r
3085 @retval NULL There is not enough space left in Buffer to add the opcode.\r
3086 @retval Other A pointer to the created opcode.\r
3087\r
3088**/\r
3089UINT8 *\r
3090EFIAPI\r
3091HiiCreateEndOpCode (\r
3092 IN VOID *OpCodeHandle\r
3093 )\r
3094{\r
3095 EFI_IFR_END OpCode;\r
3096\r
3097 return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_END_OP, sizeof (OpCode));\r
3098}\r
3099\r
3100/**\r
3101 Create EFI_IFR_ONE_OF_OPTION_OP opcode.\r
3102\r
3103 If OpCodeHandle is NULL, then ASSERT().\r
3104 If Type is invalid, then ASSERT().\r
3105 If Flags is invalid, then ASSERT().\r
3106\r
3107 @param[in] OpCodeHandle Handle to the buffer of opcodes.\r
3108 @param[in] StringId StringId for the option\r
3109 @param[in] Flags Flags for the option\r
3110 @param[in] Type Type for the option\r
3111 @param[in] Value Value for the option\r
3112\r
3113 @retval NULL There is not enough space left in Buffer to add the opcode.\r
3114 @retval Other A pointer to the created opcode.\r
3115\r
3116**/\r
3117UINT8 *\r
3118EFIAPI\r
3119HiiCreateOneOfOptionOpCode (\r
3120 IN VOID *OpCodeHandle,\r
3121 IN UINT16 StringId,\r
3122 IN UINT8 Flags,\r
3123 IN UINT8 Type,\r
3124 IN UINT64 Value\r
3125 )\r
3126{\r
3127 EFI_IFR_ONE_OF_OPTION OpCode;\r
3128\r
3129 ASSERT (Type < EFI_IFR_TYPE_OTHER);\r
3130\r
3131 ZeroMem (&OpCode, sizeof (OpCode));\r
3132 OpCode.Option = StringId;\r
3133 OpCode.Flags = (UINT8) (Flags & (EFI_IFR_OPTION_DEFAULT | EFI_IFR_OPTION_DEFAULT_MFG));\r
3134 OpCode.Type = Type;\r
3135 CopyMem (&OpCode.Value, &Value, mHiiDefaultTypeToWidth[Type]);\r
3136\r
a7f87053 3137 return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_ONE_OF_OPTION_OP, OFFSET_OF(EFI_IFR_ONE_OF_OPTION, Value) + mHiiDefaultTypeToWidth[Type]);\r
7e3bcccb
LG
3138}\r
3139\r
3140/**\r
3141 Create EFI_IFR_DEFAULT_OP opcode.\r
3142\r
3143 If OpCodeHandle is NULL, then ASSERT().\r
3144 If Type is invalid, then ASSERT().\r
3145\r
3146 @param[in] OpCodeHandle Handle to the buffer of opcodes.\r
3147 @param[in] DefaultId DefaultId for the default\r
3148 @param[in] Type Type for the default\r
3149 @param[in] Value Value for the default\r
3150\r
3151 @retval NULL There is not enough space left in Buffer to add the opcode.\r
3152 @retval Other A pointer to the created opcode.\r
3153\r
3154**/\r
3155UINT8 *\r
3156EFIAPI\r
3157HiiCreateDefaultOpCode (\r
3158 IN VOID *OpCodeHandle,\r
3159 IN UINT16 DefaultId,\r
3160 IN UINT8 Type,\r
3161 IN UINT64 Value\r
3162 )\r
3163{\r
3164 EFI_IFR_DEFAULT OpCode;\r
3165\r
3166 ASSERT (Type < EFI_IFR_TYPE_OTHER);\r
3167\r
3168 ZeroMem (&OpCode, sizeof (OpCode));\r
3169 OpCode.Type = Type;\r
3170 OpCode.DefaultId = DefaultId;\r
3171 CopyMem (&OpCode.Value, &Value, mHiiDefaultTypeToWidth[Type]);\r
3172\r
23fe74dc 3173 return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_DEFAULT_OP, OFFSET_OF(EFI_IFR_DEFAULT, Value) + mHiiDefaultTypeToWidth[Type]);\r
7e3bcccb
LG
3174}\r
3175\r
3176/**\r
3177 Create EFI_IFR_GUID opcode.\r
3178\r
3179 If OpCodeHandle is NULL, then ASSERT().\r
3180 If Guid is NULL, then ASSERT().\r
3181 If OpCodeSize < sizeof (EFI_IFR_GUID), then ASSERT().\r
3182\r
3183 @param[in] OpCodeHandle Handle to the buffer of opcodes.\r
3184 @param[in] Guid Pointer to EFI_GUID of this guided opcode.\r
3185 @param[in] GuidOpCode Pointer to an EFI_IFR_GUID opcode. This is an \r
3186 optional parameter that may be NULL. If this\r
3187 parameter is NULL, then the GUID extension \r
3188 region of the created opcode is filled with zeros.\r
3189 If this parameter is not NULL, then the GUID \r
3190 extension region of GuidData will be copied to \r
3191 the GUID extension region of the created opcode.\r
3192 @param[in] OpCodeSize The size, in bytes, of created opcode. This value \r
3193 must be >= sizeof(EFI_IFR_GUID).\r
3194\r
3195 @retval NULL There is not enough space left in Buffer to add the opcode.\r
3196 @retval Other A pointer to the created opcode.\r
3197\r
3198**/\r
3199UINT8 *\r
3200EFIAPI\r
3201HiiCreateGuidOpCode (\r
3202 IN VOID *OpCodeHandle,\r
3203 IN CONST EFI_GUID *Guid,\r
3204 IN CONST VOID *GuidOpCode, OPTIONAL\r
3205 IN UINTN OpCodeSize\r
3206 )\r
3207{\r
3208 EFI_IFR_GUID OpCode;\r
3209 EFI_IFR_GUID *OpCodePointer;\r
3210\r
3211 ASSERT (Guid != NULL);\r
3212 ASSERT (OpCodeSize >= sizeof (OpCode));\r
3213\r
3214 ZeroMem (&OpCode, sizeof (OpCode));\r
5c1ebff6 3215 CopyGuid ((EFI_GUID *)(VOID *)&OpCode.Guid, Guid);\r
7e3bcccb
LG
3216\r
3217 OpCodePointer = (EFI_IFR_GUID *)InternalHiiCreateOpCodeExtended (\r
3218 OpCodeHandle, \r
3219 &OpCode,\r
3220 EFI_IFR_GUID_OP,\r
3221 sizeof (OpCode),\r
3222 OpCodeSize - sizeof (OpCode),\r
3223 0\r
3224 );\r
3225 if (OpCodePointer != NULL && GuidOpCode != NULL) {\r
3226 CopyMem (OpCodePointer + 1, (EFI_IFR_GUID *)GuidOpCode + 1, OpCodeSize - sizeof (OpCode));\r
3227 }\r
3228 return (UINT8 *)OpCodePointer;\r
3229}\r
3230\r
3231/**\r
3232 Create EFI_IFR_ACTION_OP opcode.\r
3233\r
3234 If OpCodeHandle is NULL, then ASSERT().\r
3235 If any reserved bits are set in QuestionFlags, then ASSERT().\r
3236\r
3237 @param[in] OpCodeHandle Handle to the buffer of opcodes.\r
3238 @param[in] QuestionId Question ID\r
3239 @param[in] Prompt String ID for Prompt\r
3240 @param[in] Help String ID for Help\r
3241 @param[in] QuestionFlags Flags in Question Header\r
3242 @param[in] QuestionConfig String ID for configuration\r
3243\r
3244 @retval NULL There is not enough space left in Buffer to add the opcode.\r
3245 @retval Other A pointer to the created opcode.\r
3246\r
3247**/\r
3248UINT8 *\r
3249EFIAPI\r
3250HiiCreateActionOpCode (\r
3251 IN VOID *OpCodeHandle,\r
3252 IN EFI_QUESTION_ID QuestionId,\r
3253 IN EFI_STRING_ID Prompt,\r
3254 IN EFI_STRING_ID Help,\r
3255 IN UINT8 QuestionFlags,\r
3256 IN EFI_STRING_ID QuestionConfig\r
3257 )\r
3258{\r
3259 EFI_IFR_ACTION OpCode;\r
3260\r
e22812c7 3261 ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED))) == 0);\r
7e3bcccb
LG
3262\r
3263 ZeroMem (&OpCode, sizeof (OpCode));\r
3264 OpCode.Question.QuestionId = QuestionId;\r
3265 OpCode.Question.Header.Prompt = Prompt;\r
3266 OpCode.Question.Header.Help = Help;\r
3267 OpCode.Question.Flags = QuestionFlags;\r
3268 OpCode.QuestionConfig = QuestionConfig;\r
3269\r
3270 return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_ACTION_OP, sizeof (OpCode));\r
3271}\r
3272\r
3273/**\r
3274 Create EFI_IFR_SUBTITLE_OP opcode.\r
3275\r
3276 If OpCodeHandle is NULL, then ASSERT().\r
3277 If any reserved bits are set in Flags, then ASSERT().\r
3278 If Scope > 1, then ASSERT().\r
3279\r
3280 @param[in] OpCodeHandle Handle to the buffer of opcodes.\r
3281 @param[in] Prompt String ID for Prompt\r
3282 @param[in] Help String ID for Help\r
3283 @param[in] Flags Subtitle opcode flags\r
3284 @param[in] Scope 1 if this opcpde is the beginning of a new scope.\r
3285 0 if this opcode is within the current scope.\r
3286\r
3287 @retval NULL There is not enough space left in Buffer to add the opcode.\r
3288 @retval Other A pointer to the created opcode.\r
3289\r
3290**/\r
3291UINT8 *\r
3292EFIAPI\r
3293HiiCreateSubTitleOpCode (\r
3294 IN VOID *OpCodeHandle,\r
3295 IN EFI_STRING_ID Prompt,\r
3296 IN EFI_STRING_ID Help,\r
3297 IN UINT8 Flags,\r
3298 IN UINT8 Scope\r
3299 )\r
3300{\r
3301 EFI_IFR_SUBTITLE OpCode;\r
3302\r
3303 ASSERT (Scope <= 1);\r
3304 ASSERT ((Flags & (~(EFI_IFR_FLAGS_HORIZONTAL))) == 0);\r
3305\r
3306 ZeroMem (&OpCode, sizeof (OpCode));\r
3307 OpCode.Statement.Prompt = Prompt;\r
3308 OpCode.Statement.Help = Help;\r
3309 OpCode.Flags = Flags;\r
3310\r
3311 return InternalHiiCreateOpCodeExtended (\r
3312 OpCodeHandle, \r
3313 &OpCode,\r
3314 EFI_IFR_SUBTITLE_OP, \r
3315 sizeof (OpCode), \r
3316 0, \r
3317 Scope\r
3318 );\r
3319}\r
3320\r
3321/**\r
3322 Create EFI_IFR_REF_OP opcode.\r
3323\r
3324 If OpCodeHandle is NULL, then ASSERT().\r
3325 If any reserved bits are set in QuestionFlags, then ASSERT().\r
3326\r
3327 @param[in] OpCodeHandle Handle to the buffer of opcodes.\r
3328 @param[in] FormId Destination Form ID\r
3329 @param[in] Prompt String ID for Prompt\r
3330 @param[in] Help String ID for Help\r
3331 @param[in] QuestionFlags Flags in Question Header\r
3332 @param[in] QuestionId Question ID\r
3333\r
3334 @retval NULL There is not enough space left in Buffer to add the opcode.\r
3335 @retval Other A pointer to the created opcode.\r
3336\r
3337**/\r
3338UINT8 *\r
3339EFIAPI\r
3340HiiCreateGotoOpCode (\r
3341 IN VOID *OpCodeHandle,\r
3342 IN EFI_FORM_ID FormId,\r
3343 IN EFI_STRING_ID Prompt,\r
3344 IN EFI_STRING_ID Help,\r
3345 IN UINT8 QuestionFlags,\r
3346 IN EFI_QUESTION_ID QuestionId\r
3347 )\r
3348{\r
3349 EFI_IFR_REF OpCode;\r
3350\r
e22812c7 3351 ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED))) == 0);\r
7e3bcccb
LG
3352\r
3353 ZeroMem (&OpCode, sizeof (OpCode));\r
3354 OpCode.Question.Header.Prompt = Prompt;\r
3355 OpCode.Question.Header.Help = Help;\r
3356 OpCode.Question.QuestionId = QuestionId;\r
3357 OpCode.Question.Flags = QuestionFlags;\r
3358 OpCode.FormId = FormId;\r
3359\r
3360 return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_REF_OP, sizeof (OpCode));\r
3361}\r
3362\r
e8654a1a
LG
3363/**\r
3364 Create EFI_IFR_REF_OP, EFI_IFR_REF2_OP, EFI_IFR_REF3_OP and EFI_IFR_REF4_OP opcode.\r
3365\r
3366 When RefDevicePath is not zero, EFI_IFR_REF4 opcode will be created. \r
3367 When RefDevicePath is zero and RefFormSetId is not NULL, EFI_IFR_REF3 opcode will be created.\r
3368 When RefDevicePath is zero, RefFormSetId is NULL and RefQuestionId is not zero, EFI_IFR_REF2 opcode will be created.\r
3369 When RefDevicePath is zero, RefFormSetId is NULL and RefQuestionId is zero, EFI_IFR_REF opcode will be created.\r
3370\r
3371 If OpCodeHandle is NULL, then ASSERT().\r
3372 If any reserved bits are set in QuestionFlags, then ASSERT().\r
3373\r
3374 @param[in] OpCodeHandle The handle to the buffer of opcodes.\r
3375 @param[in] RefFormId The Destination Form ID.\r
3376 @param[in] Prompt The string ID for Prompt.\r
3377 @param[in] Help The string ID for Help.\r
3378 @param[in] QuestionFlags The flags in Question Header\r
3379 @param[in] QuestionId Question ID.\r
3380 @param[in] RefQuestionId The question on the form to which this link is referring. \r
3381 If its value is zero, then the link refers to the top of the form.\r
3382 @param[in] RefFormSetId The form set to which this link is referring. If its value is NULL, and RefDevicePath is \r
3383 zero, then the link is to the current form set.\r
3384 @param[in] RefDevicePath The string identifier that specifies the string containing the text representation of \r
3385 the device path to which the form set containing the form specified by FormId.\r
3386 If its value is zero, then the link refers to the current page.\r
3387\r
3388 @retval NULL There is not enough space left in Buffer to add the opcode.\r
3389 @retval Other A pointer to the created opcode.\r
3390\r
3391**/\r
3392UINT8 *\r
3393EFIAPI\r
3394HiiCreateGotoExOpCode (\r
3395 IN VOID *OpCodeHandle,\r
3396 IN EFI_FORM_ID RefFormId,\r
3397 IN EFI_STRING_ID Prompt,\r
3398 IN EFI_STRING_ID Help,\r
3399 IN UINT8 QuestionFlags,\r
3400 IN EFI_QUESTION_ID QuestionId,\r
3401 IN EFI_QUESTION_ID RefQuestionId,\r
3402 IN EFI_GUID *RefFormSetId, OPTIONAL\r
3403 IN EFI_STRING_ID RefDevicePath\r
3404 )\r
3405{\r
3406 EFI_IFR_REF4 OpCode;\r
3407 UINTN OpCodeSize;\r
3408\r
3409 ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED))) == 0);\r
3410\r
3411 ZeroMem (&OpCode, sizeof (OpCode));\r
3412 OpCode.Question.Header.Prompt = Prompt;\r
3413 OpCode.Question.Header.Help = Help;\r
3414 OpCode.Question.QuestionId = QuestionId;\r
3415 OpCode.Question.Flags = QuestionFlags;\r
3416 OpCode.FormId = RefFormId;\r
3417 OpCode.QuestionId = RefQuestionId;\r
3418 OpCode.DevicePath = RefDevicePath;\r
3419 if (RefFormSetId != NULL) {\r
3420 CopyMem (&OpCode.FormSetId, RefFormSetId, sizeof (OpCode.FormSetId));\r
3421 }\r
3422\r
3423 //\r
3424 // Cacluate OpCodeSize based on the input Ref value.\r
3425 // Try to use the small OpCode to save size.\r
3426 //\r
3427 OpCodeSize = sizeof (EFI_IFR_REF);\r
3428 if (RefDevicePath != 0) {\r
3429 OpCodeSize = sizeof (EFI_IFR_REF4);\r
3430 } else if (RefFormSetId != NULL) {\r
3431 OpCodeSize = sizeof (EFI_IFR_REF3);\r
3432 } else if (RefQuestionId != 0) {\r
3433 OpCodeSize = sizeof (EFI_IFR_REF2);\r
3434 }\r
3435\r
3436 return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_REF_OP, OpCodeSize);\r
3437}\r
3438\r
7e3bcccb
LG
3439/**\r
3440 Create EFI_IFR_CHECKBOX_OP opcode.\r
3441\r
3442 If OpCodeHandle is NULL, then ASSERT().\r
3443 If any reserved bits are set in QuestionFlags, then ASSERT().\r
3444 If any reserved bits are set in CheckBoxFlags, then ASSERT().\r
3445\r
3446 @param[in] OpCodeHandle Handle to the buffer of opcodes.\r
3447 @param[in] QuestionId Question ID\r
3448 @param[in] VarStoreId Storage ID\r
09acdc0b
ED
3449 @param[in] VarOffset Offset in Storage or String ID of the name (VarName)\r
3450 for this name/value pair.\r
7e3bcccb
LG
3451 @param[in] Prompt String ID for Prompt\r
3452 @param[in] Help String ID for Help\r
3453 @param[in] QuestionFlags Flags in Question Header\r
3454 @param[in] CheckBoxFlags Flags for checkbox opcode\r
3455 @param[in] DefaultsOpCodeHandle Handle for a buffer of DEFAULT opcodes. This\r
3456 is an optional parameter that may be NULL.\r
3457\r
3458 @retval NULL There is not enough space left in Buffer to add the opcode.\r
3459 @retval Other A pointer to the created opcode.\r
3460\r
3461**/\r
3462UINT8 *\r
3463EFIAPI\r
3464HiiCreateCheckBoxOpCode (\r
3465 IN VOID *OpCodeHandle,\r
3466 IN EFI_QUESTION_ID QuestionId,\r
3467 IN EFI_VARSTORE_ID VarStoreId,\r
3468 IN UINT16 VarOffset,\r
3469 IN EFI_STRING_ID Prompt,\r
3470 IN EFI_STRING_ID Help,\r
3471 IN UINT8 QuestionFlags,\r
3472 IN UINT8 CheckBoxFlags,\r
3473 IN VOID *DefaultsOpCodeHandle OPTIONAL\r
3474 )\r
3475{\r
3476 EFI_IFR_CHECKBOX OpCode;\r
3477 UINTN Position;\r
3478\r
e22812c7 3479 ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED))) == 0);\r
7e3bcccb
LG
3480\r
3481 ZeroMem (&OpCode, sizeof (OpCode));\r
3482 OpCode.Question.QuestionId = QuestionId;\r
3483 OpCode.Question.VarStoreId = VarStoreId;\r
3484 OpCode.Question.VarStoreInfo.VarOffset = VarOffset;\r
3485 OpCode.Question.Header.Prompt = Prompt;\r
3486 OpCode.Question.Header.Help = Help;\r
3487 OpCode.Question.Flags = QuestionFlags;\r
3488 OpCode.Flags = CheckBoxFlags;\r
3489\r
3490 if (DefaultsOpCodeHandle == NULL) {\r
3491 return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_CHECKBOX_OP, sizeof (OpCode));\r
3492 }\r
3493\r
3494 Position = InternalHiiOpCodeHandlePosition (OpCodeHandle);\r
3495 InternalHiiCreateOpCodeExtended (OpCodeHandle, &OpCode, EFI_IFR_CHECKBOX_OP, sizeof (OpCode), 0, 1);\r
3496 InternalHiiAppendOpCodes (OpCodeHandle, DefaultsOpCodeHandle);\r
3497 HiiCreateEndOpCode (OpCodeHandle);\r
3498 return InternalHiiOpCodeHandleBuffer (OpCodeHandle) + Position;\r
3499}\r
3500\r
3501/**\r
3502 Create EFI_IFR_NUMERIC_OP opcode.\r
3503\r
3504 If OpCodeHandle is NULL, then ASSERT().\r
3505 If any reserved bits are set in QuestionFlags, then ASSERT().\r
3506 If any reserved bits are set in NumericFlags, then ASSERT().\r
3507\r
3508 @param[in] OpCodeHandle Handle to the buffer of opcodes.\r
3509 @param[in] QuestionId Question ID\r
3510 @param[in] VarStoreId Storage ID\r
09acdc0b
ED
3511 @param[in] VarOffset Offset in Storage or String ID of the name (VarName)\r
3512 for this name/value pair.\r
7e3bcccb
LG
3513 @param[in] Prompt String ID for Prompt\r
3514 @param[in] Help String ID for Help\r
3515 @param[in] QuestionFlags Flags in Question Header\r
3516 @param[in] NumericFlags Flags for numeric opcode\r
3517 @param[in] Minimum Numeric minimum value\r
3518 @param[in] Maximum Numeric maximum value\r
3519 @param[in] Step Numeric step for edit\r
3520 @param[in] DefaultsOpCodeHandle Handle for a buffer of DEFAULT opcodes. This\r
3521 is an optional parameter that may be NULL.\r
3522\r
3523 @retval NULL There is not enough space left in Buffer to add the opcode.\r
3524 @retval Other A pointer to the created opcode.\r
3525\r
3526**/\r
3527UINT8 *\r
3528EFIAPI\r
3529HiiCreateNumericOpCode (\r
3530 IN VOID *OpCodeHandle,\r
3531 IN EFI_QUESTION_ID QuestionId,\r
3532 IN EFI_VARSTORE_ID VarStoreId,\r
3533 IN UINT16 VarOffset,\r
3534 IN EFI_STRING_ID Prompt,\r
3535 IN EFI_STRING_ID Help,\r
3536 IN UINT8 QuestionFlags,\r
3537 IN UINT8 NumericFlags,\r
3538 IN UINT64 Minimum,\r
3539 IN UINT64 Maximum,\r
3540 IN UINT64 Step,\r
3541 IN VOID *DefaultsOpCodeHandle OPTIONAL\r
3542 )\r
3543{\r
3544 EFI_IFR_NUMERIC OpCode;\r
3545 UINTN Position;\r
d5931219 3546 UINTN Length;\r
7e3bcccb 3547\r
e22812c7 3548 ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED))) == 0);\r
7e3bcccb 3549\r
d5931219 3550 Length = 0;\r
7e3bcccb
LG
3551 ZeroMem (&OpCode, sizeof (OpCode));\r
3552 OpCode.Question.QuestionId = QuestionId;\r
3553 OpCode.Question.VarStoreId = VarStoreId;\r
3554 OpCode.Question.VarStoreInfo.VarOffset = VarOffset;\r
3555 OpCode.Question.Header.Prompt = Prompt;\r
3556 OpCode.Question.Header.Help = Help;\r
3557 OpCode.Question.Flags = QuestionFlags;\r
3558 OpCode.Flags = NumericFlags;\r
3559\r
3560 switch (NumericFlags & EFI_IFR_NUMERIC_SIZE) {\r
3561 case EFI_IFR_NUMERIC_SIZE_1:\r
3562 OpCode.data.u8.MinValue = (UINT8)Minimum;\r
3563 OpCode.data.u8.MaxValue = (UINT8)Maximum;\r
3564 OpCode.data.u8.Step = (UINT8)Step;\r
d5931219 3565 Length = 3;\r
7e3bcccb
LG
3566 break;\r
3567\r
3568 case EFI_IFR_NUMERIC_SIZE_2:\r
3569 OpCode.data.u16.MinValue = (UINT16)Minimum;\r
3570 OpCode.data.u16.MaxValue = (UINT16)Maximum;\r
3571 OpCode.data.u16.Step = (UINT16)Step;\r
d5931219 3572 Length = 6;\r
7e3bcccb
LG
3573 break;\r
3574\r
3575 case EFI_IFR_NUMERIC_SIZE_4:\r
3576 OpCode.data.u32.MinValue = (UINT32)Minimum;\r
3577 OpCode.data.u32.MaxValue = (UINT32)Maximum;\r
3578 OpCode.data.u32.Step = (UINT32)Step;\r
d5931219 3579 Length = 12;\r
7e3bcccb
LG
3580 break;\r
3581\r
3582 case EFI_IFR_NUMERIC_SIZE_8:\r
3583 OpCode.data.u64.MinValue = Minimum;\r
3584 OpCode.data.u64.MaxValue = Maximum;\r
3585 OpCode.data.u64.Step = Step;\r
d5931219 3586 Length = 24;\r
7e3bcccb
LG
3587 break;\r
3588 }\r
3589\r
d5931219
ED
3590 Length += OFFSET_OF (EFI_IFR_NUMERIC, data);\r
3591\r
7e3bcccb 3592 if (DefaultsOpCodeHandle == NULL) {\r
d5931219 3593 return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_NUMERIC_OP, Length);\r
7e3bcccb
LG
3594 }\r
3595\r
3596 Position = InternalHiiOpCodeHandlePosition (OpCodeHandle);\r
d5931219 3597 InternalHiiCreateOpCodeExtended (OpCodeHandle, &OpCode, EFI_IFR_NUMERIC_OP, Length, 0, 1);\r
7e3bcccb
LG
3598 InternalHiiAppendOpCodes (OpCodeHandle, DefaultsOpCodeHandle);\r
3599 HiiCreateEndOpCode (OpCodeHandle);\r
3600 return InternalHiiOpCodeHandleBuffer (OpCodeHandle) + Position;\r
3601}\r
3602\r
3603/**\r
3604 Create EFI_IFR_STRING_OP opcode.\r
3605\r
3606 If OpCodeHandle is NULL, then ASSERT().\r
3607 If any reserved bits are set in QuestionFlags, then ASSERT().\r
3608 If any reserved bits are set in StringFlags, then ASSERT().\r
3609\r
3610 @param[in] OpCodeHandle Handle to the buffer of opcodes.\r
3611 @param[in] QuestionId Question ID\r
3612 @param[in] VarStoreId Storage ID\r
09acdc0b
ED
3613 @param[in] VarOffset Offset in Storage or String ID of the name (VarName)\r
3614 for this name/value pair.\r
7e3bcccb
LG
3615 @param[in] Prompt String ID for Prompt\r
3616 @param[in] Help String ID for Help\r
3617 @param[in] QuestionFlags Flags in Question Header\r
3618 @param[in] StringFlags Flags for string opcode\r
3619 @param[in] MinSize String minimum length\r
3620 @param[in] MaxSize String maximum length\r
3621 @param[in] DefaultsOpCodeHandle Handle for a buffer of DEFAULT opcodes. This\r
3622 is an optional parameter that may be NULL.\r
3623\r
3624 @retval NULL There is not enough space left in Buffer to add the opcode.\r
3625 @retval Other A pointer to the created opcode.\r
3626\r
3627**/\r
3628UINT8 *\r
3629EFIAPI\r
3630HiiCreateStringOpCode (\r
3631 IN VOID *OpCodeHandle,\r
3632 IN EFI_QUESTION_ID QuestionId,\r
3633 IN EFI_VARSTORE_ID VarStoreId,\r
3634 IN UINT16 VarOffset,\r
3635 IN EFI_STRING_ID Prompt,\r
3636 IN EFI_STRING_ID Help,\r
3637 IN UINT8 QuestionFlags,\r
3638 IN UINT8 StringFlags,\r
3639 IN UINT8 MinSize,\r
3640 IN UINT8 MaxSize,\r
3641 IN VOID *DefaultsOpCodeHandle OPTIONAL\r
3642 )\r
3643{\r
3644 EFI_IFR_STRING OpCode;\r
3645 UINTN Position;\r
3646\r
e22812c7 3647 ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED))) == 0);\r
7e3bcccb
LG
3648\r
3649 ZeroMem (&OpCode, sizeof (OpCode));\r
3650 OpCode.Question.Header.Prompt = Prompt;\r
3651 OpCode.Question.Header.Help = Help;\r
3652 OpCode.Question.QuestionId = QuestionId;\r
3653 OpCode.Question.VarStoreId = VarStoreId;\r
3654 OpCode.Question.VarStoreInfo.VarOffset = VarOffset;\r
3655 OpCode.Question.Flags = QuestionFlags;\r
3656 OpCode.MinSize = MinSize;\r
3657 OpCode.MaxSize = MaxSize;\r
3658 OpCode.Flags = (UINT8) (StringFlags & EFI_IFR_STRING_MULTI_LINE);\r
3659\r
3660 if (DefaultsOpCodeHandle == NULL) {\r
3661 return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_STRING_OP, sizeof (OpCode));\r
3662 }\r
3663\r
3664 Position = InternalHiiOpCodeHandlePosition (OpCodeHandle);\r
3665 InternalHiiCreateOpCodeExtended (OpCodeHandle, &OpCode, EFI_IFR_STRING_OP, sizeof (OpCode), 0, 1);\r
3666 InternalHiiAppendOpCodes (OpCodeHandle, DefaultsOpCodeHandle);\r
3667 HiiCreateEndOpCode (OpCodeHandle);\r
3668 return InternalHiiOpCodeHandleBuffer (OpCodeHandle) + Position;\r
3669}\r
3670\r
3671/**\r
3672 Create EFI_IFR_ONE_OF_OP opcode.\r
3673\r
3674 If OpCodeHandle is NULL, then ASSERT().\r
3675 If any reserved bits are set in QuestionFlags, then ASSERT().\r
3676 If any reserved bits are set in OneOfFlags, then ASSERT().\r
3677\r
3678 @param[in] OpCodeHandle Handle to the buffer of opcodes.\r
3679 @param[in] QuestionId Question ID\r
3680 @param[in] VarStoreId Storage ID\r
09acdc0b
ED
3681 @param[in] VarOffset Offset in Storage or String ID of the name (VarName)\r
3682 for this name/value pair.\r
7e3bcccb
LG
3683 @param[in] Prompt String ID for Prompt\r
3684 @param[in] Help String ID for Help\r
3685 @param[in] QuestionFlags Flags in Question Header\r
3686 @param[in] OneOfFlags Flags for oneof opcode\r
3687 @param[in] OptionsOpCodeHandle Handle for a buffer of ONE_OF_OPTION opcodes.\r
3688 @param[in] DefaultsOpCodeHandle Handle for a buffer of DEFAULT opcodes. This\r
3689 is an optional parameter that may be NULL.\r
3690\r
3691 @retval NULL There is not enough space left in Buffer to add the opcode.\r
3692 @retval Other A pointer to the created opcode.\r
3693\r
3694**/\r
3695UINT8 *\r
3696EFIAPI\r
3697HiiCreateOneOfOpCode (\r
3698 IN VOID *OpCodeHandle,\r
3699 IN EFI_QUESTION_ID QuestionId,\r
3700 IN EFI_VARSTORE_ID VarStoreId,\r
3701 IN UINT16 VarOffset,\r
3702 IN EFI_STRING_ID Prompt,\r
3703 IN EFI_STRING_ID Help,\r
3704 IN UINT8 QuestionFlags,\r
3705 IN UINT8 OneOfFlags,\r
3706 IN VOID *OptionsOpCodeHandle,\r
3707 IN VOID *DefaultsOpCodeHandle OPTIONAL\r
3708 )\r
3709{\r
3710 EFI_IFR_ONE_OF OpCode;\r
3711 UINTN Position;\r
dcf5ba47 3712 UINTN Length;\r
7e3bcccb
LG
3713\r
3714 ASSERT (OptionsOpCodeHandle != NULL);\r
3715 ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED | EFI_IFR_FLAG_OPTIONS_ONLY))) == 0);\r
3716\r
3717 ZeroMem (&OpCode, sizeof (OpCode));\r
3718 OpCode.Question.Header.Prompt = Prompt;\r
3719 OpCode.Question.Header.Help = Help;\r
3720 OpCode.Question.QuestionId = QuestionId;\r
3721 OpCode.Question.VarStoreId = VarStoreId;\r
3722 OpCode.Question.VarStoreInfo.VarOffset = VarOffset;\r
3723 OpCode.Question.Flags = QuestionFlags;\r
3724 OpCode.Flags = OneOfFlags;\r
3725\r
dcf5ba47
ED
3726 Length = OFFSET_OF (EFI_IFR_ONE_OF, data);\r
3727 Length += (1 << (OneOfFlags & EFI_IFR_NUMERIC_SIZE)) * 3;\r
3728\r
7e3bcccb 3729 Position = InternalHiiOpCodeHandlePosition (OpCodeHandle);\r
dcf5ba47 3730 InternalHiiCreateOpCodeExtended (OpCodeHandle, &OpCode, EFI_IFR_ONE_OF_OP, Length, 0, 1);\r
7e3bcccb
LG
3731 InternalHiiAppendOpCodes (OpCodeHandle, OptionsOpCodeHandle);\r
3732 if (DefaultsOpCodeHandle != NULL) {\r
3733 InternalHiiAppendOpCodes (OpCodeHandle, DefaultsOpCodeHandle);\r
3734 }\r
3735 HiiCreateEndOpCode (OpCodeHandle);\r
3736 return InternalHiiOpCodeHandleBuffer (OpCodeHandle) + Position;\r
3737}\r
3738\r
3739/**\r
3740 Create EFI_IFR_ORDERED_LIST_OP opcode.\r
3741\r
3742 If OpCodeHandle is NULL, then ASSERT().\r
3743 If any reserved bits are set in QuestionFlags, then ASSERT().\r
3744 If any reserved bits are set in OrderedListFlags, then ASSERT().\r
3745\r
3746 @param[in] OpCodeHandle Handle to the buffer of opcodes.\r
3747 @param[in] QuestionId Question ID\r
3748 @param[in] VarStoreId Storage ID\r
09acdc0b
ED
3749 @param[in] VarOffset Offset in Storage or String ID of the name (VarName)\r
3750 for this name/value pair.\r
7e3bcccb
LG
3751 @param[in] Prompt String ID for Prompt\r
3752 @param[in] Help String ID for Help\r
3753 @param[in] QuestionFlags Flags in Question Header\r
3754 @param[in] OrderedListFlags Flags for ordered list opcode\r
3755 @param[in] DataType Type for option value\r
3756 @param[in] MaxContainers Maximum count for options in this ordered list\r
3757 @param[in] OptionsOpCodeHandle Handle for a buffer of ONE_OF_OPTION opcodes.\r
3758 @param[in] DefaultsOpCodeHandle Handle for a buffer of DEFAULT opcodes. This\r
3759 is an optional parameter that may be NULL.\r
3760\r
3761 @retval NULL There is not enough space left in Buffer to add the opcode.\r
3762 @retval Other A pointer to the created opcode.\r
3763\r
3764**/\r
3765UINT8 *\r
3766EFIAPI\r
3767HiiCreateOrderedListOpCode (\r
3768 IN VOID *OpCodeHandle,\r
3769 IN EFI_QUESTION_ID QuestionId,\r
3770 IN EFI_VARSTORE_ID VarStoreId,\r
3771 IN UINT16 VarOffset,\r
3772 IN EFI_STRING_ID Prompt,\r
3773 IN EFI_STRING_ID Help,\r
3774 IN UINT8 QuestionFlags,\r
3775 IN UINT8 OrderedListFlags,\r
3776 IN UINT8 DataType,\r
3777 IN UINT8 MaxContainers,\r
3778 IN VOID *OptionsOpCodeHandle,\r
3779 IN VOID *DefaultsOpCodeHandle OPTIONAL\r
3780 )\r
3781{\r
3782 EFI_IFR_ORDERED_LIST OpCode;\r
3783 UINTN Position;\r
3784\r
3785 ASSERT (OptionsOpCodeHandle != NULL);\r
3786 ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED | EFI_IFR_FLAG_OPTIONS_ONLY))) == 0);\r
3787\r
3788 ZeroMem (&OpCode, sizeof (OpCode));\r
3789 OpCode.Question.Header.Prompt = Prompt;\r
3790 OpCode.Question.Header.Help = Help;\r
3791 OpCode.Question.QuestionId = QuestionId;\r
3792 OpCode.Question.VarStoreId = VarStoreId;\r
3793 OpCode.Question.VarStoreInfo.VarOffset = VarOffset;\r
3794 OpCode.Question.Flags = QuestionFlags;\r
3795 OpCode.MaxContainers = MaxContainers;\r
3796 OpCode.Flags = OrderedListFlags;\r
3797\r
3798 Position = InternalHiiOpCodeHandlePosition (OpCodeHandle);\r
3799 InternalHiiCreateOpCodeExtended (OpCodeHandle, &OpCode, EFI_IFR_ORDERED_LIST_OP, sizeof (OpCode), 0, 1);\r
3800 InternalHiiAppendOpCodes (OpCodeHandle, OptionsOpCodeHandle);\r
3801 if (DefaultsOpCodeHandle != NULL) {\r
3802 InternalHiiAppendOpCodes (OpCodeHandle, DefaultsOpCodeHandle);\r
3803 }\r
3804 HiiCreateEndOpCode (OpCodeHandle);\r
e22812c7
LG
3805 return InternalHiiOpCodeHandleBuffer (OpCodeHandle) + Position;\r
3806}\r
3807\r
3808/**\r
3809 Create EFI_IFR_TEXT_OP opcode.\r
3810\r
3811 If OpCodeHandle is NULL, then ASSERT().\r
3812\r
3813 @param[in] OpCodeHandle Handle to the buffer of opcodes.\r
3814 @param[in] Prompt String ID for Prompt.\r
3815 @param[in] Help String ID for Help.\r
3816 @param[in] TextTwo String ID for TextTwo.\r
3817\r
3818 @retval NULL There is not enough space left in Buffer to add the opcode.\r
3819 @retval Other A pointer to the created opcode.\r
3820\r
3821**/\r
3822UINT8 *\r
3823EFIAPI\r
3824HiiCreateTextOpCode (\r
3825 IN VOID *OpCodeHandle,\r
3826 IN EFI_STRING_ID Prompt,\r
3827 IN EFI_STRING_ID Help,\r
3828 IN EFI_STRING_ID TextTwo\r
3829 )\r
3830{\r
3831 EFI_IFR_TEXT OpCode;\r
3832\r
3833 ZeroMem (&OpCode, sizeof (OpCode));\r
3834 OpCode.Statement.Prompt = Prompt;\r
3835 OpCode.Statement.Help = Help;\r
3836 OpCode.TextTwo = TextTwo;\r
3837\r
3838 return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_TEXT_OP, sizeof (OpCode));\r
3839}\r
3840\r
3841/**\r
3842 Create EFI_IFR_DATE_OP opcode.\r
3843\r
3844 If OpCodeHandle is NULL, then ASSERT().\r
3845 If any reserved bits are set in QuestionFlags, then ASSERT().\r
3846 If any reserved bits are set in DateFlags, then ASSERT().\r
3847\r
3848 @param[in] OpCodeHandle Handle to the buffer of opcodes.\r
3849 @param[in] QuestionId Question ID\r
3850 @param[in] VarStoreId Storage ID, optional. If DateFlags is not\r
3851 QF_DATE_STORAGE_NORMAL, this parameter is ignored.\r
09acdc0b
ED
3852 @param[in] VarOffset Offset in Storage or String ID of the name (VarName)\r
3853 for this name/value pair, optional. If DateFlags is not\r
e22812c7
LG
3854 QF_DATE_STORAGE_NORMAL, this parameter is ignored.\r
3855 @param[in] Prompt String ID for Prompt\r
3856 @param[in] Help String ID for Help\r
3857 @param[in] QuestionFlags Flags in Question Header\r
3858 @param[in] DateFlags Flags for date opcode\r
3859 @param[in] DefaultsOpCodeHandle Handle for a buffer of DEFAULT opcodes. This\r
3860 is an optional parameter that may be NULL.\r
3861\r
3862 @retval NULL There is not enough space left in Buffer to add the opcode.\r
3863 @retval Other A pointer to the created opcode.\r
3864\r
3865**/\r
3866UINT8 *\r
3867EFIAPI\r
3868HiiCreateDateOpCode (\r
3869 IN VOID *OpCodeHandle,\r
3870 IN EFI_QUESTION_ID QuestionId,\r
3871 IN EFI_VARSTORE_ID VarStoreId, OPTIONAL\r
3872 IN UINT16 VarOffset, OPTIONAL\r
3873 IN EFI_STRING_ID Prompt,\r
3874 IN EFI_STRING_ID Help,\r
3875 IN UINT8 QuestionFlags,\r
3876 IN UINT8 DateFlags,\r
3877 IN VOID *DefaultsOpCodeHandle OPTIONAL\r
3878 )\r
3879{\r
3880 EFI_IFR_DATE OpCode;\r
3881 UINTN Position;\r
3882\r
3883 ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED))) == 0);\r
3884 ASSERT ((DateFlags & (~(EFI_QF_DATE_YEAR_SUPPRESS | EFI_QF_DATE_MONTH_SUPPRESS | EFI_QF_DATE_DAY_SUPPRESS | EFI_QF_DATE_STORAGE))) == 0);\r
3885\r
3886 ZeroMem (&OpCode, sizeof (OpCode));\r
3887 OpCode.Question.Header.Prompt = Prompt;\r
3888 OpCode.Question.Header.Help = Help;\r
3889 OpCode.Question.QuestionId = QuestionId;\r
3890 OpCode.Question.VarStoreId = VarStoreId;\r
3891 OpCode.Question.VarStoreInfo.VarOffset = VarOffset;\r
3892 OpCode.Question.Flags = QuestionFlags;\r
3893 OpCode.Flags = DateFlags;\r
3894\r
3895 if (DefaultsOpCodeHandle == NULL) {\r
3896 return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_DATE_OP, sizeof (OpCode));\r
3897 }\r
3898\r
3899 Position = InternalHiiOpCodeHandlePosition (OpCodeHandle);\r
3900 InternalHiiCreateOpCodeExtended (OpCodeHandle, &OpCode, EFI_IFR_DATE_OP, sizeof (OpCode), 0, 1);\r
3901 InternalHiiAppendOpCodes (OpCodeHandle, DefaultsOpCodeHandle);\r
3902 HiiCreateEndOpCode (OpCodeHandle);\r
3903 return InternalHiiOpCodeHandleBuffer (OpCodeHandle) + Position;\r
3904}\r
3905\r
3906/**\r
3907 Create EFI_IFR_TIME_OP opcode.\r
3908\r
3909 If OpCodeHandle is NULL, then ASSERT().\r
3910 If any reserved bits are set in QuestionFlags, then ASSERT().\r
3911 If any reserved bits are set in TimeFlags, then ASSERT().\r
3912\r
3913 @param[in] OpCodeHandle Handle to the buffer of opcodes.\r
3914 @param[in] QuestionId Question ID\r
3915 @param[in] VarStoreId Storage ID, optional. If TimeFlags is not\r
3916 QF_TIME_STORAGE_NORMAL, this parameter is ignored.\r
09acdc0b
ED
3917 @param[in] VarOffset Offset in Storage or String ID of the name (VarName)\r
3918 for this name/value pair, optional. If TimeFlags is not\r
e22812c7
LG
3919 QF_TIME_STORAGE_NORMAL, this parameter is ignored.\r
3920 @param[in] Prompt String ID for Prompt\r
3921 @param[in] Help String ID for Help\r
3922 @param[in] QuestionFlags Flags in Question Header\r
3923 @param[in] TimeFlags Flags for time opcode\r
3924 @param[in] DefaultsOpCodeHandle Handle for a buffer of DEFAULT opcodes. This\r
3925 is an optional parameter that may be NULL.\r
3926\r
3927 @retval NULL There is not enough space left in Buffer to add the opcode.\r
3928 @retval Other A pointer to the created opcode.\r
3929\r
3930**/\r
3931UINT8 *\r
3932EFIAPI\r
3933HiiCreateTimeOpCode (\r
3934 IN VOID *OpCodeHandle,\r
3935 IN EFI_QUESTION_ID QuestionId,\r
3936 IN EFI_VARSTORE_ID VarStoreId, OPTIONAL\r
3937 IN UINT16 VarOffset, OPTIONAL\r
3938 IN EFI_STRING_ID Prompt,\r
3939 IN EFI_STRING_ID Help,\r
3940 IN UINT8 QuestionFlags,\r
3941 IN UINT8 TimeFlags,\r
3942 IN VOID *DefaultsOpCodeHandle OPTIONAL\r
3943 )\r
3944{\r
3945 EFI_IFR_TIME OpCode;\r
3946 UINTN Position;\r
3947\r
3948 ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED))) == 0);\r
3949 ASSERT ((TimeFlags & (~(QF_TIME_HOUR_SUPPRESS | QF_TIME_MINUTE_SUPPRESS | QF_TIME_SECOND_SUPPRESS | QF_TIME_STORAGE))) == 0);\r
3950\r
3951 ZeroMem (&OpCode, sizeof (OpCode));\r
3952 OpCode.Question.Header.Prompt = Prompt;\r
3953 OpCode.Question.Header.Help = Help;\r
3954 OpCode.Question.QuestionId = QuestionId;\r
3955 OpCode.Question.VarStoreId = VarStoreId;\r
3956 OpCode.Question.VarStoreInfo.VarOffset = VarOffset;\r
3957 OpCode.Question.Flags = QuestionFlags;\r
3958 OpCode.Flags = TimeFlags;\r
3959\r
3960 if (DefaultsOpCodeHandle == NULL) {\r
3961 return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_TIME_OP, sizeof (OpCode));\r
3962 }\r
3963\r
3964 Position = InternalHiiOpCodeHandlePosition (OpCodeHandle);\r
3965 InternalHiiCreateOpCodeExtended (OpCodeHandle, &OpCode, EFI_IFR_TIME_OP, sizeof (OpCode), 0, 1);\r
3966 InternalHiiAppendOpCodes (OpCodeHandle, DefaultsOpCodeHandle);\r
3967 HiiCreateEndOpCode (OpCodeHandle);\r
7e3bcccb
LG
3968 return InternalHiiOpCodeHandleBuffer (OpCodeHandle) + Position;\r
3969}\r
3970\r
3971/**\r
3972 This is the internal worker function to update the data in\r
3973 a form specified by FormSetGuid, FormId and Label.\r
3974\r
84213069
LG
3975 @param[in] FormSetGuid The optional Formset GUID.\r
3976 @param[in] FormId The Form ID.\r
3977 @param[in] Package The package header.\r
3978 @param[in] OpCodeBufferStart An OpCode buffer that contains the set of IFR \r
3979 opcodes to be inserted or replaced in the form.\r
3980 @param[in] OpCodeBufferEnd An OpCcode buffer that contains the IFR opcode\r
3981 that marks the end of a replace operation in the form.\r
3982 @param[out] TempPackage The resultant package.\r
7e3bcccb
LG
3983\r
3984 @retval EFI_SUCCESS The function completes successfully.\r
84213069 3985 @retval EFI_NOT_FOUND The updated opcode or endopcode is not found.\r
7e3bcccb
LG
3986\r
3987**/\r
3988EFI_STATUS\r
3989EFIAPI\r
3990InternalHiiUpdateFormPackageData (\r
3991 IN EFI_GUID *FormSetGuid, OPTIONAL\r
3992 IN EFI_FORM_ID FormId,\r
3993 IN EFI_HII_PACKAGE_HEADER *Package,\r
3994 IN HII_LIB_OPCODE_BUFFER *OpCodeBufferStart,\r
3995 IN HII_LIB_OPCODE_BUFFER *OpCodeBufferEnd, OPTIONAL\r
3996 OUT EFI_HII_PACKAGE_HEADER *TempPackage\r
3997 )\r
3998{\r
3999 UINTN AddSize;\r
4000 UINT8 *BufferPos;\r
4001 EFI_HII_PACKAGE_HEADER PackageHeader;\r
4002 UINTN Offset;\r
4003 EFI_IFR_OP_HEADER *IfrOpHdr;\r
4004 EFI_IFR_OP_HEADER *UpdateIfrOpHdr;\r
4005 BOOLEAN GetFormSet;\r
4006 BOOLEAN GetForm;\r
4007 BOOLEAN Updated;\r
d91c7bf9 4008 UINTN UpdatePackageLength;\r
7e3bcccb
LG
4009\r
4010 CopyMem (TempPackage, Package, sizeof (EFI_HII_PACKAGE_HEADER));\r
4011 UpdatePackageLength = sizeof (EFI_HII_PACKAGE_HEADER);\r
4012 BufferPos = (UINT8 *) (TempPackage + 1);\r
4013\r
4014 CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));\r
4015 IfrOpHdr = (EFI_IFR_OP_HEADER *)((UINT8 *) Package + sizeof (EFI_HII_PACKAGE_HEADER));\r
4016 Offset = sizeof (EFI_HII_PACKAGE_HEADER);\r
4017 GetFormSet = (BOOLEAN) ((FormSetGuid == NULL) ? TRUE : FALSE);\r
4018 GetForm = FALSE;\r
4019 Updated = FALSE;\r
4020\r
4021 while (Offset < PackageHeader.Length) {\r
4022 CopyMem (BufferPos, IfrOpHdr, IfrOpHdr->Length);\r
4023 BufferPos += IfrOpHdr->Length;\r
4024 UpdatePackageLength += IfrOpHdr->Length;\r
4025 \r
4026 //\r
4027 // Find the matched FormSet and Form\r
4028 //\r
4029 if ((IfrOpHdr->OpCode == EFI_IFR_FORM_SET_OP) && (FormSetGuid != NULL)) {\r
4030 if (CompareGuid((GUID *)(VOID *)&((EFI_IFR_FORM_SET *) IfrOpHdr)->Guid, FormSetGuid)) {\r
4031 GetFormSet = TRUE;\r
4032 } else {\r
4033 GetFormSet = FALSE;\r
4034 }\r
2573712e 4035 } else if (IfrOpHdr->OpCode == EFI_IFR_FORM_OP || IfrOpHdr->OpCode == EFI_IFR_FORM_MAP_OP) {\r
7e3bcccb
LG
4036 if (CompareMem (&((EFI_IFR_FORM *) IfrOpHdr)->FormId, &FormId, sizeof (EFI_FORM_ID)) == 0) {\r
4037 GetForm = TRUE;\r
4038 } else {\r
4039 GetForm = FALSE;\r
4040 }\r
4041 }\r
4042 \r
4043 //\r
4044 // The matched Form is found, and Update data in this form\r
4045 //\r
d91c7bf9 4046 if (GetFormSet && GetForm) {\r
7e3bcccb
LG
4047 UpdateIfrOpHdr = (EFI_IFR_OP_HEADER *) OpCodeBufferStart->Buffer;\r
4048 if ((UpdateIfrOpHdr->Length == IfrOpHdr->Length) && \\r
4049 (CompareMem (IfrOpHdr, UpdateIfrOpHdr, UpdateIfrOpHdr->Length) == 0)) {\r
4050 //\r
4051 // Remove the original data when End OpCode buffer exist.\r
4052 //\r
4053 if (OpCodeBufferEnd != NULL) {\r
4054 Offset += IfrOpHdr->Length;\r
4055 IfrOpHdr = (EFI_IFR_OP_HEADER *) ((UINT8 *) (IfrOpHdr) + IfrOpHdr->Length);\r
4056 UpdateIfrOpHdr = (EFI_IFR_OP_HEADER *) OpCodeBufferEnd->Buffer;\r
4057 while (Offset < PackageHeader.Length) {\r
4058 //\r
4059 // Search the matched end opcode\r
4060 //\r
4061 if ((UpdateIfrOpHdr->Length == IfrOpHdr->Length) && \\r
4062 (CompareMem (IfrOpHdr, UpdateIfrOpHdr, UpdateIfrOpHdr->Length) == 0)) {\r
4063 break;\r
4064 }\r
4065 //\r
4066 // Go to the next Op-Code\r
4067 //\r
4068 Offset += IfrOpHdr->Length;\r
4069 IfrOpHdr = (EFI_IFR_OP_HEADER *) ((UINT8 *) (IfrOpHdr) + IfrOpHdr->Length);\r
4070 }\r
4071 \r
4072 if (Offset >= PackageHeader.Length) {\r
4073 //\r
4074 // The end opcode is not found.\r
4075 //\r
4076 return EFI_NOT_FOUND;\r
4077 }\r
4078 }\r
d91c7bf9 4079\r
7e3bcccb
LG
4080 //\r
4081 // Insert the updated data\r
4082 //\r
d91c7bf9
LG
4083 AddSize = ((EFI_IFR_OP_HEADER *) OpCodeBufferStart->Buffer)->Length;\r
4084 CopyMem (BufferPos, OpCodeBufferStart->Buffer + AddSize, OpCodeBufferStart->Position - AddSize);\r
4085 BufferPos += OpCodeBufferStart->Position - AddSize;\r
4086 UpdatePackageLength += OpCodeBufferStart->Position - AddSize;\r
b8215f46 4087\r
7e3bcccb
LG
4088 if (OpCodeBufferEnd != NULL) {\r
4089 //\r
4090 // Add the end opcode\r
4091 //\r
4092 CopyMem (BufferPos, IfrOpHdr, IfrOpHdr->Length);\r
4093 BufferPos += IfrOpHdr->Length;\r
4094 UpdatePackageLength += IfrOpHdr->Length;\r
4095 }\r
d91c7bf9
LG
4096\r
4097 //\r
4098 // Copy the left package data.\r
4099 //\r
4100 Offset += IfrOpHdr->Length;\r
4101 CopyMem (BufferPos, (UINT8 *) Package + Offset, PackageHeader.Length - Offset);\r
4102 UpdatePackageLength += PackageHeader.Length - Offset;\r
4103\r
7e3bcccb
LG
4104 //\r
4105 // Set update flag\r
4106 //\r
4107 Updated = TRUE;\r
d91c7bf9 4108 break;\r
7e3bcccb
LG
4109 }\r
4110 }\r
4111\r
4112 //\r
4113 // Go to the next Op-Code\r
4114 //\r
4115 Offset += IfrOpHdr->Length;\r
4116 IfrOpHdr = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (IfrOpHdr) + IfrOpHdr->Length);\r
4117 }\r
4118 \r
4119 if (!Updated) {\r
4120 //\r
4121 // The updated opcode buffer is not found.\r
4122 //\r
4123 return EFI_NOT_FOUND;\r
4124 }\r
4125 //\r
4126 // Update the package length.\r
4127 //\r
d91c7bf9 4128 PackageHeader.Length = (UINT32) UpdatePackageLength;\r
7e3bcccb
LG
4129 CopyMem (TempPackage, &PackageHeader, sizeof (EFI_HII_PACKAGE_HEADER));\r
4130\r
4131 return EFI_SUCCESS;\r
4132}\r
4133\r
4134/**\r
4135 This function updates a form that has previously been registered with the HII \r
4136 Database. This function will perform at most one update operation.\r
4137 \r
4138 The form to update is specified by Handle, FormSetGuid, and FormId. Binary \r
4139 comparisons of IFR opcodes are performed from the beginning of the form being \r
4140 updated until an IFR opcode is found that exactly matches the first IFR opcode \r
84213069 4141 specified by StartOpCodeHandle. The following rules are used to determine if\r
7e3bcccb
LG
4142 an insert, replace, or delete operation is performed.\r
4143 \r
4144 1) If no matches are found, then NULL is returned. \r
4145 2) If a match is found, and EndOpCodeHandle is NULL, then all of the IFR opcodes\r
84213069
LG
4146 from StartOpCodeHandle except the first opcode are inserted immediately after \r
4147 the matching IFR opcode in the form to be updated.\r
7e3bcccb 4148 3) If a match is found, and EndOpCodeHandle is not NULL, then a search is made \r
84213069 4149 from the matching IFR opcode until an IFR opcode exactly matches the first \r
7e3bcccb
LG
4150 IFR opcode specified by EndOpCodeHandle. If no match is found for the first\r
4151 IFR opcode specified by EndOpCodeHandle, then NULL is returned. If a match\r
4152 is found, then all of the IFR opcodes between the start match and the end \r
4153 match are deleted from the form being updated and all of the IFR opcodes\r
84213069 4154 from StartOpCodeHandle except the first opcode are inserted immediately after \r
7e3bcccb 4155 the matching start IFR opcode. If StartOpCcodeHandle only contains one\r
84213069 4156 IFR instruction, then the result of this operation will delete all of the IFR\r
7e3bcccb
LG
4157 opcodes between the start end matches.\r
4158\r
4159 If HiiHandle is NULL, then ASSERT().\r
4160 If StartOpCodeHandle is NULL, then ASSERT().\r
4161\r
4162 @param[in] HiiHandle The HII Handle of the form to update.\r
4163 @param[in] FormSetGuid The Formset GUID of the form to update. This\r
4164 is an optional parameter that may be NULL.\r
4165 If it is NULL, all FormSet will be updated.\r
4166 @param[in] FormId The ID of the form to update.\r
4167 @param[in] StartOpCodeHandle An OpCode Handle that contains the set of IFR \r
4168 opcodes to be inserted or replaced in the form.\r
4169 The first IFR instruction in StartOpCodeHandle \r
4170 is used to find matching IFR opcode in the \r
4171 form. \r
4172 @param[in] EndOpCodeHandle An OpCcode Handle that contains the IFR opcode\r
4173 that marks the end of a replace operation in\r
4174 the form. This is an optional parameter that\r
4175 may be NULL. If it is NULL, then an the IFR\r
4176 opcodes specified by StartOpCodeHandle are \r
4177 inserted into the form.\r
4178 \r
4179 @retval EFI_OUT_OF_RESOURCES No enough memory resource is allocated.\r
4180 @retval EFI_NOT_FOUND The following cases will return EFI_NOT_FOUND.\r
4181 1) The form specified by HiiHandle, FormSetGuid, \r
4182 and FormId could not be found in the HII Database.\r
4183 2) No IFR opcodes in the target form match the first\r
4184 IFR opcode in StartOpCodeHandle.\r
4185 3) EndOpCOde is not NULL, and no IFR opcodes in the \r
4186 target form following a matching start opcode match \r
4187 the first IFR opcode in EndOpCodeHandle.\r
4188 @retval EFI_SUCCESS The matched form is updated by StartOpcode.\r
4189\r
4190**/\r
4191EFI_STATUS\r
4192EFIAPI\r
4193HiiUpdateForm (\r
4194 IN EFI_HII_HANDLE HiiHandle, \r
4195 IN EFI_GUID *FormSetGuid, OPTIONAL\r
4196 IN EFI_FORM_ID FormId,\r
84213069
LG
4197 IN VOID *StartOpCodeHandle,\r
4198 IN VOID *EndOpCodeHandle OPTIONAL\r
7e3bcccb
LG
4199 )\r
4200{\r
4201 EFI_STATUS Status;\r
4202 EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;\r
4203 UINT32 PackageListLength; \r
4204 UINT32 Offset;\r
4205 EFI_HII_PACKAGE_LIST_HEADER *UpdatePackageList;\r
4206 UINTN BufferSize;\r
4207 UINT8 *UpdateBufferPos;\r
4208 EFI_HII_PACKAGE_HEADER *Package;\r
3b28e744 4209 EFI_HII_PACKAGE_HEADER *TempPackage;\r
7e3bcccb
LG
4210 EFI_HII_PACKAGE_HEADER PackageHeader;\r
4211 BOOLEAN Updated;\r
4212 HII_LIB_OPCODE_BUFFER *OpCodeBufferStart;\r
4213 HII_LIB_OPCODE_BUFFER *OpCodeBufferEnd;\r
4214 \r
4215 //\r
4216 // Input update data can't be NULL.\r
4217 //\r
4218 ASSERT (HiiHandle != NULL);\r
84213069 4219 ASSERT (StartOpCodeHandle != NULL);\r
7e3bcccb 4220 UpdatePackageList = NULL;\r
3b28e744 4221 TempPackage = NULL;\r
7e3bcccb
LG
4222 HiiPackageList = NULL;\r
4223 \r
4224 //\r
84213069 4225 // Retrieve buffer data from Opcode Handle\r
7e3bcccb 4226 //\r
84213069
LG
4227 OpCodeBufferStart = (HII_LIB_OPCODE_BUFFER *) StartOpCodeHandle;\r
4228 OpCodeBufferEnd = (HII_LIB_OPCODE_BUFFER *) EndOpCodeHandle;\r
7e3bcccb
LG
4229 \r
4230 //\r
84213069 4231 // Get the original package list\r
7e3bcccb
LG
4232 //\r
4233 BufferSize = 0;\r
4234 HiiPackageList = NULL;\r
4235 Status = gHiiDatabase->ExportPackageLists (gHiiDatabase, HiiHandle, &BufferSize, HiiPackageList);\r
4236 //\r
4237 // The return status should always be EFI_BUFFER_TOO_SMALL as input buffer's size is 0.\r
4238 //\r
4239 if (Status != EFI_BUFFER_TOO_SMALL) {\r
4240 return Status;\r
4241 }\r
4242\r
4243 HiiPackageList = AllocatePool (BufferSize);\r
4244 if (HiiPackageList == NULL) {\r
4245 Status = EFI_OUT_OF_RESOURCES;\r
4246 goto Finish;\r
4247 }\r
4248\r
4249 Status = gHiiDatabase->ExportPackageLists (gHiiDatabase, HiiHandle, &BufferSize, HiiPackageList);\r
4250 if (EFI_ERROR (Status)) {\r
4251 goto Finish;\r
4252 }\r
4253\r
4254 //\r
4255 // Calculate and allocate space for retrieval of IFR data\r
4256 //\r
4257 BufferSize += OpCodeBufferStart->Position;\r
4258 UpdatePackageList = AllocateZeroPool (BufferSize);\r
4259 if (UpdatePackageList == NULL) {\r
4260 Status = EFI_OUT_OF_RESOURCES;\r
4261 goto Finish;\r
4262 }\r
4263 \r
4264 //\r
4265 // Allocate temp buffer to store the temp updated package buffer\r
4266 //\r
3b28e744
GL
4267 TempPackage = AllocateZeroPool (BufferSize);\r
4268 if (TempPackage == NULL) {\r
7e3bcccb
LG
4269 Status = EFI_OUT_OF_RESOURCES;\r
4270 goto Finish;\r
4271 }\r
4272\r
4273 UpdateBufferPos = (UINT8 *) UpdatePackageList;\r
4274\r
4275 //\r
4276 // Copy the package list header\r
4277 //\r
4278 CopyMem (UpdateBufferPos, HiiPackageList, sizeof (EFI_HII_PACKAGE_LIST_HEADER));\r
4279 UpdateBufferPos += sizeof (EFI_HII_PACKAGE_LIST_HEADER);\r
4280 \r
4281 //\r
84213069 4282 // Go through each package to find the matched package and update one by one\r
7e3bcccb
LG
4283 //\r
4284 Updated = FALSE;\r
4285 Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);\r
4286 PackageListLength = ReadUnaligned32 (&HiiPackageList->PackageLength);\r
4287 while (Offset < PackageListLength) {\r
4288 Package = (EFI_HII_PACKAGE_HEADER *) (((UINT8 *) HiiPackageList) + Offset);\r
4289 CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));\r
4290 Offset += Package->Length;\r
4291\r
4292 if (Package->Type == EFI_HII_PACKAGE_FORMS) {\r
4293 //\r
4294 // Check this package is the matched package.\r
4295 //\r
3b28e744 4296 Status = InternalHiiUpdateFormPackageData (FormSetGuid, FormId, Package, OpCodeBufferStart, OpCodeBufferEnd, TempPackage);\r
7e3bcccb 4297 //\r
84213069 4298 // The matched package is found. Its package buffer will be updated by the input new data.\r
7e3bcccb
LG
4299 //\r
4300 if (!EFI_ERROR(Status)) {\r
4301 //\r
4302 // Set Update Flag\r
4303 // \r
4304 Updated = TRUE;\r
4305 //\r
4306 // Add updated package buffer\r
4307 //\r
3b28e744 4308 Package = TempPackage;\r
7e3bcccb
LG
4309 }\r
4310 }\r
4311\r
4312 //\r
4313 // Add pacakge buffer\r
4314 //\r
4315 CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));\r
4316 CopyMem (UpdateBufferPos, Package, PackageHeader.Length);\r
4317 UpdateBufferPos += PackageHeader.Length;\r
4318 }\r
4319 \r
4320 if (Updated) {\r
4321 //\r
4322 // Update package list length\r
4323 //\r
4324 BufferSize = UpdateBufferPos - (UINT8 *) UpdatePackageList;\r
4325 WriteUnaligned32 (&UpdatePackageList->PackageLength, (UINT32) BufferSize);\r
4326 \r
4327 //\r
84213069 4328 // Update Package to show form\r
7e3bcccb
LG
4329 //\r
4330 Status = gHiiDatabase->UpdatePackageList (gHiiDatabase, HiiHandle, UpdatePackageList);\r
4331 } else {\r
4332 //\r
4333 // Not matched form is found and updated.\r
4334 //\r
4335 Status = EFI_NOT_FOUND;\r
4336 }\r
4337\r
4338Finish:\r
4339 if (HiiPackageList != NULL) {\r
4340 FreePool (HiiPackageList);\r
4341 }\r
4342 \r
4343 if (UpdatePackageList != NULL) {\r
4344 FreePool (UpdatePackageList);\r
4345 }\r
4346 \r
3b28e744
GL
4347 if (TempPackage != NULL) {\r
4348 FreePool (TempPackage);\r
7e3bcccb
LG
4349 }\r
4350\r
4351 return Status; \r
4352}\r