1 /*++
2 
3 Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.<BR>
4 This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution.  The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
8 
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11 
12 Module Name:
13 
14   UefiIfrOpCodeCreation.c
15 
16 Abstract:
17 
18   Library Routines to create IFR independent of string data - assume tokens already exist
19   Primarily to be used for exporting op-codes at a label in pre-defined forms.
20 
21 Revision History:
22 
23 --*/
24 
25 #include "UefiIfrLibrary.h"
26 
27 EFI_GUID mIfrVendorGuid = EFI_IFR_TIANO_GUID;
28 
29 STATIC
30 BOOLEAN
IsValidQuestionFlags(IN UINT8 Flags)31 IsValidQuestionFlags (
32   IN UINT8                   Flags
33   )
34 {
35   return (BOOLEAN)((Flags & (~QUESTION_FLAGS)) ? FALSE : TRUE);
36 }
37 
38 STATIC
39 BOOLEAN
IsValidValueType(IN UINT8 Type)40 IsValidValueType (
41   IN UINT8                   Type
42   )
43 {
44   return (BOOLEAN)((Type <= EFI_IFR_TYPE_OTHER) ? TRUE : FALSE);
45 }
46 
47 STATIC
48 BOOLEAN
IsValidNumricFlags(IN UINT8 Flags)49 IsValidNumricFlags (
50   IN UINT8                   Flags
51   )
52 {
53   if (Flags & ~(EFI_IFR_NUMERIC_SIZE | EFI_IFR_DISPLAY)) {
54     return FALSE;
55   }
56 
57   if ((Flags & EFI_IFR_DISPLAY) > EFI_IFR_DISPLAY_UINT_HEX) {
58     return FALSE;
59   }
60 
61   return TRUE;
62 }
63 
64 STATIC
65 BOOLEAN
IsValidCheckboxFlags(IN UINT8 Flags)66 IsValidCheckboxFlags (
67   IN UINT8                   Flags
68   )
69 {
70   return (BOOLEAN)((Flags <= EFI_IFR_CHECKBOX_DEFAULT_MFG) ? TRUE : FALSE);
71 }
72 
73 EFI_STATUS
CreateEndOpCode(IN OUT EFI_HII_UPDATE_DATA * Data)74 CreateEndOpCode (
75   IN OUT EFI_HII_UPDATE_DATA *Data
76   )
77 {
78   EFI_IFR_END                 End;
79   UINT8                       *LocalBuffer;
80 
81   ASSERT (Data != NULL && Data->Data != NULL);
82 
83   if (Data->Offset + sizeof (EFI_IFR_END) > Data->BufferSize) {
84     return EFI_BUFFER_TOO_SMALL;
85   }
86 
87   End.Header.Length  = (UINT8) sizeof (EFI_IFR_END);
88   End.Header.OpCode  = EFI_IFR_END_OP;
89   End.Header.Scope   = 0;
90 
91   LocalBuffer = (UINT8 *) Data->Data + Data->Offset;
92   EfiCopyMem (LocalBuffer, &End, sizeof (EFI_IFR_END));
93   Data->Offset += sizeof (EFI_IFR_END);
94 
95   return EFI_SUCCESS;
96 }
97 
98 EFI_STATUS
CreateDefaultOpCode(IN EFI_IFR_TYPE_VALUE * Value,IN UINT8 Type,IN OUT EFI_HII_UPDATE_DATA * Data)99 CreateDefaultOpCode (
100   IN     EFI_IFR_TYPE_VALUE  *Value,
101   IN     UINT8               Type,
102   IN OUT EFI_HII_UPDATE_DATA *Data
103   )
104 {
105   EFI_IFR_DEFAULT            Default;
106   UINT8                      *LocalBuffer;
107 
108   ASSERT (Data != NULL && Data->Data != NULL);
109 
110   if ((Value == NULL) || !IsValidValueType (Type)) {
111     return EFI_INVALID_PARAMETER;
112   }
113 
114   if (Data->Offset + sizeof (EFI_IFR_DEFAULT) > Data->BufferSize) {
115     return EFI_BUFFER_TOO_SMALL;
116   }
117 
118   Default.Header.OpCode = EFI_IFR_DEFAULT_OP;
119   Default.Header.Length = (UINT8) sizeof (EFI_IFR_DEFAULT);
120   Default.Header.Scope  = 0;
121   Default.Type          = Type;
122   Default.DefaultId     = EFI_HII_DEFAULT_CLASS_STANDARD;
123   EfiCopyMem (&Default.Value, Value, sizeof(EFI_IFR_TYPE_VALUE));
124 
125   LocalBuffer = (UINT8 *) Data->Data + Data->Offset;
126   EfiCopyMem (LocalBuffer, &Default, sizeof (EFI_IFR_DEFAULT));
127   Data->Offset += sizeof (EFI_IFR_DEFAULT);
128 
129   return EFI_SUCCESS;
130 }
131 
132 EFI_STATUS
CreateActionOpCode(IN EFI_QUESTION_ID QuestionId,IN EFI_STRING_ID Prompt,IN EFI_STRING_ID Help,IN UINT8 QuestionFlags,IN EFI_STRING_ID QuestionConfig,IN OUT EFI_HII_UPDATE_DATA * Data)133 CreateActionOpCode (
134   IN     EFI_QUESTION_ID      QuestionId,
135   IN     EFI_STRING_ID        Prompt,
136   IN     EFI_STRING_ID        Help,
137   IN     UINT8                QuestionFlags,
138   IN     EFI_STRING_ID        QuestionConfig,
139   IN OUT EFI_HII_UPDATE_DATA  *Data
140   )
141 {
142   EFI_IFR_ACTION              Action;
143   UINT8                       *LocalBuffer;
144 
145   ASSERT (Data != NULL && Data->Data != NULL);
146 
147   if (!IsValidQuestionFlags (QuestionFlags)) {
148     return EFI_INVALID_PARAMETER;
149   }
150 
151   if (Data->Offset + sizeof (EFI_IFR_ACTION) > Data->BufferSize) {
152     return EFI_BUFFER_TOO_SMALL;
153   }
154 
155   Action.Header.OpCode          = EFI_IFR_ACTION_OP;
156   Action.Header.Length          = (UINT8) sizeof (EFI_IFR_ACTION);
157   Action.Header.Scope           = 0;
158   Action.Question.QuestionId    = QuestionId;
159   Action.Question.Header.Prompt = Prompt;
160   Action.Question.Header.Help   = Help;
161   Action.Question.VarStoreId    = INVALID_VARSTORE_ID;
162   Action.Question.Flags         = QuestionFlags;
163   Action.QuestionConfig         = QuestionConfig;
164 
165   LocalBuffer = (UINT8 *) Data->Data + Data->Offset;
166   EfiCopyMem (LocalBuffer, &Action, sizeof (EFI_IFR_ACTION));
167   Data->Offset += sizeof (EFI_IFR_ACTION);
168 
169   return EFI_SUCCESS;
170 }
171 
172 EFI_STATUS
CreateSubTitleOpCode(IN EFI_STRING_ID Prompt,IN EFI_STRING_ID Help,IN UINT8 Flags,IN UINT8 Scope,IN OUT EFI_HII_UPDATE_DATA * Data)173 CreateSubTitleOpCode (
174   IN      EFI_STRING_ID       Prompt,
175   IN      EFI_STRING_ID       Help,
176   IN      UINT8               Flags,
177   IN      UINT8               Scope,
178   IN OUT EFI_HII_UPDATE_DATA  *Data
179   )
180 {
181   EFI_IFR_SUBTITLE            Subtitle;
182   UINT8                       *LocalBuffer;
183 
184   ASSERT (Data != NULL && Data->Data != NULL);
185 
186   if (Data->Offset + sizeof (EFI_IFR_SUBTITLE) > Data->BufferSize) {
187     return EFI_BUFFER_TOO_SMALL;
188   }
189 
190   Subtitle.Header.OpCode    = EFI_IFR_SUBTITLE_OP;
191   Subtitle.Header.Length    = (UINT8) sizeof (EFI_IFR_SUBTITLE);
192   Subtitle.Header.Scope     = Scope;
193   Subtitle.Statement.Prompt = Prompt;
194   Subtitle.Statement.Help   = Help;
195   Subtitle.Flags            = Flags;
196 
197   LocalBuffer = (UINT8 *) Data->Data + Data->Offset;
198   EfiCopyMem (LocalBuffer, &Subtitle, sizeof (EFI_IFR_SUBTITLE));
199   Data->Offset += sizeof (EFI_IFR_SUBTITLE);
200 
201   return EFI_SUCCESS;
202 }
203 
204 
205 EFI_STATUS
CreateTextOpCode(IN EFI_STRING_ID Prompt,IN EFI_STRING_ID Help,IN EFI_STRING_ID TextTwo,IN OUT EFI_HII_UPDATE_DATA * Data)206 CreateTextOpCode (
207   IN     EFI_STRING_ID        Prompt,
208   IN     EFI_STRING_ID        Help,
209   IN     EFI_STRING_ID        TextTwo,
210   IN OUT EFI_HII_UPDATE_DATA  *Data
211   )
212 {
213   EFI_IFR_TEXT                Text;
214   UINT8                       *LocalBuffer;
215 
216   ASSERT (Data != NULL && Data->Data != NULL);
217 
218   if (Data->Offset + sizeof (EFI_IFR_TEXT) > Data->BufferSize) {
219     return EFI_BUFFER_TOO_SMALL;
220   }
221 
222   Text.Header.OpCode    = EFI_IFR_TEXT_OP;
223   Text.Header.Length    = (UINT8) sizeof (EFI_IFR_TEXT);
224   Text.Header.Scope     = 0;
225   Text.Statement.Prompt = Prompt;
226   Text.Statement.Help   = Help;
227   Text.TextTwo          = TextTwo;
228 
229   LocalBuffer = (UINT8 *) Data->Data + Data->Offset;
230   EfiCopyMem (LocalBuffer, &Text, sizeof (EFI_IFR_TEXT));
231   Data->Offset += sizeof (EFI_IFR_TEXT);
232 
233   return EFI_SUCCESS;
234 }
235 
236 EFI_STATUS
CreateGotoOpCode(IN EFI_FORM_ID FormId,IN EFI_STRING_ID Prompt,IN EFI_STRING_ID Help,IN UINT8 QuestionFlags,IN EFI_QUESTION_ID QuestionId,IN OUT EFI_HII_UPDATE_DATA * Data)237 CreateGotoOpCode (
238   IN     EFI_FORM_ID          FormId,
239   IN     EFI_STRING_ID        Prompt,
240   IN     EFI_STRING_ID        Help,
241   IN     UINT8                QuestionFlags,
242   IN     EFI_QUESTION_ID      QuestionId,
243   IN OUT EFI_HII_UPDATE_DATA  *Data
244   )
245 {
246   EFI_IFR_REF                 Goto;
247   UINT8                       *LocalBuffer;
248 
249   ASSERT (Data != NULL && Data->Data != NULL);
250 
251   if (!IsValidQuestionFlags (QuestionFlags)) {
252     return EFI_INVALID_PARAMETER;
253   }
254 
255   if (Data->Offset + sizeof (EFI_IFR_REF) > Data->BufferSize) {
256     return EFI_BUFFER_TOO_SMALL;
257   }
258 
259   Goto.Header.OpCode          = EFI_IFR_REF_OP;
260   Goto.Header.Length          = (UINT8) sizeof (EFI_IFR_REF);
261   Goto.Header.Scope           = 0;
262   Goto.Question.Header.Prompt = Prompt;
263   Goto.Question.Header.Help   = Help;
264   Goto.Question.VarStoreId    = INVALID_VARSTORE_ID;
265   Goto.Question.QuestionId    = QuestionId;
266   Goto.Question.Flags         = QuestionFlags;
267   Goto.FormId                 = FormId;
268 
269   LocalBuffer = (UINT8 *) Data->Data + Data->Offset;
270   EfiCopyMem (LocalBuffer, &Goto, sizeof (EFI_IFR_REF));
271   Data->Offset += sizeof (EFI_IFR_REF);
272 
273   return EFI_SUCCESS;
274 }
275 
276 EFI_STATUS
CreateOneOfOptionOpCode(IN UINTN OptionCount,IN IFR_OPTION * OptionsList,IN UINT8 Type,IN OUT EFI_HII_UPDATE_DATA * Data)277 CreateOneOfOptionOpCode (
278   IN     UINTN                OptionCount,
279   IN     IFR_OPTION           *OptionsList,
280   IN     UINT8                Type,
281   IN OUT EFI_HII_UPDATE_DATA  *Data
282   )
283 {
284   UINTN                       Index;
285   UINT8                       *LocalBuffer;
286   EFI_IFR_ONE_OF_OPTION       OneOfOption;
287 
288   ASSERT (Data != NULL && Data->Data != NULL);
289 
290   if ((OptionCount != 0) && (OptionsList == NULL)) {
291     return EFI_INVALID_PARAMETER;
292   }
293 
294   if (Data->Offset + OptionCount * sizeof (EFI_IFR_ONE_OF_OPTION) > Data->BufferSize) {
295     return EFI_BUFFER_TOO_SMALL;
296   }
297 
298   for (Index = 0; Index < OptionCount; Index++) {
299     OneOfOption.Header.OpCode = EFI_IFR_ONE_OF_OPTION_OP;
300     OneOfOption.Header.Length = (UINT8) sizeof (EFI_IFR_ONE_OF_OPTION);
301     OneOfOption.Header.Scope  = 0;
302 
303     OneOfOption.Option        = OptionsList[Index].StringToken;
304     OneOfOption.Value         = OptionsList[Index].Value;
305     OneOfOption.Flags         = (UINT8)(OptionsList[Index].Flags & (EFI_IFR_OPTION_DEFAULT | EFI_IFR_OPTION_DEFAULT_MFG));
306     OneOfOption.Type          = Type;
307 
308     LocalBuffer = (UINT8 *) Data->Data + Data->Offset;
309     EfiCopyMem (LocalBuffer, &OneOfOption, sizeof (EFI_IFR_ONE_OF_OPTION));
310     Data->Offset += sizeof (EFI_IFR_ONE_OF_OPTION);
311   }
312 
313   return EFI_SUCCESS;
314 }
315 
316 EFI_STATUS
CreateOneOfOpCode(IN EFI_QUESTION_ID QuestionId,IN EFI_VARSTORE_ID VarStoreId,IN UINT16 VarOffset,IN EFI_STRING_ID Prompt,IN EFI_STRING_ID Help,IN UINT8 QuestionFlags,IN UINT8 OneOfFlags,IN IFR_OPTION * OptionsList,IN UINTN OptionCount,IN OUT EFI_HII_UPDATE_DATA * Data)317 CreateOneOfOpCode (
318   IN     EFI_QUESTION_ID      QuestionId,
319   IN     EFI_VARSTORE_ID      VarStoreId,
320   IN     UINT16               VarOffset,
321   IN     EFI_STRING_ID        Prompt,
322   IN     EFI_STRING_ID        Help,
323   IN     UINT8                QuestionFlags,
324   IN     UINT8                OneOfFlags,
325   IN     IFR_OPTION           *OptionsList,
326   IN     UINTN                OptionCount,
327   IN OUT EFI_HII_UPDATE_DATA  *Data
328   )
329 {
330   UINTN                       Length;
331   EFI_IFR_ONE_OF              OneOf;
332   UINT8                       *LocalBuffer;
333 
334   ASSERT (Data != NULL && Data->Data != NULL);
335 
336   if (!IsValidNumricFlags (OneOfFlags) ||
337       !IsValidQuestionFlags (QuestionFlags) ||
338       ((OptionCount != 0) && (OptionsList == NULL))) {
339     return EFI_INVALID_PARAMETER;
340   }
341 
342   Length = sizeof (EFI_IFR_ONE_OF) + OptionCount * sizeof (EFI_IFR_ONE_OF_OPTION) + sizeof (EFI_IFR_END);
343   if (Data->Offset + Length > Data->BufferSize) {
344     return EFI_BUFFER_TOO_SMALL;
345   }
346 
347   OneOf.Header.OpCode                   = EFI_IFR_ONE_OF_OP;
348   OneOf.Header.Length                   = (UINT8) sizeof (EFI_IFR_ONE_OF);
349   OneOf.Header.Scope                    = 1;
350   OneOf.Question.Header.Prompt          = Prompt;
351   OneOf.Question.Header.Help            = Help;
352   OneOf.Question.QuestionId             = QuestionId;
353   OneOf.Question.VarStoreId             = VarStoreId;
354   OneOf.Question.VarStoreInfo.VarOffset = VarOffset;
355   OneOf.Question.Flags                  = QuestionFlags;
356   OneOf.Flags                           = OneOfFlags;
357   EfiZeroMem ((VOID *) &OneOf.data, sizeof (MINMAXSTEP_DATA));
358 
359   LocalBuffer = (UINT8 *) Data->Data + Data->Offset;
360   EfiCopyMem (LocalBuffer, &OneOf, sizeof (EFI_IFR_ONE_OF));
361   Data->Offset += sizeof (EFI_IFR_ONE_OF);
362 
363   CreateOneOfOptionOpCode (OptionCount, OptionsList, (UINT8)(OneOfFlags & EFI_IFR_NUMERIC_SIZE), Data);
364 
365   CreateEndOpCode (Data);
366 
367   return EFI_SUCCESS;
368 }
369 
370 EFI_STATUS
CreateOrderedListOpCode(IN EFI_QUESTION_ID QuestionId,IN EFI_VARSTORE_ID VarStoreId,IN UINT16 VarOffset,IN EFI_STRING_ID Prompt,IN EFI_STRING_ID Help,IN UINT8 QuestionFlags,IN UINT8 OrderedListFlags,IN UINT8 DataType,IN UINT8 MaxContainers,IN IFR_OPTION * OptionsList,IN UINTN OptionCount,IN OUT EFI_HII_UPDATE_DATA * Data)371 CreateOrderedListOpCode (
372   IN      EFI_QUESTION_ID     QuestionId,
373   IN      EFI_VARSTORE_ID     VarStoreId,
374   IN      UINT16              VarOffset,
375   IN      EFI_STRING_ID       Prompt,
376   IN      EFI_STRING_ID       Help,
377   IN      UINT8               QuestionFlags,
378   IN      UINT8               OrderedListFlags,
379   IN      UINT8               DataType,
380   IN      UINT8               MaxContainers,
381   IN      IFR_OPTION          *OptionsList,
382   IN     UINTN                OptionCount,
383   IN OUT EFI_HII_UPDATE_DATA  *Data
384   )
385 {
386   UINTN                       Length;
387   EFI_IFR_ORDERED_LIST        OrderedList;
388   UINT8                       *LocalBuffer;
389 
390   ASSERT (Data != NULL && Data->Data != NULL);
391 
392   if (!IsValidQuestionFlags (QuestionFlags) ||
393       ((OptionCount != 0) && (OptionsList == NULL))) {
394     return EFI_INVALID_PARAMETER;
395   }
396 
397   if ((OrderedListFlags & (~(EFI_IFR_UNIQUE_SET | EFI_IFR_NO_EMPTY_SET))) != 0) {
398     return EFI_INVALID_PARAMETER;
399   }
400 
401   Length = sizeof (EFI_IFR_ORDERED_LIST) + OptionCount * sizeof (EFI_IFR_ONE_OF_OPTION) + sizeof (EFI_IFR_END);
402   if (Data->Offset + Length > Data->BufferSize) {
403     return EFI_BUFFER_TOO_SMALL;
404   }
405 
406   OrderedList.Header.OpCode                   = EFI_IFR_ORDERED_LIST_OP;
407   OrderedList.Header.Length                   = (UINT8) sizeof (EFI_IFR_ORDERED_LIST);
408   OrderedList.Header.Scope                    = 1;
409   OrderedList.Question.Header.Prompt          = Prompt;
410   OrderedList.Question.Header.Help            = Help;
411   OrderedList.Question.QuestionId             = QuestionId;
412   OrderedList.Question.VarStoreId             = VarStoreId;
413   OrderedList.Question.VarStoreInfo.VarOffset = VarOffset;
414   OrderedList.Question.Flags                  = QuestionFlags;
415   OrderedList.MaxContainers                   = MaxContainers;
416   OrderedList.Flags                           = OrderedListFlags;
417 
418   LocalBuffer = (UINT8 *) Data->Data + Data->Offset;
419   EfiCopyMem (LocalBuffer, &OrderedList, sizeof (EFI_IFR_ORDERED_LIST));
420   Data->Offset += sizeof (EFI_IFR_ORDERED_LIST);
421 
422   CreateOneOfOptionOpCode (OptionCount, OptionsList, DataType, Data);
423 
424   CreateEndOpCode (Data);
425 
426   return EFI_SUCCESS;
427 }
428 
429 EFI_STATUS
CreateCheckBoxOpCode(IN EFI_QUESTION_ID QuestionId,IN EFI_VARSTORE_ID VarStoreId,IN UINT16 VarOffset,IN EFI_STRING_ID Prompt,IN EFI_STRING_ID Help,IN UINT8 QuestionFlags,IN UINT8 CheckBoxFlags,IN OUT EFI_HII_UPDATE_DATA * Data)430 CreateCheckBoxOpCode (
431   IN      EFI_QUESTION_ID     QuestionId,
432   IN      EFI_VARSTORE_ID     VarStoreId,
433   IN      UINT16              VarOffset,
434   IN      EFI_STRING_ID       Prompt,
435   IN      EFI_STRING_ID       Help,
436   IN      UINT8               QuestionFlags,
437   IN      UINT8               CheckBoxFlags,
438   IN OUT EFI_HII_UPDATE_DATA  *Data
439   )
440 {
441   EFI_IFR_CHECKBOX            CheckBox;
442   UINT8                       *LocalBuffer;
443 
444   ASSERT (Data != NULL && Data->Data != NULL);
445 
446   if (!IsValidQuestionFlags (QuestionFlags) || !IsValidCheckboxFlags (CheckBoxFlags)) {
447     return EFI_INVALID_PARAMETER;
448   }
449 
450   if (Data->Offset + sizeof (EFI_IFR_CHECKBOX) > Data->BufferSize) {
451     return EFI_BUFFER_TOO_SMALL;
452   }
453 
454   CheckBox.Header.OpCode                   = EFI_IFR_CHECKBOX_OP;
455   CheckBox.Header.Length                   = (UINT8) sizeof (EFI_IFR_CHECKBOX);
456   CheckBox.Header.Scope                    = 0;
457   CheckBox.Question.QuestionId             = QuestionId;
458   CheckBox.Question.VarStoreId             = VarStoreId;
459   CheckBox.Question.VarStoreInfo.VarOffset = VarOffset;
460   CheckBox.Question.Header.Prompt          = Prompt;
461   CheckBox.Question.Header.Help            = Help;
462   CheckBox.Question.Flags                  = QuestionFlags;
463   CheckBox.Flags                           = CheckBoxFlags;
464 
465   LocalBuffer = (UINT8 *) Data->Data + Data->Offset;
466   EfiCopyMem (LocalBuffer, &CheckBox, sizeof (EFI_IFR_CHECKBOX));
467   Data->Offset += sizeof (EFI_IFR_CHECKBOX);
468 
469   return EFI_SUCCESS;
470 }
471 
472 EFI_STATUS
CreateNumericOpCode(IN EFI_QUESTION_ID QuestionId,IN EFI_VARSTORE_ID VarStoreId,IN UINT16 VarOffset,IN EFI_STRING_ID Prompt,IN EFI_STRING_ID Help,IN UINT8 QuestionFlags,IN UINT8 NumericFlags,IN UINT64 Minimum,IN UINT64 Maximum,IN UINT64 Step,IN UINT64 Default,IN OUT EFI_HII_UPDATE_DATA * Data)473 CreateNumericOpCode (
474   IN     EFI_QUESTION_ID     QuestionId,
475   IN     EFI_VARSTORE_ID     VarStoreId,
476   IN     UINT16              VarOffset,
477   IN     EFI_STRING_ID       Prompt,
478   IN     EFI_STRING_ID       Help,
479   IN     UINT8               QuestionFlags,
480   IN     UINT8               NumericFlags,
481   IN     UINT64              Minimum,
482   IN     UINT64              Maximum,
483   IN     UINT64              Step,
484   IN     UINT64              Default,
485   IN OUT EFI_HII_UPDATE_DATA *Data
486   )
487 {
488   UINTN                       Length;
489   EFI_STATUS                  Status;
490   EFI_IFR_NUMERIC             Numeric;
491   MINMAXSTEP_DATA             MinMaxStep;
492   EFI_IFR_TYPE_VALUE          DefaultValue;
493   UINT8                       *LocalBuffer;
494 
495   ASSERT (Data != NULL && Data->Data != NULL);
496 
497   if (!IsValidQuestionFlags (QuestionFlags) || !IsValidNumricFlags (NumericFlags)) {
498     return EFI_INVALID_PARAMETER;
499   }
500 
501   Length = sizeof (EFI_IFR_NUMERIC) + sizeof (EFI_IFR_DEFAULT) + sizeof (EFI_IFR_END);
502   if (Data->Offset + sizeof (EFI_IFR_CHECKBOX) > Data->BufferSize) {
503     return EFI_BUFFER_TOO_SMALL;
504   }
505 
506   Numeric.Header.OpCode                   = EFI_IFR_NUMERIC_OP;
507   Numeric.Header.Length                   = (UINT8) sizeof (EFI_IFR_NUMERIC);
508   Numeric.Header.Scope                    = 1;
509   Numeric.Question.QuestionId             = QuestionId;
510   Numeric.Question.VarStoreId             = VarStoreId;
511   Numeric.Question.VarStoreInfo.VarOffset = VarOffset;
512   Numeric.Question.Header.Prompt          = Prompt;
513   Numeric.Question.Header.Help            = Help;
514   Numeric.Question.Flags                  = QuestionFlags;
515   Numeric.Flags                           = NumericFlags;
516 
517   switch (NumericFlags & EFI_IFR_NUMERIC_SIZE) {
518   case EFI_IFR_NUMERIC_SIZE_1:
519     MinMaxStep.u8.MinValue = (UINT8) Minimum;
520     MinMaxStep.u8.MaxValue = (UINT8) Maximum;
521     MinMaxStep.u8.Step     = (UINT8) Step;
522     break;
523 
524   case EFI_IFR_NUMERIC_SIZE_2:
525     MinMaxStep.u16.MinValue = (UINT16) Minimum;
526     MinMaxStep.u16.MaxValue = (UINT16) Maximum;
527     MinMaxStep.u16.Step     = (UINT16) Step;
528     break;
529 
530   case EFI_IFR_NUMERIC_SIZE_4:
531     MinMaxStep.u32.MinValue = (UINT32) Minimum;
532     MinMaxStep.u32.MaxValue = (UINT32) Maximum;
533     MinMaxStep.u32.Step     = (UINT32) Step;
534     break;
535 
536   case EFI_IFR_NUMERIC_SIZE_8:
537     MinMaxStep.u64.MinValue = Minimum;
538     MinMaxStep.u64.MaxValue = Maximum;
539     MinMaxStep.u64.Step     = Step;
540     break;
541   }
542 
543   EfiCopyMem (&Numeric.data, &MinMaxStep, sizeof (MINMAXSTEP_DATA));
544 
545   LocalBuffer = (UINT8 *) Data->Data + Data->Offset;
546   EfiCopyMem (LocalBuffer, &Numeric, sizeof (EFI_IFR_NUMERIC));
547   Data->Offset += sizeof (EFI_IFR_NUMERIC);
548 
549   DefaultValue.u64 = Default;
550   Status = CreateDefaultOpCode (&DefaultValue, (UINT8)(NumericFlags & EFI_IFR_NUMERIC_SIZE), Data);
551   if (EFI_ERROR(Status)) {
552     return Status;
553   }
554 
555   CreateEndOpCode (Data);
556 
557   return EFI_SUCCESS;
558 }
559 
560 EFI_STATUS
CreateStringOpCode(IN EFI_QUESTION_ID QuestionId,IN EFI_VARSTORE_ID VarStoreId,IN UINT16 VarOffset,IN EFI_STRING_ID Prompt,IN EFI_STRING_ID Help,IN UINT8 QuestionFlags,IN UINT8 StringFlags,IN UINT8 MinSize,IN UINT8 MaxSize,IN OUT EFI_HII_UPDATE_DATA * Data)561 CreateStringOpCode (
562   IN      EFI_QUESTION_ID     QuestionId,
563   IN      EFI_VARSTORE_ID     VarStoreId,
564   IN      UINT16              VarOffset,
565   IN      EFI_STRING_ID       Prompt,
566   IN      EFI_STRING_ID       Help,
567   IN      UINT8               QuestionFlags,
568   IN      UINT8               StringFlags,
569   IN      UINT8               MinSize,
570   IN      UINT8               MaxSize,
571   IN OUT EFI_HII_UPDATE_DATA  *Data
572   )
573 {
574   EFI_IFR_STRING              String;
575   UINT8                       *LocalBuffer;
576 
577   ASSERT (Data != NULL && Data->Data != NULL);
578 
579   if (!IsValidQuestionFlags (QuestionFlags) || (StringFlags & (~EFI_IFR_STRING_MULTI_LINE))) {
580     return EFI_INVALID_PARAMETER;
581   }
582 
583   if (Data->Offset + sizeof (EFI_IFR_STRING) > Data->BufferSize) {
584     return EFI_BUFFER_TOO_SMALL;
585   }
586 
587   String.Header.OpCode                   = EFI_IFR_STRING_OP;
588   String.Header.Length                   = (UINT8) sizeof (EFI_IFR_STRING);
589   String.Header.Scope                    = 0;
590   String.Question.Header.Prompt          = Prompt;
591   String.Question.Header.Help            = Help;
592   String.Question.QuestionId             = QuestionId;
593   String.Question.VarStoreId             = VarStoreId;
594   String.Question.VarStoreInfo.VarOffset = VarOffset;
595   String.Question.Flags                  = QuestionFlags;
596   String.MinSize                         = MinSize;
597   String.MaxSize                         = MaxSize;
598   String.Flags                           = StringFlags;
599 
600   LocalBuffer = (UINT8 *) Data->Data + Data->Offset;
601   EfiCopyMem (LocalBuffer, &String, sizeof (EFI_IFR_STRING));
602   Data->Offset += sizeof (EFI_IFR_STRING);
603 
604   return EFI_SUCCESS;
605 }
606 
607 EFI_STATUS
CreateBannerOpCode(IN EFI_STRING_ID Title,IN UINT16 LineNumber,IN UINT8 Alignment,IN OUT EFI_HII_UPDATE_DATA * Data)608 CreateBannerOpCode (
609   IN      EFI_STRING_ID       Title,
610   IN      UINT16              LineNumber,
611   IN      UINT8               Alignment,
612   IN OUT EFI_HII_UPDATE_DATA  *Data
613   )
614 {
615   EFI_IFR_GUID_BANNER         Banner;
616   UINT8                       *LocalBuffer;
617 
618   ASSERT (Data != NULL && Data->Data != NULL);
619 
620   if (Data->Offset + sizeof (EFI_IFR_GUID_BANNER) > Data->BufferSize) {
621     return EFI_BUFFER_TOO_SMALL;
622   }
623 
624   Banner.Header.OpCode  = EFI_IFR_GUID_OP;
625   Banner.Header.Length  = (UINT8) sizeof (EFI_IFR_GUID_BANNER);
626   Banner.Header.Scope   = 0;
627   EfiCopyMem (&Banner.Guid, &mIfrVendorGuid, sizeof (EFI_IFR_GUID));
628   Banner.ExtendOpCode   = EFI_IFR_EXTEND_OP_BANNER;
629   Banner.Title          = Title;
630   Banner.LineNumber     = LineNumber;
631   Banner.Alignment      = Alignment;
632 
633   LocalBuffer = (UINT8 *) Data->Data + Data->Offset;
634   EfiCopyMem (LocalBuffer, &Banner, sizeof (EFI_IFR_GUID_BANNER));
635   Data->Offset += sizeof (EFI_IFR_GUID_BANNER);
636 
637   return EFI_SUCCESS;
638 }
639