diff --git a/HelloScript.gm9 b/HelloScript.gm9 index 9c33af1..5303d23 100644 --- a/HelloScript.gm9 +++ b/HelloScript.gm9 @@ -114,6 +114,8 @@ find $[RENPATH] NULL sha $[RENPATH] $[TESTPATH].sha # Instead of an .sha file you can also use the SHA256 in hex as second argument # sha S:/sector0x96.bin 82F2730D2C2DA3F30165F987FDCCAC5CBAB24B4E5F65C981CD7BE6F438E6D9D3 +# This also allows partial SHA checks (for @x:y handling see below) +# sha S:/firm0.bin@100:100 078CC0CFD850A27093DDA2630C3603CA0C96969BD1F26DA48AC7B1BAE5DD5219 # 'inject' COMMAND # This command is used to inject part of one file into another @@ -122,8 +124,8 @@ sha $[RENPATH] $[TESTPATH].sha # y: origin size, starting at x (in hex) # z: destination offset (in hex) # If destination does not exist or z is not given, a new destination file will be created(!) -# If x is not given, the full origin file size is used to inject -# If y is not given, everything starting from x is used to inject +# If x is not given, the full origin file size, starting from offset 0, is used to inject +# If y is not given, everything starting from offset x is used to inject # -n / --no_cancel prevents user cancels (useful on critical operations) inject S:/nand_hdr.bin@100:4 $[RENPATH]@200 # offsets and sizes are in hex # As we just deliberately corrupted our test file, the subsequent SHA check will fail diff --git a/source/filesys/fsscript.c b/source/filesys/fsscript.c index 99a9450..86afb1a 100644 --- a/source/filesys/fsscript.c +++ b/source/filesys/fsscript.c @@ -347,6 +347,20 @@ bool parse_line(const char* line_start, const char* line_end, cmd_id* cmdid, u32 bool run_cmd(cmd_id id, u32 flags, char** argv, char* err_str) { bool ret = true; // true unless some cmd messes up + // process arg0 @string + u64 at_org = 0; + u64 sz_org = 0; + if ((id == CMD_ID_SHA) || (id == CMD_ID_INJECT)) { + char* atstr_org = strrchr(argv[0], '@'); + if (atstr_org) { + *(atstr_org++) = '\0'; + if (sscanf(atstr_org, "%llX:%llX", &at_org, &sz_org) != 2) { + if (sscanf(atstr_org, "%llX", &at_org) != 1) at_org = 0; + sz_org = 0; + } + } + } + // perform command if (id == CMD_ID_ECHO) { ShowPrompt(false, argv[0]); @@ -384,16 +398,6 @@ bool run_cmd(cmd_id id, u32 flags, char** argv, char* err_str) { if (err_str) snprintf(err_str, _ERR_STR_LEN, "move fail"); } else if (id == CMD_ID_INJECT) { char* atstr_dst = strrchr(argv[1], '@'); - char* atstr_org = strrchr(argv[0], '@'); - u64 at_org = 0; - u64 sz_org = 0; - if (atstr_org) { - *(atstr_org++) = '\0'; - if (sscanf(atstr_org, "%llX:%llX", &at_org, &sz_org) != 2) { - if (sscanf(atstr_org, "%llX", &at_org) != 1) at_org = 0; - sz_org = 0; - } - } u64 at_dst = 0; if (atstr_dst) { *(atstr_dst++) = '\0'; @@ -438,7 +442,7 @@ bool run_cmd(cmd_id id, u32 flags, char** argv, char* err_str) { } else if (id == CMD_ID_SHA) { u8 sha256_fil[0x20]; u8 sha256_cmp[0x20]; - if (!FileGetSha256(argv[0], sha256_fil)) { + if (!FileGetSha256(argv[0], sha256_fil, at_org, sz_org)) { ret = false; if (err_str) snprintf(err_str, _ERR_STR_LEN, "sha arg0 fail"); } else if ((FileGetData(argv[1], sha256_cmp, 0x20, 0) != 0x20) && !strntohex(argv[1], sha256_cmp, 0x20)) { diff --git a/source/filesys/fsutil.c b/source/filesys/fsutil.c index 5f202bc..06d14ff 100644 --- a/source/filesys/fsutil.c +++ b/source/filesys/fsutil.c @@ -136,7 +136,7 @@ size_t FileGetSize(const char* path) { return fno.fsize; } -bool FileGetSha256(const char* path, u8* sha256) { +bool FileGetSha256(const char* path, u8* sha256, u64 offset, u64 size) { bool ret = true; FIL file; u64 fsize; @@ -144,14 +144,17 @@ bool FileGetSha256(const char* path, u8* sha256) { if (fvx_open(&file, path, FA_READ | FA_OPEN_EXISTING) != FR_OK) return false; fsize = fvx_size(&file); - fvx_lseek(&file, 0); + if (offset + size > fsize) return false; + if (!size) size = fsize - offset; + fvx_lseek(&file, offset); ShowProgress(0, 0, path); sha_init(SHA256_MODE); - for (u64 pos = 0; (pos < fsize) && ret; pos += MAIN_BUFFER_SIZE) { + for (u64 pos = 0; (pos < size) && ret; pos += MAIN_BUFFER_SIZE) { + UINT read_bytes = min(MAIN_BUFFER_SIZE, size - pos); UINT bytes_read = 0; - if (fvx_read(&file, MAIN_BUFFER, MAIN_BUFFER_SIZE, &bytes_read) != FR_OK) + if (fvx_read(&file, MAIN_BUFFER, read_bytes, &bytes_read) != FR_OK) ret = false; - if (!ShowProgress(pos + bytes_read, fsize, path)) + if (!ShowProgress(pos + bytes_read, size, path)) ret = false; sha_update(MAIN_BUFFER, bytes_read); } diff --git a/source/filesys/fsutil.h b/source/filesys/fsutil.h index 79aeb34..80ae171 100644 --- a/source/filesys/fsutil.h +++ b/source/filesys/fsutil.h @@ -35,7 +35,7 @@ size_t FileGetData(const char* path, void* data, size_t size, size_t foffset); size_t FileGetSize(const char* path); /** Get SHA-256 of file **/ -bool FileGetSha256(const char* path, u8* sha256); +bool FileGetSha256(const char* path, u8* sha256, u64 offset, u64 size); /** Find data in file **/ u32 FileFindData(const char* path, u8* data, u32 size_data, u32 offset_file); diff --git a/source/godmode.c b/source/godmode.c index a480228..06e77af 100644 --- a/source/godmode.c +++ b/source/godmode.c @@ -789,7 +789,7 @@ u32 Sha256Calculator(const char* path) { char pathstr[32 + 1]; u8 sha256[32]; TruncateString(pathstr, path, 32, 8); - if (!FileGetSha256(path, sha256)) { + if (!FileGetSha256(path, sha256, 0, 0)) { ShowPrompt(false, "Calculating SHA-256: failed!"); return 1; } else {