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