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