From 45501d47eb208fba2d99e2eed34a0ec1cfbf3ebc Mon Sep 17 00:00:00 2001 From: d0k3 Date: Fri, 8 Apr 2016 21:02:38 +0200 Subject: [PATCH] FileGetData(): Also allow virtual files This commit also enables ReadVirtualFile() to correctly process misaligned data --- source/fs.c | 36 +++++++++++++++++---------- source/fs.h | 2 +- source/nand/nand.c | 5 ++-- source/nand/virtual.c | 58 +++++++++++++++++++++++++++++++++++++------ source/nand/virtual.h | 4 +-- 5 files changed, 79 insertions(+), 26 deletions(-) diff --git a/source/fs.c b/source/fs.c index c7fc668..82ef6a1 100644 --- a/source/fs.c +++ b/source/fs.c @@ -162,16 +162,26 @@ bool FileCreateData(const char* path, u8* data, size_t size) { return (bytes_written == size); } -bool FileGetData(const char* path, u8* data, size_t size, size_t foffset) +size_t FileGetData(const char* path, u8* data, size_t size, size_t foffset) { - FIL file; - UINT bytes_read = 0; - if (f_open(&file, path, FA_READ | FA_OPEN_EXISTING) != FR_OK) - return false; - f_lseek(&file, foffset); - f_read(&file, data, size, &bytes_read); - f_close(&file); - return (bytes_read == size); + if (PathToNumFS(path) >= 0) { + UINT bytes_read = 0; + FIL file; + if (f_open(&file, path, FA_READ | FA_OPEN_EXISTING) != FR_OK) + return 0; + f_lseek(&file, foffset); + if (f_read(&file, data, size, &bytes_read) != FR_OK) + return 0; + f_close(&file); + return bytes_read; + } else if (IsVirtualPath(path)) { + u32 bytes_read = 0; + VirtualFile vfile; + if (!FindVirtualFile(&vfile, path, 0)) + return 0; + return (ReadVirtualFile(&vfile, data, foffset, size, &bytes_read) == 0) ? bytes_read : 0; + } + return 0; } bool PathCopyVirtual(const char* destdir, const char* orig) { @@ -209,11 +219,11 @@ bool PathCopyVirtual(const char* destdir, const char* orig) { if (!ShowProgress(0, 0, orig)) ret = false; for (size_t pos = 0; (pos < osize) && ret; pos += MAIN_BUFFER_SIZE) { UINT read_bytes = min(MAIN_BUFFER_SIZE, osize - pos); - if (ReadVirtualFile(&ovfile, MAIN_BUFFER, pos, read_bytes) != 0) + if (ReadVirtualFile(&ovfile, MAIN_BUFFER, pos, read_bytes, NULL) != 0) ret = false; if (!ShowProgress(pos + (read_bytes / 2), osize, orig)) ret = false; - if (WriteVirtualFile(&dvfile, MAIN_BUFFER, pos, read_bytes) != 0) + if (WriteVirtualFile(&dvfile, MAIN_BUFFER, pos, read_bytes, NULL) != 0) ret = false; } ShowProgress(1, 1, orig); @@ -265,7 +275,7 @@ bool PathCopyVirtual(const char* destdir, const char* orig) { ret = false; if (!ShowProgress(pos + (bytes_read / 2), osize, orig)) ret = false; - if (WriteVirtualFile(&dvfile, MAIN_BUFFER, pos, bytes_read) != 0) + if (WriteVirtualFile(&dvfile, MAIN_BUFFER, pos, bytes_read, NULL) != 0) ret = false; } ShowProgress(1, 1, orig); @@ -298,7 +308,7 @@ bool PathCopyVirtual(const char* destdir, const char* orig) { for (size_t pos = 0; (pos < osize) && ret; pos += MAIN_BUFFER_SIZE) { UINT read_bytes = min(MAIN_BUFFER_SIZE, osize - pos); UINT bytes_written = 0; - if (ReadVirtualFile(&ovfile, MAIN_BUFFER, pos, read_bytes) != 0) + if (ReadVirtualFile(&ovfile, MAIN_BUFFER, pos, read_bytes, NULL) != 0) ret = false; if (!ShowProgress(pos + (read_bytes / 2), osize, orig)) ret = false; diff --git a/source/fs.h b/source/fs.h index 0f470b8..639c163 100644 --- a/source/fs.h +++ b/source/fs.h @@ -42,7 +42,7 @@ u32 GetWritePermissions(); bool FileCreateData(const char* path, u8* data, size_t size); /** Read data from file@offset **/ -bool FileGetData(const char* path, u8* data, size_t size, size_t foffset); +size_t FileGetData(const char* path, u8* data, size_t size, size_t foffset); /** Recursively copy a file or directory **/ bool PathCopy(const char* destdir, const char* orig); diff --git a/source/nand/nand.c b/source/nand/nand.c index 73edc6c..80ec7f1 100644 --- a/source/nand/nand.c +++ b/source/nand/nand.c @@ -61,7 +61,7 @@ bool LoadKeyFromFile(const char* folder, u8* keydata, u32 keyslot, char type, ch if (id) strncpy((char*) key_magic + 2, id, 10); // try to find key in 'aeskeydb.bin' file - for (u32 p = 0; FileGetData(path, buffer, 32, p); p += 32) { + for (u32 p = 0; FileGetData(path, buffer, 32, p) == 32; p += 32) { if (memcmp(buffer, key_magic, 12) == 0) { found = true; break; @@ -83,7 +83,7 @@ bool LoadKeyFromFile(const char* folder, u8* keydata, u32 keyslot, char type, ch if (!found) { snprintf(path, 256, "%s/slot0x%02XKey%.10s", folder, (unsigned int) keyslot, (id) ? id : (type == 'X') ? "X" : (type == 'Y') ? "Y" : ""); - if (FileGetData(path, key, 16, 0)) + if (FileGetData(path, key, 16, 0) == 16) found = true; } @@ -198,6 +198,7 @@ void CryptNand(u8* buffer, u32 sector, u32 count, u32 keyslot) int ReadNandSectors(u8* buffer, u32 sector, u32 count, u32 keyslot, u32 nand_src) { + if (!count) return 0; // <--- just to be safe if (nand_src == NAND_EMUNAND) { // EmuNAND int errorcode = 0; if ((sector == 0) && (emunand_base_sector % 0x200000 == 0)) { // GW EmuNAND header handling diff --git a/source/nand/virtual.c b/source/nand/virtual.c index db89e6d..42674af 100644 --- a/source/nand/virtual.c +++ b/source/nand/virtual.c @@ -91,16 +91,58 @@ bool FindVirtualFile(VirtualFile* vfile, const char* path, u32 size) return true; } -int ReadVirtualFile(const VirtualFile* vfile, u8* buffer, u32 offset, u32 count) +int ReadVirtualFile(const VirtualFile* vfile, u8* buffer, u32 offset, u32 count, u32* bytes_read) { - // simple wrapper function for ReadNandSectors(u8* buffer, u32 sector, u32 count, u32 keyslot, u32 src) - return ReadNandSectors(buffer, (vfile->offset + offset) / 0x200, (count+0x1FF) / 0x200, vfile->keyslot, - vfile->flags & (VRT_SYSNAND | VRT_EMUNAND | VRT_IMGNAND)); + u32 foffset = vfile->offset + offset; + if (offset >= vfile->size) + return 0; + else if ((offset + count) > vfile->size) + count = vfile->size - offset; + if (bytes_read) *bytes_read = count; + if (!(foffset % 0x200) && !(count % 0x200)) { // aligned data -> simple case + // simple wrapper function for ReadNandSectors(u8* buffer, u32 sector, u32 count, u32 keyslot, u32 src) + return ReadNandSectors(buffer, foffset / 0x200, count / 0x200, vfile->keyslot, + vfile->flags & (VRT_SYSNAND | VRT_EMUNAND | VRT_IMGNAND)); + } else { // nonaligned data -> -___- + u8 l_buffer[0x200]; + u32 nand_src = vfile->flags & (VRT_SYSNAND | VRT_EMUNAND | VRT_IMGNAND); + u32 keyslot = vfile->keyslot; + int errorcode = 0; + if (foffset % 0x200) { // handle misaligned offset + u32 offset_fix = 0x200 - (foffset % 0x200); + errorcode = ReadNandSectors(l_buffer, foffset / 0x200, 1, keyslot, nand_src); + if (errorcode != 0) return errorcode; + memcpy(buffer, l_buffer + 0x200 - offset_fix, min(offset_fix, count)); + if (count <= offset_fix) return 0; + foffset += offset_fix; + buffer += offset_fix; + count -= offset_fix; + } // foffset is now aligned and part of the data is read + if (count >= 0x200) { // otherwise this is misaligned and will be handled below + errorcode = ReadNandSectors(buffer, foffset / 0x200, count / 0x200, keyslot, nand_src); + if (errorcode != 0) return errorcode; + } + if (count % 0x200) { // handle misaligned count + u32 count_fix = count % 0x200; + errorcode = ReadNandSectors(l_buffer, (foffset + count) / 0x200, 1, keyslot, nand_src); + if (errorcode != 0) return errorcode; + memcpy(buffer + count - count_fix, l_buffer, count_fix); + } + return errorcode; + } } -int WriteVirtualFile(const VirtualFile* vfile, const u8* buffer, u32 offset, u32 count) +int WriteVirtualFile(const VirtualFile* vfile, const u8* buffer, u32 offset, u32 count, u32* bytes_written) { - // simple wrapper function for WriteNandSectors(const u8* buffer, u32 sector, u32 count, u32 keyslot, u32 dest) - return WriteNandSectors(buffer, (vfile->offset + offset) / 0x200, (count+0x1FF) / 0x200, vfile->keyslot, - vfile->flags & (VRT_SYSNAND | VRT_EMUNAND | VRT_IMGNAND)); + u32 foffset = vfile->offset + offset; + if (offset >= vfile->size) + return 0; + else if ((offset + count) > vfile->size) + count = vfile->size - offset; + if (bytes_written) *bytes_written = count; + if (!(foffset % 0x200) && !(count % 0x200)) { // aligned data -> simple case + // simple wrapper function for WriteNandSectors(const u8* buffer, u32 sector, u32 count, u32 keyslot, u32 dest) + return WriteNandSectors(buffer, foffset / 0x200, count / 0x200, vfile->keyslot, + vfile->flags & (VRT_SYSNAND | VRT_EMUNAND | VRT_IMGNAND)); + } else return -1; // misaligned data -> not implemented (!!!) } diff --git a/source/nand/virtual.h b/source/nand/virtual.h index db2c8f3..3c2d481 100644 --- a/source/nand/virtual.h +++ b/source/nand/virtual.h @@ -24,5 +24,5 @@ typedef struct { u32 IsVirtualPath(const char* path); bool CheckVirtualPath(const char* path); bool FindVirtualFile(VirtualFile* vfile, const char* path, u32 size); -int ReadVirtualFile(const VirtualFile* vfile, u8* buffer, u32 offset, u32 count); -int WriteVirtualFile(const VirtualFile* vfile, const u8* buffer, u32 offset, u32 count); +int ReadVirtualFile(const VirtualFile* vfile, u8* buffer, u32 offset, u32 count, u32* bytes_read); +int WriteVirtualFile(const VirtualFile* vfile, const u8* buffer, u32 offset, u32 count, u32* bytes_written);