mirror of
https://github.com/switchbrew/libnx.git
synced 2025-06-21 12:32:40 +02:00
Introduce hosversion.h - HOS version detection utilities
- Simplify kernel/detect.h logic; introduce detectKernelVersion() - Use set:sys (if available) during __appInit in order to initialize the current HOS version
This commit is contained in:
parent
6c3f72929d
commit
61cc738730
@ -108,6 +108,7 @@ extern "C" {
|
||||
#include "switch/applets/web.h"
|
||||
|
||||
#include "switch/runtime/env.h"
|
||||
#include "switch/runtime/hosversion.h"
|
||||
#include "switch/runtime/nxlink.h"
|
||||
|
||||
#include "switch/runtime/util/utf.h"
|
||||
|
@ -1,26 +1,42 @@
|
||||
/**
|
||||
* @file detect.h
|
||||
* @brief Kernel version detection
|
||||
* @brief Kernel capability detection
|
||||
* @author plutoo
|
||||
* @copyright libnx Authors
|
||||
*/
|
||||
#pragma once
|
||||
#include "../types.h"
|
||||
|
||||
/// Returns true if the kernel version is equal to or above 2.0.0.
|
||||
bool kernelAbove200(void);
|
||||
/// Returns true if the kernel version is equal to or above 3.0.0.
|
||||
bool kernelAbove300(void);
|
||||
/// Returns true if the kernel version is equal to or above 4.0.0.
|
||||
bool kernelAbove400(void);
|
||||
/// Returns true if the kernel version is equal to or above 5.0.0.
|
||||
bool kernelAbove500(void);
|
||||
/// Returns true if the kernel version is equal to or above 6.0.0.
|
||||
bool kernelAbove600(void);
|
||||
/// Returns the kernel version that can be detected by checking kernel capabilities. This only goes from 1 (representing 1.0.0) up to 6 (representing 6.0.0 and above). Generally, \ref hosversionGet should be used instead of this function.
|
||||
int detectKernelVersion(void);
|
||||
/// Returns true if the process has a debugger attached.
|
||||
bool detectDebugger(void);
|
||||
|
||||
/// Returns true if the kernel is patched to allow self-process-jit.
|
||||
bool detectJitKernelPatch(void);
|
||||
/// After this has been called, libnx will ignore the self-process-jit kernel patch. For testing purposes only.
|
||||
void detectIgnoreJitKernelPatch(void);
|
||||
|
||||
/// Returns true if the kernel version is equal to or above 2.0.0. Generally, \ref hosversionAtLeast should be used instead of this function.
|
||||
static inline bool kernelAbove200(void) {
|
||||
return detectKernelVersion() >= 2;
|
||||
}
|
||||
|
||||
/// Returns true if the kernel version is equal to or above 3.0.0. Generally, \ref hosversionAtLeast should be used instead of this function.
|
||||
static inline bool kernelAbove300(void) {
|
||||
return detectKernelVersion() >= 3;
|
||||
}
|
||||
|
||||
/// Returns true if the kernel version is equal to or above 4.0.0. Generally, \ref hosversionAtLeast should be used instead of this function.
|
||||
static inline bool kernelAbove400(void) {
|
||||
return detectKernelVersion() >= 4;
|
||||
}
|
||||
|
||||
/// Returns true if the kernel version is equal to or above 5.0.0. Generally, \ref hosversionAtLeast should be used instead of this function.
|
||||
static inline bool kernelAbove500(void) {
|
||||
return detectKernelVersion() >= 5;
|
||||
}
|
||||
|
||||
/// Returns true if the kernel version is equal to or above 6.0.0. Generally, \ref hosversionAtLeast should be used instead of this function.
|
||||
static inline bool kernelAbove600(void) {
|
||||
return detectKernelVersion() >= 6;
|
||||
}
|
||||
|
42
nx/include/switch/runtime/hosversion.h
Normal file
42
nx/include/switch/runtime/hosversion.h
Normal file
@ -0,0 +1,42 @@
|
||||
/**
|
||||
* @file hosversion.h
|
||||
* @brief Horizon OS (HOS) version detection utilities.
|
||||
* @author fincs
|
||||
* @copyright libnx Authors
|
||||
*/
|
||||
#pragma once
|
||||
#include "../types.h"
|
||||
|
||||
/// Builds a HOS version value from its constituent components.
|
||||
#define MAKEHOSVERSION(_major,_minor,_micro) (((u32)(_major) << 16) | ((u32)(_minor) << 8) | (u32)(_micro))
|
||||
|
||||
/// Extracts the major number from a HOS version value.
|
||||
#define HOSVER_MAJOR(_version) (((_version) >> 16) & 0xFF)
|
||||
|
||||
/// Extracts the minor number from a HOS version value.
|
||||
#define HOSVER_MINOR(_version) (((_version) >> 8) & 0xFF)
|
||||
|
||||
/// Extracts the micro number from a HOS version value.
|
||||
#define HOSVER_MICRO(_version) ( (_version) & 0xFF)
|
||||
|
||||
/// Returns the current HOS version that was previously set with \ref hosversionSet. If version initialization fails during startup (such as in the case set:sys is not available), this function returns zero.
|
||||
u32 hosversionGet(void);
|
||||
|
||||
/// Sets or overrides the current HOS version. This function is normally called automatically by libnx on startup with the version info obtained with \ref setsysGetFirmwareVersion.
|
||||
void hosversionSet(u32 version);
|
||||
|
||||
/// Returns true if the current HOS version is equal to or above the specified major/minor/micro version.
|
||||
static inline bool hosversionAtLeast(u8 major, u8 minor, u8 micro) {
|
||||
return hosversionGet() >= MAKEHOSVERSION(major,minor,micro);
|
||||
}
|
||||
|
||||
/// Returns true if the current HOS version is earlier than the specified major/minor/micro version.
|
||||
static inline bool hosversionBefore(u8 major, u8 minor, u8 micro) {
|
||||
return !hosversionAtLeast(major, minor, micro);
|
||||
}
|
||||
|
||||
/// Returns true if the current HOS version is between the two specified major versions, i.e. [major1, major2).
|
||||
static inline bool hosversionBetween(u8 major1, u8 major2) {
|
||||
u32 ver = hosversionGet();
|
||||
return ver >= MAKEHOSVERSION(major1,0,0) && ver < MAKEHOSVERSION(major2,0,0);
|
||||
}
|
@ -6,15 +6,11 @@
|
||||
#include "kernel/svc.h"
|
||||
#include <malloc.h>
|
||||
|
||||
static bool g_VersionCached = 0;
|
||||
static bool g_VersionCached;
|
||||
static Mutex g_VersionMutex;
|
||||
static bool g_IsAbove200;
|
||||
static bool g_IsAbove300;
|
||||
static bool g_IsAbove400;
|
||||
static bool g_IsAbove500;
|
||||
static bool g_IsAbove600;
|
||||
static int g_Version;
|
||||
|
||||
static bool g_JitKernelPatchCached = 0;
|
||||
static bool g_JitKernelPatchCached;
|
||||
static Mutex g_JitKernelPatchMutex;
|
||||
static bool g_JitKernelPatchDetected;
|
||||
|
||||
@ -31,16 +27,17 @@ static void _CacheVersion(void)
|
||||
}
|
||||
|
||||
u64 tmp;
|
||||
g_IsAbove200 = (svcGetInfo(&tmp, 12, INVALID_HANDLE, 0) != 0xF001);
|
||||
g_IsAbove300 = (svcGetInfo(&tmp, 18, INVALID_HANDLE, 0) != 0xF001);
|
||||
g_IsAbove400 = (svcGetInfo(&tmp, 19, INVALID_HANDLE, 0) != 0xF001);
|
||||
g_IsAbove500 = (svcGetInfo(&tmp, 20, INVALID_HANDLE, 0) != 0xF001);
|
||||
g_IsAbove600 = (svcGetInfo(&tmp, 21, INVALID_HANDLE, 0) != 0xF001);
|
||||
|
||||
g_IsAbove500 |= g_IsAbove600;
|
||||
g_IsAbove400 |= g_IsAbove500;
|
||||
g_IsAbove300 |= g_IsAbove400;
|
||||
g_IsAbove200 |= g_IsAbove300;
|
||||
g_Version = 1;
|
||||
if (R_VALUE(svcGetInfo(&tmp, 12, INVALID_HANDLE, 0)) != KERNELRESULT(InvalidEnumValue))
|
||||
g_Version = 2;
|
||||
if (R_VALUE(svcGetInfo(&tmp, 18, INVALID_HANDLE, 0)) != KERNELRESULT(InvalidEnumValue))
|
||||
g_Version = 3;
|
||||
if (R_VALUE(svcGetInfo(&tmp, 19, INVALID_HANDLE, 0)) != KERNELRESULT(InvalidEnumValue))
|
||||
g_Version = 4;
|
||||
if (R_VALUE(svcGetInfo(&tmp, 20, INVALID_HANDLE, 0)) != KERNELRESULT(InvalidEnumValue))
|
||||
g_Version = 5;
|
||||
if (R_VALUE(svcGetInfo(&tmp, 21, INVALID_HANDLE, 0)) != KERNELRESULT(InvalidEnumValue))
|
||||
g_Version = 6;
|
||||
|
||||
__atomic_store_n(&g_VersionCached, true, __ATOMIC_SEQ_CST);
|
||||
|
||||
@ -84,29 +81,9 @@ static void _CacheJitKernelPatch(void)
|
||||
mutexUnlock(&g_JitKernelPatchMutex);
|
||||
}
|
||||
|
||||
bool kernelAbove200(void) {
|
||||
int detectKernelVersion(void) {
|
||||
_CacheVersion();
|
||||
return g_IsAbove200;
|
||||
}
|
||||
|
||||
bool kernelAbove300(void) {
|
||||
_CacheVersion();
|
||||
return g_IsAbove300;
|
||||
}
|
||||
|
||||
bool kernelAbove400(void) {
|
||||
_CacheVersion();
|
||||
return g_IsAbove400;
|
||||
}
|
||||
|
||||
bool kernelAbove500(void) {
|
||||
_CacheVersion();
|
||||
return g_IsAbove500;
|
||||
}
|
||||
|
||||
bool kernelAbove600(void) {
|
||||
_CacheVersion();
|
||||
return g_IsAbove600;
|
||||
return g_Version;
|
||||
}
|
||||
|
||||
bool detectDebugger(void) {
|
||||
|
13
nx/source/runtime/hosversion.c
Normal file
13
nx/source/runtime/hosversion.c
Normal file
@ -0,0 +1,13 @@
|
||||
#include "runtime/hosversion.h"
|
||||
|
||||
static u32 g_hosVersion;
|
||||
|
||||
u32 hosversionGet(void)
|
||||
{
|
||||
return __atomic_load_n(&g_hosVersion, __ATOMIC_SEQ_CST);
|
||||
}
|
||||
|
||||
void hosversionSet(u32 version)
|
||||
{
|
||||
__atomic_store_n(&g_hosVersion, version, __ATOMIC_SEQ_CST);
|
||||
}
|
@ -1,11 +1,13 @@
|
||||
#include "types.h"
|
||||
#include "runtime/env.h"
|
||||
#include "runtime/hosversion.h"
|
||||
#include "services/sm.h"
|
||||
#include "services/fatal.h"
|
||||
#include "services/fs.h"
|
||||
#include "services/hid.h"
|
||||
#include "services/time.h"
|
||||
#include "services/applet.h"
|
||||
#include "services/set.h"
|
||||
#include "runtime/devices/fs_dev.h"
|
||||
|
||||
void* __stack_top;
|
||||
@ -107,6 +109,15 @@ void __attribute__((weak)) __appInit(void)
|
||||
if (R_FAILED(rc))
|
||||
fatalSimple(MAKERESULT(Module_Libnx, LibnxError_InitFail_SM));
|
||||
|
||||
rc = setsysInitialize();
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
SetSysFirmwareVersion fw;
|
||||
rc = setsysGetFirmwareVersion(&fw);
|
||||
if (R_SUCCEEDED(rc))
|
||||
hosversionSet(MAKEHOSVERSION(fw.major, fw.minor, fw.micro));
|
||||
setsysExit();
|
||||
}
|
||||
|
||||
rc = appletInitialize();
|
||||
if (R_FAILED(rc))
|
||||
fatalSimple(MAKERESULT(Module_Libnx, LibnxError_InitFail_AM));
|
||||
|
Loading…
Reference in New Issue
Block a user