]> git.proxmox.com Git - mirror_edk2.git/blame - OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDevice.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[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
ac0a286f
MK
17STATIC CONST VIRTIO_DEVICE_PROTOCOL mMmioDeviceProtocolTemplate = {\r
18 0, // Revision\r
19 0, // SubSystemDeviceId\r
20 VirtioMmioGetDeviceFeatures, // GetDeviceFeatures\r
21 VirtioMmioSetGuestFeatures, // SetGuestFeatures\r
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
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
ac0a286f 57 IN OUT VIRTIO_MMIO_DEVICE *Device\r
6fb4e772
OM
58 )\r
59{\r
ac0a286f 60 UINT32 MagicValue;\r
6fb4e772
OM
61\r
62 //\r
63 // Initialize VirtIo Mmio Device\r
64 //\r
ac0a286f
MK
65 CopyMem (\r
66 &Device->VirtioDevice,\r
67 &mMmioDeviceProtocolTemplate,\r
68 sizeof (VIRTIO_DEVICE_PROTOCOL)\r
69 );\r
70 Device->BaseAddress = BaseAddress;\r
6fb4e772 71 Device->VirtioDevice.SubSystemDeviceId =\r
ac0a286f 72 MmioRead32 (BaseAddress + VIRTIO_MMIO_OFFSET_DEVICE_ID);\r
6fb4e772
OM
73\r
74 //\r
75 // Double-check MMIO-specific values\r
76 //\r
77 MagicValue = VIRTIO_CFG_READ (Device, VIRTIO_MMIO_OFFSET_MAGIC);\r
78 if (MagicValue != VIRTIO_MMIO_MAGIC) {\r
79 return EFI_UNSUPPORTED;\r
80 }\r
81\r
08293e43
GH
82 Device->Version = VIRTIO_CFG_READ (Device, VIRTIO_MMIO_OFFSET_VERSION);\r
83 switch (Device->Version) {\r
ac0a286f
MK
84 case VIRTIO_MMIO_DEVICE_VERSION_0_95:\r
85 DEBUG ((\r
86 DEBUG_INFO,\r
87 "%a virtio 0.9.5, id %d\n",\r
88 __FUNCTION__,\r
89 Device->VirtioDevice.SubSystemDeviceId\r
90 ));\r
91 Device->VirtioDevice.Revision = VIRTIO_SPEC_REVISION (0, 9, 5);\r
92 break;\r
93 case VIRTIO_MMIO_DEVICE_VERSION_1_00:\r
94 DEBUG ((\r
95 DEBUG_INFO,\r
96 "%a virtio 1.0, id %d\n",\r
97 __FUNCTION__,\r
98 Device->VirtioDevice.SubSystemDeviceId\r
99 ));\r
100 Device->VirtioDevice.Revision = VIRTIO_SPEC_REVISION (1, 0, 0);\r
101 break;\r
102 default:\r
103 return EFI_UNSUPPORTED;\r
6fb4e772
OM
104 }\r
105\r
6fb4e772
OM
106 return EFI_SUCCESS;\r
107}\r
108\r
6fb4e772
OM
109/**\r
110\r
111 Uninitialize the internals of a virtio-mmio device that has been successfully\r
112 set up with VirtioMmioInit().\r
113\r
114 @param[in, out] Device The device to clean up.\r
115\r
116**/\r
6fb4e772
OM
117STATIC\r
118VOID\r
119EFIAPI\r
120VirtioMmioUninit (\r
ac0a286f 121 IN VIRTIO_MMIO_DEVICE *Device\r
6fb4e772
OM
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
ac0a286f
MK
132 IN PHYSICAL_ADDRESS BaseAddress,\r
133 IN EFI_HANDLE Handle\r
6fb4e772
OM
134 )\r
135{\r
136 EFI_STATUS Status;\r
ac0a286f 137 VIRTIO_MMIO_DEVICE *VirtIo;\r
6fb4e772
OM
138\r
139 if (!BaseAddress) {\r
140 return EFI_INVALID_PARAMETER;\r
141 }\r
ac0a286f 142\r
6fb4e772
OM
143 if (Handle == NULL) {\r
144 return EFI_INVALID_PARAMETER;\r
145 }\r
146\r
147 //\r
148 // Allocate VIRTIO_MMIO_DEVICE\r
149 //\r
150 VirtIo = AllocateZeroPool (sizeof (VIRTIO_MMIO_DEVICE));\r
151 if (VirtIo == NULL) {\r
152 return EFI_OUT_OF_RESOURCES;\r
153 }\r
154\r
155 VirtIo->Signature = VIRTIO_MMIO_DEVICE_SIGNATURE;\r
156\r
157 Status = VirtioMmioInit (BaseAddress, VirtIo);\r
158 if (EFI_ERROR (Status)) {\r
159 goto FreeVirtioMem;\r
160 }\r
161\r
162 //\r
163 // Install VIRTIO_DEVICE_PROTOCOL to Handle\r
164 //\r
ac0a286f
MK
165 Status = gBS->InstallProtocolInterface (\r
166 &Handle,\r
167 &gVirtioDeviceProtocolGuid,\r
168 EFI_NATIVE_INTERFACE,\r
169 &VirtIo->VirtioDevice\r
170 );\r
6fb4e772
OM
171 if (EFI_ERROR (Status)) {\r
172 goto UninitVirtio;\r
173 }\r
174\r
175 return EFI_SUCCESS;\r
176\r
177UninitVirtio:\r
178 VirtioMmioUninit (VirtIo);\r
179\r
180FreeVirtioMem:\r
181 FreePool (VirtIo);\r
182 return Status;\r
183}\r
184\r
185EFI_STATUS\r
186VirtioMmioUninstallDevice (\r
ac0a286f 187 IN EFI_HANDLE DeviceHandle\r
6fb4e772
OM
188 )\r
189{\r
190 VIRTIO_DEVICE_PROTOCOL *VirtioDevice;\r
191 VIRTIO_MMIO_DEVICE *MmioDevice;\r
192 EFI_STATUS Status;\r
193\r
194 Status = gBS->OpenProtocol (\r
195 DeviceHandle, // candidate device\r
196 &gVirtioDeviceProtocolGuid, // retrieve the VirtIo iface\r
197 (VOID **)&VirtioDevice, // target pointer\r
198 DeviceHandle, // requestor driver identity\r
199 DeviceHandle, // requesting lookup for dev.\r
200 EFI_OPEN_PROTOCOL_GET_PROTOCOL // lookup only, no ref. added\r
201 );\r
202 if (EFI_ERROR (Status)) {\r
203 return Status;\r
204 }\r
205\r
206 //\r
207 // Get the MMIO device from the VirtIo Device instance\r
208 //\r
209 MmioDevice = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (VirtioDevice);\r
210\r
211 //\r
212 // Uninstall the protocol interface\r
213 //\r
ac0a286f
MK
214 Status = gBS->UninstallProtocolInterface (\r
215 DeviceHandle,\r
216 &gVirtioDeviceProtocolGuid,\r
217 &MmioDevice->VirtioDevice\r
218 );\r
6fb4e772
OM
219 if (EFI_ERROR (Status)) {\r
220 return Status;\r
221 }\r
222\r
223 //\r
224 // Uninitialize the VirtIo Device\r
225 //\r
226 VirtioMmioUninit (MmioDevice);\r
227 FreePool (MmioDevice);\r
228\r
229 return EFI_SUCCESS;\r
230}\r