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