mirror of
https://git.proxmox.com/git/fwupd
synced 2025-08-12 12:32:26 +00:00
Add support for IFWI Intel Code Partition (aka CPD) firmware
This commit is contained in:
parent
ffac50c55d
commit
f1542c3f9f
@ -350,6 +350,7 @@ def _build(bld: Builder) -> None:
|
||||
Fuzzer("fmap"),
|
||||
Fuzzer("ihex"),
|
||||
Fuzzer("srec"),
|
||||
Fuzzer("ifwi-cpd"),
|
||||
Fuzzer("uswid"),
|
||||
Fuzzer("efi-firmware-filesystem", pattern="efi-firmware-filesystem"),
|
||||
Fuzzer("efi-firmware-volume", pattern="efi-firmware-volume"),
|
||||
|
462
libfwupdplugin/fu-ifwi-cpd-firmware.c
Normal file
462
libfwupdplugin/fu-ifwi-cpd-firmware.c
Normal file
@ -0,0 +1,462 @@
|
||||
/*
|
||||
* Copyright (C) 2022 Richard Hughes <richard@hughsie.com>
|
||||
* Copyright (C) 2022 Intel
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1+
|
||||
*/
|
||||
|
||||
#define G_LOG_DOMAIN "FuFirmware"
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "fu-byte-array.h"
|
||||
#include "fu-bytes.h"
|
||||
#include "fu-ifwi-cpd-firmware.h"
|
||||
#include "fu-mem.h"
|
||||
#include "fu-string.h"
|
||||
|
||||
/**
|
||||
* FuIfwiCpdFirmware:
|
||||
*
|
||||
* An Intel Code Partition Directory (aka CPD) can be found in IFWI (Integrated Firmware Image)
|
||||
* firmware blobs which are used in various Intel products using an IPU (Infrastructure Processing
|
||||
* Unit).
|
||||
*
|
||||
* This could include hardware like SmartNICs, GPUs, camera and audio devices.
|
||||
*
|
||||
* See also: [class@FuFirmware]
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
guint8 header_version;
|
||||
guint8 entry_version;
|
||||
} FuIfwiCpdFirmwarePrivate;
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE(FuIfwiCpdFirmware, fu_ifwi_cpd_firmware, FU_TYPE_FIRMWARE)
|
||||
#define GET_PRIVATE(o) (fu_ifwi_cpd_firmware_get_instance_private(o))
|
||||
|
||||
#define FU_IFWI_CPD_FIRMWARE_HEADER_MARKER 0x44504324
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
guint32 header_marker;
|
||||
guint32 num_of_entries;
|
||||
guint8 header_version;
|
||||
guint8 entry_version;
|
||||
guint8 header_length;
|
||||
guint8 checksum;
|
||||
guint32 partition_name;
|
||||
guint32 crc32;
|
||||
} FuIfwiCpdHeader;
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
gchar name[12];
|
||||
guint32 offset;
|
||||
guint32 length;
|
||||
guint8 reserved1[4];
|
||||
} FuIfwiCpdEntry;
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
guint32 header_type;
|
||||
guint32 header_length; /* dwords */
|
||||
guint32 header_version;
|
||||
guint32 flags;
|
||||
guint32 vendor;
|
||||
guint32 date;
|
||||
guint32 size; /* dwords */
|
||||
guint32 id;
|
||||
guint32 rsvd;
|
||||
guint64 version;
|
||||
guint32 svn;
|
||||
} FuIfwiCpdManifestHeader;
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
guint32 extension_type;
|
||||
guint32 extension_length;
|
||||
} FuIfwiCpdManifestExtHeader;
|
||||
|
||||
static void
|
||||
fu_ifwi_cpd_firmware_export(FuFirmware *firmware, FuFirmwareExportFlags flags, XbBuilderNode *bn)
|
||||
{
|
||||
FuIfwiCpdFirmware *self = FU_IFWI_CPD_FIRMWARE(firmware);
|
||||
FuIfwiCpdFirmwarePrivate *priv = GET_PRIVATE(self);
|
||||
fu_xmlb_builder_insert_kx(bn, "header_version", priv->header_version);
|
||||
fu_xmlb_builder_insert_kx(bn, "entry_version", priv->entry_version);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
fu_ifwi_cpd_firmware_parse_manifest(FuFirmware *firmware, GBytes *fw, GError **error)
|
||||
{
|
||||
gsize bufsz = 0;
|
||||
guint32 header_length = 0;
|
||||
guint32 size = 0;
|
||||
guint64 version = 0;
|
||||
gsize offset = 0;
|
||||
const guint8 *buf = g_bytes_get_data(fw, &bufsz);
|
||||
|
||||
/* raw version */
|
||||
if (!fu_memread_uint64_safe(buf,
|
||||
bufsz,
|
||||
G_STRUCT_OFFSET(FuIfwiCpdManifestHeader, version),
|
||||
&version,
|
||||
G_LITTLE_ENDIAN,
|
||||
error))
|
||||
return FALSE;
|
||||
fu_firmware_set_version_raw(firmware, version);
|
||||
|
||||
/* verify the size */
|
||||
if (!fu_memread_uint32_safe(buf,
|
||||
bufsz,
|
||||
G_STRUCT_OFFSET(FuIfwiCpdManifestHeader, size),
|
||||
&size,
|
||||
G_LITTLE_ENDIAN,
|
||||
error))
|
||||
return FALSE;
|
||||
if (size * 4 != bufsz) {
|
||||
g_set_error(error,
|
||||
G_IO_ERROR,
|
||||
G_IO_ERROR_INVALID_DATA,
|
||||
"invalid manifest invalid length, got 0x%x, expected 0x%x",
|
||||
size * 4,
|
||||
(guint)bufsz);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* parse extensions */
|
||||
if (!fu_memread_uint32_safe(buf,
|
||||
bufsz,
|
||||
G_STRUCT_OFFSET(FuIfwiCpdManifestHeader, header_length),
|
||||
&header_length,
|
||||
G_LITTLE_ENDIAN,
|
||||
error))
|
||||
return FALSE;
|
||||
offset += header_length * 4;
|
||||
while (offset < bufsz) {
|
||||
guint32 extension_type = 0;
|
||||
guint32 extension_length = 0;
|
||||
g_autoptr(GBytes) blob = NULL;
|
||||
g_autoptr(FuFirmware) img = fu_firmware_new();
|
||||
|
||||
/* set the extension type as the index */
|
||||
if (!fu_memread_uint32_safe(
|
||||
buf,
|
||||
bufsz,
|
||||
offset + G_STRUCT_OFFSET(FuIfwiCpdManifestExtHeader, extension_type),
|
||||
&extension_type,
|
||||
G_LITTLE_ENDIAN,
|
||||
error))
|
||||
return FALSE;
|
||||
if (extension_type == 0x0)
|
||||
break;
|
||||
fu_firmware_set_idx(img, extension_type);
|
||||
|
||||
/* add data section */
|
||||
if (!fu_memread_uint32_safe(
|
||||
buf,
|
||||
bufsz,
|
||||
offset + G_STRUCT_OFFSET(FuIfwiCpdManifestExtHeader, extension_length),
|
||||
&extension_length,
|
||||
G_LITTLE_ENDIAN,
|
||||
error))
|
||||
return FALSE;
|
||||
if (extension_length == 0x0)
|
||||
break;
|
||||
if (extension_length < sizeof(FuIfwiCpdManifestExtHeader)) {
|
||||
g_set_error(error,
|
||||
G_IO_ERROR,
|
||||
G_IO_ERROR_INVALID_DATA,
|
||||
"invalid manifest extension header length 0x%x",
|
||||
(guint)extension_length);
|
||||
return FALSE;
|
||||
}
|
||||
blob = fu_bytes_new_offset(fw,
|
||||
offset + sizeof(FuIfwiCpdManifestExtHeader),
|
||||
extension_length - sizeof(FuIfwiCpdManifestExtHeader),
|
||||
error);
|
||||
if (blob == NULL)
|
||||
return FALSE;
|
||||
fu_firmware_set_bytes(img, blob);
|
||||
|
||||
/* success */
|
||||
fu_firmware_set_offset(img, offset);
|
||||
fu_firmware_add_image(firmware, img);
|
||||
offset += extension_length;
|
||||
}
|
||||
|
||||
/* success */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
fu_ifwi_cpd_firmware_parse(FuFirmware *firmware,
|
||||
GBytes *fw,
|
||||
gsize offset,
|
||||
FwupdInstallFlags flags,
|
||||
GError **error)
|
||||
{
|
||||
FuIfwiCpdFirmware *self = FU_IFWI_CPD_FIRMWARE(firmware);
|
||||
FuIfwiCpdFirmwarePrivate *priv = GET_PRIVATE(self);
|
||||
gsize bufsz = 0;
|
||||
guint32 header_marker = 0;
|
||||
guint32 num_of_entries = 0;
|
||||
guint32 partition_name = 0;
|
||||
guint8 header_length = 0;
|
||||
const guint8 *buf = g_bytes_get_data(fw, &bufsz);
|
||||
|
||||
/* verify header marker */
|
||||
if (!fu_memread_uint32_safe(buf,
|
||||
bufsz,
|
||||
offset + G_STRUCT_OFFSET(FuIfwiCpdHeader, header_marker),
|
||||
&header_marker,
|
||||
G_LITTLE_ENDIAN,
|
||||
error))
|
||||
return FALSE;
|
||||
if (header_marker != FU_IFWI_CPD_FIRMWARE_HEADER_MARKER) {
|
||||
g_set_error(error,
|
||||
G_IO_ERROR,
|
||||
G_IO_ERROR_INVALID_DATA,
|
||||
"invalid CPD header marker 0x%x, expected 0x%x",
|
||||
header_marker,
|
||||
(guint)FU_IFWI_CPD_FIRMWARE_HEADER_MARKER);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* other header fields */
|
||||
if (!fu_memread_uint8_safe(buf,
|
||||
bufsz,
|
||||
offset + G_STRUCT_OFFSET(FuIfwiCpdHeader, header_version),
|
||||
&priv->header_version,
|
||||
error))
|
||||
return FALSE;
|
||||
if (!fu_memread_uint8_safe(buf,
|
||||
bufsz,
|
||||
offset + G_STRUCT_OFFSET(FuIfwiCpdHeader, entry_version),
|
||||
&priv->entry_version,
|
||||
error))
|
||||
return FALSE;
|
||||
if (!fu_memread_uint8_safe(buf,
|
||||
bufsz,
|
||||
offset + G_STRUCT_OFFSET(FuIfwiCpdHeader, header_length),
|
||||
&header_length,
|
||||
error))
|
||||
return FALSE;
|
||||
if (!fu_memread_uint32_safe(buf,
|
||||
bufsz,
|
||||
offset + G_STRUCT_OFFSET(FuIfwiCpdHeader, partition_name),
|
||||
&partition_name,
|
||||
G_LITTLE_ENDIAN,
|
||||
error))
|
||||
return FALSE;
|
||||
fu_firmware_set_idx(firmware, partition_name);
|
||||
|
||||
/* read out entries */
|
||||
if (!fu_memread_uint32_safe(buf,
|
||||
bufsz,
|
||||
offset + G_STRUCT_OFFSET(FuIfwiCpdHeader, num_of_entries),
|
||||
&num_of_entries,
|
||||
G_LITTLE_ENDIAN,
|
||||
error))
|
||||
return FALSE;
|
||||
offset += header_length;
|
||||
for (guint32 i = 0; i < num_of_entries; i++) {
|
||||
gchar name[12] = {0x0};
|
||||
g_autoptr(FuFirmware) img = fu_firmware_new();
|
||||
g_autoptr(GBytes) img_blob = NULL;
|
||||
g_autofree gchar *id = NULL;
|
||||
guint32 img_offset = 0;
|
||||
guint32 img_length = 0;
|
||||
|
||||
/* the IDX is the position in the file */
|
||||
fu_firmware_set_idx(img, i);
|
||||
|
||||
/* copy name as id */
|
||||
if (!fu_memcpy_safe((guint8 *)name,
|
||||
sizeof(name),
|
||||
0x0, /* dst */
|
||||
buf,
|
||||
bufsz,
|
||||
offset + G_STRUCT_OFFSET(FuIfwiCpdEntry, name), /* src */
|
||||
sizeof(name),
|
||||
error)) {
|
||||
return FALSE;
|
||||
}
|
||||
id = fu_strsafe(name, sizeof(name));
|
||||
fu_firmware_set_id(img, id);
|
||||
|
||||
/* copy offset, ignoring huffman and reserved bits */
|
||||
if (!fu_memread_uint32_safe(buf,
|
||||
bufsz,
|
||||
offset + G_STRUCT_OFFSET(FuIfwiCpdEntry, offset),
|
||||
&img_offset,
|
||||
G_LITTLE_ENDIAN,
|
||||
error))
|
||||
return FALSE;
|
||||
img_offset &= 0x1FFFFFF;
|
||||
fu_firmware_set_offset(img, img_offset);
|
||||
|
||||
/* copy data */
|
||||
if (!fu_memread_uint32_safe(buf,
|
||||
bufsz,
|
||||
offset + G_STRUCT_OFFSET(FuIfwiCpdEntry, length),
|
||||
&img_length,
|
||||
G_LITTLE_ENDIAN,
|
||||
error))
|
||||
return FALSE;
|
||||
img_blob = fu_bytes_new_offset(fw, img_offset, img_length, error);
|
||||
if (img_blob == NULL)
|
||||
return FALSE;
|
||||
fu_firmware_set_bytes(img, img_blob);
|
||||
|
||||
/* read the manifest */
|
||||
if (i == FU_IFWI_CPD_FIRMWARE_IDX_MANIFEST &&
|
||||
g_bytes_get_size(img_blob) > sizeof(FuIfwiCpdManifestHeader)) {
|
||||
if (!fu_ifwi_cpd_firmware_parse_manifest(img, img_blob, error))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* success */
|
||||
fu_firmware_add_image(firmware, img);
|
||||
offset += sizeof(FuIfwiCpdEntry);
|
||||
}
|
||||
|
||||
/* success */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static GBytes *
|
||||
fu_ifwi_cpd_firmware_write(FuFirmware *firmware, GError **error)
|
||||
{
|
||||
FuIfwiCpdFirmware *self = FU_IFWI_CPD_FIRMWARE(firmware);
|
||||
FuIfwiCpdFirmwarePrivate *priv = GET_PRIVATE(self);
|
||||
g_autoptr(GByteArray) buf = g_byte_array_new();
|
||||
g_autoptr(GPtrArray) imgs = fu_firmware_get_images(firmware);
|
||||
gsize offset = 0;
|
||||
|
||||
/* write the header */
|
||||
fu_byte_array_append_uint32(buf, FU_IFWI_CPD_FIRMWARE_HEADER_MARKER, G_LITTLE_ENDIAN);
|
||||
fu_byte_array_append_uint32(buf, imgs->len, G_LITTLE_ENDIAN);
|
||||
fu_byte_array_append_uint8(buf, priv->header_version);
|
||||
fu_byte_array_append_uint8(buf, priv->entry_version);
|
||||
fu_byte_array_append_uint8(buf, sizeof(FuIfwiCpdHeader));
|
||||
fu_byte_array_append_uint8(buf, 0x0); /* checksum */
|
||||
fu_byte_array_append_uint32(buf, fu_firmware_get_idx(firmware), G_LITTLE_ENDIAN);
|
||||
fu_byte_array_append_uint32(buf, 0x0, G_LITTLE_ENDIAN); /* crc32 */
|
||||
|
||||
/* fixup the image offsets */
|
||||
offset += sizeof(FuIfwiCpdHeader);
|
||||
offset += sizeof(FuIfwiCpdEntry) * imgs->len;
|
||||
for (guint i = 0; i < imgs->len; i++) {
|
||||
FuFirmware *img = g_ptr_array_index(imgs, i);
|
||||
g_autoptr(GBytes) blob = NULL;
|
||||
blob = fu_firmware_get_bytes(img, error);
|
||||
if (blob == NULL) {
|
||||
g_prefix_error(error, "image 0x%x: ", i);
|
||||
return NULL;
|
||||
}
|
||||
fu_firmware_set_offset(img, offset);
|
||||
offset += g_bytes_get_size(blob);
|
||||
}
|
||||
|
||||
/* add entry headers */
|
||||
for (guint i = 0; i < imgs->len; i++) {
|
||||
FuFirmware *img = g_ptr_array_index(imgs, i);
|
||||
const gchar *id = fu_firmware_get_id(img);
|
||||
gchar name[12] = {0x0};
|
||||
|
||||
/* sanity check */
|
||||
if (id == NULL) {
|
||||
g_set_error(error,
|
||||
G_IO_ERROR,
|
||||
G_IO_ERROR_INVALID_DATA,
|
||||
"image 0x%x must have an ID",
|
||||
(guint)fu_firmware_get_idx(img));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* copy id into name */
|
||||
if (!fu_memcpy_safe((guint8 *)name,
|
||||
sizeof(name),
|
||||
0x0, /* dst */
|
||||
(const guint8 *)id,
|
||||
strlen(id),
|
||||
0x0, /* src */
|
||||
strlen(id),
|
||||
error)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
g_byte_array_append(buf, (const guint8 *)name, sizeof(name));
|
||||
fu_byte_array_append_uint32(buf, fu_firmware_get_offset(img), G_LITTLE_ENDIAN);
|
||||
fu_byte_array_append_uint32(buf, fu_firmware_get_size(img), G_LITTLE_ENDIAN);
|
||||
fu_byte_array_append_uint32(buf, 0x0, G_LITTLE_ENDIAN); /* reserved */
|
||||
}
|
||||
|
||||
/* add entry data */
|
||||
for (guint i = 0; i < imgs->len; i++) {
|
||||
FuFirmware *img = g_ptr_array_index(imgs, i);
|
||||
g_autoptr(GBytes) blob = NULL;
|
||||
blob = fu_firmware_get_bytes(img, error);
|
||||
if (blob == NULL)
|
||||
return NULL;
|
||||
fu_byte_array_append_bytes(buf, blob);
|
||||
}
|
||||
|
||||
/* success */
|
||||
return g_byte_array_free_to_bytes(g_steal_pointer(&buf));
|
||||
}
|
||||
|
||||
static gboolean
|
||||
fu_ifwi_cpd_firmware_build(FuFirmware *firmware, XbNode *n, GError **error)
|
||||
{
|
||||
FuIfwiCpdFirmware *self = FU_IFWI_CPD_FIRMWARE(firmware);
|
||||
FuIfwiCpdFirmwarePrivate *priv = GET_PRIVATE(self);
|
||||
const gchar *tmp;
|
||||
|
||||
/* simple properties */
|
||||
tmp = xb_node_query_text(n, "header_version", NULL);
|
||||
if (tmp != NULL) {
|
||||
guint64 val = 0;
|
||||
if (!fu_strtoull(tmp, &val, 0x0, G_MAXUINT8, error))
|
||||
return FALSE;
|
||||
priv->header_version = val;
|
||||
}
|
||||
tmp = xb_node_query_text(n, "entry_version", NULL);
|
||||
if (tmp != NULL) {
|
||||
guint64 val = 0;
|
||||
if (!fu_strtoull(tmp, &val, 0x0, G_MAXUINT8, error))
|
||||
return FALSE;
|
||||
priv->entry_version = val;
|
||||
}
|
||||
|
||||
/* success */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
fu_ifwi_cpd_firmware_init(FuIfwiCpdFirmware *self)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
fu_ifwi_cpd_firmware_class_init(FuIfwiCpdFirmwareClass *klass)
|
||||
{
|
||||
FuFirmwareClass *klass_firmware = FU_FIRMWARE_CLASS(klass);
|
||||
klass_firmware->export = fu_ifwi_cpd_firmware_export;
|
||||
klass_firmware->parse = fu_ifwi_cpd_firmware_parse;
|
||||
klass_firmware->write = fu_ifwi_cpd_firmware_write;
|
||||
klass_firmware->build = fu_ifwi_cpd_firmware_build;
|
||||
}
|
||||
|
||||
/**
|
||||
* fu_ifwi_cpd_firmware_new:
|
||||
*
|
||||
* Creates a new #FuFirmware of Intel Code Partition Directory format
|
||||
*
|
||||
* Since: 1.8.2
|
||||
**/
|
||||
FuFirmware *
|
||||
fu_ifwi_cpd_firmware_new(void)
|
||||
{
|
||||
return FU_FIRMWARE(g_object_new(FU_TYPE_IFWI_CPD_FIRMWARE, NULL));
|
||||
}
|
47
libfwupdplugin/fu-ifwi-cpd-firmware.h
Normal file
47
libfwupdplugin/fu-ifwi-cpd-firmware.h
Normal file
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (C) 2022 Richard Hughes <richard@hughsie.com>
|
||||
* Copyright (C) 2022 Intel
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1+
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "fu-firmware.h"
|
||||
|
||||
#define FU_TYPE_IFWI_CPD_FIRMWARE (fu_ifwi_cpd_firmware_get_type())
|
||||
G_DECLARE_DERIVABLE_TYPE(FuIfwiCpdFirmware, fu_ifwi_cpd_firmware, FU, IFWI_CPD_FIRMWARE, FuFirmware)
|
||||
|
||||
struct _FuIfwiCpdFirmwareClass {
|
||||
FuFirmwareClass parent_class;
|
||||
};
|
||||
|
||||
/**
|
||||
* FU_IFWI_CPD_FIRMWARE_IDX_MANIFEST:
|
||||
*
|
||||
* The index for the IFWI manifest image.
|
||||
*
|
||||
* Since: 1.8.2
|
||||
**/
|
||||
#define FU_IFWI_CPD_FIRMWARE_IDX_MANIFEST 0x0
|
||||
|
||||
/**
|
||||
* FU_IFWI_CPD_FIRMWARE_IDX_METADATA:
|
||||
*
|
||||
* The index for the IFWI metadata image.
|
||||
*
|
||||
* Since: 1.8.2
|
||||
**/
|
||||
#define FU_IFWI_CPD_FIRMWARE_IDX_METADATA 0x1
|
||||
|
||||
/**
|
||||
* FU_IFWI_CPD_FIRMWARE_IDX_MODULEDATA_IDX:
|
||||
*
|
||||
* The index for the IFWI module data image.
|
||||
*
|
||||
* Since: 1.8.2
|
||||
**/
|
||||
#define FU_IFWI_CPD_FIRMWARE_IDX_MODULEDATA_IDX 0x2
|
||||
|
||||
FuFirmware *
|
||||
fu_ifwi_cpd_firmware_new(void);
|
@ -2308,6 +2308,44 @@ fu_firmware_dfu_func(void)
|
||||
g_assert_true(ret);
|
||||
}
|
||||
|
||||
static void
|
||||
fu_firmware_ifwi_cpd_func(void)
|
||||
{
|
||||
gboolean ret;
|
||||
g_autofree gchar *filename_ifwi_cpd = NULL;
|
||||
g_autoptr(FuFirmware) firmware = fu_ifwi_cpd_firmware_new();
|
||||
g_autoptr(FuFirmware) img1 = NULL;
|
||||
g_autoptr(FuFirmware) img2 = NULL;
|
||||
g_autoptr(GBytes) data_bin = NULL;
|
||||
g_autoptr(GBytes) data_ifwi_cpd = NULL;
|
||||
g_autoptr(GError) error = NULL;
|
||||
|
||||
filename_ifwi_cpd = g_test_build_filename(G_TEST_DIST, "tests", "ifwi-cpd.bin", NULL);
|
||||
data_ifwi_cpd = fu_bytes_get_contents(filename_ifwi_cpd, &error);
|
||||
g_assert_no_error(error);
|
||||
g_assert_nonnull(data_ifwi_cpd);
|
||||
ret = fu_firmware_parse(firmware, data_ifwi_cpd, FWUPD_INSTALL_FLAG_NONE, &error);
|
||||
g_assert_no_error(error);
|
||||
g_assert_true(ret);
|
||||
g_assert_cmpint(fu_firmware_get_idx(firmware), ==, 0x1234);
|
||||
data_bin = fu_firmware_write(firmware, &error);
|
||||
g_assert_no_error(error);
|
||||
g_assert_nonnull(data_bin);
|
||||
g_assert_cmpint(g_bytes_get_size(data_bin), ==, 90);
|
||||
|
||||
img1 = fu_firmware_get_image_by_id(firmware, "one", &error);
|
||||
g_assert_no_error(error);
|
||||
g_assert_nonnull(img1);
|
||||
g_assert_cmpint(fu_firmware_get_offset(img1), ==, 68);
|
||||
g_assert_cmpint(fu_firmware_get_size(img1), ==, 11);
|
||||
|
||||
img2 = fu_firmware_get_image_by_id(firmware, "two", &error);
|
||||
g_assert_no_error(error);
|
||||
g_assert_nonnull(img2);
|
||||
g_assert_cmpint(fu_firmware_get_offset(img2), ==, 79);
|
||||
g_assert_cmpint(fu_firmware_get_size(img2), ==, 11);
|
||||
}
|
||||
|
||||
static void
|
||||
fu_firmware_dfu_patch_func(void)
|
||||
{
|
||||
@ -3426,6 +3464,7 @@ main(int argc, char **argv)
|
||||
g_test_add_func("/fwupd/firmware{srec-tokenization}", fu_firmware_srec_tokenization_func);
|
||||
g_test_add_func("/fwupd/firmware{srec}", fu_firmware_srec_func);
|
||||
g_test_add_func("/fwupd/firmware{srec-xml}", fu_firmware_srec_xml_func);
|
||||
g_test_add_func("/fwupd/firmware{ifwi-cpd}", fu_firmware_ifwi_cpd_func);
|
||||
g_test_add_func("/fwupd/firmware{dfu}", fu_firmware_dfu_func);
|
||||
g_test_add_func("/fwupd/firmware{dfu-patch}", fu_firmware_dfu_patch_func);
|
||||
g_test_add_func("/fwupd/firmware{dfuse}", fu_firmware_dfuse_func);
|
||||
|
@ -45,6 +45,7 @@
|
||||
#include <libfwupdplugin/fu-ifd-bios.h>
|
||||
#include <libfwupdplugin/fu-ifd-firmware.h>
|
||||
#include <libfwupdplugin/fu-ifd-image.h>
|
||||
#include <libfwupdplugin/fu-ifwi-cpd-firmware.h>
|
||||
#include <libfwupdplugin/fu-ihex-firmware.h>
|
||||
#include <libfwupdplugin/fu-io-channel.h>
|
||||
#include <libfwupdplugin/fu-kernel.h>
|
||||
|
@ -935,6 +935,8 @@ LIBFWUPDPLUGIN_1.8.2 {
|
||||
fu_firmware_parse_full;
|
||||
fu_i2c_device_read;
|
||||
fu_i2c_device_write;
|
||||
fu_ifwi_cpd_firmware_get_type;
|
||||
fu_ifwi_cpd_firmware_new;
|
||||
fu_kernel_check_version;
|
||||
fu_kernel_get_firmware_search_path;
|
||||
fu_kernel_locked_down;
|
||||
|
@ -30,6 +30,7 @@ fwupdplugin_src = [
|
||||
'fu-device-locker.c', # fuzzing
|
||||
'fu-device.c', # fuzzing
|
||||
'fu-dfu-firmware.c', # fuzzing
|
||||
'fu-ifwi-cpd-firmware.c', # fuzzing
|
||||
'fu-cfu-common.c', # fuzzing
|
||||
'fu-cfu-offer.c', # fuzzing
|
||||
'fu-cfu-payload.c', # fuzzing
|
||||
@ -113,6 +114,7 @@ fwupdplugin_headers = [
|
||||
'fu-device-metadata.h',
|
||||
'fu-device-locker.h',
|
||||
'fu-dfu-firmware.h',
|
||||
'fu-ifwi-cpd-firmware.h',
|
||||
'fu-cfu-common.h',
|
||||
'fu-cfu-offer.h',
|
||||
'fu-cfu-payload.h',
|
||||
|
BIN
libfwupdplugin/tests/ifwi-cpd.bin
Normal file
BIN
libfwupdplugin/tests/ifwi-cpd.bin
Normal file
Binary file not shown.
13
libfwupdplugin/tests/ifwi-cpd.builder.xml
Normal file
13
libfwupdplugin/tests/ifwi-cpd.builder.xml
Normal file
@ -0,0 +1,13 @@
|
||||
<firmware gtype="FuIfwiCpdFirmware">
|
||||
<idx>0x1234</idx>
|
||||
<header_version>0x1</header_version>
|
||||
<entry_version>0x2</entry_version>
|
||||
<firmware gtype="FuFirmware">
|
||||
<id>one</id>
|
||||
<data>aGVsbG8gd29ybGQ=</data>
|
||||
</firmware>
|
||||
<firmware gtype="FuFirmware">
|
||||
<id>two</id>
|
||||
<data>aGVsbG8gd29ybGQ=</data>
|
||||
</firmware>
|
||||
</firmware>
|
@ -7226,6 +7226,7 @@ fu_engine_load(FuEngine *self, FuEngineLoadFlags flags, FuProgress *progress, GE
|
||||
fu_context_add_firmware_gtype(self->ctx, "raw", FU_TYPE_FIRMWARE);
|
||||
fu_context_add_firmware_gtype(self->ctx, "dfu", FU_TYPE_DFU_FIRMWARE);
|
||||
fu_context_add_firmware_gtype(self->ctx, "dfuse", FU_TYPE_DFUSE_FIRMWARE);
|
||||
fu_context_add_firmware_gtype(self->ctx, "ifwi-cpd", FU_TYPE_IFWI_CPD_FIRMWARE);
|
||||
fu_context_add_firmware_gtype(self->ctx, "fmap", FU_TYPE_FMAP_FIRMWARE);
|
||||
fu_context_add_firmware_gtype(self->ctx, "ihex", FU_TYPE_IHEX_FIRMWARE);
|
||||
fu_context_add_firmware_gtype(self->ctx, "srec", FU_TYPE_SREC_FIRMWARE);
|
||||
|
Loading…
Reference in New Issue
Block a user