Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement lv2_file::open() #7708

Merged
merged 1 commit into from Mar 6, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
74 changes: 49 additions & 25 deletions rpcs3/Emu/Cell/lv2/sys_fs.cpp
Expand Up @@ -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))
Expand Down Expand Up @@ -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);

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)
{
Expand Down Expand Up @@ -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)
Expand All @@ -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;
Expand Down Expand Up @@ -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};
Expand All @@ -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;
Expand All @@ -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;
Expand All @@ -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;
Expand Down
12 changes: 12 additions & 0 deletions rpcs3/Emu/Cell/lv2/sys_fs.h
Expand Up @@ -4,6 +4,8 @@
#include "Emu/Cell/ErrorCodes.h"
#include "Utilities/File.h"

#include <string>

// Open Flags
enum : s32
{
Expand Down Expand Up @@ -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);

Expand Down
19 changes: 15 additions & 4 deletions rpcs3/Emu/Cell/lv2/sys_overlay.cpp
Expand Up @@ -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());
Expand All @@ -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);

Expand Down Expand Up @@ -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)
Expand Down
10 changes: 9 additions & 1 deletion rpcs3/Emu/Cell/lv2/sys_prx.cpp
Expand Up @@ -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"
Expand Down Expand Up @@ -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());
Expand Down
14 changes: 11 additions & 3 deletions rpcs3/Emu/Cell/lv2/sys_spu.cpp
Expand Up @@ -18,6 +18,7 @@
#include "sys_memory.h"
#include "sys_mmapper.h"
#include "sys_event.h"
#include "sys_fs.h"

LOG_CHANNEL(sys_spu);

Expand Down Expand Up @@ -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);
Expand Down