]> git.proxmox.com Git - mirror_edk2.git/blame - OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDevice.c
OvmfPkg/VirtioMmioDeviceLib: Add virtio 1.0 detection.
[mirror_edk2.git] / OvmfPkg / Library / VirtioMmioDeviceLib / VirtioMmioDevice.c
CommitLineData
6fb4e772
OM
1/** @file\r
2\r
3 This driver produces Virtio Device Protocol instances for Virtio Mmio devices.\r
4\r
5 Copyright (C) 2013, ARM Ltd.\r
084cfc1a 6 Copyright (C) 2017, AMD Inc. All rights reserved.<BR>\r
6fb4e772 7\r
b26f0cf9 8 SPDX-License-Identifier: BSD-2-Clause-Patent\r
6fb4e772
OM
9\r
10**/\r
11\r
12#include <Library/BaseMemoryLib.h>\r
6fb4e772
OM
13#include <Library/UefiBootServicesTableLib.h>\r
14\r
15#include "VirtioMmioDevice.h"\r
16\r
4120bb49 17STATIC CONST VIRTIO_DEVICE_PROTOCOL mMmioDeviceProtocolTemplate = {\r
6fb4e772
OM
18 0, // Revision\r
19 0, // SubSystemDeviceId\r
20 VirtioMmioGetDeviceFeatures, // GetDeviceFeatures\r
21 VirtioMmioSetGuestFeatures, // SetGuestFeatures\r
6fb4e772
OM
22 VirtioMmioSetQueueAddress, // SetQueueAddress\r
23 VirtioMmioSetQueueSel, // SetQueueSel\r
24 VirtioMmioSetQueueNotify, // SetQueueNotify\r
25 VirtioMmioSetQueueAlignment, // SetQueueAlign\r
26 VirtioMmioSetPageSize, // SetPageSize\r
27 VirtioMmioGetQueueSize, // GetQueueNumMax\r
28 VirtioMmioSetQueueSize, // SetQueueNum\r
29 VirtioMmioGetDeviceStatus, // GetDeviceStatus\r
30 VirtioMmioSetDeviceStatus, // SetDeviceStatus\r
31 VirtioMmioDeviceWrite, // WriteDevice\r
084cfc1a
BS
32 VirtioMmioDeviceRead, // ReadDevice\r
33 VirtioMmioAllocateSharedPages, // AllocateSharedPages\r
34 VirtioMmioFreeSharedPages, // FreeSharedPages\r
35 VirtioMmioMapSharedBuffer, // MapSharedBuffer\r
36 VirtioMmioUnmapSharedBuffer // UnmapSharedBuffer\r
6fb4e772
OM
37};\r
38\r
39/**\r
40\r
41 Initialize the VirtIo MMIO Device\r
42\r
43 @param[in] BaseAddress Base Address of the VirtIo MMIO Device\r
44\r
45 @param[in, out] Device The driver instance to configure.\r
46\r
47 @retval EFI_SUCCESS Setup complete.\r
48\r
49 @retval EFI_UNSUPPORTED The driver is not a VirtIo MMIO device.\r
50\r
51**/\r
52STATIC\r
53EFI_STATUS\r
54EFIAPI\r
55VirtioMmioInit (\r
56 IN PHYSICAL_ADDRESS BaseAddress,\r
57 IN OUT VIRTIO_MMIO_DEVICE *Device\r
58 )\r
59{\r
60 UINT32 MagicValue;\r
6fb4e772
OM
61\r
62 //\r
63 // Initialize VirtIo Mmio Device\r
64 //\r
65 CopyMem (&Device->VirtioDevice, &mMmioDeviceProtocolTemplate,\r
66 sizeof (VIRTIO_DEVICE_PROTOCOL));\r
67 Device->BaseAddress = BaseAddress;\r
6fb4e772
OM
68 Device->VirtioDevice.SubSystemDeviceId =\r
69 MmioRead32 (BaseAddress + VIRTIO_MMIO_OFFSET_DEVICE_ID);\r
70\r
71 //\r
72 // Double-check MMIO-specific values\r
73 //\r
74 MagicValue = VIRTIO_CFG_READ (Device, VIRTIO_MMIO_OFFSET_MAGIC);\r
75 if (MagicValue != VIRTIO_MMIO_MAGIC) {\r
76 return EFI_UNSUPPORTED;\r
77 }\r
78\r
08293e43
GH
79 Device->Version = VIRTIO_CFG_READ (Device, VIRTIO_MMIO_OFFSET_VERSION);\r
80 switch (Device->Version) {\r
81 case VIRTIO_MMIO_DEVICE_VERSION_0_95:\r
82 DEBUG ((DEBUG_INFO, "%a virtio 0.9.5, id %d\n", __FUNCTION__,\r
83 Device->VirtioDevice.SubSystemDeviceId));\r
84 Device->VirtioDevice.Revision = VIRTIO_SPEC_REVISION (0, 9, 5);\r
85 break;\r
86 case VIRTIO_MMIO_DEVICE_VERSION_1_00:\r
87 DEBUG ((DEBUG_INFO, "%a virtio 1.0, id %d\n", __FUNCTION__,\r
88 Device->VirtioDevice.SubSystemDeviceId));\r
89 Device->VirtioDevice.Revision = VIRTIO_SPEC_REVISION (1, 0, 0);\r
90 return EFI_UNSUPPORTED;\r
91 default:\r
6fb4e772
OM
92 return EFI_UNSUPPORTED;\r
93 }\r
94\r
6fb4e772
OM
95 return EFI_SUCCESS;\r
96}\r
97\r
98\r
99/**\r
100\r
101 Uninitialize the internals of a virtio-mmio device that has been successfully\r
102 set up with VirtioMmioInit().\r
103\r
104 @param[in, out] Device The device to clean up.\r
105\r
106**/\r
107\r
108STATIC\r
109VOID\r
110EFIAPI\r
111VirtioMmioUninit (\r
112 IN VIRTIO_MMIO_DEVICE *Device\r
113 )\r
114{\r
115 //\r
116 // Note: This function mirrors VirtioMmioInit() that does not allocate any\r
117 // resources - there's nothing to free here.\r
118 //\r
119}\r
120\r
121EFI_STATUS\r
122VirtioMmioInstallDevice (\r
123 IN PHYSICAL_ADDRESS BaseAddress,\r
124 IN EFI_HANDLE Handle\r
125 )\r
126{\r
127 EFI_STATUS Status;\r
128 VIRTIO_MMIO_DEVICE *VirtIo;\r
129\r
130 if (!BaseAddress) {\r
131 return EFI_INVALID_PARAMETER;\r
132 }\r
133 if (Handle == NULL) {\r
134 return EFI_INVALID_PARAMETER;\r
135 }\r
136\r
137 //\r
138 // Allocate VIRTIO_MMIO_DEVICE\r
139 //\r
140 VirtIo = AllocateZeroPool (sizeof (VIRTIO_MMIO_DEVICE));\r
141 if (VirtIo == NULL) {\r
142 return EFI_OUT_OF_RESOURCES;\r
143 }\r
144\r
145 VirtIo->Signature = VIRTIO_MMIO_DEVICE_SIGNATURE;\r
146\r
147 Status = VirtioMmioInit (BaseAddress, VirtIo);\r
148 if (EFI_ERROR (Status)) {\r
149 goto FreeVirtioMem;\r
150 }\r
151\r
152 //\r
153 // Install VIRTIO_DEVICE_PROTOCOL to Handle\r
154 //\r
155 Status = gBS->InstallProtocolInterface (&Handle,\r
156 &gVirtioDeviceProtocolGuid, EFI_NATIVE_INTERFACE,\r
157 &VirtIo->VirtioDevice);\r
158 if (EFI_ERROR (Status)) {\r
159 goto UninitVirtio;\r
160 }\r
161\r
162 return EFI_SUCCESS;\r
163\r
164UninitVirtio:\r
165 VirtioMmioUninit (VirtIo);\r
166\r
167FreeVirtioMem:\r
168 FreePool (VirtIo);\r
169 return Status;\r
170}\r
171\r
172EFI_STATUS\r
173VirtioMmioUninstallDevice (\r
174 IN EFI_HANDLE DeviceHandle\r
175 )\r
176{\r
177 VIRTIO_DEVICE_PROTOCOL *VirtioDevice;\r
178 VIRTIO_MMIO_DEVICE *MmioDevice;\r
179 EFI_STATUS Status;\r
180\r
181 Status = gBS->OpenProtocol (\r
182 DeviceHandle, // candidate device\r
183 &gVirtioDeviceProtocolGuid, // retrieve the VirtIo iface\r
184 (VOID **)&VirtioDevice, // target pointer\r
185 DeviceHandle, // requestor driver identity\r
186 DeviceHandle, // requesting lookup for dev.\r
187 EFI_OPEN_PROTOCOL_GET_PROTOCOL // lookup only, no ref. added\r
188 );\r
189 if (EFI_ERROR (Status)) {\r
190 return Status;\r
191 }\r
192\r
193 //\r
194 // Get the MMIO device from the VirtIo Device instance\r
195 //\r
196 MmioDevice = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (VirtioDevice);\r
197\r
198 //\r
199 // Uninstall the protocol interface\r
200 //\r
201 Status = gBS->UninstallProtocolInterface (DeviceHandle,\r
202 &gVirtioDeviceProtocolGuid, &MmioDevice->VirtioDevice\r
203 );\r
204 if (EFI_ERROR (Status)) {\r
205 return Status;\r
206 }\r
207\r
208 //\r
209 // Uninitialize the VirtIo Device\r
210 //\r
211 VirtioMmioUninit (MmioDevice);\r
212 FreePool (MmioDevice);\r
213\r
214 return EFI_SUCCESS;\r
215}\r