1 | /** @file
|
---|
2 | Implementation for handling the User Interface option processing.
|
---|
3 |
|
---|
4 |
|
---|
5 | Copyright (c) 2004 - 2020, Intel Corporation. All rights reserved.<BR>
|
---|
6 | SPDX-License-Identifier: BSD-2-Clause-Patent
|
---|
7 |
|
---|
8 | **/
|
---|
9 |
|
---|
10 | #include "FormDisplay.h"
|
---|
11 |
|
---|
12 | #define MAX_TIME_OUT_LEN 0x10
|
---|
13 |
|
---|
14 | /**
|
---|
15 | Concatenate a narrow string to another string.
|
---|
16 |
|
---|
17 | @param Destination The destination string.
|
---|
18 | @param DestMax The Max length of destination string.
|
---|
19 | @param Source The source string. The string to be concatenated.
|
---|
20 | to the end of Destination.
|
---|
21 |
|
---|
22 | **/
|
---|
23 | VOID
|
---|
24 | NewStrCat (
|
---|
25 | IN OUT CHAR16 *Destination,
|
---|
26 | IN UINTN DestMax,
|
---|
27 | IN CHAR16 *Source
|
---|
28 | )
|
---|
29 | {
|
---|
30 | UINTN Length;
|
---|
31 |
|
---|
32 | for (Length = 0; Destination[Length] != 0; Length++) {
|
---|
33 | }
|
---|
34 |
|
---|
35 | //
|
---|
36 | // We now have the length of the original string
|
---|
37 | // We can safely assume for now that we are concatenating a narrow value to this string.
|
---|
38 | // For instance, the string is "XYZ" and cat'ing ">"
|
---|
39 | // If this assumption changes, we need to make this routine a bit more complex
|
---|
40 | //
|
---|
41 | Destination[Length] = NARROW_CHAR;
|
---|
42 | Length++;
|
---|
43 |
|
---|
44 | StrCpyS (Destination + Length, DestMax - Length, Source);
|
---|
45 | }
|
---|
46 |
|
---|
47 | /**
|
---|
48 | Get UINT64 type value.
|
---|
49 |
|
---|
50 | @param Value Input Hii value.
|
---|
51 |
|
---|
52 | @retval UINT64 Return the UINT64 type value.
|
---|
53 |
|
---|
54 | **/
|
---|
55 | UINT64
|
---|
56 | HiiValueToUINT64 (
|
---|
57 | IN EFI_HII_VALUE *Value
|
---|
58 | )
|
---|
59 | {
|
---|
60 | UINT64 RetVal;
|
---|
61 |
|
---|
62 | RetVal = 0;
|
---|
63 |
|
---|
64 | switch (Value->Type) {
|
---|
65 | case EFI_IFR_TYPE_NUM_SIZE_8:
|
---|
66 | RetVal = Value->Value.u8;
|
---|
67 | break;
|
---|
68 |
|
---|
69 | case EFI_IFR_TYPE_NUM_SIZE_16:
|
---|
70 | RetVal = Value->Value.u16;
|
---|
71 | break;
|
---|
72 |
|
---|
73 | case EFI_IFR_TYPE_NUM_SIZE_32:
|
---|
74 | RetVal = Value->Value.u32;
|
---|
75 | break;
|
---|
76 |
|
---|
77 | case EFI_IFR_TYPE_BOOLEAN:
|
---|
78 | RetVal = Value->Value.b;
|
---|
79 | break;
|
---|
80 |
|
---|
81 | case EFI_IFR_TYPE_DATE:
|
---|
82 | RetVal = *(UINT64 *)&Value->Value.date;
|
---|
83 | break;
|
---|
84 |
|
---|
85 | case EFI_IFR_TYPE_TIME:
|
---|
86 | RetVal = (*(UINT64 *)&Value->Value.time) & 0xffffff;
|
---|
87 | break;
|
---|
88 |
|
---|
89 | default:
|
---|
90 | RetVal = Value->Value.u64;
|
---|
91 | break;
|
---|
92 | }
|
---|
93 |
|
---|
94 | return RetVal;
|
---|
95 | }
|
---|
96 |
|
---|
97 | /**
|
---|
98 | Check whether this value type can be transfer to EFI_IFR_TYPE_BUFFER type.
|
---|
99 |
|
---|
100 | EFI_IFR_TYPE_REF, EFI_IFR_TYPE_DATE and EFI_IFR_TYPE_TIME are converted to
|
---|
101 | EFI_IFR_TYPE_BUFFER when do the value compare.
|
---|
102 |
|
---|
103 | @param Value Expression value to compare on.
|
---|
104 |
|
---|
105 | @retval TRUE This value type can be transter to EFI_IFR_TYPE_BUFFER type.
|
---|
106 | @retval FALSE This value type can't be transter to EFI_IFR_TYPE_BUFFER type.
|
---|
107 |
|
---|
108 | **/
|
---|
109 | BOOLEAN
|
---|
110 | IsTypeInBuffer (
|
---|
111 | IN EFI_HII_VALUE *Value
|
---|
112 | )
|
---|
113 | {
|
---|
114 | switch (Value->Type) {
|
---|
115 | case EFI_IFR_TYPE_BUFFER:
|
---|
116 | case EFI_IFR_TYPE_DATE:
|
---|
117 | case EFI_IFR_TYPE_TIME:
|
---|
118 | case EFI_IFR_TYPE_REF:
|
---|
119 | return TRUE;
|
---|
120 |
|
---|
121 | default:
|
---|
122 | return FALSE;
|
---|
123 | }
|
---|
124 | }
|
---|
125 |
|
---|
126 | /**
|
---|
127 | Check whether this value type can be transfer to EFI_IFR_TYPE_UINT64
|
---|
128 |
|
---|
129 | @param Value Expression value to compare on.
|
---|
130 |
|
---|
131 | @retval TRUE This value type can be transter to EFI_IFR_TYPE_BUFFER type.
|
---|
132 | @retval FALSE This value type can't be transter to EFI_IFR_TYPE_BUFFER type.
|
---|
133 |
|
---|
134 | **/
|
---|
135 | BOOLEAN
|
---|
136 | IsTypeInUINT64 (
|
---|
137 | IN EFI_HII_VALUE *Value
|
---|
138 | )
|
---|
139 | {
|
---|
140 | switch (Value->Type) {
|
---|
141 | case EFI_IFR_TYPE_NUM_SIZE_8:
|
---|
142 | case EFI_IFR_TYPE_NUM_SIZE_16:
|
---|
143 | case EFI_IFR_TYPE_NUM_SIZE_32:
|
---|
144 | case EFI_IFR_TYPE_NUM_SIZE_64:
|
---|
145 | case EFI_IFR_TYPE_BOOLEAN:
|
---|
146 | return TRUE;
|
---|
147 |
|
---|
148 | default:
|
---|
149 | return FALSE;
|
---|
150 | }
|
---|
151 | }
|
---|
152 |
|
---|
153 | /**
|
---|
154 | Return the buffer length and buffer pointer for this value.
|
---|
155 |
|
---|
156 | EFI_IFR_TYPE_REF, EFI_IFR_TYPE_DATE and EFI_IFR_TYPE_TIME are converted to
|
---|
157 | EFI_IFR_TYPE_BUFFER when do the value compare.
|
---|
158 |
|
---|
159 | @param Value Expression value to compare on.
|
---|
160 | @param Buf Return the buffer pointer.
|
---|
161 | @param BufLen Return the buffer length.
|
---|
162 |
|
---|
163 | **/
|
---|
164 | VOID
|
---|
165 | GetBufAndLenForValue (
|
---|
166 | IN EFI_HII_VALUE *Value,
|
---|
167 | OUT UINT8 **Buf,
|
---|
168 | OUT UINT16 *BufLen
|
---|
169 | )
|
---|
170 | {
|
---|
171 | switch (Value->Type) {
|
---|
172 | case EFI_IFR_TYPE_BUFFER:
|
---|
173 | *Buf = Value->Buffer;
|
---|
174 | *BufLen = Value->BufferLen;
|
---|
175 | break;
|
---|
176 |
|
---|
177 | case EFI_IFR_TYPE_DATE:
|
---|
178 | *Buf = (UINT8 *)(&Value->Value.date);
|
---|
179 | *BufLen = (UINT16)sizeof (EFI_HII_DATE);
|
---|
180 | break;
|
---|
181 |
|
---|
182 | case EFI_IFR_TYPE_TIME:
|
---|
183 | *Buf = (UINT8 *)(&Value->Value.time);
|
---|
184 | *BufLen = (UINT16)sizeof (EFI_HII_TIME);
|
---|
185 | break;
|
---|
186 |
|
---|
187 | case EFI_IFR_TYPE_REF:
|
---|
188 | *Buf = (UINT8 *)(&Value->Value.ref);
|
---|
189 | *BufLen = (UINT16)sizeof (EFI_HII_REF);
|
---|
190 | break;
|
---|
191 |
|
---|
192 | default:
|
---|
193 | *Buf = NULL;
|
---|
194 | *BufLen = 0;
|
---|
195 | }
|
---|
196 | }
|
---|
197 |
|
---|
198 | /**
|
---|
199 | Compare two Hii value.
|
---|
200 |
|
---|
201 | @param Value1 Expression value to compare on left-hand.
|
---|
202 | @param Value2 Expression value to compare on right-hand.
|
---|
203 | @param Result Return value after compare.
|
---|
204 | retval 0 Two operators equal.
|
---|
205 | return Positive value if Value1 is greater than Value2.
|
---|
206 | retval Negative value if Value1 is less than Value2.
|
---|
207 | @param HiiHandle Only required for string compare.
|
---|
208 |
|
---|
209 | @retval other Could not perform compare on two values.
|
---|
210 | @retval EFI_SUCCESS Compare the value success.
|
---|
211 |
|
---|
212 | **/
|
---|
213 | EFI_STATUS
|
---|
214 | CompareHiiValue (
|
---|
215 | IN EFI_HII_VALUE *Value1,
|
---|
216 | IN EFI_HII_VALUE *Value2,
|
---|
217 | OUT INTN *Result,
|
---|
218 | IN EFI_HII_HANDLE HiiHandle OPTIONAL
|
---|
219 | )
|
---|
220 | {
|
---|
221 | INT64 Temp64;
|
---|
222 | CHAR16 *Str1;
|
---|
223 | CHAR16 *Str2;
|
---|
224 | UINTN Len;
|
---|
225 | UINT8 *Buf1;
|
---|
226 | UINT16 Buf1Len;
|
---|
227 | UINT8 *Buf2;
|
---|
228 | UINT16 Buf2Len;
|
---|
229 |
|
---|
230 | if ((Value1->Type == EFI_IFR_TYPE_STRING) && (Value2->Type == EFI_IFR_TYPE_STRING)) {
|
---|
231 | if ((Value1->Value.string == 0) || (Value2->Value.string == 0)) {
|
---|
232 | //
|
---|
233 | // StringId 0 is reserved
|
---|
234 | //
|
---|
235 | return EFI_INVALID_PARAMETER;
|
---|
236 | }
|
---|
237 |
|
---|
238 | if (Value1->Value.string == Value2->Value.string) {
|
---|
239 | *Result = 0;
|
---|
240 | return EFI_SUCCESS;
|
---|
241 | }
|
---|
242 |
|
---|
243 | Str1 = GetToken (Value1->Value.string, HiiHandle);
|
---|
244 | if (Str1 == NULL) {
|
---|
245 | //
|
---|
246 | // String not found
|
---|
247 | //
|
---|
248 | return EFI_NOT_FOUND;
|
---|
249 | }
|
---|
250 |
|
---|
251 | Str2 = GetToken (Value2->Value.string, HiiHandle);
|
---|
252 | if (Str2 == NULL) {
|
---|
253 | FreePool (Str1);
|
---|
254 | return EFI_NOT_FOUND;
|
---|
255 | }
|
---|
256 |
|
---|
257 | *Result = StrCmp (Str1, Str2);
|
---|
258 |
|
---|
259 | FreePool (Str1);
|
---|
260 | FreePool (Str2);
|
---|
261 |
|
---|
262 | return EFI_SUCCESS;
|
---|
263 | }
|
---|
264 |
|
---|
265 | //
|
---|
266 | // Take types(date, time, ref, buffer) as buffer
|
---|
267 | //
|
---|
268 | if (IsTypeInBuffer (Value1) && IsTypeInBuffer (Value2)) {
|
---|
269 | GetBufAndLenForValue (Value1, &Buf1, &Buf1Len);
|
---|
270 | GetBufAndLenForValue (Value2, &Buf2, &Buf2Len);
|
---|
271 |
|
---|
272 | Len = Buf1Len > Buf2Len ? Buf2Len : Buf1Len;
|
---|
273 | *Result = CompareMem (Buf1, Buf2, Len);
|
---|
274 | if ((*Result == 0) && (Buf1Len != Buf2Len)) {
|
---|
275 | //
|
---|
276 | // In this case, means base on samll number buffer, the data is same
|
---|
277 | // So which value has more data, which value is bigger.
|
---|
278 | //
|
---|
279 | *Result = Buf1Len > Buf2Len ? 1 : -1;
|
---|
280 | }
|
---|
281 |
|
---|
282 | return EFI_SUCCESS;
|
---|
283 | }
|
---|
284 |
|
---|
285 | //
|
---|
286 | // Take remain types(integer, boolean, date/time) as integer
|
---|
287 | //
|
---|
288 | if (IsTypeInUINT64 (Value1) && IsTypeInUINT64 (Value2)) {
|
---|
289 | Temp64 = HiiValueToUINT64 (Value1) - HiiValueToUINT64 (Value2);
|
---|
290 | if (Temp64 > 0) {
|
---|
291 | *Result = 1;
|
---|
292 | } else if (Temp64 < 0) {
|
---|
293 | *Result = -1;
|
---|
294 | } else {
|
---|
295 | *Result = 0;
|
---|
296 | }
|
---|
297 |
|
---|
298 | return EFI_SUCCESS;
|
---|
299 | }
|
---|
300 |
|
---|
301 | return EFI_UNSUPPORTED;
|
---|
302 | }
|
---|
303 |
|
---|
304 | /**
|
---|
305 | Search an Option of a Question by its value.
|
---|
306 |
|
---|
307 | @param Question The Question
|
---|
308 | @param OptionValue Value for Option to be searched.
|
---|
309 |
|
---|
310 | @retval Pointer Pointer to the found Option.
|
---|
311 | @retval NULL Option not found.
|
---|
312 |
|
---|
313 | **/
|
---|
314 | DISPLAY_QUESTION_OPTION *
|
---|
315 | ValueToOption (
|
---|
316 | IN FORM_DISPLAY_ENGINE_STATEMENT *Question,
|
---|
317 | IN EFI_HII_VALUE *OptionValue
|
---|
318 | )
|
---|
319 | {
|
---|
320 | LIST_ENTRY *Link;
|
---|
321 | DISPLAY_QUESTION_OPTION *Option;
|
---|
322 | INTN Result;
|
---|
323 | EFI_HII_VALUE Value;
|
---|
324 |
|
---|
325 | Link = GetFirstNode (&Question->OptionListHead);
|
---|
326 | while (!IsNull (&Question->OptionListHead, Link)) {
|
---|
327 | Option = DISPLAY_QUESTION_OPTION_FROM_LINK (Link);
|
---|
328 |
|
---|
329 | ZeroMem (&Value, sizeof (EFI_HII_VALUE));
|
---|
330 | Value.Type = Option->OptionOpCode->Type;
|
---|
331 | CopyMem (&Value.Value, &Option->OptionOpCode->Value, Option->OptionOpCode->Header.Length - OFFSET_OF (EFI_IFR_ONE_OF_OPTION, Value));
|
---|
332 |
|
---|
333 | if ((CompareHiiValue (&Value, OptionValue, &Result, NULL) == EFI_SUCCESS) && (Result == 0)) {
|
---|
334 | return Option;
|
---|
335 | }
|
---|
336 |
|
---|
337 | Link = GetNextNode (&Question->OptionListHead, Link);
|
---|
338 | }
|
---|
339 |
|
---|
340 | return NULL;
|
---|
341 | }
|
---|
342 |
|
---|
343 | /**
|
---|
344 | Return data element in an Array by its Index.
|
---|
345 |
|
---|
346 | @param Array The data array.
|
---|
347 | @param Type Type of the data in this array.
|
---|
348 | @param Index Zero based index for data in this array.
|
---|
349 |
|
---|
350 | @retval Value The data to be returned
|
---|
351 |
|
---|
352 | **/
|
---|
353 | UINT64
|
---|
354 | GetArrayData (
|
---|
355 | IN VOID *Array,
|
---|
356 | IN UINT8 Type,
|
---|
357 | IN UINTN Index
|
---|
358 | )
|
---|
359 | {
|
---|
360 | UINT64 Data;
|
---|
361 |
|
---|
362 | ASSERT (Array != NULL);
|
---|
363 |
|
---|
364 | Data = 0;
|
---|
365 | switch (Type) {
|
---|
366 | case EFI_IFR_TYPE_NUM_SIZE_8:
|
---|
367 | Data = (UINT64)*(((UINT8 *)Array) + Index);
|
---|
368 | break;
|
---|
369 |
|
---|
370 | case EFI_IFR_TYPE_NUM_SIZE_16:
|
---|
371 | Data = (UINT64)*(((UINT16 *)Array) + Index);
|
---|
372 | break;
|
---|
373 |
|
---|
374 | case EFI_IFR_TYPE_NUM_SIZE_32:
|
---|
375 | Data = (UINT64)*(((UINT32 *)Array) + Index);
|
---|
376 | break;
|
---|
377 |
|
---|
378 | case EFI_IFR_TYPE_NUM_SIZE_64:
|
---|
379 | Data = (UINT64)*(((UINT64 *)Array) + Index);
|
---|
380 | break;
|
---|
381 |
|
---|
382 | default:
|
---|
383 | break;
|
---|
384 | }
|
---|
385 |
|
---|
386 | return Data;
|
---|
387 | }
|
---|
388 |
|
---|
389 | /**
|
---|
390 | Set value of a data element in an Array by its Index.
|
---|
391 |
|
---|
392 | @param Array The data array.
|
---|
393 | @param Type Type of the data in this array.
|
---|
394 | @param Index Zero based index for data in this array.
|
---|
395 | @param Value The value to be set.
|
---|
396 |
|
---|
397 | **/
|
---|
398 | VOID
|
---|
399 | SetArrayData (
|
---|
400 | IN VOID *Array,
|
---|
401 | IN UINT8 Type,
|
---|
402 | IN UINTN Index,
|
---|
403 | IN UINT64 Value
|
---|
404 | )
|
---|
405 | {
|
---|
406 | ASSERT (Array != NULL);
|
---|
407 |
|
---|
408 | switch (Type) {
|
---|
409 | case EFI_IFR_TYPE_NUM_SIZE_8:
|
---|
410 | *(((UINT8 *)Array) + Index) = (UINT8)Value;
|
---|
411 | break;
|
---|
412 |
|
---|
413 | case EFI_IFR_TYPE_NUM_SIZE_16:
|
---|
414 | *(((UINT16 *)Array) + Index) = (UINT16)Value;
|
---|
415 | break;
|
---|
416 |
|
---|
417 | case EFI_IFR_TYPE_NUM_SIZE_32:
|
---|
418 | *(((UINT32 *)Array) + Index) = (UINT32)Value;
|
---|
419 | break;
|
---|
420 |
|
---|
421 | case EFI_IFR_TYPE_NUM_SIZE_64:
|
---|
422 | *(((UINT64 *)Array) + Index) = (UINT64)Value;
|
---|
423 | break;
|
---|
424 |
|
---|
425 | default:
|
---|
426 | break;
|
---|
427 | }
|
---|
428 | }
|
---|
429 |
|
---|
430 | /**
|
---|
431 | Check whether this value already in the array, if yes, return the index.
|
---|
432 |
|
---|
433 | @param Array The data array.
|
---|
434 | @param Type Type of the data in this array.
|
---|
435 | @param Value The value to be find.
|
---|
436 | @param Index The index in the array which has same value with Value.
|
---|
437 |
|
---|
438 | @retval TRUE Found the value in the array.
|
---|
439 | @retval FALSE Not found the value.
|
---|
440 |
|
---|
441 | **/
|
---|
442 | BOOLEAN
|
---|
443 | FindArrayData (
|
---|
444 | IN VOID *Array,
|
---|
445 | IN UINT8 Type,
|
---|
446 | IN UINT64 Value,
|
---|
447 | OUT UINTN *Index OPTIONAL
|
---|
448 | )
|
---|
449 | {
|
---|
450 | UINTN Count;
|
---|
451 | UINT64 TmpValue;
|
---|
452 | UINT64 ValueComp;
|
---|
453 |
|
---|
454 | ASSERT (Array != NULL);
|
---|
455 |
|
---|
456 | Count = 0;
|
---|
457 | TmpValue = 0;
|
---|
458 |
|
---|
459 | switch (Type) {
|
---|
460 | case EFI_IFR_TYPE_NUM_SIZE_8:
|
---|
461 | ValueComp = (UINT8)Value;
|
---|
462 | break;
|
---|
463 |
|
---|
464 | case EFI_IFR_TYPE_NUM_SIZE_16:
|
---|
465 | ValueComp = (UINT16)Value;
|
---|
466 | break;
|
---|
467 |
|
---|
468 | case EFI_IFR_TYPE_NUM_SIZE_32:
|
---|
469 | ValueComp = (UINT32)Value;
|
---|
470 | break;
|
---|
471 |
|
---|
472 | case EFI_IFR_TYPE_NUM_SIZE_64:
|
---|
473 | ValueComp = (UINT64)Value;
|
---|
474 | break;
|
---|
475 |
|
---|
476 | default:
|
---|
477 | ValueComp = 0;
|
---|
478 | break;
|
---|
479 | }
|
---|
480 |
|
---|
481 | while ((TmpValue = GetArrayData (Array, Type, Count)) != 0) {
|
---|
482 | if (ValueComp == TmpValue) {
|
---|
483 | if (Index != NULL) {
|
---|
484 | *Index = Count;
|
---|
485 | }
|
---|
486 |
|
---|
487 | return TRUE;
|
---|
488 | }
|
---|
489 |
|
---|
490 | Count++;
|
---|
491 | }
|
---|
492 |
|
---|
493 | return FALSE;
|
---|
494 | }
|
---|
495 |
|
---|
496 | /**
|
---|
497 | Print Question Value according to it's storage width and display attributes.
|
---|
498 |
|
---|
499 | @param Question The Question to be printed.
|
---|
500 | @param FormattedNumber Buffer for output string.
|
---|
501 | @param BufferSize The FormattedNumber buffer size in bytes.
|
---|
502 |
|
---|
503 | @retval EFI_SUCCESS Print success.
|
---|
504 | @retval EFI_BUFFER_TOO_SMALL Buffer size is not enough for formatted number.
|
---|
505 |
|
---|
506 | **/
|
---|
507 | EFI_STATUS
|
---|
508 | PrintFormattedNumber (
|
---|
509 | IN FORM_DISPLAY_ENGINE_STATEMENT *Question,
|
---|
510 | IN OUT CHAR16 *FormattedNumber,
|
---|
511 | IN UINTN BufferSize
|
---|
512 | )
|
---|
513 | {
|
---|
514 | INT64 Value;
|
---|
515 | CHAR16 *Format;
|
---|
516 | EFI_HII_VALUE *QuestionValue;
|
---|
517 | EFI_IFR_NUMERIC *NumericOp;
|
---|
518 |
|
---|
519 | if (BufferSize < (21 * sizeof (CHAR16))) {
|
---|
520 | return EFI_BUFFER_TOO_SMALL;
|
---|
521 | }
|
---|
522 |
|
---|
523 | QuestionValue = &Question->CurrentValue;
|
---|
524 | NumericOp = (EFI_IFR_NUMERIC *)Question->OpCode;
|
---|
525 |
|
---|
526 | Value = (INT64)QuestionValue->Value.u64;
|
---|
527 | switch (NumericOp->Flags & EFI_IFR_DISPLAY) {
|
---|
528 | case EFI_IFR_DISPLAY_INT_DEC:
|
---|
529 | switch (QuestionValue->Type) {
|
---|
530 | case EFI_IFR_NUMERIC_SIZE_1:
|
---|
531 | Value = (INT64)((INT8)QuestionValue->Value.u8);
|
---|
532 | break;
|
---|
533 |
|
---|
534 | case EFI_IFR_NUMERIC_SIZE_2:
|
---|
535 | Value = (INT64)((INT16)QuestionValue->Value.u16);
|
---|
536 | break;
|
---|
537 |
|
---|
538 | case EFI_IFR_NUMERIC_SIZE_4:
|
---|
539 | Value = (INT64)((INT32)QuestionValue->Value.u32);
|
---|
540 | break;
|
---|
541 |
|
---|
542 | case EFI_IFR_NUMERIC_SIZE_8:
|
---|
543 | default:
|
---|
544 | break;
|
---|
545 | }
|
---|
546 |
|
---|
547 | if (Value < 0) {
|
---|
548 | Value = -Value;
|
---|
549 | Format = L"-%ld";
|
---|
550 | } else {
|
---|
551 | Format = L"%ld";
|
---|
552 | }
|
---|
553 |
|
---|
554 | break;
|
---|
555 |
|
---|
556 | case EFI_IFR_DISPLAY_UINT_DEC:
|
---|
557 | Format = L"%ld";
|
---|
558 | break;
|
---|
559 |
|
---|
560 | case EFI_IFR_DISPLAY_UINT_HEX:
|
---|
561 | Format = L"%lx";
|
---|
562 | break;
|
---|
563 |
|
---|
564 | default:
|
---|
565 | return EFI_UNSUPPORTED;
|
---|
566 | }
|
---|
567 |
|
---|
568 | UnicodeSPrint (FormattedNumber, BufferSize, Format, Value);
|
---|
569 |
|
---|
570 | return EFI_SUCCESS;
|
---|
571 | }
|
---|
572 |
|
---|
573 | /**
|
---|
574 | Draw a pop up windows based on the dimension, number of lines and
|
---|
575 | strings specified.
|
---|
576 |
|
---|
577 | @param RequestedWidth The width of the pop-up.
|
---|
578 | @param NumberOfLines The number of lines.
|
---|
579 | @param Marker The variable argument list for the list of string to be printed.
|
---|
580 |
|
---|
581 | **/
|
---|
582 | VOID
|
---|
583 | CreateSharedPopUp (
|
---|
584 | IN UINTN RequestedWidth,
|
---|
585 | IN UINTN NumberOfLines,
|
---|
586 | IN VA_LIST Marker
|
---|
587 | )
|
---|
588 | {
|
---|
589 | UINTN Index;
|
---|
590 | UINTN Count;
|
---|
591 | CHAR16 Character;
|
---|
592 | UINTN Start;
|
---|
593 | UINTN End;
|
---|
594 | UINTN Top;
|
---|
595 | UINTN Bottom;
|
---|
596 | CHAR16 *String;
|
---|
597 | UINTN DimensionsWidth;
|
---|
598 | UINTN DimensionsHeight;
|
---|
599 |
|
---|
600 | DimensionsWidth = gStatementDimensions.RightColumn - gStatementDimensions.LeftColumn;
|
---|
601 | DimensionsHeight = gStatementDimensions.BottomRow - gStatementDimensions.TopRow;
|
---|
602 |
|
---|
603 | gST->ConOut->SetAttribute (gST->ConOut, GetPopupColor ());
|
---|
604 |
|
---|
605 | if ((RequestedWidth + 2) > DimensionsWidth) {
|
---|
606 | RequestedWidth = DimensionsWidth - 2;
|
---|
607 | }
|
---|
608 |
|
---|
609 | //
|
---|
610 | // Subtract the PopUp width from total Columns, allow for one space extra on
|
---|
611 | // each end plus a border.
|
---|
612 | //
|
---|
613 | Start = (DimensionsWidth - RequestedWidth - 2) / 2 + gStatementDimensions.LeftColumn + 1;
|
---|
614 | End = Start + RequestedWidth + 1;
|
---|
615 |
|
---|
616 | Top = ((DimensionsHeight - NumberOfLines - 2) / 2) + gStatementDimensions.TopRow - 1;
|
---|
617 | Bottom = Top + NumberOfLines + 2;
|
---|
618 |
|
---|
619 | Character = BOXDRAW_DOWN_RIGHT;
|
---|
620 | PrintCharAt (Start, Top, Character);
|
---|
621 | Character = BOXDRAW_HORIZONTAL;
|
---|
622 | for (Index = Start; Index + 2 < End; Index++) {
|
---|
623 | PrintCharAt ((UINTN)-1, (UINTN)-1, Character);
|
---|
624 | }
|
---|
625 |
|
---|
626 | Character = BOXDRAW_DOWN_LEFT;
|
---|
627 | PrintCharAt ((UINTN)-1, (UINTN)-1, Character);
|
---|
628 | Character = BOXDRAW_VERTICAL;
|
---|
629 |
|
---|
630 | Count = 0;
|
---|
631 | for (Index = Top; Index + 2 < Bottom; Index++, Count++) {
|
---|
632 | String = VA_ARG (Marker, CHAR16 *);
|
---|
633 |
|
---|
634 | //
|
---|
635 | // This will clear the background of the line - we never know who might have been
|
---|
636 | // here before us. This differs from the next clear in that it used the non-reverse
|
---|
637 | // video for normal printing.
|
---|
638 | //
|
---|
639 | if (GetStringWidth (String) / 2 > 1) {
|
---|
640 | ClearLines (Start, End, Index + 1, Index + 1, GetPopupColor ());
|
---|
641 | }
|
---|
642 |
|
---|
643 | //
|
---|
644 | // Passing in a space results in the assumption that this is where typing will occur
|
---|
645 | //
|
---|
646 | if (String[0] == L' ') {
|
---|
647 | ClearLines (Start + 1, End - 1, Index + 1, Index + 1, GetPopupInverseColor ());
|
---|
648 | }
|
---|
649 |
|
---|
650 | //
|
---|
651 | // Passing in a NULL results in a blank space
|
---|
652 | //
|
---|
653 | if (String[0] == CHAR_NULL) {
|
---|
654 | ClearLines (Start, End, Index + 1, Index + 1, GetPopupColor ());
|
---|
655 | }
|
---|
656 |
|
---|
657 | PrintStringAt (
|
---|
658 | ((DimensionsWidth - GetStringWidth (String) / 2) / 2) + gStatementDimensions.LeftColumn + 1,
|
---|
659 | Index + 1,
|
---|
660 | String
|
---|
661 | );
|
---|
662 | gST->ConOut->SetAttribute (gST->ConOut, GetPopupColor ());
|
---|
663 | PrintCharAt (Start, Index + 1, Character);
|
---|
664 | PrintCharAt (End - 1, Index + 1, Character);
|
---|
665 | }
|
---|
666 |
|
---|
667 | Character = BOXDRAW_UP_RIGHT;
|
---|
668 | PrintCharAt (Start, Bottom - 1, Character);
|
---|
669 | Character = BOXDRAW_HORIZONTAL;
|
---|
670 | for (Index = Start; Index + 2 < End; Index++) {
|
---|
671 | PrintCharAt ((UINTN)-1, (UINTN)-1, Character);
|
---|
672 | }
|
---|
673 |
|
---|
674 | Character = BOXDRAW_UP_LEFT;
|
---|
675 | PrintCharAt ((UINTN)-1, (UINTN)-1, Character);
|
---|
676 | }
|
---|
677 |
|
---|
678 | /**
|
---|
679 | Draw a pop up windows based on the dimension, number of lines and
|
---|
680 | strings specified.
|
---|
681 |
|
---|
682 | @param RequestedWidth The width of the pop-up.
|
---|
683 | @param NumberOfLines The number of lines.
|
---|
684 | @param ... A series of text strings that displayed in the pop-up.
|
---|
685 |
|
---|
686 | **/
|
---|
687 | VOID
|
---|
688 | EFIAPI
|
---|
689 | CreateMultiStringPopUp (
|
---|
690 | IN UINTN RequestedWidth,
|
---|
691 | IN UINTN NumberOfLines,
|
---|
692 | ...
|
---|
693 | )
|
---|
694 | {
|
---|
695 | VA_LIST Marker;
|
---|
696 |
|
---|
697 | VA_START (Marker, NumberOfLines);
|
---|
698 |
|
---|
699 | CreateSharedPopUp (RequestedWidth, NumberOfLines, Marker);
|
---|
700 |
|
---|
701 | VA_END (Marker);
|
---|
702 | }
|
---|
703 |
|
---|
704 | /**
|
---|
705 | Process nothing.
|
---|
706 |
|
---|
707 | @param Event The Event need to be process
|
---|
708 | @param Context The context of the event.
|
---|
709 |
|
---|
710 | **/
|
---|
711 | VOID
|
---|
712 | EFIAPI
|
---|
713 | EmptyEventProcess (
|
---|
714 | IN EFI_EVENT Event,
|
---|
715 | IN VOID *Context
|
---|
716 | )
|
---|
717 | {
|
---|
718 | }
|
---|
719 |
|
---|
720 | /**
|
---|
721 | Process for the refresh interval statement.
|
---|
722 |
|
---|
723 | @param Event The Event need to be process
|
---|
724 | @param Context The context of the event.
|
---|
725 |
|
---|
726 | **/
|
---|
727 | VOID
|
---|
728 | EFIAPI
|
---|
729 | RefreshTimeOutProcess (
|
---|
730 | IN EFI_EVENT Event,
|
---|
731 | IN VOID *Context
|
---|
732 | )
|
---|
733 | {
|
---|
734 | WARNING_IF_CONTEXT *EventInfo;
|
---|
735 | CHAR16 TimeOutString[MAX_TIME_OUT_LEN];
|
---|
736 |
|
---|
737 | EventInfo = (WARNING_IF_CONTEXT *)Context;
|
---|
738 |
|
---|
739 | if (*(EventInfo->TimeOut) == 0) {
|
---|
740 | gBS->CloseEvent (Event);
|
---|
741 |
|
---|
742 | gBS->SignalEvent (EventInfo->SyncEvent);
|
---|
743 | return;
|
---|
744 | }
|
---|
745 |
|
---|
746 | UnicodeSPrint (TimeOutString, MAX_TIME_OUT_LEN, L"%d", *(EventInfo->TimeOut));
|
---|
747 |
|
---|
748 | CreateDialog (NULL, gEmptyString, EventInfo->ErrorInfo, gPressEnter, gEmptyString, TimeOutString, NULL);
|
---|
749 |
|
---|
750 | *(EventInfo->TimeOut) -= 1;
|
---|
751 | }
|
---|
752 |
|
---|
753 | /**
|
---|
754 | Display error message for invalid password.
|
---|
755 |
|
---|
756 | **/
|
---|
757 | VOID
|
---|
758 | PasswordInvalid (
|
---|
759 | VOID
|
---|
760 | )
|
---|
761 | {
|
---|
762 | EFI_INPUT_KEY Key;
|
---|
763 |
|
---|
764 | //
|
---|
765 | // Invalid password, prompt error message
|
---|
766 | //
|
---|
767 | do {
|
---|
768 | CreateDialog (&Key, gEmptyString, gPassowordInvalid, gPressEnter, gEmptyString, NULL);
|
---|
769 | } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
|
---|
770 | }
|
---|
771 |
|
---|
772 | /**
|
---|
773 | Process password op code.
|
---|
774 |
|
---|
775 | @param MenuOption The menu for current password op code.
|
---|
776 |
|
---|
777 | @retval EFI_SUCCESS Question Option process success.
|
---|
778 | @retval Other Question Option process fail.
|
---|
779 |
|
---|
780 | **/
|
---|
781 | EFI_STATUS
|
---|
782 | PasswordProcess (
|
---|
783 | IN UI_MENU_OPTION *MenuOption
|
---|
784 | )
|
---|
785 | {
|
---|
786 | CHAR16 *StringPtr;
|
---|
787 | CHAR16 *TempString;
|
---|
788 | UINTN Maximum;
|
---|
789 | EFI_STATUS Status;
|
---|
790 | EFI_IFR_PASSWORD *PasswordInfo;
|
---|
791 | FORM_DISPLAY_ENGINE_STATEMENT *Question;
|
---|
792 | EFI_INPUT_KEY Key;
|
---|
793 |
|
---|
794 | Question = MenuOption->ThisTag;
|
---|
795 | PasswordInfo = (EFI_IFR_PASSWORD *)Question->OpCode;
|
---|
796 | Maximum = PasswordInfo->MaxSize;
|
---|
797 | Status = EFI_SUCCESS;
|
---|
798 |
|
---|
799 | StringPtr = AllocateZeroPool ((Maximum + 1) * sizeof (CHAR16));
|
---|
800 | ASSERT (StringPtr);
|
---|
801 |
|
---|
802 | //
|
---|
803 | // Use a NULL password to test whether old password is required
|
---|
804 | //
|
---|
805 | *StringPtr = 0;
|
---|
806 | Status = Question->PasswordCheck (gFormData, Question, StringPtr);
|
---|
807 | if ((Status == EFI_NOT_AVAILABLE_YET) || (Status == EFI_UNSUPPORTED)) {
|
---|
808 | //
|
---|
809 | // Password can't be set now.
|
---|
810 | //
|
---|
811 | if (Status == EFI_UNSUPPORTED) {
|
---|
812 | do {
|
---|
813 | CreateDialog (&Key, gEmptyString, gPasswordUnsupported, gPressEnter, gEmptyString, NULL);
|
---|
814 | } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
|
---|
815 | }
|
---|
816 |
|
---|
817 | FreePool (StringPtr);
|
---|
818 | return EFI_SUCCESS;
|
---|
819 | }
|
---|
820 |
|
---|
821 | if (EFI_ERROR (Status)) {
|
---|
822 | //
|
---|
823 | // Old password exist, ask user for the old password
|
---|
824 | //
|
---|
825 | Status = ReadString (MenuOption, gPromptForPassword, StringPtr);
|
---|
826 | if (EFI_ERROR (Status)) {
|
---|
827 | ZeroMem (StringPtr, (Maximum + 1) * sizeof (CHAR16));
|
---|
828 | FreePool (StringPtr);
|
---|
829 | return Status;
|
---|
830 | }
|
---|
831 |
|
---|
832 | //
|
---|
833 | // Check user input old password
|
---|
834 | //
|
---|
835 | Status = Question->PasswordCheck (gFormData, Question, StringPtr);
|
---|
836 | if (EFI_ERROR (Status)) {
|
---|
837 | if (Status == EFI_NOT_READY) {
|
---|
838 | //
|
---|
839 | // Typed in old password incorrect
|
---|
840 | //
|
---|
841 | PasswordInvalid ();
|
---|
842 | } else {
|
---|
843 | Status = EFI_SUCCESS;
|
---|
844 | }
|
---|
845 |
|
---|
846 | ZeroMem (StringPtr, (Maximum + 1) * sizeof (CHAR16));
|
---|
847 | FreePool (StringPtr);
|
---|
848 | return Status;
|
---|
849 | }
|
---|
850 | }
|
---|
851 |
|
---|
852 | //
|
---|
853 | // Ask for new password
|
---|
854 | //
|
---|
855 | ZeroMem (StringPtr, (Maximum + 1) * sizeof (CHAR16));
|
---|
856 | Status = ReadString (MenuOption, gPromptForNewPassword, StringPtr);
|
---|
857 | if (EFI_ERROR (Status)) {
|
---|
858 | //
|
---|
859 | // Reset state machine for password
|
---|
860 | //
|
---|
861 | Question->PasswordCheck (gFormData, Question, NULL);
|
---|
862 | ZeroMem (StringPtr, (Maximum + 1) * sizeof (CHAR16));
|
---|
863 | FreePool (StringPtr);
|
---|
864 | return Status;
|
---|
865 | }
|
---|
866 |
|
---|
867 | //
|
---|
868 | // Confirm new password
|
---|
869 | //
|
---|
870 | TempString = AllocateZeroPool ((Maximum + 1) * sizeof (CHAR16));
|
---|
871 | ASSERT (TempString);
|
---|
872 | Status = ReadString (MenuOption, gConfirmPassword, TempString);
|
---|
873 | if (EFI_ERROR (Status)) {
|
---|
874 | //
|
---|
875 | // Reset state machine for password
|
---|
876 | //
|
---|
877 | Question->PasswordCheck (gFormData, Question, NULL);
|
---|
878 | ZeroMem (StringPtr, (Maximum + 1) * sizeof (CHAR16));
|
---|
879 | ZeroMem (TempString, (Maximum + 1) * sizeof (CHAR16));
|
---|
880 | FreePool (StringPtr);
|
---|
881 | FreePool (TempString);
|
---|
882 | return Status;
|
---|
883 | }
|
---|
884 |
|
---|
885 | //
|
---|
886 | // Compare two typed-in new passwords
|
---|
887 | //
|
---|
888 | if (StrCmp (StringPtr, TempString) == 0) {
|
---|
889 | gUserInput->InputValue.Buffer = AllocateCopyPool (Question->CurrentValue.BufferLen, StringPtr);
|
---|
890 | gUserInput->InputValue.BufferLen = Question->CurrentValue.BufferLen;
|
---|
891 | gUserInput->InputValue.Type = Question->CurrentValue.Type;
|
---|
892 | gUserInput->InputValue.Value.string = HiiSetString (gFormData->HiiHandle, gUserInput->InputValue.Value.string, StringPtr, NULL);
|
---|
893 |
|
---|
894 | Status = EFI_SUCCESS;
|
---|
895 | } else {
|
---|
896 | //
|
---|
897 | // Reset state machine for password
|
---|
898 | //
|
---|
899 | Question->PasswordCheck (gFormData, Question, NULL);
|
---|
900 |
|
---|
901 | //
|
---|
902 | // Two password mismatch, prompt error message
|
---|
903 | //
|
---|
904 | do {
|
---|
905 | CreateDialog (&Key, gEmptyString, gConfirmError, gPressEnter, gEmptyString, NULL);
|
---|
906 | } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
|
---|
907 |
|
---|
908 | Status = EFI_INVALID_PARAMETER;
|
---|
909 | }
|
---|
910 |
|
---|
911 | ZeroMem (TempString, (Maximum + 1) * sizeof (CHAR16));
|
---|
912 | ZeroMem (StringPtr, (Maximum + 1) * sizeof (CHAR16));
|
---|
913 | FreePool (TempString);
|
---|
914 | FreePool (StringPtr);
|
---|
915 |
|
---|
916 | return Status;
|
---|
917 | }
|
---|
918 |
|
---|
919 | /**
|
---|
920 | Print some debug message about mismatched menu info.
|
---|
921 |
|
---|
922 | @param MenuOption The MenuOption for this Question.
|
---|
923 |
|
---|
924 | **/
|
---|
925 | VOID
|
---|
926 | PrintMismatchMenuInfo (
|
---|
927 | IN UI_MENU_OPTION *MenuOption
|
---|
928 | )
|
---|
929 | {
|
---|
930 | CHAR16 *FormTitleStr;
|
---|
931 | CHAR16 *FormSetTitleStr;
|
---|
932 | CHAR16 *OneOfOptionStr;
|
---|
933 | CHAR16 *QuestionName;
|
---|
934 | LIST_ENTRY *Link;
|
---|
935 | FORM_DISPLAY_ENGINE_STATEMENT *Question;
|
---|
936 | EFI_IFR_ORDERED_LIST *OrderList;
|
---|
937 | UINT8 Index;
|
---|
938 | EFI_HII_VALUE HiiValue;
|
---|
939 | EFI_HII_VALUE *QuestionValue;
|
---|
940 | DISPLAY_QUESTION_OPTION *Option;
|
---|
941 | UINT8 *ValueArray;
|
---|
942 | UINT8 ValueType;
|
---|
943 | EFI_IFR_FORM_SET *FormsetBuffer;
|
---|
944 | UINTN FormsetBufferSize;
|
---|
945 |
|
---|
946 | Question = MenuOption->ThisTag;
|
---|
947 |
|
---|
948 | if (!EFI_ERROR (HiiGetFormSetFromHiiHandle (gFormData->HiiHandle, &FormsetBuffer, &FormsetBufferSize))) {
|
---|
949 | FormSetTitleStr = GetToken (FormsetBuffer->FormSetTitle, gFormData->HiiHandle);
|
---|
950 | FormTitleStr = GetToken (gFormData->FormTitle, gFormData->HiiHandle);
|
---|
951 |
|
---|
952 | DEBUG ((DEBUG_ERROR, "\n[%a]: Mismatch Formset : Formset Guid = %g, FormSet title = %s\n", gEfiCallerBaseName, &gFormData->FormSetGuid, FormSetTitleStr));
|
---|
953 | DEBUG ((DEBUG_ERROR, "[%a]: Mismatch Form : FormId = %d, Form title = %s.\n", gEfiCallerBaseName, gFormData->FormId, FormTitleStr));
|
---|
954 | }
|
---|
955 |
|
---|
956 | if (Question->OpCode->OpCode == EFI_IFR_ORDERED_LIST_OP) {
|
---|
957 | QuestionName = GetToken (((EFI_IFR_ORDERED_LIST *)MenuOption->ThisTag->OpCode)->Question.Header.Prompt, gFormData->HiiHandle);
|
---|
958 | Link = GetFirstNode (&Question->OptionListHead);
|
---|
959 | Option = DISPLAY_QUESTION_OPTION_FROM_LINK (Link);
|
---|
960 | ValueType = Option->OptionOpCode->Type;
|
---|
961 | DEBUG ((DEBUG_ERROR, "[%a]: Mismatch Error : OrderedList value in the array doesn't match with option value.\n", gEfiCallerBaseName));
|
---|
962 | DEBUG ((DEBUG_ERROR, "[%a]: Mismatch OrderedList: Name = %s.\n", gEfiCallerBaseName, QuestionName));
|
---|
963 | DEBUG ((DEBUG_ERROR, "[%a]: Mismatch OrderedList: OrderedList array value :\n", gEfiCallerBaseName));
|
---|
964 |
|
---|
965 | OrderList = (EFI_IFR_ORDERED_LIST *)Question->OpCode;
|
---|
966 | for (Index = 0; Index < OrderList->MaxContainers; Index++) {
|
---|
967 | ValueArray = Question->CurrentValue.Buffer;
|
---|
968 | HiiValue.Value.u64 = GetArrayData (ValueArray, ValueType, Index);
|
---|
969 | DEBUG ((DEBUG_ERROR, " Value[%d] =%ld.\n", Index, HiiValue.Value.u64));
|
---|
970 | }
|
---|
971 | } else if (Question->OpCode->OpCode == EFI_IFR_ONE_OF_OP) {
|
---|
972 | QuestionName = GetToken (((EFI_IFR_ONE_OF *)MenuOption->ThisTag->OpCode)->Question.Header.Prompt, gFormData->HiiHandle);
|
---|
973 | QuestionValue = &Question->CurrentValue;
|
---|
974 | DEBUG ((DEBUG_ERROR, "[%a]: Mismatch Error : OneOf value doesn't match with option value.\n", gEfiCallerBaseName));
|
---|
975 | DEBUG ((DEBUG_ERROR, "[%a]: Mismatch OneOf : Name = %s.\n", gEfiCallerBaseName, QuestionName));
|
---|
976 | switch (QuestionValue->Type) {
|
---|
977 | case EFI_IFR_TYPE_NUM_SIZE_64:
|
---|
978 | DEBUG ((DEBUG_ERROR, "[%a]: Mismatch OneOf : OneOf value = %ld.\n", gEfiCallerBaseName, QuestionValue->Value.u64));
|
---|
979 | break;
|
---|
980 |
|
---|
981 | case EFI_IFR_TYPE_NUM_SIZE_32:
|
---|
982 | DEBUG ((DEBUG_ERROR, "[%a]: Mismatch OneOf : OneOf value = %d.\n", gEfiCallerBaseName, QuestionValue->Value.u32));
|
---|
983 | break;
|
---|
984 |
|
---|
985 | case EFI_IFR_TYPE_NUM_SIZE_16:
|
---|
986 | DEBUG ((DEBUG_ERROR, "[%a]: Mismatch OneOf : OneOf value = %d.\n", gEfiCallerBaseName, QuestionValue->Value.u16));
|
---|
987 | break;
|
---|
988 |
|
---|
989 | case EFI_IFR_TYPE_NUM_SIZE_8:
|
---|
990 | DEBUG ((DEBUG_ERROR, "[%a]: Mismatch OneOf : OneOf value = %d.\n", gEfiCallerBaseName, QuestionValue->Value.u8));
|
---|
991 | break;
|
---|
992 |
|
---|
993 | default:
|
---|
994 | ASSERT (FALSE);
|
---|
995 | break;
|
---|
996 | }
|
---|
997 | }
|
---|
998 |
|
---|
999 | Index = 0;
|
---|
1000 | Link = GetFirstNode (&Question->OptionListHead);
|
---|
1001 | while (!IsNull (&Question->OptionListHead, Link)) {
|
---|
1002 | Option = DISPLAY_QUESTION_OPTION_FROM_LINK (Link);
|
---|
1003 | OneOfOptionStr = GetToken (Option->OptionOpCode->Option, gFormData->HiiHandle);
|
---|
1004 | switch (Option->OptionOpCode->Type) {
|
---|
1005 | case EFI_IFR_TYPE_NUM_SIZE_64:
|
---|
1006 | DEBUG ((DEBUG_ERROR, "[%a]: Option %d : Option Value = %ld, Option Name = %s.\n", gEfiCallerBaseName, Index, Option->OptionOpCode->Value.u64, OneOfOptionStr));
|
---|
1007 | break;
|
---|
1008 |
|
---|
1009 | case EFI_IFR_TYPE_NUM_SIZE_32:
|
---|
1010 | DEBUG ((DEBUG_ERROR, "[%a]: Option %d : Option Value = %d, Option Name = %s.\n", gEfiCallerBaseName, Index, Option->OptionOpCode->Value.u32, OneOfOptionStr));
|
---|
1011 | break;
|
---|
1012 |
|
---|
1013 | case EFI_IFR_TYPE_NUM_SIZE_16:
|
---|
1014 | DEBUG ((DEBUG_ERROR, "[%a]: Option %d : Option Value = %d, Option Name = %s.\n", gEfiCallerBaseName, Index, Option->OptionOpCode->Value.u16, OneOfOptionStr));
|
---|
1015 | break;
|
---|
1016 |
|
---|
1017 | case EFI_IFR_TYPE_NUM_SIZE_8:
|
---|
1018 | DEBUG ((DEBUG_ERROR, "[%a]: Option %d : Option Value = %d, Option Name = %s.\n", gEfiCallerBaseName, Index, Option->OptionOpCode->Value.u8, OneOfOptionStr));
|
---|
1019 | break;
|
---|
1020 |
|
---|
1021 | default:
|
---|
1022 | ASSERT (FALSE);
|
---|
1023 | break;
|
---|
1024 | }
|
---|
1025 |
|
---|
1026 | Link = GetNextNode (&Question->OptionListHead, Link);
|
---|
1027 | Index++;
|
---|
1028 | }
|
---|
1029 | }
|
---|
1030 |
|
---|
1031 | /**
|
---|
1032 | Process a Question's Option (whether selected or un-selected).
|
---|
1033 |
|
---|
1034 | @param MenuOption The MenuOption for this Question.
|
---|
1035 | @param Selected TRUE: if Question is selected.
|
---|
1036 | @param OptionString Pointer of the Option String to be displayed.
|
---|
1037 | @param SkipErrorValue Whether need to return when value without option for it.
|
---|
1038 |
|
---|
1039 | @retval EFI_SUCCESS Question Option process success.
|
---|
1040 | @retval Other Question Option process fail.
|
---|
1041 |
|
---|
1042 | **/
|
---|
1043 | EFI_STATUS
|
---|
1044 | ProcessOptions (
|
---|
1045 | IN UI_MENU_OPTION *MenuOption,
|
---|
1046 | IN BOOLEAN Selected,
|
---|
1047 | OUT CHAR16 **OptionString,
|
---|
1048 | IN BOOLEAN SkipErrorValue
|
---|
1049 | )
|
---|
1050 | {
|
---|
1051 | EFI_STATUS Status;
|
---|
1052 | CHAR16 *StringPtr;
|
---|
1053 | UINTN Index;
|
---|
1054 | FORM_DISPLAY_ENGINE_STATEMENT *Question;
|
---|
1055 | CHAR16 FormattedNumber[21];
|
---|
1056 | UINT16 Number;
|
---|
1057 | CHAR16 Character[2];
|
---|
1058 | EFI_INPUT_KEY Key;
|
---|
1059 | UINTN BufferSize;
|
---|
1060 | DISPLAY_QUESTION_OPTION *OneOfOption;
|
---|
1061 | LIST_ENTRY *Link;
|
---|
1062 | EFI_HII_VALUE HiiValue;
|
---|
1063 | EFI_HII_VALUE *QuestionValue;
|
---|
1064 | DISPLAY_QUESTION_OPTION *Option;
|
---|
1065 | UINTN Index2;
|
---|
1066 | UINT8 *ValueArray;
|
---|
1067 | UINT8 ValueType;
|
---|
1068 | EFI_IFR_ORDERED_LIST *OrderList;
|
---|
1069 | BOOLEAN ValueInvalid;
|
---|
1070 | UINTN MaxLen;
|
---|
1071 |
|
---|
1072 | Status = EFI_SUCCESS;
|
---|
1073 |
|
---|
1074 | StringPtr = NULL;
|
---|
1075 | Character[1] = L'\0';
|
---|
1076 | *OptionString = NULL;
|
---|
1077 | ValueInvalid = FALSE;
|
---|
1078 |
|
---|
1079 | ZeroMem (FormattedNumber, 21 * sizeof (CHAR16));
|
---|
1080 | BufferSize = (gOptionBlockWidth + 1) * 2 * gStatementDimensions.BottomRow;
|
---|
1081 |
|
---|
1082 | Question = MenuOption->ThisTag;
|
---|
1083 | QuestionValue = &Question->CurrentValue;
|
---|
1084 |
|
---|
1085 | switch (Question->OpCode->OpCode) {
|
---|
1086 | case EFI_IFR_ORDERED_LIST_OP:
|
---|
1087 |
|
---|
1088 | //
|
---|
1089 | // Check whether there are Options of this OrderedList
|
---|
1090 | //
|
---|
1091 | if (IsListEmpty (&Question->OptionListHead)) {
|
---|
1092 | break;
|
---|
1093 | }
|
---|
1094 |
|
---|
1095 | OrderList = (EFI_IFR_ORDERED_LIST *)Question->OpCode;
|
---|
1096 |
|
---|
1097 | Link = GetFirstNode (&Question->OptionListHead);
|
---|
1098 | OneOfOption = DISPLAY_QUESTION_OPTION_FROM_LINK (Link);
|
---|
1099 |
|
---|
1100 | ValueType = OneOfOption->OptionOpCode->Type;
|
---|
1101 | ValueArray = Question->CurrentValue.Buffer;
|
---|
1102 |
|
---|
1103 | if (Selected) {
|
---|
1104 | //
|
---|
1105 | // Go ask for input
|
---|
1106 | //
|
---|
1107 | Status = GetSelectionInputPopUp (MenuOption);
|
---|
1108 | } else {
|
---|
1109 | //
|
---|
1110 | // We now know how many strings we will have, so we can allocate the
|
---|
1111 | // space required for the array or strings.
|
---|
1112 | //
|
---|
1113 | MaxLen = OrderList->MaxContainers * BufferSize / sizeof (CHAR16);
|
---|
1114 | *OptionString = AllocateZeroPool (MaxLen * sizeof (CHAR16));
|
---|
1115 | ASSERT (*OptionString);
|
---|
1116 |
|
---|
1117 | HiiValue.Type = ValueType;
|
---|
1118 | HiiValue.Value.u64 = 0;
|
---|
1119 | for (Index = 0; Index < OrderList->MaxContainers; Index++) {
|
---|
1120 | HiiValue.Value.u64 = GetArrayData (ValueArray, ValueType, Index);
|
---|
1121 | if (HiiValue.Value.u64 == 0) {
|
---|
1122 | //
|
---|
1123 | // Values for the options in ordered lists should never be a 0
|
---|
1124 | //
|
---|
1125 | break;
|
---|
1126 | }
|
---|
1127 |
|
---|
1128 | OneOfOption = ValueToOption (Question, &HiiValue);
|
---|
1129 | if (OneOfOption == NULL) {
|
---|
1130 | //
|
---|
1131 | // Print debug msg for the mistach menu.
|
---|
1132 | //
|
---|
1133 | PrintMismatchMenuInfo (MenuOption);
|
---|
1134 |
|
---|
1135 | if (SkipErrorValue) {
|
---|
1136 | //
|
---|
1137 | // Just try to get the option string, skip the value which not has option.
|
---|
1138 | //
|
---|
1139 | continue;
|
---|
1140 | }
|
---|
1141 |
|
---|
1142 | //
|
---|
1143 | // Show error message
|
---|
1144 | //
|
---|
1145 | do {
|
---|
1146 | CreateDialog (&Key, gEmptyString, gOptionMismatch, gPressEnter, gEmptyString, NULL);
|
---|
1147 | } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
|
---|
1148 |
|
---|
1149 | //
|
---|
1150 | // The initial value of the orderedlist is invalid, force to be valid value
|
---|
1151 | // Exit current DisplayForm with new value.
|
---|
1152 | //
|
---|
1153 | gUserInput->SelectedStatement = Question;
|
---|
1154 | gMisMatch = TRUE;
|
---|
1155 | ValueArray = AllocateZeroPool (Question->CurrentValue.BufferLen);
|
---|
1156 | ASSERT (ValueArray != NULL);
|
---|
1157 | gUserInput->InputValue.Buffer = ValueArray;
|
---|
1158 | gUserInput->InputValue.BufferLen = Question->CurrentValue.BufferLen;
|
---|
1159 | gUserInput->InputValue.Type = Question->CurrentValue.Type;
|
---|
1160 |
|
---|
1161 | Link = GetFirstNode (&Question->OptionListHead);
|
---|
1162 | Index2 = 0;
|
---|
1163 | while (!IsNull (&Question->OptionListHead, Link) && Index2 < OrderList->MaxContainers) {
|
---|
1164 | Option = DISPLAY_QUESTION_OPTION_FROM_LINK (Link);
|
---|
1165 | Link = GetNextNode (&Question->OptionListHead, Link);
|
---|
1166 | SetArrayData (ValueArray, ValueType, Index2, Option->OptionOpCode->Value.u64);
|
---|
1167 | Index2++;
|
---|
1168 | }
|
---|
1169 |
|
---|
1170 | SetArrayData (ValueArray, ValueType, Index2, 0);
|
---|
1171 |
|
---|
1172 | FreePool (*OptionString);
|
---|
1173 | *OptionString = NULL;
|
---|
1174 | return EFI_NOT_FOUND;
|
---|
1175 | }
|
---|
1176 |
|
---|
1177 | Character[0] = LEFT_ONEOF_DELIMITER;
|
---|
1178 | NewStrCat (OptionString[0], MaxLen, Character);
|
---|
1179 | StringPtr = GetToken (OneOfOption->OptionOpCode->Option, gFormData->HiiHandle);
|
---|
1180 | ASSERT (StringPtr != NULL);
|
---|
1181 | NewStrCat (OptionString[0], MaxLen, StringPtr);
|
---|
1182 | Character[0] = RIGHT_ONEOF_DELIMITER;
|
---|
1183 | NewStrCat (OptionString[0], MaxLen, Character);
|
---|
1184 | Character[0] = CHAR_CARRIAGE_RETURN;
|
---|
1185 | NewStrCat (OptionString[0], MaxLen, Character);
|
---|
1186 | FreePool (StringPtr);
|
---|
1187 | }
|
---|
1188 |
|
---|
1189 | //
|
---|
1190 | // If valid option more than the max container, skip these options.
|
---|
1191 | //
|
---|
1192 | if (Index >= OrderList->MaxContainers) {
|
---|
1193 | break;
|
---|
1194 | }
|
---|
1195 |
|
---|
1196 | //
|
---|
1197 | // Search the other options, try to find the one not in the container.
|
---|
1198 | //
|
---|
1199 | Link = GetFirstNode (&Question->OptionListHead);
|
---|
1200 | while (!IsNull (&Question->OptionListHead, Link)) {
|
---|
1201 | OneOfOption = DISPLAY_QUESTION_OPTION_FROM_LINK (Link);
|
---|
1202 | Link = GetNextNode (&Question->OptionListHead, Link);
|
---|
1203 |
|
---|
1204 | if (FindArrayData (ValueArray, ValueType, OneOfOption->OptionOpCode->Value.u64, NULL)) {
|
---|
1205 | continue;
|
---|
1206 | }
|
---|
1207 |
|
---|
1208 | //
|
---|
1209 | // Print debug msg for the mistach menu.
|
---|
1210 | //
|
---|
1211 | PrintMismatchMenuInfo (MenuOption);
|
---|
1212 |
|
---|
1213 | if (SkipErrorValue) {
|
---|
1214 | //
|
---|
1215 | // Not report error, just get the correct option string info.
|
---|
1216 | //
|
---|
1217 | Character[0] = LEFT_ONEOF_DELIMITER;
|
---|
1218 | NewStrCat (OptionString[0], MaxLen, Character);
|
---|
1219 | StringPtr = GetToken (OneOfOption->OptionOpCode->Option, gFormData->HiiHandle);
|
---|
1220 | ASSERT (StringPtr != NULL);
|
---|
1221 | NewStrCat (OptionString[0], MaxLen, StringPtr);
|
---|
1222 | Character[0] = RIGHT_ONEOF_DELIMITER;
|
---|
1223 | NewStrCat (OptionString[0], MaxLen, Character);
|
---|
1224 | Character[0] = CHAR_CARRIAGE_RETURN;
|
---|
1225 | NewStrCat (OptionString[0], MaxLen, Character);
|
---|
1226 | FreePool (StringPtr);
|
---|
1227 |
|
---|
1228 | continue;
|
---|
1229 | }
|
---|
1230 |
|
---|
1231 | if (!ValueInvalid) {
|
---|
1232 | ValueInvalid = TRUE;
|
---|
1233 | //
|
---|
1234 | // Show error message
|
---|
1235 | //
|
---|
1236 | do {
|
---|
1237 | CreateDialog (&Key, gEmptyString, gOptionMismatch, gPressEnter, gEmptyString, NULL);
|
---|
1238 | } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
|
---|
1239 |
|
---|
1240 | //
|
---|
1241 | // The initial value of the orderedlist is invalid, force to be valid value
|
---|
1242 | // Exit current DisplayForm with new value.
|
---|
1243 | //
|
---|
1244 | gUserInput->SelectedStatement = Question;
|
---|
1245 | gMisMatch = TRUE;
|
---|
1246 | ValueArray = AllocateCopyPool (Question->CurrentValue.BufferLen, Question->CurrentValue.Buffer);
|
---|
1247 | ASSERT (ValueArray != NULL);
|
---|
1248 | gUserInput->InputValue.Buffer = ValueArray;
|
---|
1249 | gUserInput->InputValue.BufferLen = Question->CurrentValue.BufferLen;
|
---|
1250 | gUserInput->InputValue.Type = Question->CurrentValue.Type;
|
---|
1251 | }
|
---|
1252 |
|
---|
1253 | SetArrayData (ValueArray, ValueType, Index++, OneOfOption->OptionOpCode->Value.u64);
|
---|
1254 | }
|
---|
1255 |
|
---|
1256 | if (ValueInvalid) {
|
---|
1257 | FreePool (*OptionString);
|
---|
1258 | *OptionString = NULL;
|
---|
1259 | return EFI_NOT_FOUND;
|
---|
1260 | }
|
---|
1261 | }
|
---|
1262 |
|
---|
1263 | break;
|
---|
1264 |
|
---|
1265 | case EFI_IFR_ONE_OF_OP:
|
---|
1266 | //
|
---|
1267 | // Check whether there are Options of this OneOf
|
---|
1268 | //
|
---|
1269 | if (IsListEmpty (&Question->OptionListHead)) {
|
---|
1270 | break;
|
---|
1271 | }
|
---|
1272 |
|
---|
1273 | if (Selected) {
|
---|
1274 | //
|
---|
1275 | // Go ask for input
|
---|
1276 | //
|
---|
1277 | Status = GetSelectionInputPopUp (MenuOption);
|
---|
1278 | } else {
|
---|
1279 | MaxLen = BufferSize / sizeof (CHAR16);
|
---|
1280 | *OptionString = AllocateZeroPool (BufferSize);
|
---|
1281 | ASSERT (*OptionString);
|
---|
1282 |
|
---|
1283 | OneOfOption = ValueToOption (Question, QuestionValue);
|
---|
1284 | if (OneOfOption == NULL) {
|
---|
1285 | //
|
---|
1286 | // Print debug msg for the mistach menu.
|
---|
1287 | //
|
---|
1288 | PrintMismatchMenuInfo (MenuOption);
|
---|
1289 |
|
---|
1290 | if (SkipErrorValue) {
|
---|
1291 | //
|
---|
1292 | // Not report error, just get the correct option string info.
|
---|
1293 | //
|
---|
1294 | Link = GetFirstNode (&Question->OptionListHead);
|
---|
1295 | OneOfOption = DISPLAY_QUESTION_OPTION_FROM_LINK (Link);
|
---|
1296 | } else {
|
---|
1297 | //
|
---|
1298 | // Show error message
|
---|
1299 | //
|
---|
1300 | do {
|
---|
1301 | CreateDialog (&Key, gEmptyString, gOptionMismatch, gPressEnter, gEmptyString, NULL);
|
---|
1302 | } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
|
---|
1303 |
|
---|
1304 | //
|
---|
1305 | // Force the Question value to be valid
|
---|
1306 | // Exit current DisplayForm with new value.
|
---|
1307 | //
|
---|
1308 | Link = GetFirstNode (&Question->OptionListHead);
|
---|
1309 | Option = DISPLAY_QUESTION_OPTION_FROM_LINK (Link);
|
---|
1310 |
|
---|
1311 | gUserInput->InputValue.Type = Option->OptionOpCode->Type;
|
---|
1312 | switch (gUserInput->InputValue.Type) {
|
---|
1313 | case EFI_IFR_TYPE_NUM_SIZE_8:
|
---|
1314 | gUserInput->InputValue.Value.u8 = Option->OptionOpCode->Value.u8;
|
---|
1315 | break;
|
---|
1316 | case EFI_IFR_TYPE_NUM_SIZE_16:
|
---|
1317 | CopyMem (&gUserInput->InputValue.Value.u16, &Option->OptionOpCode->Value.u16, sizeof (UINT16));
|
---|
1318 | break;
|
---|
1319 | case EFI_IFR_TYPE_NUM_SIZE_32:
|
---|
1320 | CopyMem (&gUserInput->InputValue.Value.u32, &Option->OptionOpCode->Value.u32, sizeof (UINT32));
|
---|
1321 | break;
|
---|
1322 | case EFI_IFR_TYPE_NUM_SIZE_64:
|
---|
1323 | CopyMem (&gUserInput->InputValue.Value.u64, &Option->OptionOpCode->Value.u64, sizeof (UINT64));
|
---|
1324 | break;
|
---|
1325 | default:
|
---|
1326 | ASSERT (FALSE);
|
---|
1327 | break;
|
---|
1328 | }
|
---|
1329 |
|
---|
1330 | gUserInput->SelectedStatement = Question;
|
---|
1331 | gMisMatch = TRUE;
|
---|
1332 | FreePool (*OptionString);
|
---|
1333 | *OptionString = NULL;
|
---|
1334 | return EFI_NOT_FOUND;
|
---|
1335 | }
|
---|
1336 | }
|
---|
1337 |
|
---|
1338 | Character[0] = LEFT_ONEOF_DELIMITER;
|
---|
1339 | NewStrCat (OptionString[0], MaxLen, Character);
|
---|
1340 | StringPtr = GetToken (OneOfOption->OptionOpCode->Option, gFormData->HiiHandle);
|
---|
1341 | ASSERT (StringPtr != NULL);
|
---|
1342 | NewStrCat (OptionString[0], MaxLen, StringPtr);
|
---|
1343 | Character[0] = RIGHT_ONEOF_DELIMITER;
|
---|
1344 | NewStrCat (OptionString[0], MaxLen, Character);
|
---|
1345 |
|
---|
1346 | FreePool (StringPtr);
|
---|
1347 | }
|
---|
1348 |
|
---|
1349 | break;
|
---|
1350 |
|
---|
1351 | case EFI_IFR_CHECKBOX_OP:
|
---|
1352 | if (Selected) {
|
---|
1353 | //
|
---|
1354 | // Since this is a BOOLEAN operation, flip it upon selection
|
---|
1355 | //
|
---|
1356 | gUserInput->InputValue.Type = QuestionValue->Type;
|
---|
1357 | gUserInput->InputValue.Value.b = (BOOLEAN)(QuestionValue->Value.b ? FALSE : TRUE);
|
---|
1358 |
|
---|
1359 | //
|
---|
1360 | // Perform inconsistent check
|
---|
1361 | //
|
---|
1362 | return EFI_SUCCESS;
|
---|
1363 | } else {
|
---|
1364 | *OptionString = AllocateZeroPool (BufferSize);
|
---|
1365 | ASSERT (*OptionString);
|
---|
1366 |
|
---|
1367 | *OptionString[0] = LEFT_CHECKBOX_DELIMITER;
|
---|
1368 |
|
---|
1369 | if (QuestionValue->Value.b) {
|
---|
1370 | *(OptionString[0] + 1) = CHECK_ON;
|
---|
1371 | } else {
|
---|
1372 | *(OptionString[0] + 1) = CHECK_OFF;
|
---|
1373 | }
|
---|
1374 |
|
---|
1375 | *(OptionString[0] + 2) = RIGHT_CHECKBOX_DELIMITER;
|
---|
1376 | }
|
---|
1377 |
|
---|
1378 | break;
|
---|
1379 |
|
---|
1380 | case EFI_IFR_NUMERIC_OP:
|
---|
1381 | if (Selected) {
|
---|
1382 | //
|
---|
1383 | // Go ask for input
|
---|
1384 | //
|
---|
1385 | Status = GetNumericInput (MenuOption);
|
---|
1386 | } else {
|
---|
1387 | *OptionString = AllocateZeroPool (BufferSize);
|
---|
1388 | ASSERT (*OptionString);
|
---|
1389 |
|
---|
1390 | *OptionString[0] = LEFT_NUMERIC_DELIMITER;
|
---|
1391 |
|
---|
1392 | //
|
---|
1393 | // Formatted print
|
---|
1394 | //
|
---|
1395 | PrintFormattedNumber (Question, FormattedNumber, 21 * sizeof (CHAR16));
|
---|
1396 | Number = (UINT16)GetStringWidth (FormattedNumber);
|
---|
1397 | CopyMem (OptionString[0] + 1, FormattedNumber, Number);
|
---|
1398 |
|
---|
1399 | *(OptionString[0] + Number / 2) = RIGHT_NUMERIC_DELIMITER;
|
---|
1400 | }
|
---|
1401 |
|
---|
1402 | break;
|
---|
1403 |
|
---|
1404 | case EFI_IFR_DATE_OP:
|
---|
1405 | if (Selected) {
|
---|
1406 | //
|
---|
1407 | // This is similar to numerics
|
---|
1408 | //
|
---|
1409 | Status = GetNumericInput (MenuOption);
|
---|
1410 | } else {
|
---|
1411 | *OptionString = AllocateZeroPool (BufferSize);
|
---|
1412 | ASSERT (*OptionString);
|
---|
1413 |
|
---|
1414 | switch (MenuOption->Sequence) {
|
---|
1415 | case 0:
|
---|
1416 | *OptionString[0] = LEFT_NUMERIC_DELIMITER;
|
---|
1417 | if (QuestionValue->Value.date.Month == 0xff) {
|
---|
1418 | UnicodeSPrint (OptionString[0] + 1, 21 * sizeof (CHAR16), L"??");
|
---|
1419 | } else {
|
---|
1420 | UnicodeSPrint (OptionString[0] + 1, 21 * sizeof (CHAR16), L"%02d", QuestionValue->Value.date.Month);
|
---|
1421 | }
|
---|
1422 |
|
---|
1423 | *(OptionString[0] + 3) = DATE_SEPARATOR;
|
---|
1424 | break;
|
---|
1425 |
|
---|
1426 | case 1:
|
---|
1427 | SetUnicodeMem (OptionString[0], 4, L' ');
|
---|
1428 | if (QuestionValue->Value.date.Day == 0xff) {
|
---|
1429 | UnicodeSPrint (OptionString[0] + 4, 21 * sizeof (CHAR16), L"??");
|
---|
1430 | } else {
|
---|
1431 | UnicodeSPrint (OptionString[0] + 4, 21 * sizeof (CHAR16), L"%02d", QuestionValue->Value.date.Day);
|
---|
1432 | }
|
---|
1433 |
|
---|
1434 | *(OptionString[0] + 6) = DATE_SEPARATOR;
|
---|
1435 | break;
|
---|
1436 |
|
---|
1437 | case 2:
|
---|
1438 | SetUnicodeMem (OptionString[0], 7, L' ');
|
---|
1439 | if (QuestionValue->Value.date.Year == 0xff) {
|
---|
1440 | UnicodeSPrint (OptionString[0] + 7, 21 * sizeof (CHAR16), L"????");
|
---|
1441 | } else {
|
---|
1442 | UnicodeSPrint (OptionString[0] + 7, 21 * sizeof (CHAR16), L"%04d", QuestionValue->Value.date.Year);
|
---|
1443 | }
|
---|
1444 |
|
---|
1445 | *(OptionString[0] + 11) = RIGHT_NUMERIC_DELIMITER;
|
---|
1446 | break;
|
---|
1447 | }
|
---|
1448 | }
|
---|
1449 |
|
---|
1450 | break;
|
---|
1451 |
|
---|
1452 | case EFI_IFR_TIME_OP:
|
---|
1453 | if (Selected) {
|
---|
1454 | //
|
---|
1455 | // This is similar to numerics
|
---|
1456 | //
|
---|
1457 | Status = GetNumericInput (MenuOption);
|
---|
1458 | } else {
|
---|
1459 | *OptionString = AllocateZeroPool (BufferSize);
|
---|
1460 | ASSERT (*OptionString);
|
---|
1461 |
|
---|
1462 | switch (MenuOption->Sequence) {
|
---|
1463 | case 0:
|
---|
1464 | *OptionString[0] = LEFT_NUMERIC_DELIMITER;
|
---|
1465 | if (QuestionValue->Value.time.Hour == 0xff) {
|
---|
1466 | UnicodeSPrint (OptionString[0] + 1, 21 * sizeof (CHAR16), L"??");
|
---|
1467 | } else {
|
---|
1468 | UnicodeSPrint (OptionString[0] + 1, 21 * sizeof (CHAR16), L"%02d", QuestionValue->Value.time.Hour);
|
---|
1469 | }
|
---|
1470 |
|
---|
1471 | *(OptionString[0] + 3) = TIME_SEPARATOR;
|
---|
1472 | break;
|
---|
1473 |
|
---|
1474 | case 1:
|
---|
1475 | SetUnicodeMem (OptionString[0], 4, L' ');
|
---|
1476 | if (QuestionValue->Value.time.Minute == 0xff) {
|
---|
1477 | UnicodeSPrint (OptionString[0] + 4, 21 * sizeof (CHAR16), L"??");
|
---|
1478 | } else {
|
---|
1479 | UnicodeSPrint (OptionString[0] + 4, 21 * sizeof (CHAR16), L"%02d", QuestionValue->Value.time.Minute);
|
---|
1480 | }
|
---|
1481 |
|
---|
1482 | *(OptionString[0] + 6) = TIME_SEPARATOR;
|
---|
1483 | break;
|
---|
1484 |
|
---|
1485 | case 2:
|
---|
1486 | SetUnicodeMem (OptionString[0], 7, L' ');
|
---|
1487 | if (QuestionValue->Value.time.Second == 0xff) {
|
---|
1488 | UnicodeSPrint (OptionString[0] + 7, 21 * sizeof (CHAR16), L"??");
|
---|
1489 | } else {
|
---|
1490 | UnicodeSPrint (OptionString[0] + 7, 21 * sizeof (CHAR16), L"%02d", QuestionValue->Value.time.Second);
|
---|
1491 | }
|
---|
1492 |
|
---|
1493 | *(OptionString[0] + 9) = RIGHT_NUMERIC_DELIMITER;
|
---|
1494 | break;
|
---|
1495 | }
|
---|
1496 | }
|
---|
1497 |
|
---|
1498 | break;
|
---|
1499 |
|
---|
1500 | case EFI_IFR_STRING_OP:
|
---|
1501 | if (Selected) {
|
---|
1502 | StringPtr = AllocateZeroPool (Question->CurrentValue.BufferLen + sizeof (CHAR16));
|
---|
1503 | ASSERT (StringPtr);
|
---|
1504 | CopyMem (StringPtr, Question->CurrentValue.Buffer, Question->CurrentValue.BufferLen);
|
---|
1505 |
|
---|
1506 | Status = ReadString (MenuOption, gPromptForData, StringPtr);
|
---|
1507 | if (EFI_ERROR (Status)) {
|
---|
1508 | FreePool (StringPtr);
|
---|
1509 | return Status;
|
---|
1510 | }
|
---|
1511 |
|
---|
1512 | gUserInput->InputValue.Buffer = AllocateCopyPool (Question->CurrentValue.BufferLen, StringPtr);
|
---|
1513 | gUserInput->InputValue.BufferLen = Question->CurrentValue.BufferLen;
|
---|
1514 | gUserInput->InputValue.Type = Question->CurrentValue.Type;
|
---|
1515 | gUserInput->InputValue.Value.string = HiiSetString (gFormData->HiiHandle, gUserInput->InputValue.Value.string, StringPtr, NULL);
|
---|
1516 | FreePool (StringPtr);
|
---|
1517 | return EFI_SUCCESS;
|
---|
1518 | } else {
|
---|
1519 | *OptionString = AllocateZeroPool (BufferSize);
|
---|
1520 | ASSERT (*OptionString);
|
---|
1521 |
|
---|
1522 | if (((CHAR16 *)Question->CurrentValue.Buffer)[0] == 0x0000) {
|
---|
1523 | *(OptionString[0]) = '_';
|
---|
1524 | } else {
|
---|
1525 | if (Question->CurrentValue.BufferLen < BufferSize) {
|
---|
1526 | BufferSize = Question->CurrentValue.BufferLen;
|
---|
1527 | }
|
---|
1528 |
|
---|
1529 | CopyMem (OptionString[0], (CHAR16 *)Question->CurrentValue.Buffer, BufferSize);
|
---|
1530 | }
|
---|
1531 | }
|
---|
1532 |
|
---|
1533 | break;
|
---|
1534 |
|
---|
1535 | case EFI_IFR_PASSWORD_OP:
|
---|
1536 | if (Selected) {
|
---|
1537 | Status = PasswordProcess (MenuOption);
|
---|
1538 | }
|
---|
1539 |
|
---|
1540 | break;
|
---|
1541 |
|
---|
1542 | default:
|
---|
1543 | break;
|
---|
1544 | }
|
---|
1545 |
|
---|
1546 | return Status;
|
---|
1547 | }
|
---|
1548 |
|
---|
1549 | /**
|
---|
1550 | Process the help string: Split StringPtr to several lines of strings stored in
|
---|
1551 | FormattedString and the glyph width of each line cannot exceed gHelpBlockWidth.
|
---|
1552 |
|
---|
1553 | @param StringPtr The entire help string.
|
---|
1554 | @param FormattedString The oupput formatted string.
|
---|
1555 | @param EachLineWidth The max string length of each line in the formatted string.
|
---|
1556 | @param RowCount TRUE: if Question is selected.
|
---|
1557 |
|
---|
1558 | **/
|
---|
1559 | UINTN
|
---|
1560 | ProcessHelpString (
|
---|
1561 | IN CHAR16 *StringPtr,
|
---|
1562 | OUT CHAR16 **FormattedString,
|
---|
1563 | OUT UINT16 *EachLineWidth,
|
---|
1564 | IN UINTN RowCount
|
---|
1565 | )
|
---|
1566 | {
|
---|
1567 | UINTN Index;
|
---|
1568 | CHAR16 *OutputString;
|
---|
1569 | UINTN TotalRowNum;
|
---|
1570 | UINTN CheckedNum;
|
---|
1571 | UINT16 GlyphWidth;
|
---|
1572 | UINT16 LineWidth;
|
---|
1573 | UINT16 MaxStringLen;
|
---|
1574 | UINT16 StringLen;
|
---|
1575 |
|
---|
1576 | TotalRowNum = 0;
|
---|
1577 | CheckedNum = 0;
|
---|
1578 | GlyphWidth = 1;
|
---|
1579 | Index = 0;
|
---|
1580 | MaxStringLen = 0;
|
---|
1581 | StringLen = 0;
|
---|
1582 |
|
---|
1583 | //
|
---|
1584 | // Set default help string width.
|
---|
1585 | //
|
---|
1586 | LineWidth = (UINT16)(gHelpBlockWidth - 1);
|
---|
1587 |
|
---|
1588 | //
|
---|
1589 | // Get row number of the String.
|
---|
1590 | //
|
---|
1591 | while ((StringLen = GetLineByWidth (StringPtr, LineWidth, &GlyphWidth, &Index, &OutputString)) != 0) {
|
---|
1592 | if (StringLen > MaxStringLen) {
|
---|
1593 | MaxStringLen = StringLen;
|
---|
1594 | }
|
---|
1595 |
|
---|
1596 | TotalRowNum++;
|
---|
1597 | FreePool (OutputString);
|
---|
1598 | }
|
---|
1599 |
|
---|
1600 | *EachLineWidth = MaxStringLen;
|
---|
1601 |
|
---|
1602 | *FormattedString = AllocateZeroPool (TotalRowNum * MaxStringLen * sizeof (CHAR16));
|
---|
1603 | ASSERT (*FormattedString != NULL);
|
---|
1604 |
|
---|
1605 | //
|
---|
1606 | // Generate formatted help string array.
|
---|
1607 | //
|
---|
1608 | GlyphWidth = 1;
|
---|
1609 | Index = 0;
|
---|
1610 | while ((StringLen = GetLineByWidth (StringPtr, LineWidth, &GlyphWidth, &Index, &OutputString)) != 0) {
|
---|
1611 | CopyMem (*FormattedString + CheckedNum * MaxStringLen, OutputString, StringLen * sizeof (CHAR16));
|
---|
1612 | CheckedNum++;
|
---|
1613 | FreePool (OutputString);
|
---|
1614 | }
|
---|
1615 |
|
---|
1616 | return TotalRowNum;
|
---|
1617 | }
|
---|