diff --git a/core/os/os_openbsd.odin b/core/os/os_openbsd.odin index 9a3dbd874..fba079f15 100644 --- a/core/os/os_openbsd.odin +++ b/core/os/os_openbsd.odin @@ -705,4 +705,4 @@ _alloc_command_line_arguments :: proc() -> []string { res[i] = string(arg) } return res -} +} \ No newline at end of file diff --git a/core/sys/info/cpu_arm.odin b/core/sys/info/cpu_arm.odin new file mode 100644 index 000000000..f66f0e780 --- /dev/null +++ b/core/sys/info/cpu_arm.odin @@ -0,0 +1,26 @@ +//+build arm32, arm64 +package sysinfo + +// TODO: Set up an enum with the ARM equivalent of the above. +CPU_Feature :: enum u64 {} + +cpu_features: Maybe(CPU_Feature) +cpu_name: Maybe(string) + +@(init, private) +init_cpu_features :: proc "c" () { +} + +@(private) +_cpu_name_buf: [72]u8 + +@(init, private) +init_cpu_name :: proc "c" () { + when ODIN_ARCH == .arm32 { + copy(_cpu_name_buf[:], "ARM") + cpu_name = string(_cpu_name_buf[:3]) + } else { + copy(_cpu_name_buf[:], "ARM64") + cpu_name = string(_cpu_name_buf[:5]) + } +} \ No newline at end of file diff --git a/core/simd/x86/cpu.odin b/core/sys/info/cpu_intel.odin similarity index 71% rename from core/simd/x86/cpu.odin rename to core/sys/info/cpu_intel.odin index 14e90c0f0..8cd723203 100644 --- a/core/simd/x86/cpu.odin +++ b/core/sys/info/cpu_intel.odin @@ -1,5 +1,5 @@ //+build i386, amd64 -package simd_x86 +package sysinfo import "core:intrinsics" @@ -9,7 +9,6 @@ cpuid :: intrinsics.x86_cpuid // xgetbv :: proc(cx: u32) -> (eax, edx: u32) --- xgetbv :: intrinsics.x86_xgetbv - CPU_Feature :: enum u64 { aes, // AES hardware implementation (AES NI) adx, // Multi-precision add-carry instruction extensions @@ -34,6 +33,7 @@ CPU_Feature :: enum u64 { CPU_Features :: distinct bit_set[CPU_Feature; u64] cpu_features: Maybe(CPU_Features) +cpu_name: Maybe(string) @(init, private) init_cpu_features :: proc "c" () { @@ -67,6 +67,13 @@ init_cpu_features :: proc "c" () { try_set(&set, .os_xsave, 27, ecx1) try_set(&set, .rdrand, 30, ecx1) + when ODIN_OS == .FreeBSD || ODIN_OS == .OpenBSD { + // xgetbv is an illegal instruction under FreeBSD 13 & OpenBSD 7.1 + // return before probing further + cpu_features = set + return + } + os_supports_avx := false if .os_xsave in set { eax, _ := xgetbv(0) @@ -92,3 +99,31 @@ init_cpu_features :: proc "c" () { cpu_features = set } + +@(private) +_cpu_name_buf: [72]u8 + +@(init, private) +init_cpu_name :: proc "c" () { + number_of_extended_ids, _, _, _ := cpuid(0x8000_0000, 0) + if number_of_extended_ids < 0x8000_0004 { + return + } + + _buf := transmute(^[0x12]u32)&_cpu_name_buf + _buf[ 0], _buf[ 1], _buf[ 2], _buf[ 3] = cpuid(0x8000_0002, 0) + _buf[ 4], _buf[ 5], _buf[ 6], _buf[ 7] = cpuid(0x8000_0003, 0) + _buf[ 8], _buf[ 9], _buf[10], _buf[11] = cpuid(0x8000_0004, 0) + + // Some CPUs like may include leading or trailing spaces. Trim them. + // e.g. ` Intel(R) Xeon(R) CPU E5-1650 v2 @ 3.50GHz` + + brand := string(_cpu_name_buf[:]) + for len(brand) > 0 && brand[0] == 0 || brand[0] == ' ' { + brand = brand[1:] + } + for len(brand) > 0 && brand[len(brand) - 1] == 0 || brand[len(brand) - 1] == ' ' { + brand = brand[:len(brand) - 1] + } + cpu_name = brand +} \ No newline at end of file diff --git a/core/sys/info/doc.odin b/core/sys/info/doc.odin new file mode 100644 index 000000000..81e437cf8 --- /dev/null +++ b/core/sys/info/doc.odin @@ -0,0 +1,78 @@ +/* + Copyright 2022 Jeroen van Rijn . + Made available under Odin's BSD-3 license. + + Package `core:sys/info` gathers system information on: + Windows, Linux, macOS, FreeBSD & OpenBSD. + + Simply import the package and you'll have access to the OS version, RAM amount + and CPU information. + + On Windows, GPUs will also be enumerated using the registry. + + CPU feature flags can be tested against `cpu_features`, where applicable, e.g. + `if .aes in si.aes { ... }` +*/ +// +ignore +package sysinfo + +import "core:fmt" +import si "core:sys/info" + +main :: proc() { + fmt.printf("Odin: %v\n", ODIN_VERSION) + fmt.printf("OS: %v\n", si.os_version.as_string) + fmt.printf("OS: %#v\n", si.os_version) + fmt.printf("CPU: %v\n", si.cpu_name) + fmt.printf("RAM: %v MiB\n", si.ram.total_ram / 1024 / 1024) + + fmt.println() + for gpu, i in si.gpus { + fmt.printf("GPU #%v:\n", i) + fmt.printf("\tVendor: %v\n", gpu.vendor_name) + fmt.printf("\tModel: %v\n", gpu.model_name) + fmt.printf("\tVRAM: %v MiB\n", gpu.total_ram / 1024 / 1024) + } +} + +/* + Example Windows output: + Odin: dev-2022-09 + OS: Windows 10 Professional (version: 20H2), build: 19042.1466 + OS: OS_Version{ + platform = "Windows", + major = 10, + minor = 0, + patch = 0, + build = [ + 19042, + 1466, + ], + version = "20H2", + as_string = "Windows 10 Professional (version: 20H2), build: 19042.1466", + } + CPU: AMD Ryzen 7 1800X Eight-Core Processor + RAM: 65469 MiB + + GPU #0: + Vendor: Advanced Micro Devices, Inc. + Model: Radeon RX Vega + VRAM: 8176 MiB + + Example macOS output: + ODIN: dev-2022-09 + OS: OS_Version{ + platform = "MacOS", + major = 21, + minor = 5, + patch = 0, + build = [ + 0, + 0, + ], + version = "21F79", + as_string = "macOS Monterey 12.4 (build 21F79, kernel 21.5.0)", + } + CPU: Intel(R) Core(TM) i5-7360U CPU @ 2.30GHz + RAM: 8192 MiB +*/ diff --git a/core/sys/info/platform_darwin.odin b/core/sys/info/platform_darwin.odin new file mode 100644 index 000000000..fe58d5b06 --- /dev/null +++ b/core/sys/info/platform_darwin.odin @@ -0,0 +1,510 @@ +// +build darwin +package sysinfo + +import sys "core:sys/unix" +import "core:strconv" +import "core:strings" + +@(private) +version_string_buf: [1024]u8 + +@(init, private) +init_os_version :: proc () { + os_version.platform = .MacOS + + // Start building display version + b := strings.builder_from_bytes(version_string_buf[:]) + + mib := []i32{sys.CTL_KERN, sys.KERN_OSVERSION} + build_buf: [12]u8 + + ok := sys.sysctl(mib, &build_buf) + if !ok { + strings.write_string(&b, "macOS Unknown") + os_version.as_string = strings.to_string(b) + return + } + + build := string(cstring(&build_buf[0])) + + // Do we have an exact match? + match: Darwin_Match + rel, exact := macos_release_map[build] + + if exact { + match = .Exact + } else { + // Match on XNU kernel version + mib = []i32{sys.CTL_KERN, sys.KERN_OSRELEASE} + version_bits: [12]u8 // enough for 999.999.999\x00 + have_kernel_version := sys.sysctl(mib, &version_bits) + + major_ok, minor_ok, patch_ok: bool + + triplet := strings.split(string(cstring(&version_bits[0])), ".", context.temp_allocator) + if len(triplet) != 3 { + have_kernel_version = false + } else { + rel.darwin.x, major_ok = strconv.parse_int(triplet[0]) + rel.darwin.y, minor_ok = strconv.parse_int(triplet[1]) + rel.darwin.z, patch_ok = strconv.parse_int(triplet[2]) + + if !(major_ok && minor_ok && patch_ok) { + have_kernel_version = false + } + } + + if !have_kernel_version { + // We don't know the kernel version, but we do know the build + strings.write_string(&b, "macOS Unknown (build ") + l := strings.builder_len(b) + strings.write_string(&b, build) + os_version.version = strings.to_string(b)[l:] + strings.write_rune(&b, ')') + os_version.as_string = strings.to_string(b) + return + } + rel, match = map_darwin_kernel_version_to_macos_release(build, rel.darwin) + } + + os_version.major = rel.darwin.x + os_version.minor = rel.darwin.y + os_version.patch = rel.darwin.z + + strings.write_string(&b, rel.os_name) + if match == .Exact || match == .Nearest { + strings.write_rune(&b, ' ') + strings.write_string(&b, rel.release.name) + strings.write_rune(&b, ' ') + strings.write_int(&b, rel.release.version.x) + if rel.release.version.y > 0 || rel.release.version.z > 0 { + strings.write_rune(&b, '.') + strings.write_int(&b, rel.release.version.y) + } + if rel.release.version.z > 0 { + strings.write_rune(&b, '.') + strings.write_int(&b, rel.release.version.z) + } + if match == .Nearest { + strings.write_rune(&b, '?') + } + } else { + strings.write_string(&b, " Unknown") + } + + strings.write_string(&b, " (build ") + l := strings.builder_len(b) + strings.write_string(&b, build) + os_version.version = strings.to_string(b)[l:] + + strings.write_string(&b, ", kernel ") + strings.write_int(&b, rel.darwin.x) + strings.write_rune(&b, '.') + strings.write_int(&b, rel.darwin.y) + strings.write_rune(&b, '.') + strings.write_int(&b, rel.darwin.z) + strings.write_rune(&b, ')') + + os_version.as_string = strings.to_string(b) +} + +@(init) +init_ram :: proc() { + // Retrieve RAM info using `sysctl` + + mib := []i32{sys.CTL_HW, sys.HW_MEMSIZE} + mem_size: u64 + if sys.sysctl(mib, &mem_size) { + ram.total_ram = int(mem_size) + } +} + +@(private) +Darwin_To_Release :: struct { + darwin: [3]int, // Darwin kernel triplet + os_name: string, // OS X, MacOS + release: struct { + name: string, // Monterey, Mojave, etc. + version: [3]int, // 12.4, etc. + }, +} + +// Important: Order from lowest to highest kernel version +@(private) +macos_release_map: map[string]Darwin_To_Release = { + // MacOS Tiger + "8A428" = {{8, 0, 0}, "macOS", {"Tiger", {10, 4, 0}}}, + "8A432" = {{8, 0, 0}, "macOS", {"Tiger", {10, 4, 0}}}, + "8B15" = {{8, 1, 0}, "macOS", {"Tiger", {10, 4, 1}}}, + "8B17" = {{8, 1, 0}, "macOS", {"Tiger", {10, 4, 1}}}, + "8C46" = {{8, 2, 0}, "macOS", {"Tiger", {10, 4, 2}}}, + "8C47" = {{8, 2, 0}, "macOS", {"Tiger", {10, 4, 2}}}, + "8E102" = {{8, 2, 0}, "macOS", {"Tiger", {10, 4, 2}}}, + "8E45" = {{8, 2, 0}, "macOS", {"Tiger", {10, 4, 2}}}, + "8E90" = {{8, 2, 0}, "macOS", {"Tiger", {10, 4, 2}}}, + "8F46" = {{8, 3, 0}, "macOS", {"Tiger", {10, 4, 3}}}, + "8G32" = {{8, 4, 0}, "macOS", {"Tiger", {10, 4, 4}}}, + "8G1165" = {{8, 4, 0}, "macOS", {"Tiger", {10, 4, 4}}}, + "8H14" = {{8, 5, 0}, "macOS", {"Tiger", {10, 4, 5}}}, + "8G1454" = {{8, 5, 0}, "macOS", {"Tiger", {10, 4, 5}}}, + "8I127" = {{8, 6, 0}, "macOS", {"Tiger", {10, 4, 6}}}, + "8I1119" = {{8, 6, 0}, "macOS", {"Tiger", {10, 4, 6}}}, + "8J135" = {{8, 7, 0}, "macOS", {"Tiger", {10, 4, 7}}}, + "8J2135a" = {{8, 7, 0}, "macOS", {"Tiger", {10, 4, 7}}}, + "8K1079" = {{8, 7, 0}, "macOS", {"Tiger", {10, 4, 7}}}, + "8N5107" = {{8, 7, 0}, "macOS", {"Tiger", {10, 4, 7}}}, + "8L127" = {{8, 8, 0}, "macOS", {"Tiger", {10, 4, 8}}}, + "8L2127" = {{8, 8, 0}, "macOS", {"Tiger", {10, 4, 8}}}, + "8P135" = {{8, 9, 0}, "macOS", {"Tiger", {10, 4, 9}}}, + "8P2137" = {{8, 9, 0}, "macOS", {"Tiger", {10, 4, 9}}}, + "8R218" = {{8, 10, 0}, "macOS", {"Tiger", {10, 4, 10}}}, + "8R2218" = {{8, 10, 0}, "macOS", {"Tiger", {10, 4, 10}}}, + "8R2232" = {{8, 10, 0}, "macOS", {"Tiger", {10, 4, 10}}}, + "8S165" = {{8, 11, 0}, "macOS", {"Tiger", {10, 4, 11}}}, + "8S2167" = {{8, 11, 0}, "macOS", {"Tiger", {10, 4, 11}}}, + + // MacOS Leopard + "9A581" = {{9, 0, 0}, "macOS", {"Leopard", {10, 5, 0}}}, + "9B18" = {{9, 1, 0}, "macOS", {"Leopard", {10, 5, 1}}}, + "9B2117" = {{9, 1, 1}, "macOS", {"Leopard", {10, 5, 1}}}, + "9C31" = {{9, 2, 0}, "macOS", {"Leopard", {10, 5, 2}}}, + "9C7010" = {{9, 2, 0}, "macOS", {"Leopard", {10, 5, 2}}}, + "9D34" = {{9, 3, 0}, "macOS", {"Leopard", {10, 5, 3}}}, + "9E17" = {{9, 4, 0}, "macOS", {"Leopard", {10, 5, 4}}}, + "9F33" = {{9, 5, 0}, "macOS", {"Leopard", {10, 5, 5}}}, + "9G55" = {{9, 6, 0}, "macOS", {"Leopard", {10, 5, 6}}}, + "9G66" = {{9, 6, 0}, "macOS", {"Leopard", {10, 5, 6}}}, + "9G71" = {{9, 6, 0}, "macOS", {"Leopard", {10, 5, 6}}}, + "9J61" = {{9, 7, 0}, "macOS", {"Leopard", {10, 5, 7}}}, + "9L30" = {{9, 8, 0}, "macOS", {"Leopard", {10, 5, 8}}}, + "9L34" = {{9, 8, 0}, "macOS", {"Leopard", {10, 5, 8}}}, + + // MacOS Snow Leopard + "10A432" = {{10, 0, 0}, "macOS", {"Snow Leopard", {10, 6, 0}}}, + "10A433" = {{10, 0, 0}, "macOS", {"Snow Leopard", {10, 6, 0}}}, + "10B504" = {{10, 1, 0}, "macOS", {"Snow Leopard", {10, 6, 1}}}, + "10C540" = {{10, 2, 0}, "macOS", {"Snow Leopard", {10, 6, 2}}}, + "10D573" = {{10, 3, 0}, "macOS", {"Snow Leopard", {10, 6, 3}}}, + "10D575" = {{10, 3, 0}, "macOS", {"Snow Leopard", {10, 6, 3}}}, + "10D578" = {{10, 3, 0}, "macOS", {"Snow Leopard", {10, 6, 3}}}, + "10F569" = {{10, 4, 0}, "macOS", {"Snow Leopard", {10, 6, 4}}}, + "10H574" = {{10, 5, 0}, "macOS", {"Snow Leopard", {10, 6, 5}}}, + "10J567" = {{10, 6, 0}, "macOS", {"Snow Leopard", {10, 6, 6}}}, + "10J869" = {{10, 7, 0}, "macOS", {"Snow Leopard", {10, 6, 7}}}, + "10J3250" = {{10, 7, 0}, "macOS", {"Snow Leopard", {10, 6, 7}}}, + "10J4138" = {{10, 7, 0}, "macOS", {"Snow Leopard", {10, 6, 7}}}, + "10K540" = {{10, 8, 0}, "macOS", {"Snow Leopard", {10, 6, 8}}}, + "10K549" = {{10, 8, 0}, "macOS", {"Snow Leopard", {10, 6, 8}}}, + + // MacOS Lion + "11A511" = {{11, 0, 0}, "macOS", {"Lion", {10, 7, 0}}}, + "11A511s" = {{11, 0, 0}, "macOS", {"Lion", {10, 7, 0}}}, + "11A2061" = {{11, 0, 2}, "macOS", {"Lion", {10, 7, 0}}}, + "11A2063" = {{11, 0, 2}, "macOS", {"Lion", {10, 7, 0}}}, + "11B26" = {{11, 1, 0}, "macOS", {"Lion", {10, 7, 1}}}, + "11B2118" = {{11, 1, 0}, "macOS", {"Lion", {10, 7, 1}}}, + "11C74" = {{11, 2, 0}, "macOS", {"Lion", {10, 7, 2}}}, + "11D50" = {{11, 3, 0}, "macOS", {"Lion", {10, 7, 3}}}, + "11E53" = {{11, 4, 0}, "macOS", {"Lion", {10, 7, 4}}}, + "11G56" = {{11, 4, 2}, "macOS", {"Lion", {10, 7, 5}}}, + "11G63" = {{11, 4, 2}, "macOS", {"Lion", {10, 7, 5}}}, + + // MacOS Mountain Lion + "12A269" = {{12, 0, 0}, "macOS", {"Mountain Lion", {10, 8, 0}}}, + "12B19" = {{12, 1, 0}, "macOS", {"Mountain Lion", {10, 8, 1}}}, + "12C54" = {{12, 2, 0}, "macOS", {"Mountain Lion", {10, 8, 2}}}, + "12C60" = {{12, 2, 0}, "macOS", {"Mountain Lion", {10, 8, 2}}}, + "12C2034" = {{12, 2, 0}, "macOS", {"Mountain Lion", {10, 8, 2}}}, + "12C3104" = {{12, 2, 0}, "macOS", {"Mountain Lion", {10, 8, 2}}}, + "12D78" = {{12, 3, 0}, "macOS", {"Mountain Lion", {10, 8, 3}}}, + "12E55" = {{12, 4, 0}, "macOS", {"Mountain Lion", {10, 8, 4}}}, + "12E3067" = {{12, 4, 0}, "macOS", {"Mountain Lion", {10, 8, 4}}}, + "12E4022" = {{12, 4, 0}, "macOS", {"Mountain Lion", {10, 8, 4}}}, + "12F37" = {{12, 5, 0}, "macOS", {"Mountain Lion", {10, 8, 5}}}, + "12F45" = {{12, 5, 0}, "macOS", {"Mountain Lion", {10, 8, 5}}}, + "12F2501" = {{12, 5, 0}, "macOS", {"Mountain Lion", {10, 8, 5}}}, + "12F2518" = {{12, 5, 0}, "macOS", {"Mountain Lion", {10, 8, 5}}}, + "12F2542" = {{12, 5, 0}, "macOS", {"Mountain Lion", {10, 8, 5}}}, + "12F2560" = {{12, 5, 0}, "macOS", {"Mountain Lion", {10, 8, 5}}}, + + // MacOS Mavericks + "13A603" = {{13, 0, 0}, "macOS", {"Mavericks", {10, 9, 0}}}, + "13B42" = {{13, 0, 0}, "macOS", {"Mavericks", {10, 9, 1}}}, + "13C64" = {{13, 1, 0}, "macOS", {"Mavericks", {10, 9, 2}}}, + "13C1021" = {{13, 1, 0}, "macOS", {"Mavericks", {10, 9, 2}}}, + "13D65" = {{13, 2, 0}, "macOS", {"Mavericks", {10, 9, 3}}}, + "13E28" = {{13, 3, 0}, "macOS", {"Mavericks", {10, 9, 4}}}, + "13F34" = {{13, 4, 0}, "macOS", {"Mavericks", {10, 9, 5}}}, + "13F1066" = {{13, 4, 0}, "macOS", {"Mavericks", {10, 9, 5}}}, + "13F1077" = {{13, 4, 0}, "macOS", {"Mavericks", {10, 9, 5}}}, + "13F1096" = {{13, 4, 0}, "macOS", {"Mavericks", {10, 9, 5}}}, + "13F1112" = {{13, 4, 0}, "macOS", {"Mavericks", {10, 9, 5}}}, + "13F1134" = {{13, 4, 0}, "macOS", {"Mavericks", {10, 9, 5}}}, + "13F1507" = {{13, 4, 0}, "macOS", {"Mavericks", {10, 9, 5}}}, + "13F1603" = {{13, 4, 0}, "macOS", {"Mavericks", {10, 9, 5}}}, + "13F1712" = {{13, 4, 0}, "macOS", {"Mavericks", {10, 9, 5}}}, + "13F1808" = {{13, 4, 0}, "macOS", {"Mavericks", {10, 9, 5}}}, + "13F1911" = {{13, 4, 0}, "macOS", {"Mavericks", {10, 9, 5}}}, + + // MacOS Yosemite + "14A389" = {{14, 0, 0}, "macOS", {"Yosemite", {10, 10, 0}}}, + "14B25" = {{14, 0, 0}, "macOS", {"Yosemite", {10, 10, 1}}}, + "14C109" = {{14, 1, 0}, "macOS", {"Yosemite", {10, 10, 2}}}, + "14C1510" = {{14, 1, 0}, "macOS", {"Yosemite", {10, 10, 2}}}, + "14C2043" = {{14, 1, 0}, "macOS", {"Yosemite", {10, 10, 2}}}, + "14C1514" = {{14, 1, 0}, "macOS", {"Yosemite", {10, 10, 2}}}, + "14C2513" = {{14, 1, 0}, "macOS", {"Yosemite", {10, 10, 2}}}, + "14D131" = {{14, 3, 0}, "macOS", {"Yosemite", {10, 10, 3}}}, + "14D136" = {{14, 3, 0}, "macOS", {"Yosemite", {10, 10, 3}}}, + "14E46" = {{14, 4, 0}, "macOS", {"Yosemite", {10, 10, 4}}}, + "14F27" = {{14, 5, 0}, "macOS", {"Yosemite", {10, 10, 5}}}, + "14F1021" = {{14, 5, 0}, "macOS", {"Yosemite", {10, 10, 5}}}, + "14F1505" = {{14, 5, 0}, "macOS", {"Yosemite", {10, 10, 5}}}, + "14F1509" = {{14, 5, 0}, "macOS", {"Yosemite", {10, 10, 5}}}, + "14F1605" = {{14, 5, 0}, "macOS", {"Yosemite", {10, 10, 5}}}, + "14F1713" = {{14, 5, 0}, "macOS", {"Yosemite", {10, 10, 5}}}, + "14F1808" = {{14, 5, 0}, "macOS", {"Yosemite", {10, 10, 5}}}, + "14F1909" = {{14, 5, 0}, "macOS", {"Yosemite", {10, 10, 5}}}, + "14F1912" = {{14, 5, 0}, "macOS", {"Yosemite", {10, 10, 5}}}, + "14F2009" = {{14, 5, 0}, "macOS", {"Yosemite", {10, 10, 5}}}, + "14F2109" = {{14, 5, 0}, "macOS", {"Yosemite", {10, 10, 5}}}, + "14F2315" = {{14, 5, 0}, "macOS", {"Yosemite", {10, 10, 5}}}, + "14F2411" = {{14, 5, 0}, "macOS", {"Yosemite", {10, 10, 5}}}, + "14F2511" = {{14, 5, 0}, "macOS", {"Yosemite", {10, 10, 5}}}, + + // MacOS El Capitan + "15A284" = {{15, 0, 0}, "macOS", {"El Capitan", {10, 11, 0}}}, + "15B42" = {{15, 0, 0}, "macOS", {"El Capitan", {10, 11, 1}}}, + "15C50" = {{15, 2, 0}, "macOS", {"El Capitan", {10, 11, 2}}}, + "15D21" = {{15, 3, 0}, "macOS", {"El Capitan", {10, 11, 3}}}, + "15E65" = {{15, 4, 0}, "macOS", {"El Capitan", {10, 11, 4}}}, + "15F34" = {{15, 5, 0}, "macOS", {"El Capitan", {10, 11, 5}}}, + "15G31" = {{15, 6, 0}, "macOS", {"El Capitan", {10, 11, 6}}}, + "15G1004" = {{15, 6, 0}, "macOS", {"El Capitan", {10, 11, 6}}}, + "15G1011" = {{15, 6, 0}, "macOS", {"El Capitan", {10, 11, 6}}}, + "15G1108" = {{15, 6, 0}, "macOS", {"El Capitan", {10, 11, 6}}}, + "15G1212" = {{15, 6, 0}, "macOS", {"El Capitan", {10, 11, 6}}}, + "15G1217" = {{15, 6, 0}, "macOS", {"El Capitan", {10, 11, 6}}}, + "15G1421" = {{15, 6, 0}, "macOS", {"El Capitan", {10, 11, 6}}}, + "15G1510" = {{15, 6, 0}, "macOS", {"El Capitan", {10, 11, 6}}}, + "15G1611" = {{15, 6, 0}, "macOS", {"El Capitan", {10, 11, 6}}}, + "15G17023" = {{15, 6, 0}, "macOS", {"El Capitan", {10, 11, 6}}}, + "15G18013" = {{15, 6, 0}, "macOS", {"El Capitan", {10, 11, 6}}}, + "15G19009" = {{15, 6, 0}, "macOS", {"El Capitan", {10, 11, 6}}}, + "15G20015" = {{15, 6, 0}, "macOS", {"El Capitan", {10, 11, 6}}}, + "15G21013" = {{15, 6, 0}, "macOS", {"El Capitan", {10, 11, 6}}}, + "15G22010" = {{15, 6, 0}, "macOS", {"El Capitan", {10, 11, 6}}}, + + // MacOS Sierra + "16A323" = {{16, 0, 0}, "macOS", {"Sierra", {10, 12, 0}}}, + "16B2555" = {{16, 1, 0}, "macOS", {"Sierra", {10, 12, 1}}}, + "16B2657" = {{16, 1, 0}, "macOS", {"Sierra", {10, 12, 1}}}, + "16C67" = {{16, 3, 0}, "macOS", {"Sierra", {10, 12, 2}}}, + "16C68" = {{16, 3, 0}, "macOS", {"Sierra", {10, 12, 2}}}, + "16D32" = {{16, 4, 0}, "macOS", {"Sierra", {10, 12, 3}}}, + "16E195" = {{16, 5, 0}, "macOS", {"Sierra", {10, 12, 4}}}, + "16F73" = {{16, 6, 0}, "macOS", {"Sierra", {10, 12, 5}}}, + "16F2073" = {{16, 6, 0}, "macOS", {"Sierra", {10, 12, 5}}}, + "16G29" = {{16, 7, 0}, "macOS", {"Sierra", {10, 12, 6}}}, + "16G1036" = {{16, 7, 0}, "macOS", {"Sierra", {10, 12, 6}}}, + "16G1114" = {{16, 7, 0}, "macOS", {"Sierra", {10, 12, 6}}}, + "16G1212" = {{16, 7, 0}, "macOS", {"Sierra", {10, 12, 6}}}, + "16G1314" = {{16, 7, 0}, "macOS", {"Sierra", {10, 12, 6}}}, + "16G1408" = {{16, 7, 0}, "macOS", {"Sierra", {10, 12, 6}}}, + "16G1510" = {{16, 7, 0}, "macOS", {"Sierra", {10, 12, 6}}}, + "16G1618" = {{16, 7, 0}, "macOS", {"Sierra", {10, 12, 6}}}, + "16G1710" = {{16, 7, 0}, "macOS", {"Sierra", {10, 12, 6}}}, + "16G1815" = {{16, 7, 0}, "macOS", {"Sierra", {10, 12, 6}}}, + "16G1917" = {{16, 7, 0}, "macOS", {"Sierra", {10, 12, 6}}}, + "16G1918" = {{16, 7, 0}, "macOS", {"Sierra", {10, 12, 6}}}, + "16G2016" = {{16, 7, 0}, "macOS", {"Sierra", {10, 12, 6}}}, + "16G2127" = {{16, 7, 0}, "macOS", {"Sierra", {10, 12, 6}}}, + "16G2128" = {{16, 7, 0}, "macOS", {"Sierra", {10, 12, 6}}}, + "16G2136" = {{16, 7, 0}, "macOS", {"Sierra", {10, 12, 6}}}, + + // MacOS High Sierra + "17A365" = {{17, 0, 0}, "macOS", {"High Sierra", {10, 13, 0}}}, + "17A405" = {{17, 0, 0}, "macOS", {"High Sierra", {10, 13, 0}}}, + "17B48" = {{17, 2, 0}, "macOS", {"High Sierra", {10, 13, 1}}}, + "17B1002" = {{17, 2, 0}, "macOS", {"High Sierra", {10, 13, 1}}}, + "17B1003" = {{17, 2, 0}, "macOS", {"High Sierra", {10, 13, 1}}}, + "17C88" = {{17, 3, 0}, "macOS", {"High Sierra", {10, 13, 2}}}, + "17C89" = {{17, 3, 0}, "macOS", {"High Sierra", {10, 13, 2}}}, + "17C205" = {{17, 3, 0}, "macOS", {"High Sierra", {10, 13, 2}}}, + "17C2205" = {{17, 3, 0}, "macOS", {"High Sierra", {10, 13, 2}}}, + "17D47" = {{17, 4, 0}, "macOS", {"High Sierra", {10, 13, 3}}}, + "17D2047" = {{17, 4, 0}, "macOS", {"High Sierra", {10, 13, 3}}}, + "17D102" = {{17, 4, 0}, "macOS", {"High Sierra", {10, 13, 3}}}, + "17D2102" = {{17, 4, 0}, "macOS", {"High Sierra", {10, 13, 3}}}, + "17E199" = {{17, 5, 0}, "macOS", {"High Sierra", {10, 13, 4}}}, + "17E202" = {{17, 5, 0}, "macOS", {"High Sierra", {10, 13, 4}}}, + "17F77" = {{17, 6, 0}, "macOS", {"High Sierra", {10, 13, 5}}}, + "17G65" = {{17, 7, 0}, "macOS", {"High Sierra", {10, 13, 6}}}, + "17G2208" = {{17, 7, 0}, "macOS", {"High Sierra", {10, 13, 6}}}, + "17G2307" = {{17, 7, 0}, "macOS", {"High Sierra", {10, 13, 6}}}, + "17G3025" = {{17, 7, 0}, "macOS", {"High Sierra", {10, 13, 6}}}, + "17G4015" = {{17, 7, 0}, "macOS", {"High Sierra", {10, 13, 6}}}, + "17G5019" = {{17, 7, 0}, "macOS", {"High Sierra", {10, 13, 6}}}, + "17G6029" = {{17, 7, 0}, "macOS", {"High Sierra", {10, 13, 6}}}, + "17G6030" = {{17, 7, 0}, "macOS", {"High Sierra", {10, 13, 6}}}, + "17G7024" = {{17, 7, 0}, "macOS", {"High Sierra", {10, 13, 6}}}, + "17G8029" = {{17, 7, 0}, "macOS", {"High Sierra", {10, 13, 6}}}, + "17G8030" = {{17, 7, 0}, "macOS", {"High Sierra", {10, 13, 6}}}, + "17G8037" = {{17, 7, 0}, "macOS", {"High Sierra", {10, 13, 6}}}, + "17G9016" = {{17, 7, 0}, "macOS", {"High Sierra", {10, 13, 6}}}, + "17G10021" = {{17, 7, 0}, "macOS", {"High Sierra", {10, 13, 6}}}, + "17G11023" = {{17, 7, 0}, "macOS", {"High Sierra", {10, 13, 6}}}, + "17G12034" = {{17, 7, 0}, "macOS", {"High Sierra", {10, 13, 6}}}, + "17G13033" = {{17, 7, 0}, "macOS", {"High Sierra", {10, 13, 6}}}, + "17G13035" = {{17, 7, 0}, "macOS", {"High Sierra", {10, 13, 6}}}, + "17G14019" = {{17, 7, 0}, "macOS", {"High Sierra", {10, 13, 6}}}, + "17G14033" = {{17, 7, 0}, "macOS", {"High Sierra", {10, 13, 6}}}, + "17G14042" = {{17, 7, 0}, "macOS", {"High Sierra", {10, 13, 6}}}, + + // MacOS Mojave + "18A391" = {{18, 0, 0}, "macOS", {"Mojave", {10, 14, 0}}}, + "18B75" = {{18, 2, 0}, "macOS", {"Mojave", {10, 14, 1}}}, + "18B2107" = {{18, 2, 0}, "macOS", {"Mojave", {10, 14, 1}}}, + "18B3094" = {{18, 2, 0}, "macOS", {"Mojave", {10, 14, 1}}}, + "18C54" = {{18, 2, 0}, "macOS", {"Mojave", {10, 14, 2}}}, + "18D42" = {{18, 2, 0}, "macOS", {"Mojave", {10, 14, 3}}}, + "18D43" = {{18, 2, 0}, "macOS", {"Mojave", {10, 14, 3}}}, + "18D109" = {{18, 2, 0}, "macOS", {"Mojave", {10, 14, 3}}}, + "18E226" = {{18, 5, 0}, "macOS", {"Mojave", {10, 14, 4}}}, + "18E227" = {{18, 5, 0}, "macOS", {"Mojave", {10, 14, 4}}}, + "18F132" = {{18, 6, 0}, "macOS", {"Mojave", {10, 14, 5}}}, + "18G84" = {{18, 7, 0}, "macOS", {"Mojave", {10, 14, 6}}}, + "18G87" = {{18, 7, 0}, "macOS", {"Mojave", {10, 14, 6}}}, + "18G95" = {{18, 7, 0}, "macOS", {"Mojave", {10, 14, 6}}}, + "18G103" = {{18, 7, 0}, "macOS", {"Mojave", {10, 14, 6}}}, + "18G1012" = {{18, 7, 0}, "macOS", {"Mojave", {10, 14, 6}}}, + "18G2022" = {{18, 7, 0}, "macOS", {"Mojave", {10, 14, 6}}}, + "18G3020" = {{18, 7, 0}, "macOS", {"Mojave", {10, 14, 6}}}, + "18G4032" = {{18, 7, 0}, "macOS", {"Mojave", {10, 14, 6}}}, + "18G5033" = {{18, 7, 0}, "macOS", {"Mojave", {10, 14, 6}}}, + "18G6020" = {{18, 7, 0}, "macOS", {"Mojave", {10, 14, 6}}}, + "18G6032" = {{18, 7, 0}, "macOS", {"Mojave", {10, 14, 6}}}, + "18G6042" = {{18, 7, 0}, "macOS", {"Mojave", {10, 14, 6}}}, + "18G7016" = {{18, 7, 0}, "macOS", {"Mojave", {10, 14, 6}}}, + "18G8012" = {{18, 7, 0}, "macOS", {"Mojave", {10, 14, 6}}}, + "18G8022" = {{18, 7, 0}, "macOS", {"Mojave", {10, 14, 6}}}, + "18G9028" = {{18, 7, 0}, "macOS", {"Mojave", {10, 14, 6}}}, + "18G9216" = {{18, 7, 0}, "macOS", {"Mojave", {10, 14, 6}}}, + "18G9323" = {{18, 7, 0}, "macOS", {"Mojave", {10, 14, 6}}}, + + // MacOS Catalina + "19A583" = {{19, 0, 0}, "macOS", {"Catalina", {10, 15, 0}}}, + "19A602" = {{19, 0, 0}, "macOS", {"Catalina", {10, 15, 0}}}, + "19A603" = {{19, 0, 0}, "macOS", {"Catalina", {10, 15, 0}}}, + "19B88" = {{19, 0, 0}, "macOS", {"Catalina", {10, 15, 1}}}, + "19C57" = {{19, 2, 0}, "macOS", {"Catalina", {10, 15, 2}}}, + "19C58" = {{19, 2, 0}, "macOS", {"Catalina", {10, 15, 2}}}, + "19D76" = {{19, 3, 0}, "macOS", {"Catalina", {10, 15, 3}}}, + "19E266" = {{19, 4, 0}, "macOS", {"Catalina", {10, 15, 4}}}, + "19E287" = {{19, 4, 0}, "macOS", {"Catalina", {10, 15, 4}}}, + "19F96" = {{19, 5, 0}, "macOS", {"Catalina", {10, 15, 5}}}, + "19F101" = {{19, 5, 0}, "macOS", {"Catalina", {10, 15, 5}}}, + "19G73" = {{19, 6, 0}, "macOS", {"Catalina", {10, 15, 6}}}, + "19G2021" = {{19, 6, 0}, "macOS", {"Catalina", {10, 15, 6}}}, + "19H2" = {{19, 6, 0}, "macOS", {"Catalina", {10, 15, 7}}}, + "19H4" = {{19, 6, 0}, "macOS", {"Catalina", {10, 15, 7}}}, + "19H15" = {{19, 6, 0}, "macOS", {"Catalina", {10, 15, 7}}}, + "19H114" = {{19, 6, 0}, "macOS", {"Catalina", {10, 15, 7}}}, + "19H512" = {{19, 6, 0}, "macOS", {"Catalina", {10, 15, 7}}}, + "19H524" = {{19, 6, 0}, "macOS", {"Catalina", {10, 15, 7}}}, + "19H1030" = {{19, 6, 0}, "macOS", {"Catalina", {10, 15, 7}}}, + "19H1217" = {{19, 6, 0}, "macOS", {"Catalina", {10, 15, 7}}}, + "19H1323" = {{19, 6, 0}, "macOS", {"Catalina", {10, 15, 7}}}, + "19H1417" = {{19, 6, 0}, "macOS", {"Catalina", {10, 15, 7}}}, + "19H1419" = {{19, 6, 0}, "macOS", {"Catalina", {10, 15, 7}}}, + "19H1519" = {{19, 6, 0}, "macOS", {"Catalina", {10, 15, 7}}}, + "19H1615" = {{19, 6, 0}, "macOS", {"Catalina", {10, 15, 7}}}, + "19H1713" = {{19, 6, 0}, "macOS", {"Catalina", {10, 15, 7}}}, + "19H1715" = {{19, 6, 0}, "macOS", {"Catalina", {10, 15, 7}}}, + "19H1824" = {{19, 6, 0}, "macOS", {"Catalina", {10, 15, 7}}}, + "19H1922" = {{19, 6, 0}, "macOS", {"Catalina", {10, 15, 7}}}, + "19H2026" = {{19, 6, 0}, "macOS", {"Catalina", {10, 15, 7}}}, + + // MacOS Big Sur + "20A2411" = {{20, 1, 0}, "macOS", {"Big Sur", {11, 0, 0}}}, + "20B29" = {{20, 1, 0}, "macOS", {"Big Sur", {11, 0, 1}}}, + "20B50" = {{20, 1, 0}, "macOS", {"Big Sur", {11, 0, 1}}}, + "20C69" = {{20, 2, 0}, "macOS", {"Big Sur", {11, 1, 0}}}, + "20D64" = {{20, 3, 0}, "macOS", {"Big Sur", {11, 2, 0}}}, + "20D74" = {{20, 3, 0}, "macOS", {"Big Sur", {11, 2, 1}}}, + "20D75" = {{20, 3, 0}, "macOS", {"Big Sur", {11, 2, 1}}}, + "20D80" = {{20, 3, 0}, "macOS", {"Big Sur", {11, 2, 2}}}, + "20D91" = {{20, 3, 0}, "macOS", {"Big Sur", {11, 2, 3}}}, + "20E232" = {{20, 4, 0}, "macOS", {"Big Sur", {11, 3, 0}}}, + "20E241" = {{20, 4, 0}, "macOS", {"Big Sur", {11, 3, 1}}}, + "20F71" = {{20, 5, 0}, "macOS", {"Big Sur", {11, 4, 0}}}, + "20G71" = {{20, 6, 0}, "macOS", {"Big Sur", {11, 5, 0}}}, + "20G80" = {{20, 6, 0}, "macOS", {"Big Sur", {11, 5, 1}}}, + "20G95" = {{20, 6, 0}, "macOS", {"Big Sur", {11, 5, 2}}}, + "20G165" = {{20, 6, 0}, "macOS", {"Big Sur", {11, 6, 0}}}, + "20G224" = {{20, 6, 0}, "macOS", {"Big Sur", {11, 6, 1}}}, + "20G314" = {{20, 6, 0}, "macOS", {"Big Sur", {11, 6, 2}}}, + "20G415" = {{20, 6, 0}, "macOS", {"Big Sur", {11, 6, 3}}}, + "20G417" = {{20, 6, 0}, "macOS", {"Big Sur", {11, 6, 4}}}, + "20G527" = {{20, 6, 0}, "macOS", {"Big Sur", {11, 6, 5}}}, + "20G624" = {{20, 6, 0}, "macOS", {"Big Sur", {11, 6, 6}}}, + "20G630" = {{20, 6, 0}, "macOS", {"Big Sur", {11, 6, 7}}}, + "20G730" = {{20, 6, 0}, "macOS", {"Big Sur", {11, 6, 8}}}, + + // MacOS Monterey + "21A344" = {{21, 0, 1}, "macOS", {"Monterey", {12, 0, 0}}}, + "21A559" = {{21, 1, 0}, "macOS", {"Monterey", {12, 0, 1}}}, + "21C52" = {{21, 2, 0}, "macOS", {"Monterey", {12, 1, 0}}}, + "21D49" = {{21, 3, 0}, "macOS", {"Monterey", {12, 2, 0}}}, + "21D62" = {{21, 3, 0}, "macOS", {"Monterey", {12, 2, 1}}}, + "21E230" = {{21, 4, 0}, "macOS", {"Monterey", {12, 3, 0}}}, + "21E258" = {{21, 4, 0}, "macOS", {"Monterey", {12, 3, 1}}}, + "21F79" = {{21, 5, 0}, "macOS", {"Monterey", {12, 4, 0}}}, + "21F2081" = {{21, 5, 0}, "macOS", {"Monterey", {12, 4, 0}}}, + "21F2092" = {{21, 5, 0}, "macOS", {"Monterey", {12, 4, 0}}}, + "21G72" = {{21, 6, 0}, "macOS", {"Monterey", {12, 5, 0}}}, + "21G83" = {{21, 6, 0}, "macOS", {"Monterey", {12, 5, 1}}}, +} + +@(private) +Darwin_Match :: enum { + Unknown, + Exact, + Nearest, +} + +@(private) +map_darwin_kernel_version_to_macos_release :: proc(build: string, darwin: [3]int) -> (res: Darwin_To_Release, match: Darwin_Match) { + // Find exact release match if possible. + if v, v_ok := macos_release_map[build]; v_ok { + return v, .Exact + } + + nearest: Darwin_To_Release + for _, v in macos_release_map { + // Try an exact match on XNU version first. + if darwin == v.darwin { + return v, .Exact + } + + // Major kernel version needs to match exactly, + // otherwise the release is considered .Unknown + if darwin.x == v.darwin.x { + if nearest == {} { + nearest = v + } + if darwin.y >= v.darwin.y && v.darwin != nearest.darwin { + nearest = v + if darwin.z >= v.darwin.z && v.darwin != nearest.darwin { + nearest = v + } + } + } + } + + if nearest == {} { + return {darwin, "macOS", {"Unknown", {}}}, .Unknown + } else { + return nearest, .Nearest + } +} \ No newline at end of file diff --git a/core/sys/info/platform_freebsd.odin b/core/sys/info/platform_freebsd.odin new file mode 100644 index 000000000..0ca2841be --- /dev/null +++ b/core/sys/info/platform_freebsd.odin @@ -0,0 +1,76 @@ +// +build freebsd +package sysinfo + +import sys "core:sys/unix" +import "core:strings" +import "core:strconv" + +@(private) +version_string_buf: [1024]u8 + +@(init, private) +init_os_version :: proc () { + os_version.platform = .FreeBSD + + kernel_version_buf: [129]u8 + + b := strings.builder_from_bytes(version_string_buf[:]) + // Retrieve kernel info using `sysctl`, e.g. FreeBSD 13.1-RELEASE-p2 GENERIC + mib := []i32{sys.CTL_KERN, sys.KERN_VERSION} + if !sys.sysctl(mib, &kernel_version_buf) { + return + } + + pretty_name := string(cstring(raw_data(kernel_version_buf[:]))) + pretty_name = strings.trim(pretty_name, "\n") + strings.write_string(&b, pretty_name) + + // l := strings.builder_len(b) + + // Retrieve kernel revision using `sysctl`, e.g. 199506 + mib = []i32{sys.CTL_KERN, sys.KERN_OSREV} + revision: int + if !sys.sysctl(mib, &revision) { + return + } + os_version.patch = revision + + strings.write_string(&b, ", revision ") + strings.write_int(&b, revision) + + // Finalize pretty name. + os_version.as_string = strings.to_string(b) + + // Retrieve kernel release using `sysctl`, e.g. 13.1-RELEASE-p2 + mib = []i32{sys.CTL_KERN, sys.KERN_OSRELEASE} + if !sys.sysctl(mib, &kernel_version_buf) { + return + } + + // Parse kernel version + release := string(cstring(raw_data(kernel_version_buf[:]))) + version_bits := strings.split_n(release, "-", 2, context.temp_allocator) + if len(version_bits) > 1 { + // Parse major, minor from KERN_OSRELEASE + triplet := strings.split(version_bits[0], ".", context.temp_allocator) + if len(triplet) == 2 { + major, major_ok := strconv.parse_int(triplet[0]) + minor, minor_ok := strconv.parse_int(triplet[1]) + + if major_ok && minor_ok { + os_version.major = major + os_version.minor = minor + } + } + } +} + +@(init) +init_ram :: proc() { + // Retrieve RAM info using `sysctl` + mib := []i32{sys.CTL_HW, sys.HW_PHYSMEM} + mem_size: u64 + if sys.sysctl(mib, &mem_size) { + ram.total_ram = int(mem_size) + } +} \ No newline at end of file diff --git a/core/sys/info/platform_linux.odin b/core/sys/info/platform_linux.odin new file mode 100644 index 000000000..d1f9ca599 --- /dev/null +++ b/core/sys/info/platform_linux.odin @@ -0,0 +1,136 @@ +// +build linux +package sysinfo + +import "core:c" +import sys "core:sys/unix" +import "core:intrinsics" +import "core:os" +import "core:strings" +import "core:strconv" + +@(private) +version_string_buf: [1024]u8 + +@(init, private) +init_os_version :: proc () { + os_version.platform = .Linux + + // Try to parse `/etc/os-release` for `PRETTY_NAME="Ubuntu 20.04.3 LTS` + fd, err := os.open("/etc/os-release", os.O_RDONLY, 0) + if err != 0 { + return + } + defer os.close(fd) + + os_release_buf: [2048]u8 + n, read_err := os.read(fd, os_release_buf[:]) + if read_err != 0 { + return + } + release := string(os_release_buf[:n]) + + NEEDLE :: "PRETTY_NAME=\"" + pretty_start := strings.index(release, NEEDLE) + + b := strings.builder_from_bytes(version_string_buf[:]) + + if pretty_start > 0 { + for r, i in release[pretty_start + len(NEEDLE):] { + if r == '"' { + strings.write_string(&b, release[pretty_start + len(NEEDLE):][:i]) + break + } else if r == '\r' || r == '\n' { + strings.write_string(&b, "Unknown Linux Distro") + break + } + } + } + + NEW_UTS_LEN :: 64 + UTS_Name :: struct { + sys_name: [NEW_UTS_LEN + 1]u8 `fmt:"s,0"`, + node_name: [NEW_UTS_LEN + 1]u8 `fmt:"s,0"`, + release: [NEW_UTS_LEN + 1]u8 `fmt:"s,0"`, + version: [NEW_UTS_LEN + 1]u8 `fmt:"s,0"`, + machine: [NEW_UTS_LEN + 1]u8 `fmt:"s,0"`, + domain_name: [NEW_UTS_LEN + 1]u8 `fmt:"s,0"`, + } + uts: UTS_Name + + // Grab kernel info using `uname()` syscall, https://linux.die.net/man/2/uname + if intrinsics.syscall(sys.SYS_uname, uintptr(&uts)) != 0 { + return + } + + strings.write_string(&b, ", ") + strings.write_string(&b, string(cstring(&uts.sys_name[0]))) + strings.write_rune(&b, ' ') + + l := strings.builder_len(b) + strings.write_string(&b, string(cstring(&uts.release[0]))) + + // Parse kernel version, as substrings of the version info in `version_string_buf` + version_bits := strings.split_n(strings.to_string(b)[l:], "-", 2, context.temp_allocator) + if len(version_bits) > 1 { + os_version.version = version_bits[1] + } + + // Parse major, minor, patch from release info + triplet := strings.split(version_bits[0], ".", context.temp_allocator) + if len(triplet) == 3 { + major, major_ok := strconv.parse_int(triplet[0]) + minor, minor_ok := strconv.parse_int(triplet[1]) + patch, patch_ok := strconv.parse_int(triplet[2]) + + if major_ok && minor_ok && patch_ok { + os_version.major = major + os_version.minor = minor + os_version.patch = patch + } + } + + // Finish the string + os_version.as_string = strings.to_string(b) +} + +Sys_Info :: struct { + uptime: c.long, // Seconds since boot + loads: [3]c.long, // 1, 5, 15 minute load averages + totalram: c.ulong, // Total usable main memory size + freeram: c.ulong, // Available memory size + sharedram: c.ulong, // Amount of shared memory + bufferram: c.ulong, // Memory used by buffers + totalswap: c.ulong, // Total swap space size + freeswap: c.ulong, // Swap space still available + procs: c.ushort, // Number of current processes + totalhigh: c.ulong, // Total high memory size + freehigh: c.ulong, // Available high memory size + mem_unit: c.int, // Memory unit size in bytes + _padding: [20 - (2 * size_of(c.long)) - size_of(c.int)]u8, +} + +get_sysinfo :: proc "c" () -> (res: Sys_Info, ok: bool) { + si: Sys_Info + err := intrinsics.syscall(sys.SYS_sysinfo, uintptr(rawptr(&si))) + if err != 0 { + // Unable to retrieve sysinfo + return {}, false + } + return si, true +} + +@(init) +init_ram :: proc() { + // Retrieve RAM info using `sysinfo` + si, ok := get_sysinfo() + if !ok { + return + } + + ram = RAM{ + total_ram = int(si.totalram) * int(si.mem_unit), + free_ram = int(si.freeram) * int(si.mem_unit), + total_swap = int(si.totalswap) * int(si.mem_unit), + free_swap = int(si.freeswap) * int(si.mem_unit), + } +} \ No newline at end of file diff --git a/core/sys/info/platform_openbsd.odin b/core/sys/info/platform_openbsd.odin new file mode 100644 index 000000000..080fad9b7 --- /dev/null +++ b/core/sys/info/platform_openbsd.odin @@ -0,0 +1,69 @@ +// +build openbsd +package sysinfo + +import sys "core:sys/unix" +import "core:strings" +import "core:strconv" + +@(private) +version_string_buf: [1024]u8 + +@(init, private) +init_os_version :: proc () { + os_version.platform = .OpenBSD + + kernel_version_buf: [1024]u8 + + b := strings.builder_from_bytes(version_string_buf[:]) + // Retrieve kernel info using `sysctl`, e.g. OpenBSD + mib := []i32{sys.CTL_KERN, sys.KERN_OSTYPE} + if !sys.sysctl(mib, &kernel_version_buf) { + return + } + os_type := string(cstring(raw_data(kernel_version_buf[:]))) + strings.write_string(&b, os_type) + + mib = []i32{sys.CTL_KERN, sys.KERN_OSRELEASE} + if !sys.sysctl(mib, &kernel_version_buf) { + return + } + + strings.write_rune(&b, ' ') + version := string(cstring(raw_data(kernel_version_buf[:]))) + strings.write_string(&b, version) + + // // Parse kernel version + triplet := strings.split(version, ".", context.temp_allocator) + if len(triplet) == 2 { + major, major_ok := strconv.parse_int(triplet[0]) + minor, minor_ok := strconv.parse_int(triplet[1]) + + if major_ok && minor_ok { + os_version.major = major + os_version.minor = minor + } + } + + // Retrieve kernel revision using `sysctl`, e.g. 199506 + mib = []i32{sys.CTL_KERN, sys.KERN_OSREV} + revision: int + if !sys.sysctl(mib, &revision) { + return + } + os_version.patch = revision + strings.write_string(&b, ", build ") + strings.write_int(&b, revision) + + // Finalize pretty name. + os_version.as_string = strings.to_string(b) +} + +@(init) +init_ram :: proc() { + // Retrieve RAM info using `sysctl` + mib := []i32{sys.CTL_HW, sys.HW_PHYSMEM64} + mem_size: u64 + if sys.sysctl(mib, &mem_size) { + ram.total_ram = int(mem_size) + } +} \ No newline at end of file diff --git a/core/sys/info/platform_windows.odin b/core/sys/info/platform_windows.odin new file mode 100644 index 000000000..f7f689346 --- /dev/null +++ b/core/sys/info/platform_windows.odin @@ -0,0 +1,375 @@ +// +build windows +package sysinfo + +import sys "core:sys/windows" +import "core:intrinsics" +import "core:strings" +import "core:unicode/utf16" + +import "core:fmt" + +@(private) +version_string_buf: [1024]u8 + +@(init, private) +init_os_version :: proc () { + /* + NOTE(Jeroen): + `GetVersionEx` will return 6.2 for Windows 10 unless the program is manifested for Windows 10. + `RtlGetVersion` will return the true version. + + Rather than include the WinDDK, we ask the kernel directly. + `HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion` is for the minor build version (Update Build Release) + + */ + os_version.platform = .Windows + + osvi: sys.OSVERSIONINFOEXW + osvi.dwOSVersionInfoSize = size_of(osvi) + status := sys.RtlGetVersion(&osvi) + + if status != 0 { + return + } + + product_type: sys.Windows_Product_Type + sys.GetProductInfo( + osvi.dwMajorVersion, osvi.dwMinorVersion, + u32(osvi.wServicePackMajor), u32(osvi.wServicePackMinor), + &product_type, + ) + + os_version.major = int(osvi.dwMajorVersion) + os_version.minor = int(osvi.dwMinorVersion) + os_version.build[0] = int(osvi.dwBuildNumber) + + b := strings.builder_from_bytes(version_string_buf[:]) + strings.write_string(&b, "Windows ") + + switch osvi.dwMajorVersion { + case 10: + switch osvi.wProductType { + case 1: // VER_NT_WORKSTATION: + if osvi.dwBuildNumber < 22000 { + strings.write_string(&b, "10 ") + } else { + strings.write_string(&b, "11 ") + } + format_windows_product_type(&b, product_type) + + case: // Server or Domain Controller + switch osvi.dwBuildNumber { + case 14393: + strings.write_string(&b, "2016 Server") + case 17763: + strings.write_string(&b, "2019 Server") + case 20348: + strings.write_string(&b, "2022 Server") + case: + strings.write_string(&b, "Unknown Server") + } + } + + case 6: + switch osvi.dwMinorVersion { + case 0: + switch osvi.wProductType { + case 1: // VER_NT_WORKSTATION + strings.write_string(&b, "Windows Vista ") + format_windows_product_type(&b, product_type) + case 3: + strings.write_string(&b, "Windows Server 2008") + } + + case 1: + switch osvi.wProductType { + case 1: // VER_NT_WORKSTATION: + strings.write_string(&b, "Windows 7 ") + format_windows_product_type(&b, product_type) + case 3: + strings.write_string(&b, "Windows Server 2008 R2") + } + + case 2: + switch osvi.wProductType { + case 1: // VER_NT_WORKSTATION: + strings.write_string(&b, "Windows 8 ") + format_windows_product_type(&b, product_type) + case 3: + strings.write_string(&b, "Windows Server 2012") + } + + case 3: + switch osvi.wProductType { + case 1: // VER_NT_WORKSTATION: + strings.write_string(&b, "Windows 8.1 ") + format_windows_product_type(&b, product_type) + case 3: + strings.write_string(&b, "Windows Server 2012 R2") + } + } + + case 5: + switch osvi.dwMinorVersion { + case 0: + strings.write_string(&b, "Windows 2000") + case 1: + strings.write_string(&b, "Windows XP") + case 2: + strings.write_string(&b, "Windows Server 2003") + } + } + + // Grab DisplayVersion + os_version.version = format_display_version(&b) + + // Grab build number and UBR + os_version.build[1] = format_build_number(&b, int(osvi.dwBuildNumber)) + + // Finish the string + os_version.as_string = strings.to_string(b) + + format_windows_product_type :: proc (b: ^strings.Builder, prod_type: sys.Windows_Product_Type) { + #partial switch prod_type { + case .ULTIMATE: + strings.write_string(b, "Ultimate") + + case .HOME_BASIC: + strings.write_string(b, "Home Basic") + + case .HOME_PREMIUM: + strings.write_string(b, "Home Premium") + + case .ENTERPRISE: + strings.write_string(b, "Enterprise") + + case .CORE: + strings.write_string(b, "Home Basic") + + case .HOME_BASIC_N: + strings.write_string(b, "Home Basic N") + + case .EDUCATION: + strings.write_string(b, "Education") + + case .EDUCATION_N: + strings.write_string(b, "Education N") + + case .BUSINESS: + strings.write_string(b, "Business") + + case .STANDARD_SERVER: + strings.write_string(b, "Standard Server") + + case .DATACENTER_SERVER: + strings.write_string(b, "Datacenter") + + case .SMALLBUSINESS_SERVER: + strings.write_string(b, "Windows Small Business Server") + + case .ENTERPRISE_SERVER: + strings.write_string(b, "Enterprise Server") + + case .STARTER: + strings.write_string(b, "Starter") + + case .DATACENTER_SERVER_CORE: + strings.write_string(b, "Datacenter Server Core") + + case .STANDARD_SERVER_CORE: + strings.write_string(b, "Server Standard Core") + + case .ENTERPRISE_SERVER_CORE: + strings.write_string(b, "Enterprise Server Core") + + case .BUSINESS_N: + strings.write_string(b, "Business N") + + case .HOME_SERVER: + strings.write_string(b, "Home Server") + + case .SERVER_FOR_SMALLBUSINESS: + strings.write_string(b, "Windows Server 2008 for Windows Essential Server Solutions") + + case .SMALLBUSINESS_SERVER_PREMIUM: + strings.write_string(b, "Small Business Server Premium") + + case .HOME_PREMIUM_N: + strings.write_string(b, "Home Premium N") + + case .ENTERPRISE_N: + strings.write_string(b, "Enterprise N") + + case .ULTIMATE_N: + strings.write_string(b, "Ultimate N") + + case .HYPERV: + strings.write_string(b, "HyperV") + + case .STARTER_N: + strings.write_string(b, "Starter N") + + case .PROFESSIONAL: + strings.write_string(b, "Professional") + + case .PROFESSIONAL_N: + strings.write_string(b, "Professional N") + + case: + strings.write_string(b, "Unknown Edition") + } + } + + // Grab Windows DisplayVersion (like 20H02) + format_display_version :: proc (b: ^strings.Builder) -> (version: string) { + dv, ok := read_reg( + sys.HKEY_LOCAL_MACHINE, + "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", + "DisplayVersion", + string, + ) + defer delete(dv) // It'll be interned into `version_string_buf` + + if ok { + strings.write_string(b, " (version: ") + l := strings.builder_len(b^) + strings.write_string(b, dv) + version = strings.to_string(b^)[l:][:len(dv)] + strings.write_rune(b, ')') + } + return + } + + // Grab build number and UBR + format_build_number :: proc (b: ^strings.Builder, major_build: int) -> (ubr: int) { + res, ok := read_reg( + sys.HKEY_LOCAL_MACHINE, + "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", + "UBR", + i32, + ) + + if ok { + ubr = int(res) + strings.write_string(b, ", build: ") + strings.write_int(b, major_build) + strings.write_rune(b, '.') + strings.write_int(b, ubr) + } + return + } +} + +@(init) +init_ram :: proc() { + state: sys.MEMORYSTATUSEX + + state.dwLength = size_of(state) + ok := sys.GlobalMemoryStatusEx(&state) + if !ok { + return + } + ram = RAM{ + total_ram = int(state.ullTotalPhys), + free_ram = int(state.ullAvailPhys), + total_swap = int(state.ullTotalPageFil), + free_swap = int(state.ullAvailPageFil), + } +} + +@(init, private) +init_gpu_info :: proc() { + + GPU_INFO_BASE :: "SYSTEM\\ControlSet001\\Control\\Class\\{4d36e968-e325-11ce-bfc1-08002be10318}\\" + + gpu_list: [dynamic]GPU + gpu_index: int + + for { + key := fmt.tprintf("%v\\%04d", GPU_INFO_BASE, gpu_index) + + if vendor, ok := read_reg(sys.HKEY_LOCAL_MACHINE, key, "ProviderName", string); ok { + append(&gpu_list, GPU{vendor_name = vendor}) + } else { + break + } + + if desc, ok := read_reg(sys.HKEY_LOCAL_MACHINE, key, "DriverDesc", string); ok { + gpu_list[gpu_index].model_name = desc + } + + if vram, ok := read_reg(sys.HKEY_LOCAL_MACHINE, key, "HardwareInformation.qwMemorySize", i64); ok { + gpu_list[gpu_index].total_ram = int(vram) + } + gpu_index += 1 + } + gpus = gpu_list[:] +} + +@(private) +read_reg :: proc(hkey: sys.HKEY, subkey, val: string, $T: typeid) -> (res: T, ok: bool) { + BUF_SIZE :: 1024 + + if len(subkey) == 0 || len(val) == 0 { + return {}, false + } + + key_name_wide := make([]u16, BUF_SIZE, context.temp_allocator) + val_name_wide := make([]u16, BUF_SIZE, context.temp_allocator) + + utf16.encode_string(key_name_wide, subkey) + utf16.encode_string(val_name_wide, val) + + when T == string { + result_wide := make([]u16, BUF_SIZE, context.temp_allocator) + result_size := sys.DWORD(BUF_SIZE * size_of(u16)) + + status := sys.RegGetValueW( + hkey, + &key_name_wide[0], + &val_name_wide[0], + sys.RRF_RT_REG_SZ, + nil, + raw_data(result_wide[:]), + &result_size, + ) + if status != 0 { + // Couldn't retrieve string + return + } + + // Result string will be allocated for the caller. + result_utf8 := make([]u8, BUF_SIZE * 4, context.temp_allocator) + utf16.decode_to_utf8(result_utf8, result_wide[:result_size]) + return strings.clone_from_cstring(cstring(raw_data(result_utf8))), true + + } else when T == i32 { + result_size := sys.DWORD(size_of(i32)) + status := sys.RegGetValueW( + hkey, + &key_name_wide[0], + &val_name_wide[0], + sys.RRF_RT_REG_DWORD, + nil, + &res, + &result_size, + ) + return res, status == 0 + + } else when T == i64 { + result_size := sys.DWORD(size_of(i64)) + status := sys.RegGetValueW( + hkey, + &key_name_wide[0], + &val_name_wide[0], + sys.RRF_RT_REG_QWORD, + nil, + &res, + &result_size, + ) + return res, status == 0 + } else { + #assert(false, "Unhandled type for read_reg") + } + return +} \ No newline at end of file diff --git a/core/sys/info/sysinfo.odin b/core/sys/info/sysinfo.odin new file mode 100644 index 000000000..69f9f1584 --- /dev/null +++ b/core/sys/info/sysinfo.odin @@ -0,0 +1,45 @@ +package sysinfo + +when !(ODIN_ARCH == .amd64 || ODIN_ARCH == .i386 || ODIN_ARCH == .arm32 || ODIN_ARCH == .arm64) { + #assert(false, "This package is unsupported on this architecture.") +} + +os_version: OS_Version +ram: RAM +gpus: []GPU + +OS_Version_Platform :: enum { + Unknown, + Windows, + Linux, + MacOS, + iOS, + FreeBSD, + OpenBSD, + NetBSD, +} + +OS_Version :: struct { + platform: OS_Version_Platform, + + major: int, + minor: int, + patch: int, + build: [2]int, + version: string, + + as_string: string, +} + +RAM :: struct { + total_ram: int, + free_ram: int, + total_swap: int, + free_swap: int, +} + +GPU :: struct { + vendor_name: string, + model_name: string, + total_ram: int, +} \ No newline at end of file diff --git a/core/sys/unix/syscalls_freebsd.odin b/core/sys/unix/syscalls_freebsd.odin new file mode 100644 index 000000000..3441035cd --- /dev/null +++ b/core/sys/unix/syscalls_freebsd.odin @@ -0,0 +1,7 @@ +package unix + +// FreeBSD 13 syscall numbers +// See: https://alfonsosiciliano.gitlab.io/posts/2021-01-02-freebsd-system-calls-table.html + +SYS_uname : uintptr : 164 +SYS_sysctl : uintptr : 202 \ No newline at end of file diff --git a/core/sys/unix/syscalls_openbsd.odin b/core/sys/unix/syscalls_openbsd.odin new file mode 100644 index 000000000..703bc4d4e --- /dev/null +++ b/core/sys/unix/syscalls_openbsd.odin @@ -0,0 +1,6 @@ +package unix + +// OpenBSD 7.1 syscall numbers +// See: /usr/include/sys/syscall.h + +SYS_sysctl : uintptr : 202 \ No newline at end of file diff --git a/core/sys/unix/sysctl_darwin.odin b/core/sys/unix/sysctl_darwin.odin new file mode 100644 index 000000000..f9530b86f --- /dev/null +++ b/core/sys/unix/sysctl_darwin.odin @@ -0,0 +1,45 @@ +//+build darwin +package unix + +import "core:sys/darwin" +import "core:intrinsics" + +_ :: darwin + +sysctl :: proc(mib: []i32, val: ^$T) -> (ok: bool) { + mib := mib + result_size := i64(size_of(T)) + + res := intrinsics.syscall( + darwin.unix_offset_syscall(.sysctl), + uintptr(raw_data(mib)), uintptr(len(mib)), + uintptr(val), uintptr(&result_size), + uintptr(0), uintptr(0), + ) + return res == 0 +} + +// See sysctl.h for darwin for details +CTL_KERN :: 1 + KERN_OSTYPE :: 1 // Darwin + KERN_OSRELEASE :: 2 // 21.5.0 for 12.4 Monterey + KERN_OSREV :: 3 // i32: system revision + KERN_VERSION :: 4 // Darwin Kernel Version 21.5.0: Tue Apr 26 21:08:22 PDT 2022; root:darwin-8020.121.3~4/RELEASE_X86_64 + KERN_OSRELDATE :: 26 // i32: OS release date + KERN_OSVERSION :: 65 // Build number, e.g. 21F79 +CTL_VM :: 2 +CTL_VFS :: 3 +CTL_NET :: 4 +CTL_DEBUG :: 5 +CTL_HW :: 6 + HW_MACHINE :: 1 // x86_64 + HW_MODEL :: 2 // MacbookPro14,1 + HW_NCPU :: 3 /* int: number of cpus */ + HW_BYTEORDER :: 4 /* int: machine byte order */ + HW_MACHINE_ARCH :: 12 /* string: machine architecture */ + HW_VECTORUNIT :: 13 /* int: has HW vector unit? */ + HW_MEMSIZE :: 24 // u64 + HW_AVAILCPU :: 25 /* int: number of available CPUs */ + +CTL_MACHDEP :: 7 +CTL_USER :: 8 \ No newline at end of file diff --git a/core/sys/unix/sysctl_freebsd.odin b/core/sys/unix/sysctl_freebsd.odin new file mode 100644 index 000000000..5b0bcb88d --- /dev/null +++ b/core/sys/unix/sysctl_freebsd.odin @@ -0,0 +1,44 @@ +//+build freebsd +package unix + +import "core:intrinsics" + +sysctl :: proc(mib: []i32, val: ^$T) -> (ok: bool) { + mib := mib + result_size := i64(size_of(T)) + + res := intrinsics.syscall(SYS_sysctl, + uintptr(raw_data(mib)), uintptr(len(mib)), + uintptr(val), uintptr(&result_size), + uintptr(0), uintptr(0), + ) + return res == 0 +} + +// See /usr/include/sys/sysctl.h for details +CTL_SYSCTL :: 0 +CTL_KERN :: 1 + KERN_OSTYPE :: 1 + KERN_OSRELEASE :: 2 + KERN_OSREV :: 3 + KERN_VERSION :: 4 +CTL_VM :: 2 +CTL_VFS :: 3 +CTL_NET :: 4 +CTL_DEBUG :: 5 +CTL_HW :: 6 + HW_MACHINE :: 1 + HW_MODEL :: 2 + HW_NCPU :: 3 + HW_BYTEORDER :: 4 + HW_PHYSMEM :: 5 + HW_USERMEM :: 6 + HW_PAGESIZE :: 7 + HW_DISKNAMES :: 8 + HW_DISKSTATS :: 9 + HW_FLOATINGPT :: 10 + HW_MACHINE_ARCH :: 11 + HW_REALMEM :: 12 +CTL_MACHDEP :: 7 +CTL_USER :: 8 +CTL_P1003_1B :: 9 diff --git a/core/sys/unix/sysctl_openbsd.odin b/core/sys/unix/sysctl_openbsd.odin new file mode 100644 index 000000000..b93e8f9bd --- /dev/null +++ b/core/sys/unix/sysctl_openbsd.odin @@ -0,0 +1,49 @@ +//+build openbsd +package unix + +import "core:c" +foreign import libc "system:c" + +@(default_calling_convention="c") +foreign libc { + @(link_name="sysctl") _unix_sysctl :: proc(name: [^]i32, namelen: u32, oldp: rawptr, oldlenp: ^c.size_t, newp: rawptr, newlen: c.size_t) -> i32 --- +} + +sysctl :: proc(mib: []i32, val: ^$T) -> (ok: bool) { + mib := mib + result_size := c.size_t(size_of(T)) + res := _unix_sysctl(raw_data(mib), u32(len(mib)), val, &result_size, nil, 0) + return res == 0 +} + +// See /usr/include/sys/sysctl.h for details +CTL_SYSCTL :: 0 +CTL_KERN :: 1 + KERN_OSTYPE :: 1 + KERN_OSRELEASE :: 2 + KERN_OSREV :: 3 + KERN_VERSION :: 4 +CTL_VM :: 2 +CTL_FS :: 3 +CTL_NET :: 4 +CTL_DEBUG :: 5 +CTL_HW :: 6 + HW_MACHINE :: 1 + HW_MODEL :: 2 + HW_NCPU :: 3 + HW_BYTEORDER :: 4 + HW_PHYSMEM :: 5 + HW_USERMEM :: 6 + HW_PAGESIZE :: 7 + HW_DISKNAMES :: 8 + HW_DISKSTATS :: 9 + HW_DISKCOUNT :: 10 + HW_SENSORS :: 11 + HW_CPUSPEED :: 12 + HW_SETPERF :: 13 + HW_VENDOR :: 14 + HW_PRODUCT :: 15 + HW_VERSION :: 16 + HW_SERIALNO :: 17 + HW_UUID :: 18 + HW_PHYSMEM64 :: 19 \ No newline at end of file diff --git a/core/sys/windows/kernel32.odin b/core/sys/windows/kernel32.odin index 5174e6df7..15ffa2dd3 100644 --- a/core/sys/windows/kernel32.odin +++ b/core/sys/windows/kernel32.odin @@ -657,6 +657,13 @@ foreign kernel32 { ) -> BOOL --- } +@(default_calling_convention="stdcall") +foreign kernel32 { + GlobalMemoryStatusEx :: proc( + lpBuffer: ^MEMORYSTATUSEX, + ) -> BOOL --- +} + PBAD_MEMORY_CALLBACK_ROUTINE :: #type proc "stdcall" () @(default_calling_convention="stdcall") @@ -800,5 +807,16 @@ foreign kernel32 { ) -> BOOL --- } +@(default_calling_convention="stdcall") +foreign kernel32 { + GetProductInfo :: proc( + OSMajorVersion: DWORD, + OSMinorVersion: DWORD, + SpMajorVersion: DWORD, + SpMinorVersion: DWORD, + product_type: ^Windows_Product_Type, + ) -> BOOL --- +} + HandlerRoutine :: proc "stdcall" (dwCtrlType: DWORD) -> BOOL PHANDLER_ROUTINE :: HandlerRoutine diff --git a/core/sys/windows/types.odin b/core/sys/windows/types.odin index 7fbc6fea1..95e53dd46 100644 --- a/core/sys/windows/types.odin +++ b/core/sys/windows/types.odin @@ -17,6 +17,7 @@ size_t :: c.size_t wchar_t :: c.wchar_t DWORD :: c_ulong +DWORDLONG :: c.ulonglong QWORD :: c.ulonglong HANDLE :: distinct LPVOID HINSTANCE :: HANDLE @@ -3298,6 +3299,119 @@ IFileSaveDialogVtbl :: struct { ApplyProperties: proc "stdcall" (this: ^IFileSaveDialog, psi: ^IShellItem, pStore: ^IPropertyStore, hwnd: HWND, pSink: ^IFileOperationProgressSink) -> HRESULT, } +MEMORYSTATUSEX :: struct { + dwLength: DWORD, + dwMemoryLoad: DWORD, + ullTotalPhys: DWORDLONG, + ullAvailPhys: DWORDLONG, + ullTotalPageFil: DWORDLONG, + ullAvailPageFil: DWORDLONG, + ullTotalVirtual: DWORDLONG, + ullAvailVirtual: DWORDLONG, + ullAvailExtendedVirtual: DWORDLONG, +} + +Windows_Product_Type :: enum DWORD { + BUSINESS = 0x00000006, // Business + BUSINESS_N = 0x00000010, // Business N + CLUSTER_SERVER = 0x00000012, // HPC Edition + CLUSTER_SERVER_V = 0x00000040, // Server Hyper Core V + CORE = 0x00000065, // Windows 10 Home + CORE_COUNTRYSPECIFIC = 0x00000063, // Windows 10 Home China + CORE_N = 0x00000062, // Windows 10 Home N + CORE_SINGLELANGUAGE = 0x00000064, // Windows 10 Home Single Language + DATACENTER_EVALUATION_SERVER = 0x00000050, // Server Datacenter (evaluation installation) + DATACENTER_A_SERVER_CORE = 0x00000091, // Server Datacenter, Semi-Annual Channel (core installation) + STANDARD_A_SERVER_CORE = 0x00000092, // Server Standard, Semi-Annual Channel (core installation) + DATACENTER_SERVER = 0x00000008, // Server Datacenter (full installation. For Server Core installations of Windows Server 2012 and later, use the method, Determining whether Server Core is running.) + DATACENTER_SERVER_CORE = 0x0000000C, // Server Datacenter (core installation, Windows Server 2008 R2 and earlier) + DATACENTER_SERVER_CORE_V = 0x00000027, // Server Datacenter without Hyper-V (core installation) + DATACENTER_SERVER_V = 0x00000025, // Server Datacenter without Hyper-V (full installation) + EDUCATION = 0x00000079, // Windows 10 Education + EDUCATION_N = 0x0000007A, // Windows 10 Education N + ENTERPRISE = 0x00000004, // Windows 10 Enterprise + ENTERPRISE_E = 0x00000046, // Windows 10 Enterprise E + ENTERPRISE_EVALUATION = 0x00000048, // Windows 10 Enterprise Evaluation + ENTERPRISE_N = 0x0000001B, // Windows 10 Enterprise N + ENTERPRISE_N_EVALUATION = 0x00000054, // Windows 10 Enterprise N Evaluation + ENTERPRISE_S = 0x0000007D, // Windows 10 Enterprise 2015 LTSB + ENTERPRISE_S_EVALUATION = 0x00000081, // Windows 10 Enterprise 2015 LTSB Evaluation + ENTERPRISE_S_N = 0x0000007E, // Windows 10 Enterprise 2015 LTSB N + ENTERPRISE_S_N_EVALUATION = 0x00000082, // Windows 10 Enterprise 2015 LTSB N Evaluation + ENTERPRISE_SERVER = 0x0000000A, // Server Enterprise (full installation) + ENTERPRISE_SERVER_CORE = 0x0000000E, // Server Enterprise (core installation) + ENTERPRISE_SERVER_CORE_V = 0x00000029, // Server Enterprise without Hyper-V (core installation) + ENTERPRISE_SERVER_IA64 = 0x0000000F, // Server Enterprise for Itanium-based Systems + ENTERPRISE_SERVER_V = 0x00000026, // Server Enterprise without Hyper-V (full installation) + ESSENTIALBUSINESS_SERVER_ADDL = 0x0000003C, // Windows Essential Server Solution Additional + ESSENTIALBUSINESS_SERVER_ADDLSVC = 0x0000003E, // Windows Essential Server Solution Additional SVC + ESSENTIALBUSINESS_SERVER_MGMT = 0x0000003B, // Windows Essential Server Solution Management + ESSENTIALBUSINESS_SERVER_MGMTSVC = 0x0000003D, // Windows Essential Server Solution Management SVC + HOME_BASIC = 0x00000002, // Home Basic + HOME_BASIC_E = 0x00000043, // Not supported + HOME_BASIC_N = 0x00000005, // Home Basic N + HOME_PREMIUM = 0x00000003, // Home Premium + HOME_PREMIUM_E = 0x00000044, // Not supported + HOME_PREMIUM_N = 0x0000001A, // Home Premium N + HOME_PREMIUM_SERVER = 0x00000022, // Windows Home Server 2011 + HOME_SERVER = 0x00000013, // Windows Storage Server 2008 R2 Essentials + HYPERV = 0x0000002A, // Microsoft Hyper-V Server + IOTENTERPRISE = 0x000000BC, // Windows IoT Enterprise + IOTENTERPRISE_S = 0x000000BF, // Windows IoT Enterprise LTSC + IOTUAP = 0x0000007B, // Windows 10 IoT Core + IOTUAPCOMMERCIAL = 0x00000083, // Windows 10 IoT Core Commercial + MEDIUMBUSINESS_SERVER_MANAGEMENT = 0x0000001E, // Windows Essential Business Server Management Server + MEDIUMBUSINESS_SERVER_MESSAGING = 0x00000020, // Windows Essential Business Server Messaging Server + MEDIUMBUSINESS_SERVER_SECURITY = 0x0000001F, // Windows Essential Business Server Security Server + MOBILE_CORE = 0x00000068, // Windows 10 Mobile + MOBILE_ENTERPRISE = 0x00000085, // Windows 10 Mobile Enterprise + MULTIPOINT_PREMIUM_SERVER = 0x0000004D, // Windows MultiPoint Server Premium (full installation) + MULTIPOINT_STANDARD_SERVER = 0x0000004C, // Windows MultiPoint Server Standard (full installation) + PRO_WORKSTATION = 0x000000A1, // Windows 10 Pro for Workstations + PRO_WORKSTATION_N = 0x000000A2, // Windows 10 Pro for Workstations N + PROFESSIONAL = 0x00000030, // Windows 10 Pro + PROFESSIONAL_E = 0x00000045, // Not supported + PROFESSIONAL_N = 0x00000031, // Windows 10 Pro N + PROFESSIONAL_WMC = 0x00000067, // Professional with Media Center + SB_SOLUTION_SERVER = 0x00000032, // Windows Small Business Server 2011 Essentials + SB_SOLUTION_SERVER_EM = 0x00000036, // Server For SB Solutions EM + SERVER_FOR_SB_SOLUTIONS = 0x00000033, // Server For SB Solutions + SERVER_FOR_SB_SOLUTIONS_EM = 0x00000037, // Server For SB Solutions EM + SERVER_FOR_SMALLBUSINESS = 0x00000018, // Windows Server 2008 for Windows Essential Server Solutions + SERVER_FOR_SMALLBUSINESS_V = 0x00000023, // Windows Server 2008 without Hyper-V for Windows Essential Server Solutions + SERVER_FOUNDATION = 0x00000021, // Server Foundation + SMALLBUSINESS_SERVER = 0x00000009, // Windows Small Business Server + SMALLBUSINESS_SERVER_PREMIUM = 0x00000019, // Small Business Server Premium + SMALLBUSINESS_SERVER_PREMIUM_CORE = 0x0000003F, // Small Business Server Premium (core installation) + SOLUTION_EMBEDDEDSERVER = 0x00000038, // Windows MultiPoint Server + STANDARD_EVALUATION_SERVER = 0x0000004F, // Server Standard (evaluation installation) + STANDARD_SERVER = 0x00000007, // Server Standard (full installation. For Server Core installations of Windows Server 2012 and later, use the method, Determining whether Server Core is running.) + STANDARD_SERVER_CORE = 0x0000000D, // Server Standard (core installation, Windows Server 2008 R2 and earlier) + STANDARD_SERVER_CORE_V = 0x00000028, // Server Standard without Hyper-V (core installation) + STANDARD_SERVER_V = 0x00000024, // Server Standard without Hyper-V + STANDARD_SERVER_SOLUTIONS = 0x00000034, // Server Solutions Premium + STANDARD_SERVER_SOLUTIONS_CORE = 0x00000035, // Server Solutions Premium (core installation) + STARTER = 0x0000000B, // Starter + STARTER_E = 0x00000042, // Not supported + STARTER_N = 0x0000002F, // Starter N + STORAGE_ENTERPRISE_SERVER = 0x00000017, // Storage Server Enterprise + STORAGE_ENTERPRISE_SERVER_CORE = 0x0000002E, // Storage Server Enterprise (core installation) + STORAGE_EXPRESS_SERVER = 0x00000014, // Storage Server Express + STORAGE_EXPRESS_SERVER_CORE = 0x0000002B, // Storage Server Express (core installation) + STORAGE_STANDARD_EVALUATION_SERVER = 0x00000060, // Storage Server Standard (evaluation installation) + STORAGE_STANDARD_SERVER = 0x00000015, // Storage Server Standard + STORAGE_STANDARD_SERVER_CORE = 0x0000002C, // Storage Server Standard (core installation) + STORAGE_WORKGROUP_EVALUATION_SERVER = 0x0000005F, // Storage Server Workgroup (evaluation installation) + STORAGE_WORKGROUP_SERVER = 0x00000016, // Storage Server Workgroup + STORAGE_WORKGROUP_SERVER_CORE = 0x0000002D, // Storage Server Workgroup (core installation) + ULTIMATE = 0x00000001, // Ultimate + ULTIMATE_E = 0x00000047, // Not supported + ULTIMATE_N = 0x0000001C, // Ultimate N + UNDEFINED = 0x00000000, // An unknown product + WEB_SERVER = 0x00000011, // Web Server (full installation) + WEB_SERVER_CORE = 0x0000001D, // Web Server (core installation) +} + ENABLE_ECHO_INPUT : DWORD : 0x0004 ENABLE_INSERT_MODE : DWORD : 0x0020 ENABLE_LINE_INPUT : DWORD : 0x0002 diff --git a/examples/all/all_main.odin b/examples/all/all_main.odin index 9f347fad3..1f56431c1 100644 --- a/examples/all/all_main.odin +++ b/examples/all/all_main.odin @@ -109,6 +109,8 @@ import i18n "core:text/i18n" import thread "core:thread" import time "core:time" +import sysinfo "core:sys/info" + import unicode "core:unicode" import utf8 "core:unicode/utf8" import utf8string "core:unicode/utf8/utf8string" @@ -206,6 +208,7 @@ _ :: scanner _ :: i18n _ :: thread _ :: time +_ :: sysinfo _ :: unicode _ :: utf8 _ :: utf8string