mirror of
https://github.com/Karaka-Management/cOMS.git
synced 2026-01-10 19:08:39 +00:00
some system info improvements (CpuInfo, SystemInfo, SIMD helper)
This commit is contained in:
parent
208bff208f
commit
2263d6f018
20
architecture/CpuInfo.cpp
Normal file
20
architecture/CpuInfo.cpp
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
/**
|
||||
* Jingga
|
||||
*
|
||||
* @copyright Jingga
|
||||
* @license OMS License 2.0
|
||||
* @version 1.0.0
|
||||
* @link https://jingga.app
|
||||
*/
|
||||
#ifndef TOS_ARCHITECTURE_CPU_INFO_C
|
||||
#define TOS_ARCHITECTURE_CPU_INFO_C
|
||||
|
||||
#include "CpuInfo.h"
|
||||
|
||||
#if ARM
|
||||
#include "arm/CpuInfo.cpp"
|
||||
#else
|
||||
#include "x86/CpuInfo.cpp"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
101
architecture/CpuInfo.h
Normal file
101
architecture/CpuInfo.h
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
/**
|
||||
* Jingga
|
||||
*
|
||||
* @copyright Jingga
|
||||
* @license OMS License 2.0
|
||||
* @version 1.0.0
|
||||
* @link https://jingga.app
|
||||
*/
|
||||
#ifndef TOS_ARCHITECTURE_CPU_INFO_H
|
||||
#define TOS_ARCHITECTURE_CPU_INFO_H
|
||||
|
||||
#include "../stdlib/Types.h"
|
||||
|
||||
// @todo We don't care about a lot of features, consider to remove them if we can get either below 32bit
|
||||
// or if we eventually overflow 64 bit
|
||||
enum CPUFeature : uint64 {
|
||||
CPU_FEATURE_SSE3 = 1ULL << 0,
|
||||
CPU_FEATURE_PCLMULQDQ = 1ULL << 1,
|
||||
CPU_FEATURE_MONITOR = 1ULL << 2,
|
||||
CPU_FEATURE_SSSE3 = 1ULL << 3,
|
||||
CPU_FEATURE_FMA = 1ULL << 4,
|
||||
CPU_FEATURE_CMPXCHG16B = 1ULL << 5,
|
||||
CPU_FEATURE_SSE41 = 1ULL << 6,
|
||||
CPU_FEATURE_SSE42 = 1ULL << 7,
|
||||
CPU_FEATURE_MOVBE = 1ULL << 8,
|
||||
CPU_FEATURE_POPCNT = 1ULL << 9,
|
||||
CPU_FEATURE_AES = 1ULL << 10,
|
||||
CPU_FEATURE_XSAVE = 1ULL << 11,
|
||||
CPU_FEATURE_OSXSAVE = 1ULL << 12,
|
||||
CPU_FEATURE_AVX = 1ULL << 13,
|
||||
CPU_FEATURE_F16C = 1ULL << 14,
|
||||
CPU_FEATURE_RDRAND = 1ULL << 15,
|
||||
CPU_FEATURE_MSR = 1ULL << 16,
|
||||
CPU_FEATURE_CX8 = 1ULL << 17,
|
||||
CPU_FEATURE_SEP = 1ULL << 18,
|
||||
CPU_FEATURE_CMOV = 1ULL << 19,
|
||||
CPU_FEATURE_CLFSH = 1ULL << 20,
|
||||
CPU_FEATURE_MMX = 1ULL << 21,
|
||||
CPU_FEATURE_FXSR = 1ULL << 22,
|
||||
CPU_FEATURE_SSE = 1ULL << 23,
|
||||
CPU_FEATURE_SSE2 = 1ULL << 24,
|
||||
CPU_FEATURE_AVX2 = 1ULL << 25,
|
||||
CPU_FEATURE_BMI1 = 1ULL << 26,
|
||||
CPU_FEATURE_BMI2 = 1ULL << 27,
|
||||
CPU_FEATURE_ERMS = 1ULL << 28,
|
||||
CPU_FEATURE_INVPCID = 1ULL << 29,
|
||||
CPU_FEATURE_RDSEED = 1ULL << 30,
|
||||
CPU_FEATURE_ADX = 1ULL << 31,
|
||||
CPU_FEATURE_SHA = 1ULL << 32,
|
||||
CPU_FEATURE_PREFETCHWT1 = 1ULL << 33,
|
||||
CPU_FEATURE_LAHF = 1ULL << 34,
|
||||
CPU_FEATURE_LZCNT = 1ULL << 35,
|
||||
CPU_FEATURE_ABM = 1ULL << 36,
|
||||
CPU_FEATURE_SSE4a = 1ULL << 37,
|
||||
CPU_FEATURE_XOP = 1ULL << 38,
|
||||
CPU_FEATURE_TBM = 1ULL << 39,
|
||||
CPU_FEATURE_SYSCALL = 1ULL << 40,
|
||||
CPU_FEATURE_MMEXT = 1ULL << 41,
|
||||
CPU_FEATURE_RDTSCP = 1ULL << 42,
|
||||
CPU_FEATURE_3DNOWEXT = 1ULL << 43,
|
||||
CPU_FEATURE_3DNOW = 1ULL << 44,
|
||||
CPU_FEATURE_AVX512F = 1ULL << 45,
|
||||
CPU_FEATURE_AVX512PF = 1ULL << 46,
|
||||
CPU_FEATURE_AVX512ER = 1ULL << 47,
|
||||
CPU_FEATURE_AVX512CD = 1ULL << 48,
|
||||
|
||||
CPU_FEATURE_ASIMD_ARM = 1ULL << 49,
|
||||
CPU_FEATURE_ATOMICS_ARM = 1ULL << 50,
|
||||
CPU_FEATURE_PMULL_ARM = 1ULL << 51,
|
||||
CPU_FEATURE_SVEPMULL_ARM = 1ULL << 52,
|
||||
CPU_FEATURE_NEON_ARM = 1ULL << 53,
|
||||
CPU_FEATURE_SVE_ARM = 1ULL << 54,
|
||||
CPU_FEATURE_SVE2_ARM = 1ULL << 55,
|
||||
CPU_FEATURE_AES_ARM = 1ULL << 56,
|
||||
CPU_FEATURE_SHA1_ARM = 1ULL << 57,
|
||||
CPU_FEATURE_SHA2_ARM = 1ULL << 58,
|
||||
CPU_FEATURE_CRC32_ARM = 1ULL << 59,
|
||||
};
|
||||
|
||||
struct CpuCacheInfo {
|
||||
uint32 size;
|
||||
uint32 sets;
|
||||
byte level;
|
||||
byte ways;
|
||||
byte partitions;
|
||||
uint16 line_size;
|
||||
};
|
||||
|
||||
struct CpuInfo {
|
||||
char vendor[13];
|
||||
char brand[49];
|
||||
byte model;
|
||||
byte family;
|
||||
byte thread_count;
|
||||
int32 mhz;
|
||||
uint32 page_size;
|
||||
CpuCacheInfo cache[4];
|
||||
uint64 features;
|
||||
};
|
||||
|
||||
#endif
|
||||
67
architecture/arm/CpuInfo.cpp
Normal file
67
architecture/arm/CpuInfo.cpp
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
/**
|
||||
* Jingga
|
||||
*
|
||||
* @copyright Jingga
|
||||
* @license OMS License 2.0
|
||||
* @version 1.0.0
|
||||
* @link https://jingga.app
|
||||
*/
|
||||
#ifndef TOS_ARCHITECTURE_ARM_CPU_INFO_C
|
||||
#define TOS_ARCHITECTURE_ARM_CPU_INFO_C
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include "../../stdlib/Types.h"
|
||||
#include "../CpuInfo.h"
|
||||
#include <arm_sve.h>
|
||||
|
||||
uint64 cpu_info_features() {
|
||||
uint64 feature_bitfield = 0;
|
||||
|
||||
uint64 hwcap = getauxval(AT_HWCAP);
|
||||
uint64 hwcap2 = getauxval(AT_HWCAP2);
|
||||
|
||||
if (hwcap & HWCAP_ASIMD) feature_bitfield |= CPU_FEATURE_ASIMD_ARM;
|
||||
if (hwcap & HWCAP_ATOMICS) feature_bitfield |= CPU_FEATURE_ATOMICS_ARM;
|
||||
if (hwcap & HWCAP_PMULL) feature_bitfield |= CPU_FEATURE_PMULL_ARM;
|
||||
if (hwcap2 & HWCAP2_SVEPMULL) feature_bitfield |= CPU_FEATURE_SVEPMULL_ARM;
|
||||
if (hwcap & HWCAP_NEON) feature_bitfield |= CPU_FEATURE_NEON_ARM;
|
||||
if (hwcap & HWCAP_SVE) feature_bitfield |= CPU_FEATURE_SVE_ARM;
|
||||
if (hwcap2 & HWCAP2_SVE) feature_bitfield |= CPU_FEATURE_SVE2_ARM;
|
||||
if (hwcap & HWCAP_AES) feature_bitfield |= CPU_FEATURE_AES_ARM;
|
||||
if (hwcap & HWCAP_SHA1) feature_bitfield |= CPU_FEATURE_SHA1_ARM;
|
||||
if (hwcap & HWCAP_SHA2) feature_bitfield |= CPU_FEATURE_SHA2_ARM;
|
||||
if (hwcap & HWCAP_CRC32) feature_bitfield |= CPU_FEATURE_CRC32_ARM;
|
||||
|
||||
return feature_bitfield;
|
||||
}
|
||||
|
||||
void cpu_info_cache(int32_t level, CpuCacheInfo* cache) {
|
||||
uint32_t ccsidr; // Cache Size ID Register
|
||||
uint32_t line_size, associativity, num_sets;
|
||||
|
||||
cache->level = level;
|
||||
cache->size = 0;
|
||||
cache->ways = 0;
|
||||
cache->partitions = 1; // Typically 1 on ARM
|
||||
cache->sets = 0;
|
||||
cache->line_size = 0;
|
||||
|
||||
// Select cache level and type in CSSELR
|
||||
uint32_t csselr = level << 1; // Data or unified cache
|
||||
__asm__ volatile("msr csselr_el1, %0" : : "r" (csselr));
|
||||
__asm__ volatile("mrs %0, ccsidr_el1" : "=r" (ccsidr));
|
||||
|
||||
// Extract cache details from CCSIDR
|
||||
line_size = (ccsidr & 0x7) + 4; // Line size in log2 words
|
||||
associativity = ((ccsidr >> 3) & 0x3FF) + 1;
|
||||
num_sets = ((ccsidr >> 13) & 0x7FFF) + 1;
|
||||
|
||||
// Populate the cache structure
|
||||
cache->line_size = 1 << line_size; // Convert to bytes
|
||||
cache->ways = associativity;
|
||||
cache->sets = num_sets;
|
||||
cache->size = cache->ways * cache->sets * cache->line_size;
|
||||
}
|
||||
|
||||
#endif
|
||||
163
architecture/x86/CpuInfo.cpp
Normal file
163
architecture/x86/CpuInfo.cpp
Normal file
|
|
@ -0,0 +1,163 @@
|
|||
/**
|
||||
* Jingga
|
||||
*
|
||||
* @copyright Jingga
|
||||
* @license OMS License 2.0
|
||||
* @version 1.0.0
|
||||
* @link https://jingga.app
|
||||
*/
|
||||
#ifndef TOS_ARCHITECTURE_X86_CPU_INFO_C
|
||||
#define TOS_ARCHITECTURE_X86_CPU_INFO_C
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include "../../stdlib/Types.h"
|
||||
#include "../CpuInfo.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#include <intrin.h>
|
||||
|
||||
static inline
|
||||
void cpuid(int32 cpuInfo[4], int32 function_id) {
|
||||
__cpuidex(cpuInfo, function_id, 0);
|
||||
}
|
||||
#else
|
||||
/*
|
||||
#include <cpuid.h>
|
||||
|
||||
static inline
|
||||
void cpuid(int32 cpuInfo[4], int32 function_id) {
|
||||
__cpuid(function_id, cpuInfo[0], cpuInfo[1], cpuInfo[2], cpuInfo[3]);
|
||||
}
|
||||
*/
|
||||
|
||||
static inline
|
||||
void cpuid(int32 cpuInfo[4], int32 function_id) {
|
||||
__asm__ volatile(
|
||||
"cpuid"
|
||||
: "=a" (cpuInfo[0]), "=b" (cpuInfo[1]), "=c" (cpuInfo[2]), "=d" (cpuInfo[3])
|
||||
: "a" (function_id)
|
||||
);
|
||||
}
|
||||
#endif
|
||||
|
||||
inline
|
||||
int32 svcntw() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint64 cpu_info_features() {
|
||||
uint64 feature_bitfield = 0;
|
||||
int32 cpuInfo[4] = {0};
|
||||
|
||||
// Query function 0x00000001
|
||||
cpuid(cpuInfo, 0x00000001);
|
||||
uint32 ecx = (uint32) cpuInfo[2];
|
||||
uint32 edx = (uint32) cpuInfo[3];
|
||||
|
||||
// Map ECX features
|
||||
if (ecx & (1 << 0)) feature_bitfield |= CPU_FEATURE_SSE3;
|
||||
if (ecx & (1 << 1)) feature_bitfield |= CPU_FEATURE_PCLMULQDQ;
|
||||
if (ecx & (1 << 3)) feature_bitfield |= CPU_FEATURE_MONITOR;
|
||||
if (ecx & (1 << 9)) feature_bitfield |= CPU_FEATURE_SSSE3;
|
||||
if (ecx & (1 << 12)) feature_bitfield |= CPU_FEATURE_FMA;
|
||||
if (ecx & (1 << 13)) feature_bitfield |= CPU_FEATURE_CMPXCHG16B;
|
||||
if (ecx & (1 << 19)) feature_bitfield |= CPU_FEATURE_SSE41;
|
||||
if (ecx & (1 << 20)) feature_bitfield |= CPU_FEATURE_SSE42;
|
||||
if (ecx & (1 << 22)) feature_bitfield |= CPU_FEATURE_MOVBE;
|
||||
if (ecx & (1 << 23)) feature_bitfield |= CPU_FEATURE_POPCNT;
|
||||
if (ecx & (1 << 25)) feature_bitfield |= CPU_FEATURE_AES;
|
||||
if (ecx & (1 << 26)) feature_bitfield |= CPU_FEATURE_XSAVE;
|
||||
if (ecx & (1 << 27)) feature_bitfield |= CPU_FEATURE_OSXSAVE;
|
||||
if (ecx & (1 << 28)) feature_bitfield |= CPU_FEATURE_AVX;
|
||||
if (ecx & (1 << 29)) feature_bitfield |= CPU_FEATURE_F16C;
|
||||
if (ecx & (1 << 30)) feature_bitfield |= CPU_FEATURE_RDRAND;
|
||||
|
||||
// Map EDX features
|
||||
if (edx & (1 << 5)) feature_bitfield |= CPU_FEATURE_MSR;
|
||||
if (edx & (1 << 8)) feature_bitfield |= CPU_FEATURE_CX8;
|
||||
if (edx & (1 << 11)) feature_bitfield |= CPU_FEATURE_SEP;
|
||||
if (edx & (1 << 15)) feature_bitfield |= CPU_FEATURE_CMOV;
|
||||
if (edx & (1 << 19)) feature_bitfield |= CPU_FEATURE_CLFSH;
|
||||
if (edx & (1 << 23)) feature_bitfield |= CPU_FEATURE_MMX;
|
||||
if (edx & (1 << 24)) feature_bitfield |= CPU_FEATURE_FXSR;
|
||||
if (edx & (1 << 25)) feature_bitfield |= CPU_FEATURE_SSE;
|
||||
if (edx & (1 << 26)) feature_bitfield |= CPU_FEATURE_SSE2;
|
||||
|
||||
// Query function 0x00000007
|
||||
cpuid(cpuInfo, 0x00000007);
|
||||
uint32 ebx = (uint32) cpuInfo[1];
|
||||
uint32 ecx7 = (uint32) cpuInfo[2];
|
||||
|
||||
// Map EBX features
|
||||
if (ebx & (1 << 3)) feature_bitfield |= CPU_FEATURE_BMI1;
|
||||
if (ebx & (1 << 5)) feature_bitfield |= CPU_FEATURE_AVX2;
|
||||
if (ebx & (1 << 8)) feature_bitfield |= CPU_FEATURE_BMI2;
|
||||
if (ebx & (1 << 9)) feature_bitfield |= CPU_FEATURE_ERMS;
|
||||
if (ebx & (1 << 10)) feature_bitfield |= CPU_FEATURE_INVPCID;
|
||||
if (ebx & (1 << 16)) feature_bitfield |= CPU_FEATURE_AVX512F;
|
||||
if (ebx & (1 << 18)) feature_bitfield |= CPU_FEATURE_RDSEED;
|
||||
if (ebx & (1 << 19)) feature_bitfield |= CPU_FEATURE_ADX;
|
||||
if (ebx & (1 << 26)) feature_bitfield |= CPU_FEATURE_AVX512PF;
|
||||
if (ebx & (1 << 27)) feature_bitfield |= CPU_FEATURE_AVX512ER;
|
||||
if (ebx & (1 << 28)) feature_bitfield |= CPU_FEATURE_AVX512CD;
|
||||
if (ebx & (1 << 29)) feature_bitfield |= CPU_FEATURE_SHA;
|
||||
|
||||
|
||||
// Map ECX features
|
||||
if (ecx7 & (1 << 0)) feature_bitfield |= CPU_FEATURE_PREFETCHWT1;
|
||||
|
||||
// Query extended function 0x80000001
|
||||
cpuid(cpuInfo, 0x80000001);
|
||||
uint32 ecx81 = (uint32) cpuInfo[2];
|
||||
uint32 edx81 = (uint32) cpuInfo[3];
|
||||
|
||||
// Map ECX extended features
|
||||
if (ecx81 & (1 << 0)) feature_bitfield |= CPU_FEATURE_LAHF;
|
||||
if (ecx81 & (1 << 5)) feature_bitfield |= CPU_FEATURE_LZCNT;
|
||||
if (ecx81 & (1 << 6)) feature_bitfield |= CPU_FEATURE_ABM;
|
||||
if (ecx81 & (1 << 11)) feature_bitfield |= CPU_FEATURE_XOP;
|
||||
if (ecx81 & (1 << 21)) feature_bitfield |= CPU_FEATURE_TBM;
|
||||
|
||||
// Map EDX extended features
|
||||
if (edx81 & (1 << 11)) feature_bitfield |= CPU_FEATURE_SYSCALL;
|
||||
if (edx81 & (1 << 22)) feature_bitfield |= CPU_FEATURE_MMEXT;
|
||||
if (edx81 & (1 << 27)) feature_bitfield |= CPU_FEATURE_RDTSCP;
|
||||
if (edx81 & (1 << 30)) feature_bitfield |= CPU_FEATURE_3DNOWEXT;
|
||||
if (edx81 & (1 << 31)) feature_bitfield |= CPU_FEATURE_3DNOW;
|
||||
|
||||
return feature_bitfield;
|
||||
}
|
||||
|
||||
void cpu_info_cache(byte level, CpuCacheInfo* cache) {
|
||||
uint32 eax, ebx, ecx, edx;
|
||||
int32 type;
|
||||
|
||||
cache->level = level;
|
||||
cache->size = 0;
|
||||
cache->ways = 0;
|
||||
cache->partitions = 0;
|
||||
cache->sets = 0;
|
||||
cache->line_size = 0;
|
||||
|
||||
int32 regs[4];
|
||||
cpuid(regs, (0x04 << 8) | level);
|
||||
eax = regs[0];
|
||||
ebx = regs[1];
|
||||
ecx = regs[2];
|
||||
edx = regs[3];
|
||||
|
||||
type = (eax & 0x1F);
|
||||
|
||||
if (type == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
cache->ways = (byte) ((ebx >> 22) & 0x3FF) + 1;
|
||||
cache->partitions = (byte) ((ebx >> 12) & 0x3FF) + 1;
|
||||
cache->line_size = (uint16) (ebx & 0xFFF) + 1;
|
||||
cache->sets = ecx + 1;
|
||||
cache->size = cache->ways * cache->partitions * cache->line_size * cache->sets;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -11,19 +11,49 @@
|
|||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "../../stdlib/Types.h"
|
||||
#include "../../system/SystemInfo.h"
|
||||
#include "../../architecture/CpuInfo.cpp"
|
||||
|
||||
#include <locale.h>
|
||||
#include <cpuid.h>
|
||||
#include <sys/resource.h>
|
||||
|
||||
#if __aarch64__
|
||||
#include "../../stdlib/SIMD_Helper.h"
|
||||
#else
|
||||
#include "../../stdlib/sve/SVE_Helper.h"
|
||||
#endif
|
||||
// @todo Implement own line by line file reading
|
||||
|
||||
// @todo implement for arm?
|
||||
uint64 system_private_memory_usage()
|
||||
{
|
||||
struct rusage usage;
|
||||
if (getrusage(RUSAGE_SELF, &usage) == 0) {
|
||||
return usage.ru_maxrss * 1024; // Convert from kilobytes to bytes
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
uint64 system_app_memory_usage()
|
||||
{
|
||||
FILE* fp = fopen("/proc/self/smaps", "r");
|
||||
if (!fp) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint64 total_size = 0;
|
||||
char line[256];
|
||||
while (fgets(line, sizeof(line), fp)) {
|
||||
if (str_compare(line, "Private_Dirty:", sizeof("Private_Dirty:") - 1) == 0) {
|
||||
uint64 private_dirty;
|
||||
if (sscanf(line, "Private_Dirty: %lu kB", &private_dirty) == 1) {
|
||||
total_size += private_dirty * 1024; // Convert from kB to bytes
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
|
||||
return total_size;
|
||||
}
|
||||
|
||||
uint16 system_language_code()
|
||||
{
|
||||
|
|
@ -39,263 +69,87 @@ uint16 system_country_code()
|
|||
return (localeName[3] << 8) | localeName[4];
|
||||
}
|
||||
|
||||
void cache_info_get(int32 level, CpuCacheInfo* cache) {
|
||||
uint32 eax, ebx, ecx, edx;
|
||||
int32 type;
|
||||
|
||||
cache->level = level;
|
||||
cache->size = 0;
|
||||
cache->ways = 0;
|
||||
cache->partitions = 0;
|
||||
cache->sets = 0;
|
||||
cache->line_size = 0;
|
||||
|
||||
__cpuid_count(4, level, eax, ebx, ecx, edx);
|
||||
|
||||
type = (eax & 0x1F);
|
||||
|
||||
if (type == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
cache->ways = ((ebx >> 22) & 0x3FF) + 1;
|
||||
cache->line_size = (ebx & 0xFFF) + 1;
|
||||
cache->partitions = ((ebx >> 12) & 0x3FF) + 1;
|
||||
cache->sets = ecx + 1;
|
||||
cache->size = cache->ways * cache->partitions * cache->line_size * cache->sets;
|
||||
}
|
||||
|
||||
void mainboard_info_get(MainboardInfo* info) {
|
||||
info->name[63] = '\0';
|
||||
info->serial_number[63] = '\0';
|
||||
|
||||
HRESULT hres;
|
||||
FILE *fp;
|
||||
|
||||
// Step 1: Initialize COM library
|
||||
hres = CoInitializeEx(0, COINIT_MULTITHREADED);
|
||||
if (FAILED(hres)) {
|
||||
return;
|
||||
fp = fopen("/sys/class/dmi/id/board_name", "r");
|
||||
if (fp) {
|
||||
fgets(info->name, 64, fp);
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
// Step 2: Set general COM security levels
|
||||
hres = CoInitializeSecurity(
|
||||
NULL,
|
||||
-1,
|
||||
NULL,
|
||||
NULL,
|
||||
RPC_C_AUTHN_LEVEL_DEFAULT,
|
||||
RPC_C_IMP_LEVEL_IMPERSONATE,
|
||||
NULL,
|
||||
EOAC_NONE,
|
||||
NULL
|
||||
);
|
||||
if (FAILED(hres)) {
|
||||
CoUninitialize();
|
||||
return;
|
||||
fp = fopen("/sys/class/dmi/id/board_serial", "r");
|
||||
if (fp) {
|
||||
fgets(info->serial_number, 64, fp);
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
// Step 3: Obtain initial locator to WMI
|
||||
IWbemLocator *pLoc = NULL;
|
||||
hres = CoCreateInstance(
|
||||
CLSID_WbemLocator,
|
||||
0,
|
||||
CLSCTX_INPROC_SERVER,
|
||||
IID_IWbemLocator,
|
||||
(LPVOID *)&pLoc
|
||||
);
|
||||
if (FAILED(hres)) {
|
||||
CoUninitialize();
|
||||
return;
|
||||
}
|
||||
|
||||
// Step 4: Connect to WMI through IWbemLocator::ConnectServer
|
||||
IWbemServices *pSvc = NULL;
|
||||
hres = pLoc->ConnectServer(
|
||||
_bstr_t(L"ROOT\\CIMV2"),
|
||||
NULL,
|
||||
NULL,
|
||||
0,
|
||||
NULL,
|
||||
0,
|
||||
0,
|
||||
&pSvc
|
||||
);
|
||||
if (FAILED(hres)) {
|
||||
pLoc->Release();
|
||||
CoUninitialize();
|
||||
return;
|
||||
}
|
||||
|
||||
// Step 5: Set security levels on the proxy
|
||||
hres = CoSetProxyBlanket(
|
||||
pSvc,
|
||||
RPC_C_AUTHN_WINNT,
|
||||
RPC_C_AUTHZ_NONE,
|
||||
NULL,
|
||||
RPC_C_AUTHN_LEVEL_CALL,
|
||||
RPC_C_IMP_LEVEL_IMPERSONATE,
|
||||
NULL,
|
||||
EOAC_NONE
|
||||
);
|
||||
if (FAILED(hres)) {
|
||||
pSvc->Release();
|
||||
pLoc->Release();
|
||||
CoUninitialize();
|
||||
return;
|
||||
}
|
||||
|
||||
// Step 6: Use the IWbemServices pointer to make a WMI query
|
||||
IEnumWbemClassObject* pEnumerator = NULL;
|
||||
hres = pSvc->ExecQuery(
|
||||
bstr_t("WQL"),
|
||||
bstr_t("SELECT * FROM Win32_BaseBoard"),
|
||||
WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
|
||||
NULL,
|
||||
&pEnumerator
|
||||
);
|
||||
if (FAILED(hres)) {
|
||||
pSvc->Release();
|
||||
pLoc->Release();
|
||||
CoUninitialize();
|
||||
return;
|
||||
}
|
||||
|
||||
// Step 7: Retrieve the data
|
||||
IWbemClassObject *pclsObj = NULL;
|
||||
ULONG uReturn = 0;
|
||||
while (pEnumerator) {
|
||||
HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn);
|
||||
if (0 == uReturn) {
|
||||
break;
|
||||
}
|
||||
|
||||
VARIANT vtProp;
|
||||
hr = pclsObj->Get(L"Product", 0, &vtProp, 0, 0);
|
||||
if (SUCCEEDED(hr)) {
|
||||
snprintf(info->name, 64, "%S", vtProp.bstrVal);
|
||||
VariantClear(&vtProp);
|
||||
}
|
||||
|
||||
hr = pclsObj->Get(L"SerialNumber", 0, &vtProp, 0, 0);
|
||||
if (SUCCEEDED(hr)) {
|
||||
snprintf(info->serial_number, 63, "%S", vtProp.bstrVal);
|
||||
info->serial_number[64] = '\0';
|
||||
|
||||
VariantClear(&vtProp);
|
||||
}
|
||||
|
||||
pclsObj->Release();
|
||||
}
|
||||
|
||||
// Clean up
|
||||
pSvc->Release();
|
||||
pLoc->Release();
|
||||
pEnumerator->Release();
|
||||
CoUninitialize();
|
||||
info->name[strcspn(info->name, "\n")] = '\0';
|
||||
info->serial_number[strcspn(info->serial_number, "\n")] = '\0';
|
||||
}
|
||||
|
||||
int network_info_get(NetworkInfo* info) {
|
||||
WSADATA wsaData;
|
||||
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
DWORD dwSize = 0;
|
||||
PIP_ADAPTER_ADDRESSES pAdapterAddresses = NULL;
|
||||
PIP_ADAPTER_ADDRESSES pAdapter = NULL;
|
||||
|
||||
// Get the size of the adapter addresses buffer
|
||||
if (GetAdaptersAddresses(AF_UNSPEC, 0, NULL, NULL, &dwSize) == ERROR_BUFFER_OVERFLOW) {
|
||||
pAdapterAddresses = (PIP_ADAPTER_ADDRESSES) malloc(dwSize);
|
||||
if (pAdapterAddresses == NULL) {
|
||||
WSACleanup();
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
WSACleanup();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Get the adapter addresses
|
||||
if (GetAdaptersAddresses(AF_UNSPEC, 0, NULL, pAdapterAddresses, &dwSize) != NO_ERROR) {
|
||||
free(pAdapterAddresses);
|
||||
WSACleanup();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32 network_info_get(NetworkInfo* info) {
|
||||
char path[256];
|
||||
struct stat st;
|
||||
int32 i = 0;
|
||||
|
||||
// Iterate over the adapters and print their MAC addresses
|
||||
pAdapter = pAdapterAddresses;
|
||||
while (pAdapter && i < 4) {
|
||||
if (pAdapter->PhysicalAddressLength != 0) {
|
||||
info[i].slot[63] = '\0';
|
||||
for (i = 0; i < 4; i++) {
|
||||
sprintf_fast(path, "/sys/class/net/eth%d", i);
|
||||
|
||||
if (stat(path, &st) == 0) {
|
||||
// Read MAC address
|
||||
sprintf_fast(path, "/sys/class/net/eth%d/address", i);
|
||||
FILE *mac_file = fopen(path, "r");
|
||||
if (mac_file) {
|
||||
fscanf(mac_file, "%s", info[i].mac);
|
||||
fclose(mac_file);
|
||||
}
|
||||
|
||||
// Read interface name
|
||||
sprintf_fast(path, "/sys/class/net/eth%d/ifindex", i);
|
||||
FILE *index_file = fopen(path, "r");
|
||||
if (index_file) {
|
||||
fscanf(index_file, "%s", info[i].slot);
|
||||
fclose(index_file);
|
||||
}
|
||||
|
||||
info[i].mac[23] = '\0';
|
||||
|
||||
memcpy(info[i].mac, pAdapter->PhysicalAddress, 8);
|
||||
wcstombs(info[i].slot, pAdapter->FriendlyName, 63);
|
||||
|
||||
++i;
|
||||
info[i].slot[63] = '\0';
|
||||
}
|
||||
|
||||
pAdapter = pAdapter->Next;
|
||||
}
|
||||
|
||||
free(pAdapterAddresses);
|
||||
WSACleanup();
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
void cpu_info_get(CpuInfo* info) {
|
||||
int32 temp;
|
||||
info->simd.sse = (temp = max_sse_supported()) > 9 ? temp / 10.0f : temp;
|
||||
info->simd.avx256 = max_avx256_supported();
|
||||
info->simd.avx512 = max_avx512_supported();
|
||||
|
||||
cache_info_get(1, &info->cache[0]);
|
||||
cache_info_get(2, &info->cache[1]);
|
||||
cache_info_get(3, &info->cache[2]);
|
||||
cache_info_get(4, &info->cache[3]);
|
||||
|
||||
SYSTEM_INFO sys_info;
|
||||
GetSystemInfo(&sys_info);
|
||||
info->page_size = sys_info.dwPageSize;
|
||||
|
||||
int32 cpuInfo[4] = { 0 };
|
||||
__cpuid(cpuInfo, 0);
|
||||
|
||||
memset(info->vendor, 0, sizeof(info->vendor));
|
||||
*((int*)info->vendor) = cpuInfo[1];
|
||||
*((int*)(info->vendor + 4)) = cpuInfo[3];
|
||||
*((int*)(info->vendor + 8)) = cpuInfo[2];
|
||||
info->vendor[12] = '\0';
|
||||
|
||||
__cpuid(cpuInfo, 0x80000002);
|
||||
memcpy(info->brand, cpuInfo, sizeof(cpuInfo));
|
||||
__cpuid(cpuInfo, 0x80000003);
|
||||
memcpy(info->brand + 16, cpuInfo, sizeof(cpuInfo));
|
||||
__cpuid(cpuInfo, 0x80000004);
|
||||
memcpy(info->brand + 32, cpuInfo, sizeof(cpuInfo));
|
||||
info->brand[48] = '\0';
|
||||
|
||||
__cpuid(cpuInfo, 1);
|
||||
info->model = (cpuInfo[0] >> 4) & 0xF;
|
||||
info->family = (cpuInfo[0] >> 8) & 0xF;
|
||||
|
||||
DWORD bufSize = sizeof(DWORD);
|
||||
HKEY hKey;
|
||||
long lError = RegOpenKeyExA(
|
||||
HKEY_LOCAL_MACHINE,
|
||||
"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0",
|
||||
0, KEY_READ, &hKey
|
||||
);
|
||||
|
||||
if (lError == ERROR_SUCCESS) {
|
||||
RegQueryValueExA(hKey, "~MHz", NULL, NULL, (LPBYTE) &(info->mhz), &bufSize);
|
||||
FILE* fp = fopen("/proc/cpuinfo", "r");
|
||||
if (!fp) {
|
||||
return;
|
||||
}
|
||||
|
||||
RegCloseKey(hKey);
|
||||
char line[256];
|
||||
|
||||
while (fgets(line, sizeof(line), fp)) {
|
||||
if (str_compare(line, "vendor_id", 9) == 0) {
|
||||
sscanf(line, "vendor_id : %s", info->vendor);
|
||||
} else if (str_compare(line, "model", 5) == 0) {
|
||||
sscanf(line, "model : %d", &info->model);
|
||||
} else if (str_compare(line, "cpu MHz", 7) == 0) {
|
||||
sscanf(line, "cpu MHz : %d", &info->mhz);
|
||||
} else if (str_compare(line, "cpu cores", 10) == 0) {
|
||||
sscanf(line, "cpu cores : %d", &info->thread_coun);
|
||||
} else if (str_compare(line, "model name", 10) == 0) {
|
||||
sscanf(line, "model name : %63[^\n]", info->brand);
|
||||
}
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
|
||||
info->family = 0;
|
||||
info->page_size = 4096; // Assuming standard page size of 4KB in Linux
|
||||
}
|
||||
|
||||
void os_info_get(OSInfo* info) {
|
||||
|
|
@ -303,167 +157,111 @@ void os_info_get(OSInfo* info) {
|
|||
memcpy(info->name, "Linux", sizeof("Linux"));
|
||||
info->major = 0;
|
||||
info->minor = 0;
|
||||
|
||||
info->vendor[sizeof("Linux")] = '\0';
|
||||
info->name[sizeof("Linux")] = '\0';
|
||||
}
|
||||
|
||||
void ram_info_get(RamInfo* info) {
|
||||
MEMORYSTATUSEX statex;
|
||||
statex.dwLength = sizeof(statex);
|
||||
GlobalMemoryStatusEx(&statex);
|
||||
info->memory = (int) (statex.ullTotalPhys / (1024 * 1024));
|
||||
FILE* fp = fopen("/proc/meminfo", "r");
|
||||
if (fp == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
char line[256];
|
||||
uint32 total_memory = 0;
|
||||
|
||||
while (fgets(line, sizeof(line), fp)) {
|
||||
if (sscanf(line, "MemTotal: %u kB", &total_memory) == 1) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
|
||||
// Convert memory from kB to MB
|
||||
info->memory = total_memory / 1024;
|
||||
}
|
||||
|
||||
uint32 gpu_info_get(GpuInfo* info) {
|
||||
IDXGIFactory *pFactory = NULL;
|
||||
IDXGIAdapter *pAdapter = NULL;
|
||||
DXGI_ADAPTER_DESC adapterDesc;
|
||||
|
||||
HRESULT hr = CreateDXGIFactory(__uuidof(IDXGIFactory), (void**)&pFactory);
|
||||
if (FAILED(hr)) {
|
||||
FILE* fp = popen("lspci | grep VGA", "r");
|
||||
if (fp == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32 i = 0;
|
||||
while (pFactory->EnumAdapters(i, &pAdapter) != DXGI_ERROR_NOT_FOUND && i < 2) {
|
||||
hr = pAdapter->GetDesc(&adapterDesc);
|
||||
if (FAILED(hr)) {
|
||||
pAdapter->Release();
|
||||
break;
|
||||
uint32 count = 0;
|
||||
char line[256];
|
||||
|
||||
while (fgets(line, sizeof(line), fp)) {
|
||||
if (count >= 2) break;
|
||||
|
||||
// Assuming that the first part of the line contains the name of the GPU
|
||||
char* gpu_name = strtok(line, ":");
|
||||
if (gpu_name) {
|
||||
sprintf_fast(info[count].name, sizeof(info[count].name), "%s", gpu_name);
|
||||
}
|
||||
|
||||
wcstombs(info[i].name, adapterDesc.Description, 63);
|
||||
info[i].name[63] = '\0';
|
||||
info[i].vram = (int) (adapterDesc.DedicatedVideoMemory / (1024 * 1024));
|
||||
// @todo this is Wrong
|
||||
info[count].vram = 2048;
|
||||
|
||||
pAdapter->Release();
|
||||
i++;
|
||||
count++;
|
||||
}
|
||||
|
||||
pFactory->Release();
|
||||
fclose(fp);
|
||||
|
||||
return i;
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
void display_info_get_primary(DisplayInfo* info) {
|
||||
FILE* fp = popen("xrandr --current", "r");
|
||||
if (fp == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
char line[256];
|
||||
while (fgets(line, sizeof(line), fp)) {
|
||||
if (strstr(line, "primary")) {
|
||||
// Example of a line containing display info: "HDMI-1 connected 1920x1080+0+0 60.00*+"
|
||||
char name[64];
|
||||
uint32 width, height, hz;
|
||||
if (sscanf(line, "%s connected %dx%d+%*d+%*d %d", name, &width, &height, &hz) == 4) {
|
||||
str_copy_short(info->name, name);
|
||||
info->width = width;
|
||||
info->height = height;
|
||||
info->hz = hz;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
uint32 display_info_get(DisplayInfo* info) {
|
||||
DISPLAY_DEVICEA device;
|
||||
DEVMODEA mode;
|
||||
|
||||
device.cb = sizeof(DISPLAY_DEVICEA);
|
||||
|
||||
uint32 i = 0;
|
||||
|
||||
while (EnumDisplayDevicesA(NULL, i, &device, 0)) {
|
||||
mode.dmSize = sizeof(mode);
|
||||
|
||||
if (EnumDisplaySettingsA(device.DeviceName, ENUM_CURRENT_SETTINGS, &mode)) {
|
||||
str_copy_short(info[i].name, device.DeviceName);
|
||||
info[i].width = mode.dmPelsWidth;
|
||||
info[i].height = mode.dmPelsHeight;
|
||||
info[i].hz = mode.dmDisplayFrequency;
|
||||
}
|
||||
|
||||
++i;
|
||||
FILE* fp = popen("xrandr --current", "r");
|
||||
if (fp == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
char line[256];
|
||||
uint32 count = 0;
|
||||
|
||||
void system_info_render(char* buf, const SystemInfo* info) {
|
||||
const char avx512[8][12] = {
|
||||
"AVX-512F",
|
||||
"AVX-512DQ",
|
||||
"AVX-512IFMA",
|
||||
"AVX-512PF",
|
||||
"AVX-512ER",
|
||||
"AVX-512CD",
|
||||
"AVX-512BW",
|
||||
"AVX-512VL"
|
||||
};
|
||||
while (fgets(line, sizeof(line), fp)) {
|
||||
if (strstr(line, "connected")) {
|
||||
// Example: "HDMI-1 connected 1920x1080+0+0 60.00*+"
|
||||
char name[64];
|
||||
uint32 width, height, hz;
|
||||
if (sscanf(line, "%s connected %dx%d+%*d+%*d %d", name, &width, &height, &hz) == 4) {
|
||||
str_copy_short(info[count].name, name);
|
||||
info[count].width = width;
|
||||
info[count].height = height;
|
||||
info[count].hz = hz;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sprintf_s(
|
||||
buf,
|
||||
"OS:\n"
|
||||
"==============\n"
|
||||
"Vendor: %s\n" "Name: %s\n" "Major: %d\n" "Minor: %d\n"
|
||||
"\n"
|
||||
"Mainboard:\n"
|
||||
"==============\n"
|
||||
"Name: %s\n" "SN: %s\n"
|
||||
"\n"
|
||||
"Network:\n"
|
||||
"==============\n"
|
||||
"Slot: %s\n" "MAC: %02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X\n"
|
||||
"\n"
|
||||
"Slot: %s\n" "MAC: %02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X\n"
|
||||
"\n"
|
||||
"Slot: %s\n" "MAC: %02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X\n"
|
||||
"\n"
|
||||
"Slot: %s\n" "MAC: %02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X\n"
|
||||
"\n"
|
||||
"CPU:\n"
|
||||
"==============\n"
|
||||
"Hardware\n" "Vendor: %s\n" "Brand: %s\n" "Model: %d\n" "Family: %d\n" "Mhz: %d\n" "Page Size: %d\n"
|
||||
"\n"
|
||||
"Cache:\n"
|
||||
"L1: Size %d Line %d\n"
|
||||
"L2: Size %d Line %d\n"
|
||||
"L3: Size %d Line %d\n"
|
||||
"L4: Size %d Line %d\n"
|
||||
"\n"
|
||||
"SIMD:\n" "SSE: %.1f\n" "AVX256: %d\n" "AVX512: %s\n"
|
||||
"\n"
|
||||
"GPU:\n"
|
||||
"==============\n"
|
||||
"Name: %s\n" "VRAM: %d\n"
|
||||
"Name: %s\n" "VRAM: %d\n"
|
||||
"\n"
|
||||
"Display:\n"
|
||||
"==============\n"
|
||||
"Name: %s\n" "Width: %d\n" "Height: %d\n" "Hz: %d\n"
|
||||
"Name: %s\n" "Width: %d\n" "Height: %d\n" "Hz: %d\n"
|
||||
"Name: %s\n" "Width: %d\n" "Height: %d\n" "Hz: %d\n"
|
||||
"Name: %s\n" "Width: %d\n" "Height: %d\n" "Hz: %d\n"
|
||||
"Name: %s\n" "Width: %d\n" "Height: %d\n" "Hz: %d\n"
|
||||
"Name: %s\n" "Width: %d\n" "Height: %d\n" "Hz: %d\n"
|
||||
"\n"
|
||||
"RAM:\n"
|
||||
"==============\n"
|
||||
"Memory: %d MB",
|
||||
info->os.vendor, info->os.name, info->os.major, info->os.minor,
|
||||
info->mainboard.name, info->mainboard.serial_number,
|
||||
info->network[0].slot, info->network[0].mac[0], info->network[0].mac[1], info->network[0].mac[2], info->network[0].mac[3], info->network[0].mac[4], info->network[0].mac[5], info->network[0].mac[6], info->network[0].mac[7],
|
||||
info->network_count < 2 ? "" : info->network[1].slot, info->network_count < 2 ? 0 : info->network[1].mac[0], info->network_count < 2 ? 0 : info->network[1].mac[1], info->network_count < 2 ? 0 : info->network[1].mac[2], info->network_count < 2 ? 0 : info->network[1].mac[3], info->network_count < 2 ? 0 : info->network[1].mac[4], info->network_count < 2 ? 0 : info->network[1].mac[5], info->network_count < 2 ? 0 : info->network[1].mac[6], info->network_count < 2 ? 0 : info->network[1].mac[7],
|
||||
info->network_count < 3 ? "" : info->network[2].slot, info->network_count < 3 ? 0 : info->network[2].mac[0], info->network_count < 3 ? 0 : info->network[2].mac[1], info->network_count < 3 ? 0 : info->network[2].mac[2], info->network_count < 3 ? 0 : info->network[2].mac[3], info->network_count < 3 ? 0 : info->network[2].mac[4], info->network_count < 3 ? 0 : info->network[2].mac[5], info->network_count < 3 ? 0 : info->network[2].mac[6], info->network_count < 3 ? 0 : info->network[2].mac[7],
|
||||
info->network_count < 4 ? "" : info->network[3].slot, info->network_count < 4 ? 0 : info->network[3].mac[0], info->network_count < 4 ? 0 : info->network[3].mac[1], info->network_count < 4 ? 0 : info->network[3].mac[2], info->network_count < 4 ? 0 : info->network[3].mac[3], info->network_count < 4 ? 0 : info->network[3].mac[4], info->network_count < 4 ? 0 : info->network[3].mac[5], info->network_count < 4 ? 0 : info->network[3].mac[6], info->network_count < 4 ? 0 : info->network[3].mac[7],
|
||||
info->cpu.vendor, info->cpu.brand, info->cpu.model, info->cpu.family, info->cpu.mhz, info->cpu.page_size,
|
||||
info->cpu.cache[0].size, info->cpu.cache[0].line_size,
|
||||
info->cpu.cache[1].size, info->cpu.cache[1].line_size,
|
||||
info->cpu.cache[2].size, info->cpu.cache[2].line_size,
|
||||
info->cpu.cache[3].size, info->cpu.cache[3].line_size,
|
||||
info->cpu.simd.sse, info->cpu.simd.avx256, info->cpu.simd.avx512 > 0 ? avx512[info->cpu.simd.avx512 - 1] : "0",
|
||||
info->gpu[0].name, info->gpu[0].vram,
|
||||
info->gpu_count < 2 ? "" : info->gpu[1].name, info->gpu_count < 2 ? 0 : info->gpu[1].vram,
|
||||
info->display[0].name, info->display[0].width, info->display[0].height, info->display[0].hz,
|
||||
info->display_count < 2 ? "" : info->display[1].name, info->display_count < 2 ? 0 : info->display[1].width, info->display_count < 2 ? 0 : info->display[1].height, info->display_count < 2 ? 0 : info->display[1].hz,
|
||||
info->display_count < 3 ? "" : info->display[2].name, info->display_count < 3 ? 0 : info->display[2].width, info->display_count < 3 ? 0 : info->display[2].height, info->display_count < 3 ? 0 : info->display[2].hz,
|
||||
info->display_count < 4 ? "" : info->display[3].name, info->display_count < 4 ? 0 : info->display[3].width, info->display_count < 4 ? 0 : info->display[3].height, info->display_count < 4 ? 0 : info->display[3].hz,
|
||||
info->display_count < 5 ? "" : info->display[4].name, info->display_count < 5 ? 0 : info->display[4].width, info->display_count < 5 ? 0 : info->display[4].height, info->display_count < 5 ? 0 : info->display[4].hz,
|
||||
info->display_count < 6 ? "" : info->display[5].name, info->display_count < 6 ? 0 : info->display[5].width, info->display_count < 6 ? 0 : info->display[5].height, info->display_count < 6 ? 0 : info->display[5].hz,
|
||||
info->ram.memory
|
||||
);
|
||||
}
|
||||
fclose(fp);
|
||||
|
||||
void system_info_get(SystemInfo* info)
|
||||
{
|
||||
os_info_get(&info->os);
|
||||
mainboard_info_get(&info->mainboard);
|
||||
info->network_count = network_info_get(info->network);
|
||||
cpu_info_get(&info->cpu);
|
||||
ram_info_get(&info->ram);
|
||||
info->gpu_count = gpu_info_get(info->gpu);
|
||||
info->display_count = display_info_get(info->display);
|
||||
return count;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -6,8 +6,8 @@
|
|||
* @version 1.0.0
|
||||
* @link https://jingga.app
|
||||
*/
|
||||
#ifndef TOS_UTILS_FAST_PIPES_H
|
||||
#define TOS_UTILS_FAST_PIPES_H
|
||||
#ifndef TOS_PLATFORM_WIN32_FAST_PIPES_H
|
||||
#define TOS_PLATFORM_WIN32_FAST_PIPES_H
|
||||
|
||||
#include "../stdlib/Types.h"
|
||||
|
||||
|
|
|
|||
|
|
@ -12,7 +12,9 @@
|
|||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include "../../stdlib/Types.h"
|
||||
#include "../../utils/StringUtils.h"
|
||||
#include "../../system/SystemInfo.h"
|
||||
#include "../../architecture/CpuInfo.cpp"
|
||||
|
||||
#include <psapi.h>
|
||||
#include <winsock2.h>
|
||||
|
|
@ -27,12 +29,6 @@
|
|||
#include <wingdi.h>
|
||||
#include <hidsdi.h>
|
||||
|
||||
#if __aarch64__
|
||||
#include "../../stdlib/sve/SVE_Helper.h"
|
||||
#else
|
||||
#include "../../stdlib/SIMD_Helper.h"
|
||||
#endif
|
||||
|
||||
// @performance Do we really need all these libs, can't we simplify that?!
|
||||
#include <intrin.h>
|
||||
#pragma comment(lib, "Advapi32.lib")
|
||||
|
|
@ -42,8 +38,6 @@
|
|||
#pragma comment(lib, "dxgi.lib")
|
||||
#pragma comment(lib, "Ws2_32.lib")
|
||||
|
||||
// @todo implement for arm?
|
||||
|
||||
uint64 system_private_memory_usage()
|
||||
{
|
||||
PROCESS_MEMORY_COUNTERS_EX pmc;
|
||||
|
|
@ -99,37 +93,6 @@ uint16 system_country_code()
|
|||
return (local_name[3] << 8) | local_name[4];
|
||||
}
|
||||
|
||||
void cache_info_get(int32 level, CpuCacheInfo* cache) {
|
||||
uint32 eax, ebx, ecx, edx;
|
||||
int32 type;
|
||||
|
||||
cache->level = level;
|
||||
cache->size = 0;
|
||||
cache->ways = 0;
|
||||
cache->partitions = 0;
|
||||
cache->sets = 0;
|
||||
cache->line_size = 0;
|
||||
|
||||
int32 regs[4];
|
||||
__cpuidex(regs, 4, level);
|
||||
eax = regs[0];
|
||||
ebx = regs[1];
|
||||
ecx = regs[2];
|
||||
edx = regs[3];
|
||||
|
||||
type = (eax & 0x1F);
|
||||
|
||||
if (type == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
cache->ways = ((ebx >> 22) & 0x3FF) + 1;
|
||||
cache->line_size = (ebx & 0xFFF) + 1;
|
||||
cache->partitions = ((ebx >> 12) & 0x3FF) + 1;
|
||||
cache->sets = ecx + 1;
|
||||
cache->size = cache->ways * cache->partitions * cache->line_size * cache->sets;
|
||||
}
|
||||
|
||||
void mainboard_info_get(MainboardInfo* info) {
|
||||
info->name[63] = '\0';
|
||||
info->serial_number[63] = '\0';
|
||||
|
|
@ -242,13 +205,15 @@ void mainboard_info_get(MainboardInfo* info) {
|
|||
VARIANT vtProp;
|
||||
hr = pclsObj->Get(L"Product", 0, &vtProp, 0, 0);
|
||||
if (SUCCEEDED(hr)) {
|
||||
snprintf(info->name, 64, "%S", vtProp.bstrVal);
|
||||
wchar_to_char(vtProp.bstrVal);
|
||||
sprintf_fast(info->name, sizeof(info->name), "%s", vtProp.bstrVal);
|
||||
VariantClear(&vtProp);
|
||||
}
|
||||
|
||||
hr = pclsObj->Get(L"SerialNumber", 0, &vtProp, 0, 0);
|
||||
if (SUCCEEDED(hr)) {
|
||||
snprintf(info->serial_number, 63, "%S", vtProp.bstrVal);
|
||||
wchar_to_char(vtProp.bstrVal);
|
||||
sprintf_fast(info->serial_number, sizeof(info->serial_number), "%s", vtProp.bstrVal);
|
||||
info->serial_number[64] = '\0';
|
||||
|
||||
VariantClear(&vtProp);
|
||||
|
|
@ -264,7 +229,7 @@ void mainboard_info_get(MainboardInfo* info) {
|
|||
CoUninitialize();
|
||||
}
|
||||
|
||||
int network_info_get(NetworkInfo* info) {
|
||||
int32 network_info_get(NetworkInfo* info) {
|
||||
WSADATA wsaData;
|
||||
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
|
||||
return 0;
|
||||
|
|
@ -319,22 +284,17 @@ int network_info_get(NetworkInfo* info) {
|
|||
}
|
||||
|
||||
void cpu_info_get(CpuInfo* info) {
|
||||
info->simd.sse = max_sse_supported();
|
||||
info->simd.avx256 = max_avx256_supported();
|
||||
info->simd.avx512 = max_avx512_supported();
|
||||
info->simd.sve = max_sve_supported();
|
||||
info->simd.neon = max_neon_supported();
|
||||
info->simd.abm = supports_abm();
|
||||
info->features = cpu_info_features();
|
||||
|
||||
cache_info_get(1, &info->cache[0]);
|
||||
cache_info_get(2, &info->cache[1]);
|
||||
cache_info_get(3, &info->cache[2]);
|
||||
cache_info_get(4, &info->cache[3]);
|
||||
cpu_info_cache(1, &info->cache[0]);
|
||||
cpu_info_cache(2, &info->cache[1]);
|
||||
cpu_info_cache(3, &info->cache[2]);
|
||||
cpu_info_cache(4, &info->cache[3]);
|
||||
|
||||
SYSTEM_INFO sys_info;
|
||||
GetSystemInfo(&sys_info);
|
||||
info->thread_count = sys_info.dwNumberOfProcessors;
|
||||
info->page_size = sys_info.dwPageSize;
|
||||
info->thread_count = (byte) sys_info.dwNumberOfProcessors;
|
||||
info->page_size = (uint16) sys_info.dwPageSize;
|
||||
|
||||
int32 cpuInfo[4] = { 0 };
|
||||
__cpuid(cpuInfo, 0);
|
||||
|
|
@ -376,32 +336,25 @@ void os_info_get(OSInfo* info) {
|
|||
info->vendor[15] = '\0';
|
||||
info->name[63] = '\0';
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
OSVERSIONINFOEXW version_info;
|
||||
memset(&version_info, 0, sizeof(OSVERSIONINFOEXW));
|
||||
version_info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXW);
|
||||
NTSTATUS(WINAPI *RtlGetVersion)(OSVERSIONINFOEXW*) = (NTSTATUS(WINAPI *)(OSVERSIONINFOEXW*))GetProcAddress(GetModuleHandleW(L"ntdll.dll"), "RtlGetVersion");
|
||||
if (RtlGetVersion != nullptr) {
|
||||
RtlGetVersion(&version_info);
|
||||
}
|
||||
OSVERSIONINFOEXW version_info;
|
||||
memset(&version_info, 0, sizeof(OSVERSIONINFOEXW));
|
||||
version_info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXW);
|
||||
NTSTATUS(WINAPI *RtlGetVersion)(OSVERSIONINFOEXW*) = (NTSTATUS(WINAPI *)(OSVERSIONINFOEXW*))GetProcAddress(GetModuleHandleW(L"ntdll.dll"), "RtlGetVersion");
|
||||
if (RtlGetVersion != nullptr) {
|
||||
RtlGetVersion(&version_info);
|
||||
}
|
||||
|
||||
memcpy(info->vendor, "Microsoft", sizeof("Microsoft"));
|
||||
memcpy(info->name, "Windows", sizeof("Windows"));
|
||||
info->major = version_info.dwMajorVersion;
|
||||
info->minor = version_info.dwMinorVersion;
|
||||
#else
|
||||
memcpy(info->vendor, "Linux", sizeof("Linux"));
|
||||
memcpy(info->name, "Linux", sizeof("Linux"));
|
||||
info->major = 0;
|
||||
info->minor = 0;
|
||||
#endif
|
||||
memcpy(info->vendor, "Microsoft", sizeof("Microsoft"));
|
||||
memcpy(info->name, "Windows", sizeof("Windows"));
|
||||
info->major = version_info.dwMajorVersion;
|
||||
info->minor = version_info.dwMinorVersion;
|
||||
}
|
||||
|
||||
void ram_info_get(RamInfo* info) {
|
||||
MEMORYSTATUSEX statex;
|
||||
statex.dwLength = sizeof(statex);
|
||||
GlobalMemoryStatusEx(&statex);
|
||||
info->memory = (int) (statex.ullTotalPhys / (1024 * 1024));
|
||||
info->memory = (uint32) (statex.ullTotalPhys / (1024 * 1024));
|
||||
}
|
||||
|
||||
uint32 gpu_info_get(GpuInfo* info) {
|
||||
|
|
@ -424,7 +377,7 @@ uint32 gpu_info_get(GpuInfo* info) {
|
|||
|
||||
wcstombs(info[i].name, adapterDesc.Description, 63);
|
||||
info[i].name[63] = '\0';
|
||||
info[i].vram = (int) (adapterDesc.DedicatedVideoMemory / (1024 * 1024));
|
||||
info[i].vram = (uint32) (adapterDesc.DedicatedVideoMemory / (1024 * 1024));
|
||||
|
||||
pAdapter->Release();
|
||||
i++;
|
||||
|
|
@ -486,103 +439,4 @@ uint32 display_info_get(DisplayInfo* info) {
|
|||
return i;
|
||||
}
|
||||
|
||||
void system_info_render(char* buf, const SystemInfo* info) {
|
||||
const char avx512[8][12] = {
|
||||
"AVX-512F",
|
||||
"AVX-512DQ",
|
||||
"AVX-512IFMA",
|
||||
"AVX-512PF",
|
||||
"AVX-512ER",
|
||||
"AVX-512CD",
|
||||
"AVX-512BW",
|
||||
"AVX-512VL"
|
||||
};
|
||||
|
||||
sprintf_s(
|
||||
buf,
|
||||
4096,
|
||||
"OS:\n"
|
||||
"==============\n"
|
||||
"Vendor: %s\n" "Name: %s\n" "Major: %d\n" "Minor: %d\n"
|
||||
"\n"
|
||||
"Mainboard:\n"
|
||||
"==============\n"
|
||||
"Name: %s\n" "SN: %s\n"
|
||||
"\n"
|
||||
"Network:\n"
|
||||
"==============\n"
|
||||
"Slot: %s\n" "MAC: %02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X\n"
|
||||
"\n"
|
||||
"Slot: %s\n" "MAC: %02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X\n"
|
||||
"\n"
|
||||
"Slot: %s\n" "MAC: %02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X\n"
|
||||
"\n"
|
||||
"Slot: %s\n" "MAC: %02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X\n"
|
||||
"\n"
|
||||
"CPU:\n"
|
||||
"==============\n"
|
||||
"Hardware\n" "Vendor: %s\n" "Brand: %s\n" "Model: %d\n" "Family: %d\n" "Mhz: %d\n" "Thread Count: %d\n" "Page Size: %d\n"
|
||||
"\n"
|
||||
"Cache:\n"
|
||||
"L1: Size %d Line %d\n"
|
||||
"L2: Size %d Line %d\n"
|
||||
"L3: Size %d Line %d\n"
|
||||
"L4: Size %d Line %d\n"
|
||||
"\n"
|
||||
"SIMD:\n" "SSE: %.1f\n" "AVX256: %d\n" "AVX512: %s\n" "SVE: %d\n" "NEON: %d\n" "ABM: %d\n"
|
||||
"\n"
|
||||
"GPU:\n"
|
||||
"==============\n"
|
||||
"Name: %s\n" "VRAM: %d\n"
|
||||
"Name: %s\n" "VRAM: %d\n"
|
||||
"\n"
|
||||
"Display:\n"
|
||||
"==============\n"
|
||||
"Name: %s\n" "Width: %d\n" "Height: %d\n" "Hz: %d\n"
|
||||
"Name: %s\n" "Width: %d\n" "Height: %d\n" "Hz: %d\n"
|
||||
"Name: %s\n" "Width: %d\n" "Height: %d\n" "Hz: %d\n"
|
||||
"Name: %s\n" "Width: %d\n" "Height: %d\n" "Hz: %d\n"
|
||||
"Name: %s\n" "Width: %d\n" "Height: %d\n" "Hz: %d\n"
|
||||
"Name: %s\n" "Width: %d\n" "Height: %d\n" "Hz: %d\n"
|
||||
"\n"
|
||||
"RAM:\n"
|
||||
"==============\n"
|
||||
"Memory: %d MB",
|
||||
info->os.vendor, info->os.name, info->os.major, info->os.minor,
|
||||
info->mainboard.name, info->mainboard.serial_number,
|
||||
info->network[0].slot, info->network[0].mac[0], info->network[0].mac[1], info->network[0].mac[2], info->network[0].mac[3], info->network[0].mac[4], info->network[0].mac[5], info->network[0].mac[6], info->network[0].mac[7],
|
||||
info->network_count < 2 ? "" : info->network[1].slot, info->network_count < 2 ? 0 : info->network[1].mac[0], info->network_count < 2 ? 0 : info->network[1].mac[1], info->network_count < 2 ? 0 : info->network[1].mac[2], info->network_count < 2 ? 0 : info->network[1].mac[3], info->network_count < 2 ? 0 : info->network[1].mac[4], info->network_count < 2 ? 0 : info->network[1].mac[5], info->network_count < 2 ? 0 : info->network[1].mac[6], info->network_count < 2 ? 0 : info->network[1].mac[7],
|
||||
info->network_count < 3 ? "" : info->network[2].slot, info->network_count < 3 ? 0 : info->network[2].mac[0], info->network_count < 3 ? 0 : info->network[2].mac[1], info->network_count < 3 ? 0 : info->network[2].mac[2], info->network_count < 3 ? 0 : info->network[2].mac[3], info->network_count < 3 ? 0 : info->network[2].mac[4], info->network_count < 3 ? 0 : info->network[2].mac[5], info->network_count < 3 ? 0 : info->network[2].mac[6], info->network_count < 3 ? 0 : info->network[2].mac[7],
|
||||
info->network_count < 4 ? "" : info->network[3].slot, info->network_count < 4 ? 0 : info->network[3].mac[0], info->network_count < 4 ? 0 : info->network[3].mac[1], info->network_count < 4 ? 0 : info->network[3].mac[2], info->network_count < 4 ? 0 : info->network[3].mac[3], info->network_count < 4 ? 0 : info->network[3].mac[4], info->network_count < 4 ? 0 : info->network[3].mac[5], info->network_count < 4 ? 0 : info->network[3].mac[6], info->network_count < 4 ? 0 : info->network[3].mac[7],
|
||||
info->cpu.vendor, info->cpu.brand, info->cpu.model, info->cpu.family, info->cpu.mhz, info->cpu.thread_count, info->cpu.page_size,
|
||||
info->cpu.cache[0].size, info->cpu.cache[0].line_size,
|
||||
info->cpu.cache[1].size, info->cpu.cache[1].line_size,
|
||||
info->cpu.cache[2].size, info->cpu.cache[2].line_size,
|
||||
info->cpu.cache[3].size, info->cpu.cache[3].line_size,
|
||||
info->cpu.simd.sse > 9 ? (f32) info->cpu.simd.sse / 10.0f : (f32) info->cpu.simd.sse, info->cpu.simd.avx256, info->cpu.simd.avx512 > 0 ? avx512[info->cpu.simd.avx512 - 1] : "0", info->cpu.simd.sve, info->cpu.simd.neon, (int32) info->cpu.simd.abm,
|
||||
info->gpu[0].name, info->gpu[0].vram,
|
||||
info->gpu_count < 2 ? "" : info->gpu[1].name, info->gpu_count < 2 ? 0 : info->gpu[1].vram,
|
||||
info->display[0].name, info->display[0].width, info->display[0].height, info->display[0].hz,
|
||||
info->display_count < 2 ? "" : info->display[1].name, info->display_count < 2 ? 0 : info->display[1].width, info->display_count < 2 ? 0 : info->display[1].height, info->display_count < 2 ? 0 : info->display[1].hz,
|
||||
info->display_count < 3 ? "" : info->display[2].name, info->display_count < 3 ? 0 : info->display[2].width, info->display_count < 3 ? 0 : info->display[2].height, info->display_count < 3 ? 0 : info->display[2].hz,
|
||||
info->display_count < 4 ? "" : info->display[3].name, info->display_count < 4 ? 0 : info->display[3].width, info->display_count < 4 ? 0 : info->display[3].height, info->display_count < 4 ? 0 : info->display[3].hz,
|
||||
info->display_count < 5 ? "" : info->display[4].name, info->display_count < 5 ? 0 : info->display[4].width, info->display_count < 5 ? 0 : info->display[4].height, info->display_count < 5 ? 0 : info->display[4].hz,
|
||||
info->display_count < 6 ? "" : info->display[5].name, info->display_count < 6 ? 0 : info->display[5].width, info->display_count < 6 ? 0 : info->display[5].height, info->display_count < 6 ? 0 : info->display[5].hz,
|
||||
info->ram.memory
|
||||
);
|
||||
}
|
||||
|
||||
void system_info_get(SystemInfo* info)
|
||||
{
|
||||
os_info_get(&info->os);
|
||||
mainboard_info_get(&info->mainboard);
|
||||
info->network_count = network_info_get(info->network);
|
||||
cpu_info_get(&info->cpu);
|
||||
ram_info_get(&info->ram);
|
||||
info->gpu_count = gpu_info_get(info->gpu);
|
||||
info->display_count = display_info_get(info->display);
|
||||
display_info_get_primary(&info->display_primary);
|
||||
info->language = system_language_code();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -1,284 +0,0 @@
|
|||
/**
|
||||
* Jingga
|
||||
*
|
||||
* @copyright Jingga
|
||||
* @license OMS License 2.0
|
||||
* @version 1.0.0
|
||||
* @link https://jingga.app
|
||||
*/
|
||||
#ifndef TOS_STDLIB_SIMD_HELPER_H
|
||||
#define TOS_STDLIB_SIMD_HELPER_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <immintrin.h>
|
||||
#include <xmmintrin.h>
|
||||
#include "Types.h"
|
||||
|
||||
// @todo split into platform code for windows and linux
|
||||
|
||||
#if _WIN32
|
||||
#include <windows.h>
|
||||
#ifdef _MSC_VER
|
||||
#include <intrin.h>
|
||||
#endif
|
||||
#elif __linux__
|
||||
#include <sys/auxv.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#if ARM
|
||||
#include <arm_sve.h>
|
||||
#else
|
||||
int32 svcntw() {
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
enum SIMDVersion {
|
||||
SIMD_VERSION_NONE,
|
||||
SIMD_VERSION_128,
|
||||
SIMD_VERSION_256,
|
||||
SIMD_VERSION_512,
|
||||
SIMD_VERSION_SVE,
|
||||
SIMD_VERSION_NEON,
|
||||
};
|
||||
|
||||
// @todo implement for arm?
|
||||
|
||||
inline int32 max_neon_supported()
|
||||
{
|
||||
#if ARM
|
||||
#if _WIN32
|
||||
int cpu_info[4] = {0};
|
||||
__cpuid(cpu_info, 0);
|
||||
|
||||
if (cpu_info[3] & (1 << 1)) {
|
||||
return 1;
|
||||
}
|
||||
#else
|
||||
unsigned int eax, ebx, ecx, edx;
|
||||
__asm__ volatile (
|
||||
"cpuid"
|
||||
: "=a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx)
|
||||
: "a"(0)
|
||||
);
|
||||
|
||||
if (edx & (1 << 1)) {
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
inline int32 max_sve_supported()
|
||||
{
|
||||
#if ARM
|
||||
int32 hwcaps = getauxval(AT_HWCAP);
|
||||
|
||||
return (int32) ((bool) (hwcaps & (1 << 19)));
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
inline int32 max_sse_supported()
|
||||
{
|
||||
#if ARM
|
||||
return 0;
|
||||
#else
|
||||
#ifdef _MSC_VER
|
||||
int32 cpuInfo[4] = {-1};
|
||||
__cpuid(cpuInfo, 1); // CPUID function 1
|
||||
|
||||
uint32 ecx = cpuInfo[2];
|
||||
uint32 edx = cpuInfo[3];
|
||||
#else
|
||||
uint32 eax, ebx, ecx, edx;
|
||||
|
||||
eax = 1; // CPUID function 1
|
||||
__asm__ __volatile__("cpuid;"
|
||||
: "=a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx)
|
||||
: "a"(eax));
|
||||
#endif
|
||||
|
||||
bool sse42_supported = (ecx >> 20) & 1;
|
||||
if (sse42_supported) {
|
||||
return 42;
|
||||
}
|
||||
|
||||
bool sse41_supported = (ecx >> 19) & 1;
|
||||
if (sse41_supported) {
|
||||
return 41;
|
||||
}
|
||||
|
||||
bool sse3_supported = (ecx >> 0) & 1;
|
||||
if (sse3_supported) {
|
||||
return 3;
|
||||
}
|
||||
|
||||
bool sse2_supported = (edx >> 26) & 1;
|
||||
if (sse2_supported) {
|
||||
return 2;
|
||||
}
|
||||
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
inline
|
||||
int32 max_avx256_supported()
|
||||
{
|
||||
#if ARM
|
||||
return 0;
|
||||
#else
|
||||
int32 max_version = 0;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
int32 cpuInfo[4];
|
||||
__cpuid(cpuInfo, 1);
|
||||
|
||||
if ((cpuInfo[2] >> 28) & 1) {
|
||||
__cpuid(cpuInfo, 7); // Query extended features
|
||||
|
||||
if ((cpuInfo[1] >> 5) & 1) {
|
||||
max_version = 2;
|
||||
}
|
||||
}
|
||||
#else
|
||||
uint32 eax, ebx, ecx, edx;
|
||||
|
||||
__asm__ __volatile__("cpuid"
|
||||
: "=a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx)
|
||||
: "a"(1));
|
||||
if ((ecx >> 28) & 1) {
|
||||
eax = 7;
|
||||
ecx = 0;
|
||||
__asm__ __volatile__("cpuid"
|
||||
: "=a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx)
|
||||
: "a"(eax), "c"(ecx));
|
||||
|
||||
if ((ebx >> 5) & 1) {
|
||||
max_version = 2;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return max_version;
|
||||
#endif
|
||||
}
|
||||
|
||||
inline
|
||||
int32 max_avx512_supported()
|
||||
{
|
||||
#if ARM
|
||||
return 0;
|
||||
#else
|
||||
#ifdef _MSC_VER
|
||||
int32 cpuInfo[4];
|
||||
__cpuid(cpuInfo, 1);
|
||||
int32 ebx = 0;
|
||||
|
||||
if ((cpuInfo[2] >> 28) & 1) {
|
||||
__cpuid(cpuInfo, 7);
|
||||
|
||||
ebx = cpuInfo[1];
|
||||
}
|
||||
#else
|
||||
uint32 eax, ebx, ecx, edx;
|
||||
|
||||
__asm__ __volatile__("cpuid"
|
||||
: "=a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx)
|
||||
: "a"(1));
|
||||
if ((ecx >> 28) & 1) {
|
||||
eax = 7;
|
||||
ecx = 0;
|
||||
__asm__ __volatile__("cpuid"
|
||||
: "=a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx)
|
||||
: "a"(eax), "c"(ecx));
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((ebx >> 16) & 1) {
|
||||
return 1; // AVX-512F
|
||||
}
|
||||
|
||||
if ((ebx >> 17) & 1) {
|
||||
return 2; // AVX-512DQ
|
||||
}
|
||||
|
||||
if ((ebx >> 21) & 1) {
|
||||
return 3; // AVX-512IFMA
|
||||
}
|
||||
|
||||
if ((ebx >> 26) & 1) {
|
||||
return 4; // AVX-512PF
|
||||
}
|
||||
|
||||
if ((ebx >> 27) & 1) {
|
||||
return 5; // AVX-512ER
|
||||
}
|
||||
|
||||
if ((ebx >> 28) & 1) {
|
||||
return 6; // AVX-512CD
|
||||
}
|
||||
|
||||
if ((ebx >> 30) & 1) {
|
||||
return 7; // AVX-512BW
|
||||
}
|
||||
|
||||
if ((ebx >> 31) & 1) {
|
||||
return 8; // AVX-512VL
|
||||
}
|
||||
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
const char AVX512_VERSIONS[8][12] = {
|
||||
"AVX-512F",
|
||||
"AVX-512DQ",
|
||||
"AVX-512IFMA",
|
||||
"AVX-512PF",
|
||||
"AVX-512ER",
|
||||
"AVX-512CD",
|
||||
"AVX-512BW",
|
||||
"AVX-512VL"
|
||||
};
|
||||
|
||||
bool supports_abm() {
|
||||
#if ARM
|
||||
return 0;
|
||||
#else
|
||||
bool popcnt_supported;
|
||||
bool lzcnt_supported;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
int cpuInfo[4];
|
||||
__cpuid(cpuInfo, 0x80000001);
|
||||
|
||||
popcnt_supported = (cpuInfo[2] & (1 << 5)) != 0;
|
||||
lzcnt_supported = (cpuInfo[1] & (1 << 5)) != 0;
|
||||
#else
|
||||
uint32 eax, ebx, ecx, edx;
|
||||
eax = 0x80000001;
|
||||
|
||||
__asm__ __volatile__ (
|
||||
"cpuid"
|
||||
: "=a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx)
|
||||
: "a"(eax)
|
||||
);
|
||||
|
||||
// Check if the ABM (POPCNT and LZCNT) bits are set
|
||||
popcnt_supported = (ecx & (1 << 5)) != 0;
|
||||
lzcnt_supported = (ebx & (1 << 5)) != 0;
|
||||
#endif
|
||||
|
||||
return popcnt_supported && lzcnt_supported;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -15,4 +15,92 @@
|
|||
#include "../platform/linux/SystemInfo.cpp"
|
||||
#endif
|
||||
|
||||
void system_info_render(char* buf, const SystemInfo* info) {
|
||||
sprintf_s(
|
||||
buf,
|
||||
4096,
|
||||
"OS:\n"
|
||||
"==============\n"
|
||||
"Vendor: %s\n" "Name: %s\n" "Major: %d\n" "Minor: %d\n"
|
||||
"\n"
|
||||
"Mainboard:\n"
|
||||
"==============\n"
|
||||
"Name: %s\n" "SN: %s\n"
|
||||
"\n"
|
||||
"Network:\n"
|
||||
"==============\n"
|
||||
"Slot: %s\n" "MAC: %02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X\n"
|
||||
"\n"
|
||||
"Slot: %s\n" "MAC: %02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X\n"
|
||||
"\n"
|
||||
"Slot: %s\n" "MAC: %02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X\n"
|
||||
"\n"
|
||||
"Slot: %s\n" "MAC: %02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X\n"
|
||||
"\n"
|
||||
"CPU:\n"
|
||||
"==============\n"
|
||||
"Hardware\n" "Vendor: %s\n" "Brand: %s\n" "Model: %d\n" "Family: %d\n" "Mhz: %d\n" "Thread Count: %d\n" "Page Size: %d\n"
|
||||
"\n"
|
||||
"Cache:\n"
|
||||
"L1: Size %d Line %d\n"
|
||||
"L2: Size %d Line %d\n"
|
||||
"L3: Size %d Line %d\n"
|
||||
"L4: Size %d Line %d\n"
|
||||
"\n"
|
||||
"Features: %lld\n"
|
||||
"\n"
|
||||
"GPU:\n"
|
||||
"==============\n"
|
||||
"Name: %s\n" "VRAM: %d\n"
|
||||
"Name: %s\n" "VRAM: %d\n"
|
||||
"\n"
|
||||
"Display:\n"
|
||||
"==============\n"
|
||||
"Name: %s\n" "Width: %d\n" "Height: %d\n" "Hz: %d\n"
|
||||
"Name: %s\n" "Width: %d\n" "Height: %d\n" "Hz: %d\n"
|
||||
"Name: %s\n" "Width: %d\n" "Height: %d\n" "Hz: %d\n"
|
||||
"Name: %s\n" "Width: %d\n" "Height: %d\n" "Hz: %d\n"
|
||||
"Name: %s\n" "Width: %d\n" "Height: %d\n" "Hz: %d\n"
|
||||
"Name: %s\n" "Width: %d\n" "Height: %d\n" "Hz: %d\n"
|
||||
"\n"
|
||||
"RAM:\n"
|
||||
"==============\n"
|
||||
"Memory: %d MB",
|
||||
info->os.vendor, info->os.name, info->os.major, info->os.minor,
|
||||
info->mainboard.name, info->mainboard.serial_number,
|
||||
info->network[0].slot, info->network[0].mac[0], info->network[0].mac[1], info->network[0].mac[2], info->network[0].mac[3], info->network[0].mac[4], info->network[0].mac[5], info->network[0].mac[6], info->network[0].mac[7],
|
||||
info->network_count < 2 ? "" : info->network[1].slot, info->network_count < 2 ? 0 : info->network[1].mac[0], info->network_count < 2 ? 0 : info->network[1].mac[1], info->network_count < 2 ? 0 : info->network[1].mac[2], info->network_count < 2 ? 0 : info->network[1].mac[3], info->network_count < 2 ? 0 : info->network[1].mac[4], info->network_count < 2 ? 0 : info->network[1].mac[5], info->network_count < 2 ? 0 : info->network[1].mac[6], info->network_count < 2 ? 0 : info->network[1].mac[7],
|
||||
info->network_count < 3 ? "" : info->network[2].slot, info->network_count < 3 ? 0 : info->network[2].mac[0], info->network_count < 3 ? 0 : info->network[2].mac[1], info->network_count < 3 ? 0 : info->network[2].mac[2], info->network_count < 3 ? 0 : info->network[2].mac[3], info->network_count < 3 ? 0 : info->network[2].mac[4], info->network_count < 3 ? 0 : info->network[2].mac[5], info->network_count < 3 ? 0 : info->network[2].mac[6], info->network_count < 3 ? 0 : info->network[2].mac[7],
|
||||
info->network_count < 4 ? "" : info->network[3].slot, info->network_count < 4 ? 0 : info->network[3].mac[0], info->network_count < 4 ? 0 : info->network[3].mac[1], info->network_count < 4 ? 0 : info->network[3].mac[2], info->network_count < 4 ? 0 : info->network[3].mac[3], info->network_count < 4 ? 0 : info->network[3].mac[4], info->network_count < 4 ? 0 : info->network[3].mac[5], info->network_count < 4 ? 0 : info->network[3].mac[6], info->network_count < 4 ? 0 : info->network[3].mac[7],
|
||||
info->cpu.vendor, info->cpu.brand, info->cpu.model, info->cpu.family, info->cpu.mhz, info->cpu.thread_count, info->cpu.page_size,
|
||||
info->cpu.cache[0].size, info->cpu.cache[0].line_size,
|
||||
info->cpu.cache[1].size, info->cpu.cache[1].line_size,
|
||||
info->cpu.cache[2].size, info->cpu.cache[2].line_size,
|
||||
info->cpu.cache[3].size, info->cpu.cache[3].line_size,
|
||||
info->cpu.features,
|
||||
info->gpu[0].name, info->gpu[0].vram,
|
||||
info->gpu_count < 2 ? "" : info->gpu[1].name, info->gpu_count < 2 ? 0 : info->gpu[1].vram,
|
||||
info->display[0].name, info->display[0].width, info->display[0].height, info->display[0].hz,
|
||||
info->display_count < 2 ? "" : info->display[1].name, info->display_count < 2 ? 0 : info->display[1].width, info->display_count < 2 ? 0 : info->display[1].height, info->display_count < 2 ? 0 : info->display[1].hz,
|
||||
info->display_count < 3 ? "" : info->display[2].name, info->display_count < 3 ? 0 : info->display[2].width, info->display_count < 3 ? 0 : info->display[2].height, info->display_count < 3 ? 0 : info->display[2].hz,
|
||||
info->display_count < 4 ? "" : info->display[3].name, info->display_count < 4 ? 0 : info->display[3].width, info->display_count < 4 ? 0 : info->display[3].height, info->display_count < 4 ? 0 : info->display[3].hz,
|
||||
info->display_count < 5 ? "" : info->display[4].name, info->display_count < 5 ? 0 : info->display[4].width, info->display_count < 5 ? 0 : info->display[4].height, info->display_count < 5 ? 0 : info->display[4].hz,
|
||||
info->display_count < 6 ? "" : info->display[5].name, info->display_count < 6 ? 0 : info->display[5].width, info->display_count < 6 ? 0 : info->display[5].height, info->display_count < 6 ? 0 : info->display[5].hz,
|
||||
info->ram.memory
|
||||
);
|
||||
}
|
||||
|
||||
void system_info_get(SystemInfo* info)
|
||||
{
|
||||
os_info_get(&info->os);
|
||||
mainboard_info_get(&info->mainboard);
|
||||
info->network_count = network_info_get(info->network);
|
||||
cpu_info_get(&info->cpu);
|
||||
ram_info_get(&info->ram);
|
||||
info->gpu_count = gpu_info_get(info->gpu);
|
||||
info->display_count = display_info_get(info->display);
|
||||
display_info_get_primary(&info->display_primary);
|
||||
info->language = system_language_code();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -10,15 +10,7 @@
|
|||
#define TOS_SYSTEM_INFO_H
|
||||
|
||||
#include "../stdlib/Types.h"
|
||||
|
||||
struct CpuCacheInfo {
|
||||
int32 level;
|
||||
int32 size;
|
||||
int32 ways;
|
||||
int32 partitions;
|
||||
int32 sets;
|
||||
int32 line_size;
|
||||
};
|
||||
#include "../architecture/CpuInfo.h"
|
||||
|
||||
// @todo add vendor name
|
||||
struct MainboardInfo {
|
||||
|
|
@ -29,28 +21,7 @@ struct MainboardInfo {
|
|||
// @todo add ipv6
|
||||
struct NetworkInfo {
|
||||
char slot[64];
|
||||
byte mac[8];
|
||||
};
|
||||
|
||||
struct SIMDInfo {
|
||||
int32 sse;
|
||||
int32 avx256;
|
||||
int32 avx512;
|
||||
int32 sve;
|
||||
int32 neon;
|
||||
bool abm;
|
||||
};
|
||||
|
||||
struct CpuInfo {
|
||||
char vendor[13];
|
||||
char brand[49];
|
||||
int32 model;
|
||||
int32 family;
|
||||
int32 thread_count;
|
||||
int32 mhz;
|
||||
CpuCacheInfo cache[4];
|
||||
int32 page_size;
|
||||
SIMDInfo simd;
|
||||
byte mac[24];
|
||||
};
|
||||
|
||||
struct OSInfo {
|
||||
|
|
@ -61,12 +32,12 @@ struct OSInfo {
|
|||
};
|
||||
|
||||
struct RamInfo {
|
||||
int32 memory;
|
||||
uint32 memory;
|
||||
};
|
||||
|
||||
struct GpuInfo {
|
||||
char name[64];
|
||||
int32 vram;
|
||||
uint32 vram;
|
||||
};
|
||||
|
||||
struct DisplayInfo {
|
||||
|
|
|
|||
|
|
@ -1277,6 +1277,83 @@ void sprintf_fast(char* __restrict buffer, const char* __restrict format, ...) {
|
|||
va_end(args);
|
||||
}
|
||||
|
||||
void sprintf_fast(char* __restrict buffer, int32 buffer_length, const char* __restrict format, ...) {
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
|
||||
// We start at 1 since we need 1 char for '\0'
|
||||
int32 length = 1;
|
||||
int32 offset;
|
||||
|
||||
while (*format && length < buffer_length) {
|
||||
offset = 1;
|
||||
if (*format != '%') {
|
||||
*buffer++ = *format;
|
||||
} else if (*format == '\\' && *(format + 1) == '%') {
|
||||
++format;
|
||||
*buffer++ = *format;
|
||||
} else {
|
||||
++format;
|
||||
|
||||
switch (*format) {
|
||||
case 's': {
|
||||
const char* str = va_arg(args, const char*);
|
||||
--offset;
|
||||
while (*str) {
|
||||
*buffer++ = *str++;
|
||||
++offset;
|
||||
}
|
||||
} break;
|
||||
case 'c': {
|
||||
*buffer++ = va_arg(args, char);
|
||||
} break;
|
||||
case 'n': {
|
||||
int64 val = va_arg(args, int64);
|
||||
buffer += offset = int_to_str(val, buffer, ',');
|
||||
} break;
|
||||
case 'd': {
|
||||
int32 val = va_arg(args, int32);
|
||||
buffer += offset = int_to_str(val, buffer);
|
||||
} break;
|
||||
case 'l': {
|
||||
int64 val = va_arg(args, int64);
|
||||
buffer += offset = int_to_str(val, buffer);
|
||||
} break;
|
||||
case 'f': {
|
||||
f64 val = va_arg(args, f64);
|
||||
|
||||
// Default precision
|
||||
int32 precision = 5;
|
||||
|
||||
// Check for optional precision specifier
|
||||
const char* prec_ptr = format + 1;
|
||||
if (*prec_ptr >= '0' && *prec_ptr <= '9') {
|
||||
precision = 0;
|
||||
while (*prec_ptr >= '0' && *prec_ptr <= '9') {
|
||||
precision = precision * 10 + (*prec_ptr - '0');
|
||||
prec_ptr++;
|
||||
}
|
||||
|
||||
format = prec_ptr - 1;
|
||||
}
|
||||
|
||||
buffer += offset = float_to_str(val, buffer, precision);
|
||||
} break;
|
||||
default: {
|
||||
// Handle unknown format specifiers
|
||||
*buffer++ = '%';
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
length += offset;
|
||||
++format;
|
||||
}
|
||||
|
||||
*buffer = '\0';
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
// There are situations where you only want to replace a certain amount of %
|
||||
void sprintf_fast_iter(char* buffer, const char* format, ...) {
|
||||
va_list args;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user