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