/* * Copyright (C) 2020 Mario Limonciello * * SPDX-License-Identifier: LGPL-2.1+ */ #include "config.h" #include #include "fu-common.h" #include "fu-thunderbolt-firmware.h" #include "fu-thunderbolt-firmware-update.h" struct _FuThunderboltFirmwareUpdate { FuThunderboltFirmwareClass parent_instance; }; G_DEFINE_TYPE (FuThunderboltFirmwareUpdate, fu_thunderbolt_firmware_update, FU_TYPE_THUNDERBOLT_FIRMWARE) static inline gboolean fu_thunderbolt_firmware_valid_farb_pointer (guint32 pointer) { return pointer != 0 && pointer != 0xFFFFFF; } static gboolean fu_thunderbolt_firmware_read_farb_pointer_impl (FuThunderboltFirmwareUpdate *self, FuThunderboltSection section, guint32 offset, guint32 *value, GError **error) { FuThunderboltFirmware *tbt = FU_THUNDERBOLT_FIRMWARE (self); guint32 tmp = 0; if (!fu_thunderbolt_firmware_read_location (tbt, section, offset, (guint8 *) &tmp, 3, /* 24 bits */ error)) { g_prefix_error (error, "failed to read farb pointer: "); return FALSE; } *value = GUINT32_FROM_LE (tmp); return TRUE; } /* returns invalid FARB pointer on error */ static guint32 fu_thunderbolt_firmware_read_farb_pointer (FuThunderboltFirmwareUpdate *self, GError **error) { guint32 value; if (!fu_thunderbolt_firmware_read_farb_pointer_impl (self, _SECTION_DIGITAL, 0x0, &value, error)) return 0; if (fu_thunderbolt_firmware_valid_farb_pointer (value)) return value; if (!fu_thunderbolt_firmware_read_farb_pointer_impl (self, _SECTION_DIGITAL, 0x1000, &value, error)) return 0; if (!fu_thunderbolt_firmware_valid_farb_pointer (value)) { g_set_error_literal (error, FWUPD_ERROR, FWUPD_ERROR_INVALID_FILE, "Invalid FW image file format"); return 0; } return value; } static gboolean fu_thunderbolt_firmware_update_parse (FuFirmware *firmware, GBytes *fw, guint64 addr_start, guint64 addr_end, FwupdInstallFlags flags, GError **error) { FuThunderboltFirmwareUpdate *self = FU_THUNDERBOLT_FIRMWARE_UPDATE (firmware); guint32 offset = fu_thunderbolt_firmware_read_farb_pointer (self, error); if (offset == 0) return FALSE; g_debug ("detected digital section begins at 0x%x", offset); fu_thunderbolt_firmware_set_digital (FU_THUNDERBOLT_FIRMWARE (firmware), offset); return TRUE; } static void fu_thunderbolt_firmware_update_init (FuThunderboltFirmwareUpdate *self) { } static void fu_thunderbolt_firmware_update_class_init (FuThunderboltFirmwareUpdateClass *klass) { FuThunderboltFirmwareClass *klass_firmware = FU_THUNDERBOLT_FIRMWARE_CLASS (klass); klass_firmware->parse = fu_thunderbolt_firmware_update_parse; } FuThunderboltFirmwareUpdate * fu_thunderbolt_firmware_update_new (void) { return g_object_new (FU_TYPE_THUNDERBOLT_FIRMWARE_UPDATE, NULL); }