mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2025-12-29 18:11:05 +00:00
If Cr50 happens to start on a chip where Board ID programmed in INFO1
does not match the contents of the RW header, it means that for some
reason the other RW is not operational and the current image is the
only viable one.
In this case the Cr50 starts but operates in limited mode (only
commands for updating the image and reporting state are handled). In
this case the reason for recovery could be seen on the Recovery
screen, and the update could be done once Chrome OS boots in recovery
mode.
BRANCH=none
BUG=b:35586335
TEST=verified the following:
- if an image with wrong board ID is started, it tries to fall back
(sets the counter to a value above threshold and reboots)
- if the fallback fails, the image keeps running in the limited
capabilities mode but the update is possible, observed that the
new image took over worked after powercycling the device.
- observed proper error message on the recovery screen showing where
the error comes from
Change-Id: I46ba75392f8e891bb8503fb15aea2c56b5805e83
Signed-off-by: Vadim Bendebury <vbendeb@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/535978
Reviewed-by: Randall Spangler <rspangler@chromium.org>
Reviewed-by: Mary Ruthven <mruthven@chromium.org>
113 lines
2.9 KiB
C
113 lines
2.9 KiB
C
/* Copyright 2015 The Chromium OS Authors. All rights reserved.
|
|
* Use of this source code is governed by a BSD-style license that can be
|
|
* found in the LICENSE file.
|
|
*/
|
|
|
|
#include "byteorder.h"
|
|
#include "console.h"
|
|
#include "extension.h"
|
|
#include "link_defs.h"
|
|
#include "util.h"
|
|
|
|
#define CPRINTF(format, args...) cprintf(CC_EXTENSION, format, ## args)
|
|
|
|
static uint32_t extension_route_command(uint16_t command_code,
|
|
void *buffer,
|
|
size_t in_size,
|
|
size_t *out_size)
|
|
{
|
|
struct extension_command *cmd_p;
|
|
struct extension_command *end_p;
|
|
|
|
cmd_p = (struct extension_command *)&__extension_cmds;
|
|
end_p = (struct extension_command *)&__extension_cmds_end;
|
|
|
|
#ifdef CONFIG_BOARD_ID_SUPPORT
|
|
if (board_id_is_mismatched()) {
|
|
switch (command_code) {
|
|
case EXTENSION_FW_UPGRADE:
|
|
case VENDOR_CC_REPORT_TPM_STATE:
|
|
case VENDOR_CC_TURN_UPDATE_ON:
|
|
case EXTENSION_POST_RESET:
|
|
break;
|
|
default:
|
|
CPRINTF("%s: ignoring command 0x%x "
|
|
"due to board ID mismatch\n",
|
|
__func__, command_code);
|
|
return VENDOR_RC_NO_SUCH_COMMAND;
|
|
}
|
|
}
|
|
#endif
|
|
while (cmd_p != end_p) {
|
|
if (cmd_p->command_code == command_code)
|
|
return cmd_p->handler(command_code, buffer,
|
|
in_size, out_size);
|
|
cmd_p++;
|
|
}
|
|
|
|
CPRINTF("%s: handler %d not found\n", __func__, command_code);
|
|
|
|
/* This covers the case of the handler not found. */
|
|
*out_size = 0;
|
|
return VENDOR_RC_NO_SUCH_COMMAND;
|
|
}
|
|
|
|
void usb_extension_route_command(uint16_t command_code,
|
|
void *buffer,
|
|
size_t in_size,
|
|
size_t *out_size)
|
|
{
|
|
uint32_t rv;
|
|
uint8_t *buf = buffer; /* Cache it for easy pointer arithmetics. */
|
|
size_t buf_size;
|
|
|
|
switch (command_code) {
|
|
#ifdef CR50_DEV
|
|
case VENDOR_CC_IMMEDIATE_RESET:
|
|
case VENDOR_CC_INVALIDATE_INACTIVE_RW:
|
|
case VENDOR_CC_SET_BOARD_ID:
|
|
#endif /* defined(CR50_DEV) */
|
|
case EXTENSION_POST_RESET: /* Always need to be able to reset. */
|
|
case VENDOR_CC_GET_BOARD_ID:
|
|
case VENDOR_CC_TURN_UPDATE_ON:
|
|
|
|
/*
|
|
* The return code normally put into the TPM response header
|
|
* is not present in the USB response. Vendor command return
|
|
* code is guaranteed to fit in a byte. Let's keep space for
|
|
* it in the front of the buffer.
|
|
*/
|
|
buf_size = *out_size - 1;
|
|
rv = extension_route_command(command_code, buffer,
|
|
in_size, &buf_size);
|
|
/*
|
|
* Copy actual response, if any, one byte up, to free room for
|
|
* the return code.
|
|
*/
|
|
if (buf_size)
|
|
memmove(buf + 1, buf, buf_size);
|
|
*out_size = buf_size + 1;
|
|
break;
|
|
|
|
default:
|
|
/* Otherwise, we don't allow this command. */
|
|
CPRINTF("%s: ignoring vendor cmd %d\n", __func__, command_code);
|
|
*out_size = 1;
|
|
rv = VENDOR_RC_NO_SUCH_COMMAND;
|
|
break;
|
|
}
|
|
|
|
buf[0] = rv; /* We care about LSB only. */
|
|
}
|
|
|
|
uint32_t tpm_extension_route_command(uint16_t command_code,
|
|
void *buffer,
|
|
size_t in_size,
|
|
size_t *out_size)
|
|
{
|
|
/*
|
|
* TODO(aaboagye): Determine what commands (if any) should be filtered.
|
|
*/
|
|
return extension_route_command(command_code, buffer, in_size, out_size);
|
|
}
|