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