]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Library/UefiHiiLib/HiiLib.c
Remove the duplicated definitions between Framework AcpiSupport and PI AcpiSystemDesc...
[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
aa2614b7 4 Copyright (c) 2006 - 2009, Intel Corporation<BR>\r
08e4b3cf 5 All rights reserved. This program and the accompanying materials\r
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
132 the same PackageListGuid.\r
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
379 If String is NULL, then ASSERT().\r
380\r
381 @param[in] String Pointer to a Null-terminated Unicode string.\r
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
466 @param[in] VariableName Pointer to a Null-terminated Unicode string. This \r
467 is an optional parameter that may be NULL.\r
468 @param[in] VariableGuid Pointer to an EFI_GUID structure. This is an optional \r
469 parameter that may be NULL.\r
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
797 break;\r
798 }\r
799\r
800 return EFI_SUCCESS;\r
801}\r
802\r
803/**\r
804 This function checks VarOffset and VarWidth is in the block range.\r
805\r
806 @param BlockArray The block array is to be checked. \r
807 @param VarOffset Offset of var to the structure\r
808 @param VarWidth Width of var.\r
809 \r
810 @retval TRUE This Var is in the block range.\r
811 @retval FALSE This Var is not in the block range.\r
812**/\r
813BOOLEAN\r
814BlockArrayCheck (\r
815 IN IFR_BLOCK_DATA *BlockArray,\r
816 IN UINT16 VarOffset,\r
817 IN UINT16 VarWidth\r
818 )\r
819{\r
820 LIST_ENTRY *Link;\r
821 IFR_BLOCK_DATA *BlockData;\r
822 \r
823 //\r
824 // No Request Block array, all vars are got.\r
825 //\r
826 if (BlockArray == NULL) {\r
827 return TRUE;\r
828 }\r
829 \r
830 //\r
831 // Check the input var is in the request block range.\r
832 //\r
833 for (Link = BlockArray->Entry.ForwardLink; Link != &BlockArray->Entry; Link = Link->ForwardLink) {\r
834 BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);\r
835 if ((VarOffset >= BlockData->Offset) && ((VarOffset + VarWidth) <= (BlockData->Offset + BlockData->Width))) {\r
836 return TRUE;\r
837 }\r
838 }\r
839\r
840 return FALSE;\r
841}\r
842\r
843/**\r
844 Get the value of <Number> in <BlockConfig> format, i.e. the value of OFFSET\r
845 or WIDTH or VALUE.\r
846 <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>\r
847\r
848 @param ValueString String in <BlockConfig> format and points to the\r
849 first character of <Number>.\r
850 @param ValueData The output value. Caller takes the responsibility\r
851 to free memory.\r
852 @param ValueLength Length of the <Number>, in characters.\r
853\r
854 @retval EFI_OUT_OF_RESOURCES Insufficient resources to store neccessary\r
855 structures.\r
856 @retval EFI_SUCCESS Value of <Number> is outputted in Number\r
857 successfully.\r
858\r
859**/\r
860EFI_STATUS\r
861EFIAPI\r
862InternalHiiGetValueOfNumber (\r
863 IN EFI_STRING ValueString,\r
864 OUT UINT8 **ValueData,\r
865 OUT UINTN *ValueLength\r
866 )\r
867{\r
868 EFI_STRING StringPtr;\r
869 UINTN Length;\r
870 UINT8 *Buf;\r
871 UINT8 DigitUint8;\r
872 UINTN Index;\r
873 CHAR16 TemStr[2];\r
874\r
875 ASSERT (ValueString != NULL && ValueData != NULL && ValueLength != NULL);\r
876 ASSERT (*ValueString != L'\0');\r
877\r
878 //\r
879 // Get the length of value string\r
880 //\r
881 StringPtr = ValueString;\r
882 while (*StringPtr != L'\0' && *StringPtr != L'&') {\r
883 StringPtr++;\r
884 }\r
885 Length = StringPtr - ValueString;\r
886 \r
887 //\r
888 // Allocate buffer to store the value\r
889 //\r
890 Buf = (UINT8 *) AllocateZeroPool ((Length + 1) / 2);\r
891 if (Buf == NULL) {\r
892 return EFI_OUT_OF_RESOURCES;\r
893 }\r
894 \r
895 //\r
896 // Convert character one by one to the value buffer\r
897 //\r
898 ZeroMem (TemStr, sizeof (TemStr));\r
899 for (Index = 0; Index < Length; Index ++) {\r
900 TemStr[0] = ValueString[Length - Index - 1];\r
901 DigitUint8 = (UINT8) StrHexToUint64 (TemStr);\r
902 if ((Index & 1) == 0) {\r
903 Buf [Index/2] = DigitUint8;\r
904 } else {\r
905 Buf [Index/2] = (UINT8) ((DigitUint8 << 4) + Buf [Index/2]);\r
906 }\r
907 }\r
908 \r
909 //\r
910 // Set the converted value and string length.\r
911 //\r
912 *ValueData = Buf;\r
913 *ValueLength = Length;\r
914 return EFI_SUCCESS;\r
915}\r
916\r
917/**\r
8567300a
LG
918 This internal function parses IFR data to validate current setting.\r
919\r
920 @param ConfigResp ConfigResp string contains the current setting.\r
921 @param HiiPackageList Point to Hii package list.\r
922 @param PackageListLength The length of the pacakge.\r
923 @param VarGuid Guid of the buffer storage.\r
924 @param VarName Name of the buffer storage.\r
84f9a9ec 925 \r
8567300a
LG
926 @retval EFI_SUCCESS The current setting is valid.\r
927 @retval EFI_OUT_OF_RESOURCES The memory is not enough.\r
928 @retval EFI_INVALID_PARAMETER The config string or the Hii package is invalid.\r
84f9a9ec
LG
929**/\r
930EFI_STATUS\r
931EFIAPI\r
932InternalHiiValidateCurrentSetting (\r
933 IN EFI_STRING ConfigResp,\r
934 IN EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList,\r
935 IN UINTN PackageListLength,\r
936 IN EFI_GUID *VarGuid,\r
937 IN CHAR16 *VarName\r
938 )\r
939{ \r
940 IFR_BLOCK_DATA *CurrentBlockArray;\r
941 IFR_BLOCK_DATA *BlockData;\r
942 IFR_BLOCK_DATA *NewBlockData;\r
943 IFR_BLOCK_DATA VarBlockData;\r
944 EFI_STRING StringPtr;\r
945 UINTN Length;\r
946 UINT8 *TmpBuffer;\r
947 UINT16 Offset;\r
948 UINT16 Width;\r
949 UINT64 VarValue;\r
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
979 // No ConfigBlock value is requied to be validated.\r
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
1182 // 2. Check IFR value is in block data, then Validate Vaule\r
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
1232 //\r
1233 // Check the matched VarStoreId is found.\r
1234 //\r
1235 if (IfrVarStore == NULL) {\r
76c24251 1236 Status = EFI_SUCCESS;\r
84f9a9ec
LG
1237 goto Done;\r
1238 }\r
1239 break;\r
1240 case EFI_IFR_ONE_OF_OP:\r
1241 //\r
8567300a 1242 // Check whether current value is the one of option.\r
84f9a9ec
LG
1243 //\r
1244\r
1245 //\r
8567300a
LG
1246 // OneOf question is not in IFR Form. This IFR form is not valid. \r
1247 //\r
1248 if (IfrVarStore == NULL) {\r
1249 Status = EFI_INVALID_PARAMETER;\r
1250 goto Done;\r
1251 }\r
1252 // \r
84f9a9ec
LG
1253 // Check whether this question is for the requested varstore.\r
1254 //\r
1255 IfrOneOf = (EFI_IFR_ONE_OF *) IfrOpHdr;\r
1256 if (IfrOneOf->Question.VarStoreId != IfrVarStore->VarStoreId) {\r
1257 break;\r
1258 }\r
1259 \r
1260 //\r
1261 // Get Offset by Question header and Width by DataType Flags\r
1262 //\r
1263 Offset = IfrOneOf->Question.VarStoreInfo.VarOffset;\r
1264 Width = (UINT16) (1 << (IfrOneOf->Flags & EFI_IFR_NUMERIC_SIZE));\r
1265 //\r
1266 // Check whether this question is in current block array.\r
1267 //\r
1268 if (!BlockArrayCheck (CurrentBlockArray, Offset, Width)) {\r
1269 //\r
1270 // This question is not in the current configuration string. Skip it.\r
1271 //\r
1272 break;\r
1273 }\r
1274 //\r
1275 // Check this var question is in the var storage \r
1276 //\r
1277 if ((Offset + Width) > IfrVarStore->Size) {\r
1278 //\r
1279 // This question exceeds the var store size. \r
1280 //\r
1281 Status = EFI_INVALID_PARAMETER;\r
1282 goto Done;\r
1283 }\r
1284\r
1285 //\r
1286 // Get the current value for oneof opcode\r
1287 //\r
1288 VarValue = 0;\r
1289 CopyMem (&VarValue, VarBuffer + Offset, Width);\r
1290 //\r
1291 // Set Block Data, to be checked in the following Oneof option opcode.\r
1292 //\r
1293 VarBlockData.Offset = Offset;\r
1294 VarBlockData.Width = Width;\r
1295 VarBlockData.OpCode = IfrOpHdr->OpCode;\r
1296 VarBlockData.Scope = IfrOpHdr->Scope;\r
1297 break;\r
1298 case EFI_IFR_NUMERIC_OP:\r
1299 //\r
1300 // Check the current value is in the numeric range.\r
1301 //\r
1302\r
8567300a
LG
1303 //\r
1304 // Numeric question is not in IFR Form. This IFR form is not valid. \r
1305 //\r
1306 if (IfrVarStore == NULL) {\r
1307 Status = EFI_INVALID_PARAMETER;\r
1308 goto Done;\r
1309 }\r
84f9a9ec
LG
1310 //\r
1311 // Check whether this question is for the requested varstore.\r
1312 //\r
1313 IfrNumeric = (EFI_IFR_NUMERIC *) IfrOpHdr;\r
1314 if (IfrNumeric->Question.VarStoreId != IfrVarStore->VarStoreId) {\r
1315 break;\r
1316 }\r
1317 \r
1318 //\r
1319 // Get Offset by Question header and Width by DataType Flags\r
1320 //\r
1321 Offset = IfrNumeric->Question.VarStoreInfo.VarOffset;\r
1322 Width = (UINT16) (1 << (IfrNumeric->Flags & EFI_IFR_NUMERIC_SIZE));\r
1323 //\r
1324 // Check whether this question is in current block array.\r
1325 //\r
1326 if (!BlockArrayCheck (CurrentBlockArray, Offset, Width)) {\r
1327 //\r
1328 // This question is not in the current configuration string. Skip it.\r
1329 //\r
1330 break;\r
1331 }\r
1332 //\r
1333 // Check this var question is in the var storage \r
1334 //\r
1335 if ((Offset + Width) > IfrVarStore->Size) {\r
1336 //\r
1337 // This question exceeds the var store size. \r
1338 //\r
1339 Status = EFI_INVALID_PARAMETER;\r
1340 goto Done;\r
1341 }\r
1342\r
1343 //\r
1344 // Check the current value is in the numeric range.\r
1345 //\r
1346 VarValue = 0;\r
1347 CopyMem (&VarValue, VarBuffer + Offset, Width);\r
1348 switch (IfrNumeric->Flags & EFI_IFR_NUMERIC_SIZE) {\r
1349 case EFI_IFR_NUMERIC_SIZE_1:\r
1350 if ((UINT8) VarValue < IfrNumeric->data.u8.MinValue || (UINT8) VarValue > IfrNumeric->data.u8.MaxValue) {\r
1351 //\r
1352 // Not in the valid range.\r
1353 //\r
1354 Status = EFI_INVALID_PARAMETER;\r
1355 goto Done;\r
1356 }\r
1357 break;\r
1358 case EFI_IFR_NUMERIC_SIZE_2:\r
1359 if ((UINT16) VarValue < IfrNumeric->data.u16.MinValue || (UINT16) VarValue > IfrNumeric->data.u16.MaxValue) {\r
1360 //\r
1361 // Not in the valid range.\r
1362 //\r
1363 Status = EFI_INVALID_PARAMETER;\r
1364 goto Done;\r
1365 }\r
1366 break;\r
1367 case EFI_IFR_NUMERIC_SIZE_4:\r
1368 if ((UINT32) VarValue < IfrNumeric->data.u32.MinValue || (UINT32) VarValue > IfrNumeric->data.u32.MaxValue) {\r
1369 //\r
1370 // Not in the valid range.\r
1371 //\r
1372 Status = EFI_INVALID_PARAMETER;\r
1373 goto Done;\r
1374 }\r
1375 break;\r
1376 case EFI_IFR_NUMERIC_SIZE_8:\r
1377 if ((UINT64) VarValue < IfrNumeric->data.u64.MinValue || (UINT64) VarValue > IfrNumeric->data.u64.MaxValue) {\r
1378 //\r
1379 // Not in the valid range.\r
1380 //\r
1381 Status = EFI_INVALID_PARAMETER;\r
1382 goto Done;\r
1383 }\r
1384 break;\r
1385 }\r
1386\r
1387 break;\r
1388 case EFI_IFR_CHECKBOX_OP:\r
1389 //\r
1390 // Check value is BOOLEAN type, only 0 and 1 is valid.\r
1391 //\r
1392\r
8567300a
LG
1393 //\r
1394 // CheckBox question is not in IFR Form. This IFR form is not valid. \r
1395 //\r
1396 if (IfrVarStore == NULL) {\r
1397 Status = EFI_INVALID_PARAMETER;\r
1398 goto Done;\r
1399 }\r
1400\r
84f9a9ec
LG
1401 //\r
1402 // Check whether this question is for the requested varstore.\r
1403 //\r
1404 IfrCheckBox = (EFI_IFR_CHECKBOX *) IfrOpHdr;\r
1405 if (IfrCheckBox->Question.VarStoreId != IfrVarStore->VarStoreId) {\r
1406 break;\r
1407 }\r
1408 \r
1409 //\r
1410 // Get Offset by Question header\r
1411 //\r
1412 Offset = IfrCheckBox->Question.VarStoreInfo.VarOffset;\r
1413 Width = sizeof (BOOLEAN);\r
1414 //\r
1415 // Check whether this question is in current block array.\r
1416 //\r
1417 if (!BlockArrayCheck (CurrentBlockArray, Offset, Width)) {\r
1418 //\r
1419 // This question is not in the current configuration string. Skip it.\r
1420 //\r
1421 break;\r
1422 }\r
1423 //\r
1424 // Check this var question is in the var storage \r
1425 //\r
1426 if ((Offset + Width) > IfrVarStore->Size) {\r
1427 //\r
1428 // This question exceeds the var store size. \r
1429 //\r
1430 Status = EFI_INVALID_PARAMETER;\r
1431 goto Done;\r
1432 }\r
1433\r
1434 //\r
1435 // Boolean type, only 1 and 0 is valid.\r
1436 //\r
1437 if (*(VarBuffer + Offset) > 1) {\r
1438 Status = EFI_INVALID_PARAMETER;\r
1439 goto Done; \r
1440 }\r
1441 \r
1442 break;\r
1443 case EFI_IFR_STRING_OP:\r
1444 //\r
1445 // Check current string length is less than maxsize\r
1446 //\r
1447\r
8567300a
LG
1448 //\r
1449 // CheckBox question is not in IFR Form. This IFR form is not valid. \r
1450 //\r
1451 if (IfrVarStore == NULL) {\r
1452 Status = EFI_INVALID_PARAMETER;\r
1453 goto Done;\r
1454 }\r
1455\r
84f9a9ec
LG
1456 //\r
1457 // Check whether this question is for the requested varstore.\r
1458 //\r
1459 IfrString = (EFI_IFR_STRING *) IfrOpHdr;\r
1460 if (IfrString->Question.VarStoreId != IfrVarStore->VarStoreId) {\r
1461 break;\r
1462 }\r
1463 \r
1464 //\r
1465 // Get Offset/Width by Question header and OneOf Flags\r
1466 //\r
1467 Offset = IfrString->Question.VarStoreInfo.VarOffset;\r
1468 Width = (UINT16) (IfrString->MaxSize * sizeof (UINT16));\r
1469 //\r
1470 // Check whether this question is in current block array.\r
1471 //\r
1472 if (!BlockArrayCheck (CurrentBlockArray, Offset, Width)) {\r
1473 //\r
1474 // This question is not in the current configuration string. Skip it.\r
1475 //\r
1476 break;\r
1477 }\r
1478 //\r
1479 // Check this var question is in the var storage \r
1480 //\r
1481 if ((Offset + Width) > IfrVarStore->Size) {\r
1482 //\r
1483 // This question exceeds the var store size. \r
1484 //\r
1485 Status = EFI_INVALID_PARAMETER;\r
1486 goto Done;\r
1487 }\r
1488 \r
1489 //\r
1490 // Check current string length is less than maxsize\r
1491 //\r
1492 if (StrSize ((CHAR16 *) (VarBuffer + Offset)) > Width) {\r
1493 Status = EFI_INVALID_PARAMETER;\r
1494 goto Done; \r
1495 }\r
1496 break;\r
1497 case EFI_IFR_ONE_OF_OPTION_OP:\r
1498 //\r
1499 // Opcode Scope is zero. This one of option is not to be checked. \r
1500 //\r
1501 if (VarBlockData.Scope == 0) {\r
1502 break;\r
1503 }\r
1504\r
1505 //\r
1506 // Only check for OneOf and OrderList opcode\r
1507 //\r
1508 IfrOneOfOption = (EFI_IFR_ONE_OF_OPTION *) IfrOpHdr;\r
1509 if (VarBlockData.OpCode == EFI_IFR_ONE_OF_OP) {\r
1510 //\r
1511 // Check current value is the value of one of option.\r
1512 //\r
1513 if (VarValue == IfrOneOfOption->Value.u64) {\r
1514 //\r
1515 // The value is one of option value.\r
1516 // Set OpCode to Zero, don't need check again.\r
1517 //\r
1518 VarBlockData.OpCode = 0;\r
1519 }\r
1520 }\r
1521\r
1522 break;\r
1523 case EFI_IFR_END_OP:\r
1524 //\r
1525 // Decrease opcode scope for the validated opcode\r
1526 //\r
1527 if (VarBlockData.Scope > 0) {\r
1528 VarBlockData.Scope --;\r
1529 }\r
1530\r
1531 //\r
1532 // OneOf value doesn't belong to one of option value. \r
1533 //\r
62b658dd 1534 if ((VarBlockData.Scope == 0) && (VarBlockData.OpCode == EFI_IFR_ONE_OF_OP)) {\r
84f9a9ec
LG
1535 Status = EFI_INVALID_PARAMETER;\r
1536 goto Done;\r
1537 }\r
1538 break;\r
1539 default:\r
1540 //\r
1541 // Increase Scope for the validated opcode\r
1542 //\r
1543 if (VarBlockData.Scope > 0) {\r
1544 VarBlockData.Scope = (UINT8) (VarBlockData.Scope + IfrOpHdr->Scope);\r
1545 }\r
1546 break;\r
1547 }\r
1548 //\r
1549 // Go to the next opcode\r
1550 //\r
1551 IfrOffset += IfrOpHdr->Length;\r
1552 }\r
1553 //\r
1554 // Only one form is in a package list.\r
1555 //\r
1556 break;\r
1557 }\r
1558 \r
1559 //\r
1560 // Go to next package.\r
1561 //\r
1562 PackageOffset += PacakgeHeader.Length; \r
1563 }\r
1564\r
1565Done:\r
1566 if (VarBuffer != NULL) {\r
1567 FreePool (VarBuffer);\r
1568 }\r
1569 \r
1570 if (CurrentBlockArray != NULL) {\r
1571 //\r
1572 // Free Link Array CurrentBlockArray\r
1573 //\r
1574 while (!IsListEmpty (&CurrentBlockArray->Entry)) {\r
1575 BlockData = BASE_CR (CurrentBlockArray->Entry.ForwardLink, IFR_BLOCK_DATA, Entry);\r
1576 RemoveEntryList (&BlockData->Entry);\r
1577 FreePool (BlockData);\r
1578 }\r
1579 FreePool (CurrentBlockArray); \r
1580 }\r
1581\r
1582 return Status;\r
1583}\r
1584\r
1585/**\r
8567300a
LG
1586 This function parses the input ConfigRequest string and its matched IFR code\r
1587 string for setting default value and validating current setting.\r
1588\r
84f9a9ec
LG
1589 1. For setting default action, Reset the default value specified by DefaultId \r
1590 to the driver configuration got by Request string.\r
1591 2. For validating current setting, Validate the current configuration \r
1592 by parsing HII form IFR opcode.\r
1593\r
1594 NULL request string support depends on the ExportConfig interface of\r
1595 HiiConfigRouting protocol in UEFI specification.\r
1596 \r
1597 @param Request A null-terminated Unicode string in \r
1598 <MultiConfigRequest> format. It can be NULL.\r
1599 If it is NULL, all current configuration for the\r
1600 entirety of the current HII database will be validated.\r
1601 If it is NULL, all configuration for the\r
1602 entirety of the current HII database will be reset.\r
1603 @param DefaultId Specifies the type of defaults to retrieve only for setting default action.\r
1604 @param ActionType Action supports setting defaults and validate current setting.\r
1605 \r
1606 @retval TURE Action runs successfully.\r
1607 @retval FALSE Action is not valid or Action can't be executed successfully..\r
1608**/\r
1609BOOLEAN\r
1610EFIAPI\r
1611InternalHiiIfrValueAction (\r
1612 IN CONST EFI_STRING Request, OPTIONAL\r
76c24251 1613 IN UINT16 DefaultId,\r
84f9a9ec
LG
1614 IN UINT8 ActionType\r
1615 )\r
1616{\r
1617 EFI_STRING ConfigAltResp;\r
1618 EFI_STRING ConfigAltHdr;\r
1619 EFI_STRING ConfigResp;\r
1620 EFI_STRING Progress;\r
1621 EFI_STRING StringPtr;\r
1622 EFI_STRING StringHdr;\r
1623 EFI_STATUS Status;\r
1624 EFI_HANDLE DriverHandle;\r
1625 EFI_HANDLE TempDriverHandle;\r
1626 EFI_HII_HANDLE *HiiHandleBuffer;\r
1627 EFI_HII_HANDLE HiiHandle;\r
1628 UINT32 Index;\r
1629 EFI_GUID *VarGuid;\r
1630 EFI_STRING VarName;\r
1631 EFI_STRING_ID DefaultName;\r
1632\r
1633 UINT8 *PackageData;\r
1634 UINTN IfrOffset;\r
1635 EFI_IFR_OP_HEADER *IfrOpHdr;\r
1636 EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;\r
1637 UINT32 PackageOffset; \r
1638 UINTN PackageListLength;\r
1639 EFI_HII_PACKAGE_HEADER PacakgeHeader;\r
1640 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
1641 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;\r
1642 \r
1643 ConfigAltResp = NULL;\r
1644 ConfigResp = NULL;\r
1645 VarGuid = NULL;\r
1646 VarName = NULL;\r
1647 DevicePath = NULL;\r
1648 ConfigAltHdr = NULL;\r
1649 HiiHandleBuffer = NULL;\r
1650 Index = 0;\r
1651 TempDriverHandle = NULL;\r
1652 HiiHandle = NULL;\r
1653 PackageData = NULL;\r
1654 HiiPackageList = NULL;\r
1655 \r
1656 //\r
1657 // Only support set default and validate setting action.\r
1658 //\r
1659 if ((ActionType != ACTION_SET_DEFAUTL_VALUE) && (ActionType != ACTION_VALIDATE_SETTING)) {\r
1660 return FALSE;\r
1661 }\r
1662\r
1663 //\r
1664 // Get the full requested value and deault value string.\r
1665 //\r
1666 if (Request != NULL) {\r
1667 Status = gHiiConfigRouting->ExtractConfig (\r
1668 gHiiConfigRouting,\r
1669 Request,\r
1670 &Progress,\r
1671 &ConfigAltResp\r
1672 );\r
1673 } else {\r
1674 Status = gHiiConfigRouting->ExportConfig (\r
1675 gHiiConfigRouting,\r
1676 &ConfigAltResp\r
1677 );\r
1678 }\r
1679 \r
1680 if (EFI_ERROR (Status)) {\r
1681 return FALSE;\r
1682 }\r
1683 \r
1684 StringPtr = ConfigAltResp;\r
1685 \r
1686 while (StringPtr != L'\0') {\r
1687 //\r
1688 // 1. Find <ConfigHdr> GUID=...&NAME=...&PATH=...\r
1689 //\r
1690 StringHdr = StringPtr;\r
1691\r
1692 //\r
1693 // Get Guid value\r
1694 //\r
1695 if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
1696 Status = EFI_INVALID_PARAMETER;\r
1697 goto Done;\r
1698 }\r
1699 StringPtr += StrLen (L"GUID=");\r
1700 Status = InternalHiiGetBufferFromString (StringPtr, GUID_CONFIG_STRING_TYPE, (UINT8 **) &VarGuid);\r
1701 if (EFI_ERROR (Status)) {\r
1702 goto Done;\r
1703 }\r
1704\r
1705 //\r
1706 // Get Name value VarName\r
1707 //\r
1708 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&NAME=", StrLen (L"&NAME=")) != 0) {\r
1709 StringPtr++;\r
1710 }\r
1711 if (*StringPtr == L'\0') {\r
1712 Status = EFI_INVALID_PARAMETER;\r
1713 goto Done;\r
1714 }\r
1715 StringPtr += StrLen (L"&NAME=");\r
1716 Status = InternalHiiGetBufferFromString (StringPtr, NAME_CONFIG_STRING_TYPE, (UINT8 **) &VarName);\r
1717 if (EFI_ERROR (Status)) {\r
1718 goto Done;\r
1719 }\r
1720 \r
1721 //\r
1722 // Get Path value DevicePath\r
1723 //\r
1724 while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&PATH=", StrLen (L"&PATH=")) != 0) {\r
1725 StringPtr++;\r
1726 }\r
1727 if (*StringPtr == L'\0') {\r
1728 Status = EFI_INVALID_PARAMETER;\r
1729 goto Done;\r
1730 }\r
1731 StringPtr += StrLen (L"&PATH=");\r
1732 Status = InternalHiiGetBufferFromString (StringPtr, PATH_CONFIG_STRING_TYPE, (UINT8 **) &DevicePath);\r
1733 if (EFI_ERROR (Status)) {\r
1734 goto Done;\r
1735 }\r
1736\r
1737 //\r
1738 // Get the Driver handle by the got device path.\r
1739 //\r
1740 TempDevicePath = DevicePath;\r
1741 Status = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &TempDevicePath, &DriverHandle);\r
1742 if (EFI_ERROR (Status)) {\r
1743 goto Done;\r
1744 }\r
1745 \r
1746 //\r
1747 // Find the matched Hii Handle for the found Driver handle\r
1748 //\r
1749 HiiHandleBuffer = HiiGetHiiHandles (NULL);\r
1750 if (HiiHandleBuffer == NULL) {\r
1751 Status = EFI_NOT_FOUND;\r
1752 goto Done;\r
1753 }\r
1754\r
1755 for (Index = 0; HiiHandleBuffer[Index] != NULL; Index ++) {\r
1756 gHiiDatabase->GetPackageListHandle (gHiiDatabase, HiiHandleBuffer[Index], &TempDriverHandle);\r
1757 if (TempDriverHandle == DriverHandle) {\r
1758 break;\r
1759 }\r
1760 }\r
1761\r
1762 HiiHandle = HiiHandleBuffer[Index];\r
1763 FreePool (HiiHandleBuffer);\r
1764\r
1765 if (HiiHandle == NULL) {\r
1766 //\r
1767 // This request string has no its Hii package.\r
1768 // Its default value and validating can't execute by parsing IFR data.\r
1769 // Directly jump into the next ConfigAltResp string for another pair Guid, Name, and Path. \r
1770 //\r
4e069e8b 1771 Status = EFI_SUCCESS;\r
84f9a9ec
LG
1772 goto NextConfigAltResp;\r
1773 }\r
1774 \r
1775 //\r
1776 // 2. Get DefaultName string ID by parsing the PacakgeList \r
1777 //\r
1778\r
1779 //\r
1780 // Get HiiPackage by HiiHandle\r
1781 //\r
1782 PackageListLength = 0;\r
1783 HiiPackageList = NULL;\r
1784 Status = gHiiDatabase->ExportPackageLists (gHiiDatabase, HiiHandle, &PackageListLength, HiiPackageList);\r
1785 \r
1786 //\r
1787 // The return status should always be EFI_BUFFER_TOO_SMALL as input buffer's size is 0.\r
1788 //\r
1789 if (Status != EFI_BUFFER_TOO_SMALL) {\r
1790 Status = EFI_INVALID_PARAMETER;\r
1791 goto Done;\r
1792 }\r
1793 \r
1794 HiiPackageList = AllocatePool (PackageListLength);\r
1795 if (HiiPackageList == NULL) {\r
1796 Status = EFI_OUT_OF_RESOURCES;\r
1797 goto Done;\r
1798 }\r
1799 \r
1800 //\r
1801 // Get PackageList on HiiHandle\r
1802 //\r
1803 Status = gHiiDatabase->ExportPackageLists (gHiiDatabase, HiiHandle, &PackageListLength, HiiPackageList);\r
1804 if (EFI_ERROR (Status)) {\r
1805 goto Done;\r
1806 }\r
1807 \r
1808 //\r
1809 // Parse the form package and get the default name string ID.\r
1810 //\r
1811 if (ActionType == ACTION_SET_DEFAUTL_VALUE) {\r
1812 PackageOffset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);\r
1813 Status = EFI_NOT_FOUND;\r
1814 while (PackageOffset < PackageListLength) {\r
1815 CopyMem (&PacakgeHeader, (UINT8 *) HiiPackageList + PackageOffset, sizeof (PacakgeHeader));\r
1816 \r
1817 //\r
1818 // Parse IFR opcode to get default store opcode\r
1819 //\r
1820 if (PacakgeHeader.Type == EFI_HII_PACKAGE_FORMS) {\r
1821 IfrOffset = sizeof (PacakgeHeader);\r
1822 PackageData = (UINT8 *) HiiPackageList + PackageOffset;\r
1823 while (IfrOffset < PacakgeHeader.Length) {\r
1824 IfrOpHdr = (EFI_IFR_OP_HEADER *) (PackageData + IfrOffset);\r
1825 //\r
1826 // Match DefaultId to find its DefaultName\r
1827 //\r
1828 if (IfrOpHdr->OpCode == EFI_IFR_DEFAULTSTORE_OP) {\r
1829 if (((EFI_IFR_DEFAULTSTORE *) IfrOpHdr)->DefaultId == DefaultId) {\r
1830 DefaultName = ((EFI_IFR_DEFAULTSTORE *) IfrOpHdr)->DefaultName;\r
1831 Status = EFI_SUCCESS;\r
1832 break;\r
1833 }\r
1834 }\r
1835 IfrOffset += IfrOpHdr->Length;\r
1836 }\r
1837 //\r
1838 // Only one form is in a package list.\r
1839 //\r
1840 break;\r
1841 }\r
1842 \r
1843 //\r
1844 // Go to next package.\r
1845 //\r
1846 PackageOffset += PacakgeHeader.Length; \r
1847 }\r
1848 \r
1849 //\r
1850 // Not found the matched default string ID\r
1851 //\r
1852 if (EFI_ERROR (Status)) {\r
76c24251
LG
1853 Status = EFI_SUCCESS;\r
1854 goto NextConfigAltResp;\r
84f9a9ec
LG
1855 }\r
1856 }\r
1857 \r
1858 //\r
1859 // 3. Call ConfigRouting GetAltCfg(ConfigRoute, <ConfigResponse>, Guid, Name, DevicePath, AltCfgId, AltCfgResp)\r
1860 // Get the default configuration string according to the found defaultname string ID.\r
1861 //\r
1862 Status = gHiiConfigRouting->GetAltConfig (\r
1863 gHiiConfigRouting,\r
1864 ConfigAltResp,\r
1865 VarGuid,\r
1866 VarName,\r
1867 DevicePath,\r
1868 (ActionType == ACTION_SET_DEFAUTL_VALUE) ? &DefaultName:NULL, // it can be NULL to get the current setting.\r
1869 &ConfigResp\r
1870 );\r
1f1cb2f2
LG
1871 \r
1872 //\r
1873 // The required setting can't be found. So, it is not required to be validated and set.\r
1874 //\r
84f9a9ec 1875 if (EFI_ERROR (Status)) {\r
76c24251
LG
1876 Status = EFI_SUCCESS;\r
1877 goto NextConfigAltResp;\r
84f9a9ec 1878 }\r
1f1cb2f2
LG
1879 //\r
1880 // Only the ConfigHdr is found. Not any block data is found. No data is required to be validated and set.\r
1881 //\r
1882 if (StrStr (ConfigResp, L"&OFFSET=") == NULL) {\r
1883 goto NextConfigAltResp;\r
1884 }\r
84f9a9ec
LG
1885 \r
1886 //\r
1887 // 4. Set the default configuration information or Validate current setting by parse IFR code.\r
1888 // Current Setting is in ConfigResp, will be set into buffer, then check it again.\r
1889 //\r
1890 if (ActionType == ACTION_SET_DEFAUTL_VALUE) {\r
1891 //\r
1892 // Set the default configuration information.\r
1893 //\r
1894 Status = gHiiConfigRouting->RouteConfig (gHiiConfigRouting, ConfigResp, &Progress);\r
1895 } else {\r
1896 //\r
1897 // Current Setting is in ConfigResp, will be set into buffer, then check it again.\r
1898 //\r
1899 Status = InternalHiiValidateCurrentSetting (ConfigResp, HiiPackageList, PackageListLength, VarGuid, VarName);\r
1900 }\r
1901\r
1902 if (EFI_ERROR (Status)) {\r
1903 goto Done;\r
1904 }\r
1905\r
76c24251 1906NextConfigAltResp:\r
84f9a9ec
LG
1907 //\r
1908 // Free the allocated pacakge buffer and the got ConfigResp string.\r
1909 //\r
1910 if (HiiPackageList != NULL) {\r
1911 FreePool (HiiPackageList);\r
1912 HiiPackageList = NULL;\r
1913 }\r
76c24251 1914 \r
1f1cb2f2
LG
1915 if (ConfigResp != NULL) {\r
1916 FreePool (ConfigResp);\r
1917 ConfigResp = NULL;\r
1918 }\r
84f9a9ec 1919\r
84f9a9ec
LG
1920 //\r
1921 // Free the allocated buffer.\r
1922 //\r
1923 FreePool (VarGuid);\r
1924 VarGuid = NULL;\r
1925 \r
1926 FreePool (VarName);\r
1927 VarName = NULL;\r
1928 \r
1929 FreePool (DevicePath);\r
1930 DevicePath = NULL;\r
1931\r
1932 //\r
1933 // 5. Jump to next ConfigAltResp for another Guid, Name, Path.\r
1934 //\r
1935\r
1936 //\r
1937 // Get and Skip ConfigHdr\r
1938 //\r
1939 while (*StringPtr != L'\0' && *StringPtr != L'&') {\r
1940 StringPtr++;\r
1941 }\r
1942 if (*StringPtr == L'\0') {\r
1943 break;\r
1944 }\r
1945 \r
1946 //\r
1947 // Construct ConfigAltHdr string "&<ConfigHdr>&ALTCFG=\0" \r
1948 // | 1 | StrLen (ConfigHdr) | 8 | 1 |\r
1949 //\r
1950 ConfigAltHdr = AllocateZeroPool ((1 + StringPtr - StringHdr + 8 + 1) * sizeof (CHAR16));\r
1951 if (ConfigAltHdr == NULL) {\r
1952 Status = EFI_OUT_OF_RESOURCES;\r
1953 goto Done;\r
1954 }\r
1955 StrCpy (ConfigAltHdr, L"&");\r
1956 StrnCat (ConfigAltHdr, StringHdr, StringPtr - StringHdr);\r
1957 StrCat (ConfigAltHdr, L"&ALTCFG=");\r
1958 \r
1959 //\r
1960 // Skip all AltResp (AltConfigHdr ConfigBody) for the same ConfigHdr\r
1961 //\r
1962 while ((StringHdr = StrStr (StringPtr, ConfigAltHdr)) != NULL) {\r
1963 StringPtr = StringHdr + StrLen (ConfigAltHdr);\r
1964 if (*StringPtr == L'\0') {\r
1965 break;\r
1966 }\r
1967 }\r
1968 \r
1969 //\r
1970 // Free the allocated ConfigAltHdr string\r
1971 //\r
1972 FreePool (ConfigAltHdr);\r
1973 if (*StringPtr == L'\0') {\r
1974 break;\r
1975 }\r
1976 \r
1977 //\r
1978 // Find &GUID as the next ConfigHdr\r
1979 //\r
1980 StringPtr = StrStr (StringPtr, L"&GUID");\r
1981 if (StringPtr == NULL) {\r
1982 break;\r
1983 }\r
1984\r
1985 //\r
1986 // Skip char '&'\r
1987 //\r
1988 StringPtr ++;\r
1989 }\r
1990 \r
1991Done:\r
1992 if (VarGuid != NULL) {\r
1993 FreePool (VarGuid);\r
1994 }\r
1995\r
1996 if (VarName != NULL) {\r
1997 FreePool (VarName);\r
1998 }\r
1999\r
2000 if (DevicePath != NULL) {\r
2001 FreePool (DevicePath);\r
2002 }\r
2003\r
2004 if (ConfigResp != NULL) {\r
2005 FreePool (ConfigResp);\r
2006 }\r
2007\r
2008 if (ConfigAltResp != NULL) {\r
2009 FreePool (ConfigAltResp);\r
2010 }\r
2011 \r
2012 if (HiiPackageList != NULL) {\r
2013 FreePool (HiiPackageList);\r
2014 }\r
2015 \r
2016 if (EFI_ERROR (Status)) {\r
2017 return FALSE;\r
2018 }\r
2019\r
2020 return TRUE;\r
2021}\r
2022\r
2023/**\r
2024 Validate the current configuration by parsing HII form IFR opcode.\r
2025\r
4e069e8b 2026 NULL request string support depends on the ExportConfig interface of\r
84f9a9ec
LG
2027 HiiConfigRouting protocol in UEFI specification.\r
2028 \r
2029 @param Request A null-terminated Unicode string in \r
2030 <MultiConfigRequest> format. It can be NULL.\r
2031 If it is NULL, all current configuration for the\r
2032 entirety of the current HII database will be validated.\r
2033 \r
2034 @retval TURE Current configuration is valid.\r
2035 @retval FALSE Current configuration is invalid.\r
2036**/\r
2037BOOLEAN\r
2038EFIAPI \r
2039HiiValidateSettings (\r
2040 IN CONST EFI_STRING Request OPTIONAL\r
2041 )\r
2042{\r
2043 return InternalHiiIfrValueAction (Request, 0, ACTION_VALIDATE_SETTING);\r
2044}\r
2045\r
2046/**\r
2047 Reset the default value specified by DefaultId to the driver\r
2048 configuration got by Request string. \r
2049\r
2050 NULL request string support depends on the ExportConfig interface of\r
2051 HiiConfigRouting protocol in UEFI specification.\r
2052 \r
2053 @param Request A null-terminated Unicode string in \r
2054 <MultiConfigRequest> format. It can be NULL.\r
2055 If it is NULL, all configuration for the\r
2056 entirety of the current HII database will be reset.\r
2057 @param DefaultId Specifies the type of defaults to retrieve.\r
2058 \r
2059 @retval TURE The default value is set successfully.\r
2060 @retval FALSE The default value can't be found and set.\r
2061**/\r
2062BOOLEAN\r
2063EFIAPI\r
2064HiiSetToDefaults (\r
2065 IN CONST EFI_STRING Request, OPTIONAL\r
2066 IN UINT16 DefaultId\r
2067 )\r
2068{\r
2069 return InternalHiiIfrValueAction (Request, DefaultId, ACTION_SET_DEFAUTL_VALUE);\r
2070}\r
2071\r
7e3bcccb
LG
2072/**\r
2073 Determines if two values in config strings match.\r
2074\r
2075 Compares the substring between StartSearchString and StopSearchString in \r
2076 FirstString to the substring between StartSearchString and StopSearchString \r
2077 in SecondString. If the two substrings match, then TRUE is returned. If the\r
2078 two substrings do not match, then FALSE is returned.\r
2079\r
2080 If FirstString is NULL, then ASSERT().\r
2081 If SecondString is NULL, then ASSERT().\r
2082 If StartSearchString is NULL, then ASSERT().\r
2083 If StopSearchString is NULL, then ASSERT().\r
2084\r
2085 @param FirstString Pointer to the first Null-terminated Unicode string.\r
2086 @param SecondString Pointer to the second Null-terminated Unicode string.\r
2087 @param StartSearchString Pointer to the Null-terminated Unicode string that \r
2088 marks the start of the value string to compare.\r
2089 @param StopSearchString Pointer to the Null-terminated Unicode string that \r
2090 marks the end of the vakue string to compare.\r
2091\r
2092 @retval FALSE StartSearchString is not present in FirstString. \r
2093 @retval FALSE StartSearchString is not present in SecondString.\r
2094 @retval FALSE StopSearchString is not present in FirstString. \r
2095 @retval FALSE StopSearchString is not present in SecondString.\r
2096 @retval FALSE The length of the substring in FirstString is not the \r
2097 same length as the substring in SecondString.\r
2098 @retval FALSE The value string in FirstString does not matche the \r
2099 value string in SecondString.\r
2100 @retval TRUE The value string in FirstString matches the value \r
2101 string in SecondString.\r
2102\r
2103**/\r
2104BOOLEAN\r
2105EFIAPI\r
2106InternalHiiCompareSubString (\r
2107 IN CHAR16 *FirstString,\r
2108 IN CHAR16 *SecondString,\r
2109 IN CHAR16 *StartSearchString,\r
2110 IN CHAR16 *StopSearchString\r
2111 )\r
2112{\r
2113 CHAR16 *EndFirstString;\r
2114 CHAR16 *EndSecondString;\r
2115\r
2116 ASSERT (FirstString != NULL);\r
2117 ASSERT (SecondString != NULL);\r
2118 ASSERT (StartSearchString != NULL);\r
2119 ASSERT (StopSearchString != NULL);\r
2120\r
2121 FirstString = StrStr (FirstString, StartSearchString);\r
2122 if (FirstString == NULL) {\r
2123 return FALSE;\r
2124 }\r
2125\r
2126 SecondString = StrStr (SecondString, StartSearchString);\r
2127 if (SecondString == NULL) {\r
2128 return FALSE;\r
2129 }\r
2130\r
2131 EndFirstString = StrStr (FirstString, StopSearchString);\r
2132 if (EndFirstString == NULL) {\r
2133 return FALSE;\r
2134 }\r
2135\r
2136 EndSecondString = StrStr (SecondString, StopSearchString);\r
2137 if (EndSecondString == NULL) {\r
2138 return FALSE;\r
2139 }\r
2140\r
2141 if ((EndFirstString - FirstString) != (EndSecondString - SecondString)) {\r
2142 return FALSE;\r
2143 }\r
2144\r
2145 return (BOOLEAN)(StrnCmp (FirstString, SecondString, EndFirstString - FirstString) == 0);\r
2146}\r
2147\r
2148/**\r
2149 Determines if the routing data specified by GUID and NAME match a <ConfigHdr>.\r
2150\r
2151 If ConfigHdr is NULL, then ASSERT().\r
2152\r
2153 @param[in] ConfigHdr Either <ConfigRequest> or <ConfigResp>.\r
2154 @param[in] Guid GUID of the storage.\r
2155 @param[in] Name NAME of the storage.\r
2156\r
2157 @retval TRUE Routing information matches <ConfigHdr>.\r
2158 @retval FALSE Routing information does not match <ConfigHdr>.\r
2159\r
2160**/\r
2161BOOLEAN\r
2162EFIAPI\r
2163HiiIsConfigHdrMatch (\r
2164 IN CONST EFI_STRING ConfigHdr,\r
2165 IN CONST EFI_GUID *Guid, OPTIONAL\r
2166 IN CONST CHAR16 *Name OPTIONAL\r
2167 )\r
2168{\r
2169 EFI_STRING CompareConfigHdr;\r
2170 BOOLEAN Result;\r
2171\r
2172 ASSERT (ConfigHdr != NULL);\r
2173\r
2174 //\r
2175 // Use Guid and Name to generate a <ConfigHdr> string\r
2176 //\r
2177 CompareConfigHdr = HiiConstructConfigHdr (Guid, Name, NULL);\r
2178 if (CompareConfigHdr == NULL) {\r
2179 return FALSE;\r
2180 }\r
2181\r
2182 Result = TRUE;\r
2183 if (Guid != NULL) {\r
2184 //\r
2185 // Compare GUID value strings\r
2186 //\r
2187 Result = InternalHiiCompareSubString (ConfigHdr, CompareConfigHdr, L"GUID=", L"&NAME=");\r
2188 }\r
2189\r
2190 if (Result && Name != NULL) {\r
2191 //\r
2192 // Compare NAME value strings\r
2193 //\r
2194 Result = InternalHiiCompareSubString (ConfigHdr, CompareConfigHdr, L"&NAME=", L"&PATH=");\r
2195 }\r
2196\r
2197 //\r
2198 // Free the <ConfigHdr> string\r
2199 //\r
2200 FreePool (CompareConfigHdr);\r
2201\r
2202 return Result;\r
2203}\r
2204\r
2205/**\r
2206 Retrieves uncommited data from the Form Browser and converts it to a binary\r
1d451ff9 2207 buffer.\r
7e3bcccb 2208\r
b8215f46
LG
2209 @param[in] VariableName Pointer to a Null-terminated Unicode string. This \r
2210 is an optional parameter that may be NULL.\r
1d451ff9
LG
2211 @param[in] VariableGuid Pointer to an EFI_GUID structure. This is an optional \r
2212 parameter that may be NULL.\r
7e3bcccb 2213 @param[in] BufferSize Length in bytes of buffer to hold retrived data. \r
1d451ff9 2214 @param[out] Block Buffer of data to be updated.\r
7e3bcccb 2215\r
1d451ff9
LG
2216 @retval FALSE The uncommitted data could not be retrieved.\r
2217 @retval TRUE The uncommitted data was retrieved.\r
7e3bcccb
LG
2218\r
2219**/\r
1d451ff9 2220BOOLEAN\r
7e3bcccb
LG
2221EFIAPI\r
2222HiiGetBrowserData (\r
2223 IN CONST EFI_GUID *VariableGuid, OPTIONAL\r
2224 IN CONST CHAR16 *VariableName, OPTIONAL\r
1d451ff9
LG
2225 IN UINTN BlockSize,\r
2226 OUT UINT8 *Block\r
7e3bcccb
LG
2227 )\r
2228{\r
2229 EFI_STRING ResultsData;\r
2230 UINTN Size;\r
2231 EFI_STRING ConfigResp;\r
1d451ff9
LG
2232 EFI_STATUS Status;\r
2233 CHAR16 *Progress;\r
7e3bcccb
LG
2234\r
2235 //\r
2236 // Retrieve the results data from the Browser Callback\r
2237 //\r
2238 ResultsData = InternalHiiBrowserCallback (VariableGuid, VariableName, NULL);\r
2239 if (ResultsData == NULL) {\r
1d451ff9 2240 return FALSE;\r
7e3bcccb
LG
2241 }\r
2242\r
2243 //\r
5c1ebff6 2244 // Construct <ConfigResp> mConfigHdrTemplate L'&' ResultsData L'\0'\r
7e3bcccb 2245 //\r
5c1ebff6
LG
2246 Size = (StrLen (mConfigHdrTemplate) + 1) * sizeof (CHAR16);\r
2247 Size = Size + (StrLen (ResultsData) + 1) * sizeof (CHAR16);\r
7e3bcccb
LG
2248 ConfigResp = AllocateZeroPool (Size);\r
2249 UnicodeSPrint (ConfigResp, Size, L"%s&%s", mConfigHdrTemplate, ResultsData);\r
2250 \r
2251 //\r
2252 // Free the allocated buffer\r
2253 //\r
2254 FreePool (ResultsData);\r
2255 if (ConfigResp == NULL) {\r
1d451ff9 2256 return FALSE;\r
7e3bcccb
LG
2257 }\r
2258\r
2259 //\r
2260 // Convert <ConfigResp> to a buffer\r
2261 //\r
1d451ff9
LG
2262 Status = gHiiConfigRouting->ConfigToBlock (\r
2263 gHiiConfigRouting,\r
2264 ConfigResp,\r
2265 Block,\r
2266 &BlockSize,\r
2267 &Progress\r
2268 );\r
2269 //\r
2270 // Free the allocated buffer\r
2271 //\r
7e3bcccb
LG
2272 FreePool (ConfigResp);\r
2273\r
1d451ff9
LG
2274 if (EFI_ERROR (Status)) {\r
2275 return FALSE;\r
2276 }\r
2277\r
2278 return TRUE;\r
7e3bcccb
LG
2279}\r
2280\r
2281/**\r
2282 Updates uncommitted data in the Form Browser.\r
2283\r
2284 If Buffer is NULL, then ASSERT().\r
2285\r
2286 @param[in] VariableName Pointer to a Null-terminated Unicode string. This\r
2287 is an optional parameter that may be NULL.\r
2288 @param[in] VariableGuid Pointer to an EFI_GUID structure. This is an optional\r
2289 parameter that may be NULL.\r
2290 @param[in] BufferSize Length, in bytes, of Buffer.\r
2291 @param[in] Buffer Buffer of data to commit.\r
2292 @param[in] RequestElement An optional field to specify which part of the\r
2293 buffer data will be send back to Browser. If NULL,\r
2294 the whole buffer of data will be committed to\r
2295 Browser. \r
2296 <RequestElement> ::= &OFFSET=<Number>&WIDTH=<Number>*\r
2297\r
2298 @retval FALSE The uncommitted data could not be updated.\r
2299 @retval TRUE The uncommitted data was updated.\r
2300\r
2301**/\r
2302BOOLEAN\r
2303EFIAPI\r
2304HiiSetBrowserData (\r
2305 IN CONST EFI_GUID *VariableGuid, OPTIONAL\r
2306 IN CONST CHAR16 *VariableName, OPTIONAL\r
2307 IN UINTN BufferSize,\r
2308 IN CONST UINT8 *Buffer,\r
2309 IN CONST CHAR16 *RequestElement OPTIONAL\r
2310 )\r
2311{\r
2312 UINTN Size;\r
2313 EFI_STRING ConfigRequest;\r
2314 EFI_STRING ConfigResp;\r
2315 EFI_STRING ResultsData;\r
2316\r
2317 ASSERT (Buffer != NULL);\r
2318\r
2319 //\r
2320 // Construct <ConfigRequest>\r
2321 //\r
2322 if (RequestElement == NULL) {\r
2323 //\r
2324 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template \r
2325 // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator\r
2326 //\r
2327 Size = (StrLen (mConfigHdrTemplate) + 32 + 1) * sizeof (CHAR16);\r
2328 ConfigRequest = AllocateZeroPool (Size);\r
2329 UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", mConfigHdrTemplate, (UINT64)BufferSize);\r
2330 } else {\r
2331 //\r
2332 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template \r
2333 // followed by <RequestElement> followed by a Null-terminator\r
2334 //\r
5c1ebff6
LG
2335 Size = StrLen (mConfigHdrTemplate) * sizeof (CHAR16);\r
2336 Size = Size + (StrLen (RequestElement) + 1) * sizeof (CHAR16);\r
7e3bcccb
LG
2337 ConfigRequest = AllocateZeroPool (Size);\r
2338 UnicodeSPrint (ConfigRequest, Size, L"%s%s", mConfigHdrTemplate, RequestElement);\r
2339 }\r
2340 if (ConfigRequest == NULL) {\r
2341 return FALSE;\r
2342 }\r
2343\r
2344 //\r
2345 // Convert <ConfigRequest> to <ConfigResp>\r
2346 //\r
2347 ConfigResp = InternalHiiBlockToConfig (ConfigRequest, Buffer, BufferSize);\r
2348 FreePool (ConfigRequest);\r
2349 if (ConfigResp == NULL) {\r
2350 return FALSE;\r
2351 }\r
2352\r
2353 //\r
2354 // Set data in the uncommitted browser state information\r
2355 //\r
2356 ResultsData = InternalHiiBrowserCallback (VariableGuid, VariableName, ConfigResp + StrLen(mConfigHdrTemplate) + 1);\r
2357 FreePool (ConfigResp);\r
2358\r
2359 return (BOOLEAN)(ResultsData != NULL);\r
2360}\r
2361\r
2362/////////////////////////////////////////\r
2363/////////////////////////////////////////\r
2364/// IFR Functions\r
2365/////////////////////////////////////////\r
2366/////////////////////////////////////////\r
2367\r
2368#define HII_LIB_OPCODE_ALLOCATION_SIZE 0x200\r
2369\r
2370typedef struct {\r
2371 UINT8 *Buffer;\r
2372 UINTN BufferSize;\r
2373 UINTN Position;\r
2374} HII_LIB_OPCODE_BUFFER;\r
2375\r
2376///\r
2377/// Lookup table that converts EFI_IFR_TYPE_X enum values to a width in bytes\r
2378///\r
2379GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 mHiiDefaultTypeToWidth[] = {\r
2380 1, // EFI_IFR_TYPE_NUM_SIZE_8\r
2381 2, // EFI_IFR_TYPE_NUM_SIZE_16\r
2382 4, // EFI_IFR_TYPE_NUM_SIZE_32\r
2383 8, // EFI_IFR_TYPE_NUM_SIZE_64\r
2384 1, // EFI_IFR_TYPE_BOOLEAN\r
2385 3, // EFI_IFR_TYPE_TIME\r
2386 4, // EFI_IFR_TYPE_DATE\r
2387 2 // EFI_IFR_TYPE_STRING\r
2388};\r
2389\r
2390/**\r
2391 Allocates and returns a new OpCode Handle. OpCode Handles must be freed with \r
2392 HiiFreeOpCodeHandle().\r
2393\r
2394 @retval NULL There are not enough resources to allocate a new OpCode Handle.\r
2395 @retval Other A new OpCode handle.\r
2396\r
2397**/\r
2398VOID *\r
2399EFIAPI\r
2400HiiAllocateOpCodeHandle (\r
2401 VOID\r
2402 )\r
2403{\r
2404 HII_LIB_OPCODE_BUFFER *OpCodeBuffer;\r
2405\r
2406 OpCodeBuffer = (HII_LIB_OPCODE_BUFFER *)AllocatePool (sizeof (HII_LIB_OPCODE_BUFFER));\r
2407 if (OpCodeBuffer == NULL) {\r
2408 return NULL;\r
2409 }\r
2410 OpCodeBuffer->Buffer = (UINT8 *)AllocatePool (HII_LIB_OPCODE_ALLOCATION_SIZE);\r
2411 if (OpCodeBuffer->Buffer == NULL) {\r
2412 FreePool (OpCodeBuffer);\r
2413 return NULL;\r
2414 }\r
2415 OpCodeBuffer->BufferSize = HII_LIB_OPCODE_ALLOCATION_SIZE;\r
2416 OpCodeBuffer->Position = 0;\r
2417 return (VOID *)OpCodeBuffer;\r
2418}\r
2419\r
2420/**\r
2421 Frees an OpCode Handle that was peviously allocated with HiiAllocateOpCodeHandle().\r
2422 When an OpCode Handle is freed, all of the opcodes associated with the OpCode\r
2423 Handle are also freed.\r
2424\r
2425 If OpCodeHandle is NULL, then ASSERT().\r
2426\r
2427**/\r
2428VOID\r
2429EFIAPI\r
2430HiiFreeOpCodeHandle (\r
2431 VOID *OpCodeHandle\r
2432 )\r
2433{\r
2434 HII_LIB_OPCODE_BUFFER *OpCodeBuffer;\r
2435\r
2436 ASSERT (OpCodeHandle != NULL);\r
2437\r
2438 OpCodeBuffer = (HII_LIB_OPCODE_BUFFER *)OpCodeHandle;\r
2439 if (OpCodeBuffer->Buffer != NULL) {\r
2440 FreePool (OpCodeBuffer->Buffer);\r
2441 }\r
2442 FreePool (OpCodeBuffer);\r
2443}\r
2444\r
2445UINTN\r
2446EFIAPI\r
2447InternalHiiOpCodeHandlePosition (\r
2448 IN VOID *OpCodeHandle\r
2449 )\r
2450{\r
2451 return ((HII_LIB_OPCODE_BUFFER *)OpCodeHandle)->Position;\r
2452}\r
2453\r
2454UINT8 *\r
2455EFIAPI\r
2456InternalHiiOpCodeHandleBuffer (\r
2457 IN VOID *OpCodeHandle\r
2458 )\r
2459{\r
2460 return ((HII_LIB_OPCODE_BUFFER *)OpCodeHandle)->Buffer;\r
2461}\r
2462\r
2463UINT8 *\r
2464EFIAPI\r
2465InternalHiiGrowOpCodeHandle (\r
2466 VOID *OpCodeHandle,\r
2467 UINTN Size\r
2468 )\r
2469{\r
2470 HII_LIB_OPCODE_BUFFER *OpCodeBuffer;\r
2471 UINT8 *Buffer;\r
2472\r
2473 ASSERT (OpCodeHandle != NULL);\r
2474\r
2475 OpCodeBuffer = (HII_LIB_OPCODE_BUFFER *)OpCodeHandle;\r
2476 if (OpCodeBuffer->Position + Size > OpCodeBuffer->BufferSize) {\r
2477 Buffer = ReallocatePool (\r
2478 OpCodeBuffer->BufferSize, \r
2479 OpCodeBuffer->BufferSize + (Size + HII_LIB_OPCODE_ALLOCATION_SIZE),\r
2480 OpCodeBuffer->Buffer\r
2481 );\r
2482 if (Buffer == NULL) {\r
2483 return NULL;\r
2484 }\r
2485 OpCodeBuffer->Buffer = Buffer;\r
2486 OpCodeBuffer->BufferSize += (Size + HII_LIB_OPCODE_ALLOCATION_SIZE);\r
2487 }\r
2488 Buffer = OpCodeBuffer->Buffer + OpCodeBuffer->Position;\r
2489 OpCodeBuffer->Position += Size;\r
2490 return Buffer;\r
2491}\r
2492\r
2493UINT8 *\r
2494EFIAPI\r
2495InternalHiiCreateOpCodeExtended (\r
2496 IN VOID *OpCodeHandle,\r
2497 IN VOID *OpCodeTemplate,\r
2498 IN UINT8 OpCode,\r
2499 IN UINTN OpCodeSize,\r
2500 IN UINTN ExtensionSize,\r
2501 IN UINT8 Scope\r
2502 )\r
2503{\r
2504 EFI_IFR_OP_HEADER *Header;\r
2505 UINT8 *Buffer;\r
2506\r
2507 ASSERT (OpCodeTemplate != NULL);\r
2508 ASSERT ((OpCodeSize + ExtensionSize) <= 0x7F);\r
2509\r
2510 Header = (EFI_IFR_OP_HEADER *)OpCodeTemplate;\r
2511 Header->OpCode = OpCode;\r
2512 Header->Scope = Scope;\r
2513 Header->Length = (UINT8)(OpCodeSize + ExtensionSize);\r
2514 Buffer = InternalHiiGrowOpCodeHandle (OpCodeHandle, Header->Length);\r
2515 return (UINT8 *)CopyMem (Buffer, Header, OpCodeSize);\r
2516}\r
2517\r
2518UINT8 *\r
2519EFIAPI\r
2520InternalHiiCreateOpCode (\r
2521 IN VOID *OpCodeHandle,\r
2522 IN VOID *OpCodeTemplate,\r
2523 IN UINT8 OpCode,\r
2524 IN UINTN OpCodeSize\r
2525 )\r
2526{\r
2527 return InternalHiiCreateOpCodeExtended (OpCodeHandle, OpCodeTemplate, OpCode, OpCodeSize, 0, 0);\r
2528}\r
2529\r
2530/**\r
2531 Append raw opcodes to an OpCodeHandle.\r
2532\r
2533 If OpCodeHandle is NULL, then ASSERT().\r
2534 If RawBuffer is NULL, then ASSERT();\r
2535\r
2536 @param[in] OpCodeHandle Handle to the buffer of opcodes.\r
2537 @param[in] RawBuffer Buffer of opcodes to append.\r
2538 @param[in] RawBufferSize The size, in bytes, of Buffer.\r
2539\r
2540 @retval NULL There is not enough space left in Buffer to add the opcode.\r
2541 @retval Other A pointer to the appended opcodes.\r
2542\r
2543**/\r
2544UINT8 *\r
2545EFIAPI\r
278663ab 2546HiiCreateRawOpCodes (\r
7e3bcccb
LG
2547 IN VOID *OpCodeHandle,\r
2548 IN UINT8 *RawBuffer,\r
2549 IN UINTN RawBufferSize\r
2550 )\r
2551{\r
2552 UINT8 *Buffer;\r
2553\r
2554 ASSERT (RawBuffer != NULL);\r
2555\r
2556 Buffer = InternalHiiGrowOpCodeHandle (OpCodeHandle, RawBufferSize);\r
2557 return (UINT8 *)CopyMem (Buffer, RawBuffer, RawBufferSize);\r
2558}\r
2559\r
2560/**\r
2561 Append opcodes from one OpCode Handle to another OpCode handle.\r
2562\r
2563 If OpCodeHandle is NULL, then ASSERT().\r
2564 If RawOpCodeHandle is NULL, then ASSERT();\r
2565\r
2566 @param[in] OpCodeHandle Handle to the buffer of opcodes.\r
2567 @param[in] RawOpCodeHandle Handle to the buffer of opcodes.\r
2568\r
2569 @retval NULL There is not enough space left in Buffer to add the opcode.\r
2570 @retval Other A pointer to the appended opcodes.\r
2571\r
2572**/\r
2573UINT8 *\r
2574EFIAPI\r
2575InternalHiiAppendOpCodes (\r
2576 IN VOID *OpCodeHandle,\r
2577 IN VOID *RawOpCodeHandle\r
2578 )\r
2579{\r
2580 HII_LIB_OPCODE_BUFFER *RawOpCodeBuffer;\r
2581\r
2582 ASSERT (RawOpCodeHandle != NULL);\r
2583\r
2584 RawOpCodeBuffer = (HII_LIB_OPCODE_BUFFER *)RawOpCodeHandle;\r
278663ab 2585 return HiiCreateRawOpCodes (OpCodeHandle, RawOpCodeBuffer->Buffer, RawOpCodeBuffer->Position);\r
7e3bcccb
LG
2586}\r
2587\r
2588/**\r
2589 Create EFI_IFR_END_OP opcode.\r
2590\r
2591 If OpCodeHandle is NULL, then ASSERT().\r
2592\r
2593 @param[in] OpCodeHandle Handle to the buffer of opcodes.\r
2594\r
2595 @retval NULL There is not enough space left in Buffer to add the opcode.\r
2596 @retval Other A pointer to the created opcode.\r
2597\r
2598**/\r
2599UINT8 *\r
2600EFIAPI\r
2601HiiCreateEndOpCode (\r
2602 IN VOID *OpCodeHandle\r
2603 )\r
2604{\r
2605 EFI_IFR_END OpCode;\r
2606\r
2607 return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_END_OP, sizeof (OpCode));\r
2608}\r
2609\r
2610/**\r
2611 Create EFI_IFR_ONE_OF_OPTION_OP opcode.\r
2612\r
2613 If OpCodeHandle is NULL, then ASSERT().\r
2614 If Type is invalid, then ASSERT().\r
2615 If Flags is invalid, then ASSERT().\r
2616\r
2617 @param[in] OpCodeHandle Handle to the buffer of opcodes.\r
2618 @param[in] StringId StringId for the option\r
2619 @param[in] Flags Flags for the option\r
2620 @param[in] Type Type for the option\r
2621 @param[in] Value Value for the option\r
2622\r
2623 @retval NULL There is not enough space left in Buffer to add the opcode.\r
2624 @retval Other A pointer to the created opcode.\r
2625\r
2626**/\r
2627UINT8 *\r
2628EFIAPI\r
2629HiiCreateOneOfOptionOpCode (\r
2630 IN VOID *OpCodeHandle,\r
2631 IN UINT16 StringId,\r
2632 IN UINT8 Flags,\r
2633 IN UINT8 Type,\r
2634 IN UINT64 Value\r
2635 )\r
2636{\r
2637 EFI_IFR_ONE_OF_OPTION OpCode;\r
2638\r
2639 ASSERT (Type < EFI_IFR_TYPE_OTHER);\r
2640\r
2641 ZeroMem (&OpCode, sizeof (OpCode));\r
2642 OpCode.Option = StringId;\r
2643 OpCode.Flags = (UINT8) (Flags & (EFI_IFR_OPTION_DEFAULT | EFI_IFR_OPTION_DEFAULT_MFG));\r
2644 OpCode.Type = Type;\r
2645 CopyMem (&OpCode.Value, &Value, mHiiDefaultTypeToWidth[Type]);\r
2646\r
2647 return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_ONE_OF_OPTION_OP, sizeof (OpCode));\r
2648}\r
2649\r
2650/**\r
2651 Create EFI_IFR_DEFAULT_OP opcode.\r
2652\r
2653 If OpCodeHandle is NULL, then ASSERT().\r
2654 If Type is invalid, then ASSERT().\r
2655\r
2656 @param[in] OpCodeHandle Handle to the buffer of opcodes.\r
2657 @param[in] DefaultId DefaultId for the default\r
2658 @param[in] Type Type for the default\r
2659 @param[in] Value Value for the default\r
2660\r
2661 @retval NULL There is not enough space left in Buffer to add the opcode.\r
2662 @retval Other A pointer to the created opcode.\r
2663\r
2664**/\r
2665UINT8 *\r
2666EFIAPI\r
2667HiiCreateDefaultOpCode (\r
2668 IN VOID *OpCodeHandle,\r
2669 IN UINT16 DefaultId,\r
2670 IN UINT8 Type,\r
2671 IN UINT64 Value\r
2672 )\r
2673{\r
2674 EFI_IFR_DEFAULT OpCode;\r
2675\r
2676 ASSERT (Type < EFI_IFR_TYPE_OTHER);\r
2677\r
2678 ZeroMem (&OpCode, sizeof (OpCode));\r
2679 OpCode.Type = Type;\r
2680 OpCode.DefaultId = DefaultId;\r
2681 CopyMem (&OpCode.Value, &Value, mHiiDefaultTypeToWidth[Type]);\r
2682\r
2683 return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_DEFAULT_OP, sizeof (OpCode));\r
2684}\r
2685\r
2686/**\r
2687 Create EFI_IFR_GUID opcode.\r
2688\r
2689 If OpCodeHandle is NULL, then ASSERT().\r
2690 If Guid is NULL, then ASSERT().\r
2691 If OpCodeSize < sizeof (EFI_IFR_GUID), then ASSERT().\r
2692\r
2693 @param[in] OpCodeHandle Handle to the buffer of opcodes.\r
2694 @param[in] Guid Pointer to EFI_GUID of this guided opcode.\r
2695 @param[in] GuidOpCode Pointer to an EFI_IFR_GUID opcode. This is an \r
2696 optional parameter that may be NULL. If this\r
2697 parameter is NULL, then the GUID extension \r
2698 region of the created opcode is filled with zeros.\r
2699 If this parameter is not NULL, then the GUID \r
2700 extension region of GuidData will be copied to \r
2701 the GUID extension region of the created opcode.\r
2702 @param[in] OpCodeSize The size, in bytes, of created opcode. This value \r
2703 must be >= sizeof(EFI_IFR_GUID).\r
2704\r
2705 @retval NULL There is not enough space left in Buffer to add the opcode.\r
2706 @retval Other A pointer to the created opcode.\r
2707\r
2708**/\r
2709UINT8 *\r
2710EFIAPI\r
2711HiiCreateGuidOpCode (\r
2712 IN VOID *OpCodeHandle,\r
2713 IN CONST EFI_GUID *Guid,\r
2714 IN CONST VOID *GuidOpCode, OPTIONAL\r
2715 IN UINTN OpCodeSize\r
2716 )\r
2717{\r
2718 EFI_IFR_GUID OpCode;\r
2719 EFI_IFR_GUID *OpCodePointer;\r
2720\r
2721 ASSERT (Guid != NULL);\r
2722 ASSERT (OpCodeSize >= sizeof (OpCode));\r
2723\r
2724 ZeroMem (&OpCode, sizeof (OpCode));\r
5c1ebff6 2725 CopyGuid ((EFI_GUID *)(VOID *)&OpCode.Guid, Guid);\r
7e3bcccb
LG
2726\r
2727 OpCodePointer = (EFI_IFR_GUID *)InternalHiiCreateOpCodeExtended (\r
2728 OpCodeHandle, \r
2729 &OpCode,\r
2730 EFI_IFR_GUID_OP,\r
2731 sizeof (OpCode),\r
2732 OpCodeSize - sizeof (OpCode),\r
2733 0\r
2734 );\r
2735 if (OpCodePointer != NULL && GuidOpCode != NULL) {\r
2736 CopyMem (OpCodePointer + 1, (EFI_IFR_GUID *)GuidOpCode + 1, OpCodeSize - sizeof (OpCode));\r
2737 }\r
2738 return (UINT8 *)OpCodePointer;\r
2739}\r
2740\r
2741/**\r
2742 Create EFI_IFR_ACTION_OP opcode.\r
2743\r
2744 If OpCodeHandle is NULL, then ASSERT().\r
2745 If any reserved bits are set in QuestionFlags, then ASSERT().\r
2746\r
2747 @param[in] OpCodeHandle Handle to the buffer of opcodes.\r
2748 @param[in] QuestionId Question ID\r
2749 @param[in] Prompt String ID for Prompt\r
2750 @param[in] Help String ID for Help\r
2751 @param[in] QuestionFlags Flags in Question Header\r
2752 @param[in] QuestionConfig String ID for configuration\r
2753\r
2754 @retval NULL There is not enough space left in Buffer to add the opcode.\r
2755 @retval Other A pointer to the created opcode.\r
2756\r
2757**/\r
2758UINT8 *\r
2759EFIAPI\r
2760HiiCreateActionOpCode (\r
2761 IN VOID *OpCodeHandle,\r
2762 IN EFI_QUESTION_ID QuestionId,\r
2763 IN EFI_STRING_ID Prompt,\r
2764 IN EFI_STRING_ID Help,\r
2765 IN UINT8 QuestionFlags,\r
2766 IN EFI_STRING_ID QuestionConfig\r
2767 )\r
2768{\r
2769 EFI_IFR_ACTION OpCode;\r
2770\r
2771 ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED | EFI_IFR_FLAG_OPTIONS_ONLY))) == 0);\r
2772\r
2773 ZeroMem (&OpCode, sizeof (OpCode));\r
2774 OpCode.Question.QuestionId = QuestionId;\r
2775 OpCode.Question.Header.Prompt = Prompt;\r
2776 OpCode.Question.Header.Help = Help;\r
2777 OpCode.Question.Flags = QuestionFlags;\r
2778 OpCode.QuestionConfig = QuestionConfig;\r
2779\r
2780 return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_ACTION_OP, sizeof (OpCode));\r
2781}\r
2782\r
2783/**\r
2784 Create EFI_IFR_SUBTITLE_OP opcode.\r
2785\r
2786 If OpCodeHandle is NULL, then ASSERT().\r
2787 If any reserved bits are set in Flags, then ASSERT().\r
2788 If Scope > 1, then ASSERT().\r
2789\r
2790 @param[in] OpCodeHandle Handle to the buffer of opcodes.\r
2791 @param[in] Prompt String ID for Prompt\r
2792 @param[in] Help String ID for Help\r
2793 @param[in] Flags Subtitle opcode flags\r
2794 @param[in] Scope 1 if this opcpde is the beginning of a new scope.\r
2795 0 if this opcode is within the current scope.\r
2796\r
2797 @retval NULL There is not enough space left in Buffer to add the opcode.\r
2798 @retval Other A pointer to the created opcode.\r
2799\r
2800**/\r
2801UINT8 *\r
2802EFIAPI\r
2803HiiCreateSubTitleOpCode (\r
2804 IN VOID *OpCodeHandle,\r
2805 IN EFI_STRING_ID Prompt,\r
2806 IN EFI_STRING_ID Help,\r
2807 IN UINT8 Flags,\r
2808 IN UINT8 Scope\r
2809 )\r
2810{\r
2811 EFI_IFR_SUBTITLE OpCode;\r
2812\r
2813 ASSERT (Scope <= 1);\r
2814 ASSERT ((Flags & (~(EFI_IFR_FLAGS_HORIZONTAL))) == 0);\r
2815\r
2816 ZeroMem (&OpCode, sizeof (OpCode));\r
2817 OpCode.Statement.Prompt = Prompt;\r
2818 OpCode.Statement.Help = Help;\r
2819 OpCode.Flags = Flags;\r
2820\r
2821 return InternalHiiCreateOpCodeExtended (\r
2822 OpCodeHandle, \r
2823 &OpCode,\r
2824 EFI_IFR_SUBTITLE_OP, \r
2825 sizeof (OpCode), \r
2826 0, \r
2827 Scope\r
2828 );\r
2829}\r
2830\r
2831/**\r
2832 Create EFI_IFR_REF_OP opcode.\r
2833\r
2834 If OpCodeHandle is NULL, then ASSERT().\r
2835 If any reserved bits are set in QuestionFlags, then ASSERT().\r
2836\r
2837 @param[in] OpCodeHandle Handle to the buffer of opcodes.\r
2838 @param[in] FormId Destination Form ID\r
2839 @param[in] Prompt String ID for Prompt\r
2840 @param[in] Help String ID for Help\r
2841 @param[in] QuestionFlags Flags in Question Header\r
2842 @param[in] QuestionId Question ID\r
2843\r
2844 @retval NULL There is not enough space left in Buffer to add the opcode.\r
2845 @retval Other A pointer to the created opcode.\r
2846\r
2847**/\r
2848UINT8 *\r
2849EFIAPI\r
2850HiiCreateGotoOpCode (\r
2851 IN VOID *OpCodeHandle,\r
2852 IN EFI_FORM_ID FormId,\r
2853 IN EFI_STRING_ID Prompt,\r
2854 IN EFI_STRING_ID Help,\r
2855 IN UINT8 QuestionFlags,\r
2856 IN EFI_QUESTION_ID QuestionId\r
2857 )\r
2858{\r
2859 EFI_IFR_REF OpCode;\r
2860\r
2861 ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED | EFI_IFR_FLAG_OPTIONS_ONLY))) == 0);\r
2862\r
2863 ZeroMem (&OpCode, sizeof (OpCode));\r
2864 OpCode.Question.Header.Prompt = Prompt;\r
2865 OpCode.Question.Header.Help = Help;\r
2866 OpCode.Question.QuestionId = QuestionId;\r
2867 OpCode.Question.Flags = QuestionFlags;\r
2868 OpCode.FormId = FormId;\r
2869\r
2870 return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_REF_OP, sizeof (OpCode));\r
2871}\r
2872\r
2873/**\r
2874 Create EFI_IFR_CHECKBOX_OP opcode.\r
2875\r
2876 If OpCodeHandle is NULL, then ASSERT().\r
2877 If any reserved bits are set in QuestionFlags, then ASSERT().\r
2878 If any reserved bits are set in CheckBoxFlags, then ASSERT().\r
2879\r
2880 @param[in] OpCodeHandle Handle to the buffer of opcodes.\r
2881 @param[in] QuestionId Question ID\r
2882 @param[in] VarStoreId Storage ID\r
2883 @param[in] VarOffset Offset in Storage\r
2884 @param[in] Prompt String ID for Prompt\r
2885 @param[in] Help String ID for Help\r
2886 @param[in] QuestionFlags Flags in Question Header\r
2887 @param[in] CheckBoxFlags Flags for checkbox opcode\r
2888 @param[in] DefaultsOpCodeHandle Handle for a buffer of DEFAULT opcodes. This\r
2889 is an optional parameter that may be NULL.\r
2890\r
2891 @retval NULL There is not enough space left in Buffer to add the opcode.\r
2892 @retval Other A pointer to the created opcode.\r
2893\r
2894**/\r
2895UINT8 *\r
2896EFIAPI\r
2897HiiCreateCheckBoxOpCode (\r
2898 IN VOID *OpCodeHandle,\r
2899 IN EFI_QUESTION_ID QuestionId,\r
2900 IN EFI_VARSTORE_ID VarStoreId,\r
2901 IN UINT16 VarOffset,\r
2902 IN EFI_STRING_ID Prompt,\r
2903 IN EFI_STRING_ID Help,\r
2904 IN UINT8 QuestionFlags,\r
2905 IN UINT8 CheckBoxFlags,\r
2906 IN VOID *DefaultsOpCodeHandle OPTIONAL\r
2907 )\r
2908{\r
2909 EFI_IFR_CHECKBOX OpCode;\r
2910 UINTN Position;\r
2911\r
2912 ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED | EFI_IFR_FLAG_OPTIONS_ONLY))) == 0);\r
2913\r
2914 ZeroMem (&OpCode, sizeof (OpCode));\r
2915 OpCode.Question.QuestionId = QuestionId;\r
2916 OpCode.Question.VarStoreId = VarStoreId;\r
2917 OpCode.Question.VarStoreInfo.VarOffset = VarOffset;\r
2918 OpCode.Question.Header.Prompt = Prompt;\r
2919 OpCode.Question.Header.Help = Help;\r
2920 OpCode.Question.Flags = QuestionFlags;\r
2921 OpCode.Flags = CheckBoxFlags;\r
2922\r
2923 if (DefaultsOpCodeHandle == NULL) {\r
2924 return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_CHECKBOX_OP, sizeof (OpCode));\r
2925 }\r
2926\r
2927 Position = InternalHiiOpCodeHandlePosition (OpCodeHandle);\r
2928 InternalHiiCreateOpCodeExtended (OpCodeHandle, &OpCode, EFI_IFR_CHECKBOX_OP, sizeof (OpCode), 0, 1);\r
2929 InternalHiiAppendOpCodes (OpCodeHandle, DefaultsOpCodeHandle);\r
2930 HiiCreateEndOpCode (OpCodeHandle);\r
2931 return InternalHiiOpCodeHandleBuffer (OpCodeHandle) + Position;\r
2932}\r
2933\r
2934/**\r
2935 Create EFI_IFR_NUMERIC_OP opcode.\r
2936\r
2937 If OpCodeHandle is NULL, then ASSERT().\r
2938 If any reserved bits are set in QuestionFlags, then ASSERT().\r
2939 If any reserved bits are set in NumericFlags, then ASSERT().\r
2940\r
2941 @param[in] OpCodeHandle Handle to the buffer of opcodes.\r
2942 @param[in] QuestionId Question ID\r
2943 @param[in] VarStoreId Storage ID\r
2944 @param[in] VarOffset Offset in Storage\r
2945 @param[in] Prompt String ID for Prompt\r
2946 @param[in] Help String ID for Help\r
2947 @param[in] QuestionFlags Flags in Question Header\r
2948 @param[in] NumericFlags Flags for numeric opcode\r
2949 @param[in] Minimum Numeric minimum value\r
2950 @param[in] Maximum Numeric maximum value\r
2951 @param[in] Step Numeric step for edit\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
2961HiiCreateNumericOpCode (\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 NumericFlags,\r
2970 IN UINT64 Minimum,\r
2971 IN UINT64 Maximum,\r
2972 IN UINT64 Step,\r
2973 IN VOID *DefaultsOpCodeHandle OPTIONAL\r
2974 )\r
2975{\r
2976 EFI_IFR_NUMERIC OpCode;\r
2977 UINTN Position;\r
2978\r
2979 ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED | EFI_IFR_FLAG_OPTIONS_ONLY))) == 0);\r
2980\r
2981 ZeroMem (&OpCode, sizeof (OpCode));\r
2982 OpCode.Question.QuestionId = QuestionId;\r
2983 OpCode.Question.VarStoreId = VarStoreId;\r
2984 OpCode.Question.VarStoreInfo.VarOffset = VarOffset;\r
2985 OpCode.Question.Header.Prompt = Prompt;\r
2986 OpCode.Question.Header.Help = Help;\r
2987 OpCode.Question.Flags = QuestionFlags;\r
2988 OpCode.Flags = NumericFlags;\r
2989\r
2990 switch (NumericFlags & EFI_IFR_NUMERIC_SIZE) {\r
2991 case EFI_IFR_NUMERIC_SIZE_1:\r
2992 OpCode.data.u8.MinValue = (UINT8)Minimum;\r
2993 OpCode.data.u8.MaxValue = (UINT8)Maximum;\r
2994 OpCode.data.u8.Step = (UINT8)Step;\r
2995 break;\r
2996\r
2997 case EFI_IFR_NUMERIC_SIZE_2:\r
2998 OpCode.data.u16.MinValue = (UINT16)Minimum;\r
2999 OpCode.data.u16.MaxValue = (UINT16)Maximum;\r
3000 OpCode.data.u16.Step = (UINT16)Step;\r
3001 break;\r
3002\r
3003 case EFI_IFR_NUMERIC_SIZE_4:\r
3004 OpCode.data.u32.MinValue = (UINT32)Minimum;\r
3005 OpCode.data.u32.MaxValue = (UINT32)Maximum;\r
3006 OpCode.data.u32.Step = (UINT32)Step;\r
3007 break;\r
3008\r
3009 case EFI_IFR_NUMERIC_SIZE_8:\r
3010 OpCode.data.u64.MinValue = Minimum;\r
3011 OpCode.data.u64.MaxValue = Maximum;\r
3012 OpCode.data.u64.Step = Step;\r
3013 break;\r
3014 }\r
3015\r
3016 if (DefaultsOpCodeHandle == NULL) {\r
3017 return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_NUMERIC_OP, sizeof (OpCode));\r
3018 }\r
3019\r
3020 Position = InternalHiiOpCodeHandlePosition (OpCodeHandle);\r
3021 InternalHiiCreateOpCodeExtended (OpCodeHandle, &OpCode, EFI_IFR_NUMERIC_OP, sizeof (OpCode), 0, 1);\r
3022 InternalHiiAppendOpCodes (OpCodeHandle, DefaultsOpCodeHandle);\r
3023 HiiCreateEndOpCode (OpCodeHandle);\r
3024 return InternalHiiOpCodeHandleBuffer (OpCodeHandle) + Position;\r
3025}\r
3026\r
3027/**\r
3028 Create EFI_IFR_STRING_OP opcode.\r
3029\r
3030 If OpCodeHandle is NULL, then ASSERT().\r
3031 If any reserved bits are set in QuestionFlags, then ASSERT().\r
3032 If any reserved bits are set in StringFlags, then ASSERT().\r
3033\r
3034 @param[in] OpCodeHandle Handle to the buffer of opcodes.\r
3035 @param[in] QuestionId Question ID\r
3036 @param[in] VarStoreId Storage ID\r
3037 @param[in] VarOffset Offset in Storage\r
3038 @param[in] Prompt String ID for Prompt\r
3039 @param[in] Help String ID for Help\r
3040 @param[in] QuestionFlags Flags in Question Header\r
3041 @param[in] StringFlags Flags for string opcode\r
3042 @param[in] MinSize String minimum length\r
3043 @param[in] MaxSize String maximum length\r
3044 @param[in] DefaultsOpCodeHandle Handle for a buffer of DEFAULT opcodes. This\r
3045 is an optional parameter that may be NULL.\r
3046\r
3047 @retval NULL There is not enough space left in Buffer to add the opcode.\r
3048 @retval Other A pointer to the created opcode.\r
3049\r
3050**/\r
3051UINT8 *\r
3052EFIAPI\r
3053HiiCreateStringOpCode (\r
3054 IN VOID *OpCodeHandle,\r
3055 IN EFI_QUESTION_ID QuestionId,\r
3056 IN EFI_VARSTORE_ID VarStoreId,\r
3057 IN UINT16 VarOffset,\r
3058 IN EFI_STRING_ID Prompt,\r
3059 IN EFI_STRING_ID Help,\r
3060 IN UINT8 QuestionFlags,\r
3061 IN UINT8 StringFlags,\r
3062 IN UINT8 MinSize,\r
3063 IN UINT8 MaxSize,\r
3064 IN VOID *DefaultsOpCodeHandle OPTIONAL\r
3065 )\r
3066{\r
3067 EFI_IFR_STRING OpCode;\r
3068 UINTN Position;\r
3069\r
3070 ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED | EFI_IFR_FLAG_OPTIONS_ONLY))) == 0);\r
3071\r
3072 ZeroMem (&OpCode, sizeof (OpCode));\r
3073 OpCode.Question.Header.Prompt = Prompt;\r
3074 OpCode.Question.Header.Help = Help;\r
3075 OpCode.Question.QuestionId = QuestionId;\r
3076 OpCode.Question.VarStoreId = VarStoreId;\r
3077 OpCode.Question.VarStoreInfo.VarOffset = VarOffset;\r
3078 OpCode.Question.Flags = QuestionFlags;\r
3079 OpCode.MinSize = MinSize;\r
3080 OpCode.MaxSize = MaxSize;\r
3081 OpCode.Flags = (UINT8) (StringFlags & EFI_IFR_STRING_MULTI_LINE);\r
3082\r
3083 if (DefaultsOpCodeHandle == NULL) {\r
3084 return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_STRING_OP, sizeof (OpCode));\r
3085 }\r
3086\r
3087 Position = InternalHiiOpCodeHandlePosition (OpCodeHandle);\r
3088 InternalHiiCreateOpCodeExtended (OpCodeHandle, &OpCode, EFI_IFR_STRING_OP, sizeof (OpCode), 0, 1);\r
3089 InternalHiiAppendOpCodes (OpCodeHandle, DefaultsOpCodeHandle);\r
3090 HiiCreateEndOpCode (OpCodeHandle);\r
3091 return InternalHiiOpCodeHandleBuffer (OpCodeHandle) + Position;\r
3092}\r
3093\r
3094/**\r
3095 Create EFI_IFR_ONE_OF_OP opcode.\r
3096\r
3097 If OpCodeHandle is NULL, then ASSERT().\r
3098 If any reserved bits are set in QuestionFlags, then ASSERT().\r
3099 If any reserved bits are set in OneOfFlags, then ASSERT().\r
3100\r
3101 @param[in] OpCodeHandle Handle to the buffer of opcodes.\r
3102 @param[in] QuestionId Question ID\r
3103 @param[in] VarStoreId Storage ID\r
3104 @param[in] VarOffset Offset in Storage\r
3105 @param[in] Prompt String ID for Prompt\r
3106 @param[in] Help String ID for Help\r
3107 @param[in] QuestionFlags Flags in Question Header\r
3108 @param[in] OneOfFlags Flags for oneof opcode\r
3109 @param[in] OptionsOpCodeHandle Handle for a buffer of ONE_OF_OPTION opcodes.\r
3110 @param[in] DefaultsOpCodeHandle Handle for a buffer of DEFAULT opcodes. This\r
3111 is an optional parameter that may be NULL.\r
3112\r
3113 @retval NULL There is not enough space left in Buffer to add the opcode.\r
3114 @retval Other A pointer to the created opcode.\r
3115\r
3116**/\r
3117UINT8 *\r
3118EFIAPI\r
3119HiiCreateOneOfOpCode (\r
3120 IN VOID *OpCodeHandle,\r
3121 IN EFI_QUESTION_ID QuestionId,\r
3122 IN EFI_VARSTORE_ID VarStoreId,\r
3123 IN UINT16 VarOffset,\r
3124 IN EFI_STRING_ID Prompt,\r
3125 IN EFI_STRING_ID Help,\r
3126 IN UINT8 QuestionFlags,\r
3127 IN UINT8 OneOfFlags,\r
3128 IN VOID *OptionsOpCodeHandle,\r
3129 IN VOID *DefaultsOpCodeHandle OPTIONAL\r
3130 )\r
3131{\r
3132 EFI_IFR_ONE_OF OpCode;\r
3133 UINTN Position;\r
3134\r
3135 ASSERT (OptionsOpCodeHandle != NULL);\r
3136 ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED | EFI_IFR_FLAG_OPTIONS_ONLY))) == 0);\r
3137\r
3138 ZeroMem (&OpCode, sizeof (OpCode));\r
3139 OpCode.Question.Header.Prompt = Prompt;\r
3140 OpCode.Question.Header.Help = Help;\r
3141 OpCode.Question.QuestionId = QuestionId;\r
3142 OpCode.Question.VarStoreId = VarStoreId;\r
3143 OpCode.Question.VarStoreInfo.VarOffset = VarOffset;\r
3144 OpCode.Question.Flags = QuestionFlags;\r
3145 OpCode.Flags = OneOfFlags;\r
3146\r
3147 Position = InternalHiiOpCodeHandlePosition (OpCodeHandle);\r
3148 InternalHiiCreateOpCodeExtended (OpCodeHandle, &OpCode, EFI_IFR_ONE_OF_OP, sizeof (OpCode), 0, 1);\r
3149 InternalHiiAppendOpCodes (OpCodeHandle, OptionsOpCodeHandle);\r
3150 if (DefaultsOpCodeHandle != NULL) {\r
3151 InternalHiiAppendOpCodes (OpCodeHandle, DefaultsOpCodeHandle);\r
3152 }\r
3153 HiiCreateEndOpCode (OpCodeHandle);\r
3154 return InternalHiiOpCodeHandleBuffer (OpCodeHandle) + Position;\r
3155}\r
3156\r
3157/**\r
3158 Create EFI_IFR_ORDERED_LIST_OP opcode.\r
3159\r
3160 If OpCodeHandle is NULL, then ASSERT().\r
3161 If any reserved bits are set in QuestionFlags, then ASSERT().\r
3162 If any reserved bits are set in OrderedListFlags, then ASSERT().\r
3163\r
3164 @param[in] OpCodeHandle Handle to the buffer of opcodes.\r
3165 @param[in] QuestionId Question ID\r
3166 @param[in] VarStoreId Storage ID\r
3167 @param[in] VarOffset Offset in Storage\r
3168 @param[in] Prompt String ID for Prompt\r
3169 @param[in] Help String ID for Help\r
3170 @param[in] QuestionFlags Flags in Question Header\r
3171 @param[in] OrderedListFlags Flags for ordered list opcode\r
3172 @param[in] DataType Type for option value\r
3173 @param[in] MaxContainers Maximum count for options in this ordered list\r
3174 @param[in] OptionsOpCodeHandle Handle for a buffer of ONE_OF_OPTION opcodes.\r
3175 @param[in] DefaultsOpCodeHandle Handle for a buffer of DEFAULT opcodes. This\r
3176 is an optional parameter that may be NULL.\r
3177\r
3178 @retval NULL There is not enough space left in Buffer to add the opcode.\r
3179 @retval Other A pointer to the created opcode.\r
3180\r
3181**/\r
3182UINT8 *\r
3183EFIAPI\r
3184HiiCreateOrderedListOpCode (\r
3185 IN VOID *OpCodeHandle,\r
3186 IN EFI_QUESTION_ID QuestionId,\r
3187 IN EFI_VARSTORE_ID VarStoreId,\r
3188 IN UINT16 VarOffset,\r
3189 IN EFI_STRING_ID Prompt,\r
3190 IN EFI_STRING_ID Help,\r
3191 IN UINT8 QuestionFlags,\r
3192 IN UINT8 OrderedListFlags,\r
3193 IN UINT8 DataType,\r
3194 IN UINT8 MaxContainers,\r
3195 IN VOID *OptionsOpCodeHandle,\r
3196 IN VOID *DefaultsOpCodeHandle OPTIONAL\r
3197 )\r
3198{\r
3199 EFI_IFR_ORDERED_LIST OpCode;\r
3200 UINTN Position;\r
3201\r
3202 ASSERT (OptionsOpCodeHandle != NULL);\r
3203 ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED | EFI_IFR_FLAG_OPTIONS_ONLY))) == 0);\r
3204\r
3205 ZeroMem (&OpCode, sizeof (OpCode));\r
3206 OpCode.Question.Header.Prompt = Prompt;\r
3207 OpCode.Question.Header.Help = Help;\r
3208 OpCode.Question.QuestionId = QuestionId;\r
3209 OpCode.Question.VarStoreId = VarStoreId;\r
3210 OpCode.Question.VarStoreInfo.VarOffset = VarOffset;\r
3211 OpCode.Question.Flags = QuestionFlags;\r
3212 OpCode.MaxContainers = MaxContainers;\r
3213 OpCode.Flags = OrderedListFlags;\r
3214\r
3215 Position = InternalHiiOpCodeHandlePosition (OpCodeHandle);\r
3216 InternalHiiCreateOpCodeExtended (OpCodeHandle, &OpCode, EFI_IFR_ORDERED_LIST_OP, sizeof (OpCode), 0, 1);\r
3217 InternalHiiAppendOpCodes (OpCodeHandle, OptionsOpCodeHandle);\r
3218 if (DefaultsOpCodeHandle != NULL) {\r
3219 InternalHiiAppendOpCodes (OpCodeHandle, DefaultsOpCodeHandle);\r
3220 }\r
3221 HiiCreateEndOpCode (OpCodeHandle);\r
3222 return InternalHiiOpCodeHandleBuffer (OpCodeHandle) + Position;\r
3223}\r
3224\r
3225/**\r
3226 This is the internal worker function to update the data in\r
3227 a form specified by FormSetGuid, FormId and Label.\r
3228\r
3229 @param FormSetGuid The optional Formset GUID.\r
3230 @param FormId The Form ID.\r
3231 @param Package The package header.\r
3232\r
3233 @param TempPacakge The resultant package.\r
3234\r
3235 @retval EFI_SUCCESS The function completes successfully.\r
3236\r
3237**/\r
3238EFI_STATUS\r
3239EFIAPI\r
3240InternalHiiUpdateFormPackageData (\r
3241 IN EFI_GUID *FormSetGuid, OPTIONAL\r
3242 IN EFI_FORM_ID FormId,\r
3243 IN EFI_HII_PACKAGE_HEADER *Package,\r
3244 IN HII_LIB_OPCODE_BUFFER *OpCodeBufferStart,\r
3245 IN HII_LIB_OPCODE_BUFFER *OpCodeBufferEnd, OPTIONAL\r
3246 OUT EFI_HII_PACKAGE_HEADER *TempPackage\r
3247 )\r
3248{\r
3249 UINTN AddSize;\r
3250 UINT8 *BufferPos;\r
3251 EFI_HII_PACKAGE_HEADER PackageHeader;\r
3252 UINTN Offset;\r
3253 EFI_IFR_OP_HEADER *IfrOpHdr;\r
3254 EFI_IFR_OP_HEADER *UpdateIfrOpHdr;\r
3255 BOOLEAN GetFormSet;\r
3256 BOOLEAN GetForm;\r
3257 BOOLEAN Updated;\r
d91c7bf9 3258 UINTN UpdatePackageLength;\r
7e3bcccb
LG
3259\r
3260 CopyMem (TempPackage, Package, sizeof (EFI_HII_PACKAGE_HEADER));\r
3261 UpdatePackageLength = sizeof (EFI_HII_PACKAGE_HEADER);\r
3262 BufferPos = (UINT8 *) (TempPackage + 1);\r
3263\r
3264 CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));\r
3265 IfrOpHdr = (EFI_IFR_OP_HEADER *)((UINT8 *) Package + sizeof (EFI_HII_PACKAGE_HEADER));\r
3266 Offset = sizeof (EFI_HII_PACKAGE_HEADER);\r
3267 GetFormSet = (BOOLEAN) ((FormSetGuid == NULL) ? TRUE : FALSE);\r
3268 GetForm = FALSE;\r
3269 Updated = FALSE;\r
3270\r
3271 while (Offset < PackageHeader.Length) {\r
3272 CopyMem (BufferPos, IfrOpHdr, IfrOpHdr->Length);\r
3273 BufferPos += IfrOpHdr->Length;\r
3274 UpdatePackageLength += IfrOpHdr->Length;\r
3275 \r
3276 //\r
3277 // Find the matched FormSet and Form\r
3278 //\r
3279 if ((IfrOpHdr->OpCode == EFI_IFR_FORM_SET_OP) && (FormSetGuid != NULL)) {\r
3280 if (CompareGuid((GUID *)(VOID *)&((EFI_IFR_FORM_SET *) IfrOpHdr)->Guid, FormSetGuid)) {\r
3281 GetFormSet = TRUE;\r
3282 } else {\r
3283 GetFormSet = FALSE;\r
3284 }\r
3285 } else if (IfrOpHdr->OpCode == EFI_IFR_FORM_OP) {\r
3286 if (CompareMem (&((EFI_IFR_FORM *) IfrOpHdr)->FormId, &FormId, sizeof (EFI_FORM_ID)) == 0) {\r
3287 GetForm = TRUE;\r
3288 } else {\r
3289 GetForm = FALSE;\r
3290 }\r
3291 }\r
3292 \r
3293 //\r
3294 // The matched Form is found, and Update data in this form\r
3295 //\r
d91c7bf9 3296 if (GetFormSet && GetForm) {\r
7e3bcccb
LG
3297 UpdateIfrOpHdr = (EFI_IFR_OP_HEADER *) OpCodeBufferStart->Buffer;\r
3298 if ((UpdateIfrOpHdr->Length == IfrOpHdr->Length) && \\r
3299 (CompareMem (IfrOpHdr, UpdateIfrOpHdr, UpdateIfrOpHdr->Length) == 0)) {\r
3300 //\r
3301 // Remove the original data when End OpCode buffer exist.\r
3302 //\r
3303 if (OpCodeBufferEnd != NULL) {\r
3304 Offset += IfrOpHdr->Length;\r
3305 IfrOpHdr = (EFI_IFR_OP_HEADER *) ((UINT8 *) (IfrOpHdr) + IfrOpHdr->Length);\r
3306 UpdateIfrOpHdr = (EFI_IFR_OP_HEADER *) OpCodeBufferEnd->Buffer;\r
3307 while (Offset < PackageHeader.Length) {\r
3308 //\r
3309 // Search the matched end opcode\r
3310 //\r
3311 if ((UpdateIfrOpHdr->Length == IfrOpHdr->Length) && \\r
3312 (CompareMem (IfrOpHdr, UpdateIfrOpHdr, UpdateIfrOpHdr->Length) == 0)) {\r
3313 break;\r
3314 }\r
3315 //\r
3316 // Go to the next Op-Code\r
3317 //\r
3318 Offset += IfrOpHdr->Length;\r
3319 IfrOpHdr = (EFI_IFR_OP_HEADER *) ((UINT8 *) (IfrOpHdr) + IfrOpHdr->Length);\r
3320 }\r
3321 \r
3322 if (Offset >= PackageHeader.Length) {\r
3323 //\r
3324 // The end opcode is not found.\r
3325 //\r
3326 return EFI_NOT_FOUND;\r
3327 }\r
3328 }\r
d91c7bf9 3329\r
7e3bcccb
LG
3330 //\r
3331 // Insert the updated data\r
3332 //\r
d91c7bf9
LG
3333 AddSize = ((EFI_IFR_OP_HEADER *) OpCodeBufferStart->Buffer)->Length;\r
3334 CopyMem (BufferPos, OpCodeBufferStart->Buffer + AddSize, OpCodeBufferStart->Position - AddSize);\r
3335 BufferPos += OpCodeBufferStart->Position - AddSize;\r
3336 UpdatePackageLength += OpCodeBufferStart->Position - AddSize;\r
b8215f46 3337\r
7e3bcccb
LG
3338 if (OpCodeBufferEnd != NULL) {\r
3339 //\r
3340 // Add the end opcode\r
3341 //\r
3342 CopyMem (BufferPos, IfrOpHdr, IfrOpHdr->Length);\r
3343 BufferPos += IfrOpHdr->Length;\r
3344 UpdatePackageLength += IfrOpHdr->Length;\r
3345 }\r
d91c7bf9
LG
3346\r
3347 //\r
3348 // Copy the left package data.\r
3349 //\r
3350 Offset += IfrOpHdr->Length;\r
3351 CopyMem (BufferPos, (UINT8 *) Package + Offset, PackageHeader.Length - Offset);\r
3352 UpdatePackageLength += PackageHeader.Length - Offset;\r
3353\r
7e3bcccb
LG
3354 //\r
3355 // Set update flag\r
3356 //\r
3357 Updated = TRUE;\r
d91c7bf9 3358 break;\r
7e3bcccb
LG
3359 }\r
3360 }\r
3361\r
3362 //\r
3363 // Go to the next Op-Code\r
3364 //\r
3365 Offset += IfrOpHdr->Length;\r
3366 IfrOpHdr = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (IfrOpHdr) + IfrOpHdr->Length);\r
3367 }\r
3368 \r
3369 if (!Updated) {\r
3370 //\r
3371 // The updated opcode buffer is not found.\r
3372 //\r
3373 return EFI_NOT_FOUND;\r
3374 }\r
3375 //\r
3376 // Update the package length.\r
3377 //\r
d91c7bf9 3378 PackageHeader.Length = (UINT32) UpdatePackageLength;\r
7e3bcccb
LG
3379 CopyMem (TempPackage, &PackageHeader, sizeof (EFI_HII_PACKAGE_HEADER));\r
3380\r
3381 return EFI_SUCCESS;\r
3382}\r
3383\r
3384/**\r
3385 This function updates a form that has previously been registered with the HII \r
3386 Database. This function will perform at most one update operation.\r
3387 \r
3388 The form to update is specified by Handle, FormSetGuid, and FormId. Binary \r
3389 comparisons of IFR opcodes are performed from the beginning of the form being \r
3390 updated until an IFR opcode is found that exactly matches the first IFR opcode \r
3391 specifed by StartOpCodeHandle. The following rules are used to determine if\r
3392 an insert, replace, or delete operation is performed.\r
3393 \r
3394 1) If no matches are found, then NULL is returned. \r
3395 2) If a match is found, and EndOpCodeHandle is NULL, then all of the IFR opcodes\r
3396 from StartOpcodeHandle except the first opcode are inserted immediately after \r
3397 the matching IFR opcode in the form beng updated.\r
3398 3) If a match is found, and EndOpCodeHandle is not NULL, then a search is made \r
3399 from the matching IFR opcode until an IFR opcode exatly matches the first \r
3400 IFR opcode specified by EndOpCodeHandle. If no match is found for the first\r
3401 IFR opcode specified by EndOpCodeHandle, then NULL is returned. If a match\r
3402 is found, then all of the IFR opcodes between the start match and the end \r
3403 match are deleted from the form being updated and all of the IFR opcodes\r
3404 from StartOpcodeHandle except the first opcode are inserted immediately after \r
3405 the matching start IFR opcode. If StartOpCcodeHandle only contains one\r
3406 IFR instruction, then the result of ths operation will delete all of the IFR\r
3407 opcodes between the start end matches.\r
3408\r
3409 If HiiHandle is NULL, then ASSERT().\r
3410 If StartOpCodeHandle is NULL, then ASSERT().\r
3411\r
3412 @param[in] HiiHandle The HII Handle of the form to update.\r
3413 @param[in] FormSetGuid The Formset GUID of the form to update. This\r
3414 is an optional parameter that may be NULL.\r
3415 If it is NULL, all FormSet will be updated.\r
3416 @param[in] FormId The ID of the form to update.\r
3417 @param[in] StartOpCodeHandle An OpCode Handle that contains the set of IFR \r
3418 opcodes to be inserted or replaced in the form.\r
3419 The first IFR instruction in StartOpCodeHandle \r
3420 is used to find matching IFR opcode in the \r
3421 form. \r
3422 @param[in] EndOpCodeHandle An OpCcode Handle that contains the IFR opcode\r
3423 that marks the end of a replace operation in\r
3424 the form. This is an optional parameter that\r
3425 may be NULL. If it is NULL, then an the IFR\r
3426 opcodes specified by StartOpCodeHandle are \r
3427 inserted into the form.\r
3428 \r
3429 @retval EFI_OUT_OF_RESOURCES No enough memory resource is allocated.\r
3430 @retval EFI_NOT_FOUND The following cases will return EFI_NOT_FOUND.\r
3431 1) The form specified by HiiHandle, FormSetGuid, \r
3432 and FormId could not be found in the HII Database.\r
3433 2) No IFR opcodes in the target form match the first\r
3434 IFR opcode in StartOpCodeHandle.\r
3435 3) EndOpCOde is not NULL, and no IFR opcodes in the \r
3436 target form following a matching start opcode match \r
3437 the first IFR opcode in EndOpCodeHandle.\r
3438 @retval EFI_SUCCESS The matched form is updated by StartOpcode.\r
3439\r
3440**/\r
3441EFI_STATUS\r
3442EFIAPI\r
3443HiiUpdateForm (\r
3444 IN EFI_HII_HANDLE HiiHandle, \r
3445 IN EFI_GUID *FormSetGuid, OPTIONAL\r
3446 IN EFI_FORM_ID FormId,\r
3447 IN VOID *StartOpcodeHandle,\r
3448 IN VOID *EndOpcodeHandle OPTIONAL\r
3449 )\r
3450{\r
3451 EFI_STATUS Status;\r
3452 EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;\r
3453 UINT32 PackageListLength; \r
3454 UINT32 Offset;\r
3455 EFI_HII_PACKAGE_LIST_HEADER *UpdatePackageList;\r
3456 UINTN BufferSize;\r
3457 UINT8 *UpdateBufferPos;\r
3458 EFI_HII_PACKAGE_HEADER *Package;\r
3459 EFI_HII_PACKAGE_HEADER *TempPacakge;\r
3460 EFI_HII_PACKAGE_HEADER PackageHeader;\r
3461 BOOLEAN Updated;\r
3462 HII_LIB_OPCODE_BUFFER *OpCodeBufferStart;\r
3463 HII_LIB_OPCODE_BUFFER *OpCodeBufferEnd;\r
3464 \r
3465 //\r
3466 // Input update data can't be NULL.\r
3467 //\r
3468 ASSERT (HiiHandle != NULL);\r
3469 ASSERT (StartOpcodeHandle != NULL);\r
3470 UpdatePackageList = NULL;\r
3471 TempPacakge = NULL;\r
3472 HiiPackageList = NULL;\r
3473 \r
3474 //\r
3475 // Restrive buffer data from Opcode Handle\r
3476 //\r
3477 OpCodeBufferStart = (HII_LIB_OPCODE_BUFFER *) StartOpcodeHandle;\r
3478 OpCodeBufferEnd = (HII_LIB_OPCODE_BUFFER *) EndOpcodeHandle;\r
3479 \r
3480 //\r
3481 // Get the orginal package list\r
3482 //\r
3483 BufferSize = 0;\r
3484 HiiPackageList = NULL;\r
3485 Status = gHiiDatabase->ExportPackageLists (gHiiDatabase, HiiHandle, &BufferSize, HiiPackageList);\r
3486 //\r
3487 // The return status should always be EFI_BUFFER_TOO_SMALL as input buffer's size is 0.\r
3488 //\r
3489 if (Status != EFI_BUFFER_TOO_SMALL) {\r
3490 return Status;\r
3491 }\r
3492\r
3493 HiiPackageList = AllocatePool (BufferSize);\r
3494 if (HiiPackageList == NULL) {\r
3495 Status = EFI_OUT_OF_RESOURCES;\r
3496 goto Finish;\r
3497 }\r
3498\r
3499 Status = gHiiDatabase->ExportPackageLists (gHiiDatabase, HiiHandle, &BufferSize, HiiPackageList);\r
3500 if (EFI_ERROR (Status)) {\r
3501 goto Finish;\r
3502 }\r
3503\r
3504 //\r
3505 // Calculate and allocate space for retrieval of IFR data\r
3506 //\r
3507 BufferSize += OpCodeBufferStart->Position;\r
3508 UpdatePackageList = AllocateZeroPool (BufferSize);\r
3509 if (UpdatePackageList == NULL) {\r
3510 Status = EFI_OUT_OF_RESOURCES;\r
3511 goto Finish;\r
3512 }\r
3513 \r
3514 //\r
3515 // Allocate temp buffer to store the temp updated package buffer\r
3516 //\r
3517 TempPacakge = AllocateZeroPool (BufferSize);\r
3518 if (TempPacakge == NULL) {\r
3519 Status = EFI_OUT_OF_RESOURCES;\r
3520 goto Finish;\r
3521 }\r
3522\r
3523 UpdateBufferPos = (UINT8 *) UpdatePackageList;\r
3524\r
3525 //\r
3526 // Copy the package list header\r
3527 //\r
3528 CopyMem (UpdateBufferPos, HiiPackageList, sizeof (EFI_HII_PACKAGE_LIST_HEADER));\r
3529 UpdateBufferPos += sizeof (EFI_HII_PACKAGE_LIST_HEADER);\r
3530 \r
3531 //\r
3532 // Go through each package to find the matched pacakge and update one by one\r
3533 //\r
3534 Updated = FALSE;\r
3535 Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);\r
3536 PackageListLength = ReadUnaligned32 (&HiiPackageList->PackageLength);\r
3537 while (Offset < PackageListLength) {\r
3538 Package = (EFI_HII_PACKAGE_HEADER *) (((UINT8 *) HiiPackageList) + Offset);\r
3539 CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));\r
3540 Offset += Package->Length;\r
3541\r
3542 if (Package->Type == EFI_HII_PACKAGE_FORMS) {\r
3543 //\r
3544 // Check this package is the matched package.\r
3545 //\r
3546 Status = InternalHiiUpdateFormPackageData (FormSetGuid, FormId, Package, OpCodeBufferStart, OpCodeBufferEnd, TempPacakge);\r
3547 //\r
3548 // The matched package is found. Its pacakge buffer will be updated by the input new data.\r
3549 //\r
3550 if (!EFI_ERROR(Status)) {\r
3551 //\r
3552 // Set Update Flag\r
3553 // \r
3554 Updated = TRUE;\r
3555 //\r
3556 // Add updated package buffer\r
3557 //\r
3558 Package = TempPacakge;\r
3559 }\r
3560 }\r
3561\r
3562 //\r
3563 // Add pacakge buffer\r
3564 //\r
3565 CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));\r
3566 CopyMem (UpdateBufferPos, Package, PackageHeader.Length);\r
3567 UpdateBufferPos += PackageHeader.Length;\r
3568 }\r
3569 \r
3570 if (Updated) {\r
3571 //\r
3572 // Update package list length\r
3573 //\r
3574 BufferSize = UpdateBufferPos - (UINT8 *) UpdatePackageList;\r
3575 WriteUnaligned32 (&UpdatePackageList->PackageLength, (UINT32) BufferSize);\r
3576 \r
3577 //\r
3578 // Update Pacakge to show form\r
3579 //\r
3580 Status = gHiiDatabase->UpdatePackageList (gHiiDatabase, HiiHandle, UpdatePackageList);\r
3581 } else {\r
3582 //\r
3583 // Not matched form is found and updated.\r
3584 //\r
3585 Status = EFI_NOT_FOUND;\r
3586 }\r
3587\r
3588Finish:\r
3589 if (HiiPackageList != NULL) {\r
3590 FreePool (HiiPackageList);\r
3591 }\r
3592 \r
3593 if (UpdatePackageList != NULL) {\r
3594 FreePool (UpdatePackageList);\r
3595 }\r
3596 \r
3597 if (TempPacakge != NULL) {\r
3598 FreePool (TempPacakge);\r
3599 }\r
3600\r
3601 return Status; \r
3602}\r