]> git.proxmox.com Git - mirror_edk2.git/blame - OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDevice.c
OvmfPkg/VirtioMmioDeviceLib: implement IOMMU-like member functions
[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
OM
7\r
8 This program and the accompanying materials are licensed and made available\r
9 under the terms and conditions of the BSD License which accompanies this\r
10 distribution. The full text of the license may be found at\r
11 http://opensource.org/licenses/bsd-license.php\r
12\r
13 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT\r
14 WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
15\r
16**/\r
17\r
18#include <Library/BaseMemoryLib.h>\r
6fb4e772
OM
19#include <Library/UefiBootServicesTableLib.h>\r
20\r
21#include "VirtioMmioDevice.h"\r
22\r
23static VIRTIO_DEVICE_PROTOCOL mMmioDeviceProtocolTemplate = {\r
24 0, // Revision\r
25 0, // SubSystemDeviceId\r
26 VirtioMmioGetDeviceFeatures, // GetDeviceFeatures\r
27 VirtioMmioSetGuestFeatures, // SetGuestFeatures\r
6fb4e772
OM
28 VirtioMmioSetQueueAddress, // SetQueueAddress\r
29 VirtioMmioSetQueueSel, // SetQueueSel\r
30 VirtioMmioSetQueueNotify, // SetQueueNotify\r
31 VirtioMmioSetQueueAlignment, // SetQueueAlign\r
32 VirtioMmioSetPageSize, // SetPageSize\r
33 VirtioMmioGetQueueSize, // GetQueueNumMax\r
34 VirtioMmioSetQueueSize, // SetQueueNum\r
35 VirtioMmioGetDeviceStatus, // GetDeviceStatus\r
36 VirtioMmioSetDeviceStatus, // SetDeviceStatus\r
37 VirtioMmioDeviceWrite, // WriteDevice\r
084cfc1a
BS
38 VirtioMmioDeviceRead, // ReadDevice\r
39 VirtioMmioAllocateSharedPages, // AllocateSharedPages\r
40 VirtioMmioFreeSharedPages, // FreeSharedPages\r
41 VirtioMmioMapSharedBuffer, // MapSharedBuffer\r
42 VirtioMmioUnmapSharedBuffer // UnmapSharedBuffer\r
6fb4e772
OM
43};\r
44\r
45/**\r
46\r
47 Initialize the VirtIo MMIO Device\r
48\r
49 @param[in] BaseAddress Base Address of the VirtIo MMIO Device\r
50\r
51 @param[in, out] Device The driver instance to configure.\r
52\r
53 @retval EFI_SUCCESS Setup complete.\r
54\r
55 @retval EFI_UNSUPPORTED The driver is not a VirtIo MMIO device.\r
56\r
57**/\r
58STATIC\r
59EFI_STATUS\r
60EFIAPI\r
61VirtioMmioInit (\r
62 IN PHYSICAL_ADDRESS BaseAddress,\r
63 IN OUT VIRTIO_MMIO_DEVICE *Device\r
64 )\r
65{\r
66 UINT32 MagicValue;\r
67 UINT32 VendorId;\r
68 UINT32 Version;\r
69\r
70 //\r
71 // Initialize VirtIo Mmio Device\r
72 //\r
73 CopyMem (&Device->VirtioDevice, &mMmioDeviceProtocolTemplate,\r
74 sizeof (VIRTIO_DEVICE_PROTOCOL));\r
75 Device->BaseAddress = BaseAddress;\r
76 Device->VirtioDevice.Revision = VIRTIO_SPEC_REVISION (0, 9, 5);\r
77 Device->VirtioDevice.SubSystemDeviceId =\r
78 MmioRead32 (BaseAddress + VIRTIO_MMIO_OFFSET_DEVICE_ID);\r
79\r
80 //\r
81 // Double-check MMIO-specific values\r
82 //\r
83 MagicValue = VIRTIO_CFG_READ (Device, VIRTIO_MMIO_OFFSET_MAGIC);\r
84 if (MagicValue != VIRTIO_MMIO_MAGIC) {\r
85 return EFI_UNSUPPORTED;\r
86 }\r
87\r
88 Version = VIRTIO_CFG_READ (Device, VIRTIO_MMIO_OFFSET_VERSION);\r
89 if (Version != 1) {\r
90 return EFI_UNSUPPORTED;\r
91 }\r
92\r
93 //\r
94 // Double-check MMIO-specific values\r
95 //\r
96 VendorId = VIRTIO_CFG_READ (Device, VIRTIO_MMIO_OFFSET_VENDOR_ID);\r
97 if (VendorId != VIRTIO_VENDOR_ID) {\r
98 //\r
99 // The ARM Base and Foundation Models do not report a valid VirtIo VendorId.\r
100 // They return a value of 0x0 for the VendorId.\r
101 //\r
102 DEBUG((EFI_D_WARN, "VirtioMmioInit: Warning: The VendorId (0x%X) does not "\r
103 "match the VirtIo VendorId (0x%X).\n",\r
104 VendorId, VIRTIO_VENDOR_ID));\r
105 }\r
106\r
107 return EFI_SUCCESS;\r
108}\r
109\r
110\r
111/**\r
112\r
113 Uninitialize the internals of a virtio-mmio device that has been successfully\r
114 set up with VirtioMmioInit().\r
115\r
116 @param[in, out] Device The device to clean up.\r
117\r
118**/\r
119\r
120STATIC\r
121VOID\r
122EFIAPI\r
123VirtioMmioUninit (\r
124 IN VIRTIO_MMIO_DEVICE *Device\r
125 )\r
126{\r
127 //\r
128 // Note: This function mirrors VirtioMmioInit() that does not allocate any\r
129 // resources - there's nothing to free here.\r
130 //\r
131}\r
132\r
133EFI_STATUS\r
134VirtioMmioInstallDevice (\r
135 IN PHYSICAL_ADDRESS BaseAddress,\r
136 IN EFI_HANDLE Handle\r
137 )\r
138{\r
139 EFI_STATUS Status;\r
140 VIRTIO_MMIO_DEVICE *VirtIo;\r
141\r
142 if (!BaseAddress) {\r
143 return EFI_INVALID_PARAMETER;\r
144 }\r
145 if (Handle == NULL) {\r
146 return EFI_INVALID_PARAMETER;\r
147 }\r
148\r
149 //\r
150 // Allocate VIRTIO_MMIO_DEVICE\r
151 //\r
152 VirtIo = AllocateZeroPool (sizeof (VIRTIO_MMIO_DEVICE));\r
153 if (VirtIo == NULL) {\r
154 return EFI_OUT_OF_RESOURCES;\r
155 }\r
156\r
157 VirtIo->Signature = VIRTIO_MMIO_DEVICE_SIGNATURE;\r
158\r
159 Status = VirtioMmioInit (BaseAddress, VirtIo);\r
160 if (EFI_ERROR (Status)) {\r
161 goto FreeVirtioMem;\r
162 }\r
163\r
164 //\r
165 // Install VIRTIO_DEVICE_PROTOCOL to Handle\r
166 //\r
167 Status = gBS->InstallProtocolInterface (&Handle,\r
168 &gVirtioDeviceProtocolGuid, EFI_NATIVE_INTERFACE,\r
169 &VirtIo->VirtioDevice);\r
170 if (EFI_ERROR (Status)) {\r
171 goto UninitVirtio;\r
172 }\r
173\r
174 return EFI_SUCCESS;\r
175\r
176UninitVirtio:\r
177 VirtioMmioUninit (VirtIo);\r
178\r
179FreeVirtioMem:\r
180 FreePool (VirtIo);\r
181 return Status;\r
182}\r
183\r
184EFI_STATUS\r
185VirtioMmioUninstallDevice (\r
186 IN EFI_HANDLE DeviceHandle\r
187 )\r
188{\r
189 VIRTIO_DEVICE_PROTOCOL *VirtioDevice;\r
190 VIRTIO_MMIO_DEVICE *MmioDevice;\r
191 EFI_STATUS Status;\r
192\r
193 Status = gBS->OpenProtocol (\r
194 DeviceHandle, // candidate device\r
195 &gVirtioDeviceProtocolGuid, // retrieve the VirtIo iface\r
196 (VOID **)&VirtioDevice, // target pointer\r
197 DeviceHandle, // requestor driver identity\r
198 DeviceHandle, // requesting lookup for dev.\r
199 EFI_OPEN_PROTOCOL_GET_PROTOCOL // lookup only, no ref. added\r
200 );\r
201 if (EFI_ERROR (Status)) {\r
202 return Status;\r
203 }\r
204\r
205 //\r
206 // Get the MMIO device from the VirtIo Device instance\r
207 //\r
208 MmioDevice = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (VirtioDevice);\r
209\r
210 //\r
211 // Uninstall the protocol interface\r
212 //\r
213 Status = gBS->UninstallProtocolInterface (DeviceHandle,\r
214 &gVirtioDeviceProtocolGuid, &MmioDevice->VirtioDevice\r
215 );\r
216 if (EFI_ERROR (Status)) {\r
217 return Status;\r
218 }\r
219\r
220 //\r
221 // Uninitialize the VirtIo Device\r
222 //\r
223 VirtioMmioUninit (MmioDevice);\r
224 FreePool (MmioDevice);\r
225\r
226 return EFI_SUCCESS;\r
227}\r