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