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>
31 ACPI_EXTENDED_HID_DEVICE_PATH I2cController
;
35 } PLATFORM_I2C_CONTROLLER_DEVICE_PATH
;
38 ACPI_EXTENDED_HID_DEVICE_PATH I2cDevice
;
42 } PLATFORM_I2C_DEVICE_DEVICE_PATH
;
45 PLATFORM_I2C_CONTROLLER_DEVICE_PATH I2cController
;
46 PLATFORM_I2C_DEVICE_DEVICE_PATH I2cDevice
;
47 EFI_DEVICE_PATH_PROTOCOL End
;
48 } PLATFORM_I2C_DEVICE_PATH
;
51 ACPI_HID_DEVICE_PATH PciRootBridge
;
52 PCI_DEVICE_PATH PciDevice
;
53 EFI_DEVICE_PATH_PROTOCOL EndDevicePath
;
54 } PLATFORM_PCI_DEVICE_PATH
;
57 ACPI_HID_DEVICE_PATH PciRootBridge
;
58 PCI_DEVICE_PATH PciBridge
;
59 PCI_DEVICE_PATH PciDevice
;
60 EFI_DEVICE_PATH_PROTOCOL EndDevicePath
;
61 } PLATFORM_PCI_BRIDGE_DEVICE_PATH
;
64 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
66 VTD_SOURCE_ID SourceId
;
67 } PLATFORM_ACPI_DEVICE_MAPPING
;
69 #define PLATFORM_PCI_ROOT_BRIDGE \
75 (UINT8) (sizeof (ACPI_HID_DEVICE_PATH)), \
76 (UINT8) ((sizeof (ACPI_HID_DEVICE_PATH)) >> 8) \
79 EISA_PNP_ID (0x0A03), \
83 #define PLATFORM_END_ENTIRE \
85 END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, { END_DEVICE_PATH_LENGTH, 0 } \
88 #define PLATFORM_PCI(Device, Function) \
91 HARDWARE_DEVICE_PATH, \
94 (UINT8) (sizeof (PCI_DEVICE_PATH)), \
95 (UINT8) ((sizeof (PCI_DEVICE_PATH)) >> 8) \
102 #define PLATFORM_I2C(Hid, Uid, Cid, HidStr, UidStr, CidStr) \
108 {sizeof(ACPI_EXTENDED_HID_DEVICE_PATH) + sizeof(HidStr) + sizeof(UidStr) + sizeof(CidStr), 0} \
119 PLATFORM_I2C_DEVICE_PATH mPlatformI2CDevicePath
= {
120 PLATFORM_I2C(0, 2, 0, "INT33C3", "", "INT33C3"),
121 PLATFORM_I2C(0, 1, 0, "I2C01\\TPANEL", "", "I2C01\\TPANEL"),
125 PLATFORM_ACPI_DEVICE_MAPPING mAcpiDeviceMapping
[] = {
127 (EFI_DEVICE_PATH_PROTOCOL
*)&mPlatformI2CDevicePath
,
129 {{0x01, 0x15, 0x00}} // Function, Device, Bus
133 PLATFORM_PCI_BRIDGE_DEVICE_PATH mPlatformPciBridgeDevicePath
= {
134 PLATFORM_PCI_ROOT_BRIDGE
,
135 PLATFORM_PCI(0x1C, 1),
140 EDKII_PLATFORM_VTD_DEVICE_INFO mExceptionDeviceList
[] = {
143 {{0x00, 0x00, 0x02}} // Function, Device, Bus
148 Compares 2 device path.
150 @param[in] DevicePath1 A device path with EndDevicePath node.
151 @param[in] DevicePath2 A device path with EndDevicePath node.
153 @retval TRUE 2 device path are identical.
154 @retval FALSE 2 device path are not identical.
158 IN CONST EFI_DEVICE_PATH_PROTOCOL
*DevicePath1
,
159 IN CONST EFI_DEVICE_PATH_PROTOCOL
*DevicePath2
165 Size1
= GetDevicePathSize (DevicePath1
);
166 Size2
= GetDevicePathSize (DevicePath2
);
167 if (Size1
!= Size2
) {
170 if (CompareMem (DevicePath1
, DevicePath2
, Size1
) != 0) {
177 Get the VTD SourceId from the device handler.
178 This function is required for non PCI device handler.
180 Pseudo-algo in Intel VTd driver:
181 Status = PlatformGetVTdDeviceId ();
182 if (EFI_ERROR(Status)) {
183 if (DeviceHandle is PCI) {
184 Get SourceId from Bus/Device/Function
186 return EFI_UNSUPPORTED
189 Get VTd engine by Segment/Bus/Device/Function.
191 @param[in] This The protocol instance pointer.
192 @param[in] DeviceHandle Device Identifier in UEFI.
193 @param[out] DeviceInfo DeviceInfo for indentify the VTd engine in ACPI Table
194 and the VTd page entry.
196 @retval EFI_SUCCESS The VtdIndex and SourceId are returned.
197 @retval EFI_INVALID_PARAMETER DeviceHandle is not a valid handler.
198 @retval EFI_INVALID_PARAMETER DeviceInfo is NULL.
199 @retval EFI_NOT_FOUND The Segment or SourceId information is NOT found.
200 @retval EFI_UNSUPPORTED This function is not supported.
205 PlatformVTdGetDeviceId (
206 IN EDKII_PLATFORM_VTD_POLICY_PROTOCOL
*This
,
207 IN EFI_HANDLE DeviceHandle
,
208 OUT EDKII_PLATFORM_VTD_DEVICE_INFO
*DeviceInfo
211 EFI_PCI_IO_PROTOCOL
*PciIo
;
217 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
220 DEBUG ((DEBUG_VERBOSE
, "PlatformVTdGetDeviceId\n"));
222 if (DeviceInfo
== NULL
) {
223 return EFI_INVALID_PARAMETER
;
226 if (DeviceHandle
== NULL
) {
227 return EFI_INVALID_PARAMETER
;
233 Status
= gBS
->HandleProtocol (DeviceHandle
, &gEfiPciIoProtocolGuid
, (VOID
**)&PciIo
);
234 if (!EFI_ERROR(Status
)) {
235 Status
= PciIo
->GetLocation (PciIo
, &Seg
, &Bus
, &Dev
, &Func
);
236 if (EFI_ERROR(Status
)) {
237 return EFI_UNSUPPORTED
;
239 DeviceInfo
->Segment
= (UINT16
)Seg
;
240 DeviceInfo
->SourceId
.Bits
.Bus
= (UINT8
)Bus
;
241 DeviceInfo
->SourceId
.Bits
.Device
= (UINT8
)Dev
;
242 DeviceInfo
->SourceId
.Bits
.Function
= (UINT8
)Func
;
248 // Handle ACPI device
250 Status
= gBS
->HandleProtocol (DeviceHandle
, &gEfiDevicePathProtocolGuid
, (VOID
**)&DevicePath
);
251 if (!EFI_ERROR(Status
)) {
252 for (Index
= 0; Index
< ARRAY_SIZE(mAcpiDeviceMapping
); Index
++) {
253 if (CompareDevicePath (mAcpiDeviceMapping
[Index
].DevicePath
, DevicePath
)) {
254 DeviceInfo
->Segment
= mAcpiDeviceMapping
[Index
].Segment
;
255 DeviceInfo
->SourceId
= mAcpiDeviceMapping
[Index
].SourceId
;
261 return EFI_NOT_FOUND
;
265 Get a list of the exception devices.
267 The VTd driver should always set ALLOW for the device in this list.
269 @param[in] This The protocol instance pointer.
270 @param[out] DeviceInfoCount The count of the list of DeviceInfo.
271 @param[out] DeviceInfo A callee allocated buffer to hold a list of DeviceInfo.
273 @retval EFI_SUCCESS The DeviceInfoCount and DeviceInfo are returned.
274 @retval EFI_INVALID_PARAMETER DeviceInfoCount is NULL, or DeviceInfo is NULL.
275 @retval EFI_UNSUPPORTED This function is not supported.
280 PlatformVTdGetExceptionDeviceList (
281 IN EDKII_PLATFORM_VTD_POLICY_PROTOCOL
*This
,
282 OUT UINTN
*DeviceInfoCount
,
283 OUT EDKII_PLATFORM_VTD_DEVICE_INFO
**DeviceInfo
286 DEBUG ((DEBUG_VERBOSE
, "PlatformVTdGetExceptionDeviceList\n"));
288 if (DeviceInfoCount
== NULL
|| DeviceInfo
== NULL
) {
289 return EFI_INVALID_PARAMETER
;
292 *DeviceInfo
= AllocateZeroPool (sizeof(mExceptionDeviceList
));
293 if (*DeviceInfo
== NULL
) {
294 return EFI_OUT_OF_RESOURCES
;
296 CopyMem (*DeviceInfo
, mExceptionDeviceList
, sizeof(mExceptionDeviceList
));
298 *DeviceInfoCount
= ARRAY_SIZE(mExceptionDeviceList
);
303 EDKII_PLATFORM_VTD_POLICY_PROTOCOL mPlatformVTdSample
= {
304 EDKII_PLATFORM_VTD_POLICY_PROTOCOL_REVISION
,
305 PlatformVTdGetDeviceId
,
306 PlatformVTdGetExceptionDeviceList
,
310 Platform VTd sample driver.
312 @param[in] ImageHandle ImageHandle of the loaded driver
313 @param[in] SystemTable Pointer to the System Table
315 @retval EFI_SUCCESS The Protocol is installed.
316 @retval EFI_OUT_OF_RESOURCES Not enough resources available to initialize driver.
317 @retval EFI_DEVICE_ERROR A device error occurred attempting to initialize the driver.
322 PlatformVTdSampleInitialize (
323 IN EFI_HANDLE ImageHandle
,
324 IN EFI_SYSTEM_TABLE
*SystemTable
331 Status
= gBS
->InstallMultipleProtocolInterfaces (
333 &gEdkiiPlatformVTdPolicyProtocolGuid
, &mPlatformVTdSample
,
336 ASSERT_EFI_ERROR (Status
);