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