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