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