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