From 2496ecbaf6dacd7f146073635c020f7c40002793 Mon Sep 17 00:00:00 2001 From: Zak Kurka Date: Sat, 20 Oct 2018 13:09:05 -0500 Subject: [PATCH 01/10] Added IPS patching --- src/core/file_sys/ncch_container.cpp | 38 ++++++++++++++++++++++++++++ src/core/file_sys/ncch_container.h | 8 ++++++ 2 files changed, 46 insertions(+) diff --git a/src/core/file_sys/ncch_container.cpp b/src/core/file_sys/ncch_container.cpp index 4e9b2efa7..c9be5bf80 100644 --- a/src/core/file_sys/ncch_container.cpp +++ b/src/core/file_sys/ncch_container.cpp @@ -481,6 +481,21 @@ Loader::ResultStatus NCCHContainer::LoadSectionExeFS(const char* name, std::vect dec.ProcessData(&buffer[0], &buffer[0], section.size); } } + + std::string override_ips = filepath + ".exefsdir/code.ips"; + + if (FileUtil::Exists(override_ips) && strcmp(name, ".code") == 0) { + FileUtil::IOFile ips_file(override_ips, "rb"); + size_t ips_file_size = ips_file.GetSize(); + std::vector ips(ips_file_size); + + if (ips_file.IsOpen() && + ips_file.ReadBytes(&ips[0], ips_file_size) == ips_file_size) { + LOG_WARNING(Service_FS, "File {} patching code.bin", override_ips); + ApplyIPS(ips, buffer); + } + } + return Loader::ResultStatus::Success; } } @@ -519,6 +534,29 @@ Loader::ResultStatus NCCHContainer::LoadOverrideExeFSSection(const char* name, return Loader::ResultStatus::ErrorNotUsed; } +Loader::ResultStatus NCCHContainer::ApplyIPS(std::vector& ips, std::vector& buffer) { + u32 cursor = 5; + u32 patch_length = ips.size() - 3; + std::string ips_header(ips.begin(), ips.begin() + 5); + + if (strcmp(ips_header.c_str(), "PATCH")) + return Loader::ResultStatus::Error; + + while (cursor < patch_length) { + u32 offset = (ips[cursor]) << 16 | (ips[cursor + 1]) << 8 | (ips[cursor + 2]); + u32 length = (ips[cursor + 3]) << 8 | (ips[cursor + 4]); + cursor += 5; + + for (int i = 0; i < length; i++) { + buffer[offset + i] = ips[cursor + i]; + } + + cursor += length; + } + + return Loader::ResultStatus::Success; +} + Loader::ResultStatus NCCHContainer::ReadRomFS(std::shared_ptr& romfs_file) { Loader::ResultStatus result = Load(); if (result != Loader::ResultStatus::Success) diff --git a/src/core/file_sys/ncch_container.h b/src/core/file_sys/ncch_container.h index 79f87a6ef..8d6665e7a 100644 --- a/src/core/file_sys/ncch_container.h +++ b/src/core/file_sys/ncch_container.h @@ -249,6 +249,14 @@ public: */ Loader::ResultStatus ReadRomFS(std::shared_ptr& romfs_file); + /** + * Attempts to patch a buffer using an IPS + * @param ips Vector of the patches to apply + * @param buffer Vector to patch data into + * @return ResultStatus result of function + */ + Loader::ResultStatus ApplyIPS(std::vector& ips, std::vector& buffer); + /** * Get the override RomFS of the NCCH container * Since the RomFS can be huge, we return a file reference instead of copying to a buffer From bf50bb06f19fe3d8e8349b7807df3a04b1139743 Mon Sep 17 00:00:00 2001 From: Zak Kurka Date: Sat, 20 Oct 2018 18:10:32 -0500 Subject: [PATCH 02/10] Minor style changes and use memcpy --- src/core/file_sys/ncch_container.cpp | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/src/core/file_sys/ncch_container.cpp b/src/core/file_sys/ncch_container.cpp index c9be5bf80..97f4415b7 100644 --- a/src/core/file_sys/ncch_container.cpp +++ b/src/core/file_sys/ncch_container.cpp @@ -486,7 +486,7 @@ Loader::ResultStatus NCCHContainer::LoadSectionExeFS(const char* name, std::vect if (FileUtil::Exists(override_ips) && strcmp(name, ".code") == 0) { FileUtil::IOFile ips_file(override_ips, "rb"); - size_t ips_file_size = ips_file.GetSize(); + std::size_t ips_file_size = ips_file.GetSize(); std::vector ips(ips_file_size); if (ips_file.IsOpen() && @@ -543,15 +543,11 @@ Loader::ResultStatus NCCHContainer::ApplyIPS(std::vector& ips, std::vector Date: Sat, 20 Oct 2018 18:17:54 -0500 Subject: [PATCH 03/10] Be more intentional with check --- src/core/file_sys/ncch_container.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/file_sys/ncch_container.cpp b/src/core/file_sys/ncch_container.cpp index 97f4415b7..4f23d9fdd 100644 --- a/src/core/file_sys/ncch_container.cpp +++ b/src/core/file_sys/ncch_container.cpp @@ -539,7 +539,7 @@ Loader::ResultStatus NCCHContainer::ApplyIPS(std::vector& ips, std::vector Date: Sat, 20 Oct 2018 19:45:16 -0500 Subject: [PATCH 04/10] Updated based on review --- src/core/file_sys/ncch_container.cpp | 10 ++++------ src/core/file_sys/ncch_container.h | 4 ++-- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/core/file_sys/ncch_container.cpp b/src/core/file_sys/ncch_container.cpp index 4f23d9fdd..34f98e9fe 100644 --- a/src/core/file_sys/ncch_container.cpp +++ b/src/core/file_sys/ncch_container.cpp @@ -491,7 +491,7 @@ Loader::ResultStatus NCCHContainer::LoadSectionExeFS(const char* name, std::vect if (ips_file.IsOpen() && ips_file.ReadBytes(&ips[0], ips_file_size) == ips_file_size) { - LOG_WARNING(Service_FS, "File {} patching code.bin", override_ips); + LOG_INFO(Service_FS, "File {} patching code.bin", override_ips); ApplyIPS(ips, buffer); } } @@ -534,13 +534,13 @@ Loader::ResultStatus NCCHContainer::LoadOverrideExeFSSection(const char* name, return Loader::ResultStatus::ErrorNotUsed; } -Loader::ResultStatus NCCHContainer::ApplyIPS(std::vector& ips, std::vector& buffer) { +void NCCHContainer::ApplyIPS(std::vector& ips, std::vector& buffer) { u32 cursor = 5; u32 patch_length = ips.size() - 3; std::string ips_header(ips.begin(), ips.begin() + 5); - if (strcmp(ips_header.c_str(), "PATCH") != 0) - return Loader::ResultStatus::Error; + if (ips_header != "PATCH") + return; while (cursor < patch_length) { u32 offset = ips[cursor] << 16 | ips[cursor + 1] << 8 | ips[cursor + 2]; @@ -549,8 +549,6 @@ Loader::ResultStatus NCCHContainer::ApplyIPS(std::vector& ips, std::vector& romfs_file) { diff --git a/src/core/file_sys/ncch_container.h b/src/core/file_sys/ncch_container.h index 8d6665e7a..098b8df8f 100644 --- a/src/core/file_sys/ncch_container.h +++ b/src/core/file_sys/ncch_container.h @@ -253,9 +253,9 @@ public: * Attempts to patch a buffer using an IPS * @param ips Vector of the patches to apply * @param buffer Vector to patch data into - * @return ResultStatus result of function + * @return Void */ - Loader::ResultStatus ApplyIPS(std::vector& ips, std::vector& buffer); + void ApplyIPS(std::vector& ips, std::vector& buffer); /** * Get the override RomFS of the NCCH container From d0b54e993960aa392038ff971a6aaecc7188aebf Mon Sep 17 00:00:00 2001 From: Zak Kurka Date: Sat, 20 Oct 2018 23:25:16 -0500 Subject: [PATCH 05/10] Check for EOF --- src/core/file_sys/ncch_container.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/core/file_sys/ncch_container.cpp b/src/core/file_sys/ncch_container.cpp index 34f98e9fe..bdcf5837e 100644 --- a/src/core/file_sys/ncch_container.cpp +++ b/src/core/file_sys/ncch_container.cpp @@ -543,6 +543,11 @@ void NCCHContainer::ApplyIPS(std::vector& ips, std::vector& buffer) { return; while (cursor < patch_length) { + std::string eof_check(ips.begin() + cursor, ips.begin() + cursor + 3); + + if (eof_check == "EOF") + return; + u32 offset = ips[cursor] << 16 | ips[cursor + 1] << 8 | ips[cursor + 2]; std::size_t length = ips[cursor + 3] << 8 | ips[cursor + 4]; From d8284dfaccf5092ee295b259672b3f7a8f3cfd2c Mon Sep 17 00:00:00 2001 From: Zak Kurka Date: Sun, 21 Oct 2018 07:47:27 -0500 Subject: [PATCH 06/10] Log invalid IPS attempt --- src/core/file_sys/ncch_container.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/core/file_sys/ncch_container.cpp b/src/core/file_sys/ncch_container.cpp index bdcf5837e..e4693b399 100644 --- a/src/core/file_sys/ncch_container.cpp +++ b/src/core/file_sys/ncch_container.cpp @@ -539,8 +539,10 @@ void NCCHContainer::ApplyIPS(std::vector& ips, std::vector& buffer) { u32 patch_length = ips.size() - 3; std::string ips_header(ips.begin(), ips.begin() + 5); - if (ips_header != "PATCH") + if (ips_header != "PATCH") { + LOG_INFO(Service_FS, "Attempted to load invalid IPS"); return; + } while (cursor < patch_length) { std::string eof_check(ips.begin() + cursor, ips.begin() + cursor + 3); From 1c62bc06cf861887cd6f0f471fafc1127f4885d4 Mon Sep 17 00:00:00 2001 From: Zak Kurka Date: Sun, 21 Oct 2018 07:48:29 -0500 Subject: [PATCH 07/10] Add rle record support --- src/core/file_sys/ncch_container.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/core/file_sys/ncch_container.cpp b/src/core/file_sys/ncch_container.cpp index e4693b399..473a195bd 100644 --- a/src/core/file_sys/ncch_container.cpp +++ b/src/core/file_sys/ncch_container.cpp @@ -553,6 +553,18 @@ void NCCHContainer::ApplyIPS(std::vector& ips, std::vector& buffer) { u32 offset = ips[cursor] << 16 | ips[cursor + 1] << 8 | ips[cursor + 2]; std::size_t length = ips[cursor + 3] << 8 | ips[cursor + 4]; + // check for an rle record + if (length == 0) { + length = ips[cursor + 5] << 8 | ips[cursor + 6]; + + for (u32 i = 0; i < length; ++i) + buffer[offset + i] = ips[cursor + 7]; + + cursor += 8; + + continue; + } + std::memcpy(&buffer[offset], &ips[cursor + 5], length); cursor += length + 5; } From 05c1816504d1c85da008df94bd9b4cce5d41d891 Mon Sep 17 00:00:00 2001 From: Zak Kurka Date: Sun, 21 Oct 2018 07:48:54 -0500 Subject: [PATCH 08/10] Stay in bounds --- src/core/file_sys/ncch_container.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/core/file_sys/ncch_container.cpp b/src/core/file_sys/ncch_container.cpp index 473a195bd..a67f4de0c 100644 --- a/src/core/file_sys/ncch_container.cpp +++ b/src/core/file_sys/ncch_container.cpp @@ -557,6 +557,9 @@ void NCCHContainer::ApplyIPS(std::vector& ips, std::vector& buffer) { if (length == 0) { length = ips[cursor + 5] << 8 | ips[cursor + 6]; + if (buffer.size() < offset + length) + return; + for (u32 i = 0; i < length; ++i) buffer[offset + i] = ips[cursor + 7]; @@ -565,6 +568,9 @@ void NCCHContainer::ApplyIPS(std::vector& ips, std::vector& buffer) { continue; } + if (buffer.size() < offset + length) + return; + std::memcpy(&buffer[offset], &ips[cursor + 5], length); cursor += length + 5; } From 92f8b7113767311087fc106b9a3c98e91c68b0fd Mon Sep 17 00:00:00 2001 From: Zak Kurka Date: Sun, 21 Oct 2018 10:42:23 -0500 Subject: [PATCH 09/10] Make ApplyIPS static and private --- src/core/file_sys/ncch_container.h | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/core/file_sys/ncch_container.h b/src/core/file_sys/ncch_container.h index 098b8df8f..c1ee7f2c4 100644 --- a/src/core/file_sys/ncch_container.h +++ b/src/core/file_sys/ncch_container.h @@ -249,14 +249,6 @@ public: */ Loader::ResultStatus ReadRomFS(std::shared_ptr& romfs_file); - /** - * Attempts to patch a buffer using an IPS - * @param ips Vector of the patches to apply - * @param buffer Vector to patch data into - * @return Void - */ - void ApplyIPS(std::vector& ips, std::vector& buffer); - /** * Get the override RomFS of the NCCH container * Since the RomFS can be huge, we return a file reference instead of copying to a buffer @@ -302,6 +294,12 @@ public: ExHeader_Header exheader_header; private: + /** + * Attempts to patch a buffer using an IPS + * @param ips Vector of the patches to apply + * @param buffer Vector to patch data into + */ + static void ApplyIPS(std::vector& ips, std::vector& buffer); bool has_header = false; bool has_exheader = false; bool has_exefs = false; From 896577044d26b750cf85e3b30c66a1dd290ee0da Mon Sep 17 00:00:00 2001 From: Zak Kurka Date: Thu, 15 Nov 2018 07:11:06 -0600 Subject: [PATCH 10/10] Remove ApplyIPS from the class and header --- src/core/file_sys/ncch_container.cpp | 89 +++++++++++++++------------- src/core/file_sys/ncch_container.h | 6 -- 2 files changed, 47 insertions(+), 48 deletions(-) diff --git a/src/core/file_sys/ncch_container.cpp b/src/core/file_sys/ncch_container.cpp index a67f4de0c..fc84979f0 100644 --- a/src/core/file_sys/ncch_container.cpp +++ b/src/core/file_sys/ncch_container.cpp @@ -24,6 +24,53 @@ namespace FileSys { static const int kMaxSections = 8; ///< Maximum number of sections (files) in an ExeFs static const int kBlockSize = 0x200; ///< Size of ExeFS blocks (in bytes) +/** + * Attempts to patch a buffer using an IPS + * @param ips Vector of the patches to apply + * @param buffer Vector to patch data into + */ +static void ApplyIPS(std::vector& ips, std::vector& buffer) { + u32 cursor = 5; + u32 patch_length = ips.size() - 3; + std::string ips_header(ips.begin(), ips.begin() + 5); + + if (ips_header != "PATCH") { + LOG_INFO(Service_FS, "Attempted to load invalid IPS"); + return; + } + + while (cursor < patch_length) { + std::string eof_check(ips.begin() + cursor, ips.begin() + cursor + 3); + + if (eof_check == "EOF") + return; + + u32 offset = ips[cursor] << 16 | ips[cursor + 1] << 8 | ips[cursor + 2]; + std::size_t length = ips[cursor + 3] << 8 | ips[cursor + 4]; + + // check for an rle record + if (length == 0) { + length = ips[cursor + 5] << 8 | ips[cursor + 6]; + + if (buffer.size() < offset + length) + return; + + for (u32 i = 0; i < length; ++i) + buffer[offset + i] = ips[cursor + 7]; + + cursor += 8; + + continue; + } + + if (buffer.size() < offset + length) + return; + + std::memcpy(&buffer[offset], &ips[cursor + 5], length); + cursor += length + 5; + } +} + /** * Get the decompressed size of an LZSS compressed ExeFS file * @param buffer Buffer of compressed file @@ -534,48 +581,6 @@ Loader::ResultStatus NCCHContainer::LoadOverrideExeFSSection(const char* name, return Loader::ResultStatus::ErrorNotUsed; } -void NCCHContainer::ApplyIPS(std::vector& ips, std::vector& buffer) { - u32 cursor = 5; - u32 patch_length = ips.size() - 3; - std::string ips_header(ips.begin(), ips.begin() + 5); - - if (ips_header != "PATCH") { - LOG_INFO(Service_FS, "Attempted to load invalid IPS"); - return; - } - - while (cursor < patch_length) { - std::string eof_check(ips.begin() + cursor, ips.begin() + cursor + 3); - - if (eof_check == "EOF") - return; - - u32 offset = ips[cursor] << 16 | ips[cursor + 1] << 8 | ips[cursor + 2]; - std::size_t length = ips[cursor + 3] << 8 | ips[cursor + 4]; - - // check for an rle record - if (length == 0) { - length = ips[cursor + 5] << 8 | ips[cursor + 6]; - - if (buffer.size() < offset + length) - return; - - for (u32 i = 0; i < length; ++i) - buffer[offset + i] = ips[cursor + 7]; - - cursor += 8; - - continue; - } - - if (buffer.size() < offset + length) - return; - - std::memcpy(&buffer[offset], &ips[cursor + 5], length); - cursor += length + 5; - } -} - Loader::ResultStatus NCCHContainer::ReadRomFS(std::shared_ptr& romfs_file) { Loader::ResultStatus result = Load(); if (result != Loader::ResultStatus::Success) diff --git a/src/core/file_sys/ncch_container.h b/src/core/file_sys/ncch_container.h index c1ee7f2c4..79f87a6ef 100644 --- a/src/core/file_sys/ncch_container.h +++ b/src/core/file_sys/ncch_container.h @@ -294,12 +294,6 @@ public: ExHeader_Header exheader_header; private: - /** - * Attempts to patch a buffer using an IPS - * @param ips Vector of the patches to apply - * @param buffer Vector to patch data into - */ - static void ApplyIPS(std::vector& ips, std::vector& buffer); bool has_header = false; bool has_exheader = false; bool has_exefs = false;