EmuBusDriverDxe.c 15 KB

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