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