]> git.proxmox.com Git - mirror_edk2.git/blob - EmulatorPkg/EmuBusDriverDxe/EmuBusDriverDxe.c
MdePkg: Apply uncrustify changes
[mirror_edk2.git] / EmulatorPkg / EmuBusDriverDxe / EmuBusDriverDxe.c
1 /** @file
2 Emu Bus driver
3
4 Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
5 Portions copyright (c) 2011, Apple Inc. All rights reserved.
6 SPDX-License-Identifier: BSD-2-Clause-Patent
7
8
9 **/
10
11 #include "EmuBusDriverDxe.h"
12
13 //
14 // DriverBinding protocol global
15 //
16 EFI_DRIVER_BINDING_PROTOCOL gEmuBusDriverBinding = {
17 EmuBusDriverBindingSupported,
18 EmuBusDriverBindingStart,
19 EmuBusDriverBindingStop,
20 0xa,
21 NULL,
22 NULL
23 };
24
25 EFI_STATUS
26 EFIAPI
27 EmuBusDriverBindingSupported (
28 IN EFI_DRIVER_BINDING_PROTOCOL *This,
29 IN EFI_HANDLE ControllerHandle,
30 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
31 )
32 {
33 EFI_STATUS Status;
34 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
35 EMU_THUNK_PROTOCOL *EmuThunk;
36
37 //
38 // Check the contents of the first Device Path Node of RemainingDevicePath to make sure
39 // it is a legal Device Path Node for this bus driver's children.
40 //
41 if (RemainingDevicePath != NULL) {
42 //
43 // Check if RemainingDevicePath is the End of Device Path Node,
44 // if yes, go on checking other conditions
45 //
46 if (!IsDevicePathEnd (RemainingDevicePath)) {
47 //
48 // If RemainingDevicePath isn't the End of Device Path Node,
49 // check its validation
50 //
51 if ((RemainingDevicePath->Type != HARDWARE_DEVICE_PATH) ||
52 (RemainingDevicePath->SubType != HW_VENDOR_DP) ||
53 (DevicePathNodeLength (RemainingDevicePath) != sizeof (EMU_VENDOR_DEVICE_PATH_NODE)))
54 {
55 return EFI_UNSUPPORTED;
56 }
57 }
58 }
59
60 //
61 // Open the IO Abstraction(s) needed to perform the supported test
62 //
63 Status = gBS->OpenProtocol (
64 ControllerHandle,
65 &gEmuThunkProtocolGuid,
66 (VOID **)&EmuThunk,
67 This->DriverBindingHandle,
68 ControllerHandle,
69 EFI_OPEN_PROTOCOL_BY_DRIVER
70 );
71 if (Status == EFI_ALREADY_STARTED) {
72 return EFI_SUCCESS;
73 }
74
75 if (EFI_ERROR (Status)) {
76 return Status;
77 }
78
79 //
80 // Close the I/O Abstraction(s) used to perform the supported test
81 //
82 gBS->CloseProtocol (
83 ControllerHandle,
84 &gEmuThunkProtocolGuid,
85 This->DriverBindingHandle,
86 ControllerHandle
87 );
88
89 //
90 // Open the EFI Device Path protocol needed to perform the supported test
91 //
92 Status = gBS->OpenProtocol (
93 ControllerHandle,
94 &gEfiDevicePathProtocolGuid,
95 (VOID **)&ParentDevicePath,
96 This->DriverBindingHandle,
97 ControllerHandle,
98 EFI_OPEN_PROTOCOL_BY_DRIVER
99 );
100 if (Status == EFI_ALREADY_STARTED) {
101 return EFI_SUCCESS;
102 }
103
104 if (EFI_ERROR (Status)) {
105 return Status;
106 }
107
108 //
109 // Close protocol, don't use device path protocol in the Support() function
110 //
111 gBS->CloseProtocol (
112 ControllerHandle,
113 &gEfiDevicePathProtocolGuid,
114 This->DriverBindingHandle,
115 ControllerHandle
116 );
117
118 return Status;
119 }
120
121 EFI_STATUS
122 EFIAPI
123 EmuBusDriverBindingStart (
124 IN EFI_DRIVER_BINDING_PROTOCOL *This,
125 IN EFI_HANDLE ControllerHandle,
126 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
127 )
128 {
129 EFI_STATUS Status;
130 EFI_STATUS InstallStatus;
131 EMU_THUNK_PROTOCOL *EmuThunk;
132 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
133 EMU_IO_DEVICE *EmuDevice;
134 EMU_BUS_DEVICE *EmuBusDevice;
135 EMU_IO_THUNK_PROTOCOL *EmuIoThunk;
136 UINT16 ComponentName[512];
137 EMU_VENDOR_DEVICE_PATH_NODE *Node;
138 BOOLEAN CreateDevice;
139
140 InstallStatus = EFI_UNSUPPORTED;
141 Status = EFI_UNSUPPORTED;
142
143 //
144 // Grab the protocols we need
145 //
146 Status = gBS->OpenProtocol (
147 ControllerHandle,
148 &gEfiDevicePathProtocolGuid,
149 (VOID **)&ParentDevicePath,
150 This->DriverBindingHandle,
151 ControllerHandle,
152 EFI_OPEN_PROTOCOL_BY_DRIVER
153 );
154 if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {
155 return Status;
156 }
157
158 Status = gBS->OpenProtocol (
159 ControllerHandle,
160 &gEmuThunkProtocolGuid,
161 (VOID **)&EmuThunk,
162 This->DriverBindingHandle,
163 ControllerHandle,
164 EFI_OPEN_PROTOCOL_BY_DRIVER
165 );
166 if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {
167 return Status;
168 }
169
170 if (Status != EFI_ALREADY_STARTED) {
171 EmuBusDevice = AllocatePool (sizeof (EMU_BUS_DEVICE));
172 if (EmuBusDevice == NULL) {
173 return EFI_OUT_OF_RESOURCES;
174 }
175
176 EmuBusDevice->Signature = EMU_BUS_DEVICE_SIGNATURE;
177 EmuBusDevice->ControllerNameTable = NULL;
178
179 AddUnicodeString2 (
180 "eng",
181 gEmuBusDriverComponentName.SupportedLanguages,
182 &EmuBusDevice->ControllerNameTable,
183 L"Emulator Bus Controller",
184 TRUE
185 );
186 AddUnicodeString2 (
187 "en",
188 gEmuBusDriverComponentName2.SupportedLanguages,
189 &EmuBusDevice->ControllerNameTable,
190 L"Emulator Bus Controller",
191 FALSE
192 );
193
194 Status = gBS->InstallMultipleProtocolInterfaces (
195 &ControllerHandle,
196 &gEfiCallerIdGuid,
197 EmuBusDevice,
198 NULL
199 );
200 if (EFI_ERROR (Status)) {
201 FreeUnicodeStringTable (EmuBusDevice->ControllerNameTable);
202 gBS->FreePool (EmuBusDevice);
203 return Status;
204 }
205 }
206
207 for (Status = EFI_SUCCESS, EmuIoThunk = NULL; !EFI_ERROR (Status); ) {
208 Status = EmuThunk->GetNextProtocol (TRUE, &EmuIoThunk);
209 if (EFI_ERROR (Status)) {
210 break;
211 }
212
213 CreateDevice = TRUE;
214 if (RemainingDevicePath != NULL) {
215 CreateDevice = FALSE;
216 //
217 // Check if RemainingDevicePath is the End of Device Path Node,
218 // if yes, don't create any child device
219 //
220 if (!IsDevicePathEnd (RemainingDevicePath)) {
221 //
222 // If RemainingDevicePath isn't the End of Device Path Node,
223 // check its validation
224 //
225 Node = (EMU_VENDOR_DEVICE_PATH_NODE *)RemainingDevicePath;
226 if ((Node->VendorDevicePath.Header.Type == HARDWARE_DEVICE_PATH) &&
227 (Node->VendorDevicePath.Header.SubType == HW_VENDOR_DP) &&
228 (DevicePathNodeLength (&Node->VendorDevicePath.Header) == sizeof (EMU_VENDOR_DEVICE_PATH_NODE))
229 )
230 {
231 if (CompareGuid (&Node->VendorDevicePath.Guid, EmuIoThunk->Protocol) && (Node->Instance == EmuIoThunk->Instance)) {
232 CreateDevice = TRUE;
233 }
234 }
235 }
236 }
237
238 if (CreateDevice) {
239 //
240 // Allocate instance structure, and fill in parent information.
241 //
242 EmuDevice = AllocatePool (sizeof (EMU_IO_DEVICE));
243 if (EmuDevice == NULL) {
244 return EFI_OUT_OF_RESOURCES;
245 }
246
247 EmuDevice->Handle = NULL;
248 EmuDevice->ControllerHandle = ControllerHandle;
249 EmuDevice->ParentDevicePath = ParentDevicePath;
250 CopyMem (&EmuDevice->EmuIoThunk, EmuIoThunk, sizeof (EMU_IO_THUNK_PROTOCOL));
251
252 EmuDevice->ControllerNameTable = NULL;
253
254 StrnCpyS (
255 ComponentName,
256 sizeof (ComponentName) / sizeof (CHAR16),
257 EmuIoThunk->ConfigString,
258 sizeof (ComponentName) / sizeof (CHAR16)
259 );
260
261 EmuDevice->DevicePath = EmuBusCreateDevicePath (
262 ParentDevicePath,
263 EmuIoThunk->Protocol,
264 EmuIoThunk->Instance
265 );
266 if (EmuDevice->DevicePath == NULL) {
267 gBS->FreePool (EmuDevice);
268 return EFI_OUT_OF_RESOURCES;
269 }
270
271 AddUnicodeString (
272 "eng",
273 gEmuBusDriverComponentName.SupportedLanguages,
274 &EmuDevice->ControllerNameTable,
275 ComponentName
276 );
277
278 EmuDevice->Signature = EMU_IO_DEVICE_SIGNATURE;
279
280 InstallStatus = gBS->InstallMultipleProtocolInterfaces (
281 &EmuDevice->Handle,
282 &gEfiDevicePathProtocolGuid,
283 EmuDevice->DevicePath,
284 &gEmuIoThunkProtocolGuid,
285 &EmuDevice->EmuIoThunk,
286 NULL
287 );
288 if (EFI_ERROR (InstallStatus)) {
289 FreeUnicodeStringTable (EmuDevice->ControllerNameTable);
290 gBS->FreePool (EmuDevice);
291 } else {
292 //
293 // Open For Child Device
294 //
295 Status = gBS->OpenProtocol (
296 ControllerHandle,
297 &gEmuThunkProtocolGuid,
298 (VOID **)&EmuThunk,
299 This->DriverBindingHandle,
300 EmuDevice->Handle,
301 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
302 );
303 if (!EFI_ERROR (Status)) {
304 InstallStatus = EFI_SUCCESS;
305 }
306 }
307 }
308 }
309
310 return InstallStatus;
311 }
312
313 EFI_STATUS
314 EFIAPI
315 EmuBusDriverBindingStop (
316 IN EFI_DRIVER_BINDING_PROTOCOL *This,
317 IN EFI_HANDLE ControllerHandle,
318 IN UINTN NumberOfChildren,
319 IN EFI_HANDLE *ChildHandleBuffer
320 )
321 {
322 EFI_STATUS Status;
323 UINTN Index;
324 BOOLEAN AllChildrenStopped;
325 EMU_IO_THUNK_PROTOCOL *EmuIoThunk;
326 EMU_BUS_DEVICE *EmuBusDevice;
327 EMU_IO_DEVICE *EmuDevice;
328 EMU_THUNK_PROTOCOL *EmuThunk;
329
330 //
331 // Complete all outstanding transactions to Controller.
332 // Don't allow any new transaction to Controller to be started.
333 //
334
335 if (NumberOfChildren == 0) {
336 //
337 // Close the bus driver
338 //
339 Status = gBS->OpenProtocol (
340 ControllerHandle,
341 &gEfiCallerIdGuid,
342 (VOID **)&EmuBusDevice,
343 This->DriverBindingHandle,
344 ControllerHandle,
345 EFI_OPEN_PROTOCOL_GET_PROTOCOL
346 );
347 if (EFI_ERROR (Status)) {
348 return Status;
349 }
350
351 gBS->UninstallMultipleProtocolInterfaces (
352 ControllerHandle,
353 &gEfiCallerIdGuid,
354 EmuBusDevice,
355 NULL
356 );
357
358 FreeUnicodeStringTable (EmuBusDevice->ControllerNameTable);
359
360 gBS->FreePool (EmuBusDevice);
361
362 gBS->CloseProtocol (
363 ControllerHandle,
364 &gEmuThunkProtocolGuid,
365 This->DriverBindingHandle,
366 ControllerHandle
367 );
368
369 gBS->CloseProtocol (
370 ControllerHandle,
371 &gEfiDevicePathProtocolGuid,
372 This->DriverBindingHandle,
373 ControllerHandle
374 );
375 return EFI_SUCCESS;
376 }
377
378 AllChildrenStopped = TRUE;
379
380 for (Index = 0; Index < NumberOfChildren; Index++) {
381 Status = gBS->OpenProtocol (
382 ChildHandleBuffer[Index],
383 &gEmuIoThunkProtocolGuid,
384 (VOID **)&EmuIoThunk,
385 This->DriverBindingHandle,
386 ControllerHandle,
387 EFI_OPEN_PROTOCOL_GET_PROTOCOL
388 );
389 if (!EFI_ERROR (Status)) {
390 EmuDevice = EMU_IO_DEVICE_FROM_THIS (EmuIoThunk);
391
392 Status = gBS->CloseProtocol (
393 ControllerHandle,
394 &gEmuThunkProtocolGuid,
395 This->DriverBindingHandle,
396 EmuDevice->Handle
397 );
398
399 Status = gBS->UninstallMultipleProtocolInterfaces (
400 EmuDevice->Handle,
401 &gEfiDevicePathProtocolGuid,
402 EmuDevice->DevicePath,
403 &gEmuIoThunkProtocolGuid,
404 &EmuDevice->EmuIoThunk,
405 NULL
406 );
407
408 if (EFI_ERROR (Status)) {
409 gBS->OpenProtocol (
410 ControllerHandle,
411 &gEmuThunkProtocolGuid,
412 (VOID **)&EmuThunk,
413 This->DriverBindingHandle,
414 EmuDevice->Handle,
415 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
416 );
417 } else {
418 //
419 // Close the child handle
420 //
421 FreeUnicodeStringTable (EmuDevice->ControllerNameTable);
422 FreePool (EmuDevice);
423 }
424 }
425
426 if (EFI_ERROR (Status)) {
427 AllChildrenStopped = FALSE;
428 }
429 }
430
431 if (!AllChildrenStopped) {
432 return EFI_DEVICE_ERROR;
433 }
434
435 return EFI_SUCCESS;
436 }
437
438 /*++
439
440 Routine Description:
441 Create a device path node using Guid and InstanceNumber and append it to
442 the passed in RootDevicePath
443
444 Arguments:
445 RootDevicePath - Root of the device path to return.
446
447 Guid - GUID to use in vendor device path node.
448
449 InstanceNumber - Instance number to use in the vendor device path. This
450 argument is needed to make sure each device path is unique.
451
452 Returns:
453
454 EFI_DEVICE_PATH_PROTOCOL
455
456 **/
457 EFI_DEVICE_PATH_PROTOCOL *
458 EmuBusCreateDevicePath (
459 IN EFI_DEVICE_PATH_PROTOCOL *RootDevicePath,
460 IN EFI_GUID *Guid,
461 IN UINT16 InstanceNumber
462 )
463 {
464 EMU_VENDOR_DEVICE_PATH_NODE DevicePath;
465
466 DevicePath.VendorDevicePath.Header.Type = HARDWARE_DEVICE_PATH;
467 DevicePath.VendorDevicePath.Header.SubType = HW_VENDOR_DP;
468 SetDevicePathNodeLength (&DevicePath.VendorDevicePath.Header, sizeof (EMU_VENDOR_DEVICE_PATH_NODE));
469
470 //
471 // The GUID defines the Class
472 //
473 CopyMem (&DevicePath.VendorDevicePath.Guid, Guid, sizeof (EFI_GUID));
474
475 //
476 // Add an instance number so we can make sure there are no Device Path
477 // duplication.
478 //
479 DevicePath.Instance = InstanceNumber;
480
481 return AppendDevicePathNode (
482 RootDevicePath,
483 (EFI_DEVICE_PATH_PROTOCOL *)&DevicePath
484 );
485 }
486
487 /**
488 The user Entry Point for module EmuBusDriver. The user code starts with this function.
489
490 @param[in] ImageHandle The firmware allocated handle for the EFI image.
491 @param[in] SystemTable A pointer to the EFI System Table.
492
493 @retval EFI_SUCCESS The entry point is executed successfully.
494 @retval other Some error occurs when executing this entry point.
495
496 **/
497 EFI_STATUS
498 EFIAPI
499 InitializeEmuBusDriver (
500 IN EFI_HANDLE ImageHandle,
501 IN EFI_SYSTEM_TABLE *SystemTable
502 )
503 {
504 EFI_STATUS Status;
505
506 Status = EfiLibInstallAllDriverProtocols (
507 ImageHandle,
508 SystemTable,
509 &gEmuBusDriverBinding,
510 ImageHandle,
511 &gEmuBusDriverComponentName,
512 NULL,
513 NULL
514 );
515 ASSERT_EFI_ERROR (Status);
516
517 return Status;
518 }