+ EndPosition = Offset + *ReadSize;\r
+ if (EndPosition > FHand->SourceSize) {\r
+ *ReadSize = (UINT32)(FHand->SourceSize - Offset);\r
+ }\r
+ if (Offset >= FHand->SourceSize) {\r
+ *ReadSize = 0;\r
+ }\r
+\r
+ CopyMem (Buffer, (CHAR8 *)FHand->Source + Offset, *ReadSize);\r
+ return EFI_SUCCESS;\r
+}\r
+/**\r
+ To check memory usage bit map array to figure out if the memory range the image will be loaded in is available or not. If\r
+ memory range is available, the function will mark the corresponding bits to 1 which indicates the memory range is used.\r
+ The function is only invoked when load modules at fixed address feature is enabled. \r
+ \r
+ @param ImageBase The base address the image will be loaded at.\r
+ @param ImageSize The size of the image\r
+ \r
+ @retval EFI_SUCCESS The memory range the image will be loaded in is available\r
+ @retval EFI_NOT_FOUND The memory range the image will be loaded in is not available\r
+**/\r
+EFI_STATUS\r
+CheckAndMarkFixLoadingMemoryUsageBitMap (\r
+ IN EFI_PHYSICAL_ADDRESS ImageBase,\r
+ IN UINTN ImageSize\r
+ )\r
+{\r
+ UINT32 DxeCodePageNumber;\r
+ UINT64 DxeCodeSize; \r
+ EFI_PHYSICAL_ADDRESS DxeCodeBase;\r
+ UINTN BaseOffsetPageNumber;\r
+ UINTN TopOffsetPageNumber;\r
+ UINTN Index;\r
+ //\r
+ // The DXE code range includes RuntimeCodePage range and Boot time code range.\r
+ // \r
+ DxeCodePageNumber = PcdGet32(PcdLoadFixAddressRuntimeCodePageNumber);\r
+ DxeCodePageNumber += PcdGet32(PcdLoadFixAddressBootTimeCodePageNumber);\r
+ DxeCodeSize = EFI_PAGES_TO_SIZE(DxeCodePageNumber);\r
+ DxeCodeBase = gLoadModuleAtFixAddressConfigurationTable.DxeCodeTopAddress - DxeCodeSize;\r
+ \r
+ //\r
+ // If the memory usage bit map is not initialized, do it. Every bit in the array \r
+ // indicate the status of the corresponding memory page, available or not\r
+ // \r
+ if (mDxeCodeMemoryRangeUsageBitMap == NULL) {\r
+ mDxeCodeMemoryRangeUsageBitMap = AllocateZeroPool(((DxeCodePageNumber/64) + 1)*sizeof(UINT64));\r
+ }\r
+ //\r
+ // If the Dxe code memory range is not allocated or the bit map array allocation failed, return EFI_NOT_FOUND\r
+ //\r
+ if (!gLoadFixedAddressCodeMemoryReady || mDxeCodeMemoryRangeUsageBitMap == NULL) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+ //\r
+ // Test the memory range for loading the image in the DXE code range.\r
+ //\r
+ if (gLoadModuleAtFixAddressConfigurationTable.DxeCodeTopAddress < ImageBase + ImageSize ||\r
+ DxeCodeBase > ImageBase) {\r
+ return EFI_NOT_FOUND; \r
+ } \r
+ //\r
+ // Test if the memory is avalaible or not.\r
+ // \r
+ BaseOffsetPageNumber = EFI_SIZE_TO_PAGES((UINT32)(ImageBase - DxeCodeBase));\r
+ TopOffsetPageNumber = EFI_SIZE_TO_PAGES((UINT32)(ImageBase + ImageSize - DxeCodeBase));\r
+ for (Index = BaseOffsetPageNumber; Index < TopOffsetPageNumber; Index ++) {\r
+ if ((mDxeCodeMemoryRangeUsageBitMap[Index / 64] & LShiftU64(1, (Index % 64))) != 0) {\r
+ //\r
+ // This page is already used.\r
+ //\r
+ return EFI_NOT_FOUND; \r
+ }\r
+ }\r
+ \r
+ //\r
+ // Being here means the memory range is available. So mark the bits for the memory range\r
+ // \r
+ for (Index = BaseOffsetPageNumber; Index < TopOffsetPageNumber; Index ++) {\r
+ mDxeCodeMemoryRangeUsageBitMap[Index / 64] |= LShiftU64(1, (Index % 64));\r
+ }\r
+ return EFI_SUCCESS; \r