]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLibInternal.c
Update Browser to provide the customization possibilities.
[mirror_edk2.git] / MdeModulePkg / Library / CustomizedDisplayLib / CustomizedDisplayLibInternal.c
CommitLineData
7c6c064c
ED
1/** @file\r
2\r
3 This library class defines a set of interfaces to customize Display module\r
4\r
5Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>\r
6This program and the accompanying materials are licensed and made available under \r
7the terms and conditions of the BSD License that accompanies this distribution. \r
8The full text of the license may be found at\r
9http://opensource.org/licenses/bsd-license.php. \r
10\r
11THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
12WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13\r
14**/\r
15#include "CustomizedDisplayLibInternal.h"\r
16\r
17EFI_SCREEN_DESCRIPTOR gScreenDimensions;\r
18CHAR16 *mLibUnknownString;\r
19extern EFI_HII_HANDLE mCDLStringPackHandle;\r
20CHAR16 *mSpaceBuffer;\r
21#define SPACE_BUFFER_SIZE 1000\r
22\r
23//\r
24// Browser Global Strings\r
25//\r
26CHAR16 *gEnterString;\r
27CHAR16 *gEnterCommitString;\r
28CHAR16 *gEnterEscapeString;\r
29CHAR16 *gEscapeString;\r
30CHAR16 *gMoveHighlight;\r
31CHAR16 *gDecNumericInput;\r
32CHAR16 *gHexNumericInput;\r
33CHAR16 *gToggleCheckBox;\r
34CHAR16 *gLibEmptyString;\r
35CHAR16 *gAreYouSure;\r
36CHAR16 *gYesResponse;\r
37CHAR16 *gNoResponse;\r
38CHAR16 *gPlusString;\r
39CHAR16 *gMinusString;\r
40CHAR16 *gAdjustNumber;\r
41CHAR16 *gSaveChanges;\r
42CHAR16 *gNvUpdateMessage;\r
43CHAR16 *gInputErrorMessage;\r
44\r
45/**\r
46\r
47 Print banner info for front page.\r
48\r
49 @param[in] FormData Form Data to be shown in Page\r
50 \r
51**/\r
52VOID\r
53PrintBannerInfo ( \r
54 IN FORM_DISPLAY_ENGINE_FORM *FormData\r
55 )\r
56{\r
57 UINT8 Line;\r
58 UINT8 Alignment;\r
59 CHAR16 *StrFrontPageBanner;\r
60 UINT8 RowIdx;\r
61 UINT8 ColumnIdx;\r
62\r
63 //\r
64 // ClearLines(0, LocalScreen.RightColumn, 0, BANNER_HEIGHT-1, BANNER_TEXT | BANNER_BACKGROUND);\r
65 //\r
66 ClearLines (\r
67 gScreenDimensions.LeftColumn,\r
68 gScreenDimensions.RightColumn,\r
69 gScreenDimensions.TopRow,\r
70 FRONT_PAGE_HEADER_HEIGHT - 1 + gScreenDimensions.TopRow,\r
71 BANNER_TEXT | BANNER_BACKGROUND\r
72 );\r
73\r
74 //\r
75 // for (Line = 0; Line < BANNER_HEIGHT; Line++) {\r
76 //\r
77 for (Line = (UINT8) gScreenDimensions.TopRow; Line < BANNER_HEIGHT + (UINT8) gScreenDimensions.TopRow; Line++) {\r
78 //\r
79 // for (Alignment = 0; Alignment < BANNER_COLUMNS; Alignment++) {\r
80 //\r
81 for (Alignment = (UINT8) gScreenDimensions.LeftColumn;\r
82 Alignment < BANNER_COLUMNS + (UINT8) gScreenDimensions.LeftColumn;\r
83 Alignment++\r
84 ) {\r
85 RowIdx = (UINT8) (Line - (UINT8) gScreenDimensions.TopRow);\r
86 ColumnIdx = (UINT8) (Alignment - (UINT8) gScreenDimensions.LeftColumn);\r
87 \r
88 ASSERT (RowIdx < BANNER_HEIGHT && ColumnIdx < BANNER_COLUMNS);\r
89 \r
90 if (gBannerData!= NULL && gBannerData->Banner[RowIdx][ColumnIdx] != 0x0000) {\r
91 StrFrontPageBanner = LibGetToken (gBannerData->Banner[RowIdx][ColumnIdx], FormData->HiiHandle);\r
92 } else {\r
93 continue;\r
94 }\r
95 \r
96 switch (Alignment - gScreenDimensions.LeftColumn) {\r
97 case 0:\r
98 //\r
99 // Handle left column\r
100 //\r
101 PrintStringAt (gScreenDimensions.LeftColumn + BANNER_LEFT_COLUMN_INDENT, Line, StrFrontPageBanner);\r
102 break;\r
103 \r
104 case 1:\r
105 //\r
106 // Handle center column\r
107 //\r
108 PrintStringAt (\r
109 gScreenDimensions.LeftColumn + (gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn) / 3,\r
110 Line,\r
111 StrFrontPageBanner\r
112 );\r
113 break;\r
114 \r
115 case 2:\r
116 //\r
117 // Handle right column\r
118 //\r
119 PrintStringAt (\r
120 gScreenDimensions.LeftColumn + (gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn) * 2 / 3,\r
121 Line,\r
122 StrFrontPageBanner\r
123 );\r
124 break;\r
125 }\r
126 \r
127 FreePool (StrFrontPageBanner);\r
128 }\r
129 }\r
130}\r
131\r
132/**\r
133\r
134 Print framework for a page.\r
135 \r
136**/\r
137VOID\r
138PrintFramework (\r
139 VOID\r
140 )\r
141{\r
142 UINTN Index;\r
143 CHAR16 Character;\r
144 CHAR16 *Buffer;\r
145 UINTN Row;\r
146\r
147 Buffer = AllocateZeroPool (0x10000);\r
148 ASSERT (Buffer != NULL);\r
149 Character = BOXDRAW_HORIZONTAL;\r
150 for (Index = 0; Index + 2 < (gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn); Index++) {\r
151 Buffer[Index] = Character;\r
152 }\r
153\r
154 ClearLines (\r
155 gScreenDimensions.LeftColumn,\r
156 gScreenDimensions.RightColumn,\r
157 gScreenDimensions.BottomRow - STATUS_BAR_HEIGHT - gFooterHeight,\r
158 gScreenDimensions.BottomRow - STATUS_BAR_HEIGHT - 1,\r
159 KEYHELP_TEXT | KEYHELP_BACKGROUND\r
160 );\r
161\r
162 if ((gClassOfVfr & FORMSET_CLASS_PLATFORM_SETUP) == FORMSET_CLASS_PLATFORM_SETUP) {\r
163 ClearLines (\r
164 gScreenDimensions.LeftColumn,\r
165 gScreenDimensions.RightColumn,\r
166 gScreenDimensions.TopRow,\r
167 gScreenDimensions.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT - 1,\r
168 TITLE_TEXT | TITLE_BACKGROUND\r
169 );\r
170 //\r
171 // Print Top border line\r
172 // +------------------------------------------------------------------------------+\r
173 // ? ?\r
174 // +------------------------------------------------------------------------------+\r
175 //\r
176 Character = BOXDRAW_DOWN_RIGHT;\r
177\r
178 PrintCharAt ((UINTN) -1, (UINTN) -1, Character);\r
179 PrintStringAt ((UINTN) -1, (UINTN) -1, Buffer);\r
180\r
181 Character = BOXDRAW_DOWN_LEFT;\r
182 PrintCharAt ((UINTN) -1, (UINTN) -1, Character);\r
183\r
184 Character = BOXDRAW_VERTICAL;\r
185 for (Row = gScreenDimensions.TopRow + 1; Row <= gScreenDimensions.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT - 2; Row++) {\r
186 PrintCharAt (gScreenDimensions.LeftColumn, Row, Character);\r
187 PrintCharAt (gScreenDimensions.RightColumn - 1, Row, Character);\r
188 }\r
189\r
190 Character = BOXDRAW_UP_RIGHT;\r
191 PrintCharAt (gScreenDimensions.LeftColumn, gScreenDimensions.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT - 1, Character);\r
192 PrintStringAt ((UINTN) -1, (UINTN) -1, Buffer);\r
193\r
194 Character = BOXDRAW_UP_LEFT;\r
195 PrintCharAt ((UINTN) -1, (UINTN) -1, Character);\r
196\r
197 //\r
198 // Print Bottom border line\r
199 // +------------------------------------------------------------------------------+\r
200 // ? ?\r
201 // +------------------------------------------------------------------------------+\r
202 //\r
203 Character = BOXDRAW_DOWN_RIGHT;\r
204 PrintCharAt (gScreenDimensions.LeftColumn, gScreenDimensions.BottomRow - STATUS_BAR_HEIGHT - gFooterHeight, Character);\r
205\r
206 PrintStringAt ((UINTN) -1, (UINTN) -1, Buffer);\r
207\r
208 Character = BOXDRAW_DOWN_LEFT;\r
209 PrintCharAt ((UINTN) -1, (UINTN) -1, Character);\r
210 Character = BOXDRAW_VERTICAL;\r
211 for (Row = gScreenDimensions.BottomRow - STATUS_BAR_HEIGHT - gFooterHeight + 1;\r
212 Row <= gScreenDimensions.BottomRow - STATUS_BAR_HEIGHT - 2;\r
213 Row++\r
214 ) {\r
215 PrintCharAt (gScreenDimensions.LeftColumn, Row, Character);\r
216 PrintCharAt (gScreenDimensions.RightColumn - 1, Row, Character);\r
217 }\r
218\r
219 Character = BOXDRAW_UP_RIGHT;\r
220 PrintCharAt (gScreenDimensions.LeftColumn, gScreenDimensions.BottomRow - STATUS_BAR_HEIGHT - 1, Character);\r
221\r
222 PrintStringAt ((UINTN) -1, (UINTN) -1, Buffer);\r
223\r
224 Character = BOXDRAW_UP_LEFT;\r
225 PrintCharAt ((UINTN) -1, (UINTN) -1, Character);\r
226 }\r
227 \r
228 FreePool (Buffer);\r
229}\r
230\r
231/**\r
232 Print the form title.\r
233\r
234 @param[in] FormData Form Data to be shown in Page\r
235\r
236**/\r
237VOID\r
238PrintFormTitle (\r
239 IN FORM_DISPLAY_ENGINE_FORM *FormData\r
240 )\r
241{\r
242 CHAR16 *TitleStr;\r
243\r
244 if ((gClassOfVfr & FORMSET_CLASS_PLATFORM_SETUP) != FORMSET_CLASS_PLATFORM_SETUP) { \r
245 //\r
246 // Only Setup Page need Title.\r
247 //\r
248 return;\r
249 }\r
250 \r
251 TitleStr = LibGetToken (FormData->FormTitle, FormData->HiiHandle);\r
252 ASSERT (TitleStr != NULL);\r
253 \r
254 gST->ConOut->SetAttribute (gST->ConOut, TITLE_TEXT | TITLE_BACKGROUND);\r
255\r
256 ClearLines (\r
257 gScreenDimensions.LeftColumn + 1,\r
258 gScreenDimensions.RightColumn - 1,\r
259 gScreenDimensions.TopRow + 1,\r
260 gScreenDimensions.TopRow + 1,\r
261 TITLE_TEXT | TITLE_BACKGROUND\r
262 );\r
263\r
264 PrintStringAt (\r
265 (gScreenDimensions.RightColumn + gScreenDimensions.LeftColumn - LibGetStringWidth (TitleStr) / 2) / 2,\r
266 gScreenDimensions.TopRow + 1,\r
267 TitleStr\r
268 );\r
269\r
270 FreePool (TitleStr);\r
271}\r
272\r
273/**\r
274 Process some op code which is not recognized by browser core.\r
275\r
276 @param OpCodeData The pointer to the op code buffer.\r
277\r
278 @return EFI_SUCCESS Pass the statement success.\r
279\r
280**/\r
281VOID\r
282ProcessUserOpcode(\r
283 IN EFI_IFR_OP_HEADER *OpCodeData\r
284 )\r
285{\r
286 switch (OpCodeData->OpCode) {\r
287 case EFI_IFR_GUID_OP: \r
288 if (CompareGuid (&gEfiIfrTianoGuid, (EFI_GUID *)((CHAR8*) OpCodeData + sizeof (EFI_IFR_OP_HEADER)))) {\r
289 //\r
290 // Tiano specific GUIDed opcodes\r
291 //\r
292 switch (((EFI_IFR_GUID_LABEL *) OpCodeData)->ExtendOpCode) {\r
293 case EFI_IFR_EXTEND_OP_LABEL:\r
294 //\r
295 // just ignore label\r
296 //\r
297 break;\r
298\r
299 case EFI_IFR_EXTEND_OP_BANNER:\r
300 //\r
301 // Only in front page form set, we care about the banner data.\r
302 //\r
303 if ((gClassOfVfr & FORMSET_CLASS_FRONT_PAGE) == FORMSET_CLASS_FRONT_PAGE) {\r
304 //\r
305 // Initialize Driver private data\r
306 //\r
307 if (gBannerData == NULL) {\r
308 gBannerData = AllocateZeroPool (sizeof (BANNER_DATA));\r
309 ASSERT (gBannerData != NULL);\r
310 }\r
311 \r
312 CopyMem (\r
313 &gBannerData->Banner[((EFI_IFR_GUID_BANNER *) OpCodeData)->LineNumber][\r
314 ((EFI_IFR_GUID_BANNER *) OpCodeData)->Alignment],\r
315 &((EFI_IFR_GUID_BANNER *) OpCodeData)->Title,\r
316 sizeof (EFI_STRING_ID)\r
317 );\r
318 }\r
319 break;\r
320\r
321 case EFI_IFR_EXTEND_OP_SUBCLASS:\r
322 if (((EFI_IFR_GUID_SUBCLASS *) OpCodeData)->SubClass == EFI_FRONT_PAGE_SUBCLASS) {\r
323 gClassOfVfr = FORMSET_CLASS_FRONT_PAGE;\r
324 }\r
325 break;\r
326\r
327 default:\r
328 break;\r
329 }\r
330 }\r
331 break;\r
332\r
333 default:\r
334 break;\r
335 }\r
336}\r
337\r
338/**\r
339 Process some op codes which is out side of current form.\r
340 \r
341 @param FormData Pointer to the form data.\r
342\r
343 @return EFI_SUCCESS Pass the statement success.\r
344\r
345**/\r
346VOID\r
347ProcessExternedOpcode (\r
348 IN FORM_DISPLAY_ENGINE_FORM *FormData\r
349 )\r
350{\r
351 LIST_ENTRY *Link;\r
352 FORM_DISPLAY_ENGINE_STATEMENT *Statement;\r
353\r
354 Link = GetFirstNode (&FormData->StatementListOSF);\r
355 while (!IsNull (&FormData->StatementListOSF, Link)) {\r
356 Statement = FORM_DISPLAY_ENGINE_STATEMENT_FROM_LINK (Link);\r
357 Link = GetNextNode (&FormData->StatementListOSF, Link);\r
358\r
359 ProcessUserOpcode(Statement->OpCode);\r
360 }\r
361\r
362 Link = GetFirstNode (&FormData->StatementListHead);\r
363 while (!IsNull (&FormData->StatementListHead, Link)) {\r
364 Statement = FORM_DISPLAY_ENGINE_STATEMENT_FROM_LINK (Link);\r
365 Link = GetNextNode (&FormData->StatementListHead, Link);\r
366\r
367 ProcessUserOpcode(Statement->OpCode);\r
368 }\r
369}\r
370\r
371/**\r
372 Validate the input screen diemenstion info.\r
373\r
374 @param FormData The input form data info.\r
375\r
376 @return EFI_SUCCESS The input screen info is acceptable.\r
377 @return EFI_INVALID_PARAMETER The input screen info is not acceptable.\r
378\r
379**/\r
380EFI_STATUS \r
381ScreenDiemensionInfoValidate (\r
382 IN FORM_DISPLAY_ENGINE_FORM *FormData\r
383 )\r
384{\r
385 LIST_ENTRY *Link;\r
386 UINTN Index;\r
387\r
388 //\r
389 // Calculate total number of Register HotKeys. \r
390 //\r
391 Index = 0;\r
392 if (!IsListEmpty (&FormData->HotKeyListHead)){\r
393 Link = GetFirstNode (&FormData->HotKeyListHead);\r
394 while (!IsNull (&FormData->HotKeyListHead, Link)) {\r
395 Link = GetNextNode (&FormData->HotKeyListHead, Link);\r
396 Index ++;\r
397 }\r
398 }\r
399\r
400 //\r
401 // Show three HotKeys help information on one row.\r
402 //\r
403 gFooterHeight = FOOTER_HEIGHT + (Index / 3);\r
404\r
405\r
406 ZeroMem (&gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));\r
407 gST->ConOut->QueryMode (\r
408 gST->ConOut,\r
409 gST->ConOut->Mode->Mode,\r
410 &gScreenDimensions.RightColumn,\r
411 &gScreenDimensions.BottomRow\r
412 );\r
413\r
414 //\r
415 // Check local dimension vs. global dimension.\r
416 //\r
417 if (FormData->ScreenDimensions != NULL) {\r
418 if ((gScreenDimensions.RightColumn < FormData->ScreenDimensions->RightColumn) ||\r
419 (gScreenDimensions.BottomRow < FormData->ScreenDimensions->BottomRow)\r
420 ) {\r
421 return EFI_INVALID_PARAMETER;\r
422 } else {\r
423 //\r
424 // Local dimension validation.\r
425 //\r
426 if ((FormData->ScreenDimensions->RightColumn > FormData->ScreenDimensions->LeftColumn) &&\r
427 (FormData->ScreenDimensions->BottomRow > FormData->ScreenDimensions->TopRow) &&\r
428 ((FormData->ScreenDimensions->RightColumn - FormData->ScreenDimensions->LeftColumn) > 2) &&\r
429 ((FormData->ScreenDimensions->BottomRow - FormData->ScreenDimensions->TopRow) > STATUS_BAR_HEIGHT +\r
430 FRONT_PAGE_HEADER_HEIGHT + gFooterHeight + 3)) {\r
431 CopyMem (&gScreenDimensions, (VOID *) FormData->ScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));\r
432 } else {\r
433 return EFI_INVALID_PARAMETER;\r
434 }\r
435 }\r
436 }\r
437\r
438 return EFI_SUCCESS;\r
439}\r
440\r
441/**\r
442 Get the string based on the StringId and HII Package List Handle.\r
443\r
444 @param Token The String's ID.\r
445 @param HiiHandle The package list in the HII database to search for\r
446 the specified string.\r
447\r
448 @return The output string.\r
449\r
450**/\r
451CHAR16 *\r
452LibGetToken (\r
453 IN EFI_STRING_ID Token,\r
454 IN EFI_HII_HANDLE HiiHandle\r
455 )\r
456{\r
457 EFI_STRING String;\r
458\r
459 String = HiiGetString (HiiHandle, Token, NULL);\r
460 if (String == NULL) {\r
461 String = AllocateCopyPool (StrSize (mLibUnknownString), mLibUnknownString);\r
462 ASSERT (String != NULL);\r
463 }\r
464\r
465 return (CHAR16 *) String;\r
466}\r
467\r
468\r
469/**\r
470 Count the storage space of a Unicode string.\r
471\r
472 This function handles the Unicode string with NARROW_CHAR\r
473 and WIDE_CHAR control characters. NARROW_HCAR and WIDE_CHAR\r
474 does not count in the resultant output. If a WIDE_CHAR is\r
475 hit, then 2 Unicode character will consume an output storage\r
476 space with size of CHAR16 till a NARROW_CHAR is hit.\r
477\r
478 If String is NULL, then ASSERT ().\r
479\r
480 @param String The input string to be counted.\r
481\r
482 @return Storage space for the input string.\r
483\r
484**/\r
485UINTN\r
486LibGetStringWidth (\r
487 IN CHAR16 *String\r
488 )\r
489{\r
490 UINTN Index;\r
491 UINTN Count;\r
492 UINTN IncrementValue;\r
493\r
494 ASSERT (String != NULL);\r
495 if (String == NULL) {\r
496 return 0;\r
497 }\r
498\r
499 Index = 0;\r
500 Count = 0;\r
501 IncrementValue = 1;\r
502\r
503 do {\r
504 //\r
505 // Advance to the null-terminator or to the first width directive\r
506 //\r
507 for (;\r
508 (String[Index] != NARROW_CHAR) && (String[Index] != WIDE_CHAR) && (String[Index] != 0);\r
509 Index++, Count = Count + IncrementValue\r
510 )\r
511 ;\r
512\r
513 //\r
514 // We hit the null-terminator, we now have a count\r
515 //\r
516 if (String[Index] == 0) {\r
517 break;\r
518 }\r
519 //\r
520 // We encountered a narrow directive - strip it from the size calculation since it doesn't get printed\r
521 // and also set the flag that determines what we increment by.(if narrow, increment by 1, if wide increment by 2)\r
522 //\r
523 if (String[Index] == NARROW_CHAR) {\r
524 //\r
525 // Skip to the next character\r
526 //\r
527 Index++;\r
528 IncrementValue = 1;\r
529 } else {\r
530 //\r
531 // Skip to the next character\r
532 //\r
533 Index++;\r
534 IncrementValue = 2;\r
535 }\r
536 } while (String[Index] != 0);\r
537\r
538 //\r
539 // Increment by one to include the null-terminator in the size\r
540 //\r
541 Count++;\r
542\r
543 return Count * sizeof (CHAR16);\r
544}\r
545\r
546/**\r
547 Show all registered HotKey help strings on bottom Rows.\r
548\r
549 @param FormData The curent input form data info.\r
550\r
551**/\r
552VOID\r
553PrintHotKeyHelpString (\r
554 IN FORM_DISPLAY_ENGINE_FORM *FormData\r
555 )\r
556{\r
557 UINTN CurrentCol;\r
558 UINTN CurrentRow;\r
559 UINTN BottomRowOfHotKeyHelp;\r
560 UINTN ColumnWidth;\r
561 UINTN Index;\r
562 EFI_SCREEN_DESCRIPTOR LocalScreen;\r
563 LIST_ENTRY *Link;\r
564 BROWSER_HOT_KEY *HotKey;\r
565\r
566 if (IsListEmpty (&FormData->HotKeyListHead)) {\r
567 return;\r
568 }\r
569\r
570 CopyMem (&LocalScreen, &gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));\r
571 ColumnWidth = (LocalScreen.RightColumn - LocalScreen.LeftColumn) / 3;\r
572 BottomRowOfHotKeyHelp = LocalScreen.BottomRow - STATUS_BAR_HEIGHT - 3;\r
573\r
574 //\r
575 // Calculate total number of Register HotKeys. \r
576 //\r
577 Index = 0;\r
578 Link = GetFirstNode (&FormData->HotKeyListHead);\r
579 while (!IsNull (&FormData->HotKeyListHead, Link)) {\r
580 HotKey = BROWSER_HOT_KEY_FROM_LINK (Link);\r
581 //\r
582 // Help string can't exceed ColumnWidth. One Row will show three Help information. \r
583 //\r
584 if (StrLen (HotKey->HelpString) > ColumnWidth) {\r
585 HotKey->HelpString[ColumnWidth] = L'\0';\r
586 }\r
587 //\r
588 // Calculate help information Column and Row.\r
589 //\r
590 if ((Index % 3) != 2) {\r
591 CurrentCol = LocalScreen.LeftColumn + (2 - Index % 3) * ColumnWidth;\r
592 } else {\r
593 CurrentCol = LocalScreen.LeftColumn + 2;\r
594 }\r
595 CurrentRow = BottomRowOfHotKeyHelp - Index / 3;\r
596 //\r
597 // Print HotKey help string on bottom Row.\r
598 //\r
599 PrintStringAt (CurrentCol, CurrentRow, HotKey->HelpString);\r
600\r
601 //\r
602 // Get Next Hot Key.\r
603 //\r
604 Link = GetNextNode (&FormData->HotKeyListHead, Link);\r
605 Index ++;\r
606 }\r
607 \r
608 return;\r
609}\r
610\r
611/**\r
612 Get step info from numeric opcode.\r
613 \r
614 @param[in] OpCode The input numeric op code.\r
615\r
616 @return step info for this opcode.\r
617**/\r
618UINT64\r
619LibGetFieldFromNum (\r
620 IN EFI_IFR_OP_HEADER *OpCode\r
621 )\r
622{\r
623 EFI_IFR_NUMERIC *NumericOp;\r
624 UINT64 Step;\r
625\r
626 NumericOp = (EFI_IFR_NUMERIC *) OpCode;\r
627 \r
628 switch (NumericOp->Flags & EFI_IFR_NUMERIC_SIZE) {\r
629 case EFI_IFR_NUMERIC_SIZE_1:\r
630 Step = NumericOp->data.u8.Step;\r
631 break;\r
632 \r
633 case EFI_IFR_NUMERIC_SIZE_2:\r
634 Step = NumericOp->data.u16.Step;\r
635 break;\r
636 \r
637 case EFI_IFR_NUMERIC_SIZE_4:\r
638 Step = NumericOp->data.u32.Step;\r
639 break;\r
640 \r
641 case EFI_IFR_NUMERIC_SIZE_8:\r
642 Step = NumericOp->data.u64.Step;\r
643 break;\r
644 \r
645 default:\r
646 Step = 0;\r
647 break;\r
648 }\r
649\r
650 return Step;\r
651}\r
652\r
653/**\r
654 Initialize the HII String Token to the correct values.\r
655\r
656**/\r
657VOID\r
658InitializeLibStrings (\r
659 VOID\r
660 )\r
661{\r
662 mLibUnknownString = L"!";\r
663\r
664 gEnterString = LibGetToken (STRING_TOKEN (ENTER_STRING), mCDLStringPackHandle);\r
665 gEnterCommitString = LibGetToken (STRING_TOKEN (ENTER_COMMIT_STRING), mCDLStringPackHandle);\r
666 gEnterEscapeString = LibGetToken (STRING_TOKEN (ENTER_ESCAPE_STRING), mCDLStringPackHandle);\r
667 gEscapeString = LibGetToken (STRING_TOKEN (ESCAPE_STRING), mCDLStringPackHandle);\r
668 gMoveHighlight = LibGetToken (STRING_TOKEN (MOVE_HIGHLIGHT), mCDLStringPackHandle);\r
669 gDecNumericInput = LibGetToken (STRING_TOKEN (DEC_NUMERIC_INPUT), mCDLStringPackHandle);\r
670 gHexNumericInput = LibGetToken (STRING_TOKEN (HEX_NUMERIC_INPUT), mCDLStringPackHandle);\r
671 gToggleCheckBox = LibGetToken (STRING_TOKEN (TOGGLE_CHECK_BOX), mCDLStringPackHandle);\r
672\r
673 gAreYouSure = LibGetToken (STRING_TOKEN (ARE_YOU_SURE), mCDLStringPackHandle);\r
674 gYesResponse = LibGetToken (STRING_TOKEN (ARE_YOU_SURE_YES), mCDLStringPackHandle);\r
675 gNoResponse = LibGetToken (STRING_TOKEN (ARE_YOU_SURE_NO), mCDLStringPackHandle);\r
676 gPlusString = LibGetToken (STRING_TOKEN (PLUS_STRING), mCDLStringPackHandle);\r
677 gMinusString = LibGetToken (STRING_TOKEN (MINUS_STRING), mCDLStringPackHandle);\r
678 gAdjustNumber = LibGetToken (STRING_TOKEN (ADJUST_NUMBER), mCDLStringPackHandle);\r
679 gSaveChanges = LibGetToken (STRING_TOKEN (SAVE_CHANGES), mCDLStringPackHandle);\r
680\r
681 gLibEmptyString = LibGetToken (STRING_TOKEN (EMPTY_STRING), mCDLStringPackHandle);\r
682\r
683 gNvUpdateMessage = LibGetToken (STRING_TOKEN (NV_UPDATE_MESSAGE), mCDLStringPackHandle);\r
684 gInputErrorMessage = LibGetToken (STRING_TOKEN (INPUT_ERROR_MESSAGE), mCDLStringPackHandle);\r
685 \r
686 //\r
687 // SpaceBuffer;\r
688 //\r
689 mSpaceBuffer = AllocatePool ((SPACE_BUFFER_SIZE + 1) * sizeof (CHAR16));\r
690 ASSERT (mSpaceBuffer != NULL);\r
691 LibSetUnicodeMem (mSpaceBuffer, SPACE_BUFFER_SIZE, L' ');\r
692 mSpaceBuffer[SPACE_BUFFER_SIZE] = L'\0';\r
693}\r
694\r
695\r
696/**\r
697 Free the HII String.\r
698\r
699**/\r
700VOID\r
701FreeLibStrings (\r
702 VOID\r
703 )\r
704{\r
705 FreePool (gEnterString);\r
706 FreePool (gEnterCommitString);\r
707 FreePool (gEnterEscapeString);\r
708 FreePool (gEscapeString);\r
709 FreePool (gMoveHighlight);\r
710 FreePool (gDecNumericInput);\r
711 FreePool (gHexNumericInput);\r
712 FreePool (gToggleCheckBox);\r
713\r
714 FreePool (gAreYouSure);\r
715 FreePool (gYesResponse);\r
716 FreePool (gNoResponse);\r
717 FreePool (gPlusString);\r
718 FreePool (gMinusString);\r
719 FreePool (gAdjustNumber);\r
720 FreePool (gSaveChanges);\r
721\r
722 FreePool (gLibEmptyString);\r
723\r
724 FreePool (gNvUpdateMessage);\r
725 FreePool (gInputErrorMessage);\r
726 \r
727 FreePool (mSpaceBuffer);\r
728}\r
729\r
730/**\r
731 Wait for a key to be pressed by user.\r
732\r
733 @param Key The key which is pressed by user.\r
734\r
735 @retval EFI_SUCCESS The function always completed successfully.\r
736\r
737**/\r
738EFI_STATUS\r
739WaitForKeyStroke (\r
740 OUT EFI_INPUT_KEY *Key\r
741 )\r
742{\r
743 EFI_STATUS Status;\r
744 UINTN Index;\r
745\r
746 while (TRUE) {\r
747 Status = gST->ConIn->ReadKeyStroke (gST->ConIn, Key);\r
748 if (!EFI_ERROR (Status)) {\r
749 break;\r
750 }\r
751\r
752 if (Status != EFI_NOT_READY) {\r
753 continue;\r
754 }\r
755 \r
756 gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &Index);\r
757 }\r
758 return Status;\r
759}\r
760\r
761\r
762/**\r
763 Set Buffer to Value for Size bytes.\r
764\r
765 @param Buffer Memory to set.\r
766 @param Size Number of bytes to set\r
767 @param Value Value of the set operation.\r
768\r
769**/\r
770VOID\r
771LibSetUnicodeMem (\r
772 IN VOID *Buffer,\r
773 IN UINTN Size,\r
774 IN CHAR16 Value\r
775 )\r
776{\r
777 CHAR16 *Ptr;\r
778\r
779 Ptr = Buffer;\r
780 while ((Size--) != 0) {\r
781 *(Ptr++) = Value;\r
782 }\r
783}\r
784\r
785/**\r
786 The internal function prints to the EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL\r
787 protocol instance.\r
788\r
789 @param Width Width of string to be print.\r
790 @param Column The position of the output string.\r
791 @param Row The position of the output string.\r
792 @param Out The EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL instance.\r
793 @param Fmt The format string.\r
794 @param Args The additional argument for the variables in the format string.\r
795\r
796 @return Number of Unicode character printed.\r
797\r
798**/\r
799UINTN\r
800PrintInternal (\r
801 IN UINTN Width, \r
802 IN UINTN Column,\r
803 IN UINTN Row,\r
804 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *Out,\r
805 IN CHAR16 *Fmt,\r
806 IN VA_LIST Args\r
807 )\r
808{\r
809 CHAR16 *Buffer;\r
810 CHAR16 *BackupBuffer;\r
811 UINTN Index;\r
812 UINTN PreviousIndex;\r
813 UINTN Count;\r
814 UINTN PrintWidth;\r
815 UINTN CharWidth;\r
816\r
817 //\r
818 // For now, allocate an arbitrarily long buffer\r
819 //\r
820 Buffer = AllocateZeroPool (0x10000);\r
821 BackupBuffer = AllocateZeroPool (0x10000);\r
822 ASSERT (Buffer);\r
823 ASSERT (BackupBuffer);\r
824\r
825 if (Column != (UINTN) -1) {\r
826 Out->SetCursorPosition (Out, Column, Row);\r
827 }\r
828\r
829 UnicodeVSPrint (Buffer, 0x10000, Fmt, Args);\r
830\r
831 Out->Mode->Attribute = Out->Mode->Attribute & 0x7f;\r
832\r
833 Out->SetAttribute (Out, Out->Mode->Attribute);\r
834\r
835 Index = 0;\r
836 PreviousIndex = 0;\r
837 Count = 0;\r
838 PrintWidth = 0;\r
839 CharWidth = 1;\r
840\r
841 do {\r
842 for (; (Buffer[Index] != NARROW_CHAR) && (Buffer[Index] != WIDE_CHAR) && (Buffer[Index] != 0); Index++) {\r
843 BackupBuffer[Index] = Buffer[Index];\r
844 }\r
845\r
846 if (Buffer[Index] == 0) {\r
847 break;\r
848 }\r
849 //\r
850 // Null-terminate the temporary string\r
851 //\r
852 BackupBuffer[Index] = 0;\r
853\r
854 //\r
855 // Print this out, we are about to switch widths\r
856 //\r
857 Out->OutputString (Out, &BackupBuffer[PreviousIndex]);\r
858 Count += StrLen (&BackupBuffer[PreviousIndex]);\r
859 PrintWidth += Count * CharWidth;\r
860\r
861 //\r
862 // Preserve the current index + 1, since this is where we will start printing from next\r
863 //\r
864 PreviousIndex = Index + 1;\r
865\r
866 //\r
867 // We are at a narrow or wide character directive. Set attributes and strip it and print it\r
868 //\r
869 if (Buffer[Index] == NARROW_CHAR) {\r
870 //\r
871 // Preserve bits 0 - 6 and zero out the rest\r
872 //\r
873 Out->Mode->Attribute = Out->Mode->Attribute & 0x7f;\r
874 Out->SetAttribute (Out, Out->Mode->Attribute);\r
875 CharWidth = 1;\r
876 } else {\r
877 //\r
878 // Must be wide, set bit 7 ON\r
879 //\r
880 Out->Mode->Attribute = Out->Mode->Attribute | EFI_WIDE_ATTRIBUTE;\r
881 Out->SetAttribute (Out, Out->Mode->Attribute);\r
882 CharWidth = 2;\r
883 }\r
884\r
885 Index++;\r
886\r
887 } while (Buffer[Index] != 0);\r
888\r
889 //\r
890 // We hit the end of the string - print it\r
891 //\r
892 Out->OutputString (Out, &BackupBuffer[PreviousIndex]);\r
893 Count += StrLen (&BackupBuffer[PreviousIndex]);\r
894 PrintWidth += Count * CharWidth;\r
895 if (PrintWidth < Width) {\r
896 Out->Mode->Attribute = Out->Mode->Attribute & 0x7f;\r
897 Out->SetAttribute (Out, Out->Mode->Attribute);\r
898 Out->OutputString (Out, &mSpaceBuffer[SPACE_BUFFER_SIZE - Width + PrintWidth]);\r
899 }\r
900\r
901 FreePool (Buffer);\r
902 FreePool (BackupBuffer);\r
903 return Count;\r
904}\r
905\r
906/**\r
907 Prints a formatted unicode string to the default console, at\r
908 the supplied cursor position.\r
909\r
910 @param Width Width of String to be printed.\r
911 @param Column The cursor position to print the string at.\r
912 @param Row The cursor position to print the string at.\r
913 @param Fmt Format string.\r
914 @param ... Variable argument list for format string.\r
915\r
916 @return Length of string printed to the console\r
917\r
918**/\r
919UINTN\r
920EFIAPI\r
921PrintAt (\r
922 IN UINTN Width,\r
923 IN UINTN Column,\r
924 IN UINTN Row,\r
925 IN CHAR16 *Fmt,\r
926 ...\r
927 )\r
928{\r
929 VA_LIST Args;\r
930 UINTN LengthOfPrinted;\r
931\r
932 VA_START (Args, Fmt);\r
933 LengthOfPrinted = PrintInternal (Width, Column, Row, gST->ConOut, Fmt, Args);\r
934 VA_END (Args);\r
935 return LengthOfPrinted;\r
936}\r
937\r