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