brainlilo/BrainLILODrv.cpp

424 lines
12 KiB
C++
Raw Normal View History

2020-09-28 03:19:37 +09:00
/*
* BrainLILODrv
* U-Boot loader for electric dictionary.
2022-01-24 01:52:45 +09:00
*
2020-09-28 03:19:37 +09:00
* Copyright (C) 2019 C. Shirasaka <holly_programmer@outlook.com>
* based on
** ResetKitHelper
** Soft/hard reset the electronic dictionary.
2022-01-24 01:52:45 +09:00
**
2020-09-28 03:19:37 +09:00
** Copyright (C) 2012 T. Kawada <tcppjp [ at ] gmail.com>
*
* This file is licensed in MIT license.
*
2022-01-24 01:52:45 +09:00
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the "Software"),
2020-09-28 03:19:37 +09:00
* to deal in the Software without restriction, including without limitation the
2022-01-24 01:52:45 +09:00
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
2020-09-28 03:19:37 +09:00
* furnished to do so, subject to the following conditions:
*
2022-01-24 01:52:45 +09:00
* The above copyright notice and this permission notice shall be included in
2020-09-28 03:19:37 +09:00
* all copies or substantial portions of the Software.
*
2022-01-24 01:52:45 +09:00
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
2020-09-28 03:19:37 +09:00
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2022-01-24 01:52:45 +09:00
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
2020-09-28 03:19:37 +09:00
* THE SOFTWARE.
*
*/
#include <fstream>
#include <regex>
2020-09-28 03:19:37 +09:00
#include <stdint.h>
#include <stdlib.h>
2022-01-24 01:52:45 +09:00
#include <windows.h>
2020-09-28 03:19:37 +09:00
2022-01-24 01:52:45 +09:00
#define FSNOTIFY_POWER_OFF 1
#define FSNOTIFY_POWER_ON 0
2020-09-28 03:19:37 +09:00
#define BRAINLILODRV_API __declspec(dllexport)
#include "BrainLILODrv.h"
#include "models.h"
2020-09-28 03:19:37 +09:00
typedef void (*FileSystemPowerFunctionProc)(DWORD);
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 *)0xa0250000
#define BOOTLOADER_LOADADDR (uint8_t *)0xa0200000
#define PHYSICAL_INVOKER_INSTALLADDR (uint8_t *)0xb0000000
// 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;
int row;
int screenW;
int screenH;
static void outputDebugMessage(const wchar_t *format, ...)
{
wchar_t buffer[256] = {0};
va_list args;
RECT rcScreen = {.left = 0, .top = 0, .right = screenW, .bottom = screenH};
va_start(args, format);
vswprintf(buffer, format, args);
va_end(args);
OutputDebugString(buffer);
ExtTextOut(GetDC(NULL), 0, row * 14, ETO_CLIPPED, &rcScreen, buffer, wcslen(buffer), NULL);
row++;
}
2022-01-24 01:52:45 +09:00
static void disableInterrupts()
{
2020-09-28 03:19:37 +09:00
asm volatile("mrs r0, cpsr\n"
2022-01-24 01:52:45 +09:00
"orr r0,r0,#0x80\n"
"msr cpsr_c,r0\n"
"mov r0,#1" ::
: "r0");
2020-09-28 03:19:37 +09:00
}
extern "C" void EDNA2_physicalInvoker();
static void EnableMemoryRemapGen1()
2022-01-24 01:52:45 +09:00
{
*TMPA910_REMAP_REGISTER_ADDRESS = 1;
outputDebugMessage(L"BrainLILO: memory remap enable for Gen1\n");
2020-09-28 03:19:37 +09:00
}
2022-09-22 01:44:43 +09:00
static void EDNA2_installPhysicalInvoker(BrainGen gen)
2022-01-24 01:52:45 +09:00
{
if (gen == Gen1)
{
EnableMemoryRemapGen1();
}
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);
2022-01-24 01:52:45 +09:00
// clearCache();
2020-09-28 03:19:37 +09:00
}
2022-01-24 01:52:45 +09:00
__attribute__((noreturn)) static void EDNA2_runPhysicalInvoker()
{
// r0=info
asm volatile("msr cpsr_c, #211\n" // to supervisor mode
"mrc p15,0,r0,c1,c0,0\n" // read ctrl regs
"bic r0, r0, #8192\n" // reset vector to lower
"mcr p15,0,r0,c1,c0,0\n" // write ctrl regs
);
memcpy(bootloader_load_address, bootloader_preload_address, fileSize);
2022-01-24 01:52:45 +09:00
asm volatile("ldr r0, =0x0000\n"
"ldr r1, =0x0000\n"
"ldr r2, =0x0000\n"
"ldr r3, =0x0000\n"
"ldr r4, =0x0000\n"
"ldr r5, =0x0000\n"
"ldr r6, =0x0000\n"
"ldr r7, =0x0000\n"
"mov r8, %[textbase]\n"
2022-01-24 01:52:45 +09:00
"ldr r9, =0x0000\n"
"mrc p15,0,r10,c1,c0,0\n" // read ctrl regs
"bic r10, r10, #5\n" // disable MMU/DCache
"mcr p15,0,r10,c1,c0,0\n" // write ctrl regs
"swi #0\n" // jump!
: /* no outputs */
: [textbase] "r"(bootloader_load_address_pa)
: "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10");
2022-01-24 01:52:45 +09:00
// never reach here
while (true)
;
2020-09-28 03:19:37 +09:00
}
2022-09-22 01:44:43 +09:00
__attribute__((noreturn)) static DWORD EDNA2_callKernelEntryPoint(BrainGen gen)
2022-01-24 01:52:45 +09:00
{
outputDebugMessage(L"BrainLILO: disabling interrupts");
2020-09-28 03:19:37 +09:00
disableInterrupts();
outputDebugMessage(L"BrainLILO: injecting code to internal ram");
EDNA2_installPhysicalInvoker(gen);
outputDebugMessage(L"BrainLILO: invoking");
2022-05-05 22:57:51 +09:00
Sleep(1000);
2022-01-24 01:52:45 +09:00
EDNA2_runPhysicalInvoker();
2020-09-28 03:19:37 +09:00
}
static void ShowMessage(std::wstring msg, std::wstring title, UINT typ)
{
MessageBox(NULL, msg.c_str(), title.c_str(), typ);
}
2022-09-22 01:44:43 +09:00
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;
}
}
2022-09-22 01:44:43 +09:00
static BrainGen SelectGen(std::wstring model)
{
2022-09-22 01:44:43 +09:00
BrainGen brain_gen = UnknownGen;
if (model == L"gen1.bin")
{
brain_gen = Gen1;
}
else if (model == L"gen2.bin")
{
brain_gen = Gen2;
}
else if (model == L"gen3_1.bin")
{
brain_gen = Gen3_1;
}
else if (model == L"gen3_2.bin")
{
brain_gen = Gen3_2;
}
else if (model == L"gen3_3.bin")
{
brain_gen = Gen3_3;
}
else if (model == L"gen3_4.bin")
{
brain_gen = Gen3_4;
}
else if (model == L"gen3_5.bin")
{
brain_gen = Gen3_5;
}
else if (model == L"gen3_6.bin")
{
brain_gen = Gen3_6;
}
else if (model == L"gen3_7.bin")
{
brain_gen = Gen3_7;
}
else
{
brain_gen = UnknownGen;
}
return brain_gen;
}
2022-01-24 01:52:45 +09:00
static bool doLinux()
{
std::wifstream iVersion;
std::wstring line, model;
std::wregex modelRe(L"[A-Z]{2}-[A-Z0-9]+");
std::wsmatch match;
2022-09-22 01:44:43 +09:00
BrainGen brain_gen = UnknownGen;
std::wstring fn(L"\\Storage Card\\loader\\");
HANDLE hUBoot;
2022-01-24 01:52:45 +09:00
DWORD wReadSize;
iVersion.open("\\NAND\\version.txt");
while (getline(iVersion, line))
{
if (regex_search(line, match, modelRe))
{
model = match[0].str();
break;
}
}
if (model.length() == 0)
{
outputDebugMessage(L"BrainLILO: failed to match the model name");
MessageBox(NULL, L"Failed to match the model name", L"BrainLILO", MB_ICONWARNING);
return false;
}
outputDebugMessage(L"BrainLILO: internal model name: %s", model.c_str());
auto iter = models.find(model);
if (iter != models.end())
{
model = iter->second;
}
else
{
outputDebugMessage(L"BrainLILO: internal model name %s is unknown, falling back to u-boot.bin", model.c_str());
model = L"u-boot.bin";
}
fn += model;
outputDebugMessage(L"BrainLILO: opening Bootloader file: %s", fn.c_str());
brain_gen = SelectGen(model);
outputDebugMessage(L"BrainLILO: This is %d generation Brain", brain_gen);
SetAddress(brain_gen);
hUBoot = CreateFile(fn.c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hUBoot == INVALID_HANDLE_VALUE)
2022-01-24 01:52:45 +09:00
{
outputDebugMessage(L"BrainLILO: could not open the bootloader: %s", fn.c_str());
ShowMessage(L"Could not open the bootloader: " + fn, L"BrainLILO", MB_ICONWARNING);
2022-01-24 01:52:45 +09:00
return false;
}
outputDebugMessage(L"BrainLILO: bootloader file handle 0x%p", hUBoot);
fileSize = GetFileSize(hUBoot, NULL);
outputDebugMessage(L"BrainLILO: bootloader file size %d Byte", fileSize);
2022-01-24 01:52:45 +09:00
outputDebugMessage(L"BrainLILO: preloading bootloader to 0x%p...", bootloader_preload_address);
if (!ReadFile(hUBoot, (void *)bootloader_preload_address, fileSize, &wReadSize, NULL))
2022-01-24 01:52:45 +09:00
{
outputDebugMessage(L"BrainLILO: could not read the bootloader");
ShowMessage(L"Could not read the bootloader", L"BrainLILO", MB_ICONWARNING);
2022-01-24 01:52:45 +09:00
return false;
}
outputDebugMessage(L"BrainLILO: bootloader copied! Closing file handle...");
CloseHandle(hUBoot);
2022-01-24 01:52:45 +09:00
outputDebugMessage(L"BrainLILO: notifying power off to filesystems...");
2022-01-24 01:52:45 +09:00
if (FileSystemPowerFunction)
FileSystemPowerFunction(FSNOTIFY_POWER_OFF);
outputDebugMessage(L"BrainLILO: starting bootloader call sequence...");
EDNA2_callKernelEntryPoint(brain_gen);
2022-01-24 01:52:45 +09:00
return true;
2020-09-28 03:19:37 +09:00
}
2022-01-24 01:52:45 +09:00
extern "C" BRAINLILODRV_API BOOL LIN_IOControl(DWORD handle, DWORD dwIoControlCode, DWORD *pInBuf, DWORD nInBufSize,
DWORD *pOutBuf, DWORD nOutBufSize, PDWORD pBytesReturned)
{
2020-09-28 03:19:37 +09:00
SetLastError(0);
2022-01-24 01:52:45 +09:00
switch (dwIoControlCode)
{
case IOCTL_LIN_DO_LINUX:
if (!doLinux())
{
if (FileSystemPowerFunction)
FileSystemPowerFunction(FSNOTIFY_POWER_ON);
return FALSE;
}
return TRUE;
2020-09-28 03:19:37 +09:00
}
return FALSE;
}
2022-01-24 01:52:45 +09:00
extern "C" BRAINLILODRV_API BOOL LIN_Read(DWORD handle, LPVOID pBuffer, DWORD dwNumBytes)
{
2020-09-28 03:19:37 +09:00
SetLastError(ERROR_INVALID_FUNCTION);
return FALSE;
}
2022-01-24 01:52:45 +09:00
extern "C" BRAINLILODRV_API BOOL LIN_Write(DWORD handle, LPVOID pBuffer, DWORD dwNumBytes)
{
2020-09-28 03:19:37 +09:00
SetLastError(ERROR_INVALID_FUNCTION);
return FALSE;
}
2022-01-24 01:52:45 +09:00
extern "C" BRAINLILODRV_API DWORD LIN_Seek(DWORD handle, long lDistance, DWORD dwMoveMethod)
{
2020-09-28 03:19:37 +09:00
SetLastError(ERROR_INVALID_FUNCTION);
return FALSE;
}
2022-01-24 01:52:45 +09:00
extern "C" BRAINLILODRV_API void LIN_PowerUp(void)
{
OutputDebugString(L"BrainLILO: resuming.");
}
2020-09-28 03:19:37 +09:00
2022-01-24 01:52:45 +09:00
extern "C" BRAINLILODRV_API void LIN_PowerDown(void)
{
2020-09-28 03:19:37 +09:00
}
2022-01-24 01:52:45 +09:00
extern "C" BRAINLILODRV_API DWORD LIN_Init(LPCTSTR pContext, DWORD dwBusContext)
{
2020-09-28 03:19:37 +09:00
2022-01-24 01:52:45 +09:00
void *ctx;
ctx = (void *)LocalAlloc(LPTR, sizeof(4));
screenW = GetSystemMetrics(SM_CXVIRTUALSCREEN);
screenH = GetSystemMetrics(SM_CYVIRTUALSCREEN);
2022-01-24 01:52:45 +09:00
return (DWORD)ctx;
2020-09-28 03:19:37 +09:00
}
2022-01-24 01:52:45 +09:00
extern "C" BRAINLILODRV_API DWORD LIN_Open(DWORD dwData, DWORD dwAccess, DWORD dwShareMode)
{
2020-09-28 03:19:37 +09:00
2022-01-24 01:52:45 +09:00
void *hnd = (void *)LocalAlloc(LPTR, 4);
row = 0;
2022-01-24 01:52:45 +09:00
return (DWORD)hnd;
2020-09-28 03:19:37 +09:00
}
2022-01-24 01:52:45 +09:00
extern "C" BRAINLILODRV_API BOOL LIN_Close(DWORD handle)
{
LocalFree((void *)handle);
2020-09-28 03:19:37 +09:00
2022-01-24 01:52:45 +09:00
return TRUE;
2020-09-28 03:19:37 +09:00
}
2022-01-24 01:52:45 +09:00
extern "C" BRAINLILODRV_API BOOL LIN_Deinit(DWORD dwContext)
{
2020-09-28 03:19:37 +09:00
2022-01-24 01:52:45 +09:00
LocalFree((void *)dwContext);
return TRUE;
2020-09-28 03:19:37 +09:00
}
2022-01-24 01:52:45 +09:00
extern "C" BOOL APIENTRY DllMainCRTStartup(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
2020-09-28 03:19:37 +09:00
{
switch (ul_reason_for_call)
2022-01-24 01:52:45 +09:00
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
FileSystemPowerFunction =
(FileSystemPowerFunctionProc)GetProcAddress(LoadLibrary(L"COREDLL"), L"FileSystemPowerFunction");
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
2020-09-28 03:19:37 +09:00
}
return TRUE;
}