/* * Copyright (C) 2018 Evan Lojewski * Copyright (C) 2020 Richard Hughes * * SPDX-License-Identifier: GPL-2+ */ #include "config.h" #include #include #include "fu-bcm57xx-common.h" guint32 fu_bcm57xx_nvram_crc(const guint8 *buf, gsize bufsz) { return fu_common_crc32(buf, bufsz); } gboolean fu_bcm57xx_verify_crc(GBytes *fw, GError **error) { guint32 crc_actual; guint32 crc_file = 0; gsize bufsz = 0x0; const guint8 *buf = g_bytes_get_data(fw, &bufsz); /* expected */ if (!fu_common_read_uint32_safe(buf, bufsz, bufsz - sizeof(guint32), &crc_file, G_LITTLE_ENDIAN, error)) return FALSE; /* reality */ crc_actual = fu_bcm57xx_nvram_crc(buf, bufsz - sizeof(guint32)); if (crc_actual != crc_file) { g_set_error(error, FWUPD_ERROR, FWUPD_ERROR_NOT_SUPPORTED, "invalid CRC, expected 0x%08x got: 0x%08x", (guint)crc_file, (guint)crc_actual); return FALSE; } /* success */ return TRUE; } gboolean fu_bcm57xx_verify_magic(GBytes *fw, gsize offset, GError **error) { guint32 magic = 0; gsize bufsz = 0x0; const guint8 *buf = g_bytes_get_data(fw, &bufsz); /* hardcoded value */ if (!fu_common_read_uint32_safe(buf, bufsz, offset, &magic, G_BIG_ENDIAN, error)) return FALSE; if (magic != BCM_NVRAM_MAGIC) { g_set_error(error, FWUPD_ERROR, FWUPD_ERROR_NOT_SUPPORTED, "invalid magic, got: 0x%x", (guint)magic); return FALSE; } /* success */ return TRUE; } void fu_bcm57xx_veritem_free(Bcm57xxVeritem *veritem) { g_free(veritem->branch); g_free(veritem->version); g_free(veritem); } Bcm57xxVeritem * fu_bcm57xx_veritem_new(const guint8 *buf, gsize bufsz) { g_autofree gchar *tmp = NULL; g_autoptr(Bcm57xxVeritem) veritem = g_new0(Bcm57xxVeritem, 1); struct { const gchar *prefix; const gchar *branch; FwupdVersionFormat verfmt; } data[] = {{"5719-v", BCM_FW_BRANCH_UNKNOWN, FWUPD_VERSION_FORMAT_PAIR}, {"stage1-", BCM_FW_BRANCH_OSS_FIRMWARE, FWUPD_VERSION_FORMAT_TRIPLET}, {NULL, NULL, 0}}; /* do not assume this is NUL terminated */ tmp = g_strndup((const gchar *)buf, bufsz); if (tmp == NULL || tmp[0] == '\0') return NULL; /* use prefix to define object */ for (guint i = 0; data[i].prefix != NULL; i++) { if (g_str_has_prefix(tmp, data[i].prefix)) { veritem->version = g_strdup(tmp + strlen(data[i].prefix)); veritem->branch = g_strdup(data[i].branch); veritem->verfmt = data[i].verfmt; return g_steal_pointer(&veritem); } } veritem->verfmt = FWUPD_VERSION_FORMAT_UNKNOWN; veritem->version = g_strdup(tmp); return g_steal_pointer(&veritem); }