Fix non-boolean comparison expression.
[efi/edk2/.git] / edk2 / EdkCompatibilityPkg / Compatibility / FrameworkHiiOnUefiHiiThunk / OpcodeCreation.c
1 /** @file\r
2 Implement Functions to convert IFR Opcode in format defined in Framework HII specification to\r
3 format defined in UEFI HII Specification.\r
4 \r
5 Copyright (c) 2007 - 2010, Intel Corporation\r
6 All rights reserved. This program and the accompanying materials\r
7 are licensed and made available under the terms and conditions of the BSD License\r
8 which accompanies this distribution.  The full text of the license may be found at\r
9 http://opensource.org/licenses/bsd-license.php\r
10 \r
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13 \r
14 **/\r
15 \r
16 #include "HiiDatabase.h"\r
17 #include "UefiIfrDefault.h"\r
18 \r
19 /**\r
20   The dynamic creation of these opcodes is supported in Framework HII modules.\r
21   Therefore, Framework HII Thunk module only map these opcode between Framework\r
22   HII's definitions to UEFI HII's.\r
23 **/\r
24 typedef struct { \r
25   UINT8 FrameworkIfrOp;\r
26   UINT8 UefiIfrOp;\r
27 } IFR_OPCODE_MAP;\r
28   \r
29 IFR_OPCODE_MAP QuestionOpcodeMap[] = {\r
30   { FRAMEWORK_EFI_IFR_ONE_OF_OP,        EFI_IFR_ONE_OF_OP},\r
31   { FRAMEWORK_EFI_IFR_CHECKBOX_OP,      EFI_IFR_CHECKBOX_OP},\r
32   { FRAMEWORK_EFI_IFR_NUMERIC_OP,       EFI_IFR_NUMERIC_OP},\r
33   { FRAMEWORK_EFI_IFR_ONE_OF_OPTION_OP, EFI_IFR_ONE_OF_OPTION_OP},\r
34   { FRAMEWORK_EFI_IFR_ORDERED_LIST_OP,  EFI_IFR_ORDERED_LIST_OP}\r
35 };\r
36 \r
37 /**\r
38   Translate a Framework Question Opcode to UEFI Question Opcode.\r
39 \r
40   @param FwOp     Framework Opcode.\r
41   @param UefiOp   UEFI Opcode.\r
42 \r
43   @retval     EFI_SUCCESS     The UEFI opcode is found and returned.\r
44   @retval     EFI_NOT_FOUND   The UEFI opcode is not found.\r
45 **/\r
46 EFI_STATUS\r
47 QuestionOpFwToUefi (\r
48   IN            UINT8   FwOp,\r
49   OUT           UINT8   *UefiOp\r
50   )\r
51 {\r
52   UINTN       Index;\r
53 \r
54   for (Index = 0; Index < sizeof (QuestionOpcodeMap) / sizeof (QuestionOpcodeMap[0]); Index++) {\r
55     if (FwOp == QuestionOpcodeMap[Index].FrameworkIfrOp) {\r
56       *UefiOp = QuestionOpcodeMap[Index].UefiIfrOp;\r
57       return EFI_SUCCESS;\r
58     }\r
59   }\r
60 \r
61   *UefiOp = (UINT8) (EFI_IFR_LAST_OPCODE + 1);\r
62   return EFI_NOT_FOUND;\r
63 }\r
64 \r
65 /**\r
66   Translate a Framework Question ID to UEFI Question ID.\r
67 \r
68   @param FormSet   FormSet context\r
69   @param FwOpCode  Framework Opcode\r
70   @param FwQId     Framework Question Id\r
71   @param UefiQId   UEFI Question ID.\r
72 \r
73   @retval     EFI_SUCCESS     The UEFI Question Id is found and returned.\r
74   @retval     EFI_NOT_FOUND   The UEFI Question Id is not found.\r
75 **/\r
76 EFI_STATUS\r
77 FwQIdToUefiQId (\r
78   IN  CONST FORM_BROWSER_FORMSET *FormSet,\r
79   IN  UINT8                      FwOpCode,\r
80   IN  UINT16                     FwQId,\r
81   OUT UINT16                     *UefiQId\r
82   )\r
83 {\r
84   LIST_ENTRY             *FormList;\r
85   LIST_ENTRY             *StatementList;\r
86   FORM_BROWSER_FORM      *Form;\r
87   FORM_BROWSER_STATEMENT *Statement;\r
88   FORM_BROWSER_STATEMENT *StatementFound;\r
89   EFI_STATUS             Status;\r
90   UINT8                  UefiOp;\r
91   \r
92 \r
93   *UefiQId = 0;\r
94   StatementFound = NULL;\r
95 \r
96   FormList = GetFirstNode (&FormSet->FormListHead);\r
97 \r
98   while (!IsNull (&FormSet->FormListHead, FormList)) {\r
99     Form = FORM_BROWSER_FORM_FROM_LINK (FormList);\r
100 \r
101     StatementList = GetFirstNode (&Form->StatementListHead);\r
102 \r
103     while (!IsNull (&Form->StatementListHead, StatementList)) {\r
104       Statement = FORM_BROWSER_STATEMENT_FROM_LINK (StatementList);\r
105       if (Statement->VarStoreId != 0 && Statement->Storage->Type == EFI_HII_VARSTORE_BUFFER) {\r
106         if (FwQId == Statement->VarStoreInfo.VarOffset) {\r
107           Status = QuestionOpFwToUefi (FwOpCode, &UefiOp);\r
108           ASSERT_EFI_ERROR (Status);\r
109 \r
110           if ((UefiOp == Statement->Operand) && (FormSet->DefaultVarStoreId == Statement->VarStoreId)) {\r
111             //\r
112             // If ASSERT here, the Framework VFR file has two Questions with all three attibutes the same:\r
113             // 1) Same Question Type, \r
114             // 2) Same Variable Storage\r
115             // 3) Refering to the Same offset in Variable Map (NvMap). \r
116             // This is ambigurity as FwQIdToUefiQId () can't find which UEFI Question \r
117             // ID to return. \r
118             //\r
119             // One possible solution is to remove the one of the duplicated questions in this Form Set.\r
120             //\r
121             ASSERT (StatementFound == NULL);\r
122             StatementFound= Statement;\r
123 \r
124             //\r
125             // Continue the search to check if the Form Set contains more than one questins that has the 3 attributes\r
126             // with same value.\r
127             //\r
128           }\r
129         }\r
130       }\r
131 \r
132       StatementList = GetNextNode (&Form->StatementListHead, StatementList);\r
133     }\r
134 \r
135     FormList = GetNextNode (&FormSet->FormListHead, FormList);\r
136   }\r
137 \r
138   if (StatementFound != NULL) {\r
139     *UefiQId = StatementFound->QuestionId;\r
140     return EFI_SUCCESS;\r
141   }\r
142   \r
143   return EFI_NOT_FOUND;\r
144 }\r
145 \r
146 /**\r
147   Assign a Question ID.\r
148 \r
149   If FwQuestionId is 0, then assign a new question ID. The new question ID\r
150   is MaxQuestionId incremented by 1. The MaxQuestionId of FormSet is also\r
151   incremented by 1.\r
152 \r
153   If FwQuestionId is not 0, then it is used as the Framework Question ID.\r
154 \r
155   @param FwQuestionId \r
156   @param FormSet      \r
157 \r
158   @return The Framework Question ID.\r
159 **/\r
160 EFI_QUESTION_ID\r
161 AssignQuestionId (\r
162   IN  UINT16                      FwQuestionId,\r
163   IN        FORM_BROWSER_FORMSET  *FormSet\r
164   )\r
165 {\r
166   if (FwQuestionId == 0) {\r
167     FormSet->MaxQuestionId++;\r
168     return FormSet->MaxQuestionId;\r
169   } else {\r
170     return FwQuestionId;\r
171   }\r
172 }\r
173 \r
174 /**\r
175   Create UEFI HII Text Opcode from a Framework HII Text Opcode.\r
176 \r
177   @param UefiUpdateDataHandle  The newly created UEFI HII opcode is appended to UefiUpdateDataHandle.\r
178   @param FwOpcode              The input Framework Opcode.\r
179 \r
180   @retval NULL   There is not enough space left in Buffer to add the opcode.\r
181   @retval Other  A pointer to the created opcode.\r
182   \r
183 **/\r
184 UINT8 *\r
185 F2UCreateTextOpCode (\r
186   IN OUT   VOID                        *UefiUpdateDataHandle,\r
187   IN CONST FRAMEWORK_EFI_IFR_TEXT      *FwOpcode\r
188   )\r
189 {\r
190   EFI_IFR_TEXT      UTextOpCode;\r
191 \r
192   if ((FwOpcode->Flags & EFI_IFR_FLAG_INTERACTIVE) == 0) {\r
193     ZeroMem (&UTextOpCode, sizeof(UTextOpCode));\r
194     \r
195     UTextOpCode.Header.OpCode = EFI_IFR_TEXT_OP;\r
196     UTextOpCode.Header.Length = sizeof (EFI_IFR_TEXT);\r
197 \r
198     UTextOpCode.Statement.Help   = FwOpcode->Help;\r
199 \r
200     UTextOpCode.Statement.Prompt = FwOpcode->Text;\r
201     UTextOpCode.TextTwo          = FwOpcode->TextTwo;\r
202     \r
203     return HiiCreateRawOpCodes (UefiUpdateDataHandle, (UINT8 *) &UTextOpCode, sizeof(UTextOpCode));\r
204   } else {\r
205     //\r
206     // Iteractive Text Opcode is EFI_IFR_ACTION\r
207     //\r
208     return HiiCreateActionOpCode (UefiUpdateDataHandle, FwOpcode->Key, FwOpcode->Text, FwOpcode->Help, EFI_IFR_FLAG_CALLBACK, 0);\r
209   }\r
210 }\r
211 \r
212 /**\r
213   Create UEFI HII Reference Opcode from a Framework HII Reference Opcode.\r
214 \r
215   @param UefiUpdateDataHandle  The newly created UEFI HII opcode is appended to UefiUpdateDataHandle.\r
216   @param FwOpcode              The input Framework Opcode.\r
217 \r
218   @retval NULL   There is not enough space left in Buffer to add the opcode.\r
219   @retval Other  A pointer to the created opcode.\r
220   \r
221 **/\r
222 UINT8 *\r
223 F2UCreateReferenceOpCode (\r
224   IN OUT   VOID                        *UefiUpdateDataHandle,\r
225   IN CONST FRAMEWORK_EFI_IFR_REF       *FwOpcode\r
226   )\r
227 {\r
228   EFI_IFR_REF UOpcode;\r
229 \r
230   ZeroMem (&UOpcode, sizeof(UOpcode));\r
231 \r
232   UOpcode.Header.Length = sizeof(UOpcode);\r
233   UOpcode.Header.OpCode = EFI_IFR_REF_OP;\r
234 \r
235   UOpcode.Question.Header.Prompt = FwOpcode->Prompt;\r
236   UOpcode.Question.Header.Help = FwOpcode->Help;\r
237   UOpcode.Question.QuestionId = FwOpcode->Key;\r
238 \r
239   UOpcode.FormId = FwOpcode->FormId;\r
240 \r
241   //\r
242   // We only map EFI_IFR_FLAG_INTERACTIVE and EFI_IFR_FLAG_RESET_REQUIRED to \r
243   // UEFI IFR Opcode flags. The rest flags are obsolete.\r
244   //\r
245   UOpcode.Question.Flags  = (UINT8) (FwOpcode->Flags & (EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_RESET_REQUIRED));\r
246   \r
247   return HiiCreateRawOpCodes (UefiUpdateDataHandle, (UINT8 *) &UOpcode, sizeof(UOpcode));\r
248 }\r
249 \r
250 /**\r
251   Create UEFI HII "One Of Option" Opcode from a Framework HII "One Of Option" Opcode.\r
252 \r
253   @param UefiUpdateDataHandle  The newly created UEFI HII opcode is appended to UefiUpdateDataHandle.\r
254   @param FwOpcode              The input Framework Opcode.\r
255   @param Width                 The size of the One Of Option. 1 bytes or 2 bytes.\r
256 \r
257   @retval NULL   There is not enough space left in Buffer to add the opcode.\r
258   @retval Other  A pointer to the created opcode.\r
259   \r
260 **/\r
261 UINT8 *\r
262 F2UCreateOneOfOptionOpCode (\r
263   IN OUT   VOID                               *UefiUpdateDataHandle,\r
264   IN CONST FRAMEWORK_EFI_IFR_ONE_OF_OPTION    *FwOpcode,\r
265   IN       UINTN                              Width\r
266   )\r
267 {\r
268   EFI_IFR_ONE_OF_OPTION UOpcode;\r
269 \r
270   ZeroMem (&UOpcode, sizeof(UOpcode));\r
271 \r
272   UOpcode.Header.Length = sizeof(UOpcode);\r
273   UOpcode.Header.OpCode = EFI_IFR_ONE_OF_OPTION_OP;\r
274 \r
275   UOpcode.Option        = FwOpcode->Option;\r
276   CopyMem (&UOpcode.Value.u8, &FwOpcode->Value, Width);\r
277 \r
278   //\r
279   // #define EFI_IFR_FLAG_DEFAULT           0x01\r
280   // #define EFI_IFR_FLAG_MANUFACTURING     0x02\r
281   // #define EFI_IFR_OPTION_DEFAULT                   0x10\r
282   // #define EFI_IFR_OPTION_DEFAULT_MFG               0x20\r
283   //\r
284   UOpcode.Flags = (UINT8) (UOpcode.Flags  | (FwOpcode->Flags & (EFI_IFR_FLAG_DEFAULT | EFI_IFR_FLAG_MANUFACTURING)) << 4);\r
285 \r
286   switch (Width) {\r
287     case 1:\r
288       UOpcode.Type = EFI_IFR_TYPE_NUM_SIZE_8;\r
289       break;\r
290       \r
291     case 2:\r
292       UOpcode.Type = EFI_IFR_TYPE_NUM_SIZE_16;\r
293       break;\r
294       \r
295     default:\r
296       ASSERT (FALSE);\r
297       return NULL;\r
298   }\r
299 \r
300   return HiiCreateRawOpCodes (UefiUpdateDataHandle, (UINT8 *) &UOpcode, sizeof(UOpcode));\r
301 }\r
302 \r
303 /**\r
304   Create a GUID Opcode EFI_IFR_GUID_OPTIONKEY to map the Framework One Of Option callback key\r
305   to a UEFI Question ID. This information is used to invoke the Framework HII Browser Callback\r
306   function. The opcode is appened to UefiUpdateDataHandle.\r
307 \r
308   @param    UefiUpdateDataHandle  The UEFI Update Data buffer.\r
309   @param    QuestionId            The UEFI Question ID.\r
310   @param    OptionValue           The value of the "One Of Option".\r
311   @param    KeyValue              The Framework "One Of Option" callback key.\r
312 \r
313   @retval NULL   There is not enough space left in Buffer to add the opcode.\r
314   @retval Other  A pointer to the created opcode.\r
315 **/\r
316 UINT8 *\r
317 CreateGuidOptionKeyOpCode (\r
318   IN OUT   VOID                        *UefiUpdateDataHandle,\r
319   IN EFI_QUESTION_ID                   QuestionId,\r
320   IN UINT16                            OptionValue,\r
321   IN EFI_QUESTION_ID                   KeyValue\r
322   )\r
323 {\r
324   EFI_IFR_GUID_OPTIONKEY              *UOpcode;\r
325   \r
326   UOpcode = (EFI_IFR_GUID_OPTIONKEY *) HiiCreateGuidOpCode (\r
327                                          UefiUpdateDataHandle, \r
328                                          &gEfiIfrFrameworkGuid, \r
329                                          NULL,\r
330                                          sizeof (EFI_IFR_GUID_OPTIONKEY)\r
331                                          );\r
332 \r
333   UOpcode->ExtendOpCode = EFI_IFR_EXTEND_OP_OPTIONKEY;\r
334   UOpcode->QuestionId  = QuestionId;\r
335   CopyMem (&UOpcode->OptionValue, &OptionValue, sizeof (OptionValue)); \r
336   UOpcode->KeyValue = KeyValue;\r
337 \r
338   return (UINT8 *) UOpcode;\r
339 }\r
340 \r
341 /**\r
342   Create UEFI HII "One Of" Opcode from a Framework HII "One Of" Opcode.\r
343 \r
344   @param UefiUpdateDataHandle     The newly created UEFI HII opcode is appended to UefiUpdateDataHandle.\r
345   @param ThunkContext             The HII Thunk Context.\r
346   @param FwOpcode                 The input Framework Opcode.\r
347   @param NextFwOpcode             Returns the position of the next Framework Opcode after EFI_IFR_END_ONE_OF_OP of\r
348                                   the "One Of Option".\r
349   @param OpcodeCount              The number of Opcode for the complete Framework "One Of" Opcode.\r
350                       \r
351   @retval NULL   There is not enough space left in Buffer to add the opcode.\r
352   @retval Other  A pointer to the created opcode.\r
353   \r
354 **/\r
355 UINT8 *\r
356 F2UCreateOneOfOpCode (\r
357   IN OUT   VOID                        *UefiUpdateDataHandle,\r
358   IN       HII_THUNK_CONTEXT           *ThunkContext,\r
359   IN CONST FRAMEWORK_EFI_IFR_ONE_OF    *FwOpcode,\r
360   OUT      FRAMEWORK_EFI_IFR_OP_HEADER **NextFwOpcode,\r
361   OUT      UINTN                       *OpcodeCount\r
362   )\r
363 {\r
364   EFI_STATUS                          Status;\r
365   EFI_IFR_ONE_OF                      UOpcode;\r
366   FRAMEWORK_EFI_IFR_OP_HEADER         *FwOpHeader;\r
367   FRAMEWORK_EFI_IFR_ONE_OF_OPTION     *FwOneOfOp;\r
368   UINT8                               *OpCodeBuffer;\r
369   UINT8                               *OneOfOpCodeBuffer;\r
370 \r
371   ASSERT (NextFwOpcode != NULL);\r
372   ASSERT (OpcodeCount != NULL);\r
373 \r
374   ZeroMem (&UOpcode, sizeof(UOpcode));\r
375   *OpcodeCount = 0;\r
376 \r
377   UOpcode.Header.Length = sizeof(UOpcode);\r
378   UOpcode.Header.OpCode = EFI_IFR_ONE_OF_OP;\r
379   UOpcode.Header.Scope  = 1;\r
380 \r
381   UOpcode.Question.Header.Prompt = FwOpcode->Prompt;\r
382   UOpcode.Question.Header.Help = FwOpcode->Help;\r
383   UOpcode.Question.VarStoreId  = ThunkContext->FormSet->DefaultVarStoreId;\r
384   UOpcode.Question.VarStoreInfo.VarOffset = FwOpcode->QuestionId;\r
385   \r
386   //\r
387   // Go over the Framework IFR binary to get the QuestionId for generated UEFI One Of Option opcode\r
388   //\r
389   FwOpHeader = (FRAMEWORK_EFI_IFR_OP_HEADER *) ((UINT8 *) FwOpcode + FwOpcode->Header.Length);\r
390   while (FwOpHeader->OpCode != EFI_IFR_END_ONE_OF_OP) {\r
391     ASSERT (FwOpHeader->OpCode == FRAMEWORK_EFI_IFR_ONE_OF_OPTION_OP);\r
392     \r
393     FwOneOfOp = (FRAMEWORK_EFI_IFR_ONE_OF_OPTION *) FwOpHeader;\r
394     if ((FwOneOfOp->Flags & EFI_IFR_FLAG_INTERACTIVE) != 0) {\r
395       UOpcode.Question.Flags |= EFI_IFR_FLAG_CALLBACK;\r
396       \r
397       if (UOpcode.Question.QuestionId == 0) {\r
398         Status = FwQIdToUefiQId (ThunkContext->FormSet, FwOpcode->Header.OpCode, FwOpcode->QuestionId, &UOpcode.Question.QuestionId);\r
399         if (EFI_ERROR (Status)) {\r
400           UOpcode.Question.QuestionId = AssignQuestionId (FwOneOfOp->Key, ThunkContext->FormSet);\r
401         }\r
402       }\r
403 \r
404     }\r
405 \r
406     if ((FwOneOfOp->Flags & EFI_IFR_FLAG_RESET_REQUIRED) == EFI_IFR_FLAG_RESET_REQUIRED) {\r
407       UOpcode.Question.Flags |= EFI_IFR_FLAG_RESET_REQUIRED;\r
408     }\r
409 \r
410     FwOpHeader = (FRAMEWORK_EFI_IFR_OP_HEADER *) ((UINT8 *) FwOpHeader + FwOpHeader->Length);\r
411   }\r
412 \r
413 \r
414   if (UOpcode.Question.QuestionId == 0) {\r
415     //\r
416     // Assign QuestionId if still not assigned.\r
417     //\r
418     Status = FwQIdToUefiQId (ThunkContext->FormSet, FwOpcode->Header.OpCode, FwOpcode->QuestionId, &UOpcode.Question.QuestionId);\r
419     if (EFI_ERROR (Status)) {\r
420       UOpcode.Question.QuestionId = AssignQuestionId (FwOpcode->QuestionId, ThunkContext->FormSet);\r
421     }\r
422   }\r
423   \r
424   OneOfOpCodeBuffer = HiiCreateRawOpCodes (UefiUpdateDataHandle, (UINT8 *) &UOpcode, sizeof (UOpcode));\r
425   if (OneOfOpCodeBuffer == NULL) {\r
426     return NULL;\r
427   }\r
428   *OpcodeCount += 1;\r
429 \r
430   //\r
431   // Go over again the Framework IFR binary to build the UEFI One Of Option opcodes.\r
432   //\r
433   FwOpHeader = (FRAMEWORK_EFI_IFR_OP_HEADER *) ((UINT8 *) FwOpcode + FwOpcode->Header.Length);\r
434   while (FwOpHeader->OpCode != EFI_IFR_END_ONE_OF_OP) {\r
435 \r
436     FwOneOfOp = (FRAMEWORK_EFI_IFR_ONE_OF_OPTION *) FwOpHeader;\r
437       \r
438     OpCodeBuffer = F2UCreateOneOfOptionOpCode (UefiUpdateDataHandle, (FRAMEWORK_EFI_IFR_ONE_OF_OPTION *) FwOpHeader, FwOpcode->Width);\r
439     if (OpCodeBuffer == NULL) {\r
440       return NULL;\r
441     }\r
442 \r
443     OpCodeBuffer = CreateGuidOptionKeyOpCode (UefiUpdateDataHandle, UOpcode.Question.QuestionId, FwOneOfOp->Value, FwOneOfOp->Key);\r
444     if (OpCodeBuffer == NULL) {\r
445       return NULL;\r
446     }\r
447 \r
448     FwOpHeader = (FRAMEWORK_EFI_IFR_OP_HEADER *) ((UINT8 *) FwOpHeader + FwOpHeader->Length);\r
449     *OpcodeCount += 1;\r
450   }\r
451 \r
452   OpCodeBuffer = HiiCreateEndOpCode (UefiUpdateDataHandle);\r
453   if (OpCodeBuffer != NULL) {\r
454     *NextFwOpcode = (FRAMEWORK_EFI_IFR_OP_HEADER *)((UINT8 *) FwOpHeader + FwOpHeader->Length);\r
455     *OpcodeCount += 1;\r
456   }\r
457 \r
458   return OneOfOpCodeBuffer;\r
459 }\r
460 \r
461 /**\r
462   Create UEFI HII "Ordered List" Opcode from a Framework HII "Ordered List" Opcode.\r
463 \r
464   @param UefiUpdateDataHandle The newly created UEFI HII opcode is appended to UefiUpdateDataHandle.\r
465   @param ThunkContext         The HII Thunk Context.\r
466   @param FwOpcode             The input Framework Opcode.\r
467   @param NextFwOpcode         Returns the position of the next Framework Opcode after EFI_IFR_END_ONE_OF_OP of\r
468                               the "Ordered List".\r
469   @param OpcodeCount          The number of Opcode for the complete Framework "Ordered List" Opcode.\r
470                       \r
471   @retval NULL   There is not enough space left in Buffer to add the opcode.\r
472   @retval Other  A pointer to the created opcode.\r
473   \r
474 **/\r
475 UINT8 *\r
476 F2UCreateOrderedListOpCode (\r
477   IN OUT    VOID                          *UefiUpdateDataHandle,\r
478   IN       HII_THUNK_CONTEXT              *ThunkContext,\r
479   IN CONST FRAMEWORK_EFI_IFR_ORDERED_LIST *FwOpcode,\r
480   OUT      FRAMEWORK_EFI_IFR_OP_HEADER    **NextFwOpcode,\r
481   OUT      UINTN                          *OpcodeCount\r
482   )\r
483 {\r
484   EFI_IFR_ORDERED_LIST              UOpcode;\r
485   EFI_STATUS                        Status;\r
486   FRAMEWORK_EFI_IFR_OP_HEADER       *FwOpHeader;\r
487   FRAMEWORK_EFI_IFR_ONE_OF_OPTION   *FwOneOfOp;\r
488   UINT8                             *OpcodeBuffer;   \r
489   UINT8                             *OrderListOpCode;\r
490 \r
491   ZeroMem (&UOpcode, sizeof(UOpcode));\r
492   *OpcodeCount = 0;\r
493 \r
494   UOpcode.Header.Length = sizeof(UOpcode);\r
495   UOpcode.Header.OpCode = EFI_IFR_ORDERED_LIST_OP;\r
496   UOpcode.Header.Scope  = 1;\r
497 \r
498   UOpcode.Question.Header.Prompt = FwOpcode->Prompt;\r
499   UOpcode.Question.Header.Help = FwOpcode->Help;\r
500   UOpcode.Question.VarStoreId  = ThunkContext->FormSet->DefaultVarStoreId;\r
501   UOpcode.Question.VarStoreInfo.VarOffset = FwOpcode->QuestionId;\r
502 \r
503   UOpcode.MaxContainers = FwOpcode->MaxEntries;\r
504 \r
505   //\r
506   // Go over the Framework IFR binary to get the QuestionId for generated UEFI One Of Option opcode\r
507   //\r
508   FwOpHeader = (FRAMEWORK_EFI_IFR_OP_HEADER *) ((UINT8 *) FwOpcode + FwOpcode->Header.Length);\r
509   while (FwOpHeader->OpCode != EFI_IFR_END_ONE_OF_OP) {\r
510     ASSERT (FwOpHeader->OpCode == FRAMEWORK_EFI_IFR_ONE_OF_OPTION_OP);\r
511     \r
512     FwOneOfOp = (FRAMEWORK_EFI_IFR_ONE_OF_OPTION *) FwOpHeader;\r
513     if ((FwOneOfOp->Flags & EFI_IFR_FLAG_INTERACTIVE) != 0) {\r
514       UOpcode.Question.Flags |= EFI_IFR_FLAG_CALLBACK;\r
515       \r
516       if (UOpcode.Question.QuestionId == 0) {\r
517         Status = FwQIdToUefiQId (ThunkContext->FormSet, FwOpcode->Header.OpCode, FwOpcode->QuestionId, &UOpcode.Question.QuestionId);\r
518         if (EFI_ERROR (Status)) {\r
519           UOpcode.Question.QuestionId = AssignQuestionId (FwOneOfOp->Key, ThunkContext->FormSet);\r
520         }\r
521 \r
522       }\r
523     }\r
524 \r
525     if ((FwOneOfOp->Flags & EFI_IFR_FLAG_RESET_REQUIRED) ==  EFI_IFR_FLAG_RESET_REQUIRED) {\r
526       UOpcode.Question.Flags |= EFI_IFR_FLAG_RESET_REQUIRED;\r
527     }\r
528 \r
529     FwOpHeader = (FRAMEWORK_EFI_IFR_OP_HEADER *) ((UINT8 *) FwOpHeader + FwOpHeader->Length);\r
530   }\r
531 \r
532   if (UOpcode.Question.QuestionId == 0) {\r
533     Status = FwQIdToUefiQId (ThunkContext->FormSet, FwOpcode->Header.OpCode, FwOpcode->QuestionId, &UOpcode.Question.QuestionId);\r
534     if (EFI_ERROR (Status)) {\r
535       UOpcode.Question.QuestionId = AssignQuestionId (FwOpcode->QuestionId, ThunkContext->FormSet);\r
536     }\r
537   }\r
538  \r
539   OrderListOpCode = HiiCreateRawOpCodes (UefiUpdateDataHandle, (UINT8 *) &UOpcode, sizeof(UOpcode));\r
540   if (OrderListOpCode == NULL) {\r
541     return NULL;\r
542   }\r
543   *OpcodeCount += 1;\r
544 \r
545   FwOpHeader = (FRAMEWORK_EFI_IFR_OP_HEADER *) ((UINT8 *) FwOpcode + FwOpcode->Header.Length);\r
546   while (FwOpHeader->OpCode != EFI_IFR_END_ONE_OF_OP) {\r
547     //\r
548     // Each entry of Order List in Framework HII is always 1 byte in size\r
549     //\r
550     OpcodeBuffer = F2UCreateOneOfOptionOpCode (UefiUpdateDataHandle, (CONST FRAMEWORK_EFI_IFR_ONE_OF_OPTION *) FwOpHeader, 1);\r
551     if (OpcodeBuffer == NULL) {\r
552       return NULL;\r
553     }\r
554     FwOpHeader = (FRAMEWORK_EFI_IFR_OP_HEADER *) ((UINT8 *) FwOpHeader + FwOpHeader->Length);\r
555     *OpcodeCount += 1;\r
556   }\r
557 \r
558   OpcodeBuffer = HiiCreateEndOpCode (UefiUpdateDataHandle);\r
559   if (OpcodeBuffer != NULL) {\r
560     *NextFwOpcode = (FRAMEWORK_EFI_IFR_OP_HEADER *)((UINT8 *) FwOpHeader + FwOpHeader->Length);\r
561     *OpcodeCount += 1;\r
562   }\r
563 \r
564   return OrderListOpCode;\r
565 }\r
566 \r
567 /**\r
568   Create UEFI HII CheckBox Opcode from a Framework HII Checkbox Opcode.\r
569 \r
570   @param UefiUpdateDataHandle  The newly created UEFI HII opcode is appended to UefiUpdateDataHandle.\r
571   @param ThunkContext          The HII Thunk Context.\r
572   @param FwOpcode              The input Framework Opcode.\r
573 \r
574   @retval NULL   There is not enough space left in Buffer to add the opcode.\r
575   @retval Other  A pointer to the created opcode.\r
576   \r
577 **/\r
578 UINT8 *\r
579 F2UCreateCheckBoxOpCode (\r
580   IN OUT   VOID                        *UefiUpdateDataHandle,\r
581   IN       HII_THUNK_CONTEXT           *ThunkContext,\r
582   IN CONST FRAMEWORK_EFI_IFR_CHECKBOX  *FwOpcode\r
583   )\r
584 {\r
585   EFI_STATUS       Status;\r
586   EFI_IFR_CHECKBOX UOpcode;\r
587 \r
588   ZeroMem (&UOpcode, sizeof(UOpcode));\r
589 \r
590   UOpcode.Header.Length = sizeof(UOpcode);\r
591   UOpcode.Header.OpCode = EFI_IFR_CHECKBOX_OP;\r
592 \r
593   UOpcode.Question.Header.Prompt = FwOpcode->Prompt;\r
594   UOpcode.Question.Header.Help = FwOpcode->Help;\r
595 \r
596   if (FwOpcode->Key == 0) {\r
597     Status = FwQIdToUefiQId (ThunkContext->FormSet, FwOpcode->Header.OpCode, FwOpcode->QuestionId, &UOpcode.Question.QuestionId);\r
598     if (EFI_ERROR (Status)) {\r
599       //\r
600       // Add a new opcode and it will not trigger call back. So we just reuse the FW QuestionId.\r
601       //\r
602       UOpcode.Question.QuestionId = AssignQuestionId (FwOpcode->QuestionId, ThunkContext->FormSet);\r
603     }\r
604   } else {\r
605     UOpcode.Question.QuestionId    = FwOpcode->Key;\r
606   }\r
607 \r
608   //\r
609   // We map 2 flags:\r
610   //      EFI_IFR_FLAG_INTERACTIVE, \r
611   //      EFI_IFR_FLAG_RESET_REQUIRED,\r
612   // to UEFI IFR Opcode Question flags. The rest flags are obsolete.\r
613   //\r
614   UOpcode.Question.Flags  = (UINT8) (FwOpcode->Flags & (EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_RESET_REQUIRED));\r
615 \r
616 \r
617   UOpcode.Question.VarStoreId    = ThunkContext->FormSet->DefaultVarStoreId;\r
618   UOpcode.Question.VarStoreInfo.VarOffset = FwOpcode->QuestionId;\r
619 \r
620   //\r
621   // We also map these 2 flags:\r
622   //      EFI_IFR_FLAG_DEFAULT, \r
623   //      EFI_IFR_FLAG_MANUFACTURING,\r
624   // to UEFI IFR CheckBox Opcode default flags.\r
625   //\r
626   UOpcode.Flags           = (UINT8) (FwOpcode->Flags & (EFI_IFR_FLAG_DEFAULT | EFI_IFR_FLAG_MANUFACTURING));\r
627 \r
628   return HiiCreateRawOpCodes (UefiUpdateDataHandle, (UINT8 *) &UOpcode, sizeof(UOpcode));\r
629 }\r
630 \r
631 \r
632 /**\r
633   Create UEFI HII Numeric Opcode from a Framework HII Numeric Opcode.\r
634 \r
635   @param UefiUpdateDataHandle    The newly created UEFI HII opcode is appended to UefiUpdateDataHandle.\r
636   @param ThunkContext            The HII Thunk Context.\r
637   @param FwOpcode                The input Framework Opcode.\r
638 \r
639   @retval NULL   There is not enough space left in Buffer to add the opcode.\r
640   @retval Other  A pointer to the created opcode.\r
641   \r
642 **/\r
643 UINT8 *\r
644 F2UCreateNumericOpCode (\r
645   IN OUT   VOID                        *UefiUpdateDataHandle,\r
646   IN       HII_THUNK_CONTEXT           *ThunkContext,\r
647   IN CONST FRAMEWORK_EFI_IFR_NUMERIC   *FwOpcode\r
648   )\r
649 {\r
650   EFI_STATUS      Status;\r
651   EFI_IFR_NUMERIC UOpcode;\r
652   EFI_IFR_DEFAULT UOpcodeDefault;\r
653   UINT8           *NumbericOpCode;\r
654   UINT8           *OpcodeBuffer;\r
655 \r
656   ZeroMem (&UOpcode, sizeof(UOpcode));\r
657 \r
658   if (FwOpcode->Key == 0) {\r
659     Status = FwQIdToUefiQId (ThunkContext->FormSet, FwOpcode->Header.OpCode, FwOpcode->QuestionId, &UOpcode.Question.QuestionId);\r
660     if (EFI_ERROR (Status)) {\r
661       //\r
662       // Add a new opcode and it will not trigger call back. So we just reuse the FW QuestionId.\r
663       //\r
664       UOpcode.Question.QuestionId = AssignQuestionId (FwOpcode->QuestionId, ThunkContext->FormSet);\r
665     }\r
666   } else {\r
667     UOpcode.Question.QuestionId    = FwOpcode->Key;\r
668   }\r
669 \r
670   UOpcode.Header.Length = sizeof(UOpcode);\r
671   UOpcode.Header.OpCode = EFI_IFR_NUMERIC_OP;\r
672   //\r
673   // We need to create a nested default value for the UEFI Numeric Opcode.\r
674   // So turn on the scope.\r
675   //\r
676   UOpcode.Header.Scope = 1;\r
677 \r
678   UOpcode.Question.Header.Prompt = FwOpcode->Prompt;\r
679   UOpcode.Question.Header.Help = FwOpcode->Help;\r
680 \r
681   UOpcode.Question.VarStoreId    = ThunkContext->FormSet->DefaultVarStoreId;\r
682   UOpcode.Question.VarStoreInfo.VarOffset = FwOpcode->QuestionId;\r
683 \r
684   UOpcode.Question.Flags  = (UINT8) (FwOpcode->Flags & (EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_RESET_REQUIRED));\r
685 \r
686   //\r
687   // Framework Numeric values are all in UINT16 and displayed as decimal.\r
688   //\r
689   UOpcode.data.u16.MinValue = FwOpcode->Minimum;\r
690   UOpcode.data.u16.MaxValue = FwOpcode->Maximum;\r
691   UOpcode.data.u16.Step = FwOpcode->Step;\r
692 \r
693   switch (FwOpcode->Width) {\r
694     case 1: \r
695     {\r
696       UOpcode.Flags           =  EFI_IFR_NUMERIC_SIZE_1 | EFI_IFR_DISPLAY_UINT_DEC; \r
697       break;\r
698     } \r
699     case 2: \r
700     {\r
701       UOpcode.Flags           =  EFI_IFR_NUMERIC_SIZE_2 | EFI_IFR_DISPLAY_UINT_DEC; \r
702       break;\r
703     }\r
704     default: \r
705     {\r
706       ASSERT (FALSE);\r
707       return NULL;\r
708     }\r
709   }\r
710   \r
711   NumbericOpCode = HiiCreateRawOpCodes (UefiUpdateDataHandle, (UINT8 *) &UOpcode, sizeof(UOpcode));\r
712   if (NumbericOpCode == NULL) {\r
713     return NULL;\r
714   }\r
715 \r
716   //\r
717   // We need to create a default value.\r
718   //\r
719   ZeroMem (&UOpcodeDefault, sizeof (UOpcodeDefault));\r
720   UOpcodeDefault.Header.Length = sizeof (UOpcodeDefault);\r
721   UOpcodeDefault.Header.OpCode = EFI_IFR_DEFAULT_OP;\r
722 \r
723   UOpcodeDefault.DefaultId = 0;\r
724 \r
725   switch (FwOpcode->Width) {\r
726     case 1: \r
727     {\r
728       UOpcodeDefault.Type = EFI_IFR_TYPE_NUM_SIZE_8;\r
729       break;\r
730     } \r
731     case 2: \r
732     {\r
733       UOpcodeDefault.Type = EFI_IFR_TYPE_NUM_SIZE_16;\r
734       break;\r
735     }\r
736   }\r
737 \r
738   CopyMem (&UOpcodeDefault.Value.u8, &FwOpcode->Default, FwOpcode->Width);\r
739 \r
740   OpcodeBuffer = HiiCreateRawOpCodes (UefiUpdateDataHandle, (UINT8 *) &UOpcodeDefault, sizeof(UOpcodeDefault));\r
741   if (OpcodeBuffer == NULL) {\r
742     return NULL;\r
743   }\r
744 \r
745   OpcodeBuffer = HiiCreateEndOpCode (UefiUpdateDataHandle);\r
746   if (OpcodeBuffer == NULL) {\r
747     return NULL;\r
748   }\r
749 \r
750   return NumbericOpCode;\r
751 }\r
752 \r
753 \r
754 /**\r
755   Create UEFI HII String Opcode from a Framework HII String Opcode.\r
756 \r
757   @param UefiUpdateDataHandle     The newly created UEFI HII opcode is appended to UefiUpdateDataHandle.\r
758   @param ThunkContext             The HII Thunk Context.\r
759   @param FwOpcode                 The input Framework Opcode.\r
760 \r
761   @retval NULL   There is not enough space left in Buffer to add the opcode.\r
762   @retval Other  A pointer to the created opcode.\r
763   \r
764 **/\r
765 UINT8 *\r
766 F2UCreateStringOpCode (\r
767   IN OUT   VOID                        *UefiUpdateDataHandle,\r
768   IN       HII_THUNK_CONTEXT           *ThunkContext,\r
769   IN CONST FRAMEWORK_EFI_IFR_STRING    *FwOpcode\r
770   )\r
771 {\r
772   EFI_IFR_STRING UOpcode;\r
773   EFI_STATUS     Status;\r
774 \r
775   ZeroMem (&UOpcode, sizeof(UOpcode));\r
776 \r
777   if (FwOpcode->Key == 0) {\r
778     Status = FwQIdToUefiQId (ThunkContext->FormSet, FwOpcode->Header.OpCode, FwOpcode->QuestionId, &UOpcode.Question.QuestionId);\r
779     if (EFI_ERROR (Status)) {\r
780       //\r
781       // Add a new opcode and it will not trigger call back. So we just reuse the FW QuestionId.\r
782       //\r
783       UOpcode.Question.QuestionId = AssignQuestionId (FwOpcode->QuestionId, ThunkContext->FormSet);\r
784     }\r
785   } else {\r
786     UOpcode.Question.QuestionId    = FwOpcode->Key;\r
787   }\r
788 \r
789   UOpcode.Header.Length = sizeof(UOpcode);\r
790   UOpcode.Header.OpCode = EFI_IFR_STRING_OP;\r
791 \r
792   UOpcode.Question.Header.Prompt = FwOpcode->Prompt;\r
793   UOpcode.Question.Header.Help = FwOpcode->Help;\r
794 \r
795   UOpcode.Question.Flags  = (UINT8) (FwOpcode->Flags & (EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_RESET_REQUIRED));\r
796 \r
797   UOpcode.Question.VarStoreId    = ThunkContext->FormSet->DefaultVarStoreId;\r
798   UOpcode.Question.VarStoreInfo.VarOffset = FwOpcode->QuestionId;\r
799 \r
800   UOpcode.MinSize = FwOpcode->MinSize;\r
801   UOpcode.MaxSize = FwOpcode->MaxSize;\r
802   UOpcode.Flags   = EFI_IFR_STRING_MULTI_LINE;\r
803 \r
804   return HiiCreateRawOpCodes (UefiUpdateDataHandle, (UINT8 *) &UOpcode, sizeof(UOpcode));\r
805 }\r
806 \r
807 /**\r
808   Create UEFI HII Banner Opcode from a Framework HII Banner Opcode.\r
809 \r
810   @param UefiUpdateDataHandle     The newly created UEFI HII opcode is appended to UefiUpdateDataHandle.\r
811   @param FwOpcode                 The input Framework Opcode.\r
812 \r
813   @retval NULL   There is not enough space left in Buffer to add the opcode.\r
814   @retval Other  A pointer to the created opcode.\r
815   \r
816 **/\r
817 UINT8 *\r
818 F2UCreateBannerOpCode (\r
819   IN OUT   VOID              *UefiUpdateDataHandle,\r
820   IN CONST EFI_IFR_BANNER    *FwOpcode\r
821   )\r
822 {\r
823   EFI_IFR_GUID_BANNER *UOpcode;\r
824 \r
825   UOpcode = (EFI_IFR_GUID_BANNER *) HiiCreateGuidOpCode (\r
826                                       UefiUpdateDataHandle, \r
827                                       &gEfiIfrTianoGuid, \r
828                                       NULL,\r
829                                       sizeof (EFI_IFR_GUID_BANNER)\r
830                                       );  \r
831 \r
832   UOpcode->ExtendOpCode = EFI_IFR_EXTEND_OP_BANNER;\r
833   UOpcode->Title          = FwOpcode->Title;\r
834   UOpcode->LineNumber     = FwOpcode->LineNumber;\r
835   UOpcode->Alignment      = FwOpcode->Alignment;\r
836 \r
837   return (UINT8 *) UOpcode;\r
838 }\r
839 \r
840 /**\r
841   Create a Hii Update data Handle used to call IfrLibUpdateForm.\r
842 \r
843   @param ThunkContext         The HII Thunk Context.\r
844   @param FwUpdateData         The Framework Update Data.\r
845   @param UefiOpCodeHandle     The UEFI opcode hanlde.\r
846 \r
847   @retval EFI_SUCCESS       The UEFI Update Data is created successfully.\r
848   @retval EFI_UNSUPPORTED   There is unsupported opcode in FwUpdateData.\r
849   @retval EFI_OUT_OF_RESOURCES There is not enough resource.\r
850 **/\r
851 EFI_STATUS \r
852 FwUpdateDataToUefiUpdateData (\r
853   IN       HII_THUNK_CONTEXT    *ThunkContext,\r
854   IN CONST EFI_HII_UPDATE_DATA  *FwUpdateData,\r
855   IN       VOID                 *UefiOpCodeHandle\r
856   )\r
857 {\r
858   FRAMEWORK_EFI_IFR_OP_HEADER          *FwOpCode;\r
859   FRAMEWORK_EFI_IFR_OP_HEADER          *NextFwOpCode;\r
860   UINTN                                Index;\r
861   UINTN                                DataCount;\r
862   UINT8                                *OpCodeBuffer;\r
863 \r
864   FwOpCode = (FRAMEWORK_EFI_IFR_OP_HEADER *) &FwUpdateData->Data;\r
865 \r
866   for (Index = 0; Index < FwUpdateData->DataCount; Index += DataCount) {\r
867     switch (FwOpCode->OpCode) {\r
868       case FRAMEWORK_EFI_IFR_SUBTITLE_OP:\r
869         OpCodeBuffer = HiiCreateSubTitleOpCode (UefiOpCodeHandle, ((FRAMEWORK_EFI_IFR_SUBTITLE  *) FwOpCode)->SubTitle, 0, 0, 0);\r
870         DataCount = 1;\r
871         break;\r
872         \r
873       case FRAMEWORK_EFI_IFR_TEXT_OP:\r
874         OpCodeBuffer = F2UCreateTextOpCode (UefiOpCodeHandle, (FRAMEWORK_EFI_IFR_TEXT  *) FwOpCode);  \r
875         DataCount = 1;\r
876         break;\r
877 \r
878       case FRAMEWORK_EFI_IFR_REF_OP:\r
879         OpCodeBuffer = F2UCreateReferenceOpCode (UefiOpCodeHandle, (FRAMEWORK_EFI_IFR_REF *) FwOpCode);  \r
880         DataCount = 1;\r
881         break;\r
882         \r
883       case FRAMEWORK_EFI_IFR_ONE_OF_OP:\r
884         OpCodeBuffer = F2UCreateOneOfOpCode (UefiOpCodeHandle, ThunkContext, (FRAMEWORK_EFI_IFR_ONE_OF *) FwOpCode, &NextFwOpCode, &DataCount);\r
885         if (OpCodeBuffer != NULL) {\r
886           FwOpCode = NextFwOpCode;\r
887           //\r
888           // FwOpCode is already updated to point to the next opcode.\r
889           //\r
890           continue;\r
891         }\r
892         break;\r
893 \r
894       case FRAMEWORK_EFI_IFR_ORDERED_LIST_OP:\r
895         OpCodeBuffer = F2UCreateOrderedListOpCode (UefiOpCodeHandle, ThunkContext, (FRAMEWORK_EFI_IFR_ORDERED_LIST *) FwOpCode, &NextFwOpCode, &DataCount);\r
896         if (OpCodeBuffer != NULL) {\r
897           FwOpCode = NextFwOpCode;\r
898           //\r
899           // FwOpCode is already updated to point to the next opcode.\r
900           //\r
901           continue;\r
902         }\r
903         break;\r
904         \r
905       case FRAMEWORK_EFI_IFR_CHECKBOX_OP:\r
906         OpCodeBuffer = F2UCreateCheckBoxOpCode (UefiOpCodeHandle, ThunkContext, (FRAMEWORK_EFI_IFR_CHECKBOX *) FwOpCode);  \r
907         DataCount = 1;\r
908         break;\r
909 \r
910       case FRAMEWORK_EFI_IFR_STRING_OP:\r
911         OpCodeBuffer = F2UCreateStringOpCode (UefiOpCodeHandle, ThunkContext, (FRAMEWORK_EFI_IFR_STRING *) FwOpCode);  \r
912         DataCount = 1;\r
913         break;\r
914 \r
915       case EFI_IFR_BANNER_OP:\r
916         OpCodeBuffer = F2UCreateBannerOpCode (UefiOpCodeHandle, (EFI_IFR_BANNER *) FwOpCode);  \r
917         DataCount = 1;\r
918         break;\r
919 \r
920       case EFI_IFR_END_ONE_OF_OP:\r
921         OpCodeBuffer = HiiCreateEndOpCode (UefiOpCodeHandle);\r
922         DataCount = 1;\r
923         break;\r
924 \r
925       case FRAMEWORK_EFI_IFR_NUMERIC_OP:\r
926         OpCodeBuffer = F2UCreateNumericOpCode (UefiOpCodeHandle, ThunkContext, (FRAMEWORK_EFI_IFR_NUMERIC *) FwOpCode);\r
927         DataCount = 1;\r
928         break;\r
929 \r
930       default:\r
931         ASSERT (FALSE);\r
932         return EFI_UNSUPPORTED;\r
933     }\r
934 \r
935     if (OpCodeBuffer == NULL) {\r
936       return EFI_OUT_OF_RESOURCES;\r
937     }\r
938 \r
939     FwOpCode = (FRAMEWORK_EFI_IFR_OP_HEADER *)((UINT8 *) FwOpCode + FwOpCode->Length);\r
940   }\r
941 \r
942   return EFI_SUCCESS;\r
943 }\r
944 \r