From d63be0737bd348dcdb6f872aa4a39e85a651b2d1 Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Fri, 22 Oct 2021 09:54:38 -0700 Subject: [PATCH] hos: better safe than sorry --- .../source/hos/hos_version_api.cpp | 73 +++++++++---------- 1 file changed, 36 insertions(+), 37 deletions(-) diff --git a/libraries/libstratosphere/source/hos/hos_version_api.cpp b/libraries/libstratosphere/source/hos/hos_version_api.cpp index 76233755c..4dca9be89 100644 --- a/libraries/libstratosphere/source/hos/hos_version_api.cpp +++ b/libraries/libstratosphere/source/hos/hos_version_api.cpp @@ -68,53 +68,52 @@ namespace ams::hos { if (IsUnitTestProgramForSetVersion()) { g_hos_version = hos::Version_Current; g_set_hos_version = true; - return; - } + } else { + /* Get the current (and previous approximation of) target firmware. */ + hos::Version prev, current; + bool has_prev = false; + { + /* Acquire exclusive access to set hos version. */ + std::scoped_lock lk(g_hos_init_lock); - /* Get the current (and previous approximation of) target firmware. */ - hos::Version prev, current; - bool has_prev = false; - { - /* Acquire exclusive access to set hos version. */ - std::scoped_lock lk(g_hos_init_lock); + /* Save the previous value of g_hos_version. */ + prev = g_hos_version; + has_prev = g_set_hos_version; - /* Save the previous value of g_hos_version. */ - prev = g_hos_version; - has_prev = g_set_hos_version; + /* Set hos version = exosphere api version target firmware. */ + g_hos_version = static_cast(GetExosphereApiInfo(allow_approximate).GetTargetFirmware()); - /* Set hos version = exosphere api version target firmware. */ - g_hos_version = static_cast(GetExosphereApiInfo(allow_approximate).GetTargetFirmware()); + /* Save the current value of g_hos_version. */ + current = g_hos_version; - /* Save the current value of g_hos_version. */ - current = g_hos_version; + /* Note that we've set a previous hos version. */ + g_set_hos_version = true; + } - /* Note that we've set a previous hos version. */ - g_set_hos_version = true; - } + /* Ensure that this is a hos version we can sanely *try* to run. */ + /* To be friendly, we will only require that we recognize the major and minor versions. */ + /* We can consider only recognizing major in the future, but micro seems safe to ignore as */ + /* there are no breaking IPC changes in minor updates. */ + { + constexpr u32 MaxMajor = (static_cast(hos::Version_Max) >> 24) & 0xFF; + constexpr u32 MaxMinor = (static_cast(hos::Version_Max) >> 16) & 0xFF; - /* Ensure that this is a hos version we can sanely *try* to run. */ - /* To be friendly, we will only require that we recognize the major and minor versions. */ - /* We can consider only recognizing major in the future, but micro seems safe to ignore as */ - /* there are no breaking IPC changes in minor updates. */ - { - constexpr u32 MaxMajor = (static_cast(hos::Version_Max) >> 24) & 0xFF; - constexpr u32 MaxMinor = (static_cast(hos::Version_Max) >> 16) & 0xFF; + const u32 major = (static_cast(current) >> 24) & 0xFF; + const u32 minor = (static_cast(current) >> 16) & 0xFF; - const u32 major = (static_cast(current) >> 24) & 0xFF; - const u32 minor = (static_cast(current) >> 16) & 0xFF; + const bool is_safely_tryable_version = (current <= hos::Version_Max) || (major == MaxMajor && minor <= MaxMinor); + AMS_ABORT_UNLESS(is_safely_tryable_version); + } - const bool is_safely_tryable_version = (current <= hos::Version_Max) || (major == MaxMajor && minor <= MaxMinor); - AMS_ABORT_UNLESS(is_safely_tryable_version); - } + /* Ensure that this is a hos version compatible with previous approximations. */ + if (has_prev) { + AMS_ABORT_UNLESS(current >= prev); - /* Ensure that this is a hos version compatible with previous approximations. */ - if (has_prev) { - AMS_ABORT_UNLESS(current >= prev); + const u32 current_major = (static_cast(current) >> 24) & 0xFF; + const u32 prev_major = (static_cast(prev) >> 24) & 0xFF; - const u32 current_major = (static_cast(current) >> 24) & 0xFF; - const u32 prev_major = (static_cast(prev) >> 24) & 0xFF; - - AMS_ABORT_UNLESS(current_major == prev_major); + AMS_ABORT_UNLESS(current_major == prev_major); + } } /* Set the version for libnx. */