diff --git a/rpcs3/Emu/Cell/PPUModule.cpp b/rpcs3/Emu/Cell/PPUModule.cpp index 1eec01d231..3f6778c5b6 100644 --- a/rpcs3/Emu/Cell/PPUModule.cpp +++ b/rpcs3/Emu/Cell/PPUModule.cpp @@ -1,5 +1,6 @@ #include "stdafx.h" #include "Utilities/VirtualMemory.h" +#include "Utilities/bin_patch.h" #include "Crypto/sha1.h" #include "Crypto/unself.h" #include "Loader/ELF.h" @@ -954,6 +955,11 @@ void ppu_load_exec(const ppu_exec_object& elf) u32 primary_stacksize = 0x100000; u32 malloc_pagesize = 0x100000; + // Executable hash + sha1_context sha; + sha1_starts(&sha); + u8 sha1_hash[20]; + // Allocate memory at fixed positions for (const auto& prog : elf.progs) { @@ -964,7 +970,11 @@ void ppu_load_exec(const ppu_exec_object& elf) const u32 size = _seg.size = ::narrow(prog.p_memsz, "p_memsz" HERE); const u32 type = _seg.type = prog.p_type; const u32 flag = _seg.flags = prog.p_flags; - + + // Hash big-endian values + sha1_update(&sha, (uchar*)&prog.p_type, sizeof(prog.p_type)); + sha1_update(&sha, (uchar*)&prog.p_flags, sizeof(prog.p_flags)); + if (type == 0x1 /* LOAD */ && prog.p_memsz) { if (prog.bin.size() > size || prog.bin.size() != prog.p_filesz) @@ -973,8 +983,11 @@ void ppu_load_exec(const ppu_exec_object& elf) if (!vm::falloc(addr, size, vm::main)) fmt::throw_exception("vm::falloc() failed (addr=0x%x, memsz=0x%x)", addr, size); - // Copy segment data + // Copy segment data, hash it std::memcpy(vm::base(addr), prog.bin.data(), prog.bin.size()); + sha1_update(&sha, (uchar*)&prog.p_vaddr, sizeof(prog.p_vaddr)); + sha1_update(&sha, (uchar*)&prog.p_memsz, sizeof(prog.p_memsz)); + sha1_update(&sha, prog.bin.data(), prog.bin.size()); // Initialize executable code if necessary if (prog.p_flags & 0x1) @@ -1004,6 +1017,28 @@ void ppu_load_exec(const ppu_exec_object& elf) } } + sha1_finish(&sha, sha1_hash); + + // Format patch name + std::string hash("PPU-0000000000000000000000000000000000000000"); + for (u32 i = 0; i < sizeof(sha1_hash); i++) + { + constexpr auto pal = "0123456789abcdef"; + hash[4 + i * 2] = pal[sha1_hash[i] >> 4]; + hash[5 + i * 2] = pal[sha1_hash[i] & 15]; + } + + // Apply the patch + fxm::check_unlocked()->apply(hash, vm::g_base_addr); + + if (!Emu.GetTitleID().empty()) + { + // Alternative patch + fxm::check_unlocked()->apply(Emu.GetTitleID() + '-' + hash, vm::g_base_addr); + } + + LOG_NOTICE(LOADER, "PPU executable hash: %s", hash); + // Initialize HLE modules ppu_initialize_modules(link); diff --git a/rpcs3/Emu/Cell/lv2/sys_spu.cpp b/rpcs3/Emu/Cell/lv2/sys_spu.cpp index a075e29c3b..72eb927002 100644 --- a/rpcs3/Emu/Cell/lv2/sys_spu.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_spu.cpp @@ -34,24 +34,13 @@ void sys_spu_image::load(const fs::file& stream) const u32 addr = this->segs.addr() + 4096; - sha1_context ctx; - u8 output[20]; - - sha1_starts(&ctx); - sha1_update(&ctx, reinterpret_cast(&obj.header), sizeof(obj.header)); - for (const auto& shdr : obj.shdrs) { - sha1_update(&ctx, reinterpret_cast(&shdr), sizeof(spu_exec_object::shdr_t)); - LOG_NOTICE(SPU, "** Section: sh_type=0x%x, addr=0x%llx, size=0x%llx, flags=0x%x", shdr.sh_type, shdr.sh_addr, shdr.sh_size, shdr.sh_flags); } for (const auto& prog : obj.progs) { - sha1_update(&ctx, reinterpret_cast(&prog), sizeof(spu_exec_object::phdr_t)); - sha1_update(&ctx, reinterpret_cast(prog.bin.data()), prog.bin.size()); - LOG_NOTICE(SPU, "** Segment: p_type=0x%x, p_vaddr=0x%llx, p_filesz=0x%llx, p_memsz=0x%llx, flags=0x%x", prog.p_type, prog.p_vaddr, prog.p_filesz, prog.p_memsz, prog.p_flags); if (prog.p_type == SYS_SPU_SEGMENT_TYPE_COPY) @@ -85,22 +74,6 @@ void sys_spu_image::load(const fs::file& stream) LOG_ERROR(SPU, "Unknown program type (0x%x)", prog.p_type); } } - - sha1_finish(&ctx, output); - - // Format patch name - std::string hash("spu-"); - for (u8 x : output) fmt::append(hash, "%02x", x); - LOG_NOTICE(LOADER, "Loaded SPU image: %s", hash); - - // Apply the patch - fxm::check_unlocked()->apply(hash, vm::g_base_addr + addr); - - if (!Emu.GetTitleID().empty()) - { - // Alternative patch - fxm::check_unlocked()->apply(Emu.GetTitleID() + '-' + hash, vm::g_base_addr + addr); - } } void sys_spu_image::free() @@ -113,15 +86,29 @@ void sys_spu_image::free() void sys_spu_image::deploy(u32 loc) { + // Segment info dump + std::string dump; + + // Executable hash + sha1_context sha; + sha1_starts(&sha); + u8 sha1_hash[20]; + for (int i = 0; i < nsegs; i++) { auto& seg = segs[i]; - LOG_NOTICE(SPU, "*** Deploy: t=0x%x, ls=0x%x, size=0x%x, addr=0x%x", seg.type, seg.ls, seg.size, seg.addr); + fmt::append(dump, "\n\t[%d] t=0x%x, ls=0x%x, size=0x%x, addr=0x%x", i, seg.type, seg.ls, seg.size, seg.addr); + + // Hash big-endian values + sha1_update(&sha, (uchar*)&seg.type, sizeof(seg.type)); + sha1_update(&sha, (uchar*)&seg.size, sizeof(seg.size)); if (seg.type == SYS_SPU_SEGMENT_TYPE_COPY) { std::memcpy(vm::base(loc + seg.ls), vm::base(seg.addr), seg.size); + sha1_update(&sha, (uchar*)&seg.ls, sizeof(seg.ls)); + sha1_update(&sha, vm::g_base_addr + seg.addr, seg.size); } else if (seg.type == SYS_SPU_SEGMENT_TYPE_FILL) { @@ -131,8 +118,32 @@ void sys_spu_image::deploy(u32 loc) } std::fill_n(vm::_ptr(loc + seg.ls), seg.size / 4, seg.addr); + sha1_update(&sha, (uchar*)&seg.ls, sizeof(seg.ls)); + sha1_update(&sha, (uchar*)&seg.addr, sizeof(seg.addr)); } } + + sha1_finish(&sha, sha1_hash); + + // Format patch name + std::string hash("SPU-0000000000000000000000000000000000000000"); + for (u32 i = 0; i < sizeof(sha1_hash); i++) + { + constexpr auto pal = "0123456789abcdef"; + hash[4 + i * 2] = pal[sha1_hash[i] >> 4]; + hash[5 + i * 2] = pal[sha1_hash[i] & 15]; + } + + // Apply the patch + fxm::check_unlocked()->apply(hash, vm::g_base_addr + loc); + + if (!Emu.GetTitleID().empty()) + { + // Alternative patch + fxm::check_unlocked()->apply(Emu.GetTitleID() + '-' + hash, vm::g_base_addr + loc); + } + + LOG_NOTICE(LOADER, "Loaded SPU image: %s%s", hash, dump); } error_code sys_spu_initialize(u32 max_usable_spu, u32 max_raw_spu) diff --git a/rpcs3/Loader/ELF.h b/rpcs3/Loader/ELF.h index 425651fdb4..dc5c7dc132 100644 --- a/rpcs3/Loader/ELF.h +++ b/rpcs3/Loader/ELF.h @@ -98,13 +98,13 @@ struct elf_phdr template class en_t, typename sz_t> struct elf_prog final : elf_phdr { - std::vector bin; + std::vector bin; using base = elf_phdr; elf_prog() = default; - elf_prog(u32 type, u32 flags, sz_t vaddr, sz_t memsz, sz_t align, std::vector&& bin) + elf_prog(u32 type, u32 flags, sz_t vaddr, sz_t memsz, sz_t align, std::vector&& bin) : bin(std::move(bin)) { base::p_type = type;