From patchwork Wed Apr 23 19:04:49 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Gabriel L. Somlo" X-Patchwork-Id: 341955 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3160914011D for ; Thu, 24 Apr 2014 05:06:10 +1000 (EST) Received: from localhost ([::1]:34304 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Wd2Uh-0007Il-Nx for incoming@patchwork.ozlabs.org; Wed, 23 Apr 2014 15:06:07 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:52506) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Wd2Tb-0005gz-Jp for qemu-devel@nongnu.org; Wed, 23 Apr 2014 15:05:05 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Wd2TV-00041q-NY for qemu-devel@nongnu.org; Wed, 23 Apr 2014 15:04:59 -0400 Received: from mail-qg0-x22f.google.com ([2607:f8b0:400d:c04::22f]:46555) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Wd2TV-00041i-HO for qemu-devel@nongnu.org; Wed, 23 Apr 2014 15:04:53 -0400 Received: by mail-qg0-f47.google.com with SMTP id e89so1447795qgf.34 for ; Wed, 23 Apr 2014 12:04:53 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=date:from:to:cc:subject:message-id:mime-version:content-type :content-disposition:in-reply-to:user-agent; bh=H//WySqlNk0LCE06Nc69lQ1/KpXXzidqpo8FNj0yV6Q=; b=M2rtnfV9QNaVKsLUNDpQJ6fc6Hu/B4BtQB5f2486aHjYDNqbeg4aOqv85BVd2Fyfp2 Bue2aJ0rhDdd2dV2OhpdHObBKjHskW8CDaWT57r+Yq5jNNE6d2EkLljPLS1tk7mG+vMK +BhBDuf6Lc56OI1u6HHkUCrKJRPPatCtSkwkPaJDPEWZlrkCuyGfKArJ/lytXiB2aFJg mr6HjU7Mn8TaRSaOKlc2CVkeb29lamtOggytLwHxmPVWz1wKqC3vwX9APbIYPoKTLKSx ZTBOOANhSS+QzsnoZF/e9xasKp8mcS5w/a/6PcziRNn5ktfwA/vJXk3/XZHXnBIc/CqC iOKQ== X-Received: by 10.140.49.71 with SMTP id p65mr4945371qga.47.1398279891434; Wed, 23 Apr 2014 12:04:51 -0700 (PDT) Received: from ERROL.INI.CMU.EDU (ERROL.INI.CMU.EDU. [128.2.16.43]) by mx.google.com with ESMTPSA id r4sm3231232qat.16.2014.04.23.12.04.50 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 23 Apr 2014 12:04:50 -0700 (PDT) Date: Wed, 23 Apr 2014 15:04:49 -0400 From: "Gabriel L. Somlo" To: seabios@seabios.org Message-ID: <20140423190448.GG1630@ERROL.INI.CMU.EDU> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <1398264092.26634.96.camel@nilsson.home.kraxel.org> User-Agent: Mutt/1.5.21 (2010-09-15) X-detected-operating-system: by eggs.gnu.org: Error: Malformed IPv6 address (bad octet value). X-Received-From: 2607:f8b0:400d:c04::22f Cc: qemu-devel@nongnu.org, armbru@redhat.com, agraf@suse.de, kevin@koconnor.net, kraxel@redhat.com, lersek@redhat.com Subject: [Qemu-devel] [SeaBIOS v4 PATCH] SMBIOS: Check for aggregate tables & entry point in fw_cfg X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Check fw_cfg for the presence of an aggregate set of smbios tables (etc/smbios/smbios-tables) and an entry point structure (etc/smbios/smbios-anchor), and, if found, use them instead of generating entries locally. We ensure the presence of a type 0 (bios information) structure by generating it locally if necessary, which is expected to be the common case. Signed-off-by: Gabriel L. Somlo --- Only difference in this version (aside from the slightly reworded commit blurb) is a modified comment: - /* Enable targeted content distribution (needed for SVVP, per SeaBIOS) */ + /* Enable targeted content distribution (needed for SVVP) */ which I cut'n'pasted (back) from QEMU for generating the local SeaBIOS type 0 table. I figure saying "per SeaBIOS" when we're *in* SeaBIOS would be a bit silly... :) Thanks, Gabriel src/fw/biostables.c | 135 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/fw/smbios.c | 2 +- src/util.h | 3 +- 3 files changed, 138 insertions(+), 2 deletions(-) diff --git a/src/fw/biostables.c b/src/fw/biostables.c index 818a8fe..17bee8e 100644 --- a/src/fw/biostables.c +++ b/src/fw/biostables.c @@ -13,6 +13,7 @@ #include "std/mptable.h" // MPTABLE_SIGNATURE #include "std/pirtable.h" // struct pir_header #include "std/smbios.h" // struct smbios_entry_point +#include "romfile.h" #include "string.h" // memcpy #include "util.h" // copy_table #include "x86.h" // outb @@ -314,6 +315,140 @@ display_uuid(void) } } +#define set_str_field_or_skip(type, field, value) \ + do { \ + int size = (value != NULL) ? strlen(value) + 1 : 0; \ + if (size > 1) { \ + memcpy(end, value, size); \ + end += size; \ + p->field = ++str_index; \ + } else { \ + p->field = 0; \ + } \ + } while (0) + +static void * +smbios_new_type_0(void *start, + const char *vendor, const char *version, const char *date) +{ + struct smbios_type_0 *p = (struct smbios_type_0 *)start; + char *end = (char *)start + sizeof(struct smbios_type_0); + int str_index = 0; + + p->header.type = 0; + p->header.length = sizeof(struct smbios_type_0); + p->header.handle = 0; + + set_str_field_or_skip(0, vendor_str, vendor); + set_str_field_or_skip(0, bios_version_str, version); + p->bios_starting_address_segment = 0xe800; + set_str_field_or_skip(0, bios_release_date_str, date); + + p->bios_rom_size = 0; /* FIXME */ + + /* BIOS characteristics not supported */ + memset(p->bios_characteristics, 0, 8); + p->bios_characteristics[0] = 0x08; + + /* Enable targeted content distribution (needed for SVVP) */ + p->bios_characteristics_extension_bytes[0] = 0; + p->bios_characteristics_extension_bytes[1] = 4; + + p->system_bios_major_release = 0; + p->system_bios_minor_release = 0; + p->embedded_controller_major_release = 0xFF; + p->embedded_controller_minor_release = 0xFF; + + *end = 0; + end++; + if (!str_index) { + *end = 0; + end++; + } + + return end; +} + +#define BIOS_NAME "SeaBIOS" +#define BIOS_DATE "04/01/2014" + +static int +smbios_romfile_setup(void) +{ + struct romfile_s *f_anchor = romfile_find("etc/smbios/smbios-anchor"); + struct romfile_s *f_tables = romfile_find("etc/smbios/smbios-tables"); + struct smbios_entry_point ep; + struct smbios_type_0 *t0; + u16 qtables_len, need_t0 = 1; + u8 *qtables, *tables; + + if (!f_anchor || !f_tables || f_anchor->size != sizeof(ep)) + return 0; + + f_anchor->copy(f_anchor, &ep, f_anchor->size); + + if (f_tables->size != ep.structure_table_length) + return 0; + + qtables = malloc_tmphigh(f_tables->size); + if (!qtables) { + warn_noalloc(); + return 0; + } + f_tables->copy(f_tables, qtables, f_tables->size); + ep.structure_table_address = (u32)qtables; /* for smbios_next(), below */ + + /* did we get a type 0 structure ? */ + for (t0 = smbios_next(&ep, NULL); t0; t0 = smbios_next(&ep, t0)) + if (t0->header.type == 0) { + need_t0 = 0; + break; + } + + qtables_len = ep.structure_table_length; + if (need_t0) { + /* common case: add our own type 0, with 3 strings and 4 '\0's */ + u16 t0_len = sizeof(struct smbios_type_0) + strlen(BIOS_NAME) + + strlen(VERSION) + strlen(BIOS_DATE) + 4; + ep.structure_table_length += t0_len; + if (t0_len > ep.max_structure_size) + ep.max_structure_size = t0_len; + ep.number_of_structures++; + } + + /* allocate final blob and record its address in the entry point */ + if (ep.structure_table_length > BUILD_MAX_SMBIOS_FSEG) + tables = malloc_high(ep.structure_table_length); + else + tables = malloc_fseg(ep.structure_table_length); + if (!tables) { + warn_noalloc(); + free(qtables); + return 0; + } + ep.structure_table_address = (u32)tables; + + /* populate final blob */ + if (need_t0) + tables = smbios_new_type_0(tables, BIOS_NAME, VERSION, BIOS_DATE); + memcpy(tables, qtables, qtables_len); + free(qtables); + + /* finalize entry point */ + ep.checksum -= checksum(&ep, 0x10); + ep.intermediate_checksum -= checksum((void *)&ep + 0x10, ep.length - 0x10); + + copy_smbios(&ep); + return 1; +} + +void +smbios_setup(void) +{ + if (smbios_romfile_setup()) + return; + smbios_legacy_setup(); +} void copy_table(void *pos) diff --git a/src/fw/smbios.c b/src/fw/smbios.c index 0ac9ff5..dba0541 100644 --- a/src/fw/smbios.c +++ b/src/fw/smbios.c @@ -504,7 +504,7 @@ smbios_init_type_127(void *start) #define TEMPSMBIOSSIZE (32 * 1024) void -smbios_setup(void) +smbios_legacy_setup(void) { if (! CONFIG_SMBIOS) return; diff --git a/src/util.h b/src/util.h index 4f242bf..9557581 100644 --- a/src/util.h +++ b/src/util.h @@ -78,6 +78,7 @@ extern struct smbios_entry_point *SMBiosAddr; void copy_smbios(void *pos); void display_uuid(void); void copy_table(void *pos); +void smbios_setup(void); // fw/coreboot.c extern const char *CBvendor, *CBpart; @@ -117,7 +118,7 @@ void make_bios_readonly(void); void qemu_prep_reset(void); // fw/smbios.c -void smbios_setup(void); +void smbios_legacy_setup(void); // fw/smm.c void smm_device_setup(void);