From 2e6e8d7a25a6e31dee58226ea7fc374844d69732 Mon Sep 17 00:00:00 2001 From: "Gabriel L. Somlo" Date: Wed, 23 Apr 2014 09:42:41 -0400 Subject: SMBIOS: Use bitmaps to prevent incompatible comand line options Replace existing smbios_check_collision() functionality with a pair of bitmaps: have_binfile_bitmap and have_fields_bitmap. Bits corresponding to each smbios type are set by smbios_entry_add(), which also uses the bitmaps to ensure that binary blobs and field values are never accepted for the same type. These bitmaps will also be used in the future to decide whether or not to build a full table for a given smbios type. Signed-off-by: Gabriel Somlo Signed-off-by: Gerd Hoffmann --- hw/i386/smbios.c | 50 ++++++++++++++++++++------------------------------ 1 file changed, 20 insertions(+), 30 deletions(-) (limited to 'hw/i386') diff --git a/hw/i386/smbios.c b/hw/i386/smbios.c index 9f83bfba58..6bbfd15538 100644 --- a/hw/i386/smbios.c +++ b/hw/i386/smbios.c @@ -51,11 +51,8 @@ static size_t smbios_entries_len; static int smbios_type4_count = 0; static bool smbios_immutable; -static struct { - bool seen; - int headertype; - Location loc; -} first_opt[2]; +static DECLARE_BITMAP(have_binfile_bitmap, SMBIOS_MAX_TYPE+1); +static DECLARE_BITMAP(have_fields_bitmap, SMBIOS_MAX_TYPE+1); static struct { const char *vendor, *version, *date; @@ -166,29 +163,6 @@ static void smbios_validate_table(void) } } -/* - * To avoid unresolvable overlaps in data, don't allow both - * tables and fields for the same smbios type. - */ -static void smbios_check_collision(int type, int entry) -{ - if (type < ARRAY_SIZE(first_opt)) { - if (first_opt[type].seen) { - if (first_opt[type].headertype != entry) { - error_report("Can't mix file= and type= for same type"); - loc_push_restore(&first_opt[type].loc); - error_report("This is the conflicting setting"); - loc_pop(&first_opt[type].loc); - exit(1); - } - } else { - first_opt[type].seen = true; - first_opt[type].headertype = entry; - loc_save(&first_opt[type].loc); - } - } -} - /* legacy setup functions for <= 2.0 machines */ static void smbios_add_field(int type, int offset, const void *data, size_t len) @@ -337,7 +311,14 @@ void smbios_entry_add(QemuOpts *opts) } header = (struct smbios_structure_header *)(table->data); - smbios_check_collision(header->type, SMBIOS_TABLE_ENTRY); + + if (test_bit(header->type, have_fields_bitmap)) { + error_report("can't load type %d struct, fields already specified!", + header->type); + exit(1); + } + set_bit(header->type, have_binfile_bitmap); + if (header->type == 4) { smbios_type4_count++; } @@ -352,7 +333,16 @@ void smbios_entry_add(QemuOpts *opts) if (val) { unsigned long type = strtoul(val, NULL, 0); - smbios_check_collision(type, SMBIOS_FIELD_ENTRY); + if (type > SMBIOS_MAX_TYPE) { + error_report("out of range!"); + exit(1); + } + + if (test_bit(type, have_binfile_bitmap)) { + error_report("can't add fields, binary file already loaded!"); + exit(1); + } + set_bit(type, have_fields_bitmap); switch (type) { case 0: -- cgit v1.2.3