]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterGraphics.c
ECC clean up.
[mirror_edk2.git] / MdeModulePkg / Universal / Console / ConSplitterDxe / ConSplitterGraphics.c
CommitLineData
fb0b259e 1/** @file\r
2 Support for ConsoleControl protocol. Support for Graphics output spliter.\r
3 Support for DevNull Console Out. This console uses memory buffers\r
4 to represnt the console. It allows a console to start very early and\r
5 when a new console is added it is synced up with the current console.\r
95276127 6\r
fb0b259e 7Copyright (c) 2006 - 2008, Intel Corporation. <BR>\r
95276127 8All rights reserved. This program and the accompanying materials\r
9are licensed and made available under the terms and conditions of the BSD License\r
10which accompanies this distribution. The full text of the license may be found at\r
11http://opensource.org/licenses/bsd-license.php\r
12\r
13THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
14WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
15\r
a4d608d1 16\r
fb0b259e 17**/\r
95276127 18\r
95276127 19\r
95276127 20#include "ConSplitter.h"\r
21\r
95276127 22\r
fe1e36e5 23CHAR16 mCrLfString[3] = { CHAR_CARRIAGE_RETURN, CHAR_LINEFEED, CHAR_NULL };\r
a4d608d1 24\r
25\r
26/**\r
27 Return the current video mode information. Also returns info about existence\r
28 of Graphics Output devices or UGA Draw devices in system, and if the Std In device is locked. All the\r
29 arguments are optional and only returned if a non NULL pointer is passed in.\r
30\r
31 @param This Protocol instance pointer.\r
32 @param Mode Are we in text of grahics mode.\r
9e604fe4 33 @param GopUgaExists TRUE if Console Spliter has found a GOP or UGA device\r
a4d608d1 34 @param StdInLocked TRUE if StdIn device is keyboard locked\r
95276127 35\r
a4d608d1 36 @retval EFI_SUCCESS Mode information returned.\r
37 @retval EFI_INVALID_PARAMETER Invalid parameters.\r
38\r
39**/\r
95276127 40EFI_STATUS\r
41EFIAPI\r
42ConSpliterConsoleControlGetMode (\r
43 IN EFI_CONSOLE_CONTROL_PROTOCOL *This,\r
44 OUT EFI_CONSOLE_CONTROL_SCREEN_MODE *Mode,\r
4b5c4fba 45 OUT BOOLEAN *GopUgaExists,\r
95276127 46 OUT BOOLEAN *StdInLocked\r
47 )\r
95276127 48{\r
49 TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;\r
50 UINTN Index;\r
51\r
52 Private = CONSOLE_CONTROL_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
53\r
54 if (Mode == NULL) {\r
55 return EFI_INVALID_PARAMETER;\r
56 }\r
57\r
58 *Mode = Private->ConsoleOutputMode;\r
59\r
4b5c4fba 60 if (GopUgaExists != NULL) {\r
61 *GopUgaExists = FALSE;\r
95276127 62 for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++) {\r
63 if ((Private->TextOutList[Index].GraphicsOutput != NULL) || (Private->TextOutList[Index].UgaDraw != NULL)) {\r
4b5c4fba 64 *GopUgaExists = TRUE;\r
95276127 65 break;\r
66 }\r
67 }\r
68 }\r
69\r
70 if (StdInLocked != NULL) {\r
71 *StdInLocked = ConSpliterConssoleControlStdInLocked ();\r
72 }\r
73\r
74 return EFI_SUCCESS;\r
75}\r
76\r
a4d608d1 77\r
78/**\r
79 Set the current mode to either text or graphics. Graphics is\r
80 for Quiet Boot.\r
81\r
82 @param This Protocol instance pointer.\r
83 @param Mode Mode to set the\r
84\r
85 @retval EFI_SUCCESS Mode information returned.\r
86 @retval EFI_INVALID_PARAMETER Invalid parameter.\r
87 @retval EFI_UNSUPPORTED Operation unsupported.\r
88\r
89**/\r
95276127 90EFI_STATUS\r
91EFIAPI\r
92ConSpliterConsoleControlSetMode (\r
93 IN EFI_CONSOLE_CONTROL_PROTOCOL *This,\r
94 IN EFI_CONSOLE_CONTROL_SCREEN_MODE Mode\r
95 )\r
95276127 96{\r
97 TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;\r
98 UINTN Index;\r
99 TEXT_OUT_AND_GOP_DATA *TextAndGop;\r
100 BOOLEAN Supported;\r
101\r
102 Private = CONSOLE_CONTROL_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
103\r
104 if (Mode >= EfiConsoleControlScreenMaxValue) {\r
105 return EFI_INVALID_PARAMETER;\r
106 }\r
107\r
108 //\r
109 // Judge current mode with wanted mode at first.\r
110 //\r
111 if (Private->ConsoleOutputMode == Mode) {\r
112 return EFI_SUCCESS;\r
113 }\r
114\r
115 Supported = FALSE;\r
116 TextAndGop = &Private->TextOutList[0];\r
117 for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++, TextAndGop++) {\r
118 if ((TextAndGop->GraphicsOutput != NULL) || (TextAndGop->UgaDraw != NULL)) {\r
119 Supported = TRUE;\r
120 break;\r
121 }\r
122 }\r
123\r
124 if ((!Supported) && (Mode == EfiConsoleControlScreenGraphics)) {\r
125 return EFI_UNSUPPORTED;\r
126 }\r
127\r
128 Private->ConsoleOutputMode = Mode;\r
129\r
130 TextAndGop = &Private->TextOutList[0];\r
131 for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++, TextAndGop++) {\r
132\r
133 TextAndGop->TextOutEnabled = TRUE;\r
134 //\r
135 // If we are going into Graphics mode disable ConOut to any UGA device\r
136 //\r
137 if ((Mode == EfiConsoleControlScreenGraphics) &&((TextAndGop->GraphicsOutput != NULL) || (TextAndGop->UgaDraw != NULL))) {\r
138 TextAndGop->TextOutEnabled = FALSE;\r
d0c64728 139 if (FeaturePcdGet (PcdConOutGopSupport)) {\r
140 DevNullGopSync (Private, TextAndGop->GraphicsOutput, TextAndGop->UgaDraw);\r
141 } else if (FeaturePcdGet (PcdConOutUgaSupport)) {\r
142 DevNullUgaSync (Private, TextAndGop->GraphicsOutput, TextAndGop->UgaDraw);\r
143 }\r
95276127 144 }\r
145 }\r
95276127 146 if (Mode == EfiConsoleControlScreenText) {\r
aec072ad 147 DevNullSyncStdOut (Private);\r
95276127 148 }\r
95276127 149 return EFI_SUCCESS;\r
150}\r
151\r
a4d608d1 152\r
153/**\r
154 Return the current video mode information.\r
155\r
156 @param This Protocol instance pointer.\r
157 @param ModeNumber The mode number to return information on.\r
158 @param SizeOfInfo A pointer to the size, in bytes, of the Info\r
159 buffer.\r
160 @param Info Caller allocated buffer that returns information\r
161 about ModeNumber.\r
162\r
163 @retval EFI_SUCCESS Mode information returned.\r
164 @retval EFI_BUFFER_TOO_SMALL The Info buffer was too small.\r
165 @retval EFI_DEVICE_ERROR A hardware error occurred trying to retrieve the\r
166 video mode.\r
167 @retval EFI_NOT_STARTED Video display is not initialized. Call SetMode ()\r
168 @retval EFI_INVALID_PARAMETER One of the input args was NULL.\r
169\r
170**/\r
95276127 171EFI_STATUS\r
172EFIAPI\r
173ConSpliterGraphicsOutputQueryMode (\r
174 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,\r
175 IN UINT32 ModeNumber,\r
176 OUT UINTN *SizeOfInfo,\r
177 OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info\r
178 )\r
95276127 179{\r
180 TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;\r
95276127 181\r
182 if (This == NULL || Info == NULL || SizeOfInfo == NULL || ModeNumber >= This->Mode->MaxMode) {\r
183 return EFI_INVALID_PARAMETER;\r
184 }\r
185\r
186 //\r
187 // retrieve private data\r
188 //\r
189 Private = GRAPHICS_OUTPUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
190\r
191 if (Private->HardwareNeedsStarting) {\r
192 return EFI_NOT_STARTED;\r
193 }\r
194\r
195 *Info = AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION));\r
196\r
197 if (*Info == NULL) {\r
198 return EFI_OUT_OF_RESOURCES;\r
199 }\r
200\r
201 *SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);\r
202\r
aec072ad 203 CopyMem (*Info, &Private->GraphicsOutputModeBuffer[ModeNumber], *SizeOfInfo);\r
95276127 204\r
205 return EFI_SUCCESS;\r
206}\r
207\r
a4d608d1 208\r
209/**\r
4b5c4fba 210 Graphics output protocol interface to set video mode.\r
a4d608d1 211\r
212 @param This Protocol instance pointer.\r
213 @param ModeNumber The mode number to be set.\r
214\r
215 @retval EFI_SUCCESS Graphics mode was changed.\r
216 @retval EFI_DEVICE_ERROR The device had an error and could not complete\r
217 the request.\r
218 @retval EFI_UNSUPPORTED ModeNumber is not supported by this device.\r
219\r
220**/\r
95276127 221EFI_STATUS\r
222EFIAPI\r
223ConSpliterGraphicsOutputSetMode (\r
224 IN EFI_GRAPHICS_OUTPUT_PROTOCOL * This,\r
225 IN UINT32 ModeNumber\r
226 )\r
95276127 227{\r
228 EFI_STATUS Status;\r
229 TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;\r
230 UINTN Index;\r
231 EFI_STATUS ReturnStatus;\r
aec072ad 232 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Mode;\r
95276127 233 UINTN Size;\r
234 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;\r
235 UINTN NumberIndex;\r
236 UINTN SizeOfInfo;\r
237 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info;\r
238 EFI_UGA_DRAW_PROTOCOL *UgaDraw;\r
239\r
240 if (ModeNumber >= This->Mode->MaxMode) {\r
241 return EFI_UNSUPPORTED;\r
242 }\r
243\r
244 if (ModeNumber == This->Mode->Mode) {\r
245 return EFI_SUCCESS;\r
246 }\r
247\r
248 Private = GRAPHICS_OUTPUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
249\r
95276127 250 ReturnStatus = EFI_SUCCESS;\r
251\r
252 //\r
253 // Free the old version\r
254 //\r
255 if (Private->GraphicsOutputBlt != NULL) {\r
256 FreePool (Private->GraphicsOutputBlt);\r
257 }\r
258\r
259 //\r
260 // Allocate the virtual Blt buffer\r
261 //\r
262 Mode = &Private->GraphicsOutputModeBuffer[ModeNumber];\r
263 Size = Mode->HorizontalResolution * Mode->VerticalResolution * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);\r
264 Private->GraphicsOutputBlt = AllocateZeroPool (Size);\r
265\r
266 if (Private->GraphicsOutputBlt == NULL) {\r
267 return EFI_OUT_OF_RESOURCES;\r
268 }\r
269\r
95276127 270 //\r
271 // return the worst status met\r
272 //\r
273 for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++) {\r
274 GraphicsOutput = Private->TextOutList[Index].GraphicsOutput;\r
275 if (GraphicsOutput != NULL) {\r
276 //\r
277 // Find corresponding ModeNumber of this GraphicsOutput instance\r
278 //\r
279 for (NumberIndex = 0; NumberIndex < GraphicsOutput->Mode->MaxMode; NumberIndex ++) {\r
280 Status = GraphicsOutput->QueryMode (GraphicsOutput, (UINT32) NumberIndex, &SizeOfInfo, &Info);\r
281 if (EFI_ERROR (Status)) {\r
282 return Status;\r
283 }\r
284 if ((Info->HorizontalResolution == Mode->HorizontalResolution) && (Info->VerticalResolution == Mode->VerticalResolution)) {\r
285 FreePool (Info);\r
286 break;\r
287 }\r
288 FreePool (Info);\r
289 }\r
290\r
291 Status = GraphicsOutput->SetMode (GraphicsOutput, (UINT32) NumberIndex);\r
292 if (EFI_ERROR (Status)) {\r
293 ReturnStatus = Status;\r
294 }\r
295 }\r
296\r
8541adab 297 if (EFI_ERROR (ReturnStatus) && FeaturePcdGet (PcdUgaConsumeSupport)) {\r
d0c64728 298 UgaDraw = Private->TextOutList[Index].UgaDraw;\r
299 if (UgaDraw != NULL) {\r
300 Status = UgaDraw->SetMode (\r
301 UgaDraw,\r
302 Mode->HorizontalResolution,\r
303 Mode->VerticalResolution,\r
304 32,\r
305 60\r
306 );\r
307 if (EFI_ERROR (Status)) {\r
308 ReturnStatus = Status;\r
309 }\r
95276127 310 }\r
311 }\r
312 }\r
313\r
314 This->Mode->Mode = ModeNumber;\r
315\r
aec072ad 316 CopyMem (This->Mode->Info, &Private->GraphicsOutputModeBuffer[ModeNumber], This->Mode->SizeOfInfo);\r
95276127 317\r
318 //\r
319 // Information is not enough here, so the following items remain unchanged:\r
320 // GraphicsOutputMode->Info->Version, GraphicsOutputMode->Info->PixelFormat\r
321 // GraphicsOutputMode->SizeOfInfo, GraphicsOutputMode->FrameBufferBase, GraphicsOutputMode->FrameBufferSize\r
322 // These items will be initialized/updated when a new GOP device is added into ConsoleSplitter.\r
323 //\r
324\r
325 Private->HardwareNeedsStarting = FALSE;\r
326\r
327 return ReturnStatus;\r
328}\r
329\r
33019a71 330/**\r
331 The following table defines actions for BltOperations.\r
332\r
333 EfiBltVideoFill - Write data from the BltBuffer pixel (SourceX, SourceY)\r
334 directly to every pixel of the video display rectangle\r
335 (DestinationX, DestinationY)\r
336 (DestinationX + Width, DestinationY + Height).\r
337 Only one pixel will be used from the BltBuffer. Delta is NOT used.\r
338 EfiBltVideoToBltBuffer - Read data from the video display rectangle\r
339 (SourceX, SourceY) (SourceX + Width, SourceY + Height) and place it in\r
340 the BltBuffer rectangle (DestinationX, DestinationY )\r
341 (DestinationX + Width, DestinationY + Height). If DestinationX or\r
342 DestinationY is not zero then Delta must be set to the length in bytes\r
343 of a row in the BltBuffer.\r
344 EfiBltBufferToVideo - Write data from the BltBuffer rectangle\r
345 (SourceX, SourceY) (SourceX + Width, SourceY + Height) directly to the\r
346 video display rectangle (DestinationX, DestinationY)\r
347 (DestinationX + Width, DestinationY + Height). If SourceX or SourceY is\r
348 not zero then Delta must be set to the length in bytes of a row in the\r
349 BltBuffer.\r
350 EfiBltVideoToVideo - Copy from the video display rectangle\r
351 (SourceX, SourceY) (SourceX + Width, SourceY + Height) .\r
352 to the video display rectangle (DestinationX, DestinationY)\r
353 (DestinationX + Width, DestinationY + Height).\r
354 The BltBuffer and Delta are not used in this mode.\r
355\r
356 @param Private Protocol instance pointer.\r
357 @param BltBuffer Buffer containing data to blit into video buffer.\r
358 This buffer has a size of\r
359 Width*Height*sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL)\r
360 @param BltOperation Operation to perform on BlitBuffer and video\r
361 memory\r
362 @param SourceX X coordinate of source for the BltBuffer.\r
363 @param SourceY Y coordinate of source for the BltBuffer.\r
364 @param DestinationX X coordinate of destination for the BltBuffer.\r
365 @param DestinationY Y coordinate of destination for the BltBuffer.\r
366 @param Width Width of rectangle in BltBuffer in pixels.\r
367 @param Height Hight of rectangle in BltBuffer in pixels. \r
368 @param Delta OPTIONAL.\r
369\r
370 @retval EFI_SUCCESS The Blt operation completed.\r
371 @retval EFI_INVALID_PARAMETER BltOperation is not valid.\r
372 @retval EFI_DEVICE_ERROR A hardware error occured writting to the video\r
373 buffer.\r
374\r
375**/\r
95276127 376EFI_STATUS\r
377DevNullGraphicsOutputBlt (\r
378 IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private,\r
379 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL\r
380 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,\r
381 IN UINTN SourceX,\r
382 IN UINTN SourceY,\r
383 IN UINTN DestinationX,\r
384 IN UINTN DestinationY,\r
385 IN UINTN Width,\r
386 IN UINTN Height,\r
387 IN UINTN Delta OPTIONAL\r
388 )\r
389{\r
390 UINTN SrcY;\r
391 BOOLEAN Forward;\r
392 UINTN Index;\r
393 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltPtr;\r
394 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *ScreenPtr;\r
395 UINTN HorizontalResolution;\r
396 UINTN VerticalResolution;\r
397\r
398 if ((BltOperation < EfiBltVideoFill) || (BltOperation >= EfiGraphicsOutputBltOperationMax)) {\r
399 return EFI_INVALID_PARAMETER;\r
400 }\r
401\r
402 if (Width == 0 || Height == 0) {\r
403 return EFI_INVALID_PARAMETER;\r
404 }\r
405\r
406 if (Delta == 0) {\r
407 Delta = Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);\r
408 }\r
409\r
410 HorizontalResolution = Private->GraphicsOutput.Mode->Info->HorizontalResolution;\r
411 VerticalResolution = Private->GraphicsOutput.Mode->Info->VerticalResolution;\r
412\r
413 //\r
414 // We need to fill the Virtual Screen buffer with the blt data.\r
415 //\r
416 if (BltOperation == EfiBltVideoToBltBuffer) {\r
417 //\r
418 // Video to BltBuffer: Source is Video, destination is BltBuffer\r
419 //\r
420 if ((SourceY + Height) > VerticalResolution) {\r
421 return EFI_INVALID_PARAMETER;\r
422 }\r
423\r
424 if ((SourceX + Width) > HorizontalResolution) {\r
425 return EFI_INVALID_PARAMETER;\r
426 }\r
427\r
428 BltPtr = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) ((UINT8 *) BltBuffer + DestinationY * Delta + DestinationX * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));\r
429 ScreenPtr = &Private->GraphicsOutputBlt[SourceY * HorizontalResolution + SourceX];\r
a4d608d1 430 while (Height > 0) {\r
95276127 431 CopyMem (BltPtr, ScreenPtr, Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));\r
432 BltPtr = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) ((UINT8 *) BltPtr + Delta);\r
433 ScreenPtr += HorizontalResolution;\r
434 Height--;\r
435 }\r
436 } else {\r
437 //\r
438 // BltBuffer to Video: Source is BltBuffer, destination is Video\r
439 //\r
440 if (DestinationY + Height > VerticalResolution) {\r
441 return EFI_INVALID_PARAMETER;\r
442 }\r
443\r
444 if (DestinationX + Width > HorizontalResolution) {\r
445 return EFI_INVALID_PARAMETER;\r
446 }\r
447\r
448 if ((BltOperation == EfiBltVideoToVideo) && (DestinationY > SourceY)) {\r
449 //\r
450 // Copy backwards, only care the Video to Video Blt\r
451 //\r
452 ScreenPtr = &Private->GraphicsOutputBlt[(DestinationY + Height - 1) * HorizontalResolution + DestinationX];\r
453 SrcY = SourceY + Height - 1;\r
454 Forward = FALSE;\r
455 } else {\r
456 //\r
457 // Copy forwards, for other cases\r
458 //\r
459 ScreenPtr = &Private->GraphicsOutputBlt[DestinationY * HorizontalResolution + DestinationX];\r
460 SrcY = SourceY;\r
461 Forward = TRUE;\r
462 }\r
463\r
464 while (Height != 0) {\r
465 if (BltOperation == EfiBltVideoFill) {\r
466 for (Index = 0; Index < Width; Index++) {\r
467 ScreenPtr[Index] = *BltBuffer;\r
468 }\r
469 } else {\r
470 if (BltOperation == EfiBltBufferToVideo) {\r
471 BltPtr = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) ((UINT8 *) BltBuffer + SrcY * Delta + SourceX * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));\r
472 } else {\r
473 BltPtr = &Private->GraphicsOutputBlt[SrcY * HorizontalResolution + SourceX];\r
474 }\r
475\r
476 CopyMem (ScreenPtr, BltPtr, Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));\r
477 }\r
478\r
479 if (Forward) {\r
480 ScreenPtr += HorizontalResolution;\r
481 SrcY ++;\r
482 } else {\r
483 ScreenPtr -= HorizontalResolution;\r
484 SrcY --;\r
485 }\r
486 Height--;\r
487 }\r
488 }\r
489\r
490 return EFI_SUCCESS;\r
491}\r
492\r
a4d608d1 493\r
494/**\r
495 The following table defines actions for BltOperations.\r
496\r
497 EfiBltVideoFill - Write data from the BltBuffer pixel (SourceX, SourceY)\r
498 directly to every pixel of the video display rectangle\r
499 (DestinationX, DestinationY)\r
500 (DestinationX + Width, DestinationY + Height).\r
501 Only one pixel will be used from the BltBuffer. Delta is NOT used.\r
502 EfiBltVideoToBltBuffer - Read data from the video display rectangle\r
503 (SourceX, SourceY) (SourceX + Width, SourceY + Height) and place it in\r
504 the BltBuffer rectangle (DestinationX, DestinationY )\r
505 (DestinationX + Width, DestinationY + Height). If DestinationX or\r
506 DestinationY is not zero then Delta must be set to the length in bytes\r
507 of a row in the BltBuffer.\r
508 EfiBltBufferToVideo - Write data from the BltBuffer rectangle\r
509 (SourceX, SourceY) (SourceX + Width, SourceY + Height) directly to the\r
510 video display rectangle (DestinationX, DestinationY)\r
511 (DestinationX + Width, DestinationY + Height). If SourceX or SourceY is\r
512 not zero then Delta must be set to the length in bytes of a row in the\r
513 BltBuffer.\r
514 EfiBltVideoToVideo - Copy from the video display rectangle\r
515 (SourceX, SourceY) (SourceX + Width, SourceY + Height) .\r
516 to the video display rectangle (DestinationX, DestinationY)\r
517 (DestinationX + Width, DestinationY + Height).\r
518 The BltBuffer and Delta are not used in this mode.\r
519\r
520 @param This Protocol instance pointer.\r
521 @param BltBuffer Buffer containing data to blit into video buffer.\r
522 This buffer has a size of\r
523 Width*Height*sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL)\r
524 @param BltOperation Operation to perform on BlitBuffer and video\r
525 memory\r
526 @param SourceX X coordinate of source for the BltBuffer.\r
527 @param SourceY Y coordinate of source for the BltBuffer.\r
528 @param DestinationX X coordinate of destination for the BltBuffer.\r
529 @param DestinationY Y coordinate of destination for the BltBuffer.\r
530 @param Width Width of rectangle in BltBuffer in pixels.\r
415df2a3 531 @param Height Hight of rectangle in BltBuffer in pixels. \r
33019a71 532 @param Delta OPTIONAL.\r
a4d608d1 533\r
534 @retval EFI_SUCCESS The Blt operation completed.\r
535 @retval EFI_INVALID_PARAMETER BltOperation is not valid.\r
536 @retval EFI_DEVICE_ERROR A hardware error occured writting to the video\r
537 buffer.\r
538\r
539**/\r
95276127 540EFI_STATUS\r
541EFIAPI\r
542ConSpliterGraphicsOutputBlt (\r
543 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,\r
544 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL\r
545 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,\r
546 IN UINTN SourceX,\r
547 IN UINTN SourceY,\r
548 IN UINTN DestinationX,\r
549 IN UINTN DestinationY,\r
550 IN UINTN Width,\r
551 IN UINTN Height,\r
552 IN UINTN Delta OPTIONAL\r
553 )\r
95276127 554{\r
555 EFI_STATUS Status;\r
556 TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;\r
557 UINTN Index;\r
558 EFI_STATUS ReturnStatus;\r
559 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;\r
560 EFI_UGA_DRAW_PROTOCOL *UgaDraw;\r
561\r
562 Private = GRAPHICS_OUTPUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
563\r
564 //\r
565 // Sync up DevNull GOP device\r
566 //\r
567 ReturnStatus = DevNullGraphicsOutputBlt (\r
568 Private,\r
569 BltBuffer,\r
570 BltOperation,\r
571 SourceX,\r
572 SourceY,\r
573 DestinationX,\r
574 DestinationY,\r
575 Width,\r
576 Height,\r
577 Delta\r
578 );\r
579\r
580 if (Private->ConsoleOutputMode != EfiConsoleControlScreenGraphics) {\r
581 return ReturnStatus;\r
582 }\r
583 //\r
584 // return the worst status met\r
585 //\r
586 for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++) {\r
587 GraphicsOutput = Private->TextOutList[Index].GraphicsOutput;\r
588 if (GraphicsOutput != NULL) {\r
589 Status = GraphicsOutput->Blt (\r
590 GraphicsOutput,\r
591 BltBuffer,\r
592 BltOperation,\r
593 SourceX,\r
594 SourceY,\r
595 DestinationX,\r
596 DestinationY,\r
597 Width,\r
598 Height,\r
599 Delta\r
600 );\r
601 if (EFI_ERROR (Status)) {\r
602 ReturnStatus = Status;\r
603 } else if (BltOperation == EfiBltVideoToBltBuffer) {\r
604 //\r
605 // Only need to read the data into buffer one time\r
606 //\r
607 return EFI_SUCCESS;\r
608 }\r
609 }\r
610\r
611 UgaDraw = Private->TextOutList[Index].UgaDraw;\r
8541adab 612 if (UgaDraw != NULL && FeaturePcdGet (PcdUgaConsumeSupport)) {\r
95276127 613 Status = UgaDraw->Blt (\r
614 UgaDraw,\r
615 (EFI_UGA_PIXEL *) BltBuffer,\r
616 (EFI_UGA_BLT_OPERATION) BltOperation,\r
617 SourceX,\r
618 SourceY,\r
619 DestinationX,\r
620 DestinationY,\r
621 Width,\r
622 Height,\r
623 Delta\r
624 );\r
625 if (EFI_ERROR (Status)) {\r
626 ReturnStatus = Status;\r
627 } else if (BltOperation == EfiBltVideoToBltBuffer) {\r
628 //\r
629 // Only need to read the data into buffer one time\r
630 //\r
631 return EFI_SUCCESS;\r
632 }\r
633 }\r
634 }\r
635\r
636 return ReturnStatus;\r
637}\r
638\r
33019a71 639/**\r
640 Write data from the buffer to video display based on Graphics Output setting. \r
641\r
642 @param Private Consplitter Text Out pointer.\r
643 @param GraphicsOutput Graphics Output protocol pointer.\r
644 @param UgaDraw UGA Draw protocol pointer.\r
645\r
646 @retval EFI_UNSUPPORTED No graphics devcie available .\r
647 @retval EFI_SUCCESS The Blt operation completed.\r
648 @retval EFI_INVALID_PARAMETER BltOperation is not valid.\r
649 @retval EFI_DEVICE_ERROR A hardware error occured writting to the video buffer.\r
650 \r
651\r
652**/\r
95276127 653EFI_STATUS\r
654DevNullGopSync (\r
655 IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private,\r
656 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput,\r
657 IN EFI_UGA_DRAW_PROTOCOL *UgaDraw\r
658 )\r
659{\r
660 if (GraphicsOutput != NULL) {\r
661 return GraphicsOutput->Blt (\r
662 GraphicsOutput,\r
663 Private->GraphicsOutputBlt,\r
664 EfiBltBufferToVideo,\r
665 0,\r
666 0,\r
667 0,\r
668 0,\r
669 Private->GraphicsOutput.Mode->Info->HorizontalResolution,\r
670 Private->GraphicsOutput.Mode->Info->VerticalResolution,\r
671 0\r
672 );\r
8541adab 673 } else if (FeaturePcdGet (PcdUgaConsumeSupport)) {\r
95276127 674 return UgaDraw->Blt (\r
675 UgaDraw,\r
676 (EFI_UGA_PIXEL *) Private->GraphicsOutputBlt,\r
677 EfiUgaBltBufferToVideo,\r
678 0,\r
679 0,\r
680 0,\r
681 0,\r
682 Private->GraphicsOutput.Mode->Info->HorizontalResolution,\r
683 Private->GraphicsOutput.Mode->Info->VerticalResolution,\r
684 0\r
685 );\r
8541adab 686 } else {\r
687 return EFI_UNSUPPORTED;\r
95276127 688 }\r
689}\r
690\r
a4d608d1 691\r
692/**\r
693 Return the current video mode information.\r
694\r
695 @param This Protocol instance pointer.\r
696 @param HorizontalResolution Current video horizontal resolution in pixels\r
697 @param VerticalResolution Current video vertical resolution in pixels\r
698 @param ColorDepth Current video color depth in bits per pixel\r
699 @param RefreshRate Current video refresh rate in Hz.\r
700\r
701 @retval EFI_SUCCESS Mode information returned.\r
702 @retval EFI_NOT_STARTED Video display is not initialized. Call SetMode ()\r
703 @retval EFI_INVALID_PARAMETER One of the input args was NULL.\r
704\r
705**/\r
d0c64728 706EFI_STATUS\r
707EFIAPI\r
708ConSpliterUgaDrawGetMode (\r
709 IN EFI_UGA_DRAW_PROTOCOL *This,\r
710 OUT UINT32 *HorizontalResolution,\r
711 OUT UINT32 *VerticalResolution,\r
712 OUT UINT32 *ColorDepth,\r
713 OUT UINT32 *RefreshRate\r
714 )\r
d0c64728 715{\r
716 TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;\r
717\r
a4d608d1 718 if ((HorizontalResolution == NULL) ||\r
719 (VerticalResolution == NULL) ||\r
720 (RefreshRate == NULL) ||\r
721 (ColorDepth == NULL)) {\r
d0c64728 722 return EFI_INVALID_PARAMETER;\r
723 }\r
724 //\r
725 // retrieve private data\r
726 //\r
727 Private = UGA_DRAW_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
728\r
729 *HorizontalResolution = Private->UgaHorizontalResolution;\r
730 *VerticalResolution = Private->UgaVerticalResolution;\r
731 *ColorDepth = Private->UgaColorDepth;\r
732 *RefreshRate = Private->UgaRefreshRate;\r
733\r
734 return EFI_SUCCESS;\r
735}\r
736\r
a4d608d1 737\r
738/**\r
739 Return the current video mode information.\r
740\r
741 @param This Protocol instance pointer.\r
742 @param HorizontalResolution Current video horizontal resolution in pixels\r
743 @param VerticalResolution Current video vertical resolution in pixels\r
744 @param ColorDepth Current video color depth in bits per pixel\r
745 @param RefreshRate Current video refresh rate in Hz.\r
746\r
747 @retval EFI_SUCCESS Mode information returned.\r
748 @retval EFI_NOT_STARTED Video display is not initialized. Call SetMode ()\r
749 @retval EFI_OUT_OF_RESOURCES Out of resources.\r
750\r
751**/\r
d0c64728 752EFI_STATUS\r
753EFIAPI\r
754ConSpliterUgaDrawSetMode (\r
755 IN EFI_UGA_DRAW_PROTOCOL *This,\r
756 IN UINT32 HorizontalResolution,\r
757 IN UINT32 VerticalResolution,\r
758 IN UINT32 ColorDepth,\r
759 IN UINT32 RefreshRate\r
760 )\r
d0c64728 761{\r
762 EFI_STATUS Status;\r
763 TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;\r
764 UINTN Index;\r
765 EFI_STATUS ReturnStatus;\r
766 UINTN Size;\r
767 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;\r
768 UINTN NumberIndex;\r
769 UINTN SizeOfInfo;\r
770 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info;\r
771 EFI_UGA_DRAW_PROTOCOL *UgaDraw;\r
772\r
773 Private = UGA_DRAW_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
774\r
775 //\r
776 // UgaDevNullSetMode ()\r
777 //\r
778 ReturnStatus = EFI_SUCCESS;\r
779\r
780 //\r
781 // Free the old version\r
782 //\r
783 if (Private->UgaBlt != NULL) {\r
784 FreePool (Private->UgaBlt);\r
785 }\r
786\r
787 //\r
788 // Allocate the virtual Blt buffer\r
789 //\r
790 Size = HorizontalResolution * VerticalResolution * sizeof (EFI_UGA_PIXEL);\r
791 Private->UgaBlt = AllocateZeroPool (Size);\r
792 if (Private->UgaBlt == NULL) {\r
793 return EFI_OUT_OF_RESOURCES;\r
794 }\r
795\r
796 //\r
797 // Update the Mode data\r
798 //\r
799 Private->UgaHorizontalResolution = HorizontalResolution;\r
800 Private->UgaVerticalResolution = VerticalResolution;\r
801 Private->UgaColorDepth = ColorDepth;\r
802 Private->UgaRefreshRate = RefreshRate;\r
803\r
804 if (Private->ConsoleOutputMode != EfiConsoleControlScreenGraphics) {\r
805 return ReturnStatus;\r
806 }\r
807 //\r
808 // return the worst status met\r
809 //\r
810 for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++) {\r
8541adab 811\r
812 ReturnStatus = EFI_UNSUPPORTED;\r
813\r
814 if (FeaturePcdGet (PcdUgaConsumeSupport)) {\r
815 UgaDraw = Private->TextOutList[Index].UgaDraw;\r
816 if (UgaDraw != NULL && FeaturePcdGet (PcdUgaConsumeSupport)) {\r
817 Status = UgaDraw->SetMode (\r
818 UgaDraw,\r
819 HorizontalResolution,\r
820 VerticalResolution,\r
821 ColorDepth,\r
822 RefreshRate\r
823 );\r
824 if (EFI_ERROR (Status)) {\r
825 ReturnStatus = Status;\r
826 }\r
d0c64728 827 }\r
828 }\r
829\r
830 if (EFI_ERROR (ReturnStatus)) {\r
831 GraphicsOutput = Private->TextOutList[Index].GraphicsOutput;\r
832 if (GraphicsOutput != NULL) {\r
833 //\r
834 // Find corresponding ModeNumber of this GraphicsOutput instance\r
835 //\r
836 for (NumberIndex = 0; NumberIndex < GraphicsOutput->Mode->MaxMode; NumberIndex ++) {\r
837 Status = GraphicsOutput->QueryMode (GraphicsOutput, (UINT32) NumberIndex, &SizeOfInfo, &Info);\r
838 if (EFI_ERROR (Status)) {\r
839 return Status;\r
840 }\r
841 if ((Info->HorizontalResolution == HorizontalResolution) && (Info->VerticalResolution == VerticalResolution)) {\r
842 FreePool (Info);\r
843 break;\r
844 }\r
845 FreePool (Info);\r
846 }\r
847\r
848 Status = GraphicsOutput->SetMode (GraphicsOutput, (UINT32) NumberIndex);\r
849 if (EFI_ERROR (Status)) {\r
850 ReturnStatus = Status;\r
851 }\r
852 }\r
853 }\r
854 }\r
855\r
856 return ReturnStatus;\r
857}\r
858\r
33019a71 859/**\r
860 The following table defines actions for BltOperations.\r
861\r
862 EfiBltVideoFill - Write data from the BltBuffer pixel (SourceX, SourceY)\r
863 directly to every pixel of the video display rectangle\r
864 (DestinationX, DestinationY)\r
865 (DestinationX + Width, DestinationY + Height).\r
866 Only one pixel will be used from the BltBuffer. Delta is NOT used.\r
867 EfiBltVideoToBltBuffer - Read data from the video display rectangle\r
868 (SourceX, SourceY) (SourceX + Width, SourceY + Height) and place it in\r
869 the BltBuffer rectangle (DestinationX, DestinationY )\r
870 (DestinationX + Width, DestinationY + Height). If DestinationX or\r
871 DestinationY is not zero then Delta must be set to the length in bytes\r
872 of a row in the BltBuffer.\r
873 EfiBltBufferToVideo - Write data from the BltBuffer rectangle\r
874 (SourceX, SourceY) (SourceX + Width, SourceY + Height) directly to the\r
875 video display rectangle (DestinationX, DestinationY)\r
876 (DestinationX + Width, DestinationY + Height). If SourceX or SourceY is\r
877 not zero then Delta must be set to the length in bytes of a row in the\r
878 BltBuffer.\r
879 EfiBltVideoToVideo - Copy from the video display rectangle\r
880 (SourceX, SourceY) (SourceX + Width, SourceY + Height) .\r
881 to the video display rectangle (DestinationX, DestinationY)\r
882 (DestinationX + Width, DestinationY + Height).\r
883 The BltBuffer and Delta are not used in this mode.\r
884\r
885 @param Private Protocol instance pointer.\r
886 @param BltBuffer Buffer containing data to blit into video buffer.\r
887 This buffer has a size of\r
888 Width*Height*sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL)\r
889 @param BltOperation Operation to perform on BlitBuffer and video\r
890 memory\r
891 @param SourceX X coordinate of source for the BltBuffer.\r
892 @param SourceY Y coordinate of source for the BltBuffer.\r
893 @param DestinationX X coordinate of destination for the BltBuffer.\r
894 @param DestinationY Y coordinate of destination for the BltBuffer.\r
895 @param Width Width of rectangle in BltBuffer in pixels.\r
896 @param Height Hight of rectangle in BltBuffer in pixels. \r
897 @param Delta OPTIONAL.\r
898\r
899 @retval EFI_SUCCESS The Blt operation completed.\r
900 @retval EFI_INVALID_PARAMETER BltOperation is not valid.\r
901 @retval EFI_DEVICE_ERROR A hardware error occured writting to the video\r
902 buffer.\r
903\r
904**/\r
d0c64728 905EFI_STATUS\r
906DevNullUgaBlt (\r
907 IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private,\r
908 IN EFI_UGA_PIXEL *BltBuffer, OPTIONAL\r
909 IN EFI_UGA_BLT_OPERATION BltOperation,\r
910 IN UINTN SourceX,\r
911 IN UINTN SourceY,\r
912 IN UINTN DestinationX,\r
913 IN UINTN DestinationY,\r
914 IN UINTN Width,\r
915 IN UINTN Height,\r
916 IN UINTN Delta OPTIONAL\r
917 )\r
918{\r
919 UINTN SrcY;\r
920 BOOLEAN Forward;\r
921 UINTN Index;\r
922 EFI_UGA_PIXEL *BltPtr;\r
923 EFI_UGA_PIXEL *ScreenPtr;\r
924 UINT32 HorizontalResolution;\r
925 UINT32 VerticalResolution;\r
926\r
927 if ((BltOperation < 0) || (BltOperation >= EfiUgaBltMax)) {\r
928 return EFI_INVALID_PARAMETER;\r
929 }\r
930\r
931 if (Width == 0 || Height == 0) {\r
932 return EFI_INVALID_PARAMETER;\r
933 }\r
934\r
935 if (Delta == 0) {\r
936 Delta = Width * sizeof (EFI_UGA_PIXEL);\r
937 }\r
938\r
939 HorizontalResolution = Private->UgaHorizontalResolution;\r
940 VerticalResolution = Private->UgaVerticalResolution;\r
941\r
942 //\r
943 // We need to fill the Virtual Screen buffer with the blt data.\r
944 //\r
945 if (BltOperation == EfiUgaVideoToBltBuffer) {\r
946 //\r
947 // Video to BltBuffer: Source is Video, destination is BltBuffer\r
948 //\r
949 if ((SourceY + Height) > VerticalResolution) {\r
950 return EFI_INVALID_PARAMETER;\r
951 }\r
952\r
953 if ((SourceX + Width) > HorizontalResolution) {\r
954 return EFI_INVALID_PARAMETER;\r
955 }\r
956\r
957 BltPtr = (EFI_UGA_PIXEL *) ((UINT8 *) BltBuffer + DestinationY * Delta + DestinationX * sizeof (EFI_UGA_PIXEL));\r
958 ScreenPtr = &Private->UgaBlt[SourceY * HorizontalResolution + SourceX];\r
a4d608d1 959 while (Height > 0) {\r
d0c64728 960 CopyMem (BltPtr, ScreenPtr, Width * sizeof (EFI_UGA_PIXEL));\r
961 BltPtr = (EFI_UGA_PIXEL *) ((UINT8 *) BltPtr + Delta);\r
962 ScreenPtr += HorizontalResolution;\r
963 Height--;\r
964 }\r
965 } else {\r
966 //\r
967 // BltBuffer to Video: Source is BltBuffer, destination is Video\r
968 //\r
969 if (DestinationY + Height > VerticalResolution) {\r
970 return EFI_INVALID_PARAMETER;\r
971 }\r
972\r
973 if (DestinationX + Width > HorizontalResolution) {\r
974 return EFI_INVALID_PARAMETER;\r
975 }\r
976\r
977 if ((BltOperation == EfiUgaVideoToVideo) && (DestinationY > SourceY)) {\r
978 //\r
979 // Copy backwards, only care the Video to Video Blt\r
980 //\r
981 ScreenPtr = &Private->UgaBlt[(DestinationY + Height - 1) * HorizontalResolution + DestinationX];\r
982 SrcY = SourceY + Height - 1;\r
983 Forward = FALSE;\r
984 } else {\r
985 //\r
986 // Copy forwards, for other cases\r
987 //\r
988 ScreenPtr = &Private->UgaBlt[DestinationY * HorizontalResolution + DestinationX];\r
989 SrcY = SourceY;\r
990 Forward = TRUE;\r
991 }\r
992\r
993 while (Height != 0) {\r
994 if (BltOperation == EfiUgaVideoFill) {\r
995 for (Index = 0; Index < Width; Index++) {\r
996 ScreenPtr[Index] = *BltBuffer;\r
997 }\r
998 } else {\r
999 if (BltOperation == EfiUgaBltBufferToVideo) {\r
1000 BltPtr = (EFI_UGA_PIXEL *) ((UINT8 *) BltBuffer + SrcY * Delta + SourceX * sizeof (EFI_UGA_PIXEL));\r
1001 } else {\r
1002 BltPtr = &Private->UgaBlt[SrcY * HorizontalResolution + SourceX];\r
1003 }\r
1004\r
1005 CopyMem (ScreenPtr, BltPtr, Width * sizeof (EFI_UGA_PIXEL));\r
1006 }\r
1007\r
1008 if (Forward) {\r
1009 ScreenPtr += HorizontalResolution;\r
1010 SrcY ++;\r
1011 } else {\r
1012 ScreenPtr -= HorizontalResolution;\r
1013 SrcY --;\r
1014 }\r
1015 Height--;\r
1016 }\r
1017 }\r
1018\r
1019 return EFI_SUCCESS;\r
1020}\r
1021\r
a4d608d1 1022\r
1023/**\r
1024 The following table defines actions for BltOperations.\r
1025\r
1026 EfiUgaVideoFill - Write data from the BltBuffer pixel (SourceX, SourceY)\r
1027 directly to every pixel of the video display rectangle\r
1028 (DestinationX, DestinationY)\r
1029 (DestinationX + Width, DestinationY + Height).\r
1030 Only one pixel will be used from the BltBuffer. Delta is NOT used.\r
1031 EfiUgaVideoToBltBuffer - Read data from the video display rectangle\r
1032 (SourceX, SourceY) (SourceX + Width, SourceY + Height) and place it in\r
1033 the BltBuffer rectangle (DestinationX, DestinationY )\r
1034 (DestinationX + Width, DestinationY + Height). If DestinationX or\r
1035 DestinationY is not zero then Delta must be set to the length in bytes\r
1036 of a row in the BltBuffer.\r
1037 EfiUgaBltBufferToVideo - Write data from the BltBuffer rectangle\r
1038 (SourceX, SourceY) (SourceX + Width, SourceY + Height) directly to the\r
1039 video display rectangle (DestinationX, DestinationY)\r
1040 (DestinationX + Width, DestinationY + Height). If SourceX or SourceY is\r
1041 not zero then Delta must be set to the length in bytes of a row in the\r
1042 BltBuffer.\r
1043 EfiUgaVideoToVideo - Copy from the video display rectangle\r
1044 (SourceX, SourceY) (SourceX + Width, SourceY + Height) .\r
1045 to the video display rectangle (DestinationX, DestinationY)\r
1046 (DestinationX + Width, DestinationY + Height).\r
1047 The BltBuffer and Delta are not used in this mode.\r
1048\r
1049 @param This Protocol instance pointer.\r
1050 @param BltBuffer Buffer containing data to blit into video buffer.\r
1051 This buffer has a size of\r
1052 Width*Height*sizeof(EFI_UGA_PIXEL)\r
1053 @param BltOperation Operation to perform on BlitBuffer and video\r
1054 memory\r
1055 @param SourceX X coordinate of source for the BltBuffer.\r
1056 @param SourceY Y coordinate of source for the BltBuffer.\r
1057 @param DestinationX X coordinate of destination for the BltBuffer.\r
1058 @param DestinationY Y coordinate of destination for the BltBuffer.\r
1059 @param Width Width of rectangle in BltBuffer in pixels.\r
415df2a3 1060 @param Height Hight of rectangle in BltBuffer in pixels.\r
33019a71 1061 @param Delta OPTIONAL.\r
a4d608d1 1062\r
1063 @retval EFI_SUCCESS The Blt operation completed.\r
1064 @retval EFI_INVALID_PARAMETER BltOperation is not valid.\r
1065 @retval EFI_DEVICE_ERROR A hardware error occured writting to the video\r
1066 buffer.\r
1067\r
1068**/\r
d0c64728 1069EFI_STATUS\r
1070EFIAPI\r
1071ConSpliterUgaDrawBlt (\r
1072 IN EFI_UGA_DRAW_PROTOCOL *This,\r
1073 IN EFI_UGA_PIXEL *BltBuffer, OPTIONAL\r
1074 IN EFI_UGA_BLT_OPERATION BltOperation,\r
1075 IN UINTN SourceX,\r
1076 IN UINTN SourceY,\r
1077 IN UINTN DestinationX,\r
1078 IN UINTN DestinationY,\r
1079 IN UINTN Width,\r
1080 IN UINTN Height,\r
1081 IN UINTN Delta OPTIONAL\r
1082 )\r
d0c64728 1083{\r
1084 EFI_STATUS Status;\r
1085 TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;\r
1086 UINTN Index;\r
1087 EFI_STATUS ReturnStatus;\r
1088 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;\r
1089\r
1090 Private = UGA_DRAW_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
1091\r
1092 //\r
1093 // Sync up DevNull UGA device\r
1094 //\r
1095 ReturnStatus = DevNullUgaBlt (\r
1096 Private,\r
1097 BltBuffer,\r
1098 BltOperation,\r
1099 SourceX,\r
1100 SourceY,\r
1101 DestinationX,\r
1102 DestinationY,\r
1103 Width,\r
1104 Height,\r
1105 Delta\r
1106 );\r
1107 if (Private->ConsoleOutputMode != EfiConsoleControlScreenGraphics) {\r
1108 return ReturnStatus;\r
1109 }\r
1110 //\r
1111 // return the worst status met\r
1112 //\r
1113 for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++) {\r
1114 GraphicsOutput = Private->TextOutList[Index].GraphicsOutput;\r
1115 if (GraphicsOutput != NULL) {\r
1116 Status = GraphicsOutput->Blt (\r
1117 GraphicsOutput,\r
1118 (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) BltBuffer,\r
1119 (EFI_GRAPHICS_OUTPUT_BLT_OPERATION) BltOperation,\r
1120 SourceX,\r
1121 SourceY,\r
1122 DestinationX,\r
1123 DestinationY,\r
1124 Width,\r
1125 Height,\r
1126 Delta\r
1127 );\r
1128 if (EFI_ERROR (Status)) {\r
1129 ReturnStatus = Status;\r
1130 } else if (BltOperation == EfiBltVideoToBltBuffer) {\r
1131 //\r
1132 // Only need to read the data into buffer one time\r
1133 //\r
1134 return EFI_SUCCESS;\r
1135 }\r
1136 }\r
1137\r
8541adab 1138 if (Private->TextOutList[Index].UgaDraw != NULL && FeaturePcdGet (PcdUgaConsumeSupport)) {\r
d0c64728 1139 Status = Private->TextOutList[Index].UgaDraw->Blt (\r
1140 Private->TextOutList[Index].UgaDraw,\r
1141 BltBuffer,\r
1142 BltOperation,\r
1143 SourceX,\r
1144 SourceY,\r
1145 DestinationX,\r
1146 DestinationY,\r
1147 Width,\r
1148 Height,\r
1149 Delta\r
1150 );\r
1151 if (EFI_ERROR (Status)) {\r
1152 ReturnStatus = Status;\r
1153 } else if (BltOperation == EfiUgaVideoToBltBuffer) {\r
1154 //\r
1155 // Only need to read the data into buffer one time\r
1156 //\r
1157 return EFI_SUCCESS;\r
1158 }\r
1159 }\r
1160 }\r
1161\r
1162 return ReturnStatus;\r
1163}\r
1164\r
33019a71 1165/**\r
1166 Write data from the buffer to video display based on UGA Draw setting. \r
1167\r
1168 @param Private Consplitter Text Out pointer.\r
1169 @param GraphicsOutput Graphics Output protocol pointer.\r
1170 @param UgaDraw UGA Draw protocol pointer.\r
1171\r
1172 @retval EFI_UNSUPPORTED No graphics devcie available .\r
1173 @retval EFI_SUCCESS The Blt operation completed.\r
1174 @retval EFI_INVALID_PARAMETER BltOperation is not valid.\r
1175 @retval EFI_DEVICE_ERROR A hardware error occured writting to the video buffer.\r
1176 \r
1177**/\r
d0c64728 1178EFI_STATUS\r
1179DevNullUgaSync (\r
1180 IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private,\r
1181 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput,\r
1182 IN EFI_UGA_DRAW_PROTOCOL *UgaDraw\r
1183 )\r
1184{\r
8541adab 1185 if (UgaDraw != NULL && FeaturePcdGet (PcdUgaConsumeSupport)) {\r
d0c64728 1186 return UgaDraw->Blt (\r
1187 UgaDraw,\r
1188 Private->UgaBlt,\r
1189 EfiUgaBltBufferToVideo,\r
1190 0,\r
1191 0,\r
1192 0,\r
1193 0,\r
1194 Private->UgaHorizontalResolution,\r
1195 Private->UgaVerticalResolution,\r
1196 Private->UgaHorizontalResolution * sizeof (EFI_UGA_PIXEL)\r
1197 );\r
8541adab 1198 } else if (GraphicsOutput != NULL) {\r
d0c64728 1199 return GraphicsOutput->Blt (\r
1200 GraphicsOutput,\r
1201 (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) Private->UgaBlt,\r
1202 EfiBltBufferToVideo,\r
1203 0,\r
1204 0,\r
1205 0,\r
1206 0,\r
1207 Private->UgaHorizontalResolution,\r
1208 Private->UgaVerticalResolution,\r
1209 0\r
1210 );\r
8541adab 1211 } else {\r
1212 return EFI_UNSUPPORTED;\r
d0c64728 1213 }\r
1214}\r
95276127 1215\r
a4d608d1 1216\r
1217/**\r
1218 Write a Unicode string to the output device.\r
1219\r
1220 @param Private Pointer to the console output splitter's private\r
1221 data. It indicates the calling context.\r
1222 @param WString The NULL-terminated Unicode string to be\r
1223 displayed on the output device(s). All output\r
1224 devices must also support the Unicode drawing\r
1225 defined in this file.\r
1226\r
1227 @retval EFI_SUCCESS The string was output to the device.\r
1228 @retval EFI_DEVICE_ERROR The device reported an error while attempting to\r
1229 output the text.\r
1230 @retval EFI_UNSUPPORTED The output device's mode is not currently in a\r
1231 defined text mode.\r
1232 @retval EFI_WARN_UNKNOWN_GLYPH This warning code indicates that some of the\r
1233 characters in the Unicode string could not be\r
1234 rendered and were skipped.\r
1235\r
1236**/\r
95276127 1237EFI_STATUS\r
1238DevNullTextOutOutputString (\r
1239 IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private,\r
1240 IN CHAR16 *WString\r
1241 )\r
95276127 1242{\r
1243 UINTN SizeScreen;\r
1244 UINTN SizeAttribute;\r
1245 UINTN Index;\r
1246 EFI_SIMPLE_TEXT_OUTPUT_MODE *Mode;\r
1247 CHAR16 *Screen;\r
1248 CHAR16 *NullScreen;\r
1249 CHAR16 InsertChar;\r
1250 CHAR16 TempChar;\r
1251 CHAR16 *PStr;\r
1252 INT32 *Attribute;\r
1253 INT32 *NullAttributes;\r
1254 INT32 CurrentWidth;\r
1255 UINTN LastRow;\r
1256 UINTN MaxColumn;\r
1257\r
1258 Mode = &Private->TextOutMode;\r
1259 NullScreen = Private->DevNullScreen;\r
1260 NullAttributes = Private->DevNullAttributes;\r
1261 LastRow = Private->DevNullRows - 1;\r
1262 MaxColumn = Private->DevNullColumns;\r
1263\r
1264 if (Mode->Attribute & EFI_WIDE_ATTRIBUTE) {\r
1265 CurrentWidth = 2;\r
1266 } else {\r
1267 CurrentWidth = 1;\r
1268 }\r
1269\r
a4d608d1 1270 while (*WString != L'\0') {\r
95276127 1271\r
1272 if (*WString == CHAR_BACKSPACE) {\r
1273 //\r
1274 // If the cursor is at the left edge of the display, then move the cursor\r
1275 // one row up.\r
1276 //\r
1277 if (Mode->CursorColumn == 0 && Mode->CursorRow > 0) {\r
1278 Mode->CursorRow--;\r
1279 Mode->CursorColumn = (INT32) MaxColumn;\r
1280 }\r
1281\r
1282 //\r
1283 // If the cursor is not at the left edge of the display,\r
1284 // then move the cursor left one column.\r
1285 //\r
1286 if (Mode->CursorColumn > 0) {\r
1287 Mode->CursorColumn--;\r
1288 if (Mode->CursorColumn > 0 &&\r
1289 NullAttributes[Mode->CursorRow * MaxColumn + Mode->CursorColumn - 1] & EFI_WIDE_ATTRIBUTE\r
1290 ) {\r
1291 Mode->CursorColumn--;\r
1292\r
1293 //\r
1294 // Insert an extra backspace\r
1295 //\r
1296 InsertChar = CHAR_BACKSPACE;\r
1297 PStr = WString + 1;\r
a4d608d1 1298 while (*PStr != L'\0') {\r
95276127 1299 TempChar = *PStr;\r
1300 *PStr = InsertChar;\r
1301 InsertChar = TempChar;\r
1302 PStr++;\r
1303 }\r
1304\r
1305 *PStr = InsertChar;\r
1306 *(++PStr) = 0;\r
1307\r
1308 WString++;\r
1309 }\r
1310 }\r
1311\r
1312 WString++;\r
1313\r
1314 } else if (*WString == CHAR_LINEFEED) {\r
1315 //\r
1316 // If the cursor is at the bottom of the display,\r
1317 // then scroll the display one row, and do not update\r
1318 // the cursor position. Otherwise, move the cursor down one row.\r
1319 //\r
1320 if (Mode->CursorRow == (INT32) (LastRow)) {\r
1321 //\r
1322 // Scroll Screen Up One Row\r
1323 //\r
1324 SizeAttribute = LastRow * MaxColumn;\r
1325 CopyMem (\r
1326 NullAttributes,\r
1327 NullAttributes + MaxColumn,\r
1328 SizeAttribute * sizeof (INT32)\r
1329 );\r
1330\r
1331 //\r
1332 // Each row has an ending CHAR_NULL. So one more character each line\r
1333 // for DevNullScreen than DevNullAttributes\r
1334 //\r
1335 SizeScreen = SizeAttribute + LastRow;\r
1336 CopyMem (\r
1337 NullScreen,\r
1338 NullScreen + (MaxColumn + 1),\r
1339 SizeScreen * sizeof (CHAR16)\r
1340 );\r
1341\r
1342 //\r
1343 // Print Blank Line at last line\r
1344 //\r
1345 Screen = NullScreen + SizeScreen;\r
1346 Attribute = NullAttributes + SizeAttribute;\r
1347\r
1348 for (Index = 0; Index < MaxColumn; Index++, Screen++, Attribute++) {\r
4b5c4fba 1349 *Screen = L' ';\r
95276127 1350 *Attribute = Mode->Attribute;\r
1351 }\r
1352 } else {\r
1353 Mode->CursorRow++;\r
1354 }\r
1355\r
1356 WString++;\r
1357 } else if (*WString == CHAR_CARRIAGE_RETURN) {\r
1358 //\r
1359 // Move the cursor to the beginning of the current row.\r
1360 //\r
1361 Mode->CursorColumn = 0;\r
1362 WString++;\r
1363 } else {\r
1364 //\r
1365 // Print the character at the current cursor position and\r
1366 // move the cursor right one column. If this moves the cursor\r
1367 // past the right edge of the display, then the line should wrap to\r
1368 // the beginning of the next line. This is equivalent to inserting\r
1369 // a CR and an LF. Note that if the cursor is at the bottom of the\r
1370 // display, and the line wraps, then the display will be scrolled\r
1371 // one line.\r
1372 //\r
1373 Index = Mode->CursorRow * MaxColumn + Mode->CursorColumn;\r
1374\r
1375 while (Mode->CursorColumn < (INT32) MaxColumn) {\r
1376 if (*WString == CHAR_NULL) {\r
1377 break;\r
1378 }\r
1379\r
1380 if (*WString == CHAR_BACKSPACE) {\r
1381 break;\r
1382 }\r
1383\r
1384 if (*WString == CHAR_LINEFEED) {\r
1385 break;\r
1386 }\r
1387\r
1388 if (*WString == CHAR_CARRIAGE_RETURN) {\r
1389 break;\r
1390 }\r
1391\r
97a079ed
A
1392 if (*WString == UNICODE_WIDE_CHAR || *WString == UNICODE_NARROW_CHAR) {\r
1393 CurrentWidth = (*WString == UNICODE_WIDE_CHAR) ? 2 : 1;\r
95276127 1394 WString++;\r
1395 continue;\r
1396 }\r
1397\r
1398 if (Mode->CursorColumn + CurrentWidth > (INT32) MaxColumn) {\r
1399 //\r
1400 // If a wide char is at the rightmost column, then move the char\r
1401 // to the beginning of the next row\r
1402 //\r
1403 NullScreen[Index + Mode->CursorRow] = L' ';\r
1404 NullAttributes[Index] = Mode->Attribute | (UINT32) EFI_WIDE_ATTRIBUTE;\r
1405 Index++;\r
1406 Mode->CursorColumn++;\r
1407 } else {\r
1408 NullScreen[Index + Mode->CursorRow] = *WString;\r
1409 NullAttributes[Index] = Mode->Attribute;\r
1410 if (CurrentWidth == 1) {\r
1411 NullAttributes[Index] &= (~ (UINT32) EFI_WIDE_ATTRIBUTE);\r
1412 } else {\r
1413 NullAttributes[Index] |= (UINT32) EFI_WIDE_ATTRIBUTE;\r
1414 NullAttributes[Index + 1] &= (~ (UINT32) EFI_WIDE_ATTRIBUTE);\r
1415 }\r
1416\r
1417 Index += CurrentWidth;\r
1418 WString++;\r
1419 Mode->CursorColumn += CurrentWidth;\r
1420 }\r
1421 }\r
1422 //\r
1423 // At the end of line, output carriage return and line feed\r
1424 //\r
1425 if (Mode->CursorColumn >= (INT32) MaxColumn) {\r
1426 DevNullTextOutOutputString (Private, mCrLfString);\r
1427 }\r
1428 }\r
1429 }\r
1430\r
1431 return EFI_SUCCESS;\r
1432}\r
1433\r
a4d608d1 1434\r
1435/**\r
1436 Sets the output device(s) to a specified mode.\r
1437\r
1438 @param Private Private data structure pointer.\r
1439 @param ModeNumber The mode number to set.\r
1440\r
1441 @retval EFI_SUCCESS The requested text mode was set.\r
1442 @retval EFI_DEVICE_ERROR The device had an error and could not complete\r
1443 the request.\r
1444 @retval EFI_UNSUPPORTED The mode number was not valid.\r
1445 @retval EFI_OUT_OF_RESOURCES Out of resources.\r
1446\r
1447**/\r
95276127 1448EFI_STATUS\r
1449DevNullTextOutSetMode (\r
1450 IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private,\r
1451 IN UINTN ModeNumber\r
1452 )\r
95276127 1453{\r
1454 UINTN Size;\r
3012ce5c 1455 INT32 CurrentMode;\r
95276127 1456 UINTN Row;\r
1457 UINTN Column;\r
1458 TEXT_OUT_SPLITTER_QUERY_DATA *Mode;\r
1459\r
1460 //\r
1461 // No extra check for ModeNumber here, as it has been checked in\r
1462 // ConSplitterTextOutSetMode. And mode 0 should always be supported.\r
3012ce5c 1463 // Row and Column should be fetched from intersection map.\r
95276127 1464 //\r
3012ce5c 1465 if (Private->TextOutModeMap != NULL) {\r
1466 CurrentMode = *(Private->TextOutModeMap + Private->TextOutListCount * ModeNumber);\r
1467 } else {\r
1468 CurrentMode = (INT32)(ModeNumber);\r
1469 }\r
1470 Mode = &(Private->TextOutQueryData[CurrentMode]);\r
95276127 1471 Row = Mode->Rows;\r
1472 Column = Mode->Columns;\r
1473\r
1474 if (Row <= 0 && Column <= 0) {\r
1475 return EFI_UNSUPPORTED;\r
1476 }\r
1477\r
189eac21 1478 if (Private->TextOutMode.Mode != (INT32) ModeNumber) {\r
95276127 1479\r
1480 Private->TextOutMode.Mode = (INT32) ModeNumber;\r
1481 Private->DevNullColumns = Column;\r
1482 Private->DevNullRows = Row;\r
1483\r
1484 if (Private->DevNullScreen != NULL) {\r
1485 FreePool (Private->DevNullScreen);\r
1486 }\r
1487\r
1488 Size = (Row * (Column + 1)) * sizeof (CHAR16);\r
1489 Private->DevNullScreen = AllocateZeroPool (Size);\r
1490 if (Private->DevNullScreen == NULL) {\r
1491 return EFI_OUT_OF_RESOURCES;\r
1492 }\r
1493\r
1494 if (Private->DevNullAttributes != NULL) {\r
1495 FreePool (Private->DevNullAttributes);\r
1496 }\r
1497\r
1498 Size = Row * Column * sizeof (INT32);\r
1499 Private->DevNullAttributes = AllocateZeroPool (Size);\r
1500 if (Private->DevNullAttributes == NULL) {\r
1501 return EFI_OUT_OF_RESOURCES;\r
1502 }\r
1503 }\r
1504\r
1505 DevNullTextOutClearScreen (Private);\r
1506\r
1507 return EFI_SUCCESS;\r
1508}\r
1509\r
95276127 1510\r
a4d608d1 1511/**\r
1512 Clears the output device(s) display to the currently selected background\r
1513 color.\r
95276127 1514\r
a4d608d1 1515 @param Private Protocol instance pointer.\r
95276127 1516\r
a4d608d1 1517 @retval EFI_SUCCESS The operation completed successfully.\r
1518 @retval EFI_DEVICE_ERROR The device had an error and could not complete\r
1519 the request.\r
1520 @retval EFI_UNSUPPORTED The output device is not in a valid text mode.\r
95276127 1521\r
a4d608d1 1522**/\r
1523EFI_STATUS\r
1524DevNullTextOutClearScreen (\r
1525 IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private\r
1526 )\r
95276127 1527{\r
1528 UINTN Row;\r
1529 UINTN Column;\r
1530 CHAR16 *Screen;\r
1531 INT32 *Attributes;\r
1532 INT32 CurrentAttribute;\r
1533\r
1534 //\r
1535 // Clear the DevNull Text Out Buffers.\r
1536 // The screen is filled with spaces.\r
1537 // The attributes are all synced with the current Simple Text Out Attribute\r
1538 //\r
1539 Screen = Private->DevNullScreen;\r
1540 Attributes = Private->DevNullAttributes;\r
1541 CurrentAttribute = Private->TextOutMode.Attribute;\r
1542\r
1543 for (Row = 0; Row < Private->DevNullRows; Row++) {\r
1544 for (Column = 0; Column < Private->DevNullColumns; Column++, Screen++, Attributes++) {\r
4b5c4fba 1545 *Screen = L' ';\r
95276127 1546 *Attributes = CurrentAttribute;\r
1547 }\r
1548 //\r
1549 // Each line of the screen has a NULL on the end so we must skip over it\r
1550 //\r
1551 Screen++;\r
1552 }\r
1553\r
1554 DevNullTextOutSetCursorPosition (Private, 0, 0);\r
1555\r
1556 return DevNullTextOutEnableCursor (Private, TRUE);\r
1557}\r
1558\r
a4d608d1 1559\r
1560/**\r
1561 Sets the current coordinates of the cursor position.\r
1562\r
1563 @param Private Protocol instance pointer.\r
1564 @param Column \r
1565 @param Row the position to set the cursor to. Must be\r
1566 greater than or equal to zero and less than the\r
1567 number of columns and rows by QueryMode ().\r
1568\r
1569 @retval EFI_SUCCESS The operation completed successfully.\r
1570 @retval EFI_DEVICE_ERROR The device had an error and could not complete\r
1571 the request.\r
1572 @retval EFI_UNSUPPORTED The output device is not in a valid text mode, or\r
1573 the cursor position is invalid for the current\r
1574 mode.\r
1575\r
1576**/\r
95276127 1577EFI_STATUS\r
1578DevNullTextOutSetCursorPosition (\r
1579 IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private,\r
1580 IN UINTN Column,\r
1581 IN UINTN Row\r
1582 )\r
95276127 1583{\r
1584 //\r
1585 // No need to do extra check here as whether (Column, Row) is valid has\r
1586 // been checked in ConSplitterTextOutSetCursorPosition. And (0, 0) should\r
1587 // always be supported.\r
1588 //\r
1589 Private->TextOutMode.CursorColumn = (INT32) Column;\r
1590 Private->TextOutMode.CursorRow = (INT32) Row;\r
1591\r
1592 return EFI_SUCCESS;\r
1593}\r
1594\r
a4d608d1 1595\r
1596/**\r
1597 Implements SIMPLE_TEXT_OUTPUT.EnableCursor().\r
1598 In this driver, the cursor cannot be hidden.\r
1599\r
1600 @param Private Indicates the calling context.\r
1601 @param Visible If TRUE, the cursor is set to be visible, If\r
1602 FALSE, the cursor is set to be invisible.\r
1603\r
1604 @retval EFI_SUCCESS The request is valid.\r
1605\r
1606**/\r
95276127 1607EFI_STATUS\r
1608DevNullTextOutEnableCursor (\r
1609 IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private,\r
1610 IN BOOLEAN Visible\r
1611 )\r
95276127 1612{\r
1613 Private->TextOutMode.CursorVisible = Visible;\r
1614\r
1615 return EFI_SUCCESS;\r
1616}\r
1617\r
a4d608d1 1618\r
1619/**\r
1620 Take the DevNull TextOut device and update the Simple Text Out on every\r
1621 UGA device.\r
1622\r
1623 @param Private Indicates the calling context.\r
1624\r
1625 @retval EFI_SUCCESS The request is valid.\r
1626 @retval other Return status of TextOut->OutputString ()\r
1627\r
1628**/\r
95276127 1629EFI_STATUS\r
aec072ad 1630DevNullSyncStdOut (\r
95276127 1631 IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private\r
1632 )\r
95276127 1633{\r
1634 EFI_STATUS Status;\r
1635 EFI_STATUS ReturnStatus;\r
1636 UINTN Row;\r
1637 UINTN Column;\r
1638 UINTN List;\r
1639 UINTN MaxColumn;\r
1640 UINTN CurrentColumn;\r
1641 UINTN StartRow;\r
1642 UINTN StartColumn;\r
1643 INT32 StartAttribute;\r
1644 BOOLEAN StartCursorState;\r
1645 CHAR16 *Screen;\r
1646 CHAR16 *Str;\r
1647 CHAR16 *Buffer;\r
1648 CHAR16 *BufferTail;\r
1649 CHAR16 *ScreenStart;\r
1650 INT32 CurrentAttribute;\r
1651 INT32 *Attributes;\r
1652 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *Sto;\r
1653\r
1654 //\r
1655 // Save the devices Attributes, Cursor enable state and location\r
1656 //\r
1657 StartColumn = Private->TextOutMode.CursorColumn;\r
1658 StartRow = Private->TextOutMode.CursorRow;\r
1659 StartAttribute = Private->TextOutMode.Attribute;\r
1660 StartCursorState = Private->TextOutMode.CursorVisible;\r
1661\r
1662 for (List = 0; List < Private->CurrentNumberOfConsoles; List++) {\r
1663\r
1664 Sto = Private->TextOutList[List].TextOut;\r
1665\r
1666 //\r
1667 // Skip non GOP/UGA devices\r
1668 //\r
1669 if ((Private->TextOutList[List].GraphicsOutput != NULL) || (Private->TextOutList[List].UgaDraw != NULL)) {\r
1670 Sto->EnableCursor (Sto, FALSE);\r
1671 Sto->ClearScreen (Sto);\r
1672 }\r
1673 }\r
1674\r
1675 ReturnStatus = EFI_SUCCESS;\r
1676 Screen = Private->DevNullScreen;\r
1677 Attributes = Private->DevNullAttributes;\r
1678 MaxColumn = Private->DevNullColumns;\r
1679\r
1680 Buffer = AllocateZeroPool ((MaxColumn + 1) * sizeof (CHAR16));\r
cc79cef9 1681 if (Buffer == NULL) {\r
1682 return ReturnStatus;\r
1683 }\r
95276127 1684\r
1685 for (Row = 0; Row < Private->DevNullRows; Row++, Screen += (MaxColumn + 1), Attributes += MaxColumn) {\r
1686\r
1687 if (Row == (Private->DevNullRows - 1)) {\r
1688 //\r
1689 // Don't ever sync the last character as it will scroll the screen\r
1690 //\r
1691 Screen[MaxColumn - 1] = 0x00;\r
1692 }\r
1693\r
1694 Column = 0;\r
1695 while (Column < MaxColumn) {\r
a4d608d1 1696 if (Screen[Column] > 0) {\r
95276127 1697 CurrentAttribute = Attributes[Column];\r
1698 CurrentColumn = Column;\r
1699 ScreenStart = &Screen[Column];\r
1700\r
1701 //\r
1702 // the line end is alway 0x0. So Column should be less than MaxColumn\r
1703 // It should be still in the same row\r
1704 //\r
1705 for (Str = ScreenStart, BufferTail = Buffer; *Str != 0; Str++, Column++) {\r
1706\r
1707 if (Attributes[Column] != CurrentAttribute) {\r
1708 Column--;\r
1709 break;\r
1710 }\r
1711\r
1712 *BufferTail = *Str;\r
1713 BufferTail++;\r
a4d608d1 1714 if ((Attributes[Column] & EFI_WIDE_ATTRIBUTE) != 0) {\r
95276127 1715 Str++;\r
1716 Column++;\r
1717 }\r
1718 }\r
1719\r
1720 *BufferTail = 0;\r
1721\r
1722 for (List = 0; List < Private->CurrentNumberOfConsoles; List++) {\r
1723\r
1724 Sto = Private->TextOutList[List].TextOut;\r
1725\r
1726 //\r
1727 // Skip non GOP/UGA devices\r
1728 //\r
1729 if ((Private->TextOutList[List].GraphicsOutput != NULL) || (Private->TextOutList[List].UgaDraw != NULL)) {\r
1730 Sto->SetAttribute (Sto, CurrentAttribute);\r
1731 Sto->SetCursorPosition (Sto, CurrentColumn, Row);\r
1732 Status = Sto->OutputString (Sto, Buffer);\r
1733 if (EFI_ERROR (Status)) {\r
1734 ReturnStatus = Status;\r
1735 }\r
1736 }\r
1737 }\r
1738\r
1739 }\r
1740\r
1741 Column++;\r
1742 }\r
1743 }\r
1744 //\r
1745 // Restore the devices Attributes, Cursor enable state and location\r
1746 //\r
1747 for (List = 0; List < Private->CurrentNumberOfConsoles; List++) {\r
1748 Sto = Private->TextOutList[List].TextOut;\r
1749\r
1750 //\r
1751 // Skip non GOP/UGA devices\r
1752 //\r
1753 if ((Private->TextOutList[List].GraphicsOutput != NULL) || (Private->TextOutList[List].UgaDraw != NULL)) {\r
1754 Sto->SetAttribute (Sto, StartAttribute);\r
1755 Sto->SetCursorPosition (Sto, StartColumn, StartRow);\r
1756 Status = Sto->EnableCursor (Sto, StartCursorState);\r
1757 if (EFI_ERROR (Status)) {\r
1758 ReturnStatus = Status;\r
1759 }\r
1760 }\r
1761 }\r
1762\r
1763 FreePool (Buffer);\r
1764\r
1765 return ReturnStatus;\r
1766}\r