mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-25 20:22:30 +01:00
Implement ps3 application root flags detection
This commit is contained in:
parent
974bce19ed
commit
c2eb9a583d
@ -885,12 +885,17 @@ SELFDecrypter::SELFDecrypter(const fs::file& s)
|
||||
{
|
||||
}
|
||||
|
||||
bool SELFDecrypter::LoadHeaders(bool isElf32)
|
||||
bool SELFDecrypter::LoadHeaders(bool isElf32, SelfAdditionalInfo* out_info)
|
||||
{
|
||||
// Read SCE header.
|
||||
self_f.seek(0);
|
||||
sce_hdr.Load(self_f);
|
||||
|
||||
if (out_info)
|
||||
{
|
||||
out_info->valid = false;
|
||||
}
|
||||
|
||||
// Check SCE magic.
|
||||
if (!sce_hdr.CheckMagic())
|
||||
{
|
||||
@ -905,6 +910,11 @@ bool SELFDecrypter::LoadHeaders(bool isElf32)
|
||||
self_f.seek(self_hdr.se_appinfooff);
|
||||
app_info.Load(self_f);
|
||||
|
||||
if (out_info)
|
||||
{
|
||||
out_info->app_info = app_info;
|
||||
}
|
||||
|
||||
// Read ELF header.
|
||||
self_f.seek(self_hdr.se_elfoff);
|
||||
|
||||
@ -967,8 +977,7 @@ bool SELFDecrypter::LoadHeaders(bool isElf32)
|
||||
ctrlinfo_arr.clear();
|
||||
self_f.seek(self_hdr.se_controloff);
|
||||
|
||||
u32 i = 0;
|
||||
while(i < self_hdr.se_controlsize)
|
||||
for (u64 i = 0; i < self_hdr.se_controlsize;)
|
||||
{
|
||||
ctrlinfo_arr.emplace_back();
|
||||
ControlInfo &cinfo = ctrlinfo_arr.back();
|
||||
@ -976,6 +985,11 @@ bool SELFDecrypter::LoadHeaders(bool isElf32)
|
||||
i += cinfo.size;
|
||||
}
|
||||
|
||||
if (out_info)
|
||||
{
|
||||
out_info->ctrl_info = ctrlinfo_arr;
|
||||
}
|
||||
|
||||
// Read ELF section headers.
|
||||
if (isElf32)
|
||||
{
|
||||
@ -1013,6 +1027,11 @@ bool SELFDecrypter::LoadHeaders(bool isElf32)
|
||||
}
|
||||
}
|
||||
|
||||
if (out_info)
|
||||
{
|
||||
out_info->valid = true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1374,8 +1393,13 @@ static bool CheckDebugSelf(fs::file& s)
|
||||
return false;
|
||||
}
|
||||
|
||||
extern fs::file decrypt_self(fs::file elf_or_self, u8* klic_key)
|
||||
fs::file decrypt_self(fs::file elf_or_self, u8* klic_key, SelfAdditionalInfo* out_info)
|
||||
{
|
||||
if (out_info)
|
||||
{
|
||||
out_info->valid = false;
|
||||
}
|
||||
|
||||
if (!elf_or_self)
|
||||
{
|
||||
return fs::file{};
|
||||
@ -1393,7 +1417,7 @@ extern fs::file decrypt_self(fs::file elf_or_self, u8* klic_key)
|
||||
SELFDecrypter self_dec(elf_or_self);
|
||||
|
||||
// Load the SELF file headers.
|
||||
if (!self_dec.LoadHeaders(isElf32))
|
||||
if (!self_dec.LoadHeaders(isElf32, out_info))
|
||||
{
|
||||
LOG_ERROR(LOADER, "SELF: Failed to load SELF file headers!");
|
||||
return fs::file{};
|
||||
@ -1420,7 +1444,7 @@ extern fs::file decrypt_self(fs::file elf_or_self, u8* klic_key)
|
||||
return elf_or_self;
|
||||
}
|
||||
|
||||
extern bool verify_npdrm_self_headers(const fs::file& self, u8* klic_key)
|
||||
bool verify_npdrm_self_headers(const fs::file& self, u8* klic_key)
|
||||
{
|
||||
if (!self)
|
||||
return false;
|
||||
|
@ -343,6 +343,13 @@ struct SelfHeader
|
||||
void Show(){}
|
||||
};
|
||||
|
||||
struct SelfAdditionalInfo
|
||||
{
|
||||
bool valid = false;
|
||||
std::vector<ControlInfo> ctrl_info;
|
||||
AppInfo app_info;
|
||||
};
|
||||
|
||||
class SCEDecrypter
|
||||
{
|
||||
protected:
|
||||
@ -413,7 +420,7 @@ class SELFDecrypter
|
||||
public:
|
||||
SELFDecrypter(const fs::file& s);
|
||||
fs::file MakeElf(bool isElf32);
|
||||
bool LoadHeaders(bool isElf32);
|
||||
bool LoadHeaders(bool isElf32, SelfAdditionalInfo* out_info = nullptr);
|
||||
void ShowHeaders(bool isElf32);
|
||||
bool LoadMetadata(u8* klic_key);
|
||||
bool DecryptData();
|
||||
@ -497,6 +504,6 @@ private:
|
||||
}
|
||||
};
|
||||
|
||||
extern fs::file decrypt_self(fs::file elf_or_self, u8* klic_key = nullptr);
|
||||
extern bool verify_npdrm_self_headers(const fs::file& self, u8* klic_key = nullptr);
|
||||
extern std::array<u8, 0x10> get_default_self_klic();
|
||||
fs::file decrypt_self(fs::file elf_or_self, u8* klic_key = nullptr, SelfAdditionalInfo* additional_info = nullptr);
|
||||
bool verify_npdrm_self_headers(const fs::file& self, u8* klic_key = nullptr);
|
||||
std::array<u8, 0x10> get_default_self_klic();
|
||||
|
@ -1160,6 +1160,27 @@ void ppu_load_exec(const ppu_exec_object& elf)
|
||||
}
|
||||
}
|
||||
|
||||
// Read control flags (0 if doesn't exist)
|
||||
g_ps3_process_info.ctrl_flags1 = 0;
|
||||
|
||||
if (bool not_found = true)
|
||||
{
|
||||
for (const auto& ctrl : g_ps3_process_info.self_info.ctrl_info)
|
||||
{
|
||||
if (ctrl.type == 1)
|
||||
{
|
||||
if (!std::exchange(not_found, false))
|
||||
{
|
||||
LOG_ERROR(LOADER, "More than one control flags header found! (flags1=0x%x)",
|
||||
ctrl.control_flags.ctrl_flag1);
|
||||
break;
|
||||
}
|
||||
|
||||
g_ps3_process_info.ctrl_flags1 |= ctrl.control_flags.ctrl_flag1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Load other programs
|
||||
for (auto& prog : elf.progs)
|
||||
{
|
||||
@ -1207,7 +1228,8 @@ void ppu_load_exec(const ppu_exec_object& elf)
|
||||
{
|
||||
sdk_version = info.sdk_version;
|
||||
|
||||
if (s32 prio = info.primary_prio; prio < 3072 && prio >= 0)
|
||||
if (s32 prio = info.primary_prio; prio < 3072
|
||||
&& (prio >= (g_ps3_process_info.debug_or_root() ? 0 : -512)))
|
||||
{
|
||||
primary_prio = prio;
|
||||
}
|
||||
|
@ -166,7 +166,7 @@ public:
|
||||
u64 rtime{0};
|
||||
u64 rdata{0}; // Reservation data
|
||||
|
||||
atomic_t<u32> prio{0}; // Thread priority (0..3071)
|
||||
atomic_t<s32> prio{0}; // Thread priority (0..3071)
|
||||
const u32 stack_size; // Stack size
|
||||
const u32 stack_addr; // Stack address
|
||||
|
||||
|
@ -770,7 +770,7 @@ const std::array<ppu_function_t, 1024> s_ppu_syscall_table
|
||||
null_func,//BIND_FUNC(sys_ss_individual_info_manager) //868 ROOT / DBG AUTHID
|
||||
null_func,//BIND_FUNC(sys_ss_factory_data_manager) //869 ROOT
|
||||
BIND_FUNC(sys_ss_get_console_id), //870 (0x366)
|
||||
null_func,//BIND_FUNC(sys_ss_access_control_engine), //871 (0x367) DBG
|
||||
BIND_FUNC(sys_ss_access_control_engine), //871 (0x367) DBG
|
||||
BIND_FUNC(sys_ss_get_open_psid), //872 (0x368)
|
||||
null_func,//BIND_FUNC(sys_ss_get_cache_of_product_mode), //873 (0x369)
|
||||
null_func,//BIND_FUNC(sys_ss_get_cache_of_flash_ext_flag), //874 (0x36A)
|
||||
@ -1066,20 +1066,24 @@ void lv2_obj::sleep_unlocked(cpu_thread& thread, u64 timeout)
|
||||
}
|
||||
}
|
||||
|
||||
void lv2_obj::awake_unlocked(cpu_thread* cpu, u32 prio)
|
||||
void lv2_obj::awake_unlocked(cpu_thread* cpu, s32 prio)
|
||||
{
|
||||
// Check thread type
|
||||
AUDIT(!cpu || cpu->id_type() == 1);
|
||||
|
||||
if (prio < INT32_MAX)
|
||||
switch (prio)
|
||||
{
|
||||
// Priority set
|
||||
if (static_cast<ppu_thread*>(cpu)->prio.exchange(prio) == prio || !unqueue(g_ppu, cpu))
|
||||
{
|
||||
return;
|
||||
}
|
||||
default:
|
||||
{
|
||||
// Priority set
|
||||
if (static_cast<ppu_thread*>(cpu)->prio.exchange(prio) == prio || !unqueue(g_ppu, cpu))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
else if (prio == -4)
|
||||
case yield_cmd:
|
||||
{
|
||||
// Yield command
|
||||
const u64 start_time = get_guest_system_time();
|
||||
@ -1102,6 +1106,11 @@ void lv2_obj::awake_unlocked(cpu_thread* cpu, u32 prio)
|
||||
|
||||
static_cast<ppu_thread*>(cpu)->start_time = start_time;
|
||||
}
|
||||
case enqueue_cmd:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const auto emplace_thread = [](cpu_thread* const cpu)
|
||||
{
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include "Emu/Cell/ErrorCodes.h"
|
||||
#include "Emu/Cell/PPUThread.h"
|
||||
#include "sys_event.h"
|
||||
#include "sys_process.h"
|
||||
#include "sys_mmapper.h"
|
||||
|
||||
LOG_CHANNEL(sys_ppu_thread);
|
||||
@ -210,7 +211,7 @@ error_code sys_ppu_thread_set_priority(ppu_thread& ppu, u32 thread_id, s32 prio)
|
||||
{
|
||||
sys_ppu_thread.trace("sys_ppu_thread_set_priority(thread_id=0x%x, prio=%d)", thread_id, prio);
|
||||
|
||||
if (prio < 0 || prio > 3071)
|
||||
if (prio < (g_ps3_process_info.debug_or_root() ? -512 : 0) || prio > 3071)
|
||||
{
|
||||
return CELL_EINVAL;
|
||||
}
|
||||
@ -219,7 +220,7 @@ error_code sys_ppu_thread_set_priority(ppu_thread& ppu, u32 thread_id, s32 prio)
|
||||
{
|
||||
if (thread.prio != prio)
|
||||
{
|
||||
lv2_obj::awake(&thread, prio);
|
||||
lv2_obj::set_priority(thread, prio);
|
||||
}
|
||||
});
|
||||
|
||||
@ -299,7 +300,7 @@ error_code _sys_ppu_thread_create(vm::ptr<u64> thread_id, vm::ptr<ppu_thread_par
|
||||
return CELL_EFAULT;
|
||||
}
|
||||
|
||||
if (prio < 0 || prio > 3071)
|
||||
if (prio < (g_ps3_process_info.debug_or_root() ? -512 : 0) || prio > 3071)
|
||||
{
|
||||
return CELL_EINVAL;
|
||||
}
|
||||
@ -359,7 +360,7 @@ error_code sys_ppu_thread_start(ppu_thread& ppu, u32 thread_id)
|
||||
|
||||
const auto thread = idm::get<named_thread<ppu_thread>>(thread_id, [&](ppu_thread& thread)
|
||||
{
|
||||
lv2_obj::awake(&thread, -2);
|
||||
lv2_obj::awake(&thread);
|
||||
});
|
||||
|
||||
if (!thread)
|
||||
|
@ -25,7 +25,23 @@
|
||||
#include "sys_fs.h"
|
||||
#include "sys_spu.h"
|
||||
|
||||
// Check all flags known to be related to extended permissions (TODO)
|
||||
// I think anything which has root flags implicitly has debug perm as well
|
||||
// But I havn't confirmed it.
|
||||
bool ps3_process_info_t::debug_or_root() const
|
||||
{
|
||||
return (ctrl_flags1 & (0xe << 28)) != 0;
|
||||
}
|
||||
|
||||
bool ps3_process_info_t::has_root_perm() const
|
||||
{
|
||||
return (ctrl_flags1 & (0xc << 28)) != 0;
|
||||
}
|
||||
|
||||
bool ps3_process_info_t::has_debug_perm() const
|
||||
{
|
||||
return (ctrl_flags1 & (0xa << 28)) != 0;
|
||||
}
|
||||
|
||||
LOG_CHANNEL(sys_process);
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "Crypto/unself.h"
|
||||
#include "Emu/Memory/vm_ptr.h"
|
||||
|
||||
// Process Local Object Type
|
||||
@ -40,6 +41,12 @@ struct ps3_process_info_t
|
||||
{
|
||||
u32 sdk_ver;
|
||||
u32 ppc_seg;
|
||||
SelfAdditionalInfo self_info;
|
||||
u32 ctrl_flags1 = 0;
|
||||
|
||||
bool has_root_perm() const;
|
||||
bool has_debug_perm() const;
|
||||
bool debug_or_root() const;
|
||||
};
|
||||
|
||||
extern ps3_process_info_t g_ps3_process_info;
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "Emu/Cell/PPUThread.h"
|
||||
#include "Emu/Cell/RawSPUThread.h"
|
||||
#include "sys_interrupt.h"
|
||||
#include "sys_process.h"
|
||||
#include "sys_mmapper.h"
|
||||
#include "sys_event.h"
|
||||
|
||||
@ -409,7 +410,8 @@ error_code sys_spu_thread_group_create(ppu_thread& ppu, vm::ptr<u32> id, u32 num
|
||||
|
||||
// TODO: max num value should be affected by sys_spu_initialize() settings
|
||||
|
||||
if (attr->nsize > 0x80 || !num || num > 6 || ((prio < 16 || prio > 255) && (attr->type != SYS_SPU_THREAD_GROUP_TYPE_EXCLUSIVE_NON_CONTEXT && attr->type != SYS_SPU_THREAD_GROUP_TYPE_COOPERATE_WITH_SYSTEM)))
|
||||
const s32 min_prio = g_ps3_process_info.has_root_perm() ? 0 : 16;
|
||||
if (attr->nsize > 0x80 || !num || num > 6 || ((prio < min_prio || prio > 255) && (attr->type != SYS_SPU_THREAD_GROUP_TYPE_EXCLUSIVE_NON_CONTEXT && attr->type != SYS_SPU_THREAD_GROUP_TYPE_COOPERATE_WITH_SYSTEM)))
|
||||
{
|
||||
return CELL_EINVAL;
|
||||
}
|
||||
@ -802,11 +804,6 @@ error_code sys_spu_thread_group_set_priority(ppu_thread& ppu, u32 id, s32 priori
|
||||
|
||||
sys_spu.trace("sys_spu_thread_group_set_priority(id=0x%x, priority=%d)", id, priority);
|
||||
|
||||
if (priority < 16 || priority > 255)
|
||||
{
|
||||
return CELL_EINVAL;
|
||||
}
|
||||
|
||||
const auto group = idm::get<lv2_spu_group>(id);
|
||||
|
||||
if (!group)
|
||||
@ -814,6 +811,11 @@ error_code sys_spu_thread_group_set_priority(ppu_thread& ppu, u32 id, s32 priori
|
||||
return CELL_ESRCH;
|
||||
}
|
||||
|
||||
if (priority < (g_ps3_process_info.has_root_perm() ? 0 : 16) || priority > 255)
|
||||
{
|
||||
return CELL_EINVAL;
|
||||
}
|
||||
|
||||
if (group->type == SYS_SPU_THREAD_GROUP_TYPE_EXCLUSIVE_NON_CONTEXT)
|
||||
{
|
||||
return CELL_EINVAL;
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include "stdafx.h"
|
||||
#include "sys_ss.h"
|
||||
|
||||
#include "sys_process.h"
|
||||
#include "Emu/Cell/PPUThread.h"
|
||||
|
||||
|
||||
@ -64,6 +65,52 @@ error_code sys_ss_random_number_generator(u32 arg1, vm::ptr<void> buf, u64 size)
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code sys_ss_access_control_engine(u64 pkg_id, u64 a2, u64 a3)
|
||||
{
|
||||
sys_ss.todo("sys_ss_access_control_engine(pkg_id=0x%llx, a2=0x%llx, a3=0x%llx)", pkg_id, a2, a3);
|
||||
|
||||
const u64 authid = g_ps3_process_info.self_info.valid ?
|
||||
g_ps3_process_info.self_info.app_info.authid : 0;
|
||||
|
||||
switch (pkg_id)
|
||||
{
|
||||
case 0x1:
|
||||
{
|
||||
if (!g_ps3_process_info.debug_or_root())
|
||||
{
|
||||
return CELL_ENOSYS;
|
||||
}
|
||||
|
||||
if (!a2)
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
}
|
||||
|
||||
verify(HERE), a2 == process_getpid();
|
||||
vm::_ref<u64>(vm::cast(a3)) = authid;
|
||||
break;
|
||||
}
|
||||
case 0x2:
|
||||
{
|
||||
vm::_ref<u64>(vm::cast(a2)) = authid;
|
||||
break;
|
||||
}
|
||||
case 0x3:
|
||||
{
|
||||
if (!g_ps3_process_info.debug_or_root())
|
||||
{
|
||||
return CELL_ENOSYS;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return 0x8001051du;
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 sys_ss_get_console_id(vm::ptr<u8> buf)
|
||||
{
|
||||
sys_ss.todo("sys_ss_get_console_id(buf=*0x%x)", buf);
|
||||
|
@ -1,4 +1,4 @@
|
||||
#pragma once
|
||||
#pragma once
|
||||
|
||||
#include "Emu/Memory/vm_ptr.h"
|
||||
#include "Emu/Cell/ErrorCodes.h"
|
||||
@ -10,5 +10,6 @@ struct CellSsOpenPSID
|
||||
};
|
||||
|
||||
error_code sys_ss_random_number_generator(u32 arg1, vm::ptr<void> buf, u64 size);
|
||||
error_code sys_ss_access_control_engine(u64 pkg_id, u64 a2, u64 a3);
|
||||
s32 sys_ss_get_console_id(vm::ptr<u8> buf);
|
||||
s32 sys_ss_get_open_psid(vm::ptr<CellSsOpenPSID> ptr);
|
||||
|
@ -65,6 +65,15 @@ struct lv2_obj
|
||||
static const u32 id_step = 0x100;
|
||||
static const u32 id_count = 8192;
|
||||
|
||||
private:
|
||||
enum thread_cmd : s32
|
||||
{
|
||||
yield_cmd = INT32_MIN,
|
||||
enqueue_cmd,
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
// Find and remove the object from the container (deque or vector)
|
||||
template <typename T, typename E>
|
||||
static bool unqueue(std::deque<T*>& queue, const E& object)
|
||||
@ -96,7 +105,7 @@ struct lv2_obj
|
||||
return res;
|
||||
}
|
||||
|
||||
u32 prio = -1;
|
||||
s32 prio = 3071;
|
||||
auto it = queue.cbegin();
|
||||
|
||||
for (auto found = it, end = queue.cend(); found != end; found++)
|
||||
@ -120,7 +129,7 @@ private:
|
||||
static void sleep_unlocked(cpu_thread&, u64 timeout);
|
||||
|
||||
// Schedule the thread
|
||||
static void awake_unlocked(cpu_thread*, u32 prio = -1);
|
||||
static void awake_unlocked(cpu_thread*, s32 prio = enqueue_cmd);
|
||||
|
||||
public:
|
||||
static void sleep(cpu_thread& cpu, const u64 timeout = 0)
|
||||
@ -130,7 +139,7 @@ public:
|
||||
g_to_awake.clear();
|
||||
}
|
||||
|
||||
static inline void awake(cpu_thread* const thread, const u32 prio = -1)
|
||||
static inline void awake(cpu_thread* const thread, s32 prio = enqueue_cmd)
|
||||
{
|
||||
std::lock_guard lock(g_mutex);
|
||||
awake_unlocked(thread, prio);
|
||||
@ -139,7 +148,13 @@ public:
|
||||
static void yield(cpu_thread& thread)
|
||||
{
|
||||
vm::temporary_unlock(thread);
|
||||
awake(&thread, -4);
|
||||
awake(&thread, yield_cmd);
|
||||
}
|
||||
|
||||
static void set_priority(cpu_thread& thread, s32 prio)
|
||||
{
|
||||
verify(HERE), prio + 512u < 3712;
|
||||
awake(&thread, prio);
|
||||
}
|
||||
|
||||
static inline void awake_all()
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include "Emu/Cell/PPUAnalyser.h"
|
||||
#include "Emu/Cell/SPUThread.h"
|
||||
#include "Emu/Cell/RawSPUThread.h"
|
||||
#include "Emu/Cell/lv2/sys_process.h"
|
||||
#include "Emu/Cell/lv2/sys_memory.h"
|
||||
#include "Emu/Cell/lv2/sys_sync.h"
|
||||
#include "Emu/Cell/lv2/sys_prx.h"
|
||||
@ -1481,7 +1482,7 @@ void Emulator::Load(const std::string& title_id, bool add_only, bool force_globa
|
||||
elf_file.open(decrypted_path);
|
||||
}
|
||||
// Decrypt SELF
|
||||
else if ((elf_file = decrypt_self(std::move(elf_file), klic.empty() ? nullptr : klic.data())))
|
||||
else if ((elf_file = decrypt_self(std::move(elf_file), klic.empty() ? nullptr : klic.data(), &g_ps3_process_info.self_info)))
|
||||
{
|
||||
if (true)
|
||||
{
|
||||
@ -1498,6 +1499,10 @@ void Emulator::Load(const std::string& title_id, bool add_only, bool force_globa
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
g_ps3_process_info.self_info.valid = false;
|
||||
}
|
||||
|
||||
if (!elf_file)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user