2 * Virtio FDT client protocol driver for virtio,mmio DT node
4 * Copyright (c) 2014 - 2016, Linaro Ltd. All rights reserved.<BR>
6 * SPDX-License-Identifier: BSD-2-Clause-Patent
10 #include <Library/BaseLib.h>
11 #include <Library/BaseMemoryLib.h>
12 #include <Library/DebugLib.h>
13 #include <Library/DevicePathLib.h>
14 #include <Library/MemoryAllocationLib.h>
15 #include <Library/UefiBootServicesTableLib.h>
16 #include <Library/UefiDriverEntryPoint.h>
17 #include <Library/VirtioMmioDeviceLib.h>
19 #include <Guid/VirtioMmioTransport.h>
21 #include <Protocol/FdtClient.h>
25 VENDOR_DEVICE_PATH Vendor
;
27 EFI_DEVICE_PATH_PROTOCOL End
;
28 } VIRTIO_TRANSPORT_DEVICE_PATH
;
33 InitializeVirtioFdtDxe (
34 IN EFI_HANDLE ImageHandle
,
35 IN EFI_SYSTEM_TABLE
*SystemTable
38 EFI_STATUS Status
, FindNodeStatus
;
39 FDT_CLIENT_PROTOCOL
*FdtClient
;
43 VIRTIO_TRANSPORT_DEVICE_PATH
*DevicePath
;
47 Status
= gBS
->LocateProtocol (&gFdtClientProtocolGuid
, NULL
,
49 ASSERT_EFI_ERROR (Status
);
51 for (FindNodeStatus
= FdtClient
->FindCompatibleNode (FdtClient
,
52 "virtio,mmio", &Node
);
53 !EFI_ERROR (FindNodeStatus
);
54 FindNodeStatus
= FdtClient
->FindNextCompatibleNode (FdtClient
,
55 "virtio,mmio", Node
, &Node
)) {
57 Status
= FdtClient
->GetNodeProperty (FdtClient
, Node
, "reg",
58 (CONST VOID
**)&Reg
, &RegSize
);
59 if (EFI_ERROR (Status
)) {
60 DEBUG ((EFI_D_ERROR
, "%a: GetNodeProperty () failed (Status == %r)\n",
61 __FUNCTION__
, Status
));
65 ASSERT (RegSize
== 16);
68 // Create a unique device path for this transport on the fly
70 RegBase
= SwapBytes64 (*Reg
);
71 DevicePath
= (VIRTIO_TRANSPORT_DEVICE_PATH
*)CreateDeviceNode (
74 sizeof (VIRTIO_TRANSPORT_DEVICE_PATH
));
75 if (DevicePath
== NULL
) {
76 DEBUG ((EFI_D_ERROR
, "%a: Out of memory\n", __FUNCTION__
));
80 CopyGuid (&DevicePath
->Vendor
.Guid
, &gVirtioMmioTransportGuid
);
81 DevicePath
->PhysBase
= RegBase
;
82 SetDevicePathNodeLength (&DevicePath
->Vendor
,
83 sizeof (*DevicePath
) - sizeof (DevicePath
->End
));
84 SetDevicePathEndNode (&DevicePath
->End
);
87 Status
= gBS
->InstallProtocolInterface (&Handle
,
88 &gEfiDevicePathProtocolGuid
, EFI_NATIVE_INTERFACE
,
90 if (EFI_ERROR (Status
)) {
91 DEBUG ((EFI_D_ERROR
, "%a: Failed to install the EFI_DEVICE_PATH "
92 "protocol on a new handle (Status == %r)\n",
93 __FUNCTION__
, Status
));
94 FreePool (DevicePath
);
98 Status
= VirtioMmioInstallDevice (RegBase
, Handle
);
99 if (EFI_ERROR (Status
)) {
100 DEBUG ((EFI_D_ERROR
, "%a: Failed to install VirtIO transport @ 0x%Lx "
101 "on handle %p (Status == %r)\n", __FUNCTION__
, RegBase
,
104 Status
= gBS
->UninstallProtocolInterface (Handle
,
105 &gEfiDevicePathProtocolGuid
, DevicePath
);
106 ASSERT_EFI_ERROR (Status
);
107 FreePool (DevicePath
);
112 if (EFI_ERROR (FindNodeStatus
) && FindNodeStatus
!= EFI_NOT_FOUND
) {
113 DEBUG ((EFI_D_ERROR
, "%a: Error occurred while iterating DT nodes "
114 "(FindNodeStatus == %r)\n", __FUNCTION__
, FindNodeStatus
));