VirtioFdtDxe.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. /** @file
  2. * Virtio FDT client protocol driver for virtio,mmio DT node
  3. *
  4. * Copyright (c) 2014 - 2016, Linaro Ltd. All rights reserved.<BR>
  5. *
  6. * SPDX-License-Identifier: BSD-2-Clause-Patent
  7. *
  8. **/
  9. #include <Library/BaseLib.h>
  10. #include <Library/BaseMemoryLib.h>
  11. #include <Library/DebugLib.h>
  12. #include <Library/DevicePathLib.h>
  13. #include <Library/MemoryAllocationLib.h>
  14. #include <Library/UefiBootServicesTableLib.h>
  15. #include <Library/UefiDriverEntryPoint.h>
  16. #include <Library/VirtioMmioDeviceLib.h>
  17. #include <Guid/VirtioMmioTransport.h>
  18. #include <Protocol/FdtClient.h>
  19. #pragma pack (1)
  20. typedef struct {
  21. VENDOR_DEVICE_PATH Vendor;
  22. UINT64 PhysBase;
  23. EFI_DEVICE_PATH_PROTOCOL End;
  24. } VIRTIO_TRANSPORT_DEVICE_PATH;
  25. #pragma pack ()
  26. EFI_STATUS
  27. EFIAPI
  28. InitializeVirtioFdtDxe (
  29. IN EFI_HANDLE ImageHandle,
  30. IN EFI_SYSTEM_TABLE *SystemTable
  31. )
  32. {
  33. EFI_STATUS Status, FindNodeStatus;
  34. FDT_CLIENT_PROTOCOL *FdtClient;
  35. INT32 Node;
  36. CONST UINT64 *Reg;
  37. UINT32 RegSize;
  38. VIRTIO_TRANSPORT_DEVICE_PATH *DevicePath;
  39. EFI_HANDLE Handle;
  40. UINT64 RegBase;
  41. Status = gBS->LocateProtocol (
  42. &gFdtClientProtocolGuid,
  43. NULL,
  44. (VOID **)&FdtClient
  45. );
  46. ASSERT_EFI_ERROR (Status);
  47. for (FindNodeStatus = FdtClient->FindCompatibleNode (
  48. FdtClient,
  49. "virtio,mmio",
  50. &Node
  51. );
  52. !EFI_ERROR (FindNodeStatus);
  53. FindNodeStatus = FdtClient->FindNextCompatibleNode (
  54. FdtClient,
  55. "virtio,mmio",
  56. Node,
  57. &Node
  58. ))
  59. {
  60. Status = FdtClient->GetNodeProperty (
  61. FdtClient,
  62. Node,
  63. "reg",
  64. (CONST VOID **)&Reg,
  65. &RegSize
  66. );
  67. if (EFI_ERROR (Status)) {
  68. DEBUG ((
  69. DEBUG_ERROR,
  70. "%a: GetNodeProperty () failed (Status == %r)\n",
  71. __FUNCTION__,
  72. Status
  73. ));
  74. continue;
  75. }
  76. ASSERT (RegSize == 16);
  77. //
  78. // Create a unique device path for this transport on the fly
  79. //
  80. RegBase = SwapBytes64 (*Reg);
  81. DevicePath = (VIRTIO_TRANSPORT_DEVICE_PATH *)CreateDeviceNode (
  82. HARDWARE_DEVICE_PATH,
  83. HW_VENDOR_DP,
  84. sizeof (VIRTIO_TRANSPORT_DEVICE_PATH)
  85. );
  86. if (DevicePath == NULL) {
  87. DEBUG ((DEBUG_ERROR, "%a: Out of memory\n", __FUNCTION__));
  88. continue;
  89. }
  90. CopyGuid (&DevicePath->Vendor.Guid, &gVirtioMmioTransportGuid);
  91. DevicePath->PhysBase = RegBase;
  92. SetDevicePathNodeLength (
  93. &DevicePath->Vendor,
  94. sizeof (*DevicePath) - sizeof (DevicePath->End)
  95. );
  96. SetDevicePathEndNode (&DevicePath->End);
  97. Handle = NULL;
  98. Status = gBS->InstallProtocolInterface (
  99. &Handle,
  100. &gEfiDevicePathProtocolGuid,
  101. EFI_NATIVE_INTERFACE,
  102. DevicePath
  103. );
  104. if (EFI_ERROR (Status)) {
  105. DEBUG ((
  106. DEBUG_ERROR,
  107. "%a: Failed to install the EFI_DEVICE_PATH "
  108. "protocol on a new handle (Status == %r)\n",
  109. __FUNCTION__,
  110. Status
  111. ));
  112. FreePool (DevicePath);
  113. continue;
  114. }
  115. Status = VirtioMmioInstallDevice (RegBase, Handle);
  116. if (EFI_ERROR (Status)) {
  117. DEBUG ((
  118. DEBUG_ERROR,
  119. "%a: Failed to install VirtIO transport @ 0x%Lx "
  120. "on handle %p (Status == %r)\n",
  121. __FUNCTION__,
  122. RegBase,
  123. Handle,
  124. Status
  125. ));
  126. Status = gBS->UninstallProtocolInterface (
  127. Handle,
  128. &gEfiDevicePathProtocolGuid,
  129. DevicePath
  130. );
  131. ASSERT_EFI_ERROR (Status);
  132. FreePool (DevicePath);
  133. continue;
  134. }
  135. }
  136. if (EFI_ERROR (FindNodeStatus) && (FindNodeStatus != EFI_NOT_FOUND)) {
  137. DEBUG ((
  138. DEBUG_ERROR,
  139. "%a: Error occurred while iterating DT nodes "
  140. "(FindNodeStatus == %r)\n",
  141. __FUNCTION__,
  142. FindNodeStatus
  143. ));
  144. }
  145. return EFI_SUCCESS;
  146. }