Compare commits

..

1 Commits

Author SHA1 Message Date
lat9nq
bfb7cbc292 program_metadata: Unpack FileAccessHeader and FileAccessControl
Avoids a reference binding to a misaligned addresses. Unpacking one
requires unpacking the other, otherwise there'll be a misaligned address
on the leftover one.
2022-02-13 02:20:56 -05:00
8 changed files with 132 additions and 125 deletions

View File

@@ -209,7 +209,7 @@ macro(yuzu_find_packages)
endmacro()
if (NOT YUZU_USE_BUNDLED_BOOST)
find_package(Boost 1.73.0 COMPONENTS context)
find_package(Boost 1.73.0 CONFIG COMPONENTS context headers QUIET)
endif()
if (Boost_FOUND)
set(Boost_LIBRARIES Boost::boost)
@@ -222,7 +222,7 @@ if (Boost_FOUND)
list(APPEND Boost_LIBRARIES Boost::context)
endif()
elseif (${CMAKE_SYSTEM_NAME} STREQUAL "Linux" OR YUZU_USE_BUNDLED_BOOST)
message(WARNING "Boost not found or too old, falling back to externals")
message(STATUS "Boost 1.73.0 or newer not found, falling back to externals")
set(YUZU_USE_BUNDLED_BOOST ON CACHE BOOL "Download bundled Boost" FORCE)
# Use yuzu Boost binaries
@@ -522,7 +522,7 @@ if (UNIX AND NOT APPLE)
endif()
if (NOT YUZU_USE_BUNDLED_FFMPEG)
# Use system installed FFmpeg
find_package(FFmpeg 4.3 COMPONENTS ${FFmpeg_COMPONENTS})
find_package(FFmpeg 4.3 QUIET COMPONENTS ${FFmpeg_COMPONENTS})
if (FFmpeg_FOUND)
# Overwrite aggregate defines from FFmpeg module to avoid over-linking libraries.

View File

@@ -15,9 +15,7 @@ constexpr ResultCode ERR_INVALID_PARAMETERS{ErrorModule::Audio, 41};
constexpr ResultCode ERR_SPLITTER_SORT_FAILED{ErrorModule::Audio, 43};
} // namespace Audren
constexpr u8 BASE_REVISION = '0';
constexpr u32_le CURRENT_PROCESS_REVISION =
Common::MakeMagic('R', 'E', 'V', static_cast<u8>(BASE_REVISION + 0xA));
constexpr u32_le CURRENT_PROCESS_REVISION = Common::MakeMagic('R', 'E', 'V', '9');
constexpr std::size_t MAX_MIX_BUFFERS = 24;
constexpr std::size_t MAX_BIQUAD_FILTERS = 2;
constexpr std::size_t MAX_CHANNEL_COUNT = 6;

View File

@@ -16,10 +16,6 @@ std::u8string BufferToU8String(std::span<const u8> buffer) {
return std::u8string{buffer.begin(), std::ranges::find(buffer, u8{0})};
}
std::u8string_view BufferToU8StringView(std::span<const u8> buffer) {
return std::u8string_view{reinterpret_cast<const char8_t*>(buffer.data())};
}
std::string ToUTF8String(std::u8string_view u8_string) {
return std::string{u8_string.begin(), u8_string.end()};
}
@@ -28,10 +24,6 @@ std::string BufferToUTF8String(std::span<const u8> buffer) {
return std::string{buffer.begin(), std::ranges::find(buffer, u8{0})};
}
std::string_view BufferToUTF8StringView(std::span<const u8> buffer) {
return std::string_view{reinterpret_cast<const char*>(buffer.data())};
}
std::string PathToUTF8String(const std::filesystem::path& path) {
return ToUTF8String(path.u8string());
}

View File

