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