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