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