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