46#include "switchtec_priv.h"
48#include "switchtec/mfg.h"
49#include "switchtec/errors.h"
50#include "switchtec/endian.h"
51#include "switchtec/mrpc.h"
52#include "switchtec/errors.h"
65#include <openssl/pem.h>
68#define SWITCHTEC_ACTV_IMG_ID_KMAN 1
69#define SWITCHTEC_ACTV_IMG_ID_BL2 2
70#define SWITCHTEC_ACTV_IMG_ID_CFG 3
71#define SWITCHTEC_ACTV_IMG_ID_FW 4
73#define SWITCHTEC_ACTV_IMG_ID_KMAN_GEN5 1
74#define SWITCHTEC_ACTV_IMG_ID_RC_GEN5 2
75#define SWITCHTEC_ACTV_IMG_ID_BL2_GEN5 3
76#define SWITCHTEC_ACTV_IMG_ID_CFG_GEN5 4
77#define SWITCHTEC_ACTV_IMG_ID_FW_GEN5 5
79#define SWITCHTEC_MB_MAX_ENTRIES 16
80#define SWITCHTEC_ACTV_IDX_MAX_ENTRIES 32
81#define SWITCHTEC_ACTV_IDX_SET_ENTRIES 5
83#define SWITCHTEC_ATTEST_BITSHIFT 4
84#define SWITCHTEC_ATTEST_BITMASK 0x03
85#define SWITCHTEC_CLK_RATE_BITSHIFT 10
86#define SWITCHTEC_CLK_RATE_BITMASK 0x0f
87#define SWITCHTEC_RC_TMO_BITSHIFT 14
88#define SWITCHTEC_RC_TMO_BITMASK 0x0f
89#define SWITCHTEC_I2C_PORT_BITSHIFT 18
90#define SWITCHTEC_I2C_PORT_BITMASK 0x0f
91#define SWITCHTEC_I2C_ADDR_BITSHIFT 22
92#define SWITCHTEC_I2C_ADDR_BITSHIFT_GEN5 23
93#define SWITCHTEC_I2C_ADDR_BITMASK 0x7f
94#define SWITCHTEC_CMD_MAP_BITSHIFT 29
95#define SWITCHTEC_CMD_MAP_BITSHIFT_GEN5 30
96#define SWITCHTEC_CMD_MAP_BITMASK 0xfff
97#define SWITCHTEC_CMD_MAP_BITMASK_GEN5 0x3fff
98#define SWITCHTEC_UDS_SELFGEN_BITSHIFT 44
99#define SWITCHTEC_UDS_SELFGEN_BITMASK 0x01
101#define SWITCHTEC_JTAG_LOCK_AFT_RST_BITMASK 0x40
102#define SWITCHTEC_JTAG_LOCK_AFT_BL1_BITMASK 0x80
103#define SWITCHTEC_JTAG_UNLOCK_BL1_BITMASK 0x0100
104#define SWITCHTEC_JTAG_UNLOCK_AFT_BL1_BITMASK 0x0200
106static int switchtec_mfg_cmd(
struct switchtec_dev *dev, uint32_t cmd,
107 const void *payload,
size_t payload_len,
108 void *resp,
size_t resp_len);
110static void get_i2c_operands(
enum switchtec_gen gen, uint32_t *addr_shift,
111 uint32_t *map_shift, uint32_t *map_mask)
113 if (gen > SWITCHTEC_GEN4) {
114 *addr_shift = SWITCHTEC_I2C_ADDR_BITSHIFT_GEN5;
115 *map_shift = SWITCHTEC_CMD_MAP_BITSHIFT_GEN5;
116 *map_mask = SWITCHTEC_CMD_MAP_BITMASK_GEN5;
118 *addr_shift = SWITCHTEC_I2C_ADDR_BITSHIFT;
119 *map_shift = SWITCHTEC_CMD_MAP_BITSHIFT;
120 *map_mask = SWITCHTEC_CMD_MAP_BITMASK;
124static float spi_clk_rate_float[] = {
125 100, 67, 50, 40, 33.33, 28.57, 25, 22.22, 20, 18.18
128static float spi_clk_hi_rate_float[] = {
129 120, 80, 60, 48, 40, 34, 30, 26.67, 24, 21.82
132struct get_cfgs_reply {
136 uint32_t public_key_exponent;
138 uint8_t public_key_num;
139 uint8_t public_key_ver;
140 uint8_t spi_core_clk_high;
141 uint8_t public_key[4][SWITCHTEC_KMSK_LEN];
145struct get_cfgs_reply_gen5 {
149 uint32_t public_key_exponent;
151 uint8_t public_key_num;
152 uint8_t public_key_ver;
153 uint8_t spi_core_clk_high;
154 uint8_t public_key[10][SWITCHTEC_KMSK_LEN];
155 uint32_t cdi_efuse_inc_mask;
156 uint8_t uds_data[32];
159static int get_configs(
struct switchtec_dev *dev,
160 struct get_cfgs_reply *cfgs,
166 ret = switchtec_mfg_cmd(dev, MRPC_SECURITY_CONFIG_GET_EXT,
167 &subcmd,
sizeof(subcmd),
168 cfgs,
sizeof(
struct get_cfgs_reply));
169 if (ret && ERRNO_MRPC(errno) != ERR_CMD_INVALID)
178 ret = switchtec_mfg_cmd(dev, MRPC_SECURITY_CONFIG_GET,
180 sizeof(
struct get_cfgs_reply));
185static int get_configs_gen5(
struct switchtec_dev *dev,
186 struct get_cfgs_reply_gen5 *cfgs)
190 return switchtec_mfg_cmd(dev,
191 MRPC_SECURITY_CONFIG_GET_GEN5,
192 &subcmd,
sizeof(subcmd),
193 cfgs,
sizeof(
struct get_cfgs_reply_gen5));
196int switchtec_security_spi_avail_rate_get(
struct switchtec_dev *dev,
200 struct get_cfgs_reply reply;
203 ret = get_configs(dev, &reply, &otp_valid);
207 rates->num_rates = 10;
208 if (reply.spi_core_clk_high)
209 memcpy(rates->rates, spi_clk_hi_rate_float,
210 sizeof(spi_clk_hi_rate_float));
212 memcpy(rates->rates, spi_clk_rate_float,
213 sizeof(spi_clk_rate_float));
221 otp->basic_valid = !!(flags & BIT(5));
222 otp->basic = !!(flags & BIT(6));
223 otp->mixed_ver_valid = !!(flags & BIT(7));
224 otp->mixed_ver = !!(flags & BIT(8));
225 otp->main_fw_ver_valid = !!(flags & BIT(9));
226 otp->main_fw_ver = !!(flags & BIT(10));
227 otp->sec_unlock_ver_valid = !!(flags & BIT(11));
228 otp->sec_unlock_ver = !!(flags & BIT(12));
229 otp->kmsk_valid[0] = !!(flags & BIT(13));
230 otp->kmsk[0] = !!(flags & BIT(14));
231 otp->kmsk_valid[1] = !!(flags & BIT(15));
232 otp->kmsk[1] = !!(flags & BIT(16));
233 otp->kmsk_valid[2] = !!(flags & BIT(17));
234 otp->kmsk[2] = !!(flags & BIT(18));
235 otp->kmsk_valid[3] = !!(flags & BIT(19));
236 otp->kmsk[3] = !!(flags & BIT(20));
239static void parse_otp_settings_gen5(
241 uint32_t flags0, uint32_t flags1)
243 otp->basic_valid = !!(flags0 & BIT(8));
244 otp->basic = !!(flags0 & BIT(9));
245 otp->debug_mode_valid = !!(flags0 & BIT(10));
246 otp->debug_mode = !!(flags0 & BIT(11));
247 otp->key_ver_valid = !!(flags0 & BIT(12));
248 otp->key_ver = !!(flags0 & BIT(13));
249 otp->rc_ver_valid = !!(flags0 & BIT(14));
250 otp->rc_ver = !!(flags0 & BIT(15));
251 otp->bl2_ver_valid = !!(flags0 & BIT(16));
252 otp->bl2_ver = !!(flags0 & BIT(17));
253 otp->main_fw_ver_valid = !!(flags0 & BIT(18));
254 otp->main_fw_ver = !!(flags0 & BIT(19));
255 otp->sec_unlock_ver_valid = !!(flags0 & BIT(20));
256 otp->sec_unlock_ver = !!(flags0 & BIT(21));
257 otp->kmsk_valid[0] = !!(flags0 & BIT(22));
258 otp->kmsk[0] = !!(flags0 & BIT(23));
259 otp->kmsk_valid[1] = !!(flags0 & BIT(24));
260 otp->kmsk[1] = !!(flags0 & BIT(25));
261 otp->kmsk_valid[2] = !!(flags0 & BIT(26));
262 otp->kmsk[2] = !!(flags0 & BIT(27));
263 otp->kmsk_valid[3] = !!(flags0 & BIT(28));
264 otp->kmsk[3] = !!(flags0 & BIT(29));
265 otp->kmsk_valid[4] = !!(flags0 & BIT(30));
266 otp->kmsk[4] = !!(flags0 & BIT(31));
267 otp->kmsk_valid[5] = !!(flags1 & BIT(0));
268 otp->kmsk[5] = !!(flags1 & BIT(1));
269 otp->kmsk_valid[6] = !!(flags1 & BIT(2));
270 otp->kmsk[6] = !!(flags1 & BIT(3));
271 otp->kmsk_valid[7] = !!(flags1 & BIT(4));
272 otp->kmsk[7] = !!(flags1 & BIT(5));
273 otp->kmsk_valid[8] = !!(flags1 & BIT(6));
274 otp->kmsk[8] = !!(flags1 & BIT(7));
275 otp->kmsk_valid[9] = !!(flags1 & BIT(8));
276 otp->kmsk[9] = !!(flags1 & BIT(9));
277 otp->cdi_efuse_inc_mask_valid = !!(flags1 & BIT(10));
278 otp->cdi_efuse_inc_mask = !!(flags1 & BIT(11));
279 otp->uds_valid = !!(flags1 & BIT(12));
280 otp->uds = !!(flags1 & BIT(13));
281 otp->uds_mask_valid = !!(flags1 & BIT(14));
282 otp->uds_mask = !!(flags1 & BIT(15));
283 otp->mchp_uds_valid = !!(flags1 & BIT(16));
284 otp->mchp_uds = !!(flags1 & BIT(17));
285 otp->mchp_uds_mask_valid = !!(flags1 & BIT(18));
286 otp->mchp_uds_mask = !!(flags1 & BIT(19));
287 otp->did_cert0_valid = !!(flags1 & BIT(20));
288 otp->did_cert0 = !!(flags1 & BIT(21));
289 otp->did_cert1_valid = !!(flags1 & BIT(22));
290 otp->did_cert1 = !!(flags1 & BIT(23));
293static int security_config_get(
struct switchtec_dev *dev,
301 struct get_cfgs_reply reply;
304 ret = get_configs(dev, &reply, &otp_valid);
308 reply.valid = le32toh(reply.valid);
309 reply.cfg = le64toh(reply.cfg);
310 reply.public_key_exponent = le32toh(reply.public_key_exponent);
312 state->basic_setting_valid = !!(reply.valid & 0x01);
313 state->public_key_exp_valid = !!(reply.valid & 0x02);
314 state->public_key_num_valid = !!(reply.valid & 0x04);
315 state->public_key_ver_valid = !!(reply.valid & 0x08);
316 state->public_key_valid = !!(reply.valid & 0x10);
318 state->debug_mode_valid = state->basic_setting_valid;
320 state->otp_valid = otp_valid;
322 parse_otp_settings(&state->otp, reply.valid);
324 state->use_otp_ext =
false;
326 state->debug_mode = reply.cfg & 0x03;
327 state->secure_state = (reply.cfg>>2) & 0x03;
329 state->jtag_lock_after_reset = !!(reply.cfg & 0x40);
330 state->jtag_lock_after_bl1 = !!(reply.cfg & 0x80);
331 state->jtag_bl1_unlock_allowed = !!(reply.cfg & 0x0100);
332 state->jtag_post_bl1_unlock_allowed = !!(reply.cfg & 0x0200);
334 spi_clk = (reply.cfg >> SWITCHTEC_CLK_RATE_BITSHIFT) & 0x0f;
342 if (reply.spi_core_clk_high)
343 state->spi_clk_rate = spi_clk_hi_rate_float[spi_clk - 1];
345 state->spi_clk_rate = spi_clk_rate_float[spi_clk - 1];
347 state->i2c_recovery_tmo =
348 (reply.cfg >> SWITCHTEC_RC_TMO_BITSHIFT) & 0x0f;
349 state->i2c_port = (reply.cfg >> SWITCHTEC_I2C_PORT_BITSHIFT) & 0xf;
351 get_i2c_operands(
switchtec_gen(dev), &addr_shift, &map_shift,
354 (reply.cfg >> addr_shift) & SWITCHTEC_I2C_ADDR_BITMASK;
355 state->i2c_cmd_map = (reply.cfg >> map_shift) & map_mask;
357 state->public_key_exponent = reply.public_key_exponent;
358 state->public_key_num = reply.public_key_num;
359 state->public_key_ver = reply.public_key_ver;
361 if (state->public_key_num)
362 memcpy(state->public_key, reply.public_key,
363 state->public_key_num * SWITCHTEC_KMSK_LEN);
365 state->attn_state.attestation_mode =
366 SWITCHTEC_ATTESTATION_MODE_NOT_SUPPORTED;
371static int security_config_get_gen5(
struct switchtec_dev *dev,
379 struct get_cfgs_reply_gen5 reply;
382 ret = get_configs_gen5(dev, &reply);
386 reply.valid0 = le32toh(reply.valid0);
387 reply.valid1 = le32toh(reply.valid1);
389 reply.cfg = le64toh(reply.cfg);
390 reply.public_key_exponent = le32toh(reply.public_key_exponent);
392 state->basic_setting_valid = !!(reply.valid0 & 0x01);
393 state->public_key_exp_valid = !!(reply.valid0 & 0x04);
394 state->public_key_num_valid = !!(reply.valid0 & 0x08);
395 state->public_key_ver_valid = !!(reply.valid0 & 0x10);
396 state->public_key_valid = !!(reply.valid0 & 0x20);
398 state->debug_mode_valid = !!(reply.valid0 & 0x02);
399 state->attn_state.cdi_efuse_inc_mask_valid = !!(reply.valid0 & 0x40);
401 state->otp_valid =
true;
402 parse_otp_settings_gen5(&state->otp_ext, reply.valid0,
405 state->use_otp_ext =
true;
407 state->debug_mode = reply.cfg & 0x03;
408 state->secure_state = (reply.cfg>>2) & 0x03;
410 state->jtag_lock_after_reset = !!(reply.cfg & 0x40);
411 state->jtag_lock_after_bl1 = !!(reply.cfg & 0x80);
412 state->jtag_bl1_unlock_allowed = !!(reply.cfg & 0x0100);
413 state->jtag_post_bl1_unlock_allowed = !!(reply.cfg & 0x0200);
415 spi_clk = (reply.cfg >> SWITCHTEC_CLK_RATE_BITSHIFT) & 0x0f;
423 if (reply.spi_core_clk_high)
424 state->spi_clk_rate = spi_clk_hi_rate_float[spi_clk - 1];
426 state->spi_clk_rate = spi_clk_rate_float[spi_clk - 1];
428 state->i2c_recovery_tmo =
429 (reply.cfg >> SWITCHTEC_RC_TMO_BITSHIFT) & 0x0f;
430 state->i2c_port = (reply.cfg >> SWITCHTEC_I2C_PORT_BITSHIFT) & 0xf;
432 get_i2c_operands(
switchtec_gen(dev), &addr_shift, &map_shift,
435 (reply.cfg >> addr_shift) & SWITCHTEC_I2C_ADDR_BITMASK;
436 state->i2c_cmd_map = (reply.cfg >> map_shift) & map_mask;
438 state->public_key_exponent = reply.public_key_exponent;
439 state->public_key_num = reply.public_key_num;
440 state->public_key_ver = reply.public_key_ver;
441 memcpy(state->public_key, reply.public_key,
442 state->public_key_num * SWITCHTEC_KMSK_LEN);
444 attn_mode = (reply.cfg >> SWITCHTEC_ATTEST_BITSHIFT) &
445 SWITCHTEC_ATTEST_BITMASK;
447 state->attn_state.attestation_mode =
448 SWITCHTEC_ATTESTATION_MODE_DICE;
450 state->attn_state.attestation_mode =
451 SWITCHTEC_ATTESTATION_MODE_NONE;
453 state->attn_state.uds_selfgen =
454 (reply.cfg >> SWITCHTEC_UDS_SELFGEN_BITSHIFT) &
455 SWITCHTEC_UDS_SELFGEN_BITMASK;
456 state->attn_state.cdi_efuse_inc_mask =
457 le32toh(reply.cdi_efuse_inc_mask);
459 if (state->secure_state == SWITCHTEC_UNINITIALIZED_UNSECURED &&
460 state->attn_state.attestation_mode ==
461 SWITCHTEC_ATTESTATION_MODE_DICE &&
462 !state->attn_state.uds_selfgen)
463 state->attn_state.uds_visible =
true;
465 state->attn_state.uds_visible =
false;
467 if (state->attn_state.uds_visible)
468 memcpy(state->attn_state.uds_data, reply.uds_data, 32);
479int switchtec_security_config_get(
struct switchtec_dev *dev,
483 return security_config_get_gen5(dev, state);
485 return security_config_get(dev, state);
488static int mailbox_to_file(
struct switchtec_dev *dev,
int fd)
491 int num_to_read = htole32(SWITCHTEC_MB_MAX_ENTRIES);
493 uint8_t num_returned;
494 uint8_t num_remaining;
496 uint8_t data[SWITCHTEC_MB_MAX_ENTRIES *
497 SWITCHTEC_MB_LOG_LEN];
501 ret = switchtec_mfg_cmd(dev, MRPC_MAILBOX_GET, &num_to_read,
502 sizeof(
int), &reply,
sizeof(reply));
506 reply.num_remaining = le32toh(reply.num_remaining);
507 reply.num_returned = le32toh(reply.num_returned);
509 ret = write(fd, reply.data,
510 (reply.num_returned) * SWITCHTEC_MB_LOG_LEN);
513 }
while (reply.num_remaining > 0);
518static int mailbox_to_file_gen5(
struct switchtec_dev *dev,
int fd)
523 uint32_t num_to_read;
526 uint8_t num_returned;
527 uint8_t num_remaining;
529 uint8_t data[SWITCHTEC_MB_MAX_ENTRIES *
530 SWITCHTEC_MB_LOG_LEN];
534 read.num_to_read = htole32(SWITCHTEC_MB_MAX_ENTRIES);
537 ret = switchtec_mfg_cmd(dev, MRPC_MAILBOX_GET_GEN5,
539 &reply,
sizeof(reply));
543 reply.num_remaining = le32toh(reply.num_remaining);
544 reply.num_returned = le32toh(reply.num_returned);
546 ret = write(fd, reply.data,
547 (reply.num_returned) * SWITCHTEC_MB_LOG_LEN);
550 }
while (reply.num_remaining > 0);
561int switchtec_mailbox_to_file(
struct switchtec_dev *dev,
int fd)
564 return mailbox_to_file_gen5(dev, fd);
566 return mailbox_to_file(dev, fd);
569static int convert_spi_clk_rate(
float clk_float,
int hi_rate)
575 p = spi_clk_hi_rate_float;
577 p = spi_clk_rate_float;
579 for (i = 0; i < 10; i++)
580 if ((clk_float < p[i] + 0.1) && (clk_float > p[i] - 0.1))
586static int security_config_set_gen4(
struct switchtec_dev *dev,
590 struct setting_data {
592 uint32_t pub_key_exponent;
595 struct get_cfgs_reply reply;
604 if (setting->attn_set.attestation_mode !=
605 SWITCHTEC_ATTESTATION_MODE_NOT_SUPPORTED)
608 ret = get_configs(dev, &reply, &otp_valid);
612 memset(&sd, 0,
sizeof(sd));
614 sd.cfg |= setting->jtag_lock_after_reset?
615 SWITCHTEC_JTAG_LOCK_AFT_RST_BITMASK : 0;
616 sd.cfg |= setting->jtag_lock_after_bl1?
617 SWITCHTEC_JTAG_LOCK_AFT_BL1_BITMASK : 0;
618 sd.cfg |= setting->jtag_bl1_unlock_allowed?
619 SWITCHTEC_JTAG_UNLOCK_BL1_BITMASK : 0;
620 sd.cfg |= setting->jtag_post_bl1_unlock_allowed?
621 SWITCHTEC_JTAG_UNLOCK_AFT_BL1_BITMASK : 0;
623 spi_clk = convert_spi_clk_rate(setting->spi_clk_rate,
624 reply.spi_core_clk_high);
630 sd.cfg |= (spi_clk & SWITCHTEC_CLK_RATE_BITMASK) <<
631 SWITCHTEC_CLK_RATE_BITSHIFT;
633 sd.cfg |= (setting->i2c_recovery_tmo & SWITCHTEC_RC_TMO_BITMASK) <<
634 SWITCHTEC_RC_TMO_BITSHIFT;
635 sd.cfg |= (setting->i2c_port & SWITCHTEC_I2C_PORT_BITMASK) <<
636 SWITCHTEC_I2C_PORT_BITSHIFT;
638 get_i2c_operands(
switchtec_gen(dev), &addr_shift, &map_shift,
640 sd.cfg |= (setting->i2c_addr & SWITCHTEC_I2C_ADDR_BITMASK) <<
643 ldata = setting->i2c_cmd_map & map_mask;
647 sd.cfg = htole64(sd.cfg);
649 sd.pub_key_exponent = htole32(setting->public_key_exponent);
651 return switchtec_mfg_cmd(dev, MRPC_SECURITY_CONFIG_SET,
652 &sd,
sizeof(sd), NULL, 0);
655static int security_config_set_gen5(
struct switchtec_dev *dev,
659 struct setting_data {
661 uint32_t pub_key_exponent;
664 uint32_t cdi_efuse_inc_mask;
667 struct get_cfgs_reply_gen5 reply;
673 uint8_t cmd_buf[64]={};
675 ret = get_configs_gen5(dev, &reply);
679 memset(&sd, 0,
sizeof(sd));
681 sd.cfg = setting->jtag_lock_after_reset?
682 SWITCHTEC_JTAG_LOCK_AFT_RST_BITMASK : 0;
683 sd.cfg |= setting->jtag_lock_after_bl1?
684 SWITCHTEC_JTAG_LOCK_AFT_BL1_BITMASK : 0;
685 sd.cfg |= setting->jtag_bl1_unlock_allowed?
686 SWITCHTEC_JTAG_UNLOCK_BL1_BITMASK : 0;
687 sd.cfg |= setting->jtag_post_bl1_unlock_allowed?
688 SWITCHTEC_JTAG_UNLOCK_AFT_BL1_BITMASK : 0;
690 spi_clk = convert_spi_clk_rate(setting->spi_clk_rate,
691 reply.spi_core_clk_high);
697 sd.cfg |= (spi_clk & SWITCHTEC_CLK_RATE_BITMASK) <<
698 SWITCHTEC_CLK_RATE_BITSHIFT;
700 sd.cfg |= (setting->i2c_recovery_tmo & SWITCHTEC_RC_TMO_BITMASK) <<
701 SWITCHTEC_RC_TMO_BITSHIFT;
702 sd.cfg |= (setting->i2c_port & SWITCHTEC_I2C_PORT_BITMASK) <<
703 SWITCHTEC_I2C_PORT_BITSHIFT;
705 get_i2c_operands(
switchtec_gen(dev), &addr_shift, &map_shift,
707 sd.cfg |= (setting->i2c_addr & SWITCHTEC_I2C_ADDR_BITMASK) <<
710 ldata = setting->i2c_cmd_map & map_mask;
714 sd.cfg = htole64(sd.cfg);
716 sd.pub_key_exponent = htole32(setting->public_key_exponent);
718 if (setting->attn_set.attestation_mode ==
719 SWITCHTEC_ATTESTATION_MODE_DICE) {
721 sd.cdi_efuse_inc_mask = setting->attn_set.cdi_efuse_inc_mask;
723 ldata = setting->attn_set.uds_selfgen? 1 : 0;
727 sd.uds_valid = setting->attn_set.uds_valid;
729 memcpy(sd.uds, setting->attn_set.uds_data, 32);
732 memcpy(cmd_buf + 4, &sd,
sizeof(sd));
733 return switchtec_mfg_cmd(dev, MRPC_SECURITY_CONFIG_SET_GEN5,
734 cmd_buf,
sizeof(cmd_buf), NULL, 0);
743int switchtec_security_config_set(
struct switchtec_dev *dev,
747 return security_config_set_gen5(dev, setting);
749 return security_config_set_gen4(dev, setting);
752static int active_image_index_get(
struct switchtec_dev *dev,
756 struct active_indices {
757 uint8_t index[SWITCHTEC_ACTV_IDX_MAX_ENTRIES];
760 ret = switchtec_mfg_cmd(dev, MRPC_ACT_IMG_IDX_GET, NULL,
761 0, &reply,
sizeof(reply));
765 index->keyman = reply.index[SWITCHTEC_ACTV_IMG_ID_KMAN];
766 index->bl2 = reply.index[SWITCHTEC_ACTV_IMG_ID_BL2];
767 index->config = reply.index[SWITCHTEC_ACTV_IMG_ID_CFG];
768 index->firmware = reply.index[SWITCHTEC_ACTV_IMG_ID_FW];
769 index->riot = SWITCHTEC_ACTIVE_INDEX_NOT_SET;
774static int active_image_index_get_gen5(
struct switchtec_dev *dev,
779 struct active_indices {
780 uint8_t index[SWITCHTEC_ACTV_IDX_MAX_ENTRIES];
783 ret = switchtec_mfg_cmd(dev, MRPC_ACT_IMG_IDX_GET_GEN5, &subcmd,
784 sizeof(subcmd), &reply,
sizeof(reply));
788 index->keyman = reply.index[SWITCHTEC_ACTV_IMG_ID_KMAN_GEN5];
789 index->bl2 = reply.index[SWITCHTEC_ACTV_IMG_ID_BL2_GEN5];
790 index->config = reply.index[SWITCHTEC_ACTV_IMG_ID_CFG_GEN5];
791 index->firmware = reply.index[SWITCHTEC_ACTV_IMG_ID_FW_GEN5];
792 index->riot = reply.index[SWITCHTEC_ACTV_IMG_ID_RC_GEN5];
803int switchtec_active_image_index_get(
struct switchtec_dev *dev,
807 return active_image_index_get_gen5(dev, index);
809 return active_image_index_get(dev, index);
812static int active_image_index_set(
struct switchtec_dev *dev,
822 } idx[SWITCHTEC_ACTV_IDX_SET_ENTRIES];
826 if (index->riot != SWITCHTEC_ACTIVE_INDEX_NOT_SET) {
831 memset(&set, 0,
sizeof(set));
833 if (index->keyman != SWITCHTEC_ACTIVE_INDEX_NOT_SET) {
834 set.idx[i].image_id = SWITCHTEC_ACTV_IMG_ID_KMAN;
835 set.idx[i].index = index->keyman;
839 if (index->bl2 != SWITCHTEC_ACTIVE_INDEX_NOT_SET) {
840 set.idx[i].image_id = SWITCHTEC_ACTV_IMG_ID_BL2;
841 set.idx[i].index = index->bl2;
845 if (index->config != SWITCHTEC_ACTIVE_INDEX_NOT_SET) {
846 set.idx[i].image_id = SWITCHTEC_ACTV_IMG_ID_CFG;
847 set.idx[i].index = index->config;
851 if (index->firmware != SWITCHTEC_ACTIVE_INDEX_NOT_SET) {
852 set.idx[i].image_id = SWITCHTEC_ACTV_IMG_ID_FW;
853 set.idx[i].index = index->firmware;
860 set.count = htole32(i);
862 ret = switchtec_mfg_cmd(dev, MRPC_ACT_IMG_IDX_SET, &set,
863 sizeof(set), NULL, 0);
867static int active_image_index_set_gen5(
struct switchtec_dev *dev,
878 } idx[SWITCHTEC_ACTV_IDX_SET_ENTRIES];
881 if (index->keyman != SWITCHTEC_ACTIVE_INDEX_NOT_SET) {
882 set.idx[i].image_id = SWITCHTEC_ACTV_IMG_ID_KMAN_GEN5;
883 set.idx[i].index = index->keyman;
887 if (index->riot != SWITCHTEC_ACTIVE_INDEX_NOT_SET) {
888 set.idx[i].image_id = SWITCHTEC_ACTV_IMG_ID_RC_GEN5;
889 set.idx[i].index = index->riot;
893 if (index->bl2 != SWITCHTEC_ACTIVE_INDEX_NOT_SET) {
894 set.idx[i].image_id = SWITCHTEC_ACTV_IMG_ID_BL2_GEN5;
895 set.idx[i].index = index->bl2;
899 if (index->config != SWITCHTEC_ACTIVE_INDEX_NOT_SET) {
900 set.idx[i].image_id = SWITCHTEC_ACTV_IMG_ID_CFG_GEN5;
901 set.idx[i].index = index->config;
905 if (index->firmware != SWITCHTEC_ACTIVE_INDEX_NOT_SET) {
906 set.idx[i].image_id = SWITCHTEC_ACTV_IMG_ID_FW_GEN5;
907 set.idx[i].index = index->firmware;
914 set.count = htole32(i);
916 ret = switchtec_mfg_cmd(dev, MRPC_ACT_IMG_IDX_SET_GEN5, &set,
917 sizeof(set), NULL, 0);
927int switchtec_active_image_index_set(
struct switchtec_dev *dev,
931 return active_image_index_set_gen5(dev, index);
933 return active_image_index_set(dev, index);
942int switchtec_fw_exec(
struct switchtec_dev *dev,
943 enum switchtec_bl2_recovery_mode recovery_mode)
945 uint32_t cmd_id = MRPC_FW_TX;
946 struct fw_exec_struct {
948 uint8_t recovery_mode;
952 memset(&cmd, 0,
sizeof(cmd));
953 cmd.subcmd = MRPC_FW_TX_EXEC;
954 cmd.recovery_mode = recovery_mode;
957 cmd_id = MRPC_FW_TX_GEN5;
959 return switchtec_mfg_cmd(dev, cmd_id, &cmd,
sizeof(cmd), NULL, 0);
974int switchtec_boot_resume(
struct switchtec_dev *dev)
979 return switchtec_mfg_cmd(dev, MRPC_BOOTUP_RESUME_GEN5,
980 &subcmd,
sizeof(subcmd),
983 return switchtec_mfg_cmd(dev, MRPC_BOOTUP_RESUME,
987static int secure_state_set(
struct switchtec_dev *dev,
988 enum switchtec_secure_state state)
992 data = htole32(state);
994 return switchtec_mfg_cmd(dev, MRPC_SECURE_STATE_SET,
995 &data,
sizeof(data), NULL, 0);
998static int secure_state_set_gen5(
struct switchtec_dev *dev,
999 enum switchtec_secure_state state)
1007 data.state = htole32(state);
1009 return switchtec_mfg_cmd(dev, MRPC_SECURE_STATE_SET_GEN5,
1010 &data,
sizeof(data), NULL, 0);
1019int switchtec_secure_state_set(
struct switchtec_dev *dev,
1020 enum switchtec_secure_state state)
1022 if ((state != SWITCHTEC_INITIALIZED_UNSECURED)
1023 && (state != SWITCHTEC_INITIALIZED_SECURED)) {
1024 return ERR_PARAM_INVALID;
1028 return secure_state_set_gen5(dev, state);
1030 return secure_state_set(dev, state);
1033static int dbg_unlock_send_pubkey(
struct switchtec_dev *dev,
1037 struct public_key_cmd {
1040 uint8_t pub_key[SWITCHTEC_PUB_KEY_LEN];
1041 uint32_t pub_key_exp;
1044 cmd.subcmd = MRPC_DBG_UNLOCK_PKEY;
1045 memcpy(cmd.pub_key, public_key->pubkey, SWITCHTEC_PUB_KEY_LEN);
1046 cmd.pub_key_exp = htole32(public_key->pubkey_exp);
1048 return switchtec_mfg_cmd(dev, cmd_id, &cmd,
sizeof(cmd), NULL, 0);
1060int switchtec_dbg_unlock(
struct switchtec_dev *dev, uint32_t serial,
1061 uint32_t ver_sec_unlock,
1070 uint32_t unlock_ver;
1071 uint8_t signature[SWITCHTEC_SIG_LEN];
1076 cmd_id = MRPC_DBG_UNLOCK_GEN5;
1078 cmd_id = MRPC_DBG_UNLOCK;
1080 ret = dbg_unlock_send_pubkey(dev, public_key, cmd_id);
1084 cmd.subcmd = MRPC_DBG_UNLOCK_DATA;
1085 cmd.serial = htole32(serial);
1086 cmd.unlock_ver = htole32(ver_sec_unlock);
1087 memcpy(cmd.signature, signature->signature, SWITCHTEC_SIG_LEN);
1089 return switchtec_mfg_cmd(dev, cmd_id, &cmd,
sizeof(cmd), NULL, 0);
1101int switchtec_dbg_unlock_version_update(
struct switchtec_dev *dev,
1103 uint32_t ver_sec_unlock,
1112 uint32_t unlock_ver;
1113 uint8_t signature[SWITCHTEC_SIG_LEN];
1118 cmd_id = MRPC_DBG_UNLOCK_GEN5;
1120 cmd_id = MRPC_DBG_UNLOCK;
1122 ret = dbg_unlock_send_pubkey(dev, public_key, cmd_id);
1126 cmd.subcmd = MRPC_DBG_UNLOCK_UPDATE;
1127 cmd.serial = htole32(serial);
1128 cmd.unlock_ver = htole32(ver_sec_unlock);
1129 memcpy(cmd.signature, signature->signature, SWITCHTEC_SIG_LEN);
1131 return switchtec_mfg_cmd(dev, cmd_id, &cmd,
sizeof(cmd), NULL, 0);
1134static int check_sec_cfg_header(
struct switchtec_dev *dev,
1139 char magic[4] = {
'S',
'S',
'F',
'F'};
1141 struct setting_file_header {
1151 rlen = fread(&hdr,
sizeof(hdr), 1, setting_file);
1156 if (memcmp(hdr.magic, magic,
sizeof(magic)))
1159 switch (hdr.hw_gen) {
1161 gen = SWITCHTEC_GEN4;
1164 gen = SWITCHTEC_GEN5;
1173 fseek(setting_file, 0, SEEK_END);
1174 data_len = ftell(setting_file) -
sizeof(hdr);
1175 fseek(setting_file,
sizeof(hdr), SEEK_SET);
1177 rlen = fread(data, 1, data_len, setting_file);
1178 if (rlen < data_len)
1181 crc = crc32(data, data_len, 0, 1, 1);
1182 if (crc != le32toh(hdr.crc))
1185 fseek(setting_file,
sizeof(hdr), SEEK_SET);
1189static int read_sec_cfg_file(
struct switchtec_dev *dev,
1193 struct setting_file_data {
1195 uint32_t pub_key_exponent;
1198 struct get_cfgs_reply reply;
1199 uint32_t addr_shift;
1206 ret = get_configs(dev, &reply, &otp_valid);
1212 ret = fread(&data,
sizeof(data), 1, setting_file);
1217 data.cfg = le64toh(data.cfg);
1219 set->jtag_lock_after_reset =
1220 !!(data.cfg & SWITCHTEC_JTAG_LOCK_AFT_RST_BITMASK);
1221 set->jtag_lock_after_bl1 =
1222 !!(data.cfg & SWITCHTEC_JTAG_LOCK_AFT_BL1_BITMASK);
1223 set->jtag_bl1_unlock_allowed =
1224 !!(data.cfg & SWITCHTEC_JTAG_UNLOCK_BL1_BITMASK);
1225 set->jtag_post_bl1_unlock_allowed =
1226 !!(data.cfg & SWITCHTEC_JTAG_UNLOCK_AFT_BL1_BITMASK);
1228 spi_clk = (data.cfg >> SWITCHTEC_CLK_RATE_BITSHIFT) &
1229 SWITCHTEC_CLK_RATE_BITMASK;
1237 if (reply.spi_core_clk_high)
1238 set->spi_clk_rate = spi_clk_hi_rate_float[spi_clk - 1];
1240 set->spi_clk_rate = spi_clk_rate_float[spi_clk - 1];
1242 set->i2c_recovery_tmo =
1243 (data.cfg >> SWITCHTEC_RC_TMO_BITSHIFT) &
1244 SWITCHTEC_RC_TMO_BITMASK;
1246 (data.cfg >> SWITCHTEC_I2C_PORT_BITSHIFT) &
1247 SWITCHTEC_I2C_PORT_BITMASK;
1249 get_i2c_operands(
switchtec_gen(dev), &addr_shift, &map_shift,
1252 (data.cfg >> addr_shift) &
1253 SWITCHTEC_I2C_ADDR_BITMASK;
1254 set->i2c_cmd_map = (data.cfg >> map_shift) & map_mask;
1256 set->public_key_exponent = le32toh(data.pub_key_exponent);
1258 set->attn_set.attestation_mode =
1259 SWITCHTEC_ATTESTATION_MODE_NOT_SUPPORTED;
1264static int read_sec_cfg_file_gen5(
struct switchtec_dev *dev,
1268 struct setting_data {
1270 uint32_t pub_key_exponent;
1272 uint32_t cdi_efuse_inc_mask;
1274 struct get_cfgs_reply_gen5 reply;
1275 uint32_t addr_shift;
1282 ret = get_configs_gen5(dev, &reply);
1288 ret = fread(&data,
sizeof(data), 1, setting_file);
1293 data.cfg = le64toh(data.cfg);
1295 set->jtag_lock_after_reset =
1296 !!(data.cfg & SWITCHTEC_JTAG_LOCK_AFT_RST_BITMASK);
1297 set->jtag_lock_after_bl1 =
1298 !!(data.cfg & SWITCHTEC_JTAG_LOCK_AFT_BL1_BITMASK);
1299 set->jtag_bl1_unlock_allowed =
1300 !!(data.cfg & SWITCHTEC_JTAG_UNLOCK_BL1_BITMASK);
1301 set->jtag_post_bl1_unlock_allowed =
1302 !!(data.cfg & SWITCHTEC_JTAG_UNLOCK_AFT_BL1_BITMASK);
1304 spi_clk = (data.cfg >> SWITCHTEC_CLK_RATE_BITSHIFT) &
1305 SWITCHTEC_CLK_RATE_BITMASK;
1313 if (reply.spi_core_clk_high)
1314 set->spi_clk_rate = spi_clk_hi_rate_float[spi_clk - 1];
1316 set->spi_clk_rate = spi_clk_rate_float[spi_clk - 1];
1318 set->i2c_recovery_tmo =
1319 (data.cfg >> SWITCHTEC_RC_TMO_BITSHIFT) &
1320 SWITCHTEC_RC_TMO_BITMASK;
1322 (data.cfg >> SWITCHTEC_I2C_PORT_BITSHIFT) &
1323 SWITCHTEC_I2C_PORT_BITMASK;
1325 get_i2c_operands(
switchtec_gen(dev), &addr_shift, &map_shift,
1328 (data.cfg >> addr_shift) &
1329 SWITCHTEC_I2C_ADDR_BITMASK;
1330 set->i2c_cmd_map = (data.cfg >> map_shift) & map_mask;
1332 set->public_key_exponent = le32toh(data.pub_key_exponent);
1334 attest_mode = (data.cfg >> SWITCHTEC_ATTEST_BITSHIFT) &
1335 SWITCHTEC_ATTEST_BITMASK;
1336 if (attest_mode == 1) {
1337 set->attn_set.attestation_mode =
1338 SWITCHTEC_ATTESTATION_MODE_DICE;
1339 set->attn_set.cdi_efuse_inc_mask = data.cdi_efuse_inc_mask;
1340 set->attn_set.uds_selfgen = (data.cfg >> 44) & 0x1;
1342 set->attn_set.attestation_mode =
1343 SWITCHTEC_ATTESTATION_MODE_NONE;
1356int switchtec_read_sec_cfg_file(
struct switchtec_dev *dev,
1362 ret = check_sec_cfg_header(dev, setting_file);
1367 return read_sec_cfg_file(dev, setting_file, set);
1369 return read_sec_cfg_file_gen5(dev, setting_file, set);
1372static int kmsk_set_send_pubkey(
struct switchtec_dev *dev,
1376 struct kmsk_pubk_cmd {
1378 uint8_t reserved[3];
1379 uint8_t pub_key[SWITCHTEC_PUB_KEY_LEN];
1380 uint32_t pub_key_exponent;
1383 cmd.subcmd = MRPC_KMSK_ENTRY_SET_PKEY;
1384 memcpy(cmd.pub_key, public_key->pubkey,
1385 SWITCHTEC_PUB_KEY_LEN);
1386 cmd.pub_key_exponent = htole32(public_key->pubkey_exp);
1388 return switchtec_mfg_cmd(dev, cmd_id, &cmd,
1389 sizeof(cmd), NULL, 0);
1392static int kmsk_set_send_signature(
struct switchtec_dev *dev,
1396 struct kmsk_signature_cmd {
1398 uint8_t reserved[3];
1399 uint8_t signature[SWITCHTEC_SIG_LEN];
1402 cmd.subcmd = MRPC_KMSK_ENTRY_SET_SIG;
1403 memcpy(cmd.signature, signature->signature,
1406 return switchtec_mfg_cmd(dev, cmd_id, &cmd,
1407 sizeof(cmd), NULL, 0);
1410static int kmsk_set_send_kmsk(
struct switchtec_dev *dev,
1414 struct kmsk_kmsk_cmd {
1416 uint8_t num_entries;
1417 uint8_t reserved[2];
1418 uint8_t kmsk[SWITCHTEC_KMSK_LEN];
1421 cmd.subcmd = MRPC_KMSK_ENTRY_SET_KMSK;
1422 cmd.num_entries = 1;
1423 memcpy(cmd.kmsk, kmsk->kmsk, SWITCHTEC_KMSK_LEN);
1425 return switchtec_mfg_cmd(dev, cmd_id, &cmd,
sizeof(cmd),
1441int switchtec_kmsk_set(
struct switchtec_dev *dev,
1450 cmd_id = MRPC_KMSK_ENTRY_SET_GEN5;
1452 cmd_id = MRPC_KMSK_ENTRY_SET;
1455 ret = kmsk_set_send_pubkey(dev, public_key, cmd_id);
1461 ret = kmsk_set_send_signature(dev, signature, cmd_id);
1466 return kmsk_set_send_kmsk(dev, kmsk, cmd_id);
1471#ifdef HAVE_DECL_PEM_READ_PUBKEY
1473#include <openssl/core_names.h>
1481int switchtec_read_pubk_file(FILE *pubk_file,
struct switchtec_pubkey *pubk)
1483 BIGNUM *bn_priv = NULL;
1484 uint32_t exponent_tmp;
1487 pkey = PEM_read_PUBKEY(pubk_file, NULL, NULL, NULL);
1489 fseek(pubk_file, 0L, SEEK_SET);
1490 pkey = PEM_read_PrivateKey(pubk_file, NULL, NULL, NULL);
1495 EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_RSA_N, &bn_priv);
1496 BN_bn2bin(bn_priv, pubk->pubkey);
1497 EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_RSA_E, &bn_priv);
1498 BN_bn2bin(bn_priv, (uint8_t *)&exponent_tmp);
1499 pubk->pubkey_exp = be32toh(exponent_tmp);
1501 EVP_PKEY_free(pkey);
1507#if !HAVE_DECL_RSA_GET0_KEY
1512static void RSA_get0_key(
const RSA *r,
const BIGNUM **n,
1513 const BIGNUM **e,
const BIGNUM **d)
1530int switchtec_read_pubk_file(FILE *pubk_file,
struct switchtec_pubkey *pubk)
1533 const BIGNUM *modulus_bn;
1534 const BIGNUM *exponent_bn;
1535 uint32_t exponent_tmp = 0;
1537 RSAKey = PEM_read_RSA_PUBKEY(pubk_file, NULL, NULL, NULL);
1538 if (RSAKey == NULL) {
1539 fseek(pubk_file, 0L, SEEK_SET);
1540 RSAKey = PEM_read_RSAPrivateKey(pubk_file, NULL, NULL, NULL);
1545 RSA_get0_key(RSAKey, &modulus_bn, &exponent_bn, NULL);
1547 BN_bn2bin(modulus_bn, pubk->pubkey);
1548 BN_bn2bin(exponent_bn, (uint8_t *)&exponent_tmp);
1550 pubk->pubkey_exp = be32toh(exponent_tmp);
1566int switchtec_read_kmsk_file(FILE *kmsk_file,
struct switchtec_kmsk *kmsk)
1569 struct kmsk_struct {
1574 uint8_t kmsk[SWITCHTEC_KMSK_LEN];
1577 char magic[4] = {
'K',
'M',
'S',
'K'};
1580 rlen = fread(&data, 1,
sizeof(data), kmsk_file);
1582 if (rlen <
sizeof(data))
1585 if (memcmp(data.magic, magic,
sizeof(magic)))
1588 crc = crc32(data.kmsk, SWITCHTEC_KMSK_LEN, 0, 1, 1);
1589 if (crc != le32toh(data.crc32))
1592 memcpy(kmsk->kmsk, data.kmsk, SWITCHTEC_KMSK_LEN);
1603int switchtec_read_signature_file(FILE *sig_file,
1608 rlen = fread(signature->signature, 1, SWITCHTEC_SIG_LEN, sig_file);
1610 if (rlen < SWITCHTEC_SIG_LEN)
1622int switchtec_read_uds_file(FILE *uds_file,
struct switchtec_uds *uds)
1626 rlen = fread(uds->uds, 1, SWITCHTEC_UDS_LEN, uds_file);
1628 if (rlen < SWITCHTEC_UDS_LEN)
1650 for(key_idx = 0; key_idx < state->public_key_num; key_idx++) {
1651 if (memcmp(state->public_key[key_idx], kmsk->kmsk,
1652 SWITCHTEC_KMSK_LEN) == 0)
1661static int switchtec_mfg_cmd(
struct switchtec_dev *dev, uint32_t cmd,
1662 const void *payload,
size_t payload_len,
1663 void *resp,
size_t resp_len)
1665 if (dev->ops->flags & SWITCHTEC_OPS_FLAG_NO_MFG) {
1666 errno = ERR_UART_NOT_SUPPORTED | SWITCHTEC_ERRNO_MRPC_FLAG_BIT;
1674static int sn_ver_get_gen4(
struct switchtec_dev *dev,
1679 uint32_t chip_serial;
1683 uint32_t ver_sec_unlock;
1686 ret = switchtec_mfg_cmd(dev, MRPC_SN_VER_GET, NULL, 0,
1687 &reply,
sizeof(reply));
1691 info->chip_serial = reply.chip_serial;
1692 info->ver_bl2 = reply.ver_bl2;
1693 info->ver_km = reply.ver_km;
1694 info->riot_ver_valid =
false;
1695 info->ver_sec_unlock = reply.ver_sec_unlock;
1696 info->ver_main = reply.ver_main;
1701static int sn_ver_get_gen5(
struct switchtec_dev *dev,
1705 uint32_t subcmd = 0;
1707 uint32_t chip_serial;
1712 uint32_t ver_sec_unlock;
1715 ret = switchtec_mfg_cmd(dev, MRPC_SN_VER_GET_GEN5, &subcmd, 4,
1716 &reply,
sizeof(reply));
1720 info->chip_serial = reply.chip_serial;
1721 info->ver_bl2 = reply.ver_bl2;
1722 info->ver_km = reply.ver_km;
1723 info->riot_ver_valid =
true;
1724 info->ver_riot = reply.ver_riot;
1725 info->ver_sec_unlock = reply.ver_sec_unlock;
1726 info->ver_main = reply.ver_main;
1741 return sn_ver_get_gen5(dev, info);
1743 return sn_ver_get_gen4(dev, info);
int switchtec_cmd(struct switchtec_dev *dev, uint32_t cmd, const void *payload, size_t payload_len, void *resp, size_t resp_len)
Execute an MRPC command.
int switchtec_sn_ver_get(struct switchtec_dev *dev, struct switchtec_sn_ver_info *info)
Get serial number and security version.
switchtec_gen
The PCIe generations.
static int switchtec_is_gen4(struct switchtec_dev *dev)
Return whether a Switchtec device is a Gen 4 device.
static int switchtec_is_gen5(struct switchtec_dev *dev)
Return whether a Switchtec device is a Gen 5 device.