fwupd/plugins/analogix/fu-analogix-firmware.c
Analogix b518c536c7
analogic: Fix various trivial problems to enable successful device update
* Changed CUSTOM Define firmware size. 
* Extended time for transferring data time out.

Co-authored-by: xtcui <xtcui@analogix.corp-partner.google.com>
2021-04-13 08:39:18 +01:00

132 lines
4.0 KiB
C

/*
* Copyright (C) 2021 Xiaotian Cui <xtcui@analogixsemi.com>
*
* SPDX-License-Identifier: LGPL-2.1+
*/
#include "config.h"
#include "fu-analogix-common.h"
#include "fu-analogix-firmware.h"
struct _FuAnalogixFirmware {
FuIhexFirmwareClass parent_instance;
};
G_DEFINE_TYPE (FuAnalogixFirmware, fu_analogix_firmware, FU_TYPE_IHEX_FIRMWARE)
static gboolean
fu_analogix_firmware_parse (FuFirmware *firmware,
GBytes *fw,
guint64 addr_start,
guint64 addr_end,
FwupdInstallFlags flags,
GError **error)
{
FuFirmwareClass *klass = FU_FIRMWARE_CLASS (fu_analogix_firmware_parent_class);
const guint8 *buf = NULL;
gsize bufsz = 0;
guint16 ocm_version;
guint8 version_hi = 0;
guint8 version_lo = 0;
g_autofree gchar *version = NULL;
g_autoptr(FuFirmware) fw_ocm = NULL;
g_autoptr(GBytes) blob_cus = NULL;
g_autoptr(GBytes) blob = NULL;
g_autoptr(GBytes) blob_ocm = NULL;
g_autoptr(GBytes) blob_srx = NULL;
g_autoptr(GBytes) blob_stx = NULL;
/* convert to binary with FuIhexFirmware->parse */
if (!klass->parse (firmware, fw, addr_start, addr_end, flags, error))
return FALSE;
blob = fu_firmware_get_bytes (firmware, error);
if (blob == NULL)
return FALSE;
/* OCM section only, CUSTOM section only, or multiple sections excluded CUSTOM */
if (g_bytes_get_size (blob) == OCM_FLASH_SIZE) {
blob_ocm = g_bytes_ref (blob);
} else if (g_bytes_get_size (blob) == CUSTOM_FLASH_SIZE) {
/* custom */
blob_cus = fu_common_bytes_new_offset (blob, 0, CUSTOM_FLASH_SIZE, error);
} else {
blob_ocm = fu_common_bytes_new_offset (blob, 0, OCM_FLASH_SIZE, error);
if (blob_ocm == NULL)
return FALSE;
}
if (blob_ocm != NULL) {
fw_ocm = fu_firmware_new_from_bytes (blob_ocm);
fu_firmware_set_id (fw_ocm, "ocm");
fu_firmware_set_addr (fw_ocm, FLASH_OCM_ADDR);
fu_firmware_add_image (firmware, fw_ocm);
/* get OCM version */
buf = g_bytes_get_data (blob_ocm, &bufsz);
if (!fu_common_read_uint8_safe (buf, bufsz, OCM_FW_VERSION_ADDR -
FLASH_OCM_ADDR + 8,
&version_hi, error))
return FALSE;
if (!fu_common_read_uint8_safe (buf, bufsz, OCM_FW_VERSION_ADDR -
FLASH_OCM_ADDR + 12,
&version_lo, error))
return FALSE;
ocm_version = ((guint16) version_hi) << 8 | version_lo;
fu_firmware_set_version_raw (fw_ocm, ocm_version);
version = g_strdup_printf ("%02x.%02x", version_hi, version_lo);
fu_firmware_set_version (fw_ocm, version);
}
/* TXFW is optional */
blob_stx = fu_common_bytes_new_offset (blob,
FLASH_TXFW_ADDR - FLASH_OCM_ADDR,
SECURE_OCM_TX_SIZE,
NULL);
if (blob_stx != NULL && !fu_common_bytes_is_empty (blob_stx)) {
g_autoptr(FuFirmware) fw2 = fu_firmware_new_from_bytes (blob_stx);
fu_firmware_set_id (fw2, "stx");
fu_firmware_set_addr (fw2, FLASH_TXFW_ADDR);
fu_firmware_add_image (firmware, fw2);
}
/* RXFW is optional */
blob_srx = fu_common_bytes_new_offset (blob,
FLASH_RXFW_ADDR - FLASH_OCM_ADDR,
SECURE_OCM_RX_SIZE,
NULL);
if (blob_srx != NULL && !fu_common_bytes_is_empty (blob_srx)) {
g_autoptr(FuFirmware) fw2 = fu_firmware_new_from_bytes (blob_srx);
fu_firmware_set_id (fw2, "srx");
fu_firmware_set_addr (fw2, FLASH_RXFW_ADDR);
fu_firmware_add_image (firmware, fw2);
}
if (blob_cus != NULL && !fu_common_bytes_is_empty (blob_cus)) {
g_autoptr(FuFirmware) fw2 = fu_firmware_new_from_bytes (blob_cus);
fu_firmware_set_id (fw2, "custom");
fu_firmware_set_addr (fw2, FLASH_CUSTOM_ADDR);
fu_firmware_add_image (firmware, fw2);
}
/* success */
return TRUE;
}
static void
fu_analogix_firmware_init (FuAnalogixFirmware *self)
{
fu_ihex_firmware_set_padding_value (FU_IHEX_FIRMWARE (self), 0xFF);
}
static void
fu_analogix_firmware_class_init (FuAnalogixFirmwareClass *klass)
{
FuFirmwareClass *klass_firmware = FU_FIRMWARE_CLASS (klass);
klass_firmware->parse = fu_analogix_firmware_parse;
}
FuFirmware *
fu_analogix_firmware_new (void)
{
return FU_FIRMWARE (g_object_new (FU_TYPE_ANALOGIX_FIRMWARE, NULL));
}