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