Implement sys_spu_image_open_by_fd

This commit is contained in:
elad335 2025-04-17 19:10:13 +03:00
parent c2bfcb0bde
commit fe348344b3
4 changed files with 72 additions and 25 deletions

View file

@ -1343,10 +1343,13 @@ static fs::file CheckDebugSelf(const fs::file& s)
fs::file e = fs::make_stream<std::vector<u8>>();
// Copy the data.
char buf[2048];
while (const u64 size = s.read(buf, 2048))
std::vector<u8> buf(std::min<usz>(s.size(), 4096));
usz read_pos = 0;
while (const u64 size = s.read_at(read_pos, buf.data(), buf.size()))
{
e.write(buf, size);
e.write(buf.data(), size);
read_pos += size;
}
return e;
@ -1412,6 +1415,23 @@ fs::file decrypt_self(const fs::file& elf_or_self, const u8* klic_key, SelfAddit
// Make a new ELF file from this SELF.
return self_dec.MakeElf(isElf32);
}
else if (Emu.GetBoot().ends_with(".elf") || Emu.GetBoot().ends_with(".ELF"))
{
// Write the file back if the main executable is not signed
fs::file e = fs::make_stream<std::vector<u8>>();
// Copy the data.
std::vector<u8> buf(std::min<usz>(elf_or_self.size(), 4096));
usz read_pos = 0;
while (const u64 size = elf_or_self.read_at(read_pos, buf.data(), buf.size()))
{
e.write(buf.data(), size);
read_pos += size;
}
return e;
}
return {};
}

View file

@ -373,7 +373,7 @@ const std::array<std::pair<ppu_intrp_func_t, std::string_view>, 1024> g_ppu_sysc
uns_func, uns_func, uns_func, uns_func, uns_func, //255-259 UNS
NULL_FUNC(sys_spu_image_open_by_fd), //260 (0x104)
BIND_SYSC(sys_spu_image_open_by_fd), //260 (0x104)
uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, //261-269 UNS
uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, //270-279 UNS

View file

@ -66,13 +66,14 @@ void fmt_class_string<spu_stop_syscall>::format(std::string& out, u64 arg)
});
}
void sys_spu_image::load(const fs::file& stream)
bool sys_spu_image::load(const fs::file& stream)
{
const spu_exec_object obj{stream, 0, elf_opt::no_sections + elf_opt::no_data};
if (obj != elf_error::ok)
{
fmt::throw_exception("Failed to load SPU image: %s", obj.get_error());
sys_spu.error("Failed to load SPU image: %s", obj.get_error());
return false;
}
for (const auto& shdr : obj.shdrs)
@ -94,7 +95,7 @@ void sys_spu_image::load(const fs::file& stream)
const s32 nsegs = sys_spu_image::get_nsegs(obj.progs);
const u32 mem_size = nsegs * sizeof(sys_spu_segment) + ::size32(stream);
const vm::ptr<sys_spu_segment> segs = vm::cast(vm::reserve_map(vm::user64km 0, 0x10000000)->alloc(mem_size));
const vm::ptr<sys_spu_segment> segs = vm::cast(vm::reserve_map(vm::user64k, 0, 0x10000000)->alloc(mem_size));
//const u32 entry = obj.header.e_entry;
@ -116,6 +117,7 @@ void sys_spu_image::load(const fs::file& stream)
this->segs = vm::null;
vm::page_protect(segs.addr(), utils::align(mem_size, 4096), 0, 0, vm::page_writable);
return true;
}
void sys_spu_image::free() const
@ -517,28 +519,52 @@ error_code sys_spu_image_open(ppu_thread& ppu, vm::ptr<sys_spu_image> img, vm::c
u128 klic = g_fxo->get<loaded_npdrm_keys>().last_key();
fs::file elf_file;
const fs::file elf_file = decrypt_self(file, reinterpret_cast<const u8*>(&klic));
// Check for SELF header
u32 file_type = umax;
file.read_at(0, &file_type, sizeof(file_type));
if (file_type == "SCE\0"_u32)
{
elf_file = decrypt_self(file, reinterpret_cast<u8*>(&klic));
}
else
{
elf_file = std::move(file);
}
if (!elf_file)
if (!elf_file || !img->load(elf_file))
{
sys_spu.error("sys_spu_image_open(): file %s is illegal for SPU image!", path);
return {CELL_ENOEXEC, path};
}
img->load(elf_file);
return CELL_OK;
}
error_code sys_spu_image_open_by_fd(ppu_thread& ppu, vm::ptr<sys_spu_image> img, s32 fd, s64 offset)
{
ppu.state += cpu_flag::wait;
sys_spu.warning("sys_spu_image_open_by_fd(img=*0x%x, fd=%d, offset=0x%x)", img, fd, offset);
const auto file = idm::get_unlocked<lv2_fs_object, lv2_file>(fd);
if (!file)
{
return CELL_EBADF;
}
if (offset < 0)
{
return CELL_ENOEXEC;
}
std::lock_guard lock(file->mp->mutex);
if (!file->file)
{
return CELL_EBADF;
}
u128 klic = g_fxo->get<loaded_npdrm_keys>().last_key();
const fs::file elf_file = decrypt_self(lv2_file::make_view(file, offset), reinterpret_cast<const u8*>(&klic));
if (!img->load(elf_file))
{
sys_spu.error("sys_spu_image_open(): file %s is illegal for SPU image!", file->name.data());
return {CELL_ENOEXEC, file->name.data()};
}
return CELL_OK;
}
@ -570,7 +596,7 @@ error_code _sys_spu_image_close(ppu_thread& ppu, vm::ptr<sys_spu_image> img)
return CELL_ESRCH;
}
ensure(vm::dealloc(handle->segs.addr(), vm::main));
ensure(vm::dealloc(handle->segs.addr(), vm::user64k));
return CELL_OK;
}

View file

@ -225,7 +225,7 @@ struct sys_spu_image
return num_segs;
}
void load(const fs::file& stream);
bool load(const fs::file& stream);
void free() const;
static void deploy(u8* loc, std::span<const sys_spu_segment> segs, bool is_verbose = true);
};
@ -354,6 +354,7 @@ class ppu_thread;
error_code sys_spu_initialize(ppu_thread&, u32 max_usable_spu, u32 max_raw_spu);
error_code _sys_spu_image_get_information(ppu_thread&, vm::ptr<sys_spu_image> img, vm::ptr<u32> entry_point, vm::ptr<s32> nsegs);
error_code sys_spu_image_open(ppu_thread&, vm::ptr<sys_spu_image> img, vm::cptr<char> path);
error_code sys_spu_image_open_by_fd(ppu_thread&, vm::ptr<sys_spu_image> img, s32 fd, s64 offset);
error_code _sys_spu_image_import(ppu_thread&, vm::ptr<sys_spu_image> img, u32 src, u32 size, u32 arg4);
error_code _sys_spu_image_close(ppu_thread&, vm::ptr<sys_spu_image> img);
error_code _sys_spu_image_get_segments(ppu_thread&, vm::ptr<sys_spu_image> img, vm::ptr<sys_spu_segment> segments, s32 nseg);