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