mirror of
https://github.com/brain-hackers/brainlilo
synced 2024-12-22 12:10:05 +09:00
Add support 1st generation Brain (#9)
* Add support 1st generation Brain Address information was given by pepepper. Thank you! * Use CamelCase to name enum types * Update BrainLILODrv.cpp Co-authored-by: Takumi Sueda <puhitaku@gmail.com> * simplify BrainGen enum types * Remove redundant debu log * Fix Gen2 and later addresses Co-authored-by: Toshifumi NISHINAGA <tnishinaga.dev@gmail.com> Co-authored-by: Toshifumi NISHINAGA <tnishinaga@users.noreply.github.com> Co-authored-by: pepepper <hollyholly2014@outlook.jp>
This commit is contained in:
parent
c826f2581e
commit
98a6ae1c54
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,2 +1,4 @@
|
|||||||
*.dll
|
*.dll
|
||||||
*.exe
|
*.exe
|
||||||
|
*.o
|
||||||
|
|
||||||
|
147
BrainLILODrv.cpp
147
BrainLILODrv.cpp
@ -47,6 +47,30 @@
|
|||||||
typedef void (*FileSystemPowerFunctionProc)(DWORD);
|
typedef void (*FileSystemPowerFunctionProc)(DWORD);
|
||||||
static FileSystemPowerFunctionProc FileSystemPowerFunction;
|
static FileSystemPowerFunctionProc FileSystemPowerFunction;
|
||||||
|
|
||||||
|
// GEN1
|
||||||
|
// VA
|
||||||
|
#define BOOTLOADER_PRELOADADDR_GEN1 (uint8_t *)0xa0250000
|
||||||
|
#define BOOTLOADER_LOADADDR_GEN1 (uint8_t *)0xa3f00000
|
||||||
|
#define PHYSICAL_INVOKER_INSTALLADDR_GEN1 (uint8_t *)0xb0000000
|
||||||
|
#define TMPA910_REMAP_REGISTER_ADDRESS (uint32_t *)0xaa000004
|
||||||
|
// PA
|
||||||
|
#define BOOTLOADER_LOADADDR_GEN1_PA (uint8_t *)0x43f00000
|
||||||
|
|
||||||
|
// DEFAULT(GEN2)
|
||||||
|
// VA
|
||||||
|
#define BOOTLOADER_PRELOADADDR (uint8_t *)0xa0000000
|
||||||
|
#define BOOTLOADER_LOADADDR (uint8_t *)0xa0200000
|
||||||
|
#define PHYSICAL_INVOKER_INSTALLADDR (uint8_t *)0xa8000000
|
||||||
|
// PA
|
||||||
|
#define BOOTLOADER_LOADADDR_PA (uint8_t *)0x40200000
|
||||||
|
|
||||||
|
// VA
|
||||||
|
uint8_t *bootloader_preload_address = NULL;
|
||||||
|
uint8_t *bootloader_load_address = NULL;
|
||||||
|
uint8_t *physical_invoker_install_address = NULL;
|
||||||
|
// PA
|
||||||
|
uint8_t *bootloader_load_address_pa = NULL;
|
||||||
|
|
||||||
DWORD fileSize;
|
DWORD fileSize;
|
||||||
int row;
|
int row;
|
||||||
int screenW;
|
int screenW;
|
||||||
@ -56,20 +80,14 @@ static void outputDebugMessage(const wchar_t *format, ...)
|
|||||||
{
|
{
|
||||||
wchar_t buffer[256] = {0};
|
wchar_t buffer[256] = {0};
|
||||||
va_list args;
|
va_list args;
|
||||||
RECT rcScreen = {
|
RECT rcScreen = {.left = 0, .top = 0, .right = screenW, .bottom = screenH};
|
||||||
.left = 0,
|
|
||||||
.top = 0,
|
|
||||||
.right = screenW,
|
|
||||||
.bottom = screenH
|
|
||||||
};
|
|
||||||
|
|
||||||
va_start(args, format);
|
va_start(args, format);
|
||||||
vswprintf(buffer, format, args);
|
vswprintf(buffer, format, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
|
|
||||||
OutputDebugString(buffer);
|
OutputDebugString(buffer);
|
||||||
ExtTextOut(GetDC(NULL), 0, row * 14, ETO_CLIPPED, &rcScreen,
|
ExtTextOut(GetDC(NULL), 0, row * 14, ETO_CLIPPED, &rcScreen, buffer, wcslen(buffer), NULL);
|
||||||
buffer, wcslen(buffer), NULL);
|
|
||||||
|
|
||||||
row++;
|
row++;
|
||||||
}
|
}
|
||||||
@ -83,42 +101,23 @@ static void disableInterrupts()
|
|||||||
: "r0");
|
: "r0");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void EDNA2_physicalInvoker()
|
extern "C" void EDNA2_physicalInvoker();
|
||||||
|
|
||||||
|
static void EnableMemoryRemapGen1()
|
||||||
{
|
{
|
||||||
// r0-r7=params
|
*TMPA910_REMAP_REGISTER_ADDRESS = 1;
|
||||||
// r8=proc address
|
outputDebugMessage(L"BrainLILO: memory remap enable for Gen1\n");
|
||||||
asm volatile("nop\n" // who cares interrupt vectors?
|
|
||||||
"nop\n"
|
|
||||||
"nop\n"
|
|
||||||
"nop\n"
|
|
||||||
"nop\n"
|
|
||||||
"nop\n"
|
|
||||||
"nop\n"
|
|
||||||
"nop\n"
|
|
||||||
"nop\n"
|
|
||||||
"nop\n"
|
|
||||||
"msr cpsr_c, #211\n" // to supervisor mode
|
|
||||||
"mov r9, #0\n"
|
|
||||||
"mcr p15,0,r9,c13,c0,0\n" // clear fcse PID
|
|
||||||
"mrc p15,0,r9,c1,c0,0\n" // read ctrl regs
|
|
||||||
"bic r9, r9, #5\n" // disable MMU/DCache
|
|
||||||
"bic r9, r9, #4096\n" // disable ICache
|
|
||||||
"orr r9, r9, #8192\n" // and reset vectors to upper
|
|
||||||
"mcr p15,0,r9,c1,c0,0\n" // write ctrl regs
|
|
||||||
"mov r9, #0\n"
|
|
||||||
"mcr p15,0,r9,c7,c7,0\n" // invalidate cache
|
|
||||||
"mcr p15,0,r9,c8,c7,0\n" // invalidate tlb
|
|
||||||
"mov pc, r8\n"
|
|
||||||
"nop\n"
|
|
||||||
"nop\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void EDNA2_installPhysicalInvoker()
|
static void EDNA2_installPhysicalInvoker(BrainGen gen)
|
||||||
{
|
{
|
||||||
void *ptr = (void *)0xa8000000;
|
if (gen == Gen1)
|
||||||
outputDebugMessage(L"BrainLILO: copying PhysicalInvoker to 0x%p from 0x%p\n",
|
{
|
||||||
ptr, &EDNA2_physicalInvoker);
|
EnableMemoryRemapGen1();
|
||||||
memcpy(ptr, (const void *)&EDNA2_physicalInvoker, 64 * 4);
|
}
|
||||||
|
outputDebugMessage(L"BrainLILO: copying PhysicalInvoker to 0x%p from 0x%p\n", physical_invoker_install_address,
|
||||||
|
&EDNA2_physicalInvoker);
|
||||||
|
memcpy(physical_invoker_install_address, (const void *)&EDNA2_physicalInvoker, 64 * 4);
|
||||||
// clearCache();
|
// clearCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -131,8 +130,7 @@ __attribute__((noreturn)) static void EDNA2_runPhysicalInvoker()
|
|||||||
"mcr p15,0,r0,c1,c0,0\n" // write ctrl regs
|
"mcr p15,0,r0,c1,c0,0\n" // write ctrl regs
|
||||||
);
|
);
|
||||||
|
|
||||||
for (DWORD i = 0; i < fileSize; i++)
|
memcpy(bootloader_load_address, bootloader_preload_address, fileSize);
|
||||||
*((char *)(0xa0200000 + i)) = *((char *)(0xa0000000 + i));
|
|
||||||
|
|
||||||
asm volatile("ldr r0, =0x0000\n"
|
asm volatile("ldr r0, =0x0000\n"
|
||||||
"ldr r1, =0x0000\n"
|
"ldr r1, =0x0000\n"
|
||||||
@ -142,26 +140,28 @@ __attribute__((noreturn)) static void EDNA2_runPhysicalInvoker()
|
|||||||
"ldr r5, =0x0000\n"
|
"ldr r5, =0x0000\n"
|
||||||
"ldr r6, =0x0000\n"
|
"ldr r6, =0x0000\n"
|
||||||
"ldr r7, =0x0000\n"
|
"ldr r7, =0x0000\n"
|
||||||
"ldr r8, =0x40200000\n"
|
"mov r8, %[textbase]\n"
|
||||||
"ldr r9, =0x0000\n"
|
"ldr r9, =0x0000\n"
|
||||||
|
|
||||||
"mrc p15,0,r10,c1,c0,0\n" // read ctrl regs
|
"mrc p15,0,r10,c1,c0,0\n" // read ctrl regs
|
||||||
"bic r10, r10, #5\n" // disable MMU/DCache
|
"bic r10, r10, #5\n" // disable MMU/DCache
|
||||||
"mcr p15,0,r10,c1,c0,0\n" // write ctrl regs
|
"mcr p15,0,r10,c1,c0,0\n" // write ctrl regs
|
||||||
"swi #0\n" // jump!
|
"swi #0\n" // jump!
|
||||||
);
|
: /* no outputs */
|
||||||
|
: [textbase] "r"(bootloader_load_address_pa)
|
||||||
|
: "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10");
|
||||||
|
|
||||||
// never reach here
|
// never reach here
|
||||||
while (true)
|
while (true)
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
__attribute__((noreturn)) static DWORD EDNA2_callKernelEntryPoint()
|
__attribute__((noreturn)) static DWORD EDNA2_callKernelEntryPoint(BrainGen gen)
|
||||||
{
|
{
|
||||||
outputDebugMessage(L"BrainLILO: disabling interrupts");
|
outputDebugMessage(L"BrainLILO: disabling interrupts");
|
||||||
disableInterrupts();
|
disableInterrupts();
|
||||||
outputDebugMessage(L"BrainLILO: injecting code to internal ram");
|
outputDebugMessage(L"BrainLILO: injecting code to internal ram");
|
||||||
EDNA2_installPhysicalInvoker();
|
EDNA2_installPhysicalInvoker(gen);
|
||||||
outputDebugMessage(L"BrainLILO: invoking");
|
outputDebugMessage(L"BrainLILO: invoking");
|
||||||
Sleep(1000);
|
Sleep(1000);
|
||||||
|
|
||||||
@ -173,12 +173,54 @@ static void ShowMessage(std::wstring msg, std::wstring title, UINT typ)
|
|||||||
MessageBox(NULL, msg.c_str(), title.c_str(), typ);
|
MessageBox(NULL, msg.c_str(), title.c_str(), typ);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void SetAddress(BrainGen gen)
|
||||||
|
{
|
||||||
|
switch (gen)
|
||||||
|
{
|
||||||
|
case Gen1:
|
||||||
|
// VA
|
||||||
|
bootloader_preload_address = BOOTLOADER_PRELOADADDR_GEN1;
|
||||||
|
bootloader_load_address = BOOTLOADER_LOADADDR_GEN1;
|
||||||
|
physical_invoker_install_address = PHYSICAL_INVOKER_INSTALLADDR_GEN1;
|
||||||
|
// PA
|
||||||
|
bootloader_load_address_pa = BOOTLOADER_LOADADDR_GEN1_PA;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// Gen2?
|
||||||
|
// VA
|
||||||
|
bootloader_preload_address = BOOTLOADER_PRELOADADDR;
|
||||||
|
bootloader_load_address = BOOTLOADER_LOADADDR;
|
||||||
|
physical_invoker_install_address = PHYSICAL_INVOKER_INSTALLADDR;
|
||||||
|
// PA
|
||||||
|
bootloader_load_address_pa = BOOTLOADER_LOADADDR_PA;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static BrainGen SelectGen(std::wstring model)
|
||||||
|
{
|
||||||
|
BrainGen brainGen = UnknownGen;
|
||||||
|
if (model == L"gen1.bin")
|
||||||
|
{
|
||||||
|
brainGen = Gen1;
|
||||||
|
}
|
||||||
|
else if (model == L"u-boot.bin")
|
||||||
|
{
|
||||||
|
brainGen = UnknownGen;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
brainGen = Gen2Or3;
|
||||||
|
}
|
||||||
|
return brainGen;
|
||||||
|
}
|
||||||
|
|
||||||
static bool doLinux()
|
static bool doLinux()
|
||||||
{
|
{
|
||||||
std::wifstream iVersion;
|
std::wifstream iVersion;
|
||||||
std::wstring line, model;
|
std::wstring line, model;
|
||||||
std::wregex modelRe(L"[A-Z]{2}-[A-Z0-9]+");
|
std::wregex modelRe(L"[A-Z]{2}-[A-Z0-9]+");
|
||||||
std::wsmatch match;
|
std::wsmatch match;
|
||||||
|
BrainGen brain_gen = UnknownGen;
|
||||||
|
|
||||||
std::wstring fn(L"\\Storage Card\\loader\\");
|
std::wstring fn(L"\\Storage Card\\loader\\");
|
||||||
HANDLE hUBoot;
|
HANDLE hUBoot;
|
||||||
@ -207,7 +249,9 @@ static bool doLinux()
|
|||||||
if (iter != models.end())
|
if (iter != models.end())
|
||||||
{
|
{
|
||||||
model = iter->second;
|
model = iter->second;
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
outputDebugMessage(L"BrainLILO: internal model name %s is unknown, falling back to u-boot.bin", model.c_str());
|
outputDebugMessage(L"BrainLILO: internal model name %s is unknown, falling back to u-boot.bin", model.c_str());
|
||||||
model = L"u-boot.bin";
|
model = L"u-boot.bin";
|
||||||
}
|
}
|
||||||
@ -215,6 +259,9 @@ static bool doLinux()
|
|||||||
fn += model;
|
fn += model;
|
||||||
outputDebugMessage(L"BrainLILO: opening Bootloader file: %s", fn.c_str());
|
outputDebugMessage(L"BrainLILO: opening Bootloader file: %s", fn.c_str());
|
||||||
|
|
||||||
|
brain_gen = SelectGen(model);
|
||||||
|
SetAddress(brain_gen);
|
||||||
|
|
||||||
hUBoot = CreateFile(fn.c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
hUBoot = CreateFile(fn.c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||||
if (hUBoot == INVALID_HANDLE_VALUE)
|
if (hUBoot == INVALID_HANDLE_VALUE)
|
||||||
{
|
{
|
||||||
@ -228,8 +275,8 @@ static bool doLinux()
|
|||||||
fileSize = GetFileSize(hUBoot, NULL);
|
fileSize = GetFileSize(hUBoot, NULL);
|
||||||
outputDebugMessage(L"BrainLILO: bootloader file size %d Byte", fileSize);
|
outputDebugMessage(L"BrainLILO: bootloader file size %d Byte", fileSize);
|
||||||
|
|
||||||
outputDebugMessage(L"BrainLILO: preloading bootloader to 0x%p...", 0xa0000000);
|
outputDebugMessage(L"BrainLILO: preloading bootloader to 0x%p...", bootloader_preload_address);
|
||||||
if (!ReadFile(hUBoot, (void *)0xa0000000, fileSize, &wReadSize, NULL))
|
if (!ReadFile(hUBoot, (void *)bootloader_preload_address, fileSize, &wReadSize, NULL))
|
||||||
{
|
{
|
||||||
outputDebugMessage(L"BrainLILO: could not read the bootloader");
|
outputDebugMessage(L"BrainLILO: could not read the bootloader");
|
||||||
ShowMessage(L"Could not read the bootloader", L"BrainLILO", MB_ICONWARNING);
|
ShowMessage(L"Could not read the bootloader", L"BrainLILO", MB_ICONWARNING);
|
||||||
@ -243,7 +290,7 @@ static bool doLinux()
|
|||||||
FileSystemPowerFunction(FSNOTIFY_POWER_OFF);
|
FileSystemPowerFunction(FSNOTIFY_POWER_OFF);
|
||||||
|
|
||||||
outputDebugMessage(L"BrainLILO: starting bootloader call sequence...");
|
outputDebugMessage(L"BrainLILO: starting bootloader call sequence...");
|
||||||
EDNA2_callKernelEntryPoint();
|
EDNA2_callKernelEntryPoint(brain_gen);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
30
EDNA2_physicalInvoker.S
Normal file
30
EDNA2_physicalInvoker.S
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
.align 4
|
||||||
|
|
||||||
|
.global EDNA2_physicalInvoker
|
||||||
|
EDNA2_physicalInvoker:
|
||||||
|
// r0-r7=params
|
||||||
|
// r8=proc address
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
msr cpsr_c, #211 // to supervisor mode
|
||||||
|
mov r9, #0
|
||||||
|
mcr p15,0,r9,c13,c0,0 // clear fcse PID
|
||||||
|
mrc p15,0,r9,c1,c0,0 // read ctrl regs
|
||||||
|
bic r9, r9, #5 // disable MMU/DCache
|
||||||
|
bic r9, r9, #4096 // disable ICache
|
||||||
|
orr r9, r9, #8192 // and reset vectors to upper
|
||||||
|
mcr p15,0,r9,c1,c0,0 // write ctrl regs
|
||||||
|
mov r9, #0
|
||||||
|
mcr p15,0,r9,c7,c7,0 // invalidate cache
|
||||||
|
mcr p15,0,r9,c8,c7,0 // invalidate tlb
|
||||||
|
mov pc, r8
|
||||||
|
nop
|
||||||
|
nop
|
4
Makefile
4
Makefile
@ -42,8 +42,8 @@ BrainLILO.dll: BrainLILO.cpp
|
|||||||
$(CXX) BrainLILO.cpp -o BrainLILO.dll $(DLLFLAGS)
|
$(CXX) BrainLILO.cpp -o BrainLILO.dll $(DLLFLAGS)
|
||||||
$(STRIP) BrainLILO.dll
|
$(STRIP) BrainLILO.dll
|
||||||
|
|
||||||
BrainLILODrv.dll: BrainLILODrv.cpp
|
BrainLILODrv.dll: BrainLILODrv.cpp EDNA2_physicalInvoker.S
|
||||||
$(CXX) BrainLILODrv.cpp -o BrainLILODrv.dll $(DRVFLAGS)
|
$(CXX) BrainLILODrv.cpp EDNA2_physicalInvoker.S -o BrainLILODrv.dll $(DRVFLAGS)
|
||||||
$(STRIP) BrainLILODrv.dll
|
$(STRIP) BrainLILODrv.dll
|
||||||
|
|
||||||
BrainLILO.exe: bootloader.cpp
|
BrainLILO.exe: bootloader.cpp
|
||||||
|
Loading…
Reference in New Issue
Block a user