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