From be616e4fe1a11763c1c1a892d9353ff96051d3ea Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Wed, 25 Jul 2018 23:35:57 +0300 Subject: [PATCH] thunderbolt: Add validation for PD (power delivery) pointer Thunderbolt devices typically have a discrete PD (power delivery) controller and firmware for that controller is part of the NVM image. To make sure the supplied NVM image provides the necessary PD firmware we implement a check that compares existence of both PD pointers and fails the validation if they differ. Since the PD pointer is part of ARC_PARAMS section we need to populate that section offset also for hosts (following DROM section). Signed-off-by: Mika Westerberg --- plugins/thunderbolt/fu-thunderbolt-image.c | 42 ++++++++++++++++++++-- 1 file changed, 40 insertions(+), 2 deletions(-) diff --git a/plugins/thunderbolt/fu-thunderbolt-image.c b/plugins/thunderbolt/fu-thunderbolt-image.c index a68ca4bd5..268ed43bc 100644 --- a/plugins/thunderbolt/fu-thunderbolt-image.c +++ b/plugins/thunderbolt/fu-thunderbolt-image.c @@ -72,6 +72,12 @@ valid_farb_pointer (guint32 pointer) return pointer != 0 && pointer != 0xFFFFFF; } +static inline gboolean +valid_pd_pointer (guint32 pointer) +{ + return pointer != 0 && pointer != 0xFFFFFFFF; +} + /* returns NULL on error */ static GByteArray * read_location (const FuThunderboltFwLocation *location, @@ -249,9 +255,7 @@ read_sections (const FuThunderboltFwObject *fw, gboolean is_host, guint gen, GEr if (!read_uint32 (&drom_offset, fw, &offset, error)) return FALSE; fw->sections[DROM_SECTION] = offset + fw->sections[DIGITAL_SECTION]; - } - if (!is_host) { if (!read_uint32 (&arc_params_offset, fw, &offset, error)) return FALSE; fw->sections[ARC_PARAMS_SECTION] = offset + fw->sections[DIGITAL_SECTION]; @@ -474,6 +478,37 @@ compare_locations (const FuThunderboltFwLocation **locations, return TRUE; } +static gboolean +compare_pd_existence (guint16 id, + const FuThunderboltFwObject *controller, + const FuThunderboltFwObject *image, + GError **error) +{ + const FuThunderboltFwLocation pd_pointer_loc = { .offset = 0x10C, .len = 4, .section = ARC_PARAMS_SECTION, .description = "PD pointer" }; + gboolean controller_has_pd; + gboolean image_has_pd; + guint32 pd_pointer; + + if (controller->sections[ARC_PARAMS_SECTION] == 0) + return TRUE; + + if (!read_uint32 (&pd_pointer_loc, controller, &pd_pointer, error)) + return FALSE; + controller_has_pd = valid_pd_pointer (pd_pointer); + + if (!read_uint32 (&pd_pointer_loc, image, &pd_pointer, error)) + return FALSE; + image_has_pd = valid_pd_pointer (pd_pointer); + + if (controller_has_pd != image_has_pd) { + g_set_error_literal (error, FWUPD_ERROR, FWUPD_ERROR_INVALID_FILE, + "PD section mismatch"); + return FALSE; + } + + return TRUE; +} + FuPluginValidation fu_plugin_thunderbolt_validate_image (GBytes *controller_fw, GBytes *blob_fw, @@ -570,6 +605,9 @@ fu_plugin_thunderbolt_validate_image (GBytes *controller_fw, return VALIDATION_FAILED; } + if (!compare_pd_existence (hw_info->id, &controller, &image, error)) + return VALIDATION_FAILED; + /* * 0 is for the unknown device case, for being future-compatible with * new devices; so we can't know which locations to check besides the