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