2 Platform VTd Sample driver.
4 Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
17 #include <IndustryStandard/Vtd.h>
18 #include <Protocol/PlatformVtdPolicy.h>
19 #include <Protocol/PciIo.h>
20 #include <Protocol/DevicePath.h>
22 #include <Library/IoLib.h>
23 #include <Library/BaseLib.h>
24 #include <Library/BaseMemoryLib.h>
25 #include <Library/MemoryAllocationLib.h>
26 #include <Library/DebugLib.h>
27 #include <Library/UefiBootServicesTableLib.h>
28 #include <Library/DevicePathLib.h>
30 #include <IndustryStandard/DmaRemappingReportingTable.h>
33 ACPI_EXTENDED_HID_DEVICE_PATH I2cController
;
37 } PLATFORM_I2C_CONTROLLER_DEVICE_PATH
;
40 ACPI_EXTENDED_HID_DEVICE_PATH I2cDevice
;
44 } PLATFORM_I2C_DEVICE_DEVICE_PATH
;
47 PLATFORM_I2C_CONTROLLER_DEVICE_PATH I2cController
;
48 PLATFORM_I2C_DEVICE_DEVICE_PATH I2cDevice
;
49 EFI_DEVICE_PATH_PROTOCOL End
;
50 } PLATFORM_I2C_DEVICE_PATH
;
53 ACPI_HID_DEVICE_PATH PciRootBridge
;
54 PCI_DEVICE_PATH PciDevice
;
55 EFI_DEVICE_PATH_PROTOCOL EndDevicePath
;
56 } PLATFORM_PCI_DEVICE_PATH
;
59 ACPI_HID_DEVICE_PATH PciRootBridge
;
60 PCI_DEVICE_PATH PciBridge
;
61 PCI_DEVICE_PATH PciDevice
;
62 EFI_DEVICE_PATH_PROTOCOL EndDevicePath
;
63 } PLATFORM_PCI_BRIDGE_DEVICE_PATH
;
66 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
68 VTD_SOURCE_ID SourceId
;
69 } PLATFORM_ACPI_DEVICE_MAPPING
;
71 #define PLATFORM_PCI_ROOT_BRIDGE \
77 (UINT8) (sizeof (ACPI_HID_DEVICE_PATH)), \
78 (UINT8) ((sizeof (ACPI_HID_DEVICE_PATH)) >> 8) \
81 EISA_PNP_ID (0x0A03), \
85 #define PLATFORM_END_ENTIRE \
87 END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, { END_DEVICE_PATH_LENGTH, 0 } \
90 #define PLATFORM_PCI(Device, Function) \
93 HARDWARE_DEVICE_PATH, \
96 (UINT8) (sizeof (PCI_DEVICE_PATH)), \
97 (UINT8) ((sizeof (PCI_DEVICE_PATH)) >> 8) \
104 #define PLATFORM_I2C(Hid, Uid, Cid, HidStr, UidStr, CidStr) \
110 {sizeof(ACPI_EXTENDED_HID_DEVICE_PATH) + sizeof(HidStr) + sizeof(UidStr) + sizeof(CidStr), 0} \
121 PLATFORM_I2C_DEVICE_PATH mPlatformI2CDevicePath
= {
122 PLATFORM_I2C(0, 2, 0, "INT33C3", "", "INT33C3"),
123 PLATFORM_I2C(0, 1, 0, "I2C01\\TPANEL", "", "I2C01\\TPANEL"),
127 PLATFORM_ACPI_DEVICE_MAPPING mAcpiDeviceMapping
[] = {
129 (EFI_DEVICE_PATH_PROTOCOL
*)&mPlatformI2CDevicePath
,
131 {{0x01, 0x15, 0x00}} // Function, Device, Bus
135 PLATFORM_PCI_BRIDGE_DEVICE_PATH mPlatformPciBridgeDevicePath
= {
136 PLATFORM_PCI_ROOT_BRIDGE
,
137 PLATFORM_PCI(0x1C, 1),
145 EDKII_PLATFORM_VTD_EXCEPTION_DEVICE_INFO ExceptionDeviceInfo
;
146 EDKII_PLATFORM_VTD_DEVICE_SCOPE DeviceScope
;
147 EFI_ACPI_DMAR_PCI_PATH PciBridge
;
148 EFI_ACPI_DMAR_PCI_PATH PciDevice
;
149 } PLATFORM_EXCEPTION_DEVICE_SCOPE_STRUCT
;
152 EDKII_PLATFORM_VTD_EXCEPTION_DEVICE_INFO ExceptionDeviceInfo
;
153 EDKII_PLATFORM_VTD_PCI_DEVICE_ID PciDeviceId
;
154 } PLATFORM_EXCEPTION_PCI_DEVICE_ID_STRUCT
;
158 PLATFORM_EXCEPTION_DEVICE_SCOPE_STRUCT mExceptionDeviceScopeList
[] = {
161 EDKII_PLATFORM_VTD_EXCEPTION_DEVICE_INFO_TYPE_DEVICE_SCOPE
,
162 sizeof(PLATFORM_EXCEPTION_DEVICE_SCOPE_STRUCT
)
163 }, // ExceptionDeviceInfo
167 EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT
, // Type
168 sizeof(EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER
) +
169 2 * sizeof(EFI_ACPI_DMAR_PCI_PATH
), // Length
175 { 0x1C, 1 }, // PciBridge
176 { 0x0, 0 }, // PciDevice
180 PLATFORM_EXCEPTION_PCI_DEVICE_ID_STRUCT mExceptionPciDeviceIdList
[] = {
183 EDKII_PLATFORM_VTD_EXCEPTION_DEVICE_INFO_TYPE_PCI_DEVICE_ID
,
184 sizeof(PLATFORM_EXCEPTION_PCI_DEVICE_ID_STRUCT
)
185 }, // ExceptionDeviceInfo
190 0x8086, // SubsystemVendorId
191 0x7270, // SubsystemDeviceId
197 Compares 2 device path.
199 @param[in] DevicePath1 A device path with EndDevicePath node.
200 @param[in] DevicePath2 A device path with EndDevicePath node.
202 @retval TRUE 2 device path are identical.
203 @retval FALSE 2 device path are not identical.
207 IN CONST EFI_DEVICE_PATH_PROTOCOL
*DevicePath1
,
208 IN CONST EFI_DEVICE_PATH_PROTOCOL
*DevicePath2
214 Size1
= GetDevicePathSize (DevicePath1
);
215 Size2
= GetDevicePathSize (DevicePath2
);
216 if (Size1
!= Size2
) {
219 if (CompareMem (DevicePath1
, DevicePath2
, Size1
) != 0) {
226 Get the VTD SourceId from the device handler.
227 This function is required for non PCI device handler.
229 Pseudo-algo in Intel VTd driver:
230 Status = PlatformGetVTdDeviceId ();
231 if (EFI_ERROR(Status)) {
232 if (DeviceHandle is PCI) {
233 Get SourceId from Bus/Device/Function
235 return EFI_UNSUPPORTED
238 Get VTd engine by Segment/Bus/Device/Function.
240 @param[in] This The protocol instance pointer.
241 @param[in] DeviceHandle Device Identifier in UEFI.
242 @param[out] DeviceInfo DeviceInfo for indentify the VTd engine in ACPI Table
243 and the VTd page entry.
245 @retval EFI_SUCCESS The VtdIndex and SourceId are returned.
246 @retval EFI_INVALID_PARAMETER DeviceHandle is not a valid handler.
247 @retval EFI_INVALID_PARAMETER DeviceInfo is NULL.
248 @retval EFI_NOT_FOUND The Segment or SourceId information is NOT found.
249 @retval EFI_UNSUPPORTED This function is not supported.
254 PlatformVTdGetDeviceId (
255 IN EDKII_PLATFORM_VTD_POLICY_PROTOCOL
*This
,
256 IN EFI_HANDLE DeviceHandle
,
257 OUT EDKII_PLATFORM_VTD_DEVICE_INFO
*DeviceInfo
260 EFI_PCI_IO_PROTOCOL
*PciIo
;
266 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
269 DEBUG ((DEBUG_VERBOSE
, "PlatformVTdGetDeviceId\n"));
271 if (DeviceInfo
== NULL
) {
272 return EFI_INVALID_PARAMETER
;
275 if (DeviceHandle
== NULL
) {
276 return EFI_INVALID_PARAMETER
;
282 Status
= gBS
->HandleProtocol (DeviceHandle
, &gEfiPciIoProtocolGuid
, (VOID
**)&PciIo
);
283 if (!EFI_ERROR(Status
)) {
284 Status
= PciIo
->GetLocation (PciIo
, &Seg
, &Bus
, &Dev
, &Func
);
285 if (EFI_ERROR(Status
)) {
286 return EFI_UNSUPPORTED
;
288 DeviceInfo
->Segment
= (UINT16
)Seg
;
289 DeviceInfo
->SourceId
.Bits
.Bus
= (UINT8
)Bus
;
290 DeviceInfo
->SourceId
.Bits
.Device
= (UINT8
)Dev
;
291 DeviceInfo
->SourceId
.Bits
.Function
= (UINT8
)Func
;
297 // Handle ACPI device
299 Status
= gBS
->HandleProtocol (DeviceHandle
, &gEfiDevicePathProtocolGuid
, (VOID
**)&DevicePath
);
300 if (!EFI_ERROR(Status
)) {
301 for (Index
= 0; Index
< ARRAY_SIZE(mAcpiDeviceMapping
); Index
++) {
302 if (CompareDevicePath (mAcpiDeviceMapping
[Index
].DevicePath
, DevicePath
)) {
303 DeviceInfo
->Segment
= mAcpiDeviceMapping
[Index
].Segment
;
304 DeviceInfo
->SourceId
= mAcpiDeviceMapping
[Index
].SourceId
;
310 return EFI_NOT_FOUND
;
314 Get a list of the exception devices.
316 The VTd driver should always set ALLOW for the device in this list.
318 @param[in] This The protocol instance pointer.
319 @param[out] DeviceInfoCount The count of the list of DeviceInfo.
320 @param[out] DeviceInfo A callee allocated buffer to hold a list of DeviceInfo.
321 Each DeviceInfo pointer points to EDKII_PLATFORM_VTD_EXCEPTION_DEVICE_INFO.
323 @retval EFI_SUCCESS The DeviceInfoCount and DeviceInfo are returned.
324 @retval EFI_INVALID_PARAMETER DeviceInfoCount is NULL, or DeviceInfo is NULL.
325 @retval EFI_UNSUPPORTED This function is not supported.
330 PlatformVTdGetExceptionDeviceList (
331 IN EDKII_PLATFORM_VTD_POLICY_PROTOCOL
*This
,
332 OUT UINTN
*DeviceInfoCount
,
333 OUT VOID
**DeviceInfo
336 DEBUG ((DEBUG_VERBOSE
, "PlatformVTdGetExceptionDeviceList\n"));
338 if (DeviceInfoCount
== NULL
|| DeviceInfo
== NULL
) {
339 return EFI_INVALID_PARAMETER
;
343 // Sample codes for device scope based exception list.
344 // Uncomment to take affect and comment the sample codes for PCI vendor id
345 // based exception list.
348 *DeviceInfo = AllocateZeroPool (sizeof(mExceptionDeviceScopeList));
349 if (*DeviceInfo == NULL) {
350 return EFI_OUT_OF_RESOURCES;
352 CopyMem (*DeviceInfo, mExceptionDeviceScopeList, sizeof(mExceptionDeviceScopeList));
354 *DeviceInfoCount = ARRAY_SIZE(mExceptionDeviceScopeList);
358 // Sample codes for PCI vendor id based exception list.
359 // Uncomment to take affect and comment the sample codes for device scope
360 // based exception list.
362 *DeviceInfo
= AllocateZeroPool (sizeof(mExceptionPciDeviceIdList
));
363 if (*DeviceInfo
== NULL
) {
364 return EFI_OUT_OF_RESOURCES
;
366 CopyMem (*DeviceInfo
, mExceptionPciDeviceIdList
, sizeof(mExceptionPciDeviceIdList
));
368 *DeviceInfoCount
= ARRAY_SIZE(mExceptionPciDeviceIdList
);
373 EDKII_PLATFORM_VTD_POLICY_PROTOCOL mPlatformVTdSample
= {
374 EDKII_PLATFORM_VTD_POLICY_PROTOCOL_REVISION
,
375 PlatformVTdGetDeviceId
,
376 PlatformVTdGetExceptionDeviceList
,
380 Platform VTd sample driver.
382 @param[in] ImageHandle ImageHandle of the loaded driver
383 @param[in] SystemTable Pointer to the System Table
385 @retval EFI_SUCCESS The Protocol is installed.
386 @retval EFI_OUT_OF_RESOURCES Not enough resources available to initialize driver.
387 @retval EFI_DEVICE_ERROR A device error occurred attempting to initialize the driver.
392 PlatformVTdSampleInitialize (
393 IN EFI_HANDLE ImageHandle
,
394 IN EFI_SYSTEM_TABLE
*SystemTable
401 Status
= gBS
->InstallMultipleProtocolInterfaces (
403 &gEdkiiPlatformVTdPolicyProtocolGuid
, &mPlatformVTdSample
,
406 ASSERT_EFI_ERROR (Status
);