]> git.proxmox.com Git - mirror_edk2.git/blame - IntelSiliconPkg/Feature/VTd/IntelVTdDxe/BmDma.c
IntelSiliconPkg/Vtd: Add more debug info.
[mirror_edk2.git] / IntelSiliconPkg / Feature / VTd / IntelVTdDxe / BmDma.c
CommitLineData
c049fc99
JY
1/** @file\r
2 BmDma related function\r
3\r
3a716706 4 Copyright (c) 2017 - 2018, Intel Corporation. All rights reserved.<BR>\r
c049fc99
JY
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
3a716706 15#include "DmaProtection.h"\r
c049fc99
JY
16\r
17// TBD: May make it a policy\r
18#define DMA_MEMORY_TOP MAX_UINTN\r
19//#define DMA_MEMORY_TOP 0x0000000001FFFFFFULL\r
20\r
6d2d2e6e
JY
21#define MAP_HANDLE_INFO_SIGNATURE SIGNATURE_32 ('H', 'M', 'A', 'P')\r
22typedef struct {\r
23 UINT32 Signature;\r
24 LIST_ENTRY Link;\r
25 EFI_HANDLE DeviceHandle;\r
26 UINT64 IoMmuAccess;\r
27} MAP_HANDLE_INFO;\r
28#define MAP_HANDLE_INFO_FROM_LINK(a) CR (a, MAP_HANDLE_INFO, Link, MAP_HANDLE_INFO_SIGNATURE)\r
29\r
c049fc99
JY
30#define MAP_INFO_SIGNATURE SIGNATURE_32 ('D', 'M', 'A', 'P')\r
31typedef struct {\r
32 UINT32 Signature;\r
33 LIST_ENTRY Link;\r
34 EDKII_IOMMU_OPERATION Operation;\r
35 UINTN NumberOfBytes;\r
36 UINTN NumberOfPages;\r
37 EFI_PHYSICAL_ADDRESS HostAddress;\r
38 EFI_PHYSICAL_ADDRESS DeviceAddress;\r
6d2d2e6e 39 LIST_ENTRY HandleList;\r
c049fc99
JY
40} MAP_INFO;\r
41#define MAP_INFO_FROM_LINK(a) CR (a, MAP_INFO, Link, MAP_INFO_SIGNATURE)\r
42\r
43LIST_ENTRY gMaps = INITIALIZE_LIST_HEAD_VARIABLE(gMaps);\r
44\r
6d2d2e6e
JY
45/**\r
46 This function fills DeviceHandle/IoMmuAccess to the MAP_HANDLE_INFO,\r
47 based upon the DeviceAddress.\r
48\r
49 @param[in] DeviceHandle The device who initiates the DMA access request.\r
50 @param[in] DeviceAddress The base of device memory address to be used as the DMA memory.\r
51 @param[in] Length The length of device memory address to be used as the DMA memory.\r
52 @param[in] IoMmuAccess The IOMMU access.\r
53\r
54**/\r
55VOID\r
56SyncDeviceHandleToMapInfo (\r
57 IN EFI_HANDLE DeviceHandle,\r
58 IN EFI_PHYSICAL_ADDRESS DeviceAddress,\r
59 IN UINT64 Length,\r
60 IN UINT64 IoMmuAccess\r
61 )\r
62{\r
63 MAP_INFO *MapInfo;\r
64 MAP_HANDLE_INFO *MapHandleInfo;\r
65 LIST_ENTRY *Link;\r
66 EFI_TPL OriginalTpl;\r
67\r
68 //\r
69 // Find MapInfo according to DeviceAddress\r
70 //\r
71 OriginalTpl = gBS->RaiseTPL (VTD_TPL_LEVEL);\r
72 MapInfo = NULL;\r
73 for (Link = GetFirstNode (&gMaps)\r
74 ; !IsNull (&gMaps, Link)\r
75 ; Link = GetNextNode (&gMaps, Link)\r
76 ) {\r
77 MapInfo = MAP_INFO_FROM_LINK (Link);\r
78 if (MapInfo->DeviceAddress == DeviceAddress) {\r
79 break;\r
80 }\r
81 }\r
82 if ((MapInfo == NULL) || (MapInfo->DeviceAddress != DeviceAddress)) {\r
83 DEBUG ((DEBUG_ERROR, "SyncDeviceHandleToMapInfo: DeviceAddress(0x%lx) - not found\n", DeviceAddress));\r
84 gBS->RestoreTPL (OriginalTpl);\r
85 return ;\r
86 }\r
87\r
88 //\r
89 // Find MapHandleInfo according to DeviceHandle\r
90 //\r
91 MapHandleInfo = NULL;\r
92 for (Link = GetFirstNode (&MapInfo->HandleList)\r
93 ; !IsNull (&MapInfo->HandleList, Link)\r
94 ; Link = GetNextNode (&MapInfo->HandleList, Link)\r
95 ) {\r
96 MapHandleInfo = MAP_HANDLE_INFO_FROM_LINK (Link);\r
97 if (MapHandleInfo->DeviceHandle == DeviceHandle) {\r
98 break;\r
99 }\r
100 }\r
101 if ((MapHandleInfo != NULL) && (MapHandleInfo->DeviceHandle == DeviceHandle)) {\r
102 MapHandleInfo->IoMmuAccess = IoMmuAccess;\r
103 gBS->RestoreTPL (OriginalTpl);\r
104 return ;\r
105 }\r
106\r
107 //\r
108 // No DeviceHandle\r
109 // Initialize and insert the MAP_HANDLE_INFO structure\r
110 //\r
111 MapHandleInfo = AllocatePool (sizeof (MAP_HANDLE_INFO));\r
112 if (MapHandleInfo == NULL) {\r
113 DEBUG ((DEBUG_ERROR, "SyncDeviceHandleToMapInfo: %r\n", EFI_OUT_OF_RESOURCES));\r
114 gBS->RestoreTPL (OriginalTpl);\r
115 return ;\r
116 }\r
117\r
118 MapHandleInfo->Signature = MAP_HANDLE_INFO_SIGNATURE;\r
119 MapHandleInfo->DeviceHandle = DeviceHandle;\r
120 MapHandleInfo->IoMmuAccess = IoMmuAccess;\r
121\r
122 InsertTailList (&MapInfo->HandleList, &MapHandleInfo->Link);\r
123 gBS->RestoreTPL (OriginalTpl);\r
124\r
125 return ;\r
126}\r
127\r
c049fc99
JY
128/**\r
129 Provides the controller-specific addresses required to access system memory from a\r
130 DMA bus master.\r
131\r
132 @param This The protocol instance pointer.\r
133 @param Operation Indicates if the bus master is going to read or write to system memory.\r
134 @param HostAddress The system memory address to map to the PCI controller.\r
135 @param NumberOfBytes On input the number of bytes to map. On output the number of bytes\r
136 that were mapped.\r
137 @param DeviceAddress The resulting map address for the bus master PCI controller to use to\r
138 access the hosts HostAddress.\r
139 @param Mapping A resulting value to pass to Unmap().\r
140\r
141 @retval EFI_SUCCESS The range was mapped for the returned NumberOfBytes.\r
142 @retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a common buffer.\r
143 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
144 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
145 @retval EFI_DEVICE_ERROR The system hardware could not map the requested address.\r
146\r
147**/\r
148EFI_STATUS\r
149EFIAPI\r
150IoMmuMap (\r
151 IN EDKII_IOMMU_PROTOCOL *This,\r
152 IN EDKII_IOMMU_OPERATION Operation,\r
153 IN VOID *HostAddress,\r
154 IN OUT UINTN *NumberOfBytes,\r
155 OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,\r
156 OUT VOID **Mapping\r
157 )\r
158{\r
159 EFI_STATUS Status;\r
160 EFI_PHYSICAL_ADDRESS PhysicalAddress;\r
161 MAP_INFO *MapInfo;\r
162 EFI_PHYSICAL_ADDRESS DmaMemoryTop;\r
163 BOOLEAN NeedRemap;\r
3a716706 164 EFI_TPL OriginalTpl;\r
c049fc99 165\r
94fb621d 166 if (NumberOfBytes == NULL || DeviceAddress == NULL ||\r
c049fc99
JY
167 Mapping == NULL) {\r
168 DEBUG ((DEBUG_ERROR, "IoMmuMap: %r\n", EFI_INVALID_PARAMETER));\r
169 return EFI_INVALID_PARAMETER;\r
170 }\r
171\r
94fb621d
JY
172 DEBUG ((DEBUG_VERBOSE, "IoMmuMap: ==> 0x%08x - 0x%08x (%x)\n", HostAddress, *NumberOfBytes, Operation));\r
173\r
c049fc99
JY
174 //\r
175 // Make sure that Operation is valid\r
176 //\r
177 if ((UINT32) Operation >= EdkiiIoMmuOperationMaximum) {\r
178 DEBUG ((DEBUG_ERROR, "IoMmuMap: %r\n", EFI_INVALID_PARAMETER));\r
179 return EFI_INVALID_PARAMETER;\r
180 }\r
181 NeedRemap = FALSE;\r
182 PhysicalAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress;\r
183\r
184 DmaMemoryTop = DMA_MEMORY_TOP;\r
185\r
186 //\r
187 // Alignment check\r
188 //\r
189 if ((*NumberOfBytes != ALIGN_VALUE(*NumberOfBytes, SIZE_4KB)) ||\r
190 (PhysicalAddress != ALIGN_VALUE(PhysicalAddress, SIZE_4KB))) {\r
191 if ((Operation == EdkiiIoMmuOperationBusMasterCommonBuffer) ||\r
192 (Operation == EdkiiIoMmuOperationBusMasterCommonBuffer64)) {\r
193 //\r
194 // The input buffer might be a subset from IoMmuAllocateBuffer.\r
195 // Skip the check.\r
196 //\r
197 } else {\r
198 NeedRemap = TRUE;\r
199 }\r
200 }\r
201\r
202 if ((PhysicalAddress + *NumberOfBytes) >= DMA_MEMORY_TOP) {\r
203 NeedRemap = TRUE;\r
204 }\r
205\r
206 if (((Operation != EdkiiIoMmuOperationBusMasterRead64 &&\r
207 Operation != EdkiiIoMmuOperationBusMasterWrite64 &&\r
208 Operation != EdkiiIoMmuOperationBusMasterCommonBuffer64)) &&\r
209 ((PhysicalAddress + *NumberOfBytes) > SIZE_4GB)) {\r
210 //\r
211 // If the root bridge or the device cannot handle performing DMA above\r
212 // 4GB but any part of the DMA transfer being mapped is above 4GB, then\r
213 // map the DMA transfer to a buffer below 4GB.\r
214 //\r
215 NeedRemap = TRUE;\r
216 DmaMemoryTop = MIN (DmaMemoryTop, SIZE_4GB - 1);\r
217 }\r
218\r
219 if (Operation == EdkiiIoMmuOperationBusMasterCommonBuffer ||\r
220 Operation == EdkiiIoMmuOperationBusMasterCommonBuffer64) {\r
221 if (NeedRemap) {\r
222 //\r
223 // Common Buffer operations can not be remapped. If the common buffer\r
94fb621d 224 // is above 4GB, then it is not possible to generate a mapping, so return\r
c049fc99
JY
225 // an error.\r
226 //\r
227 DEBUG ((DEBUG_ERROR, "IoMmuMap: %r\n", EFI_UNSUPPORTED));\r
228 return EFI_UNSUPPORTED;\r
229 }\r
230 }\r
231\r
232 //\r
233 // Allocate a MAP_INFO structure to remember the mapping when Unmap() is\r
234 // called later.\r
235 //\r
236 MapInfo = AllocatePool (sizeof (MAP_INFO));\r
237 if (MapInfo == NULL) {\r
238 *NumberOfBytes = 0;\r
239 DEBUG ((DEBUG_ERROR, "IoMmuMap: %r\n", EFI_OUT_OF_RESOURCES));\r
240 return EFI_OUT_OF_RESOURCES;\r
241 }\r
242\r
243 //\r
244 // Initialize the MAP_INFO structure\r
245 //\r
246 MapInfo->Signature = MAP_INFO_SIGNATURE;\r
247 MapInfo->Operation = Operation;\r
248 MapInfo->NumberOfBytes = *NumberOfBytes;\r
249 MapInfo->NumberOfPages = EFI_SIZE_TO_PAGES (MapInfo->NumberOfBytes);\r
250 MapInfo->HostAddress = PhysicalAddress;\r
251 MapInfo->DeviceAddress = DmaMemoryTop;\r
6d2d2e6e 252 InitializeListHead(&MapInfo->HandleList);\r
c049fc99
JY
253\r
254 //\r
255 // Allocate a buffer below 4GB to map the transfer to.\r
256 //\r
257 if (NeedRemap) {\r
258 Status = gBS->AllocatePages (\r
259 AllocateMaxAddress,\r
260 EfiBootServicesData,\r
261 MapInfo->NumberOfPages,\r
262 &MapInfo->DeviceAddress\r
263 );\r
264 if (EFI_ERROR (Status)) {\r
265 FreePool (MapInfo);\r
266 *NumberOfBytes = 0;\r
267 DEBUG ((DEBUG_ERROR, "IoMmuMap: %r\n", Status));\r
268 return Status;\r
269 }\r
270\r
271 //\r
272 // If this is a read operation from the Bus Master's point of view,\r
273 // then copy the contents of the real buffer into the mapped buffer\r
274 // so the Bus Master can read the contents of the real buffer.\r
275 //\r
276 if (Operation == EdkiiIoMmuOperationBusMasterRead ||\r
277 Operation == EdkiiIoMmuOperationBusMasterRead64) {\r
278 CopyMem (\r
279 (VOID *) (UINTN) MapInfo->DeviceAddress,\r
280 (VOID *) (UINTN) MapInfo->HostAddress,\r
281 MapInfo->NumberOfBytes\r
282 );\r
283 }\r
284 } else {\r
285 MapInfo->DeviceAddress = MapInfo->HostAddress;\r
286 }\r
287\r
3a716706 288 OriginalTpl = gBS->RaiseTPL (VTD_TPL_LEVEL);\r
c049fc99 289 InsertTailList (&gMaps, &MapInfo->Link);\r
3a716706 290 gBS->RestoreTPL (OriginalTpl);\r
c049fc99
JY
291\r
292 //\r
293 // The DeviceAddress is the address of the maped buffer below 4GB\r
294 //\r
295 *DeviceAddress = MapInfo->DeviceAddress;\r
296 //\r
297 // Return a pointer to the MAP_INFO structure in Mapping\r
298 //\r
299 *Mapping = MapInfo;\r
300\r
301 DEBUG ((DEBUG_VERBOSE, "IoMmuMap: 0x%08x - 0x%08x <==\n", *DeviceAddress, *Mapping));\r
302\r
303 return EFI_SUCCESS;\r
304}\r
305\r
306/**\r
307 Completes the Map() operation and releases any corresponding resources.\r
308\r
309 @param This The protocol instance pointer.\r
310 @param Mapping The mapping value returned from Map().\r
311\r
312 @retval EFI_SUCCESS The range was unmapped.\r
313 @retval EFI_INVALID_PARAMETER Mapping is not a value that was returned by Map().\r
314 @retval EFI_DEVICE_ERROR The data was not committed to the target system memory.\r
315**/\r
316EFI_STATUS\r
317EFIAPI\r
318IoMmuUnmap (\r
319 IN EDKII_IOMMU_PROTOCOL *This,\r
320 IN VOID *Mapping\r
321 )\r
322{\r
323 MAP_INFO *MapInfo;\r
6d2d2e6e 324 MAP_HANDLE_INFO *MapHandleInfo;\r
c049fc99 325 LIST_ENTRY *Link;\r
3a716706 326 EFI_TPL OriginalTpl;\r
c049fc99
JY
327\r
328 DEBUG ((DEBUG_VERBOSE, "IoMmuUnmap: 0x%08x\n", Mapping));\r
329\r
330 if (Mapping == NULL) {\r
331 DEBUG ((DEBUG_ERROR, "IoMmuUnmap: %r\n", EFI_INVALID_PARAMETER));\r
332 return EFI_INVALID_PARAMETER;\r
333 }\r
334\r
3a716706 335 OriginalTpl = gBS->RaiseTPL (VTD_TPL_LEVEL);\r
c049fc99
JY
336 MapInfo = NULL;\r
337 for (Link = GetFirstNode (&gMaps)\r
338 ; !IsNull (&gMaps, Link)\r
339 ; Link = GetNextNode (&gMaps, Link)\r
340 ) {\r
341 MapInfo = MAP_INFO_FROM_LINK (Link);\r
342 if (MapInfo == Mapping) {\r
343 break;\r
344 }\r
345 }\r
346 //\r
347 // Mapping is not a valid value returned by Map()\r
348 //\r
349 if (MapInfo != Mapping) {\r
3a716706 350 gBS->RestoreTPL (OriginalTpl);\r
c049fc99
JY
351 DEBUG ((DEBUG_ERROR, "IoMmuUnmap: %r\n", EFI_INVALID_PARAMETER));\r
352 return EFI_INVALID_PARAMETER;\r
353 }\r
354 RemoveEntryList (&MapInfo->Link);\r
3a716706 355 gBS->RestoreTPL (OriginalTpl);\r
c049fc99 356\r
6d2d2e6e
JY
357 //\r
358 // remove all nodes in MapInfo->HandleList\r
359 //\r
360 while (!IsListEmpty (&MapInfo->HandleList)) {\r
361 MapHandleInfo = MAP_HANDLE_INFO_FROM_LINK (MapInfo->HandleList.ForwardLink);\r
362 RemoveEntryList (&MapHandleInfo->Link);\r
363 FreePool (MapHandleInfo);\r
364 }\r
365\r
c049fc99
JY
366 if (MapInfo->DeviceAddress != MapInfo->HostAddress) {\r
367 //\r
368 // If this is a write operation from the Bus Master's point of view,\r
369 // then copy the contents of the mapped buffer into the real buffer\r
370 // so the processor can read the contents of the real buffer.\r
371 //\r
372 if (MapInfo->Operation == EdkiiIoMmuOperationBusMasterWrite ||\r
373 MapInfo->Operation == EdkiiIoMmuOperationBusMasterWrite64) {\r
374 CopyMem (\r
375 (VOID *) (UINTN) MapInfo->HostAddress,\r
376 (VOID *) (UINTN) MapInfo->DeviceAddress,\r
377 MapInfo->NumberOfBytes\r
378 );\r
379 }\r
380\r
381 //\r
382 // Free the mapped buffer and the MAP_INFO structure.\r
383 //\r
384 gBS->FreePages (MapInfo->DeviceAddress, MapInfo->NumberOfPages);\r
385 }\r
386\r
387 FreePool (Mapping);\r
388 return EFI_SUCCESS;\r
389}\r
390\r
391/**\r
392 Allocates pages that are suitable for an OperationBusMasterCommonBuffer or\r
393 OperationBusMasterCommonBuffer64 mapping.\r
394\r
395 @param This The protocol instance pointer.\r
396 @param Type This parameter is not used and must be ignored.\r
397 @param MemoryType The type of memory to allocate, EfiBootServicesData or\r
398 EfiRuntimeServicesData.\r
399 @param Pages The number of pages to allocate.\r
400 @param HostAddress A pointer to store the base system memory address of the\r
401 allocated range.\r
402 @param Attributes The requested bit mask of attributes for the allocated range.\r
403\r
404 @retval EFI_SUCCESS The requested memory pages were allocated.\r
405 @retval EFI_UNSUPPORTED Attributes is unsupported. The only legal attribute bits are\r
34e18d17 406 MEMORY_WRITE_COMBINE, MEMORY_CACHED and DUAL_ADDRESS_CYCLE.\r
c049fc99
JY
407 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
408 @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated.\r
409\r
410**/\r
411EFI_STATUS\r
412EFIAPI\r
413IoMmuAllocateBuffer (\r
414 IN EDKII_IOMMU_PROTOCOL *This,\r
415 IN EFI_ALLOCATE_TYPE Type,\r
416 IN EFI_MEMORY_TYPE MemoryType,\r
417 IN UINTN Pages,\r
418 IN OUT VOID **HostAddress,\r
419 IN UINT64 Attributes\r
420 )\r
421{\r
422 EFI_STATUS Status;\r
423 EFI_PHYSICAL_ADDRESS PhysicalAddress;\r
424\r
425 DEBUG ((DEBUG_VERBOSE, "IoMmuAllocateBuffer: ==> 0x%08x\n", Pages));\r
426\r
427 //\r
428 // Validate Attributes\r
429 //\r
430 if ((Attributes & EDKII_IOMMU_ATTRIBUTE_INVALID_FOR_ALLOCATE_BUFFER) != 0) {\r
431 DEBUG ((DEBUG_ERROR, "IoMmuAllocateBuffer: %r\n", EFI_UNSUPPORTED));\r
432 return EFI_UNSUPPORTED;\r
433 }\r
434\r
435 //\r
436 // Check for invalid inputs\r
437 //\r
438 if (HostAddress == NULL) {\r
439 DEBUG ((DEBUG_ERROR, "IoMmuAllocateBuffer: %r\n", EFI_INVALID_PARAMETER));\r
440 return EFI_INVALID_PARAMETER;\r
441 }\r
442\r
443 //\r
444 // The only valid memory types are EfiBootServicesData and\r
445 // EfiRuntimeServicesData\r
446 //\r
447 if (MemoryType != EfiBootServicesData &&\r
448 MemoryType != EfiRuntimeServicesData) {\r
449 DEBUG ((DEBUG_ERROR, "IoMmuAllocateBuffer: %r\n", EFI_INVALID_PARAMETER));\r
450 return EFI_INVALID_PARAMETER;\r
451 }\r
452\r
453 PhysicalAddress = DMA_MEMORY_TOP;\r
454 if ((Attributes & EDKII_IOMMU_ATTRIBUTE_DUAL_ADDRESS_CYCLE) == 0) {\r
455 //\r
456 // Limit allocations to memory below 4GB\r
457 //\r
458 PhysicalAddress = MIN (PhysicalAddress, SIZE_4GB - 1);\r
459 }\r
460 Status = gBS->AllocatePages (\r
461 AllocateMaxAddress,\r
462 MemoryType,\r
463 Pages,\r
464 &PhysicalAddress\r
465 );\r
466 if (!EFI_ERROR (Status)) {\r
467 *HostAddress = (VOID *) (UINTN) PhysicalAddress;\r
468 }\r
469\r
470 DEBUG ((DEBUG_VERBOSE, "IoMmuAllocateBuffer: 0x%08x <==\n", *HostAddress));\r
471\r
472 return Status;\r
473}\r
474\r
475/**\r
476 Frees memory that was allocated with AllocateBuffer().\r
477\r
478 @param This The protocol instance pointer.\r
479 @param Pages The number of pages to free.\r
480 @param HostAddress The base system memory address of the allocated range.\r
481\r
482 @retval EFI_SUCCESS The requested memory pages were freed.\r
483 @retval EFI_INVALID_PARAMETER The memory range specified by HostAddress and Pages\r
484 was not allocated with AllocateBuffer().\r
485\r
486**/\r
487EFI_STATUS\r
488EFIAPI\r
489IoMmuFreeBuffer (\r
490 IN EDKII_IOMMU_PROTOCOL *This,\r
491 IN UINTN Pages,\r
492 IN VOID *HostAddress\r
493 )\r
494{\r
495 DEBUG ((DEBUG_VERBOSE, "IoMmuFreeBuffer: 0x%\n", Pages));\r
496 return gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress, Pages);\r
497}\r
498\r
499/**\r
500 Get device information from mapping.\r
501\r
502 @param[in] Mapping The mapping.\r
503 @param[out] DeviceAddress The device address of the mapping.\r
504 @param[out] NumberOfPages The number of pages of the mapping.\r
505\r
506 @retval EFI_SUCCESS The device information is returned.\r
507 @retval EFI_INVALID_PARAMETER The mapping is invalid.\r
508**/\r
509EFI_STATUS\r
510GetDeviceInfoFromMapping (\r
511 IN VOID *Mapping,\r
512 OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,\r
513 OUT UINTN *NumberOfPages\r
514 )\r
515{\r
516 MAP_INFO *MapInfo;\r
517 LIST_ENTRY *Link;\r
518\r
519 if (Mapping == NULL) {\r
520 return EFI_INVALID_PARAMETER;\r
521 }\r
522\r
523 MapInfo = NULL;\r
524 for (Link = GetFirstNode (&gMaps)\r
525 ; !IsNull (&gMaps, Link)\r
526 ; Link = GetNextNode (&gMaps, Link)\r
527 ) {\r
528 MapInfo = MAP_INFO_FROM_LINK (Link);\r
529 if (MapInfo == Mapping) {\r
530 break;\r
531 }\r
532 }\r
533 //\r
534 // Mapping is not a valid value returned by Map()\r
535 //\r
536 if (MapInfo != Mapping) {\r
537 return EFI_INVALID_PARAMETER;\r
538 }\r
539\r
540 *DeviceAddress = MapInfo->DeviceAddress;\r
541 *NumberOfPages = MapInfo->NumberOfPages;\r
542 return EFI_SUCCESS;\r
543}\r
544\r