Hardware: a Motherboard card
The board, the chassis and the firmware on it, which the System card was reducing to two lines. Maker, model, version, serial and asset tag; chassis and where the board sits in it; the firmware's vendor, version, revision, date, ROM size and whether the machine boots UEFI — that last one is a line in SMBIOS's characteristics list rather than a field, so the parser now keeps those lists too. Expansion slots come with it, with the device found at each occupied slot's PCI address rather than the address alone. They are only shown when the firmware tracks occupancy at all: core's NucBox lists five PCIe x1 slots it does not physically have, all "Available", copied out of a reference design. grid's board reports real addresses and real occupancy, which is the case worth printing. A machine with no SMBIOS gets a card that says so. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
38039d1adc
commit
03e0761f3e
+57
-6
@@ -2,7 +2,7 @@
|
||||
// their slots, the drives and the graphics. None of it moves, so the page is a read rather
|
||||
// than a monitor: what is live (temperature, usage, SMART) belongs to Dashboard and Disks.
|
||||
import { useCallback, useEffect, useState } from 'react'
|
||||
import { api, Hardware as HW, HWDrive, HWGPU, HWModule } from './api'
|
||||
import { api, Hardware as HW, HWBoard, HWDrive, HWGPU, HWModule } from './api'
|
||||
import { fmtBytes } from './fmt'
|
||||
import { Btn, Loading } from './ui'
|
||||
|
||||
@@ -87,6 +87,58 @@ function Gpu({ g }: { g: HWGPU }) {
|
||||
)
|
||||
}
|
||||
|
||||
// The board and the firmware on it. Everything here is SMBIOS, so a machine without one
|
||||
// — a Mac, a Pi — gets a card that says as much instead of a column of blanks.
|
||||
function Motherboard({ b }: { b: HWBoard }) {
|
||||
const named = b.maker || b.product || b.bios
|
||||
// A board that reports every slot "Available" is not telling us anything — mini PCs
|
||||
// copy the slot table out of a reference design and list slots the case has no room
|
||||
// for. Only worth showing when the firmware actually tracks what is plugged in.
|
||||
const slots = (b.slots ?? []).some((s) => s.usage === 'In Use') ? (b.slots ?? []) : []
|
||||
return (
|
||||
<section className="card">
|
||||
<h2>Motherboard</h2>
|
||||
{!named && <div className="empty">This machine has no SMBIOS table, so its firmware doesn't say what board it is.</div>}
|
||||
{named && (
|
||||
<div className="props">
|
||||
<P k="Maker" v={b.maker} />
|
||||
<P k="Model" v={b.product} />
|
||||
<P k="Version" v={b.version} />
|
||||
<P k="Kind" v={b.type} />
|
||||
<P k="Chassis" v={[b.chassis_maker, b.chassis].filter(Boolean).join(' ')} />
|
||||
<P k="In chassis" v={b.location} />
|
||||
<P k="Serial" v={b.serial} mono />
|
||||
<P k="Asset tag" v={b.asset_tag} mono />
|
||||
</div>
|
||||
)}
|
||||
{(b.bios || b.bios_date) && (
|
||||
<div className="props" style={{ marginTop: 8 }}>
|
||||
<P k="Firmware" v={b.bios} />
|
||||
<P k="Revision" v={b.bios_revision} />
|
||||
<P k="Dated" v={b.bios_date} />
|
||||
<P k="ROM" v={b.rom_size} />
|
||||
<P k="Boots" v={b.uefi ? 'UEFI' : ''} />
|
||||
</div>
|
||||
)}
|
||||
{slots.length > 0 && (
|
||||
<div style={{ marginTop: 8 }}>
|
||||
<div className="sub-head"><span className="dname">Expansion slots</span><span className="spacer" /><span className="muted small">as the firmware lists them</span></div>
|
||||
<table className="dtable">
|
||||
<thead><tr><th>Slot</th><th>Type</th><th>What is in it</th></tr></thead>
|
||||
<tbody>{slots.map((s, i) => (
|
||||
<tr key={s.designation + i}>
|
||||
<td className="mono small">{s.designation}</td>
|
||||
<td className="mono small">{[s.type, s.length && s.length !== 'Other' ? s.length.toLowerCase() : ''].filter(Boolean).join(' · ')}</td>
|
||||
<td className="small" title={s.bus}>{s.usage === 'In Use' ? (s.device ?? s.bus ?? 'in use') : <span className="muted">{(s.usage ?? '').toLowerCase() || '—'}</span>}</td>
|
||||
</tr>
|
||||
))}</tbody>
|
||||
</table>
|
||||
</div>
|
||||
)}
|
||||
</section>
|
||||
)
|
||||
}
|
||||
|
||||
export default function Hardware() {
|
||||
const [hw, setHw] = useState<HW | null>(null)
|
||||
const [err, setErr] = useState('')
|
||||
@@ -100,7 +152,7 @@ export default function Hardware() {
|
||||
if (err) return <div className="dash"><div className="notice">{err === 'not found' ? "This machine's Ham Lab is older than the Hardware tab. Update it from Machines." : err}</div></div>
|
||||
if (!hw) return <div className="dash"><Loading label="Reading the machine…" /></div>
|
||||
|
||||
const { system: sys, cpu, memory: mem } = hw
|
||||
const { system: sys, board, cpu, memory: mem } = hw
|
||||
const drives = hw.drives ?? []
|
||||
const gpus = hw.gpus ?? []
|
||||
const capacity = drives.reduce((n, d) => n + d.size, 0)
|
||||
@@ -191,14 +243,13 @@ export default function Hardware() {
|
||||
{gpus.length === 0 && <div className="empty">No display adapter found.</div>}
|
||||
</section>
|
||||
|
||||
<Motherboard b={board} />
|
||||
|
||||
<section className="card">
|
||||
<h2>System</h2>
|
||||
<div className="props">
|
||||
<P k="Model" v={sys.model} />
|
||||
<P k="Board" v={sys.board} />
|
||||
<P k="Chassis" v={sys.chassis} />
|
||||
<P k="Firmware" v={sys.bios} />
|
||||
<P k="Dated" v={sys.bios_date} />
|
||||
<P k="Family" v={sys.family} />
|
||||
<P k="Serial" v={sys.serial} mono />
|
||||
<P k="Kernel" v={sys.kernel} mono />
|
||||
<P k="Arch" v={sys.arch} />
|
||||
|
||||
Reference in New Issue
Block a user