Context layout, memory ownership, entry points, field status, and decoder contracts.
lazybiosCTX is the top-level owner. It contains the selected backend, a lazybiosDMI_t raw-data container, and one pointer per supported SMBIOS type. Each of those points at a result set — a small structure holding an entries array and its count — so an array can never be separated from the number of elements in it.
Vendor-specific structures live under ctx->oem. That member and the vendor containers beneath it (ctx->oem->dell, ctx->oem->hp) are allocated by lazybiosCTXNew and are never NULL; only the per-type members inside them are NULL until the matching getter runs. An OEM structure number means nothing without its vendor — type 212 is Dell Indexed I/O Access and also HPE 64-bit CRU Information — so the vendor is part of the path rather than the name.
Do not embed lazybiosCTX by value or take its sizeof. Always allocate it with lazybiosCTXNew, so that adding structures in a later release does not break your build.
lazybiosDMI_t owns the entry-point bytes and DMI table bytes. Its entry_tag selects the valid member of entry_union:
The entry union points into entry_data; its members become invalid when the context is cleaned up.
lazybiosDMI_t also carries a small cache describing where each structure type lives in the table: one lazybiosTypeIndex_t per possible type byte, holding how many structures of that type the table contains and the byte offset of the first one. lazybiosInit fills it once, after the table is loaded.
Parsers use it to size their result array and to start walking at the first matching structure instead of at the start of the table. Without it, every getter had to walk the entire table just to count, which dominated parse time on tables with many structures.
The cache is an optimization, never a precondition. index_valid is zero in a zero-initialized or hand-assembled lazybiosDMI_t, and the parsers then walk the table exactly as they did before, producing identical results. Code that replaces dmi_data on an existing container must clear index_valid, since the cached offsets describe the buffer they were built from.
Getters allocate their return values. Each takes only the raw lazybiosDMI_t table and returns a result set. A non-NULL result whose count is zero means the table simply contains no structure of that type; NULL is reserved for a genuine failure, either unusable arguments or a failed allocation. Because the two cases are distinguishable, a caller can tell "this machine has no TPM" from "we ran out of memory".
lazybiosParseAll runs every implemented getter and assigns each result to its context member, so the context owns all of it. It leaves members that are already populated alone, which makes it safe to call after parsing a few types by hand and safe to call twice.
Assign getter results to the matching context member when using lazybiosCleanup. If a caller keeps a result outside the context, it must call the matching lazybiosFreeType* function instead and must prevent the context from owning the same pointer. Never free individual string members independently of their containing parsed structure.
Fields that carry an encoded value are decoded while parsing and stored in the record's decoded member, which mirrors the raw member names:
The raw value is always preserved next to the decoded one, so machine-readable consumers keep the encoding while human-readable ones get the meaning. This holds for multi-flag text too: those strings are built during parsing and owned by the record, released with it. lazybios exposes no decoder functions at all — decoded is the whole interface.
Every parsed record also carries the SMBIOS handle that identifies it and the length the firmware reported. Handles are what cross-structure references resolve against: a Type 17 memory device names its array through physical_memory_array_handle, which matches the handle of a Type 16 record.
Every parsed type contains field_status metadata. Use LAZYBIOS_FIELD_STATUS with a structure pointer and field name before consuming an optional value.
Specification-defined Unknown, Other, and reserved encodings remain present values. Encodings that explicitly mean that a value, string, or referenced structure is absent or unavailable are marked absent; their raw numeric value is preserved so callers can distinguish special cases when necessary. A zero string index and an invalid string index are absent. An absent numeric field whose bytes are missing contains zero, while an absent string or array field contains NULL.
A referenced handle field with availability metadata reports 0xFFFF as absent unless a type-specific definition gives it another meaning. Some error-information handles also use 0xFFFE to state that no referenced error structure is supplied. Raw handle arrays preserve every encoded entry. Check the relevant type guide before interpreting an absent handle's preserved raw value.
SMBIOS structures grow over time. Getters check the parsed entry-point version before reading versioned fields and leave fields absent when they do not exist in that specification version. Consumers normally check field status rather than reproducing parser version checks. Use lazybiosIsVersionPlus when application behavior depends on the parsed SMBIOS version.
Include lazybios/lazybios.h for the complete API. Applications that use only one parsed type can include its lazybios/typeN.h header directly. Every public header is independently includable from C and C++.
Decoding is done during parsing, so there are no decoder functions to call and none are declared in any public header. The table walkers that back the parsers are internal for the same reason: they take bare pointers into a raw firmware buffer, and a caller holding one has no way to keep it valid across a reload. Everything a consumer needs is reachable from the parsed records.