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