Added ability to format SD cards

This commit is contained in:
d0k3 2016-07-13 19:59:36 +02:00
parent bf38dbc63b
commit a7b511687b
6 changed files with 131 additions and 7 deletions

View File

@ -55,7 +55,7 @@
/* This option switches fast seek feature. (0:Disable or 1:Enable) */
#define _USE_LABEL 0
#define _USE_LABEL 1
/* This option switches volume label functions, f_getlabel() and f_setlabel().
/ (0:Disable or 1:Enable) */
@ -154,7 +154,7 @@
/ the drive ID strings are: A-Z and 0-9. */
#define _MULTI_PARTITION 0
#define _MULTI_PARTITION 1
/* This option switches multi-partition feature. By default (0), each logical drive
/ number is bound to the same physical drive number and only an FAT volume found on
/ the physical drive will be mounted. When multi-partition feature is enabled (1),

View File

@ -3,6 +3,7 @@
#include "virtual.h"
#include "image.h"
#include "sha.h"
#include "sdmmc.h"
#include "ff.h"
#define MAIN_BUFFER ((u8*)0x21200000)
@ -11,6 +12,12 @@
#define NORM_FS 10
#define VIRT_FS 4
// Volume2Partition resolution table
PARTITION VolToPart[] = {
{0, 1}, {1, 0}, {2, 0}, {3, 0}, {4, 0},
{5, 0}, {6, 0}, {7, 0}, {8, 0}, {9, 0}
};
// don't use this area for anything else!
static FATFS* fs = (FATFS*)0x20316000;
@ -78,6 +85,63 @@ bool IsMountedFS(const char* path) {
return ((fsnum >= 0) && (fsnum < NORM_FS)) ? fs_mounted[fsnum] : false;
}
uint64_t GetSDCardSize() {
if (sdmmc_sdcard_init() != 0) return 0;
return (u64) getMMCDevice(1)->total_size * 512;
}
bool FormatSDCard(u32 hidden_mb) {
u8 mbr[0x200] = { 0 };
u8 mbrdata[0x42] = {
0x80, 0x01, 0x01, 0x00, 0x0C, 0xFE, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x80, 0x01, 0x01, 0x00, 0x1C, 0xFE, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x55, 0xAA
};
u32 sd_size = getMMCDevice(1)->total_size;
u32* fat_sector = (u32*) (mbrdata + 0x08);
u32* fat_size = (u32*) (mbrdata + 0x0C);
u32* emu_sector = (u32*) (mbrdata + 0x18);
u32* emu_size = (u32*) (mbrdata + 0x1C);
*emu_sector = 1;
*emu_size = hidden_mb * (1024 * 1024) / 512;
*fat_sector = align(*emu_sector + *emu_size, 0x2000); // align to 4MB
if (sd_size < *fat_sector + 0x80000) { // minimum free space: 256MB
ShowPrompt(false, "ERROR: SD card is too small");
return false;
}
*fat_size = sd_size - *fat_sector;
sd_size = *fat_size;
// build the MBR
memcpy(mbr + 0x1BE, mbrdata, 0x42);
if (hidden_mb) memcpy(mbr, "GATEWAYNAND", 12);
else memset(mbr + 0x1CE, 0, 0x10);
// one last warning....
if (!ShowUnlockSequence(3, "!WARNING!\n \nProceeding will format this SD.\nThis will irreversibly delete\nALL data on it.\n"))
return false;
ShowString("Formatting SD, please wait...", hidden_mb);
// write the MBR to disk
// !this assumes a fully deinitialized file system!
if ((sdmmc_sdcard_init() != 0) || (sdmmc_sdcard_writesectors(0, 1, mbr) != 0)) {
ShowPrompt(false, "ERROR: SD card i/o failure");
return false;
}
// format the SD card
// cluster size: auto (<= 4GB) / 32KiB (<= 8GB) / 64 KiB (> 8GB)
InitSDCardFS();
UINT c_size = (sd_size < 0x800000) ? 0 : (sd_size < 0x1000000) ? 32768 : 65536;
bool ret = (f_mkfs("0:", 0, c_size) == FR_OK) && (f_setlabel("0:GM9SD") == FR_OK);
DeinitSDCardFS();
return ret;
}
bool CheckWritePermissions(const char* path) {
char area_name[16];
int pdrv = PathToNumFS(path);

View File

@ -39,6 +39,12 @@ bool InitExtFS();
void DeinitExtFS();
void DeinitSDCardFS();
/** Return total size of SD card **/
uint64_t GetSDCardSize();
/** Format the SD card **/
bool FormatSDCard(u32 hidden_mb);
/** Check if writing to this path is allowed **/
bool CheckWritePermissions(const char* path);

View File

