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