]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Library/UefiHiiLib/HiiLib.c
HII Library Class interface refine.
[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
7e3bcccb
LG
17//\r
18// <ConfigHdr> Template\r
19//\r
20GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR16 mConfigHdrTemplate[] = L"GUID=00000000000000000000000000000000&NAME=0000&PATH=00";\r
08e4b3cf 21\r
cb7d01c0 22EFI_FORM_BROWSER2_PROTOCOL *mUefiFormBrowser2 = NULL;\r
23\r
7e3bcccb 24//\r
cb7d01c0 25// Template used to mark the end of a list of packages \r
7e3bcccb 26//\r
cb7d01c0 27GLOBAL_REMOVE_IF_UNREFERENCED CONST EFI_HII_PACKAGE_HEADER mEndOfPakageList = {\r
28 sizeof (EFI_HII_PACKAGE_HEADER),\r
29 EFI_HII_PACKAGE_END\r
30};\r
08e4b3cf 31\r
32/**\r
cb7d01c0 33 Registers a list of packages in the HII Database and returns the HII Handle\r
34 associated with that registration. If an HII Handle has already been registered\r
35 with the same PackageListGuid, then NULL is returned. If there are not enough \r
36 resources to perform the registration, then NULL is returned. If an empty list \r
37 of packages is passed in, then NULL is returned. If the size of the list of \r
38 package is 0, then NULL is returned.\r
39\r
40 The variable arguments are pointers which point to package header that defined \r
41 by UEFI VFR compiler and StringGather tool.\r
08e4b3cf 42\r
43 #pragma pack (push, 1)\r
44 typedef struct {\r
45 UINT32 BinaryLength;\r
46 EFI_HII_PACKAGE_HEADER PackageHeader;\r
47 } EDKII_AUTOGEN_PACKAGES_HEADER;\r
48 #pragma pack (pop)\r
cb7d01c0 49 \r
50 @param[in] PackageListGuid The GUID of the package list.\r
51 @param[in] DeviceHandle If not NULL, the Device Handle on which \r
52 an instance of DEVICE_PATH_PROTOCOL is installed.\r
53 This Device Handle uniquely defines the device that \r
54 the added packages are associated with.\r
55 @param[in] ... The variable argument list that contains pointers \r
56 to packages terminated by a NULL.\r
57\r
58 @retval NULL A HII Handle has already been registered in the HII Database with\r
59 the same PackageListGuid.\r
60 @retval NULL The HII Handle could not be created.\r
61 @retval NULL An empty list of packages was passed in.\r
62 @retval NULL All packages are empty.\r
63 @retval Other The HII Handle associated with the newly registered package list.\r
08e4b3cf 64\r
65**/\r
cb7d01c0 66EFI_HII_HANDLE\r
67EFIAPI\r
68HiiAddPackages (\r
69 IN CONST EFI_GUID *PackageListGuid,\r
70 IN EFI_HANDLE DeviceHandle OPTIONAL,\r
71 ...\r
08e4b3cf 72 )\r
73{\r
cb7d01c0 74 EFI_STATUS Status;\r
75 EFI_HII_HANDLE *HiiHandleBuffer;\r
76 VA_LIST Args;\r
77 UINT32 *Package;\r
78 EFI_HII_PACKAGE_LIST_HEADER *PackageListHeader;\r
79 EFI_HII_HANDLE HiiHandle;\r
80 UINT32 Length;\r
81 UINT8 *Data;\r
08e4b3cf 82\r
cb7d01c0 83 ASSERT (PackageListGuid != NULL);\r
08e4b3cf 84\r
85 //\r
cb7d01c0 86 // Check to see if an HII Handle has already been registered with the same \r
87 // PackageListGuid\r
08e4b3cf 88 //\r
cb7d01c0 89 HiiHandleBuffer = HiiGetHiiHandles (PackageListGuid);\r
90 if (HiiHandleBuffer != NULL) {\r
91 FreePool (HiiHandleBuffer);\r
92 return NULL;\r
08e4b3cf 93 }\r
94\r
95 //\r
cb7d01c0 96 // Calculate the length of all the packages in the variable argument list\r
08e4b3cf 97 //\r
cb7d01c0 98 for (Length = 0, VA_START (Args, DeviceHandle); (Package = VA_ARG (Args, UINT32 *)) != NULL; ) {\r
99 Length += (ReadUnaligned32 (Package) - sizeof (UINT32));\r
100 }\r
101 VA_END (Args);\r
08e4b3cf 102\r
08e4b3cf 103 //\r
cb7d01c0 104 // If there are no packages in the variable argument list or all the packages \r
105 // are empty, then return a NULL HII Handle\r
08e4b3cf 106 //\r
cb7d01c0 107 if (Length == 0) {\r
108 return NULL;\r
08e4b3cf 109 }\r
110\r
111 //\r
cb7d01c0 112 // Add the length of the Package List Header and the terminating Package Header \r
08e4b3cf 113 //\r
cb7d01c0 114 Length += sizeof (EFI_HII_PACKAGE_LIST_HEADER) + sizeof (EFI_HII_PACKAGE_HEADER);\r
08e4b3cf 115\r
cb7d01c0 116 //\r
117 // Allocate the storage for the entire Package List\r
118 //\r
119 PackageListHeader = AllocateZeroPool (Length);\r
08e4b3cf 120\r
cb7d01c0 121 //\r
122 // If the Packahge List can not be allocated, then return a NULL HII Handle\r
123 //\r
124 if (PackageListHeader == NULL) {\r
125 return NULL;\r
126 }\r
08e4b3cf 127\r
cb7d01c0 128 //\r
129 // Fill in the GUID and Length of the Package List Header\r
130 //\r
131 CopyGuid (&PackageListHeader->PackageListGuid, PackageListGuid);\r
132 PackageListHeader->PackageLength = Length;\r
08e4b3cf 133\r
cb7d01c0 134 //\r
135 // Initialize a pointer to the beginning if the Package List data\r
136 //\r
137 Data = (UINT8 *)(PackageListHeader + 1);\r
08e4b3cf 138\r
cb7d01c0 139 //\r
140 // Copy the data from each package in the variable argument list\r
141 //\r
142 for (VA_START (Args, DeviceHandle); (Package = VA_ARG (Args, UINT32 *)) != NULL; ) {\r
143 Length = ReadUnaligned32 (Package) - sizeof (UINT32);\r
144 CopyMem (Data, Package + 1, Length);\r
145 Data += Length;\r
146 }\r
147 VA_END (Args);\r
08e4b3cf 148\r
cb7d01c0 149 //\r
150 // Append a package of type EFI_HII_PACKAGE_END to mark the end of the package list\r
151 //\r
152 CopyMem (Data, &mEndOfPakageList, sizeof (mEndOfPakageList));\r
08e4b3cf 153\r
cb7d01c0 154 //\r
155 // Register the package list with the HII Database\r
156 //\r
157 Status = gHiiDatabase->NewPackageList (\r
158 gHiiDatabase, \r
159 PackageListHeader, \r
160 DeviceHandle, \r
161 &HiiHandle\r
162 );\r
163 if (EFI_ERROR (Status)) {\r
164 HiiHandle = NULL;\r
08e4b3cf 165 }\r
166\r
cb7d01c0 167 //\r
168 // Free the allocated package list\r
169 //\r
08e4b3cf 170 FreePool (PackageListHeader);\r
cb7d01c0 171\r
172 //\r
173 // Return the new HII Handle\r
174 //\r
175 return HiiHandle;\r
08e4b3cf 176}\r
177\r
178/**\r
cb7d01c0 179 Removes a package list from the HII database.\r
08e4b3cf 180\r
181 If HiiHandle is NULL, then ASSERT.\r
cb7d01c0 182 If HiiHandle is not a valid EFI_HII_HANDLE in the HII database, then ASSERT.\r
08e4b3cf 183\r
cb7d01c0 184 @param[in] HiiHandle The handle that was previously registered in the HII database\r
08e4b3cf 185\r
186**/\r
187VOID\r
188EFIAPI\r
cb7d01c0 189HiiRemovePackages (\r
08e4b3cf 190 IN EFI_HII_HANDLE HiiHandle\r
191 )\r
192{\r
193 EFI_STATUS Status;\r
08e4b3cf 194\r
cb7d01c0 195 ASSERT (HiiHandle != NULL);\r
7e3bcccb 196 Status = gHiiDatabase->RemovePackageList (gHiiDatabase, HiiHandle);\r
08e4b3cf 197 ASSERT_EFI_ERROR (Status);\r
198}\r
199\r
200\r
201/**\r
cb7d01c0 202 Retrieves the array of all the HII Handles or the HII handle of a specific\r
203 package list in the HII Database.\r
204 This array is terminated with a NULL HII Handle.\r
205 This function allocates the returned array using AllocatePool().\r
206 The caller is responsible for freeing the array with FreePool().\r
207\r
208 @param[in] PackageListGuid An optional parameter that is used to request \r
209 an HII Handle that is associatd with a specific\r
210 Package List GUID. If this parameter is NULL\r
211 then all the HII Handles in the HII Database\r
212 are returned. If this parameter is not NULL\r
213 then at most 1 HII Handle is returned.\r
214\r
215 @retval NULL No HII handles were found in the HII database\r
216 @retval NULL The array of HII Handles could not be retrieved\r
217 @retval Other A pointer to the NULL terminated array of HII Handles\r
08e4b3cf 218\r
219**/\r
cb7d01c0 220EFI_HII_HANDLE *\r
08e4b3cf 221EFIAPI\r
cb7d01c0 222HiiGetHiiHandles (\r
223 IN CONST EFI_GUID *PackageListGuid OPTIONAL\r
08e4b3cf 224 )\r
225{\r
cb7d01c0 226 EFI_STATUS Status;\r
227 UINTN HandleBufferLength;\r
228 EFI_HII_HANDLE TempHiiHandleBuffer;\r
229 EFI_HII_HANDLE *HiiHandleBuffer;\r
230 EFI_GUID Guid;\r
231 UINTN Index;\r
232\r
233 //\r
234 // Retrieve the size required for the buffer of all HII handles.\r
235 //\r
236 HandleBufferLength = 0;\r
237 Status = gHiiDatabase->ListPackageLists (\r
238 gHiiDatabase,\r
239 EFI_HII_PACKAGE_TYPE_ALL,\r
240 NULL,\r
241 &HandleBufferLength,\r
242 &TempHiiHandleBuffer\r
243 );\r
08e4b3cf 244\r
cb7d01c0 245 //\r
246 // If ListPackageLists() returns EFI_SUCCESS for a zero size, \r
247 // then there are no HII handles in the HII database. If ListPackageLists() \r
248 // returns an error other than EFI_BUFFER_TOO_SMALL, then there are no HII \r
249 // handles in the HII database.\r
250 //\r
251 if (Status != EFI_BUFFER_TOO_SMALL) {\r
252 //\r
253 // Return NULL if the size can not be retrieved, or if there are no HII \r
254 // handles in the HII Database\r
255 //\r
256 return NULL;\r
257 }\r
08e4b3cf 258\r
cb7d01c0 259 //\r
260 // Allocate the array of HII handles to hold all the HII Handles and a NULL terminator\r
261 //\r
262 HiiHandleBuffer = AllocateZeroPool (HandleBufferLength + sizeof (EFI_HII_HANDLE));\r
263 if (HiiHandleBuffer == NULL) {\r
264 //\r
265 // Return NULL if allocation fails.\r
266 //\r
267 return NULL;\r
268 }\r
08e4b3cf 269\r
270 //\r
cb7d01c0 271 // Retrieve the array of HII Handles in the HII Database\r
08e4b3cf 272 //\r
7e3bcccb 273 Status = gHiiDatabase->ListPackageLists (\r
cb7d01c0 274 gHiiDatabase,\r
275 EFI_HII_PACKAGE_TYPE_ALL,\r
276 NULL,\r
277 &HandleBufferLength,\r
278 HiiHandleBuffer\r
279 );\r
280 if (EFI_ERROR (Status)) {\r
281 //\r
282 // Free the buffer and return NULL if the HII handles can not be retrieved.\r
283 //\r
284 FreePool (HiiHandleBuffer);\r
285 return NULL;\r
fa7b3168 286 }\r
08e4b3cf 287\r
cb7d01c0 288 if (PackageListGuid == NULL) {\r
289 //\r
290 // Return the NULL terminated array of HII handles in the HII Database\r
291 //\r
292 return HiiHandleBuffer;\r
293 } else {\r
294 for (Index = 0; HiiHandleBuffer[Index] != NULL; Index++) {\r
295 Status = InternalHiiExtractGuidFromHiiHandle (HiiHandleBuffer[Index], &Guid);\r
296 ASSERT_EFI_ERROR (Status);\r
297 if (CompareGuid (&Guid, PackageListGuid)) {\r
298 HiiHandleBuffer[0] = HiiHandleBuffer[Index];\r
299 HiiHandleBuffer[1] = NULL;\r
300 return HiiHandleBuffer;\r
301 }\r
302 }\r
303 FreePool (HiiHandleBuffer);\r
304 return NULL;\r
305 }\r
08e4b3cf 306}\r
307\r
308/**\r
309 Extract Hii package list GUID for given HII handle.\r
310\r
cb7d01c0 311 If HiiHandle could not be found in the HII database, then ASSERT.\r
08e4b3cf 312 If Guid is NULL, then ASSERT.\r
313\r
314 @param Handle Hii handle\r
315 @param Guid Package list GUID\r
316\r
317 @retval EFI_SUCCESS Successfully extract GUID from Hii database.\r
318\r
319**/\r
320EFI_STATUS\r
321EFIAPI\r
cb7d01c0 322InternalHiiExtractGuidFromHiiHandle (\r
08e4b3cf 323 IN EFI_HII_HANDLE Handle,\r
324 OUT EFI_GUID *Guid\r
325 )\r
326{\r
327 EFI_STATUS Status;\r
328 UINTN BufferSize;\r
329 EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;\r
330\r
331 ASSERT (Guid != NULL);\r
cb7d01c0 332 ASSERT (Handle != NULL);\r
08e4b3cf 333\r
334 //\r
335 // Get HII PackageList\r
336 //\r
337 BufferSize = 0;\r
338 HiiPackageList = NULL;\r
339\r
7e3bcccb 340 Status = gHiiDatabase->ExportPackageLists (gHiiDatabase, Handle, &BufferSize, HiiPackageList);\r
08e4b3cf 341 ASSERT (Status != EFI_NOT_FOUND);\r
342 \r
343 if (Status == EFI_BUFFER_TOO_SMALL) {\r
344 HiiPackageList = AllocatePool (BufferSize);\r
345 ASSERT (HiiPackageList != NULL);\r
346\r
7e3bcccb 347 Status = gHiiDatabase->ExportPackageLists (gHiiDatabase, Handle, &BufferSize, HiiPackageList);\r
08e4b3cf 348 }\r
349 if (EFI_ERROR (Status)) {\r
350 FreePool (HiiPackageList);\r
351 return Status;\r
352 }\r
353\r
354 //\r
355 // Extract GUID\r
356 //\r
357 CopyGuid (Guid, &HiiPackageList->PackageListGuid);\r
358\r
359 FreePool (HiiPackageList);\r
360\r
361 return EFI_SUCCESS;\r
362}\r
363\r
7e3bcccb
LG
364/**\r
365 Converts all hex dtring characters in range ['A'..'F'] to ['a'..'f'] for \r
366 hex digits that appear between a '=' and a '&' in a config string.\r
367\r
368 If String is NULL, then ASSERT().\r
369\r
370 @param[in] String Pointer to a Null-terminated Unicode string.\r
371\r
372 @return Pointer to the Null-terminated Unicode result string.\r
373\r
374**/\r
375EFI_STRING\r
376EFIAPI\r
377InternalHiiLowerConfigString (\r
378 IN EFI_STRING ConfigString\r
379 )\r
380{\r
381 EFI_STRING String;\r
382 BOOLEAN Lower;\r
383\r
384 ASSERT (ConfigString != NULL);\r
385\r
386 //\r
387 // Convert all hex digits in range [A-F] in the configuration header to [a-f]\r
388 //\r
389 for (String = ConfigString, Lower = FALSE; *String != L'\0'; String++) {\r
390 if (*String == L'=') {\r
391 Lower = TRUE;\r
392 } else if (*String == L'&') {\r
393 Lower = FALSE;\r
3e3f86e0 394 } else if (Lower && *String >= L'A' && *String <= L'F') {\r
5c1ebff6 395 *String = (CHAR16) (*String - L'A' + L'a');\r
7e3bcccb
LG
396 }\r
397 }\r
398\r
399 return ConfigString;\r
400}\r
401\r
402/**\r
403 Uses the BlockToConfig() service of the Config Routing Protocol to \r
404 convert <ConfigRequest> and a buffer to a <ConfigResp>\r
405\r
406 If ConfigRequest is NULL, then ASSERT().\r
407 If Block is NULL, then ASSERT().\r
408\r
409 @param[in] ConfigRequest Pointer to a Null-terminated Unicode string.\r
410 @param[in] Block Pointer to a block of data.\r
411 @param[in] BlockSize The zie, in bytes, of Block.\r
412\r
413 @retval NULL The <ConfigResp> string could not be generated.\r
414 @retval Other Pointer to the Null-terminated Unicode <ConfigResp> string.\r
415\r
416**/\r
417EFI_STRING\r
418EFIAPI\r
419InternalHiiBlockToConfig (\r
420 IN CONST EFI_STRING ConfigRequest,\r
421 IN CONST UINT8 *Block,\r
422 IN UINTN BlockSize\r
423 )\r
424{\r
425 EFI_STATUS Status;\r
426 EFI_STRING ConfigResp;\r
427 CHAR16 *Progress;\r
428\r
429 ASSERT (ConfigRequest != NULL);\r
430 ASSERT (Block != NULL);\r
431\r
432 //\r
433 // Convert <ConfigRequest> to <ConfigResp>\r
434 //\r
435 Status = gHiiConfigRouting->BlockToConfig (\r
436 gHiiConfigRouting,\r
437 ConfigRequest,\r
438 Block,\r
439 BlockSize,\r
440 &ConfigResp,\r
441 &Progress\r
442 );\r
443 if (EFI_ERROR (Status)) {\r
444 return NULL;\r
445 }\r
446 return ConfigResp;\r
447}\r
448\r
449/**\r
450 Uses the ConfigToBlock() service of the Config Routing Protocol to \r
451 convert <ConfigResp> to a block. The block is allocated using\r
452 AllocatePool(). The caller is responsible for freeing the block\r
453 using FreePool().\r
454\r
455 If ConfigResp is NULL, then ASSERT().\r
456\r
457 @param[in] ConfigResp Pointer to a Null-terminated Unicode string.\r
458 @param[in] BufferSize Length in bytes of buffer to hold retrived data. \r
459\r
460 @retval NULL The block could not be generated..\r
461 @retval Other Pointer to the allocated block.\r
462\r
463**/\r
464UINT8 *\r
465EFIAPI\r
466InternalHiiConfigToBlock (\r
467 IN EFI_STRING ConfigResp,\r
468 IN UINTN BlockSize\r
469 )\r
470{\r
471 EFI_STATUS Status;\r
472 CHAR16 *Progress;\r
473 UINT8 *Block;\r
474\r
475 ASSERT (ConfigResp != NULL);\r
476\r
477 //\r
478 // Allocate a buffer to hold the <ConfigResp> conversion\r
479 //\r
480 Block = AllocateZeroPool (BlockSize);\r
481 if (Block == NULL) {\r
482 return NULL;\r
483 }\r
484\r
485 //\r
486 // Convert <ConfigResp> to a buffer\r
487 //\r
488 Status = gHiiConfigRouting->ConfigToBlock (\r
489 gHiiConfigRouting,\r
490 ConfigResp,\r
491 Block,\r
492 &BlockSize,\r
493 &Progress\r
494 );\r
495 if (EFI_ERROR (Status)) {\r
496 FreePool (Block);\r
497 return NULL;\r
498 }\r
499\r
500 //\r
501 // Return converted buffer\r
502 //\r
503 return Block;\r
504}\r
505\r
506/**\r
507 Uses the BrowserCallback() service of the Form Browser Protocol to retrieve \r
508 or set uncommitted data. If sata i being retrieved, then the buffer is \r
509 allocated using AllocatePool(). The caller is then responsible for freeing \r
510 the buffer using FreePool().\r
511\r
512 @param[in] VariableName Pointer to a Null-terminated Unicode string. This \r
513 is an optional parameter that may be NULL.\r
514 @param[in] VariableGuid Pointer to an EFI_GUID structure. This is an optional \r
515 parameter that may be NULL.\r
516 @param[in] SetResultsData If not NULL, then this parameter specified the buffer\r
517 of uncommited data to set. If this parameter is NULL,\r
518 then the caller is requesting to get the uncommited data\r
519 from the Form Browser.\r
520\r
521 @retval NULL The uncommitted data could not be retrieved.\r
522 @retval Other A pointer to a buffer containing the uncommitted data.\r
523\r
524**/\r
525EFI_STRING\r
526EFIAPI\r
527InternalHiiBrowserCallback (\r
528 IN CONST EFI_GUID *VariableGuid, OPTIONAL\r
529 IN CONST CHAR16 *VariableName, OPTIONAL\r
530 IN CONST EFI_STRING SetResultsData OPTIONAL\r
531 )\r
532{\r
533 EFI_STATUS Status;\r
534 UINTN ResultsDataSize;\r
535 EFI_STRING ResultsData;\r
536 CHAR16 TempResultsData;\r
537\r
538 //\r
539 // Locate protocols\r
540 //\r
3c7449e4
LG
541 if (mUefiFormBrowser2 == NULL) {\r
542 Status = gBS->LocateProtocol (&gEfiFormBrowser2ProtocolGuid, NULL, (VOID **) &mUefiFormBrowser2);\r
543 if (EFI_ERROR (Status) || mUefiFormBrowser2 == NULL) {\r
7e3bcccb
LG
544 return NULL;\r
545 }\r
546 }\r
547\r
548 ResultsDataSize = 0;\r
549\r
550 if (SetResultsData != NULL) {\r
551 //\r
552 // Request to to set data in the uncommitted browser state information\r
553 //\r
554 ResultsData = SetResultsData;\r
555 } else {\r
556 //\r
557 // Retrieve the length of the buffer required ResultsData from the Browser Callback\r
558 //\r
3c7449e4
LG
559 Status = mUefiFormBrowser2->BrowserCallback (\r
560 mUefiFormBrowser2,\r
7e3bcccb
LG
561 &ResultsDataSize,\r
562 &TempResultsData,\r
563 TRUE,\r
564 VariableGuid,\r
565 VariableName\r
566 );\r
567 if (Status != EFI_BUFFER_TOO_SMALL) {\r
568 return NULL;\r
569 }\r
570\r
571 //\r
572 // Allocate the ResultsData buffer\r
573 //\r
574 ResultsData = AllocateZeroPool (ResultsDataSize);\r
575 if (ResultsData == NULL) {\r
576 return NULL;\r
577 }\r
578 }\r
579\r
580 //\r
581 // Retrieve or set the ResultsData from the Browser Callback\r
582 //\r
3c7449e4
LG
583 Status = mUefiFormBrowser2->BrowserCallback (\r
584 mUefiFormBrowser2,\r
7e3bcccb
LG
585 &ResultsDataSize,\r
586 ResultsData,\r
587 (BOOLEAN)(SetResultsData == NULL),\r
588 VariableGuid,\r
589 VariableName\r
590 );\r
591 if (EFI_ERROR (Status)) {\r
592 return NULL;\r
593 }\r
594\r
595 return ResultsData;\r
596}\r
597\r
598/**\r
599 Allocates and returns a Null-terminated Unicode <ConfigHdr> string using routing \r
600 information that includes a GUID, an optional Unicode string name, and a device\r
601 path. The string returned is allocated with AllocatePool(). The caller is \r
602 responsible for freeing the allocated string with FreePool().\r
603 \r
604 The format of a <ConfigHdr> is as follows:\r
605\r
606 GUID=<HexCh>32&NAME=<Char>NameLength&PATH=<HexChar>DevicePathSize<Null>\r
607\r
608 @param[in] Guid Pointer to an EFI_GUID that is the routing information\r
609 GUID. Each of the 16 bytes in Guid is converted to \r
610 a 2 Unicode character hexidecimal string. This is \r
611 an optional parameter that may be NULL.\r
612 @param[in] Name Pointer to a Null-terminated Unicode string that is \r
613 the routing information NAME. This is an optional \r
614 parameter that may be NULL. Each 16-bit Unicode \r
615 character in Name is converted to a 4 character Unicode \r
616 hexidecimal string. \r
617 @param[in] DriverHandle The driver handle which supports a Device Path Protocol\r
618 that is the routing information PATH. Each byte of\r
619 the Device Path associated with DriverHandle is converted\r
620 to a 2 Unicode character hexidecimal string.\r
621\r
7e3bcccb
LG
622 @retval NULL DriverHandle does not support the Device Path Protocol.\r
623 @retval Other A pointer to the Null-terminate Unicode <ConfigHdr> string\r
624\r
625**/\r
626EFI_STRING\r
627EFIAPI\r
628HiiConstructConfigHdr (\r
629 IN CONST EFI_GUID *Guid, OPTIONAL\r
630 IN CONST CHAR16 *Name, OPTIONAL\r
631 IN EFI_HANDLE DriverHandle\r
632 )\r
633{\r
634 UINTN NameLength;\r
635 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
636 UINTN DevicePathSize;\r
637 CHAR16 *String;\r
638 CHAR16 *ReturnString;\r
639 UINTN Index;\r
640 UINT8 *Buffer;\r
641\r
642 //\r
643 // Compute the length of Name in Unicode characters. \r
644 // If Name is NULL, then the length is 0.\r
645 //\r
646 NameLength = 0;\r
647 if (Name != NULL) {\r
648 NameLength = StrLen (Name);\r
649 }\r
650\r
3e3f86e0
LG
651 DevicePath = NULL;\r
652 DevicePathSize = 0;\r
7e3bcccb
LG
653 //\r
654 // Retrieve DevicePath Protocol associated with DriverHandle\r
655 //\r
3e3f86e0
LG
656 if (DriverHandle != NULL) {\r
657 DevicePath = DevicePathFromHandle (DriverHandle);\r
658 if (DevicePath == NULL) {\r
659 return NULL;\r
660 }\r
661 //\r
662 // Compute the size of the device path in bytes\r
663 //\r
664 DevicePathSize = GetDevicePathSize (DevicePath);\r
7e3bcccb
LG
665 }\r
666\r
7e3bcccb
LG
667 //\r
668 // GUID=<HexCh>32&NAME=<Char>NameLength&PATH=<HexChar>DevicePathSize <Null>\r
669 // | 5 | sizeof (EFI_GUID) * 2 | 6 | NameStrLen*4 | 6 | DevicePathSize * 2 | 1 |\r
670 //\r
671 String = AllocateZeroPool ((5 + sizeof (EFI_GUID) * 2 + 6 + NameLength * 4 + 6 + DevicePathSize * 2 + 1) * sizeof (CHAR16));\r
672 if (String == NULL) {\r
673 return NULL;\r
674 }\r
675\r
676 //\r
677 // Start with L"GUID="\r
678 //\r
679 ReturnString = StrCpy (String, L"GUID=");\r
680 String += StrLen (String);\r
681\r
682 if (Guid != NULL) {\r
683 //\r
684 // Append Guid converted to <HexCh>32\r
685 //\r
686 for (Index = 0, Buffer = (UINT8 *)Guid; Index < sizeof (EFI_GUID); Index++) {\r
687 String += UnicodeValueToString (String, PREFIX_ZERO | RADIX_HEX, *(Buffer++), 2);\r
688 }\r
689 }\r
690 \r
691 //\r
692 // Append L"&NAME="\r
693 //\r
694 StrCpy (String, L"&NAME=");\r
695 String += StrLen (String);\r
696\r
697 if (Name != NULL) {\r
698 //\r
699 // Append Name converted to <Char>NameLength\r
700 //\r
701 for (; *Name != L'\0'; Name++) {\r
702 String += UnicodeValueToString (String, PREFIX_ZERO | RADIX_HEX, *Name, 4);\r
703 }\r
704 }\r
705\r
706 //\r
707 // Append L"&PATH="\r
708 //\r
709 StrCpy (String, L"&PATH=");\r
710 String += StrLen (String);\r
711\r
712 //\r
713 // Append the device path associated with DriverHandle converted to <HexChar>DevicePathSize\r
714 //\r
715 for (Index = 0, Buffer = (UINT8 *)DevicePath; Index < DevicePathSize; Index++) {\r
716 String += UnicodeValueToString (String, PREFIX_ZERO | RADIX_HEX, *(Buffer++), 2);\r
717 }\r
718\r
719 //\r
720 // Null terminate the Unicode string\r
721 //\r
722 *String = L'\0';\r
723\r
724 //\r
725 // Convert all hex digits in range [A-F] in the configuration header to [a-f]\r
726 //\r
727 return InternalHiiLowerConfigString (ReturnString);\r
728}\r
729\r
730/**\r
731 Allocates and returns a Null-terminated Unicode <ConfigAltResp> string.\r
732\r
733 If Guid is NULL, then ASSERT().\r
734 If Name is NULL, then ASSERT().\r
735 If BlockNameArray is NULL, then ASSERT().\r
736\r
737 @param[in] Guid GUID of the buffer storage.\r
738 @param[in] Name Name of the buffer storage.\r
739 @param[in] DriverHandle The DriverHandle that support a Device Path\r
740 Protocol. \r
741 @param[in] BufferStorage Content of the buffer storage.\r
742 @param[in] BufferStorageSize Length in bytes of the buffer storage.\r
743 @param[in] BlockNameArray Array generated by VFR compiler. This array\r
744 contains a UINT32 value that is the length\r
745 of BlockNameArray in bytes, followed by pairs\r
746 of 16-bit values that are the offset and length\r
747 values used to contruct a <ConfigRequest> string.\r
748 @param[in] ... A variable argument list that contains pairs of 16-bit\r
749 ALTCFG identifiers and pointers to DefaultValueArrays.\r
750 The variable argument list is terminated by a NULL \r
751 DefaultValueArray pointer. A DefaultValueArray \r
752 contains a UINT32 value that is the length, in bytes,\r
753 of the DefaultValueArray. The UINT32 length value \r
754 is followed by a series of records that contain\r
755 a 16-bit WIDTH value followed by a byte array with \r
756 WIDTH entries. The records must be parsed from\r
757 beginning to end until the UINT32 length limit\r
758 is reached. \r
759\r
760 @retval NULL There are not enough resources to process the request.\r
761 @retval NULL A <ConfigResp> could not be retrieved from the Config \r
762 Routing Protocol.\r
763 @retval Other A pointer to the Null-terminate Unicode <ConfigAltResp>\r
764 string.\r
765\r
766**/\r
767EFI_STRING\r
768EFIAPI\r
769HiiConstructConfigAltResp (\r
770 IN CONST EFI_GUID *Guid,\r
771 IN CONST CHAR16 *Name,\r
772 IN EFI_HANDLE DriverHandle,\r
773 IN CONST VOID *BufferStorage,\r
774 IN UINTN BufferStorageSize,\r
775 IN CONST VOID *BlockNameArray, \r
776 ...\r
777 )\r
778{\r
779 UINTN Length;\r
780 CHAR16 *String;\r
781 CHAR16 *ConfigHdr;\r
782 UINT8 *Buffer;\r
783 UINT8 *BufferEnd;\r
784 CHAR16 *ConfigRequest;\r
785 EFI_STRING ConfigResp;\r
786 EFI_STRING ConfigAltResp;\r
787 VA_LIST Args;\r
788 UINTN AltCfgId;\r
789 UINT16 Width;\r
5c1ebff6
LG
790 UINT16 OffsetValue;\r
791 UINT16 WidthValue;\r
7e3bcccb
LG
792\r
793 ASSERT (Guid != NULL);\r
794 ASSERT (Name != NULL);\r
795 ASSERT (BlockNameArray != NULL);\r
796\r
797 //\r
798 // Initialize local variables\r
799 //\r
800 ConfigHdr = NULL;\r
801 ConfigRequest = NULL; \r
802 ConfigResp = NULL;\r
803\r
804 //\r
805 // Construct <ConfigHdr> : "GUID=...&NAME=...&PATH=..."\r
806 //\r
807 ConfigHdr = HiiConstructConfigHdr (Guid, Name, DriverHandle);\r
808 if (ConfigHdr == NULL) {\r
809 goto Exit;\r
810 }\r
811\r
812 //\r
813 // Compute the length of the entire request starting with <ConfigHdr> and a \r
814 // Null-terminator\r
815 //\r
816 Length = StrLen (ConfigHdr) + 1;\r
817\r
818 //\r
819 // Determine the size <BlockName> Offset/Width pairs\r
820 //\r
821 Buffer = (UINT8 *)BlockNameArray;\r
822 BufferEnd = Buffer + ReadUnaligned32 ((UINT32 *)Buffer);\r
823 Buffer += sizeof (UINT32);\r
824\r
825 //\r
826 // Add <BlockName> length that is composed of one or more Offset/Width pairs\r
827 //\r
828 // <BlockName> ::= &OFFSET=1234&WIDTH=1234\r
829 // | 8 | 4 | 7 | 4 |\r
830 //\r
831 Length += (((BufferEnd - Buffer) / (sizeof (UINT16) + sizeof (UINT16))) * (8 + 4 + 7 + 4));\r
832\r
833 //\r
834 // Allocate buffer for the entire <ConfigRequest>\r
835 //\r
836 ConfigRequest = AllocateZeroPool (Length * sizeof (CHAR16));\r
837 if (ConfigRequest == NULL) {\r
838 goto Exit;\r
839 }\r
840 String = ConfigRequest;\r
841\r
842 //\r
843 // Start with <ConfigHdr>\r
844 //\r
845 StrCpy (String, ConfigHdr);\r
846 String += StrLen (String);\r
847\r
848 //\r
849 // Loop through all the Offset/Width pairs and append them to ConfigRequest\r
850 //\r
851 while (Buffer < BufferEnd) {\r
852 //\r
853 // Append &OFFSET=XXXX&WIDTH=YYYY\r
854 //\r
5c1ebff6
LG
855 OffsetValue = ReadUnaligned16 ((UINT16 *)Buffer);\r
856 WidthValue = ReadUnaligned16 ((UINT16 *)(Buffer + sizeof (UINT16)));\r
7e3bcccb
LG
857 UnicodeSPrint (\r
858 String, \r
859 (8 + 4 + 7 + 4) * sizeof (CHAR16), \r
860 L"&OFFSET=%04X&WIDTH=%04X", \r
5c1ebff6
LG
861 OffsetValue, \r
862 WidthValue\r
863 );\r
864\r
7e3bcccb
LG
865 String += StrLen (String);\r
866 Buffer += (sizeof (UINT16) + sizeof (UINT16));\r
867 }\r
868\r
869 //\r
870 // Get the <ConfigResp>\r
871 //\r
872 ConfigResp = InternalHiiBlockToConfig (ConfigRequest, BufferStorage, BufferStorageSize);\r
873 if (ConfigResp == NULL) {\r
874 goto Exit;\r
875 }\r
876\r
877 //\r
878 // Compute the length of the entire response starting with <ConfigResp> and a \r
879 // Null-terminator\r
880 //\r
881 Length = StrLen (ConfigResp) + 1;\r
882\r
883 //\r
884 // Add the length associated with each pair of variable argument parameters\r
885 //\r
886 VA_START (Args, BlockNameArray);\r
887 while (TRUE) {\r
888 AltCfgId = VA_ARG (Args, UINT16);\r
889 Buffer = VA_ARG (Args, UINT8 *);\r
890 if (Buffer == NULL) {\r
891 break;\r
892 }\r
893\r
894 //\r
895 // Add length for "&<ConfigHdr>&ALTCFG=XXXX"\r
896 // |1| StrLen (ConfigHdr) | 8 | 4 |\r
897 //\r
898 Length += (1 + StrLen (ConfigHdr) + 8 + 4);\r
899\r
900 BufferEnd = Buffer + ReadUnaligned32 ((UINT32 *)Buffer);\r
901 Buffer += sizeof (UINT32);\r
902 while (Buffer < BufferEnd) {\r
903 //\r
904 // Extract Width field\r
905 //\r
906 Width = ReadUnaligned16 ((UINT16 *)(Buffer + sizeof (UINT16)));\r
907\r
908 //\r
909 // Add length for "&OFFSET=XXXX&WIDTH=YYYY&VALUE=zzzzzzzzzzzz"\r
910 // | 8 | 4 | 7 | 4 | 7 | Width * 2 |\r
911 //\r
912 Length += (8 + 4 + 7 + 4 + 7 + Width * 2);\r
913\r
914 //\r
915 // Update Buffer to the next record\r
916 //\r
917 Buffer += (sizeof (UINT16) + sizeof (UINT16) + Width);\r
918 }\r
919 }\r
920 VA_END (Args);\r
921\r
922 //\r
923 // Allocate a buffer for the entire response\r
924 //\r
925 ConfigAltResp = AllocateZeroPool (Length * sizeof (CHAR16));\r
926 if (ConfigAltResp == NULL) {\r
927 goto Exit;\r
928 }\r
929 String = ConfigAltResp;\r
930\r
931 //\r
932 // Add <ConfigResp>\r
933 //\r
934 StrCpy (String, ConfigResp);\r
935 String += StrLen (String);\r
936\r
937 //\r
938 // Add <AltResp> for each pair of variable argument parameters\r
939 //\r
940 VA_START (Args, BlockNameArray);\r
941 while (TRUE) {\r
942 AltCfgId = VA_ARG (Args, UINT16);\r
943 Buffer = VA_ARG (Args, UINT8 *);\r
944 if (Buffer == NULL) {\r
945 break;\r
946 }\r
947\r
948 //\r
949 // Add <AltConfigHdr> of the form "&<ConfigHdr>&ALTCFG=XXXX"\r
950 // |1| StrLen (ConfigHdr) | 8 | 4 |\r
951 //\r
952 UnicodeSPrint (\r
953 String, \r
954 (1 + StrLen (ConfigHdr) + 8 + 4) * sizeof (CHAR16), \r
955 L"&%s&ALTCFG=%04X", \r
956 ConfigHdr, \r
957 AltCfgId\r
958 );\r
959 String += StrLen (String);\r
960\r
961 //\r
962 // Add <ConfigBody> ::= <ConfigElement>*\r
963 //\r
964 BufferEnd = Buffer + ReadUnaligned32 ((UINT32 *)Buffer);\r
965 Buffer += sizeof (UINT32);\r
966 while (Buffer < BufferEnd) {\r
967 //\r
968 // Extract Width field\r
969 //\r
970 Width = ReadUnaligned16 ((UINT16 *)(Buffer + sizeof (UINT16)));\r
971\r
972 //\r
973 // Add <BlockConfig>\r
974 //\r
975 UnicodeSPrint (\r
976 String, \r
977 (8 + 4 + 7 + 4 + 7 + Width * 2) * sizeof (CHAR16),\r
978 L"&OFFSET=%04X&WIDTH=%04X&VALUE=", \r
979 ReadUnaligned16 ((UINT16 *)Buffer), \r
980 Width\r
981 );\r
982 String += StrLen (String);\r
983\r
984 //\r
985 // Update Buffer to point to the value in the current record\r
986 //\r
987 Buffer += (sizeof (UINT16) + sizeof (UINT16));\r
988\r
989 //\r
990 // Convert Value to a hex string in "%x" format\r
991 // NOTE: This is in the opposite byte that GUID and PATH use\r
992 //\r
993 for (; Width > 0; Width--) {\r
994 String += UnicodeValueToString (String, PREFIX_ZERO | RADIX_HEX, Buffer[Width - 1], 2);\r
995 }\r
996 //\r
997 // Update Buffer to the next record\r
998 //\r
999 Buffer += Width;\r
1000 }\r
1001 }\r
1002 VA_END (Args);\r
1003\r
1004 //\r
1005 // Convert all hex digits in range [A-F] in the configuration header to [a-f]\r
1006 //\r
1007 return InternalHiiLowerConfigString (ConfigAltResp);\r
1008\r
1009Exit:\r
1010 if (ConfigHdr != NULL) {\r
1011 FreePool (ConfigHdr);\r
1012 }\r
1013 if (ConfigRequest != NULL) {\r
1014 FreePool (ConfigRequest);\r
1015 }\r
1016 if (ConfigResp != NULL) {\r
1017 FreePool (ConfigResp);\r
1018 }\r
1019\r
1020 return NULL;\r
1021}\r
1022\r
1023/**\r
1024 Determines if two values in config strings match.\r
1025\r
1026 Compares the substring between StartSearchString and StopSearchString in \r
1027 FirstString to the substring between StartSearchString and StopSearchString \r
1028 in SecondString. If the two substrings match, then TRUE is returned. If the\r
1029 two substrings do not match, then FALSE is returned.\r
1030\r
1031 If FirstString is NULL, then ASSERT().\r
1032 If SecondString is NULL, then ASSERT().\r
1033 If StartSearchString is NULL, then ASSERT().\r
1034 If StopSearchString is NULL, then ASSERT().\r
1035\r
1036 @param FirstString Pointer to the first Null-terminated Unicode string.\r
1037 @param SecondString Pointer to the second Null-terminated Unicode string.\r
1038 @param StartSearchString Pointer to the Null-terminated Unicode string that \r
1039 marks the start of the value string to compare.\r
1040 @param StopSearchString Pointer to the Null-terminated Unicode string that \r
1041 marks the end of the vakue string to compare.\r
1042\r
1043 @retval FALSE StartSearchString is not present in FirstString. \r
1044 @retval FALSE StartSearchString is not present in SecondString.\r
1045 @retval FALSE StopSearchString is not present in FirstString. \r
1046 @retval FALSE StopSearchString is not present in SecondString.\r
1047 @retval FALSE The length of the substring in FirstString is not the \r
1048 same length as the substring in SecondString.\r
1049 @retval FALSE The value string in FirstString does not matche the \r
1050 value string in SecondString.\r
1051 @retval TRUE The value string in FirstString matches the value \r
1052 string in SecondString.\r
1053\r
1054**/\r
1055BOOLEAN\r
1056EFIAPI\r
1057InternalHiiCompareSubString (\r
1058 IN CHAR16 *FirstString,\r
1059 IN CHAR16 *SecondString,\r
1060 IN CHAR16 *StartSearchString,\r
1061 IN CHAR16 *StopSearchString\r
1062 )\r
1063{\r
1064 CHAR16 *EndFirstString;\r
1065 CHAR16 *EndSecondString;\r
1066\r
1067 ASSERT (FirstString != NULL);\r
1068 ASSERT (SecondString != NULL);\r
1069 ASSERT (StartSearchString != NULL);\r
1070 ASSERT (StopSearchString != NULL);\r
1071\r
1072 FirstString = StrStr (FirstString, StartSearchString);\r
1073 if (FirstString == NULL) {\r
1074 return FALSE;\r
1075 }\r
1076\r
1077 SecondString = StrStr (SecondString, StartSearchString);\r
1078 if (SecondString == NULL) {\r
1079 return FALSE;\r
1080 }\r
1081\r
1082 EndFirstString = StrStr (FirstString, StopSearchString);\r
1083 if (EndFirstString == NULL) {\r
1084 return FALSE;\r
1085 }\r
1086\r
1087 EndSecondString = StrStr (SecondString, StopSearchString);\r
1088 if (EndSecondString == NULL) {\r
1089 return FALSE;\r
1090 }\r
1091\r
1092 if ((EndFirstString - FirstString) != (EndSecondString - SecondString)) {\r
1093 return FALSE;\r
1094 }\r
1095\r
1096 return (BOOLEAN)(StrnCmp (FirstString, SecondString, EndFirstString - FirstString) == 0);\r
1097}\r
1098\r
1099/**\r
1100 Determines if the routing data specified by GUID and NAME match a <ConfigHdr>.\r
1101\r
1102 If ConfigHdr is NULL, then ASSERT().\r
1103\r
1104 @param[in] ConfigHdr Either <ConfigRequest> or <ConfigResp>.\r
1105 @param[in] Guid GUID of the storage.\r
1106 @param[in] Name NAME of the storage.\r
1107\r
1108 @retval TRUE Routing information matches <ConfigHdr>.\r
1109 @retval FALSE Routing information does not match <ConfigHdr>.\r
1110\r
1111**/\r
1112BOOLEAN\r
1113EFIAPI\r
1114HiiIsConfigHdrMatch (\r
1115 IN CONST EFI_STRING ConfigHdr,\r
1116 IN CONST EFI_GUID *Guid, OPTIONAL\r
1117 IN CONST CHAR16 *Name OPTIONAL\r
1118 )\r
1119{\r
1120 EFI_STRING CompareConfigHdr;\r
1121 BOOLEAN Result;\r
1122\r
1123 ASSERT (ConfigHdr != NULL);\r
1124\r
1125 //\r
1126 // Use Guid and Name to generate a <ConfigHdr> string\r
1127 //\r
1128 CompareConfigHdr = HiiConstructConfigHdr (Guid, Name, NULL);\r
1129 if (CompareConfigHdr == NULL) {\r
1130 return FALSE;\r
1131 }\r
1132\r
1133 Result = TRUE;\r
1134 if (Guid != NULL) {\r
1135 //\r
1136 // Compare GUID value strings\r
1137 //\r
1138 Result = InternalHiiCompareSubString (ConfigHdr, CompareConfigHdr, L"GUID=", L"&NAME=");\r
1139 }\r
1140\r
1141 if (Result && Name != NULL) {\r
1142 //\r
1143 // Compare NAME value strings\r
1144 //\r
1145 Result = InternalHiiCompareSubString (ConfigHdr, CompareConfigHdr, L"&NAME=", L"&PATH=");\r
1146 }\r
1147\r
1148 //\r
1149 // Free the <ConfigHdr> string\r
1150 //\r
1151 FreePool (CompareConfigHdr);\r
1152\r
1153 return Result;\r
1154}\r
1155\r
1156/**\r
1157 Retrieves uncommited data from the Form Browser and converts it to a binary\r
1158 buffer. The returned buffer is allocated using AllocatePool(). The caller\r
1159 is responsible for freeing the returned buffer using FreePool().\r
1160\r
1161 @param[in] VariableName Pointer to a Null-terminated Unicode string. This \r
1162 is an optional parameter that may be NULL.\r
1163 @param[in] VariableGuid Pointer to an EFI_GUID structure. This is an optional \r
1164 parameter that may be NULL.\r
1165 @param[in] BufferSize Length in bytes of buffer to hold retrived data. \r
1166\r
1167 @retval NULL The uncommitted data could not be retrieved.\r
1168 @retval Other A pointer to a buffer containing the uncommitted data.\r
1169\r
1170**/\r
1171UINT8 *\r
1172EFIAPI\r
1173HiiGetBrowserData (\r
1174 IN CONST EFI_GUID *VariableGuid, OPTIONAL\r
1175 IN CONST CHAR16 *VariableName, OPTIONAL\r
1176 IN UINTN BlockSize\r
1177 )\r
1178{\r
1179 EFI_STRING ResultsData;\r
1180 UINTN Size;\r
1181 EFI_STRING ConfigResp;\r
1182 UINT8 *Block;\r
1183\r
1184 //\r
1185 // Retrieve the results data from the Browser Callback\r
1186 //\r
1187 ResultsData = InternalHiiBrowserCallback (VariableGuid, VariableName, NULL);\r
1188 if (ResultsData == NULL) {\r
1189 return NULL;\r
1190 }\r
1191\r
1192 //\r
5c1ebff6 1193 // Construct <ConfigResp> mConfigHdrTemplate L'&' ResultsData L'\0'\r
7e3bcccb 1194 //\r
5c1ebff6
LG
1195 Size = (StrLen (mConfigHdrTemplate) + 1) * sizeof (CHAR16);\r
1196 Size = Size + (StrLen (ResultsData) + 1) * sizeof (CHAR16);\r
7e3bcccb
LG
1197 ConfigResp = AllocateZeroPool (Size);\r
1198 UnicodeSPrint (ConfigResp, Size, L"%s&%s", mConfigHdrTemplate, ResultsData);\r
1199 \r
1200 //\r
1201 // Free the allocated buffer\r
1202 //\r
1203 FreePool (ResultsData);\r
1204 if (ConfigResp == NULL) {\r
1205 return NULL;\r
1206 }\r
1207\r
1208 //\r
1209 // Convert <ConfigResp> to a buffer\r
1210 //\r
1211 Block = InternalHiiConfigToBlock (ConfigResp, BlockSize);\r
1212 FreePool (ConfigResp);\r
1213\r
1214 return Block;\r
1215}\r
1216\r
1217/**\r
1218 Updates uncommitted data in the Form Browser.\r
1219\r
1220 If Buffer is NULL, then ASSERT().\r
1221\r
1222 @param[in] VariableName Pointer to a Null-terminated Unicode string. This\r
1223 is an optional parameter that may be NULL.\r
1224 @param[in] VariableGuid Pointer to an EFI_GUID structure. This is an optional\r
1225 parameter that may be NULL.\r
1226 @param[in] BufferSize Length, in bytes, of Buffer.\r
1227 @param[in] Buffer Buffer of data to commit.\r
1228 @param[in] RequestElement An optional field to specify which part of the\r
1229 buffer data will be send back to Browser. If NULL,\r
1230 the whole buffer of data will be committed to\r
1231 Browser. \r
1232 <RequestElement> ::= &OFFSET=<Number>&WIDTH=<Number>*\r
1233\r
1234 @retval FALSE The uncommitted data could not be updated.\r
1235 @retval TRUE The uncommitted data was updated.\r
1236\r
1237**/\r
1238BOOLEAN\r
1239EFIAPI\r
1240HiiSetBrowserData (\r
1241 IN CONST EFI_GUID *VariableGuid, OPTIONAL\r
1242 IN CONST CHAR16 *VariableName, OPTIONAL\r
1243 IN UINTN BufferSize,\r
1244 IN CONST UINT8 *Buffer,\r
1245 IN CONST CHAR16 *RequestElement OPTIONAL\r
1246 )\r
1247{\r
1248 UINTN Size;\r
1249 EFI_STRING ConfigRequest;\r
1250 EFI_STRING ConfigResp;\r
1251 EFI_STRING ResultsData;\r
1252\r
1253 ASSERT (Buffer != NULL);\r
1254\r
1255 //\r
1256 // Construct <ConfigRequest>\r
1257 //\r
1258 if (RequestElement == NULL) {\r
1259 //\r
1260 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template \r
1261 // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator\r
1262 //\r
1263 Size = (StrLen (mConfigHdrTemplate) + 32 + 1) * sizeof (CHAR16);\r
1264 ConfigRequest = AllocateZeroPool (Size);\r
1265 UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", mConfigHdrTemplate, (UINT64)BufferSize);\r
1266 } else {\r
1267 //\r
1268 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template \r
1269 // followed by <RequestElement> followed by a Null-terminator\r
1270 //\r
5c1ebff6
LG
1271 Size = StrLen (mConfigHdrTemplate) * sizeof (CHAR16);\r
1272 Size = Size + (StrLen (RequestElement) + 1) * sizeof (CHAR16);\r
7e3bcccb
LG
1273 ConfigRequest = AllocateZeroPool (Size);\r
1274 UnicodeSPrint (ConfigRequest, Size, L"%s%s", mConfigHdrTemplate, RequestElement);\r
1275 }\r
1276 if (ConfigRequest == NULL) {\r
1277 return FALSE;\r
1278 }\r
1279\r
1280 //\r
1281 // Convert <ConfigRequest> to <ConfigResp>\r
1282 //\r
1283 ConfigResp = InternalHiiBlockToConfig (ConfigRequest, Buffer, BufferSize);\r
1284 FreePool (ConfigRequest);\r
1285 if (ConfigResp == NULL) {\r
1286 return FALSE;\r
1287 }\r
1288\r
1289 //\r
1290 // Set data in the uncommitted browser state information\r
1291 //\r
1292 ResultsData = InternalHiiBrowserCallback (VariableGuid, VariableName, ConfigResp + StrLen(mConfigHdrTemplate) + 1);\r
1293 FreePool (ConfigResp);\r
1294\r
1295 return (BOOLEAN)(ResultsData != NULL);\r
1296}\r
1297\r
1298/////////////////////////////////////////\r
1299/////////////////////////////////////////\r
1300/// IFR Functions\r
1301/////////////////////////////////////////\r
1302/////////////////////////////////////////\r
1303\r
1304#define HII_LIB_OPCODE_ALLOCATION_SIZE 0x200\r
1305\r
1306typedef struct {\r
1307 UINT8 *Buffer;\r
1308 UINTN BufferSize;\r
1309 UINTN Position;\r
1310} HII_LIB_OPCODE_BUFFER;\r
1311\r
1312///\r
1313/// Lookup table that converts EFI_IFR_TYPE_X enum values to a width in bytes\r
1314///\r
1315GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 mHiiDefaultTypeToWidth[] = {\r
1316 1, // EFI_IFR_TYPE_NUM_SIZE_8\r
1317 2, // EFI_IFR_TYPE_NUM_SIZE_16\r
1318 4, // EFI_IFR_TYPE_NUM_SIZE_32\r
1319 8, // EFI_IFR_TYPE_NUM_SIZE_64\r
1320 1, // EFI_IFR_TYPE_BOOLEAN\r
1321 3, // EFI_IFR_TYPE_TIME\r
1322 4, // EFI_IFR_TYPE_DATE\r
1323 2 // EFI_IFR_TYPE_STRING\r
1324};\r
1325\r
1326/**\r
1327 Allocates and returns a new OpCode Handle. OpCode Handles must be freed with \r
1328 HiiFreeOpCodeHandle().\r
1329\r
1330 @retval NULL There are not enough resources to allocate a new OpCode Handle.\r
1331 @retval Other A new OpCode handle.\r
1332\r
1333**/\r
1334VOID *\r
1335EFIAPI\r
1336HiiAllocateOpCodeHandle (\r
1337 VOID\r
1338 )\r
1339{\r
1340 HII_LIB_OPCODE_BUFFER *OpCodeBuffer;\r
1341\r
1342 OpCodeBuffer = (HII_LIB_OPCODE_BUFFER *)AllocatePool (sizeof (HII_LIB_OPCODE_BUFFER));\r
1343 if (OpCodeBuffer == NULL) {\r
1344 return NULL;\r
1345 }\r
1346 OpCodeBuffer->Buffer = (UINT8 *)AllocatePool (HII_LIB_OPCODE_ALLOCATION_SIZE);\r
1347 if (OpCodeBuffer->Buffer == NULL) {\r
1348 FreePool (OpCodeBuffer);\r
1349 return NULL;\r
1350 }\r
1351 OpCodeBuffer->BufferSize = HII_LIB_OPCODE_ALLOCATION_SIZE;\r
1352 OpCodeBuffer->Position = 0;\r
1353 return (VOID *)OpCodeBuffer;\r
1354}\r
1355\r
1356/**\r
1357 Frees an OpCode Handle that was peviously allocated with HiiAllocateOpCodeHandle().\r
1358 When an OpCode Handle is freed, all of the opcodes associated with the OpCode\r
1359 Handle are also freed.\r
1360\r
1361 If OpCodeHandle is NULL, then ASSERT().\r
1362\r
1363**/\r
1364VOID\r
1365EFIAPI\r
1366HiiFreeOpCodeHandle (\r
1367 VOID *OpCodeHandle\r
1368 )\r
1369{\r
1370 HII_LIB_OPCODE_BUFFER *OpCodeBuffer;\r
1371\r
1372 ASSERT (OpCodeHandle != NULL);\r
1373\r
1374 OpCodeBuffer = (HII_LIB_OPCODE_BUFFER *)OpCodeHandle;\r
1375 if (OpCodeBuffer->Buffer != NULL) {\r
1376 FreePool (OpCodeBuffer->Buffer);\r
1377 }\r
1378 FreePool (OpCodeBuffer);\r
1379}\r
1380\r
1381UINTN\r
1382EFIAPI\r
1383InternalHiiOpCodeHandlePosition (\r
1384 IN VOID *OpCodeHandle\r
1385 )\r
1386{\r
1387 return ((HII_LIB_OPCODE_BUFFER *)OpCodeHandle)->Position;\r
1388}\r
1389\r
1390UINT8 *\r
1391EFIAPI\r
1392InternalHiiOpCodeHandleBuffer (\r
1393 IN VOID *OpCodeHandle\r
1394 )\r
1395{\r
1396 return ((HII_LIB_OPCODE_BUFFER *)OpCodeHandle)->Buffer;\r
1397}\r
1398\r
1399UINT8 *\r
1400EFIAPI\r
1401InternalHiiGrowOpCodeHandle (\r
1402 VOID *OpCodeHandle,\r
1403 UINTN Size\r
1404 )\r
1405{\r
1406 HII_LIB_OPCODE_BUFFER *OpCodeBuffer;\r
1407 UINT8 *Buffer;\r
1408\r
1409 ASSERT (OpCodeHandle != NULL);\r
1410\r
1411 OpCodeBuffer = (HII_LIB_OPCODE_BUFFER *)OpCodeHandle;\r
1412 if (OpCodeBuffer->Position + Size > OpCodeBuffer->BufferSize) {\r
1413 Buffer = ReallocatePool (\r
1414 OpCodeBuffer->BufferSize, \r
1415 OpCodeBuffer->BufferSize + (Size + HII_LIB_OPCODE_ALLOCATION_SIZE),\r
1416 OpCodeBuffer->Buffer\r
1417 );\r
1418 if (Buffer == NULL) {\r
1419 return NULL;\r
1420 }\r
1421 OpCodeBuffer->Buffer = Buffer;\r
1422 OpCodeBuffer->BufferSize += (Size + HII_LIB_OPCODE_ALLOCATION_SIZE);\r
1423 }\r
1424 Buffer = OpCodeBuffer->Buffer + OpCodeBuffer->Position;\r
1425 OpCodeBuffer->Position += Size;\r
1426 return Buffer;\r
1427}\r
1428\r
1429UINT8 *\r
1430EFIAPI\r
1431InternalHiiCreateOpCodeExtended (\r
1432 IN VOID *OpCodeHandle,\r
1433 IN VOID *OpCodeTemplate,\r
1434 IN UINT8 OpCode,\r
1435 IN UINTN OpCodeSize,\r
1436 IN UINTN ExtensionSize,\r
1437 IN UINT8 Scope\r
1438 )\r
1439{\r
1440 EFI_IFR_OP_HEADER *Header;\r
1441 UINT8 *Buffer;\r
1442\r
1443 ASSERT (OpCodeTemplate != NULL);\r
1444 ASSERT ((OpCodeSize + ExtensionSize) <= 0x7F);\r
1445\r
1446 Header = (EFI_IFR_OP_HEADER *)OpCodeTemplate;\r
1447 Header->OpCode = OpCode;\r
1448 Header->Scope = Scope;\r
1449 Header->Length = (UINT8)(OpCodeSize + ExtensionSize);\r
1450 Buffer = InternalHiiGrowOpCodeHandle (OpCodeHandle, Header->Length);\r
1451 return (UINT8 *)CopyMem (Buffer, Header, OpCodeSize);\r
1452}\r
1453\r
1454UINT8 *\r
1455EFIAPI\r
1456InternalHiiCreateOpCode (\r
1457 IN VOID *OpCodeHandle,\r
1458 IN VOID *OpCodeTemplate,\r
1459 IN UINT8 OpCode,\r
1460 IN UINTN OpCodeSize\r
1461 )\r
1462{\r
1463 return InternalHiiCreateOpCodeExtended (OpCodeHandle, OpCodeTemplate, OpCode, OpCodeSize, 0, 0);\r
1464}\r
1465\r
1466/**\r
1467 Append raw opcodes to an OpCodeHandle.\r
1468\r
1469 If OpCodeHandle is NULL, then ASSERT().\r
1470 If RawBuffer is NULL, then ASSERT();\r
1471\r
1472 @param[in] OpCodeHandle Handle to the buffer of opcodes.\r
1473 @param[in] RawBuffer Buffer of opcodes to append.\r
1474 @param[in] RawBufferSize The size, in bytes, of Buffer.\r
1475\r
1476 @retval NULL There is not enough space left in Buffer to add the opcode.\r
1477 @retval Other A pointer to the appended opcodes.\r
1478\r
1479**/\r
1480UINT8 *\r
1481EFIAPI\r
1482InternalHiiCreateRawOpCodes (\r
1483 IN VOID *OpCodeHandle,\r
1484 IN UINT8 *RawBuffer,\r
1485 IN UINTN RawBufferSize\r
1486 )\r
1487{\r
1488 UINT8 *Buffer;\r
1489\r
1490 ASSERT (RawBuffer != NULL);\r
1491\r
1492 Buffer = InternalHiiGrowOpCodeHandle (OpCodeHandle, RawBufferSize);\r
1493 return (UINT8 *)CopyMem (Buffer, RawBuffer, RawBufferSize);\r
1494}\r
1495\r
1496/**\r
1497 Append opcodes from one OpCode Handle to another OpCode handle.\r
1498\r
1499 If OpCodeHandle is NULL, then ASSERT().\r
1500 If RawOpCodeHandle is NULL, then ASSERT();\r
1501\r
1502 @param[in] OpCodeHandle Handle to the buffer of opcodes.\r
1503 @param[in] RawOpCodeHandle Handle to the buffer of opcodes.\r
1504\r
1505 @retval NULL There is not enough space left in Buffer to add the opcode.\r
1506 @retval Other A pointer to the appended opcodes.\r
1507\r
1508**/\r
1509UINT8 *\r
1510EFIAPI\r
1511InternalHiiAppendOpCodes (\r
1512 IN VOID *OpCodeHandle,\r
1513 IN VOID *RawOpCodeHandle\r
1514 )\r
1515{\r
1516 HII_LIB_OPCODE_BUFFER *RawOpCodeBuffer;\r
1517\r
1518 ASSERT (RawOpCodeHandle != NULL);\r
1519\r
1520 RawOpCodeBuffer = (HII_LIB_OPCODE_BUFFER *)RawOpCodeHandle;\r
1521 return InternalHiiCreateRawOpCodes (OpCodeHandle, RawOpCodeBuffer->Buffer, RawOpCodeBuffer->Position);\r
1522}\r
1523\r
1524/**\r
1525 Create EFI_IFR_END_OP opcode.\r
1526\r
1527 If OpCodeHandle is NULL, then ASSERT().\r
1528\r
1529 @param[in] OpCodeHandle Handle to the buffer of opcodes.\r
1530\r
1531 @retval NULL There is not enough space left in Buffer to add the opcode.\r
1532 @retval Other A pointer to the created opcode.\r
1533\r
1534**/\r
1535UINT8 *\r
1536EFIAPI\r
1537HiiCreateEndOpCode (\r
1538 IN VOID *OpCodeHandle\r
1539 )\r
1540{\r
1541 EFI_IFR_END OpCode;\r
1542\r
1543 return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_END_OP, sizeof (OpCode));\r
1544}\r
1545\r
1546/**\r
1547 Create EFI_IFR_ONE_OF_OPTION_OP opcode.\r
1548\r
1549 If OpCodeHandle is NULL, then ASSERT().\r
1550 If Type is invalid, then ASSERT().\r
1551 If Flags is invalid, then ASSERT().\r
1552\r
1553 @param[in] OpCodeHandle Handle to the buffer of opcodes.\r
1554 @param[in] StringId StringId for the option\r
1555 @param[in] Flags Flags for the option\r
1556 @param[in] Type Type for the option\r
1557 @param[in] Value Value for the option\r
1558\r
1559 @retval NULL There is not enough space left in Buffer to add the opcode.\r
1560 @retval Other A pointer to the created opcode.\r
1561\r
1562**/\r
1563UINT8 *\r
1564EFIAPI\r
1565HiiCreateOneOfOptionOpCode (\r
1566 IN VOID *OpCodeHandle,\r
1567 IN UINT16 StringId,\r
1568 IN UINT8 Flags,\r
1569 IN UINT8 Type,\r
1570 IN UINT64 Value\r
1571 )\r
1572{\r
1573 EFI_IFR_ONE_OF_OPTION OpCode;\r
1574\r
1575 ASSERT (Type < EFI_IFR_TYPE_OTHER);\r
1576\r
1577 ZeroMem (&OpCode, sizeof (OpCode));\r
1578 OpCode.Option = StringId;\r
1579 OpCode.Flags = (UINT8) (Flags & (EFI_IFR_OPTION_DEFAULT | EFI_IFR_OPTION_DEFAULT_MFG));\r
1580 OpCode.Type = Type;\r
1581 CopyMem (&OpCode.Value, &Value, mHiiDefaultTypeToWidth[Type]);\r
1582\r
1583 return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_ONE_OF_OPTION_OP, sizeof (OpCode));\r
1584}\r
1585\r
1586/**\r
1587 Create EFI_IFR_DEFAULT_OP opcode.\r
1588\r
1589 If OpCodeHandle is NULL, then ASSERT().\r
1590 If Type is invalid, then ASSERT().\r
1591\r
1592 @param[in] OpCodeHandle Handle to the buffer of opcodes.\r
1593 @param[in] DefaultId DefaultId for the default\r
1594 @param[in] Type Type for the default\r
1595 @param[in] Value Value for the default\r
1596\r
1597 @retval NULL There is not enough space left in Buffer to add the opcode.\r
1598 @retval Other A pointer to the created opcode.\r
1599\r
1600**/\r
1601UINT8 *\r
1602EFIAPI\r
1603HiiCreateDefaultOpCode (\r
1604 IN VOID *OpCodeHandle,\r
1605 IN UINT16 DefaultId,\r
1606 IN UINT8 Type,\r
1607 IN UINT64 Value\r
1608 )\r
1609{\r
1610 EFI_IFR_DEFAULT OpCode;\r
1611\r
1612 ASSERT (Type < EFI_IFR_TYPE_OTHER);\r
1613\r
1614 ZeroMem (&OpCode, sizeof (OpCode));\r
1615 OpCode.Type = Type;\r
1616 OpCode.DefaultId = DefaultId;\r
1617 CopyMem (&OpCode.Value, &Value, mHiiDefaultTypeToWidth[Type]);\r
1618\r
1619 return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_DEFAULT_OP, sizeof (OpCode));\r
1620}\r
1621\r
1622/**\r
1623 Create EFI_IFR_GUID opcode.\r
1624\r
1625 If OpCodeHandle is NULL, then ASSERT().\r
1626 If Guid is NULL, then ASSERT().\r
1627 If OpCodeSize < sizeof (EFI_IFR_GUID), then ASSERT().\r
1628\r
1629 @param[in] OpCodeHandle Handle to the buffer of opcodes.\r
1630 @param[in] Guid Pointer to EFI_GUID of this guided opcode.\r
1631 @param[in] GuidOpCode Pointer to an EFI_IFR_GUID opcode. This is an \r
1632 optional parameter that may be NULL. If this\r
1633 parameter is NULL, then the GUID extension \r
1634 region of the created opcode is filled with zeros.\r
1635 If this parameter is not NULL, then the GUID \r
1636 extension region of GuidData will be copied to \r
1637 the GUID extension region of the created opcode.\r
1638 @param[in] OpCodeSize The size, in bytes, of created opcode. This value \r
1639 must be >= sizeof(EFI_IFR_GUID).\r
1640\r
1641 @retval NULL There is not enough space left in Buffer to add the opcode.\r
1642 @retval Other A pointer to the created opcode.\r
1643\r
1644**/\r
1645UINT8 *\r
1646EFIAPI\r
1647HiiCreateGuidOpCode (\r
1648 IN VOID *OpCodeHandle,\r
1649 IN CONST EFI_GUID *Guid,\r
1650 IN CONST VOID *GuidOpCode, OPTIONAL\r
1651 IN UINTN OpCodeSize\r
1652 )\r
1653{\r
1654 EFI_IFR_GUID OpCode;\r
1655 EFI_IFR_GUID *OpCodePointer;\r
1656\r
1657 ASSERT (Guid != NULL);\r
1658 ASSERT (OpCodeSize >= sizeof (OpCode));\r
1659\r
1660 ZeroMem (&OpCode, sizeof (OpCode));\r
5c1ebff6 1661 CopyGuid ((EFI_GUID *)(VOID *)&OpCode.Guid, Guid);\r
7e3bcccb
LG
1662\r
1663 OpCodePointer = (EFI_IFR_GUID *)InternalHiiCreateOpCodeExtended (\r
1664 OpCodeHandle, \r
1665 &OpCode,\r
1666 EFI_IFR_GUID_OP,\r
1667 sizeof (OpCode),\r
1668 OpCodeSize - sizeof (OpCode),\r
1669 0\r
1670 );\r
1671 if (OpCodePointer != NULL && GuidOpCode != NULL) {\r
1672 CopyMem (OpCodePointer + 1, (EFI_IFR_GUID *)GuidOpCode + 1, OpCodeSize - sizeof (OpCode));\r
1673 }\r
1674 return (UINT8 *)OpCodePointer;\r
1675}\r
1676\r
1677/**\r
1678 Create EFI_IFR_ACTION_OP opcode.\r
1679\r
1680 If OpCodeHandle is NULL, then ASSERT().\r
1681 If any reserved bits are set in QuestionFlags, then ASSERT().\r
1682\r
1683 @param[in] OpCodeHandle Handle to the buffer of opcodes.\r
1684 @param[in] QuestionId Question ID\r
1685 @param[in] Prompt String ID for Prompt\r
1686 @param[in] Help String ID for Help\r
1687 @param[in] QuestionFlags Flags in Question Header\r
1688 @param[in] QuestionConfig String ID for configuration\r
1689\r
1690 @retval NULL There is not enough space left in Buffer to add the opcode.\r
1691 @retval Other A pointer to the created opcode.\r
1692\r
1693**/\r
1694UINT8 *\r
1695EFIAPI\r
1696HiiCreateActionOpCode (\r
1697 IN VOID *OpCodeHandle,\r
1698 IN EFI_QUESTION_ID QuestionId,\r
1699 IN EFI_STRING_ID Prompt,\r
1700 IN EFI_STRING_ID Help,\r
1701 IN UINT8 QuestionFlags,\r
1702 IN EFI_STRING_ID QuestionConfig\r
1703 )\r
1704{\r
1705 EFI_IFR_ACTION OpCode;\r
1706\r
1707 ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED | EFI_IFR_FLAG_OPTIONS_ONLY))) == 0);\r
1708\r
1709 ZeroMem (&OpCode, sizeof (OpCode));\r
1710 OpCode.Question.QuestionId = QuestionId;\r
1711 OpCode.Question.Header.Prompt = Prompt;\r
1712 OpCode.Question.Header.Help = Help;\r
1713 OpCode.Question.Flags = QuestionFlags;\r
1714 OpCode.QuestionConfig = QuestionConfig;\r
1715\r
1716 return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_ACTION_OP, sizeof (OpCode));\r
1717}\r
1718\r
1719/**\r
1720 Create EFI_IFR_SUBTITLE_OP opcode.\r
1721\r
1722 If OpCodeHandle is NULL, then ASSERT().\r
1723 If any reserved bits are set in Flags, then ASSERT().\r
1724 If Scope > 1, then ASSERT().\r
1725\r
1726 @param[in] OpCodeHandle Handle to the buffer of opcodes.\r
1727 @param[in] Prompt String ID for Prompt\r
1728 @param[in] Help String ID for Help\r
1729 @param[in] Flags Subtitle opcode flags\r
1730 @param[in] Scope 1 if this opcpde is the beginning of a new scope.\r
1731 0 if this opcode is within the current scope.\r
1732\r
1733 @retval NULL There is not enough space left in Buffer to add the opcode.\r
1734 @retval Other A pointer to the created opcode.\r
1735\r
1736**/\r
1737UINT8 *\r
1738EFIAPI\r
1739HiiCreateSubTitleOpCode (\r
1740 IN VOID *OpCodeHandle,\r
1741 IN EFI_STRING_ID Prompt,\r
1742 IN EFI_STRING_ID Help,\r
1743 IN UINT8 Flags,\r
1744 IN UINT8 Scope\r
1745 )\r
1746{\r
1747 EFI_IFR_SUBTITLE OpCode;\r
1748\r
1749 ASSERT (Scope <= 1);\r
1750 ASSERT ((Flags & (~(EFI_IFR_FLAGS_HORIZONTAL))) == 0);\r
1751\r
1752 ZeroMem (&OpCode, sizeof (OpCode));\r
1753 OpCode.Statement.Prompt = Prompt;\r
1754 OpCode.Statement.Help = Help;\r
1755 OpCode.Flags = Flags;\r
1756\r
1757 return InternalHiiCreateOpCodeExtended (\r
1758 OpCodeHandle, \r
1759 &OpCode,\r
1760 EFI_IFR_SUBTITLE_OP, \r
1761 sizeof (OpCode), \r
1762 0, \r
1763 Scope\r
1764 );\r
1765}\r
1766\r
1767/**\r
1768 Create EFI_IFR_REF_OP opcode.\r
1769\r
1770 If OpCodeHandle is NULL, then ASSERT().\r
1771 If any reserved bits are set in QuestionFlags, then ASSERT().\r
1772\r
1773 @param[in] OpCodeHandle Handle to the buffer of opcodes.\r
1774 @param[in] FormId Destination Form ID\r
1775 @param[in] Prompt String ID for Prompt\r
1776 @param[in] Help String ID for Help\r
1777 @param[in] QuestionFlags Flags in Question Header\r
1778 @param[in] QuestionId Question ID\r
1779\r
1780 @retval NULL There is not enough space left in Buffer to add the opcode.\r
1781 @retval Other A pointer to the created opcode.\r
1782\r
1783**/\r
1784UINT8 *\r
1785EFIAPI\r
1786HiiCreateGotoOpCode (\r
1787 IN VOID *OpCodeHandle,\r
1788 IN EFI_FORM_ID FormId,\r
1789 IN EFI_STRING_ID Prompt,\r
1790 IN EFI_STRING_ID Help,\r
1791 IN UINT8 QuestionFlags,\r
1792 IN EFI_QUESTION_ID QuestionId\r
1793 )\r
1794{\r
1795 EFI_IFR_REF OpCode;\r
1796\r
1797 ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED | EFI_IFR_FLAG_OPTIONS_ONLY))) == 0);\r
1798\r
1799 ZeroMem (&OpCode, sizeof (OpCode));\r
1800 OpCode.Question.Header.Prompt = Prompt;\r
1801 OpCode.Question.Header.Help = Help;\r
1802 OpCode.Question.QuestionId = QuestionId;\r
1803 OpCode.Question.Flags = QuestionFlags;\r
1804 OpCode.FormId = FormId;\r
1805\r
1806 return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_REF_OP, sizeof (OpCode));\r
1807}\r
1808\r
1809/**\r
1810 Create EFI_IFR_CHECKBOX_OP opcode.\r
1811\r
1812 If OpCodeHandle is NULL, then ASSERT().\r
1813 If any reserved bits are set in QuestionFlags, then ASSERT().\r
1814 If any reserved bits are set in CheckBoxFlags, then ASSERT().\r
1815\r
1816 @param[in] OpCodeHandle Handle to the buffer of opcodes.\r
1817 @param[in] QuestionId Question ID\r
1818 @param[in] VarStoreId Storage ID\r
1819 @param[in] VarOffset Offset in Storage\r
1820 @param[in] Prompt String ID for Prompt\r
1821 @param[in] Help String ID for Help\r
1822 @param[in] QuestionFlags Flags in Question Header\r
1823 @param[in] CheckBoxFlags Flags for checkbox opcode\r
1824 @param[in] DefaultsOpCodeHandle Handle for a buffer of DEFAULT opcodes. This\r
1825 is an optional parameter that may be NULL.\r
1826\r
1827 @retval NULL There is not enough space left in Buffer to add the opcode.\r
1828 @retval Other A pointer to the created opcode.\r
1829\r
1830**/\r
1831UINT8 *\r
1832EFIAPI\r
1833HiiCreateCheckBoxOpCode (\r
1834 IN VOID *OpCodeHandle,\r
1835 IN EFI_QUESTION_ID QuestionId,\r
1836 IN EFI_VARSTORE_ID VarStoreId,\r
1837 IN UINT16 VarOffset,\r
1838 IN EFI_STRING_ID Prompt,\r
1839 IN EFI_STRING_ID Help,\r
1840 IN UINT8 QuestionFlags,\r
1841 IN UINT8 CheckBoxFlags,\r
1842 IN VOID *DefaultsOpCodeHandle OPTIONAL\r
1843 )\r
1844{\r
1845 EFI_IFR_CHECKBOX OpCode;\r
1846 UINTN Position;\r
1847\r
1848 ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED | EFI_IFR_FLAG_OPTIONS_ONLY))) == 0);\r
1849\r
1850 ZeroMem (&OpCode, sizeof (OpCode));\r
1851 OpCode.Question.QuestionId = QuestionId;\r
1852 OpCode.Question.VarStoreId = VarStoreId;\r
1853 OpCode.Question.VarStoreInfo.VarOffset = VarOffset;\r
1854 OpCode.Question.Header.Prompt = Prompt;\r
1855 OpCode.Question.Header.Help = Help;\r
1856 OpCode.Question.Flags = QuestionFlags;\r
1857 OpCode.Flags = CheckBoxFlags;\r
1858\r
1859 if (DefaultsOpCodeHandle == NULL) {\r
1860 return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_CHECKBOX_OP, sizeof (OpCode));\r
1861 }\r
1862\r
1863 Position = InternalHiiOpCodeHandlePosition (OpCodeHandle);\r
1864 InternalHiiCreateOpCodeExtended (OpCodeHandle, &OpCode, EFI_IFR_CHECKBOX_OP, sizeof (OpCode), 0, 1);\r
1865 InternalHiiAppendOpCodes (OpCodeHandle, DefaultsOpCodeHandle);\r
1866 HiiCreateEndOpCode (OpCodeHandle);\r
1867 return InternalHiiOpCodeHandleBuffer (OpCodeHandle) + Position;\r
1868}\r
1869\r
1870/**\r
1871 Create EFI_IFR_NUMERIC_OP opcode.\r
1872\r
1873 If OpCodeHandle is NULL, then ASSERT().\r
1874 If any reserved bits are set in QuestionFlags, then ASSERT().\r
1875 If any reserved bits are set in NumericFlags, then ASSERT().\r
1876\r
1877 @param[in] OpCodeHandle Handle to the buffer of opcodes.\r
1878 @param[in] QuestionId Question ID\r
1879 @param[in] VarStoreId Storage ID\r
1880 @param[in] VarOffset Offset in Storage\r
1881 @param[in] Prompt String ID for Prompt\r
1882 @param[in] Help String ID for Help\r
1883 @param[in] QuestionFlags Flags in Question Header\r
1884 @param[in] NumericFlags Flags for numeric opcode\r
1885 @param[in] Minimum Numeric minimum value\r
1886 @param[in] Maximum Numeric maximum value\r
1887 @param[in] Step Numeric step for edit\r
1888 @param[in] DefaultsOpCodeHandle Handle for a buffer of DEFAULT opcodes. This\r
1889 is an optional parameter that may be NULL.\r
1890\r
1891 @retval NULL There is not enough space left in Buffer to add the opcode.\r
1892 @retval Other A pointer to the created opcode.\r
1893\r
1894**/\r
1895UINT8 *\r
1896EFIAPI\r
1897HiiCreateNumericOpCode (\r
1898 IN VOID *OpCodeHandle,\r
1899 IN EFI_QUESTION_ID QuestionId,\r
1900 IN EFI_VARSTORE_ID VarStoreId,\r
1901 IN UINT16 VarOffset,\r
1902 IN EFI_STRING_ID Prompt,\r
1903 IN EFI_STRING_ID Help,\r
1904 IN UINT8 QuestionFlags,\r
1905 IN UINT8 NumericFlags,\r
1906 IN UINT64 Minimum,\r
1907 IN UINT64 Maximum,\r
1908 IN UINT64 Step,\r
1909 IN VOID *DefaultsOpCodeHandle OPTIONAL\r
1910 )\r
1911{\r
1912 EFI_IFR_NUMERIC OpCode;\r
1913 UINTN Position;\r
1914\r
1915 ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED | EFI_IFR_FLAG_OPTIONS_ONLY))) == 0);\r
1916\r
1917 ZeroMem (&OpCode, sizeof (OpCode));\r
1918 OpCode.Question.QuestionId = QuestionId;\r
1919 OpCode.Question.VarStoreId = VarStoreId;\r
1920 OpCode.Question.VarStoreInfo.VarOffset = VarOffset;\r
1921 OpCode.Question.Header.Prompt = Prompt;\r
1922 OpCode.Question.Header.Help = Help;\r
1923 OpCode.Question.Flags = QuestionFlags;\r
1924 OpCode.Flags = NumericFlags;\r
1925\r
1926 switch (NumericFlags & EFI_IFR_NUMERIC_SIZE) {\r
1927 case EFI_IFR_NUMERIC_SIZE_1:\r
1928 OpCode.data.u8.MinValue = (UINT8)Minimum;\r
1929 OpCode.data.u8.MaxValue = (UINT8)Maximum;\r
1930 OpCode.data.u8.Step = (UINT8)Step;\r
1931 break;\r
1932\r
1933 case EFI_IFR_NUMERIC_SIZE_2:\r
1934 OpCode.data.u16.MinValue = (UINT16)Minimum;\r
1935 OpCode.data.u16.MaxValue = (UINT16)Maximum;\r
1936 OpCode.data.u16.Step = (UINT16)Step;\r
1937 break;\r
1938\r
1939 case EFI_IFR_NUMERIC_SIZE_4:\r
1940 OpCode.data.u32.MinValue = (UINT32)Minimum;\r
1941 OpCode.data.u32.MaxValue = (UINT32)Maximum;\r
1942 OpCode.data.u32.Step = (UINT32)Step;\r
1943 break;\r
1944\r
1945 case EFI_IFR_NUMERIC_SIZE_8:\r
1946 OpCode.data.u64.MinValue = Minimum;\r
1947 OpCode.data.u64.MaxValue = Maximum;\r
1948 OpCode.data.u64.Step = Step;\r
1949 break;\r
1950 }\r
1951\r
1952 if (DefaultsOpCodeHandle == NULL) {\r
1953 return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_NUMERIC_OP, sizeof (OpCode));\r
1954 }\r
1955\r
1956 Position = InternalHiiOpCodeHandlePosition (OpCodeHandle);\r
1957 InternalHiiCreateOpCodeExtended (OpCodeHandle, &OpCode, EFI_IFR_NUMERIC_OP, sizeof (OpCode), 0, 1);\r
1958 InternalHiiAppendOpCodes (OpCodeHandle, DefaultsOpCodeHandle);\r
1959 HiiCreateEndOpCode (OpCodeHandle);\r
1960 return InternalHiiOpCodeHandleBuffer (OpCodeHandle) + Position;\r
1961}\r
1962\r
1963/**\r
1964 Create EFI_IFR_STRING_OP opcode.\r
1965\r
1966 If OpCodeHandle is NULL, then ASSERT().\r
1967 If any reserved bits are set in QuestionFlags, then ASSERT().\r
1968 If any reserved bits are set in StringFlags, then ASSERT().\r
1969\r
1970 @param[in] OpCodeHandle Handle to the buffer of opcodes.\r
1971 @param[in] QuestionId Question ID\r
1972 @param[in] VarStoreId Storage ID\r
1973 @param[in] VarOffset Offset in Storage\r
1974 @param[in] Prompt String ID for Prompt\r
1975 @param[in] Help String ID for Help\r
1976 @param[in] QuestionFlags Flags in Question Header\r
1977 @param[in] StringFlags Flags for string opcode\r
1978 @param[in] MinSize String minimum length\r
1979 @param[in] MaxSize String maximum length\r
1980 @param[in] DefaultsOpCodeHandle Handle for a buffer of DEFAULT opcodes. This\r
1981 is an optional parameter that may be NULL.\r
1982\r
1983 @retval NULL There is not enough space left in Buffer to add the opcode.\r
1984 @retval Other A pointer to the created opcode.\r
1985\r
1986**/\r
1987UINT8 *\r
1988EFIAPI\r
1989HiiCreateStringOpCode (\r
1990 IN VOID *OpCodeHandle,\r
1991 IN EFI_QUESTION_ID QuestionId,\r
1992 IN EFI_VARSTORE_ID VarStoreId,\r
1993 IN UINT16 VarOffset,\r
1994 IN EFI_STRING_ID Prompt,\r
1995 IN EFI_STRING_ID Help,\r
1996 IN UINT8 QuestionFlags,\r
1997 IN UINT8 StringFlags,\r
1998 IN UINT8 MinSize,\r
1999 IN UINT8 MaxSize,\r
2000 IN VOID *DefaultsOpCodeHandle OPTIONAL\r
2001 )\r
2002{\r
2003 EFI_IFR_STRING OpCode;\r
2004 UINTN Position;\r
2005\r
2006 ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED | EFI_IFR_FLAG_OPTIONS_ONLY))) == 0);\r
2007\r
2008 ZeroMem (&OpCode, sizeof (OpCode));\r
2009 OpCode.Question.Header.Prompt = Prompt;\r
2010 OpCode.Question.Header.Help = Help;\r
2011 OpCode.Question.QuestionId = QuestionId;\r
2012 OpCode.Question.VarStoreId = VarStoreId;\r
2013 OpCode.Question.VarStoreInfo.VarOffset = VarOffset;\r
2014 OpCode.Question.Flags = QuestionFlags;\r
2015 OpCode.MinSize = MinSize;\r
2016 OpCode.MaxSize = MaxSize;\r
2017 OpCode.Flags = (UINT8) (StringFlags & EFI_IFR_STRING_MULTI_LINE);\r
2018\r
2019 if (DefaultsOpCodeHandle == NULL) {\r
2020 return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_STRING_OP, sizeof (OpCode));\r
2021 }\r
2022\r
2023 Position = InternalHiiOpCodeHandlePosition (OpCodeHandle);\r
2024 InternalHiiCreateOpCodeExtended (OpCodeHandle, &OpCode, EFI_IFR_STRING_OP, sizeof (OpCode), 0, 1);\r
2025 InternalHiiAppendOpCodes (OpCodeHandle, DefaultsOpCodeHandle);\r
2026 HiiCreateEndOpCode (OpCodeHandle);\r
2027 return InternalHiiOpCodeHandleBuffer (OpCodeHandle) + Position;\r
2028}\r
2029\r
2030/**\r
2031 Create EFI_IFR_ONE_OF_OP opcode.\r
2032\r
2033 If OpCodeHandle is NULL, then ASSERT().\r
2034 If any reserved bits are set in QuestionFlags, then ASSERT().\r
2035 If any reserved bits are set in OneOfFlags, then ASSERT().\r
2036\r
2037 @param[in] OpCodeHandle Handle to the buffer of opcodes.\r
2038 @param[in] QuestionId Question ID\r
2039 @param[in] VarStoreId Storage ID\r
2040 @param[in] VarOffset Offset in Storage\r
2041 @param[in] Prompt String ID for Prompt\r
2042 @param[in] Help String ID for Help\r
2043 @param[in] QuestionFlags Flags in Question Header\r
2044 @param[in] OneOfFlags Flags for oneof opcode\r
2045 @param[in] OptionsOpCodeHandle Handle for a buffer of ONE_OF_OPTION opcodes.\r
2046 @param[in] DefaultsOpCodeHandle Handle for a buffer of DEFAULT opcodes. This\r
2047 is an optional parameter that may be NULL.\r
2048\r
2049 @retval NULL There is not enough space left in Buffer to add the opcode.\r
2050 @retval Other A pointer to the created opcode.\r
2051\r
2052**/\r
2053UINT8 *\r
2054EFIAPI\r
2055HiiCreateOneOfOpCode (\r
2056 IN VOID *OpCodeHandle,\r
2057 IN EFI_QUESTION_ID QuestionId,\r
2058 IN EFI_VARSTORE_ID VarStoreId,\r
2059 IN UINT16 VarOffset,\r
2060 IN EFI_STRING_ID Prompt,\r
2061 IN EFI_STRING_ID Help,\r
2062 IN UINT8 QuestionFlags,\r
2063 IN UINT8 OneOfFlags,\r
2064 IN VOID *OptionsOpCodeHandle,\r
2065 IN VOID *DefaultsOpCodeHandle OPTIONAL\r
2066 )\r
2067{\r
2068 EFI_IFR_ONE_OF OpCode;\r
2069 UINTN Position;\r
2070\r
2071 ASSERT (OptionsOpCodeHandle != NULL);\r
2072 ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED | EFI_IFR_FLAG_OPTIONS_ONLY))) == 0);\r
2073\r
2074 ZeroMem (&OpCode, sizeof (OpCode));\r
2075 OpCode.Question.Header.Prompt = Prompt;\r
2076 OpCode.Question.Header.Help = Help;\r
2077 OpCode.Question.QuestionId = QuestionId;\r
2078 OpCode.Question.VarStoreId = VarStoreId;\r
2079 OpCode.Question.VarStoreInfo.VarOffset = VarOffset;\r
2080 OpCode.Question.Flags = QuestionFlags;\r
2081 OpCode.Flags = OneOfFlags;\r
2082\r
2083 Position = InternalHiiOpCodeHandlePosition (OpCodeHandle);\r
2084 InternalHiiCreateOpCodeExtended (OpCodeHandle, &OpCode, EFI_IFR_ONE_OF_OP, sizeof (OpCode), 0, 1);\r
2085 InternalHiiAppendOpCodes (OpCodeHandle, OptionsOpCodeHandle);\r
2086 if (DefaultsOpCodeHandle != NULL) {\r
2087 InternalHiiAppendOpCodes (OpCodeHandle, DefaultsOpCodeHandle);\r
2088 }\r
2089 HiiCreateEndOpCode (OpCodeHandle);\r
2090 return InternalHiiOpCodeHandleBuffer (OpCodeHandle) + Position;\r
2091}\r
2092\r
2093/**\r
2094 Create EFI_IFR_ORDERED_LIST_OP opcode.\r
2095\r
2096 If OpCodeHandle is NULL, then ASSERT().\r
2097 If any reserved bits are set in QuestionFlags, then ASSERT().\r
2098 If any reserved bits are set in OrderedListFlags, then ASSERT().\r
2099\r
2100 @param[in] OpCodeHandle Handle to the buffer of opcodes.\r
2101 @param[in] QuestionId Question ID\r
2102 @param[in] VarStoreId Storage ID\r
2103 @param[in] VarOffset Offset in Storage\r
2104 @param[in] Prompt String ID for Prompt\r
2105 @param[in] Help String ID for Help\r
2106 @param[in] QuestionFlags Flags in Question Header\r
2107 @param[in] OrderedListFlags Flags for ordered list opcode\r
2108 @param[in] DataType Type for option value\r
2109 @param[in] MaxContainers Maximum count for options in this ordered list\r
2110 @param[in] OptionsOpCodeHandle Handle for a buffer of ONE_OF_OPTION opcodes.\r
2111 @param[in] DefaultsOpCodeHandle Handle for a buffer of DEFAULT opcodes. This\r
2112 is an optional parameter that may be NULL.\r
2113\r
2114 @retval NULL There is not enough space left in Buffer to add the opcode.\r
2115 @retval Other A pointer to the created opcode.\r
2116\r
2117**/\r
2118UINT8 *\r
2119EFIAPI\r
2120HiiCreateOrderedListOpCode (\r
2121 IN VOID *OpCodeHandle,\r
2122 IN EFI_QUESTION_ID QuestionId,\r
2123 IN EFI_VARSTORE_ID VarStoreId,\r
2124 IN UINT16 VarOffset,\r
2125 IN EFI_STRING_ID Prompt,\r
2126 IN EFI_STRING_ID Help,\r
2127 IN UINT8 QuestionFlags,\r
2128 IN UINT8 OrderedListFlags,\r
2129 IN UINT8 DataType,\r
2130 IN UINT8 MaxContainers,\r
2131 IN VOID *OptionsOpCodeHandle,\r
2132 IN VOID *DefaultsOpCodeHandle OPTIONAL\r
2133 )\r
2134{\r
2135 EFI_IFR_ORDERED_LIST OpCode;\r
2136 UINTN Position;\r
2137\r
2138 ASSERT (OptionsOpCodeHandle != NULL);\r
2139 ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED | EFI_IFR_FLAG_OPTIONS_ONLY))) == 0);\r
2140\r
2141 ZeroMem (&OpCode, sizeof (OpCode));\r
2142 OpCode.Question.Header.Prompt = Prompt;\r
2143 OpCode.Question.Header.Help = Help;\r
2144 OpCode.Question.QuestionId = QuestionId;\r
2145 OpCode.Question.VarStoreId = VarStoreId;\r
2146 OpCode.Question.VarStoreInfo.VarOffset = VarOffset;\r
2147 OpCode.Question.Flags = QuestionFlags;\r
2148 OpCode.MaxContainers = MaxContainers;\r
2149 OpCode.Flags = OrderedListFlags;\r
2150\r
2151 Position = InternalHiiOpCodeHandlePosition (OpCodeHandle);\r
2152 InternalHiiCreateOpCodeExtended (OpCodeHandle, &OpCode, EFI_IFR_ORDERED_LIST_OP, sizeof (OpCode), 0, 1);\r
2153 InternalHiiAppendOpCodes (OpCodeHandle, OptionsOpCodeHandle);\r
2154 if (DefaultsOpCodeHandle != NULL) {\r
2155 InternalHiiAppendOpCodes (OpCodeHandle, DefaultsOpCodeHandle);\r
2156 }\r
2157 HiiCreateEndOpCode (OpCodeHandle);\r
2158 return InternalHiiOpCodeHandleBuffer (OpCodeHandle) + Position;\r
2159}\r
2160\r
2161/**\r
2162 This is the internal worker function to update the data in\r
2163 a form specified by FormSetGuid, FormId and Label.\r
2164\r
2165 @param FormSetGuid The optional Formset GUID.\r
2166 @param FormId The Form ID.\r
2167 @param Package The package header.\r
2168\r
2169 @param TempPacakge The resultant package.\r
2170\r
2171 @retval EFI_SUCCESS The function completes successfully.\r
2172\r
2173**/\r
2174EFI_STATUS\r
2175EFIAPI\r
2176InternalHiiUpdateFormPackageData (\r
2177 IN EFI_GUID *FormSetGuid, OPTIONAL\r
2178 IN EFI_FORM_ID FormId,\r
2179 IN EFI_HII_PACKAGE_HEADER *Package,\r
2180 IN HII_LIB_OPCODE_BUFFER *OpCodeBufferStart,\r
2181 IN HII_LIB_OPCODE_BUFFER *OpCodeBufferEnd, OPTIONAL\r
2182 OUT EFI_HII_PACKAGE_HEADER *TempPackage\r
2183 )\r
2184{\r
2185 UINTN AddSize;\r
2186 UINT8 *BufferPos;\r
2187 EFI_HII_PACKAGE_HEADER PackageHeader;\r
2188 UINTN Offset;\r
2189 EFI_IFR_OP_HEADER *IfrOpHdr;\r
2190 EFI_IFR_OP_HEADER *UpdateIfrOpHdr;\r
2191 BOOLEAN GetFormSet;\r
2192 BOOLEAN GetForm;\r
2193 BOOLEAN Updated;\r
2194 EFI_IFR_OP_HEADER *AddOpCode;\r
2195 UINT32 UpdatePackageLength;\r
2196\r
2197 CopyMem (TempPackage, Package, sizeof (EFI_HII_PACKAGE_HEADER));\r
2198 UpdatePackageLength = sizeof (EFI_HII_PACKAGE_HEADER);\r
2199 BufferPos = (UINT8 *) (TempPackage + 1);\r
2200\r
2201 CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));\r
2202 IfrOpHdr = (EFI_IFR_OP_HEADER *)((UINT8 *) Package + sizeof (EFI_HII_PACKAGE_HEADER));\r
2203 Offset = sizeof (EFI_HII_PACKAGE_HEADER);\r
2204 GetFormSet = (BOOLEAN) ((FormSetGuid == NULL) ? TRUE : FALSE);\r
2205 GetForm = FALSE;\r
2206 Updated = FALSE;\r
2207\r
2208 while (Offset < PackageHeader.Length) {\r
2209 CopyMem (BufferPos, IfrOpHdr, IfrOpHdr->Length);\r
2210 BufferPos += IfrOpHdr->Length;\r
2211 UpdatePackageLength += IfrOpHdr->Length;\r
2212 \r
2213 //\r
2214 // Find the matched FormSet and Form\r
2215 //\r
2216 if ((IfrOpHdr->OpCode == EFI_IFR_FORM_SET_OP) && (FormSetGuid != NULL)) {\r
2217 if (CompareGuid((GUID *)(VOID *)&((EFI_IFR_FORM_SET *) IfrOpHdr)->Guid, FormSetGuid)) {\r
2218 GetFormSet = TRUE;\r
2219 } else {\r
2220 GetFormSet = FALSE;\r
2221 }\r
2222 } else if (IfrOpHdr->OpCode == EFI_IFR_FORM_OP) {\r
2223 if (CompareMem (&((EFI_IFR_FORM *) IfrOpHdr)->FormId, &FormId, sizeof (EFI_FORM_ID)) == 0) {\r
2224 GetForm = TRUE;\r
2225 } else {\r
2226 GetForm = FALSE;\r
2227 }\r
2228 }\r
2229 \r
2230 //\r
2231 // The matched Form is found, and Update data in this form\r
2232 //\r
2233 if (GetFormSet && GetForm && !Updated) {\r
2234 UpdateIfrOpHdr = (EFI_IFR_OP_HEADER *) OpCodeBufferStart->Buffer;\r
2235 if ((UpdateIfrOpHdr->Length == IfrOpHdr->Length) && \\r
2236 (CompareMem (IfrOpHdr, UpdateIfrOpHdr, UpdateIfrOpHdr->Length) == 0)) {\r
2237 //\r
2238 // Remove the original data when End OpCode buffer exist.\r
2239 //\r
2240 if (OpCodeBufferEnd != NULL) {\r
2241 Offset += IfrOpHdr->Length;\r
2242 IfrOpHdr = (EFI_IFR_OP_HEADER *) ((UINT8 *) (IfrOpHdr) + IfrOpHdr->Length);\r
2243 UpdateIfrOpHdr = (EFI_IFR_OP_HEADER *) OpCodeBufferEnd->Buffer;\r
2244 while (Offset < PackageHeader.Length) {\r
2245 //\r
2246 // Search the matched end opcode\r
2247 //\r
2248 if ((UpdateIfrOpHdr->Length == IfrOpHdr->Length) && \\r
2249 (CompareMem (IfrOpHdr, UpdateIfrOpHdr, UpdateIfrOpHdr->Length) == 0)) {\r
2250 break;\r
2251 }\r
2252 //\r
2253 // Go to the next Op-Code\r
2254 //\r
2255 Offset += IfrOpHdr->Length;\r
2256 IfrOpHdr = (EFI_IFR_OP_HEADER *) ((UINT8 *) (IfrOpHdr) + IfrOpHdr->Length);\r
2257 }\r
2258 \r
2259 if (Offset >= PackageHeader.Length) {\r
2260 //\r
2261 // The end opcode is not found.\r
2262 //\r
2263 return EFI_NOT_FOUND;\r
2264 }\r
2265 }\r
2266 //\r
2267 // Insert the updated data\r
2268 //\r
2269 UpdateIfrOpHdr = (EFI_IFR_OP_HEADER *) OpCodeBufferStart->Buffer;\r
2270 AddOpCode = (EFI_IFR_OP_HEADER *) (OpCodeBufferStart->Buffer + UpdateIfrOpHdr->Length);\r
2271 AddSize = UpdateIfrOpHdr->Length;\r
2272 while (AddSize < OpCodeBufferStart->Position) {\r
2273 CopyMem (BufferPos, AddOpCode, AddOpCode->Length);\r
2274 BufferPos += AddOpCode->Length;\r
2275 UpdatePackageLength += AddOpCode->Length;\r
2276\r
2277 AddOpCode = (EFI_IFR_OP_HEADER *) ((UINT8 *) (AddOpCode) + AddOpCode->Length);\r
2278 AddSize += AddOpCode->Length; \r
2279 }\r
2280\r
2281 if (OpCodeBufferEnd != NULL) {\r
2282 //\r
2283 // Add the end opcode\r
2284 //\r
2285 CopyMem (BufferPos, IfrOpHdr, IfrOpHdr->Length);\r
2286 BufferPos += IfrOpHdr->Length;\r
2287 UpdatePackageLength += IfrOpHdr->Length;\r
2288 }\r
2289 //\r
2290 // Set update flag\r
2291 //\r
2292 Updated = TRUE;\r
2293 }\r
2294 }\r
2295\r
2296 //\r
2297 // Go to the next Op-Code\r
2298 //\r
2299 Offset += IfrOpHdr->Length;\r
2300 IfrOpHdr = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (IfrOpHdr) + IfrOpHdr->Length);\r
2301 }\r
2302 \r
2303 if (!Updated) {\r
2304 //\r
2305 // The updated opcode buffer is not found.\r
2306 //\r
2307 return EFI_NOT_FOUND;\r
2308 }\r
2309 //\r
2310 // Update the package length.\r
2311 //\r
2312 PackageHeader.Length = UpdatePackageLength;\r
2313 CopyMem (TempPackage, &PackageHeader, sizeof (EFI_HII_PACKAGE_HEADER));\r
2314\r
2315 return EFI_SUCCESS;\r
2316}\r
2317\r
2318/**\r
2319 This function updates a form that has previously been registered with the HII \r
2320 Database. This function will perform at most one update operation.\r
2321 \r
2322 The form to update is specified by Handle, FormSetGuid, and FormId. Binary \r
2323 comparisons of IFR opcodes are performed from the beginning of the form being \r
2324 updated until an IFR opcode is found that exactly matches the first IFR opcode \r
2325 specifed by StartOpCodeHandle. The following rules are used to determine if\r
2326 an insert, replace, or delete operation is performed.\r
2327 \r
2328 1) If no matches are found, then NULL is returned. \r
2329 2) If a match is found, and EndOpCodeHandle is NULL, then all of the IFR opcodes\r
2330 from StartOpcodeHandle except the first opcode are inserted immediately after \r
2331 the matching IFR opcode in the form beng updated.\r
2332 3) If a match is found, and EndOpCodeHandle is not NULL, then a search is made \r
2333 from the matching IFR opcode until an IFR opcode exatly matches the first \r
2334 IFR opcode specified by EndOpCodeHandle. If no match is found for the first\r
2335 IFR opcode specified by EndOpCodeHandle, then NULL is returned. If a match\r
2336 is found, then all of the IFR opcodes between the start match and the end \r
2337 match are deleted from the form being updated and all of the IFR opcodes\r
2338 from StartOpcodeHandle except the first opcode are inserted immediately after \r
2339 the matching start IFR opcode. If StartOpCcodeHandle only contains one\r
2340 IFR instruction, then the result of ths operation will delete all of the IFR\r
2341 opcodes between the start end matches.\r
2342\r
2343 If HiiHandle is NULL, then ASSERT().\r
2344 If StartOpCodeHandle is NULL, then ASSERT().\r
2345\r
2346 @param[in] HiiHandle The HII Handle of the form to update.\r
2347 @param[in] FormSetGuid The Formset GUID of the form to update. This\r
2348 is an optional parameter that may be NULL.\r
2349 If it is NULL, all FormSet will be updated.\r
2350 @param[in] FormId The ID of the form to update.\r
2351 @param[in] StartOpCodeHandle An OpCode Handle that contains the set of IFR \r
2352 opcodes to be inserted or replaced in the form.\r
2353 The first IFR instruction in StartOpCodeHandle \r
2354 is used to find matching IFR opcode in the \r
2355 form. \r
2356 @param[in] EndOpCodeHandle An OpCcode Handle that contains the IFR opcode\r
2357 that marks the end of a replace operation in\r
2358 the form. This is an optional parameter that\r
2359 may be NULL. If it is NULL, then an the IFR\r
2360 opcodes specified by StartOpCodeHandle are \r
2361 inserted into the form.\r
2362 \r
2363 @retval EFI_OUT_OF_RESOURCES No enough memory resource is allocated.\r
2364 @retval EFI_NOT_FOUND The following cases will return EFI_NOT_FOUND.\r
2365 1) The form specified by HiiHandle, FormSetGuid, \r
2366 and FormId could not be found in the HII Database.\r
2367 2) No IFR opcodes in the target form match the first\r
2368 IFR opcode in StartOpCodeHandle.\r
2369 3) EndOpCOde is not NULL, and no IFR opcodes in the \r
2370 target form following a matching start opcode match \r
2371 the first IFR opcode in EndOpCodeHandle.\r
2372 @retval EFI_SUCCESS The matched form is updated by StartOpcode.\r
2373\r
2374**/\r
2375EFI_STATUS\r
2376EFIAPI\r
2377HiiUpdateForm (\r
2378 IN EFI_HII_HANDLE HiiHandle, \r
2379 IN EFI_GUID *FormSetGuid, OPTIONAL\r
2380 IN EFI_FORM_ID FormId,\r
2381 IN VOID *StartOpcodeHandle,\r
2382 IN VOID *EndOpcodeHandle OPTIONAL\r
2383 )\r
2384{\r
2385 EFI_STATUS Status;\r
2386 EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;\r
2387 UINT32 PackageListLength; \r
2388 UINT32 Offset;\r
2389 EFI_HII_PACKAGE_LIST_HEADER *UpdatePackageList;\r
2390 UINTN BufferSize;\r
2391 UINT8 *UpdateBufferPos;\r
2392 EFI_HII_PACKAGE_HEADER *Package;\r
2393 EFI_HII_PACKAGE_HEADER *TempPacakge;\r
2394 EFI_HII_PACKAGE_HEADER PackageHeader;\r
2395 BOOLEAN Updated;\r
2396 HII_LIB_OPCODE_BUFFER *OpCodeBufferStart;\r
2397 HII_LIB_OPCODE_BUFFER *OpCodeBufferEnd;\r
2398 \r
2399 //\r
2400 // Input update data can't be NULL.\r
2401 //\r
2402 ASSERT (HiiHandle != NULL);\r
2403 ASSERT (StartOpcodeHandle != NULL);\r
2404 UpdatePackageList = NULL;\r
2405 TempPacakge = NULL;\r
2406 HiiPackageList = NULL;\r
2407 \r
2408 //\r
2409 // Restrive buffer data from Opcode Handle\r
2410 //\r
2411 OpCodeBufferStart = (HII_LIB_OPCODE_BUFFER *) StartOpcodeHandle;\r
2412 OpCodeBufferEnd = (HII_LIB_OPCODE_BUFFER *) EndOpcodeHandle;\r
2413 \r
2414 //\r
2415 // Get the orginal package list\r
2416 //\r
2417 BufferSize = 0;\r
2418 HiiPackageList = NULL;\r
2419 Status = gHiiDatabase->ExportPackageLists (gHiiDatabase, HiiHandle, &BufferSize, HiiPackageList);\r
2420 //\r
2421 // The return status should always be EFI_BUFFER_TOO_SMALL as input buffer's size is 0.\r
2422 //\r
2423 if (Status != EFI_BUFFER_TOO_SMALL) {\r
2424 return Status;\r
2425 }\r
2426\r
2427 HiiPackageList = AllocatePool (BufferSize);\r
2428 if (HiiPackageList == NULL) {\r
2429 Status = EFI_OUT_OF_RESOURCES;\r
2430 goto Finish;\r
2431 }\r
2432\r
2433 Status = gHiiDatabase->ExportPackageLists (gHiiDatabase, HiiHandle, &BufferSize, HiiPackageList);\r
2434 if (EFI_ERROR (Status)) {\r
2435 goto Finish;\r
2436 }\r
2437\r
2438 //\r
2439 // Calculate and allocate space for retrieval of IFR data\r
2440 //\r
2441 BufferSize += OpCodeBufferStart->Position;\r
2442 UpdatePackageList = AllocateZeroPool (BufferSize);\r
2443 if (UpdatePackageList == NULL) {\r
2444 Status = EFI_OUT_OF_RESOURCES;\r
2445 goto Finish;\r
2446 }\r
2447 \r
2448 //\r
2449 // Allocate temp buffer to store the temp updated package buffer\r
2450 //\r
2451 TempPacakge = AllocateZeroPool (BufferSize);\r
2452 if (TempPacakge == NULL) {\r
2453 Status = EFI_OUT_OF_RESOURCES;\r
2454 goto Finish;\r
2455 }\r
2456\r
2457 UpdateBufferPos = (UINT8 *) UpdatePackageList;\r
2458\r
2459 //\r
2460 // Copy the package list header\r
2461 //\r
2462 CopyMem (UpdateBufferPos, HiiPackageList, sizeof (EFI_HII_PACKAGE_LIST_HEADER));\r
2463 UpdateBufferPos += sizeof (EFI_HII_PACKAGE_LIST_HEADER);\r
2464 \r
2465 //\r
2466 // Go through each package to find the matched pacakge and update one by one\r
2467 //\r
2468 Updated = FALSE;\r
2469 Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);\r
2470 PackageListLength = ReadUnaligned32 (&HiiPackageList->PackageLength);\r
2471 while (Offset < PackageListLength) {\r
2472 Package = (EFI_HII_PACKAGE_HEADER *) (((UINT8 *) HiiPackageList) + Offset);\r
2473 CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));\r
2474 Offset += Package->Length;\r
2475\r
2476 if (Package->Type == EFI_HII_PACKAGE_FORMS) {\r
2477 //\r
2478 // Check this package is the matched package.\r
2479 //\r
2480 Status = InternalHiiUpdateFormPackageData (FormSetGuid, FormId, Package, OpCodeBufferStart, OpCodeBufferEnd, TempPacakge);\r
2481 //\r
2482 // The matched package is found. Its pacakge buffer will be updated by the input new data.\r
2483 //\r
2484 if (!EFI_ERROR(Status)) {\r
2485 //\r
2486 // Set Update Flag\r
2487 // \r
2488 Updated = TRUE;\r
2489 //\r
2490 // Add updated package buffer\r
2491 //\r
2492 Package = TempPacakge;\r
2493 }\r
2494 }\r
2495\r
2496 //\r
2497 // Add pacakge buffer\r
2498 //\r
2499 CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));\r
2500 CopyMem (UpdateBufferPos, Package, PackageHeader.Length);\r
2501 UpdateBufferPos += PackageHeader.Length;\r
2502 }\r
2503 \r
2504 if (Updated) {\r
2505 //\r
2506 // Update package list length\r
2507 //\r
2508 BufferSize = UpdateBufferPos - (UINT8 *) UpdatePackageList;\r
2509 WriteUnaligned32 (&UpdatePackageList->PackageLength, (UINT32) BufferSize);\r
2510 \r
2511 //\r
2512 // Update Pacakge to show form\r
2513 //\r
2514 Status = gHiiDatabase->UpdatePackageList (gHiiDatabase, HiiHandle, UpdatePackageList);\r
2515 } else {\r
2516 //\r
2517 // Not matched form is found and updated.\r
2518 //\r
2519 Status = EFI_NOT_FOUND;\r
2520 }\r
2521\r
2522Finish:\r
2523 if (HiiPackageList != NULL) {\r
2524 FreePool (HiiPackageList);\r
2525 }\r
2526 \r
2527 if (UpdatePackageList != NULL) {\r
2528 FreePool (UpdatePackageList);\r
2529 }\r
2530 \r
2531 if (TempPacakge != NULL) {\r
2532 FreePool (TempPacakge);\r
2533 }\r
2534\r
2535 return Status; \r
2536}\r
2537\r
2538/**\r
2539 Configure the buffer accrording to ConfigBody strings in the format of\r
2540 <Length:4 bytes>, <Offset: 2 bytes>, <Width:2 bytes>, <Data:n bytes>.\r
2541 This ConfigBody strings is generated by UEFI VfrCompiler for the default\r
2542 values in a Form Set. The name of the ConfigBody strings is VfrMyIfrNVDataDefault0000\r
2543 constructed following this rule: \r
2544 "Vfr" + varstore.name + "Default" + defaultstore.attributes.\r
2545 Check the generated C file in Output for details.\r
2546\r
2547 @param Buffer The start address of buffer.\r
2548 @param BufferSize The size of buffer.\r
2549 @param Number The number of the strings.\r
2550 @param ... Variable argument list for default value in <AltResp> format \r
2551 generated by the tool.\r
2552\r
2553 @retval EFI_BUFFER_TOO_SMALL the BufferSize is too small to operate.\r
2554 @retval EFI_INVALID_PARAMETER Buffer is NULL or BufferSize is 0.\r
2555 @retval EFI_SUCCESS Operation successful.\r
2556\r
2557**/\r
2558EFI_STATUS\r
2559EFIAPI\r
3c7449e4 2560HiiIfrLibExtractDefault(\r
7e3bcccb
LG
2561 IN VOID *Buffer,\r
2562 IN UINTN *BufferSize,\r
2563 UINTN Number,\r
2564 ...\r
2565 )\r
2566{\r
2567 VA_LIST Args;\r
2568 UINTN Index;\r
2569 UINT32 TotalLen;\r
2570 UINT8 *BufCfgArray;\r
2571 UINT8 *BufferPos;\r
2572 UINT16 Offset;\r
2573 UINT16 Width;\r
2574 UINT8 *Value;\r
2575\r
2576 if ((Buffer == NULL) || (BufferSize == NULL)) {\r
2577 return EFI_INVALID_PARAMETER;\r
2578 }\r
2579\r
2580 Offset = 0;\r
2581 Width = 0;\r
2582 Value = NULL;\r
2583\r
2584 VA_START (Args, Number);\r
2585 for (Index = 0; Index < Number; Index++) {\r
2586 BufCfgArray = (UINT8 *) VA_ARG (Args, VOID *);\r
2587 TotalLen = ReadUnaligned32 ((UINT32 *)BufCfgArray);\r
2588 BufferPos = BufCfgArray + sizeof (UINT32);\r
2589\r
2590 while ((UINT32)(BufferPos - BufCfgArray) < TotalLen) {\r
2591 Offset = ReadUnaligned16 ((UINT16 *)BufferPos);\r
2592 BufferPos += sizeof (UINT16);\r
2593 Width = ReadUnaligned16 ((UINT16 *)BufferPos);\r
2594 BufferPos += sizeof (UINT16);\r
2595 Value = BufferPos;\r
2596 BufferPos += Width;\r
2597\r
2598 if ((UINTN)(Offset + Width) > *BufferSize) {\r
2599 return EFI_BUFFER_TOO_SMALL;\r
2600 }\r
2601\r
2602 CopyMem ((UINT8 *)Buffer + Offset, Value, Width);\r
2603 }\r
2604 }\r
2605 VA_END (Args);\r
2606\r
2607 *BufferSize = (UINTN)Offset;\r
2608\r
2609 return EFI_SUCCESS;\r
2610}\r
cb7d01c0 2611\r