diff --git a/plugins/cros-ec/fu-cros-ec-common.c b/plugins/cros-ec/fu-cros-ec-common.c new file mode 100644 index 000000000..07111b40a --- /dev/null +++ b/plugins/cros-ec/fu-cros-ec-common.c @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2020 Benson Leung + * + * SPDX-License-Identifier: LGPL-2.1+ + */ + +#include "config.h" + +#include + +#include "fu-cros-ec-common.h" + +gboolean +fu_cros_ec_parse_version (const gchar *version_raw, + struct cros_ec_version *version, GError **error) +{ + g_auto(GStrv) v_split = NULL; + g_auto(GStrv) marker_split = NULL; + g_auto(GStrv) triplet_split = NULL; + + if (NULL == version_raw || 0 == strlen (version_raw)) { + g_set_error_literal (error, + FWUPD_ERROR, + FWUPD_ERROR_INTERNAL, + "no version string to parse"); + return FALSE; + } + + /* sample version string: cheese_v1.1.1755-4da9520 */ + v_split = g_strsplit (version_raw, "_v", 2); + if (g_strv_length (v_split) < 2) { + g_set_error_literal (error, + FWUPD_ERROR, + FWUPD_ERROR_INTERNAL, + "version marker not found"); + return FALSE; + } + marker_split = g_strsplit_set (v_split[1], "-+", 2); + if (g_strv_length (marker_split) < 2) { + g_set_error (error, + FWUPD_ERROR, + FWUPD_ERROR_INTERNAL, + "hash marker not found: %s", v_split[1]); + return FALSE; + } + triplet_split = g_strsplit_set (marker_split[0], ".", 3); + if (g_strv_length (triplet_split) < 3) { + g_set_error (error, + FWUPD_ERROR, + FWUPD_ERROR_INTERNAL, + "improper version triplet: %s", marker_split[0]); + return FALSE; + } + g_strlcpy (version->triplet, marker_split[0], 32); + if (g_strlcpy (version->boardname, v_split[0], 32) == 0) { + g_set_error_literal (error, + FWUPD_ERROR, + FWUPD_ERROR_INTERNAL, + "empty board name"); + return FALSE; + } + if (g_strlcpy (version->sha1, marker_split[1], 32) == 0) { + g_set_error_literal (error, + FWUPD_ERROR, + FWUPD_ERROR_INTERNAL, + "empty SHA"); + return FALSE; + } + version->dirty = (g_strrstr(v_split[1], "+") != NULL); + + return TRUE; +} diff --git a/plugins/cros-ec/fu-cros-ec-common.h b/plugins/cros-ec/fu-cros-ec-common.h index b5fd8a8e7..e7e07c9c2 100644 --- a/plugins/cros-ec/fu-cros-ec-common.h +++ b/plugins/cros-ec/fu-cros-ec-common.h @@ -4,6 +4,12 @@ * SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +#include "fu-plugin.h" + #define UPDATE_PROTOCOL_VERSION 6 /* @@ -123,3 +129,14 @@ enum first_response_pdu_header_type { UPDATE_HEADER_TYPE_CR50 = 0, /* Must be 0 for backwards compatibility */ UPDATE_HEADER_TYPE_COMMON = 1, }; + +struct cros_ec_version { + gchar boardname[32]; + gchar triplet[32]; + gchar sha1[32]; + gboolean dirty; +}; + +gboolean fu_cros_ec_parse_version (const gchar *version_raw, + struct cros_ec_version *version, + GError **error); diff --git a/plugins/cros-ec/fu-cros-ec-usb-device.c b/plugins/cros-ec/fu-cros-ec-usb-device.c index eaf49b385..104e7a84d 100644 --- a/plugins/cros-ec/fu-cros-ec-usb-device.c +++ b/plugins/cros-ec/fu-cros-ec-usb-device.c @@ -20,14 +20,15 @@ #define BULK_RECV_TIMEOUT_MS 5000 struct _FuCrosEcUsbDevice { - FuUsbDevice parent_instance; - guint8 iface_idx; /* bInterfaceNumber */ - guint8 ep_num; /* bEndpointAddress */ - guint16 chunk_len; /* wMaxPacketSize */ + FuUsbDevice parent_instance; + guint8 iface_idx; /* bInterfaceNumber */ + guint8 ep_num; /* bEndpointAddress */ + guint16 chunk_len; /* wMaxPacketSize */ - struct first_response_pdu targ; - guint16 protocol_version; - guint16 header_type; + struct first_response_pdu targ; + guint16 protocol_version; + guint16 header_type; + struct cros_ec_version version; }; G_DEFINE_TYPE (FuCrosEcUsbDevice, fu_cros_ec_usb_device, FU_TYPE_USB_DEVICE) @@ -279,7 +280,15 @@ fu_cros_ec_usb_device_setup (FuDevice *device, GError **error) self->targ.common.min_rollback = GINT32_FROM_BE (start_resp.rpdu.common.min_rollback); self->targ.common.key_version = GUINT32_FROM_BE (start_resp.rpdu.common.key_version); - fu_device_set_version (FU_DEVICE (device), self->targ.common.version); + if (!fu_cros_ec_parse_version (self->targ.common.version, + &self->version, error)) { + g_prefix_error (error, + "failed parsing device's version: %32s: ", + self->targ.common.version); + return FALSE; + } + + fu_device_set_version (FU_DEVICE (device), self->version.triplet); /* success */ return TRUE; @@ -305,7 +314,7 @@ fu_cros_ec_usb_device_close (FuUsbDevice *device, GError **error) static void fu_cros_ec_usb_device_init (FuCrosEcUsbDevice *device) { - fu_device_set_version_format (FU_DEVICE (device), FWUPD_VERSION_FORMAT_PLAIN); + fu_device_set_version_format (FU_DEVICE (device), FWUPD_VERSION_FORMAT_TRIPLET); } static void diff --git a/plugins/cros-ec/meson.build b/plugins/cros-ec/meson.build index 9764abeda..ff41c03d9 100644 --- a/plugins/cros-ec/meson.build +++ b/plugins/cros-ec/meson.build @@ -9,6 +9,7 @@ shared_module('fu_plugin_cros_ec', sources : [ 'fu-plugin-cros-ec.c', 'fu-cros-ec-usb-device.c', + 'fu-cros-ec-common.c', ], include_directories : [ root_incdir, @@ -18,6 +19,7 @@ shared_module('fu_plugin_cros_ec', install : true, install_dir: plugin_dir, link_with : [ + fwupd, fwupdplugin, ], c_args : cargs,