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:
parent
6a570ae57e
commit
42b388317e
@ -30,7 +30,7 @@ struct system_sw_version
|
||||
|
||||
~system_sw_version() = default;
|
||||
|
||||
u64 version;
|
||||
atomic_t<u64> version;
|
||||
};
|
||||
|
||||
struct board_storage
|
||||
|
@ -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>>());
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user