diff --git a/.github/workflows/building.yml b/.github/workflows/building.yml index 39fa5ba0..21627f72 100644 --- a/.github/workflows/building.yml +++ b/.github/workflows/building.yml @@ -15,7 +15,7 @@ on: jobs: build: runs-on: ubuntu-latest - container: devkitpro/devkitarm:20241104 + container: devkitpro/devkitarm name: Build with Docker using devkitARM steps: - name: Checkout repo @@ -31,7 +31,7 @@ jobs: - name: Build & Package GodMode9i id: build run: | - make all dsi + make chmod +x make_cia ./make_cia --srl="GodMode9i.dsi" --id_0=$(git rev-parse --short=7 HEAD) --tikID=$(git rev-parse --short=16 HEAD) mkdir GodMode9i/ diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index 5cc2dca4..00000000 --- a/.gitmodules +++ /dev/null @@ -1,3 +0,0 @@ -[submodule "libnds32"] - path = libnds32 - url = https://github.com/lifehackerhansol/libnds32 diff --git a/Makefile b/Makefile index c86487bd..fe1b50dd 100644 --- a/Makefile +++ b/Makefile @@ -1,64 +1,71 @@ #--------------------------------------------------------------------------------- .SUFFIXES: #--------------------------------------------------------------------------------- -.SECONDARY: - ifeq ($(strip $(DEVKITARM)),) $(error "Please set DEVKITARM in your environment. export DEVKITARM=devkitARM") endif -include $(DEVKITARM)/ds_rules - export TARGET := GodMode9i +export TOPDIR := $(CURDIR) -export GAME_TITLE := $(TARGET) +# specify a directory which contains the nitro filesystem +# this is relative to the Makefile +NITRO_FILES := nitrofiles -export NITRODATA := nitrofiles +# These set the information text in the nds file +GAME_TITLE := GodMode9i +GAME_SUBTITLE := +GAME_AUTHOR := Rocket Robz +GAME_CODE := HGMA +GAME_HEADER_TITLE := GODMODE9I -.PHONY: all bootloader bootstub clean dsi arm7/$(TARGET).elf arm9/$(TARGET).elf +GAME_ICON := icon.bmp -all: bootloader bootstub $(TARGET).nds - -dsi: $(TARGET).dsi +ifeq ($(strip $(GAME_SUBTITLE)),) + GAME_FULL_TITLE := $(GAME_TITLE);$(GAME_AUTHOR) +else + GAME_FULL_TITLE := $(GAME_TITLE);$(GAME_SUBTITLE);$(GAME_AUTHOR) +endif -$(TARGET).nds: arm7/$(TARGET).elf arm9/$(TARGET).elf - ndstool -c $(TARGET).nds -7 arm7/$(TARGET).elf -9 arm9/$(TARGET).elf -d $(NITRODATA) \ - -b icon.bmp "GodMode9i;Rocket Robz" \ - -z 80040000 +include $(DEVKITARM)/ds_rules -$(TARGET).dsi: arm7/$(TARGET).elf arm9/$(TARGET).elf - ndstool -c $(TARGET).dsi -7 arm7/$(TARGET).elf -9 arm9/$(TARGET).elf -d $(NITRODATA) \ - -b icon.bmp "GodMode9i;Rocket Robz" \ - -g HGMA 00 "GODMODE9I" -z 80040000 -u 00030004 +.PHONY: arm7/$(TARGET).elf bootloader bootstub clean #--------------------------------------------------------------------------------- -arm7/$(TARGET).elf: - @$(MAKE) -C arm7 +# main targets +#--------------------------------------------------------------------------------- +all: $(TARGET).nds $(TARGET).dsi #--------------------------------------------------------------------------------- -arm9/$(TARGET).elf: - @$(MAKE) -C libnds32 release - @$(MAKE) -C arm9 +$(TARGET).nds : $(NITRO_FILES) arm7/$(TARGET).elf arm9/$(TARGET).elf + ndstool -c $(TARGET).nds -7 arm7/$(TARGET).elf -9 arm9/$(TARGET).elf \ + -b $(GAME_ICON) "$(GAME_FULL_TITLE)" -z 80040000 \ + $(_ADDFILES) + +$(TARGET).dsi : $(NITRO_FILES) arm7/$(TARGET).elf arm9/$(TARGET).elf + ndstool -c $(TARGET).dsi -7 arm7/$(TARGET).elf -9 arm9/$(TARGET).elf \ + -b $(GAME_ICON) "$(GAME_FULL_TITLE)" \ + -g $(GAME_CODE) 00 "$(GAME_HEADER_TITLE)" -z 80040000 -u 00030004 \ + $(_ADDFILES) #--------------------------------------------------------------------------------- -#$(BUILD): - #@[ -d $@ ] || mkdir -p $@ - #@make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile +arm7/$(TARGET).elf: + $(MAKE) -C arm7 + #--------------------------------------------------------------------------------- -clean: - @echo clean ... - @rm -fr data/*.bin - @rm -fr $(BUILD) $(TARGET).elf $(TARGET).nds - @rm -fr $(TARGET).arm7.elf - @rm -fr $(TARGET).arm9.elf - @$(MAKE) -C libnds32 clean - @$(MAKE) -C bootloader clean - @$(MAKE) -C bootstub clean - @$(MAKE) -C arm9 clean - @$(MAKE) -C arm7 clean +arm9/$(TARGET).elf: bootloader bootstub + $(MAKE) -C arm9 bootloader: data @$(MAKE) -C bootloader LOADBIN=$(CURDIR)/data/load.bin bootstub: data @$(MAKE) -C bootstub + +clean: + @rm -fr data/*.bin + @rm -fr $(TARGET).nds + @$(MAKE) -C bootloader clean + @$(MAKE) -C bootstub clean + @$(MAKE) -C arm9 clean + @$(MAKE) -C arm7 clean diff --git a/arm7/Makefile b/arm7/Makefile index bcb7a5bc..f9fb80ff 100644 --- a/arm7/Makefile +++ b/arm7/Makefile @@ -20,7 +20,7 @@ include $(DEVKITARM)/ds_rules TARGET := GodMode9i BUILD := build SOURCES := source -INCLUDES := include build +INCLUDES := include build ../shared/include #--------------------------------------------------------------------------------- # options for code generation diff --git a/arm7/include/gba.h b/arm7/include/gba.h index 8c1c47ef..e63c1181 100644 --- a/arm7/include/gba.h +++ b/arm7/include/gba.h @@ -3,7 +3,7 @@ #include -void readEeprom(u8 *dst, u32 src, u32 len); -void writeEeprom(u32 dst, u8 *src, u32 len); +bool gbaReadEeprom(u8 *dst, u32 src, u32 len); +bool gbaWriteEeprom(u32 dst, u8 *src, u32 len); #endif // GBA_H diff --git a/arm7/include/my_i2c.h b/arm7/include/my_i2c.h new file mode 100644 index 00000000..c11a4948 --- /dev/null +++ b/arm7/include/my_i2c.h @@ -0,0 +1,9 @@ +#define MY_I2C_H +#ifdef MY_I2C_H + +#include + +u8 my_i2cReadRegister8(u8 device, u8 reg); +u8 my_i2cWriteRegister8(u8 device, u8 reg, u8 data); + +#endif // MY_I2C_H diff --git a/arm7/include/my_sdmmc.h b/arm7/include/my_sdmmc.h deleted file mode 100644 index 0e579178..00000000 --- a/arm7/include/my_sdmmc.h +++ /dev/null @@ -1,197 +0,0 @@ -#ifndef __SDMMC_H__ -#define __SDMMC_H__ - -#include - -#define DATA32_SUPPORT - -#define SDMMC_BASE 0x04004800 - - -#define REG_SDCMD 0x00 -#define REG_SDPORTSEL 0x02 -#define REG_SDCMDARG 0x04 -#define REG_SDCMDARG0 0x04 -#define REG_SDCMDARG1 0x06 -#define REG_SDSTOP 0x08 -#define REG_SDRESP 0x0c -#define REG_SDBLKCOUNT 0x0a - -#define REG_SDRESP0 0x0c -#define REG_SDRESP1 0x0e -#define REG_SDRESP2 0x10 -#define REG_SDRESP3 0x12 -#define REG_SDRESP4 0x14 -#define REG_SDRESP5 0x16 -#define REG_SDRESP6 0x18 -#define REG_SDRESP7 0x1a - -#define REG_SDSTATUS0 0x1c -#define REG_SDSTATUS1 0x1e - -#define REG_SDIRMASK0 0x20 -#define REG_SDIRMASK1 0x22 -#define REG_SDCLKCTL 0x24 - -#define REG_SDBLKLEN 0x26 -#define REG_SDOPT 0x28 -#define REG_SDFIFO 0x30 - -#define REG_SDDATACTL 0xd8 -#define REG_SDRESET 0xe0 -#define REG_SDPROTECTED 0xf6 //bit 0 determines if sd is protected or not? - -#define REG_SDDATACTL32 0x100 -#define REG_SDBLKLEN32 0x104 -#define REG_SDBLKCOUNT32 0x108 -#define REG_SDFIFO32 0x10C - -#define REG_CLK_AND_WAIT_CTL 0x138 -#define REG_RESET_SDIO 0x1e0 -//The below defines are from linux kernel drivers/mmc tmio_mmc.h. -/* Definitions for values the CTRL_STATUS register can take. */ -#define TMIO_STAT0_CMDRESPEND 0x0001 -#define TMIO_STAT0_DATAEND 0x0004 -#define TMIO_STAT0_CARD_REMOVE 0x0008 -#define TMIO_STAT0_CARD_INSERT 0x0010 -#define TMIO_STAT0_SIGSTATE 0x0020 -#define TMIO_STAT0_WRPROTECT 0x0080 -#define TMIO_STAT0_CARD_REMOVE_A 0x0100 -#define TMIO_STAT0_CARD_INSERT_A 0x0200 -#define TMIO_STAT0_SIGSTATE_A 0x0400 - -#define TMIO_STAT1_CMD_IDX_ERR 0x0001 -#define TMIO_STAT1_CRCFAIL 0x0002 -#define TMIO_STAT1_STOPBIT_ERR 0x0004 -#define TMIO_STAT1_DATATIMEOUT 0x0008 -#define TMIO_STAT1_RXOVERFLOW 0x0010 -#define TMIO_STAT1_TXUNDERRUN 0x0020 -#define TMIO_STAT1_CMDTIMEOUT 0x0040 -#define TMIO_STAT1_RXRDY 0x0100 -#define TMIO_STAT1_TXRQ 0x0200 -#define TMIO_STAT1_ILL_FUNC 0x2000 -#define TMIO_STAT1_CMD_BUSY 0x4000 -#define TMIO_STAT1_ILL_ACCESS 0x8000 - -#define SDMC_NORMAL 0x00000000 -#define SDMC_ERR_COMMAND 0x00000001 -#define SDMC_ERR_CRC 0x00000002 -#define SDMC_ERR_END 0x00000004 -#define SDMC_ERR_TIMEOUT 0x00000008 -#define SDMC_ERR_FIFO_OVF 0x00000010 -#define SDMC_ERR_FIFO_UDF 0x00000020 -#define SDMC_ERR_WP 0x00000040 -#define SDMC_ERR_ABORT 0x00000080 -#define SDMC_ERR_FPGA_TIMEOUT 0x00000100 -#define SDMC_ERR_PARAM 0x00000200 -#define SDMC_ERR_R1_STATUS 0x00000800 -#define SDMC_ERR_NUM_WR_SECTORS 0x00001000 -#define SDMC_ERR_RESET 0x00002000 -#define SDMC_ERR_ILA 0x00004000 -#define SDMC_ERR_INFO_DETECT 0x00008000 - -#define SDMC_STAT_ERR_UNKNOWN 0x00080000 -#define SDMC_STAT_ERR_CC 0x00100000 -#define SDMC_STAT_ERR_ECC_FAILED 0x00200000 -#define SDMC_STAT_ERR_CRC 0x00800000 -#define SDMC_STAT_ERR_OTHER 0xf9c70008 - -#define TMIO_MASK_ALL 0x837f031d - -#define TMIO_MASK_GW (TMIO_STAT1_ILL_ACCESS | TMIO_STAT1_CMDTIMEOUT | TMIO_STAT1_TXUNDERRUN | TMIO_STAT1_RXOVERFLOW | \ - TMIO_STAT1_DATATIMEOUT | TMIO_STAT1_STOPBIT_ERR | TMIO_STAT1_CRCFAIL | TMIO_STAT1_CMD_IDX_ERR) - -#define TMIO_MASK_READOP (TMIO_STAT1_RXRDY | TMIO_STAT1_DATAEND) -#define TMIO_MASK_WRITEOP (TMIO_STAT1_TXRQ | TMIO_STAT1_DATAEND) - -typedef struct mmcdevice { - u8* rData; - const u8* tData; - u32 size; - u32 startOffset; - u32 endOffset; - u32 error; - u16 stat0; - u16 stat1; - u32 ret[4]; - u32 initarg; - u32 isSDHC; - u32 clk; - u32 SDOPT; - u32 devicenumber; - u32 total_size; //size in sectors of the device - u32 res; -} mmcdevice; - -enum { - MMC_DEVICE_SDCARD, - MMC_DEVICE_NAND, -}; - -void my_sdmmc_controller_init(bool force_init); -void my_sdmmc_initirq(); -int my_sdmmc_cardinserted(); - -int my_sdmmc_sdcard_init(); -int my_sdmmc_nand_init(); -void my_sdmmc_get_cid(int devicenumber, u32 *cid); - -static inline void sdmmc_nand_cid( u32 *cid) { - my_sdmmc_get_cid(MMC_DEVICE_NAND,cid); -} - -static inline void sdmmc_sdcard_cid( u32 *cid) { - my_sdmmc_get_cid(MMC_DEVICE_SDCARD,cid); -} - -int my_sdmmc_sdcard_readsectors(u32 sector_no, u32 numsectors, void *out); -int my_sdmmc_sdcard_writesectors(u32 sector_no, u32 numsectors, void *in); -int my_sdmmc_nand_readsectors(u32 sector_no, u32 numsectors, void *out); -int my_sdmmc_nand_writesectors(u32 sector_no, u32 numsectors, void *in); - -extern u32 sdmmc_cid[]; -extern int sdmmc_curdevice; - -//--------------------------------------------------------------------------------- -static inline u16 sdmmc_read16(u16 reg) { -//--------------------------------------------------------------------------------- - return *(vu16*)(SDMMC_BASE + reg); -} - -//--------------------------------------------------------------------------------- -static inline void sdmmc_write16(u16 reg, u16 val) { -//--------------------------------------------------------------------------------- - *(vu16*)(SDMMC_BASE + reg) = val; -} - -//--------------------------------------------------------------------------------- -static inline u32 sdmmc_read32(u16 reg) { -//--------------------------------------------------------------------------------- - return *(vu32*)(SDMMC_BASE + reg); -} - -//--------------------------------------------------------------------------------- -static inline void sdmmc_write32(u16 reg, u32 val) { -//--------------------------------------------------------------------------------- - *(vu32*)(SDMMC_BASE + reg) = val; -} - -//--------------------------------------------------------------------------------- -static inline void sdmmc_mask16(u16 reg, u16 clear, u16 set) { -//--------------------------------------------------------------------------------- - u16 val = sdmmc_read16(reg); - val &= ~clear; - val |= set; - sdmmc_write16(reg, val); -} - - -//--------------------------------------------------------------------------------- -static inline void setckl(u32 data) { -//--------------------------------------------------------------------------------- - sdmmc_mask16(REG_SDCLKCTL, 0x100, 0); - sdmmc_mask16(REG_SDCLKCTL, 0x2FF, data & 0x2FF); - sdmmc_mask16(REG_SDCLKCTL, 0x0, 0x100); -} - -#endif diff --git a/arm7/include/pxi.h b/arm7/include/pxi.h new file mode 100644 index 00000000..2d2570a5 --- /dev/null +++ b/arm7/include/pxi.h @@ -0,0 +1,21 @@ +#ifndef PXI_H +#define PXI_H + +#include "pxiVars.h" + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern Thread s_pxiThread; +extern u8 s_pxiThreadStack[1024]; + +int pxiThreadMain(void* arg); + +#ifdef __cplusplus +} +#endif + +#endif // PXI_H diff --git a/arm7/source/gba.c b/arm7/source/gba.c index 1a44d3e6..fadc9e1d 100644 --- a/arm7/source/gba.c +++ b/arm7/source/gba.c @@ -2,7 +2,6 @@ #include #include -#include #include #define EEPROM_ADDRESS (0x09FFFF00) @@ -97,20 +96,28 @@ void gbaEepromWrite8Bytes(u8 *in, u16 addr, bool short_addr) while((REG_EEPROM & 1) == 0); } -void readEeprom(u8 *dst, u32 src, u32 len) +bool gbaReadEeprom(u8 *dst, u32 src, u32 len) { + if(!dst) + return false; + int start, end; start = src >> 3; end = (src + len) >> 3; - u8 buffer[8]; + u8 *ptr = dst; for (int j = start; j < end; j++) { - gbaEepromRead8Bytes(buffer, j, len == 0x200); - fifoSendDatamsg(FIFO_USER_02, 8, buffer); + gbaEepromRead8Bytes(ptr, j, len == 0x200); + ptr += 8; } + + return true; } -void writeEeprom(u32 dst, u8 *src, u32 len) +bool gbaWriteEeprom(u32 dst, u8 *src, u32 len) { + if(!src) + return false; + int start, end; start = dst >> 3; end = (dst + len) >> 3; @@ -118,6 +125,6 @@ void writeEeprom(u32 dst, u8 *src, u32 len) for (int j = start; j < end; j++, ptr += 8) { gbaEepromWrite8Bytes(ptr, j, len == 0x200); } - - fifoSendValue32(FIFO_USER_02, 0x454E4F44 /* 'DONE' */); + + return true; } diff --git a/arm7/source/main.c b/arm7/source/main.c index 8cd6547c..974ed1b9 100644 --- a/arm7/source/main.c +++ b/arm7/source/main.c @@ -27,192 +27,60 @@ distribution. ---------------------------------------------------------------------------------*/ -#include -#include - -#include "gba.h" - -#define SD_IRQ_STATUS (*(vu32*)0x400481C) - -void my_installSystemFIFO(void); -void my_sdmmc_get_cid(int devicenumber, u32 *cid); - -u8 my_i2cReadRegister(u8 device, u8 reg); -u8 my_i2cWriteRegister(u8 device, u8 reg, u8 data); - -//--------------------------------------------------------------------------------- -void ReturntoDSiMenu() { -//--------------------------------------------------------------------------------- - if (isDSiMode()) { - i2cWriteRegister(0x4A, 0x70, 0x01); // Bootflag = Warmboot/SkipHealthSafety - i2cWriteRegister(0x4A, 0x11, 0x01); // Reset to DSi Menu - } else { - u8 readCommand = readPowerManagement(0x10); - readCommand |= BIT(0); - writePowerManagement(0x10, readCommand); - } -} - -//--------------------------------------------------------------------------------- -void VblankHandler(void) { -//--------------------------------------------------------------------------------- - if(fifoCheckValue32(FIFO_USER_02)) { - ReturntoDSiMenu(); - } -} - -//--------------------------------------------------------------------------------- -void VcountHandler() { -//--------------------------------------------------------------------------------- - inputGetAndSend(); -} -volatile bool exitflag = false; +#include "pxi.h" -//--------------------------------------------------------------------------------- -void powerButtonCB() { -//--------------------------------------------------------------------------------- - exitflag = true; -} - -void set_ctr(u32* ctr){ - for (int i = 0; i < 4; i++) REG_AES_IV[i] = ctr[3-i]; -} - -// 10 11 22 23 24 25 -void aes(void* in, void* out, void* iv, u32 method){ //this is sort of a bodged together dsi aes function adapted from this 3ds function - REG_AES_CNT = ( AES_CNT_MODE(method) | //https://github.com/TiniVi/AHPCFW/blob/master/source/aes.c#L42 - AES_WRFIFO_FLUSH | //as long as the output changes when keyslot values change, it's good enough. - AES_RDFIFO_FLUSH | - AES_CNT_KEY_APPLY | - AES_CNT_KEYSLOT(3) | - AES_CNT_DMA_WRITE_SIZE(2) | - AES_CNT_DMA_READ_SIZE(1) - ); - - if (iv != NULL) set_ctr((u32*)iv); - REG_AES_BLKCNT = (1 << 16); - REG_AES_CNT |= 0x80000000; - - for (int j = 0; j < 0x10; j+=4) REG_AES_WRFIFO = *((u32*)(in+j)); - while(((REG_AES_CNT >> 0x5) & 0x1F) < 0x4); //wait for every word to get processed - for (int j = 0; j < 0x10; j+=4) *((u32*)(out+j)) = REG_AES_RDFIFO; - //REG_AES_CNT &= ~0x80000000; - //if (method & (AES_CTR_DECRYPT | AES_CTR_ENCRYPT)) add_ctr((u8*)iv); -} +#include +#include +// #include +#include //--------------------------------------------------------------------------------- int main() { //--------------------------------------------------------------------------------- - *(vu32*)0x400481C = 0; // Clear SD IRQ stat register - *(vu32*)0x4004820 = 0; // Clear SD IRQ mask register - // clear sound registers - dmaFillWords(0, (void*)0x04000400, 0x100); + // Read settings from NVRAM + envReadNvramSettings(); - REG_SOUNDCNT |= SOUND_ENABLE; - writePowerManagement(PM_CONTROL_REG, ( readPowerManagement(PM_CONTROL_REG) & ~PM_SOUND_MUTE ) | PM_SOUND_AMP ); - powerOn(POWER_SOUND); + // Set up extended keypad server (X/Y/hinge) + keypadStartExtServer(); - readUserSettings(); - ledBlink(0); + // Configure and enable VBlank interrupt + lcdSetIrqMask(DISPSTAT_IE_ALL, DISPSTAT_IE_VBLANK); + irqEnable(IRQ_VBLANK); - irqInit(); - // Start the RTC tracking IRQ - initClockIRQ(); + // Set up RTC + rtcInit(); + rtcSyncTime(); - touchInit(); + // Initialize power management + pmInit(); - fifoInit(); - - SetYtrigger(80); - - my_installSystemFIFO(); + // Set up block device peripherals + blkInit(); - irqSet(IRQ_VCOUNT, VcountHandler); - irqSet(IRQ_VBLANK, VblankHandler); + // Set up touch screen driver + touchInit(); + touchStartServer(80, MAIN_THREAD_PRIO); - irqEnable( IRQ_VBLANK | IRQ_VCOUNT ); + // // Set up sound and mic driver + // soundStartServer(MAIN_THREAD_PRIO-0x10); + // micStartServer(MAIN_THREAD_PRIO-0x18); - setPowerButtonCB(powerButtonCB); + // // Set up wireless manager + // wlmgrStartServer(MAIN_THREAD_PRIO-8); - // Check for 3DS - if(isDSiMode() || (REG_SCFG_EXT & BIT(22))) { - u8 byteBak = my_i2cReadRegister(0x4A, 0x71); - my_i2cWriteRegister(0x4A, 0x71, 0xD2); - fifoSendValue32(FIFO_USER_05, my_i2cReadRegister(0x4A, 0x71)); - my_i2cWriteRegister(0x4A, 0x71, byteBak); - } + // // Set up Maxmod + // mmInstall(MAIN_THREAD_PRIO+1); - if (isDSiMode() || ((REG_SCFG_EXT & BIT(17)) && (REG_SCFG_EXT & BIT(18)))) { - u8 *out=(u8*)0x02F00000; - memset(out, 0, 16); - - // first check whether we can read the console ID directly and it was not hidden by SCFG - if (((*(vu16*)0x04004000) & (1u << 10)) == 0 && ((*(vu8*)0x04004D08) & 0x1) == 0) - { - // The console id registers are readable, so use them! - memcpy(out, (u8*)0x04004D00, 8); - } - if(out[0] == 0 || out[1] == 0) { - // For getting ConsoleID without reading from 0x4004D00... - u8 base[16]={0}; - u8 in[16]={0}; - u8 iv[16]={0}; - u8 *scratch=(u8*)0x02F00200; - u8 *key3=(u8*)0x40044D0; - - aes(in, base, iv, 2); - - //write consecutive 0-255 values to any byte in key3 until we get the same aes output as "base" above - this reveals the hidden byte. this way we can uncover all 16 bytes of the key3 normalkey pretty easily. - //greets to Martin Korth for this trick https://problemkaputt.de/gbatek.htm#dsiaesioports (Reading Write-Only Values) - for(int i=0;i<16;i++){ - for(int j=0;j<256;j++){ - *(key3+i)=j & 0xFF; - aes(in, scratch, iv, 2); - if(!memcmp(scratch, base, 16)){ - out[i]=j; - //hit++; - break; - } - } - } - } - } - - fifoSendValue32(FIFO_USER_03, REG_SCFG_EXT); - fifoSendValue32(FIFO_USER_07, *(u16*)(0x4004700)); - fifoSendValue32(FIFO_USER_06, 1); + // Set up server thread + threadPrepare(&s_pxiThread, pxiThreadMain, NULL, &s_pxiThreadStack[sizeof(s_pxiThreadStack)], MAIN_THREAD_PRIO); + threadStart(&s_pxiThread); // Keep the ARM7 mostly idle - while (!exitflag) { - if ( 0 == (REG_KEYINPUT & (KEY_SELECT | KEY_START | KEY_L | KEY_R))) { - exitflag = true; - } - if (*(u32*)(0x2FFFD0C) == 0x454D4D43) { - my_sdmmc_get_cid(true, (u32*)0x2FFD7BC); // Get eMMC CID - *(u32*)(0x2FFFD0C) = 0; - } - resyncClock(); - - // Send SD status - if(isDSiMode() || *(u16*)(0x4004700) != 0) - fifoSendValue32(FIFO_USER_04, SD_IRQ_STATUS); - - // Dump EEPROM save - if(fifoCheckAddress(FIFO_USER_01)) { - switch(fifoGetValue32(FIFO_USER_01)) { - case 0x44414552: // 'READ' - readEeprom((u8 *)fifoGetAddress(FIFO_USER_01), fifoGetValue32(FIFO_USER_01), fifoGetValue32(FIFO_USER_01)); - break; - case 0x54495257: // 'WRIT' - writeEeprom(fifoGetValue32(FIFO_USER_01), (u8 *)fifoGetAddress(FIFO_USER_01), fifoGetValue32(FIFO_USER_01)); - break; - } - } - - swiWaitForVBlank(); + while(pmMainLoop()) { + threadWaitForVBlank(); } + return 0; } - diff --git a/arm7/source/my_i2c.c b/arm7/source/my_i2c.c index e49d5bc9..b4a29ac3 100644 --- a/arm7/source/my_i2c.c +++ b/arm7/source/my_i2c.c @@ -1,132 +1,126 @@ -/*--------------------------------------------------------------------------------- - - I2C control for the ARM7 - - Copyright (C) 2011 - Dave Murphy (WinterMute) - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any - damages arising from the use of this software. - - Permission is granted to anyone to use this software for any - purpose, including commercial applications, and to alter it and - redistribute it freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you - must not claim that you wrote the original software. If you use - this software in a product, an acknowledgment in the product - documentation would be appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and - must not be misrepresented as being the original software. - 3. This notice may not be removed or altered from any source - distribution. +// SPDX-License-Identifier: ZPL-2.1 +// SPDX-FileCopyrightText: Copyright fincs, devkitPro +#include +#include +#include + +static Mutex my_i2cMutex; +static s32 my_i2cDelay, my_i2cMcuDelay; + +MK_INLINE void _my_i2cWaitBusy(void) +{ + while (REG_I2C_CNT & 0x80); +} ----------------------------------------------------------------------------------*/ +MK_INLINE void _my_i2cSetDelay(I2cDevice dev) +{ + if (dev == I2cDev_MCU) { + my_i2cDelay = my_i2cMcuDelay; + } else { + my_i2cDelay = 0; + } +} -#include -#include +void _my_i2cSetMcuDelay(s32 delay) +{ + my_i2cMcuDelay = delay; +} -static u32 i2cCurrentDelay = 0; +MK_INLINE void _my_i2cDelay() +{ + _my_i2cWaitBusy(); + if (my_i2cDelay > 0) { + svcWaitByLoop(my_i2cDelay); + // !!! WARNING !!! Calling a BIOS function from within IRQ mode + // will use up 4 words of SVC and 2 words of SYS stack from the **CURRENT** thread, + // which may be the idle thread; which does NOT have enough space for nested syscall + // frames! + // For now, and because I am lazy, let's do this in shittily written C. + //for (volatile s32 i = my_i2cDelay; i; i --); + } +} -//--------------------------------------------------------------------------------- -void my_i2cDelay() { -//--------------------------------------------------------------------------------- - i2cWaitBusy(); - swiDelay(i2cCurrentDelay); +static void _my_i2cStop(u8 arg0) +{ + if (my_i2cDelay) { + REG_I2C_CNT = (arg0 << 5) | 0xC0; + _my_i2cDelay(); + REG_I2C_CNT = 0xC5; + } else { + REG_I2C_CNT = (arg0 << 5) | 0xC1; + } } -//--------------------------------------------------------------------------------- -void my_i2cStop(u8 arg0) { -//--------------------------------------------------------------------------------- - if(i2cCurrentDelay) { - REG_I2CCNT = (arg0 << 5) | 0xC0; - my_i2cDelay(); - REG_I2CCNT = 0xC5; - } else REG_I2CCNT = (arg0 << 5) | 0xC1; +MK_INLINE bool _my_i2cGetResult() +{ + _my_i2cWaitBusy(); + return (REG_I2C_CNT >> 4) & 0x01; } +MK_INLINE u8 _my_i2cGetData() +{ + _my_i2cWaitBusy(); + return REG_I2C_DATA; +} -//--------------------------------------------------------------------------------- -u8 my_i2cGetResult() { -//--------------------------------------------------------------------------------- - i2cWaitBusy(); - return (REG_I2CCNT >> 4) & 0x01; +static bool _my_i2cSelectDevice(I2cDevice dev) +{ + _my_i2cWaitBusy(); + REG_I2C_DATA = dev; + REG_I2C_CNT = 0xC2; + return _my_i2cGetResult(); } -//--------------------------------------------------------------------------------- -u8 my_i2cGetData() { -//--------------------------------------------------------------------------------- - i2cWaitBusy(); - return REG_I2CDATA; +static bool _my_i2cSelectRegister(u8 reg) +{ + _my_i2cDelay(); + REG_I2C_DATA = reg; + REG_I2C_CNT = 0xC0; + return _my_i2cGetResult(); } -//--------------------------------------------------------------------------------- -void my_i2cSetDelay(u8 device) { -//--------------------------------------------------------------------------------- - if (device == I2C_PM ) { - i2cCurrentDelay = 0x180; - } else { - i2cCurrentDelay = 0; +bool my_i2cWriteRegister8(I2cDevice dev, u8 reg, u8 data) +{ + if_unlikely (!mutexIsLockedByCurrentThread(&my_i2cMutex)) { + return false; } -} -//--------------------------------------------------------------------------------- -u8 my_i2cSelectDevice(u8 device) { -//--------------------------------------------------------------------------------- - i2cWaitBusy(); - REG_I2CDATA = device; - REG_I2CCNT = 0xC2; - return my_i2cGetResult(); -} + _my_i2cSetDelay(dev); + for (unsigned i = 0; i < 8; i ++) { + if (_my_i2cSelectDevice(dev) && _my_i2cSelectRegister(reg)) { + _my_i2cDelay(); + REG_I2C_DATA = data; + _my_i2cStop(0); -//--------------------------------------------------------------------------------- -u8 my_i2cSelectRegister(u8 reg) { -//--------------------------------------------------------------------------------- - my_i2cDelay(); - REG_I2CDATA = reg; - REG_I2CCNT = 0xC0; - return my_i2cGetResult(); -} + if (_my_i2cGetResult()) { + return true; + } + } + REG_I2C_CNT = 0xC5; + } -//--------------------------------------------------------------------------------- -u8 my_i2cWriteRegister(u8 device, u8 reg, u8 data) { -//--------------------------------------------------------------------------------- - my_i2cSetDelay(device); - int i; - - for(i = 0; i < 8; i++) { - if((my_i2cSelectDevice(device) != 0) && (my_i2cSelectRegister(reg) != 0)) { - my_i2cDelay(); - REG_I2CDATA = data; - my_i2cStop(0); - if(my_i2cGetResult() != 0) return 1; - } - REG_I2CCNT = 0xC5; - } - - return 0; + return false; } -//--------------------------------------------------------------------------------- -u8 my_i2cReadRegister(u8 device, u8 reg) { -//--------------------------------------------------------------------------------- - my_i2cSetDelay(device); - int i; - - for(i = 0; i < 8; i++) { - - if((my_i2cSelectDevice(device) != 0) && (my_i2cSelectRegister(reg) != 0)) { - my_i2cDelay(); - if(my_i2cSelectDevice(device | 1)) { - my_i2cDelay(); - my_i2cStop(1); - return my_i2cGetData(); +u8 my_i2cReadRegister8(I2cDevice dev, u8 reg) +{ + if_unlikely (!mutexIsLockedByCurrentThread(&my_i2cMutex)) { + return 0xff; + } + + _my_i2cSetDelay(dev); + for (unsigned i = 0; i < 8; i++) { + if (_my_i2cSelectDevice(dev) && _my_i2cSelectRegister(reg)) { + _my_i2cDelay(); + if (_my_i2cSelectDevice(dev | 1)) { + _my_i2cDelay(); + _my_i2cStop(1); + return _my_i2cGetData(); } } - REG_I2CCNT = 0xC5; + REG_I2C_CNT = 0xC5; } return 0xff; -} \ No newline at end of file +} diff --git a/arm7/source/my_sdmmc.c b/arm7/source/my_sdmmc.c deleted file mode 100644 index e9f32e48..00000000 --- a/arm7/source/my_sdmmc.c +++ /dev/null @@ -1,655 +0,0 @@ -#include -#include -#include "my_sdmmc.h" -#include -#include -#include - -#include - -static struct mmcdevice deviceSD; -static struct mmcdevice deviceNAND; - -/*mmcdevice *getMMCDevice(int drive) { - if(drive==0) return &deviceNAND; - return &deviceSD; -} -*/ - -//--------------------------------------------------------------------------------- -int my_geterror(struct mmcdevice *ctx) { -//--------------------------------------------------------------------------------- - //if(ctx->error == 0x4) return -1; - //else return 0; - return (ctx->error << 29) >> 31; -} - - -//--------------------------------------------------------------------------------- -void my_setTarget(struct mmcdevice *ctx) { -//--------------------------------------------------------------------------------- - sdmmc_mask16(REG_SDPORTSEL,0x3,(u16)ctx->devicenumber); - setckl(ctx->clk); - if (ctx->SDOPT == 0) { - sdmmc_mask16(REG_SDOPT, 0, 0x8000); - } else { - sdmmc_mask16(REG_SDOPT, 0x8000, 0); - } - -} - - -//--------------------------------------------------------------------------------- -void my_sdmmc_send_command(struct mmcdevice *ctx, uint32_t cmd, uint32_t args) { -//--------------------------------------------------------------------------------- - const bool getSDRESP = (cmd << 15) >> 31; - u16 flags = (cmd << 15) >> 31; - const bool readdata = cmd & 0x20000; - const bool writedata = cmd & 0x40000; - - if(readdata || writedata) - { - flags |= TMIO_STAT0_DATAEND; - } - - ctx->error = 0; - while((sdmmc_read16(REG_SDSTATUS1) & TMIO_STAT1_CMD_BUSY)); //mmc working? - sdmmc_write16(REG_SDIRMASK0,0); - sdmmc_write16(REG_SDIRMASK1,0); - sdmmc_write16(REG_SDSTATUS0,0); - sdmmc_write16(REG_SDSTATUS1,0); - sdmmc_mask16(REG_SDDATACTL32,0x1800,0x400); // Disable TX32RQ and RX32RDY IRQ. Clear fifo. - sdmmc_write16(REG_SDCMDARG0,args &0xFFFF); - sdmmc_write16(REG_SDCMDARG1,args >> 16); - sdmmc_write16(REG_SDCMD,cmd &0xFFFF); - - u32 size = ctx->size; - const u16 blkSize = sdmmc_read16(REG_SDBLKLEN32); -#ifdef DATA32_SUPPORT - u32 *rDataPtr32 = (u32*)ctx->rData; -#else - u16 *rDataPtr16 = (u16*)ctx->rData; -#endif - u8 *rDataPtr8 = ctx->rData; -#ifdef DATA32_SUPPORT - const u32 *tDataPtr32 = (u32*)ctx->tData; -#else - const u16 *tDataPtr16 = (u16*)ctx->tData; -#endif - const u8 *tDataPtr8 = ctx->tData; - -#ifdef DATA32_SUPPORT - bool rUseBuf = ( NULL != rDataPtr32 ); - bool tUseBuf = ( NULL != tDataPtr32 ); -#else - bool rUseBuf = ( NULL != rDataPtr16 ); - bool tUseBuf = ( NULL != tDataPtr16 ); -#endif - - u16 status0 = 0; - while(1) - { - volatile u16 status1 = sdmmc_read16(REG_SDSTATUS1); -#ifdef DATA32_SUPPORT - volatile u16 ctl32 = sdmmc_read16(REG_SDDATACTL32); - if((ctl32 & 0x100)) -#else - if((status1 & TMIO_STAT1_RXRDY)) -#endif - { - if(readdata) - { - if(rUseBuf) - { - sdmmc_mask16(REG_SDSTATUS1, TMIO_STAT1_RXRDY, 0); - if(size >= blkSize) - { - #ifdef DATA32_SUPPORT - if(!((u32)rDataPtr32 & 3)) - { - for(u32 i = 0; i < blkSize; i += 4) - { - *rDataPtr32++ = sdmmc_read32(REG_SDFIFO32); - } - } - else - { - for(u32 i = 0; i < blkSize; i += 4) - { - u32 data = sdmmc_read32(REG_SDFIFO32); - *rDataPtr8++ = data; - *rDataPtr8++ = data >> 8; - *rDataPtr8++ = data >> 16; - *rDataPtr8++ = data >> 24; - } - } - #else - if(!((u16)rDataPtr16 & 1)) - { - for(u16 i = 0; i < blkSize; i += 2) - { - *rDataPtr16++ = sdmmc_read16(REG_SDFIFO); - } - } - else - { - for(u16 i = 0; i < blkSize; i += 2) - { - u16 data = sdmmc_read16(REG_SDFIFO); - *rDataPtr8++ = data; - *rDataPtr8++ = data >> 8; - } - } - #endif - size -= blkSize; - } - } - - sdmmc_mask16(REG_SDDATACTL32, 0x800, 0); - } - } -#ifdef DATA32_SUPPORT - if(!(ctl32 & 0x200)) -#else - if((status1 & TMIO_STAT1_TXRQ)) -#endif - { - if(writedata) - { - if(tUseBuf) - { - sdmmc_mask16(REG_SDSTATUS1, TMIO_STAT1_TXRQ, 0); - if(size >= blkSize) - { - #ifdef DATA32_SUPPORT - if(!((u32)tDataPtr32 & 3)) - { - for(u32 i = 0; i < blkSize; i += 4) - { - sdmmc_write32(REG_SDFIFO32, *tDataPtr32++); - } - } - else - { - for(u32 i = 0; i < blkSize; i += 4) - { - u32 data = *tDataPtr8++; - data |= (u32)*tDataPtr8++ << 8; - data |= (u32)*tDataPtr8++ << 16; - data |= (u32)*tDataPtr8++ << 24; - sdmmc_write32(REG_SDFIFO32, data); - } - } - #else - if(!((u16)tDataPtr16 & 1)) - { - for(u16 i = 0; i < blkSize; i += 2) - { - sdmmc_write16(REG_SDFIFO, *tDataPtr16++); - } - } - else - { - for(u16 i = 0; i < blkSize; i += 2) - { - u16 data = *tDataPtr8++; - data |= (u16)(*tDataPtr8++ << 8); - sdmmc_write16(REG_SDFIFO, data); - } - } - #endif - size -= blkSize; - } - } - - sdmmc_mask16(REG_SDDATACTL32, 0x1000, 0); - } - } - if(status1 & TMIO_MASK_GW) - { - ctx->error |= 4; - break; - } - - if(!(status1 & TMIO_STAT1_CMD_BUSY)) - { - status0 = sdmmc_read16(REG_SDSTATUS0); - if(sdmmc_read16(REG_SDSTATUS0) & TMIO_STAT0_CMDRESPEND) - { - ctx->error |= 0x1; - } - if(status0 & TMIO_STAT0_DATAEND) - { - ctx->error |= 0x2; - } - - if((status0 & flags) == flags) - break; - } - } - ctx->stat0 = sdmmc_read16(REG_SDSTATUS0); - ctx->stat1 = sdmmc_read16(REG_SDSTATUS1); - sdmmc_write16(REG_SDSTATUS0,0); - sdmmc_write16(REG_SDSTATUS1,0); - - if(getSDRESP != 0) - { - ctx->ret[0] = (u32)(sdmmc_read16(REG_SDRESP0) | (sdmmc_read16(REG_SDRESP1) << 16)); - ctx->ret[1] = (u32)(sdmmc_read16(REG_SDRESP2) | (sdmmc_read16(REG_SDRESP3) << 16)); - ctx->ret[2] = (u32)(sdmmc_read16(REG_SDRESP4) | (sdmmc_read16(REG_SDRESP5) << 16)); - ctx->ret[3] = (u32)(sdmmc_read16(REG_SDRESP6) | (sdmmc_read16(REG_SDRESP7) << 16)); - } -} - - -//--------------------------------------------------------------------------------- -int my_sdmmc_cardinserted() { -//--------------------------------------------------------------------------------- - return 1; //my_sdmmc_cardready; -} - - -static bool my_sdmmc_controller_initialised = false; -static bool my_nand_controller_initialised = false; - -//--------------------------------------------------------------------------------- -void my_sdmmc_controller_init( bool force_init ) { -//--------------------------------------------------------------------------------- - - if (!force_init && my_sdmmc_controller_initialised && my_nand_controller_initialised) return; - - if(!my_sdmmc_controller_initialised) { - deviceSD.isSDHC = 0; - deviceSD.SDOPT = 0; - deviceSD.res = 0; - deviceSD.initarg = 0; - deviceSD.clk = 0x80; - deviceSD.devicenumber = 0; - } - - if(!my_nand_controller_initialised) { - deviceNAND.isSDHC = 0; - deviceNAND.SDOPT = 0; - deviceNAND.res = 0; - deviceNAND.initarg = 1; - deviceNAND.clk = 0x80; - deviceNAND.devicenumber = 1; - } - - *(vu16*)(SDMMC_BASE + REG_SDDATACTL32) &= 0xF7FFu; - *(vu16*)(SDMMC_BASE + REG_SDDATACTL32) &= 0xEFFFu; -#ifdef DATA32_SUPPORT - *(vu16*)(SDMMC_BASE + REG_SDDATACTL32) |= 0x402u; -#else - *(vu16*)(SDMMC_BASE + REG_SDDATACTL32) |= 0x402u; -#endif - *(vu16*)(SDMMC_BASE + REG_SDDATACTL) = (*(vu16*)(SDMMC_BASE + REG_SDDATACTL) & 0xFFDD) | 2; -#ifdef DATA32_SUPPORT - *(vu16*)(SDMMC_BASE + REG_SDDATACTL32) &= 0xFFFFu; - *(vu16*)(SDMMC_BASE + REG_SDDATACTL) &= 0xFFDFu; - *(vu16*)(SDMMC_BASE + REG_SDBLKLEN32) = 512; -#else - *(vu16*)(SDMMC_BASE + REG_SDDATACTL32) &= 0xFFFDu; - *(vu16*)(SDMMC_BASE + REG_SDDATACTL) &= 0xFFDDu; - *(vu16*)(SDMMC_BASE + REG_SDBLKLEN32) = 0; -#endif - *(vu16*)(SDMMC_BASE + REG_SDBLKCOUNT32) = 1; - *(vu16*)(SDMMC_BASE + REG_SDRESET) &= 0xFFFEu; - *(vu16*)(SDMMC_BASE + REG_SDRESET) |= 1u; - *(vu16*)(SDMMC_BASE + REG_SDIRMASK0) |= TMIO_MASK_ALL; - *(vu16*)(SDMMC_BASE + REG_SDIRMASK1) |= TMIO_MASK_ALL>>16; - *(vu16*)(SDMMC_BASE + 0x0fc) |= 0xDBu; //SDCTL_RESERVED7 - *(vu16*)(SDMMC_BASE + 0x0fe) |= 0xDBu; //SDCTL_RESERVED8 - *(vu16*)(SDMMC_BASE + REG_SDPORTSEL) &= 0xFFFCu; -#ifdef DATA32_SUPPORT - *(vu16*)(SDMMC_BASE + REG_SDCLKCTL) = 0x20; - *(vu16*)(SDMMC_BASE + REG_SDOPT) = 0x40EE; -#else - *(vu16*)(SDMMC_BASE + REG_SDCLKCTL) = 0x40; //Nintendo sets this to 0x20 - *(vu16*)(SDMMC_BASE + REG_SDOPT) = 0x40EB; //Nintendo sets this to 0x40EE -#endif - *(vu16*)(SDMMC_BASE + REG_SDPORTSEL) &= 0xFFFCu; - *(vu16*)(SDMMC_BASE + REG_SDBLKLEN) = 512; - *(vu16*)(SDMMC_BASE + REG_SDSTOP) = 0; - - my_sdmmc_controller_initialised = true; - my_nand_controller_initialised = true; - - my_setTarget(&deviceSD); -} - -//--------------------------------------------------------------------------------- -static u32 calcSDSize(u8* csd, int type) { -//--------------------------------------------------------------------------------- - u32 result = 0; - if (type == -1) type = csd[14] >> 6; - switch (type) { - case 0: - { - u32 block_len = csd[9] & 0xf; - block_len = 1 << block_len; - u32 mult = (csd[4] >> 7) | ((csd[5] & 3) << 1); - mult = 1 << (mult + 2); - result = csd[8] & 3; - result = (result << 8) | csd[7]; - result = (result << 2) | (csd[6] >> 6); - result = (result + 1) * mult * block_len / 512; - } - break; - case 1: - result = csd[7] & 0x3f; - result = (result << 8) | csd[6]; - result = (result << 8) | csd[5]; - result = (result + 1) * 1024; - break; - } - return result; -} - -//--------------------------------------------------------------------------------- -int my_sdmmc_sdcard_init() { -//--------------------------------------------------------------------------------- - // We need to send at least 74 clock pulses. - my_setTarget(&deviceSD); - swiDelay(0x1980); // ~75-76 clocks - - // card reset - my_sdmmc_send_command(&deviceSD,0,0); - - // CMD8 0x1AA - my_sdmmc_send_command(&deviceSD,0x10408,0x1AA); - u32 temp = (deviceSD.error & 0x1) << 0x1E; - - u32 temp2 = 0; - do { - do { - // CMD55 - my_sdmmc_send_command(&deviceSD,0x10437,deviceSD.initarg << 0x10); - // ACMD41 - my_sdmmc_send_command(&deviceSD,0x10769,0x00FF8000 | temp); - temp2 = 1; - } while ( !(deviceSD.error & 1) ); - - } while((deviceSD.ret[0] & 0x80000000) == 0); - - if(!((deviceSD.ret[0] >> 30) & 1) || !temp) - temp2 = 0; - - deviceSD.isSDHC = temp2; - - my_sdmmc_send_command(&deviceSD,0x10602,0); - if (deviceSD.error & 0x4) return -1; - - my_sdmmc_send_command(&deviceSD,0x10403,0); - if (deviceSD.error & 0x4) return -1; - deviceSD.initarg = deviceSD.ret[0] >> 0x10; - - my_sdmmc_send_command(&deviceSD,0x10609,deviceSD.initarg << 0x10); - if (deviceSD.error & 0x4) return -1; - - deviceSD.total_size = calcSDSize((u8*)&deviceSD.ret[0],-1); - deviceSD.clk = 1; - setckl(1); - - my_sdmmc_send_command(&deviceSD,0x10507,deviceSD.initarg << 0x10); - if (deviceSD.error & 0x4) return -1; - - // CMD55 - my_sdmmc_send_command(&deviceSD,0x10437,deviceSD.initarg << 0x10); - if (deviceSD.error & 0x4) return -1; - - // ACMD42 - my_sdmmc_send_command(&deviceSD,0x1076A,0x0); - if (deviceSD.error & 0x4) return -1; - - // CMD55 - my_sdmmc_send_command(&deviceSD,0x10437,deviceSD.initarg << 0x10); - if (deviceSD.error & 0x4) return -7; - - deviceSD.SDOPT = 1; - my_sdmmc_send_command(&deviceSD,0x10446,0x2); - if (deviceSD.error & 0x4) return -8; - - my_sdmmc_send_command(&deviceSD,0x1040D,deviceSD.initarg << 0x10); - if (deviceSD.error & 0x4) return -9; - - my_sdmmc_send_command(&deviceSD,0x10410,0x200); - if (deviceSD.error & 0x4) return -10; - deviceSD.clk |= 0x200; - - return 0; - -} - -//--------------------------------------------------------------------------------- -int my_sdmmc_nand_init() { -//--------------------------------------------------------------------------------- - my_setTarget(&deviceNAND); - swiDelay(0xF000); - - my_sdmmc_send_command(&deviceNAND,0,0); - - do { - do { - my_sdmmc_send_command(&deviceNAND,0x10701,0x100000); - } while ( !(deviceNAND.error & 1) ); - } - while((deviceNAND.ret[0] & 0x80000000) == 0); - - my_sdmmc_send_command(&deviceNAND,0x10602,0x0); - if((deviceNAND.error & 0x4))return -1; - - my_sdmmc_send_command(&deviceNAND,0x10403,deviceNAND.initarg << 0x10); - if((deviceNAND.error & 0x4))return -1; - - my_sdmmc_send_command(&deviceNAND,0x10609,deviceNAND.initarg << 0x10); - if((deviceNAND.error & 0x4))return -1; - - deviceNAND.total_size = calcSDSize((uint8_t*)&deviceNAND.ret[0],0); - deviceNAND.clk = 1; - setckl(1); - - my_sdmmc_send_command(&deviceNAND,0x10407,deviceNAND.initarg << 0x10); - if((deviceNAND.error & 0x4))return -1; - - deviceNAND.SDOPT = 1; - - my_sdmmc_send_command(&deviceNAND,0x10506,0x3B70100); - if((deviceNAND.error & 0x4))return -1; - - my_sdmmc_send_command(&deviceNAND,0x10506,0x3B90100); - if((deviceNAND.error & 0x4))return -1; - - my_sdmmc_send_command(&deviceNAND,0x1040D,deviceNAND.initarg << 0x10); - if((deviceNAND.error & 0x4))return -1; - - my_sdmmc_send_command(&deviceNAND,0x10410,0x200); - if((deviceNAND.error & 0x4))return -1; - - deviceNAND.clk |= 0x200; - - my_setTarget(&deviceSD); - - return 0; -} - -//--------------------------------------------------------------------------------- -int my_sdmmc_readsectors(struct mmcdevice *device, u32 sector_no, u32 numsectors, void *out) { -//--------------------------------------------------------------------------------- - if (device->isSDHC == 0) sector_no <<= 9; - my_setTarget(device); - sdmmc_write16(REG_SDSTOP,0x100); - -#ifdef DATA32_SUPPORT - sdmmc_write16(REG_SDBLKCOUNT32,numsectors); - sdmmc_write16(REG_SDBLKLEN32,0x200); -#endif - - sdmmc_write16(REG_SDBLKCOUNT,numsectors); - device->rData = out; - device->size = numsectors << 9; - my_sdmmc_send_command(device,0x33C12,sector_no); - my_setTarget(&deviceSD); - return my_geterror(device); -} - -//--------------------------------------------------------------------------------- -int my_sdmmc_writesectors(struct mmcdevice *device, u32 sector_no, u32 numsectors, void *in) { -//--------------------------------------------------------------------------------- - if (device->isSDHC == 0) - sector_no <<= 9; - my_setTarget(device); - sdmmc_write16(REG_SDSTOP,0x100); - -#ifdef DATA32_SUPPORT - sdmmc_write16(REG_SDBLKCOUNT32,numsectors); - sdmmc_write16(REG_SDBLKLEN32,0x200); -#endif - - sdmmc_write16(REG_SDBLKCOUNT,numsectors); - device->tData = in; - device->size = numsectors << 9; - my_sdmmc_send_command(device,0x52C19,sector_no); - my_setTarget(&deviceSD); - return my_geterror(device); -} - -//--------------------------------------------------------------------------------- -void my_sdmmc_get_cid(int devicenumber, u32 *cid) { -//--------------------------------------------------------------------------------- - - struct mmcdevice *device = (devicenumber == 1 ? &deviceNAND : &deviceSD); - - int oldIME = enterCriticalSection(); - - my_setTarget(device); - - // use cmd7 to put sd card in standby mode - // CMD7 - my_sdmmc_send_command(device, 0x10507, 0); - - // get sd card info - // use cmd10 to read CID - my_sdmmc_send_command(device, 0x1060A, device->initarg << 0x10); - - for(int i = 0; i < 4; ++i) - cid[i] = device->ret[i]; - - // put sd card back to transfer mode - // CMD7 - my_sdmmc_send_command(device, 0x10507, device->initarg << 0x10); - - leaveCriticalSection(oldIME); -} - -//--------------------------------------------------------------------------------- -void my_sdmmcMsgHandler(int bytes, void *user_data) { -//--------------------------------------------------------------------------------- - FifoMessage msg; - int retval = 0; - - fifoGetDatamsg(FIFO_SDMMC, bytes, (u8*)&msg); - - int oldIME = enterCriticalSection(); - switch (msg.type) { - - case SDMMC_SD_READ_SECTORS: - retval = my_sdmmc_readsectors(&deviceSD, msg.sdParams.startsector, msg.sdParams.numsectors, msg.sdParams.buffer); - break; - case SDMMC_SD_WRITE_SECTORS: - retval = my_sdmmc_writesectors(&deviceSD, msg.sdParams.startsector, msg.sdParams.numsectors, msg.sdParams.buffer); - break; - case SDMMC_NAND_READ_SECTORS: - retval = my_sdmmc_readsectors(&deviceNAND, msg.sdParams.startsector, msg.sdParams.numsectors, msg.sdParams.buffer); - break; - case SDMMC_NAND_WRITE_SECTORS: - retval = my_sdmmc_writesectors(&deviceNAND, msg.sdParams.startsector, msg.sdParams.numsectors, msg.sdParams.buffer); - break; - } - - leaveCriticalSection(oldIME); - - fifoSendValue32(FIFO_SDMMC, retval); -} - -//--------------------------------------------------------------------------------- -int my_sdmmc_nand_startup() { -//--------------------------------------------------------------------------------- - my_sdmmc_controller_init(false); - return my_sdmmc_nand_init(); -} - -//--------------------------------------------------------------------------------- -int my_sdmmc_sd_startup() { -//--------------------------------------------------------------------------------- - my_sdmmc_controller_init(false); - return my_sdmmc_sdcard_init(); -} - -//--------------------------------------------------------------------------------- -void my_sdmmcValueHandler(u32 value, void* user_data) { -//--------------------------------------------------------------------------------- - int result = 0; - int sdflag = 0; - int oldIME = enterCriticalSection(); - - switch(value) { - - case SDMMC_HAVE_SD: - result = sdmmc_read16(REG_SDSTATUS0); - break; - - case SDMMC_SD_START: - sdflag = 1; - /* Falls through. */ - case SDMMC_NAND_START: - if (sdmmc_read16(REG_SDSTATUS0) == 0) { - result = 1; - } else { - result = (sdflag == 1 ) ? my_sdmmc_sd_startup() : my_sdmmc_nand_startup(); - } - break; - - case SDMMC_SD_IS_INSERTED: - result = my_sdmmc_cardinserted(); - break; - - case SDMMC_SD_STOP: - my_sdmmc_controller_initialised = false; - break; - - case SDMMC_NAND_SIZE: - result = deviceNAND.total_size; - break; - } - - leaveCriticalSection(oldIME); - - fifoSendValue32(FIFO_SDMMC, result); -} - -//--------------------------------------------------------------------------------- -int my_sdmmc_sdcard_readsectors(u32 sector_no, u32 numsectors, void *out) { -//--------------------------------------------------------------------------------- - return my_sdmmc_readsectors(&deviceSD, sector_no, numsectors, out); -} - -//--------------------------------------------------------------------------------- -int my_sdmmc_sdcard_writesectors(u32 sector_no, u32 numsectors, void *in) { -//--------------------------------------------------------------------------------- - return my_sdmmc_writesectors(&deviceSD, sector_no, numsectors, in); -} - -//--------------------------------------------------------------------------------- -int my_sdmmc_nand_readsectors(u32 sector_no, u32 numsectors, void *out) { -//--------------------------------------------------------------------------------- - return my_sdmmc_readsectors(&deviceNAND, sector_no, numsectors, out); -} - -//--------------------------------------------------------------------------------- -int my_sdmmc_nand_writesectors(u32 sector_no, u32 numsectors, void *in) { -//--------------------------------------------------------------------------------- - return my_sdmmc_writesectors(&deviceNAND, sector_no, numsectors, in); -} - - diff --git a/arm7/source/my_system.c b/arm7/source/my_system.c deleted file mode 100644 index cde820a7..00000000 --- a/arm7/source/my_system.c +++ /dev/null @@ -1,53 +0,0 @@ -/*--------------------------------------------------------------------------------- - - Copyright (C) 2005 - 2010 - Michael Noland (joat) - Jason Rogers (Dovoto) - Dave Murphy (WinterMute) - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any - damages arising from the use of this software. - - Permission is granted to anyone to use this software for any - purpose, including commercial applications, and to alter it and - redistribute it freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you - must not claim that you wrote the original software. If you use - this software in a product, an acknowledgment in the product - documentation would be appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and - must not be misrepresented as being the original software. - 3. This notice may not be removed or altered from any source - distribution. - ----------------------------------------------------------------------------------*/ -#include -#include -#include -#include -#include -#include -#include -#include - -void powerValueHandler(u32 value, void* user_data); -void my_sdmmcMsgHandler(int bytes, void *user_data); -void my_sdmmcValueHandler(u32 value, void* user_data); -void firmwareMsgHandler(int bytes, void *user_data); - -//--------------------------------------------------------------------------------- -void my_installSystemFIFO(void) { -//--------------------------------------------------------------------------------- - - fifoSetValue32Handler(FIFO_PM, powerValueHandler, 0); - //if (isDSiMode() || (REG_SCFG_EXT & BIT(18))) { - fifoSetValue32Handler(FIFO_SDMMC, my_sdmmcValueHandler, 0); - fifoSetDatamsgHandler(FIFO_SDMMC, my_sdmmcMsgHandler, 0); - //} - fifoSetDatamsgHandler(FIFO_FIRMWARE, firmwareMsgHandler, 0); - -} - - diff --git a/arm7/source/pxi.c b/arm7/source/pxi.c new file mode 100644 index 00000000..f1fe1c1c --- /dev/null +++ b/arm7/source/pxi.c @@ -0,0 +1,178 @@ +#include "pxi.h" +#include "gba.h" +#include "my_i2c.h" + +#include +#include + +// Management structure and stack space for PXI server thread +Thread s_pxiThread; +alignas(8) u8 s_pxiThreadStack[1024]; +Mailbox mb; +u32 mb_slots[4]; + +u32 *pxiData = NULL; + +// void set_ctr(u32* ctr){ +// for (int i = 0; i < 4; i++) REG_AES_IV.data[i] = ctr[3-i]; +// } + +// // 10 11 22 23 24 25 +// void aes(void* in, void* out, void* iv, u32 method){ //this is sort of a bodged together dsi aes function adapted from this 3ds function +// REG_AES_CNT = ( AES_CNT_MODE(method) | //https://github.com/TiniVi/AHPCFW/blob/master/source/aes.c#L42 +// AES_WRFIFO_FLUSH | //as long as the output changes when keyslot values change, it's good enough. +// AES_RDFIFO_FLUSH | +// AES_CNT_KEY_APPLY | +// AES_CNT_KEYSLOT(3) | +// AES_CNT_DMA_WRITE_SIZE(2) | +// AES_CNT_DMA_READ_SIZE(1) +// ); + +// if(iv != NULL) set_ctr((u32*)iv); +// REG_AES_BLKCNT = (1 << 16); +// REG_AES_CNT |= 0x80000000; + +// for (int j = 0; j < 0x10; j+=4) REG_AES_WRFIFO = *((u32*)(in+j)); +// while(((REG_AES_CNT >> 0x5) & 0x1F) < 0x4); //wait for every word to get processed +// for (int j = 0; j < 0x10; j+=4) *((u32*)(out+j)) = REG_AES_RDFIFO; +// //REG_AES_CNT &= ~0x80000000; +// //if(method & (AES_CTR_DECRYPT | AES_CTR_ENCRYPT)) add_ctr((u8*)iv); +// } + +static void pxiHandler(void* user, u32 data) +{ + static unsigned data_words = 0, data_total = 0, header = 0; + // static u32 header = 0; + + if_likely(data_words == 0) { + if(pxiData) + free(pxiData); + + data_words = data >> 26; + data_total = data_words; + + pxiData = malloc(data_words * 4); + if_likely(data_words == 0) { + mailboxTrySend(&mb, data); + return; + } + + header = data & ((1U<<26)-1); + return; + } + + pxiData[data_total - (data_words--)] = data; + if (data_words == 0) { + mailboxTrySend(&mb, header); + } +} + +void getArm7Vars(u32 **vars) { + *vars[0] = REG_SCFG_EXT; + *vars[1] = REG_SNDEXCNT; + + // Check for 3DS + if(isDSiMode() || (REG_SCFG_EXT & BIT(22))) { + u8 byteBak = my_i2cReadRegister8(0x4A, 0x71); + my_i2cWriteRegister8(0x4A, 0x71, 0xD2); + *vars[2] = my_i2cReadRegister8(0x4A, 0x71) == 0xD2; + my_i2cWriteRegister8(0x4A, 0x71, byteBak); + } + + /* TODO: Was used by nandio, remove or use + if(isDSiMode() || ((REG_SCFG_EXT & BIT(17)) && (REG_SCFG_EXT & BIT(18)))) { + u8 *out=(u8*)0x02F00000; + memset(out, 0, 16); + + // first check whether we can read the console ID directly and it was not hidden by SCFG + if(((*(vu16*)0x04004000) & (1u << 10)) == 0 && ((*(vu8*)0x04004D08) & 0x1) == 0) { + // The console id registers are readable, so use them! + memcpy(out, (u8*)0x04004D00, 8); + } + if(out[0] == 0 || out[1] == 0) { + // For getting ConsoleID without reading from 0x4004D00... + u8 base[16]={0}; + u8 in[16]={0}; + u8 iv[16]={0}; + u8 *scratch=(u8*)0x02F00200; + u8 *key3=(u8*)0x40044D0; + + aes(in, base, iv, 2); + + //write consecutive 0-255 values to any byte in key3 until we get the same aes output as "base" above - this reveals the hidden byte. this way we can uncover all 16 bytes of the key3 normalkey pretty easily. + //greets to Martin Korth for this trick https://problemkaputt.de/gbatek.htm#dsiaesioports (Reading Write-Only Values) + for(int i=0;i<16;i++){ + for(int j=0;j<256;j++){ + *(key3+i)=j & 0xFF; + aes(in, scratch, iv, 2); + if(!memcmp(scratch, base, 16)){ + out[i]=j; + //hit++; + break; + } + } + } + } + } + */ +} + +//--------------------------------------------------------------------------------- +int pxiThreadMain(void* arg) { +//--------------------------------------------------------------------------------- + // Set up PXI mailbox, used to receive PXI command words + mailboxPrepare(&mb, mb_slots, sizeof(mb_slots)/4); + pxiSetHandler(PXI_MAIN, pxiHandler, NULL); + + // Main PXI message loop + for (;;) { + // Receive a message + u32 msg = mailboxRecv(&mb); + u32 retval = 0; + + switch (msg) { + case GET_ARM7_VARS: + getArm7Vars((u32 **)pxiData); + retval = 77; + break; + + case GBA_READ_EEPROM: + if(pxiData) + retval = gbaReadEeprom((u8 *)pxiData[0], pxiData[1], pxiData[2]); + break; + + case GBA_WRITE_EEPROM: + if(pxiData) + retval = gbaWriteEeprom(pxiData[0], (u8 *)pxiData[1], pxiData[2]); + break; + + default: + break; + } + + // Send a reply back to the ARM9 + pxiReply(PXI_MAIN, retval); + } + + return 0; +} + +// void powerValueHandler(u32 value, void* user_data); +// void my_sdmmcMsgHandler(int bytes, void *user_data); +// void my_sdmmcValueHandler(u32 value, void* user_data); +// void firmwareMsgHandler(int bytes, void *user_data); + +// //--------------------------------------------------------------------------------- +// void my_installSystemFIFO(void) { +// //--------------------------------------------------------------------------------- + +// fifoSetValue32Handler(FIFO_PM, powerValueHandler, 0); +// //if (isDSiMode() || (REG_SCFG_EXT & BIT(18))) { +// fifoSetValue32Handler(FIFO_SDMMC, my_sdmmcValueHandler, 0); +// fifoSetDatamsgHandler(FIFO_SDMMC, my_sdmmcMsgHandler, 0); +// //} +// fifoSetDatamsgHandler(FIFO_FIRMWARE, firmwareMsgHandler, 0); + +// } + + diff --git a/arm9/Makefile b/arm9/Makefile index e059fdce..1e0ea826 100644 --- a/arm9/Makefile +++ b/arm9/Makefile @@ -1,7 +1,6 @@ #--------------------------------------------------------------------------------- .SUFFIXES: #--------------------------------------------------------------------------------- - ifeq ($(strip $(DEVKITARM)),) $(error "Please set DEVKITARM in your environment. export DEVKITARM=devkitARM") endif @@ -27,48 +26,40 @@ $(shell printf "#ifndef VERSION_HPP\n#define VERSION_HPP\n\n#define VER_NUMBER \ endif #--------------------------------------------------------------------------------- -# TARGET is the name of the output # BUILD is the directory where object files & intermediate files will be placed # SOURCES is a list of directories containing source code # INCLUDES is a list of directories containing extra header files # DATA is a list of directories containing binary files embedded using bin2o # GRAPHICS is a list of directories containing image files to be converted with grit -# MAXMOD_SOUNDBANK contains a directory of music and sound effect files +# all directories are relative to this makefile #--------------------------------------------------------------------------------- -TARGET := GodMode9i -BUILD := build -SOURCES := source source/flashcard source/graphics dldi-include mbedtls -INCLUDES := include dldi-include source source/flashcard source/graphics -DATA := ../data -GRAPHICS := ../gfx +BUILD := build +SOURCES := source source/flashcard source/graphics dldi-include +INCLUDES := include dldi-include source source/flashcard source/graphics ../shared/include +DATA := ../data +GRAPHICS := ../gfx #--------------------------------------------------------------------------------- # options for code generation #--------------------------------------------------------------------------------- -ARCH := -mthumb-interwork - -CFLAGS := -g -Wall -Wno-psabi -O2\ - -march=armv5te -mtune=arm946e-s -fomit-frame-pointer\ - -ffast-math \ - $(ARCH) +ARCH := -march=armv5te -mtune=arm946e-s -CFLAGS += $(INCLUDE) -DARM9 -D_NO_BOOTSTUB_ -CXXFLAGS := $(CFLAGS) -fno-exceptions -std=gnu++17 - -ASFLAGS := -g $(ARCH) -LDFLAGS = -specs=../ds_arm9_hi.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map) +CFLAGS := -g -Wall -O2 -ffunction-sections -fdata-sections\ + $(ARCH) $(INCLUDE) -DARM9 +CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++20 +ASFLAGS := -g $(ARCH) +LDFLAGS = -specs=ds_arm9.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map) #--------------------------------------------------------------------------------- -# any extra libraries we wish to link with the project (order is important) +# any extra libraries we wish to link with the project #--------------------------------------------------------------------------------- -LIBS := -lfat -lnds329 +LIBS := -lfat -lnds9 #--------------------------------------------------------------------------------- # list of directories containing libraries, this must be the top level containing # include and lib #--------------------------------------------------------------------------------- -LIBDIRS := $(CURDIR) ../ $(LIBNDS) -LIBDIRS32 := $(CURDIR)/../libnds32 +LIBDIRS := $(LIBNDS) $(PORTLIBS) #--------------------------------------------------------------------------------- # no real need to edit anything past this point unless you need to add additional @@ -77,78 +68,74 @@ LIBDIRS32 := $(CURDIR)/../libnds32 ifneq ($(BUILD),$(notdir $(CURDIR))) #--------------------------------------------------------------------------------- -export OUTPUT := $(CURDIR)/$(TARGET) +export ARM9ELF := $(CURDIR)/$(TARGET).elf -export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ - $(foreach dir,$(DATA),$(CURDIR)/$(dir)) \ - $(foreach dir,$(GRAPHICS),$(CURDIR)/$(dir)) +export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir))\ + $(foreach dir,$(DATA),$(CURDIR)/$(dir))\ + $(foreach dir,$(GRAPHICS),$(CURDIR)/$(dir)) -export DEPSDIR := $(CURDIR)/$(BUILD) +export DEPSDIR := $(CURDIR)/$(BUILD) -CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) -CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) -BMPFILES := $(foreach dir,$(GRAPHICS),$(notdir $(wildcard $(dir)/*.bmp))) -PNGFILES := $(foreach dir,$(GRAPHICS),$(notdir $(wildcard $(dir)/*.png))) -SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) -BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) +CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) +CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) +SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) +PNGFILES := $(foreach dir,$(GRAPHICS),$(notdir $(wildcard $(dir)/*.png))) +BMPFILES := $(foreach dir,$(GRAPHICS),$(notdir $(wildcard $(dir)/*.bmp))) +BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) #--------------------------------------------------------------------------------- # use CXX for linking C++ projects, CC for standard C #--------------------------------------------------------------------------------- ifeq ($(strip $(CPPFILES)),) #--------------------------------------------------------------------------------- - export LD := $(CC) + export LD := $(CC) #--------------------------------------------------------------------------------- else #--------------------------------------------------------------------------------- - export LD := $(CXX) + export LD := $(CXX) #--------------------------------------------------------------------------------- endif #--------------------------------------------------------------------------------- -export OFILES := $(addsuffix .o,$(BINFILES)) \ - $(BMPFILES:.bmp=.o) \ - $(PNGFILES:.png=.o) \ - $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o) +export OFILES_BIN := $(addsuffix .o,$(BINFILES)) -export INCLUDE := $(foreach dir,$(INCLUDES),-iquote $(CURDIR)/$(dir)) \ - $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ - -I$(CURDIR)/$(BUILD) +export OFILES_SOURCES := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o) -export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) \ - $(foreach dir,$(LIBDIRS32),-L$(dir)/lib) +export OFILES := $(PNGFILES:.png=.o) $(OFILES_BIN) $(OFILES_SOURCES) +export HFILES := $(PNGFILES:.png=.h) $(addsuffix .h,$(subst .,_,$(BINFILES))) -export OUTPUT := $(CURDIR)/$(TARGET) +export INCLUDE := $(foreach dir,$(INCLUDES),-iquote $(CURDIR)/$(dir))\ + $(foreach dir,$(LIBDIRS),-I$(dir)/include)\ + -I$(CURDIR)/$(BUILD) +export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) .PHONY: $(BUILD) clean -all : $(BUILD) - #--------------------------------------------------------------------------------- $(BUILD): @[ -d $@ ] || mkdir -p $@ - @make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile + @$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile + #--------------------------------------------------------------------------------- clean: @echo clean ... @rm -fr $(BUILD) $(TARGET).elf $(TARGET).nds *.bin include/version.h + #--------------------------------------------------------------------------------- else -DEPENDS := $(OFILES:.o=.d) - #--------------------------------------------------------------------------------- # main targets #--------------------------------------------------------------------------------- -$(OUTPUT).elf : $(OFILES) +$(ARM9ELF) : $(OFILES) #--------------------------------------------------------------------------------- -%.bin.o : %.bin +%.bin.o %_bin.h : %.bin #--------------------------------------------------------------------------------- @echo $(notdir $<) - $(bin2o) + @$(bin2o) #--------------------------------------------------------------------------------- %.frf.o : %.frf diff --git a/arm9/mbedtls/aes.c b/arm9/mbedtls/aes.c deleted file mode 100644 index f2e48ab5..00000000 --- a/arm9/mbedtls/aes.c +++ /dev/null @@ -1,252 +0,0 @@ - -#include -#include -#include "aes.h" - -/* AES 128 ECB dug out from mbed TLS 2.5.1 - * https://github.com/ARMmbed/mbedtls/blob/development/include/mbedtls/aes.h - * https://github.com/ARMmbed/mbedtls/blob/development/library/aes.c - * - * C style comments are mbed TLS comments - * C++ style comments are mine - */ - -// make VC happy -#ifdef _MSC_VER -#define DTCM_BSS -#define ITCM_CODE -#endif - -// it's interesting they mix unsigned char with uint32_t -DTCM_BSS static unsigned char FSb[256]; -DTCM_BSS static uint32_t FT0[256]; -DTCM_BSS static uint32_t FT1[256]; -DTCM_BSS static uint32_t FT2[256]; -DTCM_BSS static uint32_t FT3[256]; - -// AES-CTR/CCM only uses encrypt, so R tables are not used -#define NO_R_TABLES -#ifndef NO_R_TABLES -static unsigned char RSb[256]; -static uint32_t RT0[256]; -static uint32_t RT1[256]; -static uint32_t RT2[256]; -static uint32_t RT3[256]; -#endif - -static uint32_t RCON[256]; - -/* - * Tables generation code - */ -#define ROTL8(x) ( ( x << 8 ) & 0xFFFFFFFF ) | ( x >> 24 ) -#define XTIME(x) ( ( x << 1 ) ^ ( ( x & 0x80 ) ? 0x1B : 0x00 ) ) -#define MUL(x,y) ( ( x && y ) ? pow[(log[x]+log[y]) % 255] : 0 ) - -void aes_gen_tables(void) -{ -#ifdef NO_R_TABLES - unsigned char *RSb = memalign(32, 256); - uint32_t *RT0 = memalign(32, 256 * sizeof(uint32_t)); - uint32_t *RT1 = memalign(32, 256 * sizeof(uint32_t)); - uint32_t *RT2 = memalign(32, 256 * sizeof(uint32_t)); - uint32_t *RT3 = memalign(32, 256 * sizeof(uint32_t)); -#endif - - int i, x, y, z; - int pow[256]; - int log[256]; - - /* - * compute pow and log tables over GF(2^8) - */ - for (i = 0, x = 1; i < 256; i++) - { - pow[i] = x; - log[x] = i; - x = (x ^ XTIME(x)) & 0xFF; - } - - /* - * calculate the round constants - */ - for (i = 0, x = 1; i < 10; i++) - { - RCON[i] = (uint32_t)x; - x = XTIME(x) & 0xFF; - } - - /* - * generate the forward and reverse S-boxes - */ - FSb[0x00] = 0x63; - RSb[0x63] = 0x00; - - for (i = 1; i < 256; i++) - { - x = pow[255 - log[i]]; - - y = x; y = ((y << 1) | (y >> 7)) & 0xFF; - x ^= y; y = ((y << 1) | (y >> 7)) & 0xFF; - x ^= y; y = ((y << 1) | (y >> 7)) & 0xFF; - x ^= y; y = ((y << 1) | (y >> 7)) & 0xFF; - x ^= y ^ 0x63; - - FSb[i] = (unsigned char)x; - RSb[x] = (unsigned char)i; - } - - /* - * generate the forward and reverse tables - */ - for (i = 0; i < 256; i++) - { - x = FSb[i]; - y = XTIME(x) & 0xFF; - z = (y ^ x) & 0xFF; - - FT0[i] = ((uint32_t)y) ^ - ((uint32_t)x << 8) ^ - ((uint32_t)x << 16) ^ - ((uint32_t)z << 24); - - FT1[i] = ROTL8(FT0[i]); - FT2[i] = ROTL8(FT1[i]); - FT3[i] = ROTL8(FT2[i]); - - x = RSb[i]; - - RT0[i] = ((uint32_t)MUL(0x0E, x)) ^ - ((uint32_t)MUL(0x09, x) << 8) ^ - ((uint32_t)MUL(0x0D, x) << 16) ^ - ((uint32_t)MUL(0x0B, x) << 24); - - RT1[i] = ROTL8(RT0[i]); - RT2[i] = ROTL8(RT1[i]); - RT3[i] = ROTL8(RT2[i]); - } -#ifdef NO_R_TABLES - free(RSb); - free(RT0); - free(RT1); - free(RT2); - free(RT3); -#endif -} - -// did a little counting to understand why original mbedTLS buf is [68] -// in set key, they generated: -// 128 bits key: 10 rounds of += 4, plus 4 after, 44 -// 192 bits key: 8 rounds of += 6, plus 6 after, 56 -// 256 bits key: 7 rounds of += 8, plus 8 after, 64 -// and in ecb encrypt, it used: -// 4 + 4 * 2 * 4 + 4 + 4 "++"s, 44 -// 4 + 4 * 2 * 5 + 4 + 4 "++"s, 52 -// 4 + 4 * 2 * 6 + 4 + 4 "++"s, 60 -// so they generated several bytes more in 192 and 256 modes to simplify the loop -// "able to hold 32 extra bytes" in their comment makes senses now - -void aes_set_key_enc_128_be(uint32_t rk[RK_LEN], const unsigned char *key) { - uint32_t *RK = rk; - - GET_UINT32_BE(RK[0], key, 12); - GET_UINT32_BE(RK[1], key, 8); - GET_UINT32_BE(RK[2], key, 4); - GET_UINT32_BE(RK[3], key, 0); - - for (unsigned i = 0; i < 10; ++i, RK += 4) { - RK[4] = RK[0] ^ RCON[i] ^ - ((uint32_t)FSb[(RK[3] >> 8) & 0xFF]) ^ - ((uint32_t)FSb[(RK[3] >> 16) & 0xFF] << 8) ^ - ((uint32_t)FSb[(RK[3] >> 24) & 0xFF] << 16) ^ - ((uint32_t)FSb[(RK[3]) & 0xFF] << 24); - - RK[5] = RK[1] ^ RK[4]; - RK[6] = RK[2] ^ RK[5]; - RK[7] = RK[3] ^ RK[6]; - } -} - -#define AES_FROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \ -{ \ - X0 = *RK++ ^ FT0[ ( Y0 ) & 0xFF ] ^ \ - FT1[ ( Y1 >> 8 ) & 0xFF ] ^ \ - FT2[ ( Y2 >> 16 ) & 0xFF ] ^ \ - FT3[ ( Y3 >> 24 ) & 0xFF ]; \ - \ - X1 = *RK++ ^ FT0[ ( Y1 ) & 0xFF ] ^ \ - FT1[ ( Y2 >> 8 ) & 0xFF ] ^ \ - FT2[ ( Y3 >> 16 ) & 0xFF ] ^ \ - FT3[ ( Y0 >> 24 ) & 0xFF ]; \ - \ - X2 = *RK++ ^ FT0[ ( Y2 ) & 0xFF ] ^ \ - FT1[ ( Y3 >> 8 ) & 0xFF ] ^ \ - FT2[ ( Y0 >> 16 ) & 0xFF ] ^ \ - FT3[ ( Y1 >> 24 ) & 0xFF ]; \ - \ - X3 = *RK++ ^ FT0[ ( Y3 ) & 0xFF ] ^ \ - FT1[ ( Y0 >> 8 ) & 0xFF ] ^ \ - FT2[ ( Y1 >> 16 ) & 0xFF ] ^ \ - FT3[ ( Y2 >> 24 ) & 0xFF ]; \ -} - -DTCM_BSS uint32_t X0, X1, X2, X3, Y0, Y1, Y2, Y3; -DTCM_BSS const uint32_t *RK; - -ITCM_CODE void aes_encrypt_128_be(const uint32_t rk[RK_LEN], - const unsigned char input[16], unsigned char output[16]) -{ - RK = rk; - - GET_UINT32_BE(X0, input, 12); - GET_UINT32_BE(X1, input, 8); - GET_UINT32_BE(X2, input, 4); - GET_UINT32_BE(X3, input, 0); - - X0 ^= *RK++; - X1 ^= *RK++; - X2 ^= *RK++; - X3 ^= *RK++; - - // loop unrolled - AES_FROUND(Y0, Y1, Y2, Y3, X0, X1, X2, X3); - AES_FROUND(X0, X1, X2, X3, Y0, Y1, Y2, Y3); - AES_FROUND(Y0, Y1, Y2, Y3, X0, X1, X2, X3); - AES_FROUND(X0, X1, X2, X3, Y0, Y1, Y2, Y3); - AES_FROUND(Y0, Y1, Y2, Y3, X0, X1, X2, X3); - AES_FROUND(X0, X1, X2, X3, Y0, Y1, Y2, Y3); - AES_FROUND(Y0, Y1, Y2, Y3, X0, X1, X2, X3); - AES_FROUND(X0, X1, X2, X3, Y0, Y1, Y2, Y3); - AES_FROUND(Y0, Y1, Y2, Y3, X0, X1, X2, X3); - - X0 = *RK++ ^ \ - ((uint32_t)FSb[(Y0) & 0xFF]) ^ - ((uint32_t)FSb[(Y1 >> 8) & 0xFF] << 8) ^ - ((uint32_t)FSb[(Y2 >> 16) & 0xFF] << 16) ^ - ((uint32_t)FSb[(Y3 >> 24) & 0xFF] << 24); - - X1 = *RK++ ^ \ - ((uint32_t)FSb[(Y1) & 0xFF]) ^ - ((uint32_t)FSb[(Y2 >> 8) & 0xFF] << 8) ^ - ((uint32_t)FSb[(Y3 >> 16) & 0xFF] << 16) ^ - ((uint32_t)FSb[(Y0 >> 24) & 0xFF] << 24); - - X2 = *RK++ ^ \ - ((uint32_t)FSb[(Y2) & 0xFF]) ^ - ((uint32_t)FSb[(Y3 >> 8) & 0xFF] << 8) ^ - ((uint32_t)FSb[(Y0 >> 16) & 0xFF] << 16) ^ - ((uint32_t)FSb[(Y1 >> 24) & 0xFF] << 24); - - // removed a ++ here - X3 = *RK ^ \ - ((uint32_t)FSb[(Y3) & 0xFF]) ^ - ((uint32_t)FSb[(Y0 >> 8) & 0xFF] << 8) ^ - ((uint32_t)FSb[(Y1 >> 16) & 0xFF] << 16) ^ - ((uint32_t)FSb[(Y2 >> 24) & 0xFF] << 24); - - PUT_UINT32_BE(X0, output, 12); - PUT_UINT32_BE(X1, output, 8); - PUT_UINT32_BE(X2, output, 4); - PUT_UINT32_BE(X3, output, 0); -} - diff --git a/arm9/mbedtls/aes.h b/arm9/mbedtls/aes.h deleted file mode 100644 index db99bd56..00000000 --- a/arm9/mbedtls/aes.h +++ /dev/null @@ -1,32 +0,0 @@ - -#pragma once - -#include - -#define RK_LEN 44 //round key length - -// modified to work on reversed byte order input/output -// it could work by wrapping it between byte reversed I/O, minmize modification to actual AES code -// this is just my OCD to eliminate some copy -// original mbedTLS AES GET/PUT_UINT32 macros on little endian I/O regardless of CPU endianness -// seems like Nintendo used big endian hardware AES with little endian CPU -// by byte reversing on I/O, this mimics Nintendo behavior on little endian CPU -// calling it BE is not very accurate, it becomes little endian on big endian CPU - -#define GET_UINT32_BE(n, b, i) \ - ((uint8_t*)&(n))[0] = (b)[i + 3]; \ - ((uint8_t*)&(n))[1] = (b)[i + 2]; \ - ((uint8_t*)&(n))[2] = (b)[i + 1]; \ - ((uint8_t*)&(n))[3] = (b)[i + 0] -#define PUT_UINT32_BE(n, b, i) \ - (b)[i + 0] = ((uint8_t*)&(n))[3]; \ - (b)[i + 1] = ((uint8_t*)&(n))[2]; \ - (b)[i + 2] = ((uint8_t*)&(n))[1]; \ - (b)[i + 3] = ((uint8_t*)&(n))[0] - -void aes_gen_tables(void); - -void aes_set_key_enc_128_be(uint32_t rk[RK_LEN], const unsigned char *key); - -void aes_encrypt_128_be(const uint32_t rk[RK_LEN], const unsigned char input[16], unsigned char output[16]); - diff --git a/arm9/mbedtls/bignum.c b/arm9/mbedtls/bignum.c deleted file mode 100644 index 76a5e49c..00000000 --- a/arm9/mbedtls/bignum.c +++ /dev/null @@ -1,2452 +0,0 @@ -/* - * Multi-precision integer library - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ - -/* - * The following sources were referenced in the design of this Multi-precision - * Integer library: - * - * [1] Handbook of Applied Cryptography - 1997 - * Menezes, van Oorschot and Vanstone - * - * [2] Multi-Precision Math - * Tom St Denis - * https://github.com/libtom/libtommath/blob/develop/tommath.pdf - * - * [3] GNU Multi-Precision Arithmetic Library - * https://gmplib.org/manual/index.html - * - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_BIGNUM_C) - -#include "bignum.h" -#include "bn_mul.h" - -#include - -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -// #include -#include -// #define mbedtls_printf printf -#define mbedtls_calloc calloc -#define mbedtls_free free -#endif - -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_mpi_zeroize( mbedtls_mpi_uint *v, size_t n ) { - volatile mbedtls_mpi_uint *p = v; while( n-- ) *p++ = 0; -} - -#define ciL (sizeof(mbedtls_mpi_uint)) /* chars in limb */ -#define biL (ciL << 3) /* bits in limb */ -#define biH (ciL << 2) /* half limb size */ - -#define MPI_SIZE_T_MAX ( (size_t) -1 ) /* SIZE_T_MAX is not standard */ - -/* - * Convert between bits/chars and number of limbs - * Divide first in order to avoid potential overflows - */ -#define BITS_TO_LIMBS(i) ( (i) / biL + ( (i) % biL != 0 ) ) -#define CHARS_TO_LIMBS(i) ( (i) / ciL + ( (i) % ciL != 0 ) ) - -/* - * Initialize one MPI - */ -void mbedtls_mpi_init( mbedtls_mpi *X ) -{ - if( X == NULL ) - return; - - X->s = 1; - X->n = 0; - X->p = NULL; -} - -/* - * Unallocate one MPI - */ -void mbedtls_mpi_free( mbedtls_mpi *X ) -{ - if( X == NULL ) - return; - - if( X->p != NULL ) - { - mbedtls_mpi_zeroize( X->p, X->n ); - mbedtls_free( X->p ); - } - - X->s = 1; - X->n = 0; - X->p = NULL; -} - -/* - * Enlarge to the specified number of limbs - */ -int mbedtls_mpi_grow( mbedtls_mpi *X, size_t nblimbs ) -{ - mbedtls_mpi_uint *p; - - if( nblimbs > MBEDTLS_MPI_MAX_LIMBS ) - return( MBEDTLS_ERR_MPI_ALLOC_FAILED ); - - if( X->n < nblimbs ) - { - if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( nblimbs, ciL ) ) == NULL ) - return( MBEDTLS_ERR_MPI_ALLOC_FAILED ); - - if( X->p != NULL ) - { - memcpy( p, X->p, X->n * ciL ); - mbedtls_mpi_zeroize( X->p, X->n ); - mbedtls_free( X->p ); - } - - X->n = nblimbs; - X->p = p; - } - - return( 0 ); -} - -/* - * Resize down as much as possible, - * while keeping at least the specified number of limbs - */ -int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs ) -{ - mbedtls_mpi_uint *p; - size_t i; - - /* Actually resize up in this case */ - if( X->n <= nblimbs ) - return( mbedtls_mpi_grow( X, nblimbs ) ); - - for( i = X->n - 1; i > 0; i-- ) - if( X->p[i] != 0 ) - break; - i++; - - if( i < nblimbs ) - i = nblimbs; - - if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( i, ciL ) ) == NULL ) - return( MBEDTLS_ERR_MPI_ALLOC_FAILED ); - - if( X->p != NULL ) - { - memcpy( p, X->p, i * ciL ); - mbedtls_mpi_zeroize( X->p, X->n ); - mbedtls_free( X->p ); - } - - X->n = i; - X->p = p; - - return( 0 ); -} - -/* - * Copy the contents of Y into X - */ -int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y ) -{ - int ret; - size_t i; - - if( X == Y ) - return( 0 ); - - if( Y->p == NULL ) - { - mbedtls_mpi_free( X ); - return( 0 ); - } - - for( i = Y->n - 1; i > 0; i-- ) - if( Y->p[i] != 0 ) - break; - i++; - - X->s = Y->s; - - MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i ) ); - - memset( X->p, 0, X->n * ciL ); - memcpy( X->p, Y->p, i * ciL ); - -cleanup: - - return( ret ); -} - -/* - * Swap the contents of X and Y - */ -void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y ) -{ - mbedtls_mpi T; - - memcpy( &T, X, sizeof( mbedtls_mpi ) ); - memcpy( X, Y, sizeof( mbedtls_mpi ) ); - memcpy( Y, &T, sizeof( mbedtls_mpi ) ); -} - -/* - * Conditionally assign X = Y, without leaking information - * about whether the assignment was made or not. - * (Leaking information about the respective sizes of X and Y is ok however.) - */ -int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned char assign ) -{ - int ret = 0; - size_t i; - - /* make sure assign is 0 or 1 in a time-constant manner */ - assign = (assign | (unsigned char)-assign) >> 7; - - MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) ); - - X->s = X->s * ( 1 - assign ) + Y->s * assign; - - for( i = 0; i < Y->n; i++ ) - X->p[i] = X->p[i] * ( 1 - assign ) + Y->p[i] * assign; - - for( ; i < X->n; i++ ) - X->p[i] *= ( 1 - assign ); - -cleanup: - return( ret ); -} - -/* - * Conditionally swap X and Y, without leaking information - * about whether the swap was made or not. - * Here it is not ok to simply swap the pointers, which whould lead to - * different memory access patterns when X and Y are used afterwards. - */ -int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char swap ) -{ - int ret, s; - size_t i; - mbedtls_mpi_uint tmp; - - if( X == Y ) - return( 0 ); - - /* make sure swap is 0 or 1 in a time-constant manner */ - swap = (swap | (unsigned char)-swap) >> 7; - - MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_grow( Y, X->n ) ); - - s = X->s; - X->s = X->s * ( 1 - swap ) + Y->s * swap; - Y->s = Y->s * ( 1 - swap ) + s * swap; - - - for( i = 0; i < X->n; i++ ) - { - tmp = X->p[i]; - X->p[i] = X->p[i] * ( 1 - swap ) + Y->p[i] * swap; - Y->p[i] = Y->p[i] * ( 1 - swap ) + tmp * swap; - } - -cleanup: - return( ret ); -} - -/* - * Set value from integer - */ -int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z ) -{ - int ret; - - MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, 1 ) ); - memset( X->p, 0, X->n * ciL ); - - X->p[0] = ( z < 0 ) ? -z : z; - X->s = ( z < 0 ) ? -1 : 1; - -cleanup: - - return( ret ); -} - -/* - * Get a specific bit - */ -int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos ) -{ - if( X->n * biL <= pos ) - return( 0 ); - - return( ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01 ); -} - -/* - * Set a bit to a specific value of 0 or 1 - */ -int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val ) -{ - int ret = 0; - size_t off = pos / biL; - size_t idx = pos % biL; - - if( val != 0 && val != 1 ) - return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); - - if( X->n * biL <= pos ) - { - if( val == 0 ) - return( 0 ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, off + 1 ) ); - } - - X->p[off] &= ~( (mbedtls_mpi_uint) 0x01 << idx ); - X->p[off] |= (mbedtls_mpi_uint) val << idx; - -cleanup: - - return( ret ); -} - -/* - * Return the number of less significant zero-bits - */ -size_t mbedtls_mpi_lsb( const mbedtls_mpi *X ) -{ - size_t i, j, count = 0; - - for( i = 0; i < X->n; i++ ) - for( j = 0; j < biL; j++, count++ ) - if( ( ( X->p[i] >> j ) & 1 ) != 0 ) - return( count ); - - return( 0 ); -} - -/* - * Count leading zero bits in a given integer - */ -static size_t mbedtls_clz( const mbedtls_mpi_uint x ) -{ - size_t j; - mbedtls_mpi_uint mask = (mbedtls_mpi_uint) 1 << (biL - 1); - - for( j = 0; j < biL; j++ ) - { - if( x & mask ) break; - - mask >>= 1; - } - - return j; -} - -/* - * Return the number of bits - */ -size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X ) -{ - size_t i, j; - - if( X->n == 0 ) - return( 0 ); - - for( i = X->n - 1; i > 0; i-- ) - if( X->p[i] != 0 ) - break; - - j = biL - mbedtls_clz( X->p[i] ); - - return( ( i * biL ) + j ); -} - -/* - * Return the total size in bytes - */ -size_t mbedtls_mpi_size( const mbedtls_mpi *X ) -{ - return( ( mbedtls_mpi_bitlen( X ) + 7 ) >> 3 ); -} - -#if 0 // not used -/* - * Convert an ASCII character to digit value - */ -static int mpi_get_digit( mbedtls_mpi_uint *d, int radix, char c ) -{ - *d = 255; - - if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30; - if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37; - if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57; - - if( *d >= (mbedtls_mpi_uint) radix ) - return( MBEDTLS_ERR_MPI_INVALID_CHARACTER ); - - return( 0 ); -} - -/* - * Import from an ASCII string - */ -int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s ) -{ - int ret; - size_t i, j, slen, n; - mbedtls_mpi_uint d; - mbedtls_mpi T; - - if( radix < 2 || radix > 16 ) - return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); - - mbedtls_mpi_init( &T ); - - slen = strlen( s ); - - if( radix == 16 ) - { - if( slen > MPI_SIZE_T_MAX >> 2 ) - return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); - - n = BITS_TO_LIMBS( slen << 2 ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) ); - - for( i = slen, j = 0; i > 0; i--, j++ ) - { - if( i == 1 && s[i - 1] == '-' ) - { - X->s = -1; - break; - } - - MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) ); - X->p[j / ( 2 * ciL )] |= d << ( ( j % ( 2 * ciL ) ) << 2 ); - } - } - else - { - MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) ); - - for( i = 0; i < slen; i++ ) - { - if( i == 0 && s[i] == '-' ) - { - X->s = -1; - continue; - } - - MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i] ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T, X, radix ) ); - - if( X->s == 1 ) - { - MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, &T, d ) ); - } - else - { - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( X, &T, d ) ); - } - } - } - -cleanup: - - mbedtls_mpi_free( &T ); - - return( ret ); -} - -/* - * Helper to write the digits high-order first - */ -static int mpi_write_hlp( mbedtls_mpi *X, int radix, char **p ) -{ - int ret; - mbedtls_mpi_uint r; - - if( radix < 2 || radix > 16 ) - return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, radix ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_div_int( X, NULL, X, radix ) ); - - if( mbedtls_mpi_cmp_int( X, 0 ) != 0 ) - MBEDTLS_MPI_CHK( mpi_write_hlp( X, radix, p ) ); - - if( r < 10 ) - *(*p)++ = (char)( r + 0x30 ); - else - *(*p)++ = (char)( r + 0x37 ); - -cleanup: - - return( ret ); -} - -/* - * Export into an ASCII string - */ -int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix, - char *buf, size_t buflen, size_t *olen ) -{ - int ret = 0; - size_t n; - char *p; - mbedtls_mpi T; - - if( radix < 2 || radix > 16 ) - return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); - - n = mbedtls_mpi_bitlen( X ); - if( radix >= 4 ) n >>= 1; - if( radix >= 16 ) n >>= 1; - /* - * Round up the buffer length to an even value to ensure that there is - * enough room for hexadecimal values that can be represented in an odd - * number of digits. - */ - n += 3 + ( ( n + 1 ) & 1 ); - - if( buflen < n ) - { - *olen = n; - return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL ); - } - - p = buf; - mbedtls_mpi_init( &T ); - - if( X->s == -1 ) - *p++ = '-'; - - if( radix == 16 ) - { - int c; - size_t i, j, k; - - for( i = X->n, k = 0; i > 0; i-- ) - { - for( j = ciL; j > 0; j-- ) - { - c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF; - - if( c == 0 && k == 0 && ( i + j ) != 2 ) - continue; - - *(p++) = "0123456789ABCDEF" [c / 16]; - *(p++) = "0123456789ABCDEF" [c % 16]; - k = 1; - } - } - } - else - { - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T, X ) ); - - if( T.s == -1 ) - T.s = 1; - - MBEDTLS_MPI_CHK( mpi_write_hlp( &T, radix, &p ) ); - } - - *p++ = '\0'; - *olen = p - buf; - -cleanup: - - mbedtls_mpi_free( &T ); - - return( ret ); -} -#endif // not used - -#if defined(MBEDTLS_FS_IO) -/* - * Read X from an opened file - */ -int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin ) -{ - mbedtls_mpi_uint d; - size_t slen; - char *p; - /* - * Buffer should have space for (short) label and decimal formatted MPI, - * newline characters and '\0' - */ - char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ]; - - memset( s, 0, sizeof( s ) ); - if( fgets( s, sizeof( s ) - 1, fin ) == NULL ) - return( MBEDTLS_ERR_MPI_FILE_IO_ERROR ); - - slen = strlen( s ); - if( slen == sizeof( s ) - 2 ) - return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL ); - - if( slen > 0 && s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; } - if( slen > 0 && s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; } - - p = s + slen; - while( p-- > s ) - if( mpi_get_digit( &d, radix, *p ) != 0 ) - break; - - return( mbedtls_mpi_read_string( X, radix, p + 1 ) ); -} - -/* - * Write X into an opened file (or stdout if fout == NULL) - */ -int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout ) -{ - int ret; - size_t n, slen, plen; - /* - * Buffer should have space for (short) label and decimal formatted MPI, - * newline characters and '\0' - */ - char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ]; - - memset( s, 0, sizeof( s ) ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_write_string( X, radix, s, sizeof( s ) - 2, &n ) ); - - if( p == NULL ) p = ""; - - plen = strlen( p ); - slen = strlen( s ); - s[slen++] = '\r'; - s[slen++] = '\n'; - - if( fout != NULL ) - { - if( fwrite( p, 1, plen, fout ) != plen || - fwrite( s, 1, slen, fout ) != slen ) - return( MBEDTLS_ERR_MPI_FILE_IO_ERROR ); - } - else - mbedtls_printf( "%s%s", p, s ); - -cleanup: - - return( ret ); -} -#endif /* MBEDTLS_FS_IO */ - -/* - * Import X from unsigned binary data, big endian - */ -int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen ) -{ - int ret; - size_t i, j, n; - - for( n = 0; n < buflen; n++ ) - if( buf[n] != 0 ) - break; - - MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, CHARS_TO_LIMBS( buflen - n ) ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) ); - - for( i = buflen, j = 0; i > n; i--, j++ ) - X->p[j / ciL] |= ((mbedtls_mpi_uint) buf[i - 1]) << ((j % ciL) << 3); - -cleanup: - - return( ret ); -} - -/* - * Export X into unsigned binary data, big endian - */ -int mbedtls_mpi_write_binary( const mbedtls_mpi *X, unsigned char *buf, size_t buflen ) -{ - size_t i, j, n; - - n = mbedtls_mpi_size( X ); - - if( buflen < n ) - return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL ); - - memset( buf, 0, buflen ); - - for( i = buflen - 1, j = 0; n > 0; i--, j++, n-- ) - buf[i] = (unsigned char)( X->p[j / ciL] >> ((j % ciL) << 3) ); - - return( 0 ); -} - -/* - * Left-shift: X <<= count - */ -int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count ) -{ - int ret; - size_t i, v0, t1; - mbedtls_mpi_uint r0 = 0, r1; - - v0 = count / (biL ); - t1 = count & (biL - 1); - - i = mbedtls_mpi_bitlen( X ) + count; - - if( X->n * biL < i ) - MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, BITS_TO_LIMBS( i ) ) ); - - ret = 0; - - /* - * shift by count / limb_size - */ - if( v0 > 0 ) - { - for( i = X->n; i > v0; i-- ) - X->p[i - 1] = X->p[i - v0 - 1]; - - for( ; i > 0; i-- ) - X->p[i - 1] = 0; - } - - /* - * shift by count % limb_size - */ - if( t1 > 0 ) - { - for( i = v0; i < X->n; i++ ) - { - r1 = X->p[i] >> (biL - t1); - X->p[i] <<= t1; - X->p[i] |= r0; - r0 = r1; - } - } - -cleanup: - - return( ret ); -} - -/* - * Right-shift: X >>= count - */ -int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count ) -{ - size_t i, v0, v1; - mbedtls_mpi_uint r0 = 0, r1; - - v0 = count / biL; - v1 = count & (biL - 1); - - if( v0 > X->n || ( v0 == X->n && v1 > 0 ) ) - return mbedtls_mpi_lset( X, 0 ); - - /* - * shift by count / limb_size - */ - if( v0 > 0 ) - { - for( i = 0; i < X->n - v0; i++ ) - X->p[i] = X->p[i + v0]; - - for( ; i < X->n; i++ ) - X->p[i] = 0; - } - - /* - * shift by count % limb_size - */ - if( v1 > 0 ) - { - for( i = X->n; i > 0; i-- ) - { - r1 = X->p[i - 1] << (biL - v1); - X->p[i - 1] >>= v1; - X->p[i - 1] |= r0; - r0 = r1; - } - } - - return( 0 ); -} - -/* - * Compare unsigned values - */ -int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y ) -{ - size_t i, j; - - for( i = X->n; i > 0; i-- ) - if( X->p[i - 1] != 0 ) - break; - - for( j = Y->n; j > 0; j-- ) - if( Y->p[j - 1] != 0 ) - break; - - if( i == 0 && j == 0 ) - return( 0 ); - - if( i > j ) return( 1 ); - if( j > i ) return( -1 ); - - for( ; i > 0; i-- ) - { - if( X->p[i - 1] > Y->p[i - 1] ) return( 1 ); - if( X->p[i - 1] < Y->p[i - 1] ) return( -1 ); - } - - return( 0 ); -} - -/* - * Compare signed values - */ -int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y ) -{ - size_t i, j; - - for( i = X->n; i > 0; i-- ) - if( X->p[i - 1] != 0 ) - break; - - for( j = Y->n; j > 0; j-- ) - if( Y->p[j - 1] != 0 ) - break; - - if( i == 0 && j == 0 ) - return( 0 ); - - if( i > j ) return( X->s ); - if( j > i ) return( -Y->s ); - - if( X->s > 0 && Y->s < 0 ) return( 1 ); - if( Y->s > 0 && X->s < 0 ) return( -1 ); - - for( ; i > 0; i-- ) - { - if( X->p[i - 1] > Y->p[i - 1] ) return( X->s ); - if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s ); - } - - return( 0 ); -} - -/* - * Compare signed values - */ -int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z ) -{ - mbedtls_mpi Y; - mbedtls_mpi_uint p[1]; - - *p = ( z < 0 ) ? -z : z; - Y.s = ( z < 0 ) ? -1 : 1; - Y.n = 1; - Y.p = p; - - return( mbedtls_mpi_cmp_mpi( X, &Y ) ); -} - -/* - * Unsigned addition: X = |A| + |B| (HAC 14.7) - */ -int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ) -{ - int ret; - size_t i, j; - mbedtls_mpi_uint *o, *p, c, tmp; - - if( X == B ) - { - const mbedtls_mpi *T = A; A = X; B = T; - } - - if( X != A ) - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) ); - - /* - * X should always be positive as a result of unsigned additions. - */ - X->s = 1; - - for( j = B->n; j > 0; j-- ) - if( B->p[j - 1] != 0 ) - break; - - MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) ); - - o = B->p; p = X->p; c = 0; - - /* - * tmp is used because it might happen that p == o - */ - for( i = 0; i < j; i++, o++, p++ ) - { - tmp= *o; - *p += c; c = ( *p < c ); - *p += tmp; c += ( *p < tmp ); - } - - while( c != 0 ) - { - if( i >= X->n ) - { - MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) ); - p = X->p + i; - } - - *p += c; c = ( *p < c ); i++; p++; - } - -cleanup: - - return( ret ); -} - -/* - * Helper for mbedtls_mpi subtraction - */ -static void mpi_sub_hlp( size_t n, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d ) -{ - size_t i; - mbedtls_mpi_uint c, z; - - for( i = c = 0; i < n; i++, s++, d++ ) - { - z = ( *d < c ); *d -= c; - c = ( *d < *s ) + z; *d -= *s; - } - - while( c != 0 ) - { - z = ( *d < c ); *d -= c; - c = z; i++; d++; - } -} - -/* - * Unsigned subtraction: X = |A| - |B| (HAC 14.9) - */ -int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ) -{ - mbedtls_mpi TB; - int ret; - size_t n; - - if( mbedtls_mpi_cmp_abs( A, B ) < 0 ) - return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE ); - - mbedtls_mpi_init( &TB ); - - if( X == B ) - { - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); - B = &TB; - } - - if( X != A ) - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) ); - - /* - * X should always be positive as a result of unsigned subtractions. - */ - X->s = 1; - - ret = 0; - - for( n = B->n; n > 0; n-- ) - if( B->p[n - 1] != 0 ) - break; - - mpi_sub_hlp( n, B->p, X->p ); - -cleanup: - - mbedtls_mpi_free( &TB ); - - return( ret ); -} - -/* - * Signed addition: X = A + B - */ -int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ) -{ - int ret, s = A->s; - - if( A->s * B->s < 0 ) - { - if( mbedtls_mpi_cmp_abs( A, B ) >= 0 ) - { - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) ); - X->s = s; - } - else - { - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) ); - X->s = -s; - } - } - else - { - MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) ); - X->s = s; - } - -cleanup: - - return( ret ); -} - -/* - * Signed subtraction: X = A - B - */ -int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ) -{ - int ret, s = A->s; - - if( A->s * B->s > 0 ) - { - if( mbedtls_mpi_cmp_abs( A, B ) >= 0 ) - { - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) ); - X->s = s; - } - else - { - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) ); - X->s = -s; - } - } - else - { - MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) ); - X->s = s; - } - -cleanup: - - return( ret ); -} - -/* - * Signed addition: X = A + b - */ -int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b ) -{ - mbedtls_mpi _B; - mbedtls_mpi_uint p[1]; - - p[0] = ( b < 0 ) ? -b : b; - _B.s = ( b < 0 ) ? -1 : 1; - _B.n = 1; - _B.p = p; - - return( mbedtls_mpi_add_mpi( X, A, &_B ) ); -} - -/* - * Signed subtraction: X = A - b - */ -int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b ) -{ - mbedtls_mpi _B; - mbedtls_mpi_uint p[1]; - - p[0] = ( b < 0 ) ? -b : b; - _B.s = ( b < 0 ) ? -1 : 1; - _B.n = 1; - _B.p = p; - - return( mbedtls_mpi_sub_mpi( X, A, &_B ) ); -} - -/* - * Helper for mbedtls_mpi multiplication - */ -static -#if defined(__APPLE__) && defined(__arm__) -/* - * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn) - * appears to need this to prevent bad ARM code generation at -O3. - */ -__attribute__ ((noinline)) -#endif -void mpi_mul_hlp( size_t i, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d, mbedtls_mpi_uint b ) -{ - mbedtls_mpi_uint c = 0, t = 0; - -#if defined(MULADDC_HUIT) - for( ; i >= 8; i -= 8 ) - { - MULADDC_INIT - MULADDC_HUIT - MULADDC_STOP - } - - for( ; i > 0; i-- ) - { - MULADDC_INIT - MULADDC_CORE - MULADDC_STOP - } -#else /* MULADDC_HUIT */ - for( ; i >= 16; i -= 16 ) - { - MULADDC_INIT - MULADDC_CORE MULADDC_CORE - MULADDC_CORE MULADDC_CORE - MULADDC_CORE MULADDC_CORE - MULADDC_CORE MULADDC_CORE - - MULADDC_CORE MULADDC_CORE - MULADDC_CORE MULADDC_CORE - MULADDC_CORE MULADDC_CORE - MULADDC_CORE MULADDC_CORE - MULADDC_STOP - } - - for( ; i >= 8; i -= 8 ) - { - MULADDC_INIT - MULADDC_CORE MULADDC_CORE - MULADDC_CORE MULADDC_CORE - - MULADDC_CORE MULADDC_CORE - MULADDC_CORE MULADDC_CORE - MULADDC_STOP - } - - for( ; i > 0; i-- ) - { - MULADDC_INIT - MULADDC_CORE - MULADDC_STOP - } -#endif /* MULADDC_HUIT */ - - t++; - - do { - *d += c; c = ( *d < c ); d++; - } - while( c != 0 ); -} - -/* - * Baseline multiplication: X = A * B (HAC 14.12) - */ -int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ) -{ - int ret; - size_t i, j; - mbedtls_mpi TA, TB; - - mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB ); - - if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; } - if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; } - - for( i = A->n; i > 0; i-- ) - if( A->p[i - 1] != 0 ) - break; - - for( j = B->n; j > 0; j-- ) - if( B->p[j - 1] != 0 ) - break; - - MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) ); - - for( i++; j > 0; j-- ) - mpi_mul_hlp( i - 1, A->p, X->p + j - 1, B->p[j - 1] ); - - X->s = A->s * B->s; - -cleanup: - - mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA ); - - return( ret ); -} - -/* - * Baseline multiplication: X = A * b - */ -int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b ) -{ - mbedtls_mpi _B; - mbedtls_mpi_uint p[1]; - - _B.s = 1; - _B.n = 1; - _B.p = p; - p[0] = b; - - return( mbedtls_mpi_mul_mpi( X, A, &_B ) ); -} - -/* - * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and - * mbedtls_mpi_uint divisor, d - */ -static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1, - mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint *r ) -{ -#if defined(MBEDTLS_HAVE_UDBL) - mbedtls_t_udbl dividend, quotient; -#else - const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH; - const mbedtls_mpi_uint uint_halfword_mask = ( (mbedtls_mpi_uint) 1 << biH ) - 1; - mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient; - mbedtls_mpi_uint u0_msw, u0_lsw; - size_t s; -#endif - - /* - * Check for overflow - */ - if( 0 == d || u1 >= d ) - { - if (r != NULL) *r = ~0; - - return ( ~0 ); - } - -#if defined(MBEDTLS_HAVE_UDBL) - dividend = (mbedtls_t_udbl) u1 << biL; - dividend |= (mbedtls_t_udbl) u0; - quotient = dividend / d; - if( quotient > ( (mbedtls_t_udbl) 1 << biL ) - 1 ) - quotient = ( (mbedtls_t_udbl) 1 << biL ) - 1; - - if( r != NULL ) - *r = (mbedtls_mpi_uint)( dividend - (quotient * d ) ); - - return (mbedtls_mpi_uint) quotient; -#else - - /* - * Algorithm D, Section 4.3.1 - The Art of Computer Programming - * Vol. 2 - Seminumerical Algorithms, Knuth - */ - - /* - * Normalize the divisor, d, and dividend, u0, u1 - */ - s = mbedtls_clz( d ); - d = d << s; - - u1 = u1 << s; - u1 |= ( u0 >> ( biL - s ) ) & ( -(mbedtls_mpi_sint)s >> ( biL - 1 ) ); - u0 = u0 << s; - - d1 = d >> biH; - d0 = d & uint_halfword_mask; - - u0_msw = u0 >> biH; - u0_lsw = u0 & uint_halfword_mask; - - /* - * Find the first quotient and remainder - */ - q1 = u1 / d1; - r0 = u1 - d1 * q1; - - while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) ) - { - q1 -= 1; - r0 += d1; - - if ( r0 >= radix ) break; - } - - rAX = ( u1 * radix ) + ( u0_msw - q1 * d ); - q0 = rAX / d1; - r0 = rAX - q0 * d1; - - while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) ) - { - q0 -= 1; - r0 += d1; - - if ( r0 >= radix ) break; - } - - if (r != NULL) - *r = ( rAX * radix + u0_lsw - q0 * d ) >> s; - - quotient = q1 * radix + q0; - - return quotient; -#endif -} - -/* - * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20) - */ -int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B ) -{ - int ret; - size_t i, n, t, k; - mbedtls_mpi X, Y, Z, T1, T2; - - if( mbedtls_mpi_cmp_int( B, 0 ) == 0 ) - return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO ); - - mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z ); - mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 ); - - if( mbedtls_mpi_cmp_abs( A, B ) < 0 ) - { - if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) ); - if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) ); - return( 0 ); - } - - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) ); - X.s = Y.s = 1; - - MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, 2 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T2, 3 ) ); - - k = mbedtls_mpi_bitlen( &Y ) % biL; - if( k < biL - 1 ) - { - k = biL - 1 - k; - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) ); - } - else k = 0; - - n = X.n - 1; - t = Y.n - 1; - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) ); - - while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 ) - { - Z.p[n - t]++; - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) ); - } - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) ); - - for( i = n; i > t ; i-- ) - { - if( X.p[i] >= Y.p[t] ) - Z.p[i - t - 1] = ~0; - else - { - Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1], - Y.p[t], NULL); - } - - Z.p[i - t - 1]++; - do - { - Z.p[i - t - 1]--; - - MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) ); - T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1]; - T1.p[1] = Y.p[t]; - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T2, 0 ) ); - T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2]; - T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1]; - T2.p[2] = X.p[i]; - } - while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) ); - - if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 ) - { - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) ); - Z.p[i - t - 1]--; - } - } - - if( Q != NULL ) - { - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) ); - Q->s = A->s * B->s; - } - - if( R != NULL ) - { - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) ); - X.s = A->s; - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) ); - - if( mbedtls_mpi_cmp_int( R, 0 ) == 0 ) - R->s = 1; - } - -cleanup: - - mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z ); - mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 ); - - return( ret ); -} - -/* - * Division by int: A = Q * b + R - */ -int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, mbedtls_mpi_sint b ) -{ - mbedtls_mpi _B; - mbedtls_mpi_uint p[1]; - - p[0] = ( b < 0 ) ? -b : b; - _B.s = ( b < 0 ) ? -1 : 1; - _B.n = 1; - _B.p = p; - - return( mbedtls_mpi_div_mpi( Q, R, A, &_B ) ); -} - -/* - * Modulo: R = A mod B - */ -int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B ) -{ - int ret; - - if( mbedtls_mpi_cmp_int( B, 0 ) < 0 ) - return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) ); - - while( mbedtls_mpi_cmp_int( R, 0 ) < 0 ) - MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) ); - - while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 ) - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) ); - -cleanup: - - return( ret ); -} - -/* - * Modulo: r = A mod b - */ -int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b ) -{ - size_t i; - mbedtls_mpi_uint x, y, z; - - if( b == 0 ) - return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO ); - - if( b < 0 ) - return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE ); - - /* - * handle trivial cases - */ - if( b == 1 ) - { - *r = 0; - return( 0 ); - } - - if( b == 2 ) - { - *r = A->p[0] & 1; - return( 0 ); - } - - /* - * general case - */ - for( i = A->n, y = 0; i > 0; i-- ) - { - x = A->p[i - 1]; - y = ( y << biH ) | ( x >> biH ); - z = y / b; - y -= z * b; - - x <<= biH; - y = ( y << biH ) | ( x >> biH ); - z = y / b; - y -= z * b; - } - - /* - * If A is negative, then the current y represents a negative value. - * Flipping it to the positive side. - */ - if( A->s < 0 && y != 0 ) - y = b - y; - - *r = y; - - return( 0 ); -} - -/* - * Fast Montgomery initialization (thanks to Tom St Denis) - */ -static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N ) -{ - mbedtls_mpi_uint x, m0 = N->p[0]; - unsigned int i; - - x = m0; - x += ( ( m0 + 2 ) & 4 ) << 1; - - for( i = biL; i >= 8; i /= 2 ) - x *= ( 2 - ( m0 * x ) ); - - *mm = ~x + 1; -} - -/* - * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36) - */ -static int mpi_montmul( mbedtls_mpi *A, const mbedtls_mpi *B, const mbedtls_mpi *N, mbedtls_mpi_uint mm, - const mbedtls_mpi *T ) -{ - size_t i, n, m; - mbedtls_mpi_uint u0, u1, *d; - - if( T->n < N->n + 1 || T->p == NULL ) - return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); - - memset( T->p, 0, T->n * ciL ); - - d = T->p; - n = N->n; - m = ( B->n < n ) ? B->n : n; - - for( i = 0; i < n; i++ ) - { - /* - * T = (T + u0*B + u1*N) / 2^biL - */ - u0 = A->p[i]; - u1 = ( d[0] + u0 * B->p[0] ) * mm; - - mpi_mul_hlp( m, B->p, d, u0 ); - mpi_mul_hlp( n, N->p, d, u1 ); - - *d++ = u0; d[n + 1] = 0; - } - - memcpy( A->p, d, ( n + 1 ) * ciL ); - - if( mbedtls_mpi_cmp_abs( A, N ) >= 0 ) - mpi_sub_hlp( n, N->p, A->p ); - else - /* prevent timing attacks */ - mpi_sub_hlp( n, A->p, T->p ); - - return( 0 ); -} - -/* - * Montgomery reduction: A = A * R^-1 mod N - */ -static int mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N, mbedtls_mpi_uint mm, const mbedtls_mpi *T ) -{ - mbedtls_mpi_uint z = 1; - mbedtls_mpi U; - - U.n = U.s = (int) z; - U.p = &z; - - return( mpi_montmul( A, &U, N, mm, T ) ); -} - -/* - * Sliding-window exponentiation: X = A^E mod N (HAC 14.85) - */ -int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *E, const mbedtls_mpi *N, mbedtls_mpi *_RR ) -{ - int ret; - size_t wbits, wsize, one = 1; - size_t i, j, nblimbs; - size_t bufsize, nbits; - mbedtls_mpi_uint ei, mm, state; - mbedtls_mpi RR, T, W[ 2 << MBEDTLS_MPI_WINDOW_SIZE ], Apos; - int neg; - - if( mbedtls_mpi_cmp_int( N, 0 ) < 0 || ( N->p[0] & 1 ) == 0 ) - return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); - - if( mbedtls_mpi_cmp_int( E, 0 ) < 0 ) - return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); - - /* - * Init temps and window size - */ - mpi_montg_init( &mm, N ); - mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T ); - mbedtls_mpi_init( &Apos ); - memset( W, 0, sizeof( W ) ); - - i = mbedtls_mpi_bitlen( E ); - - wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 : - ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1; - - if( wsize > MBEDTLS_MPI_WINDOW_SIZE ) - wsize = MBEDTLS_MPI_WINDOW_SIZE; - - j = N->n + 1; - MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) ); - - /* - * Compensate for negative A (and correct at the end) - */ - neg = ( A->s == -1 ); - if( neg ) - { - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) ); - Apos.s = 1; - A = &Apos; - } - - /* - * If 1st call, pre-compute R^2 mod N - */ - if( _RR == NULL || _RR->p == NULL ) - { - MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) ); - - if( _RR != NULL ) - memcpy( _RR, &RR, sizeof( mbedtls_mpi ) ); - } - else - memcpy( &RR, _RR, sizeof( mbedtls_mpi ) ); - - /* - * W[1] = A * R^2 * R^-1 mod N = A * R mod N - */ - if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 ) - MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) ); - else - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) ); - - MBEDTLS_MPI_CHK( mpi_montmul( &W[1], &RR, N, mm, &T ) ); - - /* - * X = R^2 * R^-1 mod N = R mod N - */ - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) ); - MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) ); - - if( wsize > 1 ) - { - /* - * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1) - */ - j = one << ( wsize - 1 ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) ); - - for( i = 0; i < wsize - 1; i++ ) - MBEDTLS_MPI_CHK( mpi_montmul( &W[j], &W[j], N, mm, &T ) ); - - /* - * W[i] = W[i - 1] * W[1] - */ - for( i = j + 1; i < ( one << wsize ); i++ ) - { - MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) ); - - MBEDTLS_MPI_CHK( mpi_montmul( &W[i], &W[1], N, mm, &T ) ); - } - } - - nblimbs = E->n; - bufsize = 0; - nbits = 0; - wbits = 0; - state = 0; - - while( 1 ) - { - if( bufsize == 0 ) - { - if( nblimbs == 0 ) - break; - - nblimbs--; - - bufsize = sizeof( mbedtls_mpi_uint ) << 3; - } - - bufsize--; - - ei = (E->p[nblimbs] >> bufsize) & 1; - - /* - * skip leading 0s - */ - if( ei == 0 && state == 0 ) - continue; - - if( ei == 0 && state == 1 ) - { - /* - * out of window, square X - */ - MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) ); - continue; - } - - /* - * add ei to current window - */ - state = 2; - - nbits++; - wbits |= ( ei << ( wsize - nbits ) ); - - if( nbits == wsize ) - { - /* - * X = X^wsize R^-1 mod N - */ - for( i = 0; i < wsize; i++ ) - MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) ); - - /* - * X = X * W[wbits] R^-1 mod N - */ - MBEDTLS_MPI_CHK( mpi_montmul( X, &W[wbits], N, mm, &T ) ); - - state--; - nbits = 0; - wbits = 0; - } - } - - /* - * process the remaining bits - */ - for( i = 0; i < nbits; i++ ) - { - MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) ); - - wbits <<= 1; - - if( ( wbits & ( one << wsize ) ) != 0 ) - MBEDTLS_MPI_CHK( mpi_montmul( X, &W[1], N, mm, &T ) ); - } - - /* - * X = A^E * R * R^-1 mod N = A^E mod N - */ - MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) ); - - if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 ) - { - X->s = -1; - MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) ); - } - -cleanup: - - for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ ) - mbedtls_mpi_free( &W[i] ); - - mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos ); - - if( _RR == NULL || _RR->p == NULL ) - mbedtls_mpi_free( &RR ); - - return( ret ); -} - -#if 0 // not used -/* - * Greatest common divisor: G = gcd(A, B) (HAC 14.54) - */ -int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B ) -{ - int ret; - size_t lz, lzt; - mbedtls_mpi TG, TA, TB; - - mbedtls_mpi_init( &TG ); mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); - - lz = mbedtls_mpi_lsb( &TA ); - lzt = mbedtls_mpi_lsb( &TB ); - - if( lzt < lz ) - lz = lzt; - - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, lz ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, lz ) ); - - TA.s = TB.s = 1; - - while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 ) - { - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) ); - - if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 ) - { - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) ); - } - else - { - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) ); - } - } - - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) ); - -cleanup: - - mbedtls_mpi_free( &TG ); mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB ); - - return( ret ); -} - -/* - * Fill X with size bytes of random. - * - * Use a temporary bytes representation to make sure the result is the same - * regardless of the platform endianness (useful when f_rng is actually - * deterministic, eg for tests). - */ -int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ) -{ - int ret; - unsigned char buf[MBEDTLS_MPI_MAX_SIZE]; - - if( size > MBEDTLS_MPI_MAX_SIZE ) - return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); - - MBEDTLS_MPI_CHK( f_rng( p_rng, buf, size ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( X, buf, size ) ); - -cleanup: - return( ret ); -} - -/* - * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64) - */ -int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N ) -{ - int ret; - mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2; - - if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 ) - return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); - - mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 ); - mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV ); - mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) ); - - if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 ) - { - ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; - goto cleanup; - } - - MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) ); - - do - { - while( ( TU.p[0] & 1 ) == 0 ) - { - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) ); - - if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 ) - { - MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) ); - } - - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) ); - } - - while( ( TV.p[0] & 1 ) == 0 ) - { - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) ); - - if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 ) - { - MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) ); - } - - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) ); - } - - if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 ) - { - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) ); - } - else - { - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) ); - } - } - while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 ); - - while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 ) - MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) ); - - while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 ) - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) ); - -cleanup: - - mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 ); - mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV ); - mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 ); - - return( ret ); -} - -#if defined(MBEDTLS_GENPRIME) - -static const int small_prime[] = -{ - 3, 5, 7, 11, 13, 17, 19, 23, - 29, 31, 37, 41, 43, 47, 53, 59, - 61, 67, 71, 73, 79, 83, 89, 97, - 101, 103, 107, 109, 113, 127, 131, 137, - 139, 149, 151, 157, 163, 167, 173, 179, - 181, 191, 193, 197, 199, 211, 223, 227, - 229, 233, 239, 241, 251, 257, 263, 269, - 271, 277, 281, 283, 293, 307, 311, 313, - 317, 331, 337, 347, 349, 353, 359, 367, - 373, 379, 383, 389, 397, 401, 409, 419, - 421, 431, 433, 439, 443, 449, 457, 461, - 463, 467, 479, 487, 491, 499, 503, 509, - 521, 523, 541, 547, 557, 563, 569, 571, - 577, 587, 593, 599, 601, 607, 613, 617, - 619, 631, 641, 643, 647, 653, 659, 661, - 673, 677, 683, 691, 701, 709, 719, 727, - 733, 739, 743, 751, 757, 761, 769, 773, - 787, 797, 809, 811, 821, 823, 827, 829, - 839, 853, 857, 859, 863, 877, 881, 883, - 887, 907, 911, 919, 929, 937, 941, 947, - 953, 967, 971, 977, 983, 991, 997, -103 -}; - -/* - * Small divisors test (X must be positive) - * - * Return values: - * 0: no small factor (possible prime, more tests needed) - * 1: certain prime - * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime - * other negative: error - */ -static int mpi_check_small_factors( const mbedtls_mpi *X ) -{ - int ret = 0; - size_t i; - mbedtls_mpi_uint r; - - if( ( X->p[0] & 1 ) == 0 ) - return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ); - - for( i = 0; small_prime[i] > 0; i++ ) - { - if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 ) - return( 1 ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) ); - - if( r == 0 ) - return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ); - } - -cleanup: - return( ret ); -} - -/* - * Miller-Rabin pseudo-primality test (HAC 4.24) - */ -static int mpi_miller_rabin( const mbedtls_mpi *X, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ) -{ - int ret, count; - size_t i, j, k, n, s; - mbedtls_mpi W, R, T, A, RR; - - mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R ); mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A ); - mbedtls_mpi_init( &RR ); - - /* - * W = |X| - 1 - * R = W >> lsb( W ) - */ - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) ); - s = mbedtls_mpi_lsb( &W ); - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) ); - - i = mbedtls_mpi_bitlen( X ); - /* - * HAC, table 4.4 - */ - n = ( ( i >= 1300 ) ? 2 : ( i >= 850 ) ? 3 : - ( i >= 650 ) ? 4 : ( i >= 350 ) ? 8 : - ( i >= 250 ) ? 12 : ( i >= 150 ) ? 18 : 27 ); - - for( i = 0; i < n; i++ ) - { - /* - * pick a random A, 1 < A < |X| - 1 - */ - MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) ); - - if( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ) - { - j = mbedtls_mpi_bitlen( &A ) - mbedtls_mpi_bitlen( &W ); - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &A, j + 1 ) ); - } - A.p[0] |= 3; - - count = 0; - do { - MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) ); - - j = mbedtls_mpi_bitlen( &A ); - k = mbedtls_mpi_bitlen( &W ); - if (j > k) { - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &A, j - k ) ); - } - - if (count++ > 30) { - return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; - } - - } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 || - mbedtls_mpi_cmp_int( &A, 1 ) <= 0 ); - - /* - * A = A^R mod |X| - */ - MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) ); - - if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 || - mbedtls_mpi_cmp_int( &A, 1 ) == 0 ) - continue; - - j = 1; - while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ) - { - /* - * A = A * A mod |X| - */ - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) ); - - if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 ) - break; - - j++; - } - - /* - * not prime if A != |X| - 1 or A == 1 - */ - if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 || - mbedtls_mpi_cmp_int( &A, 1 ) == 0 ) - { - ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; - break; - } - } - -cleanup: - mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A ); - mbedtls_mpi_free( &RR ); - - return( ret ); -} - -/* - * Pseudo-primality test: small factors, then Miller-Rabin - */ -int mbedtls_mpi_is_prime( const mbedtls_mpi *X, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ) -{ - int ret; - mbedtls_mpi XX; - - XX.s = 1; - XX.n = X->n; - XX.p = X->p; - - if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 || - mbedtls_mpi_cmp_int( &XX, 1 ) == 0 ) - return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ); - - if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 ) - return( 0 ); - - if( ( ret = mpi_check_small_factors( &XX ) ) != 0 ) - { - if( ret == 1 ) - return( 0 ); - - return( ret ); - } - - return( mpi_miller_rabin( &XX, f_rng, p_rng ) ); -} - -/* - * Prime number generation - */ -int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int dh_flag, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ) -{ - int ret; - size_t k, n; - mbedtls_mpi_uint r; - mbedtls_mpi Y; - - if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS ) - return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); - - mbedtls_mpi_init( &Y ); - - n = BITS_TO_LIMBS( nbits ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) ); - - k = mbedtls_mpi_bitlen( X ); - if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits + 1 ) ); - - mbedtls_mpi_set_bit( X, nbits-1, 1 ); - - X->p[0] |= 1; - - if( dh_flag == 0 ) - { - while( ( ret = mbedtls_mpi_is_prime( X, f_rng, p_rng ) ) != 0 ) - { - if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ) - goto cleanup; - - MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 2 ) ); - } - } - else - { - /* - * An necessary condition for Y and X = 2Y + 1 to be prime - * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3). - * Make sure it is satisfied, while keeping X = 3 mod 4 - */ - - X->p[0] |= 2; - - MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) ); - if( r == 0 ) - MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) ); - else if( r == 1 ) - MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) ); - - /* Set Y = (X-1) / 2, which is X / 2 because X is odd */ - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) ); - - while( 1 ) - { - /* - * First, check small factors for X and Y - * before doing Miller-Rabin on any of them - */ - if( ( ret = mpi_check_small_factors( X ) ) == 0 && - ( ret = mpi_check_small_factors( &Y ) ) == 0 && - ( ret = mpi_miller_rabin( X, f_rng, p_rng ) ) == 0 && - ( ret = mpi_miller_rabin( &Y, f_rng, p_rng ) ) == 0 ) - { - break; - } - - if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ) - goto cleanup; - - /* - * Next candidates. We want to preserve Y = (X-1) / 2 and - * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3) - * so up Y by 6 and X by 12. - */ - MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) ); - } - } - -cleanup: - - mbedtls_mpi_free( &Y ); - - return( ret ); -} - -#endif /* MBEDTLS_GENPRIME */ - -#if defined(MBEDTLS_SELF_TEST) - -#define GCD_PAIR_COUNT 3 - -static const int gcd_pairs[GCD_PAIR_COUNT][3] = -{ - { 693, 609, 21 }, - { 1764, 868, 28 }, - { 768454923, 542167814, 1 } -}; - -/* - * Checkup routine - */ -int mbedtls_mpi_self_test( int verbose ) -{ - int ret, i; - mbedtls_mpi A, E, N, X, Y, U, V; - - mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X ); - mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16, - "EFE021C2645FD1DC586E69184AF4A31E" \ - "D5F53E93B5F123FA41680867BA110131" \ - "944FE7952E2517337780CB0DB80E61AA" \ - "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16, - "B2E7EFD37075B9F03FF989C7C5051C20" \ - "34D2A323810251127E7BF8625A4F49A5" \ - "F3E27F4DA8BD59C47D6DAABA4C8127BD" \ - "5B5C25763222FEFCCFC38B832366C29E" ) ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16, - "0066A198186C18C10B2F5ED9B522752A" \ - "9830B69916E535C8F047518A889A43A5" \ - "94B6BED27A168D31D4A52F88925AA8F5" ) ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16, - "602AB7ECA597A3D6B56FF9829A5E8B85" \ - "9E857EA95A03512E2BAE7391688D264A" \ - "A5663B0341DB9CCFD2C4C5F421FEC814" \ - "8001B72E848A38CAE1C65F78E56ABDEF" \ - "E12D3C039B8A02D6BE593F0BBBDA56F1" \ - "ECF677152EF804370C1A305CAF3B5BF1" \ - "30879B56C61DE584A0F53A2447A51E" ) ); - - if( verbose != 0 ) - mbedtls_printf( " MPI test #1 (mul_mpi): " ); - - if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - ret = 1; - goto cleanup; - } - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16, - "256567336059E52CAE22925474705F39A94" ) ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16, - "6613F26162223DF488E9CD48CC132C7A" \ - "0AC93C701B001B092E4E5B9F73BCD27B" \ - "9EE50D0657C77F374E903CDFA4C642" ) ); - - if( verbose != 0 ) - mbedtls_printf( " MPI test #2 (div_mpi): " ); - - if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 || - mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - ret = 1; - goto cleanup; - } - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16, - "36E139AEA55215609D2816998ED020BB" \ - "BD96C37890F65171D948E9BC7CBAA4D9" \ - "325D24D6A3C12710F10A09FA08AB87" ) ); - - if( verbose != 0 ) - mbedtls_printf( " MPI test #3 (exp_mod): " ); - - if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - ret = 1; - goto cleanup; - } - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16, - "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \ - "C3DBA76456363A10869622EAC2DD84EC" \ - "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) ); - - if( verbose != 0 ) - mbedtls_printf( " MPI test #4 (inv_mod): " ); - - if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - ret = 1; - goto cleanup; - } - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); - - if( verbose != 0 ) - mbedtls_printf( " MPI test #5 (simple gcd): " ); - - for( i = 0; i < GCD_PAIR_COUNT; i++ ) - { - MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) ); - - if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed at %d\n", i ); - - ret = 1; - goto cleanup; - } - } - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); - -cleanup: - - if( ret != 0 && verbose != 0 ) - mbedtls_printf( "Unexpected error, return code = %08X\n", ret ); - - mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X ); - mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V ); - - if( verbose != 0 ) - mbedtls_printf( "\n" ); - - return( ret ); -} - -#endif /* MBEDTLS_SELF_TEST */ - -#endif // not used - -#endif /* MBEDTLS_BIGNUM_C */ diff --git a/arm9/mbedtls/bignum.h b/arm9/mbedtls/bignum.h deleted file mode 100644 index 456a8042..00000000 --- a/arm9/mbedtls/bignum.h +++ /dev/null @@ -1,761 +0,0 @@ -/** - * \file bignum.h - * - * \brief Multi-precision integer library - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ -#ifndef MBEDTLS_BIGNUM_H -#define MBEDTLS_BIGNUM_H - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#include -#include - -#if defined(MBEDTLS_FS_IO) -#include -#endif - -#define MBEDTLS_ERR_MPI_FILE_IO_ERROR -0x0002 /**< An error occurred while reading from or writing to a file. */ -#define MBEDTLS_ERR_MPI_BAD_INPUT_DATA -0x0004 /**< Bad input parameters to function. */ -#define MBEDTLS_ERR_MPI_INVALID_CHARACTER -0x0006 /**< There is an invalid character in the digit string. */ -#define MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL -0x0008 /**< The buffer is too small to write to. */ -#define MBEDTLS_ERR_MPI_NEGATIVE_VALUE -0x000A /**< The input arguments are negative or result in illegal output. */ -#define MBEDTLS_ERR_MPI_DIVISION_BY_ZERO -0x000C /**< The input argument for division is zero, which is not allowed. */ -#define MBEDTLS_ERR_MPI_NOT_ACCEPTABLE -0x000E /**< The input arguments are not acceptable. */ -#define MBEDTLS_ERR_MPI_ALLOC_FAILED -0x0010 /**< Memory allocation failed. */ - -#define MBEDTLS_MPI_CHK(f) do { if( ( ret = f ) != 0 ) goto cleanup; } while( 0 ) - -/* - * Maximum size MPIs are allowed to grow to in number of limbs. - */ -#define MBEDTLS_MPI_MAX_LIMBS 10000 - -#if !defined(MBEDTLS_MPI_WINDOW_SIZE) -/* - * Maximum window size used for modular exponentiation. Default: 6 - * Minimum value: 1. Maximum value: 6. - * - * Result is an array of ( 2 << MBEDTLS_MPI_WINDOW_SIZE ) MPIs used - * for the sliding window calculation. (So 64 by default) - * - * Reduction in size, reduces speed. - */ -#define MBEDTLS_MPI_WINDOW_SIZE 6 /**< Maximum windows size used. */ -#endif /* !MBEDTLS_MPI_WINDOW_SIZE */ - -#if !defined(MBEDTLS_MPI_MAX_SIZE) -/* - * Maximum size of MPIs allowed in bits and bytes for user-MPIs. - * ( Default: 512 bytes => 4096 bits, Maximum tested: 2048 bytes => 16384 bits ) - * - * Note: Calculations can results temporarily in larger MPIs. So the number - * of limbs required (MBEDTLS_MPI_MAX_LIMBS) is higher. - */ -#define MBEDTLS_MPI_MAX_SIZE 1024 /**< Maximum number of bytes for usable MPIs. */ -#endif /* !MBEDTLS_MPI_MAX_SIZE */ - -#define MBEDTLS_MPI_MAX_BITS ( 8 * MBEDTLS_MPI_MAX_SIZE ) /**< Maximum number of bits for usable MPIs. */ - -/* - * When reading from files with mbedtls_mpi_read_file() and writing to files with - * mbedtls_mpi_write_file() the buffer should have space - * for a (short) label, the MPI (in the provided radix), the newline - * characters and the '\0'. - * - * By default we assume at least a 10 char label, a minimum radix of 10 - * (decimal) and a maximum of 4096 bit numbers (1234 decimal chars). - * Autosized at compile time for at least a 10 char label, a minimum radix - * of 10 (decimal) for a number of MBEDTLS_MPI_MAX_BITS size. - * - * This used to be statically sized to 1250 for a maximum of 4096 bit - * numbers (1234 decimal chars). - * - * Calculate using the formula: - * MBEDTLS_MPI_RW_BUFFER_SIZE = ceil(MBEDTLS_MPI_MAX_BITS / ln(10) * ln(2)) + - * LabelSize + 6 - */ -#define MBEDTLS_MPI_MAX_BITS_SCALE100 ( 100 * MBEDTLS_MPI_MAX_BITS ) -#define MBEDTLS_LN_2_DIV_LN_10_SCALE100 332 -#define MBEDTLS_MPI_RW_BUFFER_SIZE ( ((MBEDTLS_MPI_MAX_BITS_SCALE100 + MBEDTLS_LN_2_DIV_LN_10_SCALE100 - 1) / MBEDTLS_LN_2_DIV_LN_10_SCALE100) + 10 + 6 ) - -/* - * Define the base integer type, architecture-wise. - * - * 32 or 64-bit integer types can be forced regardless of the underlying - * architecture by defining MBEDTLS_HAVE_INT32 or MBEDTLS_HAVE_INT64 - * respectively and undefining MBEDTLS_HAVE_ASM. - * - * Double-width integers (e.g. 128-bit in 64-bit architectures) can be - * disabled by defining MBEDTLS_NO_UDBL_DIVISION. - */ -#if !defined(MBEDTLS_HAVE_INT32) - #if defined(_MSC_VER) && defined(_M_AMD64) - /* Always choose 64-bit when using MSC */ - #if !defined(MBEDTLS_HAVE_INT64) - #define MBEDTLS_HAVE_INT64 - #endif /* !MBEDTLS_HAVE_INT64 */ - typedef int64_t mbedtls_mpi_sint; - typedef uint64_t mbedtls_mpi_uint; - #elif defined(__GNUC__) && ( \ - defined(__amd64__) || defined(__x86_64__) || \ - defined(__ppc64__) || defined(__powerpc64__) || \ - defined(__ia64__) || defined(__alpha__) || \ - ( defined(__sparc__) && defined(__arch64__) ) || \ - defined(__s390x__) || defined(__mips64) ) - #if !defined(MBEDTLS_HAVE_INT64) - #define MBEDTLS_HAVE_INT64 - #endif /* MBEDTLS_HAVE_INT64 */ - typedef int64_t mbedtls_mpi_sint; - typedef uint64_t mbedtls_mpi_uint; - #if !defined(MBEDTLS_NO_UDBL_DIVISION) - /* mbedtls_t_udbl defined as 128-bit unsigned int */ - typedef unsigned int mbedtls_t_udbl __attribute__((mode(TI))); - #define MBEDTLS_HAVE_UDBL - #endif /* !MBEDTLS_NO_UDBL_DIVISION */ - #elif defined(__ARMCC_VERSION) && defined(__aarch64__) - /* - * __ARMCC_VERSION is defined for both armcc and armclang and - * __aarch64__ is only defined by armclang when compiling 64-bit code - */ - #if !defined(MBEDTLS_HAVE_INT64) - #define MBEDTLS_HAVE_INT64 - #endif /* !MBEDTLS_HAVE_INT64 */ - typedef int64_t mbedtls_mpi_sint; - typedef uint64_t mbedtls_mpi_uint; - #if !defined(MBEDTLS_NO_UDBL_DIVISION) - /* mbedtls_t_udbl defined as 128-bit unsigned int */ - typedef __uint128_t mbedtls_t_udbl; - #define MBEDTLS_HAVE_UDBL - #endif /* !MBEDTLS_NO_UDBL_DIVISION */ - #elif defined(MBEDTLS_HAVE_INT64) - /* Force 64-bit integers with unknown compiler */ - typedef int64_t mbedtls_mpi_sint; - typedef uint64_t mbedtls_mpi_uint; - #endif -#endif /* !MBEDTLS_HAVE_INT32 */ - -#if !defined(MBEDTLS_HAVE_INT64) - /* Default to 32-bit compilation */ - #if !defined(MBEDTLS_HAVE_INT32) - #define MBEDTLS_HAVE_INT32 - #endif /* !MBEDTLS_HAVE_INT32 */ - typedef int32_t mbedtls_mpi_sint; - typedef uint32_t mbedtls_mpi_uint; - #if !defined(MBEDTLS_NO_UDBL_DIVISION) - typedef uint64_t mbedtls_t_udbl; - #define MBEDTLS_HAVE_UDBL - #endif /* !MBEDTLS_NO_UDBL_DIVISION */ -#endif /* !MBEDTLS_HAVE_INT64 */ - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief MPI structure - */ -typedef struct -{ - int s; /*!< integer sign */ - size_t n; /*!< total # of limbs */ - mbedtls_mpi_uint *p; /*!< pointer to limbs */ -} -mbedtls_mpi; - -/** - * \brief Initialize one MPI (make internal references valid) - * This just makes it ready to be set or freed, - * but does not define a value for the MPI. - * - * \param X One MPI to initialize. - */ -void mbedtls_mpi_init( mbedtls_mpi *X ); - -/** - * \brief Unallocate one MPI - * - * \param X One MPI to unallocate. - */ -void mbedtls_mpi_free( mbedtls_mpi *X ); - -/** - * \brief Enlarge to the specified number of limbs - * - * \param X MPI to grow - * \param nblimbs The target number of limbs - * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed - */ -int mbedtls_mpi_grow( mbedtls_mpi *X, size_t nblimbs ); - -/** - * \brief Resize down, keeping at least the specified number of limbs - * - * \param X MPI to shrink - * \param nblimbs The minimum number of limbs to keep - * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed - */ -int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs ); - -/** - * \brief Copy the contents of Y into X - * - * \param X Destination MPI - * \param Y Source MPI - * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed - */ -int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y ); - -/** - * \brief Swap the contents of X and Y - * - * \param X First MPI value - * \param Y Second MPI value - */ -void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y ); - -/** - * \brief Safe conditional assignement X = Y if assign is 1 - * - * \param X MPI to conditionally assign to - * \param Y Value to be assigned - * \param assign 1: perform the assignment, 0: keep X's original value - * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, - * - * \note This function is equivalent to - * if( assign ) mbedtls_mpi_copy( X, Y ); - * except that it avoids leaking any information about whether - * the assignment was done or not (the above code may leak - * information through branch prediction and/or memory access - * patterns analysis). - */ -int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned char assign ); - -/** - * \brief Safe conditional swap X <-> Y if swap is 1 - * - * \param X First mbedtls_mpi value - * \param Y Second mbedtls_mpi value - * \param assign 1: perform the swap, 0: keep X and Y's original values - * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, - * - * \note This function is equivalent to - * if( assign ) mbedtls_mpi_swap( X, Y ); - * except that it avoids leaking any information about whether - * the assignment was done or not (the above code may leak - * information through branch prediction and/or memory access - * patterns analysis). - */ -int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char assign ); - -/** - * \brief Set value from integer - * - * \param X MPI to set - * \param z Value to use - * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed - */ -int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z ); - -/** - * \brief Get a specific bit from X - * - * \param X MPI to use - * \param pos Zero-based index of the bit in X - * - * \return Either a 0 or a 1 - */ -int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos ); - -/** - * \brief Set a bit of X to a specific value of 0 or 1 - * - * \note Will grow X if necessary to set a bit to 1 in a not yet - * existing limb. Will not grow if bit should be set to 0 - * - * \param X MPI to use - * \param pos Zero-based index of the bit in X - * \param val The value to set the bit to (0 or 1) - * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, - * MBEDTLS_ERR_MPI_BAD_INPUT_DATA if val is not 0 or 1 - */ -int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val ); - -/** - * \brief Return the number of zero-bits before the least significant - * '1' bit - * - * Note: Thus also the zero-based index of the least significant '1' bit - * - * \param X MPI to use - */ -size_t mbedtls_mpi_lsb( const mbedtls_mpi *X ); - -/** - * \brief Return the number of bits up to and including the most - * significant '1' bit' - * - * Note: Thus also the one-based index of the most significant '1' bit - * - * \param X MPI to use - */ -size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X ); - -/** - * \brief Return the total size in bytes - * - * \param X MPI to use - */ -size_t mbedtls_mpi_size( const mbedtls_mpi *X ); - -/** - * \brief Import from an ASCII string - * - * \param X Destination MPI - * \param radix Input numeric base - * \param s Null-terminated string buffer - * - * \return 0 if successful, or a MBEDTLS_ERR_MPI_XXX error code - */ -int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s ); - -/** - * \brief Export into an ASCII string - * - * \param X Source MPI - * \param radix Output numeric base - * \param buf Buffer to write the string to - * \param buflen Length of buf - * \param olen Length of the string written, including final NUL byte - * - * \return 0 if successful, or a MBEDTLS_ERR_MPI_XXX error code. - * *olen is always updated to reflect the amount - * of data that has (or would have) been written. - * - * \note Call this function with buflen = 0 to obtain the - * minimum required buffer size in *olen. - */ -int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix, - char *buf, size_t buflen, size_t *olen ); - -#if defined(MBEDTLS_FS_IO) -/** - * \brief Read MPI from a line in an opened file - * - * \param X Destination MPI - * \param radix Input numeric base - * \param fin Input file handle - * - * \return 0 if successful, MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if - * the file read buffer is too small or a - * MBEDTLS_ERR_MPI_XXX error code - * - * \note On success, this function advances the file stream - * to the end of the current line or to EOF. - * - * The function returns 0 on an empty line. - * - * Leading whitespaces are ignored, as is a - * '0x' prefix for radix 16. - * - */ -int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin ); - -/** - * \brief Write X into an opened file, or stdout if fout is NULL - * - * \param p Prefix, can be NULL - * \param X Source MPI - * \param radix Output numeric base - * \param fout Output file handle (can be NULL) - * - * \return 0 if successful, or a MBEDTLS_ERR_MPI_XXX error code - * - * \note Set fout == NULL to print X on the console. - */ -int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout ); -#endif /* MBEDTLS_FS_IO */ - -/** - * \brief Import X from unsigned binary data, big endian - * - * \param X Destination MPI - * \param buf Input buffer - * \param buflen Input buffer size - * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed - */ -int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen ); - -/** - * \brief Export X into unsigned binary data, big endian. - * Always fills the whole buffer, which will start with zeros - * if the number is smaller. - * - * \param X Source MPI - * \param buf Output buffer - * \param buflen Output buffer size - * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if buf isn't large enough - */ -int mbedtls_mpi_write_binary( const mbedtls_mpi *X, unsigned char *buf, size_t buflen ); - -/** - * \brief Left-shift: X <<= count - * - * \param X MPI to shift - * \param count Amount to shift - * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed - */ -int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count ); - -/** - * \brief Right-shift: X >>= count - * - * \param X MPI to shift - * \param count Amount to shift - * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed - */ -int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count ); - -/** - * \brief Compare unsigned values - * - * \param X Left-hand MPI - * \param Y Right-hand MPI - * - * \return 1 if |X| is greater than |Y|, - * -1 if |X| is lesser than |Y| or - * 0 if |X| is equal to |Y| - */ -int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y ); - -/** - * \brief Compare signed values - * - * \param X Left-hand MPI - * \param Y Right-hand MPI - * - * \return 1 if X is greater than Y, - * -1 if X is lesser than Y or - * 0 if X is equal to Y - */ -int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y ); - -/** - * \brief Compare signed values - * - * \param X Left-hand MPI - * \param z The integer value to compare to - * - * \return 1 if X is greater than z, - * -1 if X is lesser than z or - * 0 if X is equal to z - */ -int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z ); - -/** - * \brief Unsigned addition: X = |A| + |B| - * - * \param X Destination MPI - * \param A Left-hand MPI - * \param B Right-hand MPI - * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed - */ -int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ); - -/** - * \brief Unsigned subtraction: X = |A| - |B| - * - * \param X Destination MPI - * \param A Left-hand MPI - * \param B Right-hand MPI - * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_NEGATIVE_VALUE if B is greater than A - */ -int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ); - -/** - * \brief Signed addition: X = A + B - * - * \param X Destination MPI - * \param A Left-hand MPI - * \param B Right-hand MPI - * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed - */ -int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ); - -/** - * \brief Signed subtraction: X = A - B - * - * \param X Destination MPI - * \param A Left-hand MPI - * \param B Right-hand MPI - * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed - */ -int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ); - -/** - * \brief Signed addition: X = A + b - * - * \param X Destination MPI - * \param A Left-hand MPI - * \param b The integer value to add - * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed - */ -int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b ); - -/** - * \brief Signed subtraction: X = A - b - * - * \param X Destination MPI - * \param A Left-hand MPI - * \param b The integer value to subtract - * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed - */ -int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b ); - -/** - * \brief Baseline multiplication: X = A * B - * - * \param X Destination MPI - * \param A Left-hand MPI - * \param B Right-hand MPI - * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed - */ -int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ); - -/** - * \brief Baseline multiplication: X = A * b - * - * \param X Destination MPI - * \param A Left-hand MPI - * \param b The unsigned integer value to multiply with - * - * \note b is unsigned - * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed - */ -int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b ); - -/** - * \brief Division by mbedtls_mpi: A = Q * B + R - * - * \param Q Destination MPI for the quotient - * \param R Destination MPI for the rest value - * \param A Left-hand MPI - * \param B Right-hand MPI - * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, - * MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if B == 0 - * - * \note Either Q or R can be NULL. - */ -int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B ); - -/** - * \brief Division by int: A = Q * b + R - * - * \param Q Destination MPI for the quotient - * \param R Destination MPI for the rest value - * \param A Left-hand MPI - * \param b Integer to divide by - * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, - * MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if b == 0 - * - * \note Either Q or R can be NULL. - */ -int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, mbedtls_mpi_sint b ); - -/** - * \brief Modulo: R = A mod B - * - * \param R Destination MPI for the rest value - * \param A Left-hand MPI - * \param B Right-hand MPI - * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, - * MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if B == 0, - * MBEDTLS_ERR_MPI_NEGATIVE_VALUE if B < 0 - */ -int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B ); - -/** - * \brief Modulo: r = A mod b - * - * \param r Destination mbedtls_mpi_uint - * \param A Left-hand MPI - * \param b Integer to divide by - * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, - * MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if b == 0, - * MBEDTLS_ERR_MPI_NEGATIVE_VALUE if b < 0 - */ -int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b ); - -/** - * \brief Sliding-window exponentiation: X = A^E mod N - * - * \param X Destination MPI - * \param A Left-hand MPI - * \param E Exponent MPI - * \param N Modular MPI - * \param _RR Speed-up MPI used for recalculations - * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, - * MBEDTLS_ERR_MPI_BAD_INPUT_DATA if N is negative or even or - * if E is negative - * - * \note _RR is used to avoid re-computing R*R mod N across - * multiple calls, which speeds up things a bit. It can - * be set to NULL if the extra performance is unneeded. - */ -int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *E, const mbedtls_mpi *N, mbedtls_mpi *_RR ); - -/** - * \brief Fill an MPI X with size bytes of random - * - * \param X Destination MPI - * \param size Size in bytes - * \param f_rng RNG function - * \param p_rng RNG parameter - * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed - */ -int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ); - -/** - * \brief Greatest common divisor: G = gcd(A, B) - * - * \param G Destination MPI - * \param A Left-hand MPI - * \param B Right-hand MPI - * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed - */ -int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B ); - -/** - * \brief Modular inverse: X = A^-1 mod N - * - * \param X Destination MPI - * \param A Left-hand MPI - * \param N Right-hand MPI - * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, - * MBEDTLS_ERR_MPI_BAD_INPUT_DATA if N is <= 1, - MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if A has no inverse mod N. - */ -int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N ); - -/** - * \brief Miller-Rabin primality test - * - * \param X MPI to check - * \param f_rng RNG function - * \param p_rng RNG parameter - * - * \return 0 if successful (probably prime), - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, - * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if X is not prime - */ -int mbedtls_mpi_is_prime( const mbedtls_mpi *X, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ); - -/** - * \brief Prime number generation - * - * \param X Destination MPI - * \param nbits Required size of X in bits - * ( 3 <= nbits <= MBEDTLS_MPI_MAX_BITS ) - * \param dh_flag If 1, then (X-1)/2 will be prime too - * \param f_rng RNG function - * \param p_rng RNG parameter - * - * \return 0 if successful (probably prime), - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, - * MBEDTLS_ERR_MPI_BAD_INPUT_DATA if nbits is < 3 - */ -int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int dh_flag, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ); - -/** - * \brief Checkup routine - * - * \return 0 if successful, or 1 if the test failed - */ -int mbedtls_mpi_self_test( int verbose ); - -#ifdef __cplusplus -} -#endif - -#endif /* bignum.h */ diff --git a/arm9/mbedtls/bn_mul.h b/arm9/mbedtls/bn_mul.h deleted file mode 100644 index 9210dd16..00000000 --- a/arm9/mbedtls/bn_mul.h +++ /dev/null @@ -1,887 +0,0 @@ -/** - * \file bn_mul.h - * - * \brief Multi-precision integer library - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ -/* - * Multiply source vector [s] with b, add result - * to destination vector [d] and set carry c. - * - * Currently supports: - * - * . IA-32 (386+) . AMD64 / EM64T - * . IA-32 (SSE2) . Motorola 68000 - * . PowerPC, 32-bit . MicroBlaze - * . PowerPC, 64-bit . TriCore - * . SPARC v8 . ARM v3+ - * . Alpha . MIPS32 - * . C, longlong . C, generic - */ -#ifndef MBEDTLS_BN_MUL_H -#define MBEDTLS_BN_MUL_H - -#include "bignum.h" - -#if defined(MBEDTLS_HAVE_ASM) - -#ifndef asm -#define asm __asm -#endif - -/* armcc5 --gnu defines __GNUC__ but doesn't support GNU's extended asm */ -#if defined(__GNUC__) && \ - ( !defined(__ARMCC_VERSION) || __ARMCC_VERSION >= 6000000 ) -#if defined(__i386__) - -#define MULADDC_INIT \ - asm( \ - "movl %%ebx, %0 \n\t" \ - "movl %5, %%esi \n\t" \ - "movl %6, %%edi \n\t" \ - "movl %7, %%ecx \n\t" \ - "movl %8, %%ebx \n\t" - -#define MULADDC_CORE \ - "lodsl \n\t" \ - "mull %%ebx \n\t" \ - "addl %%ecx, %%eax \n\t" \ - "adcl $0, %%edx \n\t" \ - "addl (%%edi), %%eax \n\t" \ - "adcl $0, %%edx \n\t" \ - "movl %%edx, %%ecx \n\t" \ - "stosl \n\t" - -#if defined(MBEDTLS_HAVE_SSE2) - -#define MULADDC_HUIT \ - "movd %%ecx, %%mm1 \n\t" \ - "movd %%ebx, %%mm0 \n\t" \ - "movd (%%edi), %%mm3 \n\t" \ - "paddq %%mm3, %%mm1 \n\t" \ - "movd (%%esi), %%mm2 \n\t" \ - "pmuludq %%mm0, %%mm2 \n\t" \ - "movd 4(%%esi), %%mm4 \n\t" \ - "pmuludq %%mm0, %%mm4 \n\t" \ - "movd 8(%%esi), %%mm6 \n\t" \ - "pmuludq %%mm0, %%mm6 \n\t" \ - "movd 12(%%esi), %%mm7 \n\t" \ - "pmuludq %%mm0, %%mm7 \n\t" \ - "paddq %%mm2, %%mm1 \n\t" \ - "movd 4(%%edi), %%mm3 \n\t" \ - "paddq %%mm4, %%mm3 \n\t" \ - "movd 8(%%edi), %%mm5 \n\t" \ - "paddq %%mm6, %%mm5 \n\t" \ - "movd 12(%%edi), %%mm4 \n\t" \ - "paddq %%mm4, %%mm7 \n\t" \ - "movd %%mm1, (%%edi) \n\t" \ - "movd 16(%%esi), %%mm2 \n\t" \ - "pmuludq %%mm0, %%mm2 \n\t" \ - "psrlq $32, %%mm1 \n\t" \ - "movd 20(%%esi), %%mm4 \n\t" \ - "pmuludq %%mm0, %%mm4 \n\t" \ - "paddq %%mm3, %%mm1 \n\t" \ - "movd 24(%%esi), %%mm6 \n\t" \ - "pmuludq %%mm0, %%mm6 \n\t" \ - "movd %%mm1, 4(%%edi) \n\t" \ - "psrlq $32, %%mm1 \n\t" \ - "movd 28(%%esi), %%mm3 \n\t" \ - "pmuludq %%mm0, %%mm3 \n\t" \ - "paddq %%mm5, %%mm1 \n\t" \ - "movd 16(%%edi), %%mm5 \n\t" \ - "paddq %%mm5, %%mm2 \n\t" \ - "movd %%mm1, 8(%%edi) \n\t" \ - "psrlq $32, %%mm1 \n\t" \ - "paddq %%mm7, %%mm1 \n\t" \ - "movd 20(%%edi), %%mm5 \n\t" \ - "paddq %%mm5, %%mm4 \n\t" \ - "movd %%mm1, 12(%%edi) \n\t" \ - "psrlq $32, %%mm1 \n\t" \ - "paddq %%mm2, %%mm1 \n\t" \ - "movd 24(%%edi), %%mm5 \n\t" \ - "paddq %%mm5, %%mm6 \n\t" \ - "movd %%mm1, 16(%%edi) \n\t" \ - "psrlq $32, %%mm1 \n\t" \ - "paddq %%mm4, %%mm1 \n\t" \ - "movd 28(%%edi), %%mm5 \n\t" \ - "paddq %%mm5, %%mm3 \n\t" \ - "movd %%mm1, 20(%%edi) \n\t" \ - "psrlq $32, %%mm1 \n\t" \ - "paddq %%mm6, %%mm1 \n\t" \ - "movd %%mm1, 24(%%edi) \n\t" \ - "psrlq $32, %%mm1 \n\t" \ - "paddq %%mm3, %%mm1 \n\t" \ - "movd %%mm1, 28(%%edi) \n\t" \ - "addl $32, %%edi \n\t" \ - "addl $32, %%esi \n\t" \ - "psrlq $32, %%mm1 \n\t" \ - "movd %%mm1, %%ecx \n\t" - -#define MULADDC_STOP \ - "emms \n\t" \ - "movl %4, %%ebx \n\t" \ - "movl %%ecx, %1 \n\t" \ - "movl %%edi, %2 \n\t" \ - "movl %%esi, %3 \n\t" \ - : "=m" (t), "=m" (c), "=m" (d), "=m" (s) \ - : "m" (t), "m" (s), "m" (d), "m" (c), "m" (b) \ - : "eax", "ecx", "edx", "esi", "edi" \ - ); - -#else - -#define MULADDC_STOP \ - "movl %4, %%ebx \n\t" \ - "movl %%ecx, %1 \n\t" \ - "movl %%edi, %2 \n\t" \ - "movl %%esi, %3 \n\t" \ - : "=m" (t), "=m" (c), "=m" (d), "=m" (s) \ - : "m" (t), "m" (s), "m" (d), "m" (c), "m" (b) \ - : "eax", "ecx", "edx", "esi", "edi" \ - ); -#endif /* SSE2 */ -#endif /* i386 */ - -#if defined(__amd64__) || defined (__x86_64__) - -#define MULADDC_INIT \ - asm( \ - "xorq %%r8, %%r8 \n\t" - -#define MULADDC_CORE \ - "movq (%%rsi), %%rax \n\t" \ - "mulq %%rbx \n\t" \ - "addq $8, %%rsi \n\t" \ - "addq %%rcx, %%rax \n\t" \ - "movq %%r8, %%rcx \n\t" \ - "adcq $0, %%rdx \n\t" \ - "nop \n\t" \ - "addq %%rax, (%%rdi) \n\t" \ - "adcq %%rdx, %%rcx \n\t" \ - "addq $8, %%rdi \n\t" - -#define MULADDC_STOP \ - : "+c" (c), "+D" (d), "+S" (s) \ - : "b" (b) \ - : "rax", "rdx", "r8" \ - ); - -#endif /* AMD64 */ - -#if defined(__mc68020__) || defined(__mcpu32__) - -#define MULADDC_INIT \ - asm( \ - "movl %3, %%a2 \n\t" \ - "movl %4, %%a3 \n\t" \ - "movl %5, %%d3 \n\t" \ - "movl %6, %%d2 \n\t" \ - "moveq #0, %%d0 \n\t" - -#define MULADDC_CORE \ - "movel %%a2@+, %%d1 \n\t" \ - "mulul %%d2, %%d4:%%d1 \n\t" \ - "addl %%d3, %%d1 \n\t" \ - "addxl %%d0, %%d4 \n\t" \ - "moveq #0, %%d3 \n\t" \ - "addl %%d1, %%a3@+ \n\t" \ - "addxl %%d4, %%d3 \n\t" - -#define MULADDC_STOP \ - "movl %%d3, %0 \n\t" \ - "movl %%a3, %1 \n\t" \ - "movl %%a2, %2 \n\t" \ - : "=m" (c), "=m" (d), "=m" (s) \ - : "m" (s), "m" (d), "m" (c), "m" (b) \ - : "d0", "d1", "d2", "d3", "d4", "a2", "a3" \ - ); - -#define MULADDC_HUIT \ - "movel %%a2@+, %%d1 \n\t" \ - "mulul %%d2, %%d4:%%d1 \n\t" \ - "addxl %%d3, %%d1 \n\t" \ - "addxl %%d0, %%d4 \n\t" \ - "addl %%d1, %%a3@+ \n\t" \ - "movel %%a2@+, %%d1 \n\t" \ - "mulul %%d2, %%d3:%%d1 \n\t" \ - "addxl %%d4, %%d1 \n\t" \ - "addxl %%d0, %%d3 \n\t" \ - "addl %%d1, %%a3@+ \n\t" \ - "movel %%a2@+, %%d1 \n\t" \ - "mulul %%d2, %%d4:%%d1 \n\t" \ - "addxl %%d3, %%d1 \n\t" \ - "addxl %%d0, %%d4 \n\t" \ - "addl %%d1, %%a3@+ \n\t" \ - "movel %%a2@+, %%d1 \n\t" \ - "mulul %%d2, %%d3:%%d1 \n\t" \ - "addxl %%d4, %%d1 \n\t" \ - "addxl %%d0, %%d3 \n\t" \ - "addl %%d1, %%a3@+ \n\t" \ - "movel %%a2@+, %%d1 \n\t" \ - "mulul %%d2, %%d4:%%d1 \n\t" \ - "addxl %%d3, %%d1 \n\t" \ - "addxl %%d0, %%d4 \n\t" \ - "addl %%d1, %%a3@+ \n\t" \ - "movel %%a2@+, %%d1 \n\t" \ - "mulul %%d2, %%d3:%%d1 \n\t" \ - "addxl %%d4, %%d1 \n\t" \ - "addxl %%d0, %%d3 \n\t" \ - "addl %%d1, %%a3@+ \n\t" \ - "movel %%a2@+, %%d1 \n\t" \ - "mulul %%d2, %%d4:%%d1 \n\t" \ - "addxl %%d3, %%d1 \n\t" \ - "addxl %%d0, %%d4 \n\t" \ - "addl %%d1, %%a3@+ \n\t" \ - "movel %%a2@+, %%d1 \n\t" \ - "mulul %%d2, %%d3:%%d1 \n\t" \ - "addxl %%d4, %%d1 \n\t" \ - "addxl %%d0, %%d3 \n\t" \ - "addl %%d1, %%a3@+ \n\t" \ - "addxl %%d0, %%d3 \n\t" - -#endif /* MC68000 */ - -#if defined(__powerpc64__) || defined(__ppc64__) - -#if defined(__MACH__) && defined(__APPLE__) - -#define MULADDC_INIT \ - asm( \ - "ld r3, %3 \n\t" \ - "ld r4, %4 \n\t" \ - "ld r5, %5 \n\t" \ - "ld r6, %6 \n\t" \ - "addi r3, r3, -8 \n\t" \ - "addi r4, r4, -8 \n\t" \ - "addic r5, r5, 0 \n\t" - -#define MULADDC_CORE \ - "ldu r7, 8(r3) \n\t" \ - "mulld r8, r7, r6 \n\t" \ - "mulhdu r9, r7, r6 \n\t" \ - "adde r8, r8, r5 \n\t" \ - "ld r7, 8(r4) \n\t" \ - "addze r5, r9 \n\t" \ - "addc r8, r8, r7 \n\t" \ - "stdu r8, 8(r4) \n\t" - -#define MULADDC_STOP \ - "addze r5, r5 \n\t" \ - "addi r4, r4, 8 \n\t" \ - "addi r3, r3, 8 \n\t" \ - "std r5, %0 \n\t" \ - "std r4, %1 \n\t" \ - "std r3, %2 \n\t" \ - : "=m" (c), "=m" (d), "=m" (s) \ - : "m" (s), "m" (d), "m" (c), "m" (b) \ - : "r3", "r4", "r5", "r6", "r7", "r8", "r9" \ - ); - - -#else /* __MACH__ && __APPLE__ */ - -#define MULADDC_INIT \ - asm( \ - "ld %%r3, %3 \n\t" \ - "ld %%r4, %4 \n\t" \ - "ld %%r5, %5 \n\t" \ - "ld %%r6, %6 \n\t" \ - "addi %%r3, %%r3, -8 \n\t" \ - "addi %%r4, %%r4, -8 \n\t" \ - "addic %%r5, %%r5, 0 \n\t" - -#define MULADDC_CORE \ - "ldu %%r7, 8(%%r3) \n\t" \ - "mulld %%r8, %%r7, %%r6 \n\t" \ - "mulhdu %%r9, %%r7, %%r6 \n\t" \ - "adde %%r8, %%r8, %%r5 \n\t" \ - "ld %%r7, 8(%%r4) \n\t" \ - "addze %%r5, %%r9 \n\t" \ - "addc %%r8, %%r8, %%r7 \n\t" \ - "stdu %%r8, 8(%%r4) \n\t" - -#define MULADDC_STOP \ - "addze %%r5, %%r5 \n\t" \ - "addi %%r4, %%r4, 8 \n\t" \ - "addi %%r3, %%r3, 8 \n\t" \ - "std %%r5, %0 \n\t" \ - "std %%r4, %1 \n\t" \ - "std %%r3, %2 \n\t" \ - : "=m" (c), "=m" (d), "=m" (s) \ - : "m" (s), "m" (d), "m" (c), "m" (b) \ - : "r3", "r4", "r5", "r6", "r7", "r8", "r9" \ - ); - -#endif /* __MACH__ && __APPLE__ */ - -#elif defined(__powerpc__) || defined(__ppc__) /* end PPC64/begin PPC32 */ - -#if defined(__MACH__) && defined(__APPLE__) - -#define MULADDC_INIT \ - asm( \ - "lwz r3, %3 \n\t" \ - "lwz r4, %4 \n\t" \ - "lwz r5, %5 \n\t" \ - "lwz r6, %6 \n\t" \ - "addi r3, r3, -4 \n\t" \ - "addi r4, r4, -4 \n\t" \ - "addic r5, r5, 0 \n\t" - -#define MULADDC_CORE \ - "lwzu r7, 4(r3) \n\t" \ - "mullw r8, r7, r6 \n\t" \ - "mulhwu r9, r7, r6 \n\t" \ - "adde r8, r8, r5 \n\t" \ - "lwz r7, 4(r4) \n\t" \ - "addze r5, r9 \n\t" \ - "addc r8, r8, r7 \n\t" \ - "stwu r8, 4(r4) \n\t" - -#define MULADDC_STOP \ - "addze r5, r5 \n\t" \ - "addi r4, r4, 4 \n\t" \ - "addi r3, r3, 4 \n\t" \ - "stw r5, %0 \n\t" \ - "stw r4, %1 \n\t" \ - "stw r3, %2 \n\t" \ - : "=m" (c), "=m" (d), "=m" (s) \ - : "m" (s), "m" (d), "m" (c), "m" (b) \ - : "r3", "r4", "r5", "r6", "r7", "r8", "r9" \ - ); - -#else /* __MACH__ && __APPLE__ */ - -#define MULADDC_INIT \ - asm( \ - "lwz %%r3, %3 \n\t" \ - "lwz %%r4, %4 \n\t" \ - "lwz %%r5, %5 \n\t" \ - "lwz %%r6, %6 \n\t" \ - "addi %%r3, %%r3, -4 \n\t" \ - "addi %%r4, %%r4, -4 \n\t" \ - "addic %%r5, %%r5, 0 \n\t" - -#define MULADDC_CORE \ - "lwzu %%r7, 4(%%r3) \n\t" \ - "mullw %%r8, %%r7, %%r6 \n\t" \ - "mulhwu %%r9, %%r7, %%r6 \n\t" \ - "adde %%r8, %%r8, %%r5 \n\t" \ - "lwz %%r7, 4(%%r4) \n\t" \ - "addze %%r5, %%r9 \n\t" \ - "addc %%r8, %%r8, %%r7 \n\t" \ - "stwu %%r8, 4(%%r4) \n\t" - -#define MULADDC_STOP \ - "addze %%r5, %%r5 \n\t" \ - "addi %%r4, %%r4, 4 \n\t" \ - "addi %%r3, %%r3, 4 \n\t" \ - "stw %%r5, %0 \n\t" \ - "stw %%r4, %1 \n\t" \ - "stw %%r3, %2 \n\t" \ - : "=m" (c), "=m" (d), "=m" (s) \ - : "m" (s), "m" (d), "m" (c), "m" (b) \ - : "r3", "r4", "r5", "r6", "r7", "r8", "r9" \ - ); - -#endif /* __MACH__ && __APPLE__ */ - -#endif /* PPC32 */ - -/* - * The Sparc(64) assembly is reported to be broken. - * Disable it for now, until we're able to fix it. - */ -#if 0 && defined(__sparc__) -#if defined(__sparc64__) - -#define MULADDC_INIT \ - asm( \ - "ldx %3, %%o0 \n\t" \ - "ldx %4, %%o1 \n\t" \ - "ld %5, %%o2 \n\t" \ - "ld %6, %%o3 \n\t" - -#define MULADDC_CORE \ - "ld [%%o0], %%o4 \n\t" \ - "inc 4, %%o0 \n\t" \ - "ld [%%o1], %%o5 \n\t" \ - "umul %%o3, %%o4, %%o4 \n\t" \ - "addcc %%o4, %%o2, %%o4 \n\t" \ - "rd %%y, %%g1 \n\t" \ - "addx %%g1, 0, %%g1 \n\t" \ - "addcc %%o4, %%o5, %%o4 \n\t" \ - "st %%o4, [%%o1] \n\t" \ - "addx %%g1, 0, %%o2 \n\t" \ - "inc 4, %%o1 \n\t" - - #define MULADDC_STOP \ - "st %%o2, %0 \n\t" \ - "stx %%o1, %1 \n\t" \ - "stx %%o0, %2 \n\t" \ - : "=m" (c), "=m" (d), "=m" (s) \ - : "m" (s), "m" (d), "m" (c), "m" (b) \ - : "g1", "o0", "o1", "o2", "o3", "o4", \ - "o5" \ - ); - -#else /* __sparc64__ */ - -#define MULADDC_INIT \ - asm( \ - "ld %3, %%o0 \n\t" \ - "ld %4, %%o1 \n\t" \ - "ld %5, %%o2 \n\t" \ - "ld %6, %%o3 \n\t" - -#define MULADDC_CORE \ - "ld [%%o0], %%o4 \n\t" \ - "inc 4, %%o0 \n\t" \ - "ld [%%o1], %%o5 \n\t" \ - "umul %%o3, %%o4, %%o4 \n\t" \ - "addcc %%o4, %%o2, %%o4 \n\t" \ - "rd %%y, %%g1 \n\t" \ - "addx %%g1, 0, %%g1 \n\t" \ - "addcc %%o4, %%o5, %%o4 \n\t" \ - "st %%o4, [%%o1] \n\t" \ - "addx %%g1, 0, %%o2 \n\t" \ - "inc 4, %%o1 \n\t" - -#define MULADDC_STOP \ - "st %%o2, %0 \n\t" \ - "st %%o1, %1 \n\t" \ - "st %%o0, %2 \n\t" \ - : "=m" (c), "=m" (d), "=m" (s) \ - : "m" (s), "m" (d), "m" (c), "m" (b) \ - : "g1", "o0", "o1", "o2", "o3", "o4", \ - "o5" \ - ); - -#endif /* __sparc64__ */ -#endif /* __sparc__ */ - -#if defined(__microblaze__) || defined(microblaze) - -#define MULADDC_INIT \ - asm( \ - "lwi r3, %3 \n\t" \ - "lwi r4, %4 \n\t" \ - "lwi r5, %5 \n\t" \ - "lwi r6, %6 \n\t" \ - "andi r7, r6, 0xffff \n\t" \ - "bsrli r6, r6, 16 \n\t" - -#define MULADDC_CORE \ - "lhui r8, r3, 0 \n\t" \ - "addi r3, r3, 2 \n\t" \ - "lhui r9, r3, 0 \n\t" \ - "addi r3, r3, 2 \n\t" \ - "mul r10, r9, r6 \n\t" \ - "mul r11, r8, r7 \n\t" \ - "mul r12, r9, r7 \n\t" \ - "mul r13, r8, r6 \n\t" \ - "bsrli r8, r10, 16 \n\t" \ - "bsrli r9, r11, 16 \n\t" \ - "add r13, r13, r8 \n\t" \ - "add r13, r13, r9 \n\t" \ - "bslli r10, r10, 16 \n\t" \ - "bslli r11, r11, 16 \n\t" \ - "add r12, r12, r10 \n\t" \ - "addc r13, r13, r0 \n\t" \ - "add r12, r12, r11 \n\t" \ - "addc r13, r13, r0 \n\t" \ - "lwi r10, r4, 0 \n\t" \ - "add r12, r12, r10 \n\t" \ - "addc r13, r13, r0 \n\t" \ - "add r12, r12, r5 \n\t" \ - "addc r5, r13, r0 \n\t" \ - "swi r12, r4, 0 \n\t" \ - "addi r4, r4, 4 \n\t" - -#define MULADDC_STOP \ - "swi r5, %0 \n\t" \ - "swi r4, %1 \n\t" \ - "swi r3, %2 \n\t" \ - : "=m" (c), "=m" (d), "=m" (s) \ - : "m" (s), "m" (d), "m" (c), "m" (b) \ - : "r3", "r4" "r5", "r6", "r7", "r8", \ - "r9", "r10", "r11", "r12", "r13" \ - ); - -#endif /* MicroBlaze */ - -#if defined(__tricore__) - -#define MULADDC_INIT \ - asm( \ - "ld.a %%a2, %3 \n\t" \ - "ld.a %%a3, %4 \n\t" \ - "ld.w %%d4, %5 \n\t" \ - "ld.w %%d1, %6 \n\t" \ - "xor %%d5, %%d5 \n\t" - -#define MULADDC_CORE \ - "ld.w %%d0, [%%a2+] \n\t" \ - "madd.u %%e2, %%e4, %%d0, %%d1 \n\t" \ - "ld.w %%d0, [%%a3] \n\t" \ - "addx %%d2, %%d2, %%d0 \n\t" \ - "addc %%d3, %%d3, 0 \n\t" \ - "mov %%d4, %%d3 \n\t" \ - "st.w [%%a3+], %%d2 \n\t" - -#define MULADDC_STOP \ - "st.w %0, %%d4 \n\t" \ - "st.a %1, %%a3 \n\t" \ - "st.a %2, %%a2 \n\t" \ - : "=m" (c), "=m" (d), "=m" (s) \ - : "m" (s), "m" (d), "m" (c), "m" (b) \ - : "d0", "d1", "e2", "d4", "a2", "a3" \ - ); - -#endif /* TriCore */ - -/* - * gcc -O0 by default uses r7 for the frame pointer, so it complains about our - * use of r7 below, unless -fomit-frame-pointer is passed. Unfortunately, - * passing that option is not easy when building with yotta. - * - * On the other hand, -fomit-frame-pointer is implied by any -Ox options with - * x !=0, which we can detect using __OPTIMIZE__ (which is also defined by - * clang and armcc5 under the same conditions). - * - * So, only use the optimized assembly below for optimized build, which avoids - * the build error and is pretty reasonable anyway. - */ -#if defined(__GNUC__) && !defined(__OPTIMIZE__) -#define MULADDC_CANNOT_USE_R7 -#endif - -#if defined(__arm__) && !defined(MULADDC_CANNOT_USE_R7) - -#if defined(__thumb__) && !defined(__thumb2__) - -#pragma message "using ARM THUMB MULADDC" - -#define MULADDC_INIT \ - asm( \ - "ldr r0, %3 \n\t" \ - "ldr r1, %4 \n\t" \ - "ldr r2, %5 \n\t" \ - "ldr r3, %6 \n\t" \ - "lsr r7, r3, #16 \n\t" \ - "mov r9, r7 \n\t" \ - "lsl r7, r3, #16 \n\t" \ - "lsr r7, r7, #16 \n\t" \ - "mov r8, r7 \n\t" - -#define MULADDC_CORE \ - "ldmia r0!, {r6} \n\t" \ - "lsr r7, r6, #16 \n\t" \ - "lsl r6, r6, #16 \n\t" \ - "lsr r6, r6, #16 \n\t" \ - "mov r4, r8 \n\t" \ - "mul r4, r6 \n\t" \ - "mov r3, r9 \n\t" \ - "mul r6, r3 \n\t" \ - "mov r5, r9 \n\t" \ - "mul r5, r7 \n\t" \ - "mov r3, r8 \n\t" \ - "mul r7, r3 \n\t" \ - "lsr r3, r6, #16 \n\t" \ - "add r5, r5, r3 \n\t" \ - "lsr r3, r7, #16 \n\t" \ - "add r5, r5, r3 \n\t" \ - "add r4, r4, r2 \n\t" \ - "mov r2, #0 \n\t" \ - "adc r5, r2 \n\t" \ - "lsl r3, r6, #16 \n\t" \ - "add r4, r4, r3 \n\t" \ - "adc r5, r2 \n\t" \ - "lsl r3, r7, #16 \n\t" \ - "add r4, r4, r3 \n\t" \ - "adc r5, r2 \n\t" \ - "ldr r3, [r1] \n\t" \ - "add r4, r4, r3 \n\t" \ - "adc r2, r5 \n\t" \ - "stmia r1!, {r4} \n\t" - -#define MULADDC_STOP \ - "str r2, %0 \n\t" \ - "str r1, %1 \n\t" \ - "str r0, %2 \n\t" \ - : "=m" (c), "=m" (d), "=m" (s) \ - : "m" (s), "m" (d), "m" (c), "m" (b) \ - : "r0", "r1", "r2", "r3", "r4", "r5", \ - "r6", "r7", "r8", "r9", "cc" \ - ); - -#else - -#define MULADDC_INIT \ - asm( \ - "ldr r0, %3 \n\t" \ - "ldr r1, %4 \n\t" \ - "ldr r2, %5 \n\t" \ - "ldr r3, %6 \n\t" - -#define MULADDC_CORE \ - "ldr r4, [r0], #4 \n\t" \ - "mov r5, #0 \n\t" \ - "ldr r6, [r1] \n\t" \ - "umlal r2, r5, r3, r4 \n\t" \ - "adds r7, r6, r2 \n\t" \ - "adc r2, r5, #0 \n\t" \ - "str r7, [r1], #4 \n\t" - -#define MULADDC_STOP \ - "str r2, %0 \n\t" \ - "str r1, %1 \n\t" \ - "str r0, %2 \n\t" \ - : "=m" (c), "=m" (d), "=m" (s) \ - : "m" (s), "m" (d), "m" (c), "m" (b) \ - : "r0", "r1", "r2", "r3", "r4", "r5", \ - "r6", "r7", "cc" \ - ); - -#endif /* Thumb */ - -#endif /* ARMv3 */ - -#if defined(__alpha__) - -#define MULADDC_INIT \ - asm( \ - "ldq $1, %3 \n\t" \ - "ldq $2, %4 \n\t" \ - "ldq $3, %5 \n\t" \ - "ldq $4, %6 \n\t" - -#define MULADDC_CORE \ - "ldq $6, 0($1) \n\t" \ - "addq $1, 8, $1 \n\t" \ - "mulq $6, $4, $7 \n\t" \ - "umulh $6, $4, $6 \n\t" \ - "addq $7, $3, $7 \n\t" \ - "cmpult $7, $3, $3 \n\t" \ - "ldq $5, 0($2) \n\t" \ - "addq $7, $5, $7 \n\t" \ - "cmpult $7, $5, $5 \n\t" \ - "stq $7, 0($2) \n\t" \ - "addq $2, 8, $2 \n\t" \ - "addq $6, $3, $3 \n\t" \ - "addq $5, $3, $3 \n\t" - -#define MULADDC_STOP \ - "stq $3, %0 \n\t" \ - "stq $2, %1 \n\t" \ - "stq $1, %2 \n\t" \ - : "=m" (c), "=m" (d), "=m" (s) \ - : "m" (s), "m" (d), "m" (c), "m" (b) \ - : "$1", "$2", "$3", "$4", "$5", "$6", "$7" \ - ); -#endif /* Alpha */ - -#if defined(__mips__) && !defined(__mips64) - -#define MULADDC_INIT \ - asm( \ - "lw $10, %3 \n\t" \ - "lw $11, %4 \n\t" \ - "lw $12, %5 \n\t" \ - "lw $13, %6 \n\t" - -#define MULADDC_CORE \ - "lw $14, 0($10) \n\t" \ - "multu $13, $14 \n\t" \ - "addi $10, $10, 4 \n\t" \ - "mflo $14 \n\t" \ - "mfhi $9 \n\t" \ - "addu $14, $12, $14 \n\t" \ - "lw $15, 0($11) \n\t" \ - "sltu $12, $14, $12 \n\t" \ - "addu $15, $14, $15 \n\t" \ - "sltu $14, $15, $14 \n\t" \ - "addu $12, $12, $9 \n\t" \ - "sw $15, 0($11) \n\t" \ - "addu $12, $12, $14 \n\t" \ - "addi $11, $11, 4 \n\t" - -#define MULADDC_STOP \ - "sw $12, %0 \n\t" \ - "sw $11, %1 \n\t" \ - "sw $10, %2 \n\t" \ - : "=m" (c), "=m" (d), "=m" (s) \ - : "m" (s), "m" (d), "m" (c), "m" (b) \ - : "$9", "$10", "$11", "$12", "$13", "$14", "$15" \ - ); - -#endif /* MIPS */ -#endif /* GNUC */ - -#if (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__) - -#define MULADDC_INIT \ - __asm mov esi, s \ - __asm mov edi, d \ - __asm mov ecx, c \ - __asm mov ebx, b - -#define MULADDC_CORE \ - __asm lodsd \ - __asm mul ebx \ - __asm add eax, ecx \ - __asm adc edx, 0 \ - __asm add eax, [edi] \ - __asm adc edx, 0 \ - __asm mov ecx, edx \ - __asm stosd - -#if defined(MBEDTLS_HAVE_SSE2) - -#define EMIT __asm _emit - -#define MULADDC_HUIT \ - EMIT 0x0F EMIT 0x6E EMIT 0xC9 \ - EMIT 0x0F EMIT 0x6E EMIT 0xC3 \ - EMIT 0x0F EMIT 0x6E EMIT 0x1F \ - EMIT 0x0F EMIT 0xD4 EMIT 0xCB \ - EMIT 0x0F EMIT 0x6E EMIT 0x16 \ - EMIT 0x0F EMIT 0xF4 EMIT 0xD0 \ - EMIT 0x0F EMIT 0x6E EMIT 0x66 EMIT 0x04 \ - EMIT 0x0F EMIT 0xF4 EMIT 0xE0 \ - EMIT 0x0F EMIT 0x6E EMIT 0x76 EMIT 0x08 \ - EMIT 0x0F EMIT 0xF4 EMIT 0xF0 \ - EMIT 0x0F EMIT 0x6E EMIT 0x7E EMIT 0x0C \ - EMIT 0x0F EMIT 0xF4 EMIT 0xF8 \ - EMIT 0x0F EMIT 0xD4 EMIT 0xCA \ - EMIT 0x0F EMIT 0x6E EMIT 0x5F EMIT 0x04 \ - EMIT 0x0F EMIT 0xD4 EMIT 0xDC \ - EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x08 \ - EMIT 0x0F EMIT 0xD4 EMIT 0xEE \ - EMIT 0x0F EMIT 0x6E EMIT 0x67 EMIT 0x0C \ - EMIT 0x0F EMIT 0xD4 EMIT 0xFC \ - EMIT 0x0F EMIT 0x7E EMIT 0x0F \ - EMIT 0x0F EMIT 0x6E EMIT 0x56 EMIT 0x10 \ - EMIT 0x0F EMIT 0xF4 EMIT 0xD0 \ - EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ - EMIT 0x0F EMIT 0x6E EMIT 0x66 EMIT 0x14 \ - EMIT 0x0F EMIT 0xF4 EMIT 0xE0 \ - EMIT 0x0F EMIT 0xD4 EMIT 0xCB \ - EMIT 0x0F EMIT 0x6E EMIT 0x76 EMIT 0x18 \ - EMIT 0x0F EMIT 0xF4 EMIT 0xF0 \ - EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x04 \ - EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ - EMIT 0x0F EMIT 0x6E EMIT 0x5E EMIT 0x1C \ - EMIT 0x0F EMIT 0xF4 EMIT 0xD8 \ - EMIT 0x0F EMIT 0xD4 EMIT 0xCD \ - EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x10 \ - EMIT 0x0F EMIT 0xD4 EMIT 0xD5 \ - EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x08 \ - EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ - EMIT 0x0F EMIT 0xD4 EMIT 0xCF \ - EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x14 \ - EMIT 0x0F EMIT 0xD4 EMIT 0xE5 \ - EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x0C \ - EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ - EMIT 0x0F EMIT 0xD4 EMIT 0xCA \ - EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x18 \ - EMIT 0x0F EMIT 0xD4 EMIT 0xF5 \ - EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x10 \ - EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ - EMIT 0x0F EMIT 0xD4 EMIT 0xCC \ - EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x1C \ - EMIT 0x0F EMIT 0xD4 EMIT 0xDD \ - EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x14 \ - EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ - EMIT 0x0F EMIT 0xD4 EMIT 0xCE \ - EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x18 \ - EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ - EMIT 0x0F EMIT 0xD4 EMIT 0xCB \ - EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x1C \ - EMIT 0x83 EMIT 0xC7 EMIT 0x20 \ - EMIT 0x83 EMIT 0xC6 EMIT 0x20 \ - EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ - EMIT 0x0F EMIT 0x7E EMIT 0xC9 - -#define MULADDC_STOP \ - EMIT 0x0F EMIT 0x77 \ - __asm mov c, ecx \ - __asm mov d, edi \ - __asm mov s, esi \ - -#else - -#define MULADDC_STOP \ - __asm mov c, ecx \ - __asm mov d, edi \ - __asm mov s, esi \ - -#endif /* SSE2 */ -#endif /* MSVC */ - -#endif /* MBEDTLS_HAVE_ASM */ - -#if !defined(MULADDC_CORE) -#if defined(MBEDTLS_HAVE_UDBL) - -#define MULADDC_INIT \ -{ \ - mbedtls_t_udbl r; \ - mbedtls_mpi_uint r0, r1; - -#define MULADDC_CORE \ - r = *(s++) * (mbedtls_t_udbl) b; \ - r0 = (mbedtls_mpi_uint) r; \ - r1 = (mbedtls_mpi_uint)( r >> biL ); \ - r0 += c; r1 += (r0 < c); \ - r0 += *d; r1 += (r0 < *d); \ - c = r1; *(d++) = r0; - -#define MULADDC_STOP \ -} - -#else -#define MULADDC_INIT \ -{ \ - mbedtls_mpi_uint s0, s1, b0, b1; \ - mbedtls_mpi_uint r0, r1, rx, ry; \ - b0 = ( b << biH ) >> biH; \ - b1 = ( b >> biH ); - -#define MULADDC_CORE \ - s0 = ( *s << biH ) >> biH; \ - s1 = ( *s >> biH ); s++; \ - rx = s0 * b1; r0 = s0 * b0; \ - ry = s1 * b0; r1 = s1 * b1; \ - r1 += ( rx >> biH ); \ - r1 += ( ry >> biH ); \ - rx <<= biH; ry <<= biH; \ - r0 += rx; r1 += (r0 < rx); \ - r0 += ry; r1 += (r0 < ry); \ - r0 += c; r1 += (r0 < c); \ - r0 += *d; r1 += (r0 < *d); \ - c = r1; *(d++) = r0; - -#define MULADDC_STOP \ -} - -#endif /* C (generic) */ -#endif /* C (longlong) */ - -#endif /* bn_mul.h */ diff --git a/arm9/mbedtls/config.h b/arm9/mbedtls/config.h deleted file mode 100644 index e73b62c4..00000000 --- a/arm9/mbedtls/config.h +++ /dev/null @@ -1,4 +0,0 @@ - -#define MBEDTLS_BIGNUM_C - -#define MBEDTLS_HAVE_ASM diff --git a/arm9/mbedtls/readme.txt b/arm9/mbedtls/readme.txt deleted file mode 100644 index 285faa07..00000000 --- a/arm9/mbedtls/readme.txt +++ /dev/null @@ -1,7 +0,0 @@ -aes.c/.h rsa.c/.h are heavily modified/reduced - -bignum.c/.h bn_mul.h only had some minor modifications: - headers location moved from mbedtls/ to . - disabled some unused functions by "#if 0 // unused" - ASCII I/O - everything below mbedtls_mpi_exp_mod diff --git a/arm9/mbedtls/rsa.c b/arm9/mbedtls/rsa.c deleted file mode 100644 index f43cef07..00000000 --- a/arm9/mbedtls/rsa.c +++ /dev/null @@ -1,61 +0,0 @@ - -// mbedtls RSA public -// only the pubkey function for signatures verifying -// original rsa.c had too many extra functions not used and too many dependencies - -#include -#include "bignum.h" -#include "rsa.h" - -void rsa_init(rsa_context_t *ctx) { - memset(ctx, 0, sizeof(rsa_context_t)); -} - -// I don't know why mbedtls doesn't provide this -// instead, all callers set N/E/len manually -// this could be seen in mbedtls_rsa_self_test(rsa.c), main(dh_client.c) and main(rsa_verify.c) -int rsa_set_pubkey(rsa_context_t *ctx, const unsigned char * n_buf, size_t n_len, - const unsigned char * e_buf, size_t e_len) -{ - int ret0 = (mbedtls_mpi_read_binary(&ctx->N, n_buf, n_len)); - int ret1 = (mbedtls_mpi_read_binary(&ctx->E, e_buf, e_len)); - if (ret0 == 0 && ret1 == 0) { - ctx->len = (mbedtls_mpi_bitlen(&ctx->N) + 7) >> 3; - // we should check the key now to be safe? - // anyway usually we load known working keys, so it's omitted - return 0; - } else { - return ret0 || ret1; - } -} - -// basically mbedtls_rsa_public -int rsa_public(rsa_context_t *ctx, const unsigned char *input, unsigned char *output) { - int ret; - size_t olen; - mbedtls_mpi T; - - mbedtls_mpi_init(&T); - - MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&T, input, ctx->len)); - - if (mbedtls_mpi_cmp_mpi(&T, &ctx->N) >= 0) - { - ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA; - goto cleanup; - } - - olen = ctx->len; - MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&T, &T, &ctx->E, &ctx->N, &ctx->RN)); - MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&T, output, olen)); - -cleanup: - - mbedtls_mpi_free(&T); - - if (ret != 0) - return(MBEDTLS_ERR_RSA_PUBLIC_FAILED + ret); - - return(0); -} - diff --git a/arm9/mbedtls/rsa.h b/arm9/mbedtls/rsa.h deleted file mode 100644 index 136af459..00000000 --- a/arm9/mbedtls/rsa.h +++ /dev/null @@ -1,18 +0,0 @@ - -#define MBEDTLS_ERR_RSA_PUBLIC_FAILED -0x4280 /**< The public key operation failed. */ - -#include "bignum.h" - -typedef struct { - size_t len; - mbedtls_mpi N; - mbedtls_mpi E; - mbedtls_mpi RN; -} rsa_context_t; - -void rsa_init(rsa_context_t *rsa); - -int rsa_set_pubkey(rsa_context_t *rsa, const unsigned char * n_buf, size_t n_len, - const unsigned char * e_buf, size_t e_len); - -int rsa_public(rsa_context_t *rsa, const unsigned char *input, unsigned char *output); diff --git a/arm9/source/auxspi.cpp b/arm9/source/auxspi.cpp index e00e5504..e8b8f640 100644 --- a/arm9/source/auxspi.cpp +++ b/arm9/source/auxspi.cpp @@ -35,7 +35,7 @@ using std::max; #include "auxspi_core.inc" -static uint8 data[0x8000] = {0}; +static u8 data[0x8000] = {0}; #define EXTRA_ARRAY_SIZE 16 @@ -44,7 +44,7 @@ static u8 extra_size[EXTRA_ARRAY_SIZE]; // ======================================================== // local functions -uint8 jedec_table(uint32 id) +u8 jedec_table(u32 id) { switch (id) { // 256 kB @@ -75,10 +75,10 @@ uint8 jedec_table(uint32 id) }; } -uint8 type2_size(auxspi_extra extra) +u8 type2_size(auxspi_extra extra) { - static const uint32 offset0 = (8*1024-1); // 8KB - static const uint32 offset1 = (2*8*1024-1); // 16KB + static const u32 offset0 = (8*1024-1); // 8KB + static const u32 offset1 = (2*8*1024-1); // 16KB u8 buf1; // +0k data read -> write u8 buf2; // +8k data read -> read u8 buf3; // +0k ~data write @@ -96,10 +96,10 @@ uint8 type2_size(auxspi_extra extra) } // ======================================================== -uint8 auxspi_save_type(auxspi_extra extra) +u8 auxspi_save_type(auxspi_extra extra) { - uint32 jedec = auxspi_save_jedec_id(extra); // 9f - int8 sr = auxspi_save_status_register(extra); // 05 + u32 jedec = auxspi_save_jedec_id(extra); // 9f + s8 sr = auxspi_save_status_register(extra); // 05 if ((sr & 0xfd) == 0xF0 && (jedec == 0x00ffffff)) return 1; if ((sr & 0xfd) == 0x00 && (jedec == 0x00ffffff)) return 2; @@ -108,14 +108,14 @@ uint8 auxspi_save_type(auxspi_extra extra) return 0; } -uint32 auxspi_save_size(auxspi_extra extra) +u32 auxspi_save_size(auxspi_extra extra) { return 1 << auxspi_save_size_log_2(extra); } -uint8 auxspi_save_size_log_2(auxspi_extra extra) +u8 auxspi_save_size_log_2(auxspi_extra extra) { - uint8 type = auxspi_save_type(extra); + u8 type = auxspi_save_type(extra); switch (type) { case 1: return 0x09; // 512 bytes @@ -131,9 +131,9 @@ uint8 auxspi_save_size_log_2(auxspi_extra extra) } } -uint32 auxspi_save_jedec_id(auxspi_extra extra) +u32 auxspi_save_jedec_id(auxspi_extra extra) { - uint32 id = 0; + u32 id = 0; if (extra) auxspi_disable_extra(extra); @@ -147,9 +147,9 @@ uint32 auxspi_save_jedec_id(auxspi_extra extra) return id; } -uint8 auxspi_save_status_register(auxspi_extra extra) +u8 auxspi_save_status_register(auxspi_extra extra) { - uint8 sr = 0; + u8 sr = 0; if (extra) auxspi_disable_extra(extra); auxspi_open(0); @@ -159,7 +159,7 @@ uint8 auxspi_save_status_register(auxspi_extra extra) return sr; } -void auxspi_read_data(uint32 addr, uint8* buf, uint32 cnt, uint8 type, auxspi_extra extra) +void auxspi_read_data(u32 addr, u8* buf, u32 cnt, u8 type, auxspi_extra extra) { if (type == 0) type = auxspi_save_type(extra); @@ -183,14 +183,14 @@ void auxspi_read_data(uint32 addr, uint8* buf, uint32 cnt, uint8 type, auxspi_ex auxspi_close(); } -void auxspi_write_data(uint32 addr, uint8 *buf, uint32 cnt, uint8 type, auxspi_extra extra) +void auxspi_write_data(u32 addr, u8 *buf, u32 cnt, u8 type, auxspi_extra extra) { if (type == 0) type = auxspi_save_type(); if (type == 0) return; - uint32 addr_end = addr + cnt; + u32 addr_end = addr + cnt; unsigned int i; unsigned int maxblocks = 32; if(type == 1) maxblocks = 16; @@ -359,9 +359,9 @@ auxspi_extra auxspi_has_extra() void auxspi_erase(auxspi_extra extra) { - uint8 type = auxspi_save_type(extra); + u8 type = auxspi_save_type(extra); if (type == 3) { - uint32 size; + u32 size; size = 1 << (auxspi_save_size_log_2(extra) - 16); for (unsigned int i = 0; i < size; i++) { if (extra) @@ -390,7 +390,7 @@ void auxspi_erase(auxspi_extra extra) auxspi_close(); } } else { - int32 size = 1 << max(0, (auxspi_save_size_log_2(extra) - 15)); + s32 size = 1 << max(0, (auxspi_save_size_log_2(extra) - 15)); toncset(data, 0, 0x8000); for (int i = 0; i < size; i++) { auxspi_write_data(i << 15, data, 0x8000, type, extra); @@ -400,7 +400,7 @@ void auxspi_erase(auxspi_extra extra) void auxspi_erase_sector(u32 sector, auxspi_extra extra) { - uint8 type = auxspi_save_type(extra); + u8 type = auxspi_save_type(extra); if (type == 3) { if (extra) auxspi_disable_extra(extra); diff --git a/arm9/source/auxspi.h b/arm9/source/auxspi.h index 9b017c86..cfa6400b 100644 --- a/arm9/source/auxspi.h +++ b/arm9/source/auxspi.h @@ -49,13 +49,13 @@ typedef enum { } auxspi_extra; // These functions reimplement relevant parts of "card.cpp", in a way that is easier to modify. -uint8 auxspi_save_type(auxspi_extra extra = AUXSPI_DEFAULT); -uint32 auxspi_save_size(auxspi_extra extra = AUXSPI_DEFAULT); -uint8 auxspi_save_size_log_2(auxspi_extra extra = AUXSPI_DEFAULT); -uint32 auxspi_save_jedec_id(auxspi_extra extra = AUXSPI_DEFAULT); -uint8 auxspi_save_status_register(auxspi_extra extra = AUXSPI_DEFAULT); -void auxspi_read_data(uint32 addr, uint8* buf, uint32 cnt, uint8 type = 0,auxspi_extra extra = AUXSPI_DEFAULT); -void auxspi_write_data(uint32 addr, uint8 *buf, uint32 cnt, uint8 type = 0,auxspi_extra extra = AUXSPI_DEFAULT); +u8 auxspi_save_type(auxspi_extra extra = AUXSPI_DEFAULT); +u32 auxspi_save_size(auxspi_extra extra = AUXSPI_DEFAULT); +u8 auxspi_save_size_log_2(auxspi_extra extra = AUXSPI_DEFAULT); +u32 auxspi_save_jedec_id(auxspi_extra extra = AUXSPI_DEFAULT); +u8 auxspi_save_status_register(auxspi_extra extra = AUXSPI_DEFAULT); +void auxspi_read_data(u32 addr, u8* buf, u32 cnt, u8 type = 0,auxspi_extra extra = AUXSPI_DEFAULT); +void auxspi_write_data(u32 addr, u8 *buf, u32 cnt, u8 type = 0,auxspi_extra extra = AUXSPI_DEFAULT); void auxspi_erase(auxspi_extra extra = AUXSPI_DEFAULT); void auxspi_erase_sector(u32 sector, auxspi_extra extra = AUXSPI_DEFAULT); diff --git a/arm9/source/auxspi_core.inc b/arm9/source/auxspi_core.inc index 2fe0f9d9..6defdb78 100644 --- a/arm9/source/auxspi_core.inc +++ b/arm9/source/auxspi_core.inc @@ -38,7 +38,7 @@ inline void auxspi_wait_wip() do { REG_AUXSPIDATA = 0; auxspi_wait_busy(); } while (REG_AUXSPIDATA & 0x01); // WIP (Write In Progress) ? } -inline void auxspi_open(uint8 device) +inline void auxspi_open(u8 device) { REG_AUXSPICNT = 0xa040 | (device & 3); auxspi_wait_busy(); @@ -58,24 +58,24 @@ inline void auxspi_close_lite() auxspi_wait_busy(); } -inline uint8 auxspi_transfer(uint8 out) +inline u8 auxspi_transfer(u8 out) { REG_AUXSPIDATA = out; auxspi_wait_busy(); return REG_AUXSPIDATA; } -inline void auxspi_write(uint8 out) +inline void auxspi_write(u8 out) { auxspi_transfer(out); } -inline uint8 auxspi_read() +inline u8 auxspi_read() { return auxspi_transfer(0); } -inline uint16 auxspi_read_16() +inline u16 auxspi_read_16() { REG_AUXSPIDATA = 0; auxspi_wait_busy(); diff --git a/arm9/source/config.cpp b/arm9/source/config.cpp index 4bafd95d..524c2069 100644 --- a/arm9/source/config.cpp +++ b/arm9/source/config.cpp @@ -3,6 +3,7 @@ #include "driveOperations.h" #include +#include Config *config; diff --git a/arm9/source/crypto.c b/arm9/source/crypto.c deleted file mode 100644 index 312d9233..00000000 --- a/arm9/source/crypto.c +++ /dev/null @@ -1,324 +0,0 @@ -#include -#include "../mbedtls/aes.h" -#include "sha1.h" -#include "crypto.h" -//#include "ticket0.h" -#include "utils.h" - -// more info: -// https://github.com/Jimmy-Z/TWLbf/blob/master/dsi.c -// https://github.com/Jimmy-Z/bfCL/blob/master/dsi.h -// ported back to 32 bit for ARM9 - -static const uint32_t DSi_NAND_KEY_Y[4] = - {0x0ab9dc76u, 0xbd4dc4d3u, 0x202ddd1du, 0xe1a00005u}; - -static const uint32_t DSi_ES_KEY_Y[4] = - {0x8b5acce5u, 0x72c9d056u, 0xdce8179cu, 0xa9361239u}; - -static const uint32_t DSi_BOOT2_KEY[4] = - {0x8080ee98u, 0xf6b46c00u, 0x626ec23au, 0xad34ecf9u}; - -static const uint32_t DSi_KEY_MAGIC[4] = - {0x1a4f3e79u, 0x2a680f5fu, 0x29590258u, 0xfffefb4eu}; - -static inline void xor_128(uint32_t *x, const uint32_t *a, const uint32_t *b){ - x[0] = a[0] ^ b[0]; - x[1] = a[1] ^ b[1]; - x[2] = a[2] ^ b[2]; - x[3] = a[3] ^ b[3]; -} - -static inline void add_128(uint32_t *a, const uint32_t *b){ - unsigned c1, c2, c3; // carry - // round 1 - a[3] += b[3]; - a[2] += b[2]; - a[1] += b[1]; - a[0] += b[0]; - // carry - c3 = a[2] < b[2]; - c2 = a[1] < b[1]; - c1 = a[0] < b[0]; - // round 2 - a[3] += c3; - a[2] += c2; - a[1] += c1; - // carry - c3 = a[2] < c2; - c2 = a[1] < c1; - // round 3 - a[3] += c3; - a[2] += c2; - // carry - c3 = a[2] < c2; - // round 4 - a[3] += c3; -} - -static inline void add_128_32(uint32_t *a, uint32_t b){ - a[0] += b; - if(a[0] < b){ - a[1] += 1; - if (a[1] == 0) { - a[2] += 1; - if (a[2] == 0) { - a[3] += 1; - } - } - } -} - -// Answer to life, universe and everything. -static inline void rol42_128(uint32_t *a){ - uint32_t t3 = a[3], t2 = a[2]; - a[3] = (a[2] << 10) | (a[1] >> 22); - a[2] = (a[1] << 10) | (a[0] >> 22); - a[1] = (a[0] << 10) | (t3 >> 22); - a[0] = (t3 << 10) | (t2 >> 22); -} - -static void dsi_aes_set_key(uint32_t *rk, const uint32_t *console_id, key_mode_t mode) { - uint32_t key[4]; - switch (mode) { - case NAND: - key[0] = console_id[0]; - key[1] = console_id[0] ^ 0x24ee6906; - key[2] = console_id[1] ^ 0xe65b601d; - key[3] = console_id[1]; - break; - case NAND_3DS: - key[0] = (console_id[0] ^ 0xb358a6af) | 0x80000000; - key[1] = 0x544e494e; - key[2] = 0x4f444e45; - key[3] = console_id[1] ^ 0x08c267b7; - break; - case ES: - key[0] = 0x4e00004a; - key[1] = 0x4a00004e; - key[2] = console_id[1] ^ 0xc80c4b72; - key[3] = console_id[0]; - break; - default: - break; - } - // Key = ((Key_X XOR Key_Y) + FFFEFB4E295902582A680F5F1A4F3E79h) ROL 42 - // equivalent to F_XY in twltool/f_xy.c - xor_128(key, key, mode == ES ? DSi_ES_KEY_Y : DSi_NAND_KEY_Y); - // iprintf("AES KEY: XOR KEY_Y:\n"); - // print_bytes(key, 16); - add_128(key, DSi_KEY_MAGIC); - // iprintf("AES KEY: + MAGIC:\n"); - // print_bytes(key, 16); - rol42_128(key); - // iprintf("AES KEY: ROL 42:\n"); - // print_bytes(key, 16); - aes_set_key_enc_128_be(rk, (uint8_t*)key); -} - -int dsi_sha1_verify(const void *digest_verify, const void *data, unsigned len) { - uint8_t digest[SHA1_LEN]; - SHA1((char*)digest, data, len); - // return type of swiSHA1Verify() is declared void, so how exactly should we use it? - int ret = memcmp(digest, digest_verify, SHA1_LEN); - if (ret != 0) { - //printf(" "); - print_bytes(digest_verify, SHA1_LEN); - //printf("\n "); - print_bytes(digest, SHA1_LEN); - //printf("\n"); - } - return ret; -} - -static uint32_t nand_rk[RK_LEN]; -static uint32_t nand_ctr_iv[4]; -static uint32_t es_rk[RK_LEN]; -static uint32_t boot2_rk[RK_LEN]; - -static int tables_generated = 0; - -void dsi_crypt_init(const uint8_t *console_id_be, const uint8_t *emmc_cid, int is3DS) { - if (tables_generated == 0) { - aes_gen_tables(); - tables_generated = 1; - } - - uint32_t console_id[2]; - GET_UINT32_BE(console_id[0], console_id_be, 4); - GET_UINT32_BE(console_id[1], console_id_be, 0); - - dsi_aes_set_key(nand_rk, console_id, is3DS ? NAND_3DS : NAND); - dsi_aes_set_key(es_rk, console_id, ES); - - aes_set_key_enc_128_be(boot2_rk, (uint8_t*)DSi_BOOT2_KEY); - - uint32_t digest[SHA1_LEN / sizeof(uint32_t)]; - SHA1((char*)digest, (char*)emmc_cid, 16); - nand_ctr_iv[0] = digest[0]; - nand_ctr_iv[1] = digest[1]; - nand_ctr_iv[2] = digest[2]; - nand_ctr_iv[3] = digest[3]; -} - -static inline void aes_ctr(const uint32_t *rk, const uint32_t *ctr, uint32_t *in, uint32_t *out) { - uint32_t xor[4]; - aes_encrypt_128_be(rk, (uint8_t*)ctr, (uint8_t*)xor); - xor_128(out, in, xor); -} - -// crypt one block, in/out must be aligned to 32 bit(restriction induced by xor_128) -// offset as block offset, block as AES block -void dsi_nand_crypt_1(uint8_t* out, const uint8_t* in, uint32_t offset) { - uint32_t ctr[4] = { nand_ctr_iv[0], nand_ctr_iv[1], nand_ctr_iv[2], nand_ctr_iv[3] }; - add_128_32(ctr, offset); - // iprintf("AES CTR:\n"); - // print_bytes(buf, 16); - aes_ctr(nand_rk, ctr, (uint32_t*)in, (uint32_t*)out); -} - -void dsi_nand_crypt(uint8_t* out, const uint8_t* in, uint32_t offset, unsigned count) { - uint32_t ctr[4] = { nand_ctr_iv[0], nand_ctr_iv[1], nand_ctr_iv[2], nand_ctr_iv[3] }; - add_128_32(ctr, offset); - for (unsigned i = 0; i < count; ++i) { - aes_ctr(nand_rk, ctr, (uint32_t*)in, (uint32_t*)out); - out += AES_BLOCK_SIZE; - in += AES_BLOCK_SIZE; - add_128_32(ctr, 1); - } -} - -static uint32_t boot2_ctr[4]; - -void dsi_boot2_crypt_set_ctr(uint32_t size_r) { - boot2_ctr[0] = size_r; - boot2_ctr[1] = -size_r; - boot2_ctr[2] = ~size_r; - boot2_ctr[3] = 0; -} - -void dsi_boot2_crypt(uint8_t* out, const uint8_t* in, unsigned count) { - for (unsigned i = 0; i < count; ++i) { - aes_ctr(boot2_rk, boot2_ctr, (uint32_t*)in, (uint32_t*)out); - out += AES_BLOCK_SIZE; - in += AES_BLOCK_SIZE; - add_128_32(boot2_ctr, 1); - } -} - -// http://problemkaputt.de/gbatek.htm#dsiesblockencryption -// works in place, also must be aligned to 32 bit -// why is it called ES? -/*int dsi_es_block_crypt(uint8_t *buf, unsigned buf_len, crypt_mode_t mode) { - es_block_footer_t *footer; - footer = (es_block_footer_t*)(buf + buf_len - sizeof(es_block_footer_t)); - // backup mac since it might be overwritten by padding - // and also nonce, it becomes garbage after decryption - uint8_t ccm_mac[AES_CCM_MAC_LEN]; - uint8_t nonce[AES_CCM_NONCE_LEN]; - memcpy(ccm_mac, footer->ccm_mac, AES_CCM_MAC_LEN); - memcpy(nonce, footer->nonce, AES_CCM_NONCE_LEN); - - uint32_t ctr32[4], pad32[4], mac32[4]; -// I'm too paranoid to use more stack variables -#define ctr ((uint8_t*)ctr32) -#define pad ((uint8_t*)pad32) -#define mac ((uint8_t*)mac32) -#define zero(a) static_assert(sizeof(a[0]) == 4, "invalid operand"); \ - a[0] = 0; a[1] = 0; a[2] = 0; a[3] = 0 - if (mode == DECRYPT) { - // decrypt footer - zero(ctr32); - memcpy(ctr + 1, nonce, AES_CCM_NONCE_LEN); - // footer might not be 32 bit aligned after all, so we copy it out to decrypt - memcpy(pad, footer->encrypted, AES_BLOCK_SIZE); - aes_ctr(es_rk, ctr32, pad32, pad32); - memcpy(footer->encrypted, pad, AES_BLOCK_SIZE); - } - // check decrypted footer - if (footer->fixed_3a != 0x3a) { - i//printff("ES block footer offset 0x10 should be 0x3a, got 0x%02x\n", footer->fixed_3a); - return 1; - } - uint32_t block_size; - GET_UINT32_BE(block_size, footer->len32be, 0); - block_size &= 0xffffff; - if (block_size + sizeof(es_block_footer_t) != buf_len) { - i//printff("block size in footer doesn't match, %06x != %06x\n", - (unsigned)block_size, (unsigned)(buf_len - sizeof(es_block_footer_t))); - return 1; - } - // padding to multiple of 16 - uint32_t remainder = block_size & 0xf; - if (remainder != 0) { - zero(pad32); - if (mode == DECRYPT) { - ctr32[0] = (block_size >> 4) + 1; - memcpy(ctr + 3, nonce, AES_CCM_NONCE_LEN); - ctr[0xf] = 2; - aes_ctr(es_rk, ctr32, pad32, pad32); - } - memcpy(buf + block_size, pad + remainder, 16 - remainder); - block_size += 16 - remainder; - } - // AES-CCM MAC - mac32[0] = block_size; - memcpy(mac + 3, nonce, AES_CCM_NONCE_LEN); - mac[0xf] = 0x3a; - aes_encrypt_128_be(es_rk, mac, mac); - // AES-CCM CTR - ctr32[0] = 0; - memcpy(ctr + 3, nonce, AES_CCM_NONCE_LEN); - ctr[0xf] = 2; - // AES-CCM start - zero(pad32); - aes_ctr(es_rk, ctr32, pad32, pad32); - add_128_32(ctr32, 1); - // AES-CCM loop - if (mode == DECRYPT) { - for (unsigned i = 0; i < block_size; i += 16) { - aes_ctr(es_rk, ctr32, (uint32_t*)(buf + i), (uint32_t*)(buf + i)); - add_128_32(ctr32, 1); - xor_128(mac32, mac32, (uint32_t*)(buf + i)); - aes_encrypt_128_be(es_rk, mac, mac); - } - } else { - for (unsigned i = 0; i < block_size; i += 16) { - xor_128(mac32, mac32, (uint32_t*)(buf + i)); - aes_encrypt_128_be(es_rk, mac, mac); - aes_ctr(es_rk, ctr32, (uint32_t*)(buf + i), (uint32_t*)(buf + i)); - add_128_32(ctr32, 1); - } - } - // AES-CCM MAC final - xor_128(mac32, mac32, pad32); - if (mode == DECRYPT) { - if (memcmp(mac, ccm_mac, 16) == 0) { - if (remainder != 0) { - // restore mac - memcpy(footer->ccm_mac, ccm_mac, AES_CCM_MAC_LEN); - } - // restore nonce - memcpy(footer->nonce, nonce, AES_CCM_NONCE_LEN); - return 0; - } else { - //printf("MAC verification failed\n"); - return 1; - } - } else { - memcpy(footer->ccm_mac, mac, AES_CCM_MAC_LEN); - // AES-CTR crypt later half of footer - zero(ctr32); - memcpy(ctr + 1, nonce, AES_CCM_NONCE_LEN); - memcpy(pad, footer->encrypted, AES_BLOCK_SIZE); - aes_ctr(es_rk, ctr32, pad32, pad32); - memcpy(footer->encrypted, pad, AES_BLOCK_SIZE); - // restore nonce - memcpy(footer->nonce, nonce, AES_CCM_NONCE_LEN); - return 0; - } -#undef ctr -#undef pad -#undef mac -#undef zero -}*/ diff --git a/arm9/source/crypto.h b/arm9/source/crypto.h deleted file mode 100644 index bfd9516b..00000000 --- a/arm9/source/crypto.h +++ /dev/null @@ -1,32 +0,0 @@ -#pragma once - -#include - -#define SHA1_LEN 20 - -#define AES_BLOCK_SIZE 16 - -typedef enum { - ENCRYPT, - DECRYPT -} crypt_mode_t; - -typedef enum { - NAND, - NAND_3DS, - ES -} key_mode_t; - -int dsi_sha1_verify(const void *digest_verify, const void *data, unsigned len); - -void dsi_crypt_init(const uint8_t *console_id_be, const uint8_t *emmc_cid, int is3DS); - -void dsi_nand_crypt_1(uint8_t *out, const uint8_t* in, u32 offset); - -void dsi_nand_crypt(uint8_t *out, const uint8_t* in, u32 offset, unsigned count); - -int dsi_es_block_crypt(uint8_t *buf, unsigned buf_len, crypt_mode_t mode); - -void dsi_boot2_crypt_set_ctr(uint32_t size_r); - -void dsi_boot2_crypt(uint8_t* out, const uint8_t* in, unsigned count); diff --git a/arm9/source/driveMenu.cpp b/arm9/source/driveMenu.cpp index 78b5e352..58263619 100644 --- a/arm9/source/driveMenu.cpp +++ b/arm9/source/driveMenu.cpp @@ -27,9 +27,11 @@ #include #include +#include "calico/nds/pm.h" #include "main.h" #include "config.h" #include "date.h" +#include "nds/system.h" #include "screenshot.h" #include "dumpOperations.h" #include "driveOperations.h" @@ -150,7 +152,7 @@ void dm_drawBottomScreen(void) { font->print(firstCol, row--, false, STR_START_START_MENU, alignStart); - if ((isDSiMode() && memcmp(io_dldi_data->friendlyName, "Default", 7) == 0) || sdMountedDone) { + if ((isDSiMode() && memcmp(dldiInterface.iface_name, "Default", 7) == 0) || sdMountedDone) { font->print(firstCol, row--, false, sdMounted ? STR_UNMOUNT_SDCARD : STR_REMOUNT_SDCARD, alignStart); } else if(flashcardMounted) { font->print(firstCol, row--, false, STR_UNMOUNT_FLASHCARD, alignStart); @@ -221,7 +223,7 @@ void driveMenu (void) { int pressed = 0; int held = 0; - while (true) { + while (pmMainLoop()) { if (!isDSiMode() && isRegularDS) { gbaFixedValue = *(u8*)(0x080000B2); } @@ -264,10 +266,10 @@ void driveMenu (void) { romTitle[1][0] = 0; romSize[1] = 0; } - if (((io_dldi_data->ioInterface.features & FEATURE_SLOT_GBA) || (isRegularDS && !flashcardMounted && romTitle[1][0] != 0)) + if ((dldiInterface.disc.features & FEATURE_SLOT_GBA || (isRegularDS && !flashcardMounted && romTitle[1][0] != 0)) || (isDSiMode() && !arm7SCFGLocked && !(REG_SCFG_MC & BIT(0)))) { dmOperations.push_back(DriveMenuOperation::ndsCard); - if(romTitle[0][0] == 0 && ((io_dldi_data->ioInterface.features & FEATURE_SLOT_GBA) || !flashcardMounted) && !isRegularDS) { + if(romTitle[0][0] == 0 && ((dldiInterface.disc.features & FEATURE_SLOT_GBA) || !flashcardMounted) && !isRegularDS) { sNDSHeaderExt ndsHeader; cardInit(&ndsHeader); tonccpy(romTitle[0], ndsHeader.gameTitle, 12); @@ -316,7 +318,7 @@ void driveMenu (void) { break; } } - } while (!(pressed & (KEY_UP | KEY_DOWN | KEY_LEFT | KEY_RIGHT | KEY_A | KEY_B | KEY_X | KEY_L | KEY_START | config->screenSwapKey()))); + } while (pmMainLoop() && !(pressed & (KEY_UP | KEY_DOWN | KEY_LEFT | KEY_RIGHT | KEY_A | KEY_B | KEY_X | KEY_L | KEY_START | config->screenSwapKey()))); if(dmOperations.size() != 0) { if (pressed & KEY_UP) { @@ -378,7 +380,7 @@ void driveMenu (void) { break; } else if (dmOperations[dmCursorPosition] == DriveMenuOperation::sysNandPhoto && photoMounted) { currentDrive = Drive::nandPhoto; - chdir("photo:/"); + chdir("nand2:/"); screenMode = 1; break; } else if (dmOperations[dmCursorPosition] == DriveMenuOperation::fatImage && imgMounted) { @@ -411,13 +413,14 @@ void driveMenu (void) { // Unmount/Remount SD card if ((held & KEY_R) && (pressed & KEY_B)) { - if ((isDSiMode() && memcmp(io_dldi_data->friendlyName, "Default", 7) == 0) || sdMountedDone) { + if ((isDSiMode() && memcmp(dldiInterface.iface_name, "Default", 7) == 0) || sdMountedDone) { if (sdMounted) { currentDrive = Drive::sdCard; chdir("sd:/"); sdUnmount(); } else if(!sdRemoved) { - sdMounted = sdMount(); + // TODO + // sdMounted = sdMount(); } } else { if (flashcardMounted) { diff --git a/arm9/source/driveOperations.cpp b/arm9/source/driveOperations.cpp index a082f496..86fc6a15 100644 --- a/arm9/source/driveOperations.cpp +++ b/arm9/source/driveOperations.cpp @@ -8,17 +8,19 @@ #include #include #include +#include +#include "calico/dev/dldi.h" +#include "calico/dev/dldi_defs.h" #include "main.h" #include "dldi-include.h" #include "lzss.h" +#include "nds/dldi.h" #include "ramd.h" #include "my_sd.h" -#include "nandio.h" #include "imgio.h" #include "tonccpy.h" #include "language.h" -#include "sector0.h" #include "io_m3_common.h" #include "io_g6_common.h" @@ -28,17 +30,21 @@ static sNDSHeader nds; -static bool slot1Enabled = true; +// TODO: Update for calico +// static bool slot1Enabled = true; bool nandMounted = false; bool photoMounted = false; bool sdMounted = false; bool sdMountedDone = false; // true if SD mount is successful once bool flashcardMounted = false; +bool flashcardIsSlot2 = false; bool ramdriveMounted = false; bool imgMounted = false; bool nitroMounted = false; +DLDI_INTERFACE dldiInterface; + Drive currentDrive = Drive::sdCard; Drive nitroCurrentDrive = Drive::sdCard; Drive imgCurrentDrive = Drive::sdCard; @@ -54,6 +60,8 @@ u64 fatSize = 0; u64 imgSize = 0; u32 ramdSize = 0; +extern unsigned g_dvmCalicoNandMount; + const char* getDrivePath(void) { switch (currentDrive) { case Drive::sdCard: @@ -65,7 +73,7 @@ const char* getDrivePath(void) { case Drive::nand: return "nand:/"; case Drive::nandPhoto: - return "photo:/"; + return "nand2:/"; case Drive::nitroFS: return "nitro:/"; case Drive::fatImg: @@ -84,7 +92,7 @@ Drive getDriveFromPath(const char *path) { return Drive::ramDrive; } else if(strncmp(path, "nand:", 5)) { return Drive::nand; - } else if(strncmp(path, "photo:", 6)) { + } else if(strncmp(path, "nand2:", 6)) { return Drive::nandPhoto; } else if(strncmp(path, "nitro:", 6)) { return Drive::nitroFS; @@ -109,7 +117,7 @@ bool nandFound(void) { } bool photoFound(void) { - return (access("photo:/", F_OK) == 0); + return (access("nand2:/", F_OK) == 0); } bool sdFound(void) { @@ -132,6 +140,7 @@ bool imgFound(void) { return (access("img:/", F_OK) == 0); } +/* TODO: Update for calico bool nandMount(void) { fatMountSimple("nand", &io_dsi_nand); if (nandFound()) { @@ -142,19 +151,20 @@ bool nandMount(void) { } // Photo partition - /* mbr_t mbr; - io_dsi_nand.readSectors(0, 1, &mbr); - fatMount("photo", &io_dsi_nand, mbr.partitions[1].offset, 16, 8); - - if (photoFound() && statvfs("photo:/", &st) == 0) { - photoSize = st.f_bsize * st.f_blocks; - photoMounted = true; - } */ + // mbr_t mbr; + // io_dsi_nand.readSectors(0, 1, &mbr); + // fatMount("photo", &io_dsi_nand, mbr.partitions[1].offset, 16, 8); + + // if (photoFound() && statvfs("nand2:/", &st) == 0) { + // photoSize = st.f_bsize * st.f_blocks; + // photoMounted = true; + // } } - return nandMounted /*&& photoMounted*/; + return nandMounted && photoMounted; } +*/ void nandUnmount(void) { if(nandMounted) @@ -165,8 +175,9 @@ void nandUnmount(void) { nandMounted = false; } +/* TODO: Update for calico bool sdMount(void) { - fatMountSimple("sd", __my_io_dsisd()); + fatMountSimple("sd", ); if (sdFound()) { sdMountedDone = true; fatGetVolumeLabel("sd", sdLabel); @@ -179,6 +190,7 @@ bool sdMount(void) { } return false; } +*/ u64 getBytesFree(const char* drivePath) { struct statvfs st; @@ -186,6 +198,7 @@ u64 getBytesFree(const char* drivePath) { return (u64)st.f_bsize * (u64)st.f_bavail; } +/**/ void sdUnmount(void) { if(imgMounted && imgCurrentDrive == Drive::sdCard) imgUnmount(); @@ -193,12 +206,12 @@ void sdUnmount(void) { nitroUnmount(); fatUnmount("sd"); - my_sdio_Shutdown(); sdLabel[0] = '\0'; sdSize = 0; sdMounted = false; } +/* TODO: Update for calico typedef signed int addr_t; typedef unsigned char data_t; @@ -378,9 +391,10 @@ TWL_CODE void dldiLoadFromLzss (const u8 dldiLzss[], const u32 len) { dldiRelocateBinary ((data_t*)dldiAddr, dldiSize); delete[] dldiAddr; } +*/ TWL_CODE bool UpdateCardInfo(char* gameid, char* gamename) { - cardReadHeader((uint8*)0x02000000); + cardReadHeader((u8*)0x02000000); tonccpy(&nds, (void*)0x02000000, sizeof(sNDSHeader)); tonccpy(gameid, &nds.gameCode, 4); gameid[4] = 0x00; @@ -389,6 +403,7 @@ TWL_CODE bool UpdateCardInfo(char* gameid, char* gamename) { return true; } +/* TODO: Update for calico const DISC_INTERFACE *dldiGet(void) { if(io_dldi_data->ioInterface.features & FEATURE_SLOT_GBA) sysSetCartOwner(BUS_OWNER_ARM9); @@ -447,10 +462,10 @@ TWL_CODE bool twl_flashcardMount(void) { } else if (!memcmp(gameid, "DSGB", 4)) { dldiLoadFromLzss(nrio_lz77, 0x30DD); fatMountSimple("fat", dldiGet()); - } /* else if (!memcmp(gameid, "ALXX", 4)) { // SuperCard DSTWO - dldiLoadFromBin(dstwo_dldi); - fatMountSimple("fat", dldiGet()); - } */ + } // else if (!memcmp(gameid, "ALXX", 4)) { // SuperCard DSTWO + // dldiLoadFromBin(dstwo_dldi); + // fatMountSimple("fat", dldiGet()); + // } if (flashcardFound()) { fatGetVolumeLabel("fat", fatLabel); @@ -464,23 +479,31 @@ TWL_CODE bool twl_flashcardMount(void) { } return false; } +*/ bool flashcardMount(void) { + flashcardIsSlot2 = false; if (!isDSiMode() || (arm7SCFGLocked && !sdMountedDone)) { fatInitDefault(); if (flashcardFound()) { - fatGetVolumeLabel("fat", fatLabel); + // TODO + // fatGetVolumeLabel("fat", fatLabel); fixLabel(fatLabel); struct statvfs st; if (statvfs("fat:/", &st) == 0) { fatSize = st.f_bsize * st.f_blocks; } + + // Load the current DLDI to a buffer for easy access + dldiDumpInternal(&dldiInterface); + return true; } - return false; - } else { - return twl_flashcardMount(); - } + } // else { + // return twl_flashcardMount(); + // } + + return false; } void flashcardUnmount(void) { @@ -586,7 +609,8 @@ bool imgMount(const char* imgName, bool dsiwareSave) { strcpy(currentImgName, imgName); fatMountSimple("img", dsiwareSave ? &io_dsiware_save : &io_img); if (imgFound()) { - fatGetVolumeLabel("img", imgLabel); + // TODO + // fatGetVolumeLabel("img", imgLabel); fixLabel(imgLabel); struct statvfs st; if (statvfs("img:/", &st) == 0) { @@ -611,14 +635,17 @@ void imgUnmount(void) { bool driveWritable(Drive drive) { switch(drive) { case Drive::sdCard: - return __my_io_dsisd()->features & FEATURE_MEDIUM_CANWRITE; + // TODO: Update for calico + // return __my_io_dsisd()->features & FEATURE_MEDIUM_CANWRITE; + return true; case Drive::flashcard: - return dldiGet()->features & FEATURE_MEDIUM_CANWRITE; + return dldiInterface.disc.features & FEATURE_MEDIUM_CANWRITE; case Drive::ramDrive: return io_ram_drive.features & FEATURE_MEDIUM_CANWRITE; case Drive::nand: case Drive::nandPhoto: - return io_dsi_nand.features & FEATURE_MEDIUM_CANWRITE; + // TODO: Update properly + return g_dvmCalicoNandMount >= 2; case Drive::nitroFS: return false; case Drive::fatImg: @@ -660,7 +687,7 @@ u64 driveSizeFree(Drive drive) { case Drive::nand: return getBytesFree("nand:/"); case Drive::nandPhoto: - return getBytesFree("photo:/"); + return getBytesFree("nand2:/"); case Drive::nitroFS: return 0; case Drive::fatImg: diff --git a/arm9/source/driveOperations.h b/arm9/source/driveOperations.h index 8299afd6..1f4d4190 100644 --- a/arm9/source/driveOperations.h +++ b/arm9/source/driveOperations.h @@ -1,6 +1,7 @@ #ifndef FLASHCARD_H #define FLASHCARD_H +#include "nds/dldi.h" #include #include @@ -23,6 +24,8 @@ extern bool ramdriveMounted; extern bool imgMounted; extern bool nitroMounted; +extern DLDI_INTERFACE dldiInterface; + extern Drive currentDrive; extern Drive nitroCurrentDrive; extern Drive imgCurrentDrive; @@ -47,9 +50,9 @@ extern bool sdFound(void); extern bool flashcardFound(void); extern bool bothSDandFlashcard(void); extern bool imgFound(void); -extern bool nandMount(void); +// extern bool nandMount(void); extern void nandUnmount(void); -extern bool sdMount(void); +// extern bool sdMount(void); extern void sdUnmount(void); extern bool flashcardMount(void); extern void flashcardUnmount(void); diff --git a/arm9/source/dumpOperations.cpp b/arm9/source/dumpOperations.cpp index f2f944fc..abec8df8 100644 --- a/arm9/source/dumpOperations.cpp +++ b/arm9/source/dumpOperations.cpp @@ -55,7 +55,7 @@ DumpOption dumpMenu(std::vector allowedOptions, const char *dumpName int y = font->calcHeight(dumpToStr) + 1; - while (true) { + while (pmMainLoop()) { font->clear(false); font->print(firstCol, 0, false, dumpToStr, alignStart); @@ -110,7 +110,7 @@ DumpOption dumpMenu(std::vector allowedOptions, const char *dumpName pressed = keysDownRepeat(); held = keysHeld(); swiWaitForVBlank(); - } while (!(pressed & (KEY_UP| KEY_DOWN | KEY_A | KEY_B | KEY_L))); + } while (pmMainLoop() && !(pressed & (KEY_UP| KEY_DOWN | KEY_A | KEY_B | KEY_L))); if (pressed & KEY_UP) optionOffset--; @@ -149,7 +149,7 @@ void dumpFailMsg(std::string_view msg) { scanKeys(); pressed = keysDown(); swiWaitForVBlank(); - } while (!(pressed & KEY_A)); + } while (pmMainLoop() && !(pressed & KEY_A)); } //--------------------------------------------------------------------------------- @@ -172,7 +172,7 @@ int cardEepromGetTypeFixed(void) { // https://github.com/devkitPro/libnds/blob/master/source/common/cardEeprom.c#L88 // with type 2 fixed if the first word and another % 8192 location are 0x00000000 // and type 3 with ID 0xC22017 added -uint32 cardEepromGetSizeFixed() { +u32 cardEepromGetSizeFixed() { //--------------------------------------------------------------------------------- int type = cardEepromGetTypeFixed(); @@ -193,7 +193,7 @@ uint32 cardEepromGetSizeFixed() { // Loop until the EEPROM mirrors and the first word shows up again int size = 8192; - while (1) { + while (pmMainLoop()) { cardReadEeprom(size,(u8*)&buf2,4,type); // Check if it matches, if so check again with another value to ensure no false positives if (buf2 == buf3) { @@ -331,7 +331,7 @@ bool writeToGbaSave(const char* fileName, u8* buffer, u32 size) { swiWaitForVBlank(); scanKeys(); pressed = keysDownRepeat(); - } while (!(pressed & (KEY_A | KEY_B)) && *(u8*)(0x080000B2) == 0x96); + } while (pmMainLoop() && !(pressed & (KEY_A | KEY_B)) && *(u8*)(0x080000B2) == 0x96); if(pressed & KEY_A) { font->clear(false); @@ -560,7 +560,7 @@ void ndsCardSaveDump(const char* filename) { } void ndsCardSaveRestore(const char *filename) { - bool usingFlashcard = (io_dldi_data->ioInterface.features & FEATURE_SLOT_NDS) && flashcardMounted; + bool usingFlashcard = (dldiInterface.disc.features & FEATURE_SLOT_NDS) && flashcardMounted; font->clear(false); font->print(firstCol, 0, false, (usingFlashcard ? STR_RESTORE_SELECTED_SAVE_CARD_FLASHCARD : STR_RESTORE_SELECTED_SAVE_CARD) + "\n\n" + STR_A_YES_B_NO, alignStart); @@ -572,7 +572,7 @@ void ndsCardSaveRestore(const char *filename) { scanKeys(); pressed = keysDown(); swiWaitForVBlank(); - } while (!(pressed & (KEY_A | KEY_B))); + } while (pmMainLoop() && !(pressed & (KEY_A | KEY_B))); if(pressed & KEY_A) { int type = cardEepromGetTypeFixed(); @@ -654,7 +654,7 @@ void ndsCardSaveRestore(const char *filename) { scanKeys(); pressed = keysDown(); swiWaitForVBlank(); - } while (!(pressed & KEY_A)); + } while (pmMainLoop() && !(pressed & KEY_A)); type = cardEepromGetTypeFixed(); } @@ -765,12 +765,12 @@ void ndsCardDump(void) { u16 pressed; font->clear(false); - if ((io_dldi_data->ioInterface.features & FEATURE_SLOT_NDS) && flashcardMounted) { + if ((dldiInterface.disc.features & FEATURE_SLOT_NDS) && flashcardMounted) { font->print(firstCol, 0, false, STR_FLASHCARD_WILL_UNMOUNT, alignStart); font->print(firstCol, 3, false, STR_A_YES_B_NO, alignStart); font->update(false); - while (true) { + while (pmMainLoop()) { scanKeys(); pressed = keysDownRepeat(); swiWaitForVBlank(); @@ -1005,7 +1005,7 @@ void gbaCartSaveRestore(const char *filename) { scanKeys(); pressed = keysDownRepeat(); swiWaitForVBlank(); - } while (!(pressed & (KEY_A | KEY_B))); + } while (pmMainLoop() && !(pressed & (KEY_A | KEY_B))); if (pressed & KEY_A) { saveTypeGBA type = gbaGetSaveType(); diff --git a/arm9/source/f_xy.c b/arm9/source/f_xy.c deleted file mode 100644 index d6cddd3a..00000000 --- a/arm9/source/f_xy.c +++ /dev/null @@ -1,92 +0,0 @@ -#include -#include -#include -#include -#include "tonccpy.h" - -//#define DEBUG - - -void n128_lrot(uint64_t *num, uint32_t shift) -{ - uint64_t tmp[2]; - - tmp[0] = num[0]<>(64-shift)); - tmp[1] |= (num[0]>>(64-shift)); - - num[0] = tmp[0]; - num[1] = tmp[1]; -} -void n128_rrot(uint64_t *num, uint32_t shift) -{ - uint64_t tmp[2]; - - tmp[0] = num[0]>>shift; - tmp[1] = num[1]>>shift; - tmp[0] |= (num[1]<<(64-shift)); - tmp[1] |= (num[0]<<(64-shift)); - - num[0] = tmp[0]; - num[1] = tmp[1]; -} - -void n128_add(uint64_t *a, uint64_t *b) -{ - uint64_t *a64 = a; - uint64_t *b64 = b; - uint64_t tmp = (a64[0]>>1)+(b64[0]>>1) + (a64[0] & b64[0] & 1); - - tmp = tmp >> 63; - a64[0] = a64[0] + b64[0]; - a64[1] = a64[1] + b64[1] + tmp; -} - -void n128_sub(uint64_t *a, uint64_t *b) -{ - uint64_t *a64 = a; - uint64_t *b64 = b; - uint64_t tmp = (a64[0]>>1)-(b64[0]>>1) - ((a64[0]>>63) & (b64[0]>>63) & 1); - - tmp = tmp >> 63; - a64[0] = a64[0] - b64[0]; - a64[1] = a64[1] - b64[1] - tmp; -} - -void F_XY(uint32_t *key, uint32_t *key_x, uint32_t *key_y) -{ - int i; - unsigned char key_xy[16]; - - toncset(key_xy, 0, 16); - toncset(key, 0, 16); - for(i=0; i<16; i++)key_xy[i] = ((unsigned char*)key_x)[i] ^ ((unsigned char*)key_y)[i]; - - key[0] = 0x1a4f3e79; - key[1] = 0x2a680f5f; - key[2] = 0x29590258; - key[3] = 0xfffefb4e; - - n128_add((uint64_t*)key, (uint64_t*)key_xy); - n128_lrot((uint64_t*)key, 42); -} - -//F_XY_reverse does the reverse of F(X^Y): takes (normal)key, and does F in reverse to generate the original X^Y key_xy. -void F_XY_reverse(uint32_t *key, uint32_t *key_xy) -{ - uint32_t tmpkey[4]; - toncset(key_xy, 0, 16); - toncset(tmpkey, 0, 16); - tonccpy(tmpkey, key, 16); - - key_xy[0] = 0x1a4f3e79; - key_xy[1] = 0x2a680f5f; - key_xy[2] = 0x29590258; - key_xy[3] = 0xfffefb4e; - - n128_rrot((uint64_t*)tmpkey, 42); - n128_sub((uint64_t*)tmpkey, (uint64_t*)key_xy); - tonccpy(key_xy, tmpkey, 16); -} - diff --git a/arm9/source/f_xy.h b/arm9/source/f_xy.h deleted file mode 100644 index c5485a98..00000000 --- a/arm9/source/f_xy.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef _H_F_XY -#define _H_F_XY - -#ifdef __cplusplus -extern "C" { -#endif - -void F_XY(uint32_t *key, uint32_t *key_x, uint32_t *key_y); -void F_XY_reverse(uint32_t *key, uint32_t *key_xy); - -#ifdef __cplusplus -} -#endif - -#endif - diff --git a/arm9/source/fileOperations.cpp b/arm9/source/fileOperations.cpp index 1d708a41..2f741c7a 100644 --- a/arm9/source/fileOperations.cpp +++ b/arm9/source/fileOperations.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include "sha1.h" @@ -102,7 +103,7 @@ bool calculateSHA1(const char *fileName, u8 *sha1) { font->print(0, nameHeight + 5, false, "["); font->print(-1, nameHeight + 5, false, "]"); - while (true) { + while (pmMainLoop()) { size_t ret = fread(buf, 1, shaChunkSize, fp); if (!ret) break; SHA1Update(&ctx, buf, ret); @@ -165,7 +166,7 @@ int trimNds(const char *fileName) { do { swiWaitForVBlank(); scanKeys(); - } while(!(keysDown() & KEY_A)); + } while(pmMainLoop() && !(keysDown() & KEY_A)); } else { font->clear(false); font->printf(firstCol, 0, false, alignStart, Palette::white, (STR_TRIM_TO_N_BYTES + "\n\n" + STR_A_YES_B_NO).c_str(), getBytes(romSize).c_str()); @@ -176,7 +177,7 @@ int trimNds(const char *fileName) { scanKeys(); pressed = keysDown(); swiWaitForVBlank(); - } while(!(pressed & (KEY_A | KEY_B))); + } while(pmMainLoop() && !(pressed & (KEY_A | KEY_B))); if(pressed & KEY_A) { truncate(fileName, romSize); @@ -243,7 +244,7 @@ bool fcopy(const char *sourcePath, const char *destinationPath) { do { swiWaitForVBlank(); scanKeys(); - } while(!(keysDown() & KEY_A)); + } while(pmMainLoop() && !(keysDown() & KEY_A)); chdir(startPath); return false; @@ -281,7 +282,7 @@ bool fcopy(const char *sourcePath, const char *destinationPath) { do { swiWaitForVBlank(); scanKeys(); - } while(!(keysDown() & KEY_A)); + } while(pmMainLoop() && !(keysDown() & KEY_A)); return false; } @@ -299,7 +300,7 @@ bool fcopy(const char *sourcePath, const char *destinationPath) { off_t offset = 0; size_t numr; - while (1) { + while (pmMainLoop()) { scanKeys(); if (keysHeld() & KEY_B) { // Cancel copying @@ -346,7 +347,7 @@ void changeFileAttribs(const DirEntry *entry) { if(!entry->isDirectory) stat(entry->name.c_str(), &st); - while (1) { + while (pmMainLoop()) { font->clear(false); font->print(firstCol, 0, false, entry->name, alignStart); if (!entry->isDirectory) { @@ -372,8 +373,7 @@ void changeFileAttribs(const DirEntry *entry) { held = keysHeld(); pressed = keysDown(); swiWaitForVBlank(); - } while (!(pressed & KEY_UP) && !(pressed & KEY_DOWN) && !(pressed & KEY_RIGHT) && !(pressed & KEY_LEFT) - && !(pressed & KEY_A) && !(pressed & KEY_B)); + } while (pmMainLoop() && !(pressed & (KEY_UP | KEY_DOWN | KEY_RIGHT | KEY_LEFT | KEY_A | KEY_B))); if(driveWritable(currentDrive)) { if (pressed & KEY_UP) { diff --git a/arm9/source/file_browse.cpp b/arm9/source/file_browse.cpp index 84cb5b9f..b1d954b7 100644 --- a/arm9/source/file_browse.cpp +++ b/arm9/source/file_browse.cpp @@ -32,6 +32,7 @@ #include #include +#include "calico/nds/pm.h" #include "main.h" #include "config.h" #include "date.h" @@ -85,7 +86,7 @@ bool getDirectoryContents(std::vector& dirContents) { font->update(true); return false; } else { - while (true) { + while (pmMainLoop()) { dirent *pent = readdir(pdir); if (pent == nullptr) break; @@ -190,7 +191,7 @@ FileOperation fileBrowse_A(DirEntry* entry, const char *curdir) { operations.push_back(FileOperation::trimNds); } if(extension(entry->name, {"sav", "sav1", "sav2", "sav3", "sav4", "sav5", "sav6", "sav7", "sav8", "sav9"})) { - if(!(io_dldi_data->ioInterface.features & FEATURE_SLOT_NDS) || entry->size <= (1 << 20)) + if(!(dldiInterface.disc.features & FEATURE_SLOT_NDS) || entry->size <= (1 << 20)) operations.push_back(FileOperation::restoreSaveNds); if(isRegularDS && (entry->size == 512 || entry->size == 8192 || entry->size == 32768 || entry->size == 65536 || entry->size == 131072 || entry->size == 528 || entry->size == 8208 || entry->size == 32784 || entry->size == 65552 || entry->size == 131088)) @@ -217,7 +218,7 @@ FileOperation fileBrowse_A(DirEntry* entry, const char *curdir) { operations.push_back(FileOperation::copyFatOut); } - while (true) { + while (pmMainLoop()) { font->clear(false); font->print(firstCol, 0, false, fullPath, alignStart); @@ -294,7 +295,7 @@ FileOperation fileBrowse_A(DirEntry* entry, const char *curdir) { return FileOperation::none; } - } while (!(pressed & (KEY_UP| KEY_DOWN | KEY_A | KEY_B | KEY_L))); + } while (pmMainLoop() && !(pressed & (KEY_UP| KEY_DOWN | KEY_A | KEY_B | KEY_L))); if (pressed & KEY_UP) optionOffset -= 1; if (pressed & KEY_DOWN) optionOffset += 1; @@ -429,7 +430,7 @@ FileOperation fileBrowse_A(DirEntry* entry, const char *curdir) { if(keysHeld() & KEY_R && pressed & KEY_L) { screenshot(); } - } while (!(pressed & (KEY_A | KEY_Y | KEY_B | KEY_X))); + } while (pmMainLoop() && !(pressed & (KEY_A | KEY_Y | KEY_B | KEY_X))); break; } case FileOperation::none: { break; @@ -461,7 +462,7 @@ bool fileBrowse_paste(char dest[256]) { int pressed = 0; int optionOffset = 0; - while (true) { + while (pmMainLoop()) { font->clear(false); font->print(firstCol, 0, false, STR_PASTE_CLIPBOARD_HERE, alignStart); @@ -488,7 +489,7 @@ bool fileBrowse_paste(char dest[256]) { scanKeys(); pressed = keysDownRepeat(); swiWaitForVBlank(); - } while (!(pressed & (KEY_UP | KEY_DOWN | KEY_A | KEY_B))); + } while (pmMainLoop() && !(pressed & (KEY_UP | KEY_DOWN | KEY_A | KEY_B))); if (pressed & KEY_UP) optionOffset -= 1; if (pressed & KEY_DOWN) optionOffset += 1; @@ -615,7 +616,7 @@ std::string browseForFile (void) { getDirectoryContents(dirContents); - while (true) { + while (pmMainLoop()) { getcwd(curdir, PATH_MAX); // Ensure the path ends in a slash @@ -642,7 +643,7 @@ std::string browseForFile (void) { screenMode = 0; return "null"; } - } while (!(pressed & ~(KEY_R | KEY_LID))); + } while (pmMainLoop() && !(pressed & ~(KEY_R | KEY_LID))); if (pressed & KEY_UP) { fileOffset--; @@ -781,7 +782,7 @@ std::string browseForFile (void) { font->print(firstCol, (!entry->selected || selections == 1) ? 2 : (selections > 5 ? 9 : selections + 3), false, STR_A_YES_B_NO, alignStart); font->update(false); - while (true) { + while (pmMainLoop()) { scanKeys(); pressed = keysDownRepeat(); swiWaitForVBlank(); @@ -809,7 +810,7 @@ std::string browseForFile (void) { font->print(firstCol, 3, false, STR_A_CONTINUE, alignStart); pressed = 0; - while (!(pressed & KEY_A)) { + while (pmMainLoop() && !(pressed & KEY_A)) { scanKeys(); pressed = keysDown(); swiWaitForVBlank(); @@ -866,13 +867,13 @@ std::string browseForFile (void) { } else if ((pressed & KEY_L && !(held & KEY_R)) && entry->name != "..") { // Add to selection bool select = !entry->selected; entry->selected = select; - while(held & KEY_L) { + while(pmMainLoop() && (held & KEY_L)) { do { scanKeys(); pressed = keysDownRepeat(); held = keysHeld(); swiWaitForVBlank(); - } while ((held & KEY_L) && !(pressed & (KEY_UP | KEY_DOWN | KEY_LEFT | KEY_RIGHT))); + } while (pmMainLoop() && (held & KEY_L) && !(pressed & (KEY_UP | KEY_DOWN | KEY_LEFT | KEY_RIGHT))); if(pressed & (KEY_UP | KEY_DOWN)) { if (pressed & KEY_UP) { diff --git a/arm9/source/flashcard/exptools.cpp b/arm9/source/flashcard/exptools.cpp index 15d89e71..a4692395 100644 --- a/arm9/source/flashcard/exptools.cpp +++ b/arm9/source/flashcard/exptools.cpp @@ -296,13 +296,13 @@ void cExpansion::WritePSRAM(u32 address,const u8* buffer,u32 size) } } -void cExpansion::WriteSram(uint32 address,const u8* data,uint32 size) +void cExpansion::WriteSram(u32 address,const u8* data,u32 size) { for(u32 i=0;i #include "gba.h" +#include "pxiVars.h" +// #include "calico/nds/gbacart.h" +// #include "calico/nds/pxi.h" +// #include "calico/system/mailbox.h" inline u32 min(u32 i, u32 j) { return (i < j) ? i : j;} inline u32 max(u32 i, u32 j) { return (i > j) ? i : j;} @@ -56,7 +60,7 @@ inline u32 max(u32 i, u32 j) { return (i > j) ? i : j;} bool gbaIsGame() { // look for some magic bytes of the compressed Nintendo logo - uint32 *data = (uint32*)0x08000004; + u32 *data = (u32*)0x08000004; if (*data == 0x51aeff24) { data ++; data ++; @@ -66,44 +70,35 @@ bool gbaIsGame() return false; } -void readEeprom(u8 *dst, u32 src, u32 len) { +bool readEeprom(u8 *dst, u32 src, u32 len) { // EEPROM reading needs to happen on ARM7 sysSetCartOwner(BUS_OWNER_ARM7); - fifoSendValue32(FIFO_USER_01, 0x44414552 /* 'READ' */); - fifoSendAddress(FIFO_USER_01, dst); - fifoSendValue32(FIFO_USER_01, src); - fifoSendValue32(FIFO_USER_01, len); - - // Read the data from FIFO - u8 *ptr = dst; - while(ptr < dst + len) { - if(fifoCheckDatamsg(FIFO_USER_02)) { - fifoGetDatamsg(FIFO_USER_02, 8, ptr); - ptr += 8; - } - } + + u32 args[] {(u32)dst, src, len}; + armDCacheFlush(dst, len); + u32 res = pxiSendWithDataAndReceive(PXI_MAIN, GBA_READ_EEPROM, args, sizeof(args) / sizeof(args[0])); sysSetCartOwner(BUS_OWNER_ARM9); + + return res; } -void writeEeprom(u32 dst, u8 *src, u32 len) { +bool writeEeprom(u32 dst, u8 *src, u32 len) { // EEPROM writing needs to happen on ARM7 sysSetCartOwner(BUS_OWNER_ARM7); - fifoSendValue32(FIFO_USER_01, 0x54495257 /* 'WRIT' */); - fifoSendValue32(FIFO_USER_01, dst); - fifoSendAddress(FIFO_USER_01, src); - fifoSendValue32(FIFO_USER_01, len); - // Wait for it to finish - fifoWaitValue32(FIFO_USER_02); - fifoGetValue32(FIFO_USER_02); + u32 args[] {dst, (u32)src, len}; + armDCacheFlush(src, len); + u32 res = pxiSendWithDataAndReceive(PXI_MAIN, GBA_WRITE_EEPROM, args, sizeof(args) / sizeof(args[0])); sysSetCartOwner(BUS_OWNER_ARM9); + + return res; } saveTypeGBA gbaGetSaveType() { // Search for any one of the magic version strings in the ROM. They are always dword-aligned. - uint32 *data = (uint32*)0x08000000; + u32 *data = (u32*)0x08000000; for (int i = 0; i < (0x02000000 >> 2); i++, data++) { if (*data == MAGIC_EEPR) { @@ -124,7 +119,7 @@ saveTypeGBA gbaGetSaveType() { return SAVE_GBA_SRAM_32; } else if (*data == MAGIC_FLAS) { // 64 kB oder 128 kB - uint32 *data2 = data + 1; + u32 *data2 = data + 1; if (*data2 == MAGIC_H1M_) return SAVE_GBA_FLASH_128; else @@ -135,7 +130,7 @@ saveTypeGBA gbaGetSaveType() { return SAVE_GBA_NONE; } -uint32 gbaGetSaveSizeLog2(saveTypeGBA type) +u32 gbaGetSaveSizeLog2(saveTypeGBA type) { if (type == SAVE_GBA_NONE) type = gbaGetSaveType(); @@ -157,7 +152,7 @@ uint32 gbaGetSaveSizeLog2(saveTypeGBA type) } } -uint32 gbaGetSaveSize(saveTypeGBA type) +u32 gbaGetSaveSize(saveTypeGBA type) { if (type == SAVE_GBA_NONE) return 0; diff --git a/arm9/source/gba.h b/arm9/source/gba.h index 5a61070b..cf81a647 100644 --- a/arm9/source/gba.h +++ b/arm9/source/gba.h @@ -49,8 +49,8 @@ enum GbaRtc { // -------------------- bool gbaIsGame(); saveTypeGBA gbaGetSaveType(); -uint32 gbaGetSaveSize(saveTypeGBA type = SAVE_GBA_NONE); -uint32 gbaGetSaveSizeLog2(saveTypeGBA type = SAVE_GBA_NONE); +u32 gbaGetSaveSize(saveTypeGBA type = SAVE_GBA_NONE); +u32 gbaGetSaveSizeLog2(saveTypeGBA type = SAVE_GBA_NONE); u16 gbaGetFlashId(); bool gbaReadSave(u8 *dst, u32 src, u32 len, saveTypeGBA type); diff --git a/arm9/source/hexEditor.cpp b/arm9/source/hexEditor.cpp index dfc61f5f..5c2bdb17 100644 --- a/arm9/source/hexEditor.cpp +++ b/arm9/source/hexEditor.cpp @@ -15,7 +15,7 @@ u32 jumpToOffset(u32 offset) { u8 cursorPosition = 0; u16 pressed = 0, held = 0; - while(1) { + while(pmMainLoop()) { int y = (ENTRIES_PER_SCREEN - 4) / 2; font->clear(false); font->print(0, y, false, "--------------------", Alignment::center); @@ -30,7 +30,7 @@ u32 jumpToOffset(u32 offset) { scanKeys(); pressed = keysDown(); held = keysDownRepeat(); - } while(!held); + } while(pmMainLoop() && !held); if(held & KEY_UP) { offset = (offset & ~(0xF0 << cursorPosition * 4)) | ((offset + (0x10 << (cursorPosition * 4))) & (0xF0 << cursorPosition * 4)); @@ -53,7 +53,7 @@ u32 jumpToOffset(u32 offset) { u32 search(u32 offset, FILE *file) { u8 cursorPosition = 0; u16 pressed = 0, held = 0; - while(1) { + while(pmMainLoop()) { int y = (ENTRIES_PER_SCREEN - 3) / 2; font->clear(false); font->print(0, y, false, "--------------------", Alignment::center); @@ -67,7 +67,7 @@ u32 search(u32 offset, FILE *file) { scanKeys(); pressed = keysDown(); held = keysDownRepeat(); - } while(!held); + } while(pmMainLoop() && !held); if(held & (KEY_UP | KEY_DOWN)) { cursorPosition ^= 1; @@ -91,7 +91,7 @@ u32 search(u32 offset, FILE *file) { return offset; } else { cursorPosition = 0; - while(1) { + while(pmMainLoop()) { int y = (ENTRIES_PER_SCREEN - 4) / 2; font->clear(false); font->print(0, y, false, "--------------------", Alignment::center); @@ -106,7 +106,7 @@ u32 search(u32 offset, FILE *file) { scanKeys(); pressed = keysDown(); held = keysDownRepeat(); - } while(!held); + } while(pmMainLoop() && !held); if(held & KEY_UP) { char val = str[cursorPosition / 2]; @@ -194,7 +194,7 @@ u32 search(u32 offset, FILE *file) { do { swiWaitForVBlank(); scanKeys(); - } while(!keysDown()); + } while(pmMainLoop() && !keysDown()); return offset; } @@ -221,7 +221,7 @@ void hexEditor(const char *path, Drive drive) { fseek(file, offset, SEEK_SET); fread(data, 1, sizeof(data), file); - while(1) { + while(pmMainLoop()) { font->clear(false); font->printf(0, 0, false, Alignment::left, Palette::blackGreen, "%*c", SCREEN_COLS, ' '); @@ -270,7 +270,7 @@ void hexEditor(const char *path, Drive drive) { if(driveRemoved(currentDrive)) return; - } while(!held); + } while(pmMainLoop() && !held); if(mode == 0) { if(keysHeld() & KEY_R && held & (KEY_UP | KEY_DOWN | KEY_LEFT | KEY_RIGHT)) { diff --git a/arm9/source/keyboard.cpp b/arm9/source/keyboard.cpp index 24be1245..ae57e787 100644 --- a/arm9/source/keyboard.cpp +++ b/arm9/source/keyboard.cpp @@ -33,7 +33,7 @@ std::string kbdGetString(std::string label, int maxSize, std::string oldStr) { int key; int labelHeight = font->calcHeight(label); bool done = false; - while(!done) { + while(pmMainLoop() && !done) { font->clear(false); font->print(firstCol, 0, false, label, alignStart); diff --git a/arm9/source/language.inl b/arm9/source/language.inl index c68195d1..ac9b0fa8 100644 --- a/arm9/source/language.inl +++ b/arm9/source/language.inl @@ -44,7 +44,7 @@ STRING(SDCARD_LABEL, "[sd:] SDCARD (%s)") STRING(FLASHCARD_LABEL, "[fat:] FLASHCARD (%s)") STRING(RAMDRIVE_LABEL, "[ram:] RAMDRIVE") STRING(SYSNAND_LABEL, "[nand:] SYSNAND") -STRING(SYSNAND_PHOTO_LABEL, "[photo:] SYSNAND (photo)") +STRING(SYSNAND_PHOTO_LABEL, "[nand2:] SYSNAND (photo)") STRING(NITROFS_LABEL, "[nitro:] NDS GAME IMAGE") STRING(FAT_LABEL, "[img:] FAT IMAGE (%s)") STRING(GBA_GAMECART, "GBA GAMECART (%s)") diff --git a/arm9/source/main.cpp b/arm9/source/main.cpp index 71b87049..22c9d173 100644 --- a/arm9/source/main.cpp +++ b/arm9/source/main.cpp @@ -8,6 +8,11 @@ #include #include +#include "calico/nds/pm.h" +#include "calico/nds/pxi.h" +#include "nds/arm9/console.h" +#include "nds/arm9/input.h" +#include "nds/interrupts.h" #include "nds_loader_arm9.h" #include "config.h" #include "date.h" @@ -19,6 +24,8 @@ #include "language.h" #include "my_sd.h" #include "nitrofs.h" +#include "pxiVars.h" +#include "sys/unistd.h" #include "tonccpy.h" #include "version.h" @@ -42,10 +49,12 @@ bool applaunch = false; static int bg3; +extern unsigned g_dvmCalicoNandMount; + //--------------------------------------------------------------------------------- void stop (void) { //--------------------------------------------------------------------------------- - while (1) { + while (pmMainLoop()) { swiWaitForVBlank(); } } @@ -60,7 +69,7 @@ void vblankHandler (void) { } // Check if GBA cart ejected - if(isRegularDS && (io_dldi_data->ioInterface.features & FEATURE_SLOT_NDS) && *(u8*)(0x080000B2) != 0x96 && romTitle[1][0] != '\0') { + if(isRegularDS && (dldiInterface.disc.features & FEATURE_SLOT_NDS) && *(u8*)(0x080000B2) != 0x96 && romTitle[1][0] != '\0') { romTitle[1][0] = '\0'; romSize[1] = 0; } @@ -76,6 +85,19 @@ void vblankHandler (void) { } } +void getArm7Vars(void) { + // REG_SCFG_EXT, REG_SNDEXCNT, is3DS + u32 args[3] = {0}; + armDCacheFlush(args, sizeof(args)); + u32 res = pxiSendAndReceive(PXI_MAIN, GET_ARM7_VARS); + iprintf("%d", res); + // pxiSendWithDataAndReceive(PXI_MAIN, GET_ARM7_VARS, args, sizeof(args) / sizeof(args[0])); + + if(args[0] == 0) arm7SCFGLocked = true; + if(args[1] != 0) isRegularDS = false; // If sound frequency setting is found, then the console is not a DS Phat/Lite + is3DS = args[2]; +} + //--------------------------------------------------------------------------------- int main(int argc, char **argv) { //--------------------------------------------------------------------------------- @@ -90,7 +112,7 @@ int main(int argc, char **argv) { bool yHeld = false; - sprintf(titleName, "GodMode9i %s", VER_NUMBER); + sprintf(titleName, "GodMode9i " VER_NUMBER); // initialize video mode videoSetMode(MODE_5_2D); @@ -117,11 +139,7 @@ int main(int argc, char **argv) { font->print(1, 2, false, "----------------------------------------"); font->print(1, 3, false, "https://github.com/DS-Homebrew/GodMode9i"); - fifoWaitValue32(FIFO_USER_06); - if (fifoGetValue32(FIFO_USER_03) == 0) arm7SCFGLocked = true; - u16 arm7_SNDEXCNT = fifoGetValue32(FIFO_USER_07); - if (arm7_SNDEXCNT != 0) isRegularDS = false; // If sound frequency setting is found, then the console is not a DS Phat/Lite - fifoSendValue32(FIFO_USER_07, 0); + getArm7Vars(); if (isDSiMode()) { // bios9iEnabled = true; @@ -139,6 +157,8 @@ int main(int argc, char **argv) { font->update(false); for (int i = 0; i < 60*2; i++) { swiWaitForVBlank(); + scanKeys(); + if(keysDown() & KEY_START) break; } font->clear(false); @@ -150,23 +170,29 @@ int main(int argc, char **argv) { sysSetCartOwner (BUS_OWNER_ARM9); // Allow arm9 to access GBA ROM + g_dvmCalicoNandMount = 1; + fatInitDefault(); + sdMounted = access("sd:/", F_OK) == 0; + sdMountedDone = sdMounted; + nandMounted = access("nand:/", F_OK) == 0; + photoMounted = access("nand2:/", F_OK) == 0; + if (isDSiMode() || !isRegularDS) { - fifoSetValue32Handler(FIFO_USER_04, sdStatusHandler, nullptr); - if (!sdRemoved) { - sdMounted = sdMount(); - } + // TODO: Update for calico + // fifoSetValue32Handler(FIFO_USER_04, sdStatusHandler, nullptr); + // if (!sdRemoved) { + // sdMounted = sdMount(); + // } } if (isDSiMode()) { scanKeys(); yHeld = (keysHeld() & KEY_Y); - *(vu32*)(0x0DFFFE0C) = 0x474D3969; // Check for 32MB of RAM - bool ram32MB = *(vu32*)(0x0DFFFE0C) == 0x474D3969; - ramdriveMount(ram32MB); - if (ram32MB) { - is3DS = fifoGetValue32(FIFO_USER_05) != 0xD2; - } + // TODO: Crashing on Guru Meditation Error + // *(vu32*)(0x0DFFFE0C) = 0x474D3969; // Check for 32MB of RAM + // bool ram32MB = *(vu32*)(0x0DFFFE0C) == 0x474D3969; + // ramdriveMount(ram32MB); //if (!(keysHeld() & KEY_X)) { - nandMount(); + // nandMount(); //} //is3DS = ((access("sd:/Nintendo 3DS", F_OK) == 0) && (*(vu32*)(0x0DFFFE0C) == 0x474D3969)); /*FILE* cidFile = fopen("sd:/gm9i/CID.bin", "wb"); @@ -179,9 +205,6 @@ int main(int argc, char **argv) { *(vu32*)(0x0DFFFE0C) = 0x474D3969; // Check for 32MB of RAM bool ram32MB = *(vu32*)(0x0DFFFE0C) == 0x474D3969; ramdriveMount(ram32MB); - if (ram32MB) { - is3DS = fifoGetValue32(FIFO_USER_05) != 0xD2; - } /* FILE* bios = fopen("sd:/_nds/bios9i.bin", "rb"); if (!bios) { @@ -231,9 +254,10 @@ int main(int argc, char **argv) { setVectorBase(0); bios9iEnabled = true; */ - nandMount(); + // TODO? + // nandMount(); // } - } else if (isRegularDS && (io_dldi_data->ioInterface.features & FEATURE_SLOT_NDS)) { + } else if (isRegularDS && (dldiInterface.disc.features & FEATURE_SLOT_NDS)) { ramdriveMount(false); } if (!isDSiMode() || !yHeld) { @@ -266,7 +290,7 @@ int main(int argc, char **argv) { swiWaitForVBlank(); } - if (nitroMounted && (strcmp(io_dldi_data->friendlyName, "NAND FLASH CARD LIBFATNRIO") == 0) && (*(u32*)0x02FF8000 != 0x53535A4C)) { + if (nitroMounted && (strcmp(dldiInterface.iface_name, "NAND FLASH CARD LIBFATNRIO") == 0) && (*(u32*)0x02FF8000 != 0x53535A4C)) { FILE* file = fopen("nitro:/dldi/nrio.lz77", "rb"); fread((void*)0x02FF8004, 1, 0x3FFC, file); fclose(file); @@ -311,7 +335,7 @@ int main(int argc, char **argv) { appInited = true; - while(1) { + while(pmMainLoop()) { if (screenMode == 0) { driveMenu(); @@ -375,7 +399,8 @@ int main(int argc, char **argv) { free(argarray[0]); argarray[0] = filePath; fcopy(argarray[0], "sd:/bootonce.firm"); - fifoSendValue32(FIFO_USER_02, 1); // Reboot into selected .firm payload + // TODO: Update for calico + // fifoSendValue32(FIFO_USER_02, 1); // Reboot into selected .firm payload swiWaitForVBlank(); } @@ -384,7 +409,7 @@ int main(int argc, char **argv) { argarray.erase(argarray.begin()); } - while (1) { + while (pmMainLoop()) { swiWaitForVBlank(); scanKeys(); if (!(keysHeld() & KEY_A)) break; diff --git a/arm9/source/my_sd.c b/arm9/source/my_sd.c index 1e078770..4f79cb34 100644 --- a/arm9/source/my_sd.c +++ b/arm9/source/my_sd.c @@ -1,9 +1,6 @@ #include "my_sd.h" -#include -#include -#include -#include +#include volatile bool sdRemoved = false; volatile bool sdWriteLocked = false; @@ -12,123 +9,3 @@ void sdStatusHandler(u32 sdIrqStatus, void *userdata) { sdRemoved = (sdIrqStatus & BIT(5)) == 0; sdWriteLocked = (sdIrqStatus & BIT(7)) == 0; } - -//--------------------------------------------------------------------------------- -bool my_sdio_Startup() { -//--------------------------------------------------------------------------------- - fifoSendValue32(FIFO_SDMMC,SDMMC_HAVE_SD); - while(!fifoCheckValue32(FIFO_SDMMC)); - int result = fifoGetValue32(FIFO_SDMMC); - - if(result==0) return false; - - fifoSendValue32(FIFO_SDMMC,SDMMC_SD_START); - - fifoWaitValue32(FIFO_SDMMC); - - result = fifoGetValue32(FIFO_SDMMC); - - return result == 0; -} - -//--------------------------------------------------------------------------------- -bool my_sdio_IsInserted() { -//--------------------------------------------------------------------------------- - fifoSendValue32(FIFO_SDMMC,SDMMC_SD_IS_INSERTED); - - fifoWaitValue32(FIFO_SDMMC); - - int result = fifoGetValue32(FIFO_SDMMC); - - return result == 1; -} - -//--------------------------------------------------------------------------------- -bool my_sdio_ReadSectors(sec_t sector, sec_t numSectors,void* buffer) { -//--------------------------------------------------------------------------------- - FifoMessage msg; - - DC_FlushRange(buffer,numSectors * 512); - - msg.type = SDMMC_SD_READ_SECTORS; - msg.sdParams.startsector = sector; - msg.sdParams.numsectors = numSectors; - msg.sdParams.buffer = buffer; - - fifoSendDatamsg(FIFO_SDMMC, sizeof(msg), (u8*)&msg); - - fifoWaitValue32(FIFO_SDMMC); - - int result = fifoGetValue32(FIFO_SDMMC); - - return result == 0; -} - -//--------------------------------------------------------------------------------- -bool my_sdio_WriteSectors(sec_t sector, sec_t numSectors,const void* buffer) { -//--------------------------------------------------------------------------------- - if(sdWriteLocked) - return false; - - FifoMessage msg; - - DC_FlushRange(buffer,numSectors * 512); - - msg.type = SDMMC_SD_WRITE_SECTORS; - msg.sdParams.startsector = sector; - msg.sdParams.numsectors = numSectors; - msg.sdParams.buffer = (void*)buffer; - - fifoSendDatamsg(FIFO_SDMMC, sizeof(msg), (u8*)&msg); - - fifoWaitValue32(FIFO_SDMMC); - - int result = fifoGetValue32(FIFO_SDMMC); - - return result == 0; -} - - -//--------------------------------------------------------------------------------- -bool my_sdio_ClearStatus() { -//--------------------------------------------------------------------------------- - return true; -} - -//--------------------------------------------------------------------------------- -bool my_sdio_Shutdown() { -//--------------------------------------------------------------------------------- - fifoSendValue32(FIFO_SDMMC,SDMMC_SD_STOP); - - fifoWaitValue32(FIFO_SDMMC); - - int result = fifoGetValue32(FIFO_SDMMC); - - return result == 1; -} - -const DISC_INTERFACE __my_io_dsisd_rw = { - DEVICE_TYPE_DSI_SD, - FEATURE_MEDIUM_CANREAD | FEATURE_MEDIUM_CANWRITE, - (FN_MEDIUM_STARTUP)&my_sdio_Startup, - (FN_MEDIUM_ISINSERTED)&my_sdio_IsInserted, - (FN_MEDIUM_READSECTORS)&my_sdio_ReadSectors, - (FN_MEDIUM_WRITESECTORS)&my_sdio_WriteSectors, - (FN_MEDIUM_CLEARSTATUS)&my_sdio_ClearStatus, - (FN_MEDIUM_SHUTDOWN)&my_sdio_Shutdown -}; - -const DISC_INTERFACE __my_io_dsisd_r = { - DEVICE_TYPE_DSI_SD, - FEATURE_MEDIUM_CANREAD, - (FN_MEDIUM_STARTUP)&my_sdio_Startup, - (FN_MEDIUM_ISINSERTED)&my_sdio_IsInserted, - (FN_MEDIUM_READSECTORS)&my_sdio_ReadSectors, - (FN_MEDIUM_WRITESECTORS)&my_sdio_WriteSectors, - (FN_MEDIUM_CLEARSTATUS)&my_sdio_ClearStatus, - (FN_MEDIUM_SHUTDOWN)&my_sdio_Shutdown -}; - -const DISC_INTERFACE *__my_io_dsisd() { - return sdWriteLocked ? &__my_io_dsisd_r : &__my_io_dsisd_rw; -} diff --git a/arm9/source/my_sd.h b/arm9/source/my_sd.h index 3eb6bfc1..6b710b05 100644 --- a/arm9/source/my_sd.h +++ b/arm9/source/my_sd.h @@ -11,10 +11,6 @@ extern volatile bool sdWriteLocked; void sdStatusHandler(u32 sdIrqStatus, void *userdata); -bool my_sdio_Shutdown(); - -const DISC_INTERFACE *__my_io_dsisd(); - #ifdef __cplusplus } #endif diff --git a/arm9/source/nandio.c b/arm9/source/nandio.c deleted file mode 100644 index 43f5a0f4..00000000 --- a/arm9/source/nandio.c +++ /dev/null @@ -1,208 +0,0 @@ - -#include -#include -#include -#include -#include -#include -#include "crypto.h" -#include "sector0.h" -#include "tonccpy.h" -#include "f_xy.h" - -//#define SECTOR_SIZE 512 -#define CRYPT_BUF_LEN 64 - -static u8* crypt_buf = 0; - -static u32 fat_sig_fix_offset = 0; - -static u32 sector_buf32[SECTOR_SIZE/sizeof(u32)]; -static u8 *sector_buf = (u8*)sector_buf32; - -static inline void nandio_set_fat_sig_fix(u32 offset) { - fat_sig_fix_offset = offset; -} - -void getConsoleID(u8 *consoleID){ - u8 *fifo=(u8*)0x02F00000; //shared mem address that has our computed key3 stuff - u8 key[16]; //key3 normalkey - keyslot 3 is used for DSi/twln NAND crypto - u8 key_xy[16]; //key3_y ^ key3_x - u8 key_x[16];////key3_x - contains a DSi console id (which just happens to be the LFCS on 3ds) - u8 key_y[16] = {0x76, 0xDC, 0xB9, 0x0A, 0xD3, 0xC4, 0x4D, 0xBD, 0x1D, 0xDD, 0x2D, 0x20, 0x05, 0x00, 0xA0, 0xE1}; //key3_y NAND constant - - u8 empty_buff[8] = {0}; - - tonccpy(key, fifo, 16); //receive the goods from arm7 - - if(memcmp(key + 8, empty_buff, 8) == 0) - { - //we got the consoleid directly or nothing at all, don't treat this as key3 output - tonccpy(consoleID, key, 8); - return; - } - - F_XY_reverse((uint32_t*)key, (uint32_t*)key_xy); //work backwards from the normalkey to get key_x that has the consoleID - - for(int i=0;i<16;i++){ - key_x[i] = key_xy[i] ^ key_y[i]; //'' - } - - tonccpy(&consoleID[0], &key_x[0], 4); - tonccpy(&consoleID[4], &key_x[0xC], 4); -} - -//--------------------------------------------------------------------------------- -bool my_nand_Startup() { -//--------------------------------------------------------------------------------- - fifoSendValue32(FIFO_SDMMC,SDMMC_HAVE_SD); - while(!fifoCheckValue32(FIFO_SDMMC)); - int result = fifoGetValue32(FIFO_SDMMC); - - if(result==0) return false; - - fifoSendValue32(FIFO_SDMMC,SDMMC_NAND_START); - - fifoWaitValue32(FIFO_SDMMC); - - result = fifoGetValue32(FIFO_SDMMC); - - return result == 0; -} - -//--------------------------------------------------------------------------------- -bool my_nand_ReadSectors(sec_t sector, sec_t numSectors,void* buffer) { -//--------------------------------------------------------------------------------- - FifoMessage msg; - - DC_FlushRange(buffer,numSectors * 512); - - msg.type = SDMMC_NAND_READ_SECTORS; - msg.sdParams.startsector = sector; - msg.sdParams.numsectors = numSectors; - msg.sdParams.buffer = buffer; - - fifoSendDatamsg(FIFO_SDMMC, sizeof(msg), (u8*)&msg); - - fifoWaitValue32(FIFO_SDMMC); - - int result = fifoGetValue32(FIFO_SDMMC); - - return result == 0; -} - -bool nandio_startup() { - if (!my_nand_Startup()) return false; - - my_nand_ReadSectors(0, 1, sector_buf); - bool isDSi = parse_ncsd(sector_buf, 0) != 0; - //if (!isDSi) return false; - - if (*(u32*)(0x2FFD7BC) == 0) { - if (!isDSi) { - FILE* cidFile = fopen("sd:/gm9/out/nand_cid.mem", "rb"); - if (!cidFile) return false; - fread((void*)0x2FFD7BC, 1, 16, cidFile); - fclose(cidFile); - } else { - // Get eMMC CID - *(u32*)(0xCFFFD0C) = 0x454D4D43; - while (*(u32*)(0xCFFFD0C) != 0) { - swiDelay(100); - } - } - } - - u8 consoleID[8]; - u8 consoleIDfixed[8]; - - // Get ConsoleID - getConsoleID(consoleID); - for (int i = 0; i < 8; i++) { - consoleIDfixed[i] = consoleID[7-i]; - } - - // iprintf("sector 0 is %s\n", is3DS ? "3DS" : "DSi"); - dsi_crypt_init((const u8*)consoleIDfixed, (const u8*)0x2FFD7BC, !isDSi); - dsi_nand_crypt(sector_buf, sector_buf, 0, SECTOR_SIZE / AES_BLOCK_SIZE); - parse_mbr(sector_buf, !isDSi, 0); - - mbr_t *mbr = (mbr_t*)sector_buf; - nandio_set_fat_sig_fix(isDSi ? mbr->partitions[0].offset : 0); - - if (crypt_buf == 0) { - crypt_buf = (u8*)memalign(32, SECTOR_SIZE * CRYPT_BUF_LEN); - //if (crypt_buf == 0) { - //printf("nandio: failed to alloc buffer\n"); - //} - } - return crypt_buf != 0; -} - -bool nandio_is_inserted() { - return true; -} - -// len is guaranteed <= CRYPT_BUF_LEN -static bool read_sectors(sec_t start, sec_t len, void *buffer) { - if (my_nand_ReadSectors(start, len, crypt_buf)) { - dsi_nand_crypt(buffer, crypt_buf, start * SECTOR_SIZE / AES_BLOCK_SIZE, len * SECTOR_SIZE / AES_BLOCK_SIZE); - if (fat_sig_fix_offset && - start == fat_sig_fix_offset - && ((u8*)buffer)[0x36] == 0 - && ((u8*)buffer)[0x37] == 0 - && ((u8*)buffer)[0x38] == 0) - { - ((u8*)buffer)[0x36] = 'F'; - ((u8*)buffer)[0x37] = 'A'; - ((u8*)buffer)[0x38] = 'T'; - } - return true; - } else { - //printf("NANDIO: read error\n"); - return false; - } -} - -bool nandio_read_sectors(sec_t offset, sec_t len, void *buffer) { - // iprintf("R: %u(0x%08x), %u\n", (unsigned)offset, (unsigned)offset, (unsigned)len); - while (len >= CRYPT_BUF_LEN) { - if (!read_sectors(offset, CRYPT_BUF_LEN, buffer)) { - return false; - } - offset += CRYPT_BUF_LEN; - len -= CRYPT_BUF_LEN; - buffer = ((u8*)buffer) + SECTOR_SIZE * CRYPT_BUF_LEN; - } - if (len > 0) { - return read_sectors(offset, len, buffer); - } else { - return true; - } -} - -bool nandio_write_sectors(sec_t offset, sec_t len, const void *buffer) { - // lol, nope - return false; -} - -bool nandio_clear_status() { - return true; -} - -bool nandio_shutdown() { - free(crypt_buf); - crypt_buf = 0; - return true; -} - -const DISC_INTERFACE io_dsi_nand = { - ('N' << 24) | ('A' << 16) | ('N' << 8) | 'D', - FEATURE_MEDIUM_CANREAD, - nandio_startup, - nandio_is_inserted, - nandio_read_sectors, - nandio_write_sectors, - nandio_clear_status, - nandio_shutdown -}; diff --git a/arm9/source/nandio.h b/arm9/source/nandio.h deleted file mode 100644 index 4b4687f9..00000000 --- a/arm9/source/nandio.h +++ /dev/null @@ -1,8 +0,0 @@ -#pragma once - -#include -#include - -void nandio_set_fat_sig_fix(u32 offset); - -extern const DISC_INTERFACE io_dsi_nand; diff --git a/arm9/source/ndsInfo.cpp b/arm9/source/ndsInfo.cpp index 0ac0352d..6398fa9a 100644 --- a/arm9/source/ndsInfo.cpp +++ b/arm9/source/ndsInfo.cpp @@ -115,7 +115,7 @@ void ndsInfo(const char *path) { u16 pressed = 0, held = 0; int animationFrame = 0, frameDelay = 0, lang = 1; - while(1) { + while(pmMainLoop()) { font->clear(false); font->printf(firstCol, 0, false, alignStart, Palette::white, STR_HEADER_TITLE.c_str(), headerTitle); font->printf(firstCol, 1, false, alignStart, Palette::white, STR_TITLE_ID.c_str(), tid); @@ -143,7 +143,7 @@ void ndsInfo(const char *path) { oamUpdate(&oamSub); } } - } while(!held); + } while(pmMainLoop() && !held); if(held & KEY_UP) { if(lang > 0) diff --git a/arm9/source/nds_loader_arm9.c b/arm9/source/nds_loader_arm9.c index 7e182788..f77dedb6 100644 --- a/arm9/source/nds_loader_arm9.c +++ b/arm9/source/nds_loader_arm9.c @@ -30,6 +30,7 @@ #include "load_bin.h" #include "tonccpy.h" + #ifndef _NO_BOOTSTUB_ struct __my_bootstub { u64 bootsig; @@ -42,6 +43,8 @@ struct __my_bootstub { #include "bootstub_bin.h" #endif +extern DLDI_INTERFACE dldiInterface; + #include "nds_loader_arm9.h" #define LCDC_BANK_C (u16*)0x06848000 #define STORED_FILE_CLUSTER (*(((u32*)LCDC_BANK_C) + 1)) @@ -167,7 +170,7 @@ static bool dldiPatchLoader (void) size_t dldiFileSize = 0; - data_t *pDH = (data_t*)(io_dldi_data); + data_t *pDH = (data_t*)(&dldiInterface); data_t *pAH = (data_t*)0x02FF8000; @@ -331,9 +334,10 @@ int runNds (const void* loader, u32 loaderSize, u32 cluster, bool initDisc, bool *((vu32*)0x02FFFE04) = (u32)0xE59FF018; *((vu32*)0x02FFFE24) = (u32)0x02FFFE04; - resetARM7(0x06008000); + // TODO: Update for calico + // resetARM7(0x06008000); - swiSoftReset(); + // swiSoftReset(); return true; } @@ -372,7 +376,7 @@ int runNdsFile (const char* filename, int argc, const char** argv) { installBootStub(havedsiSD); #endif */ - return runNds (load_bin, load_bin_size, st.st_ino, true, (memcmp(io_dldi_data->friendlyName, "Default", 7) != 0), argc, argv); + return runNds (load_bin, load_bin_size, st.st_ino, true, (memcmp(dldiInterface.iface_name, "Default", 7) != 0), argc, argv); } /* @@ -396,7 +400,7 @@ int runNdsFile (const char* filename, int argc, const char** argv) { */ #ifndef _NO_BOOTSTUB_ -bool installBootStub(const bool havedsiSD) { +void installBootStub(const bool havedsiSD) { extern char *fake_heap_end; struct __my_bootstub *bootstub = (struct __my_bootstub *)fake_heap_end; u32 *bootloader = (u32*)(fake_heap_end+bootstub_bin_size); @@ -406,7 +410,7 @@ bool installBootStub(const bool havedsiSD) { bootloader[8] = isDSiMode(); if (havedsiSD) { - if (memcmp(io_dldi_data->friendlyName, "Default", 7) != 0) { + if (memcmp(dldiInterface.iface_name, "Default", 7) != 0) { dldiPatchLoader (); } else { bootloader[3] = 0; // don't dldi patch diff --git a/arm9/source/screenshot.cpp b/arm9/source/screenshot.cpp index 4db2eb77..8348bf0a 100644 --- a/arm9/source/screenshot.cpp +++ b/arm9/source/screenshot.cpp @@ -3,13 +3,13 @@ #include "bmp.h" #include "date.h" #include "driveOperations.h" -#include "file_browse.h" #include "font.h" #include #include #include #include +#include void wait(); diff --git a/arm9/source/sector0.c b/arm9/source/sector0.c deleted file mode 100644 index d1103c1e..00000000 --- a/arm9/source/sector0.c +++ /dev/null @@ -1,102 +0,0 @@ - -#include -#include -#include -#include "utils.h" -#include "sector0.h" - -// return 0 for valid NCSD header -int parse_ncsd(const uint8_t sector0[SECTOR_SIZE], int verbose) { - const ncsd_header_t * h = (ncsd_header_t *)sector0; - if (h->magic == 0x4453434e) { - if (verbose) { - //printf("NCSD magic found\n"); - } - } else { - if (verbose) { - //printf("NCSD magic not found\n"); - } - return -1; - } - if (verbose) { - //iprintf("size: %" PRIu32 " sectors, %s MB\n", h->size, to_mebi(h->size * SECTOR_SIZE)); - //iprintf("media ID: %08" PRIx32 "%08" PRIx32 "\n", h->media_id_h, h->media_id_l); - } - - for (unsigned i = 0; i < NCSD_PARTITIONS; ++i) { - unsigned fs_type = h->fs_types[i]; - if (fs_type == 0) { - break; - } - const char *s_fs_type; - switch (fs_type) { - case 1: - s_fs_type = "Normal"; - break; - case 3: - s_fs_type = "FIRM"; - break; - case 4: - s_fs_type = "AGB_FIRM save"; - break; - default: - if (verbose) { - //iprintf("invalid partition type %d\n", fs_type); - } - return -2; - } - if (verbose) { - // yes I use MB for "MiB", bite me - //iprintf("partition %u, %s, crypt: %" PRIu8 ", offset: 0x%08" PRIx32 ", length: 0x%08" PRIx32 "(%s MB)\n", - //i, s_fs_type, h->crypt_types[i], - //h->partitions[i].offset, h->partitions[i].length, to_mebi(h->partitions[i].length * SECTOR_SIZE)); - } - } - return 0; -} - -const mbr_partition_t ptable_DSi[MBR_PARTITIONS] = { - {0, {3, 24, 4}, 6, {15, 224, 59}, 0x00000877, 0x00066f89}, - {0, {2, 206, 60}, 6, {15, 224, 190}, 0x0006784d, 0x000105b3}, - {0, {2, 222, 191}, 1, {15, 224, 191}, 0x00077e5d, 0x000001a3}, - {0, {0, 0, 0}, 0, {0, 0, 0}, 0, 0} -}; - -const mbr_partition_t ptable_3DS[MBR_PARTITIONS] = { - {0, {4, 24, 0}, 6, {1, 160, 63}, 0x00000097, 0x00047da9}, - {0, {4, 142, 64}, 6, {1, 160, 195}, 0x0004808d, 0x000105b3}, - {0, {0, 0, 0}, 0, {0, 0, 0}, 0, 0}, - {0, {0, 0, 0}, 0, {0, 0, 0}, 0, 0} -}; - -// return 0 for valid MBR -int parse_mbr(const uint8_t sector0[SECTOR_SIZE], int is3DS, int verbose) { - const mbr_t *m = (mbr_t*)sector0; - const mbr_partition_t *ref_ptable; // reference partition table - int ret = 0; - if (m->boot_signature_0 != 0x55 || m->boot_signature_1 != 0xaa) { - //printf("invalid boot signature(0x55, 0xaa)\n"); - ret = -1; - } - if (!is3DS) { - for (unsigned i = 0; i < sizeof(m->bootstrap); ++i) { - if (m->bootstrap[i]) { - //printf("bootstrap on DSi should be all zero\n"); - ret = 0; - break; - } - } - ref_ptable = ptable_DSi; - } else { - ref_ptable = ptable_3DS; - } - // Only check the first two as those are the only ones we mount - // There's some variation in the 3rd - for(int i = 0; i < 2; i++) { - if (memcmp(&ref_ptable[i], &m->partitions[i], sizeof(mbr_partition_t))) { - //printf("invalid partition table\n"); - ret = -2; - } - } - return ret; -} diff --git a/arm9/source/sector0.h b/arm9/source/sector0.h deleted file mode 100644 index 83c80af8..00000000 --- a/arm9/source/sector0.h +++ /dev/null @@ -1,72 +0,0 @@ -#pragma once - -#include -#include - -// https://3dbrew.org/wiki/NCSD#NCSD_header - -#define SECTOR_SIZE 0x200 - -#define NCSD_PARTITIONS 8 - -#ifdef _MSC_VER -#pragma pack(push, 1) -#define __PACKED -#elif defined __GNUC__ -#define __PACKED __attribute__ ((__packed__)) -#endif - -typedef struct { - uint32_t offset; - uint32_t length; -} __PACKED ncsd_partition_t; - -typedef struct { - uint8_t signature[0x100]; - uint32_t magic; - uint32_t size; - uint32_t media_id_l; - uint32_t media_id_h; - uint8_t fs_types[NCSD_PARTITIONS]; - uint8_t crypt_types[NCSD_PARTITIONS]; - ncsd_partition_t partitions[NCSD_PARTITIONS]; -} __PACKED ncsd_header_t; - -typedef struct { - uint8_t head; - uint8_t sector; - uint8_t cylinder; -} __PACKED chs_t; - -typedef struct { - uint8_t status; - chs_t chs_first; - uint8_t type; - chs_t chs_last; - uint32_t offset; - uint32_t length; -} __PACKED mbr_partition_t; - -#define MBR_PARTITIONS 4 -// or 446 in decimal, all zero on DSi in all my samples -#define MBR_BOOTSTRAP_SIZE 0x1be - -typedef struct { - uint8_t bootstrap[MBR_BOOTSTRAP_SIZE]; - mbr_partition_t partitions[MBR_PARTITIONS]; - uint8_t boot_signature_0; - uint8_t boot_signature_1; -} __PACKED mbr_t; - -#ifdef _MSC_VER -#pragma pack(pop) -#endif -#undef __PACKED - - -static_assert(sizeof(ncsd_header_t) == 0x160, "sizeof(ncsd_header_t) should equal 0x160"); -static_assert(sizeof(mbr_t) == SECTOR_SIZE, "sizeof(mbr_t) should equal 0x200"); - -int parse_ncsd(const uint8_t sector0[SECTOR_SIZE], int verbose); - -int parse_mbr(const uint8_t sector0[SECTOR_SIZE], int is3DS, int verbose); diff --git a/arm9/source/startMenu.cpp b/arm9/source/startMenu.cpp index 2f5d5a1d..bf79b1a7 100644 --- a/arm9/source/startMenu.cpp +++ b/arm9/source/startMenu.cpp @@ -10,6 +10,7 @@ #include #include +#include #include #define ITEMS_PER_SCREEN 8 @@ -68,7 +69,7 @@ void startMenu() { int cursorPosition = 0; u16 pressed, held; - while(1) { + while(pmMainLoop()) { font->clear(false); font->print(0, 3, false, STR_START_MENU, Alignment::center); for(int i = 0; i < (int)startMenuItems.size(); i++) { @@ -85,7 +86,7 @@ void startMenu() { scanKeys(); pressed = keysDown(); held = keysDownRepeat(); - } while(!held); + } while(pmMainLoop() && !held); if(held & KEY_UP) { cursorPosition--; @@ -101,8 +102,9 @@ void startMenu() { systemShutDown(); break; case StartMenuItem::reboot: - fifoSendValue32(FIFO_USER_02, 1); - while(1) swiWaitForVBlank(); + // TODO: Update for calico + // fifoSendValue32(FIFO_USER_02, 1); + while(pmMainLoop()) swiWaitForVBlank(); break; case StartMenuItem::titleManager: titleManager(); @@ -129,7 +131,7 @@ void languageMenu() { do { scanKeys(); swiWaitForVBlank(); - } while (!(keysDownRepeat() & KEY_A)); + } while (pmMainLoop() && !(keysDownRepeat() & KEY_A)); return; } @@ -146,7 +148,7 @@ void languageMenu() { } u16 pressed, held; - while(1) { + while(pmMainLoop()) { if(cursorPosition - scrollPosition >= ITEMS_PER_SCREEN) { scrollPosition = cursorPosition - ITEMS_PER_SCREEN + 1; } else if(cursorPosition < scrollPosition) { @@ -169,7 +171,7 @@ void languageMenu() { scanKeys(); pressed = keysDown(); held = keysDownRepeat(); - } while(!held); + } while(pmMainLoop() && !held); if(held & KEY_UP) { cursorPosition--; diff --git a/arm9/source/titleManager.cpp b/arm9/source/titleManager.cpp index cce384f4..bf1d9003 100644 --- a/arm9/source/titleManager.cpp +++ b/arm9/source/titleManager.cpp @@ -67,7 +67,7 @@ void dumpTitle(TitleInfo &title) { int y = font->calcHeight(dumpToStr) + 1; - while (true) { + while (pmMainLoop()) { font->clear(false); font->print(firstCol, 0, false, dumpToStr, alignStart); @@ -113,7 +113,7 @@ void dumpTitle(TitleInfo &title) { pressed = keysDownRepeat(); held = keysHeld(); swiWaitForVBlank(); - } while (!(pressed & (KEY_UP| KEY_DOWN | KEY_A | KEY_B | KEY_L | config->screenSwapKey()))); + } while (pmMainLoop() && !(pressed & (KEY_UP| KEY_DOWN | KEY_A | KEY_B | KEY_L | config->screenSwapKey()))); if (pressed & KEY_UP) optionOffset--; @@ -278,7 +278,7 @@ void titleManager() { u16 pressed = 0, held = 0; int cursorPosition = 0, scrollOffset = 0; - while(1) { + while(pmMainLoop()) { font->clear(false); font->printf(firstCol, 0, false, alignStart, Palette::blackGreen, "%*c", SCREEN_COLS, ' '); font->print(0, 0, false, STR_TITLE_MANAGER, Alignment::center, Palette::blackGreen); @@ -297,7 +297,7 @@ void titleManager() { scanKeys(); pressed = keysDown(); held = keysDownRepeat(); - } while(!(held & (KEY_UP | KEY_DOWN | KEY_LEFT | KEY_RIGHT | KEY_A | KEY_B | KEY_L | config->screenSwapKey()))); + } while(pmMainLoop() && !(held & (KEY_UP | KEY_DOWN | KEY_LEFT | KEY_RIGHT | KEY_A | KEY_B | KEY_L | config->screenSwapKey()))); if(held & KEY_UP) { cursorPosition--; diff --git a/arm9/source/types.h b/arm9/source/types.h deleted file mode 100644 index 78bfc758..00000000 --- a/arm9/source/types.h +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef __TYPES_H__ -#define __TYPES_H__ - -#include -#include - -typedef uint8_t u8; -typedef uint16_t u16; -typedef uint32_t u32; -typedef uint64_t u64; - -typedef int8_t s8; -typedef int16_t s16; -typedef int32_t s32; -typedef int64_t s64; - - -enum flags -{ - ExtractFlag = (1<<0), - InfoFlag = (1<<1), - PlainFlag = (1<<2), - VerboseFlag = (1<<3), - VerifyFlag = (1<<4), - RawFlag = (1<<5), - ShowKeysFlag = (1<<6), - DecompressCodeFlag = (1<<7) -}; - -enum validstate -{ - Unchecked = 0, - Good = 1, - Fail = 2, -}; - -enum sizeunits -{ - sizeKB = 0x400, - sizeMB = 0x100000, -}; - -#endif diff --git a/arm9/source/utils.c b/arm9/source/utils.c index 3555cde2..4ac6e5ae 100644 --- a/arm9/source/utils.c +++ b/arm9/source/utils.c @@ -145,7 +145,7 @@ int save_sha1_file(const char *filename) { size_t len_buf = 2 * 20 + 1 + 1 + len_fn + 1; char *sha1_buf = (char *)malloc(len_buf + 1); // extra for \0 char *p = sha1_buf; - char *digest = (char *)malloc(20); + u8 *digest = (u8 *)malloc(20); SHA1Final(digest, &sha1ctx); for (int i = 0; i < 20; ++i) { p += siprintf(p, "%02X", digest[i]); diff --git a/bootloader/Makefile b/bootloader/Makefile index 761972ef..87cf8d52 100644 --- a/bootloader/Makefile +++ b/bootloader/Makefile @@ -18,22 +18,22 @@ SOURCES := source source/patches INCLUDES := build SPECS := specs + #--------------------------------------------------------------------------------- # options for code generation #--------------------------------------------------------------------------------- -ARCH := -mthumb -mthumb-interwork +ARCH := -mthumb -mthumb-interwork -march=armv4t -mtune=arm7tdmi -CFLAGS := -g -Wall -O2\ - -mcpu=arm7tdmi -mtune=arm7tdmi -fomit-frame-pointer\ - -ffast-math \ +CFLAGS := -g -Wall -Os \ + -ffunction-sections -fdata-sections \ $(ARCH) CFLAGS += $(INCLUDE) $(EXTRA_CFLAGS) -DARM7 ASFLAGS := -g $(ARCH) $(EXTRA_CFLAGS) $(INCLUDE) -LDFLAGS = -nostartfiles -T $(TOPDIR)/load.ld -g $(ARCH) -Wl,-Map,$(TARGET).map +LDFLAGS = -nostartfiles -T $(TOPDIR)/load.ld -Wl,--no-warn-rwx-segments,--nmagic,--gc-sections -g $(ARCH) -Wl,-Map,$(TARGET).map -LIBS := +LIBS := -lnds7 -lcalico_ds7 #--------------------------------------------------------------------------------- # list of directories containing libraries, this must be the top level containing diff --git a/bootloader/load.ld b/bootloader/load.ld index 566c3e6d..c148eeb0 100644 --- a/bootloader/load.ld +++ b/bootloader/load.ld @@ -3,18 +3,19 @@ OUTPUT_ARCH(arm) ENTRY(_start) MEMORY { - - vram : ORIGIN = 0x06008000, LENGTH = 128K - 32K + wram : ORIGIN = 0x037f8000, LENGTH = 0x17000 + vram : ORIGIN = 0x06000000, LENGTH = 128K } -__vram_start = ORIGIN(vram); -__vram_top = ORIGIN(vram)+ LENGTH(vram); -__sp_irq = __vram_top - 0x60; -__sp_svc = __sp_irq - 0x100; -__sp_usr = __sp_svc - 0x100; - -__irq_flags = __vram_top - 8; -__irq_vector = __vram_top - 4; +PROVIDE_HIDDEN( __sys_start = ORIGIN(wram) + LENGTH(wram) ); +PROVIDE_HIDDEN( __sp_usr = __sys_start + 0xe80 ); +PROVIDE_HIDDEN( __sp_irq = __sp_usr + 0x100 ); +PROVIDE_HIDDEN( __sp_svc = __sp_irq + 0x40 ); +PROVIDE_HIDDEN( __irq_flags2 = __sp_svc + 0x00 ); +PROVIDE_HIDDEN( __scfg_buf = __sp_svc + 0x04 ); +PROVIDE_HIDDEN( __dma_fill = __sp_svc + 0x20 ); +PROVIDE_HIDDEN( __irq_flags = __sp_svc + 0x38 ); +PROVIDE_HIDDEN( __irq_vector = __sp_svc + 0x3c ); SECTIONS { diff --git a/bootloader/source/arm9clear.arm.c b/bootloader/source/arm9clear.arm.c index 45077083..9a076f97 100644 --- a/bootloader/source/arm9clear.arm.c +++ b/bootloader/source/arm9clear.arm.c @@ -4,7 +4,6 @@ #include #include #include -#include #include #include @@ -23,8 +22,8 @@ Modified by Chishm: --------------------------------------------------------------------------*/ void __attribute__ ((long_call)) __attribute__((naked)) __attribute__((noreturn)) resetMemory2_ARM9 (void) { - register int i, reg; - + register int i; + //clear out ARM9 DMA channels for (i=0; i<4; i++) { DMA_CR(i) = 0; @@ -32,26 +31,19 @@ void __attribute__ ((long_call)) __attribute__((naked)) __attribute__((noreturn) DMA_DEST(i) = 0; TIMER_CR(i) = 0; TIMER_DATA(i) = 0; - for (reg=0; reg<0x1c; reg+=4)*((vu32*)(0x04004104 + ((i*0x1c)+reg))) = 0;//Reset NDMA. } - // Clear out FIFO - REG_IPC_SYNC = 0; - REG_IPC_FIFO_CR = IPC_FIFO_ENABLE | IPC_FIFO_SEND_CLEAR; - REG_IPC_FIFO_CR = 0; - VRAM_CR = (VRAM_CR & 0xffff0000) | 0x00008080 ; - + vu16 *mainregs = (vu16*)0x04000000; vu16 *subregs = (vu16*)0x04001000; - + for (i=0; i<43; i++) { mainregs[i] = 0; subregs[i] = 0; } - + REG_DISPSTAT = 0; - GFX_STATUS = 0; VRAM_A_CR = 0; VRAM_B_CR = 0; @@ -88,19 +80,6 @@ Modified by Chishm: --------------------------------------------------------------------------*/ void __attribute__ ((long_call)) __attribute__((noreturn)) __attribute__((naked)) startBinary_ARM9 (void) { - if ((*(u8*)0x2FFE012 == *(u8*)0x2FFFE12) && (*(u8*)0x2FFE012 > 0)) { - *(vu32*)REG_MBK1 = *(u32*)0x02FFE180; - *(vu32*)REG_MBK2 = *(u32*)0x02FFE184; - *(vu32*)REG_MBK3 = *(u32*)0x02FFE188; - *(vu32*)REG_MBK4 = *(u32*)0x02FFE18C; - *(vu32*)REG_MBK5 = *(u32*)0x02FFE190; - REG_MBK6 = *(u32*)0x02FFE194; - REG_MBK7 = *(u32*)0x02FFE198; - REG_MBK8 = *(u32*)0x02FFE19C; - REG_MBK9 = *(u32*)0x02FFE1AC; - WRAM_CR = *(u8*)0x02FFE1AF; - } - REG_IME=0; REG_EXMEMCNT = 0xE880; // set ARM9 load address to 0 and wait for it to change again diff --git a/bootloader/source/bios.s b/bootloader/source/bios.s deleted file mode 100644 index e98f57c4..00000000 --- a/bootloader/source/bios.s +++ /dev/null @@ -1,13 +0,0 @@ - .text - .align 4 - - .thumb - -@--------------------------------------------------------------------------------- - .global swiDelay - .thumb_func -@--------------------------------------------------------------------------------- -swiDelay: -@--------------------------------------------------------------------------------- - swi 0x03 - bx lr diff --git a/bootloader/source/boot.c b/bootloader/source/boot.c index e8392ae9..36b43a8a 100644 --- a/bootloader/source/boot.c +++ b/bootloader/source/boot.c @@ -38,148 +38,76 @@ Helpful information: #include #include #include -#define ARM9 -#undef ARM7 #include -#include -#include -#undef ARM9 -#define ARM7 #include -#include -#include "dmaTwl.h" -#include "tonccpy.h" -#include "fat.h" -#include "dldi_patcher.h" -#include "card.h" +#include +#include #include "boot.h" +#include "io_dldi.h" +#include "sdmmc.h" +#include "minifat.h" //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Important things -#define TEMP_MEM 0x02FFD000 -#define TWL_HEAD 0x02FFE000 -#define NDS_HEAD 0x02FFFE00 -#define TEMP_ARM9_START_ADDRESS (*(vu32*)0x02FFFFF4) +#define TEMP_MEM MM_ENV_FREE_D000 +#define ARM9_START_ADDRESS (*(vu32*)&g_envAppNdsHeader->arm9_entrypoint) +#define DEFAULT_BOOT_NAME "BOOT.NDS" - -const char* bootName = "BOOT.NDS"; +extern volatile uptr __irq_vector; extern unsigned long _start; extern unsigned long storedFileCluster; -extern unsigned long initDisc; extern unsigned long wantToPatchDLDI; extern unsigned long argStart; extern unsigned long argSize; extern unsigned long dsiSD; extern unsigned long dsiMode; -bool sdRead = false; - -//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -// Firmware stuff - -#define FW_READ 0x03 - -void boot_readFirmware (uint32 address, uint8 * buffer, uint32 size) { - uint32 index; - - // Read command - while (REG_SPICNT & SPI_BUSY); - REG_SPICNT = SPI_ENABLE | SPI_CONTINUOUS | SPI_DEVICE_NVRAM; - REG_SPIDATA = FW_READ; - while (REG_SPICNT & SPI_BUSY); - - // Set the address - REG_SPIDATA = (address>>16) & 0xFF; - while (REG_SPICNT & SPI_BUSY); - REG_SPIDATA = (address>>8) & 0xFF; - while (REG_SPICNT & SPI_BUSY); - REG_SPIDATA = (address) & 0xFF; - while (REG_SPICNT & SPI_BUSY); - - for (index = 0; index < size; index++) { - REG_SPIDATA = 0; - while (REG_SPICNT & SPI_BUSY); - buffer[index] = REG_SPIDATA & 0xFF; - } - REG_SPICNT = 0; -} - +static uptr temp_arm9_start_address; -static inline void copyLoop (u32* dest, const u32* src, u32 size) { - size = (size +3) & ~3; - do { - *dest++ = *src++; - } while (size -= 4); -} +static char boot_nds[] = "fat:/boot.nds"; +static unsigned long argbuf[4]; -//#define resetCpu() __asm volatile("\tswi 0x000000\n"); +static MiniFat fatState; /*------------------------------------------------------------------------- passArgs_ARM7 Copies the command line arguments to the end of the ARM9 binary, then sets a flag in memory for the loaded NDS to use --------------------------------------------------------------------------*/ -void passArgs_ARM7 (void) { - u32 ARM9_DST = *((u32*)(NDS_HEAD + 0x028)); - u32 ARM9_LEN = *((u32*)(NDS_HEAD + 0x02C)); - u32* argSrc; - u32* argDst; - - if (!argStart || !argSize) return; - - if ( ARM9_DST == 0 && ARM9_LEN == 0) { - ARM9_DST = *((u32*)(NDS_HEAD + 0x038)); - ARM9_LEN = *((u32*)(NDS_HEAD + 0x03C)); - } - - argSrc = (u32*)(argStart + (int)&_start); - - argDst = (u32*)((ARM9_DST + ARM9_LEN + 3) & ~3); // Word aligned - - if (ARM9_LEN > 0x380000) { - argDst = (u32*)(TEMP_MEM - ((argSize/4)*4)); - } else if (dsiMode && (*(u8*)(NDS_HEAD + 0x012) & BIT(1))) { - u32 ARM9i_DST = *((u32*)(TWL_HEAD + 0x1C8)); - u32 ARM9i_LEN = *((u32*)(TWL_HEAD + 0x1CC)); - if (ARM9i_LEN) - { - u32* argDst2 = (u32*)((ARM9i_DST + ARM9i_LEN + 3) & ~3); // Word aligned - if (argDst2 > argDst) - argDst = argDst2; +static void passArgs_ARM7 (void) { + void* argSrc; + void* argDst; + + if (!argStart || !argSize) { + char *arg = boot_nds; + argSize = __builtin_strlen(boot_nds); + + if (dsiSD) { + arg++; + arg[0] = 's'; + arg[1] = 'd'; } + __builtin_memcpy(argbuf,arg,argSize+1); + argSrc = argbuf; + } else { + argSrc = (void*)(argStart + (uptr)&_start); } - copyLoop(argDst, argSrc, argSize); - - __system_argv->argvMagic = ARGV_MAGIC; - __system_argv->commandLine = (char*)argDst; - __system_argv->length = argSize; -} - - + argDst = (void*)((g_envAppNdsHeader->arm9_ram_address + g_envAppNdsHeader->arm9_size + 3) & ~3); // Word aligned + if (dsiMode && (g_envAppNdsHeader->unitcode & BIT(1)) && g_envAppTwlHeader->arm9i_size) + { + void* argDst2 = (void*)((g_envAppTwlHeader->arm9i_ram_address + g_envAppTwlHeader->arm9i_size + 3) & ~3); // Word aligned + if (argDst2 > argDst) + argDst = argDst2; + } -static void initMBK_dsiMode(void) { - // This function has no effect with ARM7 SCFG locked - *(vu32*)REG_MBK1 = *(u32*)0x02FFE180; - *(vu32*)REG_MBK2 = *(u32*)0x02FFE184; - *(vu32*)REG_MBK3 = *(u32*)0x02FFE188; - *(vu32*)REG_MBK4 = *(u32*)0x02FFE18C; - *(vu32*)REG_MBK5 = *(u32*)0x02FFE190; - REG_MBK6 = *(u32*)0x02FFE1A0; - REG_MBK7 = *(u32*)0x02FFE1A4; - REG_MBK8 = *(u32*)0x02FFE1A8; - REG_MBK9 = *(u32*)0x02FFE1AC; -} + armCopyMem32(argDst, argSrc, (argSize + 3) &~ 3); -void memset_addrs_arm7(u32 start, u32 end) -{ - if (!dsiMode && !(REG_SCFG_EXT & BIT(16))) { - toncset((u32*)start, 0, ((int)end - (int)start)); - return; - } - dma_twlFill32(0, 0, (u32*)start, ((int)end - (int)start)); + g_envNdsArgvHeader->magic = ENV_NDS_ARGV_MAGIC; + g_envNdsArgvHeader->args_str = argDst; + g_envNdsArgvHeader->args_str_size = argSize; } /*------------------------------------------------------------------------- @@ -189,15 +117,19 @@ Written by Darkain. Modified by Chishm: * Added STMIA clear mem loop --------------------------------------------------------------------------*/ -void resetMemory_ARM7 (void) +static void resetMemory_ARM7 (void) { - int i, reg; - u8 settings1, settings2; - u32 settingsOffset = 0; - + // Reset the interrupt controller & related BIOS variables REG_IME = 0; + REG_IE = 0; + REG_IF = ~0; + __irq_vector = 0; + __irq_flags = ~0; + __irq_flags2 = ~0; - for (i=0; i<16; i++) { + REG_POWCNT = POWCNT_SOUND; //turn off power to stuff + + for (unsigned i=0; i<16; i++) { SCHANNEL_CR(i) = 0; SCHANNEL_TIMER(i) = 0; SCHANNEL_SOURCE(i) = 0; @@ -205,103 +137,71 @@ void resetMemory_ARM7 (void) } REG_SOUNDCNT = 0; - REG_SNDCAP0CNT = 0; - REG_SNDCAP1CNT = 0; - - REG_SNDCAP0DAD = 0; - REG_SNDCAP0LEN = 0; - REG_SNDCAP1DAD = 0; - REG_SNDCAP1LEN = 0; //clear out ARM7 DMA channels and timers - for (i=0; i<4; i++) { + for (unsigned i=0; i<4; i++) { DMA_CR(i) = 0; DMA_SRC(i) = 0; DMA_DEST(i) = 0; TIMER_CR(i) = 0; TIMER_DATA(i) = 0; - for (reg=0; reg<0x1c; reg+=4)*((vu32*)(0x04004104 + ((i*0x1c)+reg))) = 0;//Reset NDMA. } - memset_addrs_arm7(0x03800000 - 0x8000, 0x03800000 + (dsiMode ? 0xC000 : 0x10000)); // clear exclusive IWRAM - memset_addrs_arm7(0x02004000, (dsiMode ? 0x03000000 : 0x02400000) - 0xC000); // clear part of EWRAM - except before bootstub + // Clear most of ARM7 exclusive WRAM + extern char __sys_start[]; + armFillMem32((void*)MM_A7WRAM, 0, __sys_start - (char*)MM_A7WRAM); - REG_IE = 0; - REG_IF = ~0; - REG_AUXIE = 0; - REG_AUXIF = ~0; - *(vu32*)0x0380FFFC = 0; // IRQ_HANDLER ARM7 version - *(vu32*)0x0380FFF8 = 0; // VBLANK_INTR_WAIT_FLAGS, ARM7 version - REG_POWERCNT = 1; //turn off power to stuff - - // Get settings location - boot_readFirmware((u32)0x00020, (u8*)&settingsOffset, 0x2); - settingsOffset *= 8; - - // Reload DS Firmware settings - boot_readFirmware(settingsOffset + 0x070, &settings1, 0x1); - boot_readFirmware(settingsOffset + 0x170, &settings2, 0x1); - - if ((settings1 & 0x7F) == ((settings2+1) & 0x7F)) { - boot_readFirmware(settingsOffset + 0x000, (u8*)0x02FFFC80, 0x70); - } else { - boot_readFirmware(settingsOffset + 0x100, (u8*)0x02FFFC80, 0x70); + // Clear most of main RAM + uptr main_ram_clr_begin = dsiMode ? MM_ENV_TWL_AUTOLOAD_EXT : MM_MAINRAM; + uptr main_ram_clr_end = MM_ENV_HB_BOOTSTUB - (dsiMode ? 0 : (MM_MAINRAM_SZ_TWL-MM_MAINRAM_SZ_NTR)); + armFillMem32((void*)main_ram_clr_begin, 0, main_ram_clr_end-main_ram_clr_begin); + + // Repair ARM7 mirror of SCFG regs if they have been previously cleared out + if (dsiMode && !__scfg_buf.ext && !__scfg_buf.other) { + __scfg_buf.ext = g_scfgBackup->ext; + __scfg_buf.other = g_scfgBackup->other; } - ((vu32*)0x040044f0)[2] = 0x202DDD1D; - ((vu32*)0x040044f0)[3] = 0xE1A00005; - while((*(vu32*)0x04004400) & 0x2000000); + // XX: Previously we would read user settings from NVRAM here. However, + // either the previously loaded app or the app we want to load are + // guaranteed to be hbmenu, which already does this on startup by virtue + // of being compiled with a modern enough version of libnds. + // Repair AES keyslot used by NAND encryption + if (dsiMode) { + REG_AES_SLOTxY(3).data[2] = 0x202DDD1D; + REG_AES_SLOTxY(3).data[3] = 0xE1A00005; + aesBusyWaitReady(); + } } - -u32 ROM_TID; - -void loadBinary_ARM7 (u32 fileCluster) +static void loadBinary_ARM7 (u32 fileCluster) { - u32 ndsHeader[0x170>>2]; + EnvNdsHeader ndsHeader; // read NDS header - fileRead ((char*)ndsHeader, fileCluster, 0, 0x170); - // read ARM9 info from NDS header - u32 ARM9_SRC = ndsHeader[0x020>>2]; - char* ARM9_DST = (char*)ndsHeader[0x028>>2]; - u32 ARM9_LEN = ndsHeader[0x02C>>2]; - // read ARM7 info from NDS header - u32 ARM7_SRC = ndsHeader[0x030>>2]; - char* ARM7_DST = (char*)ndsHeader[0x038>>2]; - u32 ARM7_LEN = ndsHeader[0x03C>>2]; - - ROM_TID = ndsHeader[0x00C>>2]; + minifatRead(&fatState, fileCluster, &ndsHeader, 0, sizeof(ndsHeader)); // Load binaries into memory - fileRead(ARM9_DST, fileCluster, ARM9_SRC, ARM9_LEN); - fileRead(ARM7_DST, fileCluster, ARM7_SRC, ARM7_LEN); + minifatRead(&fatState, fileCluster, (void*)ndsHeader.arm9_ram_address, ndsHeader.arm9_rom_offset, ndsHeader.arm9_size); + minifatRead(&fatState, fileCluster, (void*)ndsHeader.arm7_ram_address, ndsHeader.arm7_rom_offset, ndsHeader.arm7_size); // first copy the header to its proper location, excluding // the ARM9 start address, so as not to start it - TEMP_ARM9_START_ADDRESS = ndsHeader[0x024>>2]; // Store for later - ndsHeader[0x024>>2] = 0; - dmaCopyWords(3, (void*)ndsHeader, (void*)NDS_HEAD, 0x170); + temp_arm9_start_address = ndsHeader.arm9_entrypoint; // Store for later + ndsHeader.arm9_entrypoint = 0; + dmaCopyWords(3, &ndsHeader, g_envAppNdsHeader, sizeof(EnvNdsHeader)); - if (dsiMode && (ndsHeader[0x10>>2]&BIT(16+1))) + if (dsiMode && (ndsHeader.unitcode & BIT(1))) { // Read full TWL header - fileRead((char*)TWL_HEAD, fileCluster, 0, 0x1000); - - u32 ARM9i_SRC = *(u32*)(TWL_HEAD+0x1C0); - char* ARM9i_DST = (char*)*(u32*)(TWL_HEAD+0x1C8); - u32 ARM9i_LEN = *(u32*)(TWL_HEAD+0x1CC); - u32 ARM7i_SRC = *(u32*)(TWL_HEAD+0x1D0); - char* ARM7i_DST = (char*)*(u32*)(TWL_HEAD+0x1D8); - u32 ARM7i_LEN = *(u32*)(TWL_HEAD+0x1DC); + minifatRead(&fatState, fileCluster, g_envAppTwlHeader, 0, sizeof(EnvTwlHeader)); - if (ARM9i_LEN) - fileRead(ARM9i_DST, fileCluster, ARM9i_SRC, ARM9i_LEN); - if (ARM7i_LEN) - fileRead(ARM7i_DST, fileCluster, ARM7i_SRC, ARM7i_LEN); - - initMBK_dsiMode(); + // Load TWL binaries into memory + if (g_envAppTwlHeader->arm9i_size) + minifatRead(&fatState, fileCluster, (void*)g_envAppTwlHeader->arm9i_ram_address, g_envAppTwlHeader->arm9i_rom_offset, g_envAppTwlHeader->arm9i_size); + if (g_envAppTwlHeader->arm7i_size) + minifatRead(&fatState, fileCluster, (void*)g_envAppTwlHeader->arm7i_ram_address, g_envAppTwlHeader->arm7i_rom_offset, g_envAppTwlHeader->arm7i_size); } } @@ -312,101 +212,92 @@ Written by Darkain. Modified by Chishm: * Removed MultiNDS specific stuff --------------------------------------------------------------------------*/ -void startBinary_ARM7 (void) { +static void startBinary_ARM7 (void) { REG_IME=0; while(REG_VCOUNT!=191); while(REG_VCOUNT==191); // copy NDS ARM9 start address into the header, starting ARM9 - *((vu32*)0x02FFFE24) = TEMP_ARM9_START_ADDRESS; + ARM9_START_ADDRESS = temp_arm9_start_address; ARM9_START_FLAG = 1; // Start ARM7 - VoidFn arm7code = *(VoidFn*)(0x2FFFE34); + VoidFn arm7code = (VoidFn)g_envAppNdsHeader->arm7_entrypoint; arm7code(); } -void mpu_reset(); -void mpu_reset_end(); +extern const char mpu_reset[]; +extern const char mpu_reset_end[]; int main (void) { #ifdef NO_DLDI dsiSD = true; dsiMode = true; #endif + + bool ok = false; + MiniFatDiscReadFn readFn; + #ifndef NO_SDMMC - sdRead = (dsiSD && dsiMode); + if (dsiSD && dsiMode) { + sdmmc_controller_init(true); + ok = sdmmc_sdcard_init() == 0; + readFn = sdmmc_sdcard_readsectors; + } +#ifndef NO_DLDI + else #endif - if (wantToPatchDLDI) { - toncset((u32*)0x06000000, 0, 0x8000); - if (*(u32*)0x02FF4184 == 0x69684320) { // DLDI ' Chi' string in bootstub space + bootloader in DLDI driver space - const u16 dldiFileSize = 1 << *(u8*)0x02FF418D; - tonccpy((u32*)0x06000000, (u32*)0x02FF4180, dldiFileSize); - dldiRelocateBinary(); - - toncset((u32*)0x02FF4000, 0, 0x8180); // Clear bootstub + DLDI driver - } else if (*(u32*)0x02FF8004 == 0x69684320) { // DLDI ' Chi' string - const u16 dldiFileSize = 1 << *(u8*)0x02FF800D; - tonccpy((u32*)0x06000000, (u32*)0x02FF8000, (dldiFileSize > 0x4000) ? 0x4000 : dldiFileSize); - dldiClearBss(); - } else if (*(u32*)0x02FF8000 == 0x53535A4C) { // LZ77 flag - dldiDecompressBinary(); - } else { - return -1; - } +#endif +#ifndef NO_DLDI + { + ok = _io_dldi.startup(); + readFn = _io_dldi.readSectors; } +#endif u32 fileCluster = storedFileCluster; // Init card - if(!FAT_InitFiles(initDisc)) + if(!ok || !minifatInit(&fatState, readFn, 0)) { return -1; } - if ((fileCluster < CLUSTER_FIRST) || (fileCluster >= CLUSTER_EOF)) /* Invalid file cluster specified */ - { - fileCluster = getBootFileCluster(bootName); - } - if (fileCluster == CLUSTER_FREE) + if (fileCluster < MINIFAT_CLUSTER_FIRST) /* Invalid file cluster specified */ { - return -1; + MiniFatDirEnt ent; + fileCluster = minifatFind(&fatState, 0, DEFAULT_BOOT_NAME, &ent); + if (fileCluster < MINIFAT_CLUSTER_FIRST || (ent.attrib & MINIFAT_ATTRIB_DIR)) + { + return -1; + } } // ARM9 clears its memory part 2 // copy ARM9 function to RAM, and make the ARM9 jump to it - copyLoop((void*)TEMP_MEM, (void*)resetMemory2_ARM9, resetMemory2_ARM9_size); - (*(vu32*)0x02FFFE24) = (u32)TEMP_MEM; // Make ARM9 jump to the function + armCopyMem32((void*)TEMP_MEM, resetMemory2_ARM9, resetMemory2_ARM9_size); + ARM9_START_ADDRESS = TEMP_MEM; // Make ARM9 jump to the function // Wait until the ARM9 has completed its task - while ((*(vu32*)0x02FFFE24) == (u32)TEMP_MEM); + while (ARM9_START_ADDRESS == TEMP_MEM); // ARM9 sets up mpu // copy ARM9 function to RAM, and make the ARM9 jump to it - copyLoop((void*)TEMP_MEM, (void*)mpu_reset, mpu_reset_end - mpu_reset); - (*(vu32*)0x02FFFE24) = (u32)TEMP_MEM; // Make ARM9 jump to the function + armCopyMem32((void*)TEMP_MEM, mpu_reset, mpu_reset_end - mpu_reset); + ARM9_START_ADDRESS = TEMP_MEM; // Make ARM9 jump to the function // Wait until the ARM9 has completed its task - while ((*(vu32*)0x02FFFE24) == (u32)TEMP_MEM); + while (ARM9_START_ADDRESS == TEMP_MEM); // Get ARM7 to clear RAM resetMemory_ARM7(); // ARM9 enters a wait loop // copy ARM9 function to RAM, and make the ARM9 jump to it - copyLoop((void*)TEMP_MEM, (void*)startBinary_ARM9, startBinary_ARM9_size); - (*(vu32*)0x02FFFE24) = (u32)TEMP_MEM; // Make ARM9 jump to the function + armCopyMem32((void*)TEMP_MEM, startBinary_ARM9, startBinary_ARM9_size); + ARM9_START_ADDRESS = TEMP_MEM; // Make ARM9 jump to the function // Load the NDS file loadBinary_ARM7(fileCluster); - sdRead = false; - - // Fix for Pictochat and DLP - if (ROM_TID == 0x41444E48 || ROM_TID == 0x41454E48 - || ROM_TID == 0x43444E48 || ROM_TID == 0x43454E48 - || ROM_TID == 0x4B444E48 || ROM_TID == 0x4B454E48) { - (*(vu16*)0x02FFFCFA) = 0x1041; // NoCash: channel ch1+7+13 - } - #ifndef NO_DLDI // Patch with DLDI if desired if (wantToPatchDLDI) { - dldiPatchBinary ((u8*)((u32*)NDS_HEAD)[0x0A], ((u32*)NDS_HEAD)[0x0B]); + dldiPatchBinary((void*)g_envAppNdsHeader->arm9_ram_address, g_envAppNdsHeader->arm9_size, &_dldi_start); } #endif @@ -426,4 +317,3 @@ int main (void) { return 0; } - diff --git a/bootloader/source/boot.h b/bootloader/source/boot.h index 81b9ccc4..e71d9ff6 100644 --- a/bootloader/source/boot.h +++ b/bootloader/source/boot.h @@ -3,7 +3,7 @@ #define resetMemory2_ARM9_size 0x400 void __attribute__ ((long_call)) __attribute__((naked)) __attribute__((noreturn)) resetMemory2_ARM9(); -#define startBinary_ARM9_size 0x200 +#define startBinary_ARM9_size 0x100 void __attribute__ ((long_call)) __attribute__((noreturn)) __attribute__((naked)) startBinary_ARM9 (); #define ARM9_START_FLAG (*(vu8*)0x02FFFDFB) diff --git a/bootloader/source/card.h b/bootloader/source/card.h deleted file mode 100644 index 388d5aab..00000000 --- a/bootloader/source/card.h +++ /dev/null @@ -1,52 +0,0 @@ -/*----------------------------------------------------------------- - - Copyright (C) 2005 Michael "Chishm" Chisholm - - 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - - If you use this code, please give due credit and email me about your - project at chishm@hotmail.com -------------------------------------------------------------------*/ - -#ifndef CARD_H -#define CARD_H - -#include "disc_io.h" -#include "io_dldi.h" -#include "sdmmc.h" - -extern bool sdRead; - -static inline bool CARD_StartUp (void) { - if (sdRead) { - sdmmc_controller_init(true); - return sdmmc_sdcard_init() == 0; - } - return _io_dldi.fn_startup(); -} - -static inline bool CARD_IsInserted (void) { - return sdRead ? true : _io_dldi.fn_isInserted(); -} - -static inline bool CARD_ReadSector (u32 sector, void *buffer) { - return sdRead ? (sdmmc_sdcard_readsectors(sector, 1, buffer) == 0) : _io_dldi.fn_readSectors(sector, 1, buffer); -} - -static inline bool CARD_ReadSectors (u32 sector, int count, void *buffer) { - return sdRead ? (sdmmc_sdcard_readsectors(sector, count, buffer) == 0) : _io_dldi.fn_readSectors(sector, count, buffer); -} - -#endif // CARD_H diff --git a/bootloader/source/disc_io.h b/bootloader/source/disc_io.h deleted file mode 100644 index 29033b76..00000000 --- a/bootloader/source/disc_io.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - disc_io.h - Interface template for low level disc functions. - - Copyright (c) 2006 Michael "Chishm" Chisholm - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - 3. The name of the author may not be used to endorse or promote products derived - from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - 2006-07-11 - Chishm - * Original release - - 2006-07-16 - Chishm - * Renamed _CF_USE_DMA to _IO_USE_DMA - * Renamed _CF_ALLOW_UNALIGNED to _IO_ALLOW_UNALIGNED -*/ - -#ifndef _DISC_IO_H -#define _DISC_IO_H - -#include -#define BYTES_PER_SECTOR 512 - -//---------------------------------------------------------------------- -// Customisable features - -// Use DMA to read the card, remove this line to use normal reads/writes -// #define _IO_USE_DMA - -// Allow buffers not alligned to 16 bits when reading files. -// Note that this will slow down access speed, so only use if you have to. -// It is also incompatible with DMA -#define _IO_ALLOW_UNALIGNED - -#if defined _IO_USE_DMA && defined _IO_ALLOW_UNALIGNED - #error "You can't use both DMA and unaligned memory" -#endif - -#define FEATURE_MEDIUM_CANREAD 0x00000001 -#define FEATURE_MEDIUM_CANWRITE 0x00000002 -#define FEATURE_SLOT_GBA 0x00000010 -#define FEATURE_SLOT_NDS 0x00000020 - -typedef bool (* FN_MEDIUM_STARTUP)(void) ; -typedef bool (* FN_MEDIUM_ISINSERTED)(void) ; -typedef bool (* FN_MEDIUM_READSECTORS)(u32 sector, u32 numSectors, void* buffer) ; -typedef bool (* FN_MEDIUM_WRITESECTORS)(u32 sector, u32 numSectors, const void* buffer) ; -typedef bool (* FN_MEDIUM_CLEARSTATUS)(void) ; -typedef bool (* FN_MEDIUM_SHUTDOWN)(void) ; - -struct IO_INTERFACE_STRUCT { - unsigned long ioType ; - unsigned long features ; - FN_MEDIUM_STARTUP fn_startup ; - FN_MEDIUM_ISINSERTED fn_isInserted ; - FN_MEDIUM_READSECTORS fn_readSectors ; - FN_MEDIUM_WRITESECTORS fn_writeSectors ; - FN_MEDIUM_CLEARSTATUS fn_clearStatus ; - FN_MEDIUM_SHUTDOWN fn_shutdown ; -} ; - -typedef struct IO_INTERFACE_STRUCT IO_INTERFACE ; - -#endif // define _DISC_IO_H diff --git a/bootloader/source/dldi_patcher.c b/bootloader/source/dldi_patcher.c deleted file mode 100644 index 2a52756a..00000000 --- a/bootloader/source/dldi_patcher.c +++ /dev/null @@ -1,341 +0,0 @@ -/*----------------------------------------------------------------- - - Copyright (C) 2005 Michael "Chishm" Chisholm - - 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - - If you use this code, please give due credit and email me about your - project at chishm@hotmail.com -------------------------------------------------------------------*/ -#ifndef NO_DLDI -#include -#include -#include "tonccpy.h" -#include "dldi_patcher.h" - -#define FIX_ALL 0x01 -#define FIX_GLUE 0x02 -#define FIX_GOT 0x04 -#define FIX_BSS 0x08 - -enum DldiOffsets { - DO_magicString = 0x00, // "\xED\xA5\x8D\xBF Chishm" - DO_magicToken = 0x00, // 0xBF8DA5ED - DO_magicShortString = 0x04, // " Chishm" - DO_version = 0x0C, - DO_driverSize = 0x0D, - DO_fixSections = 0x0E, - DO_allocatedSpace = 0x0F, - - DO_friendlyName = 0x10, - - DO_text_start = 0x40, // Data start - DO_data_end = 0x44, // Data end - DO_glue_start = 0x48, // Interworking glue start -- Needs address fixing - DO_glue_end = 0x4C, // Interworking glue end - DO_got_start = 0x50, // GOT start -- Needs address fixing - DO_got_end = 0x54, // GOT end - DO_bss_start = 0x58, // bss start -- Needs setting to zero - DO_bss_end = 0x5C, // bss end - - // IO_INTERFACE data - DO_ioType = 0x60, - DO_features = 0x64, - DO_startup = 0x68, - DO_isInserted = 0x6C, - DO_readSectors = 0x70, - DO_writeSectors = 0x74, - DO_clearStatus = 0x78, - DO_shutdown = 0x7C, - DO_code = 0x80 -}; - -static addr_t readAddr (data_t *mem, addr_t offset) { - return ((addr_t*)mem)[offset/sizeof(addr_t)]; -} - -static void writeAddr (data_t *mem, addr_t offset, addr_t value) { - ((addr_t*)mem)[offset/sizeof(addr_t)] = value; -} - - -static addr_t quickFind (const data_t* data, const data_t* search, size_t dataLen, size_t searchLen) { - const int* dataChunk = (const int*) data; - int searchChunk = ((const int*)search)[0]; - addr_t i; - addr_t dataChunkEnd = (addr_t)(dataLen / sizeof(int)); - - for (i = 0; i < dataChunkEnd; i++) { - if (dataChunk[i] == searchChunk) { - if ((i*sizeof(int) + searchLen) > dataLen) { - return -1; - } - if (memcmp (&data[i*sizeof(int)], search, searchLen) == 0) { - return i*sizeof(int); - } - } - } - - return -1; -} - -// Strings are stored with bit 0x20 flipped (case inverted) to prevent accidental DLDI patching of them -#define DLDI_MAGIC_LEN 12 -#define DLDI_MAGIC_MANGLE_VALUE 0x20 -static const data_t dldiMagicStringMangled[DLDI_MAGIC_LEN] = "\xCD\x85\xAD\x9F\0cHISHM"; // Normal DLDI file - -// Demangle the magic string by XORing every byte with 0x20, except the NULL terminator -static void demangleMagicString(data_t *dest, const data_t *src) { - int i; - - memcpy(dest, src, DLDI_MAGIC_LEN); - for (i = 0; i < DLDI_MAGIC_LEN - 1; ++i) { - dest[i] ^= DLDI_MAGIC_MANGLE_VALUE; - } -} - -#define DEVICE_TYPE_DLDI 0x49444C44 - -extern unsigned long dsiMode; -static data_t* _dldi_start = (data_t*)0x06000000; - -bool dldiPatchBinary (data_t *binData, u32 binSize) { - - addr_t memOffset; // Offset of DLDI after the file is loaded into memory - addr_t patchOffset; // Position of patch destination in the file - addr_t relocationOffset; // Value added to all offsets within the patch to fix it properly - addr_t ddmemOffset; // Original offset used in the DLDI file - addr_t ddmemStart; // Start of range that offsets can be in the DLDI file - addr_t ddmemEnd; // End of range that offsets can be in the DLDI file - addr_t ddmemSize; // Size of range that offsets can be in the DLDI file - addr_t addrIter; - - data_t *pDH; - data_t *pAH; - - data_t dldiMagicString[DLDI_MAGIC_LEN]; - size_t dldiFileSize = 0; - - // Find the DLDI reserved space in the file - demangleMagicString(dldiMagicString, dldiMagicStringMangled); - patchOffset = quickFind (binData, dldiMagicString, binSize, sizeof(dldiMagicString)); - - if (patchOffset < 0) { - // does not have a DLDI section - return false; - } - - pDH = _dldi_start; - pAH = &(binData[patchOffset]); - - if (*((u32*)(pDH + DO_ioType)) == DEVICE_TYPE_DLDI) { - // No DLDI patch - return false; - } - - dldiFileSize = 1 << pDH[DO_driverSize]; - - memOffset = readAddr (pAH, DO_text_start); - if (memOffset == 0) { - memOffset = readAddr (pAH, DO_startup) - DO_code; - } - - const bool largeDldi = (pDH[DO_driverSize] > pAH[DO_allocatedSpace]); - - if (largeDldi) { - const u32 a9exeAddress = *(u32*)0x02FFFE24; - u32* a9exe = (u32*)a9exeAddress; - const bool libnds2 = (a9exe[0] == 0xEA000007 && a9exe[1] == 0x39444F4D); - - if (!libnds2 && (memOffset < 0x02000000 || memOffset >= 0x03000000)) { - // Not enough space for patch in arm7 WRAM - return false; - } - - // u32** bootloader = (u32**)0x02FF4010; - const u32* bootloader = (u32*)0x02FF4168; - const u32 bootsize = *(u32*)0x02FF4014; - - tonccpy (pAH+DO_code, bootloader, bootsize); - *(u32*)0x02FF4010 = (u32)pAH+DO_code; - - // Relocate DLDI file to bootstub RAM space - pAH = (data_t*)(dsiMode ? 0x02FF4180 : 0x023F4180); - toncset (pAH, 0, 0x8000); - - memOffset = (addr_t)pAH; - } - ddmemOffset = readAddr (pDH, DO_text_start); - relocationOffset = memOffset - ddmemOffset; - - ddmemStart = readAddr (pDH, DO_text_start); - ddmemSize = (1 << pDH[DO_driverSize]); - ddmemEnd = ddmemStart + ddmemSize; - - // Remember how much space is actually reserved - pDH[DO_allocatedSpace] = pAH[DO_allocatedSpace]; - // Copy the DLDI patch into the application - tonccpy (pAH, pDH, dldiFileSize); - - // Fix the section pointers in the header - writeAddr (pAH, DO_text_start, readAddr (pAH, DO_text_start) + relocationOffset); - writeAddr (pAH, DO_data_end, readAddr (pAH, DO_data_end) + relocationOffset); - writeAddr (pAH, DO_glue_start, readAddr (pAH, DO_glue_start) + relocationOffset); - writeAddr (pAH, DO_glue_end, readAddr (pAH, DO_glue_end) + relocationOffset); - writeAddr (pAH, DO_got_start, readAddr (pAH, DO_got_start) + relocationOffset); - writeAddr (pAH, DO_got_end, readAddr (pAH, DO_got_end) + relocationOffset); - writeAddr (pAH, DO_bss_start, readAddr (pAH, DO_bss_start) + relocationOffset); - writeAddr (pAH, DO_bss_end, readAddr (pAH, DO_bss_end) + relocationOffset); - // Fix the function pointers in the header - writeAddr (pAH, DO_startup, readAddr (pAH, DO_startup) + relocationOffset); - writeAddr (pAH, DO_isInserted, readAddr (pAH, DO_isInserted) + relocationOffset); - writeAddr (pAH, DO_readSectors, readAddr (pAH, DO_readSectors) + relocationOffset); - writeAddr (pAH, DO_writeSectors, readAddr (pAH, DO_writeSectors) + relocationOffset); - writeAddr (pAH, DO_clearStatus, readAddr (pAH, DO_clearStatus) + relocationOffset); - writeAddr (pAH, DO_shutdown, readAddr (pAH, DO_shutdown) + relocationOffset); - - // Put the correct DLDI magic string back into the DLDI header - tonccpy (pAH, dldiMagicString, sizeof (dldiMagicString)); - - if (pDH[DO_fixSections] & FIX_ALL) { - // Search through and fix pointers within the data section of the file - for (addrIter = (readAddr(pDH, DO_text_start) - ddmemStart); addrIter < (readAddr(pDH, DO_data_end) - ddmemStart); addrIter++) { - if ((ddmemStart <= readAddr(pAH, addrIter)) && (readAddr(pAH, addrIter) < ddmemEnd)) { - writeAddr (pAH, addrIter, readAddr(pAH, addrIter) + relocationOffset); - } - } - } - - if (pDH[DO_fixSections] & FIX_GLUE) { - // Search through and fix pointers within the glue section of the file - for (addrIter = (readAddr(pDH, DO_glue_start) - ddmemStart); addrIter < (readAddr(pDH, DO_glue_end) - ddmemStart); addrIter++) { - if ((ddmemStart <= readAddr(pAH, addrIter)) && (readAddr(pAH, addrIter) < ddmemEnd)) { - writeAddr (pAH, addrIter, readAddr(pAH, addrIter) + relocationOffset); - } - } - } - - if (pDH[DO_fixSections] & FIX_GOT) { - // Search through and fix pointers within the Global Offset Table section of the file - for (addrIter = (readAddr(pDH, DO_got_start) - ddmemStart); addrIter < (readAddr(pDH, DO_got_end) - ddmemStart); addrIter++) { - if ((ddmemStart <= readAddr(pAH, addrIter)) && (readAddr(pAH, addrIter) < ddmemEnd)) { - writeAddr (pAH, addrIter, readAddr(pAH, addrIter) + relocationOffset); - } - } - } - - if (pDH[DO_fixSections] & FIX_BSS) { - // Initialise the BSS to 0 - toncset (&pAH[readAddr(pDH, DO_bss_start) - ddmemStart] , 0, readAddr(pDH, DO_bss_end) - readAddr(pDH, DO_bss_start)); - } - - if (largeDldi) { - data_t* pAH2 = &(binData[patchOffset]); - tonccpy (pAH2, pAH, DO_code); - } - - return true; -} - -void dldiDecompressBinary (void) { - extern void LZ77_Decompress(u8* source, u8* destination); - LZ77_Decompress((u8*)0x02FF8004, (u8*)_dldi_start); - - dldiRelocateBinary(); -} - -void dldiRelocateBinary (void) { - addr_t memOffset; // Offset of DLDI after the file is loaded into memory - addr_t relocationOffset; // Value added to all offsets within the patch to fix it properly - addr_t ddmemOffset; // Original offset used in the DLDI file - addr_t ddmemStart; // Start of range that offsets can be in the DLDI file - addr_t ddmemEnd; // End of range that offsets can be in the DLDI file - addr_t ddmemSize; // Size of range that offsets can be in the DLDI file - addr_t addrIter; - - data_t *pDH = _dldi_start; - - memOffset = 0x06000000; - ddmemOffset = readAddr (pDH, DO_text_start); - relocationOffset = memOffset - ddmemOffset; - - ddmemStart = readAddr (pDH, DO_text_start); - ddmemSize = (1 << pDH[DO_driverSize]); - ddmemEnd = ddmemStart + ddmemSize; - - // Fix the function pointers in the header - writeAddr (pDH, DO_startup, readAddr (pDH, DO_startup) + relocationOffset); - writeAddr (pDH, DO_isInserted, readAddr (pDH, DO_isInserted) + relocationOffset); - writeAddr (pDH, DO_readSectors, readAddr (pDH, DO_readSectors) + relocationOffset); - writeAddr (pDH, DO_writeSectors, readAddr (pDH, DO_writeSectors) + relocationOffset); - writeAddr (pDH, DO_clearStatus, readAddr (pDH, DO_clearStatus) + relocationOffset); - writeAddr (pDH, DO_shutdown, readAddr (pDH, DO_shutdown) + relocationOffset); - - if (pDH[DO_fixSections] & FIX_ALL) { - // Search through and fix pointers within the data section of the file - for (addrIter = (readAddr(pDH, DO_text_start) - ddmemStart); addrIter < (readAddr(pDH, DO_data_end) - ddmemStart); addrIter++) { - if ((ddmemStart <= readAddr(pDH, addrIter)) && (readAddr(pDH, addrIter) < ddmemEnd)) { - writeAddr (pDH, addrIter, readAddr(pDH, addrIter) + relocationOffset); - } - } - } - - if (pDH[DO_fixSections] & FIX_GLUE) { - // Search through and fix pointers within the glue section of the file - for (addrIter = (readAddr(pDH, DO_glue_start) - ddmemStart); addrIter < (readAddr(pDH, DO_glue_end) - ddmemStart); addrIter++) { - if ((ddmemStart <= readAddr(pDH, addrIter)) && (readAddr(pDH, addrIter) < ddmemEnd)) { - writeAddr (pDH, addrIter, readAddr(pDH, addrIter) + relocationOffset); - } - } - } - - if (pDH[DO_fixSections] & FIX_GOT) { - // Search through and fix pointers within the Global Offset Table section of the file - for (addrIter = (readAddr(pDH, DO_got_start) - ddmemStart); addrIter < (readAddr(pDH, DO_got_end) - ddmemStart); addrIter++) { - if ((ddmemStart <= readAddr(pDH, addrIter)) && (readAddr(pDH, addrIter) < ddmemEnd)) { - writeAddr (pDH, addrIter, readAddr(pDH, addrIter) + relocationOffset); - } - } - } - - if (pDH[DO_fixSections] & FIX_BSS) { - // Initialise the BSS to 0 - toncset (&pDH[readAddr(pDH, DO_bss_start) - ddmemStart] , 0, readAddr(pDH, DO_bss_end) - readAddr(pDH, DO_bss_start)); - } - - // Fix the section pointers in the header - writeAddr (pDH, DO_text_start, readAddr (pDH, DO_text_start) + relocationOffset); - writeAddr (pDH, DO_data_end, readAddr (pDH, DO_data_end) + relocationOffset); - writeAddr (pDH, DO_glue_start, readAddr (pDH, DO_glue_start) + relocationOffset); - writeAddr (pDH, DO_glue_end, readAddr (pDH, DO_glue_end) + relocationOffset); - writeAddr (pDH, DO_got_start, readAddr (pDH, DO_got_start) + relocationOffset); - writeAddr (pDH, DO_got_end, readAddr (pDH, DO_got_end) + relocationOffset); - writeAddr (pDH, DO_bss_start, readAddr (pDH, DO_bss_start) + relocationOffset); - writeAddr (pDH, DO_bss_end, readAddr (pDH, DO_bss_end) + relocationOffset); -} - -void dldiClearBss (void) { - data_t *pDH = _dldi_start; - - addr_t ddmemSize = (1 << pDH[DO_driverSize]); // Size of range that offsets can be in the DLDI file - - if (ddmemSize <= 0x4000) return; // For <= 16KB DLDI file, BSS has already been cleared - - if (pDH[DO_fixSections] & FIX_BSS) { - // Initialise the BSS to 0 - toncset (&pDH[readAddr(pDH, DO_bss_start)] , 0, readAddr(pDH, DO_bss_end) - readAddr(pDH, DO_bss_start)); - } -} -#endif \ No newline at end of file diff --git a/bootloader/source/dldi_patcher.h b/bootloader/source/dldi_patcher.h deleted file mode 100644 index 956c3dc2..00000000 --- a/bootloader/source/dldi_patcher.h +++ /dev/null @@ -1,35 +0,0 @@ -/*----------------------------------------------------------------- - - Copyright (C) 2005 Michael "Chishm" Chisholm - - 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - - If you use this code, please give due credit and email me about your - project at chishm@hotmail.com -------------------------------------------------------------------*/ - -#ifndef DLDI_PATCHER_H -#define DLDI_PATCHER_H - -#include - -typedef signed int addr_t; -typedef unsigned char data_t; -bool dldiPatchBinary (data_t *binData, u32 binSize); -void dldiDecompressBinary (void); -void dldiRelocateBinary (void); -void dldiClearBss (void); - -#endif // DLDI_PATCHER_H diff --git a/bootloader/source/dmaTwl.h b/bootloader/source/dmaTwl.h deleted file mode 100644 index df34ca77..00000000 --- a/bootloader/source/dmaTwl.h +++ /dev/null @@ -1,223 +0,0 @@ -#pragma once - -typedef struct -{ - const void* src; // Source address; not used in fill mode - void* dst; // Destination address - u32 totalWordCount; // For auto-start mode without infinite repeat - u32 wordCount; // Number of words to transfer per start trigger - u32 blockInterval; // Sets prescaler and cycles of delay between physical blocks - u32 fillData; // For fill mode - u32 control; -} dma_twl_config_t; - -#define REG_NDMAGCNT (*(vu32*)0x04004100) - -#define NDMAGCNT_YIELD_CYCLES_0 (0 << 16) -#define NDMAGCNT_YIELD_CYCLES_1 (1 << 16) -#define NDMAGCNT_YIELD_CYCLES_2 (2 << 16) -#define NDMAGCNT_YIELD_CYCLES_4 (3 << 16) -#define NDMAGCNT_YIELD_CYCLES_8 (4 << 16) -#define NDMAGCNT_YIELD_CYCLES_16 (5 << 16) -#define NDMAGCNT_YIELD_CYCLES_32 (6 << 16) -#define NDMAGCNT_YIELD_CYCLES_64 (7 << 16) -#define NDMAGCNT_YIELD_CYCLES_128 (8 << 16) -#define NDMAGCNT_YIELD_CYCLES_256 (9 << 16) -#define NDMAGCNT_YIELD_CYCLES_512 (10 << 16) -#define NDMAGCNT_YIELD_CYCLES_1024 (11 << 16) -#define NDMAGCNT_YIELD_CYCLES_2048 (12 << 16) -#define NDMAGCNT_YIELD_CYCLES_4096 (13 << 16) -#define NDMAGCNT_YIELD_CYCLES_8192 (14 << 16) -#define NDMAGCNT_YIELD_CYCLES_16384 (15 << 16) - -#define NDMAGCNT_ARBITRATION_FIXED (0 << 31) -#define NDMAGCNT_ARBITRATION_ROUND_ROBIN (1 << 31) - -#define REG_NDMA0SAD (*(vu32*)0x04004104) -#define REG_NDMA0DAD (*(vu32*)0x04004108) -#define REG_NDMA0TCNT (*(vu32*)0x0400410C) -#define REG_NDMA0WCNT (*(vu32*)0x04004110) -#define REG_NDMA0BCNT (*(vu32*)0x04004114) -#define REG_NDMA0FDATA (*(vu32*)0x04004118) -#define REG_NDMA0CNT (*(vu32*)0x0400411C) - -#define REG_NDMA1SAD (*(vu32*)0x04004120) -#define REG_NDMA1DAD (*(vu32*)0x04004124) -#define REG_NDMA1TCNT (*(vu32*)0x04004128) -#define REG_NDMA1WCNT (*(vu32*)0x0400412C) -#define REG_NDMA1BCNT (*(vu32*)0x04004130) -#define REG_NDMA1FDATA (*(vu32*)0x04004134) -#define REG_NDMA1CNT (*(vu32*)0x04004138) - -#define REG_NDMA2SAD (*(vu32*)0x0400413C) -#define REG_NDMA2DAD (*(vu32*)0x04004140) -#define REG_NDMA2TCNT (*(vu32*)0x04004144) -#define REG_NDMA2WCNT (*(vu32*)0x04004148) -#define REG_NDMA2BCNT (*(vu32*)0x0400414C) -#define REG_NDMA2FDATA (*(vu32*)0x04004150) -#define REG_NDMA2CNT (*(vu32*)0x04004154) - -#define REG_NDMA3SAD (*(vu32*)0x04004158) -#define REG_NDMA3DAD (*(vu32*)0x0400415C) -#define REG_NDMA3TCNT (*(vu32*)0x04004160) -#define REG_NDMA3WCNT (*(vu32*)0x04004164) -#define REG_NDMA3BCNT (*(vu32*)0x04004168) -#define REG_NDMA3FDATA (*(vu32*)0x0400416C) -#define REG_NDMA3CNT (*(vu32*)0x04004170) - -#define NDMABCNT_INTERVAL(x) (x) -#define NDMABCNT_PRESCALER_1 (0 << 16) -#define NDMABCNT_PRESCALER_4 (1 << 16) -#define NDMABCNT_PRESCALER_16 (2 << 16) -#define NDMABCNT_PRESCALER_64 (3 << 16) - -#define NDMACNT_DST_MODE_INCREMENT (0 << 10) -#define NDMACNT_DST_MODE_DECREMENT (1 << 10) -#define NDMACNT_DST_MODE_FIXED (2 << 10) - -#define NDMACNT_DST_RELOAD (1 << 12) - -#define NDMACNT_SRC_MODE_INCREMENT (0 << 13) -#define NDMACNT_SRC_MODE_DECREMENT (1 << 13) -#define NDMACNT_SRC_MODE_FIXED (2 << 13) -#define NDMACNT_SRC_MODE_FILLDATA (3 << 13) - -#define NDMACNT_SRC_RELOAD (1 << 15) - -#define NDMACNT_PHYSICAL_COUNT_1 (0 << 16) -#define NDMACNT_PHYSICAL_COUNT_2 (1 << 16) -#define NDMACNT_PHYSICAL_COUNT_4 (2 << 16) -#define NDMACNT_PHYSICAL_COUNT_8 (3 << 16) -#define NDMACNT_PHYSICAL_COUNT_16 (4 << 16) -#define NDMACNT_PHYSICAL_COUNT_32 (5 << 16) -#define NDMACNT_PHYSICAL_COUNT_64 (6 << 16) -#define NDMACNT_PHYSICAL_COUNT_128 (7 << 16) -#define NDMACNT_PHYSICAL_COUNT_256 (8 << 16) -#define NDMACNT_PHYSICAL_COUNT_512 (9 << 16) -#define NDMACNT_PHYSICAL_COUNT_1024 (10 << 16) -#define NDMACNT_PHYSICAL_COUNT_2048 (11 << 16) -#define NDMACNT_PHYSICAL_COUNT_4096 (12 << 16) -#define NDMACNT_PHYSICAL_COUNT_8192 (13 << 16) -#define NDMACNT_PHYSICAL_COUNT_16384 (14 << 16) -#define NDMACNT_PHYSICAL_COUNT_32768 (15 << 16) - -#define NDMACNT_MODE_TIMER_0 (0 << 24) -#define NDMACNT_MODE_TIMER_1 (1 << 24) -#define NDMACNT_MODE_TIMER_2 (2 << 24) -#define NDMACNT_MODE_TIMER_3 (3 << 24) -#define NDMACNT_MODE_DS_SLOTA_ROM_XFER (4 << 24) -#define NDMACNT_MODE_DS_SLOTB_ROM_XFER (5 << 24) -#define NDMACNT_MODE_VBLANK (6 << 24) - -#ifdef LIBTWL_ARM9 - -#define NDMACNT_MODE_HBLANK (7 << 24) -#define NDMACNT_MODE_DISPLAY (8 << 24) -#define NDMACNT_MODE_MMEM_DISP_FIFO (9 << 24) -#define NDMACNT_MODE_GX_FIFO (10 << 24) -#define NDMACNT_MODE_CAMERA (11 << 24) - -#endif - -#ifdef LIBTWL_ARM7 - -#define NDMACNT_MODE_WIFI (7 << 24) -#define NDMACNT_MODE_SDMMC (8 << 24) -#define NDMACNT_MODE_SDIO (9 << 24) -#define NDMACNT_MODE_AES_IN (10 << 24) -#define NDMACNT_MODE_AES_OUT (11 << 24) -#define NDMACNT_MODE_MIC (12 << 24) - -#endif - -#define NDMACNT_MODE_IMMEDIATE (1 << 28) -#define NDMACNT_REPEAT_INFINITELY (1 << 29) -#define NDMACNT_IRQ (1 << 30) -#define NDMACNT_ENABLE (1 << 31) - -#ifdef __cplusplus -extern "C" { -#endif - -/// @brief Configures twl ndma to use fixed arbitration. -/// In this mode ndma0 has the highest and ndma3 the lowest priority, -/// similar to the nitro dma channels. Note that ndma0 has a lower -/// priority than nitro dma channel 3. When ndma channels are active -/// the dsp and cpu can not access the bus. -static inline void dma_twlSetFixedArbitration(void) -{ - REG_NDMAGCNT = NDMAGCNT_ARBITRATION_FIXED; -} - -/// @brief Configures twl ndma to use round robin arbitration. -/// In this mode nitro dma channels still have a higher priority, -/// but bus access is distributed between all ndma channels and -/// the dsp and cpu. -/// This is done in the order ndma0, ndma1, ndma2, ndma3, dsp/cpu. -/// Candidates that do not have any outstanding request are skipped, -/// and the dsp takes priority over the cpu (as usual). The amount -/// of cycles reserved for the dsp/cpu is configurable. -/// @param yieldCycles The number of cycles that will be yielded to the -/// dsp/cpu in the round robin schedule. When there is no request -/// outstanding the cycles will not be wasted. Should be one of -/// NDMAGCNT_YIELD_CYCLES_*. -static inline void dma_twlSetRoundRobinArbitration(u32 yieldCycles) -{ - REG_NDMAGCNT = NDMAGCNT_ARBITRATION_ROUND_ROBIN | yieldCycles; -} - -static inline void dma_twlSetParams(int dma, const dma_twl_config_t* config) -{ - vu32* channel = &(®_NDMA0SAD)[7 * dma]; - channel[0] = (u32)config->src; - channel[1] = (u32)config->dst; - channel[2] = config->totalWordCount; - channel[3] = config->wordCount; - channel[4] = config->blockInterval; - channel[5] = config->fillData; - channel[6] = config->control; -} - -static inline void dma_twlWait(int dma) -{ - vu32* cnt = &(®_NDMA0CNT)[7 * dma]; - while (*cnt & NDMACNT_ENABLE); -} - -static inline void dma_twlCopy32Async(int dma, const void* src, void* dst, u32 length) -{ - vu32* channel = &(®_NDMA0SAD)[7 * dma]; - channel[0] = (u32)src; //SAD - channel[1] = (u32)dst; //DAD - channel[3] = length >> 2; //WCNT - channel[4] = NDMABCNT_PRESCALER_1 | NDMABCNT_INTERVAL(0); //BCNT - channel[6] = NDMACNT_DST_MODE_INCREMENT | NDMACNT_SRC_MODE_INCREMENT | - NDMACNT_PHYSICAL_COUNT_1 | NDMACNT_MODE_IMMEDIATE | NDMACNT_ENABLE; -} - -static inline void dma_twlCopy32(int dma, const void* src, void* dst, u32 length) -{ - dma_twlCopy32Async(dma, src, dst, length); - dma_twlWait(dma); -} - -static inline void dma_twlFill32Async(int dma, u32 value, void* dst, u32 length) -{ - vu32* channel = &(®_NDMA0SAD)[7 * dma]; - channel[1] = (u32)dst; //DAD - channel[3] = length >> 2; //WCNT - channel[4] = NDMABCNT_PRESCALER_1 | NDMABCNT_INTERVAL(0); //BCNT - channel[5] = value; //FDATA - channel[6] = NDMACNT_DST_MODE_INCREMENT | NDMACNT_SRC_MODE_FILLDATA | - NDMACNT_PHYSICAL_COUNT_1 | NDMACNT_MODE_IMMEDIATE | NDMACNT_ENABLE; -} - -static inline void dma_twlFill32(int dma, u32 value, void* dst, u32 length) -{ - dma_twlFill32Async(dma, value, dst, length); - dma_twlWait(dma); -} - -#ifdef __cplusplus -} -#endif diff --git a/bootloader/source/fat.c b/bootloader/source/fat.c deleted file mode 100644 index ed57c899..00000000 --- a/bootloader/source/fat.c +++ /dev/null @@ -1,550 +0,0 @@ -/*----------------------------------------------------------------- - fat.c - - NDS MP - GBAMP NDS Firmware Hack Version 2.12 - An NDS aware firmware patch for the GBA Movie Player. - By Michael Chisholm (Chishm) - - Filesystem code based on GBAMP_CF.c by Chishm (me). - -License: - Copyright (C) 2005 Michael "Chishm" Chisholm - - 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - - If you use this code, please give due credit and email me about your - project at chishm@hotmail.com -------------------------------------------------------------------*/ - -#include "fat.h" -#include "card.h" - - -//--------------------------------------------------------------- -// FAT constants - -#define FILE_LAST 0x00 -#define FILE_FREE 0xE5 - -#define ATTRIB_ARCH 0x20 -#define ATTRIB_DIR 0x10 -#define ATTRIB_LFN 0x0F -#define ATTRIB_VOL 0x08 -#define ATTRIB_HID 0x02 -#define ATTRIB_SYS 0x04 -#define ATTRIB_RO 0x01 - -#define FAT16_ROOT_DIR_CLUSTER 0x00 - -// File Constants -#ifndef EOF -#define EOF -1 -#define SEEK_SET 0 -#define SEEK_CUR 1 -#define SEEK_END 2 -#endif - - -//----------------------------------------------------------------- -// FAT constants -#define CLUSTER_EOF_16 0xFFFF - -#define ATTRIB_ARCH 0x20 -#define ATTRIB_DIR 0x10 -#define ATTRIB_LFN 0x0F -#define ATTRIB_VOL 0x08 -#define ATTRIB_HID 0x02 -#define ATTRIB_SYS 0x04 -#define ATTRIB_RO 0x01 - -//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -// Data Structures - -#define __PACKED __attribute__ ((__packed__)) - -// BIOS Parameter Block -typedef struct { - - u16 bytesPerSector; - u8 sectorsPerCluster; - u16 reservedSectors; - u8 numFATs; - u16 rootEntries; - u16 numSectorsSmall; - u8 mediaDesc; - u16 sectorsPerFAT; - u16 sectorsPerTrk; - u16 numHeads; - u32 numHiddenSectors; - u32 numSectors; -} __PACKED BIOS_BPB; - -// Boot Sector - must be packed -typedef struct -{ - u8 jmpBoot[3]; - u8 OEMName[8]; - BIOS_BPB bpb; - union // Different types of extended BIOS Parameter Block for FAT16 and FAT32 - { - struct - { - // Ext BIOS Parameter Block for FAT16 - u8 driveNumber; - u8 reserved1; - u8 extBootSig; - u32 volumeID; - u8 volumeLabel[11]; - u8 fileSysType[8]; - // Bootcode - u8 bootCode[448]; - } __PACKED fat16; - struct - { - // FAT32 extended block - u32 sectorsPerFAT32; - u16 extFlags; - u16 fsVer; - u32 rootClus; - u16 fsInfo; - u16 bkBootSec; - u8 reserved[12]; - // Ext BIOS Parameter Block for FAT16 - u8 driveNumber; - u8 reserved1; - u8 extBootSig; - u32 volumeID; - u8 volumeLabel[11]; - u8 fileSysType[8]; - // Bootcode - u8 bootCode[420]; - } __PACKED fat32; - } __PACKED extBlock; - - __PACKED u16 bootSig; - -} __PACKED BOOT_SEC; - -_Static_assert(sizeof(BOOT_SEC) == 512); - -// Directory entry - must be packed -typedef struct -{ - u8 name[8]; - u8 ext[3]; - u8 attrib; - u8 reserved; - u8 cTime_ms; - u16 cTime; - u16 cDate; - u16 aDate; - u16 startClusterHigh; - u16 mTime; - u16 mDate; - u16 startCluster; - u32 fileSize; -} __PACKED DIR_ENT; - -// File information - no need to pack -typedef struct -{ - u32 firstCluster; - u32 length; - u32 curPos; - u32 curClus; // Current cluster to read from - int curSect; // Current sector within cluster - int curByte; // Current byte within sector - char readBuffer[512]; // Buffer used for unaligned reads - u32 appClus; // Cluster to append to - int appSect; // Sector within cluster for appending - int appByte; // Byte within sector for appending - bool read; // Can read from file - bool write; // Can write to file - bool append;// Can append to file - bool inUse; // This file is open - u32 dirEntSector; // The sector where the directory entry is stored - int dirEntOffset; // The offset within the directory sector -} FAT_FILE; - - -//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -// Global Variables - -// _VARS_IN_RAM variables are stored in the largest section of WRAM -// available: IWRAM on NDS ARM7, EWRAM on NDS ARM9 and GBA - -// Locations on card -int discRootDir; -int discRootDirClus; -int discFAT; -int discSecPerFAT; -int discNumSec; -int discData; -int discBytePerSec; -int discSecPerClus; -int discBytePerClus; - -enum {FS_UNKNOWN, FS_FAT12, FS_FAT16, FS_FAT32} discFileSystem; - -// Global sector buffer to save on stack space -unsigned char globalBuffer[BYTES_PER_SECTOR]; - - -//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -//FAT routines - -u32 FAT_ClustToSect (u32 cluster) { - return (((cluster-2) * discSecPerClus) + discData); -} - -/*----------------------------------------------------------------- -FAT_NextCluster -Internal function - gets the cluster linked from input cluster ------------------------------------------------------------------*/ -u32 FAT_NextCluster(u32 cluster) -{ - u32 nextCluster = CLUSTER_FREE; - u32 sector; - int offset; - - - switch (discFileSystem) - { - case FS_UNKNOWN: - nextCluster = CLUSTER_FREE; - break; - - case FS_FAT12: - sector = discFAT + (((cluster * 3) / 2) / BYTES_PER_SECTOR); - offset = ((cluster * 3) / 2) % BYTES_PER_SECTOR; - CARD_ReadSector(sector, globalBuffer); - nextCluster = ((u8*) globalBuffer)[offset]; - offset++; - - if (offset >= BYTES_PER_SECTOR) { - offset = 0; - sector++; - } - - CARD_ReadSector(sector, globalBuffer); - nextCluster |= (((u8*) globalBuffer)[offset]) << 8; - - if (cluster & 0x01) { - nextCluster = nextCluster >> 4; - } else { - nextCluster &= 0x0FFF; - } - - break; - - case FS_FAT16: - sector = discFAT + ((cluster << 1) / BYTES_PER_SECTOR); - offset = cluster % (BYTES_PER_SECTOR >> 1); - - CARD_ReadSector(sector, globalBuffer); - // read the nextCluster value - nextCluster = ((u16*)globalBuffer)[offset]; - - if (nextCluster >= 0xFFF7) { - nextCluster = CLUSTER_EOF; - } - break; - - case FS_FAT32: - sector = discFAT + ((cluster << 2) / BYTES_PER_SECTOR); - offset = cluster % (BYTES_PER_SECTOR >> 2); - - CARD_ReadSector(sector, globalBuffer); - // read the nextCluster value - nextCluster = (((u32*)globalBuffer)[offset]) & 0x0FFFFFFF; - - if (nextCluster >= 0x0FFFFFF7) { - nextCluster = CLUSTER_EOF; - } - break; - - default: - nextCluster = CLUSTER_FREE; - break; - } - - return nextCluster; -} - -/*----------------------------------------------------------------- -ucase -Returns the uppercase version of the given char -char IN: a character -char return OUT: uppercase version of character ------------------------------------------------------------------*/ -char ucase (char character) -{ - if ((character > 0x60) && (character < 0x7B)) - character = character - 0x20; - return (character); -} - -/*----------------------------------------------------------------- -FAT_InitFiles -Reads the FAT information from the CF card. -You need to call this before reading any files. -bool return OUT: true if successful. ------------------------------------------------------------------*/ -bool FAT_InitFiles (bool initCard) -{ - int i; - int bootSector; - BOOT_SEC* bootSec; - - if (initCard && !CARD_StartUp()) { - return (false); - } - - // Read first sector of card - if (!CARD_ReadSector (0, globalBuffer)) - { - return false; - } - if (((globalBuffer[0x36] == 'F') && (globalBuffer[0x37] == 'A') && (globalBuffer[0x38] == 'T')) // Check if there is a FAT string, which indicates this is a boot sector - || ((globalBuffer[0x52] == 'F') && (globalBuffer[0x53] == 'A') && (globalBuffer[0x54] == 'T'))) { // Check for FAT32 - bootSector = 0; - } else // This is an MBR - { - // Find first valid partition from MBR - // First check for an active partition - for (i=0x1BE; (i < 0x1FE) && (globalBuffer[i] != 0x80); i+= 0x10); - // If it didn't find an active partition, search for any valid partition - if (i == 0x1FE) - for (i=0x1BE; (i < 0x1FE) && (globalBuffer[i+0x04] == 0x00); i+= 0x10); - - // Go to first valid partition - if (i != 0x1FE) // Make sure it found a partition - { - bootSector = globalBuffer[0x8 + i] + (globalBuffer[0x9 + i] << 8) + (globalBuffer[0xA + i] << 16) + ((globalBuffer[0xB + i] << 24) & 0x0F); - } else { - bootSector = 0; // No partition found, assume this is a MBR free disk - } - } - - // Read in boot sector - bootSec = (BOOT_SEC*) globalBuffer; - CARD_ReadSector (bootSector, bootSec); - - // Store required information about the file system - if (bootSec->bpb.sectorsPerFAT != 0) { - discSecPerFAT = bootSec->bpb.sectorsPerFAT; - } else { - discSecPerFAT = bootSec->extBlock.fat32.sectorsPerFAT32; - } - - if (bootSec->bpb.numSectorsSmall != 0) { - discNumSec = bootSec->bpb.numSectorsSmall; - } else { - discNumSec = bootSec->bpb.numSectors; - } - - discBytePerSec = BYTES_PER_SECTOR; // Sector size is redefined to be 512 bytes - discSecPerClus = bootSec->bpb.sectorsPerCluster * bootSec->bpb.bytesPerSector / BYTES_PER_SECTOR; - discBytePerClus = discBytePerSec * discSecPerClus; - discFAT = bootSector + bootSec->bpb.reservedSectors; - - discRootDir = discFAT + (bootSec->bpb.numFATs * discSecPerFAT); - discData = discRootDir + ((bootSec->bpb.rootEntries * sizeof(DIR_ENT)) / BYTES_PER_SECTOR); - - if ((discNumSec - discData) / bootSec->bpb.sectorsPerCluster < 4085) { - discFileSystem = FS_FAT12; - } else if ((discNumSec - discData) / bootSec->bpb.sectorsPerCluster < 65525) { - discFileSystem = FS_FAT16; - } else { - discFileSystem = FS_FAT32; - } - - if (discFileSystem != FS_FAT32) { - discRootDirClus = FAT16_ROOT_DIR_CLUSTER; - } else // Set up for the FAT32 way - { - discRootDirClus = bootSec->extBlock.fat32.rootClus; - // Check if FAT mirroring is enabled - if (!(bootSec->extBlock.fat32.extFlags & 0x80)) { - // Use the active FAT - discFAT = discFAT + ( discSecPerFAT * (bootSec->extBlock.fat32.extFlags & 0x0F)); - } - } - - return (true); -} - - -/*----------------------------------------------------------------- -getBootFileCluster ------------------------------------------------------------------*/ -u32 getBootFileCluster (const char* bootName) -{ - DIR_ENT dir; - int firstSector = 0; - bool notFound = false; - bool found = false; -// int maxSectors; - u32 wrkDirCluster = discRootDirClus; - u32 wrkDirSector = 0; - int wrkDirOffset = 0; - int nameOffset; - - dir.startCluster = CLUSTER_FREE; // default to no file found - dir.startClusterHigh = CLUSTER_FREE; - - - // Check if fat has been initialised - if (discBytePerSec == 0) { - return (CLUSTER_FREE); - } - - char *ptr = (char*)bootName; - while (*ptr != '.') ptr++; - int namelen = ptr - bootName; - -// maxSectors = (wrkDirCluster == FAT16_ROOT_DIR_CLUSTER ? (discData - discRootDir) : discSecPerClus); - // Scan Dir for correct entry - firstSector = discRootDir; - CARD_ReadSector (firstSector + wrkDirSector, globalBuffer); - found = false; - notFound = false; - wrkDirOffset = -1; // Start at entry zero, Compensating for increment - while (!found && !notFound) { - wrkDirOffset++; - if (wrkDirOffset == BYTES_PER_SECTOR / sizeof (DIR_ENT)) { - wrkDirOffset = 0; - wrkDirSector++; - if ((wrkDirSector == discSecPerClus) && (wrkDirCluster != FAT16_ROOT_DIR_CLUSTER)) { - wrkDirSector = 0; - wrkDirCluster = FAT_NextCluster(wrkDirCluster); - if (wrkDirCluster == CLUSTER_EOF) { - notFound = true; - } - firstSector = FAT_ClustToSect(wrkDirCluster); - } else if ((wrkDirCluster == FAT16_ROOT_DIR_CLUSTER) && (wrkDirSector == (discData - discRootDir))) { - notFound = true; // Got to end of root dir - } - CARD_ReadSector (firstSector + wrkDirSector, globalBuffer); - } - dir = ((DIR_ENT*) globalBuffer)[wrkDirOffset]; - found = true; - if ((dir.attrib & ATTRIB_DIR) || (dir.attrib & ATTRIB_VOL)) { - found = false; - } - if (namelen<8 && dir.name[namelen]!=0x20) found = false; - for (nameOffset = 0; nameOffset < namelen && found; nameOffset++) { - if (ucase(dir.name[nameOffset]) != bootName[nameOffset]) - found = false; - } - for (nameOffset = 0; nameOffset < 3 && found; nameOffset++) { - if (ucase(dir.ext[nameOffset]) != bootName[nameOffset+namelen+1]) - found = false; - } - if (dir.name[0] == FILE_LAST) { - notFound = true; - } - } - - // If no file is found, return CLUSTER_FREE - if (notFound) { - return CLUSTER_FREE; - } - - return (dir.startCluster | (dir.startClusterHigh << 16)); -} - -/*----------------------------------------------------------------- -fileRead(buffer, cluster, startOffset, length) ------------------------------------------------------------------*/ -u32 fileRead (char* buffer, u32 cluster, u32 startOffset, u32 length) -{ - int curByte; - int curSect; - - int dataPos = 0; - int chunks; - int beginBytes; - - if (cluster == CLUSTER_FREE || cluster == CLUSTER_EOF) - { - return 0; - } - - // Follow cluster list until desired one is found - for (chunks = startOffset / discBytePerClus; chunks > 0; chunks--) { - cluster = FAT_NextCluster (cluster); - } - - // Calculate the sector and byte of the current position, - // and store them - curSect = (startOffset % discBytePerClus) / BYTES_PER_SECTOR; - curByte = startOffset % BYTES_PER_SECTOR; - - // Load sector buffer for new position in file - CARD_ReadSector(curSect + FAT_ClustToSect(cluster), globalBuffer); - curSect++; - - // Number of bytes needed to read to align with a sector - beginBytes = (BYTES_PER_SECTOR < length + curByte ? (BYTES_PER_SECTOR - curByte) : length); - - // Read first part from buffer, to align with sector boundary - for (dataPos = 0 ; dataPos < beginBytes; dataPos++) { - buffer[dataPos] = globalBuffer[curByte++]; - } - - // Read in all the 512 byte chunks of the file directly, saving time - for (chunks = ((int)length - beginBytes) / BYTES_PER_SECTOR; chunks > 0;) { - int sectorsToRead; - - // Move to the next cluster if necessary - if (curSect >= discSecPerClus) { - curSect = 0; - cluster = FAT_NextCluster (cluster); - } - - // Calculate how many sectors to read (read a maximum of discSecPerClus at a time) - sectorsToRead = discSecPerClus - curSect; - if (chunks < sectorsToRead) - sectorsToRead = chunks; - - // Read the sectors - CARD_ReadSectors(curSect + FAT_ClustToSect(cluster), sectorsToRead, buffer + dataPos); - chunks -= sectorsToRead; - curSect += sectorsToRead; - dataPos += BYTES_PER_SECTOR * sectorsToRead; - } - - // Take care of any bytes left over before end of read - if (dataPos < length) { - - // Update the read buffer - curByte = 0; - if (curSect >= discSecPerClus) { - curSect = 0; - cluster = FAT_NextCluster (cluster); - } - CARD_ReadSector(curSect + FAT_ClustToSect(cluster), globalBuffer); - - // Read in last partial chunk - for (; dataPos < length; dataPos++) { - buffer[dataPos] = globalBuffer[curByte]; - curByte++; - } - } - - return dataPos; -} diff --git a/bootloader/source/fat.h b/bootloader/source/fat.h deleted file mode 100644 index d39076ba..00000000 --- a/bootloader/source/fat.h +++ /dev/null @@ -1,46 +0,0 @@ -/*----------------------------------------------------------------- - fat.h - - NDS MP - GBAMP NDS Firmware Hack Version 2.12 - An NDS aware firmware patch for the GBA Movie Player. - By Michael Chisholm (Chishm) - - Filesystem code based on GBAMP_CF.c by Chishm (me). - -License: - Copyright (C) 2005 Michael "Chishm" Chisholm - - 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - - If you use this code, please give due credit and email me about your - project at chishm@hotmail.com -------------------------------------------------------------------*/ - -#ifndef FAT_H -#define FAT_H - -#include - -#define CLUSTER_FREE 0x00000000 -#define CLUSTER_EOF 0x0FFFFFFF -#define CLUSTER_FIRST 0x00000002 - -bool FAT_InitFiles (bool initCard); -u32 getBootFileCluster (const char* bootName); -u32 fileRead (char* buffer, u32 cluster, u32 startOffset, u32 length); -u32 FAT_ClustToSect (u32 cluster); - -#endif // FAT_H diff --git a/bootloader/source/io_dldi.h b/bootloader/source/io_dldi.h index e0f4efa9..9d6f1a88 100644 --- a/bootloader/source/io_dldi.h +++ b/bootloader/source/io_dldi.h @@ -1,10 +1,10 @@ /* - io_dldi.h + io_dldi.h Reserved space for post-compilation adding of an extra driver Copyright (c) 2006 Michael "Chishm" Chisholm - + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -33,12 +33,10 @@ #ifndef IO_DLDI_H #define IO_DLDI_H -// 'DLDD' -#define DEVICE_TYPE_DLDD 0x49444C44 - -#include "disc_io.h" +#include // export interface -extern IO_INTERFACE _io_dldi ; +extern DLDI_INTERFACE _dldi_start ; +extern DISC_INTERFACE _io_dldi ; #endif // define IO_DLDI_H diff --git a/bootloader/source/io_dldi.s b/bootloader/source/io_dldi.s index bb5a8a2b..fdfbde11 100644 --- a/bootloader/source/io_dldi.s +++ b/bootloader/source/io_dldi.s @@ -32,6 +32,73 @@ _dldi_start: +#ifndef NO_DLDI + +@--------------------------------------------------------------------------------- +@ Driver patch file standard header -- 16 bytes +#ifdef STANDARD_DLDI + .word 0xBF8DA5ED @ Magic number to identify this region +#else + .word 0xBF8DA5EE @ Magic number to identify this region +#endif + .asciz " Chishm" @ Identifying Magic string (8 bytes with null terminator) + .byte 0x01 @ Version number + .byte 0x0e @ 16KiB @ Log [base-2] of the size of this driver in bytes. + .byte 0x00 @ Sections to fix + .byte 0x0e @ 16KiB @ Log [base-2] of the allocated space in bytes. + +@--------------------------------------------------------------------------------- +@ Text identifier - can be anything up to 47 chars + terminating null -- 16 bytes + .align 4 + .asciz "Loader (No interface)" + +@--------------------------------------------------------------------------------- +@ Offsets to important sections within the data -- 32 bytes + .align 6 + .word _dldi_start @ data start + .word _dldi_end @ data end + .word 0x00000000 @ Interworking glue start -- Needs address fixing + .word 0x00000000 @ Interworking glue end + .word 0x00000000 @ GOT start -- Needs address fixing + .word 0x00000000 @ GOT end + .word 0x00000000 @ bss start -- Needs setting to zero + .word 0x00000000 @ bss end +@--------------------------------------------------------------------------------- +@ IO_INTERFACE data -- 32 bytes +_io_dldi: + .ascii "DLDI" @ ioType + .word 0x00000000 @ Features + .word _DLDI_startup @ + .word _DLDI_isInserted @ + .word _DLDI_readSectors @ Function pointers to standard device driver functions + .word _DLDI_writeSectors @ + .word _DLDI_clearStatus @ + .word _DLDI_shutdown @ + + +@--------------------------------------------------------------------------------- + +_DLDI_startup: +_DLDI_isInserted: +_DLDI_readSectors: +_DLDI_writeSectors: +_DLDI_clearStatus: +_DLDI_shutdown: + mov r0, #0x00 @ Return false for every function + bx lr + + + +@--------------------------------------------------------------------------------- + .align + .pool + + .space (_dldi_start + 16384) - . @ Fill to 16KiB + +_dldi_end: + .end +@--------------------------------------------------------------------------------- +#else @--------------------------------------------------------------------------------- @ IO_INTERFACE data -- 32 bytes _io_dldi: @@ -44,27 +111,14 @@ _io_dldi: .word _DLDI_clearStatus @ .word _DLDI_shutdown @ -_DLDI_startup: - mov r12, #0x06000000 - ldr r12, [r12, #0x68] - bx r12 + _DLDI_startup: _DLDI_isInserted: - mov r12, #0x06000000 - ldr r12, [r12, #0x6C] - bx r12 _DLDI_readSectors: - mov r12, #0x06000000 - ldr r12, [r12, #0x70] - bx r12 _DLDI_writeSectors: - mov r12, #0x06000000 - ldr r12, [r12, #0x74] - bx r12 _DLDI_clearStatus: - mov r12, #0x06000000 - ldr r12, [r12, #0x78] - bx r12 _DLDI_shutdown: - mov r12, #0x06000000 - ldr r12, [r12, #0x7C] - bx r12 + mov r0, #0x00 @ Return false for every function + bx lr + + +#endif diff --git a/bootloader/source/load_crt0.s b/bootloader/source/load_crt0.s index b422d767..11cc0af9 100644 --- a/bootloader/source/load_crt0.s +++ b/bootloader/source/load_crt0.s @@ -24,7 +24,6 @@ .section ".init" .global _start .global storedFileCluster - .global initDisc .global wantToPatchDLDI .global argStart .global argSize @@ -39,9 +38,7 @@ _start: b startUp storedFileCluster: - .word 0x0FFFFFFF @ default BOOT.NDS -initDisc: - .word 0x00000001 @ init the disc by default + .word 0 @ default BOOT.NDS wantToPatchDLDI: .word 0x00000001 @ by default patch the DLDI section of the loaded NDS @ Used for passing arguments to the loaded app @@ -50,7 +47,7 @@ argStart: argSize: .word 0x00000000 dldiOffset: - .word 0 + .word _dldi_start - _start dsiSD: .word 0 dsiMode: diff --git a/bootloader/source/lzss.c b/bootloader/source/lzss.c deleted file mode 100644 index d4a113b3..00000000 --- a/bootloader/source/lzss.c +++ /dev/null @@ -1,27 +0,0 @@ -#include -#include - -void LZ77_Decompress(u8* source, u8* destination) { - u32 leng = (source[1] | (source[2] << 8) | (source[3] << 16)); - int Offs = 4; - int dstoffs = 0; - while (true) { - u8 header = source[Offs++]; - for (int i = 0; i < 8; i++) { - if ((header & 0x80) == 0) destination[dstoffs++] = source[Offs++]; - else - { - u8 a = source[Offs++]; - u8 b = source[Offs++]; - int offs = (((a & 0xF) << 8) | b) + 1; - int length = (a >> 4) + 3; - for (int j = 0; j < length; j++) { - destination[dstoffs] = destination[dstoffs - offs]; - dstoffs++; - } - } - if (dstoffs >= (int)leng) return; - header <<= 1; - } - } -} diff --git a/bootloader/source/minifat.c b/bootloader/source/minifat.c new file mode 100644 index 00000000..67f84a62 --- /dev/null +++ b/bootloader/source/minifat.c @@ -0,0 +1,592 @@ +/*----------------------------------------------------------------- + + minifat.c -- Minimal FAT filesystem driver + + Copyright (c) 2023 fincs + Loosely based on code by Michael "Chishm" Chisholm + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any + damages arising from the use of this software. + + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it and + redistribute it freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you + must not claim that you wrote the original software. If you use + this software in a product, an acknowledgment in the product + documentation would be appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. + 3. This notice may not be removed or altered from any source + distribution. + +------------------------------------------------------------------*/ + +#include "minifat.h" +#include + +#ifdef MINIFAT_DEBUG +#include +#else +#define dietPrint(...) ((void)0) +#endif + +// First FAT cluster number used to indicate invalid/unusable cluster numbers +#define FAT12_BAD_CLUSTER 0x0ff7 +#define FAT16_BAD_CLUSTER 0xfff7 +#define FAT32_BAD_CLUSTER 0x0ffffff7 + +// Maximum number of clusters representable in the given FAT type +#define MAX_CLUSTERS(_type) (_type##_BAD_CLUSTER-MINIFAT_CLUSTER_FIRST) + +// MBR partition information +typedef struct { + u8 status; + u8 startHead; + u16 startCySc; + u8 type; + u8 endHead; + u16 endCySc; + u16 lbaStartLo; + u16 lbaStartHi; + u16 lbaSizeLo; + u16 lbaSizeHi; +} PARTITION; + +_Static_assert(sizeof(PARTITION) == 0x10); + +// BIOS Parameter Block +typedef struct { + u16 bytesPerSector; + u8 sectorsPerCluster; + u16 reservedSectors; + u8 numFATs; + u16 rootEntries; + u16 numSectorsSmall; + u8 mediaDesc; + u16 sectorsPerFAT; + u16 sectorsPerTrk; + u16 numHeads; + u32 numHiddenSectors; + u32 numSectors; +} MK_PACKED BIOS_BPB; + +// Boot Sector - must be packed +typedef struct { + u8 jmpBoot[3]; + u8 OEMName[8]; + BIOS_BPB bpb; + + union { // Different types of extended BIOS Parameter Block for FAT16 and FAT32 + struct { + // Ext BIOS Parameter Block for FAT16 + u8 driveNumber; + u8 reserved1; + u8 extBootSig; + u32 volumeID; + u8 volumeLabel[11]; + u8 fileSysType[8]; + // Bootcode + u8 bootCode[448]; + } MK_PACKED fat16; + + struct { + // FAT32 extended block + u32 sectorsPerFAT32; + u16 extFlags; + u16 fsVer; + u32 rootClus; + u16 fsInfo; + u16 bkBootSec; + u8 reserved[12]; + // Ext BIOS Parameter Block for FAT16 + u8 driveNumber; + u8 reserved1; + u8 extBootSig; + u32 volumeID; + u8 volumeLabel[11]; + u8 fileSysType[8]; + // Bootcode + u8 bootCode[420]; + } MK_PACKED fat32; + } extBlock; + + u16 bootSig; +} BOOT_SEC; + +_Static_assert(sizeof(BOOT_SEC) == MINIFAT_SECTOR_SZ); + +MK_INLINE u32 _minifatClustToSec(MiniFat* fat, u32 cluster) +{ + return fat->dataStart + ((cluster-MINIFAT_CLUSTER_FIRST) << fat->clusterShift); +} + +MK_CONSTEXPR char _minifatToUpper(char c) +{ + return c >= 'a' && c <= 'z' ? c + 'A' - 'a' : c; +} + +MK_CONSTEXPR bool _minifatIsNonZeroPo2(unsigned x) +{ + return x != 0 && (x & (x-1)) == 0; +} + +static bool _minifatLoadBuffer(MiniFat* fat, u32 sector) +{ + bool ok = true; + if (fat->bufferPos != sector) { + ok = fat->discReadFn(sector, 1, fat->buffer); + if (ok) { + fat->bufferPos = sector; + } + } + return ok; +} + +static bool _minifatInitParams(MiniFat* fat) +{ + BOOT_SEC* buf = (BOOT_SEC*)fat->buffer; + + // Check for a valid boot signature + if (buf->bootSig != 0xaa55) { + dietPrint("Bad boot sig\n"); + return false; + } + + // Check for a valid Microsoft VBR + unsigned jmp = buf->jmpBoot[0]; + if (jmp != 0xeb && jmp != 0xe9 && jmp != 0xe8) { + dietPrint("Bad jump opcode\n"); + goto _isUnknown; + } + + /* Not needed + static const u8 fat32_ident[] = { 'F', 'A', 'T', '3', '2', ' ', ' ', ' ' }; + if (memcmp(buf->extBlock.fat32.fileSysType, fat32_ident, 8) == 0) { + //... etc + } + */ + + // Retrieve FAT size + u32 sectorsPerFat = buf->bpb.sectorsPerFAT; + if (!sectorsPerFat) { + sectorsPerFat = buf->extBlock.fat32.sectorsPerFAT32; + } + + // Validate basic FAT VBR parameters + if ( + buf->bpb.bytesPerSector != MINIFAT_SECTOR_SZ || // Only supporting 512-byte sectors + !_minifatIsNonZeroPo2(buf->bpb.sectorsPerCluster) || + buf->bpb.reservedSectors == 0 || + (buf->bpb.numFATs != 1 && buf->bpb.numFATs != 2) || + (buf->bpb.numSectorsSmall < 0x80 && buf->bpb.numSectors < 0x10000) || + sectorsPerFat == 0 + ) { + dietPrint("Bad FAT validation\n"); + goto _isUnknown; + } + + // Calculate total volume size in sectors + u32 totalSectors = buf->bpb.numSectorsSmall; + if (!totalSectors) { + totalSectors = buf->bpb.numSectors; + } + + // Initialize FAT parameters + fat->clusterSectors = buf->bpb.sectorsPerCluster; + fat->clusterShift = 0; + fat->fatStart = fat->bufferPos + buf->bpb.reservedSectors; + fat->rootDirStart = fat->fatStart + buf->bpb.numFATs*sectorsPerFat; + fat->dataStart = fat->rootDirStart + (buf->bpb.rootEntries*sizeof(MiniFatDirEnt) + MINIFAT_SECTOR_SZ-1) / MINIFAT_SECTOR_SZ; + + // Calculate cluster sector size shift (log2) + while ((1U << fat->clusterShift) != fat->clusterSectors) { + fat->clusterShift ++; + } + + // Calculate number of clusters + u32 numClusters = (fat->bufferPos + totalSectors - fat->dataStart) >> fat->clusterShift; + dietPrint("! FAT num clus 0x%lx\n", numClusters); + + // Discriminate FAT version according to number of clusters + // XX: Note that the official FAT specification is off-by-one here. + // In any case, well-behaved formatting tools will avoid volume sizes + // dangerously close to the problematic decision boundaries. + if (numClusters > MAX_CLUSTERS(FAT32)) { + goto _isUnknown; + } else if (numClusters > MAX_CLUSTERS(FAT16)) { + // FAT32 - validate parameters + if ( + buf->bpb.rootEntries != 0 || + buf->extBlock.fat32.fsVer != 0 || + buf->extBlock.fat32.rootClus < MINIFAT_CLUSTER_FIRST || + buf->extBlock.fat32.rootClus >= (MINIFAT_CLUSTER_FIRST + numClusters) + ) { + dietPrint("Bad FAT32 params\n"); + goto _isUnknown; + } + + // Select the correct FAT if mirroring is disabled + // XX: FatFs does not implement this for some reason + if (buf->extBlock.fat32.extFlags & 0x80) { + fat->fatStart += (buf->extBlock.fat32.extFlags & 0x0f)*sectorsPerFat; + } + + fat->fsType = MiniFatType_Fat32; + fat->rootDirCluster = buf->extBlock.fat32.rootClus; + fat->rootDirStart = _minifatClustToSec(fat, fat->rootDirCluster); + } else { + // FAT12/16 - validate parameters + if (buf->bpb.rootEntries == 0) { + dietPrint("Bad FAT12/16 params\n"); + goto _isUnknown; + } + + fat->fsType = numClusters > MAX_CLUSTERS(FAT12) ? MiniFatType_Fat16 : MiniFatType_Fat12; + fat->rootDirCluster = MINIFAT_CLUSTER_FREE; // FAT12/16 store the root dir outside of the data area + } + + return true; + +_isUnknown: + fat->fsType = MiniFatType_Unknown; + return true; +} + +static bool _minifatInitPartition(MiniFat* fat, u32 sector) +{ + return + sector != 0 && + _minifatLoadBuffer(fat, sector) && + _minifatInitParams(fat) && + fat->fsType != MiniFatType_Unknown; +} + +bool minifatInit(MiniFat* fat, MiniFatDiscReadFn discReadFn, unsigned partitionIndex) +{ + if (partitionIndex > 4) { + return false; + } + + fat->discReadFn = discReadFn; + fat->bufferPos = UINT32_MAX; + + // Read and parse first sector of card + if (!_minifatLoadBuffer(fat, 0) || !_minifatInitParams(fat)) { + return false; + } + + // If we have a valid boot sector but not a valid filesystem, check MBR + if (fat->fsType == MiniFatType_Unknown) { + // Extract partition offsets from MBR + u32 partOffsets[4]; + for (unsigned i = 0; i < 4; i ++) { + PARTITION* part = &((PARTITION*)&fat->buffer[0x1be])[i]; + + // Fail if MBR is malformed + if (part->status != 0x80 && part->status != 0x00) { + return false; + } + + // Ignore unpopulated/extended partitions + if (part->type == 0x00 || part->type == 0x05 || part->type == 0x0f) { + partOffsets[i] = 0; + } else { + partOffsets[i] = part->lbaStartLo | (part->lbaStartHi << 16); + } + } + + // Try to initialize the specified partition, or the first partition that succeeds + bool ok = false; + if (partitionIndex) { + ok = _minifatInitPartition(fat, partOffsets[partitionIndex-1]); + } else for (unsigned i = 0; !ok && i < 4; i ++) { + ok = _minifatInitPartition(fat, partOffsets[i]); + } + + // If above did not successfully initialize a partition, fail + if (!ok) { + return false; + } + } + + dietPrint("! FAT at 0x%lx type%u\n", fat->bufferPos, fat->fsType); + dietPrint(" clusSect=%u clusShift=%u\n", fat->clusterSectors, fat->clusterShift); + return true; +} + +u32 minifatNextCluster(MiniFat* fat, u32 cluster) +{ + u32 sector; + u32 offset; + u32 ret = MINIFAT_CLUSTER_FREE; + + if (cluster < MINIFAT_CLUSTER_FIRST) { + return cluster; + } + + switch (fat->fsType) { + default: + case MiniFatType_Unknown: + break; + + case MiniFatType_Fat12: + sector = fat->fatStart + (((cluster * 3) / 2) / MINIFAT_SECTOR_SZ); + offset = ((cluster * 3) / 2) % MINIFAT_SECTOR_SZ; + if (!_minifatLoadBuffer(fat, sector)) { + break; + } + + ret = fat->buffer[offset]; + offset++; + + if (offset >= MINIFAT_SECTOR_SZ) { + offset = 0; + sector++; + } + + if (!_minifatLoadBuffer(fat, sector)) { + break; + } + + ret |= fat->buffer[offset] << 8; + + if (cluster & 1) { + ret >>= 4; + } else { + ret &= 0x0fff; + } + + if (ret >= FAT12_BAD_CLUSTER) { + ret = MINIFAT_CLUSTER_EOF; + } + break; + + case MiniFatType_Fat16: + sector = fat->fatStart + ((cluster << 1) / MINIFAT_SECTOR_SZ); + offset = cluster % (MINIFAT_SECTOR_SZ >> 1); + if (!_minifatLoadBuffer(fat, sector)) { + break; + } + + // read the next cluster value + ret = ((u16*)fat->buffer)[offset]; + + if (ret >= FAT16_BAD_CLUSTER) { + ret = MINIFAT_CLUSTER_EOF; + } + break; + + case MiniFatType_Fat32: + sector = fat->fatStart + ((cluster << 2) / MINIFAT_SECTOR_SZ); + offset = cluster % (MINIFAT_SECTOR_SZ >> 2); + if (!_minifatLoadBuffer(fat, sector)) { + break; + } + + // read the next cluster value + ret = ((u32*)fat->buffer)[offset] & 0x0fffffff; + + if (ret >= FAT32_BAD_CLUSTER) { + ret = MINIFAT_CLUSTER_EOF; + } + break; + } + + return ret; +} + +MK_INLINE void _minifatMake8dot3(char* buf, const char* name) +{ + unsigned i = 0; + + // Copy filename + for (; i < 8 && *name && *name != '.'; i ++, name ++) { + buf[i] = _minifatToUpper(*name); + } + + // Pad filename + for (; i < 8; i ++) { + buf[i] = ' '; + } + + // Skip extension dot + if (*name == '.') name++; + + // Copy extension + for (; i < 8+3 && *name; i ++, name ++) { + buf[i] = _minifatToUpper(*name); + } + + // Pad extension + for (; i < 8+3; i ++) { + buf[i] = ' '; + } +} + +u32 minifatFind(MiniFat* fat, u32 dirCluster, const char* name, MiniFatDirEnt* out_entry) +{ + char name8dot3[8+3]; + _minifatMake8dot3(name8dot3, name); + + u32 baseSector; + if (dirCluster < MINIFAT_CLUSTER_FIRST) { + dirCluster = fat->rootDirCluster; + baseSector = fat->rootDirStart; + } else { + baseSector = _minifatClustToSec(fat, dirCluster); + } + + u32 sectorOff = 0; + for (;;) { + if (!_minifatLoadBuffer(fat, baseSector + sectorOff)) { + return MINIFAT_CLUSTER_EOF; + } + + MiniFatDirEnt* entries = (void*)fat->buffer; + for (unsigned i = 0; i < MINIFAT_SECTOR_SZ / sizeof(MiniFatDirEnt); i ++) { + MiniFatDirEnt* entry = &entries[i]; + + if (entry->name[0] == 0x00) { + return MINIFAT_CLUSTER_EOF; + } + + if (entry->name[0] == 0xe5 || (entry->attrib & MINIFAT_ATTRIB_VOLUME)) { + continue; + } + + if (__builtin_memcmp(entry->name_ext, name8dot3, 8+3) == 0) { + if (out_entry) *out_entry = *entry; + return entry->startCluster | (entry->startClusterHigh << 16); + } + } + + sectorOff ++; + + if (dirCluster >= MINIFAT_CLUSTER_FIRST) { + if (sectorOff == fat->clusterSectors) { + dirCluster = minifatNextCluster(fat, dirCluster); + if (dirCluster < MINIFAT_CLUSTER_FIRST) { + return MINIFAT_CLUSTER_EOF; + } + + baseSector = _minifatClustToSec(fat, dirCluster); + sectorOff = 0; + } + } else if (baseSector + sectorOff == fat->dataStart) { + return MINIFAT_CLUSTER_EOF; + } + } +} + +MK_INLINE bool _minifatLargeRead(MiniFat* fat, void** pBuffer, u32* pTotalReadLen, u32 readPos, u32 readLen) +{ + bool ok = fat->discReadFn(readPos, readLen, *pBuffer); + if (ok) { + u32 readBytes = readLen * MINIFAT_SECTOR_SZ; + *pBuffer = (u8*)*pBuffer + readBytes; + *pTotalReadLen += readBytes; + } + return ok; +} + +u32 minifatRead(MiniFat* fat, u32 objCluster, void* buffer, u32 offset, u32 length) +{ + const u32 clusterSectors = fat->clusterSectors; + const u32 clusterBytes = MINIFAT_SECTOR_SZ << fat->clusterShift; + + // All offsets must be word aligned + if (((uptr)buffer | offset | length) & 3) { + return 0; + } + + // Skip over initial clusters + while (objCluster >= MINIFAT_CLUSTER_FIRST && offset >= clusterBytes) { + offset -= clusterBytes; + objCluster = minifatNextCluster(fat, objCluster); + } + + // Fail early if EOF + if (objCluster < MINIFAT_CLUSTER_FIRST) { + return 0; + } + + // Initialize variables + u32 totalReadLen = 0; + u32 baseSector = _minifatClustToSec(fat, objCluster); + u32 sectorOff = offset / MINIFAT_SECTOR_SZ; + offset &= MINIFAT_SECTOR_SZ-1; + + // Read the head if needed + if (offset || length < MINIFAT_SECTOR_SZ) { + if (!_minifatLoadBuffer(fat, baseSector+sectorOff)) { + return 0; + } + + u32 maxLen = MINIFAT_SECTOR_SZ - offset; + totalReadLen = length < maxLen ? length : maxLen; + armCopyMem32(buffer, &fat->buffer[offset], totalReadLen); + + buffer = (u8*)buffer + totalReadLen; + sectorOff ++; + length -= totalReadLen; + } + + // Main body read loop, iterating through clusters + u32 accumReadPos = 0; + u32 accumReadLen = 0; + while (length >= MINIFAT_SECTOR_SZ) { + u32 maxSectors = clusterSectors - sectorOff; + u32 remSectors = length / MINIFAT_SECTOR_SZ; + + u32 readLen = remSectors < maxSectors ? remSectors : maxSectors; + if_likely (readLen) { + u32 readPos = baseSector+sectorOff; + if_likely (accumReadLen) { + u32 nextReadPos = accumReadPos + accumReadLen; + if_likely (nextReadPos == readPos) { + accumReadLen += readLen; + } else if (!_minifatLargeRead(fat, &buffer, &totalReadLen, accumReadPos, accumReadLen)) { + return totalReadLen; + } else { + goto _startNewRead; + } + } else { +_startNewRead: + accumReadPos = readPos; + accumReadLen = readLen; + } + + sectorOff += readLen; + length -= readLen * MINIFAT_SECTOR_SZ; + } + + if (length && sectorOff >= clusterSectors) { + objCluster = minifatNextCluster(fat, objCluster); + if (objCluster < MINIFAT_CLUSTER_FIRST) { + return totalReadLen; + } + + baseSector = _minifatClustToSec(fat, objCluster); + sectorOff = 0; + } + } + + if (accumReadLen && !_minifatLargeRead(fat, &buffer, &totalReadLen, accumReadPos, accumReadLen)) { + return totalReadLen; + } + + // Read the tail if needed + if (length) { + if (!_minifatLoadBuffer(fat, baseSector+sectorOff)) { + return totalReadLen; + } + + armCopyMem32(buffer, &fat->buffer[0], length); + totalReadLen += length; + } + + return totalReadLen; +} diff --git a/bootloader/source/minifat.h b/bootloader/source/minifat.h new file mode 100644 index 00000000..052ef8ec --- /dev/null +++ b/bootloader/source/minifat.h @@ -0,0 +1,107 @@ +/*----------------------------------------------------------------- + + minifat.h -- Minimal FAT filesystem driver + + Copyright (c) 2023 fincs + Loosely based on code by Michael "Chishm" Chisholm + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any + damages arising from the use of this software. + + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it and + redistribute it freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you + must not claim that you wrote the original software. If you use + this software in a product, an acknowledgment in the product + documentation would be appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. + 3. This notice may not be removed or altered from any source + distribution. + +------------------------------------------------------------------*/ +/*! \file minifat.h +\brief Minimal FAT filesystem driver +*/ + +#pragma once +#include + +#define MINIFAT_SECTOR_SZ 512 //!< Size of a sector in bytes + +#define MINIFAT_CLUSTER_FREE 0 //!< Free cluster +#define MINIFAT_CLUSTER_EOF 1 //!< End-of-file marker +#define MINIFAT_CLUSTER_FIRST 2 //!< First valid cluster + +#define MINIFAT_ATTRIB_ARCHIVE 0x20 //!< Archive attribute +#define MINIFAT_ATTRIB_DIR 0x10 //!< Directory attribute +#define MINIFAT_ATTRIB_LFN 0x0f //!< Long File Name attribute combination +#define MINIFAT_ATTRIB_VOLUME 0x08 //!< Volume attribute +#define MINIFAT_ATTRIB_HIDDEN 0x02 //!< Hidden attribute +#define MINIFAT_ATTRIB_SYSTEM 0x04 //!< System attribute +#define MINIFAT_ATTRIB_READONLY 0x01 //!< Read-only attribute + +//! Disc read callback function type +typedef bool (*MiniFatDiscReadFn)(u32 sector, u32 numSectors, void* buffer); + +//! FAT filesystem type +typedef enum MiniFatType { + MiniFatType_Unknown, + MiniFatType_Fat12, + MiniFatType_Fat16, + MiniFatType_Fat32, +} MiniFatType; + +//! FAT filesystem driver state +typedef struct MiniFat { + alignas(4) u8 buffer[MINIFAT_SECTOR_SZ]; + + MiniFatDiscReadFn discReadFn; + u32 bufferPos; + + MiniFatType fsType; + u8 clusterSectors; + u8 clusterShift; + + u32 fatStart; + u32 rootDirStart; + u32 rootDirCluster; + u32 dataStart; +} MiniFat; + +//! FAT directory entry +typedef struct MiniFatDirEnt { + union { + char name_ext[8+3]; + struct { + char name[8]; + char ext[3]; + }; + }; + u8 attrib; + u8 reserved; + u8 cTime_ms; + u16 cTime; + u16 cDate; + u16 aDate; + u16 startClusterHigh; + u16 mTime; + u16 mDate; + u16 startCluster; + u32 fileSize; +} MiniFatDirEnt; + +//! Initialize +bool minifatInit(MiniFat* fat, MiniFatDiscReadFn discReadFn, unsigned partitionIndex); + +//! Return +u32 minifatNextCluster(MiniFat* fat, u32 cluster); + +//! Find +u32 minifatFind(MiniFat* fat, u32 dirCluster, const char* name, MiniFatDirEnt* out_entry); + +//! Read +u32 minifatRead(MiniFat* fat, u32 objCluster, void* buffer, u32 offset, u32 length); diff --git a/bootloader/source/sdmmc.c b/bootloader/source/sdmmc.c index 3910abe0..7cfcb2f2 100644 --- a/bootloader/source/sdmmc.c +++ b/bootloader/source/sdmmc.c @@ -1,12 +1,12 @@ #ifndef NO_SDMMC #include -#include "sdmmc.h" #include +#include "sdmmc.h" static struct mmcdevice deviceSD; //--------------------------------------------------------------------------------- -int geterror(struct mmcdevice *ctx) { +static int geterror(struct mmcdevice *ctx) { //--------------------------------------------------------------------------------- //if(ctx->error == 0x4) return -1; //else return 0; @@ -15,7 +15,7 @@ int geterror(struct mmcdevice *ctx) { //--------------------------------------------------------------------------------- -void setTarget(struct mmcdevice *ctx) { +static void setTarget(struct mmcdevice *ctx) { //--------------------------------------------------------------------------------- sdmmc_mask16(REG_SDPORTSEL,0x3,(u16)ctx->devicenumber); setckl(ctx->clk); @@ -29,220 +29,100 @@ void setTarget(struct mmcdevice *ctx) { //--------------------------------------------------------------------------------- -void sdmmc_send_command(struct mmcdevice *ctx, uint32_t cmd, uint32_t args) { +static void sdmmc_send_command(struct mmcdevice *ctx, uint32_t cmd, uint32_t args) { //--------------------------------------------------------------------------------- - const bool getSDRESP = (cmd << 15) >> 31; - u16 flags = (cmd << 15) >> 31; - const bool readdata = cmd & 0x20000; - const bool writedata = cmd & 0x40000; - - if(readdata || writedata) - { - flags |= TMIO_STAT0_DATAEND; - } - - ctx->error = 0; - while((sdmmc_read16(REG_SDSTATUS1) & TMIO_STAT1_CMD_BUSY)); //mmc working? - sdmmc_write16(REG_SDIRMASK0,0); - sdmmc_write16(REG_SDIRMASK1,0); - sdmmc_write16(REG_SDSTATUS0,0); - sdmmc_write16(REG_SDSTATUS1,0); - sdmmc_mask16(REG_SDDATACTL32,0x1800,0x400); // Disable TX32RQ and RX32RDY IRQ. Clear fifo. - sdmmc_write16(REG_SDCMDARG0,args &0xFFFF); - sdmmc_write16(REG_SDCMDARG1,args >> 16); - sdmmc_write16(REG_SDCMD,cmd &0xFFFF); - - u32 size = ctx->size; - const u16 blkSize = sdmmc_read16(REG_SDBLKLEN32); - u32 *rDataPtr32 = (u32*)ctx->rData; - u8 *rDataPtr8 = ctx->rData; - const u32 *tDataPtr32 = (u32*)ctx->tData; - const u8 *tDataPtr8 = ctx->tData; - - bool rUseBuf = ( NULL != rDataPtr32 ); - bool tUseBuf = ( NULL != tDataPtr32 ); - - u16 status0 = 0; - while(1) - { - volatile u16 status1 = sdmmc_read16(REG_SDSTATUS1); -#ifdef DATA32_SUPPORT - volatile u16 ctl32 = sdmmc_read16(REG_SDDATACTL32); - if((ctl32 & 0x100)) -#else - if((status1 & TMIO_STAT1_RXRDY)) -#endif - { - if(readdata) - { - if(rUseBuf) - { - sdmmc_mask16(REG_SDSTATUS1, TMIO_STAT1_RXRDY, 0); - if(size >= blkSize) - { - #ifdef DATA32_SUPPORT - if(!((u32)rDataPtr32 & 3)) - { - for(u32 i = 0; i < blkSize; i += 4) - { - *rDataPtr32++ = sdmmc_read32(REG_SDFIFO32); - } - } - else - { - for(u32 i = 0; i < blkSize; i += 4) - { - u32 data = sdmmc_read32(REG_SDFIFO32); - *rDataPtr8++ = data; - *rDataPtr8++ = data >> 8; - *rDataPtr8++ = data >> 16; - *rDataPtr8++ = data >> 24; - } - } - #else - if(!((u32)rDataPtr16 & 1)) - { - for(u32 i = 0; i < blkSize; i += 4) - { - *rDataPtr16++ = sdmmc_read16(REG_SDFIFO); - } - } - else - { - for(u32 i = 0; i < blkSize; i += 4) - { - u16 data = sdmmc_read16(REG_SDFIFO); - *rDataPtr8++ = data; - *rDataPtr8++ = data >> 8; - } - } - #endif - size -= blkSize; - } - } - - sdmmc_mask16(REG_SDDATACTL32, 0x800, 0); - } - } -#ifdef DATA32_SUPPORT - if(!(ctl32 & 0x200)) -#else - if((status1 & TMIO_STAT1_TXRQ)) -#endif - { - if(writedata) - { - if(tUseBuf) - { - sdmmc_mask16(REG_SDSTATUS1, TMIO_STAT1_TXRQ, 0); - if(size >= blkSize) - { - #ifdef DATA32_SUPPORT - if(!((u32)tDataPtr32 & 3)) - { - for(u32 i = 0; i < blkSize; i += 4) - { - sdmmc_write32(REG_SDFIFO32, *tDataPtr32++); - } - } - else - { - for(u32 i = 0; i < blkSize; i += 4) - { - u32 data = *tDataPtr8++; - data |= (u32)*tDataPtr8++ << 8; - data |= (u32)*tDataPtr8++ << 16; - data |= (u32)*tDataPtr8++ << 24; - sdmmc_write32(REG_SDFIFO32, data); - } - } - #else - if(!((u32)tDataPtr16 & 1)) - { - for(u32 i = 0; i < blkSize; i += 2) - { - sdmmc_write16(REG_SDFIFO, *tDataPtr16++); - } - } - else - { - for(u32 i = 0; i < blkSize; i += 2) - { - u16 data = *tDataPtr8++; - data |= (u16)(*tDataPtr8++ << 8); - sdmmc_write16(REG_SDFIFO, data); - } - } - #endif - size -= blkSize; - } - } - - sdmmc_mask16(REG_SDDATACTL32, 0x1000, 0); - } - } - if(status1 & TMIO_MASK_GW) - { - ctx->error |= 4; - break; - } - - if(!(status1 & TMIO_STAT1_CMD_BUSY)) - { - status0 = sdmmc_read16(REG_SDSTATUS0); - if(sdmmc_read16(REG_SDSTATUS0) & TMIO_STAT0_CMDRESPEND) - { - ctx->error |= 0x1; - } - if(status0 & TMIO_STAT0_DATAEND) - { - ctx->error |= 0x2; - } - - if((status0 & flags) == flags) - break; - } - } - ctx->stat0 = sdmmc_read16(REG_SDSTATUS0); - ctx->stat1 = sdmmc_read16(REG_SDSTATUS1); - sdmmc_write16(REG_SDSTATUS0,0); - sdmmc_write16(REG_SDSTATUS1,0); - - if(getSDRESP != 0) - { - ctx->ret[0] = (u32)(sdmmc_read16(REG_SDRESP0) | (sdmmc_read16(REG_SDRESP1) << 16)); - ctx->ret[1] = (u32)(sdmmc_read16(REG_SDRESP2) | (sdmmc_read16(REG_SDRESP3) << 16)); - ctx->ret[2] = (u32)(sdmmc_read16(REG_SDRESP4) | (sdmmc_read16(REG_SDRESP5) << 16)); - ctx->ret[3] = (u32)(sdmmc_read16(REG_SDRESP6) | (sdmmc_read16(REG_SDRESP7) << 16)); - } -} + int i; + bool getSDRESP = (cmd << 15) >> 31; + uint16_t flags = (cmd << 15) >> 31; + const bool readdata = cmd & 0x20000; + const bool writedata = cmd & 0x40000; + + if(readdata || writedata) + { + flags |= TMIO_STAT0_DATAEND; + } -//--------------------------------------------------------------------------------- -static u32 calcSDSize(u8* csd, int type) { -//--------------------------------------------------------------------------------- - u32 result = 0; - if (type == -1) type = csd[14] >> 6; - switch (type) { - case 0: - { - u32 block_len = csd[9] & 0xf; - block_len = 1 << block_len; - u32 mult = (csd[4] >> 7) | ((csd[5] & 3) << 1); - mult = 1 << (mult + 2); - result = csd[8] & 3; - result = (result << 8) | csd[7]; - result = (result << 2) | (csd[6] >> 6); - result = (result + 1) * mult * block_len / 512; + ctx->error = 0; + while((sdmmc_read16(REG_SDSTATUS1) & TMIO_STAT1_CMD_BUSY)); //mmc working? + sdmmc_write16(REG_SDIRMASK0,0); + sdmmc_write16(REG_SDIRMASK1,0); + sdmmc_write16(REG_SDSTATUS0,0); + sdmmc_write16(REG_SDSTATUS1,0); + sdmmc_write16(REG_SDCMDARG0,args &0xFFFF); + sdmmc_write16(REG_SDCMDARG1,args >> 16); + sdmmc_write16(REG_SDCMD,cmd &0xFFFF); + + uint32_t size = ctx->size; + uint16_t *dataPtr = (uint16_t*)ctx->data; + uint32_t *dataPtr32 = (uint32_t*)ctx->data; + + bool useBuf = ( NULL != dataPtr ); + bool useBuf32 = (useBuf && (0 == (3 & ((uint32_t)dataPtr)))); + + uint16_t status0 = 0; + + while(1) { + volatile uint16_t status1 = sdmmc_read16(REG_SDSTATUS1); + volatile uint16_t ctl32 = sdmmc_read16(REG_SDDATACTL32); + if((ctl32 & 0x100)) + { + if(readdata) { + if(useBuf) { + sdmmc_mask16(REG_SDSTATUS1, TMIO_STAT1_RXRDY, 0); + if(size > 0x1FF) { + if(useBuf32) { + for(i = 0; i<0x200; i+=4) { + *dataPtr32++ = sdmmc_read32(REG_SDFIFO32); + } + } else { + for(i = 0; i<0x200; i+=2) { + *dataPtr++ = sdmmc_read16(REG_SDFIFO); + } + } + size -= 0x200; + } + } + + sdmmc_mask16(REG_SDDATACTL32, 0x800, 0); } + } + + if(status1 & TMIO_MASK_GW) { + ctx->error |= 4; break; - case 1: - result = csd[7] & 0x3f; - result = (result << 8) | csd[6]; - result = (result << 8) | csd[5]; - result = (result + 1) * 1024; - break; + } + + if(!(status1 & TMIO_STAT1_CMD_BUSY)) { + status0 = sdmmc_read16(REG_SDSTATUS0); + if(sdmmc_read16(REG_SDSTATUS0) & TMIO_STAT0_CMDRESPEND) { + ctx->error |= 0x1; + } + if(status0 & TMIO_STAT0_DATAEND) { + ctx->error |= 0x2; + } + + if((status0 & flags) == flags) + break; + } + } + ctx->stat0 = sdmmc_read16(REG_SDSTATUS0); + ctx->stat1 = sdmmc_read16(REG_SDSTATUS1); + sdmmc_write16(REG_SDSTATUS0,0); + sdmmc_write16(REG_SDSTATUS1,0); + + if(getSDRESP != 0) { + ctx->ret[0] = sdmmc_read16(REG_SDRESP0) | (sdmmc_read16(REG_SDRESP1) << 16); + ctx->ret[1] = sdmmc_read16(REG_SDRESP2) | (sdmmc_read16(REG_SDRESP3) << 16); + ctx->ret[2] = sdmmc_read16(REG_SDRESP4) | (sdmmc_read16(REG_SDRESP5) << 16); + ctx->ret[3] = sdmmc_read16(REG_SDRESP6) | (sdmmc_read16(REG_SDRESP7) << 16); } - return result; +} + + +//--------------------------------------------------------------------------------- +int sdmmc_cardinserted() { +//--------------------------------------------------------------------------------- + return 1; //sdmmc_cardready; } //--------------------------------------------------------------------------------- @@ -257,21 +137,11 @@ void sdmmc_controller_init(bool force) { *(vu16*)(SDMMC_BASE + REG_SDDATACTL32) &= 0xF7FFu; *(vu16*)(SDMMC_BASE + REG_SDDATACTL32) &= 0xEFFFu; -#ifdef DATA32_SUPPORT - *(vu16*)(SDMMC_BASE + REG_SDDATACTL32) |= 0x402u; -#else *(vu16*)(SDMMC_BASE + REG_SDDATACTL32) |= 0x402u; -#endif *(vu16*)(SDMMC_BASE + REG_SDDATACTL) = (*(vu16*)(SDMMC_BASE + REG_SDDATACTL) & 0xFFDD) | 2; -#ifdef DATA32_SUPPORT *(vu16*)(SDMMC_BASE + REG_SDDATACTL32) &= 0xFFFFu; *(vu16*)(SDMMC_BASE + REG_SDDATACTL) &= 0xFFDFu; *(vu16*)(SDMMC_BASE + REG_SDBLKLEN32) = 512; -#else - *(vu16*)(SDMMC_BASE + REG_SDDATACTL32) &= 0xFFFDu; - *(vu16*)(SDMMC_BASE + REG_SDDATACTL) &= 0xFFDDu; - *(vu16*)(SDMMC_BASE + REG_SDBLKLEN32) = 0; -#endif *(vu16*)(SDMMC_BASE + REG_SDBLKCOUNT32) = 1; *(vu16*)(SDMMC_BASE + REG_SDRESET) &= 0xFFFEu; *(vu16*)(SDMMC_BASE + REG_SDRESET) |= 1u; @@ -280,40 +150,27 @@ void sdmmc_controller_init(bool force) { *(vu16*)(SDMMC_BASE + 0x0fc) |= 0xDBu; //SDCTL_RESERVED7 *(vu16*)(SDMMC_BASE + 0x0fe) |= 0xDBu; //SDCTL_RESERVED8 *(vu16*)(SDMMC_BASE + REG_SDPORTSEL) &= 0xFFFCu; -#ifdef DATA32_SUPPORT *(vu16*)(SDMMC_BASE + REG_SDCLKCTL) = 0x20; *(vu16*)(SDMMC_BASE + REG_SDOPT) = 0x40EE; -#else - *(vu16*)(SDMMC_BASE + REG_SDCLKCTL) = 0x40; //Nintendo sets this to 0x20 - *(vu16*)(SDMMC_BASE + REG_SDOPT) = 0x40EB; //Nintendo sets this to 0x40EE -#endif *(vu16*)(SDMMC_BASE + REG_SDPORTSEL) &= 0xFFFCu; *(vu16*)(SDMMC_BASE + REG_SDBLKLEN) = 512; *(vu16*)(SDMMC_BASE + REG_SDSTOP) = 0; - setTarget(&deviceSD); } //--------------------------------------------------------------------------------- int sdmmc_sdcard_init() { //--------------------------------------------------------------------------------- - // We need to send at least 74 clock pulses. setTarget(&deviceSD); - swiDelay(0x1980); // ~75-76 clocks - - // card reset + swiDelay(0xF000); sdmmc_send_command(&deviceSD,0,0); - - // CMD8 0x1AA sdmmc_send_command(&deviceSD,0x10408,0x1AA); u32 temp = (deviceSD.error & 0x1) << 0x1E; u32 temp2 = 0; do { do { - // CMD55 sdmmc_send_command(&deviceSD,0x10437,deviceSD.initarg << 0x10); - // ACMD41 sdmmc_send_command(&deviceSD,0x10769,0x00FF8000 | temp); temp2 = 1; } while ( !(deviceSD.error & 1) ); @@ -335,22 +192,18 @@ int sdmmc_sdcard_init() { sdmmc_send_command(&deviceSD,0x10609,deviceSD.initarg << 0x10); if (deviceSD.error & 0x4) return -1; - deviceSD.total_size = calcSDSize((u8*)&deviceSD.ret[0],-1); deviceSD.clk = 1; setckl(1); sdmmc_send_command(&deviceSD,0x10507,deviceSD.initarg << 0x10); if (deviceSD.error & 0x4) return -1; - // CMD55 sdmmc_send_command(&deviceSD,0x10437,deviceSD.initarg << 0x10); if (deviceSD.error & 0x4) return -1; - // ACMD42 sdmmc_send_command(&deviceSD,0x1076A,0x0); if (deviceSD.error & 0x4) return -1; - // CMD55 sdmmc_send_command(&deviceSD,0x10437,deviceSD.initarg << 0x10); if (deviceSD.error & 0x4) return -1; @@ -370,22 +223,20 @@ int sdmmc_sdcard_init() { } //--------------------------------------------------------------------------------- -int sdmmc_sdcard_readsectors(u32 sector_no, u32 numsectors, void *out) { +bool sdmmc_sdcard_readsectors(u32 sector_no, u32 numsectors, void *out) { //--------------------------------------------------------------------------------- if (deviceSD.isSDHC == 0) sector_no <<= 9; setTarget(&deviceSD); sdmmc_write16(REG_SDSTOP,0x100); -#ifdef DATA32_SUPPORT sdmmc_write16(REG_SDBLKCOUNT32,numsectors); sdmmc_write16(REG_SDBLKLEN32,0x200); -#endif sdmmc_write16(REG_SDBLKCOUNT,numsectors); - deviceSD.rData = out; + deviceSD.data = out; deviceSD.size = numsectors << 9; sdmmc_send_command(&deviceSD,0x33C12,sector_no); - return geterror(&deviceSD); + return geterror(&deviceSD) == 0; } #endif \ No newline at end of file diff --git a/bootloader/source/sdmmc.h b/bootloader/source/sdmmc.h index d3a6d8d1..01455206 100644 --- a/bootloader/source/sdmmc.h +++ b/bootloader/source/sdmmc.h @@ -105,11 +105,8 @@ #define TMIO_MASK_WRITEOP (TMIO_STAT1_TXRQ | TMIO_STAT1_DATAEND) typedef struct mmcdevice { - u8* rData; - const u8* tData; + u8* data; u32 size; - u32 startOffset; - u32 endOffset; u32 error; u16 stat0; u16 stat1; @@ -144,10 +141,12 @@ static inline void sdmmc_sdcard_cid( u32 *cid) { sdmmc_get_cid(MMC_DEVICE_SDCARD,cid); } -int sdmmc_sdcard_readsectors(u32 sector_no, u32 numsectors, void *out); +bool sdmmc_sdcard_readsectors(u32 sector_no, u32 numsectors, void *out); +/* int sdmmc_sdcard_writesectors(u32 sector_no, u32 numsectors, void *in); int sdmmc_nand_readsectors(u32 sector_no, u32 numsectors, void *out); int sdmmc_nand_writesectors(u32 sector_no, u32 numsectors, void *in); +*/ extern u32 sdmmc_cid[]; extern int sdmmc_curdevice; diff --git a/bootloader/source/tonccpy.c b/bootloader/source/tonccpy.c deleted file mode 100644 index a51437ec..00000000 --- a/bootloader/source/tonccpy.c +++ /dev/null @@ -1,136 +0,0 @@ -#include "tonccpy.h" -//# tonccpy.c - -//! VRAM-safe cpy. -/*! This version mimics memcpy in functionality, with - the benefit of working for VRAM as well. It is also - slightly faster than the original memcpy, but faster - implementations can be made. - \param dst Destination pointer. - \param src Source pointer. - \param size Fill-length in bytes. - \note The pointers and size need not be word-aligned. -*/ -void tonccpy(void *dst, const void *src, uint size) -{ - if(size==0 || dst==0 || src==0) - return; - - uint count; - u16 *dst16; // hword destination - u8 *src8; // byte source - - // Ideal case: copy by 4x words. Leaves tail for later. - if( ((u32)src|(u32)dst)%4==0 && size>=4) - { - u32 *src32= (u32*)src, *dst32= (u32*)dst; - - count= size/4; - uint tmp= count&3; - count /= 4; - - // Duff's Device, good friend! - switch(tmp) { - do { *dst32++ = *src32++; - case 3: *dst32++ = *src32++; - case 2: *dst32++ = *src32++; - case 1: *dst32++ = *src32++; - case 0: ; } while(count--); - } - - // Check for tail - size &= 3; - if(size == 0) - return; - - src8= (u8*)src32; - dst16= (u16*)dst32; - } - else // Unaligned. - { - uint dstOfs= (u32)dst&1; - src8= (u8*)src; - dst16= (u16*)(dst-dstOfs); - - // Head: 1 byte. - if(dstOfs != 0) - { - *dst16= (*dst16 & 0xFF) | *src8++<<8; - dst16++; - if(--size==0) - return; - } - } - - // Unaligned main: copy by 2x byte. - count= size/2; - while(count--) - { - *dst16++ = src8[0] | src8[1]<<8; - src8 += 2; - } - - // Tail: 1 byte. - if(size&1) - *dst16= (*dst16 &~ 0xFF) | *src8; -} -//# toncset.c - -//! VRAM-safe memset, internal routine. -/*! This version mimics memset in functionality, with - the benefit of working for VRAM as well. It is also - slightly faster than the original memset. - \param dst Destination pointer. - \param fill Word to fill with. - \param size Fill-length in bytes. - \note The \a dst pointer and \a size need not be - word-aligned. In the case of unaligned fills, \a fill - will be masked off to match the situation. -*/ -void __toncset(void *dst, u32 fill, uint size) -{ - if(size==0 || dst==0) - return; - - uint left= (u32)dst&3; - u32 *dst32= (u32*)(dst-left); - u32 count, mask; - - // Unaligned head. - if(left != 0) - { - // Adjust for very small stint. - if(left+size<4) - { - mask= BIT_MASK(size*8)<<(left*8); - *dst32= (*dst32 &~ mask) | (fill & mask); - return; - } - - mask= BIT_MASK(left*8); - *dst32= (*dst32 & mask) | (fill&~mask); - dst32++; - size -= 4-left; - } - - // Main stint. - count= size/4; - uint tmp= count&3; - count /= 4; - - switch(tmp) { - do { *dst32++ = fill; - case 3: *dst32++ = fill; - case 2: *dst32++ = fill; - case 1: *dst32++ = fill; - case 0: ; } while(count--); - } - - // Tail - size &= 3; - if(size) - { - mask= BIT_MASK(size*8); - *dst32= (*dst32 &~ mask) | (fill & mask); - } -} diff --git a/bootloader/source/tonccpy.h b/bootloader/source/tonccpy.h deleted file mode 100644 index dd4267dc..00000000 --- a/bootloader/source/tonccpy.h +++ /dev/null @@ -1,43 +0,0 @@ -//# Stuff you may not have yet. - -#ifndef TONCCPY_H -#define TONCCPY_H - - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -typedef unsigned int uint; -#define BIT_MASK(len) ( (1<<(len))-1 ) -static inline u32 quad8(u16 x) { x |= x<<8; return x | x<<16; } - - -//# Declarations and inlines. - -void tonccpy(void *dst, const void *src, uint size); - -void __toncset(void *dst, u32 fill, uint size); -static inline void toncset(void *dst, u8 src, uint size); -static inline void toncset16(void *dst, u16 src, uint size); -static inline void toncset32(void *dst, u32 src, uint size); - - -//! VRAM-safe memset, byte version. Size in bytes. -static inline void toncset(void *dst, u8 src, uint size) -{ __toncset(dst, quad8(src), size); } - -//! VRAM-safe memset, halfword version. Size in hwords. -static inline void toncset16(void *dst, u16 src, uint size) -{ __toncset(dst, src|src<<16, size*2); } - -//! VRAM-safe memset, word version. Size in words. -static inline void toncset32(void *dst, u32 src, uint size) -{ __toncset(dst, src, size*4); } - -#ifdef __cplusplus -} -#endif -#endif diff --git a/bootstub/bootstub.s b/bootstub/bootstub.s index 14a1d99c..579fb990 100644 --- a/bootstub/bootstub.s +++ b/bootstub/bootstub.s @@ -25,8 +25,6 @@ _start: .ascii "bootstub" .word hook7from9 - _start .word hook9from7 - _start -_loader_addr: - .word _loader - _start _loader_size: .word 0 @@ -121,10 +119,10 @@ hook7from9: mov r0,#0x80 strb r0,[r3,#0x242-0x180] - ldr r0, _loader_addr + adr r0, _loader ldr r2, _loader_size mov r1, #0x06800000 - add r1, r1, #0x48000 + add r1, r1, #0x40000 add r2, r0, r2 _copyloader: ldr r4, [r0], #4 @@ -142,7 +140,6 @@ _copyloader: ldr r0, arm7bootaddr mov r1, #0x06000000 - add r1, r1, #0x8000 str r1, [r0] ldr r0, resetcode diff --git a/libnds32 b/libnds32 deleted file mode 160000 index 117e4642..00000000 --- a/libnds32 +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 117e464254ec2767ee5ac8baac2536b1d4a41bac diff --git a/nitrofiles/languages/en-US/language.ini b/nitrofiles/languages/en-US/language.ini index 7b739683..ef872245 100644 --- a/nitrofiles/languages/en-US/language.ini +++ b/nitrofiles/languages/en-US/language.ini @@ -46,7 +46,7 @@ SDCARD_LABEL=[sd:] SDCARD (%s) FLASHCARD_LABEL=[fat:] FLASHCARD (%s) RAMDRIVE_LABEL=[ram:] RAMDRIVE SYSNAND_LABEL=[nand:] SYSNAND -SYSNAND_PHOTO_LABEL=[photo:] SYSNAND (photo) +SYSNAND_PHOTO_LABEL=[nand2:] SYSNAND (photo) NITROFS_LABEL=[nitro:] NDS GAME IMAGE FAT_LABEL=[img:] FAT IMAGE (%s) GBA_GAMECART=GBA GAMECART (%s) diff --git a/shared/include/pxiVars.h b/shared/include/pxiVars.h new file mode 100644 index 00000000..17280fe6 --- /dev/null +++ b/shared/include/pxiVars.h @@ -0,0 +1,27 @@ +#ifndef PXIVARS_H +#define PXIVARS_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define PXI_MAIN PxiChannel_User0 + +typedef enum { + PXI_FAILURE, + PXI_SUCCESS, + GET_ARM7_VARS, + GBA_READ_EEPROM, + GBA_WRITE_EEPROM, +} PxiCommand; + +typedef enum { + CAPTURE_MODE_PREVIEW = 1, // 256x192 + CAPTURE_MODE_CAPTURE = 2 // 640x480 +} CaptureMode; + +#ifdef __cplusplus +} +#endif + +#endif // PXIVARS_H