]> git.proxmox.com Git - mirror_edk2.git/blob - InOsEmuPkg/EmuBusDriverDxe/EmuBusDriverDxe.c
ArmPlatformPkg/Documentation: Update the instructions to build ARM Versatile Express...
[mirror_edk2.git] / InOsEmuPkg / EmuBusDriverDxe / EmuBusDriverDxe.c
1 /** @file
2 Emu Bus driver
3
4 Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
5 Portions copyright (c) 2011, Apple Inc. All rights reserved.
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
10
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13
14
15 **/
16
17 #include "EmuBusDriverDxe.h"
18
19
20
21 //
22 // DriverBinding protocol global
23 //
24 EFI_DRIVER_BINDING_PROTOCOL gEmuBusDriverBinding = {
25 EmuBusDriverBindingSupported,
26 EmuBusDriverBindingStart,
27 EmuBusDriverBindingStop,
28 0xa,
29 NULL,
30 NULL
31 };
32
33
34
35 EFI_STATUS
36 EFIAPI
37 EmuBusDriverBindingSupported (
38 IN EFI_DRIVER_BINDING_PROTOCOL *This,
39 IN EFI_HANDLE ControllerHandle,
40 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
41 )
42 {
43 EFI_STATUS Status;
44 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
45 EMU_THUNK_PROTOCOL *EmuThunk;
46
47 //
48 // Check the contents of the first Device Path Node of RemainingDevicePath to make sure
49 // it is a legal Device Path Node for this bus driver's children.
50 //
51 if (RemainingDevicePath != NULL) {
52 //
53 // Check if RemainingDevicePath is the End of Device Path Node,
54 // if yes, go on checking other conditions
55 //
56 if (!IsDevicePathEnd (RemainingDevicePath)) {
57 //
58 // If RemainingDevicePath isn't the End of Device Path Node,
59 // check its validation
60 //
61 if (RemainingDevicePath->Type != HARDWARE_DEVICE_PATH ||
62 RemainingDevicePath->SubType != HW_VENDOR_DP ||
63 DevicePathNodeLength(RemainingDevicePath) != sizeof(EMU_VENDOR_DEVICE_PATH_NODE)) {
64 return EFI_UNSUPPORTED;
65 }
66 }
67 }
68
69 //
70 // Open the IO Abstraction(s) needed to perform the supported test
71 //
72 Status = gBS->OpenProtocol (
73 ControllerHandle,
74 &gEmuThunkProtocolGuid,
75 (VOID **)&EmuThunk ,
76 This->DriverBindingHandle,
77 ControllerHandle,
78 EFI_OPEN_PROTOCOL_BY_DRIVER
79 );
80 if (Status == EFI_ALREADY_STARTED) {
81 return EFI_SUCCESS;
82 }
83
84 if (EFI_ERROR (Status)) {
85 return Status;
86 }
87
88 //
89 // Close the I/O Abstraction(s) used to perform the supported test
90 //
91 gBS->CloseProtocol (
92 ControllerHandle,
93 &gEmuThunkProtocolGuid,
94 This->DriverBindingHandle,
95 ControllerHandle
96 );
97
98 //
99 // Open the EFI Device Path protocol needed to perform the supported test
100 //
101 Status = gBS->OpenProtocol (
102 ControllerHandle,
103 &gEfiDevicePathProtocolGuid,
104 (VOID **)&ParentDevicePath,
105 This->DriverBindingHandle,
106 ControllerHandle,
107 EFI_OPEN_PROTOCOL_BY_DRIVER
108 );
109 if (Status == EFI_ALREADY_STARTED) {
110 return EFI_SUCCESS;
111 }
112
113 if (EFI_ERROR (Status)) {
114 return Status;
115 }
116
117
118 //
119 // Close protocol, don't use device path protocol in the Support() function
120 //
121 gBS->CloseProtocol (
122 ControllerHandle,
123 &gEfiDevicePathProtocolGuid,
124 This->DriverBindingHandle,
125 ControllerHandle
126 );
127
128 return Status;
129 }
130
131
132 EFI_STATUS
133 EFIAPI
134 EmuBusDriverBindingStart (
135 IN EFI_DRIVER_BINDING_PROTOCOL *This,
136 IN EFI_HANDLE ControllerHandle,
137 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
138 )
139 {
140 EFI_STATUS Status;
141 EFI_STATUS InstallStatus;
142 EMU_THUNK_PROTOCOL *EmuThunk;
143 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
144 EMU_IO_DEVICE *EmuDevice;
145 EMU_BUS_DEVICE *EmuBusDevice;
146 EMU_IO_THUNK_PROTOCOL *EmuIoThunk;
147 UINT16 ComponentName[512];
148 EMU_VENDOR_DEVICE_PATH_NODE *Node;
149 BOOLEAN CreateDevice;
150
151 Status = EFI_UNSUPPORTED;
152
153 //
154 // Grab the protocols we need
155 //
156 Status = gBS->OpenProtocol (
157 ControllerHandle,
158 &gEfiDevicePathProtocolGuid,
159 (VOID **)&ParentDevicePath,
160 This->DriverBindingHandle,
161 ControllerHandle,
162 EFI_OPEN_PROTOCOL_BY_DRIVER
163 );
164 if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {
165 return Status;
166 }
167
168 Status = gBS->OpenProtocol (
169 ControllerHandle,
170 &gEmuThunkProtocolGuid,
171 (VOID **)&EmuThunk,
172 This->DriverBindingHandle,
173 ControllerHandle,
174 EFI_OPEN_PROTOCOL_BY_DRIVER
175 );
176 if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {
177 return Status;
178 }
179
180 if (Status != EFI_ALREADY_STARTED) {
181 EmuBusDevice = AllocatePool (sizeof (EMU_BUS_DEVICE));
182 if (EmuBusDevice == NULL) {
183 return EFI_OUT_OF_RESOURCES;
184 }
185
186 EmuBusDevice->Signature = EMU_BUS_DEVICE_SIGNATURE;
187 EmuBusDevice->ControllerNameTable = NULL;
188
189 AddUnicodeString2 (
190 "eng",
191 gEmuBusDriverComponentName.SupportedLanguages,
192 &EmuBusDevice->ControllerNameTable,
193 L"InOsEmu Bus Controller",
194 TRUE
195 );
196 AddUnicodeString2 (
197 "en",
198 gEmuBusDriverComponentName2.SupportedLanguages,
199 &EmuBusDevice->ControllerNameTable,
200 L"InOsEmu Bus Controller",
201 FALSE
202 );
203
204
205 Status = gBS->InstallMultipleProtocolInterfaces (
206 &ControllerHandle,
207 &gEfiCallerIdGuid, EmuBusDevice,
208 NULL
209 );
210 if (EFI_ERROR (Status)) {
211 FreeUnicodeStringTable (EmuBusDevice->ControllerNameTable);
212 gBS->FreePool (EmuBusDevice);
213 return Status;
214 }
215 }
216
217
218 for (Status = EFI_SUCCESS, EmuIoThunk = NULL; !EFI_ERROR (Status); ) {
219 Status = EmuThunk->GetNextProtocol (TRUE, &EmuIoThunk);
220 if (EFI_ERROR (Status)) {
221 break;
222 }
223
224 CreateDevice = TRUE;
225 if (RemainingDevicePath != NULL) {
226 CreateDevice = FALSE;
227 //
228 // Check if RemainingDevicePath is the End of Device Path Node,
229 // if yes, don't create any child device
230 //
231 if (!IsDevicePathEnd (RemainingDevicePath)) {
232 //
233 // If RemainingDevicePath isn't the End of Device Path Node,
234 // check its validation
235 //
236 Node = (EMU_VENDOR_DEVICE_PATH_NODE *) RemainingDevicePath;
237 if (Node->VendorDevicePath.Header.Type == HARDWARE_DEVICE_PATH &&
238 Node->VendorDevicePath.Header.SubType == HW_VENDOR_DP &&
239 DevicePathNodeLength (&Node->VendorDevicePath.Header) == sizeof (EMU_VENDOR_DEVICE_PATH_NODE)
240 ) {
241 if (CompareGuid (&Node->VendorDevicePath.Guid, EmuIoThunk->Protocol) && Node->Instance == EmuIoThunk->Instance) {
242 CreateDevice = TRUE;
243 }
244 }
245 }
246 }
247
248 if (CreateDevice) {
249 //
250 // Allocate instance structure, and fill in parent information.
251 //
252 EmuDevice = AllocatePool (sizeof (EMU_IO_DEVICE));
253 if (EmuDevice == NULL) {
254 return EFI_OUT_OF_RESOURCES;
255 }
256
257 EmuDevice->Handle = NULL;
258 EmuDevice->ControllerHandle = ControllerHandle;
259 EmuDevice->ParentDevicePath = ParentDevicePath;
260 CopyMem (&EmuDevice->EmuIoThunk, EmuIoThunk, sizeof (EMU_IO_THUNK_PROTOCOL));
261
262 EmuDevice->ControllerNameTable = NULL;
263
264 StrnCpy (ComponentName, EmuIoThunk->ConfigString, sizeof (ComponentName)/sizeof (CHAR16));
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