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