]> git.proxmox.com Git - mirror_edk2.git/blame - IntelSiliconPkg/Feature/VTd/PlatformVTdSampleDxe/PlatformVTdSampleDxe.c
IntelSiliconPkg PlatformVTdSampleDxe: State it is only for dev/debug
[mirror_edk2.git] / IntelSiliconPkg / Feature / VTd / PlatformVTdSampleDxe / PlatformVTdSampleDxe.c
CommitLineData
5071fb9c
JY
1/** @file\r
2 Platform VTd Sample driver.\r
3\r
17ac6b23
SZ
4 Note: This module should only be used for dev/debug purposes.\r
5 It MUST never be used for production builds.\r
6\r
7 Copyright (c) 2017 - 2018, Intel Corporation. All rights reserved.<BR>\r
5071fb9c
JY
8 This program and the accompanying materials\r
9 are licensed and made available under the terms and conditions of the BSD License\r
10 which accompanies this distribution. The full text of the license may be found at\r
11 http://opensource.org/licenses/bsd-license.php\r
12\r
13 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
14 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
15\r
16**/\r
17\r
18#include <PiDxe.h>\r
19\r
20#include <IndustryStandard/Vtd.h>\r
21#include <Protocol/PlatformVtdPolicy.h>\r
22#include <Protocol/PciIo.h>\r
23#include <Protocol/DevicePath.h>\r
24\r
25#include <Library/IoLib.h>\r
26#include <Library/BaseLib.h>\r
27#include <Library/BaseMemoryLib.h>\r
28#include <Library/MemoryAllocationLib.h>\r
29#include <Library/DebugLib.h>\r
30#include <Library/UefiBootServicesTableLib.h>\r
31#include <Library/DevicePathLib.h>\r
32\r
5f5bdf4a
JY
33#include <IndustryStandard/DmaRemappingReportingTable.h>\r
34\r
5071fb9c
JY
35typedef struct {\r
36 ACPI_EXTENDED_HID_DEVICE_PATH I2cController;\r
37 UINT8 HidStr[8];\r
38 UINT8 UidStr[1];\r
39 UINT8 CidStr[8];\r
40} PLATFORM_I2C_CONTROLLER_DEVICE_PATH;\r
41\r
42typedef struct {\r
43 ACPI_EXTENDED_HID_DEVICE_PATH I2cDevice;\r
44 UINT8 HidStr[13];\r
45 UINT8 UidStr[1];\r
46 UINT8 CidStr[13];\r
47} PLATFORM_I2C_DEVICE_DEVICE_PATH;\r
48\r
49typedef struct {\r
50 PLATFORM_I2C_CONTROLLER_DEVICE_PATH I2cController;\r
51 PLATFORM_I2C_DEVICE_DEVICE_PATH I2cDevice;\r
52 EFI_DEVICE_PATH_PROTOCOL End;\r
53} PLATFORM_I2C_DEVICE_PATH;\r
54\r
55typedef struct {\r
56 ACPI_HID_DEVICE_PATH PciRootBridge;\r
57 PCI_DEVICE_PATH PciDevice;\r
58 EFI_DEVICE_PATH_PROTOCOL EndDevicePath;\r
59} PLATFORM_PCI_DEVICE_PATH;\r
60\r
61typedef struct {\r
62 ACPI_HID_DEVICE_PATH PciRootBridge;\r
63 PCI_DEVICE_PATH PciBridge;\r
64 PCI_DEVICE_PATH PciDevice;\r
65 EFI_DEVICE_PATH_PROTOCOL EndDevicePath;\r
66} PLATFORM_PCI_BRIDGE_DEVICE_PATH;\r
67\r
68typedef struct {\r
69 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
70 UINT16 Segment;\r
71 VTD_SOURCE_ID SourceId;\r
72} PLATFORM_ACPI_DEVICE_MAPPING;\r
73\r
74#define PLATFORM_PCI_ROOT_BRIDGE \\r
75 { \\r
76 { \\r
77 ACPI_DEVICE_PATH, \\r
78 ACPI_DP, \\r
79 { \\r
80 (UINT8) (sizeof (ACPI_HID_DEVICE_PATH)), \\r
81 (UINT8) ((sizeof (ACPI_HID_DEVICE_PATH)) >> 8) \\r
82 }, \\r
83 }, \\r
84 EISA_PNP_ID (0x0A03), \\r
85 0 \\r
86 }\r
87\r
88#define PLATFORM_END_ENTIRE \\r
89 { \\r
90 END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, { END_DEVICE_PATH_LENGTH, 0 } \\r
91 }\r
92\r
93#define PLATFORM_PCI(Device, Function) \\r
94 { \\r
95 { \\r
96 HARDWARE_DEVICE_PATH, \\r
97 HW_PCI_DP, \\r
98 { \\r
99 (UINT8) (sizeof (PCI_DEVICE_PATH)), \\r
100 (UINT8) ((sizeof (PCI_DEVICE_PATH)) >> 8) \\r
101 } \\r
102 }, \\r
103 (Function), \\r
104 (Device) \\r
105 }\r
106\r
107#define PLATFORM_I2C(Hid, Uid, Cid, HidStr, UidStr, CidStr) \\r
108 { \\r
109 { \\r
110 { \\r
111 ACPI_DEVICE_PATH, \\r
112 ACPI_EXTENDED_DP, \\r
113 {sizeof(ACPI_EXTENDED_HID_DEVICE_PATH) + sizeof(HidStr) + sizeof(UidStr) + sizeof(CidStr), 0} \\r
114 }, \\r
115 Hid, \\r
116 Uid, \\r
117 Cid \\r
118 }, \\r
119 HidStr, \\r
120 UidStr, \\r
121 CidStr \\r
122 }\r
123\r
124PLATFORM_I2C_DEVICE_PATH mPlatformI2CDevicePath = {\r
125 PLATFORM_I2C(0, 2, 0, "INT33C3", "", "INT33C3"),\r
126 PLATFORM_I2C(0, 1, 0, "I2C01\\TPANEL", "", "I2C01\\TPANEL"),\r
127 PLATFORM_END_ENTIRE\r
128};\r
129\r
130PLATFORM_ACPI_DEVICE_MAPPING mAcpiDeviceMapping[] = {\r
131 {\r
132 (EFI_DEVICE_PATH_PROTOCOL *)&mPlatformI2CDevicePath,\r
133 0x0, // Segment\r
134 {{0x01, 0x15, 0x00}} // Function, Device, Bus\r
135 }\r
136};\r
137\r
138PLATFORM_PCI_BRIDGE_DEVICE_PATH mPlatformPciBridgeDevicePath = {\r
139 PLATFORM_PCI_ROOT_BRIDGE,\r
140 PLATFORM_PCI(0x1C, 1),\r
141 PLATFORM_PCI(0, 0),\r
142 PLATFORM_END_ENTIRE\r
143};\r
144\r
5f5bdf4a
JY
145#pragma pack(1)\r
146\r
147typedef struct {\r
148 EDKII_PLATFORM_VTD_EXCEPTION_DEVICE_INFO ExceptionDeviceInfo;\r
149 EDKII_PLATFORM_VTD_DEVICE_SCOPE DeviceScope;\r
150 EFI_ACPI_DMAR_PCI_PATH PciBridge;\r
151 EFI_ACPI_DMAR_PCI_PATH PciDevice;\r
152} PLATFORM_EXCEPTION_DEVICE_SCOPE_STRUCT;\r
153\r
154typedef struct {\r
155 EDKII_PLATFORM_VTD_EXCEPTION_DEVICE_INFO ExceptionDeviceInfo;\r
156 EDKII_PLATFORM_VTD_PCI_DEVICE_ID PciDeviceId;\r
157} PLATFORM_EXCEPTION_PCI_DEVICE_ID_STRUCT;\r
158\r
159#pragma pack()\r
160\r
161PLATFORM_EXCEPTION_DEVICE_SCOPE_STRUCT mExceptionDeviceScopeList[] = {\r
5071fb9c 162 {\r
5f5bdf4a
JY
163 {\r
164 EDKII_PLATFORM_VTD_EXCEPTION_DEVICE_INFO_TYPE_DEVICE_SCOPE,\r
165 sizeof(PLATFORM_EXCEPTION_DEVICE_SCOPE_STRUCT)\r
166 }, // ExceptionDeviceInfo\r
167 {\r
168 0, // SegmentNumber\r
169 {\r
170 EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT, // Type\r
171 sizeof(EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER) +\r
172 2 * sizeof(EFI_ACPI_DMAR_PCI_PATH), // Length\r
173 0, // Reserved2\r
174 0, // EnumerationId\r
175 0, // StartBusNumber\r
176 },\r
177 }, // DeviceScope\r
178 { 0x1C, 1 }, // PciBridge\r
179 { 0x0, 0 }, // PciDevice\r
180 },\r
181};\r
182\r
183PLATFORM_EXCEPTION_PCI_DEVICE_ID_STRUCT mExceptionPciDeviceIdList[] = {\r
184 {\r
185 {\r
186 EDKII_PLATFORM_VTD_EXCEPTION_DEVICE_INFO_TYPE_PCI_DEVICE_ID,\r
187 sizeof(PLATFORM_EXCEPTION_PCI_DEVICE_ID_STRUCT)\r
188 }, // ExceptionDeviceInfo\r
189 {\r
190 0x8086, // VendorId\r
191 0x9D2F, // DeviceId\r
192 0x21, // RevisionId\r
193 0x8086, // SubsystemVendorId\r
194 0x7270, // SubsystemDeviceId\r
195 },\r
5071fb9c
JY
196 },\r
197};\r
198\r
199/**\r
200 Compares 2 device path.\r
201\r
202 @param[in] DevicePath1 A device path with EndDevicePath node.\r
203 @param[in] DevicePath2 A device path with EndDevicePath node.\r
204\r
205 @retval TRUE 2 device path are identical.\r
206 @retval FALSE 2 device path are not identical.\r
207**/\r
208BOOLEAN\r
209CompareDevicePath (\r
210 IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath1,\r
211 IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath2\r
212 )\r
213{\r
214 UINTN Size1;\r
215 UINTN Size2;\r
216\r
217 Size1 = GetDevicePathSize (DevicePath1);\r
218 Size2 = GetDevicePathSize (DevicePath2);\r
219 if (Size1 != Size2) {\r
220 return FALSE;\r
221 }\r
222 if (CompareMem (DevicePath1, DevicePath2, Size1) != 0) {\r
223 return FALSE;\r
224 }\r
225 return TRUE;\r
226}\r
227\r
228/**\r
229 Get the VTD SourceId from the device handler.\r
230 This function is required for non PCI device handler.\r
231\r
232 Pseudo-algo in Intel VTd driver:\r
233 Status = PlatformGetVTdDeviceId ();\r
234 if (EFI_ERROR(Status)) {\r
235 if (DeviceHandle is PCI) {\r
236 Get SourceId from Bus/Device/Function\r
237 } else {\r
238 return EFI_UNSUPPORTED\r
239 }\r
240 }\r
241 Get VTd engine by Segment/Bus/Device/Function.\r
242\r
243 @param[in] This The protocol instance pointer.\r
244 @param[in] DeviceHandle Device Identifier in UEFI.\r
245 @param[out] DeviceInfo DeviceInfo for indentify the VTd engine in ACPI Table\r
246 and the VTd page entry.\r
247\r
248 @retval EFI_SUCCESS The VtdIndex and SourceId are returned.\r
249 @retval EFI_INVALID_PARAMETER DeviceHandle is not a valid handler.\r
250 @retval EFI_INVALID_PARAMETER DeviceInfo is NULL.\r
251 @retval EFI_NOT_FOUND The Segment or SourceId information is NOT found.\r
252 @retval EFI_UNSUPPORTED This function is not supported.\r
253\r
254**/\r
255EFI_STATUS\r
256EFIAPI\r
257PlatformVTdGetDeviceId (\r
258 IN EDKII_PLATFORM_VTD_POLICY_PROTOCOL *This,\r
259 IN EFI_HANDLE DeviceHandle,\r
260 OUT EDKII_PLATFORM_VTD_DEVICE_INFO *DeviceInfo\r
261 )\r
262{\r
263 EFI_PCI_IO_PROTOCOL *PciIo;\r
264 UINTN Seg;\r
265 UINTN Bus;\r
266 UINTN Dev;\r
267 UINTN Func;\r
268 EFI_STATUS Status;\r
269 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
270 UINTN Index;\r
271\r
272 DEBUG ((DEBUG_VERBOSE, "PlatformVTdGetDeviceId\n"));\r
273\r
274 if (DeviceInfo == NULL) {\r
275 return EFI_INVALID_PARAMETER;\r
276 }\r
277\r
278 if (DeviceHandle == NULL) {\r
279 return EFI_INVALID_PARAMETER;\r
280 }\r
281\r
282 //\r
283 // Handle PCI device\r
284 //\r
285 Status = gBS->HandleProtocol (DeviceHandle, &gEfiPciIoProtocolGuid, (VOID **)&PciIo);\r
286 if (!EFI_ERROR(Status)) {\r
287 Status = PciIo->GetLocation (PciIo, &Seg, &Bus, &Dev, &Func);\r
288 if (EFI_ERROR(Status)) {\r
289 return EFI_UNSUPPORTED;\r
290 }\r
291 DeviceInfo->Segment = (UINT16)Seg;\r
292 DeviceInfo->SourceId.Bits.Bus = (UINT8)Bus;\r
293 DeviceInfo->SourceId.Bits.Device = (UINT8)Dev;\r
294 DeviceInfo->SourceId.Bits.Function = (UINT8)Func;\r
295\r
296 return EFI_SUCCESS;\r
297 }\r
298\r
299 //\r
300 // Handle ACPI device\r
301 //\r
302 Status = gBS->HandleProtocol (DeviceHandle, &gEfiDevicePathProtocolGuid, (VOID **)&DevicePath);\r
303 if (!EFI_ERROR(Status)) {\r
304 for (Index = 0; Index < ARRAY_SIZE(mAcpiDeviceMapping); Index++) {\r
305 if (CompareDevicePath (mAcpiDeviceMapping[Index].DevicePath, DevicePath)) {\r
306 DeviceInfo->Segment = mAcpiDeviceMapping[Index].Segment;\r
307 DeviceInfo->SourceId = mAcpiDeviceMapping[Index].SourceId;\r
308 return EFI_SUCCESS;\r
309 }\r
310 }\r
311 }\r
312\r
313 return EFI_NOT_FOUND;\r
314}\r
315\r
316/**\r
317 Get a list of the exception devices.\r
318\r
319 The VTd driver should always set ALLOW for the device in this list.\r
320\r
321 @param[in] This The protocol instance pointer.\r
322 @param[out] DeviceInfoCount The count of the list of DeviceInfo.\r
323 @param[out] DeviceInfo A callee allocated buffer to hold a list of DeviceInfo.\r
5f5bdf4a 324 Each DeviceInfo pointer points to EDKII_PLATFORM_VTD_EXCEPTION_DEVICE_INFO.\r
5071fb9c
JY
325\r
326 @retval EFI_SUCCESS The DeviceInfoCount and DeviceInfo are returned.\r
327 @retval EFI_INVALID_PARAMETER DeviceInfoCount is NULL, or DeviceInfo is NULL.\r
328 @retval EFI_UNSUPPORTED This function is not supported.\r
329\r
330**/\r
331EFI_STATUS\r
332EFIAPI\r
333PlatformVTdGetExceptionDeviceList (\r
334 IN EDKII_PLATFORM_VTD_POLICY_PROTOCOL *This,\r
335 OUT UINTN *DeviceInfoCount,\r
5f5bdf4a 336 OUT VOID **DeviceInfo\r
5071fb9c
JY
337 )\r
338{\r
339 DEBUG ((DEBUG_VERBOSE, "PlatformVTdGetExceptionDeviceList\n"));\r
340\r
341 if (DeviceInfoCount == NULL || DeviceInfo == NULL) {\r
342 return EFI_INVALID_PARAMETER;\r
343 }\r
344\r
7046a273
HW
345 //\r
346 // Sample codes for device scope based exception list.\r
347 // Uncomment to take affect and comment the sample codes for PCI vendor id\r
348 // based exception list.\r
349 //\r
350 /*\r
351 *DeviceInfo = AllocateZeroPool (sizeof(mExceptionDeviceScopeList));\r
352 if (*DeviceInfo == NULL) {\r
353 return EFI_OUT_OF_RESOURCES;\r
354 }\r
355 CopyMem (*DeviceInfo, mExceptionDeviceScopeList, sizeof(mExceptionDeviceScopeList));\r
5f5bdf4a 356\r
7046a273
HW
357 *DeviceInfoCount = ARRAY_SIZE(mExceptionDeviceScopeList);\r
358 */\r
5071fb9c 359\r
7046a273
HW
360 //\r
361 // Sample codes for PCI vendor id based exception list.\r
362 // Uncomment to take affect and comment the sample codes for device scope\r
363 // based exception list.\r
364 //\r
e5d84747 365 /*\r
7046a273
HW
366 *DeviceInfo = AllocateZeroPool (sizeof(mExceptionPciDeviceIdList));\r
367 if (*DeviceInfo == NULL) {\r
368 return EFI_OUT_OF_RESOURCES;\r
5f5bdf4a 369 }\r
7046a273
HW
370 CopyMem (*DeviceInfo, mExceptionPciDeviceIdList, sizeof(mExceptionPciDeviceIdList));\r
371\r
372 *DeviceInfoCount = ARRAY_SIZE(mExceptionPciDeviceIdList);\r
e5d84747
JY
373 */\r
374 return EFI_UNSUPPORTED;\r
5071fb9c
JY
375}\r
376\r
377EDKII_PLATFORM_VTD_POLICY_PROTOCOL mPlatformVTdSample = {\r
378 EDKII_PLATFORM_VTD_POLICY_PROTOCOL_REVISION,\r
379 PlatformVTdGetDeviceId,\r
380 PlatformVTdGetExceptionDeviceList,\r
381};\r
382\r
383/**\r
384 Platform VTd sample driver.\r
385\r
386 @param[in] ImageHandle ImageHandle of the loaded driver\r
387 @param[in] SystemTable Pointer to the System Table\r
388\r
389 @retval EFI_SUCCESS The Protocol is installed.\r
390 @retval EFI_OUT_OF_RESOURCES Not enough resources available to initialize driver.\r
391 @retval EFI_DEVICE_ERROR A device error occurred attempting to initialize the driver.\r
392\r
393**/\r
394EFI_STATUS\r
395EFIAPI\r
396PlatformVTdSampleInitialize (\r
397 IN EFI_HANDLE ImageHandle,\r
398 IN EFI_SYSTEM_TABLE *SystemTable\r
399 )\r
400{\r
401 EFI_STATUS Status;\r
402 EFI_HANDLE Handle;\r
403\r
404 Handle = NULL;\r
405 Status = gBS->InstallMultipleProtocolInterfaces (\r
406 &Handle,\r
407 &gEdkiiPlatformVTdPolicyProtocolGuid, &mPlatformVTdSample,\r
408 NULL\r
409 );\r
410 ASSERT_EFI_ERROR (Status);\r
411\r
412 return Status;\r
413}\r