diff options
| author | Zach Hilman <zachhilman@gmail.com> | 2019-03-10 16:51:42 -0400 | 
|---|---|---|
| committer | Zach Hilman <zachhilman@gmail.com> | 2019-03-10 16:51:42 -0400 | 
| commit | ed82bb968a2ec785485345aa202143df57c0f8fe (patch) | |
| tree | 3db6e12366aadee572fadd80920c9dcf3568d445 /src/core/hle | |
| parent | 0ea27718898e0a6327f96198ea4f315d06187a1e (diff) | |
set_sys: Implement GetFirmwareVersion(2) for libnx hosversion
Uses the synthesized system archive 9 (SystemVersion) and reports v5.1.0-0.0
Diffstat (limited to 'src/core/hle')
| -rw-r--r-- | src/core/hle/service/set/set_sys.cpp | 63 | ||||
| -rw-r--r-- | src/core/hle/service/set/set_sys.h | 2 | 
2 files changed, 63 insertions, 2 deletions
| diff --git a/src/core/hle/service/set/set_sys.cpp b/src/core/hle/service/set/set_sys.cpp index c9b4da5b0..ddab0e36f 100644 --- a/src/core/hle/service/set/set_sys.cpp +++ b/src/core/hle/service/set/set_sys.cpp @@ -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"}, diff --git a/src/core/hle/service/set/set_sys.h b/src/core/hle/service/set/set_sys.h index f602f3c77..13ee2cf46 100644 --- a/src/core/hle/service/set/set_sys.h +++ b/src/core/hle/service/set/set_sys.h @@ -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); | 