@ -7,7 +7,7 @@
#include "virtual.h"
#include "image.h"
#define VERSION "0.5.8"
#define VERSION "0.5.9"
#define N_PANES 2
#define IMG_DRV "789I"
@ -166,6 +166,36 @@ void DrawDirContents(DirStruct* contents, u32 cursor, u32* scroll) {
} else DrawRectangle(BOT_SCREEN, SCREEN_WIDTH_BOT - bar_width, 0, bar_width, SCREEN_HEIGHT, COLOR_STD_BG);
}
u32 SdFormatMenu(void) {
const u32 emunand_size_table[6] = { 0x0, 0x0, 0x3AF, 0x4D8, 0x400, 0x800 };
const char* optionstr[6] = { "No EmuNAND", "O3DS NAND size", "N3DS NAND size", "1GB (legacy size)", "2GB (legacy size)", "User input..." };
u64 sdcard_size_mb = 0;
u64 emunand_size_mb = (u64) -1;
// check actual SD card size
sdcard_size_mb = GetSDCardSize() / 0x100000;
if (!sdcard_size_mb) {
ShowPrompt(false, "ERROR: SD card not detected.");
return 1;
}
u32 user_select = ShowSelectPrompt(6, optionstr, "Format SD card (%lluGB)?\nChoose EmuNAND size:", sdcard_size_mb / 1024);
if (user_select && (user_select < 6)) {
emunand_size_mb = emunand_size_table[user_select];
} else if (user_select == 6) do {
emunand_size_mb = ShowNumberPrompt(0, "SD card size is %lluMB.\nEnter EmuNAND size (MB) below:", sdcard_size_mb);
if (emunand_size_mb == (u64) -1) break;
} while (emunand_size_mb > sdcard_size_mb);
if (emunand_size_mb == (u64) -1) return 1;
if (!FormatSDCard((u32) emunand_size_mb)) {
ShowPrompt(false, "Format SD: failed!");
return 1;
}
return 0;
}
u32 HexViewer(const char* path) {
static const u32 max_data = (SCREEN_HEIGHT / 8) * 16;
static u32 mode = 0;
@ -588,11 +618,17 @@ u32 GodMode() {
DeinitSDCardFS();
clipboard->n_entries = 0;
memset(panedata, 0x00, N_PANES * sizeof(PaneData));
ShowPrompt(false, "SD card unmounted, you can eject now.\nPut it back in before you press <A>.");
while (!InitSDCardFS()) {
if (!ShowPrompt(true, "Reinitialising SD card failed! Retry?"))
return exit_mode;
ShowString("SD card unmounted, you can eject now.\n \n<R+Y+\x1B> for format menu\n<A> to remount SD card");
while (true) {
u32 pad_choice = InputWait();
if ((pad_choice & (BUTTON_R1|BUTTON_Y|BUTTON_LEFT)) == (BUTTON_R1|BUTTON_Y|BUTTON_LEFT))
SdFormatMenu();
else if (pad_choice & (BUTTON_B|BUTTON_START)) return exit_mode;
else if (!(pad_choice & BUTTON_A)) continue;
if (InitSDCardFS()) break;
ShowString("Reinitialising SD card failed!\n \n<R+Y+\x1B> for format menu\n<A> to retry, <B> to reboot");
}
ClearScreenF(true, false, COLOR_STD_BG);
InitEmuNandBase();
InitExtFS();
GetDirContents(current_dir, current_path);

View File

@ -469,6 +469,23 @@ u64 ShowHexPrompt(u64 start_val, u32 n_digits, const char *format, ...) {
return ret;
}
u64 ShowNumberPrompt(u64 start_val, const char *format, ...) {
const char* alphabet = "0123456789";
char inputstr[20 + 1] = { 0 };
u64 ret = 0;
va_list va;
snprintf(inputstr, 20 + 1, "%llu", start_val);
va_start(va, format);
if (ShowInputPrompt(inputstr, 20 + 1, 1, alphabet, format, va)) {
sscanf(inputstr, "%llu", &ret);
} else ret = (u64) -1;
va_end(va);
return ret;
}
bool ShowDataPrompt(u8* data, u32* size, const char *format, ...) {
const char* alphabet = "0123456789ABCDEF";
char inputstr[128 + 1] = { 0 }; // maximum size of data: 64 byte

View File

@ -73,5 +73,6 @@ bool ShowUnlockSequence(u32 seqlvl, const char *format, ...);
u32 ShowSelectPrompt(u32 n, const char** options, const char *format, ...);
bool ShowStringPrompt(char* inputstr, u32 max_size, const char *format, ...);
u64 ShowHexPrompt(u64 start_val, u32 n_digits, const char *format, ...);
u64 ShowNumberPrompt(u64 start_val, const char *format, ...);
bool ShowDataPrompt(u8* data, u32* size, const char *format, ...);
bool ShowProgress(u64 current, u64 total, const char* opstr);