提交 25881d33 编写于 作者: P Peter Maydell 提交者: Andrzej Zaborowski

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: NPeter Maydell <peter.maydell@linaro.org>
Signed-off-by: NAndrzej Zaborowski <andrew.zaborowski@intel.com>
上级 e114fead
...@@ -1265,6 +1265,25 @@ static sd_rsp_type_t sd_app_command(SDState *sd, ...@@ -1265,6 +1265,25 @@ static sd_rsp_type_t sd_app_command(SDState *sd,
return sd_r0; 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, int sd_do_command(SDState *sd, SDRequest *req,
uint8_t *response) { uint8_t *response) {
uint32_t last_status = sd->card_status; uint32_t last_status = sd->card_status;
...@@ -1283,17 +1302,13 @@ int sd_do_command(SDState *sd, SDRequest *req, ...@@ -1283,17 +1302,13 @@ int sd_do_command(SDState *sd, SDRequest *req,
sd->card_status &= ~CARD_STATUS_B; sd->card_status &= ~CARD_STATUS_B;
sd_set_status(sd); sd_set_status(sd);
if (last_status & CARD_IS_LOCKED) if (last_status & CARD_IS_LOCKED) {
if (((last_status & APP_CMD) && if (!cmd_valid_while_locked(sd, req)) {
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))) {
sd->card_status |= ILLEGAL_COMMAND; sd->card_status |= ILLEGAL_COMMAND;
fprintf(stderr, "SD: Card is locked\n"); fprintf(stderr, "SD: Card is locked\n");
return 0; return 0;
} }
}
if (last_status & APP_CMD) { if (last_status & APP_CMD) {
rtype = sd_app_command(sd, *req); rtype = sd_app_command(sd, *req);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册