xref: /illumos-gate/usr/src/lib/libjedec/common/libjedec_spd.h (revision 9b9d39d2a32ff806d2431dbcc50968ef1e6d46b2)
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 2023 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 } spd_value_range_t;
105 
106 /*
107  * Common routines for parsing and nvlist work.
108  */
109 extern void spd_parse(spd_info_t *, const spd_parse_t *, size_t);
110 extern void spd_nvl_err(spd_info_t *, const char *, spd_error_kind_t,
111     const char *, ...) __PRINTFLIKE(4);
112 extern void spd_nvl_insert_str(spd_info_t *, const char *, const char *);
113 extern void spd_nvl_insert_u32(spd_info_t *, const char *, uint32_t);
114 extern void spd_nvl_insert_u64(spd_info_t *, const char *, uint64_t);
115 extern void spd_nvl_insert_u32_array(spd_info_t *, const char *,
116     uint32_t *, uint_t);
117 extern void spd_nvl_insert_key(spd_info_t *, const char *);
118 
119 extern void spd_insert_map(spd_info_t *, const char *, uint8_t,
120     const spd_value_map_t *, size_t);
121 extern void spd_insert_map64(spd_info_t *, const char *, uint8_t,
122     const spd_value_map64_t *, size_t);
123 extern void spd_insert_str_map(spd_info_t *, const char *, uint8_t,
124     const spd_str_map_t *, size_t);
125 extern void spd_insert_map_array(spd_info_t *, const char *, const uint8_t *,
126     size_t, const spd_value_map_t *, size_t);
127 extern void spd_insert_range(spd_info_t *, const char *, uint8_t,
128     const spd_value_range_t *);
129 extern void spd_upsert_flag(spd_info_t *, const char *, uint32_t);
130 
131 extern void spd_parse_jedec_id(spd_info_t *, uint32_t, uint32_t, const char *);
132 extern void spd_parse_jedec_id_str(spd_info_t *, uint32_t, uint32_t,
133     const char *);
134 extern void spd_parse_string(spd_info_t *, uint32_t, uint32_t, const char *);
135 extern void spd_parse_hex_string(spd_info_t *, uint32_t, uint32_t,
136     const char *);
137 extern void spd_parse_hex_vers(spd_info_t *, uint32_t, uint32_t, const char *);
138 extern void spd_parse_raw_u8(spd_info_t *, uint32_t, uint32_t, const char *);
139 extern void spd_parse_dram_step(spd_info_t *, uint32_t, uint32_t, const char *);
140 extern void spd_parse_crc(spd_info_t *, uint32_t, uint32_t, const char *);
141 extern void spd_parse_rev(spd_info_t *, uint32_t, uint32_t, const char *);
142 extern void spd_parse_height(spd_info_t *, uint32_t, uint32_t, const char *);
143 extern void spd_parse_thickness(spd_info_t *, uint32_t, uint32_t, const char *);
144 
145 /*
146  * Protocol-specific entry points.
147  */
148 extern void spd_parse_ddr4(spd_info_t *);
149 extern void spd_parse_ddr5(spd_info_t *);
150 
151 #ifdef __cplusplus
152 }
153 #endif
154 
155 #endif /* _LIBJEDEC_SPD_H */
156