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