mirror of
https://git.proxmox.com/git/fwupd
synced 2025-05-02 16:45:45 +00:00
116 lines
2.9 KiB
C
116 lines
2.9 KiB
C
/*
|
|
* Copyright (C) 2020 Mario Limonciello <mario.limonciello@dell.com>
|
|
*
|
|
* SPDX-License-Identifier: LGPL-2.1+
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include <fwupdplugin.h>
|
|
|
|
#include "fu-thunderbolt-firmware-update.h"
|
|
#include "fu-thunderbolt-firmware.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);
|
|
}
|