Skip to content

Commit

Permalink
DOL loader cleanup with std::vector and safety checks
Browse files Browse the repository at this point in the history
  • Loading branch information
JosJuice committed Apr 19, 2015
1 parent c74ae3d commit 2967de5
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 71 deletions.
5 changes: 4 additions & 1 deletion Source/Core/Core/Boot/Boot.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,7 @@ bool CBoot::BootUp()
{
std::unique_ptr<DiscIO::IVolume> pVolume(DiscIO::CreateVolumeFromFilename(_StartupPara.m_strFilename));
if (pVolume == nullptr)
break;
return false;

if (pVolume->IsWiiDisc() != _StartupPara.bWii)
{
Expand Down Expand Up @@ -298,6 +298,9 @@ bool CBoot::BootUp()
case SCoreStartupParameter::BOOT_DOL:
{
CDolLoader dolLoader(_StartupPara.m_strFilename);
if (!dolLoader.IsValid())
return false;

// Check if we have gotten a Wii file or not
bool dolWii = dolLoader.IsWii();
if (dolWii != _StartupPara.bWii)
Expand Down
117 changes: 58 additions & 59 deletions Source/Core/Core/Boot/Boot_DOL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// Refer to the license.txt file included.

#include <string>
#include <vector>

#include "Common/CommonFuncs.h"
#include "Common/FileUtil.h"
Expand All @@ -11,106 +12,104 @@
#include "Core/HW/Memmap.h"
#include "Core/PowerPC/PowerPC.h"

CDolLoader::CDolLoader(u8* _pBuffer, u32 _Size)
: m_isWii(false)
CDolLoader::CDolLoader(u8* buffer, size_t size)
{
Initialize(_pBuffer, _Size);
m_is_valid = Initialize(buffer, size);
}

CDolLoader::CDolLoader(const std::string& filename)
: m_isWii(false)
{
const u64 size = File::GetSize(filename);
u8* const tmpBuffer = new u8[(size_t)size];
std::vector<u8> temp_buffer(size);

{
File::IOFile pStream(filename, "rb");
pStream.ReadBytes(tmpBuffer, (size_t)size);
pStream.ReadBytes(temp_buffer.data(), temp_buffer.size());
}

Initialize(tmpBuffer, (u32)size);
delete[] tmpBuffer;
m_is_valid = Initialize(temp_buffer.data(), temp_buffer.size());
}

CDolLoader::~CDolLoader()
{
for (auto& sect : text_section)
{
delete [] sect;
sect = nullptr;
}

for (auto& sect : data_section)
{
delete [] sect;
sect = nullptr;
}
}

void CDolLoader::Initialize(u8* _pBuffer, u32 _Size)
bool CDolLoader::Initialize(u8* buffer, size_t size)
{
memcpy(&m_dolheader, _pBuffer, sizeof(SDolHeader));
if (size < sizeof(SDolHeader))
return false;

memcpy(&m_dolheader, buffer, sizeof(SDolHeader));

// swap memory
u32* p = (u32*)&m_dolheader;
for (size_t i = 0; i < (sizeof(SDolHeader)/sizeof(u32)); i++)
for (size_t i = 0; i < (sizeof(SDolHeader) / sizeof(u32)); i++)
p[i] = Common::swap32(p[i]);

for (auto& sect : text_section)
sect = nullptr;
for (auto& sect : data_section)
sect = nullptr;
const u32 HID4_pattern = Common::swap32(0x7c13fba6);
const u32 HID4_mask = Common::swap32(0xfc1fffff);

u32 HID4_pattern = 0x7c13fba6;
u32 HID4_mask = 0xfc1fffff;
m_is_wii = false;

for (int i = 0; i < DOL_NUM_TEXT; i++)
_assert_(m_text_sections.empty());
m_text_sections.reserve(DOL_NUM_TEXT);
for (int i = 0; i < DOL_NUM_TEXT; ++i)
{
if (m_dolheader.textOffset[i] != 0)
if (m_dolheader.textSize[i] != 0)
{
text_section[i] = new u8[m_dolheader.textSize[i]];
memcpy(text_section[i], _pBuffer + m_dolheader.textOffset[i], m_dolheader.textSize[i]);
for (unsigned int j = 0; j < (m_dolheader.textSize[i]/sizeof(u32)); j++)
if (size < m_dolheader.textOffset[i] + m_dolheader.textSize[i])
return false;

u8* text_start = buffer + m_dolheader.textOffset[i];
m_text_sections.emplace_back(text_start, text_start + m_dolheader.textSize[i]);

for (unsigned int j = 0; !m_is_wii && j < (m_dolheader.textSize[i] / sizeof(u32)); ++j)
{
u32 word = Common::swap32(((u32*)text_section[i])[j]);
u32 word = ((u32*)text_start)[j];
if ((word & HID4_mask) == HID4_pattern)
{
m_isWii = true;
break;
}
m_is_wii = true;
}
}
else
{
// Make sure that m_text_sections indexes match header indexes
m_text_sections.emplace_back();
}
}
_assert_(m_text_sections.size() == DOL_NUM_TEXT);

for (int i = 0; i < DOL_NUM_DATA; i++)
_assert_(m_data_sections.empty());
m_data_sections.reserve(DOL_NUM_DATA);
for (int i = 0; i < DOL_NUM_DATA; ++i)
{
if (m_dolheader.dataOffset[i] != 0)
if (m_dolheader.dataSize[i] != 0)
{
if (size < m_dolheader.dataOffset[i] + m_dolheader.dataSize[i])
return false;

u8* data_start = buffer + m_dolheader.dataOffset[i];
m_data_sections.emplace_back(data_start, data_start + m_dolheader.dataSize[i]);
}
else
{
data_section[i] = new u8[m_dolheader.dataSize[i]];
memcpy(data_section[i], _pBuffer + m_dolheader.dataOffset[i], m_dolheader.dataSize[i]);
// Make sure that m_data_sections indexes match header indexes
m_data_sections.emplace_back();
}
}
_assert_(m_text_sections.size() == DOL_NUM_DATA);

return true;
}

void CDolLoader::Load()
void CDolLoader::Load() const
{
// load all text (code) sections
for (int i = 0; i < DOL_NUM_TEXT; i++)
{
if (m_dolheader.textOffset[i] != 0)
{
for (u32 num = 0; num < m_dolheader.textSize[i]; num++)
Memory::Write_U8(text_section[i][num], m_dolheader.textAddress[i] + num);
}
}
for (size_t i = 0; i < m_text_sections.size(); ++i)
if (!m_text_sections[i].empty())
Memory::CopyToEmu(m_dolheader.textAddress[i], m_text_sections[i].data(), m_text_sections[i].size());

// load all data sections
for (int i = 0; i < DOL_NUM_DATA; i++)
{
if (m_dolheader.dataOffset[i] != 0)
{
for (u32 num = 0; num < m_dolheader.dataSize[i]; num++)
Memory::Write_U8(data_section[i][num], m_dolheader.dataAddress[i] + num);
}
}
for (size_t i = 0; i < m_data_sections.size(); ++i)
if (!m_data_sections[i].empty())
Memory::CopyToEmu(m_dolheader.dataAddress[i], m_data_sections[i].data(), m_data_sections[i].size());
}
19 changes: 11 additions & 8 deletions Source/Core/Core/Boot/Boot_DOL.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,23 @@
#pragma once

#include <string>
#include <vector>

#include "Common/CommonTypes.h"

class CDolLoader
{
public:
CDolLoader(const std::string& filename);
CDolLoader(u8* _pBuffer, u32 _Size);
CDolLoader(u8* buffer, size_t size);
~CDolLoader();

bool IsWii() const { return m_isWii; }
bool IsValid() const { return m_is_valid; }
bool IsWii() const { return m_is_wii; }
u32 GetEntryPoint() const { return m_dolheader.entryPoint; }

// Load into emulated memory
void Load();
void Load() const;

private:
enum
Expand All @@ -42,15 +44,16 @@ class CDolLoader
u32 bssAddress;
u32 bssSize;
u32 entryPoint;
u32 padd[7];
//u32 padding[7];
};
SDolHeader m_dolheader;

u8 *data_section[DOL_NUM_DATA];
u8 *text_section[DOL_NUM_TEXT];
std::vector<std::vector<u8>> m_data_sections;
std::vector<std::vector<u8>> m_text_sections;

bool m_isWii;
bool m_is_valid;
bool m_is_wii;

// Copy sections to internal buffers
void Initialize(u8* _pBuffer, u32 _Size);
bool Initialize(u8* buffer, size_t size);
};
3 changes: 3 additions & 0 deletions Source/Core/Core/Boot/Boot_WiiWAD.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,9 @@ bool CBoot::Boot_WiiWAD(const std::string& _pFilename)
{
pDolLoader = std::make_unique<CDolLoader>(pContent->m_Filename);
}
if (!pDolLoader->IsValid())
return false;

pDolLoader->Load();
PC = pDolLoader->GetEntryPoint();

Expand Down
16 changes: 13 additions & 3 deletions Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_es.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -924,10 +924,20 @@ IPCCommandResult CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
{
pDolLoader = std::make_unique<CDolLoader>(pContent->m_Filename);
}
pDolLoader->Load(); // TODO: Check why sysmenu does not load the DOL correctly
PC = pDolLoader->GetEntryPoint();

if (pDolLoader->IsValid())
{
pDolLoader->Load(); // TODO: Check why sysmenu does not load the DOL correctly
PC = pDolLoader->GetEntryPoint();
bSuccess = true;
}
else
{
PanicAlertT("IOCTL_ES_LAUNCH: The DOL file is invalid!");
bSuccess = false;
}

IOSv = ContentLoader.GetIosVersion();
bSuccess = true;
}
}
}
Expand Down

0 comments on commit 2967de5

Please sign in to comment.