set_sys: Implement GetFirmwareVersion(2) for libnx hosversion
Uses the synthesized system archive 9 (SystemVersion) and reports v5.1.0-0.0
This commit is contained in:
parent
0ea2771889
commit
ed82bb968a
|
@ -68,6 +68,8 @@ add_library(core STATIC
|
|||
file_sys/system_archive/ng_word.h
|
||||
file_sys/system_archive/system_archive.cpp
|
||||
file_sys/system_archive/system_archive.h
|
||||
file_sys/system_archive/system_version.cpp
|
||||
file_sys/system_archive/system_version.h
|
||||
file_sys/vfs.cpp
|
||||
file_sys/vfs.h
|
||||
file_sys/vfs_concat.cpp
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include "core/file_sys/romfs.h"
|
||||
#include "core/file_sys/system_archive/ng_word.h"
|
||||
#include "core/file_sys/system_archive/system_archive.h"
|
||||
#include "core/file_sys/system_archive/system_version.h"
|
||||
|
||||
namespace FileSys::SystemArchive {
|
||||
|
||||
|
@ -30,7 +31,7 @@ constexpr std::array<SystemArchiveDescriptor, SYSTEM_ARCHIVE_COUNT> SYSTEM_ARCHI
|
|||
{0x0100000000000806, "NgWord", &NgWord1},
|
||||
{0x0100000000000807, "SsidList", nullptr},
|
||||
{0x0100000000000808, "Dictionary", nullptr},
|
||||
{0x0100000000000809, "SystemVersion", nullptr},
|
||||
{0x0100000000000809, "SystemVersion", &SystemVersion},
|
||||
{0x010000000000080A, "AvatarImage", nullptr},
|
||||
{0x010000000000080B, "LocalNews", nullptr},
|
||||
{0x010000000000080C, "Eula", nullptr},
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
// Copyright 2019 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "core/file_sys/system_archive/system_version.h"
|
||||
#include "core/file_sys/vfs_vector.h"
|
||||
|
||||
namespace FileSys::SystemArchive {
|
||||
|
||||
namespace SystemVersionData {
|
||||
|
||||
// This section should reflect the best system version to describe yuzu's HLE api.
|
||||
// TODO(DarkLordZach): Update when HLE gets better.
|
||||
|
||||
constexpr u8 VERSION_MAJOR = 5;
|
||||
constexpr u8 VERSION_MINOR = 1;
|
||||
constexpr u8 VERSION_MICRO = 0;
|
||||
|
||||
constexpr u8 REVISION_MAJOR = 0;
|
||||
constexpr u8 REVISION_MINOR = 0;
|
||||
|
||||
constexpr char PLATFORM_STRING[] = "YUZU";
|
||||
constexpr char VERSION_HASH[] = "";
|
||||
constexpr char DISPLAY_VERSION[] = "5.1.0";
|
||||
constexpr char DISPLAY_TITLE[] = "YuzuEmulated Firmware for NX 5.1.0-0.0";
|
||||
|
||||
} // namespace SystemVersionData
|
||||
|
||||
VirtualDir SystemVersion() {
|
||||
VirtualFile file = std::make_shared<VectorVfsFile>(std::vector<u8>(0x100), "file");
|
||||
file->WriteObject(SystemVersionData::VERSION_MAJOR, 0);
|
||||
file->WriteObject(SystemVersionData::VERSION_MINOR, 1);
|
||||
file->WriteObject(SystemVersionData::VERSION_MICRO, 2);
|
||||
file->WriteObject(SystemVersionData::REVISION_MAJOR, 4);
|
||||
file->WriteObject(SystemVersionData::REVISION_MINOR, 5);
|
||||
file->WriteArray(SystemVersionData::PLATFORM_STRING,
|
||||
std::min(sizeof(SystemVersionData::PLATFORM_STRING), 0x20ull), 0x8);
|
||||
file->WriteArray(SystemVersionData::VERSION_HASH,
|
||||
std::min(sizeof(SystemVersionData::VERSION_HASH), 0x40ull), 0x28);
|
||||
file->WriteArray(SystemVersionData::DISPLAY_VERSION,
|
||||
std::min(sizeof(SystemVersionData::DISPLAY_VERSION), 0x18ull), 0x68);
|
||||
file->WriteArray(SystemVersionData::DISPLAY_TITLE,
|
||||
std::min(sizeof(SystemVersionData::DISPLAY_TITLE), 0x80ull), 0x80);
|
||||
return std::make_shared<VectorVfsDirectory>(std::vector<VirtualFile>{file},
|
||||
std::vector<VirtualDir>{}, "data");
|
||||
}
|
||||
|
||||
} // namespace FileSys::SystemArchive
|
|
@ -0,0 +1,13 @@
|
|||
// Copyright 2019 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/file_sys/vfs_types.h"
|
||||
|
||||
namespace FileSys::SystemArchive {
|
||||
|
||||
VirtualDir SystemVersion();
|
||||
|
||||
} // namespace FileSys::SystemArchive
|
|
@ -3,12 +3,71 @@
|
|||
// Refer to the license.txt file included.
|
||||
|
||||
#include "common/logging/log.h"
|
||||
#include "core/file_sys/system_archive/system_version.h"
|
||||
#include "core/hle/ipc_helpers.h"
|
||||
#include "core/hle/kernel/client_port.h"
|
||||
#include "core/hle/service/filesystem/filesystem.h"
|
||||
#include "core/hle/service/set/set_sys.h"
|
||||
|
||||
namespace Service::Set {
|
||||
|
||||
void SET_SYS::GetFirmwareVersion(Kernel::HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_SET, "called");
|
||||
|
||||
ASSERT(ctx.GetWriteBufferSize() == 0x100,
|
||||
"FirmwareVersion output buffer must be 0x100 bytes in size!");
|
||||
|
||||
// Instead of using the normal procedure of checking for the real system archive and if it
|
||||
// doesn't exist, synthesizing one, I feel that that would lead to strange bugs because a used
|
||||
// is using a really old or really new SystemVersion title. The synthesized one ensures
|
||||
// consistence (currently reports as 5.1.0-0.0)
|
||||
const auto archive = FileSys::SystemArchive::SystemVersion();
|
||||
|
||||
const auto early_exit_failure = [&ctx](const std::string& desc) {
|
||||
LOG_ERROR(Service_SET, "General failure while attempting to resolve firmware version ({}).",
|
||||
desc.c_str());
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultCode(-1));
|
||||
};
|
||||
|
||||
if (archive == nullptr) {
|
||||
early_exit_failure("The system version archive couldn't be synthesized.");
|
||||
return;
|
||||
}
|
||||
|
||||
const auto ver_file = archive->GetFile("file");
|
||||
if (ver_file == nullptr) {
|
||||
early_exit_failure("The system version archive didn't contain the file 'file'.");
|
||||
return;
|
||||
}
|
||||
|
||||
auto data = ver_file->ReadAllBytes();
|
||||
if (data.size() != 0x100) {
|
||||
early_exit_failure("The system version file 'file' was not the correct size.");
|
||||
return;
|
||||
}
|
||||
|
||||
// If the command is GetFirmwareVersion (as opposed to GetFirmwareVersion2), hardware will zero
|
||||
// out the REVISION_MAJOR and REVISION_MICRO fields, which are u8s at offsets 0x4 and 0x5,
|
||||
// respectively. This if statement will only execute when the true intended command is
|
||||
// GetFirmwareVersion, and allows removing duplicate code for the implementation of
|
||||
// GetFirmwareVersion2.
|
||||
if (ctx.GetCommand() == 3) {
|
||||
data[0x4] = 0x0;
|
||||
data[0x5] = 0x0;
|
||||
}
|
||||
|
||||
ctx.WriteBuffer(data);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
}
|
||||
|
||||
void SET_SYS::GetFirmwareVersion2(Kernel::HLERequestContext& ctx) {
|
||||
LOG_WARNING(Service_SET, "called - delegating to GetFirmwareVersion");
|
||||
GetFirmwareVersion(ctx);
|
||||
}
|
||||
|
||||
void SET_SYS::GetColorSetId(Kernel::HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_SET, "called");
|
||||
|
||||
|
@ -33,8 +92,8 @@ SET_SYS::SET_SYS() : ServiceFramework("set:sys") {
|
|||
{0, nullptr, "SetLanguageCode"},
|
||||
{1, nullptr, "SetNetworkSettings"},
|
||||
{2, nullptr, "GetNetworkSettings"},
|
||||
{3, nullptr, "GetFirmwareVersion"},
|
||||
{4, nullptr, "GetFirmwareVersion2"},
|
||||
{3, &SET_SYS::GetFirmwareVersion, "GetFirmwareVersion"},
|
||||
{4, &SET_SYS::GetFirmwareVersion2, "GetFirmwareVersion2"},
|
||||
{5, nullptr, "GetFirmwareVersionDigest"},
|
||||
{7, nullptr, "GetLockScreenFlag"},
|
||||
{8, nullptr, "SetLockScreenFlag"},
|
||||
|
|
|
@ -20,6 +20,8 @@ private:
|
|||
BasicBlack = 1,
|
||||
};
|
||||
|
||||
void GetFirmwareVersion(Kernel::HLERequestContext& ctx);
|
||||
void GetFirmwareVersion2(Kernel::HLERequestContext& ctx);
|
||||
void GetColorSetId(Kernel::HLERequestContext& ctx);
|
||||
void SetColorSetId(Kernel::HLERequestContext& ctx);
|
||||
|
||||
|
|
Reference in New Issue