xref: /illumos-gate/usr/src/lib/libjedec/common/libjedec_spd.h (revision 8119dad84d6416f13557b0ba8e2aaf9064cbcfd3)
1fe82ebb0SRobert Mustacchi /*
2fe82ebb0SRobert Mustacchi  * This file and its contents are supplied under the terms of the
3fe82ebb0SRobert Mustacchi  * Common Development and Distribution License ("CDDL"), version 1.0.
4fe82ebb0SRobert Mustacchi  * You may only use this file in accordance with the terms of version
5fe82ebb0SRobert Mustacchi  * 1.0 of the CDDL.
6fe82ebb0SRobert Mustacchi  *
7fe82ebb0SRobert Mustacchi  * A full copy of the text of the CDDL should have accompanied this
8fe82ebb0SRobert Mustacchi  * source.  A copy of the CDDL is also available via the Internet at
9fe82ebb0SRobert Mustacchi  * http://www.illumos.org/license/CDDL.
10fe82ebb0SRobert Mustacchi  */
11fe82ebb0SRobert Mustacchi 
12fe82ebb0SRobert Mustacchi /*
13*8119dad8SRobert Mustacchi  * Copyright 2024 Oxide Computer Company
14fe82ebb0SRobert Mustacchi  */
15fe82ebb0SRobert Mustacchi 
16fe82ebb0SRobert Mustacchi #ifndef _LIBJEDEC_SPD_H
17fe82ebb0SRobert Mustacchi #define	_LIBJEDEC_SPD_H
18fe82ebb0SRobert Mustacchi 
19fe82ebb0SRobert Mustacchi /*
20fe82ebb0SRobert Mustacchi  * This header contains all the library-specific definitions for SPD parsing
21fe82ebb0SRobert Mustacchi  * that are split up between different files. The protocol definitions are
22fe82ebb0SRobert Mustacchi  * rooted in spd_common.h and spd_<spec>.h (e.g. spd_ddr4.h).
23fe82ebb0SRobert Mustacchi  */
24fe82ebb0SRobert Mustacchi 
25fe82ebb0SRobert Mustacchi #include <stdint.h>
26fe82ebb0SRobert Mustacchi #include <stdbool.h>
27fe82ebb0SRobert Mustacchi #include <libjedec.h>
28fe82ebb0SRobert Mustacchi #include <sys/ccompile.h>
29fe82ebb0SRobert Mustacchi #include "spd_common.h"
30fe82ebb0SRobert Mustacchi 
31fe82ebb0SRobert Mustacchi #ifdef __cplusplus
32fe82ebb0SRobert Mustacchi extern "C" {
33fe82ebb0SRobert Mustacchi #endif
34fe82ebb0SRobert Mustacchi 
35fe82ebb0SRobert Mustacchi typedef enum {
36fe82ebb0SRobert Mustacchi 	SPD_INFO_F_INCOMPLETE	= 1 << 0
37fe82ebb0SRobert Mustacchi } spd_info_flags_t;
38fe82ebb0SRobert Mustacchi 
39fe82ebb0SRobert Mustacchi typedef struct {
40fe82ebb0SRobert Mustacchi 	const uint8_t *si_data;
41fe82ebb0SRobert Mustacchi 	size_t si_nbytes;
42fe82ebb0SRobert Mustacchi 	spd_dram_type_t	si_dram;
43fe82ebb0SRobert Mustacchi 	spd_module_type_t si_type;
44fe82ebb0SRobert Mustacchi 	uint32_t si_max_bytes;
45fe82ebb0SRobert Mustacchi 	spd_error_t si_error;
46fe82ebb0SRobert Mustacchi 	spd_info_flags_t si_flags;
47fe82ebb0SRobert Mustacchi 	nvlist_t *si_nvl;
48fe82ebb0SRobert Mustacchi 	nvlist_t *si_errs;
49fe82ebb0SRobert Mustacchi } spd_info_t;
50fe82ebb0SRobert Mustacchi 
51fe82ebb0SRobert Mustacchi typedef struct {
52fe82ebb0SRobert Mustacchi 	/*
53fe82ebb0SRobert Mustacchi 	 * Byte offset of this key we're going to parse.
54fe82ebb0SRobert Mustacchi 	 */
55fe82ebb0SRobert Mustacchi 	uint32_t sp_off;
56fe82ebb0SRobert Mustacchi 	/*
57fe82ebb0SRobert Mustacchi 	 * Length of the field we're parsing. If this is left as zero, we assume
58fe82ebb0SRobert Mustacchi 	 * it is one. This is mostly used for string parsing logic as opposed to
59fe82ebb0SRobert Mustacchi 	 * integer related pieces.
60fe82ebb0SRobert Mustacchi 	 */
61fe82ebb0SRobert Mustacchi 	uint32_t sp_len;
62fe82ebb0SRobert Mustacchi 	/*
63fe82ebb0SRobert Mustacchi 	 * An optional key-name. This is used when we're using a common parsing
64fe82ebb0SRobert Mustacchi 	 * function ala manufacturing data as opposed to say parsing timing
65fe82ebb0SRobert Mustacchi 	 * values that may look for multiple values.
66fe82ebb0SRobert Mustacchi 	 */
67fe82ebb0SRobert Mustacchi 	const char *sp_key;
68fe82ebb0SRobert Mustacchi 	void (*sp_parse)(spd_info_t *, uint32_t, uint32_t, const char *);
69fe82ebb0SRobert Mustacchi } spd_parse_t;
70fe82ebb0SRobert Mustacchi 
71fe82ebb0SRobert Mustacchi /*
72fe82ebb0SRobert Mustacchi  * Many SPD keys map to a different enum of set of discrete values. The
73fe82ebb0SRobert Mustacchi  * following structures are used to create pairs of these that we will process
74fe82ebb0SRobert Mustacchi  * so that way we can have basic tables that are consumed and less switch
75fe82ebb0SRobert Mustacchi  * statements. The svm_spd value tracks the value in the spec. The svm_use is
76fe82ebb0SRobert Mustacchi  * the corresponding value that should be used in the system. Finally, the
77fe82ebb0SRobert Mustacchi  * svm_skip, is a way to indicate that a value is valid, but undefined and
78fe82ebb0SRobert Mustacchi  * therefore no entry should be created as opposed to being treated as an
79fe82ebb0SRobert Mustacchi  * invalid value.
80fe82ebb0SRobert Mustacchi  */
81fe82ebb0SRobert Mustacchi typedef struct {
82fe82ebb0SRobert Mustacchi 	uint8_t svm_spd;
83fe82ebb0SRobert Mustacchi 	uint32_t svm_use;
84fe82ebb0SRobert Mustacchi 	bool svm_skip;
85fe82ebb0SRobert Mustacchi } spd_value_map_t;
86fe82ebb0SRobert Mustacchi 
87fe82ebb0SRobert Mustacchi typedef struct {
88fe82ebb0SRobert Mustacchi 	uint8_t svm_spd;
89fe82ebb0SRobert Mustacchi 	uint64_t svm_use;
90fe82ebb0SRobert Mustacchi 	bool svm_skip;
91fe82ebb0SRobert Mustacchi } spd_value_map64_t;
92fe82ebb0SRobert Mustacchi 
93fe82ebb0SRobert Mustacchi typedef struct {
94fe82ebb0SRobert Mustacchi 	uint8_t ssm_spd;
95fe82ebb0SRobert Mustacchi 	const char *ssm_str;
96fe82ebb0SRobert Mustacchi 	bool ssm_skip;
97fe82ebb0SRobert Mustacchi } spd_str_map_t;
98fe82ebb0SRobert Mustacchi 
99fe82ebb0SRobert Mustacchi typedef struct {
100fe82ebb0SRobert Mustacchi 	uint32_t svr_min;
101fe82ebb0SRobert Mustacchi 	uint32_t svr_max;
102fe82ebb0SRobert Mustacchi 	uint32_t svr_base;
103fe82ebb0SRobert Mustacchi 	uint32_t svr_mult;
104*8119dad8SRobert Mustacchi 	bool svr_exp;
105fe82ebb0SRobert Mustacchi } spd_value_range_t;
106fe82ebb0SRobert Mustacchi 
107fe82ebb0SRobert Mustacchi /*
108fe82ebb0SRobert Mustacchi  * Common routines for parsing and nvlist work.
109fe82ebb0SRobert Mustacchi  */
110fe82ebb0SRobert Mustacchi extern void spd_parse(spd_info_t *, const spd_parse_t *, size_t);
111fe82ebb0SRobert Mustacchi extern void spd_nvl_err(spd_info_t *, const char *, spd_error_kind_t,
112fe82ebb0SRobert Mustacchi     const char *, ...) __PRINTFLIKE(4);
113fe82ebb0SRobert Mustacchi extern void spd_nvl_insert_str(spd_info_t *, const char *, const char *);
114fe82ebb0SRobert Mustacchi extern void spd_nvl_insert_u32(spd_info_t *, const char *, uint32_t);
115fe82ebb0SRobert Mustacchi extern void spd_nvl_insert_u64(spd_info_t *, const char *, uint64_t);
116fe82ebb0SRobert Mustacchi extern void spd_nvl_insert_u32_array(spd_info_t *, const char *,
117fe82ebb0SRobert Mustacchi     uint32_t *, uint_t);
118*8119dad8SRobert Mustacchi extern void spd_nvl_insert_u64_array(spd_info_t *, const char *,
119*8119dad8SRobert Mustacchi     uint64_t *, uint_t);
120*8119dad8SRobert Mustacchi extern void spd_nvl_insert_boolean_array(spd_info_t *, const char *,
121*8119dad8SRobert Mustacchi     boolean_t *, uint_t);
122fe82ebb0SRobert Mustacchi extern void spd_nvl_insert_key(spd_info_t *, const char *);
123fe82ebb0SRobert Mustacchi 
124fe82ebb0SRobert Mustacchi extern void spd_insert_map(spd_info_t *, const char *, uint8_t,
125fe82ebb0SRobert Mustacchi     const spd_value_map_t *, size_t);
126fe82ebb0SRobert Mustacchi extern void spd_insert_map64(spd_info_t *, const char *, uint8_t,
127fe82ebb0SRobert Mustacchi     const spd_value_map64_t *, size_t);
128fe82ebb0SRobert Mustacchi extern void spd_insert_str_map(spd_info_t *, const char *, uint8_t,
129fe82ebb0SRobert Mustacchi     const spd_str_map_t *, size_t);
130fe82ebb0SRobert Mustacchi extern void spd_insert_map_array(spd_info_t *, const char *, const uint8_t *,
131fe82ebb0SRobert Mustacchi     size_t, const spd_value_map_t *, size_t);
132fe82ebb0SRobert Mustacchi extern void spd_insert_range(spd_info_t *, const char *, uint8_t,
133fe82ebb0SRobert Mustacchi     const spd_value_range_t *);
134fe82ebb0SRobert Mustacchi extern void spd_upsert_flag(spd_info_t *, const char *, uint32_t);
135fe82ebb0SRobert Mustacchi 
136fe82ebb0SRobert Mustacchi extern void spd_parse_jedec_id(spd_info_t *, uint32_t, uint32_t, const char *);
137fe82ebb0SRobert Mustacchi extern void spd_parse_jedec_id_str(spd_info_t *, uint32_t, uint32_t,
138fe82ebb0SRobert Mustacchi     const char *);
139fe82ebb0SRobert Mustacchi extern void spd_parse_string(spd_info_t *, uint32_t, uint32_t, const char *);
140fe82ebb0SRobert Mustacchi extern void spd_parse_hex_string(spd_info_t *, uint32_t, uint32_t,
141fe82ebb0SRobert Mustacchi     const char *);
142fe82ebb0SRobert Mustacchi extern void spd_parse_hex_vers(spd_info_t *, uint32_t, uint32_t, const char *);
143fe82ebb0SRobert Mustacchi extern void spd_parse_raw_u8(spd_info_t *, uint32_t, uint32_t, const char *);
144*8119dad8SRobert Mustacchi extern void spd_parse_u8_array(spd_info_t *, uint32_t, uint32_t, const char *);
145fe82ebb0SRobert Mustacchi extern void spd_parse_dram_step(spd_info_t *, uint32_t, uint32_t, const char *);
146fe82ebb0SRobert Mustacchi extern void spd_parse_crc(spd_info_t *, uint32_t, uint32_t, const char *);
147*8119dad8SRobert Mustacchi extern void spd_parse_crc_expect(spd_info_t *, uint32_t, uint32_t, uint16_t,
148*8119dad8SRobert Mustacchi     const char *);
149fe82ebb0SRobert Mustacchi extern void spd_parse_rev(spd_info_t *, uint32_t, uint32_t, const char *);
150fe82ebb0SRobert Mustacchi extern void spd_parse_height(spd_info_t *, uint32_t, uint32_t, const char *);
151*8119dad8SRobert Mustacchi extern void spd_parse_design(spd_info_t *, uint32_t, uint32_t);
152fe82ebb0SRobert Mustacchi extern void spd_parse_thickness(spd_info_t *, uint32_t, uint32_t, const char *);
153*8119dad8SRobert Mustacchi extern void spd_parse_ddr_time(spd_info_t *, const char *, uint8_t, uint8_t,
154*8119dad8SRobert Mustacchi     uint8_t);
155*8119dad8SRobert Mustacchi extern void spd_parse_mtb_ftb_time_pair(spd_info_t *, uint32_t, uint32_t,
156*8119dad8SRobert Mustacchi     const char *);
157*8119dad8SRobert Mustacchi extern void spd_parse_mtb_pair(spd_info_t *, uint32_t, uint32_t, const char *);
158*8119dad8SRobert Mustacchi extern void spd_parse_lp_trfcxb(spd_info_t *, uint32_t, uint32_t, const char *);
159*8119dad8SRobert Mustacchi extern void spd_parse_ddr4_nib_map(spd_info_t *, uint32_t, uint32_t,
160*8119dad8SRobert Mustacchi     const char *);
161*8119dad8SRobert Mustacchi extern void spd_parse_ddr4_design(spd_info_t *, uint32_t, uint32_t,
162*8119dad8SRobert Mustacchi     const char *);
163*8119dad8SRobert Mustacchi extern void spd_parse_ddr5_mod_type(spd_info_t *, uint32_t, uint32_t,
164*8119dad8SRobert Mustacchi     const char *);
165fe82ebb0SRobert Mustacchi 
166fe82ebb0SRobert Mustacchi /*
167fe82ebb0SRobert Mustacchi  * Protocol-specific entry points.
168fe82ebb0SRobert Mustacchi  */
169*8119dad8SRobert Mustacchi extern void spd_parse_ddr3(spd_info_t *);
170fe82ebb0SRobert Mustacchi extern void spd_parse_ddr4(spd_info_t *);
171fe82ebb0SRobert Mustacchi extern void spd_parse_ddr5(spd_info_t *);
172*8119dad8SRobert Mustacchi extern void spd_parse_lp4(spd_info_t *);
173*8119dad8SRobert Mustacchi extern void spd_parse_lp5(spd_info_t *);
174*8119dad8SRobert Mustacchi extern void spd_parse_ddr4_mfg(spd_info_t *);
175*8119dad8SRobert Mustacchi extern void spd_parse_ddr5_common(spd_info_t *);
176fe82ebb0SRobert Mustacchi 
177fe82ebb0SRobert Mustacchi #ifdef __cplusplus
178fe82ebb0SRobert Mustacchi }
179fe82ebb0SRobert Mustacchi #endif
180fe82ebb0SRobert Mustacchi 
181fe82ebb0SRobert Mustacchi #endif /* _LIBJEDEC_SPD_H */
182