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