From ab185247b711a4864d3f402f134ce59504a8339e Mon Sep 17 00:00:00 2001 From: Eladash Date: Fri, 6 Mar 2020 14:47:24 +0200 Subject: [PATCH] Implement lv2_file::open() Return accurate error codes in prx_load_module, sys_spu_image_open and overlay_load_module. --- rpcs3/Emu/Cell/lv2/sys_fs.cpp | 74 ++++++++++++++++++++---------- rpcs3/Emu/Cell/lv2/sys_fs.h | 12 +++++ rpcs3/Emu/Cell/lv2/sys_overlay.cpp | 19 ++++++-- rpcs3/Emu/Cell/lv2/sys_prx.cpp | 10 +++- rpcs3/Emu/Cell/lv2/sys_spu.cpp | 14 ++++-- 5 files changed, 96 insertions(+), 33 deletions(-) diff --git a/rpcs3/Emu/Cell/lv2/sys_fs.cpp b/rpcs3/Emu/Cell/lv2/sys_fs.cpp index a78780aee715..f8ab0a9f9600 100644 --- a/rpcs3/Emu/Cell/lv2/sys_fs.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_fs.cpp @@ -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(mself_header)) @@ -240,23 +240,17 @@ error_code sys_fs_test(ppu_thread& ppu, u32 arg1, u32 arg2, vm::ptr arg3, u return CELL_OK; } -error_code sys_fs_open(ppu_thread& ppu, vm::cptr path, s32 flags, vm::ptr fd, s32 mode, vm::cptr 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); - - 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; - - if (!path[0]) - return CELL_ENOENT; + if (vpath.empty()) + { + 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); + std::string path; + const std::string local_path = vfs::get(vpath, nullptr, &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 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 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 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 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(arg); - if (size == 8) { // check for sdata - if (*casted_arg == 0x18000000010ull) + switch (*static_cast*>(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 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 path, s32 flags, vm::ptr< file.reset(std::move(sdata_file)); } + + break; + } + default: break; } } - if (const u32 id = idm::make(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 path, s32 flags, vm::ptr fd, s32 mode, vm::cptr 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(ppath, std::move(file), mode, flags)) { *fd = id; return CELL_OK; diff --git a/rpcs3/Emu/Cell/lv2/sys_fs.h b/rpcs3/Emu/Cell/lv2/sys_fs.h index bc81c4b85a97..d62cd39edaf6 100644 --- a/rpcs3/Emu/Cell/lv2/sys_fs.h +++ b/rpcs3/Emu/Cell/lv2/sys_fs.h @@ -4,6 +4,8 @@ #include "Emu/Cell/ErrorCodes.h" #include "Utilities/File.h" +#include + // 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 buf, u64 size); diff --git a/rpcs3/Emu/Cell/lv2/sys_overlay.cpp b/rpcs3/Emu/Cell/lv2/sys_overlay.cpp index c23eb415971d..7665c3abeba8 100644 --- a/rpcs3/Emu/Cell/lv2/sys_overlay.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_overlay.cpp @@ -19,11 +19,16 @@ LOG_CHANNEL(sys_overlay); static error_code overlay_load_module(vm::ptr ovlmid, const std::string& vpath, u64 flags, vm::ptr 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()->devKlic.data()); @@ -33,7 +38,7 @@ static error_code overlay_load_module(vm::ptr 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(ovlmid); if (!_main) diff --git a/rpcs3/Emu/Cell/lv2/sys_prx.cpp b/rpcs3/Emu/Cell/lv2/sys_prx.cpp index 39ccfdee37f7..2ea5ee41397c 100644 --- a/rpcs3/Emu/Cell/lv2/sys_prx.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_prx.cpp @@ -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::ptrget()->devKlic.data()); diff --git a/rpcs3/Emu/Cell/lv2/sys_spu.cpp b/rpcs3/Emu/Cell/lv2/sys_spu.cpp index fde611d23f9e..4713113c2361 100644 --- a/rpcs3/Emu/Cell/lv2/sys_spu.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_spu.cpp @@ -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 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()->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()->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);