• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
FbGopDriverBindingSupported(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Controller,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath)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
FbGopDriverBindingStart(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Controller,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath)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
FbGopDriverBindingStop(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Controller,IN UINTN NumberOfChildren,IN EFI_HANDLE * ChildHandleBuffer)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
FbGopChildHandleInstall(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE ParentHandle,IN EFI_PCI_IO_PROTOCOL * ParentPciIo,IN VOID * ParentLegacyBios,IN EFI_DEVICE_PATH_PROTOCOL * ParentDevicePath,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath)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
FbGopChildHandleUninstall(EFI_DRIVER_BINDING_PROTOCOL * This,EFI_HANDLE Controller,EFI_HANDLE Handle)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
FbGopDeviceReleaseResource(FB_VIDEO_DEV * FbGopPrivate)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
HasChildHandle(IN EFI_HANDLE Controller)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
FbGopCheckForVbe(IN OUT FB_VIDEO_DEV * FbGopPrivate)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     = HorizontalResolution * (BitsPerPixel / 8);
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
FbGopGraphicsOutputQueryMode(IN EFI_GRAPHICS_OUTPUT_PROTOCOL * This,IN UINT32 ModeNumber,OUT UINTN * SizeOfInfo,OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION ** Info)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
FbGopGraphicsOutputSetMode(IN EFI_GRAPHICS_OUTPUT_PROTOCOL * This,IN UINT32 ModeNumber)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
CopyVideoBuffer(IN EFI_PCI_IO_PROTOCOL * PciIo,IN UINT8 * VbeBuffer,IN VOID * MemAddress,IN UINTN DestinationX,IN UINTN DestinationY,IN UINTN TotalBytes,IN UINT32 VbePixelWidth,IN UINTN BytesPerScanLine)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
FbGopVbeBltWorker(IN FB_VIDEO_DEV * FbGopPrivate,IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL * BltBuffer,OPTIONAL IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,IN UINTN SourceX,IN UINTN SourceY,IN UINTN DestinationX,IN UINTN DestinationY,IN UINTN Width,IN UINTN Height,IN UINTN Delta,IN FB_VIDEO_MODE_DATA * Mode)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
FbGopGraphicsOutputVbeBlt(IN EFI_GRAPHICS_OUTPUT_PROTOCOL * This,IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL * BltBuffer,OPTIONAL IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,IN UINTN SourceX,IN UINTN SourceY,IN UINTN DestinationX,IN UINTN DestinationY,IN UINTN Width,IN UINTN Height,IN UINTN Delta)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
FbGopEntryPoint(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)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 
1528