Skip to content

Commit 007616f

Browse files
committed
Merge branch 'devel'
2 parents e655bb7 + 0cb6cb9 commit 007616f

File tree

6 files changed

+206
-40
lines changed

6 files changed

+206
-40
lines changed

cli/mfg.c

Lines changed: 62 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,20 @@ static int ping(int argc, char **argv)
111111
return 0;
112112
}
113113

114-
static void print_security_config(struct switchtec_security_cfg_state *state)
114+
static const char* program_status_to_string(enum switchtec_otp_program_status s)
115+
{
116+
switch(s) {
117+
case SWITCHTEC_OTP_PROGRAMMABLE:
118+
return "R/W (Programmable)";
119+
case SWITCHTEC_OTP_UNPROGRAMMABLE:
120+
return "R/O (Unprogrammable)";
121+
default:
122+
return "Unknown";
123+
}
124+
}
125+
126+
static void print_security_config(struct switchtec_security_cfg_state *state,
127+
struct switchtec_security_cfg_otp_region *otp)
115128
{
116129
int key_idx;
117130
int i;
@@ -194,6 +207,27 @@ static void print_security_config(struct switchtec_security_cfg_state *state)
194207
printf("%02x", state->public_key[key_idx][i]);
195208
printf("\n");
196209
}
210+
211+
if (otp) {
212+
printf("\nOTP Region Program Status\n");
213+
printf("\tBasic Secure Settings %s%s\n",
214+
otp->basic_valid? "(Valid): ": "(Invalid):",
215+
program_status_to_string(otp->basic));
216+
printf("\tMixed Version %s\t%s\n",
217+
otp->mixed_ver_valid? "(Valid): ": "(Invalid):",
218+
program_status_to_string(otp->mixed_ver));
219+
printf("\tMain FW Version %s\t%s\n",
220+
otp->main_fw_ver_valid? "(Valid): ": "(Invalid):",
221+
program_status_to_string(otp->main_fw_ver));
222+
printf("\tSecure Unlock Version %s%s\n",
223+
otp->sec_unlock_ver_valid? "(Valid): ": "(Invalid):",
224+
program_status_to_string(otp->sec_unlock_ver));
225+
for (i = 0; i < 4; i++) {
226+
printf("\tKMSK%d %s\t\t%s\n", i,
227+
otp->kmsk_valid[i]? "(Valid): ": "(Invalid):",
228+
program_status_to_string(otp->kmsk[i]));
229+
}
230+
}
197231
}
198232

199233
static void print_security_cfg_set(struct switchtec_security_cfg_set *set)
@@ -236,17 +270,25 @@ static int info(int argc, char **argv)
236270

237271
static struct {
238272
struct switchtec_dev *dev;
273+
int verbose;
239274
} cfg = {};
240275

241276
const struct argconfig_options opts[] = {
242277
DEVICE_OPTION_MFG,
243-
{NULL}
244-
};
278+
{"verbose", 'v', "", CFG_NONE, &cfg.verbose, no_argument,
279+
"print additional chip information"},
280+
{NULL}};
245281

246-
struct switchtec_security_cfg_state state = {};
282+
struct switchtec_security_cfg_state_ext ext_state = {};
247283

248284
argconfig_parse(argc, argv, CMD_DESC_INFO, opts, &cfg, sizeof(cfg));
249285

286+
ret = switchtec_security_config_get_ext(cfg.dev, &ext_state);
287+
if (ret) {
288+
switchtec_perror("mfg info");
289+
return ret;
290+
}
291+
250292
phase_id = switchtec_boot_phase(cfg.dev);
251293
printf("Current Boot Phase: \t\t\t%s\n", phase_id_to_string(phase_id));
252294

@@ -266,13 +308,23 @@ static int info(int argc, char **argv)
266308
return 0;
267309
}
268310

