]> git.proxmox.com Git - mirror_edk2.git/blob - EdkCompatibilityPkg/Compatibility/FrameworkHiiToUefiHiiThunk/OpcodeCreation.c
Bug fixes for FrameworkHiiToUefiHiiThunk;
[mirror_edk2.git] / EdkCompatibilityPkg / Compatibility / FrameworkHiiToUefiHiiThunk / 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 #include "HiiDatabase.h"
16 #include "OpcodeCreation.h"
17 #include "UefiIfrDefault.h"
18
19 EFI_GUID mTianoExtendedOpcodeGuid = EFI_IFR_TIANO_GUID;
20
21 #define LOCAL_UPDATE_DATA_BUFFER_INCREMENTAL 0x1000
22 EFI_STATUS
23 AppendToUpdateBuffer (
24 IN CONST UINT8 *OpCodeBuf,
25 IN UINTN BufSize,
26 OUT EFI_HII_UPDATE_DATA *UefiData
27 )
28 {
29 UINT8 * NewBuff;
30
31 if (UefiData->Offset + BufSize > UefiData->BufferSize) {
32 NewBuff = AllocateCopyPool (UefiData->BufferSize + LOCAL_UPDATE_DATA_BUFFER_INCREMENTAL, UefiData->Data);
33 if (NewBuff == NULL) {
34 return EFI_OUT_OF_RESOURCES;
35 }
36 UefiData->BufferSize += LOCAL_UPDATE_DATA_BUFFER_INCREMENTAL;
37 FreePool (UefiData->Data);
38 UefiData->Data = NewBuff;
39 }
40
41 CopyMem (UefiData->Data + UefiData->Offset, OpCodeBuf, BufSize);
42 UefiData->Offset += (UINT32) BufSize;
43
44 return EFI_SUCCESS;
45 }
46
47
48
49 EFI_STATUS
50 FwQuestionIdToUefiQuestionId (
51 IN HII_THUNK_CONTEXT *ThunkContext,
52 IN UINT16 VarStoreId,
53 IN UINT16 FwId,
54 OUT EFI_QUESTION_ID *UefiQId
55 )
56 {
57 LIST_ENTRY *MapEntryListHead;
58 LIST_ENTRY *Link;
59 QUESTION_ID_MAP_ENTRY *MapEntry;
60
61 MapEntryListHead = GetMapEntryListHead (ThunkContext, VarStoreId);
62 ASSERT (MapEntryListHead != NULL);
63
64 Link = GetFirstNode (MapEntryListHead);
65
66 while (!IsNull (MapEntryListHead, Link)) {
67 MapEntry = QUESTION_ID_MAP_ENTRY_FROM_LINK (Link);
68
69 if (MapEntry->FwQId == FwId) {
70 *UefiQId = MapEntry->UefiQid;
71 return EFI_SUCCESS;
72 }
73
74 Link = GetNextNode (MapEntryListHead, Link);
75 }
76
77 return EFI_NOT_FOUND;
78 }
79
80
81
82 EFI_STATUS
83 UCreateEndOfOpcode (
84 OUT EFI_HII_UPDATE_DATA *UefiData
85 )
86 {
87 EFI_IFR_END UOpcode;
88
89 ZeroMem (&UOpcode, sizeof (UOpcode));
90
91 UOpcode.Header.OpCode = EFI_IFR_END_OP;
92 UOpcode.Header.Length = sizeof (UOpcode);
93
94 return AppendToUpdateBuffer ((UINT8 *)&UOpcode, sizeof(UOpcode), UefiData);
95 }
96
97 EFI_STATUS
98 F2UCreateSubtitleOpCode (
99 IN CONST FRAMEWORK_EFI_IFR_SUBTITLE *FwSubTitle,
100 OUT EFI_HII_UPDATE_DATA *UefiData
101 )
102 {
103 EFI_IFR_SUBTITLE UOpcode;
104
105 ZeroMem (&UOpcode, sizeof(UOpcode));
106
107 UOpcode.Header.OpCode = EFI_IFR_SUBTITLE_OP;
108 UOpcode.Header.Length = sizeof (EFI_IFR_SUBTITLE);
109
110 UOpcode.Statement.Prompt = FwSubTitle->SubTitle;
111
112 return AppendToUpdateBuffer ((UINT8 *)&UOpcode, sizeof(UOpcode), UefiData);
113 }
114
115 EFI_STATUS
116 F2UCreateTextOpCode (
117 IN CONST FRAMEWORK_EFI_IFR_TEXT *FwText,
118 OUT EFI_HII_UPDATE_DATA *UefiData
119 )
120 {
121 EFI_IFR_TEXT UTextOpCode;
122 EFI_IFR_ACTION UActionOpCode;
123
124 if ((FwText->Flags & FRAMEWORK_EFI_IFR_FLAG_INTERACTIVE) == 0) {
125 ZeroMem (&UTextOpCode, sizeof(UTextOpCode));
126
127 UTextOpCode.Header.OpCode = EFI_IFR_TEXT_OP;
128 UTextOpCode.Header.Length = sizeof (EFI_IFR_TEXT);
129
130 UTextOpCode.Statement.Help = FwText->Help;
131
132 UTextOpCode.Statement.Prompt = FwText->Text;
133 UTextOpCode.TextTwo = FwText->TextTwo;
134
135 return AppendToUpdateBuffer ((UINT8 *) &UTextOpCode, sizeof(UTextOpCode), UefiData);
136 } else {
137 //
138 // Iteractive Text Opcode is EFI_IFR_ACTION
139 //
140
141 ZeroMem (&UActionOpCode, sizeof (UActionOpCode));
142
143 UActionOpCode.Header.OpCode = EFI_IFR_ACTION_OP;
144 UActionOpCode.Header.Length = sizeof (EFI_IFR_ACTION);
145
146 UActionOpCode.Question.Header.Prompt = FwText->Text;
147 UActionOpCode.Question.Header.Help = FwText->Help;
148 UActionOpCode.Question.Flags = EFI_IFR_FLAG_CALLBACK;
149 UActionOpCode.Question.QuestionId = FwText->Key;
150
151 return AppendToUpdateBuffer ((UINT8 *) &UActionOpCode, sizeof(UActionOpCode), UefiData);
152
153 }
154 }
155
156 /*
157 typedef struct {
158 FRAMEWORK_EFI_IFR_OP_HEADER Header;
159 UINT16 FormId;
160 STRING_REF Prompt;
161 STRING_REF Help; // The string Token for the context-help
162 UINT8 Flags; // This is included solely for purposes of interactive/dynamic support.
163 UINT16 Key; // Value to be passed to caller to identify this particular op-code
164 } FRAMEWORK_EFI_IFR_REF;
165
166 */
167 EFI_STATUS
168 F2UCreateGotoOpCode (
169 IN CONST FRAMEWORK_EFI_IFR_REF *FwOpcode,
170 OUT EFI_HII_UPDATE_DATA *UefiData
171 )
172 {
173 EFI_IFR_REF UOpcode;
174
175 ZeroMem (&UOpcode, sizeof(UOpcode));
176
177 UOpcode.Header.Length = sizeof(UOpcode);
178 UOpcode.Header.OpCode = EFI_IFR_REF_OP;
179
180 UOpcode.Question.Header.Prompt = FwOpcode->Prompt;
181 UOpcode.Question.Header.Help = FwOpcode->Help;
182 UOpcode.Question.QuestionId = FwOpcode->Key;
183
184 UOpcode.FormId = FwOpcode->FormId;
185
186 //
187 // We only map FRAMEWORK_EFI_IFR_FLAG_INTERACTIVE and FRAMEWORK_EFI_IFR_FLAG_RESET_REQUIRED to
188 // UEFI IFR Opcode flags. The rest flags are obsolete.
189 //
190 UOpcode.Question.Flags = (FwOpcode->Flags & (FRAMEWORK_EFI_IFR_FLAG_INTERACTIVE | FRAMEWORK_EFI_IFR_FLAG_RESET_REQUIRED));
191
192
193 return AppendToUpdateBuffer ((UINT8 *) &UOpcode, sizeof(UOpcode), UefiData);
194 }
195
196
197 /*
198 typedef struct {
199 FRAMEWORK_EFI_IFR_OP_HEADER Header;
200 STRING_REF Option; // The string token describing the option
201 UINT16 Value; // The value associated with this option that is stored in the NVRAM if chosen
202 UINT8 Flags; // For now, if non-zero, means that it is the default option, - further definition likely above
203 UINT16 Key; // Value to be passed to caller to identify this particular op-code
204 } FRAMEWORK_EFI_IFR_ONE_OF_OPTION;
205
206 typedef union {
207 UINT8 u8;
208 UINT16 u16;
209 UINT32 u32;
210 UINT64 u64;
211 BOOLEAN b;
212 EFI_HII_TIME time;
213 EFI_HII_DATE date;
214 EFI_STRING_ID string;
215 } EFI_IFR_TYPE_VALUE;
216
217 typedef struct _EFI_IFR_ONE_OF_OPTION {
218 EFI_IFR_OP_HEADER Header;
219 EFI_STRING_ID Option;
220 UINT8 Flags;
221 UINT8 Type;
222 EFI_IFR_TYPE_VALUE Value;
223 } EFI_IFR_ONE_OF_OPTION;
224
225 */
226 EFI_STATUS
227 F2UCreateOneOfOptionOpCode (
228 IN CONST FRAMEWORK_EFI_IFR_ONE_OF_OPTION *FwOpcode,
229 IN UINTN Width,
230 OUT EFI_HII_UPDATE_DATA *UefiData
231 )
232 {
233 EFI_IFR_ONE_OF_OPTION UOpcode;
234
235 ZeroMem (&UOpcode, sizeof(UOpcode));
236
237 UOpcode.Header.Length = sizeof(UOpcode);
238 UOpcode.Header.OpCode = EFI_IFR_ONE_OF_OPTION_OP;
239
240 UOpcode.Option = FwOpcode->Option;
241 CopyMem (&UOpcode.Value.u8, &FwOpcode->Value, Width);
242
243 //
244
245 // #define FRAMEWORK_EFI_IFR_FLAG_DEFAULT 0x01
246 // #define FRAMEWORK_EFI_IFR_FLAG_MANUFACTURING 0x02
247 // #define EFI_IFR_OPTION_DEFAULT 0x10
248 // #define EFI_IFR_OPTION_DEFAULT_MFG 0x20
249 //
250 UOpcode.Flags |= (UINT8) ((FwOpcode->Flags & (FRAMEWORK_EFI_IFR_FLAG_DEFAULT | FRAMEWORK_EFI_IFR_FLAG_MANUFACTURING)) << 4);
251
252 switch (Width) {
253 case 1:
254 UOpcode.Type = EFI_IFR_TYPE_NUM_SIZE_8;
255 break;
256
257 case 2:
258 UOpcode.Type = EFI_IFR_TYPE_NUM_SIZE_16;
259 break;
260
261 default:
262 ASSERT (FALSE);
263 return EFI_UNSUPPORTED;
264 }
265
266 return AppendToUpdateBuffer ((UINT8 *) &UOpcode, sizeof(UOpcode), UefiData);
267 }
268
269
270 /*
271 typedef struct _EFI_IFR_QUESTION_HEADER {
272 EFI_IFR_STATEMENT_HEADER Header;
273 EFI_QUESTION_ID QuestionId;
274 EFI_VARSTORE_ID VarStoreId;
275 union {
276 EFI_STRING_ID VarName;
277 UINT16 VarOffset;
278 } VarStoreInfo;
279 UINT8 Flags;
280 } EFI_IFR_QUESTION_HEADER;
281
282 typedef union {
283 struct {
284 UINT8 MinValue;
285 UINT8 MaxValue;
286 UINT8 Step;
287 } u8;
288 struct {
289 UINT16 MinValue;
290 UINT16 MaxValue;
291 UINT16 Step;
292 } u16;
293 struct {
294 UINT32 MinValue;
295 UINT32 MaxValue;
296 UINT32 Step;
297 } u32;
298 struct {
299 UINT64 MinValue;
300 UINT64 MaxValue;
301 UINT64 Step;
302 } u64;
303 } MINMAXSTEP_DATA;
304
305 typedef struct _EFI_IFR_ONE_OF {
306 EFI_IFR_OP_HEADER Header;
307 EFI_IFR_QUESTION_HEADER Question;
308 UINT8 Flags;
309 MINMAXSTEP_DATA data;
310 } EFI_IFR_ONE_OF;
311
312 typedef struct {
313 FRAMEWORK_EFI_IFR_OP_HEADER Header;
314 UINT16 QuestionId; // The ID designating what the question is about...sucked in from a #define, likely in the form of a variable name
315 UINT8 Width; // The Size of the Data being saved
316 STRING_REF Prompt; // The String Token for the Prompt
317 STRING_REF Help; // The string Token for the context-help
318 } FRAMEWORK_EFI_IFR_ONE_OF;
319
320
321 */
322
323 EFI_STATUS
324 F2UCreateOneOfOpCode (
325 IN HII_THUNK_CONTEXT *ThunkContext,
326 IN UINT16 VarStoreId,
327 IN CONST FRAMEWORK_EFI_IFR_ONE_OF *FwOpcode,
328 OUT EFI_HII_UPDATE_DATA *UefiData,
329 OUT FRAMEWORK_EFI_IFR_OP_HEADER **NextFwOpcode,
330 OUT UINTN *DataCount
331 )
332 {
333 EFI_STATUS Status;
334 EFI_IFR_ONE_OF UOpcode;
335 FRAMEWORK_EFI_IFR_OP_HEADER *FwOpHeader;
336 FRAMEWORK_EFI_IFR_ONE_OF_OPTION *FwOneOfOp;
337 ONE_OF_OPTION_MAP *OneOfOptionMap;
338 ONE_OF_OPTION_MAP_ENTRY *OneOfOptionMapEntry;
339
340 ASSERT (NextFwOpcode != NULL);
341 ASSERT (DataCount != NULL);
342
343 OneOfOptionMap = NULL;
344
345 ZeroMem (&UOpcode, sizeof(UOpcode));
346 *DataCount = 0;
347
348 UOpcode.Header.Length = sizeof(UOpcode);
349 UOpcode.Header.OpCode = EFI_IFR_ONE_OF_OP;
350 UOpcode.Header.Scope = 1;
351
352 UOpcode.Question.Header.Prompt = FwOpcode->Prompt;
353 UOpcode.Question.Header.Help = FwOpcode->Help;
354
355 //
356 // Go over the Framework IFR binary to get the QuestionId for generated UEFI One Of Option opcode
357 //
358 FwOpHeader = (FRAMEWORK_EFI_IFR_OP_HEADER *) ((UINT8 *) FwOpcode + FwOpcode->Header.Length);
359 while (FwOpHeader->OpCode != FRAMEWORK_EFI_IFR_END_ONE_OF_OP) {
360 ASSERT (FwOpHeader->OpCode == FRAMEWORK_EFI_IFR_ONE_OF_OPTION_OP);
361
362 FwOneOfOp = (FRAMEWORK_EFI_IFR_ONE_OF_OPTION *) FwOpHeader;
363 if ((FwOneOfOp->Flags & FRAMEWORK_EFI_IFR_FLAG_INTERACTIVE) != 0) {
364 UOpcode.Question.Flags |= EFI_IFR_FLAG_CALLBACK;
365
366 if (UOpcode.Question.QuestionId == 0) {
367 Status = FwQuestionIdToUefiQuestionId (ThunkContext, VarStoreId, FwOpcode->QuestionId, &UOpcode.Question.QuestionId);
368 if (EFI_ERROR (Status)) {
369 UOpcode.Question.QuestionId = FwOneOfOp->Key;
370 }
371
372 OneOfOptionMap = AllocateZeroPool (sizeof (ONE_OF_OPTION_MAP));
373 ASSERT (OneOfOptionMap != NULL);
374 OneOfOptionMap->Signature = ONE_OF_OPTION_MAP_SIGNATURE;
375 OneOfOptionMap->QuestionId = UOpcode.Question.QuestionId;
376 InitializeListHead (&OneOfOptionMap->OneOfOptionMapEntryListHead);
377 switch (FwOpcode->Width) {
378 case 1:
379 OneOfOptionMap->ValueType = EFI_IFR_TYPE_NUM_SIZE_8;
380 break;
381 case 2:
382 OneOfOptionMap->ValueType = EFI_IFR_TYPE_NUM_SIZE_16;
383 default:
384 ASSERT (FALSE);
385 break;
386 }
387
388 InsertTailList (&ThunkContext->OneOfOptionMapListHead, &OneOfOptionMap->Link);
389 } else {
390 OneOfOptionMapEntry = AllocateZeroPool (sizeof (ONE_OF_OPTION_MAP_ENTRY));
391 ASSERT (OneOfOptionMapEntry != NULL);
392
393 OneOfOptionMapEntry->FwKey = FwOneOfOp->Key;
394 OneOfOptionMapEntry->Signature = ONE_OF_OPTION_MAP_ENTRY_SIGNATURE;
395
396 CopyMem (&OneOfOptionMapEntry->Value, &FwOneOfOp->Value, FwOpcode->Width);
397
398 ASSERT (OneOfOptionMap != NULL);
399 InsertTailList (&OneOfOptionMap->OneOfOptionMapEntryListHead, &OneOfOptionMapEntry->Link);
400 }
401 }
402
403 if (FwOneOfOp->Flags & FRAMEWORK_EFI_IFR_FLAG_RESET_REQUIRED) {
404 UOpcode.Question.Flags |= EFI_IFR_FLAG_RESET_REQUIRED;
405 }
406
407 FwOpHeader = (FRAMEWORK_EFI_IFR_OP_HEADER *) ((UINT8 *) FwOpHeader + FwOpHeader->Length);
408 }
409
410
411 if (UOpcode.Question.QuestionId == 0) {
412 //
413 // Assign QuestionId if still not assigned.
414 //
415 Status = FwQuestionIdToUefiQuestionId (ThunkContext, VarStoreId, FwOpcode->QuestionId, &UOpcode.Question.QuestionId);
416 if (EFI_ERROR (Status)) {
417 UOpcode.Question.QuestionId = FwOpcode->QuestionId;
418 }
419 }
420
421 Status = AppendToUpdateBuffer ((UINT8 *) &UOpcode, sizeof (UOpcode), UefiData);
422 if (EFI_ERROR (Status)) {
423 return Status;
424 }
425 *DataCount += 1;
426
427 //
428 // Go over again the Framework IFR binary to build the UEFI One Of Option opcodes.
429 //
430 FwOpHeader = (FRAMEWORK_EFI_IFR_OP_HEADER *) ((UINT8 *) FwOpcode + FwOpcode->Header.Length);
431 while (FwOpHeader->OpCode != FRAMEWORK_EFI_IFR_END_ONE_OF_OP) {
432 Status = F2UCreateOneOfOptionOpCode ((FRAMEWORK_EFI_IFR_ONE_OF_OPTION *) FwOpHeader, FwOpcode->Width, UefiData);
433 if (EFI_ERROR (Status)) {
434 return Status;
435 }
436 FwOpHeader = (FRAMEWORK_EFI_IFR_OP_HEADER *) ((UINT8 *) FwOpHeader + FwOpHeader->Length);
437 *DataCount += 1;
438 }
439
440 Status = UCreateEndOfOpcode (UefiData);
441 if (!EFI_ERROR (Status)) {
442 *NextFwOpcode = (FRAMEWORK_EFI_IFR_OP_HEADER *)((UINT8 *) FwOpHeader + FwOpHeader->Length);
443 *DataCount += 1;
444 }
445
446 return Status;
447 }
448
449 /*
450 typedef struct _EFI_IFR_QUESTION_HEADER {
451 EFI_IFR_STATEMENT_HEADER Header;
452 EFI_QUESTION_ID QuestionId;
453 EFI_VARSTORE_ID VarStoreId;
454 union {
455 EFI_STRING_ID VarName;
456 UINT16 VarOffset;
457 } VarStoreInfo;
458 UINT8 Flags;
459 } EFI_IFR_QUESTION_HEADER;
460
461 typedef struct _EFI_IFR_ORDERED_LIST {
462 EFI_IFR_OP_HEADER Header;
463 EFI_IFR_QUESTION_HEADER Question;
464 UINT8 MaxContainers;
465 UINT8 Flags;
466 } EFI_IFR_ORDERED_LIST;
467
468 typedef struct {
469 FRAMEWORK_EFI_IFR_OP_HEADER Header;
470 UINT16 QuestionId; // The offset in NV for storage of the data
471 UINT8 MaxEntries; // The maximum number of options in the ordered list (=size of NVStore)
472 STRING_REF Prompt; // The string token for the prompt
473 STRING_REF Help; // The string token for the context-help
474 } FRAMEWORK_EFI_IFR_ORDERED_LIST;
475
476 */
477 EFI_STATUS
478 F2UCreateOrderedListOpCode (
479 IN HII_THUNK_CONTEXT *ThunkContext,
480 IN UINT16 VarStoreId,
481 IN CONST FRAMEWORK_EFI_IFR_ORDERED_LIST *FwOpcode,
482 OUT EFI_HII_UPDATE_DATA *UefiData,
483 OUT FRAMEWORK_EFI_IFR_OP_HEADER **NextFwOpcode,
484 OUT UINTN *DataCount
485 )
486 {
487 EFI_IFR_ORDERED_LIST UOpcode;
488 EFI_STATUS Status;
489 FRAMEWORK_EFI_IFR_OP_HEADER *FwOpHeader;
490 FRAMEWORK_EFI_IFR_ONE_OF_OPTION *FwOneOfOp;
491
492 ZeroMem (&UOpcode, sizeof(UOpcode));
493 *DataCount = 0;
494
495 UOpcode.Header.Length = sizeof(UOpcode);
496 UOpcode.Header.OpCode = EFI_IFR_ORDERED_LIST_OP;
497 UOpcode.Header.Scope = 1;
498
499 UOpcode.Question.Header.Prompt = FwOpcode->Prompt;
500 UOpcode.Question.Header.Help = FwOpcode->Help;
501 UOpcode.Question.VarStoreId = VarStoreId;
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 != FRAMEWORK_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 & FRAMEWORK_EFI_IFR_FLAG_INTERACTIVE) != 0) {
514 UOpcode.Question.Flags |= EFI_IFR_FLAG_CALLBACK;
515
516 if (UOpcode.Question.QuestionId == 0) {
517 Status = FwQuestionIdToUefiQuestionId (ThunkContext, VarStoreId, FwOpcode->QuestionId, &UOpcode.Question.QuestionId);
518 if (EFI_ERROR (Status)) {
519 UOpcode.Question.QuestionId = FwOneOfOp->Key;
520 }
521
522 }
523 }
524
525 if (FwOneOfOp->Flags & FRAMEWORK_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 = FwQuestionIdToUefiQuestionId (ThunkContext, VarStoreId, FwOpcode->QuestionId, &UOpcode.Question.QuestionId);
534 if (EFI_ERROR (Status)) {
535 UOpcode.Question.QuestionId = FwOpcode->QuestionId;
536 }
537 }
538
539 Status = AppendToUpdateBuffer ((UINT8 *) &UOpcode, sizeof(UOpcode), UefiData);
540 if (EFI_ERROR (Status)) {
541 return Status;
542 }
543 *DataCount += 1;
544
545 FwOpHeader = (FRAMEWORK_EFI_IFR_OP_HEADER *) ((UINT8 *) FwOpcode + FwOpcode->Header.Length);
546 while (FwOpHeader->OpCode != FRAMEWORK_EFI_IFR_END_ONE_OF_OP) {
547 //
548 // Each entry of Order List in Framework HII is always 1 byte in size
549 //
550 Status = F2UCreateOneOfOptionOpCode ((CONST FRAMEWORK_EFI_IFR_ONE_OF_OPTION *) FwOpHeader, 1, UefiData);
551 if (EFI_ERROR (Status)) {
552 return Status;
553 }
554 FwOpHeader = (FRAMEWORK_EFI_IFR_OP_HEADER *) ((UINT8 *) FwOpHeader + FwOpHeader->Length);
555 *DataCount += 1;
556 }
557
558 Status = UCreateEndOfOpcode (UefiData);
559 if (!EFI_ERROR (Status)) {
560 *NextFwOpcode = (FRAMEWORK_EFI_IFR_OP_HEADER *)((UINT8 *) FwOpHeader + FwOpHeader->Length);
561 *DataCount += 1;
562 }
563
564 return Status;
565 }
566
567 /*
568 typedef struct _EFI_IFR_QUESTION_HEADER {
569 EFI_IFR_STATEMENT_HEADER Header;
570 EFI_QUESTION_ID QuestionId;
571 EFI_VARSTORE_ID VarStoreId;
572 union {
573 EFI_STRING_ID VarName;
574 UINT16 VarOffset;
575 } VarStoreInfo;
576 UINT8 Flags;
577 } EFI_IFR_QUESTION_HEADER;
578 */
579
580 /*
581 typedef struct _EFI_IFR_CHECKBOX {
582 EFI_IFR_OP_HEADER Header;
583 EFI_IFR_QUESTION_HEADER Question;
584 UINT8 Flags;
585 } EFI_IFR_CHECKBOX;
586 */
587
588 /*
589 typedef struct {
590 FRAMEWORK_EFI_IFR_OP_HEADER Header;
591 UINT16 QuestionId; // The ID designating what the question is about...sucked in from a #define, likely in the form of a variable name
592 UINT8 Width; // The Size of the Data being saved
593 STRING_REF Prompt; // The String Token for the Prompt
594 STRING_REF Help; // The string Token for the context-help
595 UINT8 Flags; // For now, if non-zero, means that it is the default option, - further definition likely
596 UINT16 Key; // Value to be passed to caller to identify this particular op-code
597 } FRAMEWORK_EFI_IFR_CHECKBOX, FRAMEWORK_EFI_IFR_CHECK_BOX;
598 */
599
600
601 EFI_STATUS
602 F2UCreateCheckBoxOpCode (
603 IN HII_THUNK_CONTEXT *ThunkContext,
604 IN UINT16 VarStoreId,
605 IN CONST FRAMEWORK_EFI_IFR_CHECKBOX *FwOpcode,
606 OUT EFI_HII_UPDATE_DATA *UefiData
607 )
608 {
609 EFI_STATUS Status;
610 EFI_IFR_CHECKBOX UOpcode;
611
612 ZeroMem (&UOpcode, sizeof(UOpcode));
613
614 UOpcode.Header.Length = sizeof(UOpcode);
615 UOpcode.Header.OpCode = EFI_IFR_CHECKBOX_OP;
616
617 UOpcode.Question.Header.Prompt = FwOpcode->Prompt;
618 UOpcode.Question.Header.Help = FwOpcode->Help;
619
620 if (FwOpcode->Key == 0) {
621 Status = FwQuestionIdToUefiQuestionId (ThunkContext, VarStoreId, FwOpcode->QuestionId, &UOpcode.Question.QuestionId);
622 if (EFI_ERROR (Status)) {
623 //
624 // Add a new opcode and it will not trigger call back. So we just reuse the FW QuestionId.
625 //
626 UOpcode.Question.QuestionId = FwOpcode->QuestionId;
627 }
628 } else {
629 UOpcode.Question.QuestionId = FwOpcode->Key;
630 }
631
632 UOpcode.Question.VarStoreId = RESERVED_VARSTORE_ID;
633 UOpcode.Question.VarStoreInfo.VarOffset = FwOpcode->QuestionId;
634
635 //
636 // We only map 2 flags:
637 // FRAMEWORK_EFI_IFR_FLAG_INTERACTIVE,
638 // FRAMEWORK_EFI_IFR_FLAG_RESET_REQUIRED,
639 // to UEFI IFR Opcode Question flags. The rest flags are obsolete.
640 //
641 UOpcode.Question.Flags = (FwOpcode->Flags & (FRAMEWORK_EFI_IFR_FLAG_INTERACTIVE | FRAMEWORK_EFI_IFR_FLAG_RESET_REQUIRED));
642
643 //
644 // We also map 2 flags:
645 // FRAMEWORK_EFI_IFR_FLAG_DEFAULT,
646 // FRAMEWORK_EFI_IFR_FLAG_MANUFACTURING,
647 // to UEFI IFR CheckBox Opcode default flags.
648 //
649 UOpcode.Flags = (FwOpcode->Flags & (FRAMEWORK_EFI_IFR_FLAG_DEFAULT | FRAMEWORK_EFI_IFR_FLAG_MANUFACTURING));
650
651 return AppendToUpdateBuffer ((UINT8 *) &UOpcode, sizeof(UOpcode), UefiData);
652 }
653
654
655 /*
656 typedef struct _EFI_IFR_QUESTION_HEADER {
657 EFI_IFR_STATEMENT_HEADER Header;
658 EFI_QUESTION_ID QuestionId;
659 EFI_VARSTORE_ID VarStoreId;
660 union {
661 EFI_STRING_ID VarName;
662 UINT16 VarOffset;
663 } VarStoreInfo;
664 UINT8 Flags;
665 } EFI_IFR_QUESTION_HEADER;
666
667 typedef union {
668 struct {
669 UINT8 MinValue;
670 UINT8 MaxValue;
671 UINT8 Step;
672 } u8;
673 struct {
674 UINT16 MinValue;
675 UINT16 MaxValue;
676 UINT16 Step;
677 } u16;
678 struct {
679 UINT32 MinValue;
680 UINT32 MaxValue;
681 UINT32 Step;
682 } u32;
683 struct {
684 UINT64 MinValue;
685 UINT64 MaxValue;
686 UINT64 Step;
687 } u64;
688 } MINMAXSTEP_DATA;
689
690 typedef struct _EFI_IFR_NUMERIC {
691 EFI_IFR_OP_HEADER Header;
692 EFI_IFR_QUESTION_HEADER Question;
693 UINT8 Flags;
694 MINMAXSTEP_DATA data;
695 } EFI_IFR_NUMERIC;
696
697
698 typedef struct {
699 FRAMEWORK_EFI_IFR_OP_HEADER Header;
700 UINT16 QuestionId; // The ID designating what the question is about...sucked in from a #define, likely in the form of a variable name
701 UINT8 Width; // The Size of the Data being saved
702 STRING_REF Prompt; // The String Token for the Prompt
703 STRING_REF Help; // The string Token for the context-help
704 UINT8 Flags; // This is included solely for purposes of interactive/dynamic support.
705 UINT16 Key; // Value to be passed to caller to identify this particular op-code
706 UINT16 Minimum;
707 UINT16 Maximum;
708 UINT16 Step; // If step is 0, then manual input is specified, otherwise, left/right arrow selection is called for
709 UINT16 Default;
710 } FRAMEWORK_EFI_IFR_NUMERIC;
711
712 */
713
714
715 EFI_STATUS
716 F2UCreateNumericOpCode (
717 IN HII_THUNK_CONTEXT *ThunkContext,
718 IN UINT16 VarStoreId,
719 IN CONST FRAMEWORK_EFI_IFR_NUMERIC *FwOpcode,
720 OUT EFI_HII_UPDATE_DATA *UefiData
721 )
722 {
723 EFI_STATUS Status;
724 EFI_IFR_NUMERIC UOpcode;
725 EFI_IFR_DEFAULT UOpcodeDefault;
726
727 ZeroMem (&UOpcode, sizeof(UOpcode));
728
729 if (FwOpcode->Key == 0) {
730 Status = FwQuestionIdToUefiQuestionId (ThunkContext, VarStoreId, FwOpcode->QuestionId, &UOpcode.Question.QuestionId);
731 if (EFI_ERROR (Status)) {
732 //
733 // Add a new opcode and it will not trigger call back. So we just reuse the FW QuestionId.
734 //
735 UOpcode.Question.QuestionId = FwOpcode->QuestionId;
736 }
737 } else {
738 UOpcode.Question.QuestionId = FwOpcode->Key;
739 }
740
741 UOpcode.Header.Length = sizeof(UOpcode);
742 UOpcode.Header.OpCode = EFI_IFR_NUMERIC_OP;
743 //
744 // We need to create a nested default value for the UEFI Numeric Opcode.
745 // So turn on the scope.
746 //
747 if (FwOpcode->Default != 0) {
748 UOpcode.Header.Scope = 1;
749 }
750
751 UOpcode.Question.Header.Prompt = FwOpcode->Prompt;
752 UOpcode.Question.Header.Help = FwOpcode->Help;
753
754 UOpcode.Question.QuestionId = FwOpcode->Key;
755 //
756 // BUGBUG RESERVED_VARSTORE_ID should be passed in.
757 //
758 UOpcode.Question.VarStoreId = RESERVED_VARSTORE_ID;
759 UOpcode.Question.VarStoreInfo.VarOffset = FwOpcode->QuestionId;
760
761 UOpcode.Question.Flags = (FwOpcode->Flags & (FRAMEWORK_EFI_IFR_FLAG_INTERACTIVE | FRAMEWORK_EFI_IFR_FLAG_RESET_REQUIRED));
762
763 //
764 // Framework Numeric values are all in UINT16 and displayed as decimal.
765 //
766 UOpcode.data.u16.MinValue = FwOpcode->Minimum;
767 UOpcode.data.u16.MaxValue = FwOpcode->Maximum;
768 UOpcode.data.u16.Step = FwOpcode->Step;
769
770 switch (FwOpcode->Width) {
771 case 1:
772 {
773 UOpcode.Flags = EFI_IFR_NUMERIC_SIZE_2 | EFI_IFR_DISPLAY_UINT_DEC;
774 break;
775 }
776 case 2:
777 {
778 UOpcode.Flags = EFI_IFR_NUMERIC_SIZE_1 | EFI_IFR_DISPLAY_UINT_DEC;
779 break;
780 }
781 default:
782 {
783 ASSERT (FALSE);
784 return EFI_INVALID_PARAMETER;
785 }
786 }
787
788 Status = AppendToUpdateBuffer ((UINT8 *) &UOpcode, sizeof(UOpcode), UefiData);
789 if (EFI_ERROR (Status)) {
790 return Status;
791 }
792
793 //
794 // We need to create a default value.
795 //
796 if (FwOpcode->Default != 0) {
797 ZeroMem (&UOpcodeDefault, sizeof (UOpcodeDefault));
798 UOpcodeDefault.Header.Length = sizeof (UOpcodeDefault);
799 UOpcodeDefault.Header.OpCode = EFI_IFR_DEFAULT_OP;
800
801 UOpcodeDefault.DefaultId = 0;
802
803 switch (FwOpcode->Width) {
804 case 1:
805 {
806 UOpcodeDefault.Type = EFI_IFR_TYPE_NUM_SIZE_8;
807 break;
808 }
809 case 2:
810 {
811 UOpcodeDefault.Type = EFI_IFR_TYPE_NUM_SIZE_16;
812 break;
813 }
814 }
815
816 CopyMem (&UOpcodeDefault.Value.u8, &FwOpcode->Default, FwOpcode->Width);
817
818 Status = AppendToUpdateBuffer ((UINT8 *) &UOpcodeDefault, sizeof(UOpcodeDefault), UefiData);
819 if (EFI_ERROR (Status)) {
820 return Status;
821 }
822 Status = UCreateEndOfOpcode (UefiData);
823 }
824
825 return Status;
826 }
827
828
829 /*
830
831 typedef struct _EFI_IFR_QUESTION_HEADER {
832 EFI_IFR_STATEMENT_HEADER Header;
833 EFI_QUESTION_ID QuestionId;
834 EFI_VARSTORE_ID VarStoreId;
835 union {
836 EFI_STRING_ID VarName;
837 UINT16 VarOffset;
838 } VarStoreInfo;
839 UINT8 Flags;
840 } EFI_IFR_QUESTION_HEADER;
841
842 typedef struct _EFI_IFR_STRING {
843 EFI_IFR_OP_HEADER Header;
844 EFI_IFR_QUESTION_HEADER Question;
845 UINT8 MinSize;
846 UINT8 MaxSize;
847 UINT8 Flags;
848 } EFI_IFR_STRING;
849
850
851 typedef struct {
852 FRAMEWORK_EFI_IFR_OP_HEADER Header;
853 UINT16 QuestionId; // The ID designating what the question is about...sucked in from a #define, likely in the form of a variable name
854 UINT8 Width; // The Size of the Data being saved -- BUGBUG -- remove someday
855 STRING_REF Prompt; // The String Token for the Prompt
856 STRING_REF Help; // The string Token for the context-help
857 UINT8 Flags; // This is included solely for purposes of interactive/dynamic support.
858 UINT16 Key; // Value to be passed to caller to identify this particular op-code
859 UINT8 MinSize; // Minimum allowable sized password
860 UINT8 MaxSize; // Maximum allowable sized password
861 } FRAMEWORK_EFI_IFR_STRING;
862
863
864 */
865
866 EFI_STATUS
867 F2UCreateStringOpCode (
868 IN HII_THUNK_CONTEXT *ThunkContext,
869 IN UINT16 VarStoreId,
870 IN CONST FRAMEWORK_EFI_IFR_STRING *FwOpcode,
871 OUT EFI_HII_UPDATE_DATA *UefiData
872 )
873 {
874 EFI_IFR_STRING UOpcode;
875
876 ZeroMem (&UOpcode, sizeof(UOpcode));
877
878 if (FwOpcode->Key == 0) {
879 FwQuestionIdToUefiQuestionId (ThunkContext, VarStoreId, FwOpcode->QuestionId, &UOpcode.Question.QuestionId);
880 } else {
881 UOpcode.Question.QuestionId = FwOpcode->Key;
882 }
883
884 UOpcode.Header.Length = sizeof(UOpcode);
885 UOpcode.Header.OpCode = EFI_IFR_STRING_OP;
886
887 UOpcode.Question.Header.Prompt = FwOpcode->Prompt;
888 UOpcode.Question.Header.Help = FwOpcode->Help;
889
890 UOpcode.Question.QuestionId = FwOpcode->Key;
891 UOpcode.Question.VarStoreId = RESERVED_VARSTORE_ID;
892 UOpcode.Question.VarStoreInfo.VarOffset = FwOpcode->QuestionId;
893
894 UOpcode.Question.Flags = (FwOpcode->Flags & (FRAMEWORK_EFI_IFR_FLAG_INTERACTIVE | FRAMEWORK_EFI_IFR_FLAG_RESET_REQUIRED));
895
896 UOpcode.MinSize = FwOpcode->MinSize;
897 UOpcode.MaxSize = FwOpcode->MaxSize;
898 UOpcode.Flags = EFI_IFR_STRING_MULTI_LINE;
899
900 return AppendToUpdateBuffer ((UINT8 *) &UOpcode, sizeof(UOpcode), UefiData);
901 }
902
903 /*
904 typedef struct _EFI_IFR_GUID_BANNER {
905 EFI_IFR_OP_HEADER Header;
906 EFI_GUID Guid;
907 UINT8 ExtendOpCode; // Extended opcode is EFI_IFR_EXTEND_OP_BANNER
908 EFI_STRING_ID Title; // The string token for the banner title
909 UINT16 LineNumber; // 1-based line number
910 UINT8 Alignment; // left, center, or right-aligned
911 } EFI_IFR_GUID_BANNER;
912
913 typedef struct {
914 FRAMEWORK_EFI_IFR_OP_HEADER Header;
915 STRING_REF Title; // The string token for the banner title
916 UINT16 LineNumber; // 1-based line number
917 UINT8 Alignment; // left, center, or right-aligned
918 } FRAMEWORK_EFI_IFR_BANNER;
919
920 */
921
922 EFI_STATUS
923 F2UCreateBannerOpCode (
924 IN CONST FRAMEWORK_EFI_IFR_BANNER *FwOpcode,
925 OUT EFI_HII_UPDATE_DATA *UefiData
926 )
927 {
928 EFI_IFR_GUID_BANNER UOpcode;
929
930 ZeroMem (&UOpcode, sizeof(UOpcode));
931
932 UOpcode.Header.Length = sizeof(UOpcode);
933 UOpcode.Header.OpCode = EFI_IFR_GUID_OP;
934
935 CopyMem (&UOpcode.Guid, &mTianoExtendedOpcodeGuid, sizeof (EFI_GUID));
936 UOpcode.ExtendOpCode = EFI_IFR_EXTEND_OP_BANNER;
937 UOpcode.Title = FwOpcode->Title;
938 UOpcode.LineNumber = FwOpcode->LineNumber;
939 UOpcode.Alignment = FwOpcode->Alignment;
940
941 return AppendToUpdateBuffer ((UINT8 *) &UOpcode, sizeof(UOpcode), UefiData);
942 }
943
944
945 EFI_STATUS
946 FwUpdateDataToUefiUpdateData (
947 IN HII_THUNK_CONTEXT *ThunkContext,
948 IN CONST FRAMEWORK_EFI_HII_UPDATE_DATA *Data,
949 IN BOOLEAN AddData,
950 OUT EFI_HII_UPDATE_DATA **UefiData
951 )
952 {
953 FRAMEWORK_EFI_IFR_OP_HEADER *FwOpCode;
954 FRAMEWORK_EFI_IFR_OP_HEADER *NextFwOpCode;
955 EFI_HII_UPDATE_DATA *UefiOpCode;
956 UINTN Index;
957 EFI_STATUS Status;
958 UINTN DataCount;
959 UINT16 VarStoreId;
960
961 //
962 // Assume all dynamic opcode created is using active variable with VarStoreId of 1.
963 //
964 VarStoreId = 1;
965
966 UefiOpCode = AllocateZeroPool (sizeof (EFI_HII_UPDATE_DATA));
967 if (UefiOpCode == NULL) {
968 return EFI_OUT_OF_RESOURCES;
969 }
970
971 UefiOpCode->Data = AllocateZeroPool (LOCAL_UPDATE_DATA_BUFFER_INCREMENTAL);
972 if (UefiOpCode->Data == NULL) {
973 return EFI_OUT_OF_RESOURCES;
974 }
975
976 UefiOpCode->BufferSize = LOCAL_UPDATE_DATA_BUFFER_INCREMENTAL;
977 UefiOpCode->Offset = 0;
978
979 FwOpCode = (FRAMEWORK_EFI_IFR_OP_HEADER *) &Data->Data;
980
981 for (Index = 0; Index < Data->DataCount; Index += DataCount) {
982 switch (FwOpCode->OpCode) {
983 case FRAMEWORK_EFI_IFR_SUBTITLE_OP:
984 Status = F2UCreateSubtitleOpCode ((FRAMEWORK_EFI_IFR_SUBTITLE *) FwOpCode, UefiOpCode);
985 DataCount = 1;
986 break;
987
988 case FRAMEWORK_EFI_IFR_TEXT_OP:
989 Status = F2UCreateTextOpCode ((FRAMEWORK_EFI_IFR_TEXT *) FwOpCode, UefiOpCode);
990 DataCount = 1;
991 break;
992
993 case FRAMEWORK_EFI_IFR_REF_OP:
994 Status = F2UCreateGotoOpCode ((FRAMEWORK_EFI_IFR_REF *) FwOpCode, UefiOpCode);
995 DataCount = 1;
996 break;
997
998 case FRAMEWORK_EFI_IFR_ONE_OF_OP:
999 Status = F2UCreateOneOfOpCode (ThunkContext, VarStoreId, (FRAMEWORK_EFI_IFR_ONE_OF *) FwOpCode, UefiOpCode, &NextFwOpCode, &DataCount);
1000 if (!EFI_ERROR (Status)) {
1001 FwOpCode = NextFwOpCode;
1002 //
1003 // FwOpCode is already updated to point to the next opcode.
1004 //
1005 continue;
1006 }
1007 break;
1008
1009 case FRAMEWORK_EFI_IFR_ORDERED_LIST_OP:
1010 Status = F2UCreateOrderedListOpCode (ThunkContext, VarStoreId, (FRAMEWORK_EFI_IFR_ORDERED_LIST *) FwOpCode, UefiOpCode, &NextFwOpCode, &DataCount);
1011 if (!EFI_ERROR (Status)) {
1012 FwOpCode = NextFwOpCode;
1013 //
1014 // FwOpCode is already updated to point to the next opcode.
1015 //
1016 continue;
1017 }
1018 break;
1019
1020 case FRAMEWORK_EFI_IFR_CHECKBOX_OP:
1021 Status = F2UCreateCheckBoxOpCode (ThunkContext, VarStoreId, (FRAMEWORK_EFI_IFR_CHECKBOX *) FwOpCode, UefiOpCode);
1022 DataCount = 1;
1023 break;
1024
1025 case FRAMEWORK_EFI_IFR_STRING_OP:
1026 Status = F2UCreateStringOpCode (ThunkContext, VarStoreId, (FRAMEWORK_EFI_IFR_STRING *) FwOpCode, UefiOpCode);
1027 DataCount = 1;
1028 break;
1029
1030 case FRAMEWORK_EFI_IFR_BANNER_OP:
1031 Status = F2UCreateBannerOpCode ((FRAMEWORK_EFI_IFR_BANNER *) FwOpCode, UefiOpCode);
1032 DataCount = 1;
1033 break;
1034
1035 case FRAMEWORK_EFI_IFR_END_ONE_OF_OP:
1036 Status = UCreateEndOfOpcode (UefiOpCode);
1037 DataCount = 1;
1038 break;
1039
1040 default:
1041 ASSERT (FALSE);
1042 return EFI_UNSUPPORTED;
1043 }
1044
1045 if (EFI_ERROR (Status)) {
1046 FreePool (UefiOpCode->Data);
1047 FreePool (UefiOpCode);
1048 return Status;
1049 }
1050
1051 FwOpCode = (FRAMEWORK_EFI_IFR_OP_HEADER *)((UINT8 *) FwOpCode + FwOpCode->Length);
1052 }
1053
1054 *UefiData = UefiOpCode;
1055
1056 return EFI_SUCCESS;
1057 }
1058