]> git.proxmox.com Git - mirror_edk2.git/blame - ShellPkg/Application/Shell/ConsoleLogger.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / ShellPkg / Application / Shell / ConsoleLogger.c
CommitLineData
a405b86d 1/** @file\r
2 Provides interface to shell console logger.\r
3\r
c011b6c9 4 (C) Copyright 2013 Hewlett-Packard Development Company, L.P.<BR>\r
10dfa028 5 Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>\r
8550b5f0 6 (C) Copyright 2016 Hewlett-Packard Development Company, L.P.<BR>\r
56ba3746 7 SPDX-License-Identifier: BSD-2-Clause-Patent\r
a405b86d 8**/\r
9\r
a405b86d 10#include "Shell.h"\r
11\r
a405b86d 12/**\r
13 Install our intermediate ConOut into the system table to\r
14 keep a log of all the info that is displayed to the user.\r
15\r
16 @param[in] ScreensToSave Sets how many screen-worths of data to save.\r
17 @param[out] ConsoleInfo The object to pass into later functions.\r
18\r
19 @retval EFI_SUCCESS The operation was successful.\r
20 @return other The operation failed.\r
21\r
22 @sa ConsoleLoggerResetBuffers\r
23 @sa InstallProtocolInterface\r
24**/\r
25EFI_STATUS\r
47d20b54
MK
26ConsoleLoggerInstall (\r
27 IN CONST UINTN ScreensToSave,\r
28 OUT CONSOLE_LOGGER_PRIVATE_DATA **ConsoleInfo\r
a405b86d 29 )\r
30{\r
47d20b54 31 EFI_STATUS Status;\r
a405b86d 32\r
47d20b54
MK
33 ASSERT (ConsoleInfo != NULL);\r
34\r
35 (*ConsoleInfo) = AllocateZeroPool (sizeof (CONSOLE_LOGGER_PRIVATE_DATA));\r
3c865f20 36 if ((*ConsoleInfo) == NULL) {\r
37 return (EFI_OUT_OF_RESOURCES);\r
38 }\r
a405b86d 39\r
733f138d 40 (*ConsoleInfo)->Signature = CONSOLE_LOGGER_PRIVATE_DATA_SIGNATURE;\r
41 (*ConsoleInfo)->OldConOut = gST->ConOut;\r
42 (*ConsoleInfo)->OldConHandle = gST->ConsoleOutHandle;\r
43 (*ConsoleInfo)->Buffer = NULL;\r
44 (*ConsoleInfo)->BufferSize = 0;\r
45 (*ConsoleInfo)->OriginalStartRow = 0;\r
46 (*ConsoleInfo)->CurrentStartRow = 0;\r
47 (*ConsoleInfo)->RowsPerScreen = 0;\r
48 (*ConsoleInfo)->ColsPerScreen = 0;\r
49 (*ConsoleInfo)->Attributes = NULL;\r
50 (*ConsoleInfo)->AttribSize = 0;\r
51 (*ConsoleInfo)->ScreenCount = ScreensToSave;\r
52 (*ConsoleInfo)->HistoryMode.MaxMode = 1;\r
53 (*ConsoleInfo)->HistoryMode.Mode = 0;\r
54 (*ConsoleInfo)->HistoryMode.Attribute = 0;\r
55 (*ConsoleInfo)->HistoryMode.CursorColumn = 0;\r
56 (*ConsoleInfo)->HistoryMode.CursorRow = 0;\r
57 (*ConsoleInfo)->HistoryMode.CursorVisible = FALSE;\r
58 (*ConsoleInfo)->OurConOut.Reset = ConsoleLoggerReset;\r
59 (*ConsoleInfo)->OurConOut.OutputString = ConsoleLoggerOutputString;\r
60 (*ConsoleInfo)->OurConOut.TestString = ConsoleLoggerTestString;\r
61 (*ConsoleInfo)->OurConOut.QueryMode = ConsoleLoggerQueryMode;\r
62 (*ConsoleInfo)->OurConOut.SetMode = ConsoleLoggerSetMode;\r
63 (*ConsoleInfo)->OurConOut.SetAttribute = ConsoleLoggerSetAttribute;\r
64 (*ConsoleInfo)->OurConOut.ClearScreen = ConsoleLoggerClearScreen;\r
a405b86d 65 (*ConsoleInfo)->OurConOut.SetCursorPosition = ConsoleLoggerSetCursorPosition;\r
733f138d 66 (*ConsoleInfo)->OurConOut.EnableCursor = ConsoleLoggerEnableCursor;\r
67 (*ConsoleInfo)->OurConOut.Mode = gST->ConOut->Mode;\r
68 (*ConsoleInfo)->Enabled = TRUE;\r
a405b86d 69\r
47d20b54
MK
70 Status = ConsoleLoggerResetBuffers (*ConsoleInfo);\r
71 if (EFI_ERROR (Status)) {\r
72 SHELL_FREE_NON_NULL ((*ConsoleInfo));\r
8be0ba36 73 *ConsoleInfo = NULL;\r
a405b86d 74 return (Status);\r
75 }\r
76\r
47d20b54
MK
77 Status = gBS->InstallProtocolInterface (&gImageHandle, &gEfiSimpleTextOutProtocolGuid, EFI_NATIVE_INTERFACE, (VOID *)&((*ConsoleInfo)->OurConOut));\r
78 if (EFI_ERROR (Status)) {\r
79 SHELL_FREE_NON_NULL ((*ConsoleInfo)->Buffer);\r
80 SHELL_FREE_NON_NULL ((*ConsoleInfo)->Attributes);\r
81 SHELL_FREE_NON_NULL ((*ConsoleInfo));\r
8be0ba36 82 *ConsoleInfo = NULL;\r
83 return (Status);\r
84 }\r
a405b86d 85\r
a405b86d 86 gST->ConsoleOutHandle = gImageHandle;\r
733f138d 87 gST->ConOut = &(*ConsoleInfo)->OurConOut;\r
a405b86d 88\r
8550b5f0
CS
89 //\r
90 // Update the CRC32 in the EFI System Table header\r
91 //\r
92 gST->Hdr.CRC32 = 0;\r
93 gBS->CalculateCrc32 (\r
47d20b54
MK
94 (UINT8 *)&gST->Hdr,\r
95 gST->Hdr.HeaderSize,\r
96 &gST->Hdr.CRC32\r
97 );\r
a405b86d 98 return (Status);\r
99}\r
100\r
101/**\r
102 Return the system to the state it was before InstallConsoleLogger\r
103 was installed.\r
104\r
733f138d 105 @param[in] ConsoleInfo The object from the install function.\r
a405b86d 106\r
107 @retval EFI_SUCCESS The operation was successful\r
108 @return other The operation failed. This was from UninstallProtocolInterface.\r
109**/\r
110EFI_STATUS\r
47d20b54
MK
111ConsoleLoggerUninstall (\r
112 IN CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo\r
a405b86d 113 )\r
114{\r
47d20b54
MK
115 ASSERT (ConsoleInfo != NULL);\r
116 ASSERT (ConsoleInfo->OldConOut != NULL);\r
a405b86d 117\r
118 if (ConsoleInfo->Buffer != NULL) {\r
47d20b54
MK
119 FreePool (ConsoleInfo->Buffer);\r
120 DEBUG_CODE (\r
121 ConsoleInfo->Buffer = NULL;\r
122 );\r
123 DEBUG_CODE (\r
124 ConsoleInfo->BufferSize = 0;\r
125 );\r
a405b86d 126 }\r
47d20b54 127\r
a405b86d 128 if (ConsoleInfo->Attributes != NULL) {\r
47d20b54
MK
129 FreePool (ConsoleInfo->Attributes);\r
130 DEBUG_CODE (\r
131 ConsoleInfo->Attributes = NULL;\r
132 );\r
133 DEBUG_CODE (\r
134 ConsoleInfo->AttribSize = 0;\r
135 );\r
a405b86d 136 }\r
137\r
138 gST->ConsoleOutHandle = ConsoleInfo->OldConHandle;\r
47d20b54 139 gST->ConOut = ConsoleInfo->OldConOut;\r
a405b86d 140\r
8550b5f0
CS
141 //\r
142 // Update the CRC32 in the EFI System Table header\r
143 //\r
144 gST->Hdr.CRC32 = 0;\r
145 gBS->CalculateCrc32 (\r
47d20b54
MK
146 (UINT8 *)&gST->Hdr,\r
147 gST->Hdr.HeaderSize,\r
148 &gST->Hdr.CRC32\r
149 );\r
8550b5f0 150\r
47d20b54 151 return (gBS->UninstallProtocolInterface (gImageHandle, &gEfiSimpleTextOutProtocolGuid, (VOID *)&ConsoleInfo->OurConOut));\r
a405b86d 152}\r
153\r
154/**\r
155 Displays previously logged output back to the screen.\r
156\r
157 This will scroll the screen forwards and backwards through the log of previous\r
158 output. If Rows is 0 then the size of 1/2 the screen will be scrolled. If Rows\r
159 is (UINTN)(-1) then the size of the screen will be scrolled.\r
160\r
161 @param[in] Forward If TRUE then the log will be displayed forwards (scroll to newer).\r
162 If FALSE then the log will be displayed backwards (scroll to older).\r
163 @param[in] Rows Determines how many rows the log should scroll.\r
164 @param[in] ConsoleInfo The pointer to the instance of the console logger information.\r
165**/\r
166EFI_STATUS\r
47d20b54
MK
167ConsoleLoggerDisplayHistory (\r
168 IN CONST BOOLEAN Forward,\r
169 IN CONST UINTN Rows,\r
170 IN CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo\r
a405b86d 171 )\r
172{\r
47d20b54 173 UINTN RowChange;\r
a405b86d 174\r
47d20b54 175 ASSERT (ConsoleInfo != NULL);\r
a405b86d 176\r
177 //\r
178 // Calculate the row number change\r
179 //\r
180 switch (Rows) {\r
47d20b54
MK
181 case ((UINTN)(-1)):\r
182 RowChange = ConsoleInfo->RowsPerScreen;\r
183 break;\r
184 case (0):\r
185 RowChange = ConsoleInfo->RowsPerScreen / 2;\r
186 break;\r
187 default:\r
188 RowChange = Rows;\r
189 break;\r
a405b86d 190 }\r
191\r
192 //\r
193 // Do the math for direction\r
194 //\r
195 if (Forward) {\r
196 if ((ConsoleInfo->OriginalStartRow - ConsoleInfo->CurrentStartRow) < RowChange) {\r
197 RowChange = ConsoleInfo->OriginalStartRow - ConsoleInfo->CurrentStartRow;\r
198 }\r
199 } else {\r
200 if (ConsoleInfo->CurrentStartRow < RowChange) {\r
201 RowChange = ConsoleInfo->CurrentStartRow;\r
202 }\r
203 }\r
204\r
205 //\r
206 // If we are already at one end or the other\r
207 //\r
208 if (RowChange == 0) {\r
209 return (EFI_SUCCESS);\r
210 }\r
211\r
212 //\r
213 // Clear the screen\r
214 //\r
47d20b54 215 ConsoleInfo->OldConOut->ClearScreen (ConsoleInfo->OldConOut);\r
a405b86d 216\r
217 //\r
218 // Set the new start row\r
219 //\r
220 if (Forward) {\r
221 ConsoleInfo->CurrentStartRow += RowChange;\r
222 } else {\r
223 ConsoleInfo->CurrentStartRow -= RowChange;\r
224 }\r
225\r
226 //\r
227 // Change the screen\r
228 //\r
47d20b54 229 return (UpdateDisplayFromHistory (ConsoleInfo));\r
a405b86d 230}\r
231\r
232/**\r
233 Function to return to normal output whent he scrolling is complete.\r
234 @param[in] ConsoleInfo The pointer to the instance of the console logger information.\r
235\r
236 @retval EFI_SUCCESS The operation was successful.\r
237 @return other The operation failed. See UpdateDisplayFromHistory.\r
238\r
239 @sa UpdateDisplayFromHistory\r
240**/\r
241EFI_STATUS\r
47d20b54
MK
242ConsoleLoggerStopHistory (\r
243 IN CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo\r
a405b86d 244 )\r
245{\r
47d20b54 246 ASSERT (ConsoleInfo != NULL);\r
a405b86d 247 if (ConsoleInfo->CurrentStartRow == ConsoleInfo->OriginalStartRow) {\r
248 return (EFI_SUCCESS);\r
249 }\r
8e4fd502
JC
250\r
251 //\r
252 // Clear the screen\r
253 //\r
47d20b54 254 ConsoleInfo->OldConOut->ClearScreen (ConsoleInfo->OldConOut);\r
8e4fd502 255\r
a405b86d 256 ConsoleInfo->CurrentStartRow = ConsoleInfo->OriginalStartRow;\r
47d20b54 257 return (UpdateDisplayFromHistory (ConsoleInfo));\r
a405b86d 258}\r
259\r
260/**\r
261 Updates the hidden ConOut to be displaying the correct stuff.\r
262 @param[in] ConsoleInfo The pointer to the instance of the console logger information.\r
263\r
264 @retval EFI_SUCCESS The operation was successful.\r
265 @return other The operation failed.\r
266**/\r
267EFI_STATUS\r
47d20b54
MK
268UpdateDisplayFromHistory (\r
269 IN CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo\r
a405b86d 270 )\r
271{\r
47d20b54
MK
272 EFI_STATUS Status;\r
273 EFI_STATUS RetVal;\r
274 CHAR16 *Screen;\r
275 INT32 *Attributes;\r
276 UINTN CurrentRow;\r
277 CHAR16 TempCharHolder;\r
278 UINTN Column;\r
279 INT32 CurrentAttrib;\r
280 UINTN CurrentColumn;\r
281 CHAR16 *StringSegment;\r
282 CHAR16 *StringSegmentEnd;\r
283 CHAR16 StringSegmentEndChar;\r
284 INT32 OrigAttribute;\r
285\r
286 ASSERT (ConsoleInfo != NULL);\r
a405b86d 287 TempCharHolder = CHAR_NULL;\r
47d20b54
MK
288 RetVal = EFI_SUCCESS;\r
289 OrigAttribute = ConsoleInfo->OldConOut->Mode->Attribute;\r
a405b86d 290\r
291 //\r
292 // Disable cursor visibility and move it to the top left corner\r
293 //\r
47d20b54
MK
294 ConsoleInfo->OldConOut->EnableCursor (ConsoleInfo->OldConOut, FALSE);\r
295 ConsoleInfo->OldConOut->SetCursorPosition (ConsoleInfo->OldConOut, 0, 0);\r
a405b86d 296\r
47d20b54 297 Screen = &ConsoleInfo->Buffer[(ConsoleInfo->ColsPerScreen + 2) * ConsoleInfo->CurrentStartRow];\r
a405b86d 298 Attributes = &ConsoleInfo->Attributes[ConsoleInfo->ColsPerScreen * ConsoleInfo->CurrentStartRow];\r
299 for ( CurrentRow = 0\r
47d20b54
MK
300 ; CurrentRow < ConsoleInfo->RowsPerScreen\r
301 ; CurrentRow++,\r
302 Screen += (ConsoleInfo->ColsPerScreen + 2),\r
303 Attributes += ConsoleInfo->ColsPerScreen\r
304 )\r
305 {\r
a405b86d 306 //\r
307 // dont use the last char - prevents screen scroll\r
308 //\r
47d20b54
MK
309 if (CurrentRow == (ConsoleInfo->RowsPerScreen-1)) {\r
310 TempCharHolder = Screen[ConsoleInfo->ColsPerScreen - 1];\r
a405b86d 311 Screen[ConsoleInfo->ColsPerScreen - 1] = CHAR_NULL;\r
312 }\r
313\r
314 for ( Column = 0\r
47d20b54
MK
315 ; Column < ConsoleInfo->ColsPerScreen\r
316 ; Column++\r
317 )\r
318 {\r
a405b86d 319 if (Screen[Column] != CHAR_NULL) {\r
320 CurrentAttrib = Attributes[Column];\r
321 CurrentColumn = Column;\r
322 StringSegment = &Screen[Column];\r
323\r
324 //\r
6a5033ca 325 // Find the first char with a different attribute and make that temporarily NULL\r
a405b86d 326 // so we can do fewer printout statements. (later) restore that one and we will\r
6a5033ca 327 // start at that column on the next loop.\r
a405b86d 328 //\r
329 StringSegmentEndChar = CHAR_NULL;\r
330 for ( StringSegmentEnd = StringSegment\r
47d20b54
MK
331 ; *StringSegmentEnd != CHAR_NULL\r
332 ; StringSegmentEnd++,\r
333 Column++\r
334 )\r
335 {\r
a405b86d 336 if (Attributes[Column] != CurrentAttrib) {\r
337 StringSegmentEndChar = *StringSegmentEnd;\r
338 *StringSegmentEnd = CHAR_NULL;\r
339 break;\r
340 }\r
341 } // StringSegmentEnd loop\r
342\r
343 //\r
344 // Now write out as much as had the same Attributes\r
345 //\r
346\r
47d20b54
MK
347 ConsoleInfo->OldConOut->SetAttribute (ConsoleInfo->OldConOut, CurrentAttrib);\r
348 ConsoleInfo->OldConOut->SetCursorPosition (ConsoleInfo->OldConOut, CurrentColumn, CurrentRow);\r
349 Status = ConsoleInfo->OldConOut->OutputString (ConsoleInfo->OldConOut, StringSegment);\r
a405b86d 350\r
47d20b54
MK
351 if (EFI_ERROR (Status)) {\r
352 ASSERT (FALSE);\r
a405b86d 353 RetVal = Status;\r
354 }\r
355\r
356 //\r
357 // If we found a change in attribute put the character back and decrement the column\r
358 // so when it increments it will point at that character and we will start printing\r
359 // a segment with that new attribute\r
360 //\r
361 if (StringSegmentEndChar != CHAR_NULL) {\r
47d20b54 362 *StringSegmentEnd = StringSegmentEndChar;\r
a405b86d 363 StringSegmentEndChar = CHAR_NULL;\r
364 Column--;\r
365 }\r
366 }\r
367 } // column for loop\r
368\r
369 //\r
370 // If we removed the last char and this was the last row put it back\r
371 //\r
372 if (TempCharHolder != CHAR_NULL) {\r
373 Screen[ConsoleInfo->ColsPerScreen - 1] = TempCharHolder;\r
47d20b54 374 TempCharHolder = CHAR_NULL;\r
a405b86d 375 }\r
376 } // row for loop\r
377\r
378 //\r
379 // If we are setting the screen back to original turn on the cursor and make it visible\r
380 // and set the attributes back to what they were\r
381 //\r
382 if (ConsoleInfo->CurrentStartRow == ConsoleInfo->OriginalStartRow) {\r
383 ConsoleInfo->OldConOut->SetAttribute (\r
47d20b54
MK
384 ConsoleInfo->OldConOut,\r
385 ConsoleInfo->HistoryMode.Attribute\r
386 );\r
a405b86d 387 ConsoleInfo->OldConOut->SetCursorPosition (\r
47d20b54
MK
388 ConsoleInfo->OldConOut,\r
389 ConsoleInfo->HistoryMode.CursorColumn,\r
390 ConsoleInfo->HistoryMode.CursorRow - ConsoleInfo->OriginalStartRow\r
391 );\r
a405b86d 392\r
393 Status = ConsoleInfo->OldConOut->EnableCursor (\r
47d20b54
MK
394 ConsoleInfo->OldConOut,\r
395 ConsoleInfo->HistoryMode.CursorVisible\r
396 );\r
a405b86d 397 if (EFI_ERROR (Status)) {\r
398 RetVal = Status;\r
399 }\r
ad7782a4 400 } else {\r
401 ConsoleInfo->OldConOut->SetAttribute (\r
47d20b54
MK
402 ConsoleInfo->OldConOut,\r
403 OrigAttribute\r
404 );\r
a405b86d 405 }\r
406\r
407 return (RetVal);\r
408}\r
409\r
410/**\r
6a5033ca 411 Reset the text output device hardware and optionally run diagnostics\r
a405b86d 412\r
413 @param This pointer to EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL\r
414 @param ExtendedVerification Indicates that a more extensive test may be performed\r
415\r
416 @retval EFI_SUCCESS The text output device was reset.\r
417 @retval EFI_DEVICE_ERROR The text output device is not functioning correctly and\r
418 could not be reset.\r
419**/\r
420EFI_STATUS\r
421EFIAPI\r
422ConsoleLoggerReset (\r
47d20b54
MK
423 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,\r
424 IN BOOLEAN ExtendedVerification\r
a405b86d 425 )\r
426{\r
47d20b54
MK
427 EFI_STATUS Status;\r
428 CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo;\r
429\r
430 ConsoleInfo = CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS (This);\r
a405b86d 431\r
432 //\r
433 // Forward the request to the original ConOut\r
434 //\r
435 Status = ConsoleInfo->OldConOut->Reset (ConsoleInfo->OldConOut, ExtendedVerification);\r
436\r
437 //\r
438 // Check that the buffers are still correct for logging\r
439 //\r
440 if (!EFI_ERROR (Status)) {\r
47d20b54 441 ConsoleLoggerResetBuffers (ConsoleInfo);\r
f5bc9da5 442 if (ExtendedVerification) {\r
c17c4a1f 443 ConsoleInfo->OriginalStartRow = 0;\r
47d20b54 444 ConsoleInfo->CurrentStartRow = 0;\r
c17c4a1f 445 }\r
a405b86d 446 }\r
447\r
448 return Status;\r
449}\r
450\r
451/**\r
452 Appends a string to the history buffer. If the buffer is full then the oldest\r
453 information in the buffer will be dropped. Information is added in a line by\r
454 line manner such that an empty line takes up just as much space as a full line.\r
455\r
456 @param[in] String String pointer to add.\r
457 @param[in] ConsoleInfo The pointer to the instance of the console logger information.\r
458**/\r
459EFI_STATUS\r
47d20b54
MK
460AppendStringToHistory (\r
461 IN CONST CHAR16 *String,\r
462 IN CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo\r
a405b86d 463 )\r
464{\r
465 CONST CHAR16 *Walker;\r
466 UINTN CopySize;\r
467 UINTN PrintIndex;\r
468 UINTN Index;\r
469\r
47d20b54 470 ASSERT (ConsoleInfo != NULL);\r
a405b86d 471\r
472 for ( Walker = String\r
47d20b54
MK
473 ; Walker != NULL && *Walker != CHAR_NULL\r
474 ; Walker++\r
475 )\r
476 {\r
a405b86d 477 switch (*Walker) {\r
47d20b54
MK
478 case (CHAR_BACKSPACE):\r
479 if (ConsoleInfo->HistoryMode.CursorColumn > 0) {\r
480 ConsoleInfo->HistoryMode.CursorColumn--;\r
a405b86d 481 }\r
482\r
47d20b54
MK
483 break;\r
484 case (CHAR_LINEFEED):\r
485 if (ConsoleInfo->HistoryMode.CursorRow >= (INT32)((ConsoleInfo->RowsPerScreen * ConsoleInfo->ScreenCount)-1)) {\r
486 //\r
487 // Should never be bigger\r
488 //\r
489 ASSERT (ConsoleInfo->HistoryMode.CursorRow == (INT32)((ConsoleInfo->RowsPerScreen * ConsoleInfo->ScreenCount)-1));\r
490\r
491 //\r
492 // scroll history attributes 'up' 1 row and set the last row to default attribute\r
493 //\r
494 CopySize = ConsoleInfo->ColsPerScreen\r
495 * ((ConsoleInfo->RowsPerScreen * ConsoleInfo->ScreenCount) - 1)\r
496 * sizeof (ConsoleInfo->Attributes[0]);\r
497 ASSERT (CopySize < ConsoleInfo->AttribSize);\r
498 CopyMem (\r
499 ConsoleInfo->Attributes,\r
500 ConsoleInfo->Attributes + ConsoleInfo->ColsPerScreen,\r
501 CopySize\r
502 );\r
503\r
504 for ( Index = 0\r
505 ; Index < ConsoleInfo->ColsPerScreen\r
506 ; Index++\r
507 )\r
508 {\r
509 *(ConsoleInfo->Attributes + (CopySize/sizeof (ConsoleInfo->Attributes[0])) + Index) = ConsoleInfo->HistoryMode.Attribute;\r
510 }\r
a405b86d 511\r
47d20b54
MK
512 //\r
513 // scroll history buffer 'up' 1 row and set the last row to spaces (L' ')\r
514 //\r
515 CopySize = (ConsoleInfo->ColsPerScreen + 2)\r
516 * ((ConsoleInfo->RowsPerScreen * ConsoleInfo->ScreenCount) - 1)\r
517 * sizeof (ConsoleInfo->Buffer[0]);\r
518 ASSERT (CopySize < ConsoleInfo->BufferSize);\r
519 CopyMem (\r
520 ConsoleInfo->Buffer,\r
521 ConsoleInfo->Buffer + (ConsoleInfo->ColsPerScreen + 2),\r
522 CopySize\r
523 );\r
524\r
525 //\r
526 // Set that last row of chars to spaces\r
527 //\r
528 SetMem16 (((UINT8 *)ConsoleInfo->Buffer)+CopySize, ConsoleInfo->ColsPerScreen*sizeof (CHAR16), L' ');\r
529 } else {\r
530 //\r
531 // we are not on the last row\r
532 //\r
533\r
534 //\r
535 // We should not be scrolling history\r
536 //\r
537 ASSERT (ConsoleInfo->OriginalStartRow == ConsoleInfo->CurrentStartRow);\r
538 //\r
539 // are we at the end of a row?\r
540 //\r
541 if (ConsoleInfo->HistoryMode.CursorRow == (INT32)(ConsoleInfo->OriginalStartRow + ConsoleInfo->RowsPerScreen - 1)) {\r
542 ConsoleInfo->OriginalStartRow++;\r
543 ConsoleInfo->CurrentStartRow++;\r
544 }\r
545\r
546 ConsoleInfo->HistoryMode.CursorRow++;\r
547 }\r
a405b86d 548\r
47d20b54
MK
549 break;\r
550 case (CHAR_CARRIAGE_RETURN):\r
a405b86d 551 //\r
47d20b54 552 // Move the cursor to the beginning of the current row.\r
a405b86d 553 //\r
47d20b54
MK
554 ConsoleInfo->HistoryMode.CursorColumn = 0;\r
555 break;\r
556 default:\r
a405b86d 557 //\r
47d20b54 558 // Acrtually print characters into the history buffer\r
a405b86d 559 //\r
a405b86d 560\r
47d20b54
MK
561 PrintIndex = ConsoleInfo->HistoryMode.CursorRow * ConsoleInfo->ColsPerScreen + ConsoleInfo->HistoryMode.CursorColumn;\r
562\r
563 for ( // no initializer needed\r
564 ; ConsoleInfo->HistoryMode.CursorColumn < (INT32)ConsoleInfo->ColsPerScreen\r
565 ; ConsoleInfo->HistoryMode.CursorColumn++,\r
566 PrintIndex++,\r
567 Walker++\r
568 )\r
569 {\r
570 if ( (*Walker == CHAR_NULL)\r
571 || (*Walker == CHAR_BACKSPACE)\r
572 || (*Walker == CHAR_LINEFEED)\r
573 || (*Walker == CHAR_CARRIAGE_RETURN)\r
574 )\r
575 {\r
a405b86d 576 Walker--;\r
577 break;\r
47d20b54 578 }\r
a405b86d 579\r
47d20b54
MK
580 //\r
581 // The buffer is 2*CursorRow more since it has that many \r\n characters at the end of each row.\r
582 //\r
a405b86d 583\r
47d20b54
MK
584 ASSERT (PrintIndex + ConsoleInfo->HistoryMode.CursorRow < ConsoleInfo->BufferSize);\r
585 ConsoleInfo->Buffer[PrintIndex + (2*ConsoleInfo->HistoryMode.CursorRow)] = *Walker;\r
586 ASSERT (PrintIndex < ConsoleInfo->AttribSize);\r
587 ConsoleInfo->Attributes[PrintIndex] = ConsoleInfo->HistoryMode.Attribute;\r
588 } // for loop\r
a405b86d 589\r
47d20b54
MK
590 //\r
591 // Add the carriage return and line feed at the end of the lines\r
592 //\r
593 if (ConsoleInfo->HistoryMode.CursorColumn >= (INT32)ConsoleInfo->ColsPerScreen) {\r
594 AppendStringToHistory (L"\r\n", ConsoleInfo);\r
595 Walker--;\r
596 }\r
597\r
598 break;\r
a405b86d 599 } // switch for character\r
600 } // for loop\r
601\r
602 return (EFI_SUCCESS);\r
603}\r
604\r
605/**\r
606 Worker function to handle printing the output to the screen\r
607 and the history buffer\r
608\r
609 @param[in] String The string to output\r
610 @param[in] ConsoleInfo The pointer to the instance of the console logger information.\r
611\r
612 @retval EFI_SUCCESS The string was printed\r
613 @retval EFI_DEVICE_ERROR The device reported an error while attempting to output\r
614 the text.\r
615 @retval EFI_UNSUPPORTED The output device's mode is not currently in a\r
616 defined text mode.\r
617 @retval EFI_WARN_UNKNOWN_GLYPH This warning code indicates that some of the\r
618 characters in the Unicode string could not be\r
619 rendered and were skipped.\r
620**/\r
621EFI_STATUS\r
47d20b54
MK
622ConsoleLoggerOutputStringSplit (\r
623 IN CONST CHAR16 *String,\r
624 IN CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo\r
a405b86d 625 )\r
626{\r
47d20b54 627 EFI_STATUS Status;\r
a405b86d 628\r
629 //\r
630 // Forward the request to the original ConOut\r
631 //\r
47d20b54 632 Status = ConsoleInfo->OldConOut->OutputString (ConsoleInfo->OldConOut, (CHAR16 *)String);\r
a405b86d 633\r
47d20b54 634 if (EFI_ERROR (Status)) {\r
a405b86d 635 return (Status);\r
636 }\r
637\r
47d20b54 638 return (AppendStringToHistory (String, ConsoleInfo));\r
a405b86d 639}\r
640\r
641/**\r
642 Function to handle page break mode.\r
643\r
644 This function will prompt for continue or break.\r
645\r
646 @retval EFI_SUCCESS Continue was choosen\r
647 @return other Break was choosen\r
648**/\r
649EFI_STATUS\r
47d20b54 650ConsoleLoggerDoPageBreak (\r
a405b86d 651 VOID\r
652 )\r
653{\r
47d20b54
MK
654 SHELL_PROMPT_RESPONSE *Resp;\r
655 EFI_STATUS Status;\r
a405b86d 656\r
657 Resp = NULL;\r
47d20b54 658 ASSERT (ShellInfoObject.PageBreakEnabled);\r
a405b86d 659 ShellInfoObject.PageBreakEnabled = FALSE;\r
47d20b54 660 Status = ShellPromptForResponseHii (ShellPromptResponseTypeQuitContinue, STRING_TOKEN (STR_SHELL_QUIT_CONT), ShellInfoObject.HiiHandle, (VOID **)&Resp);\r
a405b86d 661 ShellInfoObject.PageBreakEnabled = TRUE;\r
47d20b54 662 ASSERT (Resp != NULL);\r
a405b86d 663 if (Resp == NULL) {\r
664 return (EFI_NOT_FOUND);\r
665 }\r
47d20b54
MK
666\r
667 if (EFI_ERROR (Status)) {\r
a405b86d 668 if (Resp != NULL) {\r
47d20b54 669 FreePool (Resp);\r
a405b86d 670 }\r
47d20b54 671\r
a405b86d 672 return (Status);\r
673 }\r
47d20b54 674\r
a405b86d 675 if (*Resp == ShellPromptResponseContinue) {\r
47d20b54
MK
676 FreePool (Resp);\r
677 ShellInfoObject.ConsoleInfo->RowCounter = 0;\r
678 // ShellInfoObject.ConsoleInfo->OurConOut.Mode->CursorRow = 0;\r
679 // ShellInfoObject.ConsoleInfo->OurConOut.Mode->CursorColumn = 0;\r
733f138d 680\r
a405b86d 681 return (EFI_SUCCESS);\r
682 } else if (*Resp == ShellPromptResponseQuit) {\r
47d20b54 683 FreePool (Resp);\r
a405b86d 684 ShellInfoObject.ConsoleInfo->Enabled = FALSE;\r
85a3fa3a
CP
685 //\r
686 // When user wants to quit, the shell should stop running the command.\r
687 //\r
688 gBS->SignalEvent (ShellInfoObject.NewEfiShellProtocol->ExecutionBreak);\r
a405b86d 689 return (EFI_DEVICE_ERROR);\r
690 } else {\r
47d20b54 691 ASSERT (FALSE);\r
a405b86d 692 }\r
47d20b54 693\r
a405b86d 694 return (EFI_SUCCESS);\r
695}\r
47d20b54 696\r
a405b86d 697/**\r
698 Worker function to handle printing the output with page breaks.\r
699\r
700 @param[in] String The string to output\r
701 @param[in] ConsoleInfo The pointer to the instance of the console logger information.\r
702\r
703 @retval EFI_SUCCESS The string was printed\r
704 @retval EFI_DEVICE_ERROR The device reported an error while attempting to output\r
705 the text.\r
706 @retval EFI_UNSUPPORTED The output device's mode is not currently in a\r
707 defined text mode.\r
708 @retval EFI_WARN_UNKNOWN_GLYPH This warning code indicates that some of the\r
709 characters in the Unicode string could not be\r
710 rendered and were skipped.\r
711**/\r
712EFI_STATUS\r
47d20b54
MK
713ConsoleLoggerPrintWithPageBreak (\r
714 IN CONST CHAR16 *String,\r
715 IN CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo\r
a405b86d 716 )\r
717{\r
718 CONST CHAR16 *Walker;\r
719 CONST CHAR16 *LineStart;\r
733f138d 720 CHAR16 *StringCopy;\r
a405b86d 721 CHAR16 TempChar;\r
722\r
733f138d 723 StringCopy = NULL;\r
47d20b54 724 StringCopy = StrnCatGrow (&StringCopy, NULL, String, 0);\r
733f138d 725 if (StringCopy == NULL) {\r
726 return (EFI_OUT_OF_RESOURCES);\r
727 }\r
728\r
47d20b54
MK
729 for ( Walker = StringCopy,\r
730 LineStart = StringCopy\r
731 ; Walker != NULL && *Walker != CHAR_NULL\r
732 ; Walker++\r
733 )\r
734 {\r
a405b86d 735 switch (*Walker) {\r
47d20b54
MK
736 case (CHAR_BACKSPACE):\r
737 if (ConsoleInfo->OurConOut.Mode->CursorColumn > 0) {\r
738 ConsoleInfo->OurConOut.Mode->CursorColumn--;\r
739 }\r
a405b86d 740\r
47d20b54
MK
741 break;\r
742 case (CHAR_LINEFEED):\r
a405b86d 743 //\r
744 // add a temp NULL terminator\r
745 //\r
47d20b54
MK
746 TempChar = *(Walker + 1);\r
747 *((CHAR16 *)(Walker+1)) = CHAR_NULL;\r
a405b86d 748\r
749 //\r
750 // output the string\r
751 //\r
752 ConsoleLoggerOutputStringSplit (LineStart, ConsoleInfo);\r
753\r
754 //\r
6a5033ca 755 // restore the temp NULL terminator to its original character\r
a405b86d 756 //\r
47d20b54 757 *((CHAR16 *)(Walker+1)) = TempChar;\r
a405b86d 758\r
759 //\r
760 // Update LineStart Variable\r
761 //\r
a49f6a2f 762 LineStart = Walker + 1;\r
a405b86d 763\r
764 //\r
47d20b54 765 // increment row count\r
a405b86d 766 //\r
767 ShellInfoObject.ConsoleInfo->RowCounter++;\r
768 ConsoleInfo->OurConOut.Mode->CursorRow++;\r
47d20b54
MK
769\r
770 break;\r
771 case (CHAR_CARRIAGE_RETURN):\r
772 //\r
773 // Move the cursor to the beginning of the current row.\r
774 //\r
a405b86d 775 ConsoleInfo->OurConOut.Mode->CursorColumn = 0;\r
47d20b54
MK
776 break;\r
777 default:\r
778 //\r
779 // increment column count\r
780 //\r
781 ConsoleInfo->OurConOut.Mode->CursorColumn++;\r
782 //\r
783 // check if that is the last column\r
784 //\r
785 if ((INTN)ConsoleInfo->ColsPerScreen == ConsoleInfo->OurConOut.Mode->CursorColumn + 1) {\r
786 //\r
787 // output a line similar to the linefeed character.\r
788 //\r
789\r
790 //\r
791 // add a temp NULL terminator\r
792 //\r
793 TempChar = *(Walker + 1);\r
794 *((CHAR16 *)(Walker+1)) = CHAR_NULL;\r
795\r
796 //\r
797 // output the string\r
798 //\r
799 ConsoleLoggerOutputStringSplit (LineStart, ConsoleInfo);\r
800\r
801 //\r
802 // restore the temp NULL terminator to its original character\r
803 //\r
804 *((CHAR16 *)(Walker+1)) = TempChar;\r
805\r
806 //\r
807 // Update LineStart Variable\r
808 //\r
809 LineStart = Walker + 1;\r
810\r
811 //\r
812 // increment row count and zero the column\r
813 //\r
814 ShellInfoObject.ConsoleInfo->RowCounter++;\r
815 ConsoleInfo->OurConOut.Mode->CursorRow++;\r
816 ConsoleInfo->OurConOut.Mode->CursorColumn = 0;\r
817 } // last column on line\r
818\r
819 break;\r
a405b86d 820 } // switch for character\r
821\r
822 //\r
823 // check if that was the last printable row. If yes handle PageBreak mode\r
824 //\r
825 if ((ConsoleInfo->RowsPerScreen) -1 == ShellInfoObject.ConsoleInfo->RowCounter) {\r
47d20b54 826 if (EFI_ERROR (ConsoleLoggerDoPageBreak ())) {\r
a405b86d 827 //\r
828 // We got an error which means 'break' and halt the printing\r
829 //\r
47d20b54 830 SHELL_FREE_NON_NULL (StringCopy);\r
a405b86d 831 return (EFI_DEVICE_ERROR);\r
832 }\r
833 }\r
834 } // for loop\r
835\r
47d20b54 836 if ((LineStart != NULL) && (*LineStart != CHAR_NULL)) {\r
a405b86d 837 ConsoleLoggerOutputStringSplit (LineStart, ConsoleInfo);\r
838 }\r
839\r
47d20b54 840 SHELL_FREE_NON_NULL (StringCopy);\r
a405b86d 841 return (EFI_SUCCESS);\r
842}\r
843\r
844/**\r
845 Write a Unicode string to the output device.\r
846\r
847 @param[in] This Protocol instance pointer.\r
848 @param[in] WString The NULL-terminated Unicode string to be displayed on the output\r
849 device(s). All output devices must also support the Unicode\r
850 drawing defined in this file.\r
851 @retval EFI_SUCCESS The string was output to the device.\r
852 @retval EFI_DEVICE_ERROR The device reported an error while attempting to output\r
853 the text.\r
854 @retval EFI_UNSUPPORTED The output device's mode is not currently in a\r
855 defined text mode.\r
856 @retval EFI_WARN_UNKNOWN_GLYPH This warning code indicates that some of the\r
857 characters in the Unicode string could not be\r
858 rendered and were skipped.\r
859**/\r
860EFI_STATUS\r
861EFIAPI\r
862ConsoleLoggerOutputString (\r
47d20b54
MK
863 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,\r
864 IN CHAR16 *WString\r
a405b86d 865 )\r
866{\r
47d20b54
MK
867 EFI_STATUS Status;\r
868 EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *TxtInEx;\r
869 EFI_KEY_DATA KeyData;\r
870 UINTN EventIndex;\r
871 CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo;\r
31c2a2c7 872\r
47d20b54 873 ConsoleInfo = CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS (This);\r
733f138d 874 if (ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoConsoleOut) {\r
875 return (EFI_UNSUPPORTED);\r
876 }\r
31c2a2c7 877\r
47d20b54
MK
878 ASSERT (ShellInfoObject.ConsoleInfo == ConsoleInfo);\r
879\r
880 Status = gBS->HandleProtocol (gST->ConsoleInHandle, &gEfiSimpleTextInputExProtocolGuid, (VOID **)&TxtInEx);\r
31c2a2c7
RN
881 if (!EFI_ERROR (Status)) {\r
882 while (ShellInfoObject.HaltOutput) {\r
31c2a2c7
RN
883 ShellInfoObject.HaltOutput = FALSE;\r
884 //\r
885 // just get some key\r
886 //\r
887 Status = gBS->WaitForEvent (1, &TxtInEx->WaitForKeyEx, &EventIndex);\r
888 ASSERT_EFI_ERROR (Status);\r
889 Status = TxtInEx->ReadKeyStrokeEx (TxtInEx, &KeyData);\r
47d20b54 890 if (EFI_ERROR (Status)) {\r
8e4a89a3
JC
891 break;\r
892 }\r
31c2a2c7
RN
893\r
894 if ((KeyData.Key.UnicodeChar == L's') && (KeyData.Key.ScanCode == SCAN_NULL) &&\r
895 ((KeyData.KeyState.KeyShiftState == (EFI_SHIFT_STATE_VALID | EFI_LEFT_CONTROL_PRESSED)) ||\r
896 (KeyData.KeyState.KeyShiftState == (EFI_SHIFT_STATE_VALID | EFI_RIGHT_CONTROL_PRESSED))\r
897 )\r
47d20b54
MK
898 )\r
899 {\r
31c2a2c7
RN
900 ShellInfoObject.HaltOutput = TRUE;\r
901 }\r
902 }\r
a49f6a2f 903 }\r
31c2a2c7 904\r
a405b86d 905 if (!ShellInfoObject.ConsoleInfo->Enabled) {\r
906 return (EFI_DEVICE_ERROR);\r
907 } else if (ShellInfoObject.PageBreakEnabled) {\r
47d20b54 908 return (ConsoleLoggerPrintWithPageBreak (WString, ConsoleInfo));\r
a405b86d 909 } else {\r
47d20b54 910 return (ConsoleLoggerOutputStringSplit (WString, ConsoleInfo));\r
a405b86d 911 }\r
912}\r
913\r
914/**\r
915 Verifies that all characters in a Unicode string can be output to the\r
916 target device.\r
917\r
918 @param[in] This Protocol instance pointer.\r
919 @param[in] WString The NULL-terminated Unicode string to be examined for the output\r
920 device(s).\r
921\r
922 @retval EFI_SUCCESS The device(s) are capable of rendering the output string.\r
923 @retval EFI_UNSUPPORTED Some of the characters in the Unicode string cannot be\r
924 rendered by one or more of the output devices mapped\r
925 by the EFI handle.\r
926\r
927**/\r
928EFI_STATUS\r
929EFIAPI\r
930ConsoleLoggerTestString (\r
931 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,\r
47d20b54 932 IN CHAR16 *WString\r
a405b86d 933 )\r
934{\r
47d20b54
MK
935 CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo;\r
936\r
937 ConsoleInfo = CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS (This);\r
a405b86d 938 //\r
939 // Forward the request to the original ConOut\r
940 //\r
941 return (ConsoleInfo->OldConOut->TestString (ConsoleInfo->OldConOut, WString));\r
942}\r
943\r
944/**\r
945 Returns information for an available text mode that the output device(s)\r
946 supports.\r
947\r
948 @param[in] This Protocol instance pointer.\r
949 @param[in] ModeNumber The mode number to return information on.\r
950 @param[out] Columns Upon return, the number of columns in the selected geometry\r
951 @param[out] Rows Upon return, the number of rows in the selected geometry\r
952\r
953 @retval EFI_SUCCESS The requested mode information was returned.\r
954 @retval EFI_DEVICE_ERROR The device had an error and could not\r
955 complete the request.\r
956 @retval EFI_UNSUPPORTED The mode number was not valid.\r
957**/\r
958EFI_STATUS\r
959EFIAPI\r
960ConsoleLoggerQueryMode (\r
961 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,\r
47d20b54
MK
962 IN UINTN ModeNumber,\r
963 OUT UINTN *Columns,\r
964 OUT UINTN *Rows\r
a405b86d 965 )\r
966{\r
47d20b54
MK
967 CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo;\r
968\r
969 ConsoleInfo = CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS (This);\r
a405b86d 970 //\r
971 // Forward the request to the original ConOut\r
972 //\r
973 return (ConsoleInfo->OldConOut->QueryMode (\r
47d20b54
MK
974 ConsoleInfo->OldConOut,\r
975 ModeNumber,\r
976 Columns,\r
977 Rows\r
978 ));\r
a405b86d 979}\r
980\r
981/**\r
982 Sets the output device(s) to a specified mode.\r
983\r
984 @param[in] This Protocol instance pointer.\r
985 @param[in] ModeNumber The mode number to set.\r
986\r
987\r
988 @retval EFI_SUCCESS The requested text mode was set.\r
989 @retval EFI_DEVICE_ERROR The device had an error and\r
990 could not complete the request.\r
991 @retval EFI_UNSUPPORTED The mode number was not valid.\r
992**/\r
993EFI_STATUS\r
994EFIAPI\r
995ConsoleLoggerSetMode (\r
47d20b54
MK
996 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,\r
997 IN UINTN ModeNumber\r
a405b86d 998 )\r
999{\r
47d20b54 1000 EFI_STATUS Status;\r
a405b86d 1001\r
47d20b54
MK
1002 CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo;\r
1003\r
1004 ConsoleInfo = CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS (This);\r
a405b86d 1005\r
1006 //\r
1007 // Forward the request to the original ConOut\r
1008 //\r
1009 Status = ConsoleInfo->OldConOut->SetMode (ConsoleInfo->OldConOut, ModeNumber);\r
1010\r
1011 //\r
1012 // Check that the buffers are still correct for logging\r
1013 //\r
1014 if (!EFI_ERROR (Status)) {\r
c17c4a1f 1015 ConsoleInfo->OurConOut.Mode = ConsoleInfo->OldConOut->Mode;\r
47d20b54 1016 ConsoleLoggerResetBuffers (ConsoleInfo);\r
c17c4a1f 1017 ConsoleInfo->OriginalStartRow = 0;\r
47d20b54 1018 ConsoleInfo->CurrentStartRow = 0;\r
c17c4a1f 1019 ConsoleInfo->OurConOut.ClearScreen (&ConsoleInfo->OurConOut);\r
a405b86d 1020 }\r
ba0014b9 1021\r
a405b86d 1022 return Status;\r
1023}\r
1024\r
1025/**\r
1026 Sets the background and foreground colors for the OutputString () and\r
1027 ClearScreen () functions.\r
1028\r
1029 @param[in] This Protocol instance pointer.\r
1030 @param[in] Attribute The attribute to set. Bits 0..3 are the foreground color, and\r
1031 bits 4..6 are the background color. All other bits are undefined\r
1032 and must be zero. The valid Attributes are defined in this file.\r
1033\r
1034 @retval EFI_SUCCESS The attribute was set.\r
1035 @retval EFI_DEVICE_ERROR The device had an error and\r
1036 could not complete the request.\r
1037 @retval EFI_UNSUPPORTED The attribute requested is not defined.\r
1038\r
1039**/\r
1040EFI_STATUS\r
1041EFIAPI\r
1042ConsoleLoggerSetAttribute (\r
47d20b54
MK
1043 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,\r
1044 IN UINTN Attribute\r
a405b86d 1045 )\r
1046{\r
47d20b54 1047 EFI_STATUS Status;\r
a405b86d 1048\r
47d20b54
MK
1049 CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo;\r
1050\r
1051 ConsoleInfo = CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS (This);\r
a405b86d 1052\r
1053 //\r
1054 // Forward the request to the original ConOut\r
1055 //\r
1056 Status = ConsoleInfo->OldConOut->SetAttribute (ConsoleInfo->OldConOut, Attribute);\r
1057\r
1058 //\r
1059 // Record console output history\r
1060 //\r
1061 if (!EFI_ERROR (Status)) {\r
47d20b54 1062 ConsoleInfo->HistoryMode.Attribute = (INT32)Attribute;\r
a405b86d 1063 }\r
1064\r
1065 return Status;\r
1066}\r
1067\r
1068/**\r
1069 Clears the output device(s) display to the currently selected background\r
1070 color.\r
1071\r
1072 @param[in] This Protocol instance pointer.\r
1073\r
1074 @retval EFI_SUCCESS The operation completed successfully.\r
1075 @retval EFI_DEVICE_ERROR The device had an error and\r
1076 could not complete the request.\r
1077 @retval EFI_UNSUPPORTED The output device is not in a valid text mode.\r
1078**/\r
1079EFI_STATUS\r
1080EFIAPI\r
1081ConsoleLoggerClearScreen (\r
1082 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This\r
1083 )\r
1084{\r
47d20b54
MK
1085 EFI_STATUS Status;\r
1086 CHAR16 *Screen;\r
1087 INT32 *Attributes;\r
1088 UINTN Row;\r
1089 UINTN Column;\r
1090 CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo;\r
a405b86d 1091\r
733f138d 1092 if (ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoConsoleOut) {\r
1093 return (EFI_UNSUPPORTED);\r
1094 }\r
a405b86d 1095\r
47d20b54 1096 ConsoleInfo = CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS (This);\r
a405b86d 1097\r
1098 //\r
1099 // Forward the request to the original ConOut\r
1100 //\r
1101 Status = ConsoleInfo->OldConOut->ClearScreen (ConsoleInfo->OldConOut);\r
1102\r
1103 //\r
1104 // Record console output history\r
1105 //\r
1106 if (!EFI_ERROR (Status)) {\r
47d20b54 1107 Screen = &ConsoleInfo->Buffer[(ConsoleInfo->ColsPerScreen + 2) * ConsoleInfo->CurrentStartRow];\r
a405b86d 1108 Attributes = &ConsoleInfo->Attributes[ConsoleInfo->ColsPerScreen * ConsoleInfo->CurrentStartRow];\r
1109 for ( Row = ConsoleInfo->OriginalStartRow\r
47d20b54
MK
1110 ; Row < (ConsoleInfo->RowsPerScreen * ConsoleInfo->ScreenCount)\r
1111 ; Row++\r
1112 )\r
1113 {\r
a405b86d 1114 for ( Column = 0\r
47d20b54
MK
1115 ; Column < ConsoleInfo->ColsPerScreen\r
1116 ; Column++,\r
1117 Screen++,\r
1118 Attributes++\r
1119 )\r
1120 {\r
1121 *Screen = L' ';\r
a405b86d 1122 *Attributes = ConsoleInfo->OldConOut->Mode->Attribute;\r
1123 }\r
47d20b54 1124\r
a405b86d 1125 //\r
1126 // Skip the NULL on each column end in text buffer only\r
1127 //\r
1df5c64c 1128 Screen += 2;\r
a405b86d 1129 }\r
47d20b54 1130\r
a405b86d 1131 ConsoleInfo->HistoryMode.CursorColumn = 0;\r
1132 ConsoleInfo->HistoryMode.CursorRow = 0;\r
1133 }\r
1134\r
1135 return Status;\r
1136}\r
1137\r
1138/**\r
1139 Sets the current coordinates of the cursor position\r
1140\r
1141 @param[in] This Protocol instance pointer.\r
1142 @param[in] Column Column to put the cursor in. Must be between zero and Column returned from QueryMode\r
1143 @param[in] Row Row to put the cursor in. Must be between zero and Row returned from QueryMode\r
1144\r
1145 @retval EFI_SUCCESS The operation completed successfully.\r
1146 @retval EFI_DEVICE_ERROR The device had an error and\r
1147 could not complete the request.\r
1148 @retval EFI_UNSUPPORTED The output device is not in a valid text mode, or the\r
1149 cursor position is invalid for the current mode.\r
1150**/\r
1151EFI_STATUS\r
1152EFIAPI\r
1153ConsoleLoggerSetCursorPosition (\r
1154 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,\r
47d20b54
MK
1155 IN UINTN Column,\r
1156 IN UINTN Row\r
a405b86d 1157 )\r
1158{\r
47d20b54
MK
1159 EFI_STATUS Status;\r
1160 CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo;\r
733f138d 1161\r
1162 if (ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoConsoleOut) {\r
1163 return (EFI_UNSUPPORTED);\r
1164 }\r
1165\r
47d20b54 1166 ConsoleInfo = CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS (This);\r
a405b86d 1167 //\r
1168 // Forward the request to the original ConOut\r
1169 //\r
1170 Status = ConsoleInfo->OldConOut->SetCursorPosition (\r
47d20b54
MK
1171 ConsoleInfo->OldConOut,\r
1172 Column,\r
1173 Row\r
1174 );\r
a405b86d 1175\r
1176 //\r
1177 // Record console output history\r
1178 //\r
1179 if (!EFI_ERROR (Status)) {\r
1180 ConsoleInfo->HistoryMode.CursorColumn = (INT32)Column;\r
1181 ConsoleInfo->HistoryMode.CursorRow = (INT32)(ConsoleInfo->OriginalStartRow + Row);\r
1182 }\r
1183\r
1184 return Status;\r
1185}\r
1186\r
1187/**\r
1188 Makes the cursor visible or invisible\r
1189\r
1190 @param[in] This Protocol instance pointer.\r
1191 @param[in] Visible If TRUE, the cursor is set to be visible. If FALSE, the cursor is\r
1192 set to be invisible.\r
1193\r
1194 @retval EFI_SUCCESS The operation completed successfully.\r
1195 @retval EFI_DEVICE_ERROR The device had an error and could not complete the\r
1196 request, or the device does not support changing\r
1197 the cursor mode.\r
1198 @retval EFI_UNSUPPORTED The output device is not in a valid text mode.\r
1199**/\r
1200EFI_STATUS\r
1201EFIAPI\r
1202ConsoleLoggerEnableCursor (\r
1203 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,\r
47d20b54 1204 IN BOOLEAN Visible\r
a405b86d 1205 )\r
1206{\r
47d20b54 1207 EFI_STATUS Status;\r
a405b86d 1208\r
47d20b54
MK
1209 CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo;\r
1210\r
1211 ConsoleInfo = CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS (This);\r
a405b86d 1212 //\r
1213 // Forward the request to the original ConOut\r
1214 //\r
1215 Status = ConsoleInfo->OldConOut->EnableCursor (ConsoleInfo->OldConOut, Visible);\r
1216\r
1217 //\r
1218 // Record console output history\r
1219 //\r
1220 if (!EFI_ERROR (Status)) {\r
1221 ConsoleInfo->HistoryMode.CursorVisible = Visible;\r
1222 }\r
1223\r
1224 return Status;\r
1225}\r
1226\r
1227/**\r
1228 Function to update and verify that the current buffers are correct.\r
1229\r
1230 @param[in] ConsoleInfo The pointer to the instance of the console logger information.\r
1231\r
6a5033ca 1232 This will be used when a mode has changed or a reset occurred to verify all\r
a405b86d 1233 history buffers.\r
1234**/\r
1235EFI_STATUS\r
47d20b54
MK
1236ConsoleLoggerResetBuffers (\r
1237 IN CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo\r
a405b86d 1238 )\r
1239{\r
47d20b54 1240 EFI_STATUS Status;\r
a405b86d 1241\r
1242 if (ConsoleInfo->Buffer != NULL) {\r
47d20b54 1243 FreePool (ConsoleInfo->Buffer);\r
a405b86d 1244 ConsoleInfo->Buffer = NULL;\r
1245 ConsoleInfo->BufferSize = 0;\r
1246 }\r
47d20b54 1247\r
a405b86d 1248 if (ConsoleInfo->Attributes != NULL) {\r
47d20b54 1249 FreePool (ConsoleInfo->Attributes);\r
a405b86d 1250 ConsoleInfo->Attributes = NULL;\r
1251 ConsoleInfo->AttribSize = 0;\r
1252 }\r
1253\r
1254 Status = gST->ConOut->QueryMode (gST->ConOut, gST->ConOut->Mode->Mode, &ConsoleInfo->ColsPerScreen, &ConsoleInfo->RowsPerScreen);\r
47d20b54 1255 if (EFI_ERROR (Status)) {\r
a405b86d 1256 return (Status);\r
1257 }\r
1258\r
47d20b54
MK
1259 ConsoleInfo->BufferSize = (ConsoleInfo->ColsPerScreen + 2) * ConsoleInfo->RowsPerScreen * ConsoleInfo->ScreenCount * sizeof (ConsoleInfo->Buffer[0]);\r
1260 ConsoleInfo->AttribSize = ConsoleInfo->ColsPerScreen * ConsoleInfo->RowsPerScreen * ConsoleInfo->ScreenCount * sizeof (ConsoleInfo->Attributes[0]);\r
a405b86d 1261\r
47d20b54 1262 ConsoleInfo->Buffer = (CHAR16 *)AllocateZeroPool (ConsoleInfo->BufferSize);\r
a405b86d 1263\r
1264 if (ConsoleInfo->Buffer == NULL) {\r
1265 return (EFI_OUT_OF_RESOURCES);\r
1266 }\r
1267\r
47d20b54 1268 ConsoleInfo->Attributes = (INT32 *)AllocateZeroPool (ConsoleInfo->AttribSize);\r
a405b86d 1269 if (ConsoleInfo->Attributes == NULL) {\r
47d20b54
MK
1270 FreePool (ConsoleInfo->Buffer);\r
1271 ConsoleInfo->Buffer = NULL;\r
a405b86d 1272 return (EFI_OUT_OF_RESOURCES);\r
1273 }\r
1274\r
a405b86d 1275 CopyMem (&ConsoleInfo->HistoryMode, ConsoleInfo->OldConOut->Mode, sizeof (EFI_SIMPLE_TEXT_OUTPUT_MODE));\r
1276\r
1277 return (EFI_SUCCESS);\r
1278}\r