diff --git a/src/soc/intel/broadwell/include/soc/pei_data.h b/src/soc/intel/broadwell/include/soc/pei_data.h index 339dadd4d6..d12011e797 100644 --- a/src/soc/intel/broadwell/include/soc/pei_data.h +++ b/src/soc/intel/broadwell/include/soc/pei_data.h @@ -31,7 +31,6 @@ #include #include -#include #define PEI_VERSION 22 @@ -87,6 +86,87 @@ struct usb3_port_setting { uint8_t fixed_eq; } __packed; +#define PEI_DIMM_INFO_SERIAL_SIZE 5 +#define PEI_DIMM_INFO_PART_NUMBER_SIZE 19 +#define PEI_DIMM_INFO_TOTAL 8 /* Maximum num of dimm is 8 */ + + +/** + * This table is filled by the MRC blob and used to populate the mem_info + * struct, which is placed in CBMEM and then used to generate SMBIOS type + * 17 table(s) + * + * Values are specified according to the JEDEC SPD Standard. + */ +struct pei_dimm_info { + /* + * Size of the module in MiB. + */ + uint32_t dimm_size; + /* + * SMBIOS (not SPD) device type. + * + * See the smbios.h smbios_memory_device_type enum. + */ + uint16_t ddr_type; + uint16_t ddr_frequency; + uint8_t rank_per_dimm; + uint8_t channel_num; + uint8_t dimm_num; + uint8_t bank_locator; + /* + * The last byte is '\0' for the end of string. + * + * Even though the SPD spec defines this field as a byte array the value + * is passed directly to SMBIOS as a string, and thus must be printable + * ASCII. + */ + uint8_t serial[PEI_DIMM_INFO_SERIAL_SIZE]; + /* + * The last byte is '\0' for the end of string + * + * Must contain only printable ASCII. + */ + uint8_t module_part_number[PEI_DIMM_INFO_PART_NUMBER_SIZE]; + /* + * SPD Manufacturer ID + */ + uint16_t mod_id; + /* + * SPD Module Type. + * + * See spd.h for valid values. + * + * e.g., SPD_RDIMM, SPD_SODIMM, SPD_MICRO_DIMM + */ + uint8_t mod_type; + /* + * SPD bus width. + * + * Bits 0 - 2 encode the primary bus width: + * 0b000 = 8 bit width + * 0b001 = 16 bit width + * 0b010 = 32 bit width + * 0b011 = 64 bit width + * + * Bits 3 - 4 encode the extension bits (ECC): + * 0b00 = 0 extension bits + * 0b01 = 8 bit of ECC + * + * e.g., + * 64 bit bus with 8 bits of ECC (72 bits total): 0b1011 + * 64 bit bus with 0 bits of ECC (64 bits total): 0b0011 + * + * See the smbios.h smbios_memory_bus_width enum. + */ + uint8_t bus_width; +} __packed; + +struct pei_memory_info { + uint8_t dimm_cnt; + struct pei_dimm_info dimm[PEI_DIMM_INFO_TOTAL]; +} __packed; + struct pei_data { uint32_t pei_version; @@ -191,7 +271,7 @@ struct pei_data { /* Data from MRC that should be saved to flash */ void *data_to_save; int data_to_save_size; - struct memory_info meminfo; + struct pei_memory_info meminfo; } __packed; typedef struct pei_data PEI_DATA; diff --git a/src/soc/intel/broadwell/romstage/raminit.c b/src/soc/intel/broadwell/romstage/raminit.c index 665dad277e..54db3d1564 100644 --- a/src/soc/intel/broadwell/romstage/raminit.c +++ b/src/soc/intel/broadwell/romstage/raminit.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #if IS_ENABLED(CONFIG_EC_GOOGLE_CHROMEEC) @@ -121,6 +122,29 @@ void raminit(struct pei_data *pei_data) printk(BIOS_DEBUG, "create cbmem for dimm information\n"); mem_info = cbmem_add(CBMEM_ID_MEMINFO, sizeof(struct memory_info)); - memcpy(mem_info, &pei_data->meminfo, sizeof(struct memory_info)); - + memset(mem_info, 0, sizeof(*mem_info)); + /* Translate pei_memory_info struct data into memory_info struct */ + mem_info->dimm_cnt = pei_data->meminfo.dimm_cnt; + for (int i = 0; i < MIN(DIMM_INFO_TOTAL, PEI_DIMM_INFO_TOTAL); i++) { + struct dimm_info *dimm = &mem_info->dimm[i]; + const struct pei_dimm_info *pei_dimm = + &pei_data->meminfo.dimm[i]; + dimm->dimm_size = pei_dimm->dimm_size; + dimm->ddr_type = pei_dimm->ddr_type; + dimm->ddr_frequency = pei_dimm->ddr_frequency; + dimm->rank_per_dimm = pei_dimm->rank_per_dimm; + dimm->channel_num = pei_dimm->channel_num; + dimm->dimm_num = pei_dimm->dimm_num; + dimm->bank_locator = pei_dimm->bank_locator; + memcpy(&dimm->serial, &pei_dimm->serial, + MIN(sizeof(dimm->serial), sizeof(pei_dimm->serial))); + memcpy(&dimm->module_part_number, + &pei_dimm->module_part_number, + MIN(sizeof(dimm->module_part_number), + sizeof(pei_dimm->module_part_number))); + dimm->module_part_number[DIMM_INFO_PART_NUMBER_SIZE - 1] = '\0'; + dimm->mod_id = pei_dimm->mod_id; + dimm->mod_type = pei_dimm->mod_type; + dimm->bus_width = pei_dimm->bus_width; + } }