diff --git a/arm9/source/system/spiflash.c b/arm9/source/system/spiflash.c new file mode 100644 index 0000000..3c51f92 --- /dev/null +++ b/arm9/source/system/spiflash.c @@ -0,0 +1,89 @@ +/* + * This file is part of fastboot 3DS + * Copyright (C) 2017 derrek, profi200 + * + * 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 3 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 . + */ + +#include "common.h" +#include "spiflash.h" + + +#define SPI_REGS_BUS2_BASE (0x10000000 + 0x100000 + 0x60000) +#define REG_SPI_BUS2_CNT *((vu16*)(SPI_REGS_BUS2_BASE + 0x00)) +#define REG_SPI_BUS2_DATA *((vu8* )(SPI_REGS_BUS2_BASE + 0x02)) + + + +static void spi_busy_wait() +{ + while(REG_SPI_BUS2_CNT & 0x80); +} + +static void spi_put_byte(u8 data) +{ + REG_SPI_BUS2_DATA = data; + spi_busy_wait(); +} + +static u8 spi_receive_byte() +{ + // clock out a dummy byte + REG_SPI_BUS2_DATA = 0x00; + spi_busy_wait(); + return REG_SPI_BUS2_DATA; +} + +// select spiflash if select=true, deselect otherwise +static void spiflash_select(bool select) +{ + // select device 1, enable SPI bus + REG_SPI_BUS2_CNT = 0x8100 | (select << 11); +} + +bool spiflash_get_status() +{ + u8 resp; + + spi_busy_wait(); + spiflash_select(1); + spi_put_byte(SPIFLASH_CMD_RDSR); + spiflash_select(0); + resp = spi_receive_byte(); + + if(resp & 1) return false; + return true; +} + +void spiflash_read(u32 offset, u32 size, u8 *buf) +{ + spi_busy_wait(); + spiflash_select(1); + spi_put_byte(SPIFLASH_CMD_READ); + + // write addr (24-bit, msb first) + for(int i=0; i<3; i++) + { + offset <<= 8; + spi_put_byte((offset >> 24) & 0xFF); + } + + // read bytes + for(u32 i=0; i. + */ + +#include "common.h" + + +#define NVRAM_SIZE 0x20000 // 1 Mbit (128kiB) +#define SPIFLASH_CMD_RDSR (0x05) +#define SPIFLASH_CMD_READ (0x03) + + + +// true if spiflash is installed, false otherwise +bool spiflash_get_status(); +void spiflash_read(u32 offset, u32 size, u8 *buf); diff --git a/arm9/source/virtual/vmem.c b/arm9/source/virtual/vmem.c index 01efe39..eca8533 100644 --- a/arm9/source/virtual/vmem.c +++ b/arm9/source/virtual/vmem.c @@ -5,6 +5,7 @@ #include "keydb.h" #include "sdmmc.h" #include "itcm.h" +#include "spiflash.h" #include "i2c.h" #define VFLAG_CALLBACK (1UL<<27) @@ -46,17 +47,20 @@ enum VMemCallbackType { VMEM_CALLBACK_OTP_DECRYPTED, VMEM_CALLBACK_MCU_REGISTERS, VMEM_CALLBACK_FLASH_CID, + VMEM_CALLBACK_NVRAM, VMEM_NUM_CALLBACKS }; ReadVMemFileCallback ReadVMemOTPDecrypted; ReadVMemFileCallback ReadVMemMCURegisters; ReadVMemFileCallback ReadVMemFlashCID; +ReadVMemFileCallback ReadVMemNVRAM; static ReadVMemFileCallback* const vMemCallbacks[] = { ReadVMemOTPDecrypted, ReadVMemMCURegisters, - ReadVMemFlashCID + ReadVMemFlashCID, + ReadVMemNVRAM }; STATIC_ASSERT(sizeof(vMemCallbacks) / sizeof(vMemCallbacks[0]) == VMEM_NUM_CALLBACKS); @@ -83,7 +87,8 @@ static const VirtualFile vMemFileTemplates[] = { { "mcu_3ds_regs.mem" , VMEM_CALLBACK_MCU_REGISTERS, 0x00000100, I2C_DEV_MCU, VFLAG_CALLBACK | VFLAG_READONLY }, { "mcu_dsi_regs.mem" , VMEM_CALLBACK_MCU_REGISTERS, 0x00000100, I2C_DEV_POWER, VFLAG_CALLBACK | VFLAG_READONLY }, { "sd_cid.mem" , VMEM_CALLBACK_FLASH_CID , 0x00000010, 0x00, VFLAG_CALLBACK | VFLAG_READONLY }, - { "nand_cid.mem" , VMEM_CALLBACK_FLASH_CID , 0x00000010, 0x01, VFLAG_CALLBACK | VFLAG_READONLY } + { "nand_cid.mem" , VMEM_CALLBACK_FLASH_CID , 0x00000010, 0x01, VFLAG_CALLBACK | VFLAG_READONLY }, + { "nvram.mem" , VMEM_CALLBACK_NVRAM , NVRAM_SIZE, 0x00, VFLAG_CALLBACK | VFLAG_READONLY } }; bool ReadVMemDir(VirtualFile* vfile, VirtualDir* vdir) { // uses a generic vdir object generated in virtual.c @@ -156,6 +161,20 @@ int ReadVMemFlashCID(const VirtualFile* vfile, void* buffer, u64 offset, u64 cou return 0; } +// Read NVRAM. +int ReadVMemNVRAM(const VirtualFile* vfile, void* buffer, u64 offset, u64 count) { + static bool wififlash_initialized = false; + (void) vfile; + + if (!wififlash_initialized) { + wififlash_initialized = spiflash_get_status(); + if (!wififlash_initialized) return 1; + } + + spiflash_read((u32) offset, (u32) count, buffer); + return 0; +} + int ReadVMemFile(const VirtualFile* vfile, void* buffer, u64 offset, u64 count) { if (vfile->flags & VFLAG_CALLBACK) { if ((offset + count > vfile->size) || (0u + offset + count < offset))