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