diff --git a/Tools/CCode/Source/GenFvMap/GenFvMap.cpp b/Tools/CCode/Source/GenFvMap/GenFvMap.cpp new file mode 100644 index 0000000000..4a8c726785 --- /dev/null +++ b/Tools/CCode/Source/GenFvMap/GenFvMap.cpp @@ -0,0 +1,507 @@ +//**************************************************************************** +//** +//** Copyright (C) 2006 Intel Corporation. All rights reserved. +//** +//** The information and source code contained herein is the exclusive +//** property of Intel Corporation and may not be disclosed, examined +//** or reproduced in whole or in part without explicit written authorization +//** from the company. +//** +//**************************************************************************** + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +using namespace std; + +typedef unsigned __int64 ulonglong_t; + +template +class CMemoryLeakChecker : public list +{ +public: + static CMemoryLeakChecker& GetInstance(void); + +private: + CMemoryLeakChecker(void) + { + } + + ~CMemoryLeakChecker(void); +}; + +template +CMemoryLeakChecker& CMemoryLeakChecker::GetInstance(void) +{ + static CMemoryLeakChecker s_memLeakChecker; + return s_memLeakChecker; +} + +template +CMemoryLeakChecker::~CMemoryLeakChecker(void) +{ + if (!list::empty()) + throw logic_error(__FUNCTION__ ": Memory leak detected!"); +} + +class CObjRoot +{ +protected: + CObjRoot(void); + virtual ~CObjRoot(void); +}; + +CObjRoot::CObjRoot(void) +{ + CMemoryLeakChecker::GetInstance().push_back(this); +} + +CObjRoot::~CObjRoot(void) +{ + CMemoryLeakChecker::GetInstance().remove(this); +} + +class CIdentity : public CObjRoot +{ +public: + CIdentity(void); + CIdentity(const string&); + CIdentity(const CIdentity&); + + bool operator < (const CIdentity&) const; + friend istream& operator >> (istream&, CIdentity&); + + static const string::size_type s_nIdStrLen; + +protected: + ulonglong_t m_ullId[2]; +}; + +const string::size_type CIdentity::s_nIdStrLen = 36; + +CIdentity::CIdentity(void) +{ + memset(m_ullId, 0, sizeof(m_ullId)); +} + +CIdentity::CIdentity(const string& strId) +{ + if (strId.length() != CIdentity::s_nIdStrLen || + strId[8] != '-' || + strId[13] != '-' || + strId[18] != '-' || + strId[23] != '-') + throw runtime_error( + __FUNCTION__ ": Error GUID format " + strId); + + string strIdCopy(strId); + strIdCopy.erase(23, 1); + strIdCopy[18] = ' '; + strIdCopy.erase(13, 1); + strIdCopy.erase(8, 1); + + istringstream is(strIdCopy); + is >> hex >> m_ullId[0] >> m_ullId[1]; + if (!is) + throw runtime_error( + __FUNCTION__ ": GUID contains invalid characters" + strId); +} + +CIdentity::CIdentity(const CIdentity& idRight) +{ + memmove(m_ullId, idRight.m_ullId, sizeof(m_ullId)); +} + +bool CIdentity::operator < (const CIdentity& idRight) const +{ + return memcmp(m_ullId, idRight.m_ullId, sizeof(m_ullId)) < 0; +} + +istream& operator >> (istream& is, CIdentity& idRight) +{ + string strId; + is >> strId; + if (!!is) + idRight = CIdentity(strId); + return is; +} + +class CInputFile : public CObjRoot +{ +protected: + CInputFile(const string&); + CInputFile(istream&); + istream& GetLine(string&); + +private: + CInputFile(const CInputFile&); + CInputFile& operator = (const CInputFile&); + +private: + auto_ptr m_pIs; + +protected: + istream& m_is; +}; + +CInputFile::CInputFile(const string& strFName) +: m_pIs(new ifstream(strFName.c_str())) +, m_is(*m_pIs) +{ + if (!m_is) + throw runtime_error(__FUNCTION__ ": Error opening input file " + strFName); +} + +CInputFile::CInputFile(istream& is) +: m_is(is) +{ + if (!m_is) + throw runtime_error(__FUNCTION__ ": Error opening input stream"); +} + +istream& CInputFile::GetLine(string& strALine) +{ + if (!!m_is) + while (!!getline(m_is, strALine)) + { + string::size_type pos = strALine.find_last_not_of(' '); + if (pos != string::npos) + { + strALine.erase(pos + 1); + strALine.erase(0, strALine.find_first_not_of(' ')); + break; + } + } + return m_is; +} + +class CIdAddressMap : public CInputFile, public map +{ +public: + CIdAddressMap(istream&); +}; + +CIdAddressMap::CIdAddressMap(istream& is) +: CInputFile(is) +{ + CIdentity id; + ulonglong_t ullBase; + + while (!!(m_is >> hex >> id >> ullBase)) + if (!insert(value_type(id, ullBase)).second) + throw runtime_error(__FUNCTION__ ": Duplicated files"); +} + +class CIdPathMap : public CInputFile, public map +{ +public: + CIdPathMap(istream&); +}; + +CIdPathMap::CIdPathMap(istream& is) +: CInputFile(is) +{ + static const char cszFileSec[] = "[files]"; + static const char cszFfsFile[] = "EFI_FILE_NAME"; + + string strALine; + + // Find the [files] section + while (!!GetLine(strALine) && strALine.compare(0, sizeof(cszFileSec) - 1, cszFileSec)); + + // m_is error means no FFS files listed in this INF file + if (!m_is) + return; + + // Parse FFS files one by one + while (!!GetLine(strALine)) + { + // Test if this begins a new section + if (strALine[0] == '[') + break; + + // Is it a line of FFS file? + if (strALine.compare(0, sizeof(cszFfsFile) - 1, cszFfsFile)) + continue; + + string::size_type pos = strALine.find_first_not_of(' ', sizeof(cszFfsFile) - 1); + if (pos == string::npos || strALine[pos] != '=') + throw runtime_error(__FUNCTION__ ": Invalid FV INF format"); + pos = strALine.find_first_not_of(' ', pos + 1); + if (pos == string::npos) + throw runtime_error(__FUNCTION__ ": Incomplete line"); + + strALine.erase(0, pos); + pos = strALine.rfind('\\'); + if (pos == string::npos) + pos = 0; + else pos++; + + CIdentity id(strALine.substr(pos, CIdentity::s_nIdStrLen)); + if (!insert(value_type(id, strALine)).second) + throw runtime_error(__FUNCTION__ ": Duplicated FFS files"); + } +} + +class CSymbol : public CObjRoot +{ +public: + string m_strAddress; + string m_strName; + ulonglong_t m_ullRva; + string m_strFrom; + bool m_bStatic; + bool m_bFunction; + + CSymbol() + { + } + CSymbol(const string&, bool = false); + friend ostream& operator << (ostream&, const CSymbol&); +}; + +CSymbol::CSymbol(const string& strALine, bool bStatic) +: m_bStatic(bStatic) +{ + istringstream is(strALine); + + is >> m_strAddress >> m_strName >> hex >> m_ullRva >> m_strFrom; + if (m_strFrom == "F" || m_strFrom == "f") + { + m_bFunction = true; + is >> m_strFrom; + } else m_bFunction = false; +} + +ostream& operator << (ostream& os, const CSymbol& symbol) +{ + os << hex << setw(16) << setfill('0') << symbol.m_ullRva << setw(0); + os << ' ' << (symbol.m_bFunction ? 'F' : ' ') + << (symbol.m_bStatic ? 'S' : ' ') << ' '; + return os << symbol.m_strName << endl; +} + +class CMapFile : public CInputFile, public list +{ +public: + CMapFile(const string&); + + void SetLoadAddress(ulonglong_t); + friend ostream& operator << (ostream&, const CMapFile&); + + string m_strModuleName; + ulonglong_t m_ullLoadAddr; + string m_strEntryPoint; +}; + +CMapFile::CMapFile(const string& strFName) +: CInputFile(strFName) +{ + static const char cszLoadAddr[] = "Preferred load address is"; + static const char cszGlobal[] = "Address"; + static const char cszEntryPoint[] = "entry point at"; + static const char cszStatic[] = "Static symbols"; + + string strALine; + + GetLine(m_strModuleName); + + while (!!GetLine(strALine) && strALine.compare(0, sizeof(cszLoadAddr) - 1, cszLoadAddr)); + if (!m_is) + throw runtime_error(__FUNCTION__ ": Load Address not listed in map file"); + + istringstream is(strALine.substr(sizeof(cszLoadAddr) - 1)); + if (!(is >> hex >> m_ullLoadAddr)) + throw runtime_error(__FUNCTION__ ": Unexpected Load Address format"); + + while (!!GetLine(strALine) && strALine.compare(0, sizeof(cszGlobal) - 1, cszGlobal)); + if (!m_is) + throw runtime_error(__FUNCTION__ ": Global symbols not found in map file"); + + while (!!GetLine(strALine) && strALine.compare(0, sizeof(cszEntryPoint) - 1, cszEntryPoint)) + push_back(CSymbol(strALine)); + if (!m_is) + throw runtime_error(__FUNCTION__ ": Entry Point not listed in map file"); + + is.str(strALine.substr(strALine.find_first_not_of(' ', sizeof(cszEntryPoint) - 1))); + is.clear(); + if (!getline(is, m_strEntryPoint)) + throw runtime_error(__FUNCTION__ ": Unexpected Entry Point format"); + + while (!!GetLine(strALine) && strALine.compare(0, sizeof(cszStatic) - 1, cszStatic)); + while (!!GetLine(strALine)) + push_back(CSymbol(strALine, true)); +} + +void CMapFile::SetLoadAddress(ulonglong_t ullLoadAddr) +{ + for (iterator i = begin(); i != end(); i++) + if (i->m_ullRva != 0) + i->m_ullRva += ullLoadAddr - m_ullLoadAddr; + m_ullLoadAddr = ullLoadAddr; +} + +ostream& operator << (ostream& os, const CMapFile& mapFile) +{ + CMapFile::const_iterator i = mapFile.begin(); + while (i != mapFile.end() && i->m_strAddress != mapFile.m_strEntryPoint) + i++; + if (i == mapFile.end()) + throw runtime_error( + __FUNCTION__ ": Entry point not found for module " + + mapFile.m_strModuleName); + + os << endl << hex + << mapFile.m_strModuleName << " (EP=" << i->m_ullRva + << ", BA=" << mapFile.m_ullLoadAddr << ')' << endl + << endl; + + for (i = mapFile.begin(); i != mapFile.end(); i++) + os << " " << *i; + + return os << endl; +} + +class COutputFile : public CObjRoot +{ +protected: + COutputFile(ostream&); + ostream& m_os; + +private: + COutputFile(const COutputFile&); + COutputFile& operator = (const COutputFile&); +}; + +class CFvMapFile : public CObjRoot, public map +{ +public: + CFvMapFile(const CIdAddressMap&, const CIdPathMap&); + ~CFvMapFile(void); + + friend ostream& operator << (ostream&, const CFvMapFile&); + +private: + void Cleanup(void); +}; + +CFvMapFile::CFvMapFile(const CIdAddressMap& idAddr, const CIdPathMap& idPath) +{ + for (CIdAddressMap::const_iterator i = idAddr.begin(); i != idAddr.end(); i++) + { + CIdPathMap::const_iterator j = idPath.find(i->first); + if (j == idPath.end()) + throw runtime_error(__FUNCTION__ ": Map file not found"); + + try + { + pair k = insert(value_type(i->first, + new CMapFile(j->second.substr(0, j->second.rfind('.')) + ".map"))); + if (!k.second) + throw logic_error(__FUNCTION__ ": Duplicated file found in rebase log"); + + k.first->second->SetLoadAddress(i->second); + } + catch (const runtime_error& e) + { + cerr << e.what() << endl; + } + } +} + +void CFvMapFile::Cleanup(void) +{ + for (iterator i = begin(); i != end(); i++) + delete i->second; +} + +ostream& operator << (ostream& os, const CFvMapFile& fvMap) +{ + for (CFvMapFile::const_iterator i = fvMap.begin(); !!os && i != fvMap.end(); i++) + os << *i->second; + return os; +} + +CFvMapFile::~CFvMapFile(void) +{ + Cleanup(); +} + +class CGenFvMapUsage : public invalid_argument +{ +public: + CGenFvMapUsage(void) : invalid_argument(s_szUsage) + { + } + +private: + static const char s_szUsage[]; +}; + +const char CGenFvMapUsage::s_szUsage[] = "Usage: GenFvMap "; + +class CGenFvMapApp : public CObjRoot +{ +public: + CGenFvMapApp(int, char *[]); + ~CGenFvMapApp(void); + + int Run(void); + +private: + int m_cArgc; + char **m_ppszArgv; +}; + +CGenFvMapApp::CGenFvMapApp(int cArgc, char *ppszArgv[]) +: m_cArgc(cArgc) +, m_ppszArgv(ppszArgv) +{ + if (cArgc != 4) + throw CGenFvMapUsage(); +} + +CGenFvMapApp::~CGenFvMapApp(void) +{ +} + +int CGenFvMapApp::Run(void) +{ + ifstream isLog(m_ppszArgv[1]); + ifstream isInf(m_ppszArgv[2]); + + CIdAddressMap idAddress(isLog); + CIdPathMap idPath(isInf); + + CFvMapFile fvMap(idAddress, idPath); + + ofstream osMap(m_ppszArgv[3], ios_base::out | ios_base::trunc); + osMap << fvMap; + + if (!osMap) + throw runtime_error(__FUNCTION__ ": Error writing output file"); + + return 0; +} + +int main(int argc, char *argv[]) +{ + try + { + CGenFvMapApp app(argc, argv); + return app.Run(); + } + catch (const exception& e) + { + cerr << e.what() << endl; + return -1; + } +} diff --git a/Tools/CCode/Source/GenFvMap/build.xml b/Tools/CCode/Source/GenFvMap/build.xml new file mode 100644 index 0000000000..6c236bf979 --- /dev/null +++ b/Tools/CCode/Source/GenFvMap/build.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Tools/CCode/Source/PeiRebase/PeiRebaseExe.c b/Tools/CCode/Source/PeiRebase/PeiRebaseExe.c index 2d28a83066..11192c428b 100644 --- a/Tools/CCode/Source/PeiRebase/PeiRebaseExe.c +++ b/Tools/CCode/Source/PeiRebase/PeiRebaseExe.c @@ -1,8 +1,8 @@ /*++ Copyright (c) 1999-2006 Intel Corporation. All rights reserved -This program and the accompanying materials are licensed and made available -under the terms and conditions of the BSD License which accompanies this +This program and the accompanying materials are licensed and made available +under the terms and conditions of the BSD License which accompanies this distribution. The full text of the license may be found at http://opensource.org/licenses/bsd-license.php @@ -59,23 +59,21 @@ Arguments: argc - Number of command line arguments argv[]: - BaseAddress The base address to use for rebasing the FV. The correct + BaseAddress The base address to use for rebasing the FV. The correct format is a hex number preceded by 0x. InputFileName The name of the input FV file. OutputFileName The name of the output FV file. - MapFileName The name of the map file of relocation info. Arguments come in pair in any order. - -I InputFileName + -I InputFileName -O OutputFileName - -B BaseAddress - -M MapFileName + -B BaseAddress Returns: 0 No error conditions detected. 1 One or more of the input parameters is invalid. - 2 A resource required by the utility was unavailable. + 2 A resource required by the utility was unavailable. Most commonly this will be memory allocation or file creation. 3 PeiRebase.dll could not be loaded. 4 Error executing the PEI rebase. @@ -84,14 +82,13 @@ Returns: { UINT8 Index; CHAR8 InputFileName[_MAX_PATH]; - CHAR8 OutputFileName[_MAX_PATH]; - CHAR8 MapFileName[_MAX_PATH]; - EFI_PHYSICAL_ADDRESS BaseAddress; - BOOLEAN BaseAddressSet; + CHAR8 *OutputFileName; + EFI_PHYSICAL_ADDRESS XipBase, BsBase, RtBase; + UINT32 BaseTypes; EFI_STATUS Status; FILE *InputFile; FILE *OutputFile; - FILE *MapFile; + FILE *LogFile; UINT64 FvOffset; UINT32 FileCount; int BytesRead; @@ -99,11 +96,8 @@ Returns: UINT32 FvSize; EFI_FFS_FILE_HEADER *CurrentFile; BOOLEAN ErasePolarity; - EFI_PHYSICAL_ADDRESS CurrentFileBaseAddress; - CHAR8 InfFileName[_MAX_PATH]; - CHAR8 *InfFileImage; - UINTN InfFileSize; MEMORY_FILE InfMemoryFile; + CHAR8 StringBuffer[0x100]; ErasePolarity = FALSE; // @@ -121,21 +115,17 @@ Returns: // // Initialize variables // - InputFileName[0] = 0; - OutputFileName[0] = 0; - MapFileName[0] = 0; - BaseAddress = 0; - BaseAddressSet = FALSE; + InputFileName[0] = '\0'; + OutputFileName = NULL; + XipBase = BsBase = RtBase = 0; + BaseTypes = 0; FvOffset = 0; FileCount = 0; ErasePolarity = FALSE; InputFile = NULL; OutputFile = NULL; - MapFile = NULL; + LogFile = NULL; FvImage = NULL; - InfFileImage = NULL; - InfFileSize = 0; - strcpy (InfFileName, ""); // // Parse the command line arguments @@ -156,7 +146,7 @@ Returns: PrintUsage (); Error (NULL, 0, 0, argv[Index], "unrecognized option"); return STATUS_ERROR; - } + } // // Determine argument to read // @@ -174,8 +164,8 @@ Returns: case 'O': case 'o': - if (strlen (OutputFileName) == 0) { - strcpy (OutputFileName, argv[Index + 1]); + if (OutputFileName == NULL) { + OutputFileName = argv[Index + 1]; } else { PrintUsage (); Error (NULL, 0, 0, argv[Index + 1], "only one -o OutputFileName may be specified"); @@ -183,79 +173,86 @@ Returns: } break; - case 'B': - case 'b': - if (!BaseAddressSet) { - Status = AsciiStringToUint64 (argv[Index + 1], FALSE, &BaseAddress); - if (EFI_ERROR (Status)) { - PrintUsage (); - Error (NULL, 0, 0, argv[Index + 1], "invalid hex digit given for the base address"); - return STATUS_ERROR; - } - - BaseAddressSet = TRUE; - } else { - PrintUsage (); - Error (NULL, 0, 0, argv[Index + 1], "-b BaseAddress may only be specified once"); - return STATUS_ERROR; - } - break; - case 'F': case 'f': - if (!BaseAddressSet) { - strcpy (InfFileName, argv[Index + 1]); - // - // Read the INF file image - // - Status = GetFileImage (InfFileName, &InfFileImage, &InfFileSize); - if (EFI_ERROR (Status)) { - PrintUsage (); - Error (NULL, 0, 0, argv[Index + 1], "-f FvInfFile can't be opened."); - return STATUS_ERROR; - } - // - // Initialize file structures - // - InfMemoryFile.FileImage = InfFileImage; - InfMemoryFile.CurrentFilePointer = InfFileImage; - InfMemoryFile.Eof = InfFileImage + InfFileSize; - // - // Read BaseAddress from fv.inf file. - // - FindToken (&InfMemoryFile, "[options]", "EFI_BASE_ADDRESS", 0, InfFileName); - // - // free Inf File Image - // - free (InfFileImage); - - // - // Convert string to UINT64 base address. - // - Status = AsciiStringToUint64 (InfFileName, FALSE, &BaseAddress); - if (EFI_ERROR (Status)) { - PrintUsage (); - Error (NULL, 0, 0, argv[Index + 1], "can't find the base address in the specified fv.inf file."); - return STATUS_ERROR; - } - - BaseAddressSet = TRUE; - } else { - PrintUsage (); - Error (NULL, 0, 0, argv[Index + 1], "BaseAddress has been got once from fv.inf or the specified base address."); + // + // Load INF file into memory & initialize MEMORY_FILE structure + // + Status = GetFileImage (argv[Index + 1], &InfMemoryFile.FileImage, (UINT32*)&InfMemoryFile.Eof); + InfMemoryFile.Eof = InfMemoryFile.FileImage + (UINT32)(UINTN)InfMemoryFile.Eof; + InfMemoryFile.CurrentFilePointer = InfMemoryFile.FileImage; + if (EFI_ERROR (Status)) { + Error (NULL, 0, 0, argv[Index + 1], "Error opening FvInfFile"); return STATUS_ERROR; } + + // + // Read BaseAddress from fv.inf file + // + FindToken (&InfMemoryFile, "[options]", "EFI_BASE_ADDRESS", 0, StringBuffer); + + // + // Free INF file image + // + free (InfMemoryFile.FileImage); + + // + // Point argv[Index + 1] to StringBuffer so that it could be processed as "-b" + // + argv[Index + 1] = StringBuffer; + + case 'B': + case 'b': + if (BaseTypes & 1) { + PrintUsage (); + Error (NULL, 0, 0, argv[Index + 1], "XipBaseAddress may be specified only once by either -b or -f"); + return STATUS_ERROR; + } + + Status = AsciiStringToUint64 (argv[Index + 1], FALSE, &XipBase); + if (EFI_ERROR (Status)) { + PrintUsage (); + Error (NULL, 0, 0, argv[Index + 1], "invalid hex digit given for XIP base address"); + return STATUS_ERROR; + } + + BaseTypes |= 1; break; - case 'M': - case 'm': - if (strlen (MapFileName) == 0) { - strcpy (MapFileName, argv[Index + 1]); - } else { + case 'D': + case 'd': + if (BaseTypes & 2) { PrintUsage (); - Error (NULL, 0, 0, argv[Index + 1], "only one -m MapFileName may be specified"); + Error (NULL, 0, 0, argv[Index + 1], "-d BsBaseAddress may be specified only once"); return STATUS_ERROR; } + + Status = AsciiStringToUint64 (argv[Index + 1], FALSE, &BsBase); + if (EFI_ERROR (Status)) { + PrintUsage (); + Error (NULL, 0, 0, argv[Index + 1], "invalid hex digit given for BS_DRIVER base address"); + return STATUS_ERROR; + } + + BaseTypes |= 2; + break; + + case 'R': + case 'r': + if (BaseTypes & 4) { + PrintUsage (); + Error (NULL, 0, 0, argv[Index + 1], "-r RtBaseAddress may be specified only once"); + return STATUS_ERROR; + } + + Status = AsciiStringToUint64 (argv[Index + 1], FALSE, &RtBase); + if (EFI_ERROR (Status)) { + PrintUsage (); + Error (NULL, 0, 0, argv[Index + 1], "invalid hex digit given for RT_DRIVER base address"); + return STATUS_ERROR; + } + + BaseTypes |= 4; break; default: @@ -265,18 +262,6 @@ Returns: break; } } - - // - // Create the Map file if we need it - // - if (strlen (MapFileName) != 0) { - MapFile = fopen (MapFileName, "w"); - if (MapFile == NULL) { - Error (NULL, 0, 0, MapFileName, "failed to open map file"); - goto Finish; - } - } - // // Open the file containing the FV // @@ -285,6 +270,16 @@ Returns: Error (NULL, 0, 0, InputFileName, "could not open input file for reading"); return STATUS_ERROR; } + + // + // Open the log file + // + strcat (InputFileName, ".log"); + LogFile = fopen (InputFileName, "a"); + if (LogFile == NULL) { + Error (NULL, 0, 0, InputFileName, "could not append to log file"); + } + // // Determine size of FV // @@ -330,8 +325,14 @@ Returns: // // Rebase this file // - CurrentFileBaseAddress = BaseAddress + ((UINTN) CurrentFile - (UINTN) FvImage); - Status = FfsRebase (CurrentFile, CurrentFileBaseAddress, MapFile); + FfsRebase ( + CurrentFile, + BaseTypes, + XipBase + (UINTN)CurrentFile - (UINTN)FvImage, + &BsBase, + &RtBase, + LogFile + ); if (EFI_ERROR (Status)) { switch (Status) { @@ -359,7 +360,6 @@ Returns: goto Finish; } - // // Get the next file // @@ -399,8 +399,8 @@ Finish: fclose (OutputFile); } - if (MapFile != NULL) { - fclose (MapFile); + if (LogFile != NULL) { + fclose (LogFile); } if (FvImage != NULL) { @@ -420,7 +420,7 @@ ReadHeader ( Routine Description: - This function determines the size of the FV and the erase polarity. The + This function determines the size of the FV and the erase polarity. The erase polarity is the FALSE value for file state. Arguments: @@ -428,9 +428,9 @@ Arguments: InputFile The file that contains the FV image. FvSize The size of the FV. ErasePolarity The FV erase polarity. - + Returns: - + EFI_SUCCESS Function completed successfully. EFI_INVALID_PARAMETER A required parameter was NULL or is out of range. EFI_ABORTED The function encountered an error. @@ -539,38 +539,36 @@ Returns: --*/ { printf ( - "Usage: %s -I InputFileName -O OutputFileName [-B BaseAddress] -F FvInfFileName -M MapFile\n", + "Usage: %s -I InputFileName -O OutputFileName -B BaseAddress\n", UTILITY_NAME ); printf (" Where:\n"); - printf (" InputFileName is the name of the EFI FV file to rebase.\n"); + printf (" InputFileName is the name of the EFI FV file to rebase.\n"); printf (" OutputFileName is the desired output file name.\n"); - printf (" BaseAddress is the FV base address to rebase agains.\n"); - printf (" FvInfFileName is the fv.inf to be used to generate this fv image.\n"); - printf (" BaseAddress can also be got from the fv.inf file.\n"); - printf (" Choose only one method to input BaseAddress.\n"); - printf (" MapFileName is an optional map file of the relocations\n"); - printf (" Argument pair may be in any order.\n\n"); + printf (" BaseAddress is the FV base address to rebase agains.\n"); + printf (" Argument pair may be in any order.\n\n"); } EFI_STATUS FfsRebase ( - IN OUT EFI_FFS_FILE_HEADER *FfsFile, - IN EFI_PHYSICAL_ADDRESS BaseAddress, - IN FILE *MapFile OPTIONAL + IN OUT EFI_FFS_FILE_HEADER *FfsFile, + IN UINT32 Flags, + IN OUT EFI_PHYSICAL_ADDRESS XipBase, + IN OUT EFI_PHYSICAL_ADDRESS *BsBase, + IN OUT EFI_PHYSICAL_ADDRESS *RtBase, + OUT FILE *LogFile ) /*++ Routine Description: - This function determines if a file is XIP and should be rebased. It will + This function determines if a file is XIP and should be rebased. It will rebase any PE32 sections found in the file using the base address. - + Arguments: FfsFile A pointer to Ffs file image. BaseAddress The base address to use for rebasing the file image. - MapFile Optional file to dump relocation information into Returns: @@ -590,20 +588,21 @@ Returns: UINT64 ImageSize; EFI_PHYSICAL_ADDRESS EntryPoint; UINT32 Pe32ImageSize; - UINT32 NewPe32BaseAddress; + EFI_PHYSICAL_ADDRESS NewPe32BaseAddress; UINTN Index; EFI_FILE_SECTION_POINTER CurrentPe32Section; EFI_FFS_FILE_STATE SavedState; - EFI_IMAGE_NT_HEADERS *PeHdr; + EFI_IMAGE_NT_HEADERS32 *PeHdr; + EFI_IMAGE_NT_HEADERS64 *PePlusHdr; UINT32 *PeHdrSizeOfImage; UINT32 *PeHdrChecksum; - UINT32 FoundCount; EFI_TE_IMAGE_HEADER *TEImageHeader; UINT8 *TEBuffer; EFI_IMAGE_DOS_HEADER *DosHeader; UINT8 FileGuidString[80]; UINT32 TailSize; EFI_FFS_FILE_TAIL TailValue; + EFI_PHYSICAL_ADDRESS *BaseToUpdate; // // Verify input parameters @@ -611,7 +610,6 @@ Returns: if (FfsFile == NULL) { return EFI_INVALID_PARAMETER; } - // // Convert the GUID to a string so we can at least report which file // if we find an error. @@ -622,7 +620,6 @@ Returns: } else { TailSize = 0; } - // // Do some cursory checks on the FFS file contents // @@ -632,36 +629,31 @@ Returns: return EFI_INVALID_PARAMETER; } - memset (&ImageContext, 0, sizeof (ImageContext)); - // - // Check if XIP file type. If not XIP, don't rebase. + // We only process files potentially containing PE32 sections. // - if (FfsFile->Type != EFI_FV_FILETYPE_PEI_CORE && - FfsFile->Type != EFI_FV_FILETYPE_PEIM && - FfsFile->Type != EFI_FV_FILETYPE_SECURITY_CORE && - FfsFile->Type != EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER - ) { - return EFI_SUCCESS; + switch (FfsFile->Type) { + case EFI_FV_FILETYPE_SECURITY_CORE: + case EFI_FV_FILETYPE_PEI_CORE: + case EFI_FV_FILETYPE_PEIM: + case EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER: + case EFI_FV_FILETYPE_DRIVER: + case EFI_FV_FILETYPE_DXE_CORE: + break; + default: + return EFI_SUCCESS; } // // Rebase each PE32 section // Status = EFI_SUCCESS; - FoundCount = 0; for (Index = 1;; Index++) { Status = GetSectionByType (FfsFile, EFI_SECTION_PE32, Index, &CurrentPe32Section); if (EFI_ERROR (Status)) { break; } - FoundCount++; - - // - // Calculate the PE32 base address, the FFS file base plus the offset of the PE32 section - // - NewPe32BaseAddress = ((UINT32) BaseAddress) + ((UINTN) CurrentPe32Section.Pe32Section + sizeof (EFI_COMMON_SECTION_HEADER) - (UINTN) FfsFile); // // Initialize context @@ -669,25 +661,102 @@ Returns: memset (&ImageContext, 0, sizeof (ImageContext)); ImageContext.Handle = (VOID *) ((UINTN) CurrentPe32Section.Pe32Section + sizeof (EFI_PE32_SECTION)); ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE) FfsRebaseImageRead; - Status = PeCoffLoaderGetImageInfo (&ImageContext); - if (EFI_ERROR (Status)) { Error (NULL, 0, 0, "GetImageInfo() call failed on rebase", FileGuidString); return Status; } + + // + // Calculate the PE32 base address, based on file type + // + switch (FfsFile->Type) { + case EFI_FV_FILETYPE_SECURITY_CORE: + case EFI_FV_FILETYPE_PEI_CORE: + case EFI_FV_FILETYPE_PEIM: + case EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER: + if ((Flags & 1) == 0) { + // + // We aren't relocating XIP code, so skip it. + // + return EFI_SUCCESS; + } + + NewPe32BaseAddress = + XipBase + + (UINTN)CurrentPe32Section.Pe32Section + + sizeof (EFI_COMMON_SECTION_HEADER) - + (UINTN)FfsFile; + BaseToUpdate = &XipBase; + break; + + case EFI_FV_FILETYPE_DRIVER: + PeHdr = (EFI_IMAGE_NT_HEADERS32*)( + (UINTN)CurrentPe32Section.Pe32Section + + sizeof (EFI_COMMON_SECTION_HEADER) + + ImageContext.PeCoffHeaderOffset + ); + switch (PeHdr->OptionalHeader.Subsystem) { + case EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER: + if ((Flags & 4) == 0) { + // + // RT drivers aren't supposed to be relocated + // + continue; + } + + NewPe32BaseAddress = *RtBase; + BaseToUpdate = RtBase; + break; + + default: + // + // We treat all other subsystems the same as BS_DRIVER + // + if ((Flags & 2) == 0) { + // + // Skip all BS_DRIVER's + // + continue; + } + + NewPe32BaseAddress = *BsBase; + BaseToUpdate = BsBase; + break; + } + break; + + case EFI_FV_FILETYPE_DXE_CORE: + if ((Flags & 2) == 0) { + // + // Skip DXE core + // + return EFI_SUCCESS; + } + + NewPe32BaseAddress = *BsBase; + BaseToUpdate = BsBase; + break; + + default: + // + // Not supported file type + // + return EFI_SUCCESS; + } + // // Allocate a buffer for the image to be loaded into. // Pe32ImageSize = GetLength (CurrentPe32Section.Pe32Section->CommonHeader.Size) - sizeof (EFI_PE32_SECTION); - MemoryImagePointer = (UINTN) (malloc (Pe32ImageSize + 0x10000)); + MemoryImagePointer = (UINTN) (malloc (Pe32ImageSize + 0x1000)); if (MemoryImagePointer == 0) { Error (NULL, 0, 0, "memory allocation failure", NULL); return EFI_OUT_OF_RESOURCES; } - memset ((void *) MemoryImagePointer, 0, Pe32ImageSize + 0x10000); - MemoryImagePointerAligned = (MemoryImagePointer + 0x0FFFF) & (-1 << 16); - + memset ((void *) MemoryImagePointer, 0, Pe32ImageSize + 0x1000); + MemoryImagePointerAligned = (MemoryImagePointer + 0x0FFF) & (-1 << 12); + ImageContext.ImageAddress = MemoryImagePointerAligned; @@ -697,24 +766,6 @@ Returns: free ((VOID *) MemoryImagePointer); return Status; } - - // - // Check if section-alignment and file-alignment match or not - // - if (!(ImageContext.IsTeImage)) { - PeHdr = (EFI_IMAGE_NT_HEADERS *)((UINTN)ImageContext.ImageAddress + - ImageContext.PeCoffHeaderOffset); - if (PeHdr->OptionalHeader.SectionAlignment != PeHdr->OptionalHeader.FileAlignment) { - Error (NULL, 0, 0, "Section-Alignment and File-Alignment does not match", FileGuidString); - free ((VOID *) MemoryImagePointer); - return EFI_ABORTED; - } - } - else { - // - // BUGBUG: TE Image Header lack section-alignment and file-alignment info - // - } ImageContext.DestinationAddress = NewPe32BaseAddress; Status = PeCoffLoaderRelocateImage (&ImageContext); @@ -742,21 +793,34 @@ Returns: free ((VOID *) MemoryImagePointer); return EFI_ABORTED; } + + // + // Update BASE address + // + fprintf ( + LogFile, + "%s %016I64X\n", + FileGuidString, + ImageContext.DestinationAddress + ); + *BaseToUpdate += EFI_SIZE_TO_PAGES (ImageContext.ImageSize) * EFI_PAGE_SIZE; + // // Since we may have updated the Codeview RVA, we need to insure the PE // header indicates the image is large enough to contain the Codeview data // so it will be loaded properly later if the PEIM is reloaded into memory... // PeHdr = (VOID *) ((UINTN) ImageAddress + ImageContext.PeCoffHeaderOffset); + PePlusHdr = (EFI_IMAGE_NT_HEADERS64*)PeHdr; if (PeHdr->FileHeader.Machine == EFI_IMAGE_MACHINE_IA32) { - PeHdrSizeOfImage = (UINT32 *) (&(*(EFI_IMAGE_OPTIONAL_HEADER32 *) &PeHdr->OptionalHeader).SizeOfImage); - PeHdrChecksum = (UINT32 *) (&(*(EFI_IMAGE_OPTIONAL_HEADER32 *) &PeHdr->OptionalHeader).CheckSum); + PeHdrSizeOfImage = (UINT32 *) (&(PeHdr->OptionalHeader).SizeOfImage); + PeHdrChecksum = (UINT32 *) (&(PeHdr->OptionalHeader).CheckSum); } else if (PeHdr->FileHeader.Machine == EFI_IMAGE_MACHINE_IA64) { - PeHdrSizeOfImage = (UINT32 *) (&(*(EFI_IMAGE_OPTIONAL_HEADER64 *) &PeHdr->OptionalHeader).SizeOfImage); - PeHdrChecksum = (UINT32 *) (&(*(EFI_IMAGE_OPTIONAL_HEADER64 *) &PeHdr->OptionalHeader).CheckSum); + PeHdrSizeOfImage = (UINT32 *) (&(PePlusHdr->OptionalHeader).SizeOfImage); + PeHdrChecksum = (UINT32 *) (&(PePlusHdr->OptionalHeader).CheckSum); } else if (PeHdr->FileHeader.Machine == EFI_IMAGE_MACHINE_X64) { - PeHdrSizeOfImage = (UINT32 *) (&(*(EFI_IMAGE_OPTIONAL_HEADER64 *) &PeHdr->OptionalHeader).SizeOfImage); - PeHdrChecksum = (UINT32 *) (&(*(EFI_IMAGE_OPTIONAL_HEADER64 *) &PeHdr->OptionalHeader).CheckSum); + PeHdrSizeOfImage = (UINT32 *) (&(PePlusHdr->OptionalHeader).SizeOfImage); + PeHdrChecksum = (UINT32 *) (&(PePlusHdr->OptionalHeader).CheckSum); } else { Error ( NULL, @@ -779,24 +843,6 @@ Returns: } memcpy (CurrentPe32Section.Pe32Section + 1, (VOID *) MemoryImagePointerAligned, (UINT32) ImageSize); - - // - // Get EntryPoint in Flash Region. - // - EntryPoint = NewPe32BaseAddress + EntryPoint - ImageAddress; - - // - // If a map file was selected output mapping information for any file that - // was rebased. - // - if (MapFile != NULL) { - fprintf (MapFile, "PE32 File: %s Base:%08lx", FileGuidString, BaseAddress); - fprintf (MapFile, " EntryPoint:%08lx", EntryPoint); - if (ImageContext.PdbPointer != NULL) { - fprintf (MapFile, " FileName: %s", ImageContext.PdbPointer); - } - fprintf (MapFile, "\n"); - } free ((VOID *) MemoryImagePointer); @@ -832,6 +878,20 @@ Returns: *(EFI_FFS_FILE_TAIL *) (((UINTN) FfsFile + GetLength (FfsFile->Size) - sizeof (EFI_FFS_FILE_TAIL))) = TailValue; } } + + if ((Flags & 1) == 0 || ( + FfsFile->Type != EFI_FV_FILETYPE_SECURITY_CORE && + FfsFile->Type != EFI_FV_FILETYPE_PEI_CORE && + + FfsFile->Type != EFI_FV_FILETYPE_PEIM && + FfsFile->Type != EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER + )) { + // + // Only XIP code may have a TE section + // + return EFI_SUCCESS; + } + // // Now process TE sections // @@ -841,15 +901,13 @@ Returns: break; } - FoundCount++; - // // Calculate the TE base address, the FFS file base plus the offset of the TE section less the size stripped off // by GenTEImage // TEImageHeader = (EFI_TE_IMAGE_HEADER *) ((UINT8 *) CurrentPe32Section.Pe32Section + sizeof (EFI_COMMON_SECTION_HEADER)); - NewPe32BaseAddress = ((UINT32) BaseAddress) + + NewPe32BaseAddress = ((UINT32) XipBase) + ( (UINTN) CurrentPe32Section.Pe32Section + sizeof (EFI_COMMON_SECTION_HEADER) + @@ -880,6 +938,7 @@ Returns: DosHeader->e_magic = EFI_IMAGE_DOS_SIGNATURE; *(UINT32 *) (TEBuffer + 0x3C) = 0x40; PeHdr = (EFI_IMAGE_NT_HEADERS *) (TEBuffer + 0x40); + PePlusHdr = (EFI_IMAGE_NT_HEADERS64*)PeHdr; PeHdr->Signature = EFI_IMAGE_NT_SIGNATURE; PeHdr->FileHeader.Machine = TEImageHeader->Machine; PeHdr->FileHeader.NumberOfSections = TEImageHeader->NumberOfSections; @@ -889,39 +948,89 @@ Returns: // the 0x40 bytes for our DOS header. // PeHdr->FileHeader.SizeOfOptionalHeader = (UINT16) (TEImageHeader->StrippedSize - 0x40 - sizeof (UINT32) - sizeof (EFI_IMAGE_FILE_HEADER)); - PeHdr->OptionalHeader.ImageBase = (UINTN) (TEImageHeader->ImageBase - TEImageHeader->StrippedSize + sizeof (EFI_TE_IMAGE_HEADER)); - PeHdr->OptionalHeader.AddressOfEntryPoint = TEImageHeader->AddressOfEntryPoint; - PeHdr->OptionalHeader.BaseOfCode = TEImageHeader->BaseOfCode; - PeHdr->OptionalHeader.SizeOfImage = Pe32ImageSize; - PeHdr->OptionalHeader.Subsystem = TEImageHeader->Subsystem; - PeHdr->OptionalHeader.SizeOfImage = Pe32ImageSize; - PeHdr->OptionalHeader.SizeOfHeaders = TEImageHeader->StrippedSize + TEImageHeader->NumberOfSections * - sizeof (EFI_IMAGE_SECTION_HEADER) - 12; - - // - // Set NumberOfRvaAndSizes in the optional header to what we had available in the original image - // - if ((TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress != 0) || - (TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size != 0) - ) { - PeHdr->OptionalHeader.NumberOfRvaAndSizes = EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC + 1; - PeHdr->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress; - PeHdr->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size; + if (TEImageHeader->Machine == EFI_IMAGE_MACHINE_IA32) { + PeHdr->OptionalHeader.Magic = EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC; + } else if (TEImageHeader->Machine == EFI_IMAGE_MACHINE_IA64) { + PePlusHdr->OptionalHeader.Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC; + } else if (TEImageHeader->Machine == EFI_IMAGE_MACHINE_X64) { + PePlusHdr->OptionalHeader.Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC; + } else { + Error ( + NULL, + 0, + 0, + "unknown machine type in TE image", + "machine type=0x%X, file=%s", + (UINT32) TEImageHeader->Machine, + FileGuidString + ); + free (TEBuffer); + return EFI_ABORTED; } - if ((TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress != 0) || - (TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].Size != 0) - ) { - PeHdr->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress = TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress; - PeHdr->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size = TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].Size; - if (PeHdr->OptionalHeader.NumberOfRvaAndSizes < EFI_IMAGE_DIRECTORY_ENTRY_DEBUG + 1) { - PeHdr->OptionalHeader.NumberOfRvaAndSizes = EFI_IMAGE_DIRECTORY_ENTRY_DEBUG + 1; + if (PeHdr->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { + PeHdr->OptionalHeader.ImageBase = (UINTN) (TEImageHeader->ImageBase - TEImageHeader->StrippedSize + sizeof (EFI_TE_IMAGE_HEADER)); + PeHdr->OptionalHeader.SizeOfImage = Pe32ImageSize; + PeHdr->OptionalHeader.Subsystem = TEImageHeader->Subsystem; + PeHdr->OptionalHeader.SizeOfHeaders = TEImageHeader->StrippedSize + TEImageHeader->NumberOfSections * + sizeof (EFI_IMAGE_SECTION_HEADER) - 12; + + // + // Set NumberOfRvaAndSizes in the optional header to what we had available in the original image + // + if ((TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress != 0) || + (TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size != 0) + ) { + PeHdr->OptionalHeader.NumberOfRvaAndSizes = EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC + 1; + PeHdr->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress; + PeHdr->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size; } + + if ((TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress != 0) || + (TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].Size != 0) + ) { + PeHdr->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress = TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress; + PeHdr->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size = TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].Size; + if (PeHdr->OptionalHeader.NumberOfRvaAndSizes < EFI_IMAGE_DIRECTORY_ENTRY_DEBUG + 1) { + PeHdr->OptionalHeader.NumberOfRvaAndSizes = EFI_IMAGE_DIRECTORY_ENTRY_DEBUG + 1; + } + } + // + // NOTE: These values are defaults, and should be verified to be correct in the GenTE utility + // + PeHdr->OptionalHeader.SectionAlignment = 0x10; + } else { + PePlusHdr->OptionalHeader.ImageBase = (UINTN) (TEImageHeader->ImageBase - TEImageHeader->StrippedSize + sizeof (EFI_TE_IMAGE_HEADER)); + PePlusHdr->OptionalHeader.SizeOfImage = Pe32ImageSize; + PePlusHdr->OptionalHeader.Subsystem = TEImageHeader->Subsystem; + PePlusHdr->OptionalHeader.SizeOfHeaders = TEImageHeader->StrippedSize + TEImageHeader->NumberOfSections * + sizeof (EFI_IMAGE_SECTION_HEADER) - 12; + + // + // Set NumberOfRvaAndSizes in the optional header to what we had available in the original image + // + if ((TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress != 0) || + (TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size != 0) + ) { + PePlusHdr->OptionalHeader.NumberOfRvaAndSizes = EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC + 1; + PePlusHdr->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress; + PePlusHdr->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size; + } + + if ((TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress != 0) || + (TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].Size != 0) + ) { + PePlusHdr->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress = TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress; + PePlusHdr->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size = TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].Size; + if (PePlusHdr->OptionalHeader.NumberOfRvaAndSizes < EFI_IMAGE_DIRECTORY_ENTRY_DEBUG + 1) { + PePlusHdr->OptionalHeader.NumberOfRvaAndSizes = EFI_IMAGE_DIRECTORY_ENTRY_DEBUG + 1; + } + } + // + // NOTE: These values are defaults, and should be verified to be correct in the GenTE utility + // + PePlusHdr->OptionalHeader.SectionAlignment = 0x10; } - // - // NOTE: These values are defaults, and should be verified to be correct in the GenTE utility - // - PeHdr->OptionalHeader.SectionAlignment = 0x10; // // Copy the rest of the image to its original offset @@ -950,15 +1059,15 @@ Returns: // // Allocate a buffer for the image to be loaded into. // - MemoryImagePointer = (UINTN) (malloc (Pe32ImageSize + 0x10000)); + MemoryImagePointer = (UINTN) (malloc (Pe32ImageSize + 0x1000)); if (MemoryImagePointer == 0) { Error (NULL, 0, 0, "memory allocation error on rebase of TE image", FileGuidString); free (TEBuffer); return EFI_OUT_OF_RESOURCES; } - memset ((void *) MemoryImagePointer, 0, Pe32ImageSize + 0x10000); - MemoryImagePointerAligned = (MemoryImagePointer + 0x0FFFF) & (-1 << 16); - + memset ((void *) MemoryImagePointer, 0, Pe32ImageSize + 0x1000); + MemoryImagePointerAligned = (MemoryImagePointer + 0x0FFF) & (-1 << 12); + ImageContext.ImageAddress = MemoryImagePointerAligned; Status = PeCoffLoaderLoadImage (&ImageContext); @@ -968,11 +1077,6 @@ Returns: free ((VOID *) MemoryImagePointer); return Status; } - - // - // Check if section-alignment and file-alignment match or not - // BUGBUG: TE Image Header lack section-alignment and file-alignment info - // ImageContext.DestinationAddress = NewPe32BaseAddress; Status = PeCoffLoaderRelocateImage (&ImageContext); @@ -993,12 +1097,16 @@ Returns: // so it will be loaded properly later if the PEIM is reloaded into memory... // PeHdr = (VOID *) ((UINTN) ImageAddress + ImageContext.PeCoffHeaderOffset); + PePlusHdr = (EFI_IMAGE_NT_HEADERS64*)PeHdr; if (PeHdr->FileHeader.Machine == EFI_IMAGE_MACHINE_IA32) { - PeHdrSizeOfImage = (UINT32 *) (&(*(EFI_IMAGE_OPTIONAL_HEADER32 *) &PeHdr->OptionalHeader).SizeOfImage); - PeHdrChecksum = (UINT32 *) (&(*(EFI_IMAGE_OPTIONAL_HEADER32 *) &PeHdr->OptionalHeader).CheckSum); + PeHdrSizeOfImage = (UINT32 *) (&(PeHdr->OptionalHeader).SizeOfImage); + PeHdrChecksum = (UINT32 *) (&(PeHdr->OptionalHeader).CheckSum); } else if (PeHdr->FileHeader.Machine == EFI_IMAGE_MACHINE_IA64) { - PeHdrSizeOfImage = (UINT32 *) (&(*(EFI_IMAGE_OPTIONAL_HEADER64 *) &PeHdr->OptionalHeader).SizeOfImage); - PeHdrChecksum = (UINT32 *) (&(*(EFI_IMAGE_OPTIONAL_HEADER64 *) &PeHdr->OptionalHeader).CheckSum); + PeHdrSizeOfImage = (UINT32 *) (&(PePlusHdr->OptionalHeader).SizeOfImage); + PeHdrChecksum = (UINT32 *) (&(PePlusHdr->OptionalHeader).CheckSum); + } else if (PeHdr->FileHeader.Machine == EFI_IMAGE_MACHINE_X64) { + PeHdrSizeOfImage = (UINT32 *) (&(PePlusHdr->OptionalHeader).SizeOfImage); + PeHdrChecksum = (UINT32 *) (&(PePlusHdr->OptionalHeader).CheckSum); } else { Error ( NULL, @@ -1028,25 +1136,6 @@ Returns: GetLength (CurrentPe32Section.Pe32Section->CommonHeader.Size) - sizeof (EFI_PE32_SECTION) - sizeof (EFI_TE_IMAGE_HEADER) ); - - // - // Get EntryPoint in Flash Region. - // - EntryPoint = NewPe32BaseAddress + EntryPoint - ImageAddress; - - // - // If a map file was selected output mapping information for any file that - // was rebased. - // - if (MapFile != NULL) { - fprintf (MapFile, "TE File: %s Base:%08lx", FileGuidString, BaseAddress); - fprintf (MapFile, " EntryPoint:%08lx", EntryPoint); - if (ImageContext.PdbPointer != NULL) { - fprintf (MapFile, " FileName: %s", ImageContext.PdbPointer); - } - fprintf (MapFile, "\n"); - } - free ((VOID *) MemoryImagePointer); free (TEBuffer); if (FfsFile->Attributes & FFS_ATTRIB_TAIL_PRESENT) { @@ -1079,18 +1168,15 @@ Returns: TailValue = (EFI_FFS_FILE_TAIL) (~(FfsFile->IntegrityCheck.TailReference)); *(EFI_FFS_FILE_TAIL *) (((UINTN) FfsFile + GetLength (FfsFile->Size) - sizeof (EFI_FFS_FILE_TAIL))) = TailValue; } + + fprintf ( + LogFile, + "%s %016I64X\n", + FileGuidString, + ImageContext.DestinationAddress + ); } - // - // If we found no files, then emit an error if no compressed sections either - // - if (FoundCount == 0) { - Status = GetSectionByType (FfsFile, EFI_SECTION_COMPRESSION, Index, &CurrentPe32Section); - if (EFI_ERROR (Status)) { - Error (NULL, 0, 0, "no PE32, TE, nor compressed section found in FV file", FileGuidString); - return EFI_NOT_FOUND; - } - } - + return EFI_SUCCESS; } diff --git a/Tools/CCode/Source/PeiRebase/PeiRebaseExe.h b/Tools/CCode/Source/PeiRebase/PeiRebaseExe.h index b05baefb59..253387e6ab 100644 --- a/Tools/CCode/Source/PeiRebase/PeiRebaseExe.h +++ b/Tools/CCode/Source/PeiRebase/PeiRebaseExe.h @@ -1,8 +1,8 @@ /*++ Copyright (c) 1999-2006 Intel Corporation. All rights reserved -This program and the accompanying materials are licensed and made available -under the terms and conditions of the BSD License which accompanies this +This program and the accompanying materials are licensed and made available +under the terms and conditions of the BSD License which accompanies this distribution. The full text of the license may be found at http://opensource.org/licenses/bsd-license.php @@ -11,7 +11,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. Module Name: - + PeiRebaseExe.h Abstract: @@ -43,7 +43,7 @@ Abstract: // // The maximum number of arguments accepted from the command line. // -#define MAX_ARGS 9 +#define MAX_ARGS 7 // // The file copy buffer size @@ -130,9 +130,12 @@ Returns: EFI_STATUS FfsRebase ( - IN OUT EFI_FFS_FILE_HEADER *FfsFile, - IN EFI_PHYSICAL_ADDRESS BaseAddress, - IN FILE *MapFile OPTIONAL + IN OUT EFI_FFS_FILE_HEADER *FfsFile, + IN UINT32 Flags, + IN OUT EFI_PHYSICAL_ADDRESS XipBase, + IN OUT EFI_PHYSICAL_ADDRESS *BsBase, + IN OUT EFI_PHYSICAL_ADDRESS *RtBase, + OUT FILE *LogFile ) /*++ diff --git a/Tools/CCode/Source/TianoTools.msa b/Tools/CCode/Source/TianoTools.msa index 2e4b27c19d..b7101dda18 100644 --- a/Tools/CCode/Source/TianoTools.msa +++ b/Tools/CCode/Source/TianoTools.msa @@ -13,8 +13,8 @@ updates either the OS or the HOST tool chain, these tools should be rebuilt. Copyright 2006, Intel Corporation All rights reserved. This program and the accompanying materials -are licensed and made available under the terms and conditions of the -BSD License which accompanies this distribution. The full text of the +are licensed and made available under the terms and conditions of the +BSD License which accompanies this distribution. The full text of the license may be found at http://opensource.org/licenses/bsd-license.php @@ -96,6 +96,8 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.GenFvImage/GenFvImageLib.c GenFvImage/GenFvImageLib.h GenFvImage/GenFvImageLibInternal.h + GenFvMap/build.xml + GenFvMap/GenFvMap.cpp GenSection/build.xml GenSection/GenSection.c GenSection/GenSection.h diff --git a/Tools/Java/Source/FrameworkTasks/org/tianocore/framework/tasks/PeiReBaseTask.java b/Tools/Java/Source/FrameworkTasks/org/tianocore/framework/tasks/PeiReBaseTask.java index 07154921d2..ab563823e8 100644 --- a/Tools/Java/Source/FrameworkTasks/org/tianocore/framework/tasks/PeiReBaseTask.java +++ b/Tools/Java/Source/FrameworkTasks/org/tianocore/framework/tasks/PeiReBaseTask.java @@ -51,11 +51,11 @@ public class PeiReBaseTask extends Task implements EfiDefine { private ToolArg baseAddr = new ToolArg(); // // Fv.inf file - // + // private FileArg fvinfFile = new FileArg(); // // map file - // + // private FileArg mapFile = new FileArg(); // // Architecture @@ -64,10 +64,10 @@ public class PeiReBaseTask extends Task implements EfiDefine { /** execute - + PeiReBaseTask execute function is to assemble tool command line & execute tool command line - + @throws BuidException **/ public void execute() throws BuildException { @@ -103,7 +103,7 @@ public class PeiReBaseTask extends Task implements EfiDefine { if (mapFile.getValue().length() == 0) { mapFile.setArg(" -M ", outputFile.getValue() + ".map"); } - argument = "" + inputFile + outputFile + baseAddr + fvinfFile + mapFile; + argument = "" + inputFile + outputFile + baseAddr + fvinfFile; // // return value of fwimage execution @@ -125,7 +125,7 @@ public class PeiReBaseTask extends Task implements EfiDefine { // Set debug log information. // EdkLog.log(this, EdkLog.EDK_VERBOSE, Commandline.toString(cmdline.getCommandline())); - EdkLog.log(this, EdkLog.EDK_INFO, inputFile.toFileList() + " => " + EdkLog.log(this, EdkLog.EDK_INFO, inputFile.toFileList() + " => " + outputFile.toFileList() + mapFile.toFileList()); @@ -150,9 +150,9 @@ public class PeiReBaseTask extends Task implements EfiDefine { /** getInputFile - + This function is to get class member "inputFile". - + @return string of input file name. **/ public String getInputFile() { @@ -161,9 +161,9 @@ public class PeiReBaseTask extends Task implements EfiDefine { /** setComponentType - + This function is to set class member "inputFile". - + @param inputFile string of input file name. **/ @@ -173,9 +173,9 @@ public class PeiReBaseTask extends Task implements EfiDefine { /** getOutputFile - + This function is to get class member "outputFile" - + @return outputFile string of output file name. **/ public String getOutputFile() { @@ -184,9 +184,9 @@ public class PeiReBaseTask extends Task implements EfiDefine { /** setOutputFile - + This function is to set class member "outputFile" - + @param outputFile string of output file name. **/ @@ -196,9 +196,9 @@ public class PeiReBaseTask extends Task implements EfiDefine { /** getBaseAddr - + This function is to get class member "baseAddr" - + @return baseAddr string of base address. **/ public String getBaseAddr() { @@ -207,9 +207,9 @@ public class PeiReBaseTask extends Task implements EfiDefine { /** setBaseAddr - + This function is to set class member "baseAddr" - + @param baseAddr string of base address **/ public void setBaseAddr(String baseAddr) { @@ -218,9 +218,9 @@ public class PeiReBaseTask extends Task implements EfiDefine { /** getArch - + This function is to get class member "arch". - + @return arch Architecture **/ public String getArch() { @@ -229,9 +229,9 @@ public class PeiReBaseTask extends Task implements EfiDefine { /** setArch - + This function is to set class member "arch" - + @param arch Architecture **/ public void setArch(String arch) { @@ -276,7 +276,7 @@ public class PeiReBaseTask extends Task implements EfiDefine { // // Dependency check - // + // private boolean isUptodate() { File srcFile = new File(inputFile.getValue()); File dstFile = new File(outputFile.getValue());