From 25881d33905798e6fddda3827b4345e867c02b7f Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Sun, 18 Dec 2011 21:37:51 +0100 Subject: hw/sd.c: Fix the set of commands which are failed when card is locked Fix bugs in the code determining whether to accept a command when the SD card is locked. Most notably, we had the condition completely reversed, so we would accept all the commands we should refuse and refuse all the commands we should accept. Correct this by refactoring the enormous if () clause into a separate function. We had also missed ACMD42 off the list of commands which are accepted in locked state: add it. This is one of the two problems reported in LP:597641. Signed-off-by: Peter Maydell Signed-off-by: Andrzej Zaborowski --- hw/sd.c | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) (limited to 'hw/sd.c') diff --git a/hw/sd.c b/hw/sd.c index 10e26ade58..a1c98c0100 100644 --- a/hw/sd.c +++ b/hw/sd.c @@ -1265,6 +1265,25 @@ static sd_rsp_type_t sd_app_command(SDState *sd, return sd_r0; } +static int cmd_valid_while_locked(SDState *sd, SDRequest *req) +{ + /* Valid commands in locked state: + * basic class (0) + * lock card class (7) + * CMD16 + * implicitly, the ACMD prefix CMD55 + * ACMD41 and ACMD42 + * Anything else provokes an "illegal command" response. + */ + if (sd->card_status & APP_CMD) { + return req->cmd == 41 || req->cmd == 42; + } + if (req->cmd == 16 || req->cmd == 55) { + return 1; + } + return sd_cmd_class[req->cmd] == 0 || sd_cmd_class[req->cmd] == 7; +} + int sd_do_command(SDState *sd, SDRequest *req, uint8_t *response) { uint32_t last_status = sd->card_status; @@ -1283,17 +1302,13 @@ int sd_do_command(SDState *sd, SDRequest *req, sd->card_status &= ~CARD_STATUS_B; sd_set_status(sd); - if (last_status & CARD_IS_LOCKED) - if (((last_status & APP_CMD) && - req->cmd == 41) || - (!(last_status & APP_CMD) && - (sd_cmd_class[req->cmd] == 0 || - sd_cmd_class[req->cmd] == 7 || - req->cmd == 16 || req->cmd == 55))) { + if (last_status & CARD_IS_LOCKED) { + if (!cmd_valid_while_locked(sd, req)) { sd->card_status |= ILLEGAL_COMMAND; fprintf(stderr, "SD: Card is locked\n"); return 0; } + } if (last_status & APP_CMD) { rtype = sd_app_command(sd, *req); -- cgit v1.2.3