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