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:
Eladash 2020-03-06 14:47:24 +02:00 committed by Ivan
parent acd50eefaf
commit 1669e95870
5 changed files with 96 additions and 33 deletions

View file

@ -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_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}; 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; FsMselfHeader mself_header;
if (!mself_file.read<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; 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) const auto mp = lv2_fs_object::get_mp(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);
if (vpath.find_first_not_of('/') == umax) 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) 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) 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) 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; 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) 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) switch (auto error = fs::g_tls_error)
{ {
case fs::error::noent: return {CELL_ENOENT, path}; 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}; 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}; return {CELL_ENOTMSELF, path};
} }
const auto casted_arg = vm::static_ptr_cast<const u64>(arg);
if (size == 8) if (size == 8)
{ {
// check for sdata // 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 // check if the file has the NPD header, or else assume its not encrypted
u32 magic; 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)); file.reset(std::move(sdata_file));
} }
break;
} }
// edata // edata
else if (*casted_arg == 0x2u) case 0x2:
{ {
// check if the file has the NPD header, or else assume its not encrypted // check if the file has the NPD header, or else assume its not encrypted
u32 magic; 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)); 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; *fd = id;
return CELL_OK; return CELL_OK;

View file

@ -4,6 +4,8 @@
#include "Emu/Cell/ErrorCodes.h" #include "Emu/Cell/ErrorCodes.h"
#include "Utilities/File.h" #include "Utilities/File.h"
#include <string>
// Open Flags // Open Flags
enum : s32 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 // File reading with intermediate buffer
static u64 op_read(const fs::file& file, vm::ptr<void> buf, u64 size); static u64 op_read(const fs::file& file, vm::ptr<void> buf, u64 size);

View file

@ -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 = {}) 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) 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()); 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()}; 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); 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); 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); const auto _main = idm::withdraw<lv2_obj, lv2_overlay>(ovlmid);
if (!_main) if (!_main)

View file

@ -6,6 +6,7 @@
#include "Crypto/unself.h" #include "Crypto/unself.h"
#include "Loader/ELF.h" #include "Loader/ELF.h"
#include "Emu/Cell/PPUModule.h"
#include "Emu/Cell/ErrorCodes.h" #include "Emu/Cell/ErrorCodes.h"
#include "Crypto/unedat.h" #include "Crypto/unedat.h"
#include "Utilities/StrUtil.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) 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()); const ppu_prx_object obj = decrypt_self(std::move(src), g_fxo->get<loaded_npdrm_keys>()->devKlic.data());

View file

@ -18,6 +18,7 @@
#include "sys_memory.h" #include "sys_memory.h"
#include "sys_mmapper.h" #include "sys_mmapper.h"
#include "sys_event.h" #include "sys_event.h"
#include "sys_fs.h"
LOG_CHANNEL(sys_spu); 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); 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) if (!elf_file)
{ {
sys_spu.error("sys_spu_image_open() error: failed to open %s!", path); sys_spu.error("sys_spu_image_open(): file %s is illegal for SPU image!", path);
return CELL_ENOENT; return {CELL_ENOEXEC, path};
} }
img->load(elf_file); img->load(elf_file);