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