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