mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-12 01:38:37 +12:00
_sys_spu_image_import implemented
vm:var<T[]> improved (begin/end) sys_spu_image_import rewritten
This commit is contained in:
parent
dfc970c926
commit
aa5dc5455e
6 changed files with 421 additions and 81 deletions
|
@ -20,20 +20,13 @@ logs::channel sys_spu("sys_spu");
|
|||
|
||||
void sys_spu_image::load(const fs::file& stream)
|
||||
{
|
||||
const spu_exec_object obj{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" HERE, obj.get_error());
|
||||
}
|
||||
|
||||
this->type = SYS_SPU_IMAGE_TYPE_KERNEL;
|
||||
this->entry_point = obj.header.e_entry;
|
||||
this->segs.set(vm::alloc(65 * 4096, vm::main));
|
||||
this->nsegs = 0;
|
||||
|
||||
const u32 addr = this->segs.addr() + 4096;
|
||||
|
||||
for (const auto& shdr : obj.shdrs)
|
||||
{
|
||||
LOG_NOTICE(SPU, "** Section: sh_type=0x%x, addr=0x%llx, size=0x%llx, flags=0x%x", shdr.sh_type, shdr.sh_addr, shdr.sh_size, shdr.sh_flags);
|
||||
|
@ -43,37 +36,26 @@ void sys_spu_image::load(const fs::file& stream)
|
|||
{
|
||||
LOG_NOTICE(SPU, "** Segment: p_type=0x%x, p_vaddr=0x%llx, p_filesz=0x%llx, p_memsz=0x%llx, flags=0x%x", prog.p_type, prog.p_vaddr, prog.p_filesz, prog.p_memsz, prog.p_flags);
|
||||
|
||||
if (prog.p_type == SYS_SPU_SEGMENT_TYPE_COPY)
|
||||
{
|
||||
auto& seg = segs[nsegs++];
|
||||
seg.type = prog.p_type;
|
||||
seg.ls = prog.p_vaddr;
|
||||
seg.addr = addr + prog.p_vaddr;
|
||||
seg.size = std::min(prog.p_filesz, prog.p_memsz);
|
||||
std::memcpy(vm::base(seg.addr), prog.bin.data(), seg.size);
|
||||
|
||||
if (prog.p_memsz > prog.p_filesz)
|
||||
{
|
||||
auto& zero = segs[nsegs++];
|
||||
zero.type = SYS_SPU_SEGMENT_TYPE_FILL;
|
||||
zero.ls = prog.p_vaddr + prog.p_filesz;
|
||||
zero.addr = 0;
|
||||
zero.size = prog.p_memsz - seg.size;
|
||||
}
|
||||
}
|
||||
else if (prog.p_type == SYS_SPU_SEGMENT_TYPE_INFO)
|
||||
{
|
||||
auto& seg = segs[nsegs++];
|
||||
seg.type = SYS_SPU_SEGMENT_TYPE_INFO;
|
||||
seg.ls = prog.p_vaddr;
|
||||
seg.addr = 0;
|
||||
seg.size = prog.p_filesz;
|
||||
}
|
||||
else
|
||||
if (prog.p_type != SYS_SPU_SEGMENT_TYPE_COPY && prog.p_type != SYS_SPU_SEGMENT_TYPE_INFO)
|
||||
{
|
||||
LOG_ERROR(SPU, "Unknown program type (0x%x)", prog.p_type);
|
||||
}
|
||||
}
|
||||
|
||||
type = SYS_SPU_IMAGE_TYPE_KERNEL;
|
||||
entry_point = obj.header.e_entry;
|
||||
nsegs = sys_spu_image::get_nsegs(obj.progs);
|
||||
segs = vm::cast(vm::alloc(nsegs * sizeof(sys_spu_segment) + ::size32(stream), vm::main));
|
||||
|
||||
const u32 src = segs.addr() + nsegs * sizeof(sys_spu_segment);
|
||||
|
||||
stream.seek(0);
|
||||
stream.read(vm::base(src), stream.size());
|
||||
|
||||
if (nsegs < 0 || sys_spu_image::fill(segs, obj.progs, src) != nsegs)
|
||||
{
|
||||
fmt::throw_exception("Failed to load SPU segments (%d)" HERE, nsegs);
|
||||
}
|
||||
}
|
||||
|
||||
void sys_spu_image::free()
|
||||
|
@ -100,13 +82,13 @@ void sys_spu_image::deploy(u32 loc)
|
|||
|
||||
fmt::append(dump, "\n\t[%d] t=0x%x, ls=0x%x, size=0x%x, addr=0x%x", i, seg.type, seg.ls, seg.size, seg.addr);
|
||||
|
||||
// Hash big-endian values
|
||||
sha1_update(&sha, (uchar*)&seg.type, sizeof(seg.type));
|
||||
sha1_update(&sha, (uchar*)&seg.size, sizeof(seg.size));
|
||||
|
||||
// Hash big-endian values
|
||||
if (seg.type == SYS_SPU_SEGMENT_TYPE_COPY)
|
||||
{
|
||||
std::memcpy(vm::base(loc + seg.ls), vm::base(seg.addr), seg.size);
|
||||
sha1_update(&sha, (uchar*)&seg.size, sizeof(seg.size));
|
||||
sha1_update(&sha, (uchar*)&seg.ls, sizeof(seg.ls));
|
||||
sha1_update(&sha, vm::g_base_addr + seg.addr, seg.size);
|
||||
}
|
||||
|
@ -118,9 +100,15 @@ void sys_spu_image::deploy(u32 loc)
|
|||
}
|
||||
|
||||
std::fill_n(vm::_ptr<u32>(loc + seg.ls), seg.size / 4, seg.addr);
|
||||
sha1_update(&sha, (uchar*)&seg.size, sizeof(seg.size));
|
||||
sha1_update(&sha, (uchar*)&seg.ls, sizeof(seg.ls));
|
||||
sha1_update(&sha, (uchar*)&seg.addr, sizeof(seg.addr));
|
||||
}
|
||||
else if (seg.type == SYS_SPU_SEGMENT_TYPE_INFO)
|
||||
{
|
||||
const be_t<u32> size = seg.size + 0x14; // Workaround
|
||||
sha1_update(&sha, (uchar*)&size, sizeof(size));
|
||||
}
|
||||
}
|
||||
|
||||
sha1_finish(&sha, sha1_hash);
|
||||
|
@ -182,18 +170,20 @@ error_code sys_spu_image_open(vm::ptr<sys_spu_image> img, vm::cptr<char> path)
|
|||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code _sys_spu_image_import(vm::ptr<sys_spu_image> img, u32 src, u32 arg3, u32 arg4)
|
||||
error_code _sys_spu_image_import(vm::ptr<sys_spu_image> img, u32 src, u32 size, u32 arg4)
|
||||
{
|
||||
sys_spu.todo("_sys_spu_image_import(img=*0x%x, src=*0x%x, arg3=0x%x, arg4=0x%x)", img, src, arg3, arg4);
|
||||
sys_spu.warning("_sys_spu_image_import(img=*0x%x, src=*0x%x, size=0x%x, arg4=0x%x)", img, src, size, arg4);
|
||||
|
||||
fmt::throw_exception("Unimplemented syscall: _sys_spu_image_import");
|
||||
img->load(fs::file{vm::base(src), size});
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code _sys_spu_image_close(vm::ptr<sys_spu_image> img)
|
||||
{
|
||||
sys_spu.todo("_sys_spu_image_close(img=*0x%x)", img);
|
||||
sys_spu.warning("_sys_spu_image_close(img=*0x%x)", img);
|
||||
|
||||
fmt::throw_exception("Unimplemented syscall: _sys_spu_image_close");
|
||||
vm::dealloc(img->segs.addr(), vm::main);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code _sys_raw_spu_image_load(vm::ptr<sys_spu_image> img, u32 ptr, u32 arg3)
|
||||
|
|
|
@ -112,6 +112,74 @@ struct sys_spu_image
|
|||
vm::ps3::bptr<sys_spu_segment> segs;
|
||||
be_t<s32> nsegs;
|
||||
|
||||
template <typename Phdrs>
|
||||
static s32 get_nsegs(const Phdrs& phdrs)
|
||||
{
|
||||
s32 num_segs = 0;
|
||||
|
||||
for (const auto& phdr : phdrs)
|
||||
{
|
||||
if (phdr.p_type != 1 && phdr.p_type != 4)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (phdr.p_type == 1 && phdr.p_filesz != phdr.p_memsz && phdr.p_filesz)
|
||||
{
|
||||
num_segs += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
num_segs += 1;
|
||||
}
|
||||
}
|
||||
|
||||
return num_segs;
|
||||
}
|
||||
|
||||
template <typename Phdrs>
|
||||
static s32 fill(vm::ps3::ptr<sys_spu_segment> segs, const Phdrs& phdrs, u32 src)
|
||||
{
|
||||
s32 num_segs = 0;
|
||||
|
||||
for (const auto& phdr : phdrs)
|
||||
{
|
||||
if (phdr.p_type == 1)
|
||||
{
|
||||
if (phdr.p_filesz)
|
||||
{
|
||||
auto* seg = &segs[num_segs++];
|
||||
seg->type = SYS_SPU_SEGMENT_TYPE_COPY;
|
||||
seg->ls = static_cast<u32>(phdr.p_vaddr);
|
||||
seg->size = static_cast<u32>(phdr.p_filesz);
|
||||
seg->addr = static_cast<u32>(phdr.p_offset + src);
|
||||
}
|
||||
|
||||
if (phdr.p_memsz > phdr.p_filesz)
|
||||
{
|
||||
auto* seg = &segs[num_segs++];
|
||||
seg->type = SYS_SPU_SEGMENT_TYPE_FILL;
|
||||
seg->ls = static_cast<u32>(phdr.p_vaddr + phdr.p_filesz);
|
||||
seg->size = static_cast<u32>(phdr.p_memsz - phdr.p_filesz);
|
||||
seg->addr = 0;
|
||||
}
|
||||
}
|
||||
else if (phdr.p_type == 4)
|
||||
{
|
||||
auto* seg = &segs[num_segs++];
|
||||
seg->type = SYS_SPU_SEGMENT_TYPE_INFO;
|
||||
seg->size = 0x20;
|
||||
seg->addr = static_cast<u32>(phdr.p_offset + 0x14 + src);
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return num_segs;
|
||||
}
|
||||
|
||||
void load(const fs::file& stream);
|
||||
void free();
|
||||
void deploy(u32 loc);
|
||||
|
@ -205,7 +273,7 @@ class ppu_thread;
|
|||
error_code sys_spu_initialize(u32 max_usable_spu, u32 max_raw_spu);
|
||||
error_code _sys_spu_image_get_information(vm::ps3::ptr<sys_spu_image> img, u32 ptr1, u32 ptr2);
|
||||
error_code sys_spu_image_open(vm::ps3::ptr<sys_spu_image> img, vm::ps3::cptr<char> path);
|
||||
error_code _sys_spu_image_import(vm::ps3::ptr<sys_spu_image> img, u32 src, u32 arg3, u32 arg4);
|
||||
error_code _sys_spu_image_import(vm::ps3::ptr<sys_spu_image> img, u32 src, u32 size, u32 arg4);
|
||||
error_code _sys_spu_image_close(vm::ps3::ptr<sys_spu_image> img);
|
||||
error_code _sys_raw_spu_image_load(vm::ps3::ptr<sys_spu_image> img, u32 ptr, u32 arg3);
|
||||
error_code sys_spu_thread_initialize(vm::ps3::ptr<u32> thread, u32 group, u32 spu_num, vm::ps3::ptr<sys_spu_image>, vm::ps3::ptr<sys_spu_thread_attribute>, vm::ps3::ptr<sys_spu_thread_argument>);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue