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