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