]> git.proxmox.com Git - mirror_edk2.git/blame - DuetPkg/BiosVideoThunkDxe/BiosVideo.c
Update BiosVideo driver to produce GOP protocol but not UgaDraw protocol which is...
[mirror_edk2.git] / DuetPkg / BiosVideoThunkDxe / BiosVideo.c
CommitLineData
7da78b1f 1/*++\r
2\r
3Copyright (c) 2006 - 2008, 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 BiosVideo.c\r
0d92cdc2 15\r
7da78b1f 16Abstract:\r
17\r
18 ConsoleOut Routines that speak VGA.\r
19\r
20Revision History\r
21\r
22--*/\r
23\r
24#include "BiosVideo.h"\r
25\r
7da78b1f 26//\r
27// EFI Driver Binding Protocol Instance\r
28//\r
29EFI_DRIVER_BINDING_PROTOCOL gBiosVideoDriverBinding = {\r
30 BiosVideoDriverBindingSupported,\r
31 BiosVideoDriverBindingStart,\r
32 BiosVideoDriverBindingStop,\r
33 0x3,\r
34 NULL,\r
35 NULL\r
36};\r
37\r
38//\r
39// Global lookup tables for VGA graphics modes\r
40//\r
41UINT8 mVgaLeftMaskTable[] = { 0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01 };\r
42\r
43UINT8 mVgaRightMaskTable[] = { 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff };\r
44\r
45UINT8 mVgaBitMaskTable[] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };\r
46\r
0d92cdc2 47EFI_GRAPHICS_OUTPUT_BLT_PIXEL mVgaColorToGraphicsOutputColor[] = {\r
7da78b1f 48 {\r
49 0x00,\r
50 0x00,\r
51 0x00,\r
52 0x00\r
53 },\r
54 {\r
55 0x98,\r
56 0x00,\r
57 0x00,\r
58 0x00\r
59 },\r
60 {\r
61 0x00,\r
62 0x98,\r
63 0x00,\r
64 0x00\r
65 },\r
66 {\r
67 0x98,\r
68 0x98,\r
69 0x00,\r
70 0x00\r
71 },\r
72 {\r
73 0x00,\r
74 0x00,\r
75 0x98,\r
76 0x00\r
77 },\r
78 {\r
79 0x98,\r
80 0x00,\r
81 0x98,\r
82 0x00\r
83 },\r
84 {\r
85 0x00,\r
86 0x98,\r
87 0x98,\r
88 0x00\r
89 },\r
90 {\r
91 0x98,\r
92 0x98,\r
93 0x98,\r
94 0x00\r
95 },\r
96 {\r
97 0x10,\r
98 0x10,\r
99 0x10,\r
100 0x00\r
101 },\r
102 {\r
103 0xff,\r
104 0x10,\r
105 0x10,\r
106 0x00\r
107 },\r
108 {\r
109 0x10,\r
110 0xff,\r
111 0x10,\r
112 0x00\r
113 },\r
114 {\r
115 0xff,\r
116 0xff,\r
117 0x10,\r
118 0x00\r
119 },\r
120 {\r
121 0x10,\r
122 0x10,\r
123 0xff,\r
124 0x00\r
125 },\r
126 {\r
127 0xf0,\r
128 0x10,\r
129 0xff,\r
130 0x00\r
131 },\r
132 {\r
133 0x10,\r
134 0xff,\r
135 0xff,\r
136 0x00\r
137 },\r
138 {\r
139 0xff,\r
140 0xff,\r
141 0xff,\r
142 0x00\r
143 }\r
144};\r
145\r
0d92cdc2 146//\r
147// Standard timing defined by VESA EDID\r
148//\r
149VESA_BIOS_EXTENSIONS_EDID_TIMING mEstablishedEdidTiming[] = {\r
150 //\r
151 // Established Timing I\r
152 //\r
153 {800, 600, 60},\r
154 {800, 600, 56},\r
155 {640, 480, 75},\r
156 {640, 480, 72},\r
157 {640, 480, 67},\r
158 {640, 480, 60},\r
159 {720, 400, 88},\r
160 {720, 400, 70},\r
161 //\r
162 // Established Timing II\r
163 //\r
164 {1280, 1024, 75},\r
165 {1024, 768, 75},\r
166 {1024, 768, 70},\r
167 {1024, 768, 60},\r
168 {1024, 768, 87},\r
169 {832, 624, 75},\r
170 {800, 600, 75},\r
171 {800, 600, 72},\r
172 //\r
173 // Established Timing III\r
174 //\r
175 {1152, 870, 75}\r
176};\r
177\r
178EFI_STATUS\r
179BiosVideoChildHandleInstall (\r
180 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
181 IN EFI_HANDLE ParentHandle,\r
182 IN EFI_PCI_IO_PROTOCOL *ParentPciIo,\r
183 IN EFI_LEGACY_8259_PROTOCOL *ParentLegacy8259,\r
184 IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath,\r
185 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
186 )\r
187;\r
188\r
189EFI_STATUS\r
190BiosVideoChildHandleUninstall (\r
191 EFI_DRIVER_BINDING_PROTOCOL *This,\r
192 EFI_HANDLE Controller,\r
193 EFI_HANDLE Handle\r
194 )\r
195;\r
196\r
7da78b1f 197VOID\r
0d92cdc2 198BiosVideoDeviceReleaseResource (\r
199 BIOS_VIDEO_DEV *BiosVideoPrivate\r
200 )\r
201;\r
202\r
7da78b1f 203EFI_STATUS\r
204EFIAPI\r
205BiosVideoDriverEntryPoint (\r
206 IN EFI_HANDLE ImageHandle,\r
207 IN EFI_SYSTEM_TABLE *SystemTable\r
208 )\r
209/*++\r
0d92cdc2 210\r
7da78b1f 211 Routine Description:\r
0d92cdc2 212\r
7da78b1f 213 Driver Entry Point.\r
0d92cdc2 214\r
7da78b1f 215 Arguments:\r
0d92cdc2 216\r
7da78b1f 217 ImageHandle - Handle of driver image.\r
218 SystemTable - Pointer to system table.\r
0d92cdc2 219\r
7da78b1f 220 Returns:\r
0d92cdc2 221\r
7da78b1f 222 EFI_STATUS\r
0d92cdc2 223\r
7da78b1f 224--*/\r
225{\r
226 EFI_STATUS Status;\r
227\r
228 Status = EfiLibInstallDriverBindingComponentName2 (\r
229 ImageHandle,\r
230 SystemTable,\r
231 &gBiosVideoDriverBinding,\r
232 ImageHandle,\r
233 &gBiosVideoComponentName,\r
234 &gBiosVideoComponentName2\r
235 );\r
0d92cdc2 236 \r
7da78b1f 237 return Status;\r
238}\r
239\r
240VOID\r
241EFIAPI\r
242BiosVideoExitBootServices (\r
243 EFI_EVENT Event,\r
244 VOID *Context\r
245 )\r
246/*++\r
247\r
248Routine Description:\r
249\r
250 Callback function for exit boot service event\r
251\r
252Arguments:\r
253\r
254 Event - EFI_EVENT structure\r
255 Context - Event context\r
256\r
257Returns:\r
258\r
259 None\r
260\r
261--*/\r
262{\r
263/*\r
264 BIOS_VIDEO_DEV *BiosVideoPrivate;\r
265 EFI_IA32_REGISTER_SET Regs;\r
266\r
267 //\r
268 // Get our context\r
269 //\r
270 BiosVideoPrivate = (BIOS_VIDEO_DEV *) Context;\r
271\r
272 //\r
273 // Set the 80x25 Text VGA Mode\r
274 //\r
275 Regs.H.AH = 0x00;\r
276 Regs.H.AL = 0x83;\r
277 BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);\r
278\r
279 Regs.H.AH = 0x11;\r
280 Regs.H.AL = 0x14;\r
281 Regs.H.BL = 0;\r
282 BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);\r
283*/\r
284}\r
285\r
286EFI_STATUS\r
287EFIAPI\r
288BiosVideoDriverBindingSupported (\r
289 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
290 IN EFI_HANDLE Controller,\r
291 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
292 )\r
293/*++\r
0d92cdc2 294\r
7da78b1f 295 Routine Description:\r
296\r
297 Supported.\r
0d92cdc2 298\r
7da78b1f 299 Arguments:\r
300\r
301 This - Pointer to driver binding protocol\r
302 Controller - Controller handle to connect\r
303 RemainingDevicePath - A pointer to the remaining portion of a device path\r
0d92cdc2 304\r
305\r
7da78b1f 306 Returns:\r
307\r
308 EFI_STATUS - EFI_SUCCESS:This controller can be managed by this driver,\r
309 Otherwise, this controller cannot be managed by this driver\r
0d92cdc2 310\r
7da78b1f 311--*/\r
312{\r
0d92cdc2 313 EFI_STATUS Status;\r
314 EFI_LEGACY_8259_PROTOCOL *LegacyBios;\r
315 EFI_PCI_IO_PROTOCOL *PciIo;\r
7da78b1f 316\r
317 //\r
0d92cdc2 318 // See if the Legacy 8259 Protocol is available\r
7da78b1f 319 //\r
0d92cdc2 320 Status = gBS->LocateProtocol (&gEfiLegacy8259ProtocolGuid, NULL, (VOID **) &LegacyBios);\r
7da78b1f 321 if (EFI_ERROR (Status)) {\r
322 return Status;\r
323 }\r
0d92cdc2 324 \r
7da78b1f 325 //\r
326 // Open the IO Abstraction(s) needed to perform the supported test\r
327 //\r
328 Status = gBS->OpenProtocol (\r
329 Controller,\r
330 &gEfiPciIoProtocolGuid,\r
331 (VOID **) &PciIo,\r
332 This->DriverBindingHandle,\r
333 Controller,\r
334 EFI_OPEN_PROTOCOL_BY_DRIVER\r
335 );\r
336 if (EFI_ERROR (Status)) {\r
7da78b1f 337 return Status;\r
338 }\r
0d92cdc2 339\r
7da78b1f 340 if (!BiosVideoIsVga (PciIo)) {\r
7da78b1f 341 Status = EFI_UNSUPPORTED;\r
342 }\r
343\r
344 gBS->CloseProtocol (\r
0d92cdc2 345 Controller,\r
346 &gEfiPciIoProtocolGuid,\r
347 This->DriverBindingHandle,\r
348 Controller\r
349 );\r
7da78b1f 350\r
351 return Status;\r
352}\r
353\r
354EFI_STATUS\r
355EFIAPI\r
356BiosVideoDriverBindingStart (\r
357 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
358 IN EFI_HANDLE Controller,\r
359 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
360 )\r
361/*++\r
0d92cdc2 362\r
7da78b1f 363 Routine Description:\r
364\r
0d92cdc2 365 Install Graphics Output Protocol onto VGA device handles\r
366\r
7da78b1f 367 Arguments:\r
368\r
369 This - Pointer to driver binding protocol\r
370 Controller - Controller handle to connect\r
371 RemainingDevicePath - A pointer to the remaining portion of a device path\r
0d92cdc2 372\r
7da78b1f 373 Returns:\r
374\r
375 EFI_STATUS\r
0d92cdc2 376\r
7da78b1f 377--*/\r
378{\r
0d92cdc2 379 EFI_STATUS Status;\r
380 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r
381 EFI_PCI_IO_PROTOCOL *PciIo;\r
382 EFI_LEGACY_8259_PROTOCOL *Legacy8259;\r
7da78b1f 383\r
0d92cdc2 384 PciIo = NULL;\r
7da78b1f 385 //\r
0d92cdc2 386 // Prepare for status code\r
7da78b1f 387 //\r
0d92cdc2 388 Status = gBS->HandleProtocol (\r
389 Controller,\r
390 &gEfiDevicePathProtocolGuid,\r
391 (VOID **) &ParentDevicePath\r
392 );\r
393 if (EFI_ERROR (Status)) {\r
394 goto Done;\r
395 }\r
7da78b1f 396\r
397 //\r
0d92cdc2 398 // Open the IO Abstraction(s) needed\r
7da78b1f 399 //\r
0d92cdc2 400 Status = gBS->OpenProtocol (\r
401 Controller,\r
402 &gEfiPciIoProtocolGuid,\r
403 (VOID **) &PciIo,\r
404 This->DriverBindingHandle,\r
405 Controller,\r
406 EFI_OPEN_PROTOCOL_BY_DRIVER\r
7da78b1f 407 );\r
408 if (EFI_ERROR (Status)) {\r
409 goto Done;\r
410 }\r
411\r
7da78b1f 412 //\r
413 // See if the Legacy BIOS Protocol is available\r
414 //\r
0d92cdc2 415 Status = gBS->LocateProtocol (&gEfiLegacy8259ProtocolGuid, NULL, (VOID **) &Legacy8259);\r
7da78b1f 416 if (EFI_ERROR (Status)) {\r
417 goto Done;\r
418 }\r
0d92cdc2 419\r
420\r
7da78b1f 421 //\r
0d92cdc2 422 // Create child handle and install GraphicsOutputProtocol on it\r
7da78b1f 423 //\r
0d92cdc2 424 Status = BiosVideoChildHandleInstall (\r
425 This,\r
426 Controller,\r
427 PciIo,\r
428 Legacy8259,\r
429 ParentDevicePath,\r
430 RemainingDevicePath\r
431 );\r
432\r
433Done:\r
7da78b1f 434 if (EFI_ERROR (Status)) {\r
0d92cdc2 435 if (PciIo != NULL) {\r
436 //\r
437 // Release PCI I/O Protocols on the controller handle.\r
438 //\r
439 gBS->CloseProtocol (\r
440 Controller,\r
441 &gEfiPciIoProtocolGuid,\r
442 This->DriverBindingHandle,\r
443 Controller\r
444 );\r
445 }\r
7da78b1f 446 }\r
0d92cdc2 447\r
448 return Status;\r
449}\r
450\r
451EFI_STATUS\r
452EFIAPI\r
453BiosVideoDriverBindingStop (\r
454 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
455 IN EFI_HANDLE Controller,\r
456 IN UINTN NumberOfChildren,\r
457 IN EFI_HANDLE *ChildHandleBuffer\r
458 )\r
459/*++\r
460\r
461 Routine Description:\r
462\r
463 Stop.\r
464\r
465 Arguments:\r
466\r
467 This - Pointer to driver binding protocol\r
468 Controller - Controller handle to connect\r
469 NumberOfChilren - Number of children handle created by this driver\r
470 ChildHandleBuffer - Buffer containing child handle created\r
471\r
472 Returns:\r
473\r
474 EFI_SUCCESS - Driver disconnected successfully from controller\r
475 EFI_UNSUPPORTED - Cannot find BIOS_VIDEO_DEV structure\r
476\r
477--*/\r
478{\r
479 EFI_STATUS Status;\r
480 BIOS_VIDEO_DEV *BiosVideoPrivate;\r
481 BOOLEAN AllChildrenStopped;\r
482 UINTN Index;\r
483\r
484 BiosVideoPrivate = NULL;\r
485\r
486 if (NumberOfChildren == 0) {\r
487 //\r
488 // Close PCI I/O protocol on the controller handle\r
489 //\r
490 gBS->CloseProtocol (\r
491 Controller,\r
492 &gEfiPciIoProtocolGuid,\r
493 This->DriverBindingHandle,\r
494 Controller\r
495 );\r
496\r
497 return EFI_SUCCESS;\r
498 }\r
499\r
500 AllChildrenStopped = TRUE;\r
501 for (Index = 0; Index < NumberOfChildren; Index++) {\r
502 Status = BiosVideoChildHandleUninstall (This, Controller, ChildHandleBuffer[Index]);\r
503\r
504 if (EFI_ERROR (Status)) {\r
505 AllChildrenStopped = FALSE;\r
506 }\r
507 }\r
508\r
509 if (!AllChildrenStopped) {\r
510 return EFI_DEVICE_ERROR;\r
511 }\r
512\r
513 return EFI_SUCCESS;\r
514}\r
515\r
516EFI_STATUS\r
517BiosVideoChildHandleInstall (\r
518 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
519 IN EFI_HANDLE ParentHandle,\r
520 IN EFI_PCI_IO_PROTOCOL *ParentPciIo,\r
521 IN EFI_LEGACY_8259_PROTOCOL *ParentLegacy8259,\r
522 IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath,\r
523 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
524 )\r
525/*++\r
526\r
527Routine Description:\r
528 Install child handles if the Handle supports MBR format.\r
529\r
530Arguments: \r
531 This - Calling context.\r
532 Handle - Parent Handle \r
533 PciIo - Parent PciIo interface\r
534 LegacyBios - Parent LegacyBios interface\r
535 DevicePath - Parent Device Path\r
536\r
537Returns:\r
538 EFI_SUCCESS - If a child handle was added\r
539 other - A child handle was not added\r
540\r
541--*/\r
542{\r
543 EFI_STATUS Status;\r
544 BIOS_VIDEO_DEV *BiosVideoPrivate;\r
545 ACPI_ADR_DEVICE_PATH AcpiDeviceNode;\r
546\r
7da78b1f 547 //\r
0d92cdc2 548 // Allocate the private device structure for video device\r
7da78b1f 549 //\r
0d92cdc2 550 Status = gBS->AllocatePool (\r
551 EfiBootServicesData,\r
552 sizeof (BIOS_VIDEO_DEV),\r
553 &BiosVideoPrivate\r
7da78b1f 554 );\r
555 if (EFI_ERROR (Status)) {\r
556 goto Done;\r
557 }\r
0d92cdc2 558\r
559 ZeroMem (BiosVideoPrivate, sizeof (BIOS_VIDEO_DEV));\r
560\r
561 if (!BiosVideoIsVga (ParentPciIo)) {\r
7da78b1f 562 Status = EFI_UNSUPPORTED;\r
563 goto Done;\r
564 }\r
565 \r
0d92cdc2 566 BiosVideoPrivate->VgaCompatible = TRUE;\r
567\r
7da78b1f 568 //\r
0d92cdc2 569 // Initialize the child private structure\r
7da78b1f 570 //\r
571 BiosVideoPrivate->Signature = BIOS_VIDEO_DEV_SIGNATURE;\r
0d92cdc2 572 BiosVideoPrivate->Handle = NULL;\r
7da78b1f 573\r
574 /**\r
575 Status = gBS->CreateEvent (\r
576 EFI_EVENT_SIGNAL_EXIT_BOOT_SERVICES,\r
577 EFI_TPL_NOTIFY,\r
578 BiosVideoExitBootServices,\r
579 BiosVideoPrivate,\r
580 &BiosVideoPrivate->ExitBootServicesEvent\r
581 );\r
582 if (EFI_ERROR (Status)) {\r
583 goto Done;\r
584 }\r
585 **/\r
586 \r
587 //\r
0d92cdc2 588 // Fill in Graphics Output specific mode structures\r
7da78b1f 589 //\r
590 BiosVideoPrivate->HardwareNeedsStarting = TRUE;\r
7da78b1f 591 BiosVideoPrivate->ModeData = NULL;\r
592 BiosVideoPrivate->LineBuffer = NULL;\r
593 BiosVideoPrivate->VgaFrameBuffer = NULL;\r
594 BiosVideoPrivate->VbeFrameBuffer = NULL;\r
595\r
596 //\r
597 // Fill in the VGA Mini Port Protocol fields\r
598 //\r
599 BiosVideoPrivate->VgaMiniPort.SetMode = BiosVideoVgaMiniPortSetMode;\r
600 BiosVideoPrivate->VgaMiniPort.VgaMemoryOffset = 0xb8000;\r
601 BiosVideoPrivate->VgaMiniPort.CrtcAddressRegisterOffset = 0x3d4;\r
602 BiosVideoPrivate->VgaMiniPort.CrtcDataRegisterOffset = 0x3d5;\r
603 BiosVideoPrivate->VgaMiniPort.VgaMemoryBar = EFI_PCI_IO_PASS_THROUGH_BAR;\r
604 BiosVideoPrivate->VgaMiniPort.CrtcAddressRegisterBar = EFI_PCI_IO_PASS_THROUGH_BAR;\r
605 BiosVideoPrivate->VgaMiniPort.CrtcDataRegisterBar = EFI_PCI_IO_PASS_THROUGH_BAR;\r
606\r
607 //\r
0d92cdc2 608 // Assume that Graphics Output Protocol will be produced until proven otherwise\r
609 //\r
610 BiosVideoPrivate->ProduceGraphicsOutput = TRUE;\r
611\r
612 //\r
613 // Child handle need to consume the Legacy Bios protocol\r
7da78b1f 614 //\r
0d92cdc2 615 BiosVideoPrivate->Legacy8259 = ParentLegacy8259;\r
7da78b1f 616\r
617 //\r
0d92cdc2 618 // When check for VBE, PCI I/O protocol is needed, so use parent's protocol interface temporally\r
619 //\r
620 BiosVideoPrivate->PciIo = ParentPciIo;\r
621\r
622 InitializeBiosIntCaller(BiosVideoPrivate);\r
623 InitializeInterruptRedirection(BiosVideoPrivate);\r
624\r
625 //\r
626 // Check for VESA BIOS Extensions for modes that are compatible with Graphics Output\r
7da78b1f 627 //\r
7da78b1f 628 Status = BiosVideoCheckForVbe (BiosVideoPrivate);\r
7da78b1f 629 if (EFI_ERROR (Status)) {\r
7da78b1f 630 //\r
0d92cdc2 631 // The VESA BIOS Extensions are not compatible with Graphics Output, so check for support\r
7da78b1f 632 // for the standard 640x480 16 color VGA mode\r
633 //\r
634 if (BiosVideoPrivate->VgaCompatible) {\r
635 Status = BiosVideoCheckForVga (BiosVideoPrivate);\r
636 }\r
637\r
638 if (EFI_ERROR (Status)) {\r
639 //\r
640 // Neither VBE nor the standard 640x480 16 color VGA mode are supported, so do\r
0d92cdc2 641 // not produce the Graphics Output protocol. Instead, produce the VGA MiniPort Protocol.\r
7da78b1f 642 //\r
0d92cdc2 643 BiosVideoPrivate->ProduceGraphicsOutput = FALSE;\r
7da78b1f 644\r
645 //\r
646 // INT services are available, so on the 80x25 and 80x50 text mode are supported\r
647 //\r
648 BiosVideoPrivate->VgaMiniPort.MaxMode = 2;\r
649 }\r
650 }\r
651\r
0d92cdc2 652 if (BiosVideoPrivate->ProduceGraphicsOutput) {\r
653 if (RemainingDevicePath == NULL) {\r
654 ZeroMem (&AcpiDeviceNode, sizeof (ACPI_ADR_DEVICE_PATH));\r
655 AcpiDeviceNode.Header.Type = ACPI_DEVICE_PATH;\r
656 AcpiDeviceNode.Header.SubType = ACPI_ADR_DP;\r
657 AcpiDeviceNode.ADR = ACPI_DISPLAY_ADR (1, 0, 0, 1, 0, ACPI_ADR_DISPLAY_TYPE_VGA, 0, 0);\r
658 SetDevicePathNodeLength (&AcpiDeviceNode.Header, sizeof (ACPI_ADR_DEVICE_PATH));\r
659\r
660 BiosVideoPrivate->DevicePath = AppendDevicePathNode (\r
661 ParentDevicePath, \r
662 (EFI_DEVICE_PATH_PROTOCOL *) &AcpiDeviceNode\r
663 );\r
664 } else {\r
665 BiosVideoPrivate->DevicePath = AppendDevicePathNode (ParentDevicePath, RemainingDevicePath);\r
666 }\r
667\r
7da78b1f 668 //\r
0d92cdc2 669 // Creat child handle and install Graphics Output Protocol,EDID Discovered/Active Protocol\r
7da78b1f 670 //\r
671 Status = gBS->InstallMultipleProtocolInterfaces (\r
0d92cdc2 672 &BiosVideoPrivate->Handle,\r
673 &gEfiDevicePathProtocolGuid,\r
674 BiosVideoPrivate->DevicePath,\r
675 &gEfiGraphicsOutputProtocolGuid,\r
676 &BiosVideoPrivate->GraphicsOutput,\r
677 &gEfiEdidDiscoveredProtocolGuid,\r
678 &BiosVideoPrivate->EdidDiscovered,\r
679 &gEfiEdidActiveProtocolGuid,\r
680 &BiosVideoPrivate->EdidActive,\r
7da78b1f 681 NULL\r
682 );\r
0d92cdc2 683\r
684 if (!EFI_ERROR (Status)) {\r
685 //\r
686 // Open the Parent Handle for the child\r
687 //\r
688 Status = gBS->OpenProtocol (\r
689 ParentHandle,\r
690 &gEfiPciIoProtocolGuid,\r
691 (VOID **) &BiosVideoPrivate->PciIo,\r
692 This->DriverBindingHandle,\r
693 BiosVideoPrivate->Handle,\r
694 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
695 );\r
696 if (EFI_ERROR (Status)) {\r
697 goto Done;\r
698 }\r
699 }\r
7da78b1f 700 } else {\r
701 //\r
702 // Install VGA Mini Port Protocol\r
703 //\r
704 Status = gBS->InstallMultipleProtocolInterfaces (\r
0d92cdc2 705 &BiosVideoPrivate->Handle,\r
7da78b1f 706 &gEfiVgaMiniPortProtocolGuid,\r
707 &BiosVideoPrivate->VgaMiniPort,\r
708 NULL\r
709 );\r
710 }\r
711\r
712Done:\r
713 if (EFI_ERROR (Status)) {\r
0d92cdc2 714 //\r
715 // Free private data structure\r
716 //\r
717 BiosVideoDeviceReleaseResource (BiosVideoPrivate);\r
7da78b1f 718 }\r
719\r
720 return Status;\r
721}\r
722\r
723EFI_STATUS\r
0d92cdc2 724BiosVideoChildHandleUninstall (\r
725 EFI_DRIVER_BINDING_PROTOCOL *This,\r
726 EFI_HANDLE Controller,\r
727 EFI_HANDLE Handle\r
7da78b1f 728 )\r
729/*++\r
7da78b1f 730\r
0d92cdc2 731Routine Description:\r
7da78b1f 732\r
0d92cdc2 733 Deregister an video child handle and free resources\r
734\r
735Arguments:\r
736\r
737 This - Protocol instance pointer.\r
738 Controller - Video controller handle\r
739 Handle - Video child handle\r
740\r
741Returns:\r
742\r
743 EFI_STATUS\r
7da78b1f 744\r
7da78b1f 745--*/\r
746{\r
0d92cdc2 747 EFI_STATUS Status;\r
748 EFI_IA32_REGISTER_SET Regs;\r
749 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;\r
750 EFI_VGA_MINI_PORT_PROTOCOL *VgaMiniPort;\r
751 BIOS_VIDEO_DEV *BiosVideoPrivate;\r
752 EFI_PCI_IO_PROTOCOL *PciIo;\r
7da78b1f 753\r
754 BiosVideoPrivate = NULL;\r
755\r
756 Status = gBS->OpenProtocol (\r
0d92cdc2 757 Handle,\r
758 &gEfiGraphicsOutputProtocolGuid,\r
759 (VOID **) &GraphicsOutput,\r
7da78b1f 760 This->DriverBindingHandle,\r
0d92cdc2 761 Handle,\r
7da78b1f 762 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
763 );\r
764 if (!EFI_ERROR (Status)) {\r
0d92cdc2 765 BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (GraphicsOutput);\r
7da78b1f 766 }\r
767\r
768 Status = gBS->OpenProtocol (\r
0d92cdc2 769 Handle,\r
7da78b1f 770 &gEfiVgaMiniPortProtocolGuid,\r
771 (VOID **) &VgaMiniPort,\r
772 This->DriverBindingHandle,\r
0d92cdc2 773 Handle,\r
7da78b1f 774 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
775 );\r
776 if (!EFI_ERROR (Status)) {\r
777 BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_VGA_MINI_PORT_THIS (VgaMiniPort);\r
778 }\r
779\r
780 if (BiosVideoPrivate == NULL) {\r
781 return EFI_UNSUPPORTED;\r
782 }\r
783\r
0d92cdc2 784 //\r
785 // Close PCI I/O protocol that opened by child handle\r
786 //\r
787 Status = gBS->CloseProtocol (\r
788 Controller,\r
789 &gEfiPciIoProtocolGuid,\r
790 This->DriverBindingHandle,\r
791 Handle\r
792 );\r
793\r
794 //\r
795 // Uninstall protocols on child handle\r
796 //\r
797 if (BiosVideoPrivate->ProduceGraphicsOutput) {\r
7da78b1f 798 Status = gBS->UninstallMultipleProtocolInterfaces (\r
0d92cdc2 799 BiosVideoPrivate->Handle,\r
800 &gEfiDevicePathProtocolGuid,\r
801 BiosVideoPrivate->DevicePath,\r
802 &gEfiGraphicsOutputProtocolGuid,\r
803 &BiosVideoPrivate->GraphicsOutput,\r
804 &gEfiEdidDiscoveredProtocolGuid,\r
805 &BiosVideoPrivate->EdidDiscovered,\r
806 &gEfiEdidActiveProtocolGuid,\r
807 &BiosVideoPrivate->EdidActive,\r
7da78b1f 808 NULL\r
809 );\r
810 } else {\r
811 Status = gBS->UninstallMultipleProtocolInterfaces (\r
0d92cdc2 812 BiosVideoPrivate->Handle,\r
7da78b1f 813 &gEfiVgaMiniPortProtocolGuid,\r
814 &BiosVideoPrivate->VgaMiniPort,\r
815 NULL\r
816 );\r
817 }\r
7da78b1f 818 if (EFI_ERROR (Status)) {\r
0d92cdc2 819 gBS->OpenProtocol (\r
820 Controller,\r
821 &gEfiPciIoProtocolGuid,\r
822 (VOID **) &PciIo,\r
823 This->DriverBindingHandle,\r
824 Handle,\r
825 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
826 );\r
7da78b1f 827 return Status;\r
828 }\r
0d92cdc2 829\r
830 gBS->SetMem (&Regs, sizeof (Regs), 0);\r
831\r
7da78b1f 832 //\r
833 // Set the 80x25 Text VGA Mode\r
834 //\r
835 Regs.H.AH = 0x00;\r
836 Regs.H.AL = 0x03;\r
0d92cdc2 837 LegacyBiosInt86 (BiosVideoPrivate, 0x10, &Regs);\r
838 \r
7da78b1f 839 Regs.H.AH = 0x11;\r
840 Regs.H.AL = 0x14;\r
841 Regs.H.BL = 0;\r
0d92cdc2 842 LegacyBiosInt86 (BiosVideoPrivate, 0x10, &Regs);\r
843 \r
7da78b1f 844 //\r
845 // Do not disable IO/memory decode since that would prevent legacy ROM from working\r
846 //\r
0d92cdc2 847\r
848 //\r
849 // Release all allocated resources\r
850 //\r
851 BiosVideoDeviceReleaseResource (BiosVideoPrivate);\r
852\r
853 return EFI_SUCCESS;\r
854}\r
855\r
856VOID\r
857BiosVideoDeviceReleaseResource (\r
858 BIOS_VIDEO_DEV *BiosVideoPrivate\r
859 )\r
860/*++\r
861Routing Description:\r
862\r
863 Release resources of an video child device before stopping it.\r
864\r
865Arguments:\r
866\r
867 BiosVideoPrivate - Video child device private data structure\r
868\r
869Returns:\r
870\r
871 NONE\r
872 \r
873---*/\r
874{\r
875 if (BiosVideoPrivate == NULL) {\r
876 return ;\r
877 }\r
878\r
879 //\r
880 // Release all the resourses occupied by the BIOS_VIDEO_DEV\r
881 //\r
882 \r
7da78b1f 883 //\r
884 // Free VGA Frame Buffer\r
885 //\r
886 if (BiosVideoPrivate->VgaFrameBuffer != NULL) {\r
887 gBS->FreePool (BiosVideoPrivate->VgaFrameBuffer);\r
888 }\r
889 //\r
890 // Free VBE Frame Buffer\r
891 //\r
892 if (BiosVideoPrivate->VbeFrameBuffer != NULL) {\r
893 gBS->FreePool (BiosVideoPrivate->VbeFrameBuffer);\r
894 }\r
895 //\r
896 // Free line buffer\r
897 //\r
898 if (BiosVideoPrivate->LineBuffer != NULL) {\r
899 gBS->FreePool (BiosVideoPrivate->LineBuffer);\r
900 }\r
901 //\r
902 // Free mode data\r
903 //\r
904 if (BiosVideoPrivate->ModeData != NULL) {\r
905 gBS->FreePool (BiosVideoPrivate->ModeData);\r
906 }\r
907 //\r
908 // Free memory allocated below 1MB\r
909 //\r
910 if (BiosVideoPrivate->PagesBelow1MB != 0) {\r
911 gBS->FreePages (BiosVideoPrivate->PagesBelow1MB, BiosVideoPrivate->NumberOfPagesBelow1MB);\r
912 }\r
913\r
914 if (BiosVideoPrivate->VbeSaveRestorePages != 0) {\r
915 gBS->FreePages (BiosVideoPrivate->VbeSaveRestoreBuffer, BiosVideoPrivate->VbeSaveRestorePages);\r
916 }\r
917 //\r
0d92cdc2 918 // Free graphics output protocol occupied resource\r
7da78b1f 919 //\r
0d92cdc2 920 if (BiosVideoPrivate->GraphicsOutput.Mode != NULL) {\r
921 if (BiosVideoPrivate->GraphicsOutput.Mode->Info != NULL) {\r
922 gBS->FreePool (BiosVideoPrivate->GraphicsOutput.Mode->Info);\r
923 }\r
924 gBS->FreePool (BiosVideoPrivate->GraphicsOutput.Mode);\r
925 }\r
926 //\r
927 // Free EDID discovered protocol occupied resource\r
928 //\r
929 if (BiosVideoPrivate->EdidDiscovered.Edid != NULL) {\r
930 gBS->FreePool (BiosVideoPrivate->EdidDiscovered.Edid);\r
931 }\r
932 //\r
933 // Free EDID active protocol occupied resource\r
934 //\r
935 if (BiosVideoPrivate->EdidActive.Edid != NULL) {\r
936 gBS->FreePool (BiosVideoPrivate->EdidActive.Edid);\r
937 }\r
938\r
939 if (BiosVideoPrivate->DevicePath!= NULL) {\r
940 gBS->FreePool (BiosVideoPrivate->DevicePath);\r
941 }\r
7da78b1f 942\r
943 //\r
944 // Close the ExitBootServices event\r
945 //\r
0d92cdc2 946 if (BiosVideoPrivate->ExitBootServicesEvent != NULL) {\r
947 gBS->CloseEvent (BiosVideoPrivate->ExitBootServicesEvent);\r
948 }\r
949\r
950 gBS->FreePool (BiosVideoPrivate);\r
951\r
952 return ;\r
953}\r
954\r
955STATIC\r
956UINT32\r
957CalculateEdidKey (\r
958 VESA_BIOS_EXTENSIONS_EDID_TIMING *EdidTiming\r
959 )\r
960/*++\r
961\r
962 Routine Description:\r
963\r
964 Generate a search key for a specified timing data.\r
965\r
966 Arguments:\r
967\r
968 EdidTiming - Pointer to EDID timing\r
969\r
970 Returns:\r
971 The 32 bit unique key for search.\r
972\r
973--*/\r
974{\r
975 UINT32 Key;\r
7da78b1f 976\r
977 //\r
0d92cdc2 978 // Be sure no conflicts for all standard timing defined by VESA.\r
7da78b1f 979 //\r
0d92cdc2 980 Key = (EdidTiming->HorizontalResolution * 2) + EdidTiming->VerticalResolution;\r
981 return Key;\r
982}\r
7da78b1f 983\r
0d92cdc2 984STATIC\r
985BOOLEAN\r
986ParseEdidData (\r
987 UINT8 *EdidBuffer,\r
988 VESA_BIOS_EXTENSIONS_VALID_EDID_TIMING *ValidEdidTiming\r
989 )\r
990/*++\r
991\r
992 Routine Description:\r
993\r
994 Parse the Established Timing and Standard Timing in EDID data block.\r
995\r
996 Arguments:\r
997\r
998 EdidBuffer - Pointer to EDID data block\r
999 ValidEdidTiming - Valid EDID timing information\r
1000\r
1001 Returns:\r
1002 TRUE - The EDID data is valid.\r
1003 FALSE - The EDID data is invalid.\r
1004\r
1005--*/\r
1006{\r
1007 UINT8 CheckSum;\r
1008 UINT32 Index;\r
1009 UINT32 ValidNumber;\r
1010 UINT32 TimingBits;\r
1011 UINT8 *BufferIndex;\r
1012 UINT16 HorizontalResolution;\r
1013 UINT16 VerticalResolution;\r
1014 UINT8 AspectRatio;\r
1015 UINT8 RefreshRate;\r
1016 VESA_BIOS_EXTENSIONS_EDID_TIMING TempTiming;\r
1017 VESA_BIOS_EXTENSIONS_EDID_DATA_BLOCK *EdidDataBlock;\r
1018\r
1019 EdidDataBlock = (VESA_BIOS_EXTENSIONS_EDID_DATA_BLOCK *) EdidBuffer;\r
1020\r
1021 //\r
1022 // Check the checksum of EDID data\r
1023 //\r
1024 CheckSum = 0;\r
1025 for (Index = 0; Index < VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE; Index ++) {\r
1026 CheckSum = CheckSum + EdidBuffer[Index];\r
1027 }\r
1028 if (CheckSum != 0) {\r
1029 return FALSE;\r
1030 }\r
1031\r
1032 ValidNumber = 0;\r
1033 gBS->SetMem (ValidEdidTiming, sizeof (VESA_BIOS_EXTENSIONS_VALID_EDID_TIMING), 0);\r
1034\r
1035 if ((EdidDataBlock->EstablishedTimings[0] != 0) ||\r
1036 (EdidDataBlock->EstablishedTimings[1] != 0) ||\r
1037 (EdidDataBlock->EstablishedTimings[2] != 0)\r
1038 ) {\r
1039 //\r
1040 // Established timing data\r
1041 //\r
1042 TimingBits = EdidDataBlock->EstablishedTimings[0] |\r
1043 (EdidDataBlock->EstablishedTimings[1] << 8) |\r
1044 ((EdidDataBlock->EstablishedTimings[2] & 0x80) << 9) ;\r
1045 for (Index = 0; Index < VESA_BIOS_EXTENSIONS_EDID_ESTABLISHED_TIMING_MAX_NUMBER; Index ++) {\r
1046 if (TimingBits & 0x1) {\r
1047 ValidEdidTiming->Key[ValidNumber] = CalculateEdidKey (&mEstablishedEdidTiming[Index]);\r
1048 ValidNumber ++;\r
1049 }\r
1050 TimingBits = TimingBits >> 1;\r
1051 }\r
1052 } else {\r
1053 //\r
1054 // If no Established timing data, read the standard timing data\r
1055 //\r
1056 BufferIndex = &EdidDataBlock->StandardTimingIdentification[0];\r
1057 for (Index = 0; Index < 8; Index ++) {\r
1058 if ((BufferIndex[0] != 0x1) && (BufferIndex[1] != 0x1)){\r
1059 //\r
1060 // A valid Standard Timing\r
1061 //\r
1062 HorizontalResolution = BufferIndex[0] * 8 + 248;\r
1063 AspectRatio = BufferIndex[1] >> 6;\r
1064 switch (AspectRatio) {\r
1065 case 0:\r
1066 VerticalResolution = HorizontalResolution / 16 * 10;\r
1067 break;\r
1068 case 1:\r
1069 VerticalResolution = HorizontalResolution / 4 * 3;\r
1070 break;\r
1071 case 2:\r
1072 VerticalResolution = HorizontalResolution / 5 * 4;\r
1073 break;\r
1074 case 3:\r
1075 VerticalResolution = HorizontalResolution / 16 * 9;\r
1076 break;\r
1077 default:\r
1078 VerticalResolution = HorizontalResolution / 4 * 3;\r
1079 break;\r
1080 }\r
1081 RefreshRate = (BufferIndex[1] & 0x1f) + 60;\r
1082 TempTiming.HorizontalResolution = HorizontalResolution;\r
1083 TempTiming.VerticalResolution = VerticalResolution;\r
1084 TempTiming.RefreshRate = RefreshRate;\r
1085 ValidEdidTiming->Key[ValidNumber] = CalculateEdidKey (&TempTiming);\r
1086 ValidNumber ++;\r
1087 }\r
1088 BufferIndex += 2;\r
1089 }\r
1090 }\r
1091\r
1092 ValidEdidTiming->ValidNumber = ValidNumber;\r
1093 return TRUE;\r
1094}\r
1095\r
1096STATIC\r
1097BOOLEAN\r
1098SearchEdidTiming (\r
1099 VESA_BIOS_EXTENSIONS_VALID_EDID_TIMING *ValidEdidTiming,\r
1100 VESA_BIOS_EXTENSIONS_EDID_TIMING *EdidTiming\r
1101 )\r
1102/*++\r
1103\r
1104 Routine Description:\r
1105\r
1106 Search a specified Timing in all the valid EDID timings.\r
1107\r
1108 Arguments:\r
1109\r
1110 ValidEdidTiming - All valid EDID timing information.\r
1111 EdidTiming - The Timing to search for.\r
1112\r
1113 Returns:\r
1114\r
1115 TRUE - Found.\r
1116 FALSE - Not found.\r
1117\r
1118--*/\r
1119{\r
1120 UINT32 Index;\r
1121 UINT32 Key;\r
1122\r
1123 Key = CalculateEdidKey (EdidTiming);\r
1124\r
1125 for (Index = 0; Index < ValidEdidTiming->ValidNumber; Index ++) {\r
1126 if (Key == ValidEdidTiming->Key[Index]) {\r
1127 return TRUE;\r
1128 }\r
1129 }\r
1130\r
1131 return FALSE;\r
7da78b1f 1132}\r
1133\r
1134#define PCI_DEVICE_ENABLED (EFI_PCI_COMMAND_IO_SPACE | EFI_PCI_COMMAND_MEMORY_SPACE)\r
1135\r
1136\r
1137BOOLEAN\r
1138BiosVideoIsVga (\r
1139 IN EFI_PCI_IO_PROTOCOL *PciIo\r
1140 )\r
1141{\r
1142 EFI_STATUS Status;\r
1143 BOOLEAN VgaCompatible;\r
1144 PCI_TYPE00 Pci;\r
1145\r
1146 VgaCompatible = FALSE;\r
1147\r
1148 //\r
1149 // Read the PCI Configuration Header\r
1150 //\r
1151 Status = PciIo->Pci.Read (\r
1152 PciIo,\r
1153 EfiPciIoWidthUint32,\r
1154 0,\r
1155 sizeof (Pci) / sizeof (UINT32),\r
1156 &Pci\r
1157 );\r
1158 if (EFI_ERROR (Status)) {\r
1159 return VgaCompatible;\r
1160 }\r
1161\r
1162 //\r
1163 // See if this is a VGA compatible controller or not\r
1164 //\r
1165 if ((Pci.Hdr.Command & PCI_DEVICE_ENABLED) == PCI_DEVICE_ENABLED) {\r
1166 if (Pci.Hdr.ClassCode[2] == PCI_CLASS_OLD && Pci.Hdr.ClassCode[1] == PCI_CLASS_OLD_VGA) {\r
1167 //\r
1168 // Base Class 0x00 Sub-Class 0x01 - Backward compatible VGA device\r
1169 //\r
1170 VgaCompatible = TRUE;\r
1171 }\r
1172\r
1173 if (Pci.Hdr.ClassCode[2] == PCI_CLASS_DISPLAY && Pci.Hdr.ClassCode[1] == PCI_CLASS_DISPLAY_VGA && Pci.Hdr.ClassCode[0] == 0x00) {\r
1174 //\r
1175 // Base Class 3 Sub-Class 0 Programming interface 0 - VGA compatible Display controller\r
1176 //\r
1177 VgaCompatible = TRUE;\r
1178 }\r
1179 }\r
1180\r
1181 return VgaCompatible;\r
1182}\r
1183\r
1184\r
1185EFI_STATUS\r
0d92cdc2 1186EFIAPI\r
7da78b1f 1187BiosVideoCheckForVbe (\r
0d92cdc2 1188 IN OUT BIOS_VIDEO_DEV *BiosVideoPrivate\r
7da78b1f 1189 )\r
1190/*++\r
0d92cdc2 1191\r
7da78b1f 1192 Routine Description:\r
1193\r
0d92cdc2 1194 Check for VBE device\r
1195\r
7da78b1f 1196 Arguments:\r
0d92cdc2 1197\r
7da78b1f 1198 BiosVideoPrivate - Pointer to BIOS_VIDEO_DEV structure\r
0d92cdc2 1199\r
7da78b1f 1200 Returns:\r
0d92cdc2 1201\r
7da78b1f 1202 EFI_SUCCESS - VBE device found\r
0d92cdc2 1203\r
7da78b1f 1204--*/\r
1205{\r
0d92cdc2 1206 EFI_STATUS Status;\r
1207 EFI_IA32_REGISTER_SET Regs;\r
1208 UINT16 *ModeNumberPtr;\r
1209 BOOLEAN ModeFound;\r
1210 BOOLEAN EdidFound;\r
1211 BIOS_VIDEO_MODE_DATA *ModeBuffer;\r
1212 BIOS_VIDEO_MODE_DATA *CurrentModeData;\r
1213 UINTN PreferMode;\r
1214 UINTN ModeNumber;\r
1215 VESA_BIOS_EXTENSIONS_EDID_TIMING Timing;\r
1216 VESA_BIOS_EXTENSIONS_VALID_EDID_TIMING ValidEdidTiming;\r
1217 EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE *GraphicsOutputMode;\r
7da78b1f 1218\r
1219 //\r
1220 // Allocate buffer under 1MB for VBE data structures\r
1221 //\r
1222 BiosVideoPrivate->NumberOfPagesBelow1MB = EFI_SIZE_TO_PAGES (\r
0d92cdc2 1223 sizeof (VESA_BIOS_EXTENSIONS_INFORMATION_BLOCK) +\r
1224 sizeof (VESA_BIOS_EXTENSIONS_MODE_INFORMATION_BLOCK) +\r
1225 sizeof (VESA_BIOS_EXTENSIONS_EDID_DATA_BLOCK) +\r
7da78b1f 1226 sizeof (VESA_BIOS_EXTENSIONS_CRTC_INFORMATION_BLOCK)\r
1227 );\r
1228\r
1229 BiosVideoPrivate->PagesBelow1MB = 0x00100000 - 1;\r
1230\r
1231 Status = gBS->AllocatePages (\r
1232 AllocateMaxAddress,\r
1233 EfiBootServicesData,\r
1234 BiosVideoPrivate->NumberOfPagesBelow1MB,\r
1235 &BiosVideoPrivate->PagesBelow1MB\r
1236 );\r
1237 if (EFI_ERROR (Status)) {\r
1238 return Status;\r
1239 }\r
0d92cdc2 1240\r
1241 ZeroMem (&ValidEdidTiming, sizeof (VESA_BIOS_EXTENSIONS_VALID_EDID_TIMING));\r
1242\r
7da78b1f 1243 //\r
0d92cdc2 1244 // Fill in the Graphics Output Protocol\r
7da78b1f 1245 //\r
0d92cdc2 1246 BiosVideoPrivate->GraphicsOutput.QueryMode = BiosVideoGraphicsOutputQueryMode;\r
1247 BiosVideoPrivate->GraphicsOutput.SetMode = BiosVideoGraphicsOutputSetMode;\r
1248 BiosVideoPrivate->GraphicsOutput.Blt = BiosVideoGraphicsOutputVbeBlt;\r
1249 BiosVideoPrivate->GraphicsOutput.Mode = NULL;\r
7da78b1f 1250\r
1251 //\r
1252 // Fill in the VBE related data structures\r
1253 //\r
1254 BiosVideoPrivate->VbeInformationBlock = (VESA_BIOS_EXTENSIONS_INFORMATION_BLOCK *) (UINTN) (BiosVideoPrivate->PagesBelow1MB);\r
1255 BiosVideoPrivate->VbeModeInformationBlock = (VESA_BIOS_EXTENSIONS_MODE_INFORMATION_BLOCK *) (BiosVideoPrivate->VbeInformationBlock + 1);\r
0d92cdc2 1256 BiosVideoPrivate->VbeEdidDataBlock = (VESA_BIOS_EXTENSIONS_EDID_DATA_BLOCK *) (BiosVideoPrivate->VbeModeInformationBlock + 1);\r
1257 BiosVideoPrivate->VbeCrtcInformationBlock = (VESA_BIOS_EXTENSIONS_CRTC_INFORMATION_BLOCK *) (BiosVideoPrivate->VbeEdidDataBlock + 1);\r
7da78b1f 1258 BiosVideoPrivate->VbeSaveRestorePages = 0;\r
1259 BiosVideoPrivate->VbeSaveRestoreBuffer = 0;\r
1260\r
1261 //\r
1262 // Test to see if the Video Adapter is compliant with VBE 3.0\r
1263 //\r
1264 gBS->SetMem (&Regs, sizeof (Regs), 0);\r
1265 Regs.X.AX = VESA_BIOS_EXTENSIONS_RETURN_CONTROLLER_INFORMATION;\r
1266 gBS->SetMem (BiosVideoPrivate->VbeInformationBlock, sizeof (VESA_BIOS_EXTENSIONS_INFORMATION_BLOCK), 0);\r
1267 BiosVideoPrivate->VbeInformationBlock->VESASignature = VESA_BIOS_EXTENSIONS_VBE2_SIGNATURE;\r
0d92cdc2 1268 Regs.X.ES = EFI_SEGMENT ((UINTN) BiosVideoPrivate->VbeInformationBlock);\r
1269 Regs.X.DI = EFI_OFFSET ((UINTN) BiosVideoPrivate->VbeInformationBlock);\r
7da78b1f 1270\r
0d92cdc2 1271 LegacyBiosInt86 (BiosVideoPrivate, 0x10, &Regs);\r
1272 \r
7da78b1f 1273 Status = EFI_DEVICE_ERROR;\r
1274\r
1275 //\r
1276 // See if the VESA call succeeded\r
1277 //\r
1278 if (Regs.X.AX != VESA_BIOS_EXTENSIONS_STATUS_SUCCESS) {\r
1279 return Status;\r
1280 }\r
1281 //\r
1282 // Check for 'VESA' signature\r
1283 //\r
1284 if (BiosVideoPrivate->VbeInformationBlock->VESASignature != VESA_BIOS_EXTENSIONS_VESA_SIGNATURE) {\r
1285 return Status;\r
1286 }\r
1287 //\r
1288 // Check to see if this is VBE 2.0 or higher\r
1289 //\r
1290 if (BiosVideoPrivate->VbeInformationBlock->VESAVersion < VESA_BIOS_EXTENSIONS_VERSION_2_0) {\r
1291 return Status;\r
1292 }\r
0d92cdc2 1293\r
1294 //\r
1295 // Read EDID information\r
1296 //\r
1297 gBS->SetMem (&Regs, sizeof (Regs), 0);\r
1298 Regs.X.AX = VESA_BIOS_EXTENSIONS_EDID;\r
1299 Regs.X.BX = 1;\r
1300 Regs.X.CX = 0;\r
1301 Regs.X.DX = 0;\r
1302 Regs.X.ES = EFI_SEGMENT ((UINTN) BiosVideoPrivate->VbeEdidDataBlock);\r
1303 Regs.X.DI = EFI_OFFSET ((UINTN) BiosVideoPrivate->VbeEdidDataBlock);\r
1304\r
1305 LegacyBiosInt86 (BiosVideoPrivate, 0x10, &Regs);\r
1306 \r
1307 //\r
1308 // See if the VESA call succeeded\r
1309 //\r
1310 EdidFound = FALSE;\r
1311 if (Regs.X.AX == VESA_BIOS_EXTENSIONS_STATUS_SUCCESS) {\r
1312 //\r
1313 // Parse EDID data structure to retrieve modes supported by monitor\r
1314 //\r
1315 if (ParseEdidData ((UINT8 *) BiosVideoPrivate->VbeEdidDataBlock, &ValidEdidTiming) == TRUE) {\r
1316 EdidFound = TRUE;\r
1317\r
1318 BiosVideoPrivate->EdidDiscovered.SizeOfEdid = VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE;\r
1319 Status = gBS->AllocatePool (\r
1320 EfiBootServicesData,\r
1321 VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE,\r
1322 &BiosVideoPrivate->EdidDiscovered.Edid\r
1323 );\r
1324 if (EFI_ERROR (Status)) {\r
1325 goto Done;\r
1326 }\r
1327 gBS->CopyMem (\r
1328 BiosVideoPrivate->EdidDiscovered.Edid,\r
1329 BiosVideoPrivate->VbeEdidDataBlock,\r
1330 VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE\r
1331 );\r
1332\r
1333 BiosVideoPrivate->EdidActive.SizeOfEdid = VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE;\r
1334 Status = gBS->AllocatePool (\r
1335 EfiBootServicesData,\r
1336 VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE,\r
1337 &BiosVideoPrivate->EdidActive.Edid\r
1338 );\r
1339 if (EFI_ERROR (Status)) {\r
1340 goto Done;\r
1341 }\r
1342 gBS->CopyMem (\r
1343 BiosVideoPrivate->EdidActive.Edid,\r
1344 BiosVideoPrivate->VbeEdidDataBlock,\r
1345 VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE\r
1346 );\r
1347 } else {\r
1348 BiosVideoPrivate->EdidDiscovered.SizeOfEdid = 0;\r
1349 BiosVideoPrivate->EdidDiscovered.Edid = NULL;\r
1350\r
1351 BiosVideoPrivate->EdidActive.SizeOfEdid = 0;\r
1352 BiosVideoPrivate->EdidActive.Edid = NULL;\r
1353 }\r
1354 }\r
1355\r
7da78b1f 1356 //\r
0d92cdc2 1357 // Walk through the mode list to see if there is at least one mode the is compatible with the EDID mode\r
7da78b1f 1358 //\r
1359 ModeNumberPtr = (UINT16 *)\r
1360 (\r
1361 (((UINTN) BiosVideoPrivate->VbeInformationBlock->VideoModePtr & 0xffff0000) >> 12) |\r
1362 ((UINTN) BiosVideoPrivate->VbeInformationBlock->VideoModePtr & 0x0000ffff)\r
1363 );\r
0d92cdc2 1364\r
1365 PreferMode = 0;\r
1366 ModeNumber = 0;\r
1367\r
7da78b1f 1368 for (; *ModeNumberPtr != VESA_BIOS_EXTENSIONS_END_OF_MODE_LIST; ModeNumberPtr++) {\r
1369 //\r
1370 // Make sure this is a mode number defined by the VESA VBE specification. If it isn'tm then skip this mode number.\r
1371 //\r
1372 if ((*ModeNumberPtr & VESA_BIOS_EXTENSIONS_MODE_NUMBER_VESA) == 0) {\r
1373 continue;\r
1374 }\r
1375 //\r
1376 // Get the information about the mode\r
1377 //\r
1378 gBS->SetMem (&Regs, sizeof (Regs), 0);\r
1379 Regs.X.AX = VESA_BIOS_EXTENSIONS_RETURN_MODE_INFORMATION;\r
1380 Regs.X.CX = *ModeNumberPtr;\r
1381 gBS->SetMem (BiosVideoPrivate->VbeModeInformationBlock, sizeof (VESA_BIOS_EXTENSIONS_MODE_INFORMATION_BLOCK), 0);\r
0d92cdc2 1382 Regs.X.ES = EFI_SEGMENT ((UINTN) BiosVideoPrivate->VbeModeInformationBlock);\r
1383 Regs.X.DI = EFI_OFFSET ((UINTN) BiosVideoPrivate->VbeModeInformationBlock);\r
7da78b1f 1384\r
0d92cdc2 1385 LegacyBiosInt86 (BiosVideoPrivate, 0x10, &Regs);\r
1386 \r
7da78b1f 1387 //\r
1388 // See if the call succeeded. If it didn't, then try the next mode.\r
1389 //\r
1390 if (Regs.X.AX != VESA_BIOS_EXTENSIONS_STATUS_SUCCESS) {\r
1391 continue;\r
1392 }\r
1393 //\r
1394 // See if the mode supports color. If it doesn't then try the next mode.\r
1395 //\r
1396 if ((BiosVideoPrivate->VbeModeInformationBlock->ModeAttributes & VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_COLOR) == 0) {\r
1397 continue;\r
1398 }\r
1399 //\r
1400 // See if the mode supports graphics. If it doesn't then try the next mode.\r
1401 //\r
1402 if ((BiosVideoPrivate->VbeModeInformationBlock->ModeAttributes & VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_GRAPHICS) == 0) {\r
1403 continue;\r
1404 }\r
1405 //\r
1406 // See if the mode supports a linear frame buffer. If it doesn't then try the next mode.\r
1407 //\r
1408 if ((BiosVideoPrivate->VbeModeInformationBlock->ModeAttributes & VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_LINEAR_FRAME_BUFFER) == 0) {\r
1409 continue;\r
1410 }\r
1411 //\r
1412 // See if the mode supports 32 bit color. If it doesn't then try the next mode.\r
1413 // 32 bit mode can be implemented by 24 Bits Per Pixels. Also make sure the\r
1414 // number of bits per pixel is a multiple of 8 or more than 32 bits per pixel\r
1415 //\r
1416 if (BiosVideoPrivate->VbeModeInformationBlock->BitsPerPixel < 24) {\r
1417 continue;\r
1418 }\r
1419\r
1420 if (BiosVideoPrivate->VbeModeInformationBlock->BitsPerPixel > 32) {\r
1421 continue;\r
1422 }\r
1423\r
1424 if ((BiosVideoPrivate->VbeModeInformationBlock->BitsPerPixel % 8) != 0) {\r
1425 continue;\r
1426 }\r
1427 //\r
1428 // See if the physical base pointer for the linear mode is valid. If it isn't then try the next mode.\r
1429 //\r
1430 if (BiosVideoPrivate->VbeModeInformationBlock->PhysBasePtr == 0) {\r
1431 continue;\r
1432 }\r
0d92cdc2 1433\r
1434 if (EdidFound && (ValidEdidTiming.ValidNumber > 0)) {\r
1435 //\r
1436 // EDID exist, check whether this mode match with any mode in EDID\r
1437 //\r
1438 Timing.HorizontalResolution = BiosVideoPrivate->VbeModeInformationBlock->XResolution;\r
1439 Timing.VerticalResolution = BiosVideoPrivate->VbeModeInformationBlock->YResolution;\r
1440 if (SearchEdidTiming (&ValidEdidTiming, &Timing) == FALSE) {\r
1441 continue;\r
1442 }\r
1443 }\r
1444\r
7da78b1f 1445 //\r
0d92cdc2 1446 // Select a reasonable mode to be set for current display mode\r
7da78b1f 1447 //\r
1448 ModeFound = FALSE;\r
0d92cdc2 1449\r
7da78b1f 1450 if (BiosVideoPrivate->VbeModeInformationBlock->XResolution == 1024 &&\r
1451 BiosVideoPrivate->VbeModeInformationBlock->YResolution == 768\r
1452 ) {\r
1453 ModeFound = TRUE;\r
1454 }\r
7da78b1f 1455 if (BiosVideoPrivate->VbeModeInformationBlock->XResolution == 800 &&\r
1456 BiosVideoPrivate->VbeModeInformationBlock->YResolution == 600\r
1457 ) {\r
1458 ModeFound = TRUE;\r
0d92cdc2 1459 PreferMode = ModeNumber;\r
7da78b1f 1460 }\r
7da78b1f 1461 if (BiosVideoPrivate->VbeModeInformationBlock->XResolution == 640 &&\r
1462 BiosVideoPrivate->VbeModeInformationBlock->YResolution == 480\r
1463 ) {\r
1464 ModeFound = TRUE;\r
1465 }\r
0d92cdc2 1466 if ((!EdidFound) && (!ModeFound)) {\r
1467 //\r
1468 // When no EDID exist, only select three possible resolutions, i.e. 1024x768, 800x600, 640x480\r
1469 //\r
7da78b1f 1470 continue;\r
1471 }\r
0d92cdc2 1472\r
7da78b1f 1473 //\r
1474 // Add mode to the list of available modes\r
1475 //\r
0d92cdc2 1476 ModeNumber ++;\r
7da78b1f 1477 Status = gBS->AllocatePool (\r
1478 EfiBootServicesData,\r
0d92cdc2 1479 ModeNumber * sizeof (BIOS_VIDEO_MODE_DATA),\r
7da78b1f 1480 (VOID **) &ModeBuffer\r
1481 );\r
1482 if (EFI_ERROR (Status)) {\r
1483 goto Done;\r
1484 }\r
1485\r
0d92cdc2 1486 if (ModeNumber > 1) {\r
7da78b1f 1487 gBS->CopyMem (\r
1488 ModeBuffer,\r
1489 BiosVideoPrivate->ModeData,\r
0d92cdc2 1490 (ModeNumber - 1) * sizeof (BIOS_VIDEO_MODE_DATA)\r
7da78b1f 1491 );\r
1492 }\r
1493\r
1494 if (BiosVideoPrivate->ModeData != NULL) {\r
1495 gBS->FreePool (BiosVideoPrivate->ModeData);\r
1496 }\r
1497\r
0d92cdc2 1498 CurrentModeData = &ModeBuffer[ModeNumber - 1];\r
1499 CurrentModeData->VbeModeNumber = *ModeNumberPtr;\r
7da78b1f 1500 if (BiosVideoPrivate->VbeInformationBlock->VESAVersion >= VESA_BIOS_EXTENSIONS_VERSION_3_0) {\r
0d92cdc2 1501 CurrentModeData->BytesPerScanLine = BiosVideoPrivate->VbeModeInformationBlock->LinBytesPerScanLine;\r
1502 CurrentModeData->Red.Position = BiosVideoPrivate->VbeModeInformationBlock->LinRedFieldPosition;\r
1503 CurrentModeData->Red.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->LinRedMaskSize) - 1);\r
1504 CurrentModeData->Blue.Position = BiosVideoPrivate->VbeModeInformationBlock->LinBlueFieldPosition;\r
1505 CurrentModeData->Blue.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->LinBlueMaskSize) - 1);\r
1506 CurrentModeData->Green.Position = BiosVideoPrivate->VbeModeInformationBlock->LinGreenFieldPosition;\r
1507 CurrentModeData->Green.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->LinGreenMaskSize) - 1);\r
1508 CurrentModeData->Reserved.Position = BiosVideoPrivate->VbeModeInformationBlock->LinRsvdFieldPosition;\r
1509 CurrentModeData->Reserved.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->LinRsvdMaskSize) - 1);\r
7da78b1f 1510 } else {\r
0d92cdc2 1511 CurrentModeData->BytesPerScanLine = BiosVideoPrivate->VbeModeInformationBlock->BytesPerScanLine;\r
1512 CurrentModeData->Red.Position = BiosVideoPrivate->VbeModeInformationBlock->RedFieldPosition;\r
1513 CurrentModeData->Red.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->RedMaskSize) - 1);\r
1514 CurrentModeData->Blue.Position = BiosVideoPrivate->VbeModeInformationBlock->BlueFieldPosition;\r
1515 CurrentModeData->Blue.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->BlueMaskSize) - 1);\r
1516 CurrentModeData->Green.Position = BiosVideoPrivate->VbeModeInformationBlock->GreenFieldPosition;\r
1517 CurrentModeData->Green.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->GreenMaskSize) - 1);\r
1518 CurrentModeData->Reserved.Position = BiosVideoPrivate->VbeModeInformationBlock->RsvdFieldPosition;\r
1519 CurrentModeData->Reserved.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->RsvdMaskSize) - 1);\r
7da78b1f 1520 }\r
0d92cdc2 1521 CurrentModeData->PixelFormat = PixelBitMask;\r
1522 if ((BiosVideoPrivate->VbeModeInformationBlock->BitsPerPixel == 32) &&\r
1523 (CurrentModeData->Red.Mask == 0xff) && (CurrentModeData->Green.Mask == 0xff) && (CurrentModeData->Blue.Mask == 0xff)) {\r
1524 if ((CurrentModeData->Red.Position == 0) && (CurrentModeData->Green.Position == 8) && (CurrentModeData->Blue.Position == 16)) {\r
1525 CurrentModeData->PixelFormat = PixelRedGreenBlueReserved8BitPerColor;\r
1526 } else if ((CurrentModeData->Blue.Position == 0) && (CurrentModeData->Green.Position == 8) && (CurrentModeData->Red.Position == 16)) {\r
1527 CurrentModeData->PixelFormat = PixelBlueGreenRedReserved8BitPerColor;\r
1528 }\r
7da78b1f 1529 }\r
0d92cdc2 1530 CurrentModeData->PixelBitMask.RedMask = ((UINT32) CurrentModeData->Red.Mask) << CurrentModeData->Red.Position;\r
1531 CurrentModeData->PixelBitMask.GreenMask = ((UINT32) CurrentModeData->Green.Mask) << CurrentModeData->Green.Position;\r
1532 CurrentModeData->PixelBitMask.BlueMask = ((UINT32) CurrentModeData->Blue.Mask) << CurrentModeData->Blue.Position;\r
1533 CurrentModeData->PixelBitMask.ReservedMask = ((UINT32) CurrentModeData->Reserved.Mask) << CurrentModeData->Reserved.Position;\r
7da78b1f 1534\r
0d92cdc2 1535 CurrentModeData->LinearFrameBuffer = (VOID *) (UINTN)BiosVideoPrivate->VbeModeInformationBlock->PhysBasePtr;\r
1536 CurrentModeData->FrameBufferSize = BiosVideoPrivate->VbeInformationBlock->TotalMemory * 64 * 1024;\r
1537 CurrentModeData->HorizontalResolution = BiosVideoPrivate->VbeModeInformationBlock->XResolution;\r
1538 CurrentModeData->VerticalResolution = BiosVideoPrivate->VbeModeInformationBlock->YResolution;\r
7da78b1f 1539\r
0d92cdc2 1540 CurrentModeData->BitsPerPixel = BiosVideoPrivate->VbeModeInformationBlock->BitsPerPixel;\r
7da78b1f 1541\r
1542 BiosVideoPrivate->ModeData = ModeBuffer;\r
1543 }\r
1544 //\r
0d92cdc2 1545 // Check to see if we found any modes that are compatible with GRAPHICS OUTPUT\r
7da78b1f 1546 //\r
0d92cdc2 1547 if (ModeNumber == 0) {\r
7da78b1f 1548 Status = EFI_DEVICE_ERROR;\r
1549 goto Done;\r
1550 }\r
0d92cdc2 1551\r
1552 //\r
1553 // Allocate buffer for Graphics Output Protocol mode information\r
1554 //\r
1555 Status = gBS->AllocatePool (\r
1556 EfiBootServicesData,\r
1557 sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE),\r
1558 (VOID **) &BiosVideoPrivate->GraphicsOutput.Mode\r
1559 );\r
1560 if (EFI_ERROR (Status)) {\r
1561 goto Done;\r
1562 }\r
1563 GraphicsOutputMode = BiosVideoPrivate->GraphicsOutput.Mode;\r
1564 Status = gBS->AllocatePool (\r
1565 EfiBootServicesData,\r
1566 sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION),\r
1567 (VOID **) &GraphicsOutputMode->Info\r
1568 );\r
1569 if (EFI_ERROR (Status)) {\r
1570 goto Done;\r
1571 }\r
1572\r
1573 GraphicsOutputMode->MaxMode = (UINT32) ModeNumber;\r
1574 //\r
1575 // Current mode is unknow till now, set it to an invalid mode.\r
1576 //\r
1577 GraphicsOutputMode->Mode = GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER;\r
1578\r
7da78b1f 1579 //\r
1580 // Find the best mode to initialize\r
1581 //\r
0d92cdc2 1582 Status = BiosVideoGraphicsOutputSetMode (&BiosVideoPrivate->GraphicsOutput, (UINT32) PreferMode);\r
7da78b1f 1583 if (EFI_ERROR (Status)) {\r
0d92cdc2 1584 for (PreferMode = 0; PreferMode < ModeNumber; PreferMode ++) {\r
1585 Status = BiosVideoGraphicsOutputSetMode (\r
1586 &BiosVideoPrivate->GraphicsOutput,\r
1587 (UINT32) PreferMode\r
1588 );\r
1589 if (!EFI_ERROR (Status)) {\r
1590 break;\r
7da78b1f 1591 }\r
1592 }\r
0d92cdc2 1593 if (PreferMode == ModeNumber) {\r
1594 //\r
1595 // None mode is set successfully.\r
1596 //\r
1597 goto Done;\r
1598 }\r
7da78b1f 1599 }\r
1600\r
1601Done:\r
1602 //\r
1603 // If there was an error, then free the mode structure\r
1604 //\r
1605 if (EFI_ERROR (Status)) {\r
1606 if (BiosVideoPrivate->ModeData != NULL) {\r
1607 gBS->FreePool (BiosVideoPrivate->ModeData);\r
0d92cdc2 1608 }\r
1609 if (BiosVideoPrivate->GraphicsOutput.Mode != NULL) {\r
1610 if (BiosVideoPrivate->GraphicsOutput.Mode->Info != NULL) {\r
1611 gBS->FreePool (BiosVideoPrivate->GraphicsOutput.Mode->Info);\r
1612 }\r
1613 gBS->FreePool (BiosVideoPrivate->GraphicsOutput.Mode);\r
7da78b1f 1614 }\r
1615 }\r
1616\r
1617 return Status;\r
1618}\r
1619\r
1620EFI_STATUS\r
0d92cdc2 1621EFIAPI\r
7da78b1f 1622BiosVideoCheckForVga (\r
0d92cdc2 1623 IN OUT BIOS_VIDEO_DEV *BiosVideoPrivate\r
7da78b1f 1624 )\r
1625/*++\r
0d92cdc2 1626\r
7da78b1f 1627 Routine Description:\r
1628\r
1629 Check for VGA device\r
0d92cdc2 1630\r
7da78b1f 1631 Arguments:\r
0d92cdc2 1632\r
7da78b1f 1633 BiosVideoPrivate - Pointer to BIOS_VIDEO_DEV structure\r
0d92cdc2 1634\r
7da78b1f 1635 Returns:\r
0d92cdc2 1636\r
7da78b1f 1637 EFI_SUCCESS - Standard VGA device found\r
0d92cdc2 1638\r
7da78b1f 1639--*/\r
1640{\r
1641 EFI_STATUS Status;\r
1642 BIOS_VIDEO_MODE_DATA *ModeBuffer;\r
0d92cdc2 1643 \r
1644 //\r
1645 // Fill in the Graphics Output Protocol\r
1646 //\r
1647 BiosVideoPrivate->GraphicsOutput.QueryMode = BiosVideoGraphicsOutputQueryMode;\r
1648 BiosVideoPrivate->GraphicsOutput.SetMode = BiosVideoGraphicsOutputSetMode;\r
1649 BiosVideoPrivate->GraphicsOutput.Blt = BiosVideoGraphicsOutputVgaBlt;\r
7da78b1f 1650\r
1651 //\r
0d92cdc2 1652 // Allocate buffer for Graphics Output Protocol mode information\r
7da78b1f 1653 //\r
0d92cdc2 1654 Status = gBS->AllocatePool (\r
1655 EfiBootServicesData,\r
1656 sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE),\r
1657 (VOID **) &BiosVideoPrivate->GraphicsOutput.Mode\r
1658 );\r
1659 if (EFI_ERROR (Status)) {\r
1660 goto Done;\r
1661 }\r
1662 Status = gBS->AllocatePool (\r
1663 EfiBootServicesData,\r
1664 sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION),\r
1665 (VOID **) &BiosVideoPrivate->GraphicsOutput.Mode->Info\r
1666 );\r
1667 if (EFI_ERROR (Status)) {\r
1668 goto Done;\r
1669 }\r
7da78b1f 1670\r
1671 //\r
1672 // Add mode to the list of available modes\r
1673 //\r
0d92cdc2 1674 BiosVideoPrivate->GraphicsOutput.Mode->MaxMode = 1;\r
1675\r
7da78b1f 1676 Status = gBS->AllocatePool (\r
1677 EfiBootServicesData,\r
0d92cdc2 1678 sizeof (BIOS_VIDEO_MODE_DATA),\r
7da78b1f 1679 (VOID **) &ModeBuffer\r
1680 );\r
1681 if (EFI_ERROR (Status)) {\r
0d92cdc2 1682 goto Done;\r
7da78b1f 1683 }\r
1684\r
0d92cdc2 1685 ModeBuffer->VbeModeNumber = 0x0012;\r
1686 ModeBuffer->BytesPerScanLine = 640;\r
1687 ModeBuffer->LinearFrameBuffer = (VOID *) (UINTN) (0xa0000);\r
1688 ModeBuffer->FrameBufferSize = 0;\r
1689 ModeBuffer->HorizontalResolution = 640;\r
1690 ModeBuffer->VerticalResolution = 480;\r
1691 ModeBuffer->BitsPerPixel = 8; \r
1692 ModeBuffer->PixelFormat = PixelBltOnly;\r
7da78b1f 1693\r
1694 BiosVideoPrivate->ModeData = ModeBuffer;\r
1695\r
1696 //\r
1697 // Test to see if the Video Adapter support the 640x480 16 color mode\r
1698 //\r
0d92cdc2 1699 BiosVideoPrivate->GraphicsOutput.Mode->Mode = GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER;\r
1700 Status = BiosVideoGraphicsOutputSetMode (&BiosVideoPrivate->GraphicsOutput, 0);\r
7da78b1f 1701\r
0d92cdc2 1702Done:\r
7da78b1f 1703 //\r
1704 // If there was an error, then free the mode structure\r
1705 //\r
1706 if (EFI_ERROR (Status)) {\r
7da78b1f 1707 if (BiosVideoPrivate->ModeData != NULL) {\r
1708 gBS->FreePool (BiosVideoPrivate->ModeData);\r
1709 }\r
0d92cdc2 1710 if (BiosVideoPrivate->GraphicsOutput.Mode != NULL) {\r
1711 if (BiosVideoPrivate->GraphicsOutput.Mode->Info != NULL) {\r
1712 gBS->FreePool (BiosVideoPrivate->GraphicsOutput.Mode->Info);\r
1713 }\r
1714 gBS->FreePool (BiosVideoPrivate->GraphicsOutput.Mode);\r
1715 }\r
7da78b1f 1716 }\r
7da78b1f 1717 return Status;\r
1718}\r
1719//\r
0d92cdc2 1720// Graphics Output Protocol Member Functions for VESA BIOS Extensions\r
7da78b1f 1721//\r
1722EFI_STATUS\r
1723EFIAPI\r
0d92cdc2 1724BiosVideoGraphicsOutputQueryMode (\r
1725 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,\r
1726 IN UINT32 ModeNumber,\r
1727 OUT UINTN *SizeOfInfo,\r
1728 OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info\r
7da78b1f 1729 )\r
1730/*++\r
1731\r
1732Routine Description:\r
1733\r
0d92cdc2 1734 Graphics Output protocol interface to get video mode\r
7da78b1f 1735\r
0d92cdc2 1736 Arguments:\r
1737 This - Protocol instance pointer.\r
1738 ModeNumber - The mode number to return information on.\r
1739 Info - Caller allocated buffer that returns information about ModeNumber.\r
1740 SizeOfInfo - A pointer to the size, in bytes, of the Info buffer.\r
7da78b1f 1741\r
0d92cdc2 1742 Returns:\r
1743 EFI_SUCCESS - Mode information returned.\r
1744 EFI_DEVICE_ERROR - A hardware error occurred trying to retrieve the video mode.\r
1745 EFI_NOT_STARTED - Video display is not initialized. Call SetMode ()\r
1746 EFI_INVALID_PARAMETER - One of the input args was NULL.\r
7da78b1f 1747\r
1748--*/\r
1749{\r
0d92cdc2 1750 BIOS_VIDEO_DEV *BiosVideoPrivate;\r
1751 EFI_STATUS Status;\r
1752 BIOS_VIDEO_MODE_DATA *ModeData;\r
7da78b1f 1753\r
0d92cdc2 1754 BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This);\r
7da78b1f 1755\r
1756 if (BiosVideoPrivate->HardwareNeedsStarting) {\r
0d92cdc2 1757 return EFI_NOT_STARTED;\r
7da78b1f 1758 }\r
1759\r
0d92cdc2 1760 if (This == NULL || Info == NULL || SizeOfInfo == NULL || ModeNumber >= This->Mode->MaxMode) {\r
7da78b1f 1761 return EFI_INVALID_PARAMETER;\r
1762 }\r
1763\r
0d92cdc2 1764 Status = gBS->AllocatePool (\r
1765 EfiBootServicesData,\r
1766 sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION),\r
1767 Info\r
1768 );\r
1769 if (EFI_ERROR (Status)) {\r
1770 return Status;\r
1771 }\r
1772\r
1773 *SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);\r
1774\r
1775 ModeData = &BiosVideoPrivate->ModeData[ModeNumber];\r
1776 (*Info)->Version = 0;\r
1777 (*Info)->HorizontalResolution = ModeData->HorizontalResolution;\r
1778 (*Info)->VerticalResolution = ModeData->VerticalResolution;\r
1779 (*Info)->PixelFormat = ModeData->PixelFormat;\r
1780 (*Info)->PixelInformation = ModeData->PixelBitMask;\r
1781\r
1782 (*Info)->PixelsPerScanLine = (ModeData->BytesPerScanLine * 8) / ModeData->BitsPerPixel;\r
7da78b1f 1783\r
1784 return EFI_SUCCESS;\r
1785}\r
1786\r
1787EFI_STATUS\r
1788EFIAPI\r
0d92cdc2 1789BiosVideoGraphicsOutputSetMode (\r
1790 IN EFI_GRAPHICS_OUTPUT_PROTOCOL * This,\r
1791 IN UINT32 ModeNumber\r
7da78b1f 1792 )\r
1793/*++\r
1794\r
1795Routine Description:\r
1796\r
0d92cdc2 1797 Graphics Output protocol interface to set video mode\r
7da78b1f 1798\r
0d92cdc2 1799 Arguments:\r
1800 This - Protocol instance pointer.\r
1801 ModeNumber - The mode number to be set.\r
7da78b1f 1802\r
0d92cdc2 1803 Returns:\r
1804 EFI_SUCCESS - Graphics mode was changed.\r
1805 EFI_DEVICE_ERROR - The device had an error and could not complete the request.\r
1806 EFI_UNSUPPORTED - ModeNumber is not supported by this device.\r
7da78b1f 1807\r
1808--*/\r
1809{\r
0d92cdc2 1810 EFI_STATUS Status;\r
1811 BIOS_VIDEO_DEV *BiosVideoPrivate;\r
1812 EFI_IA32_REGISTER_SET Regs;\r
1813 BIOS_VIDEO_MODE_DATA *ModeData;\r
7da78b1f 1814\r
0d92cdc2 1815 BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This);\r
7da78b1f 1816\r
0d92cdc2 1817 if (This == NULL) {\r
1818 return EFI_INVALID_PARAMETER;\r
1819 }\r
7da78b1f 1820\r
0d92cdc2 1821 if (ModeNumber >= This->Mode->MaxMode) {\r
1822 return EFI_UNSUPPORTED;\r
1823 }\r
7da78b1f 1824\r
0d92cdc2 1825 if (ModeNumber == This->Mode->Mode) {\r
1826 return EFI_SUCCESS;\r
1827 }\r
7da78b1f 1828\r
0d92cdc2 1829 ModeData = &BiosVideoPrivate->ModeData[ModeNumber];\r
7da78b1f 1830\r
0d92cdc2 1831 if (BiosVideoPrivate->LineBuffer) {\r
1832 gBS->FreePool (BiosVideoPrivate->LineBuffer);\r
1833 }\r
7da78b1f 1834\r
0d92cdc2 1835 if (BiosVideoPrivate->VgaFrameBuffer) {\r
1836 gBS->FreePool (BiosVideoPrivate->VgaFrameBuffer);\r
1837 }\r
7da78b1f 1838\r
0d92cdc2 1839 if (BiosVideoPrivate->VbeFrameBuffer) {\r
1840 gBS->FreePool (BiosVideoPrivate->VbeFrameBuffer);\r
1841 }\r
7da78b1f 1842\r
0d92cdc2 1843 BiosVideoPrivate->LineBuffer = NULL;\r
1844 Status = gBS->AllocatePool (\r
1845 EfiBootServicesData,\r
1846 ModeData->BytesPerScanLine,\r
1847 &BiosVideoPrivate->LineBuffer\r
1848 );\r
1849 if (EFI_ERROR (Status)) {\r
1850 return Status;\r
1851 }\r
1852 //\r
1853 // Clear all registers\r
1854 //\r
1855 gBS->SetMem (&Regs, sizeof (Regs), 0);\r
7da78b1f 1856\r
0d92cdc2 1857 if (ModeData->VbeModeNumber < 0x100) {\r
1858 //\r
1859 // Allocate a working buffer for BLT operations to the VGA frame buffer\r
1860 //\r
1861 BiosVideoPrivate->VgaFrameBuffer = NULL;\r
7da78b1f 1862 Status = gBS->AllocatePool (\r
1863 EfiBootServicesData,\r
0d92cdc2 1864 4 * 480 * 80,\r
1865 &BiosVideoPrivate->VgaFrameBuffer\r
7da78b1f 1866 );\r
1867 if (EFI_ERROR (Status)) {\r
1868 return Status;\r
1869 }\r
1870 //\r
0d92cdc2 1871 // Set VGA Mode\r
7da78b1f 1872 //\r
0d92cdc2 1873 Regs.X.AX = ModeData->VbeModeNumber;\r
1874 LegacyBiosInt86 (BiosVideoPrivate, 0x10, &Regs);\r
7da78b1f 1875\r
0d92cdc2 1876 } else {\r
1877 //\r
1878 // Allocate a working buffer for BLT operations to the VBE frame buffer\r
1879 //\r
1880 BiosVideoPrivate->VbeFrameBuffer = NULL;\r
1881 Status = gBS->AllocatePool (\r
1882 EfiBootServicesData,\r
1883 ModeData->BytesPerScanLine * ModeData->VerticalResolution,\r
1884 &BiosVideoPrivate->VbeFrameBuffer\r
1885 );\r
1886 if (EFI_ERROR (Status)) {\r
1887 return Status;\r
1888 }\r
1889 //\r
1890 // Set VBE mode\r
1891 //\r
1892 Regs.X.AX = VESA_BIOS_EXTENSIONS_SET_MODE;\r
1893 Regs.X.BX = (UINT16) (ModeData->VbeModeNumber | VESA_BIOS_EXTENSIONS_MODE_NUMBER_LINEAR_FRAME_BUFFER);\r
1894 gBS->SetMem (BiosVideoPrivate->VbeCrtcInformationBlock, sizeof (VESA_BIOS_EXTENSIONS_CRTC_INFORMATION_BLOCK), 0);\r
1895 Regs.X.ES = EFI_SEGMENT ((UINTN) BiosVideoPrivate->VbeCrtcInformationBlock);\r
1896 Regs.X.DI = EFI_OFFSET ((UINTN) BiosVideoPrivate->VbeCrtcInformationBlock);\r
1897 LegacyBiosInt86 (BiosVideoPrivate, 0x10, &Regs);\r
1898 \r
1899 //\r
1900 // Check to see if the call succeeded\r
1901 //\r
1902 if (Regs.X.AX != VESA_BIOS_EXTENSIONS_STATUS_SUCCESS) {\r
1903 return EFI_DEVICE_ERROR;\r
1904 }\r
1905 //\r
1906 // Initialize the state of the VbeFrameBuffer\r
1907 //\r
1908 Status = BiosVideoPrivate->PciIo->Mem.Read (\r
1909 BiosVideoPrivate->PciIo,\r
1910 EfiPciIoWidthUint32,\r
1911 EFI_PCI_IO_PASS_THROUGH_BAR,\r
1912 (UINT64) (UINTN) ModeData->LinearFrameBuffer,\r
1913 (ModeData->BytesPerScanLine * ModeData->VerticalResolution) >> 2,\r
1914 BiosVideoPrivate->VbeFrameBuffer\r
1915 );\r
1916 if (EFI_ERROR (Status)) {\r
1917 return Status;\r
7da78b1f 1918 }\r
0d92cdc2 1919 }\r
7da78b1f 1920\r
0d92cdc2 1921 This->Mode->Mode = ModeNumber;\r
1922 This->Mode->Info->Version = 0;\r
1923 This->Mode->Info->HorizontalResolution = ModeData->HorizontalResolution;\r
1924 This->Mode->Info->VerticalResolution = ModeData->VerticalResolution;\r
1925 This->Mode->Info->PixelFormat = ModeData->PixelFormat;\r
1926 This->Mode->Info->PixelInformation = ModeData->PixelBitMask;\r
1927 This->Mode->Info->PixelsPerScanLine = (ModeData->BytesPerScanLine * 8) / ModeData->BitsPerPixel;\r
1928 This->Mode->SizeOfInfo = sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);\r
7da78b1f 1929\r
0d92cdc2 1930 //\r
1931 // Frame BufferSize remain unchanged\r
1932 //\r
1933 This->Mode->FrameBufferBase = (EFI_PHYSICAL_ADDRESS) ModeData->LinearFrameBuffer;\r
1934 This->Mode->FrameBufferSize = ModeData->FrameBufferSize;\r
7da78b1f 1935\r
0d92cdc2 1936 BiosVideoPrivate->HardwareNeedsStarting = FALSE;\r
7da78b1f 1937\r
0d92cdc2 1938 return EFI_SUCCESS;\r
7da78b1f 1939}\r
1940\r
1941VOID\r
1942CopyVideoBuffer (\r
1943 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
1944 IN UINT8 *VbeBuffer,\r
1945 IN VOID *MemAddress,\r
1946 IN UINTN DestinationX,\r
1947 IN UINTN DestinationY,\r
1948 IN UINTN TotalBytes,\r
1949 IN UINT32 VbePixelWidth,\r
1950 IN UINTN BytesPerScanLine\r
1951 )\r
1952/*++\r
1953\r
1954Routine Description:\r
1955\r
1956 Update physical frame buffer, copy 4 bytes block, then copy remaining bytes.\r
1957\r
1958Arguments:\r
1959\r
1960 PciIo - The pointer of EFI_PCI_IO_PROTOCOL\r
1961 VbeBuffer - The data to transfer to screen\r
1962 MemAddress - Physical frame buffer base address\r
1963 DestinationX - The X coordinate of the destination for BltOperation\r
1964 DestinationY - The Y coordinate of the destination for BltOperation\r
1965 TotalBytes - The total bytes of copy\r
1966 VbePixelWidth - Bytes per pixel\r
1967 BytesPerScanLine - Bytes per scan line\r
1968\r
1969Returns:\r
1970\r
1971 None.\r
1972\r
1973--*/\r
1974{\r
1975 UINTN FrameBufferAddr;\r
1976 UINTN CopyBlockNum;\r
1977 UINTN RemainingBytes;\r
1978 UINTN UnalignedBytes;\r
1979 EFI_STATUS Status;\r
1980\r
1981 FrameBufferAddr = (UINTN) MemAddress + (DestinationY * BytesPerScanLine) + DestinationX * VbePixelWidth;\r
1982\r
1983 //\r
1984 // If TotalBytes is less than 4 bytes, only start byte copy.\r
1985 //\r
1986 if (TotalBytes < 4) {\r
1987 Status = PciIo->Mem.Write (\r
1988 PciIo,\r
1989 EfiPciIoWidthUint8,\r
1990 EFI_PCI_IO_PASS_THROUGH_BAR,\r
1991 (UINT64) FrameBufferAddr,\r
1992 TotalBytes,\r
1993 VbeBuffer\r
1994 );\r
1995 ASSERT_EFI_ERROR (Status);\r
1996 return;\r
1997 }\r
1998\r
1999 //\r
2000 // If VbeBuffer is not 4-byte aligned, start byte copy.\r
2001 //\r
2002 UnalignedBytes = (4 - ((UINTN) VbeBuffer & 0x3)) & 0x3;\r
2003\r
2004 if (UnalignedBytes != 0) {\r
2005 Status = PciIo->Mem.Write (\r
2006 PciIo,\r
2007 EfiPciIoWidthUint8,\r
2008 EFI_PCI_IO_PASS_THROUGH_BAR,\r
2009 (UINT64) FrameBufferAddr,\r
2010 UnalignedBytes,\r
2011 VbeBuffer\r
2012 );\r
2013 ASSERT_EFI_ERROR (Status);\r
2014 FrameBufferAddr += UnalignedBytes;\r
2015 VbeBuffer += UnalignedBytes;\r
2016 }\r
2017\r
2018 //\r
2019 // Calculate 4-byte block count and remaining bytes.\r
2020 //\r
2021 CopyBlockNum = (TotalBytes - UnalignedBytes) >> 2;\r
2022 RemainingBytes = (TotalBytes - UnalignedBytes) & 3;\r
2023\r
2024 //\r
2025 // Copy 4-byte block and remaining bytes to physical frame buffer.\r
2026 //\r
2027 if (CopyBlockNum != 0) {\r
2028 Status = PciIo->Mem.Write (\r
2029 PciIo,\r
2030 EfiPciIoWidthUint32,\r
2031 EFI_PCI_IO_PASS_THROUGH_BAR,\r
2032 (UINT64) FrameBufferAddr,\r
2033 CopyBlockNum,\r
2034 VbeBuffer\r
2035 );\r
2036 ASSERT_EFI_ERROR (Status);\r
2037 }\r
2038\r
2039 if (RemainingBytes != 0) {\r
2040 FrameBufferAddr += (CopyBlockNum << 2);\r
2041 VbeBuffer += (CopyBlockNum << 2);\r
2042 Status = PciIo->Mem.Write (\r
2043 PciIo,\r
2044 EfiPciIoWidthUint8,\r
2045 EFI_PCI_IO_PASS_THROUGH_BAR,\r
2046 (UINT64) FrameBufferAddr,\r
2047 RemainingBytes,\r
2048 VbeBuffer\r
2049 );\r
2050 ASSERT_EFI_ERROR (Status);\r
2051 }\r
2052}\r
2053\r
2054//\r
2055// BUGBUG : Add Blt for 16 bit color, 15 bit color, and 8 bit color modes\r
2056//\r
2057EFI_STATUS\r
2058EFIAPI\r
0d92cdc2 2059BiosVideoGraphicsOutputVbeBlt (\r
2060 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,\r
2061 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL\r
2062 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,\r
2063 IN UINTN SourceX,\r
2064 IN UINTN SourceY,\r
2065 IN UINTN DestinationX,\r
2066 IN UINTN DestinationY,\r
2067 IN UINTN Width,\r
2068 IN UINTN Height,\r
2069 IN UINTN Delta\r
7da78b1f 2070 )\r
2071/*++\r
2072\r
2073Routine Description:\r
2074\r
0d92cdc2 2075 Graphics Output protocol instance to block transfer for VBE device\r
7da78b1f 2076\r
2077Arguments:\r
2078\r
0d92cdc2 2079 This - Pointer to Graphics Output protocol instance\r
7da78b1f 2080 BltBuffer - The data to transfer to screen\r
2081 BltOperation - The operation to perform\r
2082 SourceX - The X coordinate of the source for BltOperation\r
2083 SourceY - The Y coordinate of the source for BltOperation\r
2084 DestinationX - The X coordinate of the destination for BltOperation\r
2085 DestinationY - The Y coordinate of the destination for BltOperation\r
2086 Width - The width of a rectangle in the blt rectangle in pixels\r
2087 Height - The height of a rectangle in the blt rectangle in pixels\r
0d92cdc2 2088 Delta - Not used for EfiBltVideoFill and EfiBltVideoToVideo operation.\r
7da78b1f 2089 If a Delta of 0 is used, the entire BltBuffer will be operated on.\r
0d92cdc2 2090 If a subrectangle of the BltBuffer is used, then Delta represents\r
7da78b1f 2091 the number of bytes in a row of the BltBuffer.\r
2092\r
2093Returns:\r
2094\r
2095 EFI_INVALID_PARAMETER - Invalid parameter passed in\r
2096 EFI_SUCCESS - Blt operation success\r
2097\r
2098--*/\r
2099{\r
0d92cdc2 2100 BIOS_VIDEO_DEV *BiosVideoPrivate;\r
2101 BIOS_VIDEO_MODE_DATA *Mode;\r
2102 EFI_PCI_IO_PROTOCOL *PciIo;\r
2103 EFI_TPL OriginalTPL;\r
2104 UINTN DstY;\r
2105 UINTN SrcY;\r
2106 UINTN DstX;\r
2107 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt;\r
2108 VOID *MemAddress;\r
2109 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *VbeFrameBuffer;\r
2110 UINTN BytesPerScanLine;\r
2111 UINTN Index;\r
2112 UINT8 *VbeBuffer;\r
2113 UINT8 *VbeBuffer1;\r
2114 UINT8 *BltUint8;\r
2115 UINT32 VbePixelWidth;\r
2116 UINT32 Pixel;\r
2117 UINTN TotalBytes;\r
2118\r
2119 BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This);\r
2120 Mode = &BiosVideoPrivate->ModeData[This->Mode->Mode];\r
7da78b1f 2121 PciIo = BiosVideoPrivate->PciIo;\r
2122\r
2123 VbeFrameBuffer = BiosVideoPrivate->VbeFrameBuffer;\r
2124 MemAddress = Mode->LinearFrameBuffer;\r
2125 BytesPerScanLine = Mode->BytesPerScanLine;\r
2126 VbePixelWidth = Mode->BitsPerPixel / 8;\r
2127 BltUint8 = (UINT8 *) BltBuffer;\r
2128 TotalBytes = Width * VbePixelWidth;\r
2129\r
0d92cdc2 2130 if (This == NULL || ((UINTN) BltOperation) >= EfiGraphicsOutputBltOperationMax) {\r
7da78b1f 2131 return EFI_INVALID_PARAMETER;\r
2132 }\r
2133\r
2134 if (Width == 0 || Height == 0) {\r
2135 return EFI_INVALID_PARAMETER;\r
2136 }\r
2137 //\r
2138 // We need to fill the Virtual Screen buffer with the blt data.\r
2139 // The virtual screen is upside down, as the first row is the bootom row of\r
2140 // the image.\r
2141 //\r
0d92cdc2 2142 if (BltOperation == EfiBltVideoToBltBuffer) {\r
7da78b1f 2143 //\r
2144 // Video to BltBuffer: Source is Video, destination is BltBuffer\r
2145 //\r
2146 if (SourceY + Height > Mode->VerticalResolution) {\r
2147 return EFI_INVALID_PARAMETER;\r
2148 }\r
2149\r
2150 if (SourceX + Width > Mode->HorizontalResolution) {\r
2151 return EFI_INVALID_PARAMETER;\r
2152 }\r
2153 } else {\r
2154 //\r
2155 // BltBuffer to Video: Source is BltBuffer, destination is Video\r
2156 //\r
2157 if (DestinationY + Height > Mode->VerticalResolution) {\r
2158 return EFI_INVALID_PARAMETER;\r
2159 }\r
2160\r
2161 if (DestinationX + Width > Mode->HorizontalResolution) {\r
2162 return EFI_INVALID_PARAMETER;\r
2163 }\r
2164 }\r
2165 //\r
2166 // If Delta is zero, then the entire BltBuffer is being used, so Delta\r
2167 // is the number of bytes in each row of BltBuffer. Since BltBuffer is Width pixels size,\r
2168 // the number of bytes in each row can be computed.\r
2169 //\r
2170 if (Delta == 0) {\r
0d92cdc2 2171 Delta = Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);\r
7da78b1f 2172 }\r
2173 //\r
2174 // We have to raise to TPL Notify, so we make an atomic write the frame buffer.\r
2175 // We would not want a timer based event (Cursor, ...) to come in while we are\r
2176 // doing this operation.\r
2177 //\r
2178 OriginalTPL = gBS->RaiseTPL (TPL_NOTIFY);\r
2179\r
2180 switch (BltOperation) {\r
0d92cdc2 2181 case EfiBltVideoToBltBuffer:\r
7da78b1f 2182 for (SrcY = SourceY, DstY = DestinationY; DstY < (Height + DestinationY); SrcY++, DstY++) {\r
0d92cdc2 2183 Blt = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) (BltUint8 + DstY * Delta + DestinationX * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));\r
7da78b1f 2184 //\r
0d92cdc2 2185 // Shuffle the packed bytes in the hardware buffer to match EFI_GRAPHICS_OUTPUT_BLT_PIXEL\r
7da78b1f 2186 //\r
2187 VbeBuffer = ((UINT8 *) VbeFrameBuffer + (SrcY * BytesPerScanLine + SourceX * VbePixelWidth));\r
2188 for (DstX = DestinationX; DstX < (Width + DestinationX); DstX++) {\r
2189 Pixel = *(UINT32 *) (VbeBuffer);\r
2190 Blt->Red = (UINT8) ((Pixel >> Mode->Red.Position) & Mode->Red.Mask);\r
2191 Blt->Blue = (UINT8) ((Pixel >> Mode->Blue.Position) & Mode->Blue.Mask);\r
2192 Blt->Green = (UINT8) ((Pixel >> Mode->Green.Position) & Mode->Green.Mask);\r
2193 Blt->Reserved = 0;\r
2194 Blt++;\r
2195 VbeBuffer += VbePixelWidth;\r
2196 }\r
2197\r
2198 }\r
2199 break;\r
2200\r
0d92cdc2 2201 case EfiBltVideoToVideo:\r
7da78b1f 2202 for (Index = 0; Index < Height; Index++) {\r
2203 if (DestinationY <= SourceY) {\r
2204 SrcY = SourceY + Index;\r
2205 DstY = DestinationY + Index;\r
2206 } else {\r
2207 SrcY = SourceY + Height - Index - 1;\r
2208 DstY = DestinationY + Height - Index - 1;\r
2209 }\r
2210\r
2211 VbeBuffer = ((UINT8 *) VbeFrameBuffer + DstY * BytesPerScanLine + DestinationX * VbePixelWidth);\r
2212 VbeBuffer1 = ((UINT8 *) VbeFrameBuffer + SrcY * BytesPerScanLine + SourceX * VbePixelWidth);\r
2213\r
2214 gBS->CopyMem (\r
2215 VbeBuffer,\r
2216 VbeBuffer1,\r
2217 TotalBytes\r
2218 );\r
2219\r
2220 //\r
2221 // Update physical frame buffer.\r
2222 //\r
2223 CopyVideoBuffer (\r
2224 PciIo,\r
2225 VbeBuffer,\r
2226 MemAddress,\r
2227 DestinationX,\r
2228 DstY,\r
2229 TotalBytes,\r
2230 VbePixelWidth,\r
2231 BytesPerScanLine\r
2232 );\r
2233 }\r
2234 break;\r
2235\r
0d92cdc2 2236 case EfiBltVideoFill:\r
7da78b1f 2237 VbeBuffer = (UINT8 *) ((UINTN) VbeFrameBuffer + (DestinationY * BytesPerScanLine) + DestinationX * VbePixelWidth);\r
0d92cdc2 2238 Blt = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) BltUint8;\r
7da78b1f 2239 //\r
0d92cdc2 2240 // Shuffle the RGB fields in EFI_GRAPHICS_OUTPUT_BLT_PIXEL to match the hardware buffer\r
7da78b1f 2241 //\r
2242 Pixel = ((Blt->Red & Mode->Red.Mask) << Mode->Red.Position) |\r
2243 (\r
2244 (Blt->Green & Mode->Green.Mask) <<\r
2245 Mode->Green.Position\r
2246 ) |\r
2247 ((Blt->Blue & Mode->Blue.Mask) << Mode->Blue.Position);\r
2248\r
2249 for (Index = 0; Index < Width; Index++) {\r
2250 gBS->CopyMem (\r
2251 VbeBuffer,\r
2252 &Pixel,\r
2253 VbePixelWidth\r
2254 );\r
2255 VbeBuffer += VbePixelWidth;\r
2256 }\r
2257\r
2258 VbeBuffer = (UINT8 *) ((UINTN) VbeFrameBuffer + (DestinationY * BytesPerScanLine) + DestinationX * VbePixelWidth);\r
2259 for (DstY = DestinationY + 1; DstY < (Height + DestinationY); DstY++) {\r
2260 gBS->CopyMem (\r
2261 (VOID *) ((UINTN) VbeFrameBuffer + (DstY * BytesPerScanLine) + DestinationX * VbePixelWidth),\r
2262 VbeBuffer,\r
2263 TotalBytes\r
2264 );\r
2265 }\r
2266 for (DstY = DestinationY; DstY < (Height + DestinationY); DstY++) {\r
2267 //\r
2268 // Update physical frame buffer.\r
2269 //\r
2270 CopyVideoBuffer (\r
2271 PciIo,\r
2272 VbeBuffer,\r
2273 MemAddress,\r
2274 DestinationX,\r
2275 DstY,\r
2276 TotalBytes,\r
2277 VbePixelWidth,\r
2278 BytesPerScanLine\r
2279 );\r
2280 }\r
7da78b1f 2281 break;\r
2282\r
0d92cdc2 2283 case EfiBltBufferToVideo:\r
7da78b1f 2284 for (SrcY = SourceY, DstY = DestinationY; SrcY < (Height + SourceY); SrcY++, DstY++) {\r
0d92cdc2 2285 Blt = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) (BltUint8 + (SrcY * Delta) + (SourceX) * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));\r
7da78b1f 2286 VbeBuffer = ((UINT8 *) VbeFrameBuffer + (DstY * BytesPerScanLine + DestinationX * VbePixelWidth));\r
2287 for (DstX = DestinationX; DstX < (Width + DestinationX); DstX++) {\r
2288 //\r
0d92cdc2 2289 // Shuffle the RGB fields in EFI_GRAPHICS_OUTPUT_BLT_PIXEL to match the hardware buffer\r
7da78b1f 2290 //\r
2291 Pixel = ((Blt->Red & Mode->Red.Mask) << Mode->Red.Position) |\r
2292 ((Blt->Green & Mode->Green.Mask) << Mode->Green.Position) |\r
2293 ((Blt->Blue & Mode->Blue.Mask) << Mode->Blue.Position);\r
2294 gBS->CopyMem (\r
2295 VbeBuffer,\r
2296 &Pixel,\r
2297 VbePixelWidth\r
2298 );\r
2299 Blt++;\r
2300 VbeBuffer += VbePixelWidth;\r
2301 }\r
2302\r
2303 VbeBuffer = ((UINT8 *) VbeFrameBuffer + (DstY * BytesPerScanLine + DestinationX * VbePixelWidth));\r
2304\r
2305 //\r
2306 // Update physical frame buffer.\r
2307 //\r
2308 CopyVideoBuffer (\r
2309 PciIo,\r
2310 VbeBuffer,\r
2311 MemAddress,\r
2312 DestinationX,\r
2313 DstY,\r
2314 TotalBytes,\r
2315 VbePixelWidth,\r
2316 BytesPerScanLine\r
2317 );\r
2318 }\r
2319 break;\r
2320 }\r
2321\r
2322 gBS->RestoreTPL (OriginalTPL);\r
2323\r
2324 return EFI_SUCCESS;\r
2325}\r
2326\r
2327STATIC\r
2328VOID\r
2329WriteGraphicsController (\r
2330 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
2331 IN UINTN Address,\r
2332 IN UINTN Data\r
2333 )\r
2334/*++\r
2335\r
2336Routine Description:\r
2337\r
2338 Write graphics controller registers\r
2339\r
2340Arguments:\r
2341\r
2342 PciIo - Pointer to PciIo protocol instance of the controller\r
2343 Address - Register address\r
2344 Data - Data to be written to register\r
2345\r
2346Returns:\r
2347\r
2348 None\r
2349\r
2350--*/\r
2351{\r
2352 Address = Address | (Data << 8);\r
2353 PciIo->Io.Write (\r
2354 PciIo,\r
2355 EfiPciIoWidthUint16,\r
2356 EFI_PCI_IO_PASS_THROUGH_BAR,\r
2357 VGA_GRAPHICS_CONTROLLER_ADDRESS_REGISTER,\r
2358 1,\r
2359 &Address\r
2360 );\r
2361}\r
2362\r
2363VOID\r
2364VgaReadBitPlanes (\r
2365 EFI_PCI_IO_PROTOCOL *PciIo,\r
2366 UINT8 *HardwareBuffer,\r
2367 UINT8 *MemoryBuffer,\r
2368 UINTN WidthInBytes,\r
2369 UINTN Height\r
2370 )\r
2371/*++\r
2372\r
2373Routine Description:\r
2374\r
2375 Read the four bit plane of VGA frame buffer\r
2376\r
2377Arguments:\r
2378\r
2379 PciIo - Pointer to PciIo protocol instance of the controller\r
2380 HardwareBuffer - Hardware VGA frame buffer address\r
2381 MemoryBuffer - Memory buffer address\r
2382 WidthInBytes - Number of bytes in a line to read\r
2383 Height - Height of the area to read\r
2384\r
2385Returns:\r
2386\r
2387 None\r
2388\r
2389--*/\r
2390{\r
2391 UINTN BitPlane;\r
2392 UINTN Rows;\r
2393 UINTN FrameBufferOffset;\r
2394 UINT8 *Source;\r
2395 UINT8 *Destination;\r
2396\r
2397 //\r
2398 // Program the Mode Register Write mode 0, Read mode 0\r
2399 //\r
2400 WriteGraphicsController (\r
2401 PciIo,\r
2402 VGA_GRAPHICS_CONTROLLER_MODE_REGISTER,\r
2403 VGA_GRAPHICS_CONTROLLER_READ_MODE_0 | VGA_GRAPHICS_CONTROLLER_WRITE_MODE_0\r
2404 );\r
2405\r
2406 for (BitPlane = 0, FrameBufferOffset = 0;\r
2407 BitPlane < VGA_NUMBER_OF_BIT_PLANES;\r
2408 BitPlane++, FrameBufferOffset += VGA_BYTES_PER_BIT_PLANE\r
2409 ) {\r
2410 //\r
2411 // Program the Read Map Select Register to select the correct bit plane\r
2412 //\r
2413 WriteGraphicsController (\r
2414 PciIo,\r
2415 VGA_GRAPHICS_CONTROLLER_READ_MAP_SELECT_REGISTER,\r
2416 BitPlane\r
2417 );\r
2418\r
2419 Source = HardwareBuffer;\r
2420 Destination = MemoryBuffer + FrameBufferOffset;\r
2421\r
2422 for (Rows = 0; Rows < Height; Rows++, Source += VGA_BYTES_PER_SCAN_LINE, Destination += VGA_BYTES_PER_SCAN_LINE) {\r
2423 PciIo->Mem.Read (\r
2424 PciIo,\r
2425 EfiPciIoWidthUint8,\r
2426 EFI_PCI_IO_PASS_THROUGH_BAR,\r
0d92cdc2 2427 (UINT64) Source,\r
7da78b1f 2428 WidthInBytes,\r
2429 (VOID *) Destination\r
2430 );\r
2431 }\r
2432 }\r
2433}\r
2434\r
2435VOID\r
0d92cdc2 2436VgaConvertToGraphicsOutputColor (\r
2437 UINT8 *MemoryBuffer,\r
2438 UINTN X,\r
2439 UINTN Y,\r
2440 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer\r
7da78b1f 2441 )\r
2442/*++\r
2443\r
2444Routine Description:\r
2445\r
0d92cdc2 2446 Internal routine to convert VGA color to Grahpics Output color\r
7da78b1f 2447\r
2448Arguments:\r
2449\r
2450 MemoryBuffer - Buffer containing VGA color\r
2451 X - The X coordinate of pixel on screen\r
2452 Y - The Y coordinate of pixel on screen\r
0d92cdc2 2453 BltBuffer - Buffer to contain converted Grahpics Output color\r
7da78b1f 2454\r
2455Returns:\r
2456\r
2457 None\r
2458\r
2459--*/\r
2460{\r
2461 UINTN Mask;\r
2462 UINTN Bit;\r
2463 UINTN Color;\r
2464\r
2465 MemoryBuffer += ((Y << 6) + (Y << 4) + (X >> 3));\r
2466 Mask = mVgaBitMaskTable[X & 0x07];\r
2467 for (Bit = 0x01, Color = 0; Bit < 0x10; Bit <<= 1, MemoryBuffer += VGA_BYTES_PER_BIT_PLANE) {\r
2468 if (*MemoryBuffer & Mask) {\r
2469 Color |= Bit;\r
2470 }\r
2471 }\r
2472\r
0d92cdc2 2473 *BltBuffer = mVgaColorToGraphicsOutputColor[Color];\r
7da78b1f 2474}\r
2475\r
2476UINT8\r
2477VgaConvertColor (\r
0d92cdc2 2478 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer\r
7da78b1f 2479 )\r
2480/*++\r
2481\r
2482Routine Description:\r
2483\r
0d92cdc2 2484 Internal routine to convert Grahpics Output color to VGA color\r
7da78b1f 2485\r
2486Arguments:\r
2487\r
0d92cdc2 2488 BltBuffer - buffer containing Grahpics Output color\r
7da78b1f 2489\r
2490Returns:\r
2491\r
2492 Converted VGA color\r
2493\r
2494--*/\r
2495{\r
2496 UINT8 Color;\r
2497\r
2498 Color = (UINT8) ((BltBuffer->Blue >> 7) | ((BltBuffer->Green >> 6) & 0x02) | ((BltBuffer->Red >> 5) & 0x04));\r
2499 if ((BltBuffer->Red + BltBuffer->Green + BltBuffer->Blue) > 0x180) {\r
2500 Color |= 0x08;\r
2501 }\r
2502\r
2503 return Color;\r
2504}\r
2505\r
2506EFI_STATUS\r
2507EFIAPI\r
0d92cdc2 2508BiosVideoGraphicsOutputVgaBlt (\r
2509 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,\r
2510 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL\r
2511 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,\r
2512 IN UINTN SourceX,\r
2513 IN UINTN SourceY,\r
2514 IN UINTN DestinationX,\r
2515 IN UINTN DestinationY,\r
2516 IN UINTN Width,\r
2517 IN UINTN Height,\r
2518 IN UINTN Delta\r
7da78b1f 2519 )\r
2520/*++\r
2521\r
2522Routine Description:\r
2523\r
0d92cdc2 2524 Grahpics Output protocol instance to block transfer for VGA device\r
7da78b1f 2525\r
2526Arguments:\r
2527\r
0d92cdc2 2528 This - Pointer to Grahpics Output protocol instance\r
7da78b1f 2529 BltBuffer - The data to transfer to screen\r
2530 BltOperation - The operation to perform\r
2531 SourceX - The X coordinate of the source for BltOperation\r
2532 SourceY - The Y coordinate of the source for BltOperation\r
2533 DestinationX - The X coordinate of the destination for BltOperation\r
2534 DestinationY - The Y coordinate of the destination for BltOperation\r
2535 Width - The width of a rectangle in the blt rectangle in pixels\r
2536 Height - The height of a rectangle in the blt rectangle in pixels\r
0d92cdc2 2537 Delta - Not used for EfiBltVideoFill and EfiBltVideoToVideo operation.\r
7da78b1f 2538 If a Delta of 0 is used, the entire BltBuffer will be operated on.\r
0d92cdc2 2539 If a subrectangle of the BltBuffer is used, then Delta represents\r
7da78b1f 2540 the number of bytes in a row of the BltBuffer.\r
2541\r
2542Returns:\r
2543\r
2544 EFI_INVALID_PARAMETER - Invalid parameter passed in\r
2545 EFI_SUCCESS - Blt operation success\r
2546\r
2547--*/\r
2548{\r
2549 BIOS_VIDEO_DEV *BiosVideoPrivate;\r
2550 EFI_TPL OriginalTPL;\r
2551 UINT8 *MemAddress;\r
2552 UINTN BytesPerScanLine;\r
2553 UINTN BytesPerBitPlane;\r
2554 UINTN Bit;\r
2555 UINTN Index;\r
2556 UINTN Index1;\r
2557 UINTN StartAddress;\r
2558 UINTN Bytes;\r
2559 UINTN Offset;\r
2560 UINT8 LeftMask;\r
2561 UINT8 RightMask;\r
2562 UINTN Address;\r
2563 UINTN AddressFix;\r
2564 UINT8 *Address1;\r
2565 UINT8 *SourceAddress;\r
2566 UINT8 *DestinationAddress;\r
2567 EFI_PCI_IO_PROTOCOL *PciIo;\r
2568 UINT8 Data;\r
2569 UINT8 PixelColor;\r
2570 UINT8 *VgaFrameBuffer;\r
2571 UINTN SourceOffset;\r
2572 UINTN SourceWidth;\r
2573 UINTN Rows;\r
2574 UINTN Columns;\r
2575 UINTN X;\r
2576 UINTN Y;\r
0d92cdc2 2577 UINTN CurrentMode;\r
7da78b1f 2578\r
0d92cdc2 2579 BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This);\r
7da78b1f 2580\r
0d92cdc2 2581 CurrentMode = This->Mode->Mode;\r
7da78b1f 2582 PciIo = BiosVideoPrivate->PciIo;\r
0d92cdc2 2583 MemAddress = BiosVideoPrivate->ModeData[CurrentMode].LinearFrameBuffer;\r
2584 BytesPerScanLine = BiosVideoPrivate->ModeData[CurrentMode].BytesPerScanLine >> 3;\r
2585 BytesPerBitPlane = BytesPerScanLine * BiosVideoPrivate->ModeData[CurrentMode].VerticalResolution;\r
7da78b1f 2586 VgaFrameBuffer = BiosVideoPrivate->VgaFrameBuffer;\r
2587\r
0d92cdc2 2588 if (This == NULL || ((UINTN) BltOperation) >= EfiGraphicsOutputBltOperationMax) {\r
7da78b1f 2589 return EFI_INVALID_PARAMETER;\r
2590 }\r
2591\r
2592 if (Width == 0 || Height == 0) {\r
2593 return EFI_INVALID_PARAMETER;\r
2594 }\r
2595 //\r
2596 // We need to fill the Virtual Screen buffer with the blt data.\r
2597 // The virtual screen is upside down, as the first row is the bootom row of\r
2598 // the image.\r
2599 //\r
0d92cdc2 2600 if (BltOperation == EfiBltVideoToBltBuffer) {\r
7da78b1f 2601 //\r
2602 // Video to BltBuffer: Source is Video, destination is BltBuffer\r
2603 //\r
0d92cdc2 2604 if (SourceY + Height > BiosVideoPrivate->ModeData[CurrentMode].VerticalResolution) {\r
7da78b1f 2605 return EFI_INVALID_PARAMETER;\r
2606 }\r
2607\r
0d92cdc2 2608 if (SourceX + Width > BiosVideoPrivate->ModeData[CurrentMode].HorizontalResolution) {\r
7da78b1f 2609 return EFI_INVALID_PARAMETER;\r
2610 }\r
2611 } else {\r
2612 //\r
2613 // BltBuffer to Video: Source is BltBuffer, destination is Video\r
2614 //\r
0d92cdc2 2615 if (DestinationY + Height > BiosVideoPrivate->ModeData[CurrentMode].VerticalResolution) {\r
7da78b1f 2616 return EFI_INVALID_PARAMETER;\r
2617 }\r
2618\r
0d92cdc2 2619 if (DestinationX + Width > BiosVideoPrivate->ModeData[CurrentMode].HorizontalResolution) {\r
7da78b1f 2620 return EFI_INVALID_PARAMETER;\r
2621 }\r
2622 }\r
2623 //\r
2624 // If Delta is zero, then the entire BltBuffer is being used, so Delta\r
2625 // is the number of bytes in each row of BltBuffer. Since BltBuffer is Width pixels size,\r
2626 // the number of bytes in each row can be computed.\r
2627 //\r
2628 if (Delta == 0) {\r
0d92cdc2 2629 Delta = Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);\r
7da78b1f 2630 }\r
2631 //\r
2632 // We have to raise to TPL Notify, so we make an atomic write the frame buffer.\r
2633 // We would not want a timer based event (Cursor, ...) to come in while we are\r
2634 // doing this operation.\r
2635 //\r
2636 OriginalTPL = gBS->RaiseTPL (TPL_NOTIFY);\r
2637\r
2638 //\r
2639 // Compute some values we need for VGA\r
2640 //\r
2641 switch (BltOperation) {\r
0d92cdc2 2642 case EfiBltVideoToBltBuffer:\r
7da78b1f 2643\r
2644 SourceOffset = (SourceY << 6) + (SourceY << 4) + (SourceX >> 3);\r
2645 SourceWidth = ((SourceX + Width - 1) >> 3) - (SourceX >> 3) + 1;\r
2646\r
2647 //\r
2648 // Read all the pixels in the 4 bit planes into a memory buffer that looks like the VGA buffer\r
2649 //\r
2650 VgaReadBitPlanes (\r
2651 PciIo,\r
2652 MemAddress + SourceOffset,\r
2653 VgaFrameBuffer + SourceOffset,\r
2654 SourceWidth,\r
2655 Height\r
2656 );\r
2657\r
2658 //\r
0d92cdc2 2659 // Convert VGA Bit Planes to a Graphics Output 32-bit color value\r
7da78b1f 2660 //\r
2661 BltBuffer += (DestinationY * (Delta >> 2) + DestinationX);\r
2662 for (Rows = 0, Y = SourceY; Rows < Height; Rows++, Y++, BltBuffer += (Delta >> 2)) {\r
2663 for (Columns = 0, X = SourceX; Columns < Width; Columns++, X++, BltBuffer++) {\r
0d92cdc2 2664 VgaConvertToGraphicsOutputColor (VgaFrameBuffer, X, Y, BltBuffer);\r
7da78b1f 2665 }\r
2666\r
2667 BltBuffer -= Width;\r
2668 }\r
2669\r
2670 break;\r
2671\r
0d92cdc2 2672 case EfiBltVideoToVideo:\r
7da78b1f 2673 //\r
2674 // Check for an aligned Video to Video operation\r
2675 //\r
2676 if ((SourceX & 0x07) == 0x00 && (DestinationX & 0x07) == 0x00 && (Width & 0x07) == 0x00) {\r
2677 //\r
2678 // Program the Mode Register Write mode 1, Read mode 0\r
2679 //\r
2680 WriteGraphicsController (\r
0d92cdc2 2681 PciIo,\r
7da78b1f 2682 VGA_GRAPHICS_CONTROLLER_MODE_REGISTER,\r
2683 VGA_GRAPHICS_CONTROLLER_READ_MODE_0 | VGA_GRAPHICS_CONTROLLER_WRITE_MODE_1\r
2684 );\r
2685\r
2686 SourceAddress = (UINT8 *) (MemAddress + (SourceY << 6) + (SourceY << 4) + (SourceX >> 3));\r
2687 DestinationAddress = (UINT8 *) (MemAddress + (DestinationY << 6) + (DestinationY << 4) + (DestinationX >> 3));\r
2688 Bytes = Width >> 3;\r
2689 for (Index = 0, Offset = 0; Index < Height; Index++, Offset += BytesPerScanLine) {\r
2690 PciIo->CopyMem (\r
2691 PciIo,\r
2692 EfiPciIoWidthUint8,\r
2693 EFI_PCI_IO_PASS_THROUGH_BAR,\r
0d92cdc2 2694 (UINT64) (DestinationAddress + Offset),\r
7da78b1f 2695 EFI_PCI_IO_PASS_THROUGH_BAR,\r
0d92cdc2 2696 (UINT64) (SourceAddress + Offset),\r
7da78b1f 2697 Bytes\r
2698 );\r
2699 }\r
2700 } else {\r
2701 SourceOffset = (SourceY << 6) + (SourceY << 4) + (SourceX >> 3);\r
2702 SourceWidth = ((SourceX + Width - 1) >> 3) - (SourceX >> 3) + 1;\r
2703\r
2704 //\r
2705 // Read all the pixels in the 4 bit planes into a memory buffer that looks like the VGA buffer\r
2706 //\r
2707 VgaReadBitPlanes (\r
2708 PciIo,\r
2709 MemAddress + SourceOffset,\r
2710 VgaFrameBuffer + SourceOffset,\r
2711 SourceWidth,\r
2712 Height\r
2713 );\r
2714 }\r
2715\r
2716 break;\r
2717\r
0d92cdc2 2718 case EfiBltVideoFill:\r
7da78b1f 2719 StartAddress = (UINTN) (MemAddress + (DestinationY << 6) + (DestinationY << 4) + (DestinationX >> 3));\r
2720 Bytes = ((DestinationX + Width - 1) >> 3) - (DestinationX >> 3);\r
2721 LeftMask = mVgaLeftMaskTable[DestinationX & 0x07];\r
2722 RightMask = mVgaRightMaskTable[(DestinationX + Width - 1) & 0x07];\r
2723 if (Bytes == 0) {\r
2724 LeftMask &= RightMask;\r
2725 RightMask = 0;\r
2726 }\r
2727\r
2728 if (LeftMask == 0xff) {\r
2729 StartAddress--;\r
2730 Bytes++;\r
2731 LeftMask = 0;\r
2732 }\r
2733\r
2734 if (RightMask == 0xff) {\r
2735 Bytes++;\r
2736 RightMask = 0;\r
2737 }\r
2738\r
2739 PixelColor = VgaConvertColor (BltBuffer);\r
2740\r
2741 //\r
2742 // Program the Mode Register Write mode 2, Read mode 0\r
2743 //\r
2744 WriteGraphicsController (\r
0d92cdc2 2745 PciIo,\r
7da78b1f 2746 VGA_GRAPHICS_CONTROLLER_MODE_REGISTER,\r
2747 VGA_GRAPHICS_CONTROLLER_READ_MODE_0 | VGA_GRAPHICS_CONTROLLER_WRITE_MODE_2\r
2748 );\r
2749\r
2750 //\r
2751 // Program the Data Rotate/Function Select Register to replace\r
2752 //\r
2753 WriteGraphicsController (\r
0d92cdc2 2754 PciIo,\r
7da78b1f 2755 VGA_GRAPHICS_CONTROLLER_DATA_ROTATE_REGISTER,\r
2756 VGA_GRAPHICS_CONTROLLER_FUNCTION_REPLACE\r
2757 );\r
2758\r
2759 if (LeftMask != 0) {\r
2760 //\r
2761 // Program the BitMask register with the Left column mask\r
2762 //\r
2763 WriteGraphicsController (\r
0d92cdc2 2764 PciIo,\r
7da78b1f 2765 VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER,\r
2766 LeftMask\r
2767 );\r
2768\r
2769 for (Index = 0, Address = StartAddress; Index < Height; Index++, Address += BytesPerScanLine) {\r
2770 //\r
2771 // Read data from the bit planes into the latches\r
2772 //\r
2773 PciIo->Mem.Read (\r
2774 PciIo,\r
2775 EfiPciIoWidthUint8,\r
2776 EFI_PCI_IO_PASS_THROUGH_BAR,\r
2777 (UINT64) Address,\r
2778 1,\r
2779 &Data\r
2780 );\r
2781 //\r
2782 // Write the lower 4 bits of PixelColor to the bit planes in the pixels enabled by BitMask\r
2783 //\r
2784 PciIo->Mem.Write (\r
2785 PciIo,\r
2786 EfiPciIoWidthUint8,\r
2787 EFI_PCI_IO_PASS_THROUGH_BAR,\r
2788 (UINT64) Address,\r
2789 1,\r
2790 &PixelColor\r
2791 );\r
2792 }\r
2793 }\r
2794\r
2795 if (Bytes > 1) {\r
2796 //\r
2797 // Program the BitMask register with the middle column mask of 0xff\r
2798 //\r
2799 WriteGraphicsController (\r
0d92cdc2 2800 PciIo,\r
7da78b1f 2801 VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER,\r
2802 0xff\r
2803 );\r
2804\r
2805 for (Index = 0, Address = StartAddress + 1; Index < Height; Index++, Address += BytesPerScanLine) {\r
2806 PciIo->Mem.Write (\r
2807 PciIo,\r
2808 EfiPciIoWidthFillUint8,\r
2809 EFI_PCI_IO_PASS_THROUGH_BAR,\r
2810 (UINT64) Address,\r
2811 Bytes - 1,\r
2812 &PixelColor\r
2813 );\r
2814 }\r
2815 }\r
2816\r
2817 if (RightMask != 0) {\r
2818 //\r
2819 // Program the BitMask register with the Right column mask\r
2820 //\r
2821 WriteGraphicsController (\r
0d92cdc2 2822 PciIo,\r
7da78b1f 2823 VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER,\r
2824 RightMask\r
2825 );\r
2826\r
2827 for (Index = 0, Address = StartAddress + Bytes; Index < Height; Index++, Address += BytesPerScanLine) {\r
2828 //\r
2829 // Read data from the bit planes into the latches\r
2830 //\r
2831 PciIo->Mem.Read (\r
2832 PciIo,\r
2833 EfiPciIoWidthUint8,\r
2834 EFI_PCI_IO_PASS_THROUGH_BAR,\r
2835 (UINT64) Address,\r
2836 1,\r
2837 &Data\r
2838 );\r
2839 //\r
2840 // Write the lower 4 bits of PixelColor to the bit planes in the pixels enabled by BitMask\r
2841 //\r
2842 PciIo->Mem.Write (\r
2843 PciIo,\r
2844 EfiPciIoWidthUint8,\r
2845 EFI_PCI_IO_PASS_THROUGH_BAR,\r
2846 (UINT64) Address,\r
2847 1,\r
2848 &PixelColor\r
2849 );\r
2850 }\r
2851 }\r
2852 break;\r
2853\r
0d92cdc2 2854 case EfiBltBufferToVideo:\r
7da78b1f 2855 StartAddress = (UINTN) (MemAddress + (DestinationY << 6) + (DestinationY << 4) + (DestinationX >> 3));\r
2856 LeftMask = mVgaBitMaskTable[DestinationX & 0x07];\r
2857\r
2858 //\r
2859 // Program the Mode Register Write mode 2, Read mode 0\r
2860 //\r
2861 WriteGraphicsController (\r
0d92cdc2 2862 PciIo,\r
7da78b1f 2863 VGA_GRAPHICS_CONTROLLER_MODE_REGISTER,\r
2864 VGA_GRAPHICS_CONTROLLER_READ_MODE_0 | VGA_GRAPHICS_CONTROLLER_WRITE_MODE_2\r
2865 );\r
2866\r
2867 //\r
2868 // Program the Data Rotate/Function Select Register to replace\r
2869 //\r
2870 WriteGraphicsController (\r
0d92cdc2 2871 PciIo,\r
7da78b1f 2872 VGA_GRAPHICS_CONTROLLER_DATA_ROTATE_REGISTER,\r
2873 VGA_GRAPHICS_CONTROLLER_FUNCTION_REPLACE\r
2874 );\r
2875\r
2876 for (Index = 0, Address = StartAddress; Index < Height; Index++, Address += BytesPerScanLine) {\r
2877 for (Index1 = 0; Index1 < Width; Index1++) {\r
2878 BiosVideoPrivate->LineBuffer[Index1] = VgaConvertColor (&BltBuffer[(SourceY + Index) * (Delta >> 2) + SourceX + Index1]);\r
2879 }\r
2880 AddressFix = Address;\r
2881\r
2882 for (Bit = 0; Bit < 8; Bit++) {\r
2883 //\r
2884 // Program the BitMask register with the Left column mask\r
2885 //\r
2886 WriteGraphicsController (\r
0d92cdc2 2887 PciIo,\r
7da78b1f 2888 VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER,\r
2889 LeftMask\r
2890 );\r
2891\r
2892 for (Index1 = Bit, Address1 = (UINT8 *) AddressFix; Index1 < Width; Index1 += 8, Address1++) {\r
2893 //\r
2894 // Read data from the bit planes into the latches\r
2895 //\r
2896 PciIo->Mem.Read (\r
2897 PciIo,\r
2898 EfiPciIoWidthUint8,\r
2899 EFI_PCI_IO_PASS_THROUGH_BAR,\r
0d92cdc2 2900 (UINT64) Address1,\r
7da78b1f 2901 1,\r
2902 &Data\r
2903 );\r
2904\r
2905 PciIo->Mem.Write (\r
2906 PciIo,\r
2907 EfiPciIoWidthUint8,\r
2908 EFI_PCI_IO_PASS_THROUGH_BAR,\r
0d92cdc2 2909 (UINT64) Address1,\r
7da78b1f 2910 1,\r
2911 &BiosVideoPrivate->LineBuffer[Index1]\r
2912 );\r
2913 }\r
2914\r
2915 LeftMask = (UINT8) (LeftMask >> 1);\r
2916 if (LeftMask == 0) {\r
2917 LeftMask = 0x80;\r
2918 AddressFix++;\r
2919 }\r
2920 }\r
2921 }\r
2922\r
2923 break;\r
2924 }\r
2925\r
2926 gBS->RestoreTPL (OriginalTPL);\r
2927\r
2928 return EFI_SUCCESS;\r
2929}\r
2930//\r
2931// VGA Mini Port Protocol Functions\r
2932//\r
2933EFI_STATUS\r
2934EFIAPI\r
2935BiosVideoVgaMiniPortSetMode (\r
2936 IN EFI_VGA_MINI_PORT_PROTOCOL *This,\r
2937 IN UINTN ModeNumber\r
2938 )\r
2939/*++\r
2940\r
2941Routine Description:\r
2942\r
2943 VgaMiniPort protocol interface to set mode\r
2944\r
2945Arguments:\r
2946\r
2947 This - Pointer to VgaMiniPort protocol instance\r
2948 ModeNumber - The index of the mode\r
2949\r
2950Returns:\r
2951\r
2952 EFI_UNSUPPORTED - The requested mode is not supported\r
2953 EFI_SUCCESS - The requested mode is set successfully\r
2954\r
2955--*/\r
2956{\r
2957 BIOS_VIDEO_DEV *BiosVideoPrivate;\r
2958 EFI_IA32_REGISTER_SET Regs;\r
2959\r
0d92cdc2 2960 if (This == NULL) {\r
2961 return EFI_INVALID_PARAMETER;\r
2962 }\r
2963\r
7da78b1f 2964 //\r
2965 // Make sure the ModeNumber is a valid value\r
2966 //\r
2967 if (ModeNumber >= This->MaxMode) {\r
2968 return EFI_UNSUPPORTED;\r
2969 }\r
2970 //\r
2971 // Get the device structure for this device\r
2972 //\r
2973 BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_VGA_MINI_PORT_THIS (This);\r
0d92cdc2 2974 \r
7da78b1f 2975 gBS->SetMem (&Regs, sizeof (Regs), 0);\r
2976\r
2977 switch (ModeNumber) {\r
2978 case 0:\r
2979 //\r
2980 // Set the 80x25 Text VGA Mode\r
2981 //\r
2982 Regs.H.AH = 0x00;\r
2983 Regs.H.AL = 0x83;\r
0d92cdc2 2984 LegacyBiosInt86 (BiosVideoPrivate, 0x10, &Regs);\r
2985 \r
7da78b1f 2986 Regs.H.AH = 0x11;\r
2987 Regs.H.AL = 0x14;\r
2988 Regs.H.BL = 0;\r
0d92cdc2 2989 LegacyBiosInt86 (BiosVideoPrivate, 0x10, &Regs);\r
2990 \r
7da78b1f 2991 break;\r
2992\r
2993 case 1:\r
2994 //\r
2995 // Set the 80x50 Text VGA Mode\r
2996 //\r
2997 Regs.H.AH = 0x00;\r
2998 Regs.H.AL = 0x83;\r
0d92cdc2 2999 LegacyBiosInt86 (BiosVideoPrivate, 0x10, &Regs);\r
3000 \r
7da78b1f 3001 Regs.H.AH = 0x11;\r
3002 Regs.H.AL = 0x12;\r
3003 Regs.H.BL = 0;\r
0d92cdc2 3004 LegacyBiosInt86 (BiosVideoPrivate, 0x10, &Regs);\r
7da78b1f 3005 break;\r
3006\r
3007 default:\r
3008 return EFI_UNSUPPORTED;\r
3009 }\r
3010\r
3011 return EFI_SUCCESS;\r
3012}\r