From 42b388317ea9f8c3f402b7046343c37b3b5b6555 Mon Sep 17 00:00:00 2001 From: brian218 Date: Mon, 5 Jun 2023 00:45:04 +0800 Subject: [PATCH] sys_ss: Further implemented Update Manager service for VSH --- rpcs3/Emu/Cell/lv2/sys_game.cpp | 2 +- rpcs3/Emu/Cell/lv2/sys_prx.cpp | 3 +- rpcs3/Emu/Cell/lv2/sys_ss.cpp | 288 ++++++++++++++++++++++++++++---- rpcs3/Emu/System.cpp | 2 +- 4 files changed, 257 insertions(+), 38 deletions(-) diff --git a/rpcs3/Emu/Cell/lv2/sys_game.cpp b/rpcs3/Emu/Cell/lv2/sys_game.cpp index 64bd930ce0..d734546c10 100644 --- a/rpcs3/Emu/Cell/lv2/sys_game.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_game.cpp @@ -30,7 +30,7 @@ struct system_sw_version ~system_sw_version() = default; - u64 version; + atomic_t version; }; struct board_storage diff --git a/rpcs3/Emu/Cell/lv2/sys_prx.cpp b/rpcs3/Emu/Cell/lv2/sys_prx.cpp index 6bc148ceda..8433836a17 100644 --- a/rpcs3/Emu/Cell/lv2/sys_prx.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_prx.cpp @@ -1,6 +1,7 @@ #include "stdafx.h" #include "sys_prx.h" +#include "Emu/System.h" #include "Emu/system_config.h" #include "Emu/VFS.h" #include "Emu/IdManager.h" @@ -842,7 +843,7 @@ error_code _sys_prx_register_module(ppu_thread& ppu, vm::cptr name, vm::pt if (info.type & 0x1) { - if (g_ps3_process_info.get_cellos_appname() == "vsh.self"sv) + if (Emu.IsVsh()) { ppu_manual_load_imports_exports(info.lib_stub_ea.addr(), info.lib_stub_size, info.lib_entries_ea.addr(), info.lib_entries_size, *std::make_unique>()); } diff --git a/rpcs3/Emu/Cell/lv2/sys_ss.cpp b/rpcs3/Emu/Cell/lv2/sys_ss.cpp index 67e4088f1f..b887f5be8d 100644 --- a/rpcs3/Emu/Cell/lv2/sys_ss.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_ss.cpp @@ -6,12 +6,87 @@ #include "Emu/Cell/PPUThread.h" #include "Emu/Cell/timers.hpp" #include "Emu/system_config.h" +#include "util/sysinfo.hpp" + +#include +#include +#include #ifdef _WIN32 #include #include #endif +struct lv2_update_manager +{ + lv2_update_manager() + { + std::string version_str = utils::get_firmware_version(); + + // For example, 4.90 should be converted to 0x4900000000000 + std::erase(version_str, '.'); + if (std::from_chars(version_str.data(), version_str.data() + version_str.size(), system_sw_version, 16).ec != std::errc{}) + system_sw_version <<= 40; + else + system_sw_version = 0; + } + + lv2_update_manager(const lv2_update_manager&) = delete; + lv2_update_manager& operator=(const lv2_update_manager&) = delete; + ~lv2_update_manager() = default; + + u64 system_sw_version; + + std::unordered_map eeprom_map // offset, value + { + // system language + // *i think* this gives english + {0x48C18, 0x00}, + {0x48C19, 0x00}, + {0x48C1A, 0x00}, + {0x48C1B, 0x01}, + // system language end + + // vsh target (seems it can be 0xFFFFFFFE, 0xFFFFFFFF, 0x00000001 default: 0x00000000 / vsh sets it to 0x00000000 on boot if it isn't 0x00000000) + {0x48C1C, 0x00}, + {0x48C1D, 0x00}, + {0x48C1E, 0x00}, + {0x48C1F, 0x00} + // vsh target end + }; + mutable std::shared_mutex eeprom_mutex; + + std::unordered_set malloc_set; + mutable std::shared_mutex malloc_mutex; + + // return address + u32 allocate(u32 size) + { + std::unique_lock unique_lock(malloc_mutex); + + if (const auto addr = vm::alloc(size, vm::main); addr) + { + malloc_set.emplace(addr); + return addr; + } + + return 0; + } + + // return size + u32 deallocate(u32 addr) + { + std::unique_lock unique_lock(malloc_mutex); + + if (malloc_set.count(addr)) + { + return vm::dealloc(addr, vm::main); + } + + return 0; + } +}; + template<> void fmt_class_string::format(std::string& out, u64 arg) { @@ -145,10 +220,11 @@ error_code sys_ss_appliance_info_manager(u32 code, vm::ptr buffer) { sys_ss.notice("sys_ss_appliance_info_manager(code=0x%x, buffer=*0x%x)", code, buffer); + if (!g_ps3_process_info.has_root_perm()) + return CELL_ENOSYS; + if (!buffer) - { return CELL_EFAULT; - } switch (code) { @@ -158,7 +234,7 @@ error_code sys_ss_appliance_info_manager(u32 code, vm::ptr buffer) constexpr u8 product_code[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x89 }; std::memcpy(buffer.get_ptr(), product_code, 16); if (g_cfg.core.debug_console_mode) - buffer[15] = 0xA0; + buffer[15] = 0x81; // DECR break; } case 0x19003: @@ -167,7 +243,10 @@ error_code sys_ss_appliance_info_manager(u32 code, vm::ptr buffer) constexpr u8 idps[] = { 0x00, 0x00, 0x00, 0x01, 0x00, 0x89, 0x00, 0x0B, 0x14, 0x00, 0xEF, 0xDD, 0xCA, 0x25, 0x52, 0x66 }; std::memcpy(buffer.get_ptr(), idps, 16); if (g_cfg.core.debug_console_mode) - buffer[5] = 0xA0; + { + buffer[5] = 0x81; // DECR + buffer[7] = 0x09; // DECR-1400 + } break; } case 0x19004: @@ -272,46 +351,185 @@ error_code sys_ss_get_boot_device(vm::ptr dev) error_code sys_ss_update_manager(u64 pkg_id, u64 a1, u64 a2, u64 a3, u64 a4, u64 a5, u64 a6) { - sys_ss.todo("sys_ss_update_manager(pkg=0x%x, a1=0x%x, a2=0x%x, a3=0x%x, a4=0x%x, a5=0x%x, a6=0x%x)", pkg_id, a1, a2, a3, a4, a5, a6); + sys_ss.notice("sys_ss_update_manager(pkg=0x%x, a1=0x%x, a2=0x%x, a3=0x%x, a4=0x%x, a5=0x%x, a6=0x%x)", pkg_id, a1, a2, a3, a4, a5, a6); - if (pkg_id == 0x600B) + if (!g_ps3_process_info.has_root_perm()) + return CELL_ENOSYS; + + auto& update_manager = g_fxo->get(); + + switch (pkg_id) { - // read eeprom - // a1 == offset - // a2 == *value - if (a1 == 0x48C06) - { - // fself ctrl? - vm::write8(a2, 0xFF); - } - else if (a1 == 0x48C42) - { - // hddcopymode - vm::write8(a2, 0xFF); - } - else if (a1 >= 0x48C1C && a1 <= 0x48C1F) - { - // vsh target? (seems it can be 0xFFFFFFFE, 0xFFFFFFFF, 0x00000001 default: 0x00000000 /maybe QA,Debug,Retail,Kiosk?) - vm::write8(a2, a1 == 0x48C1F ? 0x1 : 0); - } - else if (a1 >= 0x48C18 && a1 <= 0x48C1B) - { - // system language - // *i think* this gives english - vm::write8(a2, a1 == 0x48C1B ? 0x1 : 0); - } - } - else if (pkg_id == 0x600C) + case 0x6001: { - // write eeprom + // update package async + break; } - else if (pkg_id == 0x6009) + case 0x6002: + { + // inspect package async + break; + } + case 0x6003: + { + // get installed package info + [[maybe_unused]] const auto type = ::narrow(a1); + const auto info_ptr = ::narrow(a2); + + if (!info_ptr) + return CELL_EFAULT; + + vm::write64(info_ptr, update_manager.system_sw_version); + + break; + } + case 0x6004: + { + // get fix instruction + break; + } + case 0x6005: + { + // extract package async + break; + } + case 0x6006: + { + // get extract package + break; + } + case 0x6007: + { + // get flash initialized + break; + } + case 0x6008: + { + // set flash initialized + break; + } + case 0x6009: { // get seed token + break; } - else if (pkg_id == 0x600A) + case 0x600A: { // set seed token + break; + } + case 0x600B: + { + // read eeprom + const auto offset = ::narrow(a1); + const auto value_ptr = ::narrow(a2); + + if (!value_ptr) + return CELL_EFAULT; + + std::shared_lock shared_lock(update_manager.eeprom_mutex); + + if (const auto iterator = update_manager.eeprom_map.find(offset); iterator != update_manager.eeprom_map.end()) + vm::write8(value_ptr, iterator->second); + else + vm::write8(value_ptr, 0xFF); // 0xFF if not set + + break; + } + case 0x600C: + { + // write eeprom + const auto offset = ::narrow(a1); + const auto value = ::narrow(a2); + + std::unique_lock unique_lock(update_manager.eeprom_mutex); + + if (value != 0xFF) + update_manager.eeprom_map[offset] = value; + else + update_manager.eeprom_map.erase(offset); // 0xFF: unset + + break; + } + case 0x600D: + { + // get async status + break; + } + case 0x600E: + { + // allocate buffer + const auto size = ::narrow(a1); + const auto addr_ptr = ::narrow(a2); + + if (!addr_ptr) + return CELL_EFAULT; + + const auto addr = update_manager.allocate(size); + + if (!addr) + return CELL_ENOMEM; + + vm::write32(addr_ptr, addr); + + break; + } + case 0x600F: + { + // release buffer + const auto addr = ::narrow(a1); + + if (!update_manager.deallocate(addr)) + return CELL_ENOMEM; + + break; + } + case 0x6010: + { + // check integrity + break; + } + case 0x6011: + { + // get applicable version + const auto addr_ptr = ::narrow(a2); + + if (!addr_ptr) + return CELL_EFAULT; + + vm::write64(addr_ptr, 0x340ULL << 40); // 3.40 + + break; + } + case 0x6012: + { + // allocate buffer from memory container + [[maybe_unused]] const auto mem_ct = ::narrow(a1); + const auto size = ::narrow(a2); + const auto addr_ptr = ::narrow(a3); + + if (!addr_ptr) + return CELL_EFAULT; + + const auto addr = update_manager.allocate(size); + + if (!addr) + return CELL_ENOMEM; + + vm::write32(addr_ptr, addr); + + break; + } + case 0x6013: + { + // unknown + break; + } + default: + { + sys_ss.error("sys_ss_update_manager(): invalid packet id 0x%x ", pkg_id); + return CELL_EINVAL; + } } return CELL_OK; diff --git a/rpcs3/Emu/System.cpp b/rpcs3/Emu/System.cpp index 5b185a88a8..99c8991b18 100644 --- a/rpcs3/Emu/System.cpp +++ b/rpcs3/Emu/System.cpp @@ -3460,7 +3460,7 @@ utils::serial* Emulator::DeserialManager() const bool Emulator::IsVsh() { - return g_ps3_process_info.get_cellos_appname() == "vsh.self"sv; + return g_ps3_process_info.self_info.prog_id_hdr.program_authority_id >> 52 == 0x107; // Not only VSH but also all LV2 SELFs need the special treatment } bool Emulator::IsValidSfb(const std::string& path)