LIBJEDEC_SPD(3JEDEC) | 3JEDEC | LIBJEDEC_SPD(3JEDEC) |
libjedec_spd
—
parse DIMM SPD data
library “libjedec”
#include
<libjedec.h>
nvlist_t *
libjedec_spd
(const uint8_t *buf,
size_t buflen, spd_error_t
*errp);
The
libjedec_spd
()
function parses a binary payload of SPD (serial presence detect) data and
transforms it into a nvlist_t that can be used by
callers to inspect the data.
SPD data is defined by JEDEC and used in various DDR DRAM standards. This information describes everything from the size and organization of the DIMM and its dies, timing information, electrical properties, manufacturing data, and more. A DRAM module (the thing we plug into a computer) is made up of a number of different components. For example, a DDR5 module (which is plugged into a slot) contains not only a number of different DRAM dies, but also power controllers, registers, clock drivers, and more. The SPD data describes all of this information.
There are two major properties of SPD information that determine which keys are present in it:
While each DDR version has different SPD information and the
module's type may further modify parts of it, the
nvlist_t that is returned attempts to normalize this
information as much as possible. Each key that is returned is defined in
<libjedec.h>
as a macro. The
key space is dot (‘.’) delineated. The following key spaces
are currently used:
Similarly, there are subdivisions based on the device in question. For example, “ddr3.mb” and “ddr4.rcd” refer to properties of the DDR3 memory buffer and the DDR4 registering clock driver respectively.
The library attempts to use a fixed number of data types when performing conversions and follows the following guidelines:
All integers are denoted as such explicitly with their size: either ‘uint32_t’ or ‘uint64_t’. Some banks of keys all have the same type and are denoted as such in the introductory block comment. Use nvlist_lookup_uint32(3NVPAIR) or nvlist_lookup_uint64(3NVPAIR) to retrieve these keys.
All strings are denoted as such by using the comment ‘string’. Use nvlist_lookup_string(3NVPAIR) to retrieve these keys.
For example, consider the spd_temp_type_t which is an enumeration that describes the kind of temperature monitoring device present. The enumeration contains values from DDR3, DDR4, and DDR5; however, each standard has its own defined type of SPD temperature sensor.
All enumerations are denoted as such by using the comment ‘uint32_t (enum)’. Use nvlist_lookup_uint32(3NVPAIR) to retrieve these keys.
All such items are denoted as such by using the comment ‘key’. Use nvlist_lookup_boolean(3NVPAIR) to retrieve these keys.
All fixed size arrays denote their size by using the comment ‘uint32_t [4]’, where the number four is replaced with the actual size. All variable sized arrays elide the number and are denoted by the comment ‘uint32_t []’. Use nvlist_lookup_uint32_array(3NVPAIR) to retrieve these keys.
A few keys will use different sized integer arrays. For example, arrays that relate to timing parameters use arrays of uint64_t to match the broader pattern of using the uint64_t for timing.
There are a number of different issues that can arise when trying to parse the SPD data that a device returns. The library attempts to parse as much as it can and breaks errors into two large categories:
The “errors” section is a nested
nvlist_t that can be retrieved by using the
SPD_KEY_ERRS
key. This keys in this nvlist use the
same name as the normal data keys. For example, if we were unable to
properly parse the manufacturer's JEDEC ID, then the key
SPD_KEY_MFG_MOD_MFG_ID
(“mfg.module-mfg-id”) would not be present in the top-level
nvlist_t and would instead be in the error
nvlist_t.
Each item present in the error nvlist_t is itself a nvlist_t which contains the following keys:
SPD_KEY_ERRS_CODE
SPD_KEY_ERRS_MSG
Finally, there is one last top-level key that we will set
if we find that the set of data that we had was incomplete. Rather than tag
every single item in the “errors”
nvlist_t, we instead insert the key
SPD_KEY_INCOMPLETE
on the top-level nvlist. The key
is a uint32_t that contains the starting offset of the
key that we were
unable to parse, which may be less than the total amount of data that was
provided. For example, if we had 100 bytes of data, but there was a 20 byte
key starting at byte 90, the this key would have a value of 90 as that's
what we were unable to parse.
Upon successful completion, the
libjedec_spd
() function returns an allocated
nvlist_t that contains the parsed SPD data. There may
be individual SPD fields that were unparsable which will be found in the
SPD_KEY_ERRS
field of the nvlist still. Otherwise
NULL
is returned and errp is
set with a value that indicates why the function was unable to parse any
data.
Example 1 Printing SPD DRAM and Module Type
The following example shows how to parse the SPD information and print out the type of DRAM and module's type. This example assumes that one has already obtained the raw SPD file from somewhere and just prints the raw values.
#include <stdio.h> #include <stdint.h> #include <libjedec.h> void dump_dram_module_type(const uint8_t *buf, size_t len) { nvlist_t *nvl; spd_error_t err; uint32_t ddr, mod; nvl = libjedec_spd(buf, len, &err); if (nvl == NULL) { (void) fprintf(stderr, "failed to parse SPD data: 0x%x\n", err); return; } if (nvlist_lookup_pairs(nvl, 0, SPD_KEY_DRAM_TYPE, DATA_TYPE_UINT32, &ddr, SPD_KEY_MOD_TYPE, DATA_TYPE_UINT32, &mod, NULL) != 0) { nvlist_free(nvl); (void) fprintf(stderr, "failed to look up keys\n"); return; } nvlist_free(nvl); (void) printf("Found DDR type 0x%x, module type 0x%x\n", ddr, mod); }
Upon returning from the libjedec_spd
()
function, the errp pointer will be set to one of the
following values:
LIBJEDEC_SPD_OK
NULL
. Callers must still cehck the contents of the
SPD_KEY_ERRS
nvlist.LIBJEDEC_SPD_NOMEM
LIBJEDEC_SPD_TOOSHORT
LIBJEDEC_SPD_UNSUP_TYPE
LIBJEDEC_SPD_UNSUP_REV
libjedec(3LIB), nvlist_lookup_boolean(3NVPAIR), nvlist_lookup_string(3NVPAIR), nvlist_lookup_uint32(3NVPAIR), nvlist_lookup_uint32_array(3NVPAIR), nvlist_lookup_uint64(3NVPAIR)
Serial Presence Detect (SPD), General Standard, 21-C, JEDEC Solid State Technology Association.
DDR5 Serial Presence Detect (SPD) Contents, JESD400-5B Document Release 1.2, JEDEC Solid State Technology Association, October 2023.
LPDDR5/5X Serial Presence Detect (SPD) Contents, JESD406-5 Document Release 1.0, JEDEC Solid State Technology Association, June 2024.
September 2, 2024 | OmniOS |