1 /* SPDX-License-Identifier: GPL-2.0-only */
4 #include <console/console.h>
7 #include <device/pci_ops.h>
8 #include <device/smbus_host.h>
9 #include <soc/intel/common/block/smbus/smbuslib.h>
15 #define I2C_ADDR_EEPROM 0x57
18 * Check Signature in EEPROM (M24C32-FMN6TP)
19 * If signature is there we assume that that the content is valid
21 int check_signature(const size_t offset
, const uint64_t signature
)
25 if (!eeprom_read_buffer(blob
, offset
, ARRAY_SIZE(blob
))) {
27 if (*(uint64_t *)blob
== signature
) {
28 printk(BIOS_DEBUG
, "CFG EEPROM: Signature valid.\n");
31 printk(BIOS_DEBUG
, "CFG EEPROM: Signature invalid - skipping option write.\n");
38 * Read board settings from the EEPROM and verify their checksum.
39 * If checksum is valid, we assume the settings are sane as well.
41 static size_t get_board_settings_from_eeprom(struct eeprom_board_settings
*board_cfg
)
43 const size_t board_settings_offset
= offsetof(struct eeprom_layout
, board_settings
);
45 if (eeprom_read_buffer(board_cfg
, board_settings_offset
, sizeof(*board_cfg
))) {
46 printk(BIOS_ERR
, "CFG EEPROM: Failed to read board settings\n");
51 * Ideally, the definition for board settings would always be the same across
52 * coreboot and the BMC. However, this is not always the case. When there's a
53 * mismatch, coreboot often has the newer definition with more settings. When
54 * there's a mismatch, coreboot and the BMC calculate the CRC for a different
55 * set of bytes, which results in two different CRC values.
57 * As existing board settings do not get repurposed, it is relatively easy to
58 * make coreboot backwards compatible with older BMC firmware revisions which
59 * do not provide the latest board settings. Starting with all board settings
60 * coreboot knows about, if the CRC does not match, we drop the last byte and
61 * try again until we find a match or exhaust all bytes.
63 for (size_t len
= sizeof(board_cfg
->raw_settings
); len
> 0; len
--) {
64 const uint32_t crc
= CRC(&board_cfg
->raw_settings
, len
, crc32_byte
);
65 if (crc
!= board_cfg
->signature
)
68 printk(BIOS_DEBUG
, "CFG EEPROM: Board settings CRC OK for %zu / %lu bytes\n",
69 len
, sizeof(board_cfg
->raw_settings
));
73 printk(BIOS_ERR
, "CFG EEPROM: Board settings have invalid checksum\n");
77 struct eeprom_board_settings
*get_board_settings(void)
80 * Default settings to be used if the EEPROM settings are unavailable.
81 * Unspecified settings default to 0. These default values do not get
82 * passed to edk2 in any way, so there is no need to provide defaults
83 * for edk2-only options like `secureboot`.
85 const struct eeprom_board_settings default_cfg
= {
88 .power_state_after_g3
= !CONFIG_MAINBOARD_POWER_FAILURE_STATE
,
93 static struct eeprom_board_settings board_cfg
= {0};
94 static bool cfg_cached
= false;
99 const size_t valid_bytes
= get_board_settings_from_eeprom(&board_cfg
);
101 /* If we could not read all settings from the EEPROM, get the rest from defaults */
102 for (size_t i
= valid_bytes
; i
< sizeof(board_cfg
.raw_settings
); i
++)
103 board_cfg
.raw_settings
[i
] = default_cfg
.raw_settings
[i
];
110 struct eeprom_bmc_settings
*get_bmc_settings(void)
112 const size_t bmc_settings_offset
= offsetof(struct eeprom_layout
, bmc_settings
);
113 static struct eeprom_bmc_settings bmc_cfg
= {0};
115 /* 0: uninitialized, 1: settings are valid */
116 static int valid
= 0;
119 if (eeprom_read_buffer(&bmc_cfg
, bmc_settings_offset
, sizeof(bmc_cfg
))) {
120 printk(BIOS_ERR
, "CFG EEPROM: Failed to read BMC settings\n");
128 const char *eeprom_read_serial(const size_t offset
, const char *const fallback
)
130 static char serial_no
[HERMES_SN_PN_LENGTH
+ 1] = { 0 };
131 memset(serial_no
, 0, sizeof(serial_no
));
133 if (eeprom_read_buffer(serial_no
, offset
, HERMES_SN_PN_LENGTH
) == 0)
139 uint8_t get_bmc_hsi(void)
142 struct eeprom_bmc_settings
*s
= get_bmc_settings();
145 printk(BIOS_DEBUG
, "CFG EEPROM: HSI 0x%x\n", hsi
);
150 /* Read data from an EEPROM on SMBus and write it to a buffer */
151 bool eeprom_read_buffer(void *blob
, size_t read_offset
, size_t size
)
155 u32 smb_ctrl_reg
= pci_read_config32(PCH_DEV_SMBUS
, HOSTC
);
156 pci_write_config32(PCH_DEV_SMBUS
, HOSTC
, smb_ctrl_reg
| I2C_EN
);
158 printk(BIOS_SPEW
, "%s\tOffset: %04zx\tSize: %02zx\n", __func__
,
161 /* We can always read two bytes at a time */
162 for (size_t i
= 0; i
< size
; i
= i
+ 2) {
165 ret
= do_smbus_process_call(SMBUS_IO_BASE
, I2C_ADDR_EEPROM
, 0,
166 swab16(read_offset
+ i
), (uint16_t *)&tmp
[0]);
171 uint8_t *write_ptr
= (uint8_t *)blob
+ i
;
172 write_ptr
[0] = tmp
[0];
174 write_ptr
[1] = tmp
[1];
177 /* Restore I2C_EN bit */
178 pci_write_config32(PCH_DEV_SMBUS
, HOSTC
, smb_ctrl_reg
);
183 void report_eeprom_error(const size_t off
)
185 printk(BIOS_ERR
, "MB: Failed to read from EEPROM at addr. 0x%zx\n", off
);
189 * Write a single byte into the EEPROM at specified offset.
190 * Returns true on error, false on success.
192 bool eeprom_write_byte(const uint8_t data
, const uint16_t write_offset
)
196 printk(BIOS_SPEW
, "CFG EEPROM: Writing %x at %x\n", data
, write_offset
);
198 const uint32_t smb_ctrl_reg
= pci_read_config32(PCH_DEV_SMBUS
, HOSTC
);
199 pci_write_config32(PCH_DEV_SMBUS
, HOSTC
, smb_ctrl_reg
| I2C_EN
);
202 * The EEPROM expects two address bytes.
203 * Use the first byte of the block data as second address byte.
205 uint8_t buffer
[2] = {
210 for (size_t retry
= 3; retry
> 0; retry
--) {
211 /* The EEPROM NACKs request when busy writing */
212 ret
= do_smbus_block_write(SMBUS_IO_BASE
, I2C_ADDR_EEPROM
,
213 (write_offset
>> 8) & 0xff,
214 sizeof(buffer
), buffer
);
215 if (ret
== sizeof(buffer
))
217 /* Maximum of 5 milliseconds write duration */
221 /* Restore I2C_EN bit */
222 pci_write_config32(PCH_DEV_SMBUS
, HOSTC
, smb_ctrl_reg
);
224 return ret
!= sizeof(buffer
);
228 * Write board layout if it has changed into EEPROM.
229 * Return true on error, false on success.
231 bool write_board_settings(const struct eeprom_board_layout
*new_layout
)
233 const size_t off
= offsetof(struct eeprom_layout
, board_layout
);
234 struct eeprom_board_layout old_layout
= {0};
236 bool changed
= false;
238 /* Read old settings */
239 if (eeprom_read_buffer(&old_layout
, off
, sizeof(old_layout
))) {
240 printk(BIOS_ERR
, "CFG EEPROM: Read operation failed\n");
244 assert(sizeof(old_layout
) == sizeof(*new_layout
));
245 const uint8_t *const old
= (const uint8_t *)&old_layout
;
246 const uint8_t *const new = (const uint8_t *)new_layout
;
248 /* Compare with new settings and only write changed bytes */
249 for (size_t i
= 0; i
< sizeof(old_layout
); i
++) {
250 if (old
[i
] != new[i
]) {
252 if (eeprom_write_byte(new[i
], off
+ i
)) {
253 printk(BIOS_ERR
, "CFG EEPROM: Write operation failed\n");
260 printk(BIOS_DEBUG
, "CFG EEPROM: Board Layout up%s\n", changed
? "dated" : " to date");