diff --git a/arm11/link.ld b/arm11/link.ld index b1ca2a9..a0f3845 100644 --- a/arm11/link.ld +++ b/arm11/link.ld @@ -4,7 +4,7 @@ ENTRY(__boot) MEMORY { - AXIWRAM (RWX) : ORIGIN = 0x1FF80000, LENGTH = 96K + AXIWRAM (RWX) : ORIGIN = 0x1FF80000, LENGTH = 128K HIGHRAM (RWX) : ORIGIN = 0xFFFF0000, LENGTH = 4K } diff --git a/arm11/source/main.c b/arm11/source/main.c index c0d22f4..9e7424e 100644 --- a/arm11/source/main.c +++ b/arm11/source/main.c @@ -31,6 +31,7 @@ #include "hw/nvram.h" #include "system/sys.h" +#include "system/xalloc.h" static GlobalSharedMemory SharedMemory_State; @@ -57,7 +58,7 @@ void VBlank_Handler(u32 __attribute__((unused)) irqn) #endif // 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 SharedMemory_State.hid_state = HID_GetState(); ARM_WbDC_Range(&SharedMemory_State, sizeof(SharedMemory_State)); @@ -158,6 +159,12 @@ void PXI_RX_Handler(u32 __attribute__((unused)) irqn) break; } + case PXI_XALLOC: + { + ret = (u32)XAlloc(args[0]); + break; + } + /* New CMD template: case CMD_ID: { diff --git a/arm11/source/system/xalloc.c b/arm11/source/system/xalloc.c new file mode 100755 index 0000000..3850ea8 --- /dev/null +++ b/arm11/source/system/xalloc.c @@ -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 . + */ + +// 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; +} diff --git a/arm11/source/system/xalloc.h b/arm11/source/system/xalloc.h new file mode 100755 index 0000000..02bcd60 --- /dev/null +++ b/arm11/source/system/xalloc.h @@ -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 . + */ + +#pragma once + +#include "types.h" + +#define XALLOC_BUF_SIZE (16384) + +void *XAlloc(size_t size); diff --git a/arm9/source/common/touchcal.c b/arm9/source/common/touchcal.c index d4f874e..91d0d66 100644 --- a/arm9/source/common/touchcal.c +++ b/arm9/source/common/touchcal.c @@ -106,7 +106,9 @@ bool CalibrateTouchFromFlash(void) { // check NVRAM console ID 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) return false; // not a 3DS @@ -114,7 +116,9 @@ bool CalibrateTouchFromFlash(void) { // see: https://problemkaputt.de/gbatek.htm#dsfirmwareusersettings u32 fw_usercfg_buf[0x100 / 0x4]; 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)) return false; diff --git a/arm9/source/system/i2c.c b/arm9/source/system/i2c.c index 0a1844a..d9a3586 100755 --- a/arm9/source/system/i2c.c +++ b/arm9/source/system/i2c.c @@ -4,63 +4,57 @@ #include "i2c.h" #include "pxi.h" -/* - disgusting hack that deserves to die in hell - ideally all buffers would be able to be accessed - by the ARM11, but those in ARM9 RAM are inaccessible - (.data, .rodata & .bss) +// buffer is allocated only once and remains through runtime +static char *i2c_xfer_buf = NULL; - the current hack assumes all buffers in the heap are - located in FCRAM, which is accessible to both processors - but it's horrendous, and hopefully temporary -*/ +static bool I2C_AllocBuffer(void) +{ + 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) { - if (!i2c_fcram_buf) - i2c_fcram_buf = malloc(256); - 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(); ret = PXI_DoCMD(PXI_I2C_READ, args, 4); - ARM_InvDC_Range(i2c_fcram_buf, size); - memcpy(out, i2c_fcram_buf, size); + ARM_InvDC_Range(i2c_xfer_buf, size); + memcpy(out, i2c_xfer_buf, size); return ret; } bool I2C_writeRegBuf(I2cDevice devId, u8 regAddr, const u8 *in, u32 size) { - if (!i2c_fcram_buf) - i2c_fcram_buf = malloc(256); - int ret; - u32 args[] = {devId, regAddr, (u32)i2c_fcram_buf, size}; - memcpy(i2c_fcram_buf, in, size); - ARM_WbDC_Range(i2c_fcram_buf, size); + if (!I2C_AllocBuffer()) + 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(); ret = PXI_DoCMD(PXI_I2C_WRITE, args, 4); 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 data; @@ -69,16 +63,6 @@ u8 I2C_readReg(I2cDevice devId, u8 regAddr) 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) { return I2C_writeRegBuf(devId, regAddr, &data, 1); diff --git a/arm9/source/system/spiflash.c b/arm9/source/system/spiflash.c new file mode 100755 index 0000000..4dbb830 --- /dev/null +++ b/arm9/source/system/spiflash.c @@ -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; +} diff --git a/arm9/source/system/spiflash.h b/arm9/source/system/spiflash.h index a3af1c6..9cea180 100644 --- a/arm9/source/system/spiflash.h +++ b/arm9/source/system/spiflash.h @@ -25,16 +25,6 @@ #define NVRAM_SIZE 0x20000 // 1 Mbit (128kiB) // true if spiflash is installed, false otherwise -static inline bool spiflash_get_status(void) -{ // there should probably be a command for this... - return PXI_DoCMD(PXI_NVRAM_ONLINE, NULL, 0); -} +bool spiflash_get_status(void); -static inline void 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); -} +bool spiflash_read(u32 offset, u32 size, u8 *buf); diff --git a/arm9/source/virtual/vmem.c b/arm9/source/virtual/vmem.c index 5a18180..dd59cef 100644 --- a/arm9/source/virtual/vmem.c +++ b/arm9/source/virtual/vmem.c @@ -165,8 +165,9 @@ int ReadVMemNVRAM(const VirtualFile* vfile, void* buffer, u64 offset, u64 count) wififlash_initialized = spiflash_get_status(); if (!wififlash_initialized) return 1; } - - spiflash_read((u32) offset, (u32) count, buffer); + + if (!spiflash_read((u32) offset, (u32) count, buffer)) + return 1; return 0; } diff --git a/common/pxi.h b/common/pxi.h index 8d8cf84..f302fb4 100644 --- a/common/pxi.h +++ b/common/pxi.h @@ -40,6 +40,8 @@ enum { PXI_NOTIFY_LED, PXI_BRIGHTNESS, + + PXI_XALLOC, }; /*