brainlilo/BrainLILODrv.cpp

367 lines
11 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"
2022-01-24 01:52:45 +09:00
#define FILE_DEVICE_POWER FILE_DEVICE_ACPI
2020-09-28 03:19:37 +09:00
2022-01-24 01:52:45 +09:00
#define IOCTL_POWER_CAPABILITIES CTL_CODE(FILE_DEVICE_POWER, 0x400, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_POWER_GET CTL_CODE(FILE_DEVICE_POWER, 0x401, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_POWER_SET CTL_CODE(FILE_DEVICE_POWER, 0x402, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_POWER_QUERY CTL_CODE(FILE_DEVICE_POWER, 0x403, METHOD_BUFFERED, FILE_ANY_ACCESS)
2020-09-28 03:19:37 +09:00
2022-01-24 01:52:45 +09:00
typedef BOOL (*KernelIoControlProc)(DWORD dwIoControlCode, LPVOID lpInBuf, DWORD nInBufSize, LPVOID lpOutBuf,
DWORD nOutBufSize, LPDWORD lpBytesReturned);
2020-09-28 03:19:37 +09:00
static KernelIoControlProc KernelIoControl;
typedef LARGE_INTEGER PHYSICAL_ADDRESS, *PPHYSICAL_ADDRESS;
typedef PVOID (*MmMapIoSpaceProc)(PHYSICAL_ADDRESS, ULONG, BOOL);
static MmMapIoSpaceProc MmMapIoSpace;
typedef void (*FileSystemPowerFunctionProc)(DWORD);
static FileSystemPowerFunctionProc FileSystemPowerFunction;
2022-01-24 01:52:45 +09:00
typedef LPVOID (*AllocPhysMemProc)(DWORD, DWORD, DWORD, DWORD, PULONG);
2020-09-28 03:19:37 +09:00
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 * 12, 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
}
2022-01-24 01:52:45 +09:00
static void EDNA2_physicalInvoker()
{
// r0-r7=params
// r8=proc address
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");
2020-09-28 03:19:37 +09:00
}
2022-01-24 01:52:45 +09:00
static void EDNA2_installPhysicalInvoker()
{
void *ptr = (void *)0xa8000000;
outputDebugMessage(L"BrainLILO: copying PhysicalInvoker to 0x%p from 0x%p\n",
ptr, &EDNA2_physicalInvoker);
2022-01-24 01:52:45 +09:00
memcpy(ptr, (const void *)&EDNA2_physicalInvoker, 64 * 4);
// 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
);
for (DWORD i = 0; i < FileSize; i++)
*((char *)(0xa0200000 + i)) = *((char *)(0xa0000000 + i));
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"
"ldr r8, =0x40200000\n"
"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!
);
// never reach here
while (true)
;
2020-09-28 03:19:37 +09:00
}
2022-01-24 01:52:45 +09:00
__attribute__((noreturn)) static DWORD EDNA2_callKernelEntryPoint()
{
outputDebugMessage(L"BrainLILO: disabling interrupts");
2020-09-28 03:19:37 +09:00
disableInterrupts();
outputDebugMessage(L"BrainLILO: injecting code to internal ram");
2022-01-24 01:52:45 +09:00
EDNA2_installPhysicalInvoker();
outputDebugMessage(L"BrainLILO: invoking");
2022-01-24 01:52:45 +09:00
EDNA2_runPhysicalInvoker();
2020-09-28 03:19:37 +09:00
}
static void ShowMessage(std::string msg, std::string title, UINT typ)
{
void *bufMsg;
void *bufTitle;
bufMsg = LocalAlloc(LPTR, msg.length() * sizeof(wchar_t));
bufTitle = LocalAlloc(LPTR, title.length() * sizeof(wchar_t));
mbstowcs((wchar_t *)bufMsg, msg.c_str(), msg.length());
mbstowcs((wchar_t *)bufTitle, title.c_str(), title.length());
MessageBox(NULL, (wchar_t *)bufMsg, (wchar_t *)bufTitle, typ);
LocalFree(bufMsg);
LocalFree(bufTitle);
}
2022-01-24 01:52:45 +09:00
static bool doLinux()
{
2022-04-19 03:24:54 +09:00
wchar_t wcBuf[256] = {};
std::ifstream iVersion;
std::string line, model;
std::regex modelRe("[A-Z]{2}-[A-Z0-9]+");
std::smatch match;
std::string fn("\\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"Failed to match the model name");
ShowMessage("Failed to match the model name", "BrainLILO", MB_ICONWARNING);
return false;
}
outputDebugMessage(L"BrainLILO: Opening Bootloader file...");
fn += model + ".bin";
2022-04-19 03:24:54 +09:00
mbstowcs(wcBuf, fn.c_str(), fn.length());
hUBoot = CreateFile(wcBuf, 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"Could not open the bootloader: %s", wcBuf);
2022-04-19 03:21:52 +09:00
ShowMessage("Could not open the bootloader: " + fn, "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 0xa0000000...");
if (!ReadFile(hUBoot, (void *)0xa0000000, FileSize, &wReadSize, NULL))
2022-01-24 01:52:45 +09:00
{
outputDebugMessage(L"Could not read the bootloader");
2022-04-19 03:21:52 +09:00
ShowMessage("Could not read the bootloader", "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...");
2022-01-24 01:52:45 +09:00
EDNA2_callKernelEntryPoint();
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:
KernelIoControl = (KernelIoControlProc)GetProcAddress(LoadLibrary(L"COREDLL"), L"KernelIoControl");
MmMapIoSpace = (MmMapIoSpaceProc)GetProcAddress(LoadLibrary(L"CEDDK"), L"MmMapIoSpace");
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;
}