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