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