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