dmi_fields_decode
Description
The dmi_fields_decode function reads a structure according to the layout its
specification declares, instead of a decoding handler written for the type.
A specification describes its layout with the fields member of
dmi_entity_spec_t, a list of dmi_field_t written with DMI_FIELDS and
terminated with an empty field.
Fields are read in the order they are declared, starting at the beginning of
the structure body. A specification which declares fields and no decoding
handler is decoded by this function, which dmi_entity_decode calls on its
own, so it rarely has to be named. The bytes are read through the decoder the
structure is being decoded with, see dmi_decoder_initialize.
Fields describe the bytes, while the attributes of dmi_attribute_t describe
the values they are decoded into. The two are joined by the member of the
decoded structure they name, and neither is a complete description of the
other: a field may carry no member of its own, and a member may be computed
rather than read.
Groups and truncation
The firmware of a platform writes the fields of the version of the specification it follows, and leaves out the ones of the newer versions, so a structure of a type is not as long as the decoder knows it to be.
DMI_FIELD_GROUP declares where the data is allowed to end. When the data ends
at the beginning of a group, the fields of that group and of the ones after it
are left unset, and the structure is marked as stopped rather than as broken;
the version of the group the data has been read up to becomes the level of the
structure. Ending anywhere else marks the structure as incomplete, except
within the fields before the first group, which every structure of the type is
required to carry.
A group may also name a bool member with present, which the function sets
once every field of the group has been read, and leaves false if the data
ends before the group or in the middle of it, e.g.
DMI_FIELD_GROUP(.present = dmi_member(dmi_hpe_trusted_module_t, has_chip)).
This is how the structures of the vendors, whose groups carry no version,
tell the fields they hold from the ones they are too short for.
Integers and other values
An integer field names the type it is written with, e.g.
DMI_FIELD(dmi_slot_t, ident, dmi_word_t), whose size is the width of the
field. The member it is decoded into may be wider than the field, so that the
value standing for "unknown" does not collide with a value a device may really
have. String references, UUIDs, binary-coded decimals and bytes taken as they
are have macros of their own: DMI_FIELD_STRING, DMI_FIELD_UUID,
DMI_FIELD_BCD and DMI_FIELD_BINARY.
Arrays
DMI_FIELD_ARRAY declares a number of elements the data gives, which are
decoded into an array of their own, allocated by the function: the member
holds the pointer to the elements, and the counter the field names holds the
number of the ones decoded in full. The arrays belong to the library, which
frees them with the decoded structure, see dmi_fields_release, so the
cleanup handler of a specification does not free them.
Values which need decoding
A field whose value means something other than the number the data carries
declares a pair of handlers, decode and encode, which turn the data into
the member and back. A field declared with DMI_FIELD_SPLIT gives its
handlers the whole structure instead of one member, which is how the data
feeding several members at once is decoded.
Parameters
decoder-
Decoder of the structure, see
dmi_decoder_initialize. The structure is decoded into the structure of its type.
Return value
Returns true if the structure has been decoded, which includes the
structures the data ends within, and false if it cannot be.
Errors
DMI_ERROR_ARGUMENT_NULL-
Decoder is
nullptr. DMI_ERROR_ARGUMENT_INVALID-
A field declares a number wider than the widest one the engine reads and writes, which is eight bytes.
DMI_ERROR_STATE_INVALID-
Specification declares no fields.
DMI_ERROR_INTERNAL-
Fields reach another offset than the one declared.
DMI_ERROR_OUT_OF_MEMORY-
Elements of an array cannot be allocated.
Examples
const dmi_entity_spec_t dmi_slot_spec =
{
.code = "slot",
.type = DMI_TYPE(system_slots),
...
.fields = DMI_FIELDS({
DMI_FIELD_STRING(dmi_slot_t, designator),
DMI_FIELD(dmi_slot_t, type, dmi_byte_t),
DMI_FIELD(dmi_slot_t, bus_width, dmi_byte_t),
DMI_FIELD_GROUP(.since = DMI_VERSION(2, 1, 0)),
DMI_FIELD(dmi_slot_t, features_ex, dmi_byte_t),
DMI_FIELD_GROUP(.since = DMI_VERSION(3, 2, 0)),
DMI_FIELD_ARRAY(dmi_slot_t, peer_groups, peer_group_count,
.count_length = sizeof(dmi_byte_t),
.fields = DMI_FIELDS({
DMI_FIELD(dmi_slot_peer_group_t, bus_width, dmi_byte_t),
{}
})),
{}
})
};