+ @param ImageContext Pointer to the image context structure that describes the PE/COFF\r
+ image that needs to be examined by this function.\r
+ @retval EFI_SUCCESS An fixed loading address is assigned to this image by build tools .\r
+ @retval EFI_NOT_FOUND The image has no assigned fixed loading address.\r
+\r
+**/\r
+EFI_STATUS\r
+GetPeCoffImageFixLoadingAssignedAddress(\r
+ IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext\r
+ )\r
+{\r
+ UINTN SectionHeaderOffset;\r
+ EFI_STATUS Status;\r
+ EFI_IMAGE_SECTION_HEADER SectionHeader;\r
+ EFI_IMAGE_OPTIONAL_HEADER_UNION *ImgHdr;\r
+ UINT16 Index;\r
+ UINTN Size;\r
+ UINT16 NumberOfSections;\r
+ IMAGE_FILE_HANDLE *Handle;\r
+ UINT64 ValueInSectionHeader;\r
+ \r
+\r
+ Status = EFI_NOT_FOUND;\r
+ \r
+ //\r
+ // Get PeHeader pointer\r
+ //\r
+ Handle = (IMAGE_FILE_HANDLE*)ImageContext->Handle;\r
+ ImgHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)((CHAR8* )Handle->Source + ImageContext->PeCoffHeaderOffset);\r
+ SectionHeaderOffset = ImageContext->PeCoffHeaderOffset +\r
+ sizeof (UINT32) +\r
+ sizeof (EFI_IMAGE_FILE_HEADER) +\r
+ ImgHdr->Pe32.FileHeader.SizeOfOptionalHeader;\r
+ NumberOfSections = ImgHdr->Pe32.FileHeader.NumberOfSections;\r
+\r
+ //\r
+ // Get base address from the first section header that doesn't point to code section.\r
+ //\r
+ for (Index = 0; Index < NumberOfSections; Index++) {\r
+ //\r
+ // Read section header from file\r
+ //\r
+ Size = sizeof (EFI_IMAGE_SECTION_HEADER);\r
+ Status = ImageContext->ImageRead (\r
+ ImageContext->Handle,\r
+ SectionHeaderOffset,\r
+ &Size,\r
+ &SectionHeader\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ if (Size != sizeof (EFI_IMAGE_SECTION_HEADER)) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ Status = EFI_NOT_FOUND;\r
+ \r
+ if ((SectionHeader.Characteristics & EFI_IMAGE_SCN_CNT_CODE) == 0) {\r
+ //\r
+ // Build tool will save the address in PointerToRelocations & PointerToLineNumbers fields in the first section header\r
+ // that doesn't point to code section in image header, as well as ImageBase field of image header. And there is an \r
+ // assumption that when the feature is enabled, if a module is assigned a loading address by tools, PointerToRelocations \r
+ // & PointerToLineNumbers fields should NOT be Zero, or else, these 2 fields should be set to Zero\r
+ //\r
+ ValueInSectionHeader = ReadUnaligned64((UINT64*)&SectionHeader.PointerToRelocations);\r
+ if (ValueInSectionHeader != 0) {\r
+ //\r
+ // When the feature is configured as load module at fixed absolute address, the ImageAddress field of ImageContext \r
+ // hold the spcified address. If the feature is configured as load module at fixed offset, ImageAddress hold an offset\r
+ // relative to top address\r
+ //\r
+ if ((INT64)PcdGet64(PcdLoadModuleAtFixAddressEnable) < 0) {\r
+ ImageContext->ImageAddress = gLoadModuleAtFixAddressConfigurationTable.DxeCodeTopAddress + (INT64)(INTN)ImageContext->ImageAddress;\r
+ }\r
+ //\r
+ // Check if the memory range is available.\r
+ //\r
+ Status = CheckAndMarkFixLoadingMemoryUsageBitMap (ImageContext->ImageAddress, (UINTN)(ImageContext->ImageSize + ImageContext->SectionAlignment));\r
+ }\r
+ break; \r
+ }\r
+ SectionHeaderOffset += sizeof (EFI_IMAGE_SECTION_HEADER);\r
+ }\r
+ DEBUG ((EFI_D_INFO|EFI_D_LOAD, "LOADING MODULE FIXED INFO: Loading module at fixed address 0x%11p. Status = %r \n", (VOID *)(UINTN)(ImageContext->ImageAddress), Status));\r
+ return Status;\r
+}\r