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