xref: /illumos-gate/usr/src/man/man3jedec/libjedec_spd.3jedec (revision f334afcfaebea1b7dc3430015651d8d748fa8a3e)
1.\"
2.\" This file and its contents are supplied under the terms of the
3.\" Common Development and Distribution License ("CDDL"), version 1.0.
4.\" You may only use this file in accordance with the terms of version
5.\" 1.0 of the CDDL.
6.\"
7.\" A full copy of the text of the CDDL should have accompanied this
8.\" source.  A copy of the CDDL is also available via the Internet at
9.\" http://www.illumos.org/license/CDDL.
10.\"
11.\"
12.\" Copyright 2023 Oxide Computer Company
13.\"
14.Dd September 22, 2023
15.Dt LIBJEDEC_SPD 3JEDEC
16.Os
17.Sh NAME
18.Nm libjedec_spd
19.Nd parse DIMM SPD data
20.Sh LIBRARY
21.Lb libjedec
22.Sh SYNOPSIS
23.In libjedec.h
24.Ft "nvlist_t *"
25.Fo libjedec_spd
26.Fa "const uint8_t *buf"
27.Fa "size_t buflen"
28.Fa "spd_error_t *errp
29.Fc
30.Sh DESCRIPTION
31The
32.Fn libjedec_spd
33function parses a binary payload of SPD
34.Pq serial presence detect
35data and transforms it into a
36.Vt nvlist_t
37that can be used by callers to inspect the data.
38.Pp
39SPD data is defined by JEDEC and used in various DDR DRAM standards.
40This information describes everything from the size and organization of
41the DIMM and its dies,
42timing information, electrical properties, manufacturing data, and more.
43A DRAM module
44.Pq the thing we plug into a computer
45is made up of a number of different components.
46For example, a DDR5 module
47.Pq which is plugged into a slot
48contains not only a number of different DRAM dies, but also power
49controllers, registers, clock drivers, and more.
50The SPD data describes all of this information.
51.Pp
52There are two major properties of SPD information that determine which
53keys are present in it:
54.Bl -enum -width Ds
55.It
56The DDR version that the device implements.
57Examples of the version information include DDR4, LPDDR5, DDR3, and many
58others.
59.It
60The module's type.
61Examples of this include whether it is an RDIMM
62.Pq registered DIMM ,
63UDIMM
64.Pq unregistered DIMM ,
65soldered down, etc.
66.El
67.Pp
68While each DDR version has different SPD information and the module's
69type may further modify parts of it, the
70.Vt nvlist_t
71that is returned attempts to normalize this information as much as
72possible.
73Each key that is returned is defined in
74.In libjedec.h
75as a macro.
76The key space is dot
77.Pq Sq \&.
78delineated.
79The following key spaces are currently used:
80.Bl -tag -width Ds
81.It Dq meta
82This contains information about the SPD ROM itself, the encoding
83revision, the DRAM standard in use, the type of module, etc.
84This section also contains all of the CRC values and information that
85affects how the rest of data is parsed
86.Pq such as whether or not the package is monolithic .
87.It Dq dram
88This section contains information that is specific to the SDRAM dies
89that are present.
90This includes addressing information such as the number of rows,
91columns, banks, and bank groups that are on each die.
92It also includes information such as the supported voltages of the dies
93themselves and then describes a lot of the different timing properties
94such as the minimum times that a controller must wait between certain
95actions.
96.It Dq ddr4 , Dq ddr5
97This section contains information that is specific to a given DDR
98standard and cannot otherwise share a common definition.
99This section has a few additional subdivisions of information to cover
100items related to the module's type or are otherwise logically grouped
101together such as refresh management.
102For example, the library uses namespaces such as
103.Dq ddr4.rdimm
104and
105.Dq ddr5.lrdimm
106for properties that would be specific to DDR4 RDIMMs and DDR5 LRDIMMs
107respectively.
108.It Dq module
109This section relates to information about the physical module which
110includes information such as its physical dimensions, the types of
111components that are present on it, signal mapping, and related.
112.It Dq mfg
113This section contains information about the module manufacturing.
114This is where things like the module's serial number, the manufacturer,
115the part number, and related can be found.
116Generally this information is found in a different part of the SPD ROM
117and therefore may not always be present.
118.It Dq errors
119This section is an embedded
120.Vt nvlist_t
121that contains keys for each value that couldn't be parsed.
122For more information, see the
123.Sx Parsing Errors
124section for more information.
125.El
126.Ss Data Types
127The library attempts to use a fixed number of data types when performing
128conversions and follows the following guidelines:
129.Bl -bullet
130.It
131By default, integer values use a
132.Vt uint32_t
133to try and make things more uniform where possible and to allow for
134future changes.
135A
136.Vt uint64_t
137is used when the types contain data that could naturally overflow a
138.Vt uint32_t
139such as when counting the number of bits, bytes, or measuring time
140.Pq which is normalized to picoseconds .
141.Pp
142All integers are denoted as such explicitly with their size: either
143.Sq uint32_t
144or
145.Sq uint64_t .
146Some banks of keys all have the same type and are denoted as such in the
147introductory block comment.
148Use
149.Xr nvlist_lookup_uint32 3NVPAIR
150or
151.Xr nvlist_lookup_uint64 3NVPAIR
152to retrieve these keys.
153.It
154Strings, which are stored as traditional
155.Vt char *
156values should only contain printable characters.
157.Pp
158All strings are denoted as such by using the comment
159.Sq string .
160Use
161.Xr nvlist_lookup_string 3NVPAIR
162to retrieve these keys.
163.It
164There are many values which represent enumerations.
165The raw type is stored as a
166.Vt uint32_t .
167In general, these enumerations, unless otherwise indicated should not be
168assumed to have the identical values of a given specification.
169This is done because the values are not always uniform from
170specification to specification, except in rare cases.
171Not all DDR specifications can result in the same set of enumeration
172values.
173.Pp
174For example, consider the
175.Vt spd_temp_type_t
176which is an enumeration that describes the kind of temperature
177monitoring device present.
178The enumeration contains values from DDR3, DDR4, and DDR5; however, each
179standard has its own defined type of SPD temperature sensor.
180.Pp
181All enumerations are denoted as such by using the comment
182.Sq uint32_t Pq enum .
183Use
184.Xr nvlist_lookup_uint32 3NVPAIR
185to retrieve these keys.
186.It
187Several items are used to indicate a fact, but do not have any actual
188data associated with them.
189Their mere presence is sufficient to indicate a unique property of the
190DIMM.
191Examples of this include if the package is non-monolithic, the DIMM has
192asymmetrical ranks, etc.
193.Pp
194All such items are denoted as such by using the comment
195.Sq key .
196Use
197.Xr nvlist_lookup_boolean 3NVPAIR
198to retrieve these keys.
199.It
200A few types use arrays of
201.Vt uint32_t
202values to denote information.
203Some of the keys have a fixed number of entries that are expected, while
204others are variable and will depend on the parsed data.
205For example, a JEDEC ID is always encoded as two
206.Vt uint32_t
207values, the continuation and the underlying ID itself.
208Other values, such as the number of supported voltages or CAS latencies
209will vary.
210.Pp
211All fixed size arrays denote their size by using the comment
212.Sq uint32_t [4] ,
213where the number four is replaced with the actual size.
214All variable sized arrays elide the number and are denoted by the
215comment
216.Sq uint32_t [] .
217Use
218.Xr nvlist_lookup_uint32_array 3NVPAIR
219to retrieve these keys.
220.El
221.Ss Parsing Errors
222There are a number of different issues that can arise when trying to
223parse the SPD data that a device returns.
224The library attempts to parse as much as it can and breaks errors into
225two large categories:
226.Bl -enum -width Ds
227.It
228Errors which prevent us from doing anything at all, which are noted in
229the
230.Sx ERRORS
231section.
232The main items that relate to data
233.Pq as opposed to issues like running out of memory
234include when we encounter a DDR specification that we don't support or
235that the data has an encoding version we don't understand.
236This can also occur if there's not enough data for us to figure out what
237kind of SPD information is encoded.
238.It
239Errors that mean we cannot parse a specific piece of SPD data.
240This is by far the most common form of error that we encounter and these
241are the entries that make up the
242.Dq errors
243section of the returned
244.Vt nvlist_t
245that was mentioned earlier.
246.El
247.Pp
248The
249.Dq errors
250section is a nested
251.Vt nvlist_t
252that can be retrieved by using the
253.Dv SPD_KEY_ERRS
254key.
255This keys in this nvlist use the same name as the normal data keys.
256For example, if we were unable to properly parse the manufacturer's
257JEDEC ID, then the key
258.Dv SPD_KEY_MFG_MOD_MFG_ID
259.Pq Dq mfg.module-mfg-id
260would not be present in the top-level
261.Vt nvlist_t
262and would instead be in the error
263.Vt nvlist_t .
264.Pp
265Each item present in the error
266.Vt nvlist_t
267is itself a
268.Vt nvlist_t
269which contains the following keys:
270.Bl -tag -width Ds
271.It Dv SPD_KEY_ERRS_CODE
272The error code, a
273.Vt uint32_t,
274indicates a class of issue that occurred and its values are defined by
275the
276.Vt spd_error_kind_t
277enumeration.
278The following errors are defined:
279.Bl -tag -width Ds
280.It SPD_ERROR_NO_XLATE
281This indicates that the library did not know how to interpret a specific
282binary value.
283For example, if a given particular field was using what we believed to
284be a reserved value then we would set this error.
285.It SPD_ERROR_UNPRINT
286This indicates that we encountered a non-ASCII or otherwise unprintable
287character that was not allowed in the SPD string character set.
288.It SPD_ERROR_NO_DATA
289This indicates that there was no data for a given key.
290For example, this would be a string that consisted solely of space
291characters which are used to represent padding.
292.It SPD_ERROR_INTERNAL
293This indicates that something went wrong inside the library that was
294unexpected.
295.It SPD_ERROR_BAD_DATA
296This indicates that we've encountered something strange about the data
297in question.
298For example, this would be used for an invalid CRC or if the combination
299of values would cause an underflow in a calculation.
300.El
301.It Dv SPD_KEY_ERRS_MSG
302This is an error message that is intended for a person to understand and
303contains more specific information than the code above.
304.El
305.Pp
306Finally, there is one last top-level key that we will set if we find
307that the set of data that we had was incomplete.
308Rather than tag every single item in the
309.Dq errors
310.Vt nvlist_t ,
311we instead insert the key
312.Dv SPD_KEY_INCOMPLETE
313on the top-level nvlist.
314The key is a
315.Vt uint32_t
316that contains the starting offset of the
317.Sy key
318that we were unable to parse, which may be less than the total amount of
319data that was provided.
320For example, if we had 100 bytes of data, but there was a 20 byte key
321starting at byte 90, the this key would have a value of 90 as that's
322what we were unable to parse.
323.Sh RETURN VALUES
324Upon successful completion, the
325.Fn libjedec_spd
326function returns an allocated
327.Vt nvlist_t
328that contains the parsed SPD data.
329There may be individual SPD fields that were unparsable which will be
330found in the
331.Dv SPD_KEY_ERRS
332field of the nvlist still.
333Otherwise
334.Dv NULL
335is returned
336and
337.Fa errp
338is set with a value that indicates why the function was unable to parse
339any data.
340.Sh EXAMPLES
341.Sy Example 1
342Printing SPD DRAM and Module Type
343.Pp
344The following example shows how to parse the SPD information and print
345out the type of DRAM and module's type.
346This example assumes that one has already obtained the raw SPD file from
347somewhere and just prints the raw values.
348.Bd -literal -offset 2
349#include <stdio.h>
350#include <stdint.h>
351#include <libjedec.h>
352
353void
354dump_dram_module_type(const uint8_t *buf, size_t len)
355{
356	nvlist_t *nvl;
357	spd_error_t err;
358	uint32_t ddr, mod;
359
360	nvl = libjedec_spd(buf, len, &err);
361	if (nvl == NULL) {
362		(void) fprintf(stderr, "failed to parse SPD data: 0x%x\en",
363		    err);
364		return;
365	}
366
367	if (nvlist_lookup_pairs(nvl, 0,
368	    SPD_KEY_DRAM_TYPE, DATA_TYPE_UINT32, &ddr,
369	    SPD_KEY_MOD_TYPE, DATA_TYPE_UINT32, &mod,
370	    NULL) != 0) {
371		nvlist_free(nvl);
372		(void) fprintf(stderr, "failed to look up keys\en");
373		return;
374	}
375
376	nvlist_free(nvl);
377	(void) printf("Found DDR type 0x%x, module type 0x%x\en", ddr,
378	    mod);
379}
380.Ed
381.Sh ERRORS
382Upon returning from the
383.Fn libjedec_spd
384function, the
385.Fa errp
386pointer will be set to one of the following values:
387.Bl  -tag -width Dv
388.It Er LIBJEDEC_SPD_OK
389This indicates that the system was able to parse SPD data into a valid
390.Vt nvlist_t
391and return it to the caller.
392This code should never appear when the function fails and returns
393.Dv NULL .
394Callers must still cehck the contents of the
395.Dv SPD_KEY_ERRS
396nvlist.
397.It Dv LIBJEDEC_SPD_NOMEM
398This indicates that the system ran out of memory while trying to
399construct the
400.Vt nvlist_t
401to return.
402.It Dv LIBJEDEC_SPD_TOOSHORT
403This indicates that not enough SPD data was present as indicated by
404.Fa buf
405and
406.Fa buflen
407for the given type of SPD information and therefore we were unable to
408successfully parse basic information.
409.It Dv LIBJEDEC_SPD_UNSUP_TYPE
410This indicates that the type of SPD data present, e.g. DDR4 SDRAM,
411LPDDR3, etc., that was found is not currently supported by the library.
412.It Dv LIBJEDEC_SPD_UNSUP_REV
413This indicates that while the library is familiar with the specific type
414of SPD data present, the encoding level of the data
415.Pq similar to a major version
416is unsupported by the library.
417.El
418.Sh INTERFACE STABILITY
419.Sy Uncommitted
420.Sh MT-LEVEL
421.Sy MT-Safe
422.Sh SEE ALSO
423.Xr libjedec 3LIB ,
424.Xr nvlist_lookup_boolean 3NVPAIR ,
425.Xr nvlist_lookup_string 3NVPAIR ,
426.Xr nvlist_lookup_uint32 3NVPAIR ,
427.Xr nvlist_lookup_uint32_array 3NVPAIR ,
428.Xr nvlist_lookup_uint64 3NVPAIR
429.Pp
430.Rs
431.%Q JEDEC Solid State Technology Association
432.%T Serial Presence Detect (SPD), General Standard
433.%N 21-C
434.Re
435.Rs
436.%Q JEDEC Solid State Technology Association
437.%T DDR5 Serial Presence Detect (SPD) Contents
438.%N JESD400-5A.01
439.%D January 2023
440.Re
441