+/**\r
+ Retrieve the AddrTranslationOffset from RootBridgeIo for the\r
+ specified range.\r
+\r
+ @param RootBridgeIo Root Bridge IO instance.\r
+ @param AddrRangeMin The base address of the MMIO.\r
+ @param AddrLen The length of the MMIO.\r
+\r
+ @retval The AddrTranslationOffset from RootBridgeIo for the\r
+ specified range, or (UINT64) -1 if the range is not\r
+ found in RootBridgeIo.\r
+**/\r
+UINT64\r
+GetMmioAddressTranslationOffset (\r
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *RootBridgeIo,\r
+ UINT64 AddrRangeMin,\r
+ UINT64 AddrLen\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Configuration;\r
+\r
+ Status = RootBridgeIo->Configuration (\r
+ RootBridgeIo,\r
+ (VOID **) &Configuration\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return (UINT64) -1;\r
+ }\r
+\r
+ // According to UEFI 2.7, EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL::Configuration()\r
+ // returns host address instead of device address, while AddrTranslationOffset\r
+ // is not zero, and device address = host address + AddrTranslationOffset, so\r
+ // we convert host address to device address for range compare.\r
+ while (Configuration->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR) {\r
+ if ((Configuration->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) &&\r
+ (Configuration->AddrRangeMin + Configuration->AddrTranslationOffset <= AddrRangeMin) &&\r
+ (Configuration->AddrRangeMin + Configuration->AddrLen + Configuration->AddrTranslationOffset >= AddrRangeMin + AddrLen)\r
+ ) {\r
+ return Configuration->AddrTranslationOffset;\r
+ }\r
+ Configuration++;\r
+ }\r
+\r
+ //\r
+ // The resource occupied by BAR should be in the range reported by RootBridge.\r
+ //\r
+ ASSERT (FALSE);\r
+ return (UINT64) -1;\r
+}\r
+\r