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