Skip to content

Commit 62ce547

Browse files
author
Android Build Coastguard Worker
committed
Snap for 7796451 from 857115b to sc-qpr1-d-release
Change-Id: I21ecffe751ec20ae3de57d0cf6b3502072a6dd1e
2 parents dcdac24 + 857115b commit 62ce547

1 file changed

Lines changed: 79 additions & 35 deletions

File tree

trusty/storage/proxy/rpmb.c

Lines changed: 79 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,17 @@
5757

5858
#define MMC_BLOCK_SIZE 512
5959

60+
/*
61+
* Number of retry attempts when an RPMB authenticated write triggers a UNIT
62+
* ATTENTION
63+
*/
64+
#define UFS_RPMB_WRITE_RETRY_COUNT 1
65+
/*
66+
* Number of retry attempts when an RPMB read operation triggers a UNIT
67+
* ATTENTION
68+
*/
69+
#define UFS_RPMB_READ_RETRY_COUNT 3
70+
6071
/*
6172
* There should be no timeout for security protocol ioctl call, so we choose a
6273
* large number for timeout.
@@ -180,14 +191,20 @@ static void set_sg_io_hdr(sg_io_hdr_t* io_hdrp, int dxfer_direction, unsigned ch
180191
}
181192

182193
/**
183-
* unexpected_scsi_sense - Check for unexpected codes in the sense buffer.
184-
* @sense_buf: buffer containing sense data
185-
* @len: length of @sense_buf
194+
* enum scsi_result - Results of checking the SCSI status and sense buffer
186195
*
187-
* Return: %true if the sense data is not valid or contains an unexpected sense
188-
* code, %false otherwise.
196+
* @SCSI_RES_OK: SCSI status and sense are good
197+
* @SCSI_RES_ERR: SCSI status or sense contain an unhandled error
198+
* @SCSI_RES_RETRY: SCSI sense buffer contains a status that indicates that the
199+
* command should be retried
189200
*/
190-
static bool unexpected_scsi_sense(const uint8_t* sense_buf, size_t len) {
201+
enum scsi_result {
202+
SCSI_RES_OK = 0,
203+
SCSI_RES_ERR,
204+
SCSI_RES_RETRY,
205+
};
206+
207+
static enum scsi_result check_scsi_sense(const uint8_t* sense_buf, size_t len) {
191208
uint8_t response_code = 0;
192209
uint8_t sense_key = 0;
193210
uint8_t additional_sense_code = 0;
@@ -196,14 +213,14 @@ static bool unexpected_scsi_sense(const uint8_t* sense_buf, size_t len) {
196213

197214
if (!sense_buf || len == 0) {
198215
ALOGE("Invalid SCSI sense buffer, length: %zu\n", len);
199-
return true;
216+
return SCSI_RES_ERR;
200217
}
201218

202219
response_code = 0x7f & sense_buf[0];
203220

204221
if (response_code < 0x70 || response_code > 0x73) {
205222
ALOGE("Invalid SCSI sense response code: %hhu\n", response_code);
206-
return true;
223+
return SCSI_RES_ERR;
207224
}
208225

209226
if (response_code >= 0x72) {
@@ -241,31 +258,43 @@ static bool unexpected_scsi_sense(const uint8_t* sense_buf, size_t len) {
241258
case 0x0f: /* COMPLETED, not present in kernel headers */
242259
ALOGD("SCSI success with sense data: key=%hhu, asc=%hhu, ascq=%hhu\n", sense_key,
243260
additional_sense_code, additional_sense_code_qualifier);
244-
return false;
261+
return SCSI_RES_OK;
262+
case UNIT_ATTENTION:
263+
ALOGD("UNIT ATTENTION with sense data: key=%hhu, asc=%hhu, ascq=%hhu\n", sense_key,
264+
additional_sense_code, additional_sense_code_qualifier);
265+
if (additional_sense_code == 0x29) {
266+
/* POWER ON or RESET condition */
267+
return SCSI_RES_RETRY;
268+
}
269+
270+
/* treat this UNIT ATTENTION as an error if we don't recognize it */
271+
break;
245272
}
246273

247274
ALOGE("Unexpected SCSI sense data: key=%hhu, asc=%hhu, ascq=%hhu\n", sense_key,
248275
additional_sense_code, additional_sense_code_qualifier);
249276
log_buf(ANDROID_LOG_ERROR, "sense buffer: ", sense_buf, len);
250-
return true;
277+
return SCSI_RES_ERR;
251278
}
252279

253-
static void check_sg_io_hdr(const sg_io_hdr_t* io_hdrp) {
280+
static enum scsi_result check_sg_io_hdr(const sg_io_hdr_t* io_hdrp) {
254281
if (io_hdrp->status == 0 && io_hdrp->host_status == 0 && io_hdrp->driver_status == 0) {
255-
return;
282+
return SCSI_RES_OK;
256283
}
257284

258285
if (io_hdrp->status & 0x01) {
259286
ALOGE("SG_IO received unknown status, LSB is set: %hhu", io_hdrp->status);
260287
}
261288

262289
if (io_hdrp->masked_status != GOOD && io_hdrp->sb_len_wr > 0) {
263-
bool sense_error = unexpected_scsi_sense(io_hdrp->sbp, io_hdrp->sb_len_wr);
264-
if (sense_error) {
290+
enum scsi_result scsi_res = check_scsi_sense(io_hdrp->sbp, io_hdrp->sb_len_wr);
291+
if (scsi_res == SCSI_RES_RETRY) {
292+
return SCSI_RES_RETRY;
293+
} else if (scsi_res != SCSI_RES_OK) {
265294
ALOGE("Unexpected SCSI sense. masked_status: %hhu, host_status: %hu, driver_status: "
266295
"%hu\n",
267296
io_hdrp->masked_status, io_hdrp->host_status, io_hdrp->driver_status);
268-
return;
297+
return scsi_res;
269298
}
270299
}
271300

@@ -278,7 +307,7 @@ static void check_sg_io_hdr(const sg_io_hdr_t* io_hdrp) {
278307
default:
279308
ALOGE("SG_IO failed with masked_status: %hhu, host_status: %hu, driver_status: %hu\n",
280309
io_hdrp->masked_status, io_hdrp->host_status, io_hdrp->driver_status);
281-
return;
310+
return SCSI_RES_ERR;
282311
}
283312

284313
if (io_hdrp->host_status != 0) {
@@ -289,6 +318,7 @@ static void check_sg_io_hdr(const sg_io_hdr_t* io_hdrp) {
289318
if (io_hdrp->resid != 0) {
290319
ALOGE("SG_IO resid was non-zero: %d\n", io_hdrp->resid);
291320
}
321+
return SCSI_RES_ERR;
292322
}
293323

294324
static int send_mmc_rpmb_req(int mmc_fd, const struct storage_rpmb_send_req* req) {
@@ -363,6 +393,8 @@ static int send_ufs_rpmb_req(int sg_fd, const struct storage_rpmb_send_req* req)
363393
struct sec_proto_cdb out_cdb = {0xB5, 0xEC, 0x00, 0x01, 0x00, 0x00, 0, 0x00, 0x00};
364394
unsigned char sense_buffer[32];
365395

396+
bool is_request_write = req->reliable_write_size > 0;
397+
366398
wl_rc = acquire_wake_lock(PARTIAL_WAKE_LOCK, UFS_WAKE_LOCK_NAME);
367399
if (wl_rc < 0) {
368400
ALOGE("%s: failed to acquire wakelock: %d, %s\n", __func__, wl_rc, strerror(errno));
@@ -371,32 +403,44 @@ static int send_ufs_rpmb_req(int sg_fd, const struct storage_rpmb_send_req* req)
371403

372404
if (req->reliable_write_size) {
373405
/* Prepare SECURITY PROTOCOL OUT command. */
374-
out_cdb.length = __builtin_bswap32(req->reliable_write_size);
375406
sg_io_hdr_t io_hdr;
376-
set_sg_io_hdr(&io_hdr, SG_DXFER_TO_DEV, sizeof(out_cdb), sizeof(sense_buffer),
377-
req->reliable_write_size, (void*)write_buf, (unsigned char*)&out_cdb,
378-
sense_buffer);
379-
rc = ioctl(sg_fd, SG_IO, &io_hdr);
380-
if (rc < 0) {
381-
ALOGE("%s: ufs ioctl failed: %d, %s\n", __func__, rc, strerror(errno));
382-
goto err_op;
383-
}
384-
check_sg_io_hdr(&io_hdr);
407+
int retry_count = UFS_RPMB_WRITE_RETRY_COUNT;
408+
do {
409+
out_cdb.length = __builtin_bswap32(req->reliable_write_size);
410+
set_sg_io_hdr(&io_hdr, SG_DXFER_TO_DEV, sizeof(out_cdb), sizeof(sense_buffer),
411+
req->reliable_write_size, (void*)write_buf, (unsigned char*)&out_cdb,
412+
sense_buffer);
413+
rc = ioctl(sg_fd, SG_IO, &io_hdr);
414+
if (rc < 0) {
415+
ALOGE("%s: ufs ioctl failed: %d, %s\n", __func__, rc, strerror(errno));
416+
goto err_op;
417+
}
418+
} while (check_sg_io_hdr(&io_hdr) == SCSI_RES_RETRY && retry_count-- > 0);
385419
write_buf += req->reliable_write_size;
386420
}
387421

388422
if (req->write_size) {
389423
/* Prepare SECURITY PROTOCOL OUT command. */
390-
out_cdb.length = __builtin_bswap32(req->write_size);
391424
sg_io_hdr_t io_hdr;
392-
set_sg_io_hdr(&io_hdr, SG_DXFER_TO_DEV, sizeof(out_cdb), sizeof(sense_buffer),
393-
req->write_size, (void*)write_buf, (unsigned char*)&out_cdb, sense_buffer);
394-
rc = ioctl(sg_fd, SG_IO, &io_hdr);
395-
if (rc < 0) {
396-
ALOGE("%s: ufs ioctl failed: %d, %s\n", __func__, rc, strerror(errno));
397-
goto err_op;
398-
}
399-
check_sg_io_hdr(&io_hdr);
425+
/*
426+
* We don't retry write response request messages (is_request_write ==
427+
* true) because a unit attention condition between the write and
428+
* requesting a response means that the device was reset and we can't
429+
* get a response to our original write. We can only retry this SG_IO
430+
* call when it is the first call in our sequence.
431+
*/
432+
int retry_count = is_request_write ? 0 : UFS_RPMB_READ_RETRY_COUNT;
433+
do {
434+
out_cdb.length = __builtin_bswap32(req->write_size);
435+
set_sg_io_hdr(&io_hdr, SG_DXFER_TO_DEV, sizeof(out_cdb), sizeof(sense_buffer),
436+
req->write_size, (void*)write_buf, (unsigned char*)&out_cdb,
437+
sense_buffer);
438+
rc = ioctl(sg_fd, SG_IO, &io_hdr);
439+
if (rc < 0) {
440+
ALOGE("%s: ufs ioctl failed: %d, %s\n", __func__, rc, strerror(errno));
441+
goto err_op;
442+
}
443+
} while (check_sg_io_hdr(&io_hdr) == SCSI_RES_RETRY && retry_count-- > 0);
400444
write_buf += req->write_size;
401445
}
402446

0 commit comments

Comments
 (0)