2 * Virtio FDT client protocol driver for virtio,mmio DT node
4 * Copyright (c) 2014 - 2016, Linaro Ltd. All rights reserved.<BR>
6 * This program and the accompanying materials are
7 * 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
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.
16 #include <Library/BaseLib.h>
17 #include <Library/BaseMemoryLib.h>
18 #include <Library/DebugLib.h>
19 #include <Library/DevicePathLib.h>
20 #include <Library/MemoryAllocationLib.h>
21 #include <Library/UefiBootServicesTableLib.h>
22 #include <Library/UefiDriverEntryPoint.h>
23 #include <Library/VirtioMmioDeviceLib.h>
25 #include <Guid/VirtioMmioTransport.h>
27 #include <Protocol/FdtClient.h>
31 VENDOR_DEVICE_PATH Vendor
;
33 EFI_DEVICE_PATH_PROTOCOL End
;
34 } VIRTIO_TRANSPORT_DEVICE_PATH
;
39 InitializeVirtioFdtDxe (
40 IN EFI_HANDLE ImageHandle
,
41 IN EFI_SYSTEM_TABLE
*SystemTable
44 EFI_STATUS Status
, FindNodeStatus
;
45 FDT_CLIENT_PROTOCOL
*FdtClient
;
49 VIRTIO_TRANSPORT_DEVICE_PATH
*DevicePath
;
53 Status
= gBS
->LocateProtocol (&gFdtClientProtocolGuid
, NULL
,
55 ASSERT_EFI_ERROR (Status
);
57 for (FindNodeStatus
= FdtClient
->FindCompatibleNode (FdtClient
,
58 "virtio,mmio", &Node
);
59 !EFI_ERROR (FindNodeStatus
);
60 FindNodeStatus
= FdtClient
->FindNextCompatibleNode (FdtClient
,
61 "virtio,mmio", Node
, &Node
)) {
63 Status
= FdtClient
->GetNodeProperty (FdtClient
, Node
, "reg",
64 (CONST VOID
**)&Reg
, &RegSize
);
65 if (EFI_ERROR (Status
)) {
66 DEBUG ((EFI_D_ERROR
, "%a: GetNodeProperty () failed (Status == %r)\n",
67 __FUNCTION__
, Status
));
71 ASSERT (RegSize
== 16);
74 // Create a unique device path for this transport on the fly
76 RegBase
= SwapBytes64 (*Reg
);
77 DevicePath
= (VIRTIO_TRANSPORT_DEVICE_PATH
*)CreateDeviceNode (
80 sizeof (VIRTIO_TRANSPORT_DEVICE_PATH
));
81 if (DevicePath
== NULL
) {
82 DEBUG ((EFI_D_ERROR
, "%a: Out of memory\n", __FUNCTION__
));
86 CopyGuid (&DevicePath
->Vendor
.Guid
, &gVirtioMmioTransportGuid
);
87 DevicePath
->PhysBase
= RegBase
;
88 SetDevicePathNodeLength (&DevicePath
->Vendor
,
89 sizeof (*DevicePath
) - sizeof (DevicePath
->End
));
90 SetDevicePathEndNode (&DevicePath
->End
);
93 Status
= gBS
->InstallProtocolInterface (&Handle
,
94 &gEfiDevicePathProtocolGuid
, EFI_NATIVE_INTERFACE
,
96 if (EFI_ERROR (Status
)) {
97 DEBUG ((EFI_D_ERROR
, "%a: Failed to install the EFI_DEVICE_PATH "
98 "protocol on a new handle (Status == %r)\n",
99 __FUNCTION__
, Status
));
100 FreePool (DevicePath
);
104 Status
= VirtioMmioInstallDevice (RegBase
, Handle
);
105 if (EFI_ERROR (Status
)) {
106 DEBUG ((EFI_D_ERROR
, "%a: Failed to install VirtIO transport @ 0x%Lx "
107 "on handle %p (Status == %r)\n", __FUNCTION__
, RegBase
,
110 Status
= gBS
->UninstallProtocolInterface (Handle
,
111 &gEfiDevicePathProtocolGuid
, DevicePath
);
112 ASSERT_EFI_ERROR (Status
);
113 FreePool (DevicePath
);
118 if (EFI_ERROR (FindNodeStatus
) && FindNodeStatus
!= EFI_NOT_FOUND
) {
119 DEBUG ((EFI_D_ERROR
, "%a: Error occurred while iterating DT nodes "
120 "(FindNodeStatus == %r)\n", __FUNCTION__
, FindNodeStatus
));