]> git.proxmox.com Git - mirror_edk2.git/blob - CorebootPayloadPkg/FbGop/FbGop.c
CorebootPayloadPkg/FbGop: Locate correct framebuffer device
[mirror_edk2.git] / CorebootPayloadPkg / FbGop / FbGop.c
1 /** @file
2 ConsoleOut Routines that speak VGA.
3
4 Copyright (c) 2007 - 2013, Intel Corporation. All rights reserved.<BR>
5
6 SPDX-License-Identifier: BSD-2-Clause-Patent
7
8 **/
9
10 #include "FbGop.h"
11
12 EFI_PIXEL_BITMASK mPixelBitMask = {0x0000FF, 0x00FF00, 0xFF0000, 0x000000};
13
14 //
15 // Save controller attributes during first start
16 //
17 UINT64 mOriginalPciAttributes;
18 BOOLEAN mPciAttributesSaved = FALSE;
19 FRAME_BUFFER_INFO *mFrameBufferInfo;
20
21 //
22 // EFI Driver Binding Protocol Instance
23 //
24 EFI_DRIVER_BINDING_PROTOCOL gFbGopDriverBinding = {
25 FbGopDriverBindingSupported,
26 FbGopDriverBindingStart,
27 FbGopDriverBindingStop,
28 0x3,
29 NULL,
30 NULL
31 };
32
33 //
34 // Native resolution in EDID DetailedTiming[0]
35 //
36 UINT32 mNativeModeHorizontal;
37 UINT32 mNativeModeVertical;
38
39 /**
40 Supported.
41
42 @param This Pointer to driver binding protocol
43 @param Controller Controller handle to connect
44 @param RemainingDevicePath A pointer to the remaining portion of a device
45 path
46
47 @retval EFI_STATUS EFI_SUCCESS:This controller can be managed by this
48 driver, Otherwise, this controller cannot be
49 managed by this driver
50
51 **/
52 EFI_STATUS
53 EFIAPI
54 FbGopDriverBindingSupported (
55 IN EFI_DRIVER_BINDING_PROTOCOL *This,
56 IN EFI_HANDLE Controller,
57 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
58 )
59 {
60 EFI_STATUS Status;
61 EFI_PCI_IO_PROTOCOL *PciIo;
62 PCI_TYPE00 Pci;
63 EFI_DEV_PATH *Node;
64 UINT8 Index;
65 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Resources;
66
67 //
68 // Open the IO Abstraction(s) needed to perform the supported test
69 //
70 Status = gBS->OpenProtocol (
71 Controller,
72 &gEfiPciIoProtocolGuid,
73 (VOID **) &PciIo,
74 This->DriverBindingHandle,
75 Controller,
76 EFI_OPEN_PROTOCOL_BY_DRIVER
77 );
78 if (EFI_ERROR (Status)) {
79 return Status;
80 }
81
82 //
83 // See if this is a PCI Graphics Controller by looking at the Command register and
84 // Class Code Register
85 //
86 Status = PciIo->Pci.Read (
87 PciIo,
88 EfiPciIoWidthUint32,
89 0,
90 sizeof (Pci) / sizeof (UINT32),
91 &Pci
92 );
93 if (EFI_ERROR (Status)) {
94 Status = EFI_UNSUPPORTED;
95 goto Done;
96 }
97
98 Status = EFI_UNSUPPORTED;
99 if (IS_PCI_DISPLAY (&Pci) || IS_PCI_OLD_VGA (&Pci)) {
100 //
101 // Check if PCI BAR matches the framebuffer base
102 //
103 Status = EFI_UNSUPPORTED;
104 for (Index = 0; Index < PCI_MAX_BAR; Index++) {
105 Status = PciIo->GetBarAttributes (PciIo, Index, NULL, (VOID**) &Resources);
106 if (!EFI_ERROR (Status)) {
107 if ((Resources->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR) &&
108 (Resources->Len == (UINT16) (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3)) &&
109 (Resources->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) &&
110 (Resources->AddrRangeMin == mFrameBufferInfo->LinearFrameBuffer)) {
111 DEBUG ((DEBUG_INFO, "Found matched framebuffer PCI BAR !\n"));
112 Status = EFI_SUCCESS;
113 break;
114 }
115 }
116 }
117
118 if (!EFI_ERROR (Status)) {
119 //
120 // If this is a graphics controller,
121 // go further check RemainingDevicePath
122 //
123 if (RemainingDevicePath != NULL) {
124 Node = (EFI_DEV_PATH *) RemainingDevicePath;
125 //
126 // Check if RemainingDevicePath is the End of Device Path Node,
127 // if yes, return EFI_SUCCESS
128 //
129 if (!IsDevicePathEnd (Node)) {
130 //
131 // Verify RemainingDevicePath
132 //
133 if (Node->DevPath.Type != ACPI_DEVICE_PATH ||
134 Node->DevPath.SubType != ACPI_ADR_DP ||
135 DevicePathNodeLength(&Node->DevPath) < sizeof(ACPI_ADR_DEVICE_PATH)) {
136 Status = EFI_UNSUPPORTED;
137 }
138 }
139 }
140 }
141 }
142
143 Done:
144 gBS->CloseProtocol (
145 Controller,
146 &gEfiPciIoProtocolGuid,
147 This->DriverBindingHandle,
148 Controller
149 );
150
151 return Status;
152 }
153
154
155 /**
156 Install Graphics Output Protocol onto VGA device handles.
157
158 @param This Pointer to driver binding protocol
159 @param Controller Controller handle to connect
160 @param RemainingDevicePath A pointer to the remaining portion of a device
161 path
162
163 @return EFI_STATUS
164
165 **/
166 EFI_STATUS
167 EFIAPI
168 FbGopDriverBindingStart (
169 IN EFI_DRIVER_BINDING_PROTOCOL *This,
170 IN EFI_HANDLE Controller,
171 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
172 )
173 {
174 EFI_STATUS Status;
175 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
176 EFI_PCI_IO_PROTOCOL *PciIo;
177 UINT64 Supports;
178
179 DEBUG ((DEBUG_INFO, "GOP START\n"));
180
181 //
182 // Initialize local variables
183 //
184 PciIo = NULL;
185 ParentDevicePath = NULL;
186
187 //
188 // Prepare for status code
189 //
190 Status = gBS->HandleProtocol (
191 Controller,
192 &gEfiDevicePathProtocolGuid,
193 (VOID **) &ParentDevicePath
194 );
195 if (EFI_ERROR (Status)) {
196 return Status;
197 }
198
199 //
200 // Open the IO Abstraction(s) needed
201 //
202 Status = gBS->OpenProtocol (
203 Controller,
204 &gEfiPciIoProtocolGuid,
205 (VOID **) &PciIo,
206 This->DriverBindingHandle,
207 Controller,
208 EFI_OPEN_PROTOCOL_BY_DRIVER
209 );
210 if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {
211 return Status;
212 }
213
214 //
215 // Save original PCI attributes
216 //
217 if (!mPciAttributesSaved) {
218 Status = PciIo->Attributes (
219 PciIo,
220 EfiPciIoAttributeOperationGet,
221 0,
222 &mOriginalPciAttributes
223 );
224
225 if (EFI_ERROR (Status)) {
226 goto Done;
227 }
228 mPciAttributesSaved = TRUE;
229 }
230
231 //
232 // Get supported PCI attributes
233 //
234 Status = PciIo->Attributes (
235 PciIo,
236 EfiPciIoAttributeOperationSupported,
237 0,
238 &Supports
239 );
240 if (EFI_ERROR (Status)) {
241 goto Done;
242 }
243
244 Supports &= (EFI_PCI_IO_ATTRIBUTE_VGA_IO | EFI_PCI_IO_ATTRIBUTE_VGA_IO_16);
245 if (Supports == 0 || Supports == (EFI_PCI_IO_ATTRIBUTE_VGA_IO | EFI_PCI_IO_ATTRIBUTE_VGA_IO_16)) {
246 Status = EFI_UNSUPPORTED;
247 goto Done;
248 }
249
250 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
251 EFI_PROGRESS_CODE,
252 EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_PC_ENABLE,
253 ParentDevicePath
254 );
255 //
256 // Enable the device and make sure VGA cycles are being forwarded to this VGA device
257 //
258 Status = PciIo->Attributes (
259 PciIo,
260 EfiPciIoAttributeOperationEnable,
261 EFI_PCI_DEVICE_ENABLE,
262 NULL
263 );
264 if (EFI_ERROR (Status)) {
265 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
266 EFI_ERROR_CODE | EFI_ERROR_MINOR,
267 EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_EC_RESOURCE_CONFLICT,
268 ParentDevicePath
269 );
270 goto Done;
271 }
272
273 if (RemainingDevicePath != NULL) {
274 if (IsDevicePathEnd (RemainingDevicePath)) {
275 //
276 // If RemainingDevicePath is the End of Device Path Node,
277 // don't create any child device and return EFI_SUCCESS
278 Status = EFI_SUCCESS;
279 goto Done;
280 }
281 }
282
283 //
284 // Create child handle and install GraphicsOutputProtocol on it
285 //
286 Status = FbGopChildHandleInstall (
287 This,
288 Controller,
289 PciIo,
290 NULL,
291 ParentDevicePath,
292 RemainingDevicePath
293 );
294
295 Done:
296 if ((EFI_ERROR (Status)) && (Status != EFI_ALREADY_STARTED)) {
297
298 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
299 EFI_PROGRESS_CODE,
300 EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_PC_DISABLE,
301 ParentDevicePath
302 );
303
304 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
305 EFI_PROGRESS_CODE,
306 EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_EC_NOT_DETECTED,
307 ParentDevicePath
308 );
309 if (!HasChildHandle (Controller)) {
310 if (mPciAttributesSaved) {
311 //
312 // Restore original PCI attributes
313 //
314 PciIo->Attributes (
315 PciIo,
316 EfiPciIoAttributeOperationSet,
317 mOriginalPciAttributes,
318 NULL
319 );
320 }
321 }
322 //
323 // Release PCI I/O Protocols on the controller handle.
324 //
325 gBS->CloseProtocol (
326 Controller,
327 &gEfiPciIoProtocolGuid,
328 This->DriverBindingHandle,
329 Controller
330 );
331 }
332
333 return Status;
334 }
335
336
337 /**
338 Stop.
339
340 @param This Pointer to driver binding protocol
341 @param Controller Controller handle to connect
342 @param NumberOfChildren Number of children handle created by this driver
343 @param ChildHandleBuffer Buffer containing child handle created
344
345 @retval EFI_SUCCESS Driver disconnected successfully from controller
346 @retval EFI_UNSUPPORTED Cannot find FB_VIDEO_DEV structure
347
348 **/
349 EFI_STATUS
350 EFIAPI
351 FbGopDriverBindingStop (
352 IN EFI_DRIVER_BINDING_PROTOCOL *This,
353 IN EFI_HANDLE Controller,
354 IN UINTN NumberOfChildren,
355 IN EFI_HANDLE *ChildHandleBuffer
356 )
357 {
358 EFI_STATUS Status;
359 BOOLEAN AllChildrenStopped;
360 UINTN Index;
361 EFI_PCI_IO_PROTOCOL *PciIo;
362
363 AllChildrenStopped = TRUE;
364
365 if (NumberOfChildren == 0) {
366 //
367 // Close PCI I/O protocol on the controller handle
368 //
369 gBS->CloseProtocol (
370 Controller,
371 &gEfiPciIoProtocolGuid,
372 This->DriverBindingHandle,
373 Controller
374 );
375
376 return EFI_SUCCESS;
377 }
378
379 for (Index = 0; Index < NumberOfChildren; Index++) {
380
381 Status = EFI_SUCCESS;
382
383 FbGopChildHandleUninstall (This, Controller, ChildHandleBuffer[Index]);
384
385 if (EFI_ERROR (Status)) {
386 AllChildrenStopped = FALSE;
387 }
388 }
389
390 if (!AllChildrenStopped) {
391 return EFI_DEVICE_ERROR;
392 }
393
394 if (!HasChildHandle (Controller)) {
395 if (mPciAttributesSaved) {
396 Status = gBS->HandleProtocol (
397 Controller,
398 &gEfiPciIoProtocolGuid,
399 (VOID **) &PciIo
400 );
401 ASSERT_EFI_ERROR (Status);
402
403 //
404 // Restore original PCI attributes
405 //
406 Status = PciIo->Attributes (
407 PciIo,
408 EfiPciIoAttributeOperationSet,
409 mOriginalPciAttributes,
410 NULL
411 );
412 ASSERT_EFI_ERROR (Status);
413 }
414 }
415
416
417 return EFI_SUCCESS;
418 }
419
420
421 /**
422 Install child handles if the Handle supports MBR format.
423
424 @param This Calling context.
425 @param ParentHandle Parent Handle
426 @param ParentPciIo Parent PciIo interface
427 @param ParentLegacyBios Parent LegacyBios interface
428 @param ParentDevicePath Parent Device Path
429 @param RemainingDevicePath Remaining Device Path
430
431 @retval EFI_SUCCESS If a child handle was added
432 @retval other A child handle was not added
433
434 **/
435 EFI_STATUS
436 FbGopChildHandleInstall (
437 IN EFI_DRIVER_BINDING_PROTOCOL *This,
438 IN EFI_HANDLE ParentHandle,
439 IN EFI_PCI_IO_PROTOCOL *ParentPciIo,
440 IN VOID *ParentLegacyBios,
441 IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath,
442 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
443 )
444 {
445 EFI_STATUS Status;
446 FB_VIDEO_DEV *FbGopPrivate;
447 PCI_TYPE00 Pci;
448 ACPI_ADR_DEVICE_PATH AcpiDeviceNode;
449
450 //
451 // Allocate the private device structure for video device
452 //
453 FbGopPrivate = (FB_VIDEO_DEV *) AllocateZeroPool (
454 sizeof (FB_VIDEO_DEV)
455 );
456 if (NULL == FbGopPrivate) {
457 Status = EFI_OUT_OF_RESOURCES;
458 goto Done;
459 }
460
461 //
462 // See if this is a VGA compatible controller or not
463 //
464 Status = ParentPciIo->Pci.Read (
465 ParentPciIo,
466 EfiPciIoWidthUint32,
467 0,
468 sizeof (Pci) / sizeof (UINT32),
469 &Pci
470 );
471 if (EFI_ERROR (Status)) {
472 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
473 EFI_ERROR_CODE | EFI_ERROR_MINOR,
474 EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_EC_CONTROLLER_ERROR,
475 ParentDevicePath
476 );
477 goto Done;
478 }
479
480 //
481 // Initialize the child private structure
482 //
483 FbGopPrivate->Signature = FB_VIDEO_DEV_SIGNATURE;
484
485 //
486 // Fill in Graphics Output specific mode structures
487 //
488 FbGopPrivate->ModeData = NULL;
489
490 FbGopPrivate->VbeFrameBuffer = NULL;
491
492 FbGopPrivate->EdidDiscovered.SizeOfEdid = 0;
493 FbGopPrivate->EdidDiscovered.Edid = NULL;
494 FbGopPrivate->EdidActive.SizeOfEdid = 0;
495 FbGopPrivate->EdidActive.Edid = NULL;
496
497 //
498 // Fill in the Graphics Output Protocol
499 //
500 FbGopPrivate->GraphicsOutput.QueryMode = FbGopGraphicsOutputQueryMode;
501 FbGopPrivate->GraphicsOutput.SetMode = FbGopGraphicsOutputSetMode;
502
503
504 //
505 // Allocate buffer for Graphics Output Protocol mode information
506 //
507 FbGopPrivate->GraphicsOutput.Mode = (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE *) AllocatePool (
508 sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE)
509 );
510 if (NULL == FbGopPrivate->GraphicsOutput.Mode) {
511 Status = EFI_OUT_OF_RESOURCES;
512 goto Done;
513 }
514
515 FbGopPrivate->GraphicsOutput.Mode->Info = (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *) AllocatePool (
516 sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION)
517 );
518 if (NULL == FbGopPrivate->GraphicsOutput.Mode->Info) {
519 Status = EFI_OUT_OF_RESOURCES;
520 goto Done;
521 }
522
523 //
524 // Set Gop Device Path, here RemainingDevicePath will not be one End of Device Path Node.
525 //
526 if ((RemainingDevicePath == NULL) || (!IsDevicePathEnd (RemainingDevicePath))) {
527 if (RemainingDevicePath == NULL) {
528 ZeroMem (&AcpiDeviceNode, sizeof (ACPI_ADR_DEVICE_PATH));
529 AcpiDeviceNode.Header.Type = ACPI_DEVICE_PATH;
530 AcpiDeviceNode.Header.SubType = ACPI_ADR_DP;
531 AcpiDeviceNode.ADR = ACPI_DISPLAY_ADR (1, 0, 0, 1, 0, ACPI_ADR_DISPLAY_TYPE_VGA, 0, 0);
532 SetDevicePathNodeLength (&AcpiDeviceNode.Header, sizeof (ACPI_ADR_DEVICE_PATH));
533
534 FbGopPrivate->GopDevicePath = AppendDevicePathNode (
535 ParentDevicePath,
536 (EFI_DEVICE_PATH_PROTOCOL *) &AcpiDeviceNode
537 );
538 } else {
539 FbGopPrivate->GopDevicePath = AppendDevicePathNode (ParentDevicePath, RemainingDevicePath);
540 }
541
542 //
543 // Creat child handle and device path protocol firstly
544 //
545 FbGopPrivate->Handle = NULL;
546 Status = gBS->InstallMultipleProtocolInterfaces (
547 &FbGopPrivate->Handle,
548 &gEfiDevicePathProtocolGuid,
549 FbGopPrivate->GopDevicePath,
550 NULL
551 );
552 if (EFI_ERROR (Status)) {
553 goto Done;
554 }
555 }
556
557 //
558 // When check for VBE, PCI I/O protocol is needed, so use parent's protocol interface temporally
559 //
560 FbGopPrivate->PciIo = ParentPciIo;
561
562 //
563 // Check for VESA BIOS Extensions for modes that are compatible with Graphics Output
564 //
565 Status = FbGopCheckForVbe (FbGopPrivate);
566 DEBUG ((DEBUG_INFO, "FbGopCheckForVbe - %r\n", Status));
567
568 if (EFI_ERROR (Status)) {
569 Status = EFI_UNSUPPORTED;
570 //goto Done;
571 }
572
573 //
574 // Creat child handle and install Graphics Output Protocol,EDID Discovered/Active Protocol
575 //
576 Status = gBS->InstallMultipleProtocolInterfaces (
577 &FbGopPrivate->Handle,
578 &gEfiGraphicsOutputProtocolGuid,
579 &FbGopPrivate->GraphicsOutput,
580 &gEfiEdidDiscoveredProtocolGuid,
581 &FbGopPrivate->EdidDiscovered,
582 &gEfiEdidActiveProtocolGuid,
583 &FbGopPrivate->EdidActive,
584 NULL
585 );
586
587 if (!EFI_ERROR (Status)) {
588 //
589 // Open the Parent Handle for the child
590 //
591 Status = gBS->OpenProtocol (
592 ParentHandle,
593 &gEfiPciIoProtocolGuid,
594 (VOID **) &FbGopPrivate->PciIo,
595 This->DriverBindingHandle,
596 FbGopPrivate->Handle,
597 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
598 );
599 if (EFI_ERROR (Status)) {
600 goto Done;
601 }
602 }
603
604 Done:
605 if (EFI_ERROR (Status)) {
606 //
607 // Free private data structure
608 //
609 FbGopDeviceReleaseResource (FbGopPrivate);
610 }
611
612 return Status;
613 }
614
615
616 /**
617 Deregister an video child handle and free resources.
618
619 @param This Protocol instance pointer.
620 @param Controller Video controller handle
621 @param Handle Video child handle
622
623 @return EFI_STATUS
624
625 **/
626 EFI_STATUS
627 FbGopChildHandleUninstall (
628 EFI_DRIVER_BINDING_PROTOCOL *This,
629 EFI_HANDLE Controller,
630 EFI_HANDLE Handle
631 )
632 {
633 EFI_STATUS Status;
634 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
635 FB_VIDEO_DEV *FbGopPrivate;
636 EFI_PCI_IO_PROTOCOL *PciIo;
637
638 FbGopPrivate = NULL;
639 GraphicsOutput = NULL;
640 PciIo = NULL;
641 Status = EFI_UNSUPPORTED;
642
643 Status = gBS->OpenProtocol (
644 Handle,
645 &gEfiGraphicsOutputProtocolGuid,
646 (VOID **) &GraphicsOutput,
647 This->DriverBindingHandle,
648 Handle,
649 EFI_OPEN_PROTOCOL_GET_PROTOCOL
650 );
651 if (!EFI_ERROR (Status)) {
652 FbGopPrivate = FB_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (GraphicsOutput);
653 }
654
655 if (FbGopPrivate == NULL) {
656 return EFI_UNSUPPORTED;
657 }
658
659 //
660 // Close PCI I/O protocol that opened by child handle
661 //
662 Status = gBS->CloseProtocol (
663 Controller,
664 &gEfiPciIoProtocolGuid,
665 This->DriverBindingHandle,
666 Handle
667 );
668
669 //
670 // Uninstall protocols on child handle
671 //
672 Status = gBS->UninstallMultipleProtocolInterfaces (
673 FbGopPrivate->Handle,
674 &gEfiDevicePathProtocolGuid,
675 FbGopPrivate->GopDevicePath,
676 &gEfiGraphicsOutputProtocolGuid,
677 &FbGopPrivate->GraphicsOutput,
678 NULL
679 );
680
681 if (EFI_ERROR (Status)) {
682 gBS->OpenProtocol (
683 Controller,
684 &gEfiPciIoProtocolGuid,
685 (VOID **) &PciIo,
686 This->DriverBindingHandle,
687 Handle,
688 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
689 );
690 return Status;
691 }
692
693 //
694 // Release all allocated resources
695 //
696 FbGopDeviceReleaseResource (FbGopPrivate);
697
698 return EFI_SUCCESS;
699 }
700
701
702 /**
703 Release resource for bios video instance.
704
705 @param FbGopPrivate Video child device private data structure
706
707 **/
708 VOID
709 FbGopDeviceReleaseResource (
710 FB_VIDEO_DEV *FbGopPrivate
711 )
712 {
713 if (FbGopPrivate == NULL) {
714 return ;
715 }
716
717 //
718 // Release all the resources occupied by the FB_VIDEO_DEV
719 //
720
721 //
722 // Free VBE Frame Buffer
723 //
724 if (FbGopPrivate->VbeFrameBuffer != NULL) {
725 FreePool (FbGopPrivate->VbeFrameBuffer);
726 }
727
728 //
729 // Free mode data
730 //
731 if (FbGopPrivate->ModeData != NULL) {
732 FreePool (FbGopPrivate->ModeData);
733 }
734
735 //
736 // Free graphics output protocol occupied resource
737 //
738 if (FbGopPrivate->GraphicsOutput.Mode != NULL) {
739 if (FbGopPrivate->GraphicsOutput.Mode->Info != NULL) {
740 FreePool (FbGopPrivate->GraphicsOutput.Mode->Info);
741 FbGopPrivate->GraphicsOutput.Mode->Info = NULL;
742 }
743 FreePool (FbGopPrivate->GraphicsOutput.Mode);
744 FbGopPrivate->GraphicsOutput.Mode = NULL;
745 }
746
747 if (FbGopPrivate->GopDevicePath!= NULL) {
748 FreePool (FbGopPrivate->GopDevicePath);
749 }
750
751 FreePool (FbGopPrivate);
752
753 return ;
754 }
755
756
757
758 /**
759 Check if all video child handles have been uninstalled.
760
761 @param Controller Video controller handle
762
763 @return TRUE Child handles exist.
764 @return FALSE All video child handles have been uninstalled.
765
766 **/
767 BOOLEAN
768 HasChildHandle (
769 IN EFI_HANDLE Controller
770 )
771 {
772 UINTN Index;
773 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer;
774 UINTN EntryCount;
775 BOOLEAN HasChild;
776
777 EntryCount = 0;
778 HasChild = FALSE;
779 gBS->OpenProtocolInformation (
780 Controller,
781 &gEfiPciIoProtocolGuid,
782 &OpenInfoBuffer,
783 &EntryCount
784 );
785 for (Index = 0; Index < EntryCount; Index++) {
786 if ((OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {
787 HasChild = TRUE;
788 }
789 }
790
791 return HasChild;
792 }
793
794 /**
795 Check for VBE device.
796
797 @param FbGopPrivate Pointer to FB_VIDEO_DEV structure
798
799 @retval EFI_SUCCESS VBE device found
800
801 **/
802 EFI_STATUS
803 FbGopCheckForVbe (
804 IN OUT FB_VIDEO_DEV *FbGopPrivate
805 )
806 {
807 EFI_STATUS Status;
808 FB_VIDEO_MODE_DATA *ModeBuffer;
809 FB_VIDEO_MODE_DATA *CurrentModeData;
810 UINTN ModeNumber;
811 UINTN BitsPerPixel;
812 UINTN BytesPerScanLine;
813 UINT32 HorizontalResolution;
814 UINT32 VerticalResolution;
815 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *VbeFrameBuffer;
816 FRAME_BUFFER_INFO *FbInfo;
817
818 Status = EFI_SUCCESS;
819
820 FbInfo = mFrameBufferInfo;
821
822 //
823 // Add mode to the list of available modes
824 //
825 VbeFrameBuffer = NULL;
826 ModeBuffer = NULL;
827
828 ModeNumber = 1;
829 BitsPerPixel = FbInfo->BitsPerPixel;
830 HorizontalResolution = FbInfo->HorizontalResolution;
831 VerticalResolution = FbInfo->VerticalResolution;
832 BytesPerScanLine = FbInfo->BytesPerScanLine;
833
834 ModeBuffer = (FB_VIDEO_MODE_DATA *) AllocatePool (
835 ModeNumber * sizeof (FB_VIDEO_MODE_DATA)
836 );
837 if (NULL == ModeBuffer) {
838 Status = EFI_OUT_OF_RESOURCES;
839 goto Done;
840 }
841
842 VbeFrameBuffer =
843 (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) AllocatePool (
844 BytesPerScanLine * VerticalResolution
845 );
846 if (NULL == VbeFrameBuffer) {
847 Status = EFI_OUT_OF_RESOURCES;
848 goto Done;
849 }
850
851 if (FbGopPrivate->ModeData != NULL) {
852 FreePool (FbGopPrivate->ModeData);
853 }
854
855 if (FbGopPrivate->VbeFrameBuffer != NULL) {
856 FreePool (FbGopPrivate->VbeFrameBuffer);
857 }
858
859 CurrentModeData = &ModeBuffer[ModeNumber - 1];
860 CurrentModeData->BytesPerScanLine = (UINT16)BytesPerScanLine;
861
862 CurrentModeData->Red = *(FB_VIDEO_COLOR_PLACEMENT *)&(FbInfo->Red);
863 CurrentModeData->Blue = *(FB_VIDEO_COLOR_PLACEMENT *)&(FbInfo->Blue);
864 CurrentModeData->Green = *(FB_VIDEO_COLOR_PLACEMENT *)&(FbInfo->Green);
865 CurrentModeData->Reserved = *(FB_VIDEO_COLOR_PLACEMENT *)&(FbInfo->Reserved);
866
867 CurrentModeData->BitsPerPixel = (UINT32)BitsPerPixel;
868 CurrentModeData->HorizontalResolution = HorizontalResolution;
869 CurrentModeData->VerticalResolution = VerticalResolution;
870 CurrentModeData->FrameBufferSize = CurrentModeData->BytesPerScanLine * CurrentModeData->VerticalResolution;
871 CurrentModeData->LinearFrameBuffer = (VOID *) (UINTN) FbInfo->LinearFrameBuffer;
872 CurrentModeData->VbeModeNumber = 0;
873 CurrentModeData->ColorDepth = 32;
874 CurrentModeData->RefreshRate = 60;
875
876 CurrentModeData->PixelFormat = PixelBitMask;
877 if ((CurrentModeData->BitsPerPixel == 32) &&
878 (CurrentModeData->Red.Mask == 0xff) && (CurrentModeData->Green.Mask == 0xff) && (CurrentModeData->Blue.Mask == 0xff)) {
879 if ((CurrentModeData->Red.Position == 0) && (CurrentModeData->Green.Position == 8) && (CurrentModeData->Blue.Position == 16)) {
880 CurrentModeData->PixelFormat = PixelRedGreenBlueReserved8BitPerColor;
881 } else if ((CurrentModeData->Blue.Position == 0) && (CurrentModeData->Green.Position == 8) && (CurrentModeData->Red.Position == 16)) {
882 CurrentModeData->PixelFormat = PixelBlueGreenRedReserved8BitPerColor;
883 }
884 }
885
886 CopyMem (&(CurrentModeData->PixelBitMask), &mPixelBitMask, sizeof (EFI_PIXEL_BITMASK));
887
888 FbGopPrivate->ModeData = ModeBuffer;
889 FbGopPrivate->VbeFrameBuffer = VbeFrameBuffer;
890
891 //
892 // Assign Gop's Blt function
893 //
894 FbGopPrivate->GraphicsOutput.Blt = FbGopGraphicsOutputVbeBlt;
895
896 FbGopPrivate->GraphicsOutput.Mode->MaxMode = 1;
897 FbGopPrivate->GraphicsOutput.Mode->Mode = 0;
898 FbGopPrivate->GraphicsOutput.Mode->Info->Version = 0;
899 FbGopPrivate->GraphicsOutput.Mode->Info->HorizontalResolution = HorizontalResolution;
900 FbGopPrivate->GraphicsOutput.Mode->Info->VerticalResolution = VerticalResolution;
901 FbGopPrivate->GraphicsOutput.Mode->Info->PixelFormat = CurrentModeData->PixelFormat;
902 CopyMem (&(FbGopPrivate->GraphicsOutput.Mode->Info->PixelInformation), &mPixelBitMask, sizeof (EFI_PIXEL_BITMASK));
903 FbGopPrivate->GraphicsOutput.Mode->Info->PixelsPerScanLine = (UINT32)(BytesPerScanLine * 8 / BitsPerPixel);
904 FbGopPrivate->GraphicsOutput.Mode->SizeOfInfo = sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
905 FbGopPrivate->GraphicsOutput.Mode->FrameBufferBase = (EFI_PHYSICAL_ADDRESS) (UINTN) CurrentModeData->LinearFrameBuffer;
906 FbGopPrivate->GraphicsOutput.Mode->FrameBufferSize = CurrentModeData->FrameBufferSize;
907
908 //
909 // Find the best mode to initialize
910 //
911
912 Done:
913 //
914 // If there was an error, then free the mode structure
915 //
916 if (EFI_ERROR (Status)) {
917
918 if (VbeFrameBuffer != NULL) {
919 FreePool (VbeFrameBuffer);
920 }
921
922 if (ModeBuffer != NULL) {
923 FreePool (ModeBuffer);
924 }
925 }
926
927 return Status;
928 }
929
930
931 //
932 // Graphics Output Protocol Member Functions for VESA BIOS Extensions
933 //
934
935 /**
936 Graphics Output protocol interface to get video mode.
937
938 @param This Protocol instance pointer.
939 @param ModeNumber The mode number to return information on.
940 @param SizeOfInfo A pointer to the size, in bytes, of the Info
941 buffer.
942 @param Info Caller allocated buffer that returns information
943 about ModeNumber.
944
945 @retval EFI_SUCCESS Mode information returned.
946 @retval EFI_DEVICE_ERROR A hardware error occurred trying to retrieve the
947 video mode.
948 @retval EFI_NOT_STARTED Video display is not initialized. Call SetMode ()
949 @retval EFI_INVALID_PARAMETER One of the input args was NULL.
950
951 **/
952 EFI_STATUS
953 EFIAPI
954 FbGopGraphicsOutputQueryMode (
955 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
956 IN UINT32 ModeNumber,
957 OUT UINTN *SizeOfInfo,
958 OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info
959 )
960 {
961 FB_VIDEO_DEV *FbGopPrivate;
962 FB_VIDEO_MODE_DATA *ModeData;
963
964 FbGopPrivate = FB_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This);
965
966 if (This == NULL || Info == NULL || SizeOfInfo == NULL || ModeNumber >= This->Mode->MaxMode) {
967 return EFI_INVALID_PARAMETER;
968 }
969
970 *Info = (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *) AllocatePool (
971 sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION)
972 );
973 if (NULL == *Info) {
974 return EFI_OUT_OF_RESOURCES;
975 }
976
977 *SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
978
979 ModeData = &FbGopPrivate->ModeData[ModeNumber];
980 (*Info)->Version = 0;
981 (*Info)->HorizontalResolution = ModeData->HorizontalResolution;
982 (*Info)->VerticalResolution = ModeData->VerticalResolution;
983 (*Info)->PixelFormat = ModeData->PixelFormat;
984 CopyMem (&((*Info)->PixelInformation), &(ModeData->PixelBitMask), sizeof(ModeData->PixelBitMask));
985
986 (*Info)->PixelsPerScanLine = (ModeData->BytesPerScanLine * 8) / ModeData->BitsPerPixel;
987
988 return EFI_SUCCESS;
989 }
990
991 /**
992 Graphics Output protocol interface to set video mode.
993
994 @param This Protocol instance pointer.
995 @param ModeNumber The mode number to be set.
996
997 @retval EFI_SUCCESS Graphics mode was changed.
998 @retval EFI_DEVICE_ERROR The device had an error and could not complete the
999 request.
1000 @retval EFI_UNSUPPORTED ModeNumber is not supported by this device.
1001
1002 **/
1003 EFI_STATUS
1004 EFIAPI
1005 FbGopGraphicsOutputSetMode (
1006 IN EFI_GRAPHICS_OUTPUT_PROTOCOL * This,
1007 IN UINT32 ModeNumber
1008 )
1009 {
1010 FB_VIDEO_DEV *FbGopPrivate;
1011 FB_VIDEO_MODE_DATA *ModeData;
1012 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background;
1013
1014 if (This == NULL) {
1015 return EFI_INVALID_PARAMETER;
1016 }
1017
1018 FbGopPrivate = FB_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This);
1019
1020 ModeData = &FbGopPrivate->ModeData[ModeNumber];
1021
1022 if (ModeNumber >= This->Mode->MaxMode) {
1023 return EFI_UNSUPPORTED;
1024 }
1025
1026 if (ModeNumber == This->Mode->Mode) {
1027 //
1028 // Clear screen to black
1029 //
1030 ZeroMem (&Background, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
1031 FbGopGraphicsOutputVbeBlt (
1032 This,
1033 &Background,
1034 EfiBltVideoFill,
1035 0,
1036 0,
1037 0,
1038 0,
1039 ModeData->HorizontalResolution,
1040 ModeData->VerticalResolution,
1041 0
1042 );
1043 return EFI_SUCCESS;
1044 } else {
1045 return EFI_UNSUPPORTED;
1046 }
1047
1048 }
1049
1050 /**
1051 Update physical frame buffer, copy 4 bytes block, then copy remaining bytes.
1052
1053 @param PciIo The pointer of EFI_PCI_IO_PROTOCOL
1054 @param VbeBuffer The data to transfer to screen
1055 @param MemAddress Physical frame buffer base address
1056 @param DestinationX The X coordinate of the destination for BltOperation
1057 @param DestinationY The Y coordinate of the destination for BltOperation
1058 @param TotalBytes The total bytes of copy
1059 @param VbePixelWidth Bytes per pixel
1060 @param BytesPerScanLine Bytes per scan line
1061
1062 **/
1063 VOID
1064 CopyVideoBuffer (
1065 IN EFI_PCI_IO_PROTOCOL *PciIo,
1066 IN UINT8 *VbeBuffer,
1067 IN VOID *MemAddress,
1068 IN UINTN DestinationX,
1069 IN UINTN DestinationY,
1070 IN UINTN TotalBytes,
1071 IN UINT32 VbePixelWidth,
1072 IN UINTN BytesPerScanLine
1073 )
1074 {
1075 UINTN FrameBufferAddr;
1076 UINTN CopyBlockNum;
1077 UINTN RemainingBytes;
1078 UINTN UnalignedBytes;
1079 EFI_STATUS Status;
1080
1081 FrameBufferAddr = (UINTN) MemAddress + (DestinationY * BytesPerScanLine) + DestinationX * VbePixelWidth;
1082
1083 //
1084 // If TotalBytes is less than 4 bytes, only start byte copy.
1085 //
1086 if (TotalBytes < 4) {
1087 Status = PciIo->Mem.Write (
1088 PciIo,
1089 EfiPciIoWidthUint8,
1090 EFI_PCI_IO_PASS_THROUGH_BAR,
1091 (UINT64) FrameBufferAddr,
1092 TotalBytes,
1093 VbeBuffer
1094 );
1095 ASSERT_EFI_ERROR (Status);
1096 return;
1097 }
1098
1099 //
1100 // If VbeBuffer is not 4-byte aligned, start byte copy.
1101 //
1102 UnalignedBytes = (4 - ((UINTN) VbeBuffer & 0x3)) & 0x3;
1103
1104 if (UnalignedBytes != 0) {
1105 Status = PciIo->Mem.Write (
1106 PciIo,
1107 EfiPciIoWidthUint8,
1108 EFI_PCI_IO_PASS_THROUGH_BAR,
1109 (UINT64) FrameBufferAddr,
1110 UnalignedBytes,
1111 VbeBuffer
1112 );
1113 ASSERT_EFI_ERROR (Status);
1114 FrameBufferAddr += UnalignedBytes;
1115 VbeBuffer += UnalignedBytes;
1116 }
1117
1118 //
1119 // Calculate 4-byte block count and remaining bytes.
1120 //
1121 CopyBlockNum = (TotalBytes - UnalignedBytes) >> 2;
1122 RemainingBytes = (TotalBytes - UnalignedBytes) & 3;
1123
1124 //
1125 // Copy 4-byte block and remaining bytes to physical frame buffer.
1126 //
1127 if (CopyBlockNum != 0) {
1128 Status = PciIo->Mem.Write (
1129 PciIo,
1130 EfiPciIoWidthUint32,
1131 EFI_PCI_IO_PASS_THROUGH_BAR,
1132 (UINT64) FrameBufferAddr,
1133 CopyBlockNum,
1134 VbeBuffer
1135 );
1136 ASSERT_EFI_ERROR (Status);
1137 }
1138
1139 if (RemainingBytes != 0) {
1140 FrameBufferAddr += (CopyBlockNum << 2);
1141 VbeBuffer += (CopyBlockNum << 2);
1142 Status = PciIo->Mem.Write (
1143 PciIo,
1144 EfiPciIoWidthUint8,
1145 EFI_PCI_IO_PASS_THROUGH_BAR,
1146 (UINT64) FrameBufferAddr,
1147 RemainingBytes,
1148 VbeBuffer
1149 );
1150 ASSERT_EFI_ERROR (Status);
1151 }
1152 }
1153
1154 /**
1155 Worker function to block transfer for VBE device.
1156
1157 @param FbGopPrivate Instance of FB_VIDEO_DEV
1158 @param BltBuffer The data to transfer to screen
1159 @param BltOperation The operation to perform
1160 @param SourceX The X coordinate of the source for BltOperation
1161 @param SourceY The Y coordinate of the source for BltOperation
1162 @param DestinationX The X coordinate of the destination for
1163 BltOperation
1164 @param DestinationY The Y coordinate of the destination for
1165 BltOperation
1166 @param Width The width of a rectangle in the blt rectangle in
1167 pixels
1168 @param Height The height of a rectangle in the blt rectangle in
1169 pixels
1170 @param Delta Not used for EfiBltVideoFill and
1171 EfiBltVideoToVideo operation. If a Delta of 0 is
1172 used, the entire BltBuffer will be operated on. If
1173 a subrectangle of the BltBuffer is used, then
1174 Delta represents the number of bytes in a row of
1175 the BltBuffer.
1176 @param Mode Mode data.
1177
1178 @retval EFI_INVALID_PARAMETER Invalid parameter passed in
1179 @retval EFI_SUCCESS Blt operation success
1180
1181 **/
1182 EFI_STATUS
1183 FbGopVbeBltWorker (
1184 IN FB_VIDEO_DEV *FbGopPrivate,
1185 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL
1186 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,
1187 IN UINTN SourceX,
1188 IN UINTN SourceY,
1189 IN UINTN DestinationX,
1190 IN UINTN DestinationY,
1191 IN UINTN Width,
1192 IN UINTN Height,
1193 IN UINTN Delta,
1194 IN FB_VIDEO_MODE_DATA *Mode
1195 )
1196 {
1197 EFI_PCI_IO_PROTOCOL *PciIo;
1198 EFI_TPL OriginalTPL;
1199 UINTN DstY;
1200 UINTN SrcY;
1201 UINTN DstX;
1202 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt;
1203 VOID *MemAddress;
1204 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *VbeFrameBuffer;
1205 UINTN BytesPerScanLine;
1206 UINTN Index;
1207 UINT8 *VbeBuffer;
1208 UINT8 *VbeBuffer1;
1209 UINT8 *BltUint8;
1210 UINT32 VbePixelWidth;
1211 UINT32 Pixel;
1212 UINTN TotalBytes;
1213
1214 PciIo = FbGopPrivate->PciIo;
1215
1216 VbeFrameBuffer = FbGopPrivate->VbeFrameBuffer;
1217 MemAddress = Mode->LinearFrameBuffer;
1218 BytesPerScanLine = Mode->BytesPerScanLine;
1219 VbePixelWidth = Mode->BitsPerPixel / 8;
1220 BltUint8 = (UINT8 *) BltBuffer;
1221 TotalBytes = Width * VbePixelWidth;
1222
1223 if (((UINTN) BltOperation) >= EfiGraphicsOutputBltOperationMax) {
1224 return EFI_INVALID_PARAMETER;
1225 }
1226
1227 if (Width == 0 || Height == 0) {
1228 return EFI_INVALID_PARAMETER;
1229 }
1230 //
1231 // We need to fill the Virtual Screen buffer with the blt data.
1232 // The virtual screen is upside down, as the first row is the bottom row of
1233 // the image.
1234 //
1235 if (BltOperation == EfiBltVideoToBltBuffer) {
1236 //
1237 // Video to BltBuffer: Source is Video, destination is BltBuffer
1238 //
1239 if (SourceY + Height > Mode->VerticalResolution) {
1240 return EFI_INVALID_PARAMETER;
1241 }
1242
1243 if (SourceX + Width > Mode->HorizontalResolution) {
1244 return EFI_INVALID_PARAMETER;
1245 }
1246 } else {
1247 //
1248 // BltBuffer to Video: Source is BltBuffer, destination is Video
1249 //
1250 if (DestinationY + Height > Mode->VerticalResolution) {
1251 return EFI_INVALID_PARAMETER;
1252 }
1253
1254 if (DestinationX + Width > Mode->HorizontalResolution) {
1255 return EFI_INVALID_PARAMETER;
1256 }
1257 }
1258 //
1259 // If Delta is zero, then the entire BltBuffer is being used, so Delta
1260 // is the number of bytes in each row of BltBuffer. Since BltBuffer is Width pixels size,
1261 // the number of bytes in each row can be computed.
1262 //
1263 if (Delta == 0) {
1264 Delta = Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
1265 }
1266 //
1267 // We have to raise to TPL Notify, so we make an atomic write the frame buffer.
1268 // We would not want a timer based event (Cursor, ...) to come in while we are
1269 // doing this operation.
1270 //
1271 OriginalTPL = gBS->RaiseTPL (TPL_NOTIFY);
1272
1273 switch (BltOperation) {
1274 case EfiBltVideoToBltBuffer:
1275 for (SrcY = SourceY, DstY = DestinationY; DstY < (Height + DestinationY); SrcY++, DstY++) {
1276 Blt = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) (BltUint8 + DstY * Delta + DestinationX * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
1277 //
1278 // Shuffle the packed bytes in the hardware buffer to match EFI_GRAPHICS_OUTPUT_BLT_PIXEL
1279 //
1280 VbeBuffer = ((UINT8 *) VbeFrameBuffer + (SrcY * BytesPerScanLine + SourceX * VbePixelWidth));
1281 for (DstX = DestinationX; DstX < (Width + DestinationX); DstX++) {
1282 Pixel = VbeBuffer[0] | VbeBuffer[1] << 8 | VbeBuffer[2] << 16 | VbeBuffer[3] << 24;
1283 Blt->Red = (UINT8) ((Pixel >> Mode->Red.Position) & Mode->Red.Mask);
1284 Blt->Blue = (UINT8) ((Pixel >> Mode->Blue.Position) & Mode->Blue.Mask);
1285 Blt->Green = (UINT8) ((Pixel >> Mode->Green.Position) & Mode->Green.Mask);
1286 Blt->Reserved = 0;
1287 Blt++;
1288 VbeBuffer += VbePixelWidth;
1289 }
1290
1291 }
1292 break;
1293
1294 case EfiBltVideoToVideo:
1295 for (Index = 0; Index < Height; Index++) {
1296 if (DestinationY <= SourceY) {
1297 SrcY = SourceY + Index;
1298 DstY = DestinationY + Index;
1299 } else {
1300 SrcY = SourceY + Height - Index - 1;
1301 DstY = DestinationY + Height - Index - 1;
1302 }
1303
1304 VbeBuffer = ((UINT8 *) VbeFrameBuffer + DstY * BytesPerScanLine + DestinationX * VbePixelWidth);
1305 VbeBuffer1 = ((UINT8 *) VbeFrameBuffer + SrcY * BytesPerScanLine + SourceX * VbePixelWidth);
1306
1307 gBS->CopyMem (
1308 VbeBuffer,
1309 VbeBuffer1,
1310 TotalBytes
1311 );
1312
1313 //
1314 // Update physical frame buffer.
1315 //
1316 CopyVideoBuffer (
1317 PciIo,
1318 VbeBuffer,
1319 MemAddress,
1320 DestinationX,
1321 DstY,
1322 TotalBytes,
1323 VbePixelWidth,
1324 BytesPerScanLine
1325 );
1326 }
1327 break;
1328
1329 case EfiBltVideoFill:
1330 VbeBuffer = (UINT8 *) ((UINTN) VbeFrameBuffer + (DestinationY * BytesPerScanLine) + DestinationX * VbePixelWidth);
1331 Blt = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) BltUint8;
1332 //
1333 // Shuffle the RGB fields in EFI_GRAPHICS_OUTPUT_BLT_PIXEL to match the hardware buffer
1334 //
1335 Pixel = ((Blt->Red & Mode->Red.Mask) << Mode->Red.Position) |
1336 (
1337 (Blt->Green & Mode->Green.Mask) <<
1338 Mode->Green.Position
1339 ) |
1340 ((Blt->Blue & Mode->Blue.Mask) << Mode->Blue.Position);
1341
1342 for (Index = 0; Index < Width; Index++) {
1343 gBS->CopyMem (
1344 VbeBuffer,
1345 &Pixel,
1346 VbePixelWidth
1347 );
1348 VbeBuffer += VbePixelWidth;
1349 }
1350
1351 VbeBuffer = (UINT8 *) ((UINTN) VbeFrameBuffer + (DestinationY * BytesPerScanLine) + DestinationX * VbePixelWidth);
1352 for (DstY = DestinationY + 1; DstY < (Height + DestinationY); DstY++) {
1353 gBS->CopyMem (
1354 (VOID *) ((UINTN) VbeFrameBuffer + (DstY * BytesPerScanLine) + DestinationX * VbePixelWidth),
1355 VbeBuffer,
1356 TotalBytes
1357 );
1358 }
1359
1360 for (DstY = DestinationY; DstY < (Height + DestinationY); DstY++) {
1361 //
1362 // Update physical frame buffer.
1363 //
1364 CopyVideoBuffer (
1365 PciIo,
1366 VbeBuffer,
1367 MemAddress,
1368 DestinationX,
1369 DstY,
1370 TotalBytes,
1371 VbePixelWidth,
1372 BytesPerScanLine
1373 );
1374 }
1375 break;
1376
1377 case EfiBltBufferToVideo:
1378 for (SrcY = SourceY, DstY = DestinationY; SrcY < (Height + SourceY); SrcY++, DstY++) {
1379 Blt = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) (BltUint8 + (SrcY * Delta) + (SourceX) * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
1380 VbeBuffer = ((UINT8 *) VbeFrameBuffer + (DstY * BytesPerScanLine + DestinationX * VbePixelWidth));
1381 for (DstX = DestinationX; DstX < (Width + DestinationX); DstX++) {
1382 //
1383 // Shuffle the RGB fields in EFI_GRAPHICS_OUTPUT_BLT_PIXEL to match the hardware buffer
1384 //
1385 Pixel = ((Blt->Red & Mode->Red.Mask) << Mode->Red.Position) |
1386 ((Blt->Green & Mode->Green.Mask) << Mode->Green.Position) |
1387 ((Blt->Blue & Mode->Blue.Mask) << Mode->Blue.Position);
1388 gBS->CopyMem (
1389 VbeBuffer,
1390 &Pixel,
1391 VbePixelWidth
1392 );
1393 Blt++;
1394 VbeBuffer += VbePixelWidth;
1395 }
1396
1397 VbeBuffer = ((UINT8 *) VbeFrameBuffer + (DstY * BytesPerScanLine + DestinationX * VbePixelWidth));
1398
1399 //
1400 // Update physical frame buffer.
1401 //
1402 CopyVideoBuffer (
1403 PciIo,
1404 VbeBuffer,
1405 MemAddress,
1406 DestinationX,
1407 DstY,
1408 TotalBytes,
1409 VbePixelWidth,
1410 BytesPerScanLine
1411 );
1412 }
1413 break;
1414
1415 default: ;
1416 }
1417
1418 gBS->RestoreTPL (OriginalTPL);
1419
1420 return EFI_SUCCESS;
1421 }
1422
1423 /**
1424 Graphics Output protocol instance to block transfer for VBE device.
1425
1426 @param This Pointer to Graphics Output protocol instance
1427 @param BltBuffer The data to transfer to screen
1428 @param BltOperation The operation to perform
1429 @param SourceX The X coordinate of the source for BltOperation
1430 @param SourceY The Y coordinate of the source for BltOperation
1431 @param DestinationX The X coordinate of the destination for
1432 BltOperation
1433 @param DestinationY The Y coordinate of the destination for
1434 BltOperation
1435 @param Width The width of a rectangle in the blt rectangle in
1436 pixels
1437 @param Height The height of a rectangle in the blt rectangle in
1438 pixels
1439 @param Delta Not used for EfiBltVideoFill and
1440 EfiBltVideoToVideo operation. If a Delta of 0 is
1441 used, the entire BltBuffer will be operated on. If
1442 a subrectangle of the BltBuffer is used, then
1443 Delta represents the number of bytes in a row of
1444 the BltBuffer.
1445
1446 @retval EFI_INVALID_PARAMETER Invalid parameter passed in
1447 @retval EFI_SUCCESS Blt operation success
1448
1449 **/
1450 EFI_STATUS
1451 EFIAPI
1452 FbGopGraphicsOutputVbeBlt (
1453 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
1454 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL
1455 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,
1456 IN UINTN SourceX,
1457 IN UINTN SourceY,
1458 IN UINTN DestinationX,
1459 IN UINTN DestinationY,
1460 IN UINTN Width,
1461 IN UINTN Height,
1462 IN UINTN Delta
1463 )
1464 {
1465 FB_VIDEO_DEV *FbGopPrivate;
1466 FB_VIDEO_MODE_DATA *Mode;
1467
1468 if (This == NULL) {
1469 return EFI_INVALID_PARAMETER;
1470 }
1471
1472 FbGopPrivate = FB_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This);
1473 Mode = &FbGopPrivate->ModeData[This->Mode->Mode];
1474
1475 return FbGopVbeBltWorker (
1476 FbGopPrivate,
1477 BltBuffer,
1478 BltOperation,
1479 SourceX,
1480 SourceY,
1481 DestinationX,
1482 DestinationY,
1483 Width,
1484 Height,
1485 Delta,
1486 Mode
1487 );
1488 }
1489
1490
1491 /**
1492 The user Entry Point for module UefiFbGop. The user code starts with this function.
1493
1494 @param[in] ImageHandle The firmware allocated handle for the EFI image.
1495 @param[in] SystemTable A pointer to the EFI System Table.
1496
1497 @retval EFI_SUCCESS The entry point is executed successfully.
1498 @retval other Some error occurs when executing this entry point.
1499
1500 **/
1501 EFI_STATUS
1502 EFIAPI
1503 FbGopEntryPoint(
1504 IN EFI_HANDLE ImageHandle,
1505 IN EFI_SYSTEM_TABLE *SystemTable
1506 )
1507 {
1508 EFI_STATUS Status;
1509 EFI_HOB_GUID_TYPE *GuidHob;
1510
1511 //
1512 // Find the frame buffer information guid hob
1513 //
1514 GuidHob = GetFirstGuidHob (&gUefiFrameBufferInfoGuid);
1515 if (GuidHob != NULL) {
1516 mFrameBufferInfo = (FRAME_BUFFER_INFO *)GET_GUID_HOB_DATA (GuidHob);
1517
1518 //
1519 // Install driver model protocol(s).
1520 //
1521 Status = EfiLibInstallDriverBindingComponentName2 (
1522 ImageHandle,
1523 SystemTable,
1524 &gFbGopDriverBinding,
1525 ImageHandle,
1526 &gFbGopComponentName,
1527 &gFbGopComponentName2
1528 );
1529 ASSERT_EFI_ERROR (Status);
1530 } else {
1531 DEBUG ((DEBUG_ERROR, "No FrameBuffer information from coreboot. NO GOP driver !!!\n"));
1532 Status = EFI_ABORTED;
1533 }
1534 return Status;
1535 }
1536