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