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_MB_MAX_ENTRIES 16
74 #define SWITCHTEC_ACTV_IDX_MAX_ENTRIES 32
75 #define SWITCHTEC_ACTV_IDX_SET_ENTRIES 4
77 #define SWITCHTEC_CLK_RATE_BITSHIFT 10
78 #define SWITCHTEC_CLK_RATE_BITMASK 0x0f
79 #define SWITCHTEC_RC_TMO_BITSHIFT 14
80 #define SWITCHTEC_RC_TMO_BITMASK 0x0f
81 #define SWITCHTEC_I2C_PORT_BITSHIFT 18
82 #define SWITCHTEC_I2C_PORT_BITMASK 0x0f
83 #define SWITCHTEC_I2C_ADDR_BITSHIFT 22
84 #define SWITCHTEC_I2C_ADDR_BITSHIFT_GEN5 23
85 #define SWITCHTEC_I2C_ADDR_BITMASK 0x7f
86 #define SWITCHTEC_CMD_MAP_BITSHIFT 29
87 #define SWITCHTEC_CMD_MAP_BITSHIFT_GEN5 30
88 #define SWITCHTEC_CMD_MAP_BITMASK 0xfff
89 #define SWITCHTEC_CMD_MAP_BITMASK_GEN5 0x3fff
91 #define SWITCHTEC_JTAG_LOCK_AFT_RST_BITMASK 0x40
92 #define SWITCHTEC_JTAG_LOCK_AFT_BL1_BITMASK 0x80
93 #define SWITCHTEC_JTAG_UNLOCK_BL1_BITMASK 0x0100
94 #define SWITCHTEC_JTAG_UNLOCK_AFT_BL1_BITMASK 0x0200
96 static int switchtec_mfg_cmd(
struct switchtec_dev *dev, uint32_t cmd,
97 const void *payload,
size_t payload_len,
98 void *resp,
size_t resp_len);
100 #if (HAVE_LIBCRYPTO && !HAVE_DECL_RSA_GET0_KEY)
105 static void RSA_get0_key(
const RSA *r,
const BIGNUM **n,
106 const BIGNUM **e,
const BIGNUM **d)
117 static void get_i2c_operands(
enum switchtec_gen gen, uint32_t *addr_shift,
118 uint32_t *map_shift, uint32_t *map_mask)
120 if (gen > SWITCHTEC_GEN4) {
121 *addr_shift = SWITCHTEC_I2C_ADDR_BITSHIFT_GEN5;
122 *map_shift = SWITCHTEC_CMD_MAP_BITSHIFT_GEN5;
123 *map_mask = SWITCHTEC_CMD_MAP_BITMASK_GEN5;
125 *addr_shift = SWITCHTEC_I2C_ADDR_BITSHIFT;
126 *map_shift = SWITCHTEC_CMD_MAP_BITSHIFT;
127 *map_mask = SWITCHTEC_CMD_MAP_BITMASK;
131 static float spi_clk_rate_float[] = {
132 100, 67, 50, 40, 33.33, 28.57, 25, 22.22, 20, 18.18
135 static float spi_clk_hi_rate_float[] = {
136 120, 80, 60, 48, 40, 34, 30, 26.67, 24, 21.82
139 struct get_cfgs_reply {
143 uint32_t public_key_exponent;
145 uint8_t public_key_num;
146 uint8_t public_key_ver;
147 uint8_t spi_core_clk_high;
148 uint8_t public_key[SWITCHTEC_KMSK_NUM][SWITCHTEC_KMSK_LEN];
152 static int get_configs(
struct switchtec_dev *dev,
153 struct get_cfgs_reply *cfgs,
161 ret = switchtec_mfg_cmd(dev,
162 MRPC_SECURITY_CONFIG_GET_GEN5,
163 &subcmd,
sizeof(subcmd),
164 cfgs,
sizeof(
struct get_cfgs_reply));
168 ret = switchtec_mfg_cmd(dev, MRPC_SECURITY_CONFIG_GET_EXT,
169 &subcmd,
sizeof(subcmd),
170 cfgs,
sizeof(
struct get_cfgs_reply));
171 if (ret && ERRNO_MRPC(errno) != ERR_CMD_INVALID)
180 ret = switchtec_mfg_cmd(dev, MRPC_SECURITY_CONFIG_GET,
182 sizeof(
struct get_cfgs_reply));
188 int switchtec_security_spi_avail_rate_get(
struct switchtec_dev *dev,
192 struct get_cfgs_reply reply;
195 ret = get_configs(dev, &reply, &otp_valid);
199 rates->num_rates = 10;
200 if (reply.spi_core_clk_high)
201 memcpy(rates->rates, spi_clk_hi_rate_float,
202 sizeof(spi_clk_hi_rate_float));
204 memcpy(rates->rates, spi_clk_rate_float,
205 sizeof(spi_clk_rate_float));
213 otp->basic_valid = !!(flags & BIT(5));
214 otp->basic = !!(flags & BIT(6));
215 otp->mixed_ver_valid = !!(flags & BIT(7));
216 otp->mixed_ver = !!(flags & BIT(8));
217 otp->main_fw_ver_valid = !!(flags & BIT(9));
218 otp->main_fw_ver = !!(flags & BIT(10));
219 otp->sec_unlock_ver_valid = !!(flags & BIT(11));
220 otp->sec_unlock_ver = !!(flags & BIT(12));
221 otp->kmsk_valid[0] = !!(flags & BIT(13));
222 otp->kmsk[0] = !!(flags & BIT(14));
223 otp->kmsk_valid[1] = !!(flags & BIT(15));
224 otp->kmsk[1] = !!(flags & BIT(16));
225 otp->kmsk_valid[2] = !!(flags & BIT(17));
226 otp->kmsk[2] = !!(flags & BIT(18));
227 otp->kmsk_valid[3] = !!(flags & BIT(19));
228 otp->kmsk[3] = !!(flags & BIT(20));
237 int switchtec_security_config_get(
struct switchtec_dev *dev,
245 struct get_cfgs_reply reply;
248 ret = get_configs(dev, &reply, &otp_valid);
252 reply.valid = le32toh(reply.valid);
253 reply.cfg = le64toh(reply.cfg);
254 reply.public_key_exponent = le32toh(reply.public_key_exponent);
256 state->basic_setting_valid = !!(reply.valid & 0x01);
257 state->public_key_exp_valid = !!(reply.valid & 0x02);
258 state->public_key_num_valid = !!(reply.valid & 0x04);
259 state->public_key_ver_valid = !!(reply.valid & 0x08);
260 state->public_key_valid = !!(reply.valid & 0x10);
262 state->otp_valid = otp_valid;
264 parse_otp_settings(&state->otp, reply.valid);
266 state->debug_mode = reply.cfg & 0x03;
267 state->secure_state = (reply.cfg>>2) & 0x03;
269 state->jtag_lock_after_reset = !!(reply.cfg & 0x40);
270 state->jtag_lock_after_bl1 = !!(reply.cfg & 0x80);
271 state->jtag_bl1_unlock_allowed = !!(reply.cfg & 0x0100);
272 state->jtag_post_bl1_unlock_allowed = !!(reply.cfg & 0x0200);
274 spi_clk = (reply.cfg >> SWITCHTEC_CLK_RATE_BITSHIFT) & 0x0f;
282 if (reply.spi_core_clk_high)
283 state->spi_clk_rate = spi_clk_hi_rate_float[spi_clk - 1];
285 state->spi_clk_rate = spi_clk_rate_float[spi_clk - 1];
287 state->i2c_recovery_tmo =
288 (reply.cfg >> SWITCHTEC_RC_TMO_BITSHIFT) & 0x0f;
289 state->i2c_port = (reply.cfg >> SWITCHTEC_I2C_PORT_BITSHIFT) & 0xf;
291 get_i2c_operands(
switchtec_gen(dev), &addr_shift, &map_shift,
294 (reply.cfg >> addr_shift) & SWITCHTEC_I2C_ADDR_BITMASK;
295 state->i2c_cmd_map = (reply.cfg >> map_shift) & map_mask;
297 state->public_key_exponent = reply.public_key_exponent;
298 state->public_key_num = reply.public_key_num;
299 state->public_key_ver = reply.public_key_ver;
300 memcpy(state->public_key, reply.public_key,
301 SWITCHTEC_KMSK_NUM * SWITCHTEC_KMSK_LEN);
312 int switchtec_mailbox_to_file(
struct switchtec_dev *dev,
int fd)
315 int num_to_read = htole32(SWITCHTEC_MB_MAX_ENTRIES);
317 uint8_t num_returned;
318 uint8_t num_remaining;
320 uint8_t data[SWITCHTEC_MB_MAX_ENTRIES *
321 SWITCHTEC_MB_LOG_LEN];
325 ret = switchtec_mfg_cmd(dev, MRPC_MAILBOX_GET, &num_to_read,
326 sizeof(
int), &reply,
sizeof(reply));
330 reply.num_remaining = le32toh(reply.num_remaining);
331 reply.num_returned = le32toh(reply.num_returned);
333 ret = write(fd, reply.data,
334 (reply.num_returned) * SWITCHTEC_MB_LOG_LEN);
337 }
while (reply.num_remaining > 0);
342 static int convert_spi_clk_rate(
float clk_float,
int hi_rate)
348 p = spi_clk_hi_rate_float;
350 p = spi_clk_rate_float;
352 for (i = 0; i < 10; i++)
353 if ((clk_float < p[i] + 0.1) && (clk_float > p[i] - 0.1))
365 int switchtec_security_config_set(
struct switchtec_dev *dev,
369 struct setting_data {
371 uint32_t pub_key_exponent;
374 struct get_cfgs_reply reply;
380 uint8_t cmd_buf[20] = {};
383 ret = get_configs(dev, &reply, &otp_valid);
387 memset(&sd, 0,
sizeof(sd));
389 sd.cfg |= setting->jtag_lock_after_reset?
390 SWITCHTEC_JTAG_LOCK_AFT_RST_BITMASK : 0;
391 sd.cfg |= setting->jtag_lock_after_bl1?
392 SWITCHTEC_JTAG_LOCK_AFT_BL1_BITMASK : 0;
393 sd.cfg |= setting->jtag_bl1_unlock_allowed?
394 SWITCHTEC_JTAG_UNLOCK_BL1_BITMASK : 0;
395 sd.cfg |= setting->jtag_post_bl1_unlock_allowed?
396 SWITCHTEC_JTAG_UNLOCK_AFT_BL1_BITMASK : 0;
398 spi_clk = convert_spi_clk_rate(setting->spi_clk_rate,
399 reply.spi_core_clk_high);
405 sd.cfg |= (spi_clk & SWITCHTEC_CLK_RATE_BITMASK) <<
406 SWITCHTEC_CLK_RATE_BITSHIFT;
408 sd.cfg |= (setting->i2c_recovery_tmo & SWITCHTEC_RC_TMO_BITMASK) <<
409 SWITCHTEC_RC_TMO_BITSHIFT;
410 sd.cfg |= (setting->i2c_port & SWITCHTEC_I2C_PORT_BITMASK) <<
411 SWITCHTEC_I2C_PORT_BITSHIFT;
413 get_i2c_operands(
switchtec_gen(dev), &addr_shift, &map_shift,
415 sd.cfg |= (setting->i2c_addr & SWITCHTEC_I2C_ADDR_BITMASK) <<
418 ldata = setting->i2c_cmd_map & map_mask;
422 sd.cfg = htole64(sd.cfg);
424 sd.pub_key_exponent = htole32(setting->public_key_exponent);
427 ret = switchtec_mfg_cmd(dev, MRPC_SECURITY_CONFIG_SET,
428 &sd,
sizeof(sd), NULL, 0);
431 memcpy(cmd_buf + 4, &sd,
sizeof(sd));
432 ret = switchtec_mfg_cmd(dev, MRPC_SECURITY_CONFIG_SET_GEN5,
433 cmd_buf,
sizeof(cmd_buf), NULL, 0);
444 int switchtec_active_image_index_get(
struct switchtec_dev *dev,
448 struct active_indices {
449 uint8_t index[SWITCHTEC_ACTV_IDX_MAX_ENTRIES];
452 ret = switchtec_mfg_cmd(dev, MRPC_ACT_IMG_IDX_GET, NULL,
453 0, &reply,
sizeof(reply));
457 index->keyman = reply.index[SWITCHTEC_ACTV_IMG_ID_KMAN];
458 index->bl2 = reply.index[SWITCHTEC_ACTV_IMG_ID_BL2];
459 index->config = reply.index[SWITCHTEC_ACTV_IMG_ID_CFG];
460 index->firmware = reply.index[SWITCHTEC_ACTV_IMG_ID_FW];
471 int switchtec_active_image_index_set(
struct switchtec_dev *dev,
481 } idx[SWITCHTEC_ACTV_IDX_SET_ENTRIES];
484 memset(&set, 0,
sizeof(set));
486 if (index->keyman != SWITCHTEC_ACTIVE_INDEX_NOT_SET) {
487 set.idx[i].image_id = SWITCHTEC_ACTV_IMG_ID_KMAN;
488 set.idx[i].index = index->keyman;
492 if (index->bl2 != SWITCHTEC_ACTIVE_INDEX_NOT_SET) {
493 set.idx[i].image_id = SWITCHTEC_ACTV_IMG_ID_BL2;
494 set.idx[i].index = index->bl2;
498 if (index->config != SWITCHTEC_ACTIVE_INDEX_NOT_SET) {
499 set.idx[i].image_id = SWITCHTEC_ACTV_IMG_ID_CFG;
500 set.idx[i].index = index->config;
504 if (index->firmware != SWITCHTEC_ACTIVE_INDEX_NOT_SET) {
505 set.idx[i].image_id = SWITCHTEC_ACTV_IMG_ID_FW;
506 set.idx[i].index = index->firmware;
513 set.count = htole32(i);
515 ret = switchtec_mfg_cmd(dev, MRPC_ACT_IMG_IDX_SET, &set,
516 sizeof(set), NULL, 0);
526 int switchtec_fw_exec(
struct switchtec_dev *dev,
527 enum switchtec_bl2_recovery_mode recovery_mode)
529 struct fw_exec_struct {
531 uint8_t recovery_mode;
535 memset(&cmd, 0,
sizeof(cmd));
536 cmd.subcmd = MRPC_FW_TX_EXEC;
537 cmd.recovery_mode = recovery_mode;
539 return switchtec_mfg_cmd(dev, MRPC_FW_TX, &cmd,
sizeof(cmd), NULL, 0);
554 int switchtec_boot_resume(
struct switchtec_dev *dev)
556 return switchtec_mfg_cmd(dev, MRPC_BOOTUP_RESUME, NULL, 0,
566 int switchtec_secure_state_set(
struct switchtec_dev *dev,
567 enum switchtec_secure_state state)
571 if ((state != SWITCHTEC_INITIALIZED_UNSECURED)
572 && (state != SWITCHTEC_INITIALIZED_SECURED)) {
573 return ERR_PARAM_INVALID;
575 data = htole32(state);
577 return switchtec_mfg_cmd(dev, MRPC_SECURE_STATE_SET, &data,
578 sizeof(data), NULL, 0);
581 static int dbg_unlock_send_pubkey(
struct switchtec_dev *dev,
584 struct public_key_cmd {
587 uint8_t pub_key[SWITCHTEC_PUB_KEY_LEN];
588 uint32_t pub_key_exp;
591 cmd.subcmd = MRPC_DBG_UNLOCK_PKEY;
592 memcpy(cmd.pub_key, public_key->pubkey, SWITCHTEC_PUB_KEY_LEN);
593 cmd.pub_key_exp = htole32(public_key->pubkey_exp);
595 return switchtec_mfg_cmd(dev, MRPC_DBG_UNLOCK, &cmd,
596 sizeof(cmd), NULL, 0);
608 int switchtec_dbg_unlock(
struct switchtec_dev *dev, uint32_t serial,
609 uint32_t ver_sec_unlock,
619 uint8_t signature[SWITCHTEC_SIG_LEN];
622 ret = dbg_unlock_send_pubkey(dev, public_key);
626 cmd.subcmd = MRPC_DBG_UNLOCK_DATA;
627 cmd.serial = htole32(serial);
628 cmd.unlock_ver = htole32(ver_sec_unlock);
629 memcpy(cmd.signature, signature->signature, SWITCHTEC_SIG_LEN);
631 return switchtec_mfg_cmd(dev, MRPC_DBG_UNLOCK, &cmd,
632 sizeof(cmd), NULL, 0);
644 int switchtec_dbg_unlock_version_update(
struct switchtec_dev *dev,
646 uint32_t ver_sec_unlock,
656 uint8_t signature[SWITCHTEC_SIG_LEN];
659 ret = dbg_unlock_send_pubkey(dev, public_key);
663 cmd.subcmd = MRPC_DBG_UNLOCK_UPDATE;
664 cmd.serial = htole32(serial);
665 cmd.unlock_ver = htole32(ver_sec_unlock);
666 memcpy(cmd.signature, signature->signature, SWITCHTEC_SIG_LEN);
668 return switchtec_mfg_cmd(dev, MRPC_DBG_UNLOCK, &cmd,
sizeof(cmd),
679 int switchtec_read_sec_cfg_file(
struct switchtec_dev *dev,
684 char magic[4] = {
'S',
'S',
'F',
'F'};
686 struct setting_file_header {
693 struct setting_file_data {
695 uint32_t pub_key_exponent;
698 struct setting_file {
699 struct setting_file_header header;
700 struct setting_file_data data;
702 struct get_cfgs_reply reply;
711 ret = get_configs(dev, &reply, &otp_valid);
715 rlen = fread(&file_data, 1,
sizeof(file_data), setting_file);
717 if (rlen <
sizeof(file_data))
720 if (memcmp(file_data.header.magic, magic,
sizeof(magic)))
723 crc = crc32((uint8_t*)&file_data.data,
724 sizeof(file_data.data), 0, 1, 1);
725 if (crc != le32toh(file_data.header.crc))
727 switch (file_data.header.hw_gen) {
729 gen = SWITCHTEC_GEN4;
732 gen = SWITCHTEC_GEN5;
743 file_data.data.cfg = le64toh(file_data.data.cfg);
745 set->jtag_lock_after_reset =
746 !!(file_data.data.cfg & SWITCHTEC_JTAG_LOCK_AFT_RST_BITMASK);
747 set->jtag_lock_after_bl1 =
748 !!(file_data.data.cfg & SWITCHTEC_JTAG_LOCK_AFT_BL1_BITMASK);
749 set->jtag_bl1_unlock_allowed =
750 !!(file_data.data.cfg & SWITCHTEC_JTAG_UNLOCK_BL1_BITMASK);
751 set->jtag_post_bl1_unlock_allowed =
752 !!(file_data.data.cfg & SWITCHTEC_JTAG_UNLOCK_AFT_BL1_BITMASK);
754 spi_clk = (file_data.data.cfg >> SWITCHTEC_CLK_RATE_BITSHIFT) &
755 SWITCHTEC_CLK_RATE_BITMASK;
756 if (reply.spi_core_clk_high)
757 set->spi_clk_rate = spi_clk_hi_rate_float[spi_clk - 1];
759 set->spi_clk_rate = spi_clk_rate_float[spi_clk - 1];
761 set->i2c_recovery_tmo =
762 (file_data.data.cfg >> SWITCHTEC_RC_TMO_BITSHIFT) &
763 SWITCHTEC_RC_TMO_BITMASK;
765 (file_data.data.cfg >> SWITCHTEC_I2C_PORT_BITSHIFT) &
766 SWITCHTEC_I2C_PORT_BITMASK;
768 get_i2c_operands(gen, &addr_shift, &map_shift, &map_mask);
770 (file_data.data.cfg >> addr_shift) &
771 SWITCHTEC_I2C_ADDR_BITMASK;
772 set->i2c_cmd_map = (file_data.data.cfg >> map_shift) & map_mask;
774 set->public_key_exponent = le32toh(file_data.data.pub_key_exponent);
779 static int kmsk_set_send_pubkey(
struct switchtec_dev *dev,
782 struct kmsk_pubk_cmd {
785 uint8_t pub_key[SWITCHTEC_PUB_KEY_LEN];
786 uint32_t pub_key_exponent;
789 cmd.subcmd = MRPC_KMSK_ENTRY_SET_PKEY;
790 memcpy(cmd.pub_key, public_key->pubkey,
791 SWITCHTEC_PUB_KEY_LEN);
792 cmd.pub_key_exponent = htole32(public_key->pubkey_exp);
794 return switchtec_mfg_cmd(dev, MRPC_KMSK_ENTRY_SET, &cmd,
795 sizeof(cmd), NULL, 0);
798 static int kmsk_set_send_signature(
struct switchtec_dev *dev,
801 struct kmsk_signature_cmd {
804 uint8_t signature[SWITCHTEC_SIG_LEN];
807 cmd.subcmd = MRPC_KMSK_ENTRY_SET_SIG;
808 memcpy(cmd.signature, signature->signature,
811 return switchtec_mfg_cmd(dev, MRPC_KMSK_ENTRY_SET, &cmd,
812 sizeof(cmd), NULL, 0);
815 static int kmsk_set_send_kmsk(
struct switchtec_dev *dev,
818 struct kmsk_kmsk_cmd {
822 uint8_t kmsk[SWITCHTEC_KMSK_LEN];
825 cmd.subcmd = MRPC_KMSK_ENTRY_SET_KMSK;
827 memcpy(cmd.kmsk, kmsk->kmsk, SWITCHTEC_KMSK_LEN);
829 return switchtec_mfg_cmd(dev, MRPC_KMSK_ENTRY_SET, &cmd,
sizeof(cmd),
845 int switchtec_kmsk_set(
struct switchtec_dev *dev,
853 ret = kmsk_set_send_pubkey(dev, public_key);
859 ret = kmsk_set_send_signature(dev, signature);
864 return kmsk_set_send_kmsk(dev, kmsk);
874 int switchtec_read_pubk_file(FILE *pubk_file,
struct switchtec_pubkey *pubk)
877 const BIGNUM *modulus_bn;
878 const BIGNUM *exponent_bn;
879 uint32_t exponent_tmp = 0;
881 RSAKey = PEM_read_RSA_PUBKEY(pubk_file, NULL, NULL, NULL);
882 if (RSAKey == NULL) {
883 fseek(pubk_file, 0L, SEEK_SET);
884 RSAKey = PEM_read_RSAPrivateKey(pubk_file, NULL, NULL, NULL);
889 RSA_get0_key(RSAKey, &modulus_bn, &exponent_bn, NULL);
891 BN_bn2bin(modulus_bn, pubk->pubkey);
892 BN_bn2bin(exponent_bn, (uint8_t *)&exponent_tmp);
894 pubk->pubkey_exp = be32toh(exponent_tmp);
907 int switchtec_read_kmsk_file(FILE *kmsk_file,
struct switchtec_kmsk *kmsk)
915 uint8_t kmsk[SWITCHTEC_KMSK_LEN];
918 char magic[4] = {
'K',
'M',
'S',
'K'};
921 rlen = fread(&data, 1,
sizeof(data), kmsk_file);
923 if (rlen <
sizeof(data))
926 if (memcmp(data.magic, magic,
sizeof(magic)))
929 crc = crc32(data.kmsk, SWITCHTEC_KMSK_LEN, 0, 1, 1);
930 if (crc != le32toh(data.crc32))
933 memcpy(kmsk->kmsk, data.kmsk, SWITCHTEC_KMSK_LEN);
944 int switchtec_read_signature_file(FILE *sig_file,
949 rlen = fread(signature->signature, 1, SWITCHTEC_SIG_LEN, sig_file);
951 if (rlen < SWITCHTEC_SIG_LEN)
973 for(key_idx = 0; key_idx < state->public_key_num; key_idx++) {
974 if (memcmp(state->public_key[key_idx], kmsk->kmsk,
975 SWITCHTEC_KMSK_LEN) == 0)
984 static int switchtec_mfg_cmd(
struct switchtec_dev *dev, uint32_t cmd,
985 const void *payload,
size_t payload_len,
986 void *resp,
size_t resp_len)
988 if (dev->ops->flags & SWITCHTEC_OPS_FLAG_NO_MFG) {
989 errno = ERR_UART_NOT_SUPPORTED | SWITCHTEC_ERRNO_MRPC_FLAG_BIT;
1008 ret = switchtec_mfg_cmd(dev, MRPC_SN_VER_GET, NULL, 0, info,
1013 info->chip_serial = le32toh(info->chip_serial);
1014 info->ver_bl2 = le32toh(info->ver_bl2);
1015 info->ver_km = le32toh(info->ver_km);
1016 info->ver_main = le32toh(info->ver_main);
1017 info->ver_sec_unlock = le32toh(info->ver_sec_unlock);
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.