Fix ROM PPID searching to work for all ROMs

This commit is contained in:
Richard Hughes 2015-07-06 08:25:07 +01:00
parent f720e9fe92
commit 8ffbd403cb
5 changed files with 206 additions and 121 deletions

View File

@ -92,7 +92,7 @@ fu_provider_udev_verify (FuProvider *provider,
}
file = g_file_new_for_path (rom_fn);
rom = fu_rom_new ();
if (!fu_rom_load_file (rom, file, NULL, error))
if (!fu_rom_load_file (rom, file, FU_ROM_LOAD_FLAG_BLANK_PPID, NULL, error))
return FALSE;
fu_device_set_metadata (device, FU_DEVICE_KEY_FIRMWARE_HASH,
fu_rom_get_checksum (rom));
@ -164,7 +164,7 @@ fu_provider_udev_client_add (FuProviderUdev *provider_udev, GUdevDevice *device)
_cleanup_object_unref_ FuRom *rom = NULL;
file = g_file_new_for_path (rom_fn);
rom = fu_rom_new ();
if (!fu_rom_load_file (rom, file, NULL, &error)) {
if (!fu_rom_load_file (rom, file, FU_ROM_LOAD_FLAG_BLANK_PPID, NULL, &error)) {
g_warning ("Failed to parse ROM from %s: %s",
rom_fn, error->message);
}

View File

@ -36,7 +36,9 @@ static void fu_rom_finalize (GObject *object);
/* data from http://resources.infosecinstitute.com/pci-expansion-rom/ */
typedef struct {
guint8 *rom_data;
guint32 rom_len;
guint32 rom_offset;
guint32 entry_point;
guint8 reserved[18];
guint16 cpi_ptr;
@ -53,7 +55,6 @@ typedef struct {
guint32 max_runtime_len;
guint16 config_header_ptr;
guint16 dmtf_clp_ptr;
guint32 offset_in_buffer;
} FuRomPciHeader;
/**
@ -74,6 +75,16 @@ struct _FuRomPrivate
G_DEFINE_TYPE (FuRom, fu_rom, G_TYPE_OBJECT)
/**
* fu_rom_pci_header_free:
**/
static void
fu_rom_pci_header_free (FuRomPciHeader *hdr)
{
g_free (hdr->rom_data);
g_free (hdr);
}
/**
* fu_rom_kind_to_string:
**/
@ -94,13 +105,25 @@ fu_rom_kind_to_string (FuRomKind kind)
}
/**
* fu_rom_strstr_bin:
* fu_rom_pci_strstr:
**/
static guint8 *
fu_rom_strstr_bin (guint8 *haystack, gsize haystack_len, const gchar *needle)
fu_rom_pci_strstr (FuRomPciHeader *hdr, const gchar *needle)
{
guint i;
guint needle_len = strlen (needle);
guint needle_len;
guint8 *haystack;
gsize haystack_len;
if (needle == NULL || needle[0] == '\0')
return NULL;
if (hdr->rom_data == NULL)
return NULL;
if (hdr->data_len > hdr->rom_len)
return NULL;
haystack = &hdr->rom_data[hdr->data_len];
haystack_len = hdr->rom_len - hdr->data_len;
needle_len = strlen (needle);
if (needle_len > haystack_len)
return NULL;
for (i = 0; i < haystack_len - needle_len; i++) {
@ -137,9 +160,10 @@ fu_rom_get_hex_dump (guint8 *buffer, gssize sz)
GString *str = NULL;
guint i;
str = g_string_new ("");
for (i = 0; i < sz; i++) {
if (sz <= 0)
return NULL;
for (i = 0; i < sz; i++)
g_string_append_printf (str, "%02x ", buffer[i]);
}
g_string_append (str, " ");
for (i = 0; i < sz; i++) {
gchar tmp = '?';
@ -151,8 +175,10 @@ fu_rom_get_hex_dump (guint8 *buffer, gssize sz)
}
typedef struct {
guint8 segment_kind;
guint16 next_offset;
guint8 segment_kind;
guint8 *data;
guint16 data_len;
guint16 next_offset;
} FooRomPciCertificateHdr;
/**
@ -176,18 +202,34 @@ fu_rom_pci_print_certificate_data (guint8 *buffer, gssize sz)
FooRomPciCertificateHdr h;
_cleanup_free_ gchar *segment_str = NULL;
segment_str = fu_rom_get_hex_dump (buffer+off, 29);
g_debug (" ISBN segment: %s", segment_str);
g_debug (" ISBN segment @%02x: %s", off, segment_str);
h.segment_kind = buffer[off+1];
h.next_offset = ((guint16) buffer[off+14] << 8) + buffer[off+13];
if (h.next_offset == 0x0000) {
/* length of this segment must be (sz - off - 27) */
h.data = &buffer[off+29];
/* calculate last block length automatically */
if (h.next_offset == 0)
h.data_len = sz - off - 29 - 27;
else
h.data_len = h.next_offset - off - 29;
/* print the certificate */
if (h.segment_kind == 0x01) {
_cleanup_free_ gchar *tmp = NULL;
tmp = fu_rom_get_hex_dump (h.data, h.data_len);
g_debug ("%s(%i)", tmp, h.data_len);
} else if (h.segment_kind == 0x02) {
_cleanup_free_ gchar *tmp = NULL;
tmp = fu_rom_get_hex_dump (h.data,
h.data_len < 32 ? h.data_len : 32);
g_debug ("%s(%i)", tmp, h.data_len);
} else {
g_warning ("unknown segment kind %i", h.segment_kind);
}
/* last block */
if (h.next_offset == 0x0000)
break;
}
if (h.segment_kind == 0x01 && FALSE) {
_cleanup_free_ gchar *cert = NULL;
cert = g_strndup ((gchar*) buffer + off + 29, h.next_offset - off - 29);
g_debug ("%s(%i)", cert, h.next_offset - off - 29);
}
off = h.next_offset;
}
}
@ -213,12 +255,12 @@ fu_rom_pci_code_type_to_string (guint8 code_type)
* fu_rom_pci_header_get_checksum:
**/
static guint8
fu_rom_pci_header_get_checksum (FuRomPciHeader *hdr, guint8 *buffer, gssize sz)
fu_rom_pci_header_get_checksum (FuRomPciHeader *hdr)
{
guint8 chksum_check = 0x00;
guint i;
for (i = 0; i < hdr->image_len; i++)
chksum_check += buffer[hdr->offset_in_buffer + i];
for (i = 0; i < hdr->rom_len; i++)
chksum_check += hdr->rom_data[i];
return chksum_check;
}
@ -226,13 +268,15 @@ fu_rom_pci_header_get_checksum (FuRomPciHeader *hdr, guint8 *buffer, gssize sz)
* fu_rom_pci_print_header:
**/
static void
fu_rom_pci_print_header (FuRomPciHeader *hdr, guint8 *buffer, gssize sz)
fu_rom_pci_print_header (FuRomPciHeader *hdr)
{
guint8 chksum_check;
guint8 *buffer;
_cleanup_free_ gchar *data_str = NULL;
_cleanup_free_ gchar *reserved_str = NULL;
g_debug ("PCI Header");
g_debug (" RomOffset: 0x%04x", hdr->rom_offset);
g_debug (" RomSize: 0x%04x", hdr->rom_len);
g_debug (" EntryPnt: 0x%06x", hdr->entry_point);
reserved_str = fu_rom_get_hex_dump (hdr->reserved, 18);
@ -240,7 +284,7 @@ fu_rom_pci_print_header (FuRomPciHeader *hdr, guint8 *buffer, gssize sz)
g_debug (" CpiPtr: 0x%04x", hdr->cpi_ptr);
/* print the data */
buffer += hdr->offset_in_buffer + hdr->cpi_ptr;
buffer = &hdr->rom_data[hdr->cpi_ptr];
g_debug (" PCI Data");
g_debug (" VendorID: 0x%04x", hdr->vendor_id);
g_debug (" DeviceID: 0x%04x", hdr->device_id);
@ -271,9 +315,9 @@ fu_rom_pci_print_header (FuRomPciHeader *hdr, guint8 *buffer, gssize sz)
}
/* verify the checksum byte */
if (hdr->image_len <= sz && hdr->image_len > 0) {
buffer -= hdr->cpi_ptr;
chksum_check = fu_rom_pci_header_get_checksum (hdr, buffer, sz);
if (hdr->image_len <= hdr->rom_len && hdr->image_len > 0) {
buffer = hdr->rom_data;
chksum_check = fu_rom_pci_header_get_checksum (hdr);
if (chksum_check == 0x00) {
g_debug (" ChkSum: 0x%02x [valid]",
buffer[hdr->image_len-1]);
@ -287,48 +331,64 @@ fu_rom_pci_print_header (FuRomPciHeader *hdr, guint8 *buffer, gssize sz)
}
}
/**
* fu_rom_extract_all:
**/
gboolean
fu_rom_extract_all (FuRom *rom, const gchar *path, GError **error)
{
FuRomPrivate *priv = rom->priv;
FuRomPciHeader *hdr;
guint i;
for (i = 0; i < priv->hdrs->len; i++) {
_cleanup_free_ gchar *fn = NULL;
hdr = g_ptr_array_index (priv->hdrs, i);
fn = g_strdup_printf ("%s/%02i.bin", path, i);
g_debug ("dumping ROM #%i at 0x%04x [0x%02x] to %s",
i, hdr->rom_offset, hdr->rom_len, fn);
if (hdr->rom_len == 0)
continue;
if (!g_file_set_contents (fn,
(const gchar *) hdr->rom_data,
(gssize) hdr->rom_len, error))
return FALSE;
}
return TRUE;
}
/**
* fu_rom_find_and_blank_serial_numbers:
**/
static void
fu_rom_find_and_blank_serial_numbers (FuRom *rom, guint8 *buffer, gsize sz)
fu_rom_find_and_blank_serial_numbers (FuRom *rom)
{
FuRomPrivate *priv = rom->priv;
FuRomPciHeader *hdr;
guint i;
guint8 *tmp;
/* bail if not likely */
if (priv->kind == FU_ROM_KIND_PCI ||
priv->kind == FU_ROM_KIND_INTEL) {
g_debug ("no serial numbers likely");
return;
}
for (i = 0; i < priv->hdrs->len; i++) {
guint32 off;
hdr = g_ptr_array_index (priv->hdrs, i);
g_debug ("Looking for serial numbers at ROM 0x%04x", hdr->offset_in_buffer);
if (priv->kind == FU_ROM_KIND_PCI)
continue;
if (priv->kind == FU_ROM_KIND_INTEL)
continue;
if (hdr->image_len < 4)
continue;
if (hdr->image_len > sz)
continue;
/* Only NVIDIA and ATI embed the PPID in the ROM */
off = hdr->offset_in_buffer;
off += hdr->data_len;
if (off > sz)
continue;
tmp = fu_rom_strstr_bin (&buffer[off], hdr->image_len, "PPID");
g_debug ("looking for PPID at 0x%04x", hdr->rom_offset);
tmp = fu_rom_pci_strstr (hdr, "PPID");
if (tmp != NULL) {
guint len;
guint8 chk;
len = fu_rom_blank_serial_numbers (tmp, sz - (tmp - buffer));
g_debug ("cleared %i chars @ 0x%04lx", len, tmp - buffer);
len = fu_rom_blank_serial_numbers (tmp, hdr->rom_len - hdr->data_len);
g_debug ("cleared %i chars @ 0x%04lx", len, tmp - &hdr->rom_data[hdr->data_len]);
/* we have to fix the checksum */
chk = fu_rom_pci_header_get_checksum (hdr, buffer, sz);
buffer[hdr->offset_in_buffer + hdr->image_len - 1] -= chk;
fu_rom_pci_print_header (hdr, buffer, sz);
chk = fu_rom_pci_header_get_checksum (hdr);
hdr->rom_data[hdr->rom_len - 1] -= chk;
fu_rom_pci_print_header (hdr);
}
}
}
@ -337,43 +397,46 @@ fu_rom_find_and_blank_serial_numbers (FuRom *rom, guint8 *buffer, gsize sz)
* fu_rom_pci_get_data:
**/
static gboolean
fu_rom_pci_parse_data (FuRomPciHeader *hdr, guint8 *buffer, gssize sz)
fu_rom_pci_parse_data (FuRomPciHeader *hdr)
{
guint8 *buffer;
/* check valid */
if (hdr == NULL ||
hdr->cpi_ptr == 0x0000) {
g_debug ("No PCI DATA");
g_debug ("No PCI DATA @ 0x%04x", hdr->rom_offset);
return FALSE;
}
if (hdr->rom_len > 0 && hdr->cpi_ptr > hdr->rom_len) {
g_debug ("Invalid PCI DATA");
g_debug ("Invalid PCI DATA @ 0x%04x", hdr->rom_offset);
return FALSE;
}
/* gahh, CPI is out of the first chunk */
if (hdr->cpi_ptr > sz) {
g_debug ("No available PCI DATA");
if (hdr->cpi_ptr > hdr->rom_len) {
g_debug ("No available PCI DATA @ 0x%04x : 0x%04x > 0x%04x",
hdr->rom_offset, hdr->cpi_ptr, hdr->rom_len);
return FALSE;
}
/* check signature */
if (memcmp (&buffer[hdr->cpi_ptr], "PCIR", 4) != 0) {
if (memcmp (&buffer[hdr->cpi_ptr], "RGIS", 4) == 0 ||
memcmp (&buffer[hdr->cpi_ptr], "NPDS", 4) == 0 ||
memcmp (&buffer[hdr->cpi_ptr], "NPDE", 4) == 0) {
buffer = &hdr->rom_data[hdr->cpi_ptr];
if (memcmp (buffer, "PCIR", 4) != 0) {
if (memcmp (buffer, "RGIS", 4) == 0 ||
memcmp (buffer, "NPDS", 4) == 0 ||
memcmp (buffer, "NPDE", 4) == 0) {
g_debug ("-- using NVIDIA DATA quirk");
} else {
g_debug ("Not PCI DATA: %02x%02x%02x%02x [%c%c%c%c]",
buffer[hdr->cpi_ptr+0], buffer[hdr->cpi_ptr+1],
buffer[hdr->cpi_ptr+2], buffer[hdr->cpi_ptr+3],
buffer[hdr->cpi_ptr+0], buffer[hdr->cpi_ptr+1],
buffer[hdr->cpi_ptr+2], buffer[hdr->cpi_ptr+3]);
buffer[0], buffer[1],
buffer[2], buffer[3],
buffer[0], buffer[1],
buffer[2], buffer[3]);
return FALSE;
}
}
/* parse */
buffer += hdr->cpi_ptr;
hdr->vendor_id = ((guint16) buffer[0x05] << 8) + buffer[0x04];
hdr->device_id = ((guint16) buffer[0x07] << 8) + buffer[0x06];
hdr->device_list_ptr = ((guint16) buffer[0x09] << 8) + buffer[0x08];
@ -416,6 +479,17 @@ fu_rom_pci_get_header (guint8 *buffer, gssize sz)
/* decode structure */
hdr = g_new0 (FuRomPciHeader, 1);
hdr->rom_len = buffer[0x02] * 512;
/* fix up misreporting */
if (hdr->rom_len == 0) {
g_debug ("fixing up last image size");
hdr->rom_len = sz;
}
/* copy this locally to the header */
hdr->rom_data = g_memdup (buffer, hdr->rom_len);
/* parse out CPI */
hdr->entry_point = ((guint32) buffer[0x05] << 16) +
((guint16) buffer[0x04] << 8) +
buffer[0x03];
@ -424,7 +498,7 @@ fu_rom_pci_get_header (guint8 *buffer, gssize sz)
/* parse the header data */
g_debug ("looking for PCI DATA @ 0x%04x", hdr->cpi_ptr);
fu_rom_pci_parse_data (hdr, buffer, sz);
fu_rom_pci_parse_data (hdr);
return hdr;
}
@ -432,13 +506,13 @@ fu_rom_pci_get_header (guint8 *buffer, gssize sz)
* fu_rom_find_version_pci:
**/
static gchar *
fu_rom_find_version_pci (FuRomPciHeader *hdr, guint8 *buffer, gsize sz)
fu_rom_find_version_pci (FuRomPciHeader *hdr)
{
gchar *str;
/* ARC storage */
if (memcmp (hdr->reserved, "\0\0ARC", 5) == 0) {
str = (gchar *) fu_rom_strstr_bin (buffer, sz, "BIOS: ");
str = (gchar *) fu_rom_pci_strstr (hdr, "BIOS: ");
if (str != NULL)
return g_strdup (str + 6);
}
@ -449,32 +523,30 @@ fu_rom_find_version_pci (FuRomPciHeader *hdr, guint8 *buffer, gsize sz)
* fu_rom_find_version_nvidia:
**/
static gchar *
fu_rom_find_version_nvidia (FuRomPciHeader *hdr, guint8 *buffer, gsize sz)
fu_rom_find_version_nvidia (FuRomPciHeader *hdr)
{
gchar *str;
/* static location for some firmware */
if (memcmp (buffer + 0x0d7, "Version ", 8) == 0)
return g_strdup ((gchar *) &buffer[0x0d7 + 8]);
if (memcmp (buffer + 0x155, "Version ", 8) == 0)
return g_strdup ((gchar *) &buffer[0x155 + 8]);
if (memcmp (hdr->rom_data + 0x013d, "Version ", 8) == 0)
return g_strdup ((gchar *) &hdr->rom_data[0x013d + 8]);
/* usual search string */
str = (gchar *) fu_rom_strstr_bin (buffer, sz, "Version ");
str = (gchar *) fu_rom_pci_strstr (hdr, "Version ");
if (str != NULL)
return g_strdup (str + 8);
/* broken */
str = (gchar *) fu_rom_strstr_bin (buffer, sz, "Vension:");
str = (gchar *) fu_rom_pci_strstr (hdr, "Vension:");
if (str != NULL)
return g_strdup (str + 8);
str = (gchar *) fu_rom_strstr_bin (buffer, sz, "Version");
str = (gchar *) fu_rom_pci_strstr (hdr, "Version");
if (str != NULL)
return g_strdup (str + 7);
/* fallback to VBIOS */
if (memcmp (buffer + 0xfa, "VBIOS Ver", 9) == 0)
return g_strdup ((gchar *) &buffer[0xfa + 9]);
if (memcmp (hdr->rom_data + 0xfa, "VBIOS Ver", 9) == 0)
return g_strdup ((gchar *) &hdr->rom_data[0xfa + 9]);
return NULL;
}
@ -482,12 +554,12 @@ fu_rom_find_version_nvidia (FuRomPciHeader *hdr, guint8 *buffer, gsize sz)
* fu_rom_find_version_intel:
**/
static gchar *
fu_rom_find_version_intel (FuRomPciHeader *hdr, guint8 *buffer, gsize sz)
fu_rom_find_version_intel (FuRomPciHeader *hdr)
{
gchar *str;
/* 2175_RYan PC 14.34 06/06/2013 21:27:53 */
str = (gchar *) fu_rom_strstr_bin (buffer, sz, "Build Number:");
str = (gchar *) fu_rom_pci_strstr (hdr, "Build Number:");
if (str != NULL) {
guint i;
_cleanup_strv_free_ gchar **split = NULL;
@ -500,7 +572,7 @@ fu_rom_find_version_intel (FuRomPciHeader *hdr, guint8 *buffer, gsize sz)
}
/* fallback to VBIOS */
str = (gchar *) fu_rom_strstr_bin (buffer, sz, "VBIOS ");
str = (gchar *) fu_rom_pci_strstr (hdr, "VBIOS ");
if (str != NULL)
return g_strdup (str + 6);
return NULL;
@ -510,16 +582,16 @@ fu_rom_find_version_intel (FuRomPciHeader *hdr, guint8 *buffer, gsize sz)
* fu_rom_find_version_ati:
**/
static gchar *
fu_rom_find_version_ati (FuRomPciHeader *hdr, guint8 *buffer, gsize sz)
fu_rom_find_version_ati (FuRomPciHeader *hdr)
{
gchar *str;
str = (gchar *) fu_rom_strstr_bin (buffer, sz, " VER0");
str = (gchar *) fu_rom_pci_strstr (hdr, " VER0");
if (str != NULL)
return g_strdup (str + 4);
/* broken */
str = (gchar *) fu_rom_strstr_bin (buffer, sz, " VR");
str = (gchar *) fu_rom_pci_strstr (hdr, " VR");
if (str != NULL)
return g_strdup (str + 4);
return NULL;
@ -529,21 +601,16 @@ fu_rom_find_version_ati (FuRomPciHeader *hdr, guint8 *buffer, gsize sz)
* fu_rom_find_version:
**/
static gchar *
fu_rom_find_version (FuRomKind kind, FuRomPciHeader *hdr,
guint8 *buffer, gsize sz)
fu_rom_find_version (FuRomKind kind, FuRomPciHeader *hdr)
{
/* narrow the search space down a bit */
buffer = &buffer[hdr->offset_in_buffer];
sz = hdr->rom_len;
if (kind == FU_ROM_KIND_PCI)
return fu_rom_find_version_pci (hdr, buffer, sz);
return fu_rom_find_version_pci (hdr);
if (kind == FU_ROM_KIND_NVIDIA)
return fu_rom_find_version_nvidia (hdr, buffer, sz);
return fu_rom_find_version_nvidia (hdr);
if (kind == FU_ROM_KIND_INTEL)
return fu_rom_find_version_intel (hdr, buffer, sz);
return fu_rom_find_version_intel (hdr);
if (kind == FU_ROM_KIND_ATI)
return fu_rom_find_version_ati (hdr, buffer, sz);
return fu_rom_find_version_ati (hdr);
return NULL;
}
@ -551,7 +618,8 @@ fu_rom_find_version (FuRomKind kind, FuRomPciHeader *hdr,
* fu_rom_load_file:
**/
gboolean
fu_rom_load_file (FuRom *rom, GFile *file, GCancellable *cancellable, GError **error)
fu_rom_load_file (FuRom *rom, GFile *file, FuRomLoadFlags flags,
GCancellable *cancellable, GError **error)
{
FuRomPrivate *priv = rom->priv;
FuRomPciHeader *hdr = NULL;
@ -653,12 +721,13 @@ fu_rom_load_file (FuRom *rom, GFile *file, GCancellable *cancellable, GError **e
if (found_data) {
g_debug ("found junk data, adding fake");
hdr = g_new0 (FuRomPciHeader, 1);
hdr->vendor_id = 0xdead;
hdr->device_id = 0xbeef;
hdr->code_type = 0xff;
hdr->vendor_id = 0x0000;
hdr->device_id = 0x0000;
hdr->code_type = 0x00;
hdr->last_image = 0x80;
hdr->offset_in_buffer = hdr_sz + jump;
hdr->rom_len = sz - (hdr_sz + jump);
hdr->rom_offset = hdr_sz + jump;
hdr->rom_len = sz - hdr->rom_offset;
hdr->rom_data = g_memdup (&buffer[hdr->rom_offset], hdr->rom_len);
hdr->image_len = hdr->rom_len;
g_ptr_array_add (priv->hdrs, hdr);
} else {
@ -668,7 +737,7 @@ fu_rom_load_file (FuRom *rom, GFile *file, GCancellable *cancellable, GError **e
}
/* save this so we can fix checksums */
hdr->offset_in_buffer = hdr_sz + jump;
hdr->rom_offset = hdr_sz + jump;
/* we can't break on hdr->last_image as
* NVIDIA uses packed but not merged extended headers */
@ -696,7 +765,7 @@ fu_rom_load_file (FuRom *rom, GFile *file, GCancellable *cancellable, GError **e
/* print all headers */
for (i = 0; i < priv->hdrs->len; i++) {
hdr = g_ptr_array_index (priv->hdrs, i);
fu_rom_pci_print_header (hdr, buffer, sz);
fu_rom_pci_print_header (hdr);
}
/* find first ROM header */
@ -708,13 +777,13 @@ fu_rom_load_file (FuRom *rom, GFile *file, GCancellable *cancellable, GError **e
/* detect intel header */
if (memcmp (hdr->reserved, "00000000000", 11) == 0)
hdr_sz = (buffer[0x1b] << 8) + buffer[0x1a];
if (hdr_sz > sz) {
g_set_error_literal (error,
FWUPD_ERROR,
FWUPD_ERROR_INVALID_FILE,
"firmware corrupt (overflow)");
return FALSE;
}
if (hdr_sz > sz) {
g_set_error_literal (error,
FWUPD_ERROR,
FWUPD_ERROR_INVALID_FILE,
"firmware corrupt (overflow)");
return FALSE;
}
if (memcmp (buffer + hdr_sz + 0x04, "K74", 3) == 0) {
priv->kind = FU_ROM_KIND_NVIDIA;
@ -736,15 +805,19 @@ fu_rom_load_file (FuRom *rom, GFile *file, GCancellable *cancellable, GError **e
}
/* find version string */
priv->version = fu_rom_find_version (priv->kind, hdr, buffer, sz);
priv->version = fu_rom_find_version (priv->kind, hdr);
if (priv->version != NULL) {
g_strstrip (priv->version);
g_strdelimit (priv->version, "\r\n ", '\0');
}
/* update checksum */
fu_rom_find_and_blank_serial_numbers (rom, buffer, sz);
g_checksum_update (priv->checksum_wip, buffer, sz);
if (flags & FU_ROM_LOAD_FLAG_BLANK_PPID)
fu_rom_find_and_blank_serial_numbers (rom);
for (i = 0; i < priv->hdrs->len; i++) {
hdr = g_ptr_array_index (priv->hdrs, i);
g_checksum_update (priv->checksum_wip, hdr->rom_data, hdr->rom_len);
}
/* not known */
if (priv->version == NULL) {
@ -829,7 +902,7 @@ fu_rom_init (FuRom *rom)
{
rom->priv = FU_ROM_GET_PRIVATE (rom);
rom->priv->checksum_wip = g_checksum_new (G_CHECKSUM_SHA1);
rom->priv->hdrs = g_ptr_array_new_with_free_func (g_free);
rom->priv->hdrs = g_ptr_array_new_with_free_func ((GDestroyNotify) fu_rom_pci_header_free);
}
/**

View File

@ -59,13 +59,23 @@ typedef enum {
FU_ROM_KIND_LAST
} FuRomKind;
typedef enum {
FU_ROM_LOAD_FLAG_NONE,
FU_ROM_LOAD_FLAG_BLANK_PPID = 1,
FU_ROM_LOAD_FLAG_LAST
} FuRomLoadFlags;
GType fu_rom_get_type (void);
FuRom *fu_rom_new (void);
gboolean fu_rom_load_file (FuRom *rom,
GFile *file,
FuRomLoadFlags flags,
GCancellable *cancellable,
GError **error);
gboolean fu_rom_extract_all (FuRom *rom,
const gchar *path,
GError **error);
FuRomKind fu_rom_get_kind (FuRom *rom);
const gchar *fu_rom_get_version (FuRom *rom);
const gchar *fu_rom_get_checksum (FuRom *rom);

View File

@ -74,7 +74,7 @@ fu_rom_func (void)
{ FU_ROM_KIND_ATI, /* atombios, with serial */
"Asus.HD7970.3072.121018.rom",
"015.023.000.002.000000",
"e4107546d3df3e52db2068babbcacc6329f05d46",
"ba8b6ce38f2499c8463fc9d983b8e0162b1121e4",
0x1002, 0x6798 },
{ FU_ROM_KIND_NVIDIA,
"Asus.GTX480.1536.100406_1.rom",
@ -84,12 +84,12 @@ fu_rom_func (void)
{ FU_ROM_KIND_NVIDIA, /* nvgi */
"Asus.GTX980.4096.140905.rom",
"84.04.1F.00.02",
"f314b90d4279935726ae2752bd5ec29e66140ad1",
"98f58321145bd347156455356bc04c5b04a292f5",
0x10de, 0x13c0 },
{ FU_ROM_KIND_NVIDIA, /* nvgi, with serial */
"Asus.TitanBlack.6144.140212.rom",
"80.80.4E.00.01",
"298627b23efea5a8fb62d992a66fba10b06a136d",
"3c80f35d4e3c440ffb427957d9271384113d7721",
0x10de, 0x100c },
{ FU_ROM_KIND_UNKNOWN, NULL, NULL, NULL, 0x0000, 0x0000 }
};
@ -109,7 +109,7 @@ fu_rom_func (void)
continue;
g_print ("\nparsing %s...", filename);
file = g_file_new_for_path (filename);
ret = fu_rom_load_file (rom, file, NULL, &error);
ret = fu_rom_load_file (rom, file, FU_ROM_LOAD_FLAG_BLANK_PPID, NULL, &error);
g_assert_no_error (error);
g_assert (ret);
g_assert_cmpstr (fu_rom_get_version (rom), ==, data[i].ver);
@ -147,7 +147,7 @@ fu_rom_all_func (void)
g_print ("\nparsing %s...", filename);
file = g_file_new_for_path (filename);
rom = fu_rom_new ();
ret = fu_rom_load_file (rom, file, NULL, &error);
ret = fu_rom_load_file (rom, file, FU_ROM_LOAD_FLAG_BLANK_PPID, NULL, &error);
if (!ret) {
g_print ("%s %s : %s\n",
fu_rom_kind_to_string (fu_rom_get_kind (rom)),

View File

@ -803,7 +803,8 @@ fu_util_dump_rom (FuUtilPrivate *priv, gchar **values, GError **error)
file = g_file_new_for_path (values[i]);
rom = fu_rom_new ();
g_print ("%s:\n", values[i]);
if (!fu_rom_load_file (rom, file, NULL, &error_local)) {
if (!fu_rom_load_file (rom, file, FU_ROM_LOAD_FLAG_BLANK_PPID,
NULL, &error_local)) {
g_print ("%s\n", error_local->message);
continue;
}
@ -856,7 +857,8 @@ fu_util_verify_update (FuUtilPrivate *priv, gchar **values, GError **error)
file = g_file_new_for_path (values[i]);
rom = fu_rom_new ();
g_print ("Processing %s...\n", values[i]);
if (!fu_rom_load_file (rom, file, NULL, &error_local)) {
if (!fu_rom_load_file (rom, file, FU_ROM_LOAD_FLAG_BLANK_PPID,
NULL, &error_local)) {
g_print ("%s\n", error_local->message);
continue;
}