- EFI_STATUS Status;\r
- UINTN HandleCount;\r
- EFI_HANDLE *HandleBuffer;\r
- UINTN Index;\r
- EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv;\r
- UINTN Key;\r
- EFI_GUID NameGuid;\r
- EFI_FV_FILE_ATTRIBUTES Attributes;\r
- VOID *SourceBuffer;\r
- UINT32 AuthenticationStatus;\r
-\r
- HandleBuffer = NULL;\r
- Status = gBS->LocateHandleBuffer (\r
- ByProtocol,\r
- &gEfiFirmwareVolume2ProtocolGuid,\r
- NULL,\r
- &HandleCount,\r
- &HandleBuffer\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return NULL;\r
- }\r
-\r
- for (Index = 0; Index < HandleCount; Index++) {\r
- Status = gBS->HandleProtocol (\r
- HandleBuffer[Index],\r
- &gEfiFirmwareVolume2ProtocolGuid,\r
- (VOID **)&Fv\r
- );\r
- if (EFI_ERROR (Status)) {\r
- continue;\r
- }\r
-\r
- //\r
- // Use Firmware Volume 2 Protocol to search for a file of type FileType\r
- //\r
- Key = 0; \r
- Status = Fv->GetNextFile (Fv, &Key, &FileType, &NameGuid, &Attributes, SourceSize);\r
- if (EFI_ERROR (Status)) {\r
- continue;\r
- }\r
-\r
- //\r
- // Use Firmware Volume 2 Protocol to read a section of type SectionType\r
- //\r
- SourceBuffer = NULL;\r
- Status = Fv->ReadSection (Fv, &NameGuid, SectionType, 0, &SourceBuffer, SourceSize, &AuthenticationStatus);\r
- if (!EFI_ERROR (Status)) {\r
- FreePool (HandleBuffer);\r
- return SourceBuffer;\r
- }\r
- } \r
-\r
- FreePool(HandleBuffer);\r
- \r
- return NULL;\r
+ UINTN SectionHeaderOffset;\r
+ EFI_STATUS Status;\r
+ EFI_IMAGE_SECTION_HEADER SectionHeader;\r
+ EFI_IMAGE_OPTIONAL_HEADER_UNION *ImgHdr;\r
+ EFI_PHYSICAL_ADDRESS FixLoaddingAddress;\r
+ UINT16 Index;\r
+ UINTN Size;\r
+ UINT16 NumberOfSections;\r
+ EFI_PHYSICAL_ADDRESS SmramBase;\r
+ UINT64 SmmCodeSize;\r
+ UINT64 ValueInSectionHeader;\r
+ //\r
+ // Build tool will calculate the smm code size and then patch the PcdLoadFixAddressSmmCodePageNumber\r
+ //\r
+ SmmCodeSize = EFI_PAGES_TO_SIZE (PcdGet32(PcdLoadFixAddressSmmCodePageNumber));\r
+ \r
+ FixLoaddingAddress = 0;\r
+ Status = EFI_NOT_FOUND;\r
+ SmramBase = mCurrentSmramRange->CpuStart;\r
+ //\r
+ // Get PeHeader pointer\r
+ //\r
+ ImgHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)((CHAR8* )ImageContext->Handle + ImageContext->PeCoffHeaderOffset);\r
+ SectionHeaderOffset = (UINTN)(\r
+ ImageContext->PeCoffHeaderOffset +\r
+ sizeof (UINT32) +\r
+ sizeof (EFI_IMAGE_FILE_HEADER) +\r
+ ImgHdr->Pe32.FileHeader.SizeOfOptionalHeader\r
+ );\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
+ \r
+ Status = EFI_NOT_FOUND;\r
+ \r
+ if ((SectionHeader.Characteristics & EFI_IMAGE_SCN_CNT_CODE) == 0) {\r
+ //\r
+ // Build tool saves the offset to SMRAM base as image base in PointerToRelocations & PointerToLineNumbers fields in the\r
+ // first section header that doesn't point to code section in image header. And there is an assumption that when the\r
+ // feature is enabled, if a module is assigned a loading address by tools, PointerToRelocations & PointerToLineNumbers\r
+ // fields should NOT be Zero, or else, these 2 fileds should be set to Zero\r
+ //\r
+ ValueInSectionHeader = ReadUnaligned64((UINT64*)&SectionHeader.PointerToRelocations);\r
+ if (ValueInSectionHeader != 0) {\r
+ //\r
+ // Found first section header that doesn't point to code section in which uild tool saves the\r
+ // offset to SMRAM base as image base in PointerToRelocations & PointerToLineNumbers fields\r
+ //\r
+ FixLoaddingAddress = (EFI_PHYSICAL_ADDRESS)(SmramBase + (INT64)ValueInSectionHeader);\r
+\r
+ if (SmramBase + SmmCodeSize > FixLoaddingAddress && SmramBase <= FixLoaddingAddress) {\r
+ //\r
+ // The assigned address is valid. Return the specified loadding address\r
+ //\r
+ ImageContext->ImageAddress = FixLoaddingAddress;\r
+ Status = EFI_SUCCESS;\r
+ }\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 %x, Status = %r \n", FixLoaddingAddress, Status));\r
+ return Status;\r