1
0
mirror of https://github.com/RPCS3/rpcs3.git synced 2024-11-22 10:42:36 +01:00

sys_ss: Further implemented Update Manager service for VSH

This commit is contained in:
brian218 2023-06-05 00:45:04 +08:00 committed by kd-11
parent 6a570ae57e
commit 42b388317e
4 changed files with 257 additions and 38 deletions

View File

@ -30,7 +30,7 @@ struct system_sw_version
~system_sw_version() = default;
u64 version;
atomic_t<u64> version;
};
struct board_storage

View File

@ -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<char> 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<std::basic_string<bool>>());
}

View File

@ -6,12 +6,87 @@
#include "Emu/Cell/PPUThread.h"
#include "Emu/Cell/timers.hpp"
#include "Emu/system_config.h"
#include "util/sysinfo.hpp"
#include <charconv>
#include <shared_mutex>
#include <unordered_set>
#ifdef _WIN32
#include <Windows.h>
#include <bcrypt.h>
#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<u32, u8> 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<u32> 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<sys_ss_rng_error>::format(std::string& out, u64 arg)
{
@ -145,10 +220,11 @@ error_code sys_ss_appliance_info_manager(u32 code, vm::ptr<u8> 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<u8> 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<u8> 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<u64> 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<lv2_update_manager>();
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<u32>(a1);
const auto info_ptr = ::narrow<u32>(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<u32>(a1);
const auto value_ptr = ::narrow<u32>(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<u32>(a1);
const auto value = ::narrow<u8>(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<u32>(a1);
const auto addr_ptr = ::narrow<u32>(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<u32>(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<u32>(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<u32>(a1);
const auto size = ::narrow<u32>(a2);
const auto addr_ptr = ::narrow<u32>(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;

View File

@ -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)