]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDevice.c
OvmfPkg: Replace BSD License with BSD+Patent License
[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 UINT32 VendorId;
62 UINT32 Version;
63
64 //
65 // Initialize VirtIo Mmio Device
66 //
67 CopyMem (&Device->VirtioDevice, &mMmioDeviceProtocolTemplate,
68 sizeof (VIRTIO_DEVICE_PROTOCOL));
69 Device->BaseAddress = BaseAddress;
70 Device->VirtioDevice.Revision = VIRTIO_SPEC_REVISION (0, 9, 5);
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 Version = VIRTIO_CFG_READ (Device, VIRTIO_MMIO_OFFSET_VERSION);
83 if (Version != 1) {
84 return EFI_UNSUPPORTED;
85 }
86
87 //
88 // Double-check MMIO-specific values
89 //
90 VendorId = VIRTIO_CFG_READ (Device, VIRTIO_MMIO_OFFSET_VENDOR_ID);
91 if (VendorId != VIRTIO_VENDOR_ID) {
92 //
93 // The ARM Base and Foundation Models do not report a valid VirtIo VendorId.
94 // They return a value of 0x0 for the VendorId.
95 //
96 DEBUG((EFI_D_WARN, "VirtioMmioInit: Warning: The VendorId (0x%X) does not "
97 "match the VirtIo VendorId (0x%X).\n",
98 VendorId, VIRTIO_VENDOR_ID));
99 }
100
101 return EFI_SUCCESS;
102 }
103
104
105 /**
106
107 Uninitialize the internals of a virtio-mmio device that has been successfully
108 set up with VirtioMmioInit().
109
110 @param[in, out] Device The device to clean up.
111
112 **/
113
114 STATIC
115 VOID
116 EFIAPI
117 VirtioMmioUninit (
118 IN VIRTIO_MMIO_DEVICE *Device
119 )
120 {
121 //
122 // Note: This function mirrors VirtioMmioInit() that does not allocate any
123 // resources - there's nothing to free here.
124 //
125 }
126
127 EFI_STATUS
128 VirtioMmioInstallDevice (
129 IN PHYSICAL_ADDRESS BaseAddress,
130 IN EFI_HANDLE Handle
131 )
132 {
133 EFI_STATUS Status;
134 VIRTIO_MMIO_DEVICE *VirtIo;
135
136 if (!BaseAddress) {
137 return EFI_INVALID_PARAMETER;
138 }
139 if (Handle == NULL) {
140 return EFI_INVALID_PARAMETER;
141 }
142
143 //
144 // Allocate VIRTIO_MMIO_DEVICE
145 //
146 VirtIo = AllocateZeroPool (sizeof (VIRTIO_MMIO_DEVICE));
147 if (VirtIo == NULL) {
148 return EFI_OUT_OF_RESOURCES;
149 }
150
151 VirtIo->Signature = VIRTIO_MMIO_DEVICE_SIGNATURE;
152
153 Status = VirtioMmioInit (BaseAddress, VirtIo);
154 if (EFI_ERROR (Status)) {
155 goto FreeVirtioMem;
156 }
157
158 //
159 // Install VIRTIO_DEVICE_PROTOCOL to Handle
160 //
161 Status = gBS->InstallProtocolInterface (&Handle,
162 &gVirtioDeviceProtocolGuid, EFI_NATIVE_INTERFACE,
163 &VirtIo->VirtioDevice);
164 if (EFI_ERROR (Status)) {
165 goto UninitVirtio;
166 }
167
168 return EFI_SUCCESS;
169
170 UninitVirtio:
171 VirtioMmioUninit (VirtIo);
172
173 FreeVirtioMem:
174 FreePool (VirtIo);
175 return Status;
176 }
177
178 EFI_STATUS
179 VirtioMmioUninstallDevice (
180 IN EFI_HANDLE DeviceHandle
181 )
182 {
183 VIRTIO_DEVICE_PROTOCOL *VirtioDevice;
184 VIRTIO_MMIO_DEVICE *MmioDevice;
185 EFI_STATUS Status;
186
187 Status = gBS->OpenProtocol (
188 DeviceHandle, // candidate device
189 &gVirtioDeviceProtocolGuid, // retrieve the VirtIo iface
190 (VOID **)&VirtioDevice, // target pointer
191 DeviceHandle, // requestor driver identity
192 DeviceHandle, // requesting lookup for dev.
193 EFI_OPEN_PROTOCOL_GET_PROTOCOL // lookup only, no ref. added
194 );
195 if (EFI_ERROR (Status)) {
196 return Status;
197 }
198
199 //
200 // Get the MMIO device from the VirtIo Device instance
201 //
202 MmioDevice = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (VirtioDevice);
203
204 //
205 // Uninstall the protocol interface
206 //
207 Status = gBS->UninstallProtocolInterface (DeviceHandle,
208 &gVirtioDeviceProtocolGuid, &MmioDevice->VirtioDevice
209 );
210 if (EFI_ERROR (Status)) {
211 return Status;
212 }
213
214 //
215 // Uninitialize the VirtIo Device
216 //
217 VirtioMmioUninit (MmioDevice);
218 FreePool (MmioDevice);
219
220 return EFI_SUCCESS;
221 }