📄 bin.cpp
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// This source code is licensed under Microsoft Shared Source License
// Version 1.0 for Windows CE.
// For a copy of the license visit http://go.microsoft.com/fwlink/?LinkId=3223.
//
#include "bin.h"
/*****************************************************************************/
bool write_bin(AddressList &hole_list, CopyList ©_list,
ModuleList &module_list, FileList &file_list,
MemoryList &memory_list, MemoryList &reserve_list,
ModuleList::iterator &kernel, Config &config, MemoryList::iterator xip_mem){
// open bin file
if(config.output_file.empty())
config.output_file = kernel->full_path();
if(config.output_file.rfind("\\") != string::npos)
config.output_file = config.output_file.substr(0, config.output_file.rfind("\\"));
config.output_file += "\\" + xip_mem->name() + ".bin";
ofstream image_file(config.output_file.c_str(), ios::trunc | ios::binary);
if(image_file.bad()){
cerr << "Error: Could not open '" << config.output_file << "' for writing\n";
return false;
}
// write out bin file header
DWORD image_length = 0;
DWORD image_start = config.rom_info.offset + xip_mem->address();
File::set_rom_offset(config.rom_info.offset);
Module::write_bin(image_file, 0, 0, 0, false); // reset this function
LAST_PASS_PRINT cout << "\nWriting " << config.output_file << endl;
image_file.write("B000FF\n", 7);
image_file.write((char *)&image_start, sizeof(DWORD));
image_file.write((char *)&image_length, sizeof(DWORD));
// clear up Module::s_romhdr
Module::s_romhdr.nummods = 0;
Module::s_romhdr.numfiles = 0;
// dump the files and modules!
DWORD romhdr_offset;
Data temp;
// get modules entries
for(ModuleList::iterator mod_itr = module_list.begin(); mod_itr != module_list.end(); mod_itr++){
if(mod_itr->memory_iterator() == xip_mem){
Module::s_romhdr.nummods++;
TOCentry module_toc = mod_itr->get_TOC();
temp.append(&module_toc, sizeof(module_toc));
}
}
// get files entries
for(FileList::iterator file_itr = file_list.begin(); file_itr != file_list.end(); file_itr++){
if(file_itr->memory_iterator() == xip_mem){
Module::s_romhdr.numfiles++;
FILESentry file_toc = file_itr->get_TOC();
temp.append(&file_toc, sizeof(file_toc));
}
}
// set romhrd_offset for later.
// Romhdr needs to be written physically before the toc's and stuff but needs data from them so should
// be written chronologically after them in the build process
romhdr_offset = Memory::allocate_range(hole_list, sizeof(Module::s_romhdr) + temp.size());
if(romhdr_offset == -1){
fprintf(stderr, "Error: Ran out of space in ROM for %s\nsize %d", "ROMHDR/TOC", sizeof(Module::s_romhdr));
return false;
}
// write module/file TOC data
if(temp.size()){
LAST_PASS_PRINT printf("Table of contents %08x %08x (%10u)\n", romhdr_offset + sizeof(ROMHDR), temp.size(), temp.size());
Module::write_bin(image_file, romhdr_offset + sizeof(ROMHDR), temp.ptr(), temp.size());
}
// write toc into kernel
if(xip_mem->is_kernel() && kernel->is_kernel())
kernel->write_TOC_ptr(romhdr_offset);
// write modules data
for(mod_itr = module_list.begin(); mod_itr != module_list.end(); mod_itr++)
if(mod_itr->memory_iterator() == xip_mem)
if(!mod_itr->write(image_file)) {
fprintf(stderr, "Error: module write failed\n");
return false;
}
// write files data
for(file_itr = file_list.begin(); file_itr != file_list.end(); file_itr++)
if(file_itr->memory_iterator() == xip_mem)
file_itr->write(image_file);
// write out kernel signature
DWORD signature[SIGNATURE_SIZE];
signature[0] = ROM_SIGNATURE;
signature[1] = romhdr_offset;
LAST_PASS_PRINT printf("Writing ROM signature and TOC pointer at %08x\n", xip_mem->address() + ROM_SIGNATURE_OFFSET);
File::write_bin(image_file, xip_mem->address() + ROM_SIGNATURE_OFFSET, (char *)signature, sizeof(signature));
DWORD toc_offset = romhdr_offset - xip_mem->address();
File::write_bin(image_file, xip_mem->address() + ROM_SIGNATURE_OFFSET + sizeof(signature), (char *)&toc_offset, sizeof(toc_offset));
// write profile information if applicable
if(config.profile && xip_mem->is_kernel()){
Data address_hitcount;
Data symbol_name;
DWORD next_avail = 0;
DWORD index = 0;
// funky two pass thing just to get next_avail and correctly use that to compute the Symbol address in the profile entry
for(int i = 0; i <= 1; i++){
temp.clear();
address_hitcount.clear();
symbol_name.clear();
ProfileList profile_list;
DWORD current_offset = 0;
MemoryList::iterator mem_itr;
for(mem_itr = memory_list.begin(); mem_itr != memory_list.end(); mem_itr++){
if(mem_itr->type() == RAMIMAGE_TYPE || mem_itr->type() == NANDIMAGE_TYPE){
for(ModuleList::iterator mod_itr = module_list.begin(); mod_itr != module_list.end(); mod_itr++){
if(mod_itr->memory_iterator()->name() == mem_itr->name()){
current_offset += sizeof(PROFentry);
}
}
}
}
index = 0;
for(mem_itr = memory_list.begin(); mem_itr != memory_list.end(); mem_itr++){
if(mem_itr->type() == RAMIMAGE_TYPE || mem_itr->type() == NANDIMAGE_TYPE){
for(ModuleList::iterator mod_itr = module_list.begin(); mod_itr != module_list.end(); mod_itr++){
if(mod_itr->memory_iterator()->name() == mem_itr->name()){
profile_list.push_back(mod_itr->get_profile(i));
profile_list[index].ulModNum = index;
profile_list[index].ulHitAddress = Module::s_romhdr.ulRAMFree + current_offset;
current_offset += profile_list[index].m_function_list.size() * 8;
index++;
}
}
}
}
#if 0
for(ModuleList::iterator mod_itr = module_list.begin(); mod_itr != module_list.end(); mod_itr++){
if(mod_itr->memory_iterator() == xip_mem)
current_offset += sizeof(PROFentry);
}
index = 0;
for(mod_itr = module_list.begin(); mod_itr != module_list.end(); mod_itr++){
if(mod_itr->memory_iterator() == xip_mem){
profile_list.push_back(mod_itr->get_profile(i));
profile_list[index].ulModNum = index;
profile_list[index].ulHitAddress = Module::s_romhdr.ulRAMFree + current_offset;
current_offset += profile_list[index].m_function_list.size() * 8;
index++;
}
}
#endif
static char *suppress = (suppress = getenv("ri_suppress_info")) ? strstr(suppress, "symbol") : NULL;
if(!suppress && i){
LAST_PASS_PRINT printf(" Module Section Start End Hits Symbols HitAddr SymAddr\n");
LAST_PASS_PRINT printf("---------- ---------- -------- -------- ---------- ---------- -------- --------\n");
}
for(ProfileList::iterator prof_itr = profile_list.begin(); prof_itr != profile_list.end(); prof_itr++){
if(!prof_itr->m_function_list.empty())
prof_itr->ulSymAddress = next_avail + current_offset;
for(FunctionList::iterator fun_itr = prof_itr->m_function_list.begin(); fun_itr != prof_itr->m_function_list.end(); fun_itr++){
DWORD name_length = fun_itr->name.size() + 1; // + 1 for the null
current_offset += name_length;
address_hitcount.append(&*fun_itr, 8);
symbol_name.append(fun_itr->name.c_str(), name_length);
}
DWORD zero = 0;
current_offset = align_dword(current_offset);
symbol_name.append(&zero, align_dword(symbol_name.size()) - symbol_name.size()); // dword pad
if(!suppress && i){
static char *delim = getenv("ri_comma_delimit") ? "," : " ";
LAST_PASS_PRINT
printf("%10d%s%10d%s%08x%s%08x%s%10d%s%10d%s%08x%s%08x\n",
prof_itr->ulModNum, delim,
prof_itr->ulSectNum, delim,
prof_itr->ulStartAddr, delim,
prof_itr->ulEndAddr, delim,
prof_itr->ulHits, delim,
prof_itr->ulNumSym, delim,
prof_itr->ulHitAddress, delim,
prof_itr->ulSymAddress);
}
temp.append(&*prof_itr, sizeof(PROFentry));
}
temp.append(address_hitcount);
temp.append(symbol_name);
if(!i){
next_avail = Memory::allocate_range(hole_list, temp.size());
if(next_avail == -1){
fprintf(stderr, "Error: Ran out of space in ROM for %s\nsize %d", "Profile section", temp.size());
return false;
}
}
}
CopyEntry ce;
Module::s_romhdr.ulProfileOffset = Module::s_romhdr.ulRAMFree;
ce.ulSource = next_avail;
ce.ulDest = Module::s_romhdr.ulRAMFree;
ce.ulCopyLen = index * sizeof(PROFentry) + address_hitcount.size();
ce.ulDestLen = index * sizeof(PROFentry) + address_hitcount.size();
ce.m_memory_iterator = xip_mem;
copy_list.push_back(ce);
Module::s_romhdr.ulProfileLen = temp.size();
Module::s_romhdr.ulRAMFree += temp.size();
LAST_PASS_PRINT printf("Profile Header: %08x %08x (%10u)\n", next_avail, index * sizeof(PROFentry), index * sizeof(PROFentry));
Module::write_bin(image_file, next_avail, temp.ptr(), temp.size());
}
// write copylist information if applicable
temp.clear();
// clear this first
Module::s_romhdr.ulCopyEntries = 0;
Module::s_romhdr.ulCopyOffset = 0;
for(unsigned i = 0; i < copy_list.size(); i++){
if(copy_list[i].memory_iterator() == xip_mem){
temp.append(©_list[i], sizeof(COPYentry)); // I really mean COPYentry and *NOT* the CopyEntry wrapper class
Module::s_romhdr.ulCopyEntries++;
}
}
if(Module::s_romhdr.ulCopyEntries){
DWORD addr = Memory::allocate_range(hole_list, temp.size());
if(addr == -1){
fprintf(stderr, "Error: Ran out of space in ROM for %s\nsize %d", "CopyEntries", temp.size());
return false;
}
Module::s_romhdr.ulCopyOffset = addr;
LAST_PASS_PRINT printf("Kernel data copy section %08x %08x (%10u)\n", addr, temp.size(), temp.size());
Module::write_bin(image_file, addr, temp.ptr(), temp.size());
}
// set glob stuff
for(MemoryList::iterator ritr = reserve_list.begin(); ritr != reserve_list.end(); ritr++){
if(ritr->name() == "drivglob"){
Module::s_romhdr.ulDrivglobStart = ritr->address();
Module::s_romhdr.ulDrivglobLen = ritr->length();
}
if(ritr->name() == "tracking"){
Module::s_romhdr.ulTrackingStart = ritr->address();
Module::s_romhdr.ulTrackingLen = ritr->length();
}
}
if(xip_mem->dll_data_start < xip_mem->dll_data_bottom || xip_mem->dll_data_start > xip_mem->dll_data_orig){
fprintf(stderr, "Error: Too much data space used by DLL's in MODULES section\n");
fprintf(stderr, " Current usage = %4dk, Maximum usage = %4dk.\n",
(xip_mem->dll_data_orig - xip_mem->dll_data_start) >> 10,
(xip_mem->dll_data_orig - xip_mem->dll_data_bottom) >> 10);
fprintf(stderr, " Reduce DLL usage or move some DLL's into the FILES section.\n");
return false;
}
if(xip_mem->dll_code_start < xip_mem->dll_code_bottom || xip_mem->dll_code_start > xip_mem->dll_code_orig){
fprintf(stderr, "Error: Too much code space used by DLL's in MODULES section\n");
fprintf(stderr, " Current usage = %4dk, Maximum usage = %4dk.\n",
(xip_mem->dll_code_orig - xip_mem->dll_code_start) >> 10,
(xip_mem->dll_code_orig - xip_mem->dll_code_bottom) >> 10);
fprintf(stderr, " Reduce DLL usage or move some DLL's into the FILES section.\n");
return false;
}
// setup rest of romhdr
if(!xip_mem->dll_data_split)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -