VirtioFdtDxe.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  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 (&gFdtClientProtocolGuid, NULL,
  42. (VOID **)&FdtClient);
  43. ASSERT_EFI_ERROR (Status);
  44. for (FindNodeStatus = FdtClient->FindCompatibleNode (FdtClient,
  45. "virtio,mmio", &Node);
  46. !EFI_ERROR (FindNodeStatus);
  47. FindNodeStatus = FdtClient->FindNextCompatibleNode (FdtClient,
  48. "virtio,mmio", Node, &Node)) {
  49. Status = FdtClient->GetNodeProperty (FdtClient, Node, "reg",
  50. (CONST VOID **)&Reg, &RegSize);
  51. if (EFI_ERROR (Status)) {
  52. DEBUG ((EFI_D_ERROR, "%a: GetNodeProperty () failed (Status == %r)\n",
  53. __FUNCTION__, Status));
  54. continue;
  55. }
  56. ASSERT (RegSize == 16);
  57. //
  58. // Create a unique device path for this transport on the fly
  59. //
  60. RegBase = SwapBytes64 (*Reg);
  61. DevicePath = (VIRTIO_TRANSPORT_DEVICE_PATH *)CreateDeviceNode (
  62. HARDWARE_DEVICE_PATH,
  63. HW_VENDOR_DP,
  64. sizeof (VIRTIO_TRANSPORT_DEVICE_PATH));
  65. if (DevicePath == NULL) {
  66. DEBUG ((EFI_D_ERROR, "%a: Out of memory\n", __FUNCTION__));
  67. continue;
  68. }
  69. CopyGuid (&DevicePath->Vendor.Guid, &gVirtioMmioTransportGuid);
  70. DevicePath->PhysBase = RegBase;
  71. SetDevicePathNodeLength (&DevicePath->Vendor,
  72. sizeof (*DevicePath) - sizeof (DevicePath->End));
  73. SetDevicePathEndNode (&DevicePath->End);
  74. Handle = NULL;
  75. Status = gBS->InstallProtocolInterface (&Handle,
  76. &gEfiDevicePathProtocolGuid, EFI_NATIVE_INTERFACE,
  77. DevicePath);
  78. if (EFI_ERROR (Status)) {
  79. DEBUG ((EFI_D_ERROR, "%a: Failed to install the EFI_DEVICE_PATH "
  80. "protocol on a new handle (Status == %r)\n",
  81. __FUNCTION__, Status));
  82. FreePool (DevicePath);
  83. continue;
  84. }
  85. Status = VirtioMmioInstallDevice (RegBase, Handle);
  86. if (EFI_ERROR (Status)) {
  87. DEBUG ((EFI_D_ERROR, "%a: Failed to install VirtIO transport @ 0x%Lx "
  88. "on handle %p (Status == %r)\n", __FUNCTION__, RegBase,
  89. Handle, Status));
  90. Status = gBS->UninstallProtocolInterface (Handle,
  91. &gEfiDevicePathProtocolGuid, DevicePath);
  92. ASSERT_EFI_ERROR (Status);
  93. FreePool (DevicePath);
  94. continue;
  95. }
  96. }
  97. if (EFI_ERROR (FindNodeStatus) && FindNodeStatus != EFI_NOT_FOUND) {
  98. DEBUG ((EFI_D_ERROR, "%a: Error occurred while iterating DT nodes "
  99. "(FindNodeStatus == %r)\n", __FUNCTION__, FindNodeStatus));
  100. }
  101. return EFI_SUCCESS;
  102. }