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