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