ajhahn.de
← FlashOS
Flash 93 lines
// cpuinfo — one-shot CPU monitor for /bin/cpuinfo.
//
// Prints the SoC temperature and ARM core clock as aligned key/value rows,
// then exits. Both come from the VideoCore mailbox (sys_cpu_temp /
// sys_cpu_freq) and read 0 = unknown on a board without it (virt), rendered
// "n/a" — cpuinfo never fabricates a reading. CPU load is intentionally
// absent: a busy/idle percentage needs idle-task accounting the scheduler
// does not keep yet, so it waits for that layer rather than being faked.
//
// Print-and-exit, so it needs neither the alt-screen buffer nor readKey.
// Same coreutil recipe as ls / sysinfo (flibc _start shim, flibc_mem, single
// R+X PT_LOAD, stack buffers only). Kept out of the CI FSH_SCRIPT like
// sysinfo: the readings are non-deterministic and do not belong in the
// baseline-checkpoint trace. Source is Flash — flashc transpiles it to Zig
// at build time via addFlashSource.

use flibc
use console_ui

link "flibc_start"
link "flibc_mem"

fn sink(bytes []u8) void {
    _ = flibc.sys.write_fd(1, bytes.ptr, bytes.len)
}

export fn main(_ usize, _ argv) noreturn {
    console_ui.banner(sink, "FlashOS cpu")

    // One scratch buffer reused across both rows: kv consumes each value
    // before the next formatter overwrites it.
    var buf [32]u8 = undefined
    console_ui.screen.kv(sink, "temp", tempStr(&buf))
    console_ui.screen.kv(sink, "freq", freqStr(&buf))

    flibc.exit()
}

// SoC temperature in whole degrees Celsius, or "n/a" when unknown (0 —
// virt's stub, or a mailbox timeout on real hardware). cpu_temp() is
// milli-degrees. ASCII "C" keeps every byte single-width on any console.
fn tempStr(buf []mut u8) []u8 {
    milli := flibc.sys.cpu_temp()
    if milli == 0 {
        return "n/a"
    }
    var i usize = u64dec(buf, milli / 1000)
    suffix := " C"
    for c in suffix {
        buf[i] = c
        i += 1
    }
    return buf[0..i]
}

// ARM core clock in MHz, or "n/a" when unknown (0). cpu_freq() is Hz.
fn freqStr(buf []mut u8) []u8 {
    hz := flibc.sys.cpu_freq()
    if hz == 0 {
        return "n/a"
    }
    var i usize = u64dec(buf, hz / 1_000_000)
    suffix := " MHz"
    for c in suffix {
        buf[i] = c
        i += 1
    }
    return buf[0..i]
}

// Write `v` as decimal ASCII into `out` (>= 20 bytes for the u64 max),
// returning the byte count.
fn u64dec(out []mut u8, v u64) usize {
    if v == 0 {
        out[0] = '0'
        return 1
    }
    var tmp [20]u8 = undefined
    var n usize = 0
    var x u64 = v
    while x != 0 {
        tmp[n] = '0' + #as(u8, #intCast(x % 10))
        n += 1
        x /= 10
    }
    var i usize = 0
    while i < n {
        out[i] = tmp[n - 1 - i]
        i += 1
    }
    return n
}