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