]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsole.c
1. Added USER_DEFINED support;
[mirror_edk2.git] / MdeModulePkg / Universal / Console / GraphicsConsoleDxe / GraphicsConsole.c
CommitLineData
95276127 1/**@file\r
2 This is the main routine for initializing the Graphics Console support routines.\r
3Remaining Tasks\r
4 Add all standard Glyphs from EFI 1.02 Specification\r
5 Implement optimal automatic Mode creation algorithm\r
6 Solve palette issues for mixed graphics and text\r
7 When does this protocol reset the palette?\r
8 \r
9Copyright (c) 2006 - 2007 Intel Corporation. <BR>\r
10All rights reserved. This program and the accompanying materials \r
11are licensed and made available under the terms and conditions of the BSD License \r
12which accompanies this distribution. The full text of the license may be found at \r
13http://opensource.org/licenses/bsd-license.php \r
14 \r
15THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
16WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
17\r
18**/\r
19\r
20//\r
21// Include common header file for this module.\r
22//\r
23#include "CommonHeader.h"\r
24\r
25#include "GraphicsConsole.h"\r
26\r
27STATIC\r
28EFI_STATUS\r
29GetTextColors (\r
30 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,\r
31 OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Foreground,\r
32 OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Background\r
33 );\r
34\r
35STATIC\r
36EFI_STATUS\r
37DrawUnicodeWeightAtCursorN (\r
38 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,\r
39 IN CHAR16 *UnicodeWeight,\r
40 IN UINTN Count\r
41 );\r
42\r
43STATIC\r
44EFI_STATUS\r
45EraseCursor (\r
46 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This\r
47 );\r
48\r
49//\r
50// Globals\r
51//\r
52GRAPHICS_CONSOLE_DEV mGraphicsConsoleDevTemplate = {\r
53 GRAPHICS_CONSOLE_DEV_SIGNATURE,\r
54 (EFI_GRAPHICS_OUTPUT_PROTOCOL *) NULL,\r
55 (EFI_UGA_DRAW_PROTOCOL *) NULL,\r
56 {\r
57 GraphicsConsoleConOutReset,\r
58 GraphicsConsoleConOutOutputString,\r
59 GraphicsConsoleConOutTestString,\r
60 GraphicsConsoleConOutQueryMode,\r
61 GraphicsConsoleConOutSetMode,\r
62 GraphicsConsoleConOutSetAttribute,\r
63 GraphicsConsoleConOutClearScreen,\r
64 GraphicsConsoleConOutSetCursorPosition,\r
65 GraphicsConsoleConOutEnableCursor,\r
66 (EFI_SIMPLE_TEXT_OUTPUT_MODE *) NULL\r
67 },\r
68 {\r
69 0,\r
70 0,\r
71 EFI_TEXT_ATTR(EFI_LIGHTGRAY, EFI_BLACK),\r
72 0,\r
73 0,\r
74 TRUE\r
75 },\r
76 {\r
77 { 80, 25, 0, 0, 0, 0 }, // Mode 0\r
78 { 80, 50, 0, 0, 0, 0 }, // Mode 1 \r
79 { 0, 0, 0, 0, 0, 0 } // Mode 2\r
80 },\r
81 (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) NULL,\r
82 (EFI_HII_HANDLE) 0\r
83};\r
84\r
85EFI_HII_PROTOCOL *mHii;\r
86\r
87static CHAR16 mCrLfString[3] = { CHAR_CARRIAGE_RETURN, CHAR_LINEFEED, CHAR_NULL };\r
88\r
89static EFI_GRAPHICS_OUTPUT_BLT_PIXEL mEfiColors[16] = {\r
90 //\r
91 // B G R\r
92 //\r
93 {0x00, 0x00, 0x00, 0x00}, // BLACK\r
94 {0x98, 0x00, 0x00, 0x00}, // BLUE\r
95 {0x00, 0x98, 0x00, 0x00}, // GREEN\r
96 {0x98, 0x98, 0x00, 0x00}, // CYAN\r
97 {0x00, 0x00, 0x98, 0x00}, // RED\r
98 {0x98, 0x00, 0x98, 0x00}, // MAGENTA\r
99 {0x00, 0x98, 0x98, 0x00}, // BROWN\r
100 {0x98, 0x98, 0x98, 0x00}, // LIGHTGRAY\r
101 {0x30, 0x30, 0x30, 0x00}, // DARKGRAY - BRIGHT BLACK\r
102 {0xff, 0x00, 0x00, 0x00}, // LIGHTBLUE - ?\r
103 {0x00, 0xff, 0x00, 0x00}, // LIGHTGREEN - ?\r
104 {0xff, 0xff, 0x00, 0x00}, // LIGHTCYAN\r
105 {0x00, 0x00, 0xff, 0x00}, // LIGHTRED\r
106 {0xff, 0x00, 0xff, 0x00}, // LIGHTMAGENTA\r
107 {0x00, 0xff, 0xff, 0x00}, // LIGHTBROWN\r
108 {0xff, 0xff, 0xff, 0x00} // WHITE\r
109};\r
110\r
111static EFI_NARROW_GLYPH mCursorGlyph = {\r
112 0x0000,\r
113 0x00,\r
114 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF }\r
115};\r
116\r
117EFI_DRIVER_BINDING_PROTOCOL gGraphicsConsoleDriverBinding = {\r
118 GraphicsConsoleControllerDriverSupported,\r
119 GraphicsConsoleControllerDriverStart,\r
120 GraphicsConsoleControllerDriverStop,\r
121 0xa,\r
122 NULL,\r
123 NULL\r
124};\r
125\r
126EFI_STATUS\r
127EFIAPI\r
128GraphicsConsoleControllerDriverSupported (\r
129 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
130 IN EFI_HANDLE Controller,\r
131 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
132 )\r
133{\r
134 EFI_STATUS Status;\r
135 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;\r
136 EFI_UGA_DRAW_PROTOCOL *UgaDraw;\r
137 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
138\r
139 UgaDraw = NULL;\r
140 //\r
141 // Open the IO Abstraction(s) needed to perform the supported test\r
142 //\r
143 Status = gBS->OpenProtocol (\r
144 Controller,\r
145 &gEfiGraphicsOutputProtocolGuid,\r
146 (VOID **) &GraphicsOutput,\r
147 This->DriverBindingHandle,\r
148 Controller,\r
149 EFI_OPEN_PROTOCOL_BY_DRIVER\r
150 );\r
151 \r
152 if (EFI_ERROR (Status)) {\r
153 GraphicsOutput = NULL;\r
154 //\r
155 // Open Graphics Output Protocol failed, try to open UGA Draw Protocol\r
156 //\r
157 Status = gBS->OpenProtocol (\r
158 Controller,\r
159 &gEfiUgaDrawProtocolGuid,\r
160 (VOID **) &UgaDraw,\r
161 This->DriverBindingHandle,\r
162 Controller,\r
163 EFI_OPEN_PROTOCOL_BY_DRIVER\r
164 );\r
165 if (EFI_ERROR (Status)) {\r
166 return Status;\r
167 }\r
168 }\r
169\r
170 //\r
171 // We need to ensure that we do not layer on top of a virtual handle.\r
172 // We need to ensure that the handles produced by the conspliter do not\r
173 // get used.\r
174 //\r
175 Status = gBS->OpenProtocol (\r
176 Controller,\r
177 &gEfiDevicePathProtocolGuid,\r
178 (VOID **) &DevicePath,\r
179 This->DriverBindingHandle,\r
180 Controller,\r
181 EFI_OPEN_PROTOCOL_BY_DRIVER\r
182 );\r
183 if (!EFI_ERROR (Status)) {\r
184 gBS->CloseProtocol (\r
185 Controller,\r
186 &gEfiDevicePathProtocolGuid,\r
187 This->DriverBindingHandle,\r
188 Controller\r
189 );\r
190 } else {\r
191 goto Error;\r
192 }\r
193 //\r
194 // Does Hii Exist? If not, we aren't ready to run\r
195 //\r
196 Status = EfiLocateHiiProtocol ();\r
197\r
198 //\r
199 // Close the I/O Abstraction(s) used to perform the supported test\r
200 //\r
201Error:\r
202 if (GraphicsOutput != NULL) {\r
203 gBS->CloseProtocol (\r
204 Controller,\r
205 &gEfiGraphicsOutputProtocolGuid,\r
206 This->DriverBindingHandle,\r
207 Controller\r
208 );\r
209 } else {\r
210 gBS->CloseProtocol (\r
211 Controller,\r
212 &gEfiUgaDrawProtocolGuid,\r
213 This->DriverBindingHandle,\r
214 Controller\r
215 );\r
216 }\r
217 return Status;\r
218}\r
219\r
220EFI_STATUS\r
221EFIAPI\r
222GraphicsConsoleControllerDriverStart (\r
223 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
224 IN EFI_HANDLE Controller,\r
225 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
226 )\r
227/*++\r
228\r
229 Routine Description:\r
230\r
231 Start the controller.\r
232\r
233 Arguments:\r
234\r
235 This - A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
236 Controller - The handle of the controller to start.\r
237 RemainingDevicePath - A pointer to the remaining portion of a devcie path.\r
238\r
239 Returns:\r
240\r
241 EFI_SUCCESS - Return successfully.\r
242 EFI_OUT_OF_RESOURCES - Out of resources.\r
243\r
244--*/\r
245{\r
246 EFI_STATUS Status;\r
247 GRAPHICS_CONSOLE_DEV *Private;\r
248 EFI_HII_PACKAGES *Package;\r
249 EFI_HII_FONT_PACK *FontPack;\r
250 UINTN NarrowFontSize;\r
251 UINT32 HorizontalResolution;\r
252 UINT32 VerticalResolution;\r
253 UINT32 ColorDepth;\r
254 UINT32 RefreshRate;\r
255 UINTN MaxMode;\r
256 UINTN Columns;\r
257 UINTN Rows;\r
258 UINT8 *Location;\r
259 UINT32 ModeNumber;\r
260 UINTN SizeOfInfo;\r
261 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info;\r
262 \r
263 ModeNumber = 0;\r
264\r
265 //\r
266 // Initialize the Graphics Console device instance\r
267 //\r
268 Private = AllocateCopyPool (\r
269 sizeof (GRAPHICS_CONSOLE_DEV),\r
270 &mGraphicsConsoleDevTemplate\r
271 );\r
272 if (Private == NULL) {\r
273 return EFI_OUT_OF_RESOURCES;\r
274 }\r
275\r
276 Private->SimpleTextOutput.Mode = &(Private->SimpleTextOutputMode);\r
277\r
278 Status = gBS->OpenProtocol (\r
279 Controller,\r
280 &gEfiGraphicsOutputProtocolGuid,\r
281 (VOID **) &Private->GraphicsOutput,\r
282 This->DriverBindingHandle,\r
283 Controller,\r
284 EFI_OPEN_PROTOCOL_BY_DRIVER\r
285 );\r
286 if (EFI_ERROR(Status)) {\r
287 Private->GraphicsOutput = NULL;\r
288\r
289 Status = gBS->OpenProtocol (\r
290 Controller,\r
291 &gEfiUgaDrawProtocolGuid,\r
292 (VOID **) &Private->UgaDraw,\r
293 This->DriverBindingHandle,\r
294 Controller,\r
295 EFI_OPEN_PROTOCOL_BY_DRIVER\r
296 );\r
297 if (EFI_ERROR (Status)) {\r
298 goto Error;\r
299 }\r
300 }\r
301\r
302 //\r
303 // Get the HII protocol. If Supported() succeeds, do we really\r
304 // need to get HII protocol again?\r
305 //\r
306 Status = EfiLocateHiiProtocol ();\r
307 if (EFI_ERROR (Status)) {\r
308 goto Error;\r
309 }\r
310\r
311 NarrowFontSize = ReturnNarrowFontSize ();\r
312\r
313 FontPack = AllocateZeroPool (sizeof (EFI_HII_FONT_PACK) + NarrowFontSize);\r
314 ASSERT (FontPack);\r
315\r
316 FontPack->Header.Length = (UINT32) (sizeof (EFI_HII_FONT_PACK) + NarrowFontSize);\r
317 FontPack->Header.Type = EFI_HII_FONT;\r
318 FontPack->NumberOfNarrowGlyphs = (UINT16) (NarrowFontSize / sizeof (EFI_NARROW_GLYPH));\r
319\r
320 Location = (UINT8 *) (&FontPack->NumberOfWideGlyphs + sizeof (UINT8));\r
321 CopyMem (Location, UsStdNarrowGlyphData, NarrowFontSize);\r
322\r
323 //\r
324 // Register our Fonts into the global database\r
325 //\r
326 Package = PreparePackages (1, NULL, FontPack);\r
327 mHii->NewPack (mHii, Package, &(Private->HiiHandle));\r
328 FreePool (Package);\r
329\r
330 //\r
331 // Free the font database\r
332 //\r
333 FreePool (FontPack);\r
334\r
335 //\r
336 // If the current mode information can not be retrieved, then attemp to set the default mode\r
337 // of 800x600, 32 bit colot, 60 Hz refresh.\r
338 //\r
339 HorizontalResolution = 800;\r
340 VerticalResolution = 600;\r
341\r
342 if (Private->GraphicsOutput != NULL) {\r
343 //\r
344 // The console is build on top of Graphics Output Protocol, find the mode number for 800x600\r
345 //\r
346 for (ModeNumber = 0; ModeNumber < Private->GraphicsOutput->Mode->MaxMode; ModeNumber++) {\r
347 Status = Private->GraphicsOutput->QueryMode (\r
348 Private->GraphicsOutput,\r
349 ModeNumber,\r
350 &SizeOfInfo,\r
351 &Info\r
352 );\r
353 if (!EFI_ERROR (Status)) {\r
354 if ((Info->HorizontalResolution == 800) &&\r
355 (Info->VerticalResolution == 600)) {\r
356 Status = Private->GraphicsOutput->SetMode (Private->GraphicsOutput, ModeNumber);\r
357 if (!EFI_ERROR (Status)) {\r
358 FreePool (Info);\r
359 break;\r
360 }\r
361 }\r
362 FreePool (Info);\r
363 }\r
364 }\r
365\r
366 if (EFI_ERROR (Status) || (ModeNumber == Private->GraphicsOutput->Mode->MaxMode)) {\r
367 //\r
368 // Set default mode failed or device don't support default mode, then get the current mode information\r
369 //\r
370 HorizontalResolution = Private->GraphicsOutput->Mode->Info->HorizontalResolution;\r
371 VerticalResolution = Private->GraphicsOutput->Mode->Info->VerticalResolution;\r
372 ModeNumber = Private->GraphicsOutput->Mode->Mode;\r
373 }\r
374 } else {\r
375 //\r
376 // The console is build on top of UGA Draw Protocol\r
377 //\r
378 ColorDepth = 32;\r
379 RefreshRate = 60;\r
380 Status = Private->UgaDraw->SetMode (\r
381 Private->UgaDraw,\r
382 HorizontalResolution,\r
383 VerticalResolution,\r
384 ColorDepth,\r
385 RefreshRate\r
386 );\r
387 if (EFI_ERROR (Status)) {\r
388 //\r
389 // Get the current mode information from the UGA Draw Protocol\r
390 //\r
391 Status = Private->UgaDraw->GetMode (\r
392 Private->UgaDraw,\r
393 &HorizontalResolution,\r
394 &VerticalResolution,\r
395 &ColorDepth,\r
396 &RefreshRate\r
397 );\r
398 if (EFI_ERROR (Status)) {\r
399 goto Error;\r
400 }\r
401 }\r
402 }\r
403\r
404 //\r
405 // Compute the maximum number of text Rows and Columns that this current graphics mode can support\r
406 //\r
407 Columns = HorizontalResolution / GLYPH_WIDTH;\r
408 Rows = VerticalResolution / GLYPH_HEIGHT;\r
409\r
410 //\r
411 // See if the mode is too small to support the required 80x25 text mode\r
412 //\r
413 if (Columns < 80 || Rows < 25) {\r
414 goto Error;\r
415 }\r
416 //\r
417 // Add Mode #0 that must be 80x25\r
418 //\r
419 MaxMode = 0;\r
420 Private->ModeData[MaxMode].GopWidth = HorizontalResolution;\r
421 Private->ModeData[MaxMode].GopHeight = VerticalResolution;\r
422 Private->ModeData[MaxMode].GopModeNumber = ModeNumber;\r
423 Private->ModeData[MaxMode].DeltaX = (HorizontalResolution - (80 * GLYPH_WIDTH)) >> 1;\r
424 Private->ModeData[MaxMode].DeltaY = (VerticalResolution - (25 * GLYPH_HEIGHT)) >> 1;\r
425 MaxMode++;\r
426\r
427 //\r
428 // If it is possible to support Mode #1 - 80x50, than add it as an active mode\r
429 //\r
430 if (Rows >= 50) {\r
431 Private->ModeData[MaxMode].GopWidth = HorizontalResolution;\r
432 Private->ModeData[MaxMode].GopHeight = VerticalResolution;\r
433 Private->ModeData[MaxMode].GopModeNumber = ModeNumber;\r
434 Private->ModeData[MaxMode].DeltaX = (HorizontalResolution - (80 * GLYPH_WIDTH)) >> 1;\r
435 Private->ModeData[MaxMode].DeltaY = (VerticalResolution - (50 * GLYPH_HEIGHT)) >> 1;\r
436 MaxMode++;\r
437 }\r
438 //\r
439 // If the graphics mode is 800x600, than add a text mode that uses the entire display\r
440 //\r
441 if (HorizontalResolution == 800 && VerticalResolution == 600) {\r
442\r
443 if (MaxMode < 2) {\r
444 Private->ModeData[MaxMode].Columns = 0;\r
445 Private->ModeData[MaxMode].Rows = 0;\r
446 Private->ModeData[MaxMode].GopWidth = 800;\r
447 Private->ModeData[MaxMode].GopHeight = 600;\r
448 Private->ModeData[MaxMode].GopModeNumber = ModeNumber;\r
449 Private->ModeData[MaxMode].DeltaX = 0;\r
450 Private->ModeData[MaxMode].DeltaY = 0;\r
451 MaxMode++;\r
452 }\r
453\r
454 Private->ModeData[MaxMode].Columns = 800 / GLYPH_WIDTH;\r
455 Private->ModeData[MaxMode].Rows = 600 / GLYPH_HEIGHT;\r
456 Private->ModeData[MaxMode].GopWidth = 800;\r
457 Private->ModeData[MaxMode].GopHeight = 600;\r
458 Private->ModeData[MaxMode].GopModeNumber = ModeNumber;\r
459 Private->ModeData[MaxMode].DeltaX = (800 % GLYPH_WIDTH) >> 1;\r
460 Private->ModeData[MaxMode].DeltaY = (600 % GLYPH_HEIGHT) >> 1;\r
461 MaxMode++;\r
462 }\r
463 //\r
464 // Update the maximum number of modes\r
465 //\r
466 Private->SimpleTextOutputMode.MaxMode = (INT32) MaxMode;\r
467\r
468 //\r
469 // Determine the number of text modes that this protocol can support\r
470 //\r
471 Status = GraphicsConsoleConOutSetMode (&Private->SimpleTextOutput, 0);\r
472 if (EFI_ERROR (Status)) {\r
473 goto Error;\r
474 }\r
475\r
476 DEBUG_CODE_BEGIN ();\r
477 GraphicsConsoleConOutOutputString (&Private->SimpleTextOutput, (CHAR16 *)L"Graphics Console Started\n\r");\r
478 DEBUG_CODE_END ();\r
479\r
480 //\r
481 // Install protocol interfaces for the Graphics Console device.\r
482 //\r
483 Status = gBS->InstallMultipleProtocolInterfaces (\r
484 &Controller,\r
485 &gEfiSimpleTextOutProtocolGuid,\r
486 &Private->SimpleTextOutput,\r
487 NULL\r
488 );\r
489\r
490Error:\r
491 if (EFI_ERROR (Status)) {\r
492 //\r
493 // Close the GOP or UGA IO Protocol\r
494 //\r
495 if (Private->GraphicsOutput != NULL) {\r
496 gBS->CloseProtocol (\r
497 Controller,\r
498 &gEfiGraphicsOutputProtocolGuid,\r
499 This->DriverBindingHandle,\r
500 Controller\r
501 );\r
502 } else {\r
503 gBS->CloseProtocol (\r
504 Controller,\r
505 &gEfiUgaDrawProtocolGuid,\r
506 This->DriverBindingHandle,\r
507 Controller\r
508 );\r
509 }\r
510\r
511 //\r
512 // Free private data\r
513 //\r
514 if (Private != NULL) {\r
515 if (Private->LineBuffer != NULL) {\r
516 FreePool (Private->LineBuffer);\r
517 }\r
518 FreePool (Private);\r
519 }\r
520 }\r
521\r
522 return Status;\r
523}\r
524\r
525EFI_STATUS\r
526EFIAPI\r
527GraphicsConsoleControllerDriverStop (\r
528 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
529 IN EFI_HANDLE Controller,\r
530 IN UINTN NumberOfChildren,\r
531 IN EFI_HANDLE *ChildHandleBuffer\r
532 )\r
533{\r
534 EFI_STATUS Status;\r
535 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *SimpleTextOutput;\r
536 GRAPHICS_CONSOLE_DEV *Private;\r
537\r
538 Status = gBS->OpenProtocol (\r
539 Controller,\r
540 &gEfiSimpleTextOutProtocolGuid,\r
541 (VOID **) &SimpleTextOutput,\r
542 This->DriverBindingHandle,\r
543 Controller,\r
544 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
545 );\r
546 if (EFI_ERROR (Status)) {\r
547 return EFI_NOT_STARTED;\r
548 }\r
549\r
550 Private = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (SimpleTextOutput);\r
551\r
552 Status = gBS->UninstallProtocolInterface (\r
553 Controller,\r
554 &gEfiSimpleTextOutProtocolGuid,\r
555 &Private->SimpleTextOutput\r
556 );\r
557\r
558 if (!EFI_ERROR (Status)) {\r
559 //\r
560 // Close the GOP or UGA IO Protocol\r
561 //\r
562 if (Private->GraphicsOutput != NULL) {\r
563 gBS->CloseProtocol (\r
564 Controller,\r
565 &gEfiGraphicsOutputProtocolGuid,\r
566 This->DriverBindingHandle,\r
567 Controller\r
568 );\r
569 } else {\r
570 gBS->CloseProtocol (\r
571 Controller,\r
572 &gEfiUgaDrawProtocolGuid,\r
573 This->DriverBindingHandle,\r
574 Controller\r
575 );\r
576 }\r
577\r
578 //\r
579 // Remove the font pack\r
580 //\r
581 mHii->RemovePack (mHii, Private->HiiHandle);\r
582\r
583 //\r
584 // Free our instance data\r
585 //\r
586 if (Private != NULL) {\r
587 FreePool (Private->LineBuffer);\r
588 FreePool (Private);\r
589 }\r
590 }\r
591\r
592 return Status;\r
593}\r
594\r
595EFI_STATUS\r
596EfiLocateHiiProtocol (\r
597 VOID\r
598 )\r
599/*++\r
600\r
601 Routine Description:\r
602 Find if the HII protocol is available. If yes, locate the HII protocol\r
603\r
604 Arguments:\r
605\r
606 Returns:\r
607\r
608--*/\r
609{\r
610 EFI_HANDLE Handle;\r
611 UINTN Size;\r
612 EFI_STATUS Status;\r
613\r
614 //\r
615 // There should only be one - so buffer size is this\r
616 //\r
617 Size = sizeof (EFI_HANDLE);\r
618\r
619 Status = gBS->LocateHandle (\r
620 ByProtocol,\r
621 &gEfiHiiProtocolGuid,\r
622 NULL,\r
623 &Size,\r
624 &Handle\r
625 );\r
626\r
627 if (EFI_ERROR (Status)) {\r
628 return Status;\r
629 }\r
630\r
631 Status = gBS->HandleProtocol (\r
632 Handle,\r
633 &gEfiHiiProtocolGuid,\r
634 (VOID **)&mHii\r
635 );\r
636\r
637 return Status;\r
638}\r
639//\r
640// Body of the STO functions\r
641//\r
642EFI_STATUS\r
643EFIAPI\r
644GraphicsConsoleConOutReset (\r
645 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,\r
646 IN BOOLEAN ExtendedVerification\r
647 )\r
648/*++\r
649 Routine Description:\r
650 \r
651 Implements SIMPLE_TEXT_OUTPUT.Reset().\r
652 If ExtendeVerification is TRUE, then perform dependent Graphics Console \r
653 device reset, and set display mode to mode 0.\r
654 If ExtendedVerification is FALSE, only set display mode to mode 0.\r
655 \r
656 Arguments:\r
657 \r
658 This - Indicates the calling context.\r
659 \r
660 ExtendedVerification - Indicates that the driver may perform a more exhaustive\r
661 verification operation of the device during reset.\r
662 \r
663 Returns:\r
664 \r
665 EFI_SUCCESS\r
666 The reset operation succeeds. \r
667 \r
668 EFI_DEVICE_ERROR\r
669 The Graphics Console is not functioning correctly \r
670 \r
671--*/\r
672{\r
673 This->SetAttribute (This, EFI_TEXT_ATTR (This->Mode->Attribute & 0x0F, EFI_BACKGROUND_BLACK));\r
674 return This->SetMode (This, 0);\r
675}\r
676\r
677EFI_STATUS\r
678EFIAPI\r
679GraphicsConsoleConOutOutputString (\r
680 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,\r
681 IN CHAR16 *WString\r
682 )\r
683/*++\r
684 Routine Description:\r
685 \r
686 Implements SIMPLE_TEXT_OUTPUT.OutputString().\r
687 The Unicode string will be converted to Glyphs and will be \r
688 sent to the Graphics Console.\r
689 \r
690 \r
691 Arguments:\r
692 \r
693 This - Indicates the calling context.\r
694 \r
695 WString - The Null-terminated Unicode string to be displayed on \r
696 the Graphics Console.\r
697 \r
698 Returns:\r
699 \r
700 EFI_SUCCESS\r
701 The string is output successfully. \r
702 \r
703 EFI_DEVICE_ERROR\r
704 The Graphics Console failed to send the string out.\r
705 \r
706 EFI_WARN_UNKNOWN_GLYPH\r
707 Indicates that some of the characters in the Unicode string could not \r
708 be rendered and are skipped. \r
709 \r
710--*/\r
711{\r
712 GRAPHICS_CONSOLE_DEV *Private;\r
713 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;\r
714 EFI_UGA_DRAW_PROTOCOL *UgaDraw;\r
715 INTN Mode;\r
716 UINTN MaxColumn;\r
717 UINTN MaxRow;\r
718 UINTN Width;\r
719 UINTN Height;\r
720 UINTN Delta;\r
721 EFI_STATUS Status;\r
722 BOOLEAN Warning;\r
723 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground;\r
724 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background;\r
725 UINTN DeltaX;\r
726 UINTN DeltaY;\r
727 UINTN Count;\r
728 UINTN Index;\r
729 INT32 OriginAttribute;\r
730 EFI_TPL OldTpl;\r
731 CHAR16 SpaceStr[] = { NARROW_CHAR, ' ', 0 };\r
732\r
733 Status = EFI_SUCCESS;\r
734\r
735 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
736 //\r
737 // Current mode\r
738 //\r
739 Mode = This->Mode->Mode;\r
740 Private = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This);\r
741 GraphicsOutput = Private->GraphicsOutput;\r
742 UgaDraw = Private->UgaDraw;\r
743\r
744 MaxColumn = Private->ModeData[Mode].Columns;\r
745 MaxRow = Private->ModeData[Mode].Rows;\r
746 DeltaX = Private->ModeData[Mode].DeltaX;\r
747 DeltaY = Private->ModeData[Mode].DeltaY;\r
748 Width = MaxColumn * GLYPH_WIDTH;\r
749 Height = (MaxRow - 1) * GLYPH_HEIGHT;\r
750 Delta = Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);\r
751\r
752 //\r
753 // The Attributes won't change when during the time OutputString is called\r
754 //\r
755 GetTextColors (This, &Foreground, &Background);\r
756\r
757 EraseCursor (This);\r
758\r
759 Warning = FALSE;\r
760\r
761 //\r
762 // Backup attribute\r
763 //\r
764 OriginAttribute = This->Mode->Attribute;\r
765\r
766 while (*WString) {\r
767\r
768 if (*WString == CHAR_BACKSPACE) {\r
769 //\r
770 // If the cursor is at the left edge of the display, then move the cursor\r
771 // one row up.\r
772 //\r
773 if (This->Mode->CursorColumn == 0 && This->Mode->CursorRow > 0) {\r
774 This->Mode->CursorRow--;\r
775 This->Mode->CursorColumn = (INT32) (MaxColumn - 1);\r
776 This->OutputString (This, SpaceStr);\r
777 EraseCursor (This);\r
778 This->Mode->CursorRow--;\r
779 This->Mode->CursorColumn = (INT32) (MaxColumn - 1);\r
780 } else if (This->Mode->CursorColumn > 0) {\r
781 //\r
782 // If the cursor is not at the left edge of the display, then move the cursor\r
783 // left one column.\r
784 //\r
785 This->Mode->CursorColumn--;\r
786 This->OutputString (This, SpaceStr);\r
787 EraseCursor (This);\r
788 This->Mode->CursorColumn--;\r
789 }\r
790\r
791 WString++;\r
792\r
793 } else if (*WString == CHAR_LINEFEED) {\r
794 //\r
795 // If the cursor is at the bottom of the display, then scroll the display one\r
796 // row, and do not update the cursor position. Otherwise, move the cursor\r
797 // down one row.\r
798 //\r
799 if (This->Mode->CursorRow == (INT32) (MaxRow - 1)) {\r
800 if (GraphicsOutput != NULL) {\r
801 //\r
802 // Scroll Screen Up One Row\r
803 //\r
804 GraphicsOutput->Blt (\r
805 GraphicsOutput,\r
806 NULL,\r
807 EfiBltVideoToVideo,\r
808 DeltaX,\r
809 DeltaY + GLYPH_HEIGHT,\r
810 DeltaX,\r
811 DeltaY,\r
812 Width,\r
813 Height,\r
814 Delta\r
815 );\r
816\r
817 //\r
818 // Print Blank Line at last line\r
819 //\r
820 GraphicsOutput->Blt (\r
821 GraphicsOutput,\r
822 &Background,\r
823 EfiBltVideoFill,\r
824 0,\r
825 0,\r
826 DeltaX,\r
827 DeltaY + Height,\r
828 Width,\r
829 GLYPH_HEIGHT,\r
830 Delta\r
831 );\r
832 } else {\r
833 //\r
834 // Scroll Screen Up One Row\r
835 //\r
836 UgaDraw->Blt (\r
837 UgaDraw,\r
838 NULL,\r
839 EfiUgaVideoToVideo,\r
840 DeltaX,\r
841 DeltaY + GLYPH_HEIGHT,\r
842 DeltaX,\r
843 DeltaY,\r
844 Width,\r
845 Height,\r
846 Delta\r
847 );\r
848\r
849 //\r
850 // Print Blank Line at last line\r
851 //\r
852 UgaDraw->Blt (\r
853 UgaDraw,\r
854 (EFI_UGA_PIXEL *) (UINTN) &Background,\r
855 EfiUgaVideoFill,\r
856 0,\r
857 0,\r
858 DeltaX,\r
859 DeltaY + Height,\r
860 Width,\r
861 GLYPH_HEIGHT,\r
862 Delta\r
863 );\r
864 }\r
865 } else {\r
866 This->Mode->CursorRow++;\r
867 }\r
868\r
869 WString++;\r
870\r
871 } else if (*WString == CHAR_CARRIAGE_RETURN) {\r
872 //\r
873 // Move the cursor to the beginning of the current row.\r
874 //\r
875 This->Mode->CursorColumn = 0;\r
876 WString++;\r
877\r
878 } else if (*WString == WIDE_CHAR) {\r
879\r
880 This->Mode->Attribute |= EFI_WIDE_ATTRIBUTE;\r
881 WString++;\r
882\r
883 } else if (*WString == NARROW_CHAR) {\r
884\r
885 This->Mode->Attribute &= (~ (UINT32) EFI_WIDE_ATTRIBUTE);\r
886 WString++;\r
887\r
888 } else {\r
889 //\r
890 // Print the character at the current cursor position and move the cursor\r
891 // right one column. If this moves the cursor past the right edge of the\r
892 // display, then the line should wrap to the beginning of the next line. This\r
893 // is equivalent to inserting a CR and an LF. Note that if the cursor is at the\r
894 // bottom of the display, and the line wraps, then the display will be scrolled\r
895 // one line.\r
896 // If wide char is going to be displayed, need to display one character at a time\r
897 // Or, need to know the display length of a certain string.\r
898 //\r
899 // Index is used to determine how many character width units (wide = 2, narrow = 1)\r
900 // Count is used to determine how many characters are used regardless of their attributes\r
901 //\r
902 for (Count = 0, Index = 0; (This->Mode->CursorColumn + Index) < MaxColumn; Count++, Index++) {\r
903 if (WString[Count] == CHAR_NULL) {\r
904 break;\r
905 }\r
906\r
907 if (WString[Count] == CHAR_BACKSPACE) {\r
908 break;\r
909 }\r
910\r
911 if (WString[Count] == CHAR_LINEFEED) {\r
912 break;\r
913 }\r
914\r
915 if (WString[Count] == CHAR_CARRIAGE_RETURN) {\r
916 break;\r
917 }\r
918\r
919 if (WString[Count] == WIDE_CHAR) {\r
920 break;\r
921 }\r
922\r
923 if (WString[Count] == NARROW_CHAR) {\r
924 break;\r
925 }\r
926 //\r
927 // Is the wide attribute on?\r
928 //\r
929 if (This->Mode->Attribute & EFI_WIDE_ATTRIBUTE) {\r
930 //\r
931 // If wide, add one more width unit than normal since we are going to increment at the end of the for loop\r
932 //\r
933 Index++;\r
934 //\r
935 // This is the end-case where if we are at column 79 and about to print a wide character\r
936 // We should prevent this from happening because we will wrap inappropriately. We should\r
937 // not print this character until the next line.\r
938 //\r
939 if ((This->Mode->CursorColumn + Index + 1) > MaxColumn) {\r
940 Index++;\r
941 break;\r
942 }\r
943 }\r
944 }\r
945\r
946 Status = DrawUnicodeWeightAtCursorN (This, WString, Count);\r
947 if (EFI_ERROR (Status)) {\r
948 Warning = TRUE;\r
949 }\r
950 //\r
951 // At the end of line, output carriage return and line feed\r
952 //\r
953 WString += Count;\r
954 This->Mode->CursorColumn += (INT32) Index;\r
955 if (This->Mode->CursorColumn > (INT32) MaxColumn) {\r
956 This->Mode->CursorColumn -= 2;\r
957 This->OutputString (This, SpaceStr);\r
958 }\r
959\r
960 if (This->Mode->CursorColumn >= (INT32) MaxColumn) {\r
961 EraseCursor (This);\r
962 This->OutputString (This, mCrLfString);\r
963 EraseCursor (This);\r
964 }\r
965 }\r
966 }\r
967\r
968 This->Mode->Attribute = OriginAttribute;\r
969\r
970 EraseCursor (This);\r
971\r
972 if (Warning) {\r
973 Status = EFI_WARN_UNKNOWN_GLYPH;\r
974 }\r
975\r
976 gBS->RestoreTPL (OldTpl);\r
977 return Status;\r
978\r
979}\r
980\r
981EFI_STATUS\r
982EFIAPI\r
983GraphicsConsoleConOutTestString (\r
984 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,\r
985 IN CHAR16 *WString\r
986 )\r
987/*++\r
988 Routine Description:\r
989 \r
990 Implements SIMPLE_TEXT_OUTPUT.TestString().\r
991 If one of the characters in the *Wstring is\r
992 neither valid valid Unicode drawing characters,\r
993 not ASCII code, then this function will return\r
994 EFI_UNSUPPORTED.\r
995 \r
996 \r
997 Arguments:\r
998 \r
999 This - Indicates the calling context.\r
1000 \r
1001 WString - The Null-terminated Unicode string to be tested.\r
1002 \r
1003 Returns:\r
1004 \r
1005 EFI_SUCCESS\r
1006 The Graphics Console is capable of rendering the output string. \r
1007 \r
1008 EFI_UNSUPPORTED\r
1009 Some of the characters in the Unicode string cannot be rendered. \r
1010 \r
1011--*/\r
1012{\r
1013 EFI_STATUS Status;\r
1014 UINT16 GlyphWidth;\r
1015 UINT32 GlyphStatus;\r
1016 UINT16 Count;\r
1017 GLYPH_UNION *Glyph;\r
1018\r
1019 GlyphStatus = 0;\r
1020 Count = 0;\r
1021\r
1022 while (WString[Count]) {\r
1023 Status = mHii->GetGlyph (\r
1024 mHii,\r
1025 WString,\r
1026 &Count,\r
1027 (UINT8 **) &Glyph,\r
1028 &GlyphWidth,\r
1029 &GlyphStatus\r
1030 );\r
1031\r
1032 if (EFI_ERROR (Status)) {\r
1033 return EFI_UNSUPPORTED;\r
1034 }\r
1035 }\r
1036\r
1037 return EFI_SUCCESS;\r
1038}\r
1039\r
1040EFI_STATUS\r
1041EFIAPI\r
1042GraphicsConsoleConOutQueryMode (\r
1043 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,\r
1044 IN UINTN ModeNumber,\r
1045 OUT UINTN *Columns,\r
1046 OUT UINTN *Rows\r
1047 )\r
1048/*++\r
1049 Routine Description:\r
1050 \r
1051 Implements SIMPLE_TEXT_OUTPUT.QueryMode().\r
1052 It returnes information for an available text mode\r
1053 that the Graphics Console supports.\r
1054 In this driver,we only support text mode 80x25, which is\r
1055 defined as mode 0.\r
1056 \r
1057 \r
1058 Arguments:\r
1059 \r
1060 This - Indicates the calling context.\r
1061 \r
1062 ModeNumber - The mode number to return information on.\r
1063 \r
1064 Columns - The returned columns of the requested mode.\r
1065 \r
1066 Rows - The returned rows of the requested mode. \r
1067 \r
1068 Returns:\r
1069 \r
1070 EFI_SUCCESS\r
1071 The requested mode information is returned. \r
1072 \r
1073 EFI_UNSUPPORTED\r
1074 The mode number is not valid. \r
1075 \r
1076--*/\r
1077{\r
1078 GRAPHICS_CONSOLE_DEV *Private;\r
1079 EFI_STATUS Status;\r
1080 EFI_TPL OldTpl;\r
1081\r
1082 if (ModeNumber >= (UINTN) This->Mode->MaxMode) {\r
1083 return EFI_UNSUPPORTED;\r
1084 }\r
1085\r
1086 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
1087 Status = EFI_SUCCESS;\r
1088 \r
1089 Private = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This);\r
1090\r
1091 *Columns = Private->ModeData[ModeNumber].Columns;\r
1092 *Rows = Private->ModeData[ModeNumber].Rows;\r
1093\r
1094 if (*Columns <= 0 && *Rows <= 0) {\r
1095 Status = EFI_UNSUPPORTED;\r
1096 goto Done;\r
1097\r
1098 }\r
1099\r
1100Done:\r
1101 gBS->RestoreTPL (OldTpl);\r
1102 return Status;\r
1103}\r
1104\r
1105EFI_STATUS\r
1106EFIAPI\r
1107GraphicsConsoleConOutSetMode (\r
1108 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,\r
1109 IN UINTN ModeNumber\r
1110 )\r
1111/*++\r
1112 Routine Description:\r
1113 \r
1114 Implements SIMPLE_TEXT_OUTPUT.SetMode().\r
1115 Set the Graphics Console to a specified mode.\r
1116 In this driver, we only support mode 0. \r
1117 \r
1118 Arguments:\r
1119 \r
1120 This - Indicates the calling context.\r
1121 \r
1122 ModeNumber - The text mode to set.\r
1123 \r
1124 Returns:\r
1125 \r
1126 EFI_SUCCESS\r
1127 The requested text mode is set.\r
1128 \r
1129 EFI_DEVICE_ERROR\r
1130 The requested text mode cannot be set because of Graphics Console device error.\r
1131 \r
1132 EFI_UNSUPPORTED\r
1133 The text mode number is not valid. \r
1134 \r
1135--*/\r
1136{\r
1137 EFI_STATUS Status;\r
1138 GRAPHICS_CONSOLE_DEV *Private;\r
1139 GRAPHICS_CONSOLE_MODE_DATA *ModeData;\r
1140 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *NewLineBuffer;\r
1141 UINT32 HorizontalResolution;\r
1142 UINT32 VerticalResolution;\r
1143 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;\r
1144 EFI_UGA_DRAW_PROTOCOL *UgaDraw;\r
1145 UINT32 ColorDepth;\r
1146 UINT32 RefreshRate;\r
1147 EFI_TPL OldTpl;\r
1148\r
1149 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
1150\r
1151 Private = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This);\r
1152 GraphicsOutput = Private->GraphicsOutput;\r
1153 UgaDraw = Private->UgaDraw;\r
1154 ModeData = &(Private->ModeData[ModeNumber]);\r
1155\r
1156 if (ModeData->Columns <= 0 && ModeData->Rows <= 0) {\r
1157 Status = EFI_UNSUPPORTED;\r
1158 goto Done;\r
1159 }\r
1160\r
1161 //\r
1162 // Make sure the requested mode number is supported\r
1163 //\r
1164 if (ModeNumber >= (UINTN) This->Mode->MaxMode) {\r
1165 Status = EFI_UNSUPPORTED;\r
1166 goto Done;\r
1167 }\r
1168\r
1169 if (ModeData->Columns <= 0 && ModeData->Rows <= 0) {\r
1170 Status = EFI_UNSUPPORTED;\r
1171 goto Done;\r
1172 }\r
1173 //\r
1174 // Attempt to allocate a line buffer for the requested mode number\r
1175 //\r
1176 NewLineBuffer = AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) * ModeData->Columns * GLYPH_WIDTH * GLYPH_HEIGHT);\r
1177\r
1178 if (NewLineBuffer == NULL) {\r
1179 //\r
1180 // The new line buffer could not be allocated, so return an error.\r
1181 // No changes to the state of the current console have been made, so the current console is still valid\r
1182 //\r
1183 Status = EFI_OUT_OF_RESOURCES;\r
1184 goto Done;\r
1185 }\r
1186 //\r
1187 // If the mode has been set at least one other time, then LineBuffer will not be NULL\r
1188 //\r
1189 if (Private->LineBuffer != NULL) {\r
1190 //\r
1191 // Clear the current text window on the current graphics console\r
1192 //\r
1193 This->ClearScreen (This);\r
1194\r
1195 //\r
1196 // If the new mode is the same as the old mode, then just return EFI_SUCCESS\r
1197 //\r
1198 if ((INT32) ModeNumber == This->Mode->Mode) {\r
1199 FreePool (NewLineBuffer);\r
1200 Status = EFI_SUCCESS;\r
1201 goto Done;\r
1202 }\r
1203 //\r
1204 // Otherwise, the size of the text console and/or the UGA mode will be changed,\r
1205 // so turn off the cursor, and free the LineBuffer for the current mode\r
1206 //\r
1207 This->EnableCursor (This, FALSE);\r
1208\r
1209 FreePool (Private->LineBuffer);\r
1210 }\r
1211 //\r
1212 // Assign the current line buffer to the newly allocated line buffer\r
1213 //\r
1214 Private->LineBuffer = NewLineBuffer;\r
1215\r
1216 if (GraphicsOutput != NULL) {\r
1217 if (ModeData->GopModeNumber != GraphicsOutput->Mode->Mode) {\r
1218 //\r
1219 // Either no graphics mode is currently set, or it is set to the wrong resolution, so set the new grapghics mode\r
1220 //\r
1221 Status = GraphicsOutput->SetMode (GraphicsOutput, ModeData->GopModeNumber);\r
1222 if (EFI_ERROR (Status)) {\r
1223 //\r
1224 // The mode set operation failed\r
1225 //\r
1226 goto Done;\r
1227 }\r
1228 } else {\r
1229 //\r
1230 // The current graphics mode is correct, so simply clear the entire display\r
1231 //\r
1232 Status = GraphicsOutput->Blt (\r
1233 GraphicsOutput,\r
1234 &mEfiColors[0],\r
1235 EfiBltVideoFill,\r
1236 0,\r
1237 0,\r
1238 0,\r
1239 0,\r
1240 ModeData->GopWidth,\r
1241 ModeData->GopHeight,\r
1242 0\r
1243 );\r
1244 }\r
1245 } else {\r
1246 //\r
1247 // Get the current UGA Draw mode information\r
1248 //\r
1249 Status = UgaDraw->GetMode (\r
1250 UgaDraw,\r
1251 &HorizontalResolution,\r
1252 &VerticalResolution,\r
1253 &ColorDepth,\r
1254 &RefreshRate\r
1255 );\r
1256 if (EFI_ERROR (Status) || HorizontalResolution != ModeData->GopWidth || VerticalResolution != ModeData->GopHeight) {\r
1257 //\r
1258 // Either no graphics mode is currently set, or it is set to the wrong resolution, so set the new grapghics mode\r
1259 //\r
1260 Status = UgaDraw->SetMode (\r
1261 UgaDraw,\r
1262 ModeData->GopWidth,\r
1263 ModeData->GopHeight,\r
1264 32,\r
1265 60\r
1266 );\r
1267 if (EFI_ERROR (Status)) {\r
1268 //\r
1269 // The mode set operation failed\r
1270 //\r
1271 goto Done;\r
1272 }\r
1273 } else {\r
1274 //\r
1275 // The current graphics mode is correct, so simply clear the entire display\r
1276 //\r
1277 Status = UgaDraw->Blt (\r
1278 UgaDraw,\r
1279 (EFI_UGA_PIXEL *) (UINTN) &mEfiColors[0],\r
1280 EfiUgaVideoFill,\r
1281 0,\r
1282 0,\r
1283 0,\r
1284 0,\r
1285 ModeData->GopWidth,\r
1286 ModeData->GopHeight,\r
1287 0\r
1288 );\r
1289 }\r
1290 }\r
1291\r
1292 //\r
1293 // The new mode is valid, so commit the mode change\r
1294 //\r
1295 This->Mode->Mode = (INT32) ModeNumber;\r
1296\r
1297 //\r
1298 // Move the text cursor to the upper left hand corner of the displat and enable it\r
1299 //\r
1300 This->SetCursorPosition (This, 0, 0);\r
1301 This->EnableCursor (This, TRUE);\r
1302\r
1303 Status = EFI_SUCCESS;\r
1304\r
1305Done:\r
1306 gBS->RestoreTPL (OldTpl);\r
1307 return Status;\r
1308}\r
1309\r
1310EFI_STATUS\r
1311EFIAPI\r
1312GraphicsConsoleConOutSetAttribute (\r
1313 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,\r
1314 IN UINTN Attribute\r
1315 )\r
1316/*++\r
1317 Routine Description:\r
1318 \r
1319 Implements SIMPLE_TEXT_OUTPUT.SetAttribute(). \r
1320 \r
1321 Arguments:\r
1322 \r
1323 This - Indicates the calling context.\r
1324 \r
1325 Attrubute - The attribute to set. Only bit0..6 are valid, all other bits\r
1326 are undefined and must be zero.\r
1327 \r
1328 Returns:\r
1329 \r
1330 EFI_SUCCESS\r
1331 The requested attribute is set. \r
1332 \r
1333 EFI_DEVICE_ERROR\r
1334 The requested attribute cannot be set due to Graphics Console port error.\r
1335 \r
1336 EFI_UNSUPPORTED\r
1337 The attribute requested is not defined by EFI spec. \r
1338 \r
1339--*/\r
1340{\r
1341 EFI_TPL OldTpl;\r
1342 \r
1343 if ((Attribute | 0xFF) != 0xFF) {\r
1344 return EFI_UNSUPPORTED;\r
1345 }\r
1346\r
1347 if ((INT32) Attribute == This->Mode->Attribute) {\r
1348 return EFI_SUCCESS;\r
1349 }\r
1350\r
1351 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
1352\r
1353 EraseCursor (This);\r
1354\r
1355 This->Mode->Attribute = (INT32) Attribute;\r
1356\r
1357 EraseCursor (This);\r
1358\r
1359 gBS->RestoreTPL (OldTpl);\r
1360\r
1361 return EFI_SUCCESS;\r
1362}\r
1363\r
1364EFI_STATUS\r
1365EFIAPI\r
1366GraphicsConsoleConOutClearScreen (\r
1367 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This\r
1368 )\r
1369/*++\r
1370 Routine Description:\r
1371 \r
1372 Implements SIMPLE_TEXT_OUTPUT.ClearScreen().\r
1373 It clears the Graphics Console's display to the \r
1374 currently selected background color.\r
1375 \r
1376 \r
1377 Arguments:\r
1378 \r
1379 This - Indicates the calling context.\r
1380\r
1381 Returns:\r
1382 \r
1383 EFI_SUCCESS\r
1384 The operation completed successfully.\r
1385 \r
1386 EFI_DEVICE_ERROR\r
1387 The Graphics Console cannot be cleared due to Graphics Console device error. \r
1388 \r
1389 EFI_UNSUPPORTED\r
1390 The Graphics Console is not in a valid text mode. \r
1391 \r
1392--*/\r
1393{\r
1394 EFI_STATUS Status;\r
1395 GRAPHICS_CONSOLE_DEV *Private;\r
1396 GRAPHICS_CONSOLE_MODE_DATA *ModeData;\r
1397 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;\r
1398 EFI_UGA_DRAW_PROTOCOL *UgaDraw;\r
1399 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground;\r
1400 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background;\r
1401 EFI_TPL OldTpl;\r
1402\r
1403 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
1404\r
1405 Private = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This);\r
1406 GraphicsOutput = Private->GraphicsOutput;\r
1407 UgaDraw = Private->UgaDraw;\r
1408 ModeData = &(Private->ModeData[This->Mode->Mode]);\r
1409\r
1410 GetTextColors (This, &Foreground, &Background);\r
1411 if (GraphicsOutput != NULL) {\r
1412 Status = GraphicsOutput->Blt (\r
1413 GraphicsOutput,\r
1414 &Background,\r
1415 EfiBltVideoFill,\r
1416 0,\r
1417 0,\r
1418 0,\r
1419 0,\r
1420 ModeData->GopWidth,\r
1421 ModeData->GopHeight,\r
1422 0\r
1423 );\r
1424 } else {\r
1425 Status = UgaDraw->Blt (\r
1426 UgaDraw,\r
1427 (EFI_UGA_PIXEL *) (UINTN) &Background,\r
1428 EfiUgaVideoFill,\r
1429 0,\r
1430 0,\r
1431 0,\r
1432 0,\r
1433 ModeData->GopWidth,\r
1434 ModeData->GopHeight,\r
1435 0\r
1436 );\r
1437 }\r
1438\r
1439 This->Mode->CursorColumn = 0;\r
1440 This->Mode->CursorRow = 0;\r
1441\r
1442 EraseCursor (This);\r
1443\r
1444 gBS->RestoreTPL (OldTpl);\r
1445\r
1446 return Status;\r
1447}\r
1448\r
1449EFI_STATUS\r
1450EFIAPI\r
1451GraphicsConsoleConOutSetCursorPosition (\r
1452 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,\r
1453 IN UINTN Column,\r
1454 IN UINTN Row\r
1455 )\r
1456/*++\r
1457 Routine Description:\r
1458 \r
1459 Implements SIMPLE_TEXT_OUTPUT.SetCursorPosition(). \r
1460 \r
1461 Arguments:\r
1462 \r
1463 This - Indicates the calling context.\r
1464 \r
1465 Column - The row to set cursor to.\r
1466 \r
1467 Row - The column to set cursor to. \r
1468\r
1469 Returns:\r
1470 \r
1471 EFI_SUCCESS\r
1472 The operation completed successfully.\r
1473 \r
1474 EFI_DEVICE_ERROR\r
1475 The request fails due to Graphics Console device error. \r
1476 \r
1477 EFI_UNSUPPORTED\r
1478 The Graphics Console is not in a valid text mode, or the cursor position\r
1479 is invalid for current mode. \r
1480 \r
1481--*/\r
1482{\r
1483 GRAPHICS_CONSOLE_DEV *Private;\r
1484 GRAPHICS_CONSOLE_MODE_DATA *ModeData;\r
1485 EFI_STATUS Status;\r
1486 EFI_TPL OldTpl;\r
1487\r
1488 Status = EFI_SUCCESS;\r
1489\r
1490 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
1491\r
1492 Private = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This);\r
1493 ModeData = &(Private->ModeData[This->Mode->Mode]);\r
1494\r
1495 if ((Column >= ModeData->Columns) || (Row >= ModeData->Rows)) {\r
1496 Status = EFI_UNSUPPORTED;\r
1497 goto Done;\r
1498 }\r
1499\r
1500 if (((INT32) Column == This->Mode->CursorColumn) && ((INT32) Row == This->Mode->CursorRow)) {\r
1501 Status = EFI_SUCCESS;\r
1502 goto Done;\r
1503 }\r
1504\r
1505 EraseCursor (This);\r
1506\r
1507 This->Mode->CursorColumn = (INT32) Column;\r
1508 This->Mode->CursorRow = (INT32) Row;\r
1509\r
1510 EraseCursor (This);\r
1511\r
1512Done:\r
1513 gBS->RestoreTPL (OldTpl);\r
1514\r
1515 return Status;\r
1516}\r
1517\r
1518EFI_STATUS\r
1519EFIAPI\r
1520GraphicsConsoleConOutEnableCursor (\r
1521 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,\r
1522 IN BOOLEAN Visible\r
1523 )\r
1524/*++\r
1525 Routine Description:\r
1526 \r
1527 Implements SIMPLE_TEXT_OUTPUT.EnableCursor().\r
1528 In this driver, the cursor cannot be hidden. \r
1529 \r
1530 Arguments:\r
1531 \r
1532 This - Indicates the calling context.\r
1533 \r
1534 Visible - If TRUE, the cursor is set to be visible,\r
1535 If FALSE, the cursor is set to be invisible. \r
1536\r
1537 Returns:\r
1538 \r
1539 EFI_SUCCESS\r
1540 The request is valid.\r
1541 \r
1542 EFI_UNSUPPORTED\r
1543 The Graphics Console does not support a hidden cursor. \r
1544 \r
1545--*/\r
1546{\r
1547 EFI_TPL OldTpl;\r
1548 \r
1549 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
1550 \r
1551 EraseCursor (This);\r
1552\r
1553 This->Mode->CursorVisible = Visible;\r
1554\r
1555 EraseCursor (This);\r
1556\r
1557 gBS->RestoreTPL (OldTpl);\r
1558 return EFI_SUCCESS;\r
1559}\r
1560\r
1561STATIC\r
1562EFI_STATUS\r
1563GetTextColors (\r
1564 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,\r
1565 OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Foreground,\r
1566 OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Background\r
1567 )\r
1568{\r
1569 INTN Attribute;\r
1570\r
1571 Attribute = This->Mode->Attribute & 0x7F;\r
1572\r
1573 *Foreground = mEfiColors[Attribute & 0x0f];\r
1574 *Background = mEfiColors[Attribute >> 4];\r
1575\r
1576 return EFI_SUCCESS;\r
1577}\r
1578\r
1579STATIC\r
1580EFI_STATUS\r
1581DrawUnicodeWeightAtCursorN (\r
1582 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,\r
1583 IN CHAR16 *UnicodeWeight,\r
1584 IN UINTN Count\r
1585 )\r
1586{\r
1587 GRAPHICS_CONSOLE_DEV *Private;\r
1588 EFI_STATUS Status;\r
1589 EFI_STATUS ReturnStatus;\r
1590 GLYPH_UNION *Glyph;\r
1591 GLYPH_UNION GlyphData;\r
1592 INTN GlyphX;\r
1593 INTN GlyphY;\r
1594 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;\r
1595 EFI_UGA_DRAW_PROTOCOL *UgaDraw;\r
1596 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground;\r
1597 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background;\r
1598 UINTN Index;\r
1599 UINTN ArrayIndex;\r
1600 UINTN Counts;\r
1601 UINT16 GlyphWidth;\r
1602 UINT32 GlyphStatus;\r
1603\r
1604 Private = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This);\r
1605\r
1606 ReturnStatus = EFI_SUCCESS;\r
1607 GlyphStatus = 0;\r
1608 GlyphWidth = 0x08;\r
1609\r
1610 GetTextColors (This, &Foreground, &Background);\r
1611\r
1612 Index = 0;\r
1613 ArrayIndex = 0;\r
1614 while (Index < Count) {\r
1615 if (This->Mode->Attribute & EFI_WIDE_ATTRIBUTE) {\r
1616 GlyphStatus = WIDE_CHAR;\r
1617 } else {\r
1618 GlyphStatus = NARROW_CHAR;\r
1619 }\r
1620\r
1621 Status = mHii->GetGlyph (\r
1622 mHii,\r
1623 UnicodeWeight,\r
1624 (UINT16 *) &Index,\r
1625 (UINT8 **) &Glyph,\r
1626 &GlyphWidth,\r
1627 &GlyphStatus\r
1628 );\r
1629 if (EFI_ERROR (Status)) {\r
1630 ReturnStatus = Status;\r
1631 }\r
1632\r
1633 Counts = 0;\r
1634\r
1635 CopyMem (&GlyphData, Glyph, sizeof (GLYPH_UNION));\r
1636\r
1637 do {\r
1638 //\r
1639 // We are creating the second half of the wide character's BLT buffer\r
1640 //\r
1641 if (GlyphWidth == 0x10 && Counts == 1) {\r
1642 CopyMem (&GlyphData.NarrowGlyph.GlyphCol1, &Glyph->WideGlyph.GlyphCol2, sizeof (Glyph->WideGlyph.GlyphCol2));\r
1643 }\r
1644\r
1645 Counts++;\r
1646\r
1647 if (GlyphWidth == 0x10) {\r
1648 mHii->GlyphToBlt (\r
1649 mHii,\r
1650 (UINT8 *) &GlyphData,\r
1651 Foreground,\r
1652 Background,\r
1653 Count * 2,\r
1654 GLYPH_WIDTH,\r
1655 GLYPH_HEIGHT,\r
1656 &Private->LineBuffer[ArrayIndex * GLYPH_WIDTH]\r
1657 );\r
1658 } else {\r
1659 mHii->GlyphToBlt (\r
1660 mHii,\r
1661 (UINT8 *) &GlyphData,\r
1662 Foreground,\r
1663 Background,\r
1664 Count,\r
1665 GLYPH_WIDTH,\r
1666 GLYPH_HEIGHT,\r
1667 &Private->LineBuffer[ArrayIndex * GLYPH_WIDTH]\r
1668 );\r
1669 }\r
1670\r
1671 ArrayIndex++;\r
1672\r
1673 } while (Counts < 2 && GlyphWidth == 0x10);\r
1674\r
1675 }\r
1676 //\r
1677 // If we are printing Wide characters, treat the BLT as if it is twice as many characters\r
1678 //\r
1679 if (GlyphWidth == 0x10) {\r
1680 Count = Count * 2;\r
1681 }\r
1682 //\r
1683 // Blt a character to the screen\r
1684 //\r
1685 GlyphX = This->Mode->CursorColumn * GLYPH_WIDTH;\r
1686 GlyphY = This->Mode->CursorRow * GLYPH_HEIGHT;\r
1687 GraphicsOutput = Private->GraphicsOutput;\r
1688 UgaDraw = Private->UgaDraw;\r
1689 if (GraphicsOutput != NULL) {\r
1690 GraphicsOutput->Blt (\r
1691 GraphicsOutput,\r
1692 Private->LineBuffer,\r
1693 EfiBltBufferToVideo,\r
1694 0,\r
1695 0,\r
1696 GlyphX + Private->ModeData[This->Mode->Mode].DeltaX,\r
1697 GlyphY + Private->ModeData[This->Mode->Mode].DeltaY,\r
1698 GLYPH_WIDTH * Count,\r
1699 GLYPH_HEIGHT,\r
1700 GLYPH_WIDTH * Count * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)\r
1701 );\r
1702 } else {\r
1703 UgaDraw->Blt (\r
1704 UgaDraw,\r
1705 (EFI_UGA_PIXEL *) (UINTN) Private->LineBuffer,\r
1706 EfiUgaBltBufferToVideo,\r
1707 0,\r
1708 0,\r
1709 GlyphX + Private->ModeData[This->Mode->Mode].DeltaX,\r
1710 GlyphY + Private->ModeData[This->Mode->Mode].DeltaY,\r
1711 GLYPH_WIDTH * Count,\r
1712 GLYPH_HEIGHT,\r
1713 GLYPH_WIDTH * Count * sizeof (EFI_UGA_PIXEL)\r
1714 );\r
1715 }\r
1716\r
1717 return ReturnStatus;\r
1718}\r
1719\r
1720STATIC\r
1721EFI_STATUS\r
1722EraseCursor (\r
1723 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This\r
1724 )\r
1725{\r
1726 GRAPHICS_CONSOLE_DEV *Private;\r
1727 EFI_SIMPLE_TEXT_OUTPUT_MODE *CurrentMode;\r
1728 INTN GlyphX;\r
1729 INTN GlyphY;\r
1730 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;\r
1731 EFI_UGA_DRAW_PROTOCOL *UgaDraw;\r
1732 EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION Foreground;\r
1733 EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION Background;\r
1734 EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION BltChar[GLYPH_HEIGHT][GLYPH_WIDTH];\r
1735 UINTN X;\r
1736 UINTN Y;\r
1737\r
1738 CurrentMode = This->Mode;\r
1739\r
1740 if (!CurrentMode->CursorVisible) {\r
1741 return EFI_SUCCESS;\r
1742 }\r
1743\r
1744 Private = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This);\r
1745 GraphicsOutput = Private->GraphicsOutput;\r
1746 UgaDraw = Private->UgaDraw;\r
1747\r
1748 //\r
1749 // BUGBUG - we need to think about what to do with wide and narrow character deletions.\r
1750 //\r
1751 //\r
1752 // Blt a character to the screen\r
1753 //\r
1754 GlyphX = (CurrentMode->CursorColumn * GLYPH_WIDTH) + Private->ModeData[CurrentMode->Mode].DeltaX;\r
1755 GlyphY = (CurrentMode->CursorRow * GLYPH_HEIGHT) + Private->ModeData[CurrentMode->Mode].DeltaY;\r
1756 if (GraphicsOutput != NULL) {\r
1757 GraphicsOutput->Blt (\r
1758 GraphicsOutput,\r
1759 (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) BltChar,\r
1760 EfiBltVideoToBltBuffer,\r
1761 GlyphX,\r
1762 GlyphY,\r
1763 0,\r
1764 0,\r
1765 GLYPH_WIDTH,\r
1766 GLYPH_HEIGHT,\r
1767 GLYPH_WIDTH * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)\r
1768 );\r
1769 } else {\r
1770 UgaDraw->Blt (\r
1771 UgaDraw,\r
1772 (EFI_UGA_PIXEL *) (UINTN) BltChar,\r
1773 EfiUgaVideoToBltBuffer,\r
1774 GlyphX,\r
1775 GlyphY,\r
1776 0,\r
1777 0,\r
1778 GLYPH_WIDTH,\r
1779 GLYPH_HEIGHT,\r
1780 GLYPH_WIDTH * sizeof (EFI_UGA_PIXEL)\r
1781 );\r
1782 }\r
1783\r
1784 GetTextColors (This, &Foreground.Pixel, &Background.Pixel);\r
1785\r
1786 //\r
1787 // Convert Monochrome bitmap of the Glyph to BltBuffer structure\r
1788 //\r
1789 for (Y = 0; Y < GLYPH_HEIGHT; Y++) {\r
1790 for (X = 0; X < GLYPH_WIDTH; X++) {\r
1791 if ((mCursorGlyph.GlyphCol1[Y] & (1 << X)) != 0) {\r
1792 BltChar[Y][GLYPH_WIDTH - X - 1].Raw ^= Foreground.Raw;\r
1793 }\r
1794 }\r
1795 }\r
1796\r
1797 if (GraphicsOutput != NULL) {\r
1798 GraphicsOutput->Blt (\r
1799 GraphicsOutput,\r
1800 (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) BltChar,\r
1801 EfiBltBufferToVideo,\r
1802 0,\r
1803 0,\r
1804 GlyphX,\r
1805 GlyphY,\r
1806 GLYPH_WIDTH,\r
1807 GLYPH_HEIGHT,\r
1808 GLYPH_WIDTH * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)\r
1809 );\r
1810 } else {\r
1811 UgaDraw->Blt (\r
1812 UgaDraw,\r
1813 (EFI_UGA_PIXEL *) (UINTN) BltChar,\r
1814 EfiUgaBltBufferToVideo,\r
1815 0,\r
1816 0,\r
1817 GlyphX,\r
1818 GlyphY,\r
1819 GLYPH_WIDTH,\r
1820 GLYPH_HEIGHT,\r
1821 GLYPH_WIDTH * sizeof (EFI_UGA_PIXEL)\r
1822 );\r
1823 }\r
1824\r
1825 return EFI_SUCCESS;\r
1826}\r