@@ -37,15 +37,6 @@ concept IsChar = std::same_as<T, char>;
*/
[[nodiscard]] std::u8string BufferToU8String(std::span<const u8> buffer);
/**
* Same as BufferToU8String, but returns a string view of the buffer.
*
* @param buffer Buffer of bytes
*
* @returns UTF-8 encoded std::u8string_view.
*/
[[nodiscard]] std::u8string_view BufferToU8StringView(std::span<const u8> buffer);
/**
* Converts a std::u8string or std::u8string_view to a UTF-8 encoded std::string.
*
@@ -66,15 +57,6 @@ concept IsChar = std::same_as<T, char>;
*/
[[nodiscard]] std::string BufferToUTF8String(std::span<const u8> buffer);
/**
* Same as BufferToUTF8String, but returns a string view of the buffer.
*
* @param buffer Buffer of bytes
*
* @returns UTF-8 encoded std::string_view.
*/
[[nodiscard]] std::string_view BufferToUTF8StringView(std::span<const u8> buffer);
/**
* Converts a filesystem path to a UTF-8 encoded std::string.
*

View File

@@ -34,11 +34,55 @@ Loader::ResultStatus ProgramMetadata::Load(VirtualFile file) {
return Loader::ResultStatus::ErrorBadACIHeader;
}
if (sizeof(FileAccessControl) != file->ReadObject(&acid_file_access, acid_header.fac_offset)) {
// Load acid_file_access per-component instead of the entire struct, since this struct does not
// reflect the layout of the real data.
std::size_t current_offset = acid_header.fac_offset;
if (sizeof(FileAccessControl::version) != file->ReadBytes(&acid_file_access.version,
sizeof(FileAccessControl::version),
current_offset)) {
return Loader::ResultStatus::ErrorBadFileAccessControl;
}
if (sizeof(FileAccessControl::permissions) !=
file->ReadBytes(&acid_file_access.permissions, sizeof(FileAccessControl::permissions),
current_offset += sizeof(FileAccessControl::version) + 3)) {
return Loader::ResultStatus::ErrorBadFileAccessControl;
}
if (sizeof(FileAccessControl::unknown) !=
file->ReadBytes(&acid_file_access.unknown, sizeof(FileAccessControl::unknown),
current_offset + sizeof(FileAccessControl::permissions))) {
return Loader::ResultStatus::ErrorBadFileAccessControl;
}
if (sizeof(FileAccessHeader) != file->ReadObject(&aci_file_access, aci_header.fah_offset)) {
// Load aci_file_access per-component instead of the entire struct, same as acid_file_access
current_offset = aci_header.fah_offset;
if (sizeof(FileAccessHeader::version) != file->ReadBytes(&aci_file_access.version,
sizeof(FileAccessHeader::version),
current_offset)) {
return Loader::ResultStatus::ErrorBadFileAccessHeader;
}
if (sizeof(FileAccessHeader::permissions) !=
file->ReadBytes(&aci_file_access.permissions, sizeof(FileAccessHeader::permissions),
current_offset += sizeof(FileAccessHeader::version) + 3)) {
return Loader::ResultStatus::ErrorBadFileAccessHeader;
}
if (sizeof(FileAccessHeader::unk_offset) !=
file->ReadBytes(&aci_file_access.unk_offset, sizeof(FileAccessHeader::unk_offset),
current_offset += sizeof(FileAccessHeader::permissions))) {
return Loader::ResultStatus::ErrorBadFileAccessHeader;
}
if (sizeof(FileAccessHeader::unk_size) !=
file->ReadBytes(&aci_file_access.unk_size, sizeof(FileAccessHeader::unk_size),
current_offset += sizeof(FileAccessHeader::unk_offset))) {
return Loader::ResultStatus::ErrorBadFileAccessHeader;
}
if (sizeof(FileAccessHeader::unk_offset_2) !=
file->ReadBytes(&aci_file_access.unk_offset_2, sizeof(FileAccessHeader::unk_offset_2),
current_offset += sizeof(FileAccessHeader::unk_size))) {
return Loader::ResultStatus::ErrorBadFileAccessHeader;
}
if (sizeof(FileAccessHeader::unk_size_2) !=
file->ReadBytes(&aci_file_access.unk_size_2, sizeof(FileAccessHeader::unk_size_2),
current_offset + sizeof(FileAccessHeader::unk_offset_2))) {
return Loader::ResultStatus::ErrorBadFileAccessHeader;
}
@@ -153,9 +197,7 @@ void ProgramMetadata::Print() const {
LOG_DEBUG(Service_FS, " > Is Retail: {}", acid_header.is_retail ? "YES" : "NO");
LOG_DEBUG(Service_FS, "Title ID Min: 0x{:016X}", acid_header.title_id_min);
LOG_DEBUG(Service_FS, "Title ID Max: 0x{:016X}", acid_header.title_id_max);
u64_le permissions_l; // local copy to fix alignment error
std::memcpy(&permissions_l, &acid_file_access.permissions, sizeof(permissions_l));
LOG_DEBUG(Service_FS, "Filesystem Access: 0x{:016X}\n", permissions_l);
LOG_DEBUG(Service_FS, "Filesystem Access: 0x{:016X}\n", acid_file_access.permissions);
// Begin ACI0 printing (actual perms, unsigned)
LOG_DEBUG(Service_FS, "Magic: {:.4}", aci_header.magic.data());

View File

@@ -143,20 +143,18 @@ private:
static_assert(sizeof(AciHeader) == 0x40, "ACI0 header structure size is wrong");
#pragma pack(push, 1)
// FileAccessControl and FileAccessHeader need loaded per-component: this layout does not
// reflect the real layout to avoid reference binding to misaligned addresses
struct FileAccessControl {
u8 version;
INSERT_PADDING_BYTES(3);
// 3 padding bytes
u64_le permissions;
std::array<u8, 0x20> unknown;
};
static_assert(sizeof(FileAccessControl) == 0x2C, "FS access control structure size is wrong");
struct FileAccessHeader {
u8 version;
INSERT_PADDING_BYTES(3);
// 3 padding bytes
u64_le permissions;
u32_le unk_offset;
u32_le unk_size;
@@ -164,10 +162,6 @@ private:
u32_le unk_size_2;
};
static_assert(sizeof(FileAccessHeader) == 0x1C, "FS access header structure size is wrong");
#pragma pack(pop)
Header npdm_header;
AciHeader aci_header;
AcidHeader acid_header;

View File

@@ -2559,9 +2559,9 @@ struct FunctionDef {
} // namespace
static const FunctionDef SVC_Table_32[] = {
{0x00, nullptr, "Unknown0"},
{0x00, nullptr, "Unknown"},
{0x01, SvcWrap32<SetHeapSize32>, "SetHeapSize32"},
{0x02, nullptr, "SetMemoryPermission32"},
{0x02, nullptr, "Unknown"},
{0x03, SvcWrap32<SetMemoryAttribute32>, "SetMemoryAttribute32"},
{0x04, SvcWrap32<MapMemory32>, "MapMemory32"},
{0x05, SvcWrap32<UnmapMemory32>, "UnmapMemory32"},
@@ -2591,97 +2591,97 @@ static const FunctionDef SVC_Table_32[] = {
{0x1d, SvcWrap32<SignalProcessWideKey32>, "SignalProcessWideKey32"},
{0x1e, SvcWrap32<GetSystemTick32>, "GetSystemTick32"},
{0x1f, SvcWrap32<ConnectToNamedPort32>, "ConnectToNamedPort32"},
{0x20, nullptr, "SendSyncRequestLight32"},
{0x20, nullptr, "Unknown"},
{0x21, SvcWrap32<SendSyncRequest32>, "SendSyncRequest32"},
{0x22, nullptr, "SendSyncRequestWithUserBuffer32"},
{0x23, nullptr, "SendAsyncRequestWithUserBuffer32"},
{0x23, nullptr, "Unknown"},
{0x24, SvcWrap32<GetProcessId32>, "GetProcessId32"},
{0x25, SvcWrap32<GetThreadId32>, "GetThreadId32"},
{0x26, SvcWrap32<Break32>, "Break32"},
{0x27, nullptr, "OutputDebugString32"},
{0x28, nullptr, "ReturnFromException32"},
{0x28, nullptr, "Unknown"},
{0x29, SvcWrap32<GetInfo32>, "GetInfo32"},
{0x2a, nullptr, "FlushEntireDataCache32"},
{0x2b, nullptr, "FlushDataCache32"},
{0x2a, nullptr, "Unknown"},
{0x2b, nullptr, "Unknown"},
{0x2c, SvcWrap32<MapPhysicalMemory32>, "MapPhysicalMemory32"},
{0x2d, SvcWrap32<UnmapPhysicalMemory32>, "UnmapPhysicalMemory32"},
{0x2e, nullptr, "GetDebugFutureThreadInfo32"},
{0x2f, nullptr, "GetLastThreadInfo32"},
{0x30, nullptr, "GetResourceLimitLimitValue32"},
{0x31, nullptr, "GetResourceLimitCurrentValue32"},
{0x2e, nullptr, "Unknown"},
{0x2f, nullptr, "Unknown"},
{0x30, nullptr, "Unknown"},
{0x31, nullptr, "Unknown"},
{0x32, SvcWrap32<SetThreadActivity32>, "SetThreadActivity32"},
{0x33, SvcWrap32<GetThreadContext32>, "GetThreadContext32"},
{0x34, SvcWrap32<WaitForAddress32>, "WaitForAddress32"},
{0x35, SvcWrap32<SignalToAddress32>, "SignalToAddress32"},
{0x36, SvcWrap32<SynchronizePreemptionState>, "SynchronizePreemptionState32"},
{0x37, nullptr, "GetResourceLimitPeakValue32"},
{0x38, nullptr, "Unknown38"},
{0x39, nullptr, "CreateIoPool32"},
{0x3a, nullptr, "CreateIoRegion32"},
{0x3b, nullptr, "Unknown3b"},
{0x3c, nullptr, "KernelDebug32"},
{0x3d, nullptr, "ChangeKernelTraceState32"},
{0x3e, nullptr, "Unknown3e"},
{0x3f, nullptr, "Unknown3f"},
{0x37, nullptr, "Unknown"},
{0x38, nullptr, "Unknown"},
{0x39, nullptr, "Unknown"},
{0x3a, nullptr, "Unknown"},
{0x3b, nullptr, "Unknown"},
{0x3c, nullptr, "Unknown"},
{0x3d, nullptr, "Unknown"},
{0x3e, nullptr, "Unknown"},
{0x3f, nullptr, "Unknown"},
{0x40, nullptr, "CreateSession32"},
{0x41, nullptr, "AcceptSession32"},
{0x42, nullptr, "ReplyAndReceiveLight32"},
{0x42, nullptr, "Unknown"},
{0x43, nullptr, "ReplyAndReceive32"},
{0x44, nullptr, "ReplyAndReceiveWithUserBuffer32"},
{0x44, nullptr, "Unknown"},
{0x45, SvcWrap32<CreateEvent32>, "CreateEvent32"},
{0x46, nullptr, "MapIoRegion32"},
{0x47, nullptr, "UnmapIoRegion32"},
{0x48, nullptr, "MapPhysicalMemoryUnsafe32"},
{0x49, nullptr, "UnmapPhysicalMemoryUnsafe32"},
{0x4a, nullptr, "SetUnsafeLimit32"},
{0x4b, nullptr, "CreateCodeMemory32"},
{0x4c, nullptr, "ControlCodeMemory32"},
{0x4d, nullptr, "SleepSystem32"},
{0x4e, nullptr, "ReadWriteRegister32"},
{0x4f, nullptr, "SetProcessActivity32"},
{0x50, nullptr, "CreateSharedMemory32"},
{0x51, nullptr, "MapTransferMemory32"},
{0x52, nullptr, "UnmapTransferMemory32"},
{0x53, nullptr, "CreateInterruptEvent32"},
{0x54, nullptr, "QueryPhysicalAddress32"},
{0x55, nullptr, "QueryIoMapping32"},
{0x56, nullptr, "CreateDeviceAddressSpace32"},
{0x57, nullptr, "AttachDeviceAddressSpace32"},
{0x58, nullptr, "DetachDeviceAddressSpace32"},
{0x59, nullptr, "MapDeviceAddressSpaceByForce32"},
{0x5a, nullptr, "MapDeviceAddressSpaceAligned32"},
{0x5b, nullptr, "MapDeviceAddressSpace32"},
{0x5c, nullptr, "UnmapDeviceAddressSpace32"},
{0x5d, nullptr, "InvalidateProcessDataCache32"},
{0x5e, nullptr, "StoreProcessDataCache32"},
{0x46, nullptr, "Unknown"},
{0x47, nullptr, "Unknown"},
{0x48, nullptr, "Unknown"},
{0x49, nullptr, "Unknown"},
{0x4a, nullptr, "Unknown"},
{0x4b, nullptr, "Unknown"},
{0x4c, nullptr, "Unknown"},
{0x4d, nullptr, "Unknown"},
{0x4e, nullptr, "Unknown"},
{0x4f, nullptr, "Unknown"},
{0x50, nullptr, "Unknown"},
{0x51, nullptr, "Unknown"},
{0x52, nullptr, "Unknown"},
{0x53, nullptr, "Unknown"},
{0x54, nullptr, "Unknown"},
{0x55, nullptr, "Unknown"},
{0x56, nullptr, "Unknown"},
{0x57, nullptr, "Unknown"},
{0x58, nullptr, "Unknown"},
{0x59, nullptr, "Unknown"},
{0x5a, nullptr, "Unknown"},
{0x5b, nullptr, "Unknown"},
{0x5c, nullptr, "Unknown"},
{0x5d, nullptr, "Unknown"},
{0x5e, nullptr, "Unknown"},
{0x5F, SvcWrap32<FlushProcessDataCache32>, "FlushProcessDataCache32"},
{0x60, nullptr, "StoreProcessDataCache32"},
{0x61, nullptr, "BreakDebugProcess32"},
{0x62, nullptr, "TerminateDebugProcess32"},
{0x63, nullptr, "GetDebugEvent32"},
{0x64, nullptr, "ContinueDebugEvent32"},
{0x60, nullptr, "Unknown"},
{0x61, nullptr, "Unknown"},
{0x62, nullptr, "Unknown"},
{0x63, nullptr, "Unknown"},
{0x64, nullptr, "Unknown"},
{0x65, nullptr, "GetProcessList32"},
{0x66, nullptr, "GetThreadList"},
{0x67, nullptr, "GetDebugThreadContext32"},
{0x68, nullptr, "SetDebugThreadContext32"},
{0x69, nullptr, "QueryDebugProcessMemory32"},
{0x6A, nullptr, "ReadDebugProcessMemory32"},
{0x6B, nullptr, "WriteDebugProcessMemory32"},
{0x6C, nullptr, "SetHardwareBreakPoint32"},
{0x6D, nullptr, "GetDebugThreadParam32"},
{0x6E, nullptr, "Unknown6E"},
{0x66, nullptr, "Unknown"},
{0x67, nullptr, "Unknown"},
{0x68, nullptr, "Unknown"},
{0x69, nullptr, "Unknown"},
{0x6A, nullptr, "Unknown"},
{0x6B, nullptr, "Unknown"},
{0x6C, nullptr, "Unknown"},
{0x6D, nullptr, "Unknown"},
{0x6E, nullptr, "Unknown"},
{0x6f, nullptr, "GetSystemInfo32"},
{0x70, nullptr, "CreatePort32"},
{0x71, nullptr, "ManageNamedPort32"},
{0x72, nullptr, "ConnectToPort32"},
{0x73, nullptr, "SetProcessMemoryPermission32"},
{0x74, nullptr, "MapProcessMemory32"},
{0x75, nullptr, "UnmapProcessMemory32"},
{0x76, nullptr, "QueryProcessMemory32"},
{0x74, nullptr, "Unknown"},
{0x75, nullptr, "Unknown"},
{0x76, nullptr, "Unknown"},
{0x77, nullptr, "MapProcessCodeMemory32"},
{0x78, nullptr, "UnmapProcessCodeMemory32"},
{0x79, nullptr, "CreateProcess32"},
{0x7A, nullptr, "StartProcess32"},
{0x79, nullptr, "Unknown"},
{0x7A, nullptr, "Unknown"},
{0x7B, nullptr, "TerminateProcess32"},
{0x7C, nullptr, "GetProcessInfo32"},
{0x7D, nullptr, "CreateResourceLimit32"},
@@ -2754,7 +2754,7 @@ static const FunctionDef SVC_Table_32[] = {
};
static const FunctionDef SVC_Table_64[] = {
{0x00, nullptr, "Unknown0"},
{0x00, nullptr, "Unknown"},
{0x01, SvcWrap64<SetHeapSize>, "SetHeapSize"},
{0x02, SvcWrap64<SetMemoryPermission>, "SetMemoryPermission"},
{0x03, SvcWrap64<SetMemoryAttribute>, "SetMemoryAttribute"},
@@ -2809,23 +2809,23 @@ static const FunctionDef SVC_Table_64[] = {
{0x34, SvcWrap64<WaitForAddress>, "WaitForAddress"},
{0x35, SvcWrap64<SignalToAddress>, "SignalToAddress"},
{0x36, SvcWrap64<SynchronizePreemptionState>, "SynchronizePreemptionState"},
{0x37, nullptr, "GetResourceLimitPeakValue"},
{0x38, nullptr, "Unknown38"},
{0x39, nullptr, "CreateIoPool"},
{0x3A, nullptr, "CreateIoRegion"},
{0x3B, nullptr, "Unknown3B"},
{0x37, nullptr, "Unknown"},
{0x38, nullptr, "Unknown"},
{0x39, nullptr, "Unknown"},
{0x3A, nullptr, "Unknown"},
{0x3B, nullptr, "Unknown"},
{0x3C, SvcWrap64<KernelDebug>, "KernelDebug"},
{0x3D, SvcWrap64<ChangeKernelTraceState>, "ChangeKernelTraceState"},
{0x3E, nullptr, "Unknown3e"},
{0x3F, nullptr, "Unknown3f"},
{0x3E, nullptr, "Unknown"},
{0x3F, nullptr, "Unknown"},
{0x40, nullptr, "CreateSession"},
{0x41, nullptr, "AcceptSession"},
{0x42, nullptr, "ReplyAndReceiveLight"},
{0x43, nullptr, "ReplyAndReceive"},
{0x44, nullptr, "ReplyAndReceiveWithUserBuffer"},
{0x45, SvcWrap64<CreateEvent>, "CreateEvent"},
{0x46, nullptr, "MapIoRegion"},
{0x47, nullptr, "UnmapIoRegion"},
{0x46, nullptr, "Unknown"},
{0x47, nullptr, "Unknown"},
{0x48, nullptr, "MapPhysicalMemoryUnsafe"},
{0x49, nullptr, "UnmapPhysicalMemoryUnsafe"},
{0x4A, nullptr, "SetUnsafeLimit"},
@@ -2864,7 +2864,7 @@ static const FunctionDef SVC_Table_64[] = {
{0x6B, nullptr, "WriteDebugProcessMemory"},
{0x6C, nullptr, "SetHardwareBreakPoint"},
{0x6D, nullptr, "GetDebugThreadParam"},
{0x6E, nullptr, "Unknown6E"},
{0x6E, nullptr, "Unknown"},
{0x6F, nullptr, "GetSystemInfo"},
{0x70, nullptr, "CreatePort"},
{0x71, nullptr, "ManageNamedPort"},

View File

@@ -30,7 +30,6 @@ void ToggleConsole() {
freopen_s(&temp, "CONIN$", "r", stdin);
freopen_s(&temp, "CONOUT$", "w", stdout);
freopen_s(&temp, "CONOUT$", "w", stderr);
SetConsoleOutputCP(65001);
SetColorConsoleBackendEnabled(true);
}
} else {