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