diff --git a/libraries/libmesosphere/include/mesosphere/kern_k_capabilities.hpp b/libraries/libmesosphere/include/mesosphere/kern_k_capabilities.hpp index 9c590e3db..7c9863049 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_k_capabilities.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_k_capabilities.hpp @@ -354,6 +354,10 @@ namespace ams::kern { constexpr bool CanForceDebug() const { return this->debug_capabilities.Get(); } + + constexpr u32 GetIntendedKernelMajorVersion() const { return this->intended_kernel_version.Get(); } + constexpr u32 GetIntendedKernelMinorVersion() const { return this->intended_kernel_version.Get(); } + constexpr u32 GetIntendedKernelVersion() const { return ams::svc::EncodeKernelVersion(this->GetIntendedKernelMajorVersion(), this->GetIntendedKernelMinorVersion()); } }; } diff --git a/libraries/libmesosphere/source/kern_k_capabilities.cpp b/libraries/libmesosphere/source/kern_k_capabilities.cpp index 169afc06d..c7abfc4b7 100644 --- a/libraries/libmesosphere/source/kern_k_capabilities.cpp +++ b/libraries/libmesosphere/source/kern_k_capabilities.cpp @@ -27,8 +27,10 @@ namespace ams::kern { /* Initial processes may use any user priority they like. */ this->priority_mask = ~0xFul; - /* TODO: Here, Nintendo sets the kernel version to (current kernel version). */ - /* How should we handle this? Not a MESOSPHERE_TODO because it's not critical. */ + /* Here, Nintendo sets the kernel version to the current kernel version. */ + /* We will follow suit and set the version to the highest supported kernel version. */ + this->intended_kernel_version.Set(ams::svc::SupportedKernelMajorVersion); + this->intended_kernel_version.Set(ams::svc::SupportedKernelMinorVersion); /* Parse the capabilities array. */ return this->SetCapabilities(caps, num_caps, page_table); diff --git a/libraries/libmesosphere/source/kern_k_process.cpp b/libraries/libmesosphere/source/kern_k_process.cpp index 499dd6392..bd8336160 100644 --- a/libraries/libmesosphere/source/kern_k_process.cpp +++ b/libraries/libmesosphere/source/kern_k_process.cpp @@ -146,8 +146,11 @@ namespace ams::kern { } Result KProcess::Initialize(const ams::svc::CreateProcessParameter ¶ms) { - /* TODO: Validate intended kernel version. */ - /* How should we do this? */ + /* Validate that the intended kernel version is high enough for us to support. */ + R_UNLESS(this->capabilities.GetIntendedKernelVersion() >= ams::svc::RequiredKernelVersion, svc::ResultInvalidCombination()); + + /* Validate that the intended kernel version isn't too high for us to support. */ + R_UNLESS(this->capabilities.GetIntendedKernelVersion() <= ams::svc::SupportedKernelVersion, svc::ResultInvalidCombination()); /* Create and clear the process local region. */ R_TRY(this->CreateThreadLocalRegion(std::addressof(this->plr_address))); diff --git a/libraries/libvapours/include/vapours/svc.hpp b/libraries/libvapours/include/vapours/svc.hpp index 2ce0d36aa..84e84f3f6 100644 --- a/libraries/libvapours/include/vapours/svc.hpp +++ b/libraries/libvapours/include/vapours/svc.hpp @@ -21,4 +21,5 @@ #include #include +#include #include diff --git a/libraries/libvapours/include/vapours/svc/svc_version.hpp b/libraries/libvapours/include/vapours/svc/svc_version.hpp new file mode 100644 index 000000000..b4ec65d61 --- /dev/null +++ b/libraries/libvapours/include/vapours/svc/svc_version.hpp @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2018-2020 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once +#include +#include +#include + +namespace ams::svc { + + constexpr inline u32 ConvertToSvcMajorVersion(u32 sdk) { return sdk + 4; } + constexpr inline u32 ConvertToSdkMajorVersion(u32 svc) { return svc - 4; } + + constexpr inline u32 ConvertToSvcMinorVersion(u32 sdk) { return sdk; } + constexpr inline u32 ConvertToSdkMinorVersion(u32 svc) { return svc; } + + struct KernelVersion { + using MinorVersion = util::BitPack32::Field<0, 4>; + using MajorVersion = util::BitPack32::Field; + }; + + constexpr inline u32 EncodeKernelVersion(u32 major, u32 minor) { + util::BitPack32 pack = {}; + pack.Set(minor); + pack.Set(major); + return pack.value; + } + + constexpr inline u32 GetKernelMajorVersion(u32 encoded) { + const util::BitPack32 pack = { encoded }; + return pack.Get(); + } + + constexpr inline u32 GetKernelMinorVersion(u32 encoded) { + const util::BitPack32 pack = { encoded }; + return pack.Get(); + } + + /* Nintendo doesn't support programs targeting SVC versions < 3.0. */ + constexpr inline u32 RequiredKernelMajorVersion = 3; + constexpr inline u32 RequiredKernelMinorVersion = 0; + + constexpr inline u32 RequiredKernelVersion = EncodeKernelVersion(RequiredKernelMajorVersion, RequiredKernelMinorVersion); + + /* This is the highest SVC version supported by Atmosphere, to be updated on new kernel releases. */ + /* NOTE: Official kernel versions have SVC major = SDK major + 4, SVC minor = SDK minor. */ + constexpr inline u32 SupportedKernelMajorVersion = ConvertToSvcMajorVersion(10); + constexpr inline u32 SupportedKernelMinorVersion = ConvertToSvcMinorVersion( 4); + + constexpr inline u32 SupportedKernelVersion = EncodeKernelVersion(SupportedKernelMajorVersion, SupportedKernelMinorVersion); + +}