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