]> git.proxmox.com Git - mirror_edk2.git/blob - ArmVirtPkg/VirtioFdtDxe/VirtioFdtDxe.c
BaseTools: Library hashing fix and optimization for --hash feature
[mirror_edk2.git] / ArmVirtPkg / VirtioFdtDxe / VirtioFdtDxe.c
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
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>
18
19 #include <Guid/VirtioMmioTransport.h>
20
21 #include <Protocol/FdtClient.h>
22
23 #pragma pack (1)
24 typedef struct {
25 VENDOR_DEVICE_PATH Vendor;
26 UINT64 PhysBase;
27 EFI_DEVICE_PATH_PROTOCOL End;
28 } VIRTIO_TRANSPORT_DEVICE_PATH;
29 #pragma pack ()
30
31 EFI_STATUS
32 EFIAPI
33 InitializeVirtioFdtDxe (
34 IN EFI_HANDLE ImageHandle,
35 IN EFI_SYSTEM_TABLE *SystemTable
36 )
37 {
38 EFI_STATUS Status, FindNodeStatus;
39 FDT_CLIENT_PROTOCOL *FdtClient;
40 INT32 Node;
41 CONST UINT64 *Reg;
42 UINT32 RegSize;
43 VIRTIO_TRANSPORT_DEVICE_PATH *DevicePath;
44 EFI_HANDLE Handle;
45 UINT64 RegBase;
46
47 Status = gBS->LocateProtocol (&gFdtClientProtocolGuid, NULL,
48 (VOID **)&FdtClient);
49 ASSERT_EFI_ERROR (Status);
50
51 for (FindNodeStatus = FdtClient->FindCompatibleNode (FdtClient,
52 "virtio,mmio", &Node);
53 !EFI_ERROR (FindNodeStatus);
54 FindNodeStatus = FdtClient->FindNextCompatibleNode (FdtClient,
55 "virtio,mmio", Node, &Node)) {
56
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));
62 continue;
63 }
64
65 ASSERT (RegSize == 16);
66
67 //
68 // Create a unique device path for this transport on the fly
69 //
70 RegBase = SwapBytes64 (*Reg);
71 DevicePath = (VIRTIO_TRANSPORT_DEVICE_PATH *)CreateDeviceNode (
72 HARDWARE_DEVICE_PATH,
73 HW_VENDOR_DP,
74 sizeof (VIRTIO_TRANSPORT_DEVICE_PATH));
75 if (DevicePath == NULL) {
76 DEBUG ((EFI_D_ERROR, "%a: Out of memory\n", __FUNCTION__));
77 continue;
78 }
79
80 CopyGuid (&DevicePath->Vendor.Guid, &gVirtioMmioTransportGuid);
81 DevicePath->PhysBase = RegBase;
82 SetDevicePathNodeLength (&DevicePath->Vendor,
83 sizeof (*DevicePath) - sizeof (DevicePath->End));
84 SetDevicePathEndNode (&DevicePath->End);
85
86 Handle = NULL;
87 Status = gBS->InstallProtocolInterface (&Handle,
88 &gEfiDevicePathProtocolGuid, EFI_NATIVE_INTERFACE,
89 DevicePath);
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);
95 continue;
96 }
97
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,
102 Handle, Status));
103
104 Status = gBS->UninstallProtocolInterface (Handle,
105 &gEfiDevicePathProtocolGuid, DevicePath);
106 ASSERT_EFI_ERROR (Status);
107 FreePool (DevicePath);
108 continue;
109 }
110 }
111
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));
115 }
116
117 return EFI_SUCCESS;
118 }