Browse Source

Merge pull request #2022 from Kelimion/sysinfo

Add `core:sys/info` system information querying package.
Jeroen van Rijn 3 years ago
parent
commit
99a7bf9faa

+ 1 - 1
core/os/os_openbsd.odin

@@ -705,4 +705,4 @@ _alloc_command_line_arguments :: proc() -> []string {
 		res[i] = string(arg)
 	}
 	return res
-}
+}

+ 26 - 0
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])
+	}
+}

+ 37 - 2
core/simd/x86/cpu.odin → 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
+}

+ 78 - 0
core/sys/info/doc.odin

@@ -0,0 +1,78 @@
+/*
+	Copyright 2022 Jeroen van Rijn <[email protected]>.
+	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
+*/

+ 510 - 0
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
+	}
+}

+ 76 - 0
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)
+	}
+}

+ 136 - 0
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),
+	}
+}

+ 69 - 0
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)
+	}
+}

+ 375 - 0
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
+}

+ 45 - 0
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,
+}

+ 7 - 0
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

+ 6 - 0
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

+ 45 - 0
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

+ 44 - 0
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

+ 49 - 0
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

+ 18 - 0
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

+ 114 - 0
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

+ 3 - 0
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