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