--- /dev/null
+//****************************************************************************\r
+//**\r
+//** Copyright (C) 2006 Intel Corporation. All rights reserved. \r
+//**\r
+//** The information and source code contained herein is the exclusive \r
+//** property of Intel Corporation and may not be disclosed, examined\r
+//** or reproduced in whole or in part without explicit written authorization \r
+//** from the company.\r
+//**\r
+//****************************************************************************\r
+\r
+#include <stdexcept>\r
+#include <list>\r
+#include <map>\r
+#include <iostream>\r
+#include <iomanip>\r
+#include <fstream>\r
+#include <sstream>\r
+#include <string>\r
+#include <utility>\r
+#include <algorithm>\r
+#include <functional>\r
+using namespace std;\r
+\r
+typedef unsigned __int64 ulonglong_t;\r
+\r
+template <class T>\r
+class CMemoryLeakChecker : public list<T*>\r
+{\r
+public:\r
+ static CMemoryLeakChecker<T>& GetInstance(void);\r
+\r
+private:\r
+ CMemoryLeakChecker(void)\r
+ {\r
+ }\r
+\r
+ ~CMemoryLeakChecker(void);\r
+};\r
+\r
+template <class T>\r
+CMemoryLeakChecker<T>& CMemoryLeakChecker<T>::GetInstance(void)\r
+{\r
+ static CMemoryLeakChecker<T> s_memLeakChecker;\r
+ return s_memLeakChecker;\r
+}\r
+\r
+template <class T>\r
+CMemoryLeakChecker<T>::~CMemoryLeakChecker(void)\r
+{\r
+ if (!list<T*>::empty())\r
+ throw logic_error(__FUNCTION__ ": Memory leak detected!");\r
+}\r
+\r
+class CObjRoot\r
+{\r
+protected:\r
+ CObjRoot(void);\r
+ virtual ~CObjRoot(void);\r
+};\r
+\r
+CObjRoot::CObjRoot(void)\r
+{\r
+ CMemoryLeakChecker<CObjRoot>::GetInstance().push_back(this);\r
+}\r
+\r
+CObjRoot::~CObjRoot(void)\r
+{\r
+ CMemoryLeakChecker<CObjRoot>::GetInstance().remove(this);\r
+}\r
+\r
+class CIdentity : public CObjRoot\r
+{\r
+public:\r
+ CIdentity(void);\r
+ CIdentity(const string&);\r
+ CIdentity(const CIdentity&);\r
+\r
+ bool operator < (const CIdentity&) const;\r
+ friend istream& operator >> (istream&, CIdentity&);\r
+\r
+ static const string::size_type s_nIdStrLen;\r
+\r
+protected:\r
+ ulonglong_t m_ullId[2];\r
+};\r
+\r
+const string::size_type CIdentity::s_nIdStrLen = 36;\r
+\r
+CIdentity::CIdentity(void)\r
+{\r
+ memset(m_ullId, 0, sizeof(m_ullId));\r
+}\r
+\r
+CIdentity::CIdentity(const string& strId)\r
+{\r
+ if (strId.length() != CIdentity::s_nIdStrLen ||\r
+ strId[8] != '-' ||\r
+ strId[13] != '-' ||\r
+ strId[18] != '-' ||\r
+ strId[23] != '-')\r
+ throw runtime_error(\r
+ __FUNCTION__ ": Error GUID format " + strId);\r
+\r
+ string strIdCopy(strId);\r
+ strIdCopy.erase(23, 1);\r
+ strIdCopy[18] = ' ';\r
+ strIdCopy.erase(13, 1);\r
+ strIdCopy.erase(8, 1);\r
+\r
+ istringstream is(strIdCopy);\r
+ is >> hex >> m_ullId[0] >> m_ullId[1];\r
+ if (!is)\r
+ throw runtime_error(\r
+ __FUNCTION__ ": GUID contains invalid characters" + strId);\r
+}\r
+\r
+CIdentity::CIdentity(const CIdentity& idRight)\r
+{\r
+ memmove(m_ullId, idRight.m_ullId, sizeof(m_ullId));\r
+}\r
+\r
+bool CIdentity::operator < (const CIdentity& idRight) const\r
+{\r
+ return memcmp(m_ullId, idRight.m_ullId, sizeof(m_ullId)) < 0;\r
+}\r
+\r
+istream& operator >> (istream& is, CIdentity& idRight)\r
+{\r
+ string strId;\r
+ is >> strId;\r
+ if (!!is)\r
+ idRight = CIdentity(strId);\r
+ return is;\r
+}\r
+\r
+class CInputFile : public CObjRoot\r
+{\r
+protected:\r
+ CInputFile(const string&);\r
+ CInputFile(istream&);\r
+ istream& GetLine(string&);\r
+\r
+private:\r
+ CInputFile(const CInputFile&);\r
+ CInputFile& operator = (const CInputFile&);\r
+\r
+private:\r
+ auto_ptr<istream> m_pIs;\r
+\r
+protected:\r
+ istream& m_is;\r
+};\r
+\r
+CInputFile::CInputFile(const string& strFName)\r
+: m_pIs(new ifstream(strFName.c_str()))\r
+, m_is(*m_pIs)\r
+{\r
+ if (!m_is)\r
+ throw runtime_error(__FUNCTION__ ": Error opening input file " + strFName);\r
+}\r
+\r
+CInputFile::CInputFile(istream& is)\r
+: m_is(is)\r
+{\r
+ if (!m_is)\r
+ throw runtime_error(__FUNCTION__ ": Error opening input stream");\r
+}\r
+\r
+istream& CInputFile::GetLine(string& strALine)\r
+{\r
+ if (!!m_is)\r
+ while (!!getline(m_is, strALine))\r
+ {\r
+ string::size_type pos = strALine.find_last_not_of(' ');\r
+ if (pos != string::npos)\r
+ {\r
+ strALine.erase(pos + 1);\r
+ strALine.erase(0, strALine.find_first_not_of(' '));\r
+ break;\r
+ }\r
+ }\r
+ return m_is;\r
+}\r
+\r
+class CIdAddressMap : public CInputFile, public map<CIdentity, ulonglong_t>\r
+{\r
+public:\r
+ CIdAddressMap(istream&);\r
+};\r
+\r
+CIdAddressMap::CIdAddressMap(istream& is)\r
+: CInputFile(is)\r
+{\r
+ CIdentity id;\r
+ ulonglong_t ullBase;\r
+\r
+ while (!!(m_is >> hex >> id >> ullBase))\r
+ if (!insert(value_type(id, ullBase)).second)\r
+ throw runtime_error(__FUNCTION__ ": Duplicated files");\r
+}\r
+\r
+class CIdPathMap : public CInputFile, public map<CIdentity, string>\r
+{\r
+public:\r
+ CIdPathMap(istream&);\r
+};\r
+\r
+CIdPathMap::CIdPathMap(istream& is)\r
+: CInputFile(is)\r
+{\r
+ static const char cszFileSec[] = "[files]";\r
+ static const char cszFfsFile[] = "EFI_FILE_NAME";\r
+\r
+ string strALine;\r
+\r
+ // Find the [files] section\r
+ while (!!GetLine(strALine) && strALine.compare(0, sizeof(cszFileSec) - 1, cszFileSec));\r
+\r
+ // m_is error means no FFS files listed in this INF file\r
+ if (!m_is)\r
+ return;\r
+\r
+ // Parse FFS files one by one\r
+ while (!!GetLine(strALine))\r
+ {\r
+ // Test if this begins a new section\r
+ if (strALine[0] == '[')\r
+ break;\r
+\r
+ // Is it a line of FFS file?\r
+ if (strALine.compare(0, sizeof(cszFfsFile) - 1, cszFfsFile))\r
+ continue;\r
+\r
+ string::size_type pos = strALine.find_first_not_of(' ', sizeof(cszFfsFile) - 1);\r
+ if (pos == string::npos || strALine[pos] != '=')\r
+ throw runtime_error(__FUNCTION__ ": Invalid FV INF format");\r
+ pos = strALine.find_first_not_of(' ', pos + 1);\r
+ if (pos == string::npos)\r
+ throw runtime_error(__FUNCTION__ ": Incomplete line");\r
+\r
+ strALine.erase(0, pos);\r
+ pos = strALine.rfind('\\');\r
+ if (pos == string::npos)\r
+ pos = 0;\r
+ else pos++;\r
+\r
+ CIdentity id(strALine.substr(pos, CIdentity::s_nIdStrLen));\r
+ if (!insert(value_type(id, strALine)).second)\r
+ throw runtime_error(__FUNCTION__ ": Duplicated FFS files");\r
+ }\r
+}\r
+\r
+class CSymbol : public CObjRoot\r
+{\r
+public:\r
+ string m_strAddress;\r
+ string m_strName;\r
+ ulonglong_t m_ullRva;\r
+ string m_strFrom;\r
+ bool m_bStatic;\r
+ bool m_bFunction;\r
+\r
+ CSymbol()\r
+ {\r
+ }\r
+ CSymbol(const string&, bool = false);\r
+ friend ostream& operator << (ostream&, const CSymbol&);\r
+};\r
+\r
+CSymbol::CSymbol(const string& strALine, bool bStatic)\r
+: m_bStatic(bStatic)\r
+{\r
+ istringstream is(strALine);\r
+\r
+ is >> m_strAddress >> m_strName >> hex >> m_ullRva >> m_strFrom;\r
+ if (m_strFrom == "F" || m_strFrom == "f")\r
+ {\r
+ m_bFunction = true;\r
+ is >> m_strFrom;\r
+ } else m_bFunction = false;\r
+}\r
+\r
+ostream& operator << (ostream& os, const CSymbol& symbol)\r
+{\r
+ os << hex << setw(16) << setfill('0') << symbol.m_ullRva << setw(0);\r
+ os << ' ' << (symbol.m_bFunction ? 'F' : ' ')\r
+ << (symbol.m_bStatic ? 'S' : ' ') << ' ';\r
+ return os << symbol.m_strName << endl;\r
+}\r
+\r
+class CMapFile : public CInputFile, public list<CSymbol>\r
+{\r
+public:\r
+ CMapFile(const string&);\r
+\r
+ void SetLoadAddress(ulonglong_t);\r
+ friend ostream& operator << (ostream&, const CMapFile&);\r
+\r
+ string m_strModuleName;\r
+ ulonglong_t m_ullLoadAddr;\r
+ string m_strEntryPoint;\r
+};\r
+\r
+CMapFile::CMapFile(const string& strFName)\r
+: CInputFile(strFName)\r
+{\r
+ static const char cszLoadAddr[] = "Preferred load address is";\r
+ static const char cszGlobal[] = "Address";\r
+ static const char cszEntryPoint[] = "entry point at";\r
+ static const char cszStatic[] = "Static symbols";\r
+\r
+ string strALine;\r
+\r
+ GetLine(m_strModuleName);\r
+\r
+ while (!!GetLine(strALine) && strALine.compare(0, sizeof(cszLoadAddr) - 1, cszLoadAddr));\r
+ if (!m_is)\r
+ throw runtime_error(__FUNCTION__ ": Load Address not listed in map file");\r
+\r
+ istringstream is(strALine.substr(sizeof(cszLoadAddr) - 1));\r
+ if (!(is >> hex >> m_ullLoadAddr))\r
+ throw runtime_error(__FUNCTION__ ": Unexpected Load Address format");\r
+\r
+ while (!!GetLine(strALine) && strALine.compare(0, sizeof(cszGlobal) - 1, cszGlobal));\r
+ if (!m_is)\r
+ throw runtime_error(__FUNCTION__ ": Global symbols not found in map file");\r
+\r
+ while (!!GetLine(strALine) && strALine.compare(0, sizeof(cszEntryPoint) - 1, cszEntryPoint))\r
+ push_back(CSymbol(strALine));\r
+ if (!m_is)\r
+ throw runtime_error(__FUNCTION__ ": Entry Point not listed in map file");\r
+\r
+ is.str(strALine.substr(strALine.find_first_not_of(' ', sizeof(cszEntryPoint) - 1)));\r
+ is.clear();\r
+ if (!getline(is, m_strEntryPoint))\r
+ throw runtime_error(__FUNCTION__ ": Unexpected Entry Point format");\r
+\r
+ while (!!GetLine(strALine) && strALine.compare(0, sizeof(cszStatic) - 1, cszStatic));\r
+ while (!!GetLine(strALine))\r
+ push_back(CSymbol(strALine, true));\r
+}\r
+\r
+void CMapFile::SetLoadAddress(ulonglong_t ullLoadAddr)\r
+{\r
+ for (iterator i = begin(); i != end(); i++)\r
+ if (i->m_ullRva != 0)\r
+ i->m_ullRva += ullLoadAddr - m_ullLoadAddr;\r
+ m_ullLoadAddr = ullLoadAddr;\r
+}\r
+\r
+ostream& operator << (ostream& os, const CMapFile& mapFile)\r
+{\r
+ CMapFile::const_iterator i = mapFile.begin();\r
+ while (i != mapFile.end() && i->m_strAddress != mapFile.m_strEntryPoint)\r
+ i++;\r
+ if (i == mapFile.end())\r
+ throw runtime_error(\r
+ __FUNCTION__ ": Entry point not found for module " +\r
+ mapFile.m_strModuleName);\r
+\r
+ os << endl << hex\r
+ << mapFile.m_strModuleName << " (EP=" << i->m_ullRva\r
+ << ", BA=" << mapFile.m_ullLoadAddr << ')' << endl\r
+ << endl;\r
+\r
+ for (i = mapFile.begin(); i != mapFile.end(); i++)\r
+ os << " " << *i;\r
+\r
+ return os << endl;\r
+}\r
+\r
+class COutputFile : public CObjRoot\r
+{\r
+protected:\r
+ COutputFile(ostream&);\r
+ ostream& m_os;\r
+\r
+private:\r
+ COutputFile(const COutputFile&);\r
+ COutputFile& operator = (const COutputFile&);\r
+};\r
+\r
+class CFvMapFile : public CObjRoot, public map<CIdentity, CMapFile*>\r
+{\r
+public:\r
+ CFvMapFile(const CIdAddressMap&, const CIdPathMap&);\r
+ ~CFvMapFile(void);\r
+\r
+ friend ostream& operator << (ostream&, const CFvMapFile&);\r
+\r
+private:\r
+ void Cleanup(void);\r
+};\r
+\r
+CFvMapFile::CFvMapFile(const CIdAddressMap& idAddr, const CIdPathMap& idPath)\r
+{\r
+ for (CIdAddressMap::const_iterator i = idAddr.begin(); i != idAddr.end(); i++)\r
+ {\r
+ CIdPathMap::const_iterator j = idPath.find(i->first);\r
+ if (j == idPath.end())\r
+ throw runtime_error(__FUNCTION__ ": Map file not found");\r
+\r
+ try\r
+ {\r
+ pair<iterator, bool> k = insert(value_type(i->first,\r
+ new CMapFile(j->second.substr(0, j->second.rfind('.')) + ".map")));\r
+ if (!k.second)\r
+ throw logic_error(__FUNCTION__ ": Duplicated file found in rebase log");\r
+\r
+ k.first->second->SetLoadAddress(i->second);\r
+ }\r
+ catch (const runtime_error& e)\r
+ {\r
+ cerr << e.what() << endl;\r
+ }\r
+ }\r
+}\r
+\r
+void CFvMapFile::Cleanup(void)\r
+{\r
+ for (iterator i = begin(); i != end(); i++)\r
+ delete i->second;\r
+}\r
+\r
+ostream& operator << (ostream& os, const CFvMapFile& fvMap)\r
+{\r
+ for (CFvMapFile::const_iterator i = fvMap.begin(); !!os && i != fvMap.end(); i++)\r
+ os << *i->second;\r
+ return os;\r
+}\r
+\r
+CFvMapFile::~CFvMapFile(void)\r
+{\r
+ Cleanup();\r
+}\r
+\r
+class CGenFvMapUsage : public invalid_argument\r
+{\r
+public:\r
+ CGenFvMapUsage(void) : invalid_argument(s_szUsage)\r
+ {\r
+ }\r
+\r
+private:\r
+ static const char s_szUsage[];\r
+};\r
+\r
+const char CGenFvMapUsage::s_szUsage[] = "Usage: GenFvMap <LOG> <INF> <MAP>";\r
+\r
+class CGenFvMapApp : public CObjRoot\r
+{\r
+public:\r
+ CGenFvMapApp(int, char *[]);\r
+ ~CGenFvMapApp(void);\r
+\r
+ int Run(void);\r
+\r
+private:\r
+ int m_cArgc;\r
+ char **m_ppszArgv;\r
+};\r
+\r
+CGenFvMapApp::CGenFvMapApp(int cArgc, char *ppszArgv[])\r
+: m_cArgc(cArgc)\r
+, m_ppszArgv(ppszArgv)\r
+{\r
+ if (cArgc != 4)\r
+ throw CGenFvMapUsage();\r
+}\r
+\r
+CGenFvMapApp::~CGenFvMapApp(void)\r
+{\r
+}\r
+\r
+int CGenFvMapApp::Run(void)\r
+{\r
+ ifstream isLog(m_ppszArgv[1]);\r
+ ifstream isInf(m_ppszArgv[2]);\r
+\r
+ CIdAddressMap idAddress(isLog);\r
+ CIdPathMap idPath(isInf);\r
+\r
+ CFvMapFile fvMap(idAddress, idPath);\r
+\r
+ ofstream osMap(m_ppszArgv[3], ios_base::out | ios_base::trunc);\r
+ osMap << fvMap;\r
+\r
+ if (!osMap)\r
+ throw runtime_error(__FUNCTION__ ": Error writing output file");\r
+\r
+ return 0;\r
+}\r
+\r
+int main(int argc, char *argv[])\r
+{\r
+ try\r
+ {\r
+ CGenFvMapApp app(argc, argv);\r
+ return app.Run();\r
+ }\r
+ catch (const exception& e)\r
+ {\r
+ cerr << e.what() << endl;\r
+ return -1;\r
+ }\r
+}\r
/*++\r
\r
Copyright (c) 1999-2006 Intel Corporation. All rights reserved\r
-This program and the accompanying materials are licensed and made available \r
-under the terms and conditions of the BSD License which accompanies this \r
+This program and the accompanying materials are licensed and made available\r
+under the terms and conditions of the BSD License which accompanies this\r
distribution. The full text of the license may be found at\r
http://opensource.org/licenses/bsd-license.php\r
\r
\r
argc - Number of command line arguments\r
argv[]:\r
- BaseAddress The base address to use for rebasing the FV. The correct \r
+ BaseAddress The base address to use for rebasing the FV. The correct\r
format is a hex number preceded by 0x.\r
InputFileName The name of the input FV file.\r
OutputFileName The name of the output FV file.\r
- MapFileName The name of the map file of relocation info.\r
\r
Arguments come in pair in any order.\r
- -I InputFileName \r
+ -I InputFileName\r
-O OutputFileName\r
- -B BaseAddress \r
- -M MapFileName \r
+ -B BaseAddress\r
\r
Returns:\r
\r
0 No error conditions detected.\r
1 One or more of the input parameters is invalid.\r
- 2 A resource required by the utility was unavailable. \r
+ 2 A resource required by the utility was unavailable.\r
Most commonly this will be memory allocation or file creation.\r
3 PeiRebase.dll could not be loaded.\r
4 Error executing the PEI rebase.\r
{\r
UINT8 Index;\r
CHAR8 InputFileName[_MAX_PATH];\r
- CHAR8 OutputFileName[_MAX_PATH];\r
- CHAR8 MapFileName[_MAX_PATH];\r
- EFI_PHYSICAL_ADDRESS BaseAddress;\r
- BOOLEAN BaseAddressSet;\r
+ CHAR8 *OutputFileName;\r
+ EFI_PHYSICAL_ADDRESS XipBase, BsBase, RtBase;\r
+ UINT32 BaseTypes;\r
EFI_STATUS Status;\r
FILE *InputFile;\r
FILE *OutputFile;\r
- FILE *MapFile;\r
+ FILE *LogFile;\r
UINT64 FvOffset;\r
UINT32 FileCount;\r
int BytesRead;\r
UINT32 FvSize;\r
EFI_FFS_FILE_HEADER *CurrentFile;\r
BOOLEAN ErasePolarity;\r
- EFI_PHYSICAL_ADDRESS CurrentFileBaseAddress;\r
- CHAR8 InfFileName[_MAX_PATH];\r
- CHAR8 *InfFileImage;\r
- UINTN InfFileSize;\r
MEMORY_FILE InfMemoryFile;\r
+ CHAR8 StringBuffer[0x100];\r
\r
ErasePolarity = FALSE;\r
//\r
//\r
// Initialize variables\r
//\r
- InputFileName[0] = 0;\r
- OutputFileName[0] = 0;\r
- MapFileName[0] = 0;\r
- BaseAddress = 0;\r
- BaseAddressSet = FALSE;\r
+ InputFileName[0] = '\0';\r
+ OutputFileName = NULL;\r
+ XipBase = BsBase = RtBase = 0;\r
+ BaseTypes = 0;\r
FvOffset = 0;\r
FileCount = 0;\r
ErasePolarity = FALSE;\r
InputFile = NULL;\r
OutputFile = NULL;\r
- MapFile = NULL;\r
+ LogFile = NULL;\r
FvImage = NULL;\r
- InfFileImage = NULL;\r
- InfFileSize = 0;\r
- strcpy (InfFileName, "");\r
\r
//\r
// Parse the command line arguments\r
PrintUsage ();\r
Error (NULL, 0, 0, argv[Index], "unrecognized option");\r
return STATUS_ERROR;\r
- } \r
+ }\r
//\r
// Determine argument to read\r
//\r
\r
case 'O':\r
case 'o':\r
- if (strlen (OutputFileName) == 0) {\r
- strcpy (OutputFileName, argv[Index + 1]);\r
+ if (OutputFileName == NULL) {\r
+ OutputFileName = argv[Index + 1];\r
} else {\r
PrintUsage ();\r
Error (NULL, 0, 0, argv[Index + 1], "only one -o OutputFileName may be specified");\r
}\r
break;\r
\r
+ case 'F':\r
+ case 'f':\r
+ //\r
+ // Load INF file into memory & initialize MEMORY_FILE structure\r
+ //\r
+ Status = GetFileImage (argv[Index + 1], &InfMemoryFile.FileImage, (UINT32*)&InfMemoryFile.Eof);\r
+ InfMemoryFile.Eof = InfMemoryFile.FileImage + (UINT32)(UINTN)InfMemoryFile.Eof;\r
+ InfMemoryFile.CurrentFilePointer = InfMemoryFile.FileImage;\r
+ if (EFI_ERROR (Status)) {\r
+ Error (NULL, 0, 0, argv[Index + 1], "Error opening FvInfFile");\r
+ return STATUS_ERROR;\r
+ }\r
+\r
+ //\r
+ // Read BaseAddress from fv.inf file\r
+ //\r
+ FindToken (&InfMemoryFile, "[options]", "EFI_BASE_ADDRESS", 0, StringBuffer);\r
+\r
+ //\r
+ // Free INF file image\r
+ //\r
+ free (InfMemoryFile.FileImage);\r
+\r
+ //\r
+ // Point argv[Index + 1] to StringBuffer so that it could be processed as "-b"\r
+ //\r
+ argv[Index + 1] = StringBuffer;\r
+\r
case 'B':\r
case 'b':\r
- if (!BaseAddressSet) {\r
- Status = AsciiStringToUint64 (argv[Index + 1], FALSE, &BaseAddress);\r
- if (EFI_ERROR (Status)) {\r
- PrintUsage ();\r
- Error (NULL, 0, 0, argv[Index + 1], "invalid hex digit given for the base address");\r
- return STATUS_ERROR;\r
- }\r
+ if (BaseTypes & 1) {\r
+ PrintUsage ();\r
+ Error (NULL, 0, 0, argv[Index + 1], "XipBaseAddress may be specified only once by either -b or -f");\r
+ return STATUS_ERROR;\r
+ }\r
\r
- BaseAddressSet = TRUE;\r
- } else {\r
+ Status = AsciiStringToUint64 (argv[Index + 1], FALSE, &XipBase);\r
+ if (EFI_ERROR (Status)) {\r
PrintUsage ();\r
- Error (NULL, 0, 0, argv[Index + 1], "-b BaseAddress may only be specified once");\r
+ Error (NULL, 0, 0, argv[Index + 1], "invalid hex digit given for XIP base address");\r
return STATUS_ERROR;\r
}\r
+\r
+ BaseTypes |= 1;\r
break;\r
\r
- case 'F':\r
- case 'f':\r
- if (!BaseAddressSet) {\r
- strcpy (InfFileName, argv[Index + 1]);\r
- //\r
- // Read the INF file image\r
- //\r
- Status = GetFileImage (InfFileName, &InfFileImage, &InfFileSize);\r
- if (EFI_ERROR (Status)) {\r
- PrintUsage ();\r
- Error (NULL, 0, 0, argv[Index + 1], "-f FvInfFile can't be opened.");\r
- return STATUS_ERROR;\r
- }\r
- //\r
- // Initialize file structures\r
- //\r
- InfMemoryFile.FileImage = InfFileImage;\r
- InfMemoryFile.CurrentFilePointer = InfFileImage;\r
- InfMemoryFile.Eof = InfFileImage + InfFileSize;\r
- //\r
- // Read BaseAddress from fv.inf file.\r
- //\r
- FindToken (&InfMemoryFile, "[options]", "EFI_BASE_ADDRESS", 0, InfFileName);\r
- //\r
- // free Inf File Image\r
- //\r
- free (InfFileImage);\r
- \r
- //\r
- // Convert string to UINT64 base address.\r
- //\r
- Status = AsciiStringToUint64 (InfFileName, FALSE, &BaseAddress);\r
- if (EFI_ERROR (Status)) {\r
- PrintUsage ();\r
- Error (NULL, 0, 0, argv[Index + 1], "can't find the base address in the specified fv.inf file.");\r
- return STATUS_ERROR;\r
- }\r
+ case 'D':\r
+ case 'd':\r
+ if (BaseTypes & 2) {\r
+ PrintUsage ();\r
+ Error (NULL, 0, 0, argv[Index + 1], "-d BsBaseAddress may be specified only once");\r
+ return STATUS_ERROR;\r
+ }\r
\r
- BaseAddressSet = TRUE;\r
- } else {\r
+ Status = AsciiStringToUint64 (argv[Index + 1], FALSE, &BsBase);\r
+ if (EFI_ERROR (Status)) {\r
PrintUsage ();\r
- Error (NULL, 0, 0, argv[Index + 1], "BaseAddress has been got once from fv.inf or the specified base address.");\r
+ Error (NULL, 0, 0, argv[Index + 1], "invalid hex digit given for BS_DRIVER base address");\r
return STATUS_ERROR;\r
}\r
+\r
+ BaseTypes |= 2;\r
break;\r
\r
- case 'M':\r
- case 'm':\r
- if (strlen (MapFileName) == 0) {\r
- strcpy (MapFileName, argv[Index + 1]);\r
- } else {\r
+ case 'R':\r
+ case 'r':\r
+ if (BaseTypes & 4) {\r
+ PrintUsage ();\r
+ Error (NULL, 0, 0, argv[Index + 1], "-r RtBaseAddress may be specified only once");\r
+ return STATUS_ERROR;\r
+ }\r
+\r
+ Status = AsciiStringToUint64 (argv[Index + 1], FALSE, &RtBase);\r
+ if (EFI_ERROR (Status)) {\r
PrintUsage ();\r
- Error (NULL, 0, 0, argv[Index + 1], "only one -m MapFileName may be specified");\r
+ Error (NULL, 0, 0, argv[Index + 1], "invalid hex digit given for RT_DRIVER base address");\r
return STATUS_ERROR;\r
}\r
+\r
+ BaseTypes |= 4;\r
break;\r
\r
default:\r
break;\r
}\r
}\r
- \r
- //\r
- // Create the Map file if we need it\r
- //\r
- if (strlen (MapFileName) != 0) {\r
- MapFile = fopen (MapFileName, "w");\r
- if (MapFile == NULL) {\r
- Error (NULL, 0, 0, MapFileName, "failed to open map file");\r
- goto Finish;\r
- }\r
- } \r
-\r
//\r
// Open the file containing the FV\r
//\r
Error (NULL, 0, 0, InputFileName, "could not open input file for reading");\r
return STATUS_ERROR;\r
}\r
+\r
+ //\r
+ // Open the log file\r
+ //\r
+ strcat (InputFileName, ".log");\r
+ LogFile = fopen (InputFileName, "a");\r
+ if (LogFile == NULL) {\r
+ Error (NULL, 0, 0, InputFileName, "could not append to log file");\r
+ }\r
+\r
//\r
// Determine size of FV\r
//\r
//\r
// Rebase this file\r
//\r
- CurrentFileBaseAddress = BaseAddress + ((UINTN) CurrentFile - (UINTN) FvImage);\r
- Status = FfsRebase (CurrentFile, CurrentFileBaseAddress, MapFile);\r
+ FfsRebase (\r
+ CurrentFile,\r
+ BaseTypes,\r
+ XipBase + (UINTN)CurrentFile - (UINTN)FvImage,\r
+ &BsBase,\r
+ &RtBase,\r
+ LogFile\r
+ );\r
\r
if (EFI_ERROR (Status)) {\r
switch (Status) {\r
\r
goto Finish;\r
}\r
-\r
//\r
// Get the next file\r
//\r
fclose (OutputFile);\r
}\r
\r
- if (MapFile != NULL) {\r
- fclose (MapFile);\r
+ if (LogFile != NULL) {\r
+ fclose (LogFile);\r
}\r
\r
if (FvImage != NULL) {\r
\r
Routine Description:\r
\r
- This function determines the size of the FV and the erase polarity. The \r
+ This function determines the size of the FV and the erase polarity. The\r
erase polarity is the FALSE value for file state.\r
\r
Arguments:\r
InputFile The file that contains the FV image.\r
FvSize The size of the FV.\r
ErasePolarity The FV erase polarity.\r
- \r
+\r
Returns:\r
- \r
+\r
EFI_SUCCESS Function completed successfully.\r
EFI_INVALID_PARAMETER A required parameter was NULL or is out of range.\r
EFI_ABORTED The function encountered an error.\r
--*/\r
{\r
printf (\r
- "Usage: %s -I InputFileName -O OutputFileName [-B BaseAddress] -F FvInfFileName -M MapFile\n",\r
+ "Usage: %s -I InputFileName -O OutputFileName -B BaseAddress\n",\r
UTILITY_NAME\r
);\r
printf (" Where:\n");\r
- printf (" InputFileName is the name of the EFI FV file to rebase.\n");\r
+ printf (" InputFileName is the name of the EFI FV file to rebase.\n");\r
printf (" OutputFileName is the desired output file name.\n");\r
- printf (" BaseAddress is the FV base address to rebase agains.\n");\r
- printf (" FvInfFileName is the fv.inf to be used to generate this fv image.\n");\r
- printf (" BaseAddress can also be got from the fv.inf file.\n");\r
- printf (" Choose only one method to input BaseAddress.\n");\r
- printf (" MapFileName is an optional map file of the relocations\n");\r
- printf (" Argument pair may be in any order.\n\n");\r
+ printf (" BaseAddress is the FV base address to rebase agains.\n");\r
+ printf (" Argument pair may be in any order.\n\n");\r
}\r
\r
EFI_STATUS\r
FfsRebase (\r
- IN OUT EFI_FFS_FILE_HEADER *FfsFile,\r
- IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
- IN FILE *MapFile OPTIONAL\r
+ IN OUT EFI_FFS_FILE_HEADER *FfsFile,\r
+ IN UINT32 Flags,\r
+ IN OUT EFI_PHYSICAL_ADDRESS XipBase,\r
+ IN OUT EFI_PHYSICAL_ADDRESS *BsBase,\r
+ IN OUT EFI_PHYSICAL_ADDRESS *RtBase,\r
+ OUT FILE *LogFile\r
)\r
/*++\r
\r
Routine Description:\r
\r
- This function determines if a file is XIP and should be rebased. It will \r
+ This function determines if a file is XIP and should be rebased. It will\r
rebase any PE32 sections found in the file using the base address.\r
- \r
+\r
Arguments:\r
\r
FfsFile A pointer to Ffs file image.\r
BaseAddress The base address to use for rebasing the file image.\r
- MapFile Optional file to dump relocation information into\r
\r
Returns:\r
\r
UINT64 ImageSize;\r
EFI_PHYSICAL_ADDRESS EntryPoint;\r
UINT32 Pe32ImageSize;\r
- UINT32 NewPe32BaseAddress;\r
+ EFI_PHYSICAL_ADDRESS NewPe32BaseAddress;\r
UINTN Index;\r
EFI_FILE_SECTION_POINTER CurrentPe32Section;\r
EFI_FFS_FILE_STATE SavedState;\r
- EFI_IMAGE_NT_HEADERS *PeHdr;\r
+ EFI_IMAGE_NT_HEADERS32 *PeHdr;\r
+ EFI_IMAGE_NT_HEADERS64 *PePlusHdr;\r
UINT32 *PeHdrSizeOfImage;\r
UINT32 *PeHdrChecksum;\r
- UINT32 FoundCount;\r
EFI_TE_IMAGE_HEADER *TEImageHeader;\r
UINT8 *TEBuffer;\r
EFI_IMAGE_DOS_HEADER *DosHeader;\r
UINT8 FileGuidString[80];\r
UINT32 TailSize;\r
EFI_FFS_FILE_TAIL TailValue;\r
+ EFI_PHYSICAL_ADDRESS *BaseToUpdate;\r
\r
//\r
// Verify input parameters\r
if (FfsFile == NULL) {\r
return EFI_INVALID_PARAMETER;\r
}\r
- \r
//\r
// Convert the GUID to a string so we can at least report which file\r
// if we find an error.\r
} else {\r
TailSize = 0;\r
}\r
- \r
//\r
// Do some cursory checks on the FFS file contents\r
//\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
- memset (&ImageContext, 0, sizeof (ImageContext));\r
-\r
//\r
- // Check if XIP file type. If not XIP, don't rebase.\r
+ // We only process files potentially containing PE32 sections.\r
//\r
- if (FfsFile->Type != EFI_FV_FILETYPE_PEI_CORE &&\r
- FfsFile->Type != EFI_FV_FILETYPE_PEIM &&\r
- FfsFile->Type != EFI_FV_FILETYPE_SECURITY_CORE &&\r
- FfsFile->Type != EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER\r
- ) {\r
- return EFI_SUCCESS;\r
+ switch (FfsFile->Type) {\r
+ case EFI_FV_FILETYPE_SECURITY_CORE:\r
+ case EFI_FV_FILETYPE_PEI_CORE:\r
+ case EFI_FV_FILETYPE_PEIM:\r
+ case EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER:\r
+ case EFI_FV_FILETYPE_DRIVER:\r
+ case EFI_FV_FILETYPE_DXE_CORE:\r
+ break;\r
+ default:\r
+ return EFI_SUCCESS;\r
}\r
\r
//\r
// Rebase each PE32 section\r
//\r
Status = EFI_SUCCESS;\r
- FoundCount = 0;\r
for (Index = 1;; Index++) {\r
Status = GetSectionByType (FfsFile, EFI_SECTION_PE32, Index, &CurrentPe32Section);\r
if (EFI_ERROR (Status)) {\r
break;\r
}\r
\r
- FoundCount++;\r
-\r
- //\r
- // Calculate the PE32 base address, the FFS file base plus the offset of the PE32 section\r
- //\r
- NewPe32BaseAddress = ((UINT32) BaseAddress) + ((UINTN) CurrentPe32Section.Pe32Section + sizeof (EFI_COMMON_SECTION_HEADER) - (UINTN) FfsFile);\r
\r
//\r
// Initialize context\r
memset (&ImageContext, 0, sizeof (ImageContext));\r
ImageContext.Handle = (VOID *) ((UINTN) CurrentPe32Section.Pe32Section + sizeof (EFI_PE32_SECTION));\r
ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE) FfsRebaseImageRead;\r
-\r
Status = PeCoffLoaderGetImageInfo (&ImageContext);\r
-\r
if (EFI_ERROR (Status)) {\r
Error (NULL, 0, 0, "GetImageInfo() call failed on rebase", FileGuidString);\r
return Status;\r
}\r
+\r
+ //\r
+ // Calculate the PE32 base address, based on file type\r
+ //\r
+ switch (FfsFile->Type) {\r
+ case EFI_FV_FILETYPE_SECURITY_CORE:\r
+ case EFI_FV_FILETYPE_PEI_CORE:\r
+ case EFI_FV_FILETYPE_PEIM:\r
+ case EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER:\r
+ if ((Flags & 1) == 0) {\r
+ //\r
+ // We aren't relocating XIP code, so skip it.\r
+ //\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ NewPe32BaseAddress =\r
+ XipBase +\r
+ (UINTN)CurrentPe32Section.Pe32Section +\r
+ sizeof (EFI_COMMON_SECTION_HEADER) -\r
+ (UINTN)FfsFile;\r
+ BaseToUpdate = &XipBase;\r
+ break;\r
+\r
+ case EFI_FV_FILETYPE_DRIVER:\r
+ PeHdr = (EFI_IMAGE_NT_HEADERS32*)(\r
+ (UINTN)CurrentPe32Section.Pe32Section +\r
+ sizeof (EFI_COMMON_SECTION_HEADER) +\r
+ ImageContext.PeCoffHeaderOffset\r
+ );\r
+ switch (PeHdr->OptionalHeader.Subsystem) {\r
+ case EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER:\r
+ if ((Flags & 4) == 0) {\r
+ //\r
+ // RT drivers aren't supposed to be relocated\r
+ //\r
+ continue;\r
+ }\r
+\r
+ NewPe32BaseAddress = *RtBase;\r
+ BaseToUpdate = RtBase;\r
+ break;\r
+\r
+ default:\r
+ //\r
+ // We treat all other subsystems the same as BS_DRIVER\r
+ //\r
+ if ((Flags & 2) == 0) {\r
+ //\r
+ // Skip all BS_DRIVER's\r
+ //\r
+ continue;\r
+ }\r
+\r
+ NewPe32BaseAddress = *BsBase;\r
+ BaseToUpdate = BsBase;\r
+ break;\r
+ }\r
+ break;\r
+\r
+ case EFI_FV_FILETYPE_DXE_CORE:\r
+ if ((Flags & 2) == 0) {\r
+ //\r
+ // Skip DXE core\r
+ //\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ NewPe32BaseAddress = *BsBase;\r
+ BaseToUpdate = BsBase;\r
+ break;\r
+\r
+ default:\r
+ //\r
+ // Not supported file type\r
+ //\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
//\r
// Allocate a buffer for the image to be loaded into.\r
//\r
Pe32ImageSize = GetLength (CurrentPe32Section.Pe32Section->CommonHeader.Size) - sizeof (EFI_PE32_SECTION);\r
- MemoryImagePointer = (UINTN) (malloc (Pe32ImageSize + 0x10000));\r
+ MemoryImagePointer = (UINTN) (malloc (Pe32ImageSize + 0x1000));\r
if (MemoryImagePointer == 0) {\r
Error (NULL, 0, 0, "memory allocation failure", NULL);\r
return EFI_OUT_OF_RESOURCES;\r
}\r
- memset ((void *) MemoryImagePointer, 0, Pe32ImageSize + 0x10000);\r
- MemoryImagePointerAligned = (MemoryImagePointer + 0x0FFFF) & (-1 << 16);\r
- \r
+ memset ((void *) MemoryImagePointer, 0, Pe32ImageSize + 0x1000);\r
+ MemoryImagePointerAligned = (MemoryImagePointer + 0x0FFF) & (-1 << 12);\r
+\r
\r
ImageContext.ImageAddress = MemoryImagePointerAligned;\r
\r
free ((VOID *) MemoryImagePointer);\r
return Status;\r
}\r
- \r
- //\r
- // Check if section-alignment and file-alignment match or not\r
- //\r
- if (!(ImageContext.IsTeImage)) {\r
- PeHdr = (EFI_IMAGE_NT_HEADERS *)((UINTN)ImageContext.ImageAddress + \r
- ImageContext.PeCoffHeaderOffset);\r
- if (PeHdr->OptionalHeader.SectionAlignment != PeHdr->OptionalHeader.FileAlignment) {\r
- Error (NULL, 0, 0, "Section-Alignment and File-Alignment does not match", FileGuidString);\r
- free ((VOID *) MemoryImagePointer);\r
- return EFI_ABORTED;\r
- }\r
- }\r
- else {\r
- //\r
- // BUGBUG: TE Image Header lack section-alignment and file-alignment info\r
- //\r
- }\r
\r
ImageContext.DestinationAddress = NewPe32BaseAddress;\r
Status = PeCoffLoaderRelocateImage (&ImageContext);\r
free ((VOID *) MemoryImagePointer);\r
return EFI_ABORTED;\r
}\r
+\r
+ //\r
+ // Update BASE address\r
+ //\r
+ fprintf (\r
+ LogFile,\r
+ "%s %016I64X\n",\r
+ FileGuidString,\r
+ ImageContext.DestinationAddress\r
+ );\r
+ *BaseToUpdate += EFI_SIZE_TO_PAGES (ImageContext.ImageSize) * EFI_PAGE_SIZE;\r
+\r
//\r
// Since we may have updated the Codeview RVA, we need to insure the PE\r
// header indicates the image is large enough to contain the Codeview data\r
// so it will be loaded properly later if the PEIM is reloaded into memory...\r
//\r
PeHdr = (VOID *) ((UINTN) ImageAddress + ImageContext.PeCoffHeaderOffset);\r
+ PePlusHdr = (EFI_IMAGE_NT_HEADERS64*)PeHdr;\r
if (PeHdr->FileHeader.Machine == EFI_IMAGE_MACHINE_IA32) {\r
- PeHdrSizeOfImage = (UINT32 *) (&(*(EFI_IMAGE_OPTIONAL_HEADER32 *) &PeHdr->OptionalHeader).SizeOfImage);\r
- PeHdrChecksum = (UINT32 *) (&(*(EFI_IMAGE_OPTIONAL_HEADER32 *) &PeHdr->OptionalHeader).CheckSum);\r
+ PeHdrSizeOfImage = (UINT32 *) (&(PeHdr->OptionalHeader).SizeOfImage);\r
+ PeHdrChecksum = (UINT32 *) (&(PeHdr->OptionalHeader).CheckSum);\r
} else if (PeHdr->FileHeader.Machine == EFI_IMAGE_MACHINE_IA64) {\r
- PeHdrSizeOfImage = (UINT32 *) (&(*(EFI_IMAGE_OPTIONAL_HEADER64 *) &PeHdr->OptionalHeader).SizeOfImage);\r
- PeHdrChecksum = (UINT32 *) (&(*(EFI_IMAGE_OPTIONAL_HEADER64 *) &PeHdr->OptionalHeader).CheckSum);\r
+ PeHdrSizeOfImage = (UINT32 *) (&(PePlusHdr->OptionalHeader).SizeOfImage);\r
+ PeHdrChecksum = (UINT32 *) (&(PePlusHdr->OptionalHeader).CheckSum);\r
} else if (PeHdr->FileHeader.Machine == EFI_IMAGE_MACHINE_X64) {\r
- PeHdrSizeOfImage = (UINT32 *) (&(*(EFI_IMAGE_OPTIONAL_HEADER64 *) &PeHdr->OptionalHeader).SizeOfImage);\r
- PeHdrChecksum = (UINT32 *) (&(*(EFI_IMAGE_OPTIONAL_HEADER64 *) &PeHdr->OptionalHeader).CheckSum);\r
+ PeHdrSizeOfImage = (UINT32 *) (&(PePlusHdr->OptionalHeader).SizeOfImage);\r
+ PeHdrChecksum = (UINT32 *) (&(PePlusHdr->OptionalHeader).CheckSum);\r
} else {\r
Error (\r
NULL,\r
}\r
\r
memcpy (CurrentPe32Section.Pe32Section + 1, (VOID *) MemoryImagePointerAligned, (UINT32) ImageSize);\r
- \r
- //\r
- // Get EntryPoint in Flash Region.\r
- //\r
- EntryPoint = NewPe32BaseAddress + EntryPoint - ImageAddress;\r
-\r
- //\r
- // If a map file was selected output mapping information for any file that\r
- // was rebased.\r
- //\r
- if (MapFile != NULL) {\r
- fprintf (MapFile, "PE32 File: %s Base:%08lx", FileGuidString, BaseAddress);\r
- fprintf (MapFile, " EntryPoint:%08lx", EntryPoint);\r
- if (ImageContext.PdbPointer != NULL) {\r
- fprintf (MapFile, " FileName: %s", ImageContext.PdbPointer);\r
- }\r
- fprintf (MapFile, "\n");\r
- }\r
\r
free ((VOID *) MemoryImagePointer);\r
\r
*(EFI_FFS_FILE_TAIL *) (((UINTN) FfsFile + GetLength (FfsFile->Size) - sizeof (EFI_FFS_FILE_TAIL))) = TailValue;\r
}\r
}\r
+\r
+ if ((Flags & 1) == 0 || (\r
+ FfsFile->Type != EFI_FV_FILETYPE_SECURITY_CORE &&\r
+ FfsFile->Type != EFI_FV_FILETYPE_PEI_CORE &&\r
+\r
+ FfsFile->Type != EFI_FV_FILETYPE_PEIM &&\r
+ FfsFile->Type != EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER\r
+ )) {\r
+ //\r
+ // Only XIP code may have a TE section\r
+ //\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
//\r
// Now process TE sections\r
//\r
break;\r
}\r
\r
- FoundCount++;\r
-\r
//\r
// Calculate the TE base address, the FFS file base plus the offset of the TE section less the size stripped off\r
// by GenTEImage\r
//\r
TEImageHeader = (EFI_TE_IMAGE_HEADER *) ((UINT8 *) CurrentPe32Section.Pe32Section + sizeof (EFI_COMMON_SECTION_HEADER));\r
\r
- NewPe32BaseAddress = ((UINT32) BaseAddress) +\r
+ NewPe32BaseAddress = ((UINT32) XipBase) +\r
(\r
(UINTN) CurrentPe32Section.Pe32Section +\r
sizeof (EFI_COMMON_SECTION_HEADER) +\r
DosHeader->e_magic = EFI_IMAGE_DOS_SIGNATURE;\r
*(UINT32 *) (TEBuffer + 0x3C) = 0x40;\r
PeHdr = (EFI_IMAGE_NT_HEADERS *) (TEBuffer + 0x40);\r
+ PePlusHdr = (EFI_IMAGE_NT_HEADERS64*)PeHdr;\r
PeHdr->Signature = EFI_IMAGE_NT_SIGNATURE;\r
PeHdr->FileHeader.Machine = TEImageHeader->Machine;\r
PeHdr->FileHeader.NumberOfSections = TEImageHeader->NumberOfSections;\r
// the 0x40 bytes for our DOS header.\r
//\r
PeHdr->FileHeader.SizeOfOptionalHeader = (UINT16) (TEImageHeader->StrippedSize - 0x40 - sizeof (UINT32) - sizeof (EFI_IMAGE_FILE_HEADER));\r
- PeHdr->OptionalHeader.ImageBase = (UINTN) (TEImageHeader->ImageBase - TEImageHeader->StrippedSize + sizeof (EFI_TE_IMAGE_HEADER));\r
- PeHdr->OptionalHeader.AddressOfEntryPoint = TEImageHeader->AddressOfEntryPoint;\r
- PeHdr->OptionalHeader.BaseOfCode = TEImageHeader->BaseOfCode;\r
- PeHdr->OptionalHeader.SizeOfImage = Pe32ImageSize;\r
- PeHdr->OptionalHeader.Subsystem = TEImageHeader->Subsystem;\r
- PeHdr->OptionalHeader.SizeOfImage = Pe32ImageSize;\r
- PeHdr->OptionalHeader.SizeOfHeaders = TEImageHeader->StrippedSize + TEImageHeader->NumberOfSections *\r
- sizeof (EFI_IMAGE_SECTION_HEADER) - 12;\r
-\r
- //\r
- // Set NumberOfRvaAndSizes in the optional header to what we had available in the original image\r
- //\r
- if ((TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress != 0) ||\r
- (TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size != 0)\r
- ) {\r
- PeHdr->OptionalHeader.NumberOfRvaAndSizes = EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC + 1;\r
- PeHdr->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress;\r
- PeHdr->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;\r
+ if (TEImageHeader->Machine == EFI_IMAGE_MACHINE_IA32) {\r
+ PeHdr->OptionalHeader.Magic = EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC;\r
+ } else if (TEImageHeader->Machine == EFI_IMAGE_MACHINE_IA64) {\r
+ PePlusHdr->OptionalHeader.Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;\r
+ } else if (TEImageHeader->Machine == EFI_IMAGE_MACHINE_X64) {\r
+ PePlusHdr->OptionalHeader.Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;\r
+ } else {\r
+ Error (\r
+ NULL,\r
+ 0,\r
+ 0,\r
+ "unknown machine type in TE image",\r
+ "machine type=0x%X, file=%s",\r
+ (UINT32) TEImageHeader->Machine,\r
+ FileGuidString\r
+ );\r
+ free (TEBuffer);\r
+ return EFI_ABORTED;\r
}\r
\r
- if ((TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress != 0) ||\r
- (TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].Size != 0)\r
- ) {\r
- PeHdr->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress = TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;\r
- PeHdr->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size = TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].Size;\r
- if (PeHdr->OptionalHeader.NumberOfRvaAndSizes < EFI_IMAGE_DIRECTORY_ENTRY_DEBUG + 1) {\r
- PeHdr->OptionalHeader.NumberOfRvaAndSizes = EFI_IMAGE_DIRECTORY_ENTRY_DEBUG + 1;\r
+ if (PeHdr->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+ PeHdr->OptionalHeader.ImageBase = (UINTN) (TEImageHeader->ImageBase - TEImageHeader->StrippedSize + sizeof (EFI_TE_IMAGE_HEADER));\r
+ PeHdr->OptionalHeader.SizeOfImage = Pe32ImageSize;\r
+ PeHdr->OptionalHeader.Subsystem = TEImageHeader->Subsystem;\r
+ PeHdr->OptionalHeader.SizeOfHeaders = TEImageHeader->StrippedSize + TEImageHeader->NumberOfSections *\r
+ sizeof (EFI_IMAGE_SECTION_HEADER) - 12;\r
+\r
+ //\r
+ // Set NumberOfRvaAndSizes in the optional header to what we had available in the original image\r
+ //\r
+ if ((TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress != 0) ||\r
+ (TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size != 0)\r
+ ) {\r
+ PeHdr->OptionalHeader.NumberOfRvaAndSizes = EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC + 1;\r
+ PeHdr->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress;\r
+ PeHdr->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;\r
+ }\r
+\r
+ if ((TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress != 0) ||\r
+ (TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].Size != 0)\r
+ ) {\r
+ PeHdr->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress = TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;\r
+ PeHdr->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size = TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].Size;\r
+ if (PeHdr->OptionalHeader.NumberOfRvaAndSizes < EFI_IMAGE_DIRECTORY_ENTRY_DEBUG + 1) {\r
+ PeHdr->OptionalHeader.NumberOfRvaAndSizes = EFI_IMAGE_DIRECTORY_ENTRY_DEBUG + 1;\r
+ }\r
+ }\r
+ //\r
+ // NOTE: These values are defaults, and should be verified to be correct in the GenTE utility\r
+ //\r
+ PeHdr->OptionalHeader.SectionAlignment = 0x10;\r
+ } else {\r
+ PePlusHdr->OptionalHeader.ImageBase = (UINTN) (TEImageHeader->ImageBase - TEImageHeader->StrippedSize + sizeof (EFI_TE_IMAGE_HEADER));\r
+ PePlusHdr->OptionalHeader.SizeOfImage = Pe32ImageSize;\r
+ PePlusHdr->OptionalHeader.Subsystem = TEImageHeader->Subsystem;\r
+ PePlusHdr->OptionalHeader.SizeOfHeaders = TEImageHeader->StrippedSize + TEImageHeader->NumberOfSections *\r
+ sizeof (EFI_IMAGE_SECTION_HEADER) - 12;\r
+\r
+ //\r
+ // Set NumberOfRvaAndSizes in the optional header to what we had available in the original image\r
+ //\r
+ if ((TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress != 0) ||\r
+ (TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size != 0)\r
+ ) {\r
+ PePlusHdr->OptionalHeader.NumberOfRvaAndSizes = EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC + 1;\r
+ PePlusHdr->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress;\r
+ PePlusHdr->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;\r
}\r
+\r
+ if ((TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress != 0) ||\r
+ (TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].Size != 0)\r
+ ) {\r
+ PePlusHdr->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress = TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;\r
+ PePlusHdr->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size = TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].Size;\r
+ if (PePlusHdr->OptionalHeader.NumberOfRvaAndSizes < EFI_IMAGE_DIRECTORY_ENTRY_DEBUG + 1) {\r
+ PePlusHdr->OptionalHeader.NumberOfRvaAndSizes = EFI_IMAGE_DIRECTORY_ENTRY_DEBUG + 1;\r
+ }\r
+ }\r
+ //\r
+ // NOTE: These values are defaults, and should be verified to be correct in the GenTE utility\r
+ //\r
+ PePlusHdr->OptionalHeader.SectionAlignment = 0x10;\r
}\r
- //\r
- // NOTE: These values are defaults, and should be verified to be correct in the GenTE utility\r
- //\r
- PeHdr->OptionalHeader.SectionAlignment = 0x10;\r
\r
//\r
// Copy the rest of the image to its original offset\r
//\r
// Allocate a buffer for the image to be loaded into.\r
//\r
- MemoryImagePointer = (UINTN) (malloc (Pe32ImageSize + 0x10000));\r
+ MemoryImagePointer = (UINTN) (malloc (Pe32ImageSize + 0x1000));\r
if (MemoryImagePointer == 0) {\r
Error (NULL, 0, 0, "memory allocation error on rebase of TE image", FileGuidString);\r
free (TEBuffer);\r
return EFI_OUT_OF_RESOURCES;\r
}\r
- memset ((void *) MemoryImagePointer, 0, Pe32ImageSize + 0x10000);\r
- MemoryImagePointerAligned = (MemoryImagePointer + 0x0FFFF) & (-1 << 16);\r
- \r
+ memset ((void *) MemoryImagePointer, 0, Pe32ImageSize + 0x1000);\r
+ MemoryImagePointerAligned = (MemoryImagePointer + 0x0FFF) & (-1 << 12);\r
+\r
\r
ImageContext.ImageAddress = MemoryImagePointerAligned;\r
Status = PeCoffLoaderLoadImage (&ImageContext);\r
free ((VOID *) MemoryImagePointer);\r
return Status;\r
}\r
- \r
- //\r
- // Check if section-alignment and file-alignment match or not\r
- // BUGBUG: TE Image Header lack section-alignment and file-alignment info\r
- //\r
\r
ImageContext.DestinationAddress = NewPe32BaseAddress;\r
Status = PeCoffLoaderRelocateImage (&ImageContext);\r
// so it will be loaded properly later if the PEIM is reloaded into memory...\r
//\r
PeHdr = (VOID *) ((UINTN) ImageAddress + ImageContext.PeCoffHeaderOffset);\r
+ PePlusHdr = (EFI_IMAGE_NT_HEADERS64*)PeHdr;\r
if (PeHdr->FileHeader.Machine == EFI_IMAGE_MACHINE_IA32) {\r
- PeHdrSizeOfImage = (UINT32 *) (&(*(EFI_IMAGE_OPTIONAL_HEADER32 *) &PeHdr->OptionalHeader).SizeOfImage);\r
- PeHdrChecksum = (UINT32 *) (&(*(EFI_IMAGE_OPTIONAL_HEADER32 *) &PeHdr->OptionalHeader).CheckSum);\r
+ PeHdrSizeOfImage = (UINT32 *) (&(PeHdr->OptionalHeader).SizeOfImage);\r
+ PeHdrChecksum = (UINT32 *) (&(PeHdr->OptionalHeader).CheckSum);\r
} else if (PeHdr->FileHeader.Machine == EFI_IMAGE_MACHINE_IA64) {\r
- PeHdrSizeOfImage = (UINT32 *) (&(*(EFI_IMAGE_OPTIONAL_HEADER64 *) &PeHdr->OptionalHeader).SizeOfImage);\r
- PeHdrChecksum = (UINT32 *) (&(*(EFI_IMAGE_OPTIONAL_HEADER64 *) &PeHdr->OptionalHeader).CheckSum);\r
+ PeHdrSizeOfImage = (UINT32 *) (&(PePlusHdr->OptionalHeader).SizeOfImage);\r
+ PeHdrChecksum = (UINT32 *) (&(PePlusHdr->OptionalHeader).CheckSum);\r
+ } else if (PeHdr->FileHeader.Machine == EFI_IMAGE_MACHINE_X64) {\r
+ PeHdrSizeOfImage = (UINT32 *) (&(PePlusHdr->OptionalHeader).SizeOfImage);\r
+ PeHdrChecksum = (UINT32 *) (&(PePlusHdr->OptionalHeader).CheckSum);\r
} else {\r
Error (\r
NULL,\r
GetLength (CurrentPe32Section.Pe32Section->CommonHeader.Size) - sizeof (EFI_PE32_SECTION) -\r
sizeof (EFI_TE_IMAGE_HEADER)\r
);\r
- \r
- //\r
- // Get EntryPoint in Flash Region.\r
- //\r
- EntryPoint = NewPe32BaseAddress + EntryPoint - ImageAddress;\r
-\r
- //\r
- // If a map file was selected output mapping information for any file that\r
- // was rebased.\r
- //\r
- if (MapFile != NULL) {\r
- fprintf (MapFile, "TE File: %s Base:%08lx", FileGuidString, BaseAddress);\r
- fprintf (MapFile, " EntryPoint:%08lx", EntryPoint);\r
- if (ImageContext.PdbPointer != NULL) {\r
- fprintf (MapFile, " FileName: %s", ImageContext.PdbPointer);\r
- }\r
- fprintf (MapFile, "\n");\r
- }\r
-\r
free ((VOID *) MemoryImagePointer);\r
free (TEBuffer);\r
if (FfsFile->Attributes & FFS_ATTRIB_TAIL_PRESENT) {\r
TailValue = (EFI_FFS_FILE_TAIL) (~(FfsFile->IntegrityCheck.TailReference));\r
*(EFI_FFS_FILE_TAIL *) (((UINTN) FfsFile + GetLength (FfsFile->Size) - sizeof (EFI_FFS_FILE_TAIL))) = TailValue;\r
}\r
+\r
+ fprintf (\r
+ LogFile,\r
+ "%s %016I64X\n",\r
+ FileGuidString,\r
+ ImageContext.DestinationAddress\r
+ );\r
}\r
- //\r
- // If we found no files, then emit an error if no compressed sections either\r
- //\r
- if (FoundCount == 0) {\r
- Status = GetSectionByType (FfsFile, EFI_SECTION_COMPRESSION, Index, &CurrentPe32Section);\r
- if (EFI_ERROR (Status)) {\r
- Error (NULL, 0, 0, "no PE32, TE, nor compressed section found in FV file", FileGuidString);\r
- return EFI_NOT_FOUND;\r
- }\r
- }\r
- \r
+\r
return EFI_SUCCESS;\r
}\r
\r