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