mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-02-06 00:40:11 +00:00
Implement lv2_file::open()
Return accurate error codes in prx_load_module, sys_spu_image_open and overlay_load_module.
This commit is contained in:
parent
acd50eefaf
commit
1669e95870
@ -27,7 +27,7 @@ lv2_fs_mount_point g_mp_sys_app_home{512, 512, lv2_mp_flag::strict_get_block_siz
|
||||
lv2_fs_mount_point g_mp_sys_host_root{512, 512, lv2_mp_flag::strict_get_block_size + lv2_mp_flag::no_uid_gid};
|
||||
lv2_fs_mount_point g_mp_sys_dev_flash{512, 8192, lv2_mp_flag::read_only + lv2_mp_flag::no_uid_gid};
|
||||
|
||||
bool verify_mself(u32 fd, fs::file const& mself_file)
|
||||
bool verify_mself(const fs::file& mself_file)
|
||||
{
|
||||
FsMselfHeader mself_header;
|
||||
if (!mself_file.read<FsMselfHeader>(mself_header))
|
||||
@ -240,23 +240,17 @@ error_code sys_fs_test(ppu_thread& ppu, u32 arg1, u32 arg2, vm::ptr<u32> arg3, u
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code sys_fs_open(ppu_thread& ppu, vm::cptr<char> path, s32 flags, vm::ptr<u32> fd, s32 mode, vm::cptr<void> arg, u64 size)
|
||||
lv2_file::open_result_t lv2_file::open(std::string_view vpath, s32 flags, s32 mode, const void* arg, u64 size)
|
||||
{
|
||||
lv2_obj::sleep(ppu);
|
||||
if (vpath.empty())
|
||||
{
|
||||
return {CELL_ENOENT};
|
||||
}
|
||||
|
||||
sys_fs.warning("sys_fs_open(path=%s, flags=%#o, fd=*0x%x, mode=%#o, arg=*0x%x, size=0x%llx)", path, flags, fd, mode, arg, size);
|
||||
std::string path;
|
||||
const std::string local_path = vfs::get(vpath, nullptr, &path);
|
||||
|
||||
if (!path)
|
||||
return CELL_EFAULT;
|
||||
|
||||
if (!path[0])
|
||||
return CELL_ENOENT;
|
||||
|
||||
std::string processed_path;
|
||||
const std::string_view vpath = path.get_ptr();
|
||||
const std::string local_path = vfs::get(vpath, nullptr, &processed_path);
|
||||
|
||||
const auto mp = lv2_fs_object::get_mp(vpath);
|
||||
const auto mp = lv2_fs_object::get_mp(path);
|
||||
|
||||
if (vpath.find_first_not_of('/') == umax)
|
||||
{
|
||||
@ -319,7 +313,7 @@ error_code sys_fs_open(ppu_thread& ppu, vm::cptr<char> path, s32 flags, vm::ptr<
|
||||
|
||||
if (flags & CELL_FS_O_UNK)
|
||||
{
|
||||
sys_fs.warning("sys_fs_open called with CELL_FS_O_UNK flag enabled. FLAGS: %#o", flags);
|
||||
sys_fs.warning("lv2_file::open() called with CELL_FS_O_UNK flag enabled. FLAGS: %#o", flags);
|
||||
}
|
||||
|
||||
if (mp->flags & lv2_mp_flag::read_only)
|
||||
@ -342,7 +336,7 @@ error_code sys_fs_open(ppu_thread& ppu, vm::cptr<char> path, s32 flags, vm::ptr<
|
||||
|
||||
if (!open_mode)
|
||||
{
|
||||
fmt::throw_exception("sys_fs_open(%s): Invalid or unimplemented flags: %#o" HERE, path, flags);
|
||||
fmt::throw_exception("lv2_file::open(%s): Invalid or unimplemented flags: %#o" HERE, path, flags);
|
||||
}
|
||||
|
||||
fs::file file;
|
||||
@ -387,13 +381,13 @@ error_code sys_fs_open(ppu_thread& ppu, vm::cptr<char> path, s32 flags, vm::ptr<
|
||||
|
||||
if (open_mode & fs::excl && fs::g_tls_error == fs::error::exist)
|
||||
{
|
||||
return not_an_error(CELL_EEXIST);
|
||||
return {CELL_EEXIST};
|
||||
}
|
||||
|
||||
switch (auto error = fs::g_tls_error)
|
||||
{
|
||||
case fs::error::noent: return {CELL_ENOENT, path};
|
||||
default: sys_fs.error("sys_fs_open(): unknown error %s", error);
|
||||
default: sys_fs.error("lv2_file::open(): unknown error %s", error);
|
||||
}
|
||||
|
||||
return {CELL_EIO, path};
|
||||
@ -414,17 +408,17 @@ error_code sys_fs_open(ppu_thread& ppu, vm::cptr<char> path, s32 flags, vm::ptr<
|
||||
}
|
||||
}
|
||||
|
||||
if ((flags & CELL_FS_O_MSELF) && (!verify_mself(*fd, file)))
|
||||
if (flags & CELL_FS_O_MSELF && !verify_mself(file))
|
||||
{
|
||||
return {CELL_ENOTMSELF, path};
|
||||
}
|
||||
|
||||
const auto casted_arg = vm::static_ptr_cast<const u64>(arg);
|
||||
|
||||
if (size == 8)
|
||||
{
|
||||
// check for sdata
|
||||
if (*casted_arg == 0x18000000010ull)
|
||||
switch (*static_cast<const be_t<u64>*>(arg))
|
||||
{
|
||||
case 0x18000000010:
|
||||
{
|
||||
// check if the file has the NPD header, or else assume its not encrypted
|
||||
u32 magic;
|
||||
@ -440,9 +434,11 @@ error_code sys_fs_open(ppu_thread& ppu, vm::cptr<char> path, s32 flags, vm::ptr<
|
||||
|
||||
file.reset(std::move(sdata_file));
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
// edata
|
||||
else if (*casted_arg == 0x2u)
|
||||
case 0x2:
|
||||
{
|
||||
// check if the file has the NPD header, or else assume its not encrypted
|
||||
u32 magic;
|
||||
@ -459,10 +455,38 @@ error_code sys_fs_open(ppu_thread& ppu, vm::cptr<char> path, s32 flags, vm::ptr<
|
||||
|
||||
file.reset(std::move(sdata_file));
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
if (const u32 id = idm::make<lv2_fs_object, lv2_file>(processed_path, std::move(file), mode, flags))
|
||||
return {.error = {}, .ppath = path, .file = std::move(file)};
|
||||
}
|
||||
|
||||
error_code sys_fs_open(ppu_thread& ppu, vm::cptr<char> path, s32 flags, vm::ptr<u32> fd, s32 mode, vm::cptr<void> arg, u64 size)
|
||||
{
|
||||
lv2_obj::sleep(ppu);
|
||||
|
||||
sys_fs.warning("sys_fs_open(path=%s, flags=%#o, fd=*0x%x, mode=%#o, arg=*0x%x, size=0x%llx)", path, flags, fd, mode, arg, size);
|
||||
|
||||
if (!path)
|
||||
return CELL_EFAULT;
|
||||
|
||||
auto [error, ppath, file] = lv2_file::open(path.get_ptr(), flags, mode, arg.get_ptr(), size);
|
||||
|
||||
if (error)
|
||||
{
|
||||
if (error == CELL_EEXIST)
|
||||
{
|
||||
return not_an_error(CELL_EEXIST);
|
||||
}
|
||||
|
||||
return {error, path};
|
||||
}
|
||||
|
||||
if (const u32 id = idm::make<lv2_fs_object, lv2_file>(ppath, std::move(file), mode, flags))
|
||||
{
|
||||
*fd = id;
|
||||
return CELL_OK;
|
||||
|
@ -4,6 +4,8 @@
|
||||
#include "Emu/Cell/ErrorCodes.h"
|
||||
#include "Utilities/File.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
// Open Flags
|
||||
enum : s32
|
||||
{
|
||||
@ -192,6 +194,16 @@ struct lv2_file final : lv2_fs_object
|
||||
{
|
||||
}
|
||||
|
||||
struct open_result_t
|
||||
{
|
||||
CellError error;
|
||||
std::string ppath;
|
||||
fs::file file;
|
||||
};
|
||||
|
||||
// Open a file with wrapped logic of sys_fs_open
|
||||
static open_result_t open(std::string_view path, s32 flags, s32 mode, const void* arg = {}, u64 size = 0);
|
||||
|
||||
// File reading with intermediate buffer
|
||||
static u64 op_read(const fs::file& file, vm::ptr<void> buf, u64 size);
|
||||
|
||||
|
@ -19,11 +19,16 @@ LOG_CHANNEL(sys_overlay);
|
||||
|
||||
static error_code overlay_load_module(vm::ptr<u32> ovlmid, const std::string& vpath, u64 flags, vm::ptr<u32> entry, fs::file src = {})
|
||||
{
|
||||
const std::string path = vfs::get(vpath);
|
||||
|
||||
if (!src)
|
||||
{
|
||||
src.open(path);
|
||||
auto [fs_error, ppath, lv2_file] = lv2_file::open(vpath, 0, 0);
|
||||
|
||||
if (fs_error)
|
||||
{
|
||||
return {fs_error, vpath};
|
||||
}
|
||||
|
||||
src = std::move(lv2_file);
|
||||
}
|
||||
|
||||
const ppu_exec_object obj = decrypt_self(std::move(src), g_fxo->get<loaded_npdrm_keys>()->devKlic.data());
|
||||
@ -33,7 +38,7 @@ static error_code overlay_load_module(vm::ptr<u32> ovlmid, const std::string& vp
|
||||
return {CELL_ENOEXEC, obj.operator elf_error()};
|
||||
}
|
||||
|
||||
const auto ovlm = ppu_load_overlay(obj, path);
|
||||
const auto ovlm = ppu_load_overlay(obj, vfs::get(vpath));
|
||||
|
||||
ppu_initialize(*ovlm);
|
||||
|
||||
@ -92,6 +97,12 @@ error_code sys_overlay_unload_module(u32 ovlmid)
|
||||
{
|
||||
sys_overlay.warning("sys_overlay_unload_module(ovlmid=0x%x)", ovlmid);
|
||||
|
||||
if (!g_ps3_process_info.ppc_seg)
|
||||
{
|
||||
// Process not permitted
|
||||
return CELL_ENOSYS;
|
||||
}
|
||||
|
||||
const auto _main = idm::withdraw<lv2_obj, lv2_overlay>(ovlmid);
|
||||
|
||||
if (!_main)
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include "Crypto/unself.h"
|
||||
#include "Loader/ELF.h"
|
||||
|
||||
#include "Emu/Cell/PPUModule.h"
|
||||
#include "Emu/Cell/ErrorCodes.h"
|
||||
#include "Crypto/unedat.h"
|
||||
#include "Utilities/StrUtil.h"
|
||||
@ -154,7 +155,14 @@ static error_code prx_load_module(const std::string& vpath, u64 flags, vm::ptr<s
|
||||
|
||||
if (!src)
|
||||
{
|
||||
src.open(path);
|
||||
auto [fs_error, ppath, lv2_file] = lv2_file::open(vpath, 0, 0);
|
||||
|
||||
if (fs_error)
|
||||
{
|
||||
return {fs_error, vpath};
|
||||
}
|
||||
|
||||
src = std::move(lv2_file);
|
||||
}
|
||||
|
||||
const ppu_prx_object obj = decrypt_self(std::move(src), g_fxo->get<loaded_npdrm_keys>()->devKlic.data());
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "sys_memory.h"
|
||||
#include "sys_mmapper.h"
|
||||
#include "sys_event.h"
|
||||
#include "sys_fs.h"
|
||||
|
||||
LOG_CHANNEL(sys_spu);
|
||||
|
||||
@ -217,12 +218,19 @@ error_code sys_spu_image_open(ppu_thread& ppu, vm::ptr<sys_spu_image> img, vm::c
|
||||
|
||||
sys_spu.warning("sys_spu_image_open(img=*0x%x, path=%s)", img, path);
|
||||
|
||||
const fs::file elf_file = decrypt_self(fs::file(vfs::get(path.get_ptr())), g_fxo->get<loaded_npdrm_keys>()->devKlic.data());
|
||||
auto [fs_error, ppath, file] = lv2_file::open(path.get_ptr(), 0, 0);
|
||||
|
||||
if (fs_error)
|
||||
{
|
||||
return {fs_error, path};
|
||||
}
|
||||
|
||||
const fs::file elf_file = decrypt_self(std::move(file), g_fxo->get<loaded_npdrm_keys>()->devKlic.data());
|
||||
|
||||
if (!elf_file)
|
||||
{
|
||||
sys_spu.error("sys_spu_image_open() error: failed to open %s!", path);
|
||||
return CELL_ENOENT;
|
||||
sys_spu.error("sys_spu_image_open(): file %s is illegal for SPU image!", path);
|
||||
return {CELL_ENOEXEC, path};
|
||||
}
|
||||
|
||||
img->load(elf_file);
|
||||
|
Loading…
x
Reference in New Issue
Block a user