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