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