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