mirror of
https://github.com/LNH-team/pico-loader.git
synced 2026-06-02 09:16:49 +02:00
Initial commit
This commit is contained in:
106
arm7/source/loader/DldiDriver.cpp
Normal file
106
arm7/source/loader/DldiDriver.cpp
Normal file
@@ -0,0 +1,106 @@
|
||||
#include "common.h"
|
||||
#include <string.h>
|
||||
#include "DldiDriver.h"
|
||||
|
||||
void DldiDriver::Relocate(u32 targetAddress)
|
||||
{
|
||||
u32 currentAddress = _driver->driverStartAddress;
|
||||
if (currentAddress == targetAddress)
|
||||
return;
|
||||
|
||||
u32 currentEndAddress = _driver->driverEndAddress;
|
||||
|
||||
if (_driver->fixFlags & DLDI_FIX_ALL)
|
||||
{
|
||||
LOG_WARNING("Dldi driver uses FIX_ALL flag");
|
||||
u32* ptr = (u32*)((u8*)_driver + sizeof(dldi_header_t));
|
||||
u32 size = currentEndAddress - currentAddress;
|
||||
for (u32 i = 0; i < size; i += 4)
|
||||
{
|
||||
u32 word = *ptr;
|
||||
if (currentAddress <= word && word < currentEndAddress)
|
||||
*ptr = word - currentAddress + targetAddress;
|
||||
ptr++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// note that we are not going to do those fixes when we did
|
||||
// FIX_ALL already, since it covers them already
|
||||
if (_driver->fixFlags & DLDI_FIX_GLUE)
|
||||
{
|
||||
u32* ptr = (u32*)((u8*)_driver + _driver->glueStartAddress - currentAddress);
|
||||
u32 size = _driver->glueEndAddress - _driver->glueStartAddress;
|
||||
for (u32 i = 0; i < size; i += 4)
|
||||
{
|
||||
u32 word = *ptr;
|
||||
if (currentAddress <= word && word < currentEndAddress)
|
||||
*ptr = word - currentAddress + targetAddress;
|
||||
ptr++;
|
||||
}
|
||||
}
|
||||
if (_driver->fixFlags & DLDI_FIX_GOT)
|
||||
{
|
||||
u32* ptr = (u32*)((u8*)_driver + _driver->gotStartAddress - currentAddress);
|
||||
u32 size = _driver->gotEndAddress - _driver->gotStartAddress;
|
||||
for (u32 i = 0; i < size; i += 4)
|
||||
{
|
||||
u32 word = *ptr;
|
||||
if (currentAddress <= word && word < currentEndAddress)
|
||||
*ptr = word - currentAddress + targetAddress;
|
||||
ptr++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_driver->driverStartAddress = targetAddress;
|
||||
_driver->driverEndAddress = _driver->driverEndAddress + targetAddress - currentAddress;
|
||||
_driver->glueStartAddress = _driver->glueStartAddress + targetAddress - currentAddress;
|
||||
_driver->glueEndAddress = _driver->glueEndAddress + targetAddress - currentAddress;
|
||||
_driver->gotStartAddress = _driver->gotStartAddress + targetAddress - currentAddress;
|
||||
_driver->gotEndAddress = _driver->gotEndAddress + targetAddress - currentAddress;
|
||||
_driver->bssStartAddress = _driver->bssStartAddress + targetAddress - currentAddress;
|
||||
_driver->bssEndAddress = _driver->bssEndAddress + targetAddress - currentAddress;
|
||||
|
||||
_driver->startupFuncAddress = _driver->startupFuncAddress + targetAddress - currentAddress;
|
||||
_driver->isInsertedFuncAddress = _driver->isInsertedFuncAddress + targetAddress - currentAddress;
|
||||
_driver->readSectorsFuncAddress = _driver->readSectorsFuncAddress + targetAddress - currentAddress;
|
||||
_driver->writeSectorsFuncAddress = _driver->writeSectorsFuncAddress + targetAddress - currentAddress;
|
||||
_driver->clearStatusFuncAddress = _driver->clearStatusFuncAddress + targetAddress - currentAddress;
|
||||
_driver->shutdownFuncAddress = _driver->shutdownFuncAddress + targetAddress - currentAddress;
|
||||
}
|
||||
|
||||
void DldiDriver::PrepareForUse()
|
||||
{
|
||||
if (_driver->fixFlags & DLDI_FIX_BSS)
|
||||
{
|
||||
memset((u8*)_driver + _driver->bssStartAddress - _driver->driverStartAddress, 0,
|
||||
_driver->bssEndAddress - _driver->bssStartAddress);
|
||||
}
|
||||
}
|
||||
|
||||
bool DldiDriver::PatchTo(dldi_header_t* stub)
|
||||
{
|
||||
if (_driver->dldiMagic != DLDI_MAGIC)
|
||||
return false;
|
||||
|
||||
u32 stubSize = stub->stubSize;
|
||||
if (stubSize < _driver->driverSize)
|
||||
{
|
||||
LOG_ERROR("Dldi stub of size %d is not large enough for driver of size %d\n",
|
||||
stubSize, _driver->driverSize);
|
||||
return false;
|
||||
}
|
||||
|
||||
u32 targetAddress = stub->driverStartAddress;
|
||||
u32 driverSize = 1 << _driver->driverSize;
|
||||
|
||||
memcpy(stub, _driver, driverSize);
|
||||
stub->stubSize = stubSize;
|
||||
|
||||
auto newDriver = DldiDriver(stub);
|
||||
newDriver.Relocate(targetAddress);
|
||||
newDriver.PrepareForUse();
|
||||
|
||||
return true;
|
||||
}
|
||||
Reference in New Issue
Block a user