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