]> 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,
141 Private->IsaHc,
142 &gEfiCallerIdGuid,
143 Child,
144 NULL
145 );
146 if (EFI_ERROR (Status)) {
147 FreePool (Child);
148 return Status;
149 }
150
151 return gBS->OpenProtocol (
152 Private->IsaHcHandle,
153 &gEfiIsaHcProtocolGuid,
154 (VOID **)&IsaHc,
155 gIsaBusDriverBinding.DriverBindingHandle,
156 *ChildHandle,
157 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
158 );
159 }
160
161 /**
162 Destroys a child handle with a protocol installed on it.
163
164 The DestroyChild() function does the opposite of CreateChild(). It removes a protocol
165 that was installed by CreateChild() from ChildHandle. If the removed protocol is the
166 last protocol on ChildHandle, then ChildHandle is destroyed.
167
168 @param This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
169 @param ChildHandle Handle of the child to destroy
170
171 @retval EFI_SUCCESS The protocol was removed from ChildHandle.
172 @retval EFI_UNSUPPORTED ChildHandle does not support the protocol that is being removed.
173 @retval EFI_INVALID_PARAMETER Child handle is NULL.
174 @retval EFI_ACCESS_DENIED The protocol could not be removed from the ChildHandle
175 because its services are being used.
176 @retval other The child handle was not destroyed
177
178 **/
179 EFI_STATUS
180 EFIAPI
181 IsaBusDestroyChild (
182 IN EFI_SERVICE_BINDING_PROTOCOL *This,
183 IN EFI_HANDLE ChildHandle
184 )
185 {
186 EFI_STATUS Status;
187 ISA_BUS_PRIVATE_DATA *Private;
188 EFI_ISA_HC_PROTOCOL *IsaHc;
189 ISA_BUS_CHILD_PRIVATE_DATA *Child;
190
191 Private = ISA_BUS_PRIVATE_DATA_FROM_THIS (This);
192
193 Status = gBS->OpenProtocol (
194 ChildHandle,
195 &gEfiCallerIdGuid,
196 (VOID **)&Child,
197 gIsaBusDriverBinding.DriverBindingHandle,
198 ChildHandle,
199 EFI_OPEN_PROTOCOL_GET_PROTOCOL
200 );
201 if (EFI_ERROR (Status)) {
202 return Status;
203 }
204
205 ASSERT (Child->Signature == ISA_BUS_CHILD_PRIVATE_DATA_SIGNATURE);
206
207 if (Child->InDestroying) {
208 return EFI_SUCCESS;
209 }
210
211 Child->InDestroying = TRUE;
212 Status = gBS->CloseProtocol (
213 Private->IsaHcHandle,
214 &gEfiIsaHcProtocolGuid,
215 gIsaBusDriverBinding.DriverBindingHandle,
216 ChildHandle
217 );
218 ASSERT_EFI_ERROR (Status);
219 if (!EFI_ERROR (Status)) {
220 Status = gBS->UninstallMultipleProtocolInterfaces (
221 ChildHandle,
222 &gEfiIsaHcProtocolGuid,
223 Private->IsaHc,
224 &gEfiCallerIdGuid,
225 Child,
226 NULL
227 );
228 if (EFI_ERROR (Status)) {
229 gBS->OpenProtocol (
230 Private->IsaHcHandle,
231 &gEfiIsaHcProtocolGuid,
232 (VOID **)&IsaHc,
233 gIsaBusDriverBinding.DriverBindingHandle,
234 ChildHandle,
235 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
236 );
237 }
238 }
239
240 if (EFI_ERROR (Status)) {
241 Child->InDestroying = FALSE;
242 } else {
243 FreePool (Child);
244 }
245
246 return Status;
247 }
248
249 ISA_BUS_PRIVATE_DATA mIsaBusPrivateTemplate = {
250 ISA_BUS_PRIVATE_DATA_SIGNATURE,
251 {
252 IsaBusCreateChild,
253 IsaBusDestroyChild
254 }
255 };
256
257 /**
258 Starts a device controller or a bus controller.
259
260 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
261 @param[in] ControllerHandle The handle of the controller to start. This handle
262 must support a protocol interface that supplies
263 an I/O abstraction to the driver.
264 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
265 parameter is ignored by device drivers, and is optional for bus
266 drivers. For a bus driver, if this parameter is NULL, then handles
267 for all the children of Controller are created by this driver.
268 If this parameter is not NULL and the first Device Path Node is
269 not the End of Device Path Node, then only the handle for the
270 child device specified by the first Device Path Node of
271 RemainingDevicePath is created by this driver.
272 If the first Device Path Node of RemainingDevicePath is
273 the End of Device Path Node, no child handle is created by this
274 driver.
275
276 @retval EFI_SUCCESS The device was started.
277 @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented.
278 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
279 @retval Others The driver failed to start the device.
280
281 **/
282 EFI_STATUS
283 EFIAPI
284 IsaBusDriverBindingStart (
285 IN EFI_DRIVER_BINDING_PROTOCOL *This,
286 IN EFI_HANDLE Controller,
287 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
288 )
289 {
290 EFI_STATUS Status;
291 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
292 ISA_BUS_PRIVATE_DATA *Private;
293
294 Status = gBS->OpenProtocol (
295 Controller,
296 &gEfiIsaHcProtocolGuid,
297 (VOID **)&mIsaBusPrivateTemplate.IsaHc,
298 This->DriverBindingHandle,
299 Controller,
300 EFI_OPEN_PROTOCOL_BY_DRIVER
301 );
302 if (EFI_ERROR (Status)) {
303 return Status;
304 }
305
306 Status = gBS->OpenProtocol (
307 Controller,
308 &gEfiDevicePathProtocolGuid,
309 (VOID **)&DevicePath,
310 This->DriverBindingHandle,
311 Controller,
312 EFI_OPEN_PROTOCOL_BY_DRIVER
313 );
314 if (EFI_ERROR (Status)) {
315 gBS->CloseProtocol (
316 Controller,
317 &gEfiIsaHcProtocolGuid,
318 This->DriverBindingHandle,
319 Controller
320 );
321 return Status;
322 }
323
324 Private = AllocateCopyPool (sizeof (mIsaBusPrivateTemplate), &mIsaBusPrivateTemplate);
325 ASSERT (Private != NULL);
326
327 Private->IsaHcHandle = Controller;
328
329 Status = gBS->InstallMultipleProtocolInterfaces (
330 &Controller,
331 &gEfiIsaHcServiceBindingProtocolGuid,
332 &Private->ServiceBinding,
333 NULL
334 );
335 ASSERT_EFI_ERROR (Status);
336
337 return Status;
338 }
339
340 /**
341 Stops a device controller or a bus controller.
342
343 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
344 @param[in] ControllerHandle A handle to the device being stopped. The handle must
345 support a bus specific I/O protocol for the driver
346 to use to stop the device.
347 @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
348 @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
349 if NumberOfChildren is 0.
350
351 @retval EFI_SUCCESS The device was stopped.
352 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
353
354 **/
355 EFI_STATUS
356 EFIAPI
357 IsaBusDriverBindingStop (
358 IN EFI_DRIVER_BINDING_PROTOCOL *This,
359 IN EFI_HANDLE Controller,
360 IN UINTN NumberOfChildren,
361 IN EFI_HANDLE *ChildHandleBuffer
362 )
363 {
364 EFI_STATUS Status;
365 EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;
366 ISA_BUS_PRIVATE_DATA *Private;
367 UINTN Index;
368 BOOLEAN AllChildrenStopped;
369
370 Status = gBS->OpenProtocol (
371 Controller,
372 &gEfiIsaHcServiceBindingProtocolGuid,
373 (VOID **)&ServiceBinding,
374 This->DriverBindingHandle,
375 Controller,
376 EFI_OPEN_PROTOCOL_GET_PROTOCOL
377 );
378 if (EFI_ERROR (Status)) {
379 return Status;
380 }
381
382 Private = ISA_BUS_PRIVATE_DATA_FROM_THIS (ServiceBinding);
383
384 if (NumberOfChildren == 0) {
385 Status = gBS->UninstallMultipleProtocolInterfaces (
386 Controller,
387 &gEfiIsaHcServiceBindingProtocolGuid,
388 &Private->ServiceBinding,
389 NULL
390 );
391 if (!EFI_ERROR (Status)) {
392 gBS->CloseProtocol (
393 Controller,
394 &gEfiDevicePathProtocolGuid,
395 This->DriverBindingHandle,
396 Controller
397 );
398 gBS->CloseProtocol (
399 Controller,
400 &gEfiIsaHcProtocolGuid,
401 This->DriverBindingHandle,
402 Controller
403 );
404 FreePool (Private);
405 }
406
407 return Status;
408 }
409
410 AllChildrenStopped = TRUE;
411 for (Index = 0; Index < NumberOfChildren; Index++) {
412 Status = ServiceBinding->DestroyChild (ServiceBinding, ChildHandleBuffer[Index]);
413 if (EFI_ERROR (Status)) {
414 AllChildrenStopped = FALSE;
415 }
416 }
417
418 return AllChildrenStopped ? EFI_SUCCESS : EFI_DEVICE_ERROR;
419 }
420
421 //
422 // ISA Bus Driver Binding Protocol Instance
423 //
424 EFI_DRIVER_BINDING_PROTOCOL gIsaBusDriverBinding = {
425 IsaBusDriverBindingSupported,
426 IsaBusDriverBindingStart,
427 IsaBusDriverBindingStop,
428 0x10,
429 NULL,
430 NULL
431 };
432
433 /**
434 Entry point of the IsaBusDxe driver.
435
436 @param[in] ImageHandle The firmware allocated handle for the EFI image.
437 @param[in] SystemTable A pointer to the EFI System Table.
438
439 @retval EFI_SUCCESS The entry point is executed successfully.
440 @retval other Some error occurs when executing this entry point.
441 **/
442 EFI_STATUS
443 EFIAPI
444 InitializeIsaBus (
445 IN EFI_HANDLE ImageHandle,
446 IN EFI_SYSTEM_TABLE *SystemTable
447 )
448 {
449 EFI_STATUS Status;
450
451 Status = EfiLibInstallDriverBindingComponentName2 (
452 ImageHandle,
453 SystemTable,
454 &gIsaBusDriverBinding,
455 ImageHandle,
456 &gIsaBusComponentName,
457 &gIsaBusComponentName2
458 );
459 ASSERT_EFI_ERROR (Status);
460 return Status;
461 }