From: bxing Date: Sat, 30 Dec 2006 09:17:16 +0000 (+0000) Subject: 1. Added a new tool GenFvMap, which is able to generate FV map files upon LOG files... X-Git-Tag: edk2-stable201903~23720 X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=commitdiff_plain;h=8733430b83565480540d1d890986cbf22c54db0d 1. Added a new tool GenFvMap, which is able to generate FV map files upon LOG files generated by PeiRebase. 2. Updated PeiRebase to generate LOG files while processing FV images. The original MAP feature and its corresponding option '-M' are dropped, however, they are superceded by the FV map file. 3. The FV map file are not generated yet. My next check-in will update FPD files to generate FV map files. git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@2157 6f19259b-4bc3-4df7-8a09-765794883524 --- 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 'F': + case 'f': + // + // 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 (!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; - } + 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; + } - BaseAddressSet = TRUE; - } else { + Status = AsciiStringToUint64 (argv[Index + 1], FALSE, &XipBase); + if (EFI_ERROR (Status)) { PrintUsage (); - Error (NULL, 0, 0, argv[Index + 1], "-b BaseAddress may only be specified once"); + Error (NULL, 0, 0, argv[Index + 1], "invalid hex digit given for XIP base address"); return STATUS_ERROR; } + + BaseTypes |= 1; 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; - } + case 'D': + case 'd': + if (BaseTypes & 2) { + PrintUsage (); + Error (NULL, 0, 0, argv[Index + 1], "-d BsBaseAddress may be specified only once"); + return STATUS_ERROR; + } - BaseAddressSet = TRUE; - } else { + Status = AsciiStringToUint64 (argv[Index + 1], FALSE, &BsBase); + if (EFI_ERROR (Status)) { PrintUsage (); - Error (NULL, 0, 0, argv[Index + 1], "BaseAddress has been got once from fv.inf or the specified base address."); + Error (NULL, 0, 0, argv[Index + 1], "invalid hex digit given for BS_DRIVER base address"); return STATUS_ERROR; } + + BaseTypes |= 2; break; - case 'M': - case 'm': - if (strlen (MapFileName) == 0) { - strcpy (MapFileName, argv[Index + 1]); - } else { + 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], "only one -m MapFileName may be specified"); + 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());