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