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