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