fix broken cross-buffer assumption, check nvram reads

This commit is contained in:
Wolfvak 2019-09-02 23:34:27 -03:00 committed by d0k3
parent 1a0fe17b6c
commit 2ef408f4af
10 changed files with 156 additions and 62 deletions

View File

@ -4,7 +4,7 @@ ENTRY(__boot)
MEMORY MEMORY
{ {
AXIWRAM (RWX) : ORIGIN = 0x1FF80000, LENGTH = 96K AXIWRAM (RWX) : ORIGIN = 0x1FF80000, LENGTH = 128K
HIGHRAM (RWX) : ORIGIN = 0xFFFF0000, LENGTH = 4K HIGHRAM (RWX) : ORIGIN = 0xFFFF0000, LENGTH = 4K
} }

View File

@ -31,6 +31,7 @@
#include "hw/nvram.h" #include "hw/nvram.h"
#include "system/sys.h" #include "system/sys.h"
#include "system/xalloc.h"
static GlobalSharedMemory SharedMemory_State; static GlobalSharedMemory SharedMemory_State;
@ -57,7 +58,7 @@ void VBlank_Handler(u32 __attribute__((unused)) irqn)
#endif #endif
// the state should probably be stored on its own // the state should probably be stored on its own
// setion without caching enabled, since it must // section without caching enabled, since it must
// be readable by the ARM9 at all times anyway // be readable by the ARM9 at all times anyway
SharedMemory_State.hid_state = HID_GetState(); SharedMemory_State.hid_state = HID_GetState();
ARM_WbDC_Range(&SharedMemory_State, sizeof(SharedMemory_State)); ARM_WbDC_Range(&SharedMemory_State, sizeof(SharedMemory_State));
@ -158,6 +159,12 @@ void PXI_RX_Handler(u32 __attribute__((unused)) irqn)
break; break;
} }
case PXI_XALLOC:
{
ret = (u32)XAlloc(args[0]);
break;
}
/* New CMD template: /* New CMD template:
case CMD_ID: case CMD_ID:
{ {

37
arm11/source/system/xalloc.c Executable file
View File

@ -0,0 +1,37 @@
/*
* This file is part of GodMode9
* Copyright (C) 2019 Wolfvak
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// super simple watermark allocator for ARM9 <-> ARM11 xfers
// designed to be request once, free never
#include "system/xalloc.h"
static char xalloc_buf[XALLOC_BUF_SIZE];
static size_t mark = 0;
void *XAlloc(size_t size)
{ // not thread-safe at all
void *ret;
size_t end = size + mark;
if (end >= XALLOC_BUF_SIZE)
return NULL;
ret = &xalloc_buf[mark];
mark = end;
return ret;
}

25
arm11/source/system/xalloc.h Executable file
View File

@ -0,0 +1,25 @@
/*
* This file is part of GodMode9
* Copyright (C) 2019 Wolfvak
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "types.h"
#define XALLOC_BUF_SIZE (16384)
void *XAlloc(size_t size);

View File

@ -106,7 +106,9 @@ bool CalibrateTouchFromFlash(void) {
// check NVRAM console ID // check NVRAM console ID
u32 console_id = 0; u32 console_id = 0;
spiflash_read(0x001C, 4, (u8*)&console_id); if (!spiflash_read(0x001C, 4, (u8*)&console_id))
return false;
if (((console_id >> 8) & 0xFF) != 0x57) if (((console_id >> 8) & 0xFF) != 0x57)
return false; // not a 3DS return false; // not a 3DS
@ -114,7 +116,9 @@ bool CalibrateTouchFromFlash(void) {
// see: https://problemkaputt.de/gbatek.htm#dsfirmwareusersettings // see: https://problemkaputt.de/gbatek.htm#dsfirmwareusersettings
u32 fw_usercfg_buf[0x100 / 0x4]; u32 fw_usercfg_buf[0x100 / 0x4];
u8* fw_usercfg = (u8*) fw_usercfg_buf; u8* fw_usercfg = (u8*) fw_usercfg_buf;
spiflash_read(0x1FE00, 0x100, fw_usercfg); if (!spiflash_read(0x1FE00, 0x100, fw_usercfg))
return false;
if (getle16(fw_usercfg + 0x72) != crc16_quick(fw_usercfg, 0x70)) if (getle16(fw_usercfg + 0x72) != crc16_quick(fw_usercfg, 0x70))
return false; return false;

View File

@ -4,63 +4,57 @@
#include "i2c.h" #include "i2c.h"
#include "pxi.h" #include "pxi.h"
/* // buffer is allocated only once and remains through runtime
disgusting hack that deserves to die in hell static char *i2c_xfer_buf = NULL;
ideally all buffers would be able to be accessed
by the ARM11, but those in ARM9 RAM are inaccessible
(.data, .rodata & .bss)
the current hack assumes all buffers in the heap are static bool I2C_AllocBuffer(void)
located in FCRAM, which is accessible to both processors {
but it's horrendous, and hopefully temporary if (!i2c_xfer_buf) {
*/ u32 xbuf = PXI_DoCMD(PXI_XALLOC, (u32[]){256}, 1);
if (xbuf == 0 || xbuf == 0xFFFFFFFF)
return false;
i2c_xfer_buf = (char*)xbuf;
}
return true;
}
static char *i2c_fcram_buf = NULL;
bool I2C_readRegBuf(I2cDevice devId, u8 regAddr, u8 *out, u32 size) bool I2C_readRegBuf(I2cDevice devId, u8 regAddr, u8 *out, u32 size)
{ {
if (!i2c_fcram_buf)
i2c_fcram_buf = malloc(256);
int ret; int ret;
u32 args[] = {devId, regAddr, (u32)i2c_fcram_buf, size}; u32 *args;
ARM_WbDC_Range(i2c_fcram_buf, size); if (!I2C_AllocBuffer())
return false;
args = (u32[]){devId, regAddr, (u32)i2c_xfer_buf, size};
ARM_WbDC_Range(i2c_xfer_buf, size);
ARM_DSB(); ARM_DSB();
ret = PXI_DoCMD(PXI_I2C_READ, args, 4); ret = PXI_DoCMD(PXI_I2C_READ, args, 4);
ARM_InvDC_Range(i2c_fcram_buf, size); ARM_InvDC_Range(i2c_xfer_buf, size);
memcpy(out, i2c_fcram_buf, size); memcpy(out, i2c_xfer_buf, size);
return ret; return ret;
} }
bool I2C_writeRegBuf(I2cDevice devId, u8 regAddr, const u8 *in, u32 size) bool I2C_writeRegBuf(I2cDevice devId, u8 regAddr, const u8 *in, u32 size)
{ {
if (!i2c_fcram_buf)
i2c_fcram_buf = malloc(256);
int ret; int ret;
u32 args[] = {devId, regAddr, (u32)i2c_fcram_buf, size};
memcpy(i2c_fcram_buf, in, size); if (!I2C_AllocBuffer())
ARM_WbDC_Range(i2c_fcram_buf, size); return false;
u32 args[] = {devId, regAddr, (u32)i2c_xfer_buf, size};
memcpy(i2c_xfer_buf, in, size);
ARM_WbDC_Range(i2c_xfer_buf, size);
ARM_DSB(); ARM_DSB();
ret = PXI_DoCMD(PXI_I2C_WRITE, args, 4); ret = PXI_DoCMD(PXI_I2C_WRITE, args, 4);
return ret; return ret;
} }
/*bool I2C_readRegBuf(I2cDevice devId, u8 regAddr, u8 *out, u32 size)
{
int ret;
u32 args[] = {devId, regAddr, (u32)out, size};
cpu_writeback_invalidate_dc_range(out, size);
cpu_membarrier();
ret = PXI_DoCMD(PXI_I2C_READ, args, 4);
cpu_invalidate_dc_range(out, size);
return ret;
}*/
u8 I2C_readReg(I2cDevice devId, u8 regAddr) u8 I2C_readReg(I2cDevice devId, u8 regAddr)
{ {
u8 data; u8 data;
@ -69,16 +63,6 @@ u8 I2C_readReg(I2cDevice devId, u8 regAddr)
return data; return data;
} }
/*bool I2C_writeRegBuf(I2cDevice devId, u8 regAddr, const u8 *in, u32 size)
{
int ret;
u32 args[] = {devId, regAddr, (u32)in, size};
cpu_writeback_dc_range(in, size);
cpu_membarrier();
ret = PXI_DoCMD(PXI_I2C_WRITE, args, 4);
return ret;
}*/
bool I2C_writeReg(I2cDevice devId, u8 regAddr, u8 data) bool I2C_writeReg(I2cDevice devId, u8 regAddr, u8 data)
{ {
return I2C_writeRegBuf(devId, regAddr, &data, 1); return I2C_writeRegBuf(devId, regAddr, &data, 1);

44
arm9/source/system/spiflash.c Executable file
View File

@ -0,0 +1,44 @@
#include "common.h"
#include "arm.h"
#include "pxi.h"
#define SPIFLASH_CHUNK_SIZE (0x1000)
static char *spiflash_xalloc_buf = NULL;
bool spiflash_get_status(void)
{
return PXI_DoCMD(PXI_NVRAM_ONLINE, NULL, 0);
}
bool spiflash_read(u32 offset, u32 size, u8 *buf)
{
u32 args[3];
if (!spiflash_xalloc_buf) {
u32 xbuf = PXI_DoCMD(PXI_XALLOC, (u32[]){SPIFLASH_CHUNK_SIZE}, 1);
if (xbuf == 0 || xbuf == 0xFFFFFFFF)
return false;
spiflash_xalloc_buf = (char*)xbuf;
}
args[1] = (u32)spiflash_xalloc_buf;
while(size > 0) {
u32 rem = min(size, SPIFLASH_CHUNK_SIZE);
args[0] = offset;
args[2] = rem;
ARM_DSB();
PXI_DoCMD(PXI_NVRAM_READ, args, 3);
ARM_InvDC_Range(spiflash_xalloc_buf, rem);
memcpy(buf, spiflash_xalloc_buf, rem);
buf += rem;
size -= rem;
offset += rem;
}
return true;
}

View File

@ -25,16 +25,6 @@
#define NVRAM_SIZE 0x20000 // 1 Mbit (128kiB) #define NVRAM_SIZE 0x20000 // 1 Mbit (128kiB)
// true if spiflash is installed, false otherwise // true if spiflash is installed, false otherwise
static inline bool spiflash_get_status(void) bool spiflash_get_status(void);
{ // there should probably be a command for this...
return PXI_DoCMD(PXI_NVRAM_ONLINE, NULL, 0);
}
static inline void spiflash_read(u32 offset, u32 size, u8 *buf) bool spiflash_read(u32 offset, u32 size, u8 *buf);
{
u32 args[] = {offset, (u32)buf, size};
ARM_WbDC_Range(buf, size);
ARM_DSB();
PXI_DoCMD(PXI_NVRAM_READ, args, 3);
ARM_InvDC_Range(buf, size);
}

View File

@ -165,8 +165,9 @@ int ReadVMemNVRAM(const VirtualFile* vfile, void* buffer, u64 offset, u64 count)
wififlash_initialized = spiflash_get_status(); wififlash_initialized = spiflash_get_status();
if (!wififlash_initialized) return 1; if (!wififlash_initialized) return 1;
} }
spiflash_read((u32) offset, (u32) count, buffer); if (!spiflash_read((u32) offset, (u32) count, buffer))
return 1;
return 0; return 0;
} }

View File

@ -40,6 +40,8 @@ enum {
PXI_NOTIFY_LED, PXI_NOTIFY_LED,
PXI_BRIGHTNESS, PXI_BRIGHTNESS,
PXI_XALLOC,
}; };
/* /*