2 Platform VTd Sample driver.
4 Note: This module should only be used for dev/debug purposes.
5 It MUST never be used for production builds.
7 Copyright (c) 2017 - 2018, Intel Corporation. All rights reserved.<BR>
8 SPDX-License-Identifier: BSD-2-Clause-Patent
14 #include <IndustryStandard/Vtd.h>
15 #include <Protocol/PlatformVtdPolicy.h>
16 #include <Protocol/PciIo.h>
17 #include <Protocol/DevicePath.h>
19 #include <Library/IoLib.h>
20 #include <Library/BaseLib.h>
21 #include <Library/BaseMemoryLib.h>
22 #include <Library/MemoryAllocationLib.h>
23 #include <Library/DebugLib.h>
24 #include <Library/UefiBootServicesTableLib.h>
25 #include <Library/DevicePathLib.h>
27 #include <IndustryStandard/DmaRemappingReportingTable.h>
30 ACPI_EXTENDED_HID_DEVICE_PATH I2cController
;
34 } PLATFORM_I2C_CONTROLLER_DEVICE_PATH
;
37 ACPI_EXTENDED_HID_DEVICE_PATH I2cDevice
;
41 } PLATFORM_I2C_DEVICE_DEVICE_PATH
;
44 PLATFORM_I2C_CONTROLLER_DEVICE_PATH I2cController
;
45 PLATFORM_I2C_DEVICE_DEVICE_PATH I2cDevice
;
46 EFI_DEVICE_PATH_PROTOCOL End
;
47 } PLATFORM_I2C_DEVICE_PATH
;
50 ACPI_HID_DEVICE_PATH PciRootBridge
;
51 PCI_DEVICE_PATH PciDevice
;
52 EFI_DEVICE_PATH_PROTOCOL EndDevicePath
;
53 } PLATFORM_PCI_DEVICE_PATH
;
56 ACPI_HID_DEVICE_PATH PciRootBridge
;
57 PCI_DEVICE_PATH PciBridge
;
58 PCI_DEVICE_PATH PciDevice
;
59 EFI_DEVICE_PATH_PROTOCOL EndDevicePath
;
60 } PLATFORM_PCI_BRIDGE_DEVICE_PATH
;
63 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
65 VTD_SOURCE_ID SourceId
;
66 } PLATFORM_ACPI_DEVICE_MAPPING
;
68 #define PLATFORM_PCI_ROOT_BRIDGE \
74 (UINT8) (sizeof (ACPI_HID_DEVICE_PATH)), \
75 (UINT8) ((sizeof (ACPI_HID_DEVICE_PATH)) >> 8) \
78 EISA_PNP_ID (0x0A03), \
82 #define PLATFORM_END_ENTIRE \
84 END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, { END_DEVICE_PATH_LENGTH, 0 } \
87 #define PLATFORM_PCI(Device, Function) \
90 HARDWARE_DEVICE_PATH, \
93 (UINT8) (sizeof (PCI_DEVICE_PATH)), \
94 (UINT8) ((sizeof (PCI_DEVICE_PATH)) >> 8) \
101 #define PLATFORM_I2C(Hid, Uid, Cid, HidStr, UidStr, CidStr) \
107 {sizeof(ACPI_EXTENDED_HID_DEVICE_PATH) + sizeof(HidStr) + sizeof(UidStr) + sizeof(CidStr), 0} \
118 PLATFORM_I2C_DEVICE_PATH mPlatformI2CDevicePath
= {
119 PLATFORM_I2C(0, 2, 0, "INT33C3", "", "INT33C3"),
120 PLATFORM_I2C(0, 1, 0, "I2C01\\TPANEL", "", "I2C01\\TPANEL"),
124 PLATFORM_ACPI_DEVICE_MAPPING mAcpiDeviceMapping
[] = {
126 (EFI_DEVICE_PATH_PROTOCOL
*)&mPlatformI2CDevicePath
,
128 {{0x01, 0x15, 0x00}} // Function, Device, Bus
132 PLATFORM_PCI_BRIDGE_DEVICE_PATH mPlatformPciBridgeDevicePath
= {
133 PLATFORM_PCI_ROOT_BRIDGE
,
134 PLATFORM_PCI(0x1C, 1),
142 EDKII_PLATFORM_VTD_EXCEPTION_DEVICE_INFO ExceptionDeviceInfo
;
143 EDKII_PLATFORM_VTD_DEVICE_SCOPE DeviceScope
;
144 EFI_ACPI_DMAR_PCI_PATH PciBridge
;
145 EFI_ACPI_DMAR_PCI_PATH PciDevice
;
146 } PLATFORM_EXCEPTION_DEVICE_SCOPE_STRUCT
;
149 EDKII_PLATFORM_VTD_EXCEPTION_DEVICE_INFO ExceptionDeviceInfo
;
150 EDKII_PLATFORM_VTD_PCI_DEVICE_ID PciDeviceId
;
151 } PLATFORM_EXCEPTION_PCI_DEVICE_ID_STRUCT
;
155 PLATFORM_EXCEPTION_DEVICE_SCOPE_STRUCT mExceptionDeviceScopeList
[] = {
158 EDKII_PLATFORM_VTD_EXCEPTION_DEVICE_INFO_TYPE_DEVICE_SCOPE
,
159 sizeof(PLATFORM_EXCEPTION_DEVICE_SCOPE_STRUCT
)
160 }, // ExceptionDeviceInfo
164 EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT
, // Type
165 sizeof(EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER
) +
166 2 * sizeof(EFI_ACPI_DMAR_PCI_PATH
), // Length
172 { 0x1C, 1 }, // PciBridge
173 { 0x0, 0 }, // PciDevice
177 PLATFORM_EXCEPTION_PCI_DEVICE_ID_STRUCT mExceptionPciDeviceIdList
[] = {
180 EDKII_PLATFORM_VTD_EXCEPTION_DEVICE_INFO_TYPE_PCI_DEVICE_ID
,
181 sizeof(PLATFORM_EXCEPTION_PCI_DEVICE_ID_STRUCT
)
182 }, // ExceptionDeviceInfo
187 0x8086, // SubsystemVendorId
188 0x7270, // SubsystemDeviceId
194 Compares 2 device path.
196 @param[in] DevicePath1 A device path with EndDevicePath node.
197 @param[in] DevicePath2 A device path with EndDevicePath node.
199 @retval TRUE 2 device path are identical.
200 @retval FALSE 2 device path are not identical.
204 IN CONST EFI_DEVICE_PATH_PROTOCOL
*DevicePath1
,
205 IN CONST EFI_DEVICE_PATH_PROTOCOL
*DevicePath2
211 Size1
= GetDevicePathSize (DevicePath1
);
212 Size2
= GetDevicePathSize (DevicePath2
);
213 if (Size1
!= Size2
) {
216 if (CompareMem (DevicePath1
, DevicePath2
, Size1
) != 0) {
223 Get the VTD SourceId from the device handler.
224 This function is required for non PCI device handler.
226 Pseudo-algo in Intel VTd driver:
227 Status = PlatformGetVTdDeviceId ();
228 if (EFI_ERROR(Status)) {
229 if (DeviceHandle is PCI) {
230 Get SourceId from Bus/Device/Function
232 return EFI_UNSUPPORTED
235 Get VTd engine by Segment/Bus/Device/Function.
237 @param[in] This The protocol instance pointer.
238 @param[in] DeviceHandle Device Identifier in UEFI.
239 @param[out] DeviceInfo DeviceInfo for indentify the VTd engine in ACPI Table
240 and the VTd page entry.
242 @retval EFI_SUCCESS The VtdIndex and SourceId are returned.
243 @retval EFI_INVALID_PARAMETER DeviceHandle is not a valid handler.
244 @retval EFI_INVALID_PARAMETER DeviceInfo is NULL.
245 @retval EFI_NOT_FOUND The Segment or SourceId information is NOT found.
246 @retval EFI_UNSUPPORTED This function is not supported.
251 PlatformVTdGetDeviceId (
252 IN EDKII_PLATFORM_VTD_POLICY_PROTOCOL
*This
,
253 IN EFI_HANDLE DeviceHandle
,
254 OUT EDKII_PLATFORM_VTD_DEVICE_INFO
*DeviceInfo
257 EFI_PCI_IO_PROTOCOL
*PciIo
;
263 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
266 DEBUG ((DEBUG_VERBOSE
, "PlatformVTdGetDeviceId\n"));
268 if (DeviceInfo
== NULL
) {
269 return EFI_INVALID_PARAMETER
;
272 if (DeviceHandle
== NULL
) {
273 return EFI_INVALID_PARAMETER
;
279 Status
= gBS
->HandleProtocol (DeviceHandle
, &gEfiPciIoProtocolGuid
, (VOID
**)&PciIo
);
280 if (!EFI_ERROR(Status
)) {
281 Status
= PciIo
->GetLocation (PciIo
, &Seg
, &Bus
, &Dev
, &Func
);
282 if (EFI_ERROR(Status
)) {
283 return EFI_UNSUPPORTED
;
285 DeviceInfo
->Segment
= (UINT16
)Seg
;
286 DeviceInfo
->SourceId
.Bits
.Bus
= (UINT8
)Bus
;
287 DeviceInfo
->SourceId
.Bits
.Device
= (UINT8
)Dev
;
288 DeviceInfo
->SourceId
.Bits
.Function
= (UINT8
)Func
;
294 // Handle ACPI device
296 Status
= gBS
->HandleProtocol (DeviceHandle
, &gEfiDevicePathProtocolGuid
, (VOID
**)&DevicePath
);
297 if (!EFI_ERROR(Status
)) {
298 for (Index
= 0; Index
< ARRAY_SIZE(mAcpiDeviceMapping
); Index
++) {
299 if (CompareDevicePath (mAcpiDeviceMapping
[Index
].DevicePath
, DevicePath
)) {
300 DeviceInfo
->Segment
= mAcpiDeviceMapping
[Index
].Segment
;
301 DeviceInfo
->SourceId
= mAcpiDeviceMapping
[Index
].SourceId
;
307 return EFI_NOT_FOUND
;
311 Get a list of the exception devices.
313 The VTd driver should always set ALLOW for the device in this list.
315 @param[in] This The protocol instance pointer.
316 @param[out] DeviceInfoCount The count of the list of DeviceInfo.
317 @param[out] DeviceInfo A callee allocated buffer to hold a list of DeviceInfo.
318 Each DeviceInfo pointer points to EDKII_PLATFORM_VTD_EXCEPTION_DEVICE_INFO.
320 @retval EFI_SUCCESS The DeviceInfoCount and DeviceInfo are returned.
321 @retval EFI_INVALID_PARAMETER DeviceInfoCount is NULL, or DeviceInfo is NULL.
322 @retval EFI_UNSUPPORTED This function is not supported.
327 PlatformVTdGetExceptionDeviceList (
328 IN EDKII_PLATFORM_VTD_POLICY_PROTOCOL
*This
,
329 OUT UINTN
*DeviceInfoCount
,
330 OUT VOID
**DeviceInfo
333 DEBUG ((DEBUG_VERBOSE
, "PlatformVTdGetExceptionDeviceList\n"));
335 if (DeviceInfoCount
== NULL
|| DeviceInfo
== NULL
) {
336 return EFI_INVALID_PARAMETER
;
340 // Sample codes for device scope based exception list.
341 // Uncomment to take affect and comment the sample codes for PCI vendor id
342 // based exception list.
345 *DeviceInfo = AllocateZeroPool (sizeof(mExceptionDeviceScopeList));
346 if (*DeviceInfo == NULL) {
347 return EFI_OUT_OF_RESOURCES;
349 CopyMem (*DeviceInfo, mExceptionDeviceScopeList, sizeof(mExceptionDeviceScopeList));
351 *DeviceInfoCount = ARRAY_SIZE(mExceptionDeviceScopeList);
355 // Sample codes for PCI vendor id based exception list.
356 // Uncomment to take affect and comment the sample codes for device scope
357 // based exception list.
360 *DeviceInfo = AllocateZeroPool (sizeof(mExceptionPciDeviceIdList));
361 if (*DeviceInfo == NULL) {
362 return EFI_OUT_OF_RESOURCES;
364 CopyMem (*DeviceInfo, mExceptionPciDeviceIdList, sizeof(mExceptionPciDeviceIdList));
366 *DeviceInfoCount = ARRAY_SIZE(mExceptionPciDeviceIdList);
368 return EFI_UNSUPPORTED
;
371 EDKII_PLATFORM_VTD_POLICY_PROTOCOL mPlatformVTdSample
= {
372 EDKII_PLATFORM_VTD_POLICY_PROTOCOL_REVISION
,
373 PlatformVTdGetDeviceId
,
374 PlatformVTdGetExceptionDeviceList
,
378 Platform VTd sample driver.
380 @param[in] ImageHandle ImageHandle of the loaded driver
381 @param[in] SystemTable Pointer to the System Table
383 @retval EFI_SUCCESS The Protocol is installed.
384 @retval EFI_OUT_OF_RESOURCES Not enough resources available to initialize driver.
385 @retval EFI_DEVICE_ERROR A device error occurred attempting to initialize the driver.
390 PlatformVTdSampleInitialize (
391 IN EFI_HANDLE ImageHandle
,
392 IN EFI_SYSTEM_TABLE
*SystemTable
399 Status
= gBS
->InstallMultipleProtocolInterfaces (
401 &gEdkiiPlatformVTdPolicyProtocolGuid
, &mPlatformVTdSample
,
404 ASSERT_EFI_ERROR (Status
);