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