diff --git a/Makefile b/Makefile index b924a20..71a0bef 100644 --- a/Makefile +++ b/Makefile @@ -12,4 +12,4 @@ code11.bin: make -f Makefile.arm11 firm.bin: - $(DEVKITARM)/bin/firm_builder firm.bin 0x08000040 0x1FF85040 0x08000040 0 code9.bin 0x1FF85000 1 code11.bin + firm_builder firm.bin 0x08000040 0x1FF85040 0x08000040 0 code9.bin 0x1FF85000 1 code11.bin diff --git a/include/arm9/firm.h b/include/arm9/firm.h index a422865..9e5dade 100644 --- a/include/arm9/firm.h +++ b/include/arm9/firm.h @@ -6,7 +6,9 @@ #define FIRM_LOAD_ADDR (VRAM_BASE + 0x200000) #define FIRM_MAX_SIZE (0x00400000) - +#define FIRM_SECTION_CORRUPTED 0xBAD5EC +#define FIRM_FATAL_ERROR 0xBADBAD +#define FIRM_GOOD 0x900D typedef struct { diff --git a/include/arm9/main.h b/include/arm9/main.h index ba95c96..8b4dfbe 100644 --- a/include/arm9/main.h +++ b/include/arm9/main.h @@ -32,5 +32,4 @@ void unmount_nand_fs(); u8 rng_get_byte(); void clearConsoles(); -bool tryLoadFirmware(const char *filepath); void power_off_safe(); diff --git a/include/arm9/menu.h b/include/arm9/menu.h index ced43ce..2809231 100644 --- a/include/arm9/menu.h +++ b/include/arm9/menu.h @@ -9,6 +9,7 @@ MENU_STATE_FIRM_LAUNCH, MENU_STATE_BROWSER, MENU_STATE_TEST_CONFIG, + MENU_STATE_EXIT, STATE_PREVIOUS // pseudo state for menuSetReturnToState() }; diff --git a/source/arm9/filebrowse.c b/source/arm9/filebrowse.c deleted file mode 100644 index 42400ca..0000000 --- a/source/arm9/filebrowse.c +++ /dev/null @@ -1,337 +0,0 @@ -#include -#include -#include -#include "types.h" -#include "mem_map.h" -#include "fatfs/ff.h" -#include "arm9/console.h" -#include "arm9/main.h" -#include "arm9/menu.h" -#include "arm9/interrupt.h" -#include "util.h" -#include "hid.h" - -#define MAX_CACHED_ENTRIES 0x400 -#define MAX_ENTRY_SIZE _MAX_LFN + 2 -#define MAX_NEW_ENTRIES 0x20 -#define MAX_PATH_LENGTH 0x400 -#define MAX_PATH_DEPTH 0x20 - -typedef struct { - char name[MAX_ENTRY_SIZE]; - bool isDir; -} EntryType; - -static EntryType *dirEntries; // [MAX_ENTRY_SIZE][MAX_CACHED_ENTRIES]; -static DIR curDirectory; -static char curPath[MAX_PATH_LENGTH]; -static u32 curEntriesCount; - -// This stack is used to recover the original cursor position -// in the dir entries list when returning from a subdir. -static u32 indexStack[MAX_PATH_DEPTH]; -static u32 *indexStackPtr = indexStack; - -/* This scans the current directory for entries. - Only MAX_NEW_ENTRIES will be added at maximum. - This also updates the curEntriesCount. - Returns true if new entries were added. */ -static bool scanDirectory() -{ - FRESULT res; - static FILINFO fno; - unsigned i = 0; - - for(i=0; i bufSize - 1) - { - end = in + entryLen; - strcpy(&out[3], end - bufSize + 3); - memcpy(out, "...", 3); - } - else strcpy(out, in); - } - else - { - if(entryLen > bufSize - 1) - { - memcpy(out, in, bufSize - 4); - memcpy(&out[bufSize - 5], "...", 4); - } - else strcpy(out, in); - } -} - -static void updateCursor(int cursor_pos, int old_cursor_pos, int maxEntries) -{ - // clear old '*' char - consoleSetCursor(&con_bottom, 0, (old_cursor_pos % (maxEntries)) + 1); - printf(" "); - - consoleSetCursor(&con_bottom, 0, (cursor_pos % (maxEntries)) + 1); - printf("*"); -} - -static void updateScreen(int cursor_pos, bool dirChange) -{ - // we don't want ugly line breaks in our list - const int maxLen = con_bottom.windowWidth - 1; - const int maxEntries = con_bottom.windowHeight - 1; - - static int old_cursor_pos; - - consoleSelect(&con_bottom); - - if(!dirChange && (cursor_pos < maxEntries) && (old_cursor_pos < maxEntries)) - { - updateCursor(cursor_pos, old_cursor_pos, maxEntries); - old_cursor_pos = cursor_pos; - return; - } - - old_cursor_pos = cursor_pos; - - char entry [maxLen]; // should be safe - unsigned start, end; - - consoleClear(); - - // print the current path in the first line - formatEntry(entry, curPath, (u32) maxLen - 3, false); - printf("%s :", entry); - - if(cursor_pos < (u32) maxEntries) - { - start = 0; - end = min(maxEntries, curEntriesCount); - } - else - { - start = cursor_pos - maxEntries + 1; - end = min(cursor_pos + 1, curEntriesCount); - } - - for(unsigned i = start; i < end; i++) - { - formatEntry(entry, dirEntries[i].name, (u32) maxLen - 2, true); - printf("\n%s %s", i == (unsigned) cursor_pos ? "*" : " ", entry); - } -} - -const char *browseForFile(const char *basePath) -{ - FRESULT res; - u32 keys; - u32 cursor_pos = 0; - bool fileSelected = false; - - curEntriesCount = 0; - indexStackPtr = indexStack; - - dirEntries = (EntryType *) malloc(MAX_CACHED_ENTRIES * sizeof(EntryType)); - if(!dirEntries) - { - menuSetReturnToState(STATE_PREVIOUS); - menuUpdateGlobalState(); - menuActState(); - return NULL; - } - - if(basePath) - strncpy_s(curPath, basePath, sizeof(curPath) - 1, sizeof(curPath)); - else - strncpy_s(curPath, "sdmc:", sizeof(curPath) - 1, sizeof(curPath)); - - res = f_opendir(&curDirectory, curPath); - if (res != FR_OK) - { - free(dirEntries); - menuSetReturnToState(STATE_PREVIOUS); - menuUpdateGlobalState(); - menuActState(); - return NULL; - } - - // do an initial scan - scanDirectory(); - - updateScreen((int)cursor_pos, true); - - for(;;) - { - hidScanInput(); - keys = hidKeysDown()/* | hidKeysHeld()*/; - - if(curEntriesCount != 0) - { - if(keys & KEY_DUP || keys & KEY_DLEFT) - { - if(cursor_pos != 0) - { - cursor_pos -= keys & KEY_DLEFT ? min(cursor_pos, 8) : 1; - updateScreen((int)cursor_pos, false); - } - } - - else if(keys & KEY_DDOWN || keys & KEY_DRIGHT) - { - // we reached the end of our entries list? - u32 old_pos = cursor_pos; - cursor_pos += keys & KEY_DRIGHT ? 8 : 1; - if(cursor_pos >= curEntriesCount) - { - scanDirectory(); - // we got more entries? - if(curEntriesCount > cursor_pos) - cursor_pos = min(cursor_pos, curEntriesCount - 1); - else - cursor_pos = curEntriesCount - 1; - if(cursor_pos != old_pos) - updateScreen((int)cursor_pos, false); - } - else - { - updateScreen((int)cursor_pos, false); - } - } - - else if(keys & KEY_A) // select entry - { - if(dirEntries[cursor_pos].isDir) // it's a dir - { - if(descendPath(cursor_pos, dirEntries[cursor_pos].name)) - { - f_closedir(&curDirectory); - res = f_opendir(&curDirectory, curPath); - if (res != FR_OK) - ascendPath(); - else - { - // fetch new entries - curEntriesCount = 0; - scanDirectory(); - cursor_pos = 0; - updateScreen((int)cursor_pos, true); - } - } - } - else // we got our file! - { - if(strlen(dirEntries[cursor_pos].name) + strlen(curPath) + 2 > sizeof(curPath)) - goto fail; // TODO? Path too long. - strcat(curPath, "\\"); - strcat(curPath, dirEntries[cursor_pos].name); - fileSelected = true; - menuSetReturnToState(STATE_PREVIOUS); - } - } - } - if(keys & KEY_B) // go back - { - if(indexStackPtr != indexStack) - { - cursor_pos = ascendPath(); - f_closedir(&curDirectory); - - res = f_opendir(&curDirectory, curPath); - if (res != FR_OK) - goto fail; - curEntriesCount = 0; - - do { - if(!scanDirectory()) - goto fail; - } while(curEntriesCount <= cursor_pos); - - updateScreen((int)cursor_pos, true); - } - else - menuSetReturnToState(STATE_PREVIOUS); - } - - switch(menuUpdateGlobalState()) - { - case MENU_EVENT_HOME_PRESSED: - case MENU_EVENT_POWER_PRESSED: - case MENU_EVENT_SD_CARD_REMOVED: - goto fail; - case MENU_EVENT_STATE_CHANGE: - if(!fileSelected) goto fail; - else goto done; - default: - break; - } - - //menuActState(); - - } - -done: - - f_closedir(&curDirectory); - free(dirEntries); - - //menuActState(); - - return curPath; - -fail: - - f_closedir(&curDirectory); - free(dirEntries); - - //menuActState(); - - return NULL; -} diff --git a/source/arm9/main.c b/source/arm9/main.c index 6ca312c..a323101 100644 --- a/source/arm9/main.c +++ b/source/arm9/main.c @@ -21,7 +21,6 @@ static void fw_detect(); static bool loadSettings(int *mode); bool tryLoadFirmwareFromSettings(); -u32 loadFirmSd(const char *filePath); // TODO: remove after debugging extern void panic(void); @@ -326,7 +325,7 @@ } } - if(tryLoadFirmware(path)) + if(menuLaunchFirm(path)) break; } @@ -339,72 +338,6 @@ return true; } -bool tryLoadFirmware(const char *filepath) -{ - u32 fw_size; - - if(!filepath) - return false; - - printf("Loading firmware:\n%s\n", filepath); - - if(strncmp(filepath, "sdmc:", 5) == 0) - fw_size = loadFirmSd(filepath); - else - return false; // TODO: Support more devices - - if(fw_size == 0) - return false; - - return firm_verify(fw_size); -} - -static void loadFirmNand(void) -{ - dev_decnand->read_sector(0x0005A980, 0x00002000, (u8*)FIRM_LOAD_ADDR); -} - -u32 loadFirmSd(const char *filePath) -{ - FIL file; - u32 fileSize; - UINT bytesRead = 0; - FILINFO fileStat; - - if(f_stat(filePath, &fileStat) != FR_OK) - { - printf("Failed to get file status!\n"); - return 0; - } - - fileSize = fileStat.fsize; - - if(f_open(&file, filePath, FA_READ) != FR_OK) - { - printf("Failed to open '%s'!\n", filePath); - return 0; - } - - if(fileSize > FIRM_MAX_SIZE) - { - f_close(&file); - return 0; - } - - if(f_read(&file, (u8*)FIRM_LOAD_ADDR, fileSize, &bytesRead) != FR_OK) - { - printf("Failed to read from file!\n"); - fileSize = 0; - } - - if(bytesRead != fileSize) - fileSize = 0; - - f_close(&file); - - return fileSize; -} - void clearConsoles() { consoleSelect(&con_bottom); diff --git a/source/arm9/menu.c b/source/arm9/menu.c index 0892d76..6b7e1c6 100644 --- a/source/arm9/menu.c +++ b/source/arm9/menu.c @@ -96,7 +96,7 @@ cursor_pos = 0; - TIMER_start(TIMER_0, TIMER_PRESCALER_64, TIMER_FREQ_64(60.0f), menuActState); + TIMER_start(TIMER_0, TIMER_PRESCALER_64, TIMER_FREQ_64(60.0f), NULL); // caller requested to enter a submenu? if(initial_state != MENU_STATE_MAIN) @@ -180,9 +180,8 @@ const char* path = browseForFile("sdmc:"); consoleClear(); printf("selected file:\n%s\n", path); - wait(0x8000000); - if(!tryLoadFirmware(path)) printf("bad firm\n"); - else goto exitAndLaunchFirm; + if(!menuLaunchFirm(path)) + clearConsoles(); break; case MENU_STATE_TEST_CONFIG: @@ -226,12 +225,14 @@ { case MENU_EVENT_HOME_PRESSED: break; - + case MENU_EVENT_STATE_CHANGE: + if(menu_next_state == MENU_STATE_EXIT) + goto exitAndLaunchFirm; default: break; } - //menuActState(); + menuActState(); } exitAndLaunchFirm: @@ -251,6 +252,10 @@ state = menu_previous_states[menu_previous_states_count - 1]; menu_previous_states_count--; } + else if(state == MENU_STATE_EXIT) + { + menu_previous_states_count = 0; + } else { for(i=menu_previous_states_count; i>0; i--) @@ -290,7 +295,7 @@ // Later if PXI interrupts are implemented we need an // interrupt handler here which can tell the timer and // PXI interrupts apart. - waitForIrq(); + //waitForIrq(); /* Check PXI Response register */ diff --git a/source/arm9/menu_filebrowse.c b/source/arm9/menu_filebrowse.c new file mode 100644 index 0000000..a8eca5a --- /dev/null +++ b/source/arm9/menu_filebrowse.c @@ -0,0 +1,337 @@ +#include +#include +#include +#include "types.h" +#include "mem_map.h" +#include "fatfs/ff.h" +#include "arm9/console.h" +#include "arm9/main.h" +#include "arm9/menu.h" +#include "arm9/interrupt.h" +#include "util.h" +#include "hid.h" + +#define MAX_CACHED_ENTRIES 0x400 +#define MAX_ENTRY_SIZE _MAX_LFN + 2 +#define MAX_NEW_ENTRIES 0x20 +#define MAX_PATH_LENGTH 0x400 +#define MAX_PATH_DEPTH 0x20 + +typedef struct { + char name[MAX_ENTRY_SIZE]; + bool isDir; +} EntryType; + +static EntryType *dirEntries; // [MAX_ENTRY_SIZE][MAX_CACHED_ENTRIES]; +static DIR curDirectory; +static char curPath[MAX_PATH_LENGTH]; +static u32 curEntriesCount; + +// This stack is used to recover the original cursor position +// in the dir entries list when returning from a subdir. +static u32 indexStack[MAX_PATH_DEPTH]; +static u32 *indexStackPtr = indexStack; + +/* This scans the current directory for entries. + Only MAX_NEW_ENTRIES will be added at maximum. + This also updates the curEntriesCount. + Returns true if new entries were added. */ +static bool scanDirectory() +{ + FRESULT res; + static FILINFO fno; + unsigned i = 0; + + for(i=0; i bufSize - 1) + { + end = in + entryLen; + strcpy(&out[3], end - bufSize + 3); + memcpy(out, "...", 3); + } + else strcpy(out, in); + } + else + { + if(entryLen > bufSize - 1) + { + memcpy(out, in, bufSize - 4); + memcpy(&out[bufSize - 5], "...", 4); + } + else strcpy(out, in); + } +} + +static void updateCursor(int cursor_pos, int old_cursor_pos, int maxEntries) +{ + // clear old '*' char + consoleSetCursor(&con_bottom, 0, (old_cursor_pos % (maxEntries)) + 1); + printf(" "); + + consoleSetCursor(&con_bottom, 0, (cursor_pos % (maxEntries)) + 1); + printf("*"); +} + +static void updateScreen(int cursor_pos, bool dirChange) +{ + // we don't want ugly line breaks in our list + const int maxLen = con_bottom.windowWidth - 1; + const int maxEntries = con_bottom.windowHeight - 1; + + static int old_cursor_pos; + + consoleSelect(&con_bottom); + + if(!dirChange && (cursor_pos < maxEntries) && (old_cursor_pos < maxEntries)) + { + updateCursor(cursor_pos, old_cursor_pos, maxEntries); + old_cursor_pos = cursor_pos; + return; + } + + old_cursor_pos = cursor_pos; + + char entry [maxLen]; // should be safe + unsigned start, end; + + consoleClear(); + + // print the current path in the first line + formatEntry(entry, curPath, (u32) maxLen - 3, false); + printf("%s :", entry); + + if(cursor_pos < (u32) maxEntries) + { + start = 0; + end = min(maxEntries, curEntriesCount); + } + else + { + start = cursor_pos - maxEntries + 1; + end = min(cursor_pos + 1, curEntriesCount); + } + + for(unsigned i = start; i < end; i++) + { + formatEntry(entry, dirEntries[i].name, (u32) maxLen - 2, true); + printf("\n%s %s", i == (unsigned) cursor_pos ? "*" : " ", entry); + } +} + +const char *browseForFile(const char *basePath) +{ + FRESULT res; + u32 keys; + u32 cursor_pos = 0; + bool fileSelected = false; + + curEntriesCount = 0; + indexStackPtr = indexStack; + + dirEntries = (EntryType *) malloc(MAX_CACHED_ENTRIES * sizeof(EntryType)); + if(!dirEntries) + { + menuSetReturnToState(STATE_PREVIOUS); + menuUpdateGlobalState(); + menuActState(); + return NULL; + } + + if(basePath) + strncpy_s(curPath, basePath, sizeof(curPath) - 1, sizeof(curPath)); + else + strncpy_s(curPath, "sdmc:", sizeof(curPath) - 1, sizeof(curPath)); + + res = f_opendir(&curDirectory, curPath); + if (res != FR_OK) + { + free(dirEntries); + menuSetReturnToState(STATE_PREVIOUS); + menuUpdateGlobalState(); + menuActState(); + return NULL; + } + + // do an initial scan + scanDirectory(); + + updateScreen((int)cursor_pos, true); + + for(;;) + { + hidScanInput(); + keys = hidKeysDown()/* | hidKeysHeld()*/; + + if(curEntriesCount != 0) + { + if(keys & KEY_DUP || keys & KEY_DLEFT) + { + if(cursor_pos != 0) + { + cursor_pos -= keys & KEY_DLEFT ? min(cursor_pos, 8) : 1; + updateScreen((int)cursor_pos, false); + } + } + + else if(keys & KEY_DDOWN || keys & KEY_DRIGHT) + { + // we reached the end of our entries list? + u32 old_pos = cursor_pos; + cursor_pos += keys & KEY_DRIGHT ? 8 : 1; + if(cursor_pos >= curEntriesCount) + { + scanDirectory(); + // we got more entries? + if(curEntriesCount > cursor_pos) + cursor_pos = min(cursor_pos, curEntriesCount - 1); + else + cursor_pos = curEntriesCount - 1; + if(cursor_pos != old_pos) + updateScreen((int)cursor_pos, false); + } + else + { + updateScreen((int)cursor_pos, false); + } + } + + else if(keys & KEY_A) // select entry + { + if(dirEntries[cursor_pos].isDir) // it's a dir + { + if(descendPath(cursor_pos, dirEntries[cursor_pos].name)) + { + f_closedir(&curDirectory); + res = f_opendir(&curDirectory, curPath); + if (res != FR_OK) + ascendPath(); + else + { + // fetch new entries + curEntriesCount = 0; + scanDirectory(); + cursor_pos = 0; + updateScreen((int)cursor_pos, true); + } + } + } + else // we got our file! + { + if(strlen(dirEntries[cursor_pos].name) + strlen(curPath) + 2 > sizeof(curPath)) + goto fail; // TODO? Path too long. + strcat(curPath, "\\"); + strcat(curPath, dirEntries[cursor_pos].name); + fileSelected = true; + menuSetReturnToState(STATE_PREVIOUS); + } + } + } + if(keys & KEY_B) // go back + { + if(indexStackPtr != indexStack) + { + cursor_pos = ascendPath(); + f_closedir(&curDirectory); + + res = f_opendir(&curDirectory, curPath); + if (res != FR_OK) + goto fail; + curEntriesCount = 0; + + do { + if(!scanDirectory()) + goto fail; + } while(curEntriesCount <= cursor_pos); + + updateScreen((int)cursor_pos, true); + } + else + menuSetReturnToState(STATE_PREVIOUS); + } + + switch(menuUpdateGlobalState()) + { + case MENU_EVENT_HOME_PRESSED: + case MENU_EVENT_POWER_PRESSED: + case MENU_EVENT_SD_CARD_REMOVED: + goto fail; + case MENU_EVENT_STATE_CHANGE: + if(!fileSelected) goto fail; + else goto done; + default: + break; + } + + menuActState(); + + } + +done: + + f_closedir(&curDirectory); + free(dirEntries); + + menuActState(); + + return curPath; + +fail: + + f_closedir(&curDirectory); + free(dirEntries); + + menuActState(); + + return NULL; +} diff --git a/source/arm9/menu_firmloader.c b/source/arm9/menu_firmloader.c new file mode 100644 index 0000000..49ded80 --- /dev/null +++ b/source/arm9/menu_firmloader.c @@ -0,0 +1,124 @@ +#include +#include +#include "types.h" +#include "mem_map.h" +#include "arm9/console.h" +#include "arm9/dev.h" +#include "fatfs/ff.h" +#include "hid.h" +#include "util.h" +#include "arm9/main.h" +#include "arm9/timer.h" +#include "arm9/menu.h" +#include "arm9/firm.h" + +static bool tryLoadFirmware(const char *filepath); +static u32 loadFirmSd(const char *filePath); + +bool menuLaunchFirm(const char *filePath) +{ + u32 keys; + + consoleSelect(&con_bottom); + consoleClear(); + consoleSelect(&con_top); + consoleClear(); + + printf("FIRM Loader\n\n"); + + menuUpdateGlobalState(); + + if(!tryLoadFirmware(filePath)) + { + printf("\x1B[31mBad firmware.\e[0m\n"); + goto fail; + } + + printf("\x1B[32mFirmware verification SUCCESS!\e[0m\n\n"); + + printf("Attempting to run firmware, press B to exit...\n"); + + for(int i=0; i<0x800000; i++) + { + hidScanInput(); + keys = hidKeysDown(); + + if(keys & KEY_B) + goto fail; + } + + menuSetReturnToState(MENU_STATE_EXIT); + + return true; + +fail: + + printf("FIRM-Launch aborted.\n"); + + TIMER_sleep(2000); + + menuSetReturnToState(STATE_PREVIOUS); + + return false; +} + +static bool tryLoadFirmware(const char *filepath) +{ + u32 fw_size; + + if(!filepath) + return false; + + printf("Loading firmware:\n%s\n", filepath); + + if(strncmp(filepath, "sdmc:", 5) == 0) + fw_size = loadFirmSd(filepath); + else + return false; // TODO: Support more devices + + if(fw_size == 0) + return false; + + return firm_verify(fw_size); +} + +static u32 loadFirmSd(const char *filePath) +{ + FIL file; + u32 fileSize; + UINT bytesRead = 0; + FILINFO fileStat; + + if(f_stat(filePath, &fileStat) != FR_OK) + { + printf("Failed to get file status!\n"); + return 0; + } + + fileSize = fileStat.fsize; + + if(f_open(&file, filePath, FA_READ) != FR_OK) + { + printf("Failed to open '%s'!\n", filePath); + return 0; + } + + if(fileSize > FIRM_MAX_SIZE) + { + f_close(&file); + return 0; + } + + if(f_read(&file, (u8*)FIRM_LOAD_ADDR, fileSize, &bytesRead) != FR_OK) + { + printf("Failed to read from file!\n"); + fileSize = 0; + } + + if(bytesRead != fileSize) + fileSize = 0; + + f_close(&file); + + return fileSize; +} diff --git a/source/arm9/menu_nand.c b/source/arm9/menu_nand.c new file mode 100644 index 0000000..b39e0bf --- /dev/null +++ b/source/arm9/menu_nand.c @@ -0,0 +1,213 @@ +#include +#include +#include "types.h" +#include "mem_map.h" +#include "arm9/console.h" +#include "arm9/dev.h" +#include "fatfs/ff.h" +#include "hid.h" +#include "util.h" +#include "arm9/menu.h" +#include "arm9/util_nand.h" + + +u64 getFreeSpace(const char *drive) +{ + FATFS *fs; + DWORD freeClusters; + + if(f_getfree(drive, &freeClusters, &fs) != FR_OK) + { + printf("Failed to get free space for '%s'!\n", drive); + return 0; + } + return ((u64)(freeClusters * fs->csize)) * 512; +} + +bool dumpNand(const char *filePath) +{ + const u32 sectorCount = dev_rawnand->get_sector_count(); + const u32 sectorBlkSize = 0x400; // 512 KB in sectors + FIL file; + FRESULT fres; + UINT bytesWritten; + + + consoleSelect(&con_bottom); + printf("\n\t\tPress B to cancel"); + consoleSelect(&con_top); + + u8 *buf = (u8*)malloc(sectorBlkSize<<9); + if(!buf) + panic(); // this should never happen. + + if(getFreeSpace("sdmc:") < sectorCount<<9) + { + printf("Not enough space on the SD card!\n"); + goto fail; + } + + if((fres = f_open(&file, filePath, FA_CREATE_ALWAYS | FA_WRITE)) != FR_OK) + { + printf("Failed to create '%s'! Error: %X\n", filePath, fres); + f_close(&file); + goto fail; + } + + + /* Main loop */ + + u32 curSector = 0; + u32 curSectorBlkSize; + while(curSector < sectorCount) + { + if(curSector + sectorBlkSize < sectorCount) curSectorBlkSize = sectorBlkSize; + else curSectorBlkSize = sectorCount - curSector; + + if(!dev_rawnand->read_sector(curSector, curSectorBlkSize, buf)) + { + printf("\nFailed to read sector 0x%"PRIx32"!\n", curSector); + f_close(&file); + goto fail; + } + if((f_write(&file, buf, curSectorBlkSize<<9, &bytesWritten) != FR_OK) || (bytesWritten != curSectorBlkSize<<9)) + { + printf("\nFailed to write to file!\n"); + f_close(&file); + goto fail; + } + + hidScanInput(); + if(hidKeysDown() & KEY_B) + { + printf("\n...canceled!\n"); + f_close(&file); + goto fail; + } + + curSector += curSectorBlkSize; + + // print current progress information + printf("\r%"PRId32"/%"PRId32" MB (Sector 0x%"PRIX32"/0x%"PRIX32")", curSector>>11, sectorCount>>11, + curSector, sectorCount); + + + switch(menuUpdateGlobalState()) + { + case MENU_EVENT_HOME_PRESSED: + case MENU_EVENT_POWER_PRESSED: + f_close(&file); + case MENU_EVENT_SD_CARD_REMOVED: + menuActState(); + goto fail; + default: + break; + } + + menuActState(); + } + + f_close(&file); + free(buf); + return true; + +fail: + free(buf); + wait(0x8000000); + return false; +} + +bool restoreNand(const char *filePath) +{ + const u32 sectorBlkSize = 0x400; // 512 KB in sectors + FIL file; + UINT bytesRead; + + consoleSelect(&con_bottom); + printf("\n\t\tPress B to cancel"); + consoleSelect(&con_top); + + u8 *buf = (u8*)malloc(sectorBlkSize<<9); + if(!buf) + panic(); // this should never happen. + + FILINFO fileStat; + if(f_stat(filePath, &fileStat) != FR_OK) + { + printf("Failed to get file status!\n"); + goto fail; + } + if(fileStat.fsize > dev_rawnand->get_sector_count()<<9) + { + printf("NAND file is bigger than NAND!\n"); + goto fail; + } + if(fileStat.fsize < 0x200) + { + printf("NAND file is too small!\n"); + goto fail; + } + + if(f_open(&file, filePath, FA_READ) != FR_OK) + { + printf("Failed to open '%s'!\n", filePath); + f_close(&file); + goto fail; + } + + + unmount_nand_fs(); + + /* Main loop */ + + const u32 sectorCount = fileStat.fsize>>9; + u32 curSector = 0; + u32 curSectorBlkSize; + while(curSector < sectorCount) + { + if(curSector + sectorBlkSize < sectorCount) curSectorBlkSize = sectorBlkSize; + else curSectorBlkSize = sectorCount - curSector; + + if(f_read(&file, buf, curSectorBlkSize<<9, &bytesRead) != FR_OK || bytesRead != curSectorBlkSize<<9) + { + printf("\nFailed to read from file!\n"); + f_close(&file); + goto fail; + } + if(!dev_rawnand->write_sector(curSector, curSectorBlkSize, buf)) + { + printf("\nFailed to write sector 0x%"PRIX32"!\n", curSector); + f_close(&file); + goto fail; + } + + curSector += curSectorBlkSize; + printf("\r%"PRId32"/%"PRId32" MB (Sector 0x%"PRIX32"/0x%"PRIX32")", curSector>>11, sectorCount>>11, + curSector, sectorCount); + + switch(menuUpdateGlobalState()) + { + case MENU_EVENT_HOME_PRESSED: + case MENU_EVENT_POWER_PRESSED: + f_close(&file); + case MENU_EVENT_SD_CARD_REMOVED: + menuActState(); + goto fail; + default: + break; + } + + menuActState(); + } + + f_close(&file); + free(buf); + remount_nand_fs(); + return true; + +fail: + free(buf); + remount_nand_fs(); + wait(0x8000000); + return false; +} diff --git a/source/arm9/util_nand.c b/source/arm9/util_nand.c deleted file mode 100644 index b39e0bf..0000000 --- a/source/arm9/util_nand.c +++ /dev/null @@ -1,213 +0,0 @@ -#include -#include -#include "types.h" -#include "mem_map.h" -#include "arm9/console.h" -#include "arm9/dev.h" -#include "fatfs/ff.h" -#include "hid.h" -#include "util.h" -#include "arm9/menu.h" -#include "arm9/util_nand.h" - - -u64 getFreeSpace(const char *drive) -{ - FATFS *fs; - DWORD freeClusters; - - if(f_getfree(drive, &freeClusters, &fs) != FR_OK) - { - printf("Failed to get free space for '%s'!\n", drive); - return 0; - } - return ((u64)(freeClusters * fs->csize)) * 512; -} - -bool dumpNand(const char *filePath) -{ - const u32 sectorCount = dev_rawnand->get_sector_count(); - const u32 sectorBlkSize = 0x400; // 512 KB in sectors - FIL file; - FRESULT fres; - UINT bytesWritten; - - - consoleSelect(&con_bottom); - printf("\n\t\tPress B to cancel"); - consoleSelect(&con_top); - - u8 *buf = (u8*)malloc(sectorBlkSize<<9); - if(!buf) - panic(); // this should never happen. - - if(getFreeSpace("sdmc:") < sectorCount<<9) - { - printf("Not enough space on the SD card!\n"); - goto fail; - } - - if((fres = f_open(&file, filePath, FA_CREATE_ALWAYS | FA_WRITE)) != FR_OK) - { - printf("Failed to create '%s'! Error: %X\n", filePath, fres); - f_close(&file); - goto fail; - } - - - /* Main loop */ - - u32 curSector = 0; - u32 curSectorBlkSize; - while(curSector < sectorCount) - { - if(curSector + sectorBlkSize < sectorCount) curSectorBlkSize = sectorBlkSize; - else curSectorBlkSize = sectorCount - curSector; - - if(!dev_rawnand->read_sector(curSector, curSectorBlkSize, buf)) - { - printf("\nFailed to read sector 0x%"PRIx32"!\n", curSector); - f_close(&file); - goto fail; - } - if((f_write(&file, buf, curSectorBlkSize<<9, &bytesWritten) != FR_OK) || (bytesWritten != curSectorBlkSize<<9)) - { - printf("\nFailed to write to file!\n"); - f_close(&file); - goto fail; - } - - hidScanInput(); - if(hidKeysDown() & KEY_B) - { - printf("\n...canceled!\n"); - f_close(&file); - goto fail; - } - - curSector += curSectorBlkSize; - - // print current progress information - printf("\r%"PRId32"/%"PRId32" MB (Sector 0x%"PRIX32"/0x%"PRIX32")", curSector>>11, sectorCount>>11, - curSector, sectorCount); - - - switch(menuUpdateGlobalState()) - { - case MENU_EVENT_HOME_PRESSED: - case MENU_EVENT_POWER_PRESSED: - f_close(&file); - case MENU_EVENT_SD_CARD_REMOVED: - menuActState(); - goto fail; - default: - break; - } - - menuActState(); - } - - f_close(&file); - free(buf); - return true; - -fail: - free(buf); - wait(0x8000000); - return false; -} - -bool restoreNand(const char *filePath) -{ - const u32 sectorBlkSize = 0x400; // 512 KB in sectors - FIL file; - UINT bytesRead; - - consoleSelect(&con_bottom); - printf("\n\t\tPress B to cancel"); - consoleSelect(&con_top); - - u8 *buf = (u8*)malloc(sectorBlkSize<<9); - if(!buf) - panic(); // this should never happen. - - FILINFO fileStat; - if(f_stat(filePath, &fileStat) != FR_OK) - { - printf("Failed to get file status!\n"); - goto fail; - } - if(fileStat.fsize > dev_rawnand->get_sector_count()<<9) - { - printf("NAND file is bigger than NAND!\n"); - goto fail; - } - if(fileStat.fsize < 0x200) - { - printf("NAND file is too small!\n"); - goto fail; - } - - if(f_open(&file, filePath, FA_READ) != FR_OK) - { - printf("Failed to open '%s'!\n", filePath); - f_close(&file); - goto fail; - } - - - unmount_nand_fs(); - - /* Main loop */ - - const u32 sectorCount = fileStat.fsize>>9; - u32 curSector = 0; - u32 curSectorBlkSize; - while(curSector < sectorCount) - { - if(curSector + sectorBlkSize < sectorCount) curSectorBlkSize = sectorBlkSize; - else curSectorBlkSize = sectorCount - curSector; - - if(f_read(&file, buf, curSectorBlkSize<<9, &bytesRead) != FR_OK || bytesRead != curSectorBlkSize<<9) - { - printf("\nFailed to read from file!\n"); - f_close(&file); - goto fail; - } - if(!dev_rawnand->write_sector(curSector, curSectorBlkSize, buf)) - { - printf("\nFailed to write sector 0x%"PRIX32"!\n", curSector); - f_close(&file); - goto fail; - } - - curSector += curSectorBlkSize; - printf("\r%"PRId32"/%"PRId32" MB (Sector 0x%"PRIX32"/0x%"PRIX32")", curSector>>11, sectorCount>>11, - curSector, sectorCount); - - switch(menuUpdateGlobalState()) - { - case MENU_EVENT_HOME_PRESSED: - case MENU_EVENT_POWER_PRESSED: - f_close(&file); - case MENU_EVENT_SD_CARD_REMOVED: - menuActState(); - goto fail; - default: - break; - } - - menuActState(); - } - - f_close(&file); - free(buf); - remount_nand_fs(); - return true; - -fail: - free(buf); - remount_nand_fs(); - wait(0x8000000); - return false; -}