forked from Mirror/GodMode9
Added ability to format SD cards
This commit is contained in:
parent
bf38dbc63b
commit
a7b511687b
@ -55,7 +55,7 @@
|
|||||||
/* This option switches fast seek feature. (0:Disable or 1:Enable) */
|
/* 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().
|
/* This option switches volume label functions, f_getlabel() and f_setlabel().
|
||||||
/ (0:Disable or 1:Enable) */
|
/ (0:Disable or 1:Enable) */
|
||||||
|
|
||||||
@ -154,7 +154,7 @@
|
|||||||
/ the drive ID strings are: A-Z and 0-9. */
|
/ 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
|
/* 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
|
/ 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),
|
/ the physical drive will be mounted. When multi-partition feature is enabled (1),
|
||||||
|
64
source/fs.c
64
source/fs.c
@ -3,6 +3,7 @@
|
|||||||
#include "virtual.h"
|
#include "virtual.h"
|
||||||
#include "image.h"
|
#include "image.h"
|
||||||
#include "sha.h"
|
#include "sha.h"
|
||||||
|
#include "sdmmc.h"
|
||||||
#include "ff.h"
|
#include "ff.h"
|
||||||
|
|
||||||
#define MAIN_BUFFER ((u8*)0x21200000)
|
#define MAIN_BUFFER ((u8*)0x21200000)
|
||||||
@ -11,6 +12,12 @@
|
|||||||
#define NORM_FS 10
|
#define NORM_FS 10
|
||||||
#define VIRT_FS 4
|
#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!
|
// don't use this area for anything else!
|
||||||
static FATFS* fs = (FATFS*)0x20316000;
|
static FATFS* fs = (FATFS*)0x20316000;
|
||||||
|
|
||||||
@ -78,6 +85,63 @@ bool IsMountedFS(const char* path) {
|
|||||||
return ((fsnum >= 0) && (fsnum < NORM_FS)) ? fs_mounted[fsnum] : false;
|
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) {
|
bool CheckWritePermissions(const char* path) {
|
||||||
char area_name[16];
|
char area_name[16];
|
||||||
int pdrv = PathToNumFS(path);
|
int pdrv = PathToNumFS(path);
|
||||||
|
@ -39,6 +39,12 @@ bool InitExtFS();
|
|||||||
void DeinitExtFS();
|
void DeinitExtFS();
|
||||||
void DeinitSDCardFS();
|
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 **/
|
/** Check if writing to this path is allowed **/
|
||||||
bool CheckWritePermissions(const char* path);
|
bool CheckWritePermissions(const char* path);
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
#include "virtual.h"
|
#include "virtual.h"
|
||||||
#include "image.h"
|
#include "image.h"
|
||||||
|
|
||||||
#define VERSION "0.5.8"
|
#define VERSION "0.5.9"
|
||||||
|
|
||||||
#define N_PANES 2
|
#define N_PANES 2
|
||||||
#define IMG_DRV "789I"
|
#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);
|
} 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) {
|
u32 HexViewer(const char* path) {
|
||||||
static const u32 max_data = (SCREEN_HEIGHT / 8) * 16;
|
static const u32 max_data = (SCREEN_HEIGHT / 8) * 16;
|
||||||
static u32 mode = 0;
|
static u32 mode = 0;
|
||||||
@ -588,11 +618,17 @@ u32 GodMode() {
|
|||||||
DeinitSDCardFS();
|
DeinitSDCardFS();
|
||||||
clipboard->n_entries = 0;
|
clipboard->n_entries = 0;
|
||||||
memset(panedata, 0x00, N_PANES * sizeof(PaneData));
|
memset(panedata, 0x00, N_PANES * sizeof(PaneData));
|
||||||
ShowPrompt(false, "SD card unmounted, you can eject now.\nPut it back in before you press <A>.");
|
ShowString("SD card unmounted, you can eject now.\n \n<R+Y+\x1B> for format menu\n<A> to remount SD card");
|
||||||
while (!InitSDCardFS()) {
|
while (true) {
|
||||||
if (!ShowPrompt(true, "Reinitialising SD card failed! Retry?"))
|
u32 pad_choice = InputWait();
|
||||||
return exit_mode;
|
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();
|
InitEmuNandBase();
|
||||||
InitExtFS();
|
InitExtFS();
|
||||||
GetDirContents(current_dir, current_path);
|
GetDirContents(current_dir, current_path);
|
||||||
|
17
source/ui.c
17
source/ui.c
@ -469,6 +469,23 @@ u64 ShowHexPrompt(u64 start_val, u32 n_digits, const char *format, ...) {
|
|||||||
return ret;
|
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, ...) {
|
bool ShowDataPrompt(u8* data, u32* size, const char *format, ...) {
|
||||||
const char* alphabet = "0123456789ABCDEF";
|
const char* alphabet = "0123456789ABCDEF";
|
||||||
char inputstr[128 + 1] = { 0 }; // maximum size of data: 64 byte
|
char inputstr[128 + 1] = { 0 }; // maximum size of data: 64 byte
|
||||||
|
@ -73,5 +73,6 @@ bool ShowUnlockSequence(u32 seqlvl, const char *format, ...);
|
|||||||
u32 ShowSelectPrompt(u32 n, const char** options, const char *format, ...);
|
u32 ShowSelectPrompt(u32 n, const char** options, const char *format, ...);
|
||||||
bool ShowStringPrompt(char* inputstr, u32 max_size, 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 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 ShowDataPrompt(u8* data, u32* size, const char *format, ...);
|
||||||
bool ShowProgress(u64 current, u64 total, const char* opstr);
|
bool ShowProgress(u64 current, u64 total, const char* opstr);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user