]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/PvScsiDxe/PvScsi.c
OvmfPkg/PvScsiDxe: Install stubbed EXT_SCSI_PASS_THRU
[mirror_edk2.git] / OvmfPkg / PvScsiDxe / PvScsi.c
1 /** @file
2
3 This driver produces Extended SCSI Pass Thru Protocol instances for
4 pvscsi devices.
5
6 Copyright (C) 2020, Oracle and/or its affiliates.
7
8 SPDX-License-Identifier: BSD-2-Clause-Patent
9
10 **/
11
12 #include <IndustryStandard/Pci.h>
13 #include <IndustryStandard/PvScsi.h>
14 #include <Library/MemoryAllocationLib.h>
15 #include <Library/UefiBootServicesTableLib.h>
16 #include <Library/UefiLib.h>
17 #include <Protocol/PciIo.h>
18 #include <Uefi/UefiSpec.h>
19
20 #include "PvScsi.h"
21
22 //
23 // Higher versions will be used before lower, 0x10-0xffffffef is the version
24 // range for IHV (Indie Hardware Vendors)
25 //
26 #define PVSCSI_BINDING_VERSION 0x10
27
28 //
29 // Ext SCSI Pass Thru
30 //
31
32 STATIC
33 EFI_STATUS
34 EFIAPI
35 PvScsiPassThru (
36 IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,
37 IN UINT8 *Target,
38 IN UINT64 Lun,
39 IN OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet,
40 IN EFI_EVENT Event OPTIONAL
41 )
42 {
43 return EFI_UNSUPPORTED;
44 }
45
46 STATIC
47 EFI_STATUS
48 EFIAPI
49 PvScsiGetNextTargetLun (
50 IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,
51 IN OUT UINT8 **Target,
52 IN OUT UINT64 *Lun
53 )
54 {
55 return EFI_UNSUPPORTED;
56 }
57
58 STATIC
59 EFI_STATUS
60 EFIAPI
61 PvScsiBuildDevicePath (
62 IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,
63 IN UINT8 *Target,
64 IN UINT64 Lun,
65 IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath
66 )
67 {
68 return EFI_UNSUPPORTED;
69 }
70
71 STATIC
72 EFI_STATUS
73 EFIAPI
74 PvScsiGetTargetLun (
75 IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,
76 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
77 OUT UINT8 **Target,
78 OUT UINT64 *Lun
79 )
80 {
81 return EFI_UNSUPPORTED;
82 }
83
84 STATIC
85 EFI_STATUS
86 EFIAPI
87 PvScsiResetChannel (
88 IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This
89 )
90 {
91 return EFI_UNSUPPORTED;
92 }
93
94 STATIC
95 EFI_STATUS
96 EFIAPI
97 PvScsiResetTargetLun (
98 IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,
99 IN UINT8 *Target,
100 IN UINT64 Lun
101 )
102 {
103 return EFI_UNSUPPORTED;
104 }
105
106 STATIC
107 EFI_STATUS
108 EFIAPI
109 PvScsiGetNextTarget (
110 IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,
111 IN OUT UINT8 **Target
112 )
113 {
114 return EFI_UNSUPPORTED;
115 }
116
117 STATIC
118 EFI_STATUS
119 PvScsiInit (
120 IN OUT PVSCSI_DEV *Dev
121 )
122 {
123 //
124 // Populate the exported interface's attributes
125 //
126 Dev->PassThru.Mode = &Dev->PassThruMode;
127 Dev->PassThru.PassThru = &PvScsiPassThru;
128 Dev->PassThru.GetNextTargetLun = &PvScsiGetNextTargetLun;
129 Dev->PassThru.BuildDevicePath = &PvScsiBuildDevicePath;
130 Dev->PassThru.GetTargetLun = &PvScsiGetTargetLun;
131 Dev->PassThru.ResetChannel = &PvScsiResetChannel;
132 Dev->PassThru.ResetTargetLun = &PvScsiResetTargetLun;
133 Dev->PassThru.GetNextTarget = &PvScsiGetNextTarget;
134
135 //
136 // AdapterId is a target for which no handle will be created during bus scan.
137 // Prevent any conflict with real devices.
138 //
139 Dev->PassThruMode.AdapterId = MAX_UINT32;
140
141 //
142 // Set both physical and logical attributes for non-RAID SCSI channel
143 //
144 Dev->PassThruMode.Attributes = EFI_EXT_SCSI_PASS_THRU_ATTRIBUTES_PHYSICAL |
145 EFI_EXT_SCSI_PASS_THRU_ATTRIBUTES_LOGICAL;
146
147 //
148 // No restriction on transfer buffer alignment
149 //
150 Dev->PassThruMode.IoAlign = 0;
151
152 return EFI_SUCCESS;
153 }
154
155 STATIC
156 VOID
157 PvScsiUninit (
158 IN OUT PVSCSI_DEV *Dev
159 )
160 {
161 // Currently nothing to do here
162 }
163
164 //
165 // Driver Binding
166 //
167
168 STATIC
169 EFI_STATUS
170 EFIAPI
171 PvScsiDriverBindingSupported (
172 IN EFI_DRIVER_BINDING_PROTOCOL *This,
173 IN EFI_HANDLE ControllerHandle,
174 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
175 )
176 {
177 EFI_STATUS Status;
178 EFI_PCI_IO_PROTOCOL *PciIo;
179 PCI_TYPE00 Pci;
180
181 Status = gBS->OpenProtocol (
182 ControllerHandle,
183 &gEfiPciIoProtocolGuid,
184 (VOID **)&PciIo,
185 This->DriverBindingHandle,
186 ControllerHandle,
187 EFI_OPEN_PROTOCOL_BY_DRIVER
188 );
189 if (EFI_ERROR (Status)) {
190 return Status;
191 }
192
193 Status = PciIo->Pci.Read (
194 PciIo,
195 EfiPciIoWidthUint32,
196 0,
197 sizeof (Pci) / sizeof (UINT32),
198 &Pci
199 );
200 if (EFI_ERROR (Status)) {
201 goto Done;
202 }
203
204 if ((Pci.Hdr.VendorId != PCI_VENDOR_ID_VMWARE) ||
205 (Pci.Hdr.DeviceId != PCI_DEVICE_ID_VMWARE_PVSCSI)) {
206 Status = EFI_UNSUPPORTED;
207 goto Done;
208 }
209
210 Status = EFI_SUCCESS;
211
212 Done:
213 gBS->CloseProtocol (
214 ControllerHandle,
215 &gEfiPciIoProtocolGuid,
216 This->DriverBindingHandle,
217 ControllerHandle
218 );
219
220 return Status;
221 }
222
223 STATIC
224 EFI_STATUS
225 EFIAPI
226 PvScsiDriverBindingStart (
227 IN EFI_DRIVER_BINDING_PROTOCOL *This,
228 IN EFI_HANDLE ControllerHandle,
229 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
230 )
231 {
232 PVSCSI_DEV *Dev;
233 EFI_STATUS Status;
234
235 Dev = (PVSCSI_DEV *) AllocateZeroPool (sizeof (*Dev));
236 if (Dev == NULL) {
237 return EFI_OUT_OF_RESOURCES;
238 }
239
240 Status = PvScsiInit (Dev);
241 if (EFI_ERROR (Status)) {
242 goto FreePvScsi;
243 }
244
245 //
246 // Setup complete, attempt to export the driver instance's PassThru interface
247 //
248 Dev->Signature = PVSCSI_SIG;
249 Status = gBS->InstallProtocolInterface (
250 &ControllerHandle,
251 &gEfiExtScsiPassThruProtocolGuid,
252 EFI_NATIVE_INTERFACE,
253 &Dev->PassThru
254 );
255 if (EFI_ERROR (Status)) {
256 goto UninitDev;
257 }
258
259 return EFI_SUCCESS;
260
261 UninitDev:
262 PvScsiUninit (Dev);
263
264 FreePvScsi:
265 FreePool (Dev);
266
267 return Status;
268 }
269
270 STATIC
271 EFI_STATUS
272 EFIAPI
273 PvScsiDriverBindingStop (
274 IN EFI_DRIVER_BINDING_PROTOCOL *This,
275 IN EFI_HANDLE ControllerHandle,
276 IN UINTN NumberOfChildren,
277 IN EFI_HANDLE *ChildHandleBuffer
278 )
279 {
280 EFI_STATUS Status;
281 EFI_EXT_SCSI_PASS_THRU_PROTOCOL *PassThru;
282 PVSCSI_DEV *Dev;
283
284 Status = gBS->OpenProtocol (
285 ControllerHandle,
286 &gEfiExtScsiPassThruProtocolGuid,
287 (VOID **)&PassThru,
288 This->DriverBindingHandle,
289 ControllerHandle,
290 EFI_OPEN_PROTOCOL_GET_PROTOCOL // Lookup only
291 );
292 if (EFI_ERROR (Status)) {
293 return Status;
294 }
295
296 Dev = PVSCSI_FROM_PASS_THRU (PassThru);
297
298 Status = gBS->UninstallProtocolInterface (
299 ControllerHandle,
300 &gEfiExtScsiPassThruProtocolGuid,
301 &Dev->PassThru
302 );
303 if (EFI_ERROR (Status)) {
304 return Status;
305 }
306
307 PvScsiUninit (Dev);
308
309 FreePool (Dev);
310
311 return EFI_SUCCESS;
312 }
313
314 STATIC EFI_DRIVER_BINDING_PROTOCOL mPvScsiDriverBinding = {
315 &PvScsiDriverBindingSupported,
316 &PvScsiDriverBindingStart,
317 &PvScsiDriverBindingStop,
318 PVSCSI_BINDING_VERSION,
319 NULL, // ImageHandle, filled by EfiLibInstallDriverBindingComponentName2()
320 NULL // DriverBindingHandle, filled as well
321 };
322
323 //
324 // Component Name
325 //
326
327 STATIC EFI_UNICODE_STRING_TABLE mDriverNameTable[] = {
328 { "eng;en", L"PVSCSI Host Driver" },
329 { NULL, NULL }
330 };
331
332 STATIC EFI_COMPONENT_NAME_PROTOCOL mComponentName;
333
334 STATIC
335 EFI_STATUS
336 EFIAPI
337 PvScsiGetDriverName (
338 IN EFI_COMPONENT_NAME_PROTOCOL *This,
339 IN CHAR8 *Language,
340 OUT CHAR16 **DriverName
341 )
342 {
343 return LookupUnicodeString2 (
344 Language,
345 This->SupportedLanguages,
346 mDriverNameTable,
347 DriverName,
348 (BOOLEAN)(This == &mComponentName) // Iso639Language
349 );
350 }
351
352 STATIC
353 EFI_STATUS
354 EFIAPI
355 PvScsiGetDeviceName (
356 IN EFI_COMPONENT_NAME_PROTOCOL *This,
357 IN EFI_HANDLE DeviceHandle,
358 IN EFI_HANDLE ChildHandle,
359 IN CHAR8 *Language,
360 OUT CHAR16 **ControllerName
361 )
362 {
363 return EFI_UNSUPPORTED;
364 }
365
366 STATIC EFI_COMPONENT_NAME_PROTOCOL mComponentName = {
367 &PvScsiGetDriverName,
368 &PvScsiGetDeviceName,
369 "eng" // SupportedLanguages, ISO 639-2 language codes
370 };
371
372 STATIC EFI_COMPONENT_NAME2_PROTOCOL mComponentName2 = {
373 (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) &PvScsiGetDriverName,
374 (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) &PvScsiGetDeviceName,
375 "en" // SupportedLanguages, RFC 4646 language codes
376 };
377
378 //
379 // Entry Point
380 //
381
382 EFI_STATUS
383 EFIAPI
384 PvScsiEntryPoint (
385 IN EFI_HANDLE ImageHandle,
386 IN EFI_SYSTEM_TABLE *SystemTable
387 )
388 {
389 return EfiLibInstallDriverBindingComponentName2 (
390 ImageHandle,
391 SystemTable,
392 &mPvScsiDriverBinding,
393 ImageHandle,
394 &mComponentName,
395 &mComponentName2
396 );
397 }