kip.cpp 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. // Copyright 2019 yuzu emulator team
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #include <cstring>
  5. #include "core/file_sys/kernel_executable.h"
  6. #include "core/file_sys/program_metadata.h"
  7. #include "core/gdbstub/gdbstub.h"
  8. #include "core/hle/kernel/code_set.h"
  9. #include "core/hle/kernel/process.h"
  10. #include "core/loader/kip.h"
  11. namespace Loader {
  12. namespace {
  13. constexpr u32 PageAlignSize(u32 size) {
  14. return (size + Memory::PAGE_MASK) & ~Memory::PAGE_MASK;
  15. }
  16. } // Anonymous namespace
  17. AppLoader_KIP::AppLoader_KIP(FileSys::VirtualFile file_)
  18. : AppLoader(std::move(file_)), kip(std::make_unique<FileSys::KIP>(file)) {}
  19. AppLoader_KIP::~AppLoader_KIP() = default;
  20. FileType AppLoader_KIP::IdentifyType(const FileSys::VirtualFile& file) {
  21. u32_le magic{};
  22. if (file->GetSize() < sizeof(u32) || file->ReadObject(&magic) != sizeof(u32)) {
  23. return FileType::Error;
  24. }
  25. if (magic == Common::MakeMagic('K', 'I', 'P', '1')) {
  26. return FileType::KIP;
  27. }
  28. return FileType::Error;
  29. }
  30. FileType AppLoader_KIP::GetFileType() const {
  31. return (kip != nullptr && kip->GetStatus() == ResultStatus::Success) ? FileType::KIP
  32. : FileType::Error;
  33. }
  34. AppLoader::LoadResult AppLoader_KIP::Load(Kernel::Process& process) {
  35. if (is_loaded) {
  36. return {ResultStatus::ErrorAlreadyLoaded, {}};
  37. }
  38. if (kip == nullptr) {
  39. return {ResultStatus::ErrorNullFile, {}};
  40. }
  41. if (kip->GetStatus() != ResultStatus::Success) {
  42. return {kip->GetStatus(), {}};
  43. }
  44. const auto get_kip_address_space_type = [](const auto& kip) {
  45. return kip.Is64Bit()
  46. ? (kip.Is39BitAddressSpace() ? FileSys::ProgramAddressSpaceType::Is39Bit
  47. : FileSys::ProgramAddressSpaceType::Is36Bit)
  48. : FileSys::ProgramAddressSpaceType::Is32Bit;
  49. };
  50. const auto address_space = get_kip_address_space_type(*kip);
  51. FileSys::ProgramMetadata metadata;
  52. metadata.LoadManual(kip->Is64Bit(), address_space, kip->GetMainThreadPriority(),
  53. kip->GetMainThreadCpuCore(), kip->GetMainThreadStackSize(),
  54. kip->GetTitleID(), 0xFFFFFFFFFFFFFFFF, kip->GetKernelCapabilities());
  55. const VAddr base_address = process.VMManager().GetCodeRegionBaseAddress();
  56. Kernel::CodeSet codeset;
  57. Kernel::PhysicalMemory program_image;
  58. const auto load_segment = [&program_image](Kernel::CodeSet::Segment& segment,
  59. const std::vector<u8>& data, u32 offset) {
  60. segment.addr = offset;
  61. segment.offset = offset;
  62. segment.size = PageAlignSize(static_cast<u32>(data.size()));
  63. program_image.resize(offset + data.size());
  64. std::memcpy(program_image.data() + offset, data.data(), data.size());
  65. };
  66. load_segment(codeset.CodeSegment(), kip->GetTextSection(), kip->GetTextOffset());
  67. load_segment(codeset.RODataSegment(), kip->GetRODataSection(), kip->GetRODataOffset());
  68. load_segment(codeset.DataSegment(), kip->GetDataSection(), kip->GetDataOffset());
  69. program_image.resize(PageAlignSize(kip->GetBSSOffset()) + kip->GetBSSSize());
  70. codeset.DataSegment().size += kip->GetBSSSize();
  71. GDBStub::RegisterModule(kip->GetName(), base_address, base_address + program_image.size());
  72. codeset.memory = std::move(program_image);
  73. process.LoadModule(std::move(codeset), base_address);
  74. LOG_DEBUG(Loader, "loaded module {} @ 0x{:X}", kip->GetName(), base_address);
  75. is_loaded = true;
  76. return {ResultStatus::Success,
  77. LoadParameters{kip->GetMainThreadPriority(), kip->GetMainThreadStackSize()}};
  78. }
  79. } // namespace Loader