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