1 /** @file
2   Implements EFI Driver Binding Protocol and VGA Mini Port Protocol for VGA Mini Port Driver.
3 
4 Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6 
7 **/
8 
9 #include "VgaMiniPort.h"
10 
11 //
12 // EFI Driver Binding Protocol Instance
13 //
14 //   This driver has a version value of 0x00000000.  This is the
15 //   lowest possible priority for a driver.  This is done on purpose to help
16 //   the developers of UGA drivers.  This driver can bind if no UGA driver
17 //   is present, so a console is available.  Then, when a UGA driver is loaded
18 //   this driver can be disconnected, and the UGA driver can be connected.
19 //   As long as the UGA driver has a version value greater than 0x00000000, it
20 //   will be connected first and will block this driver from connecting.
21 //
22 EFI_DRIVER_BINDING_PROTOCOL gPciVgaMiniPortDriverBinding = {
23   PciVgaMiniPortDriverBindingSupported,
24   PciVgaMiniPortDriverBindingStart,
25   PciVgaMiniPortDriverBindingStop,
26   0x00000000,
27   NULL,
28   NULL
29 };
30 
31 /**
32   Entrypoint of VGA Mini Port Driver.
33 
34   This function is the entrypoint of UVGA Mini Port Driver. It installs Driver Binding
35   Protocols together with Component Name Protocols.
36 
37   @param  ImageHandle       The firmware allocated handle for the EFI image.
38   @param  SystemTable       A pointer to the EFI System Table.
39 
40   @retval EFI_SUCCESS       The entry point is executed successfully.
41 
42 **/
43 EFI_STATUS
44 EFIAPI
PciVgaMiniPortDriverEntryPoint(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)45 PciVgaMiniPortDriverEntryPoint (
46   IN EFI_HANDLE         ImageHandle,
47   IN EFI_SYSTEM_TABLE   *SystemTable
48   )
49 {
50   EFI_STATUS              Status;
51 
52   Status = EfiLibInstallDriverBindingComponentName2 (
53              ImageHandle,
54              SystemTable,
55              &gPciVgaMiniPortDriverBinding,
56              ImageHandle,
57              &gPciVgaMiniPortComponentName,
58              &gPciVgaMiniPortComponentName2
59              );
60   ASSERT_EFI_ERROR (Status);
61 
62   return EFI_SUCCESS;
63 }
64 
65 
66 /**
67   Check whether VGA Mini Port driver supports this device.
68 
69   @param  This                   The driver binding protocol.
70   @param  Controller             The controller handle to check.
71   @param  RemainingDevicePath    The remaining device path.
72 
73   @retval EFI_SUCCESS            The driver supports this controller.
74   @retval EFI_UNSUPPORTED        This device isn't supported.
75 
76 **/
77 EFI_STATUS
78 EFIAPI
PciVgaMiniPortDriverBindingSupported(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Controller,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath)79 PciVgaMiniPortDriverBindingSupported (
80   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
81   IN EFI_HANDLE                   Controller,
82   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
83   )
84 {
85   EFI_STATUS          Status;
86   EFI_PCI_IO_PROTOCOL *PciIo;
87   PCI_TYPE00          Pci;
88 
89   //
90   // Open the IO Abstraction(s) needed to perform the supported test
91   //
92   Status = gBS->OpenProtocol (
93                   Controller,
94                   &gEfiPciIoProtocolGuid,
95                   (VOID **) &PciIo,
96                   This->DriverBindingHandle,
97                   Controller,
98                   EFI_OPEN_PROTOCOL_BY_DRIVER
99                   );
100   if (EFI_ERROR (Status)) {
101     return Status;
102   }
103   //
104   // See if this is a PCI VGA Controller by looking at the Command register and
105   // Class Code Register
106   //
107   Status = PciIo->Pci.Read (
108                         PciIo,
109                         EfiPciIoWidthUint32,
110                         0,
111                         sizeof (Pci) / sizeof (UINT32),
112                         &Pci
113                         );
114   if (EFI_ERROR (Status)) {
115     goto Done;
116   }
117 
118   Status = EFI_UNSUPPORTED;
119   //
120   // See if the device is an enabled VGA device.
121   // Most systems can only have on VGA device on at a time.
122   //
123   if (((Pci.Hdr.Command & 0x03) == 0x03) && IS_PCI_VGA (&Pci)) {
124     Status = EFI_SUCCESS;
125   }
126 
127 Done:
128   gBS->CloseProtocol (
129          Controller,
130          &gEfiPciIoProtocolGuid,
131          This->DriverBindingHandle,
132          Controller
133          );
134 
135   return Status;
136 }
137 
138 
139 /**
140   Starts the VGA device with this driver.
141 
142   This function consumes PCI I/O Protocol, and installs VGA Mini Port Protocol
143   onto the VGA device handle.
144 
145   @param  This                   The driver binding instance.
146   @param  Controller             The controller to check.
147   @param  RemainingDevicePath    The remaining device patch.
148 
149   @retval EFI_SUCCESS            The controller is controlled by the driver.
150   @retval EFI_ALREADY_STARTED    The controller is already controlled by the driver.
151   @retval EFI_OUT_OF_RESOURCES   Failed to allocate resources.
152 
153 **/
154 EFI_STATUS
155 EFIAPI
PciVgaMiniPortDriverBindingStart(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Controller,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath)156 PciVgaMiniPortDriverBindingStart (
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_PCI_IO_PROTOCOL   *PciIo;
164   PCI_VGA_MINI_PORT_DEV *PciVgaMiniPortPrivate;
165 
166   PciVgaMiniPortPrivate = NULL;
167   PciIo                 = NULL;
168   //
169   // Open the IO Abstraction(s) needed
170   //
171   Status = gBS->OpenProtocol (
172                   Controller,
173                   &gEfiPciIoProtocolGuid,
174                   (VOID **) &PciIo,
175                   This->DriverBindingHandle,
176                   Controller,
177                   EFI_OPEN_PROTOCOL_BY_DRIVER
178                   );
179   if (EFI_ERROR (Status)) {
180     goto Done;
181   }
182   //
183   // Allocate the private device structure
184   //
185   PciVgaMiniPortPrivate = AllocateZeroPool (sizeof (PCI_VGA_MINI_PORT_DEV));
186   ASSERT (PciVgaMiniPortPrivate != NULL);
187 
188   //
189   // Initialize the private device structure
190   //
191   PciVgaMiniPortPrivate->Signature = PCI_VGA_MINI_PORT_DEV_SIGNATURE;
192   PciVgaMiniPortPrivate->Handle = Controller;
193   PciVgaMiniPortPrivate->PciIo = PciIo;
194 
195   PciVgaMiniPortPrivate->VgaMiniPort.SetMode = PciVgaMiniPortSetMode;
196   PciVgaMiniPortPrivate->VgaMiniPort.VgaMemoryOffset = 0xb8000;
197   PciVgaMiniPortPrivate->VgaMiniPort.CrtcAddressRegisterOffset = 0x3d4;
198   PciVgaMiniPortPrivate->VgaMiniPort.CrtcDataRegisterOffset = 0x3d5;
199   PciVgaMiniPortPrivate->VgaMiniPort.VgaMemoryBar = EFI_PCI_IO_PASS_THROUGH_BAR;
200   PciVgaMiniPortPrivate->VgaMiniPort.CrtcAddressRegisterBar = EFI_PCI_IO_PASS_THROUGH_BAR;
201   PciVgaMiniPortPrivate->VgaMiniPort.CrtcDataRegisterBar = EFI_PCI_IO_PASS_THROUGH_BAR;
202   PciVgaMiniPortPrivate->VgaMiniPort.MaxMode = 1;
203 
204   //
205   // Install VGA Mini Port Protocol
206   //
207   Status = gBS->InstallMultipleProtocolInterfaces (
208                   &Controller,
209                   &gEfiVgaMiniPortProtocolGuid,
210                   &PciVgaMiniPortPrivate->VgaMiniPort,
211                   NULL
212                   );
213 Done:
214   if (EFI_ERROR (Status)) {
215     gBS->CloseProtocol (
216            Controller,
217            &gEfiPciIoProtocolGuid,
218            This->DriverBindingHandle,
219            Controller
220            );
221     if (PciVgaMiniPortPrivate != NULL) {
222       FreePool (PciVgaMiniPortPrivate);
223     }
224   }
225 
226   return Status;
227 }
228 
229 
230 /**
231   Stop the VGA device with this driver.
232 
233   This function uninstalls VGA Mini Port Protocol from the VGA device handle,
234   and closes PCI I/O Protocol.
235 
236   @param  This                   The driver binding protocol.
237   @param  Controller             The controller to release.
238   @param  NumberOfChildren       The child number that opened controller
239                                  BY_CHILD.
240   @param  ChildHandleBuffer      The array of child handle.
241 
242   @retval EFI_SUCCESS            The controller or children are stopped.
243   @retval EFI_DEVICE_ERROR       Failed to stop the driver.
244 
245 **/
246 EFI_STATUS
247 EFIAPI
PciVgaMiniPortDriverBindingStop(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Controller,IN UINTN NumberOfChildren,IN EFI_HANDLE * ChildHandleBuffer)248 PciVgaMiniPortDriverBindingStop (
249   IN  EFI_DRIVER_BINDING_PROTOCOL     *This,
250   IN  EFI_HANDLE                      Controller,
251   IN  UINTN                           NumberOfChildren,
252   IN  EFI_HANDLE                      *ChildHandleBuffer
253   )
254 {
255   EFI_STATUS                  Status;
256   EFI_VGA_MINI_PORT_PROTOCOL  *VgaMiniPort;
257   PCI_VGA_MINI_PORT_DEV       *PciVgaMiniPortPrivate;
258 
259   Status = gBS->OpenProtocol (
260                   Controller,
261                   &gEfiVgaMiniPortProtocolGuid,
262                   (VOID **) &VgaMiniPort,
263                   This->DriverBindingHandle,
264                   Controller,
265                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
266                   );
267   if (EFI_ERROR (Status)) {
268     return Status;
269   }
270 
271   PciVgaMiniPortPrivate = PCI_VGA_MINI_PORT_DEV_FROM_THIS (VgaMiniPort);
272 
273   Status = gBS->UninstallProtocolInterface (
274                   Controller,
275                   &gEfiVgaMiniPortProtocolGuid,
276                   &PciVgaMiniPortPrivate->VgaMiniPort
277                   );
278   if (EFI_ERROR (Status)) {
279     return Status;
280   }
281 
282   gBS->CloseProtocol (
283          Controller,
284          &gEfiPciIoProtocolGuid,
285          This->DriverBindingHandle,
286          Controller
287          );
288 
289   FreePool (PciVgaMiniPortPrivate);
290 
291   return EFI_SUCCESS;
292 }
293 //
294 // VGA Mini Port Protocol Functions
295 //
296 
297 /**
298   Sets the text display mode of a VGA controller.
299 
300   This function implements EFI_VGA_MINI_PORT_PROTOCOL.SetMode().
301   If ModeNumber exceeds the valid range, then EFI_UNSUPPORTED is returned.
302   Otherwise, EFI_SUCCESS is directly returned without real operation.
303 
304   @param This                 Protocol instance pointer.
305   @param ModeNumber           Mode number.  0 - 80x25   1-80x50
306 
307   @retval EFI_SUCCESS         The mode was set
308   @retval EFI_UNSUPPORTED     ModeNumber is not supported.
309   @retval EFI_DEVICE_ERROR    The device is not functioning properly.
310 
311 **/
312 EFI_STATUS
313 EFIAPI
PciVgaMiniPortSetMode(IN EFI_VGA_MINI_PORT_PROTOCOL * This,IN UINTN ModeNumber)314 PciVgaMiniPortSetMode (
315   IN  EFI_VGA_MINI_PORT_PROTOCOL  *This,
316   IN  UINTN                       ModeNumber
317   )
318 {
319   if (ModeNumber > This->MaxMode) {
320     return EFI_UNSUPPORTED;
321   }
322 
323   return EFI_SUCCESS;
324 }
325 
326