269-
ret = switchtec_security_config_get(cfg.dev, &state);
270-
if (ret) {
271-
switchtec_perror("mfg info");
272-
return ret;
311+
if (cfg.verbose) {
312+
if (!ext_state.otp_valid) {
313+
print_security_config(&ext_state.state, NULL);
314+
fprintf(stderr,
315+
"\nAdditional (verbose) chip info is not available on this chip!\n\n");
316+
} else if (phase_id != SWITCHTEC_BOOT_PHASE_FW) {
317+
print_security_config(&ext_state.state, NULL);
318+
fprintf(stderr,
319+
"\nAdditional (verbose) chip info is only available in the Main Firmware phase!\n\n");
320+
} else {
321+
print_security_config(&ext_state.state, &ext_state.otp);
322+
}
323+
324+
return 0;
273325
}
274326

275-
print_security_config(&state);
327+
print_security_config(&ext_state.state, NULL);
276328

277329
return 0;
278330
}
@@ -714,7 +766,7 @@ static int state_set(int argc, char **argv)
714766
return -3;
715767
}
716768

717-
print_security_config(&state);
769+
print_security_config(&state, NULL);
718770

719771
if (!cfg.assume_yes) {
720772
fprintf(stderr,

inc/switchtec/fabric.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -702,7 +702,7 @@ int switchtec_ep_bar_write64(struct switchtec_dev *dev, uint16_t pdfid,
702702
uint8_t bar_index, uint64_t val, uint64_t addr);
703703

704704
/********** ADMIN PASSTHRU COMMAND *********/
705-
#define SWITCHTEC_NVME_ADMIN_PASSTHRU_MAX_DATA_LEN (MRPC_MAX_DATA_LEN - 8)
705+
#define SWITCHTEC_NVME_ADMIN_PASSTHRU_MAX_DATA_LEN (4096 + 16 * 4)
706706

707707
int switchtec_nvme_admin_passthru(struct switchtec_dev *dev, uint16_t pdfid,
708708
size_t data_len, void *data,

inc/switchtec/mfg.h

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,36 @@ struct switchtec_security_cfg_state {
9292
uint8_t public_key[SWITCHTEC_KMSK_NUM][SWITCHTEC_KMSK_LEN];
9393
};
9494

95+
/**
96+
* @brief Flag which indicates if an OTP region is programmable or not
97+
*/
98+
enum switchtec_otp_program_status {
99+
SWITCHTEC_OTP_PROGRAMMABLE = 0,
100+
SWITCHTEC_OTP_UNPROGRAMMABLE = 1,
101+
};
102+
103+
struct switchtec_security_cfg_otp_region {
104+
bool basic_valid;
105+
bool mixed_ver_valid;
106+
bool main_fw_ver_valid;
107+
bool sec_unlock_ver_valid;
108+
bool kmsk_valid[4];
109+
enum switchtec_otp_program_status basic;
110+
enum switchtec_otp_program_status mixed_ver;
111+
enum switchtec_otp_program_status main_fw_ver;
112+
enum switchtec_otp_program_status sec_unlock_ver;
113+
enum switchtec_otp_program_status kmsk[4];
114+
};
115+
116+
/**
117+
* @brief extended security configuration
118+
*/
119+
struct switchtec_security_cfg_state_ext {
120+
bool otp_valid;
121+
struct switchtec_security_cfg_state state;
122+
struct switchtec_security_cfg_otp_region otp;
123+
};
124+
95125
struct switchtec_security_cfg_set {
96126
uint8_t jtag_lock_after_reset;
97127
uint8_t jtag_lock_after_bl1;
@@ -142,6 +172,8 @@ int switchtec_sn_ver_get(struct switchtec_dev *dev,
142172
struct switchtec_sn_ver_info *info);
143173
int switchtec_security_config_get(struct switchtec_dev *dev,
144174
struct switchtec_security_cfg_state *state);
175+
int switchtec_security_config_get_ext(struct switchtec_dev *dev,
176+
struct switchtec_security_cfg_state_ext *ext);
145177
int switchtec_security_config_set(struct switchtec_dev *dev,
146178
struct switchtec_security_cfg_set *setting);
147179
int switchtec_mailbox_to_file(struct switchtec_dev *dev, int fd);

inc/switchtec/mrpc.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ enum mrpc_cmd {
6363
MRPC_GAS_READ = 41,
6464
MRPC_PART_INFO = 43,
6565
MRPC_GAS_WRITE = 52,
66+
MRPC_SECURITY_CONFIG_GET_EXT = 60,
6667
MRPC_ECHO = 65,
6768
MRPC_GET_PAX_ID = 129,
6869

lib/fabric.c

Lines changed: 39 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1380,32 +1380,61 @@ static int admin_passthru_start(struct switchtec_dev *dev, uint16_t pdfid,
13801380
size_t *rsp_len)
13811381
{
13821382
int ret;
1383-
int copy_len;
1383+
uint16_t copy_len;
1384+
uint16_t offset = 0;
1385+
13841386
struct {
13851387
uint8_t subcmd;
13861388
uint8_t rsvd[3];
13871389
uint16_t pdfid;
13881390
uint16_t expected_rsp_len;
1389-
uint8_t data[SWITCHTEC_NVME_ADMIN_PASSTHRU_MAX_DATA_LEN];
1391+
uint8_t more_data;
1392+
uint8_t rsvd1[3];
1393+
uint16_t data_offset;
1394+
uint16_t data_len;
1395+
uint8_t data[MRPC_MAX_DATA_LEN - 16];
13901396
} cmd = {
13911397
.subcmd = MRPC_NVME_ADMIN_PASSTHRU_START,
1392-
.pdfid = htole16(pdfid),
1393-
.expected_rsp_len = htole16(*rsp_len)
1398+
.pdfid = htole16(pdfid)
13941399
};
13951400

13961401
struct {
1397-
uint8_t subcmd;
1398-
uint8_t rsvd[3];
13991402
uint16_t rsp_len;
14001403
uint16_t rsvd1;
14011404
} reply = {};
14021405

14031406
if (data_len && data != NULL) {
1404-
copy_len = data_len > sizeof(cmd.data)?
1405-
sizeof(cmd.data) : data_len;
1406-
memcpy(cmd.data, data, copy_len);
1407+
cmd.more_data = data_len > sizeof(cmd.data);
1408+
while (cmd.more_data) {
1409+
copy_len = sizeof(cmd.data);
1410+
memcpy(cmd.data, data + offset, copy_len);
1411+
1412+
cmd.data_offset = htole16(offset);
1413+
cmd.data_len = htole16(copy_len);
1414+
1415+
ret = switchtec_cmd(dev, MRPC_NVME_ADMIN_PASSTHRU,
1416+
&cmd, sizeof(cmd), NULL, 0);
1417+
if (ret)
1418+
return ret;
1419+
1420+
offset += copy_len;
1421+
data_len -= copy_len;
1422+
cmd.more_data = data_len > sizeof(cmd.data);
1423+
}
1424+
1425+
if (data_len) {
1426+
memcpy(cmd.data, data + offset, data_len);
1427+
1428+
cmd.data_offset = htole16(offset);
1429+
cmd.data_len = htole16(data_len);
1430+
} else {
1431+
cmd.data_len = 0;
1432+
cmd.data_offset = 0;
1433+
}
14071434
}
14081435

1436+
cmd.expected_rsp_len = htole16(*rsp_len);
1437+
14091438
ret = switchtec_cmd(dev, MRPC_NVME_ADMIN_PASSTHRU,
14101439
&cmd, sizeof(cmd), &reply, sizeof(reply));
14111440
if (ret) {
@@ -1433,11 +1462,9 @@ static int admin_passthru_data(struct switchtec_dev *dev, uint16_t pdfid,
14331462
};
14341463

14351464
struct {
1436-
uint8_t subcmd;
1437-
uint8_t rsvd[3];
14381465
uint16_t offset;
14391466
uint16_t len;
1440-
uint8_t data[MRPC_MAX_DATA_LEN - 8];
1467+
uint8_t data[MRPC_MAX_DATA_LEN - 4];
14411468
} reply = {};
14421469

14431470
while (offset < rsp_len) {

lib/mfg.c

Lines changed: 71 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -111,34 +111,64 @@ static void RSA_get0_key(const RSA *r, const BIGNUM **n,
111111
}
112112
#endif
113113

114-
/**
115-
* @brief Get secure boot configurations
116-
* @param[in] dev Switchtec device handle
117-
* @param[out] state Current secure boot settings
118-
* @return 0 on success, error code on failure
119-
*/
120-
int switchtec_security_config_get(struct switchtec_dev *dev,
121-
struct switchtec_security_cfg_state *state)
114+
static int secure_config_get(struct switchtec_dev *dev,
115+
struct switchtec_security_cfg_state *state,
116+
struct switchtec_security_cfg_otp_region *otp,
117+
bool *otp_valid)
122118
{
123119
int ret;
120+
uint8_t subcmd = 0;
124121
struct cfg_reply {
125122
uint32_t valid;
126123
uint32_t rsvd1;
127124
uint64_t cfg;
128-
uint32_t public_key_exponent;
129-
uint8_t rsvd2;
130-
uint8_t public_key_num;
131-
uint8_t public_key_ver;
132-
uint8_t rsvd3;
133-
uint8_t public_key[SWITCHTEC_KMSK_NUM][SWITCHTEC_KMSK_LEN];
134-
uint8_t rsvd4[32];
125+
uint32_t public_key_exponent;
126+
uint8_t rsvd2;
127+
uint8_t public_key_num;
128+
uint8_t public_key_ver;
129+
uint8_t rsvd3;
130+
uint8_t public_key[SWITCHTEC_KMSK_NUM][SWITCHTEC_KMSK_LEN];
131+
uint8_t rsvd4[32];
135132
} reply;
136133

137-
ret = switchtec_mfg_cmd(dev, MRPC_SECURITY_CONFIG_GET, NULL, 0,
134+
if (otp_valid)
135+
*otp_valid = false;
136+
137+
ret = switchtec_mfg_cmd(dev, MRPC_SECURITY_CONFIG_GET_EXT,
138+
&subcmd, sizeof(subcmd),
138139
&reply, sizeof(reply));
139-
if (ret)
140+
if (ret && ERRNO_MRPC(errno) != ERR_CMD_INVALID)
140141
return ret;
141142

143+
if (!ret) {
144+
if (otp) {
145+
otp->basic_valid = !!(reply.valid & BIT(5));
146+
otp->basic = !!(reply.valid & BIT(6));
147+
otp->mixed_ver_valid = !!(reply.valid & BIT(7));
148+
otp->mixed_ver = !!(reply.valid & BIT(8));
149+
otp->main_fw_ver_valid = !!(reply.valid & BIT(9));
150+
otp->main_fw_ver = !!(reply.valid & BIT(10));
151+
otp->sec_unlock_ver_valid = !!(reply.valid & BIT(11));
152+
otp->sec_unlock_ver = !!(reply.valid & BIT(12));
153+
otp->kmsk_valid[0] = !!(reply.valid & BIT(13));
154+
otp->kmsk[0] = !!(reply.valid & BIT(14));
155+
otp->kmsk_valid[1] = !!(reply.valid & BIT(15));
156+
otp->kmsk[1] = !!(reply.valid & BIT(16));
157+
otp->kmsk_valid[2] = !!(reply.valid & BIT(17));
158+
otp->kmsk[2] = !!(reply.valid & BIT(18));
159+
otp->kmsk_valid[3] = !!(reply.valid & BIT(19));
160+
otp->kmsk[3] = !!(reply.valid & BIT(20));
161+
162+
if (otp_valid)
163+
*otp_valid = true;
164+
}
165+
} else {
166+
ret = switchtec_mfg_cmd(dev, MRPC_SECURITY_CONFIG_GET, NULL, 0,
167+
&reply, sizeof(reply));
168+
if (ret)
169+
return ret;
170+
}
171+
142172
reply.valid = le32toh(reply.valid);
143173
reply.cfg = le64toh(reply.cfg);
144174
reply.public_key_exponent = le32toh(reply.public_key_exponent);
@@ -178,6 +208,30 @@ int switchtec_security_config_get(struct switchtec_dev *dev,
178208
return 0;
179209
}
180210

211+
/**
212+
* @brief Get secure boot configurations
213+
* @param[in] dev Switchtec device handle
214+
* @param[out] state Current secure boot settings
215+
* @return 0 on success, error code on failure
216+
*/
217+
int switchtec_security_config_get(struct switchtec_dev *dev,
218+
struct switchtec_security_cfg_state *state)
219+
{
220+
return secure_config_get(dev, state, NULL, NULL);
221+
}
222+
223+
/**
224+
* @brief Get secure boot extended configurations
225+
* @param[in] dev Switchtec device handle
226+
* @param[out] ext Current extended secure boot settings
227+
* @return 0 on success, error code on failure
228+
*/
229+
int switchtec_security_config_get_ext(struct switchtec_dev *dev,
230+
struct switchtec_security_cfg_state_ext *ext)
231+
{
232+
return secure_config_get(dev, &ext->state, &ext->otp, &ext->otp_valid);
233+
}
234+
181235
/**
182236
* @brief Retrieve mailbox entries
183237
* @param[in] dev Switchtec device handle

0 commit comments

Comments
 (0)