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