summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--common/system.c28
-rw-r--r--include/ec_commands.h23
-rw-r--r--util/ectool.c21
3 files changed, 51 insertions, 21 deletions
diff --git a/common/system.c b/common/system.c
index 985d64752e..1670857241 100644
--- a/common/system.c
+++ b/common/system.c
@@ -1568,16 +1568,12 @@ DECLARE_CONSOLE_COMMAND(rflags, command_rflags,
static enum ec_status
host_command_get_version(struct host_cmd_handler_args *args)
{
- struct ec_response_get_version *r = args->response;
+ struct ec_response_get_version_v1 *r = args->response;
enum ec_image active_slot = system_get_active_copy();
- /* Clear optional fields (i.e. cros_fwid). */
- memset(r, 0, sizeof(*r));
-
strzcpy(r->version_string_ro, system_get_version(EC_IMAGE_RO),
sizeof(r->version_string_ro));
- strzcpy(r->version_string_rw,
- system_get_version(active_slot),
+ strzcpy(r->version_string_rw, system_get_version(active_slot),
sizeof(r->version_string_rw));
switch (system_get_image_copy()) {
@@ -1593,18 +1589,30 @@ host_command_get_version(struct host_cmd_handler_args *args)
break;
}
+ /*
+ * Assuming args->response is zero'd in host_command_process, so no need
+ * to zero uninitialized fields here.
+ */
if (args->version > 0 && IS_ENABLED(CONFIG_CROS_FWID_VERSION)) {
strzcpy(r->cros_fwid_ro, system_get_cros_fwid(EC_IMAGE_RO),
sizeof(r->cros_fwid_ro));
strzcpy(r->cros_fwid_rw, system_get_cros_fwid(EC_IMAGE_RW),
sizeof(r->cros_fwid_rw));
}
+
+ /*
+ * By convention, ec_response_get_version_v1 is a strict superset of
+ * ec_response_get_version(v0). The v1 response changes the semantics
+ * of one field (reserved to cros_fwid_ro) and adds one additional field
+ * (cros_fwid_rw). So simply adjusting the response size here is safe.
+ */
if (args->version == 0)
- /* cros_fwid_rw[32] is not present in version 0 */
- args->response_size =
- offsetof(struct ec_response_get_version, cros_fwid_rw);
- else
args->response_size = sizeof(struct ec_response_get_version);
+ else if (args->version == 1)
+ args->response_size = sizeof(struct ec_response_get_version_v1);
+ else
+ /* Shouldn't happen because of EC_VER_MASK */
+ return EC_RES_INVALID_VERSION;
return EC_RES_SUCCESS;
}
diff --git a/include/ec_commands.h b/include/ec_commands.h
index 6e9c538e5e..95431babad 100644
--- a/include/ec_commands.h
+++ b/include/ec_commands.h
@@ -1149,14 +1149,33 @@ enum ec_image {
};
/**
- * struct ec_response_get_version - Response to the get version command.
+ * struct ec_response_get_version - Response to the v0 get version command.
+ * @version_string_ro: Null-terminated RO firmware version string.
+ * @version_string_rw: Null-terminated RW firmware version string.
+ * @reserved: Unused bytes; was previously RW-B firmware version string.
+ * @current_image: One of ec_image.
+ */
+struct ec_response_get_version {
+ char version_string_ro[32];
+ char version_string_rw[32];
+ char reserved[32]; /* Changed to cros_fwid_ro in version 1 */
+ uint32_t current_image;
+} __ec_align4;
+
+/**
+ * struct ec_response_get_version_v1 - Response to the v1 get version command.
+ *
+ * ec_response_get_version_v1 is a strict superset of ec_response_get_version.
+ * The v1 response changes the semantics of one field (reserved to cros_fwid_ro)
+ * and adds one additional field (cros_fwid_rw).
+ *
* @version_string_ro: Null-terminated RO firmware version string.
* @version_string_rw: Null-terminated RW firmware version string.
* @cros_fwid_ro: Null-terminated RO CrOS FWID string.
* @current_image: One of ec_image.
* @cros_fwid_rw: Null-terminated RW CrOS FWID string.
*/
-struct ec_response_get_version {
+struct ec_response_get_version_v1 {
char version_string_ro[32];
char version_string_rw[32];
char cros_fwid_ro[32]; /* Added in version 1 (Used to be reserved) */
diff --git a/util/ectool.c b/util/ectool.c
index 4f983e24f1..79e496f262 100644
--- a/util/ectool.c
+++ b/util/ectool.c
@@ -1069,23 +1069,26 @@ int cmd_uptimeinfo(int argc, char *argv[])
int cmd_version(int argc, char *argv[])
{
- struct ec_response_get_version r;
+ struct ec_response_get_version_v1 r;
char *build_string = (char *)ec_inbuf;
- int cmdver = 1;
int rv;
- if (!ec_cmd_version_supported(EC_CMD_GET_VERSION, 1)) {
- cmdver = 0;
- /* CrOS FWID is not supported. Set it to empty string. */
+ if (ec_cmd_version_supported(EC_CMD_GET_VERSION, 1)) {
+ rv = ec_command(EC_CMD_GET_VERSION, 1, NULL, 0, &r,
+ sizeof(struct ec_response_get_version_v1));
+ } else {
+ /* Fall-back to version 0 if version 1 is not supported */
+ rv = ec_command(EC_CMD_GET_VERSION, 0, NULL, 0, &r,
+ sizeof(struct ec_response_get_version));
+ /* These fields are not supported in version 0, ensure empty */
r.cros_fwid_ro[0] = '\0';
r.cros_fwid_rw[0] = '\0';
}
-
- rv = ec_command(EC_CMD_GET_VERSION, cmdver, NULL, 0, &r, sizeof(r));
if (rv < 0) {
fprintf(stderr, "ERROR: EC_CMD_GET_VERSION failed: %d\n", rv);
goto exit;
}
+
rv = ec_command(EC_CMD_GET_BUILD_INFO, 0,
NULL, 0, ec_inbuf, ec_max_insize);
if (rv < 0) {
@@ -1104,10 +1107,10 @@ int cmd_version(int argc, char *argv[])
r.cros_fwid_rw[sizeof(r.cros_fwid_rw) - 1] = '\0';
/* Print versions */
printf("RO version: %s\n", r.version_string_ro);
- if (cmdver > 0 && strlen(r.cros_fwid_ro))
+ if (strlen(r.cros_fwid_ro))
printf("RO cros fwid: %s\n", r.cros_fwid_ro);
printf("RW version: %s\n", r.version_string_rw);
- if (cmdver > 0 && strlen(r.cros_fwid_rw))
+ if (strlen(r.cros_fwid_rw))
printf("RW cros fwid: %s\n", r.cros_fwid_rw);
printf("Firmware copy: %s\n",
(r.current_image < ARRAY_SIZE(image_names) ?