]> git.proxmox.com Git - mirror_edk2.git/blob - CorebootPayloadPkg/FbGop/FbGop.c
679061703358427fb367736fc8444ef8342e9d74
[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
438 //
439 // Allocate the private device structure for video device
440 //
441 FbGopPrivate = (FB_VIDEO_DEV *) AllocateZeroPool (
442 sizeof (FB_VIDEO_DEV)
443 );
444 if (NULL == FbGopPrivate) {
445 Status = EFI_OUT_OF_RESOURCES;
446 goto Done;
447 }
448
449 //
450 // See if this is a VGA compatible controller or not
451 //
452 Status = ParentPciIo->Pci.Read (
453 ParentPciIo,
454 EfiPciIoWidthUint32,
455 0,
456 sizeof (Pci) / sizeof (UINT32),
457 &Pci
458 );
459 if (EFI_ERROR (Status)) {
460 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
461 EFI_ERROR_CODE | EFI_ERROR_MINOR,
462 EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_EC_CONTROLLER_ERROR,
463 ParentDevicePath
464 );
465 goto Done;
466 }
467
468 //
469 // Initialize the child private structure
470 //
471 FbGopPrivate->Signature = FB_VIDEO_DEV_SIGNATURE;
472
473 //
474 // Fill in Graphics Output specific mode structures
475 //
476 FbGopPrivate->ModeData = NULL;
477
478 FbGopPrivate->VbeFrameBuffer = NULL;
479
480 FbGopPrivate->EdidDiscovered.SizeOfEdid = 0;
481 FbGopPrivate->EdidDiscovered.Edid = NULL;
482 FbGopPrivate->EdidActive.SizeOfEdid = 0;
483 FbGopPrivate->EdidActive.Edid = NULL;
484
485 //
486 // Fill in the Graphics Output Protocol
487 //
488 FbGopPrivate->GraphicsOutput.QueryMode = FbGopGraphicsOutputQueryMode;
489 FbGopPrivate->GraphicsOutput.SetMode = FbGopGraphicsOutputSetMode;
490
491
492 //
493 // Allocate buffer for Graphics Output Protocol mode information
494 //
495 FbGopPrivate->GraphicsOutput.Mode = (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE *) AllocatePool (
496 sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE)
497 );
498 if (NULL == FbGopPrivate->GraphicsOutput.Mode) {
499 Status = EFI_OUT_OF_RESOURCES;
500 goto Done;
501 }
502
503 FbGopPrivate->GraphicsOutput.Mode->Info = (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *) AllocatePool (
504 sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION)
505 );
506 if (NULL == FbGopPrivate->GraphicsOutput.Mode->Info) {
507 Status = EFI_OUT_OF_RESOURCES;
508 goto Done;
509 }
510
511 //
512 // Set Gop Device Path, here RemainingDevicePath will not be one End of Device Path Node.
513 //
514 if ((RemainingDevicePath == NULL) || (!IsDevicePathEnd (RemainingDevicePath))) {
515 if (RemainingDevicePath == NULL) {
516 ZeroMem (&AcpiDeviceNode, sizeof (ACPI_ADR_DEVICE_PATH));
517 AcpiDeviceNode.Header.Type = ACPI_DEVICE_PATH;
518 AcpiDeviceNode.Header.SubType = ACPI_ADR_DP;
519 AcpiDeviceNode.ADR = ACPI_DISPLAY_ADR (1, 0, 0, 1, 0, ACPI_ADR_DISPLAY_TYPE_VGA, 0, 0);
520 SetDevicePathNodeLength (&AcpiDeviceNode.Header, sizeof (ACPI_ADR_DEVICE_PATH));
521
522 FbGopPrivate->GopDevicePath = AppendDevicePathNode (
523 ParentDevicePath,
524 (EFI_DEVICE_PATH_PROTOCOL *) &AcpiDeviceNode
525 );
526 } else {
527 FbGopPrivate->GopDevicePath = AppendDevicePathNode (ParentDevicePath, RemainingDevicePath);
528 }
529
530 //
531 // Creat child handle and device path protocol firstly
532 //
533 FbGopPrivate->Handle = NULL;
534 Status = gBS->InstallMultipleProtocolInterfaces (
535 &FbGopPrivate->Handle,
536 &gEfiDevicePathProtocolGuid,
537 FbGopPrivate->GopDevicePath,
538 NULL
539 );
540 if (EFI_ERROR (Status)) {
541 goto Done;
542 }
543 }
544
545 //
546 // When check for VBE, PCI I/O protocol is needed, so use parent's protocol interface temporally
547 //
548 FbGopPrivate->PciIo = ParentPciIo;
549
550 //
551 // Check for VESA BIOS Extensions for modes that are compatible with Graphics Output
552 //
553 Status = FbGopCheckForVbe (FbGopPrivate);
554 DEBUG ((EFI_D_INFO, "FbGopCheckForVbe - %r\n", Status));
555
556 if (EFI_ERROR (Status)) {
557 Status = EFI_UNSUPPORTED;
558 //goto Done;
559 }
560
561 //
562 // Creat child handle and install Graphics Output Protocol,EDID Discovered/Active Protocol
563 //
564 Status = gBS->InstallMultipleProtocolInterfaces (
565 &FbGopPrivate->Handle,
566 &gEfiGraphicsOutputProtocolGuid,
567 &FbGopPrivate->GraphicsOutput,
568 &gEfiEdidDiscoveredProtocolGuid,
569 &FbGopPrivate->EdidDiscovered,
570 &gEfiEdidActiveProtocolGuid,
571 &FbGopPrivate->EdidActive,
572 NULL
573 );
574
575 if (!EFI_ERROR (Status)) {
576 //
577 // Open the Parent Handle for the child
578 //
579 Status = gBS->OpenProtocol (
580 ParentHandle,
581 &gEfiPciIoProtocolGuid,
582 (VOID **) &FbGopPrivate->PciIo,
583 This->DriverBindingHandle,
584 FbGopPrivate->Handle,
585 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
586 );
587 if (EFI_ERROR (Status)) {
588 goto Done;
589 }
590 }
591
592 Done:
593 if (EFI_ERROR (Status)) {
594 //
595 // Free private data structure
596 //
597 FbGopDeviceReleaseResource (FbGopPrivate);
598 }
599
600 return Status;
601 }
602
603
604 /**
605 Deregister an video child handle and free resources.
606
607 @param This Protocol instance pointer.
608 @param Controller Video controller handle
609 @param Handle Video child handle
610
611 @return EFI_STATUS
612
613 **/
614 EFI_STATUS
615 FbGopChildHandleUninstall (
616 EFI_DRIVER_BINDING_PROTOCOL *This,
617 EFI_HANDLE Controller,
618 EFI_HANDLE Handle
619 )
620 {
621 EFI_STATUS Status;
622 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
623 FB_VIDEO_DEV *FbGopPrivate;
624 EFI_PCI_IO_PROTOCOL *PciIo;
625
626 FbGopPrivate = NULL;
627 GraphicsOutput = NULL;
628 PciIo = NULL;
629 Status = EFI_UNSUPPORTED;
630
631 Status = gBS->OpenProtocol (
632 Handle,
633 &gEfiGraphicsOutputProtocolGuid,
634 (VOID **) &GraphicsOutput,
635 This->DriverBindingHandle,
636 Handle,
637 EFI_OPEN_PROTOCOL_GET_PROTOCOL
638 );
639 if (!EFI_ERROR (Status)) {
640 FbGopPrivate = FB_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (GraphicsOutput);
641 }
642
643 if (FbGopPrivate == NULL) {
644 return EFI_UNSUPPORTED;
645 }
646
647 //
648 // Close PCI I/O protocol that opened by child handle
649 //
650 Status = gBS->CloseProtocol (
651 Controller,
652 &gEfiPciIoProtocolGuid,
653 This->DriverBindingHandle,
654 Handle
655 );
656
657 //
658 // Uninstall protocols on child handle
659 //
660 Status = gBS->UninstallMultipleProtocolInterfaces (
661 FbGopPrivate->Handle,
662 &gEfiDevicePathProtocolGuid,
663 FbGopPrivate->GopDevicePath,
664 &gEfiGraphicsOutputProtocolGuid,
665 &FbGopPrivate->GraphicsOutput,
666 NULL
667 );
668
669 if (EFI_ERROR (Status)) {
670 gBS->OpenProtocol (
671 Controller,
672 &gEfiPciIoProtocolGuid,
673 (VOID **) &PciIo,
674 This->DriverBindingHandle,
675 Handle,
676 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
677 );
678 return Status;
679 }
680
681 //
682 // Release all allocated resources
683 //
684 FbGopDeviceReleaseResource (FbGopPrivate);
685
686 return EFI_SUCCESS;
687 }
688
689
690 /**
691 Release resource for biso video instance.
692
693 @param FbGopPrivate Video child device private data structure
694
695 **/
696 VOID
697 FbGopDeviceReleaseResource (
698 FB_VIDEO_DEV *FbGopPrivate
699 )
700 {
701 if (FbGopPrivate == NULL) {
702 return ;
703 }
704
705 //
706 // Release all the resourses occupied by the FB_VIDEO_DEV
707 //
708
709 //
710 // Free VBE Frame Buffer
711 //
712 if (FbGopPrivate->VbeFrameBuffer != NULL) {
713 FreePool (FbGopPrivate->VbeFrameBuffer);
714 }
715
716 //
717 // Free mode data
718 //
719 if (FbGopPrivate->ModeData != NULL) {
720 FreePool (FbGopPrivate->ModeData);
721 }
722
723 //
724 // Free graphics output protocol occupied resource
725 //
726 if (FbGopPrivate->GraphicsOutput.Mode != NULL) {
727 if (FbGopPrivate->GraphicsOutput.Mode->Info != NULL) {
728 FreePool (FbGopPrivate->GraphicsOutput.Mode->Info);
729 FbGopPrivate->GraphicsOutput.Mode->Info = NULL;
730 }
731 FreePool (FbGopPrivate->GraphicsOutput.Mode);
732 FbGopPrivate->GraphicsOutput.Mode = NULL;
733 }
734
735 if (FbGopPrivate->GopDevicePath!= NULL) {
736 FreePool (FbGopPrivate->GopDevicePath);
737 }
738
739 FreePool (FbGopPrivate);
740
741 return ;
742 }
743
744
745
746 /**
747 Check if all video child handles have been uninstalled.
748
749 @param Controller Video controller handle
750
751 @return TRUE Child handles exist.
752 @return FALSE All video child handles have been uninstalled.
753
754 **/
755 BOOLEAN
756 HasChildHandle (
757 IN EFI_HANDLE Controller
758 )
759 {
760 UINTN Index;
761 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer;
762 UINTN EntryCount;
763 BOOLEAN HasChild;
764
765 EntryCount = 0;
766 HasChild = FALSE;
767 gBS->OpenProtocolInformation (
768 Controller,
769 &gEfiPciIoProtocolGuid,
770 &OpenInfoBuffer,
771 &EntryCount
772 );
773 for (Index = 0; Index < EntryCount; Index++) {
774 if ((OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {
775 HasChild = TRUE;
776 }
777 }
778
779 return HasChild;
780 }
781
782 /**
783 Check for VBE device.
784
785 @param FbGopPrivate Pointer to FB_VIDEO_DEV structure
786
787 @retval EFI_SUCCESS VBE device found
788
789 **/
790 EFI_STATUS
791 FbGopCheckForVbe (
792 IN OUT FB_VIDEO_DEV *FbGopPrivate
793 )
794 {
795 EFI_STATUS Status;
796 FB_VIDEO_MODE_DATA *ModeBuffer;
797 FB_VIDEO_MODE_DATA *CurrentModeData;
798 UINTN ModeNumber;
799 UINTN BitsPerPixel;
800 UINTN BytesPerScanLine;
801 UINT32 HorizontalResolution;
802 UINT32 VerticalResolution;
803 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *VbeFrameBuffer;
804 EFI_HOB_GUID_TYPE *GuidHob;
805 FRAME_BUFFER_INFO *pFbInfo;
806
807 Status = EFI_SUCCESS;
808 //
809 // Find the frame buffer information guid hob
810 //
811 GuidHob = GetFirstGuidHob (&gUefiFrameBufferInfoGuid);
812 ASSERT (GuidHob != NULL);
813 pFbInfo = (FRAME_BUFFER_INFO *)GET_GUID_HOB_DATA (GuidHob);
814
815 //
816 // Add mode to the list of available modes
817 //
818 VbeFrameBuffer = NULL;
819 ModeBuffer = NULL;
820
821 ModeNumber = 1;
822 BitsPerPixel = pFbInfo->BitsPerPixel;
823 HorizontalResolution = pFbInfo->HorizontalResolution;
824 VerticalResolution = pFbInfo->VerticalResolution;
825 BytesPerScanLine = pFbInfo->BytesPerScanLine;
826
827 ModeBuffer = (FB_VIDEO_MODE_DATA *) AllocatePool (
828 ModeNumber * sizeof (FB_VIDEO_MODE_DATA)
829 );
830 if (NULL == ModeBuffer) {
831 Status = EFI_OUT_OF_RESOURCES;
832 goto Done;
833 }
834
835 VbeFrameBuffer =
836 (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) AllocatePool (
837 BytesPerScanLine * VerticalResolution
838 );
839 if (NULL == VbeFrameBuffer) {
840 Status = EFI_OUT_OF_RESOURCES;
841 goto Done;
842 }
843
844 if (FbGopPrivate->ModeData != NULL) {
845 FreePool (FbGopPrivate->ModeData);
846 }
847
848 if (FbGopPrivate->VbeFrameBuffer != NULL) {
849 FreePool (FbGopPrivate->VbeFrameBuffer);
850 }
851
852 CurrentModeData = &ModeBuffer[ModeNumber - 1];
853 CurrentModeData->BytesPerScanLine = (UINT16)BytesPerScanLine;
854
855 CurrentModeData->Red = *(FB_VIDEO_COLOR_PLACEMENT *)&(pFbInfo->Red);
856 CurrentModeData->Blue = *(FB_VIDEO_COLOR_PLACEMENT *)&(pFbInfo->Blue);
857 CurrentModeData->Green = *(FB_VIDEO_COLOR_PLACEMENT *)&(pFbInfo->Green);
858 CurrentModeData->Reserved = *(FB_VIDEO_COLOR_PLACEMENT *)&(pFbInfo->Reserved);
859
860 CurrentModeData->BitsPerPixel = (UINT32)BitsPerPixel;
861 CurrentModeData->HorizontalResolution = HorizontalResolution;
862 CurrentModeData->VerticalResolution = VerticalResolution;
863 CurrentModeData->FrameBufferSize = CurrentModeData->BytesPerScanLine * CurrentModeData->VerticalResolution;
864 CurrentModeData->LinearFrameBuffer = (VOID *) (UINTN) pFbInfo->LinearFrameBuffer;
865 CurrentModeData->VbeModeNumber = 0;
866 CurrentModeData->ColorDepth = 32;
867 CurrentModeData->RefreshRate = 60;
868
869 CurrentModeData->PixelFormat = PixelBitMask;
870 if ((CurrentModeData->BitsPerPixel == 32) &&
871 (CurrentModeData->Red.Mask == 0xff) && (CurrentModeData->Green.Mask == 0xff) && (CurrentModeData->Blue.Mask == 0xff)) {
872 if ((CurrentModeData->Red.Position == 0) && (CurrentModeData->Green.Position == 8) && (CurrentModeData->Blue.Position == 16)) {
873 CurrentModeData->PixelFormat = PixelRedGreenBlueReserved8BitPerColor;
874 } else if ((CurrentModeData->Blue.Position == 0) && (CurrentModeData->Green.Position == 8) && (CurrentModeData->Red.Position == 16)) {
875 CurrentModeData->PixelFormat = PixelBlueGreenRedReserved8BitPerColor;
876 }
877 }
878
879 CopyMem (&(CurrentModeData->PixelBitMask), &mPixelBitMask, sizeof (EFI_PIXEL_BITMASK));
880
881 FbGopPrivate->ModeData = ModeBuffer;
882 FbGopPrivate->VbeFrameBuffer = VbeFrameBuffer;
883
884 //
885 // Assign Gop's Blt function
886 //
887 FbGopPrivate->GraphicsOutput.Blt = FbGopGraphicsOutputVbeBlt;
888
889 FbGopPrivate->GraphicsOutput.Mode->MaxMode = 1;
890 FbGopPrivate->GraphicsOutput.Mode->Mode = 0;
891 FbGopPrivate->GraphicsOutput.Mode->Info->Version = 0;
892 FbGopPrivate->GraphicsOutput.Mode->Info->HorizontalResolution = HorizontalResolution;
893 FbGopPrivate->GraphicsOutput.Mode->Info->VerticalResolution = VerticalResolution;
894 FbGopPrivate->GraphicsOutput.Mode->Info->PixelFormat = CurrentModeData->PixelFormat;
895 CopyMem (&(FbGopPrivate->GraphicsOutput.Mode->Info->PixelInformation), &mPixelBitMask, sizeof (EFI_PIXEL_BITMASK));
896 FbGopPrivate->GraphicsOutput.Mode->Info->PixelsPerScanLine = HorizontalResolution;
897 FbGopPrivate->GraphicsOutput.Mode->SizeOfInfo = sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
898 FbGopPrivate->GraphicsOutput.Mode->FrameBufferBase = (EFI_PHYSICAL_ADDRESS) (UINTN) CurrentModeData->LinearFrameBuffer;
899 FbGopPrivate->GraphicsOutput.Mode->FrameBufferSize = CurrentModeData->FrameBufferSize;
900
901 //
902 // Find the best mode to initialize
903 //
904
905 Done:
906 //
907 // If there was an error, then free the mode structure
908 //
909 if (EFI_ERROR (Status)) {
910
911 if (VbeFrameBuffer != NULL) {
912 FreePool (VbeFrameBuffer);
913 }
914
915 if (ModeBuffer != NULL) {
916 FreePool (ModeBuffer);
917 }
918 }
919
920 return Status;
921 }
922
923
924 //
925 // Graphics Output Protocol Member Functions for VESA BIOS Extensions
926 //
927
928 /**
929 Graphics Output protocol interface to get video mode.
930
931 @param This Protocol instance pointer.
932 @param ModeNumber The mode number to return information on.
933 @param SizeOfInfo A pointer to the size, in bytes, of the Info
934 buffer.
935 @param Info Caller allocated buffer that returns information
936 about ModeNumber.
937
938 @retval EFI_SUCCESS Mode information returned.
939 @retval EFI_DEVICE_ERROR A hardware error occurred trying to retrieve the
940 video mode.
941 @retval EFI_NOT_STARTED Video display is not initialized. Call SetMode ()
942 @retval EFI_INVALID_PARAMETER One of the input args was NULL.
943
944 **/
945 EFI_STATUS
946 EFIAPI
947 FbGopGraphicsOutputQueryMode (
948 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
949 IN UINT32 ModeNumber,
950 OUT UINTN *SizeOfInfo,
951 OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info
952 )
953 {
954 FB_VIDEO_DEV *FbGopPrivate;
955 FB_VIDEO_MODE_DATA *ModeData;
956
957 FbGopPrivate = FB_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This);
958
959 if (This == NULL || Info == NULL || SizeOfInfo == NULL || ModeNumber >= This->Mode->MaxMode) {
960 return EFI_INVALID_PARAMETER;
961 }
962
963 *Info = (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *) AllocatePool (
964 sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION)
965 );
966 if (NULL == *Info) {
967 return EFI_OUT_OF_RESOURCES;
968 }
969
970 *SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
971
972 ModeData = &FbGopPrivate->ModeData[ModeNumber];
973 (*Info)->Version = 0;
974 (*Info)->HorizontalResolution = ModeData->HorizontalResolution;
975 (*Info)->VerticalResolution = ModeData->VerticalResolution;
976 (*Info)->PixelFormat = ModeData->PixelFormat;
977 CopyMem (&((*Info)->PixelInformation), &(ModeData->PixelBitMask), sizeof(ModeData->PixelBitMask));
978
979 (*Info)->PixelsPerScanLine = (ModeData->BytesPerScanLine * 8) / ModeData->BitsPerPixel;
980
981 return EFI_SUCCESS;
982 }
983
984 /**
985 Graphics Output protocol interface to set video mode.
986
987 @param This Protocol instance pointer.
988 @param ModeNumber The mode number to be set.
989
990 @retval EFI_SUCCESS Graphics mode was changed.
991 @retval EFI_DEVICE_ERROR The device had an error and could not complete the
992 request.
993 @retval EFI_UNSUPPORTED ModeNumber is not supported by this device.
994
995 **/
996 EFI_STATUS
997 EFIAPI
998 FbGopGraphicsOutputSetMode (
999 IN EFI_GRAPHICS_OUTPUT_PROTOCOL * This,
1000 IN UINT32 ModeNumber
1001 )
1002 {
1003 FB_VIDEO_DEV *FbGopPrivate;
1004 FB_VIDEO_MODE_DATA *ModeData;
1005 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background;
1006
1007 if (This == NULL) {
1008 return EFI_INVALID_PARAMETER;
1009 }
1010
1011 FbGopPrivate = FB_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This);
1012
1013 ModeData = &FbGopPrivate->ModeData[ModeNumber];
1014
1015 if (ModeNumber >= This->Mode->MaxMode) {
1016 return EFI_UNSUPPORTED;
1017 }
1018
1019 if (ModeNumber == This->Mode->Mode) {
1020 //
1021 // Clear screen to black
1022 //
1023 ZeroMem (&Background, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
1024 FbGopGraphicsOutputVbeBlt (
1025 This,
1026 &Background,
1027 EfiBltVideoFill,
1028 0,
1029 0,
1030 0,
1031 0,
1032 ModeData->HorizontalResolution,
1033 ModeData->VerticalResolution,
1034 0
1035 );
1036 return EFI_SUCCESS;
1037 } else {
1038 return EFI_UNSUPPORTED;
1039 }
1040
1041 }
1042
1043 /**
1044 Update physical frame buffer, copy 4 bytes block, then copy remaining bytes.
1045
1046 @param PciIo The pointer of EFI_PCI_IO_PROTOCOL
1047 @param VbeBuffer The data to transfer to screen
1048 @param MemAddress Physical frame buffer base address
1049 @param DestinationX The X coordinate of the destination for BltOperation
1050 @param DestinationY The Y coordinate of the destination for BltOperation
1051 @param TotalBytes The total bytes of copy
1052 @param VbePixelWidth Bytes per pixel
1053 @param BytesPerScanLine Bytes per scan line
1054
1055 **/
1056 VOID
1057 CopyVideoBuffer (
1058 IN EFI_PCI_IO_PROTOCOL *PciIo,
1059 IN UINT8 *VbeBuffer,
1060 IN VOID *MemAddress,
1061 IN UINTN DestinationX,
1062 IN UINTN DestinationY,
1063 IN UINTN TotalBytes,
1064 IN UINT32 VbePixelWidth,
1065 IN UINTN BytesPerScanLine
1066 )
1067 {
1068 UINTN FrameBufferAddr;
1069 UINTN CopyBlockNum;
1070 UINTN RemainingBytes;
1071 UINTN UnalignedBytes;
1072 EFI_STATUS Status;
1073
1074 FrameBufferAddr = (UINTN) MemAddress + (DestinationY * BytesPerScanLine) + DestinationX * VbePixelWidth;
1075
1076 //
1077 // If TotalBytes is less than 4 bytes, only start byte copy.
1078 //
1079 if (TotalBytes < 4) {
1080 Status = PciIo->Mem.Write (
1081 PciIo,
1082 EfiPciIoWidthUint8,
1083 EFI_PCI_IO_PASS_THROUGH_BAR,
1084 (UINT64) FrameBufferAddr,
1085 TotalBytes,
1086 VbeBuffer
1087 );
1088 ASSERT_EFI_ERROR (Status);
1089 return;
1090 }
1091
1092 //
1093 // If VbeBuffer is not 4-byte aligned, start byte copy.
1094 //
1095 UnalignedBytes = (4 - ((UINTN) VbeBuffer & 0x3)) & 0x3;
1096
1097 if (UnalignedBytes != 0) {
1098 Status = PciIo->Mem.Write (
1099 PciIo,
1100 EfiPciIoWidthUint8,
1101 EFI_PCI_IO_PASS_THROUGH_BAR,
1102 (UINT64) FrameBufferAddr,
1103 UnalignedBytes,
1104 VbeBuffer
1105 );
1106 ASSERT_EFI_ERROR (Status);
1107 FrameBufferAddr += UnalignedBytes;
1108 VbeBuffer += UnalignedBytes;
1109 }
1110
1111 //
1112 // Calculate 4-byte block count and remaining bytes.
1113 //
1114 CopyBlockNum = (TotalBytes - UnalignedBytes) >> 2;
1115 RemainingBytes = (TotalBytes - UnalignedBytes) & 3;
1116
1117 //
1118 // Copy 4-byte block and remaining bytes to physical frame buffer.
1119 //
1120 if (CopyBlockNum != 0) {
1121 Status = PciIo->Mem.Write (
1122 PciIo,
1123 EfiPciIoWidthUint32,
1124 EFI_PCI_IO_PASS_THROUGH_BAR,
1125 (UINT64) FrameBufferAddr,
1126 CopyBlockNum,
1127 VbeBuffer
1128 );
1129 ASSERT_EFI_ERROR (Status);
1130 }
1131
1132 if (RemainingBytes != 0) {
1133 FrameBufferAddr += (CopyBlockNum << 2);
1134 VbeBuffer += (CopyBlockNum << 2);
1135 Status = PciIo->Mem.Write (
1136 PciIo,
1137 EfiPciIoWidthUint8,
1138 EFI_PCI_IO_PASS_THROUGH_BAR,
1139 (UINT64) FrameBufferAddr,
1140 RemainingBytes,
1141 VbeBuffer
1142 );
1143 ASSERT_EFI_ERROR (Status);
1144 }
1145 }
1146
1147 /**
1148 Worker function to block transfer for VBE device.
1149
1150 @param FbGopPrivate Instance of FB_VIDEO_DEV
1151 @param BltBuffer The data to transfer to screen
1152 @param BltOperation The operation to perform
1153 @param SourceX The X coordinate of the source for BltOperation
1154 @param SourceY The Y coordinate of the source for BltOperation
1155 @param DestinationX The X coordinate of the destination for
1156 BltOperation
1157 @param DestinationY The Y coordinate of the destination for
1158 BltOperation
1159 @param Width The width of a rectangle in the blt rectangle in
1160 pixels
1161 @param Height The height of a rectangle in the blt rectangle in
1162 pixels
1163 @param Delta Not used for EfiBltVideoFill and
1164 EfiBltVideoToVideo operation. If a Delta of 0 is
1165 used, the entire BltBuffer will be operated on. If
1166 a subrectangle of the BltBuffer is used, then
1167 Delta represents the number of bytes in a row of
1168 the BltBuffer.
1169 @param Mode Mode data.
1170
1171 @retval EFI_INVALID_PARAMETER Invalid parameter passed in
1172 @retval EFI_SUCCESS Blt operation success
1173
1174 **/
1175 EFI_STATUS
1176 FbGopVbeBltWorker (
1177 IN FB_VIDEO_DEV *FbGopPrivate,
1178 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL
1179 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,
1180 IN UINTN SourceX,
1181 IN UINTN SourceY,
1182 IN UINTN DestinationX,
1183 IN UINTN DestinationY,
1184 IN UINTN Width,
1185 IN UINTN Height,
1186 IN UINTN Delta,
1187 IN FB_VIDEO_MODE_DATA *Mode
1188 )
1189 {
1190 EFI_PCI_IO_PROTOCOL *PciIo;
1191 EFI_TPL OriginalTPL;
1192 UINTN DstY;
1193 UINTN SrcY;
1194 UINTN DstX;
1195 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt;
1196 VOID *MemAddress;
1197 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *VbeFrameBuffer;
1198 UINTN BytesPerScanLine;
1199 UINTN Index;
1200 UINT8 *VbeBuffer;
1201 UINT8 *VbeBuffer1;
1202 UINT8 *BltUint8;
1203 UINT32 VbePixelWidth;
1204 UINT32 Pixel;
1205 UINTN TotalBytes;
1206
1207 PciIo = FbGopPrivate->PciIo;
1208
1209 VbeFrameBuffer = FbGopPrivate->VbeFrameBuffer;
1210 MemAddress = Mode->LinearFrameBuffer;
1211 BytesPerScanLine = Mode->BytesPerScanLine;
1212 VbePixelWidth = Mode->BitsPerPixel / 8;
1213 BltUint8 = (UINT8 *) BltBuffer;
1214 TotalBytes = Width * VbePixelWidth;
1215
1216 if (((UINTN) BltOperation) >= EfiGraphicsOutputBltOperationMax) {
1217 return EFI_INVALID_PARAMETER;
1218 }
1219
1220 if (Width == 0 || Height == 0) {
1221 return EFI_INVALID_PARAMETER;
1222 }
1223 //
1224 // We need to fill the Virtual Screen buffer with the blt data.
1225 // The virtual screen is upside down, as the first row is the bootom row of
1226 // the image.
1227 //
1228 if (BltOperation == EfiBltVideoToBltBuffer) {
1229 //
1230 // Video to BltBuffer: Source is Video, destination is BltBuffer
1231 //
1232 if (SourceY + Height > Mode->VerticalResolution) {
1233 return EFI_INVALID_PARAMETER;
1234 }
1235
1236 if (SourceX + Width > Mode->HorizontalResolution) {
1237 return EFI_INVALID_PARAMETER;
1238 }
1239 } else {
1240 //
1241 // BltBuffer to Video: Source is BltBuffer, destination is Video
1242 //
1243 if (DestinationY + Height > Mode->VerticalResolution) {
1244 return EFI_INVALID_PARAMETER;
1245 }
1246
1247 if (DestinationX + Width > Mode->HorizontalResolution) {
1248 return EFI_INVALID_PARAMETER;
1249 }
1250 }
1251 //
1252 // If Delta is zero, then the entire BltBuffer is being used, so Delta
1253 // is the number of bytes in each row of BltBuffer. Since BltBuffer is Width pixels size,
1254 // the number of bytes in each row can be computed.
1255 //
1256 if (Delta == 0) {
1257 Delta = Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
1258 }
1259 //
1260 // We have to raise to TPL Notify, so we make an atomic write the frame buffer.
1261 // We would not want a timer based event (Cursor, ...) to come in while we are
1262 // doing this operation.
1263 //
1264 OriginalTPL = gBS->RaiseTPL (TPL_NOTIFY);
1265
1266 switch (BltOperation) {
1267 case EfiBltVideoToBltBuffer:
1268 for (SrcY = SourceY, DstY = DestinationY; DstY < (Height + DestinationY); SrcY++, DstY++) {
1269 Blt = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) (BltUint8 + DstY * Delta + DestinationX * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
1270 //
1271 // Shuffle the packed bytes in the hardware buffer to match EFI_GRAPHICS_OUTPUT_BLT_PIXEL
1272 //
1273 VbeBuffer = ((UINT8 *) VbeFrameBuffer + (SrcY * BytesPerScanLine + SourceX * VbePixelWidth));
1274 for (DstX = DestinationX; DstX < (Width + DestinationX); DstX++) {
1275 Pixel = VbeBuffer[0] | VbeBuffer[1] << 8 | VbeBuffer[2] << 16 | VbeBuffer[3] << 24;
1276 Blt->Red = (UINT8) ((Pixel >> Mode->Red.Position) & Mode->Red.Mask);
1277 Blt->Blue = (UINT8) ((Pixel >> Mode->Blue.Position) & Mode->Blue.Mask);
1278 Blt->Green = (UINT8) ((Pixel >> Mode->Green.Position) & Mode->Green.Mask);
1279 Blt->Reserved = 0;
1280 Blt++;
1281 VbeBuffer += VbePixelWidth;
1282 }
1283
1284 }
1285 break;
1286
1287 case EfiBltVideoToVideo:
1288 for (Index = 0; Index < Height; Index++) {
1289 if (DestinationY <= SourceY) {
1290 SrcY = SourceY + Index;
1291 DstY = DestinationY + Index;
1292 } else {
1293 SrcY = SourceY + Height - Index - 1;
1294 DstY = DestinationY + Height - Index - 1;
1295 }
1296
1297 VbeBuffer = ((UINT8 *) VbeFrameBuffer + DstY * BytesPerScanLine + DestinationX * VbePixelWidth);
1298 VbeBuffer1 = ((UINT8 *) VbeFrameBuffer + SrcY * BytesPerScanLine + SourceX * VbePixelWidth);
1299
1300 gBS->CopyMem (
1301 VbeBuffer,
1302 VbeBuffer1,
1303 TotalBytes
1304 );
1305
1306 //
1307 // Update physical frame buffer.
1308 //
1309 CopyVideoBuffer (
1310 PciIo,
1311 VbeBuffer,
1312 MemAddress,
1313 DestinationX,
1314 DstY,
1315 TotalBytes,
1316 VbePixelWidth,
1317 BytesPerScanLine
1318 );
1319 }
1320 break;
1321
1322 case EfiBltVideoFill:
1323 VbeBuffer = (UINT8 *) ((UINTN) VbeFrameBuffer + (DestinationY * BytesPerScanLine) + DestinationX * VbePixelWidth);
1324 Blt = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) BltUint8;
1325 //
1326 // Shuffle the RGB fields in EFI_GRAPHICS_OUTPUT_BLT_PIXEL to match the hardware buffer
1327 //
1328 Pixel = ((Blt->Red & Mode->Red.Mask) << Mode->Red.Position) |
1329 (
1330 (Blt->Green & Mode->Green.Mask) <<
1331 Mode->Green.Position
1332 ) |
1333 ((Blt->Blue & Mode->Blue.Mask) << Mode->Blue.Position);
1334
1335 for (Index = 0; Index < Width; Index++) {
1336 gBS->CopyMem (
1337 VbeBuffer,
1338 &Pixel,
1339 VbePixelWidth
1340 );
1341 VbeBuffer += VbePixelWidth;
1342 }
1343
1344 VbeBuffer = (UINT8 *) ((UINTN) VbeFrameBuffer + (DestinationY * BytesPerScanLine) + DestinationX * VbePixelWidth);
1345 for (DstY = DestinationY + 1; DstY < (Height + DestinationY); DstY++) {
1346 gBS->CopyMem (
1347 (VOID *) ((UINTN) VbeFrameBuffer + (DstY * BytesPerScanLine) + DestinationX * VbePixelWidth),
1348 VbeBuffer,
1349 TotalBytes
1350 );
1351 }
1352
1353 for (DstY = DestinationY; DstY < (Height + DestinationY); DstY++) {
1354 //
1355 // Update physical frame buffer.
1356 //
1357 CopyVideoBuffer (
1358 PciIo,
1359 VbeBuffer,
1360 MemAddress,
1361 DestinationX,
1362 DstY,
1363 TotalBytes,
1364 VbePixelWidth,
1365 BytesPerScanLine
1366 );
1367 }
1368 break;
1369
1370 case EfiBltBufferToVideo:
1371 for (SrcY = SourceY, DstY = DestinationY; SrcY < (Height + SourceY); SrcY++, DstY++) {
1372 Blt = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) (BltUint8 + (SrcY * Delta) + (SourceX) * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
1373 VbeBuffer = ((UINT8 *) VbeFrameBuffer + (DstY * BytesPerScanLine + DestinationX * VbePixelWidth));
1374 for (DstX = DestinationX; DstX < (Width + DestinationX); DstX++) {
1375 //
1376 // Shuffle the RGB fields in EFI_GRAPHICS_OUTPUT_BLT_PIXEL to match the hardware buffer
1377 //
1378 Pixel = ((Blt->Red & Mode->Red.Mask) << Mode->Red.Position) |
1379 ((Blt->Green & Mode->Green.Mask) << Mode->Green.Position) |
1380 ((Blt->Blue & Mode->Blue.Mask) << Mode->Blue.Position);
1381 gBS->CopyMem (
1382 VbeBuffer,
1383 &Pixel,
1384 VbePixelWidth
1385 );
1386 Blt++;
1387 VbeBuffer += VbePixelWidth;
1388 }
1389
1390 VbeBuffer = ((UINT8 *) VbeFrameBuffer + (DstY * BytesPerScanLine + DestinationX * VbePixelWidth));
1391
1392 //
1393 // Update physical frame buffer.
1394 //
1395 CopyVideoBuffer (
1396 PciIo,
1397 VbeBuffer,
1398 MemAddress,
1399 DestinationX,
1400 DstY,
1401 TotalBytes,
1402 VbePixelWidth,
1403 BytesPerScanLine
1404 );
1405 }
1406 break;
1407
1408 default: ;
1409 }
1410
1411 gBS->RestoreTPL (OriginalTPL);
1412
1413 return EFI_SUCCESS;
1414 }
1415
1416 /**
1417 Graphics Output protocol instance to block transfer for VBE device.
1418
1419 @param This Pointer to Graphics Output protocol instance
1420 @param BltBuffer The data to transfer to screen
1421 @param BltOperation The operation to perform
1422 @param SourceX The X coordinate of the source for BltOperation
1423 @param SourceY The Y coordinate of the source for BltOperation
1424 @param DestinationX The X coordinate of the destination for
1425 BltOperation
1426 @param DestinationY The Y coordinate of the destination for
1427 BltOperation
1428 @param Width The width of a rectangle in the blt rectangle in
1429 pixels
1430 @param Height The height of a rectangle in the blt rectangle in
1431 pixels
1432 @param Delta Not used for EfiBltVideoFill and
1433 EfiBltVideoToVideo operation. If a Delta of 0 is
1434 used, the entire BltBuffer will be operated on. If
1435 a subrectangle of the BltBuffer is used, then
1436 Delta represents the number of bytes in a row of
1437 the BltBuffer.
1438
1439 @retval EFI_INVALID_PARAMETER Invalid parameter passed in
1440 @retval EFI_SUCCESS Blt operation success
1441
1442 **/
1443 EFI_STATUS
1444 EFIAPI
1445 FbGopGraphicsOutputVbeBlt (
1446 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
1447 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL
1448 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,
1449 IN UINTN SourceX,
1450 IN UINTN SourceY,
1451 IN UINTN DestinationX,
1452 IN UINTN DestinationY,
1453 IN UINTN Width,
1454 IN UINTN Height,
1455 IN UINTN Delta
1456 )
1457 {
1458 FB_VIDEO_DEV *FbGopPrivate;
1459 FB_VIDEO_MODE_DATA *Mode;
1460
1461 if (This == NULL) {
1462 return EFI_INVALID_PARAMETER;
1463 }
1464
1465 FbGopPrivate = FB_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This);
1466 Mode = &FbGopPrivate->ModeData[This->Mode->Mode];
1467
1468 return FbGopVbeBltWorker (
1469 FbGopPrivate,
1470 BltBuffer,
1471 BltOperation,
1472 SourceX,
1473 SourceY,
1474 DestinationX,
1475 DestinationY,
1476 Width,
1477 Height,
1478 Delta,
1479 Mode
1480 );
1481 }
1482
1483
1484 /**
1485 The user Entry Point for module UefiFbGop. The user code starts with this function.
1486
1487 @param[in] ImageHandle The firmware allocated handle for the EFI image.
1488 @param[in] SystemTable A pointer to the EFI System Table.
1489
1490 @retval EFI_SUCCESS The entry point is executed successfully.
1491 @retval other Some error occurs when executing this entry point.
1492
1493 **/
1494 EFI_STATUS
1495 EFIAPI
1496 FbGopEntryPoint(
1497 IN EFI_HANDLE ImageHandle,
1498 IN EFI_SYSTEM_TABLE *SystemTable
1499 )
1500 {
1501 EFI_STATUS Status;
1502 EFI_HOB_GUID_TYPE *GuidHob;
1503
1504 //
1505 // Find the frame buffer information guid hob
1506 //
1507 GuidHob = GetFirstGuidHob (&gUefiFrameBufferInfoGuid);
1508 if (GuidHob != NULL) {
1509 //
1510 // Install driver model protocol(s).
1511 //
1512 Status = EfiLibInstallDriverBindingComponentName2 (
1513 ImageHandle,
1514 SystemTable,
1515 &gFbGopDriverBinding,
1516 ImageHandle,
1517 &gFbGopComponentName,
1518 &gFbGopComponentName2
1519 );
1520 ASSERT_EFI_ERROR (Status);
1521 } else {
1522 DEBUG ((EFI_D_ERROR, "No FrameBuffer information from coreboot. NO GOP driver !!!\n"));
1523 Status = EFI_ABORTED;
1524 }
1525 return Status;
1526 }
1527