diff --git a/architecture/CpuInfo.cpp b/architecture/CpuInfo.cpp new file mode 100644 index 0000000..55a02d7 --- /dev/null +++ b/architecture/CpuInfo.cpp @@ -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 \ No newline at end of file diff --git a/architecture/CpuInfo.h b/architecture/CpuInfo.h new file mode 100644 index 0000000..6eefb0d --- /dev/null +++ b/architecture/CpuInfo.h @@ -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 \ No newline at end of file diff --git a/architecture/arm/CpuInfo.cpp b/architecture/arm/CpuInfo.cpp new file mode 100644 index 0000000..5db8d38 --- /dev/null +++ b/architecture/arm/CpuInfo.cpp @@ -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 +#include +#include "../../stdlib/Types.h" +#include "../CpuInfo.h" +#include + +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 \ No newline at end of file diff --git a/architecture/x86/CpuInfo.cpp b/architecture/x86/CpuInfo.cpp new file mode 100644 index 0000000..4f3263f --- /dev/null +++ b/architecture/x86/CpuInfo.cpp @@ -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 +#include +#include "../../stdlib/Types.h" +#include "../CpuInfo.h" + +#ifdef _MSC_VER + #include + + static inline + void cpuid(int32 cpuInfo[4], int32 function_id) { + __cpuidex(cpuInfo, function_id, 0); + } +#else + /* + #include + + 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 \ No newline at end of file diff --git a/platform/linux/SystemInfo.cpp b/platform/linux/SystemInfo.cpp index dc704c5..321d3ea 100644 --- a/platform/linux/SystemInfo.cpp +++ b/platform/linux/SystemInfo.cpp @@ -11,19 +11,49 @@ #include #include +#include +#include #include "../../stdlib/Types.h" #include "../../system/SystemInfo.h" +#include "../../architecture/CpuInfo.cpp" #include -#include +#include -#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 \ No newline at end of file diff --git a/platform/win32/FastPipes.h b/platform/win32/FastPipes.h index 8ff1f43..072ad1e 100644 --- a/platform/win32/FastPipes.h +++ b/platform/win32/FastPipes.h @@ -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" diff --git a/platform/win32/SystemInfo.cpp b/platform/win32/SystemInfo.cpp index 7c01857..e0963f0 100644 --- a/platform/win32/SystemInfo.cpp +++ b/platform/win32/SystemInfo.cpp @@ -12,7 +12,9 @@ #include #include #include "../../stdlib/Types.h" +#include "../../utils/StringUtils.h" #include "../../system/SystemInfo.h" +#include "../../architecture/CpuInfo.cpp" #include #include @@ -27,12 +29,6 @@ #include #include -#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 #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 \ No newline at end of file diff --git a/stdlib/SIMD_Helper.h b/stdlib/SIMD_Helper.h deleted file mode 100644 index cc070bd..0000000 --- a/stdlib/SIMD_Helper.h +++ /dev/null @@ -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 -#include -#include -#include "Types.h" - -// @todo split into platform code for windows and linux - -#if _WIN32 - #include - #ifdef _MSC_VER - #include - #endif -#elif __linux__ - #include - #include -#endif - -#if ARM - #include -#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 \ No newline at end of file diff --git a/system/SystemInfo.cpp b/system/SystemInfo.cpp index 720af75..bc6a35a 100644 --- a/system/SystemInfo.cpp +++ b/system/SystemInfo.cpp @@ -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 \ No newline at end of file diff --git a/system/SystemInfo.h b/system/SystemInfo.h index 1c90aab..39c6576 100644 --- a/system/SystemInfo.h +++ b/system/SystemInfo.h @@ -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 { diff --git a/utils/StringUtils.h b/utils/StringUtils.h index fa8a3d4..587b8d3 100644 --- a/utils/StringUtils.h +++ b/utils/StringUtils.h @@ -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;