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