]> git.proxmox.com Git - mirror_edk2.git/blob - EmulatorPkg/EmuGopDxe/GopDriver.c
IntelFsp2WrapperPkg: Support UPD allocation outside FspWrapper
[mirror_edk2.git] / EmulatorPkg / EmuGopDxe / GopDriver.c
1 /*++ @file
2
3 Copyright (c) 2006, Intel Corporation. All rights reserved.<BR>
4 Portions copyright (c) 2010,Apple Inc. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13
14 **/
15
16 #include "Gop.h"
17
18
19 EFI_STATUS
20 FreeNotifyList (
21 IN OUT LIST_ENTRY *ListHead
22 )
23 /*++
24
25 Routine Description:
26
27 Arguments:
28
29 ListHead - The list head
30
31 Returns:
32
33 EFI_SUCCESS - Free the notify list successfully
34 EFI_INVALID_PARAMETER - ListHead is invalid.
35
36 **/
37 {
38 EMU_GOP_SIMPLE_TEXTIN_EX_NOTIFY *NotifyNode;
39
40 if (ListHead == NULL) {
41 return EFI_INVALID_PARAMETER;
42 }
43 while (!IsListEmpty (ListHead)) {
44 NotifyNode = CR (
45 ListHead->ForwardLink,
46 EMU_GOP_SIMPLE_TEXTIN_EX_NOTIFY,
47 NotifyEntry,
48 EMU_GOP_SIMPLE_TEXTIN_EX_NOTIFY_SIGNATURE
49 );
50 RemoveEntryList (ListHead->ForwardLink);
51 gBS->FreePool (NotifyNode);
52 }
53
54 return EFI_SUCCESS;
55 }
56
57
58 /**
59 Tests to see if this driver supports a given controller. If a child device is provided,
60 it further tests to see if this driver supports creating a handle for the specified child device.
61
62 This function checks to see if the driver specified by This supports the device specified by
63 ControllerHandle. Drivers will typically use the device path attached to
64 ControllerHandle and/or the services from the bus I/O abstraction attached to
65 ControllerHandle to determine if the driver supports ControllerHandle. This function
66 may be called many times during platform initialization. In order to reduce boot times, the tests
67 performed by this function must be very small, and take as little time as possible to execute. This
68 function must not change the state of any hardware devices, and this function must be aware that the
69 device specified by ControllerHandle may already be managed by the same driver or a
70 different driver. This function must match its calls to AllocatePages() with FreePages(),
71 AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
72 Because ControllerHandle may have been previously started by the same driver, if a protocol is
73 already in the opened state, then it must not be closed with CloseProtocol(). This is required
74 to guarantee the state of ControllerHandle is not modified by this function.
75
76 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
77 @param[in] ControllerHandle The handle of the controller to test. This handle
78 must support a protocol interface that supplies
79 an I/O abstraction to the driver.
80 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
81 parameter is ignored by device drivers, and is optional for bus
82 drivers. For bus drivers, if this parameter is not NULL, then
83 the bus driver must determine if the bus controller specified
84 by ControllerHandle and the child controller specified
85 by RemainingDevicePath are both supported by this
86 bus driver.
87
88 @retval EFI_SUCCESS The device specified by ControllerHandle and
89 RemainingDevicePath is supported by the driver specified by This.
90 @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
91 RemainingDevicePath is already being managed by the driver
92 specified by This.
93 @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
94 RemainingDevicePath is already being managed by a different
95 driver or an application that requires exclusive access.
96 Currently not implemented.
97 @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
98 RemainingDevicePath is not supported by the driver specified by This.
99 **/
100 EFI_STATUS
101 EFIAPI
102 EmuGopDriverBindingSupported (
103 IN EFI_DRIVER_BINDING_PROTOCOL *This,
104 IN EFI_HANDLE Handle,
105 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
106 )
107 {
108 EFI_STATUS Status;
109 EMU_IO_THUNK_PROTOCOL *EmuIoThunk;
110
111 //
112 // Open the IO Abstraction(s) needed to perform the supported test
113 //
114 Status = gBS->OpenProtocol (
115 Handle,
116 &gEmuIoThunkProtocolGuid,
117 (VOID **)&EmuIoThunk,
118 This->DriverBindingHandle,
119 Handle,
120 EFI_OPEN_PROTOCOL_BY_DRIVER
121 );
122 if (EFI_ERROR (Status)) {
123 return Status;
124 }
125
126 Status = EmuGopSupported (EmuIoThunk);
127
128 //
129 // Close the I/O Abstraction(s) used to perform the supported test
130 //
131 gBS->CloseProtocol (
132 Handle,
133 &gEmuIoThunkProtocolGuid,
134 This->DriverBindingHandle,
135 Handle
136 );
137
138 return Status;
139 }
140
141
142 /**
143 Starts a device controller or a bus controller.
144
145 The Start() function is designed to be invoked from the EFI boot service ConnectController().
146 As a result, much of the error checking on the parameters to Start() has been moved into this
147 common boot service. It is legal to call Start() from other locations,
148 but the following calling restrictions must be followed, or the system behavior will not be deterministic.
149 1. ControllerHandle must be a valid EFI_HANDLE.
150 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
151 EFI_DEVICE_PATH_PROTOCOL.
152 3. Prior to calling Start(), the Supported() function for the driver specified by This must
153 have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
154
155 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
156 @param[in] ControllerHandle The handle of the controller to start. This handle
157 must support a protocol interface that supplies
158 an I/O abstraction to the driver.
159 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
160 parameter is ignored by device drivers, and is optional for bus
161 drivers. For a bus driver, if this parameter is NULL, then handles
162 for all the children of Controller are created by this driver.
163 If this parameter is not NULL and the first Device Path Node is
164 not the End of Device Path Node, then only the handle for the
165 child device specified by the first Device Path Node of
166 RemainingDevicePath is created by this driver.
167 If the first Device Path Node of RemainingDevicePath is
168 the End of Device Path Node, no child handle is created by this
169 driver.
170
171 @retval EFI_SUCCESS The device was started.
172 @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented.
173 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
174 @retval Others The driver failded to start the device.
175
176 **/
177 EFI_STATUS
178 EFIAPI
179 EmuGopDriverBindingStart (
180 IN EFI_DRIVER_BINDING_PROTOCOL *This,
181 IN EFI_HANDLE Handle,
182 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
183 )
184 {
185 EMU_IO_THUNK_PROTOCOL *EmuIoThunk;
186 EFI_STATUS Status;
187 GOP_PRIVATE_DATA *Private;
188
189 //
190 // Grab the protocols we need
191 //
192 Status = gBS->OpenProtocol (
193 Handle,
194 &gEmuIoThunkProtocolGuid,
195 (VOID **)&EmuIoThunk,
196 This->DriverBindingHandle,
197 Handle,
198 EFI_OPEN_PROTOCOL_BY_DRIVER
199 );
200 if (EFI_ERROR (Status)) {
201 return EFI_UNSUPPORTED;
202 }
203
204 //
205 // Allocate Private context data for SGO inteface.
206 //
207 Private = NULL;
208 Status = gBS->AllocatePool (
209 EfiBootServicesData,
210 sizeof (GOP_PRIVATE_DATA),
211 (VOID **)&Private
212 );
213 if (EFI_ERROR (Status)) {
214 goto Done;
215 }
216 //
217 // Set up context record
218 //
219 Private->Signature = GOP_PRIVATE_DATA_SIGNATURE;
220 Private->Handle = Handle;
221 Private->EmuIoThunk = EmuIoThunk;
222 Private->WindowName = EmuIoThunk->ConfigString;
223 Private->ControllerNameTable = NULL;
224
225 AddUnicodeString (
226 "eng",
227 gEmuGopComponentName.SupportedLanguages,
228 &Private->ControllerNameTable,
229 EmuIoThunk->ConfigString
230 );
231 AddUnicodeString2 (
232 "en",
233 gEmuGopComponentName2.SupportedLanguages,
234 &Private->ControllerNameTable,
235 EmuIoThunk->ConfigString,
236 FALSE
237 );
238
239 Status = EmuGopConstructor (Private);
240 if (EFI_ERROR (Status)) {
241 goto Done;
242 }
243 //
244 // Publish the Gop interface to the world
245 //
246 Status = gBS->InstallMultipleProtocolInterfaces (
247 &Private->Handle,
248 &gEfiGraphicsOutputProtocolGuid, &Private->GraphicsOutput,
249 &gEfiSimpleTextInProtocolGuid, &Private->SimpleTextIn,
250 &gEfiSimplePointerProtocolGuid, &Private->SimplePointer,
251 &gEfiSimpleTextInputExProtocolGuid, &Private->SimpleTextInEx,
252 NULL
253 );
254
255 Done:
256 if (EFI_ERROR (Status)) {
257
258 gBS->CloseProtocol (
259 Handle,
260 &gEmuIoThunkProtocolGuid,
261 This->DriverBindingHandle,
262 Handle
263 );
264
265 if (Private != NULL) {
266 //
267 // On Error Free back private data
268 //
269 if (Private->ControllerNameTable != NULL) {
270 FreeUnicodeStringTable (Private->ControllerNameTable);
271 }
272 if (Private->SimpleTextIn.WaitForKey != NULL) {
273 gBS->CloseEvent (Private->SimpleTextIn.WaitForKey);
274 }
275 if (Private->SimpleTextInEx.WaitForKeyEx != NULL) {
276 gBS->CloseEvent (Private->SimpleTextInEx.WaitForKeyEx);
277 }
278 FreeNotifyList (&Private->NotifyList);
279
280 gBS->FreePool (Private);
281 }
282 }
283
284 return Status;
285 }
286
287
288
289 /**
290 Stops a device controller or a bus controller.
291
292 The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
293 As a result, much of the error checking on the parameters to Stop() has been moved
294 into this common boot service. It is legal to call Stop() from other locations,
295 but the following calling restrictions must be followed, or the system behavior will not be deterministic.
296 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
297 same driver's Start() function.
298 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
299 EFI_HANDLE. In addition, all of these handles must have been created in this driver's
300 Start() function, and the Start() function must have called OpenProtocol() on
301 ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
302
303 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
304 @param[in] ControllerHandle A handle to the device being stopped. The handle must
305 support a bus specific I/O protocol for the driver
306 to use to stop the device.
307 @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
308 @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
309 if NumberOfChildren is 0.
310
311 @retval EFI_SUCCESS The device was stopped.
312 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
313
314 **/
315 EFI_STATUS
316 EFIAPI
317 EmuGopDriverBindingStop (
318 IN EFI_DRIVER_BINDING_PROTOCOL *This,
319 IN EFI_HANDLE Handle,
320 IN UINTN NumberOfChildren,
321 IN EFI_HANDLE *ChildHandleBuffer
322 )
323 {
324 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
325 EFI_STATUS Status;
326 GOP_PRIVATE_DATA *Private;
327
328 Status = gBS->OpenProtocol (
329 Handle,
330 &gEfiGraphicsOutputProtocolGuid,
331 (VOID **)&GraphicsOutput,
332 This->DriverBindingHandle,
333 Handle,
334 EFI_OPEN_PROTOCOL_GET_PROTOCOL
335 );
336 if (EFI_ERROR (Status)) {
337 //
338 // If the GOP interface does not exist the driver is not started
339 //
340 return EFI_NOT_STARTED;
341 }
342
343 //
344 // Get our private context information
345 //
346 Private = GOP_PRIVATE_DATA_FROM_THIS (GraphicsOutput);
347
348 //
349 // Remove the SGO interface from the system
350 //
351 Status = gBS->UninstallMultipleProtocolInterfaces (
352 Private->Handle,
353 &gEfiGraphicsOutputProtocolGuid, &Private->GraphicsOutput,
354 &gEfiSimpleTextInProtocolGuid, &Private->SimpleTextIn,
355 &gEfiSimplePointerProtocolGuid, &Private->SimplePointer,
356 &gEfiSimpleTextInputExProtocolGuid, &Private->SimpleTextInEx,
357 NULL
358 );
359 if (!EFI_ERROR (Status)) {
360 //
361 // Shutdown the hardware
362 //
363 Status = EmuGopDestructor (Private);
364 if (EFI_ERROR (Status)) {
365 return EFI_DEVICE_ERROR;
366 }
367
368 gBS->CloseProtocol (
369 Handle,
370 &gEmuIoThunkProtocolGuid,
371 This->DriverBindingHandle,
372 Handle
373 );
374
375 //
376 // Free our instance data
377 //
378 FreeUnicodeStringTable (Private->ControllerNameTable);
379
380 Status = gBS->CloseEvent (Private->SimpleTextIn.WaitForKey);
381 ASSERT_EFI_ERROR (Status);
382
383 Status = gBS->CloseEvent (Private->SimpleTextInEx.WaitForKeyEx);
384 ASSERT_EFI_ERROR (Status);
385
386 FreeNotifyList (&Private->NotifyList);
387
388 gBS->FreePool (Private);
389
390 }
391
392 return Status;
393 }
394
395
396 ///
397 /// This protocol provides the services required to determine if a driver supports a given controller.
398 /// If a controller is supported, then it also provides routines to start and stop the controller.
399 ///
400 EFI_DRIVER_BINDING_PROTOCOL gEmuGopDriverBinding = {
401 EmuGopDriverBindingSupported,
402 EmuGopDriverBindingStart,
403 EmuGopDriverBindingStop,
404 0xa,
405 NULL,
406 NULL
407 };
408
409
410
411 /**
412 The user Entry Point for module EmuGop. The user code starts with this function.
413
414 @param[in] ImageHandle The firmware allocated handle for the EFI image.
415 @param[in] SystemTable A pointer to the EFI System Table.
416
417 @retval EFI_SUCCESS The entry point is executed successfully.
418 @retval other Some error occurs when executing this entry point.
419
420 **/
421 EFI_STATUS
422 EFIAPI
423 InitializeEmuGop (
424 IN EFI_HANDLE ImageHandle,
425 IN EFI_SYSTEM_TABLE *SystemTable
426 )
427 {
428 EFI_STATUS Status;
429
430 Status = EfiLibInstallDriverBindingComponentName2 (
431 ImageHandle,
432 SystemTable,
433 &gEmuGopDriverBinding,
434 ImageHandle,
435 &gEmuGopComponentName,
436 &gEmuGopComponentName2
437 );
438 ASSERT_EFI_ERROR (Status);
439
440
441 return Status;
442 }
443