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