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