]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Bus/Isa/IsaBusDxe/IsaBusDxe.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / MdeModulePkg / Bus / Isa / IsaBusDxe / IsaBusDxe.c
1 /** @file
2 This file consumes the ISA Host Controller protocol produced by the ISA Host
3 Controller and installs the ISA Host Controller Service Binding protocol
4 on the ISA Host Controller's handle.
5
6 Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
7 SPDX-License-Identifier: BSD-2-Clause-Patent
8
9
10 **/
11
12 #include "IsaBusDxe.h"
13 #include "ComponentName.h"
14
15 /**
16 Tests to see if this driver supports a given controller. If a child device is provided,
17 it further tests to see if this driver supports creating a handle for the specified child device.
18
19 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
20 @param[in] ControllerHandle The handle of the controller to test. This handle
21 must support a protocol interface that supplies
22 an I/O abstraction to the driver.
23 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
24 parameter is ignored by device drivers, and is optional for bus
25 drivers. For bus drivers, if this parameter is not NULL, then
26 the bus driver must determine if the bus controller specified
27 by ControllerHandle and the child controller specified
28 by RemainingDevicePath are both supported by this
29 bus driver.
30
31 @retval EFI_SUCCESS The device specified by ControllerHandle and
32 RemainingDevicePath is supported by the driver specified by This.
33 @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
34 RemainingDevicePath is already being managed by the driver
35 specified by This.
36 @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
37 RemainingDevicePath is already being managed by a different
38 driver or an application that requires exclusive access.
39 Currently not implemented.
40 @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
41 RemainingDevicePath is not supported by the driver specified by This.
42 **/
43 EFI_STATUS
44 EFIAPI
45 IsaBusDriverBindingSupported (
46 IN EFI_DRIVER_BINDING_PROTOCOL *This,
47 IN EFI_HANDLE Controller,
48 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
49 )
50 {
51 EFI_STATUS Status;
52 VOID *Instance;
53
54 Status = gBS->OpenProtocol (
55 Controller,
56 &gEfiIsaHcProtocolGuid,
57 &Instance,
58 This->DriverBindingHandle,
59 Controller,
60 EFI_OPEN_PROTOCOL_BY_DRIVER
61 );
62 if (!EFI_ERROR (Status)) {
63 gBS->CloseProtocol (
64 Controller,
65 &gEfiIsaHcProtocolGuid,
66 This->DriverBindingHandle,
67 Controller
68 );
69 }
70
71 if (EFI_ERROR (Status)) {
72 return Status;
73 }
74
75 Status = gBS->OpenProtocol (
76 Controller,
77 &gEfiDevicePathProtocolGuid,
78 &Instance,
79 This->DriverBindingHandle,
80 Controller,
81 EFI_OPEN_PROTOCOL_BY_DRIVER
82 );
83 if (!EFI_ERROR (Status)) {
84 gBS->CloseProtocol (
85 Controller,
86 &gEfiDevicePathProtocolGuid,
87 This->DriverBindingHandle,
88 Controller
89 );
90 }
91
92 return Status;
93 }
94
95 ISA_BUS_CHILD_PRIVATE_DATA mIsaBusChildPrivateTemplate = {
96 ISA_BUS_CHILD_PRIVATE_DATA_SIGNATURE,
97 FALSE
98 };
99
100 /**
101 Creates a child handle and installs a protocol.
102
103 The CreateChild() function installs a protocol on ChildHandle.
104 If ChildHandle is a pointer to NULL, then a new handle is created and returned in ChildHandle.
105 If ChildHandle is not a pointer to NULL, then the protocol installs on the existing ChildHandle.
106
107 @param This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
108 @param ChildHandle Pointer to the handle of the child to create. If it is NULL,
109 then a new handle is created. If it is a pointer to an existing UEFI handle,
110 then the protocol is added to the existing UEFI handle.
111
112 @retval EFI_SUCCESS The protocol was added to ChildHandle.
113 @retval EFI_INVALID_PARAMETER ChildHandle is NULL.
114 @retval EFI_OUT_OF_RESOURCES There are not enough resources available to create
115 the child
116 @retval other The child handle was not created
117
118 **/
119 EFI_STATUS
120 EFIAPI
121 IsaBusCreateChild (
122 IN EFI_SERVICE_BINDING_PROTOCOL *This,
123 IN OUT EFI_HANDLE *ChildHandle
124 )
125 {
126 EFI_STATUS Status;
127 ISA_BUS_PRIVATE_DATA *Private;
128 EFI_ISA_HC_PROTOCOL *IsaHc;
129 ISA_BUS_CHILD_PRIVATE_DATA *Child;
130
131 Private = ISA_BUS_PRIVATE_DATA_FROM_THIS (This);
132
133 Child = AllocateCopyPool (sizeof (mIsaBusChildPrivateTemplate), &mIsaBusChildPrivateTemplate);
134 if (Child == NULL) {
135 return EFI_OUT_OF_RESOURCES;
136 }
137
138 Status = gBS->InstallMultipleProtocolInterfaces (
139 ChildHandle,
140 &gEfiIsaHcProtocolGuid, Private->IsaHc,
141 &gEfiCallerIdGuid, Child,
142 NULL
143 );
144 if (EFI_ERROR (Status)) {
145 FreePool (Child);
146 return Status;
147 }
148
149 return gBS->OpenProtocol (
150 Private->IsaHcHandle,
151 &gEfiIsaHcProtocolGuid,
152 (VOID **) &IsaHc,
153 gIsaBusDriverBinding.DriverBindingHandle,
154 *ChildHandle,
155 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
156 );
157 }
158
159 /**
160 Destroys a child handle with a protocol installed on it.
161
162 The DestroyChild() function does the opposite of CreateChild(). It removes a protocol
163 that was installed by CreateChild() from ChildHandle. If the removed protocol is the
164 last protocol on ChildHandle, then ChildHandle is destroyed.
165
166 @param This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
167 @param ChildHandle Handle of the child to destroy
168
169 @retval EFI_SUCCESS The protocol was removed from ChildHandle.
170 @retval EFI_UNSUPPORTED ChildHandle does not support the protocol that is being removed.
171 @retval EFI_INVALID_PARAMETER Child handle is NULL.
172 @retval EFI_ACCESS_DENIED The protocol could not be removed from the ChildHandle
173 because its services are being used.
174 @retval other The child handle was not destroyed
175
176 **/
177 EFI_STATUS
178 EFIAPI
179 IsaBusDestroyChild (
180 IN EFI_SERVICE_BINDING_PROTOCOL *This,
181 IN EFI_HANDLE ChildHandle
182 )
183 {
184 EFI_STATUS Status;
185 ISA_BUS_PRIVATE_DATA *Private;
186 EFI_ISA_HC_PROTOCOL *IsaHc;
187 ISA_BUS_CHILD_PRIVATE_DATA *Child;
188
189 Private = ISA_BUS_PRIVATE_DATA_FROM_THIS (This);
190
191 Status = gBS->OpenProtocol (
192 ChildHandle,
193 &gEfiCallerIdGuid,
194 (VOID **) &Child,
195 gIsaBusDriverBinding.DriverBindingHandle,
196 ChildHandle,
197 EFI_OPEN_PROTOCOL_GET_PROTOCOL
198 );
199 if (EFI_ERROR (Status)) {
200 return Status;
201 }
202
203 ASSERT (Child->Signature == ISA_BUS_CHILD_PRIVATE_DATA_SIGNATURE);
204
205 if (Child->InDestroying) {
206 return EFI_SUCCESS;
207 }
208
209 Child->InDestroying = TRUE;
210 Status = gBS->CloseProtocol (
211 Private->IsaHcHandle,
212 &gEfiIsaHcProtocolGuid,
213 gIsaBusDriverBinding.DriverBindingHandle,
214 ChildHandle
215 );
216 ASSERT_EFI_ERROR (Status);
217 if (!EFI_ERROR (Status)) {
218 Status = gBS->UninstallMultipleProtocolInterfaces (
219 ChildHandle,
220 &gEfiIsaHcProtocolGuid, Private->IsaHc,
221 &gEfiCallerIdGuid, Child,
222 NULL
223 );
224 if (EFI_ERROR (Status)) {
225 gBS->OpenProtocol (
226 Private->IsaHcHandle,
227 &gEfiIsaHcProtocolGuid,
228 (VOID **) &IsaHc,
229 gIsaBusDriverBinding.DriverBindingHandle,
230 ChildHandle,
231 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
232 );
233 }
234 }
235
236 if (EFI_ERROR (Status)) {
237 Child->InDestroying = FALSE;
238 } else {
239 FreePool (Child);
240 }
241
242 return Status;
243 }
244
245 ISA_BUS_PRIVATE_DATA mIsaBusPrivateTemplate = {
246 ISA_BUS_PRIVATE_DATA_SIGNATURE,
247 {
248 IsaBusCreateChild,
249 IsaBusDestroyChild
250 }
251 };
252
253 /**
254 Starts a device controller or a bus controller.
255
256 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
257 @param[in] ControllerHandle The handle of the controller to start. This handle
258 must support a protocol interface that supplies
259 an I/O abstraction to the driver.
260 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
261 parameter is ignored by device drivers, and is optional for bus
262 drivers. For a bus driver, if this parameter is NULL, then handles
263 for all the children of Controller are created by this driver.
264 If this parameter is not NULL and the first Device Path Node is
265 not the End of Device Path Node, then only the handle for the
266 child device specified by the first Device Path Node of
267 RemainingDevicePath is created by this driver.
268 If the first Device Path Node of RemainingDevicePath is
269 the End of Device Path Node, no child handle is created by this
270 driver.
271
272 @retval EFI_SUCCESS The device was started.
273 @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented.
274 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
275 @retval Others The driver failed to start the device.
276
277 **/
278 EFI_STATUS
279 EFIAPI
280 IsaBusDriverBindingStart (
281 IN EFI_DRIVER_BINDING_PROTOCOL *This,
282 IN EFI_HANDLE Controller,
283 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
284 )
285 {
286 EFI_STATUS Status;
287 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
288 ISA_BUS_PRIVATE_DATA *Private;
289
290 Status = gBS->OpenProtocol (
291 Controller,
292 &gEfiIsaHcProtocolGuid,
293 (VOID **) &mIsaBusPrivateTemplate.IsaHc,
294 This->DriverBindingHandle,
295 Controller,
296 EFI_OPEN_PROTOCOL_BY_DRIVER
297 );
298 if (EFI_ERROR (Status)) {
299 return Status;
300 }
301
302 Status = gBS->OpenProtocol (
303 Controller,
304 &gEfiDevicePathProtocolGuid,
305 (VOID **) &DevicePath,
306 This->DriverBindingHandle,
307 Controller,
308 EFI_OPEN_PROTOCOL_BY_DRIVER
309 );
310 if (EFI_ERROR (Status)) {
311 gBS->CloseProtocol (
312 Controller,
313 &gEfiIsaHcProtocolGuid,
314 This->DriverBindingHandle,
315 Controller
316 );
317 return Status;
318 }
319
320 Private = AllocateCopyPool (sizeof (mIsaBusPrivateTemplate), &mIsaBusPrivateTemplate);
321 ASSERT (Private != NULL);
322
323 Private->IsaHcHandle = Controller;
324
325 Status = gBS->InstallMultipleProtocolInterfaces (
326 &Controller,
327 &gEfiIsaHcServiceBindingProtocolGuid, &Private->ServiceBinding,
328 NULL
329 );
330 ASSERT_EFI_ERROR (Status);
331
332 return Status;
333 }
334
335 /**
336 Stops a device controller or a bus controller.
337
338 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
339 @param[in] ControllerHandle A handle to the device being stopped. The handle must
340 support a bus specific I/O protocol for the driver
341 to use to stop the device.
342 @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
343 @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
344 if NumberOfChildren is 0.
345
346 @retval EFI_SUCCESS The device was stopped.
347 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
348
349 **/
350 EFI_STATUS
351 EFIAPI
352 IsaBusDriverBindingStop (
353 IN EFI_DRIVER_BINDING_PROTOCOL *This,
354 IN EFI_HANDLE Controller,
355 IN UINTN NumberOfChildren,
356 IN EFI_HANDLE *ChildHandleBuffer
357 )
358 {
359 EFI_STATUS Status;
360 EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;
361 ISA_BUS_PRIVATE_DATA *Private;
362 UINTN Index;
363 BOOLEAN AllChildrenStopped;
364
365 Status = gBS->OpenProtocol (
366 Controller,
367 &gEfiIsaHcServiceBindingProtocolGuid,
368 (VOID **) &ServiceBinding,
369 This->DriverBindingHandle,
370 Controller,
371 EFI_OPEN_PROTOCOL_GET_PROTOCOL
372 );
373 if (EFI_ERROR (Status)) {
374 return Status;
375 }
376
377 Private = ISA_BUS_PRIVATE_DATA_FROM_THIS (ServiceBinding);
378
379 if (NumberOfChildren == 0) {
380 Status = gBS->UninstallMultipleProtocolInterfaces (
381 Controller,
382 &gEfiIsaHcServiceBindingProtocolGuid, &Private->ServiceBinding,
383 NULL
384 );
385 if (!EFI_ERROR (Status)) {
386 gBS->CloseProtocol (
387 Controller,
388 &gEfiDevicePathProtocolGuid,
389 This->DriverBindingHandle,
390 Controller
391 );
392 gBS->CloseProtocol (
393 Controller,
394 &gEfiIsaHcProtocolGuid,
395 This->DriverBindingHandle,
396 Controller
397 );
398 FreePool (Private);
399 }
400
401 return Status;
402 }
403
404 AllChildrenStopped = TRUE;
405 for (Index = 0; Index < NumberOfChildren; Index++) {
406 Status = ServiceBinding->DestroyChild (ServiceBinding, ChildHandleBuffer[Index]);
407 if (EFI_ERROR (Status)) {
408 AllChildrenStopped = FALSE;
409 }
410 }
411
412 return AllChildrenStopped ? EFI_SUCCESS : EFI_DEVICE_ERROR;
413 }
414
415 //
416 // ISA Bus Driver Binding Protocol Instance
417 //
418 EFI_DRIVER_BINDING_PROTOCOL gIsaBusDriverBinding = {
419 IsaBusDriverBindingSupported,
420 IsaBusDriverBindingStart,
421 IsaBusDriverBindingStop,
422 0x10,
423 NULL,
424 NULL
425 };
426
427 /**
428 Entry point of the IsaBusDxe driver.
429
430 @param[in] ImageHandle The firmware allocated handle for the EFI image.
431 @param[in] SystemTable A pointer to the EFI System Table.
432
433 @retval EFI_SUCCESS The entry point is executed successfully.
434 @retval other Some error occurs when executing this entry point.
435 **/
436 EFI_STATUS
437 EFIAPI
438 InitializeIsaBus (
439 IN EFI_HANDLE ImageHandle,
440 IN EFI_SYSTEM_TABLE *SystemTable
441 )
442 {
443 EFI_STATUS Status;
444
445 Status = EfiLibInstallDriverBindingComponentName2 (
446 ImageHandle,
447 SystemTable,
448 &gIsaBusDriverBinding,
449 ImageHandle,
450 &gIsaBusComponentName,
451 &gIsaBusComponentName2
452 );
453 ASSERT_EFI_ERROR (Status);
454 return Status;
455 }