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