From patchwork Thu Feb 16 23:15:33 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: ben@skyportsystems.com X-Patchwork-Id: 9578513 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 4AA8660244 for ; Thu, 16 Feb 2017 23:20:57 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 352902768C for ; Thu, 16 Feb 2017 23:20:57 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 2594728698; Thu, 16 Feb 2017 23:20:57 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.8 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI,T_DKIM_INVALID autolearn=ham version=3.3.1 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 mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 545B12768C for ; Thu, 16 Feb 2017 23:20:56 +0000 (UTC) Received: from localhost ([::1]:50764 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ceVM7-0005OY-6p for patchwork-qemu-devel@patchwork.kernel.org; Thu, 16 Feb 2017 18:20:55 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:42921) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ceVHA-0000R0-D0 for qemu-devel@nongnu.org; Thu, 16 Feb 2017 18:15:49 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ceVH8-0000tZ-1q for qemu-devel@nongnu.org; Thu, 16 Feb 2017 18:15:48 -0500 Received: from mail-pf0-x22b.google.com ([2607:f8b0:400e:c00::22b]:33026) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1ceVH7-0000sE-IQ for qemu-devel@nongnu.org; Thu, 16 Feb 2017 18:15:45 -0500 Received: by mail-pf0-x22b.google.com with SMTP id c73so8711345pfb.0 for ; Thu, 16 Feb 2017 15:15:45 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=skyportsystems.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :in-reply-to:references; bh=jXQCT/kPvJtkjZX3tIvfPLZlD0I0WdNoSXWwb51HPnE=; b=huXLZOSuAPbe6LJqXek6hllrbN3ISk5sbUTGSYucbkM3w93NPmEzYdeVyKozLZ0C7i bagXTzG2aR4OJvQqtwImPrxZxWsTyN3ld7SPU/S6PDv6IjlbpGttCeAAE2QYH+LMP2zJ uCrnBPZ1P7Qyb8AyMjMlF4Z1sVS1e40eqpn0Q= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:in-reply-to:references; bh=jXQCT/kPvJtkjZX3tIvfPLZlD0I0WdNoSXWwb51HPnE=; b=oKMf7jgflxas/le6EpPjfyro2uiQXyyq5XqEpQtBpiae48EAwB5voHRo/0sDGvNlxA QqTHjt3XyAxDfRutRIcAhh8HzrAHfmFq34SHnvWrBO5LaitdXfFfoU+f74Odp3RWPSVJ 3yOJtsrHjfi7n4QZ1s6DGoSdiSPKq2OsCzGeBiq8MKfc1vIcuQzG0L9d8FN1oepiKO/k 8Oi3GzZMe4BQcFlJhcg+Jki2UKaVGmUHs0YUyc8sO8WC1wucGL9KJkaK32UEhGrSf5NK yslgXZ+/HyvDRRAVyb3hYYPH7g+XbYvQLNQtTRd50hl1GqVX2bSSq2w82CUN2Rx2Tgur hipA== X-Gm-Message-State: AMke39n9FIml9u7gIcsGLWgSXzhBrimgxyRQXzngTQOElVKxbCIGCDPBOSUnYMu3aH5uwy4u X-Received: by 10.98.14.84 with SMTP id w81mr5693691pfi.168.1487286944624; Thu, 16 Feb 2017 15:15:44 -0800 (PST) Received: from Arrow.corp.skyportsystems.com (67-207-112-138.static.wiline.com. [67.207.112.138]) by smtp.gmail.com with ESMTPSA id r74sm15455696pfb.67.2017.02.16.15.15.43 (version=TLS1 cipher=AES128-SHA bits=128/128); Thu, 16 Feb 2017 15:15:43 -0800 (PST) From: ben@skyportsystems.com To: qemu-devel@nongnu.org Date: Thu, 16 Feb 2017 15:15:33 -0800 Message-Id: X-Mailer: git-send-email 2.10.1 (Apple Git-78) In-Reply-To: References: In-Reply-To: References: X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 2607:f8b0:400e:c00::22b Subject: [Qemu-devel] [PATCH v8 1/8] linker-loader: Add new 'write pointer' command X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: imammedo@redhat.com, lersek@redhat.com, Ben Warren , mst@redhat.com Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP From: Ben Warren This is similar to the existing 'add pointer' functionality, but instead of instructing the guest (BIOS or UEFI) to patch memory, it instructs the guest to write the pointer back to QEMU via a writeable fw_cfg file. Signed-off-by: Ben Warren Reviewed-by: Laszlo Ersek Reviewed-by: Igor Mammedov Tested-by: Laszlo Ersek --- hw/acpi/bios-linker-loader.c | 66 ++++++++++++++++++++++++++++++++++-- include/hw/acpi/bios-linker-loader.h | 7 ++++ 2 files changed, 70 insertions(+), 3 deletions(-) diff --git a/hw/acpi/bios-linker-loader.c b/hw/acpi/bios-linker-loader.c index d963ebe..046183a 100644 --- a/hw/acpi/bios-linker-loader.c +++ b/hw/acpi/bios-linker-loader.c @@ -78,6 +78,21 @@ struct BiosLinkerLoaderEntry { uint32_t length; } cksum; + /* + * COMMAND_WRITE_POINTER - write the fw_cfg file (originating from + * @dest_file) at @wr_pointer.offset, by adding a pointer to + * @src_offset within the table originating from @src_file. + * 1,2,4 or 8 byte unsigned addition is used depending on + * @wr_pointer.size. + */ + struct { + char dest_file[BIOS_LINKER_LOADER_FILESZ]; + char src_file[BIOS_LINKER_LOADER_FILESZ]; + uint32_t dst_offset; + uint32_t src_offset; + uint8_t size; + } wr_pointer; + /* padding */ char pad[124]; }; @@ -85,9 +100,10 @@ struct BiosLinkerLoaderEntry { typedef struct BiosLinkerLoaderEntry BiosLinkerLoaderEntry; enum { - BIOS_LINKER_LOADER_COMMAND_ALLOCATE = 0x1, - BIOS_LINKER_LOADER_COMMAND_ADD_POINTER = 0x2, - BIOS_LINKER_LOADER_COMMAND_ADD_CHECKSUM = 0x3, + BIOS_LINKER_LOADER_COMMAND_ALLOCATE = 0x1, + BIOS_LINKER_LOADER_COMMAND_ADD_POINTER = 0x2, + BIOS_LINKER_LOADER_COMMAND_ADD_CHECKSUM = 0x3, + BIOS_LINKER_LOADER_COMMAND_WRITE_POINTER = 0x4, }; enum { @@ -278,3 +294,47 @@ void bios_linker_loader_add_pointer(BIOSLinker *linker, g_array_append_vals(linker->cmd_blob, &entry, sizeof entry); } + +/* + * bios_linker_loader_write_pointer: ask guest to write a pointer to the + * source file into the destination file, and write it back to QEMU via + * fw_cfg DMA. + * + * @linker: linker object instance + * @dest_file: destination file that must be written + * @dst_patched_offset: location within destination file blob to be patched + * with the pointer to @src_file, in bytes + * @dst_patched_offset_size: size of the pointer to be patched + * at @dst_patched_offset in @dest_file blob, in bytes + * @src_file: source file who's address must be taken + * @src_offset: location within source file blob to which + * @dest_file+@dst_patched_offset will point to after + * firmware's executed WRITE_POINTER command + */ +void bios_linker_loader_write_pointer(BIOSLinker *linker, + const char *dest_file, + uint32_t dst_patched_offset, + uint8_t dst_patched_size, + const char *src_file, + uint32_t src_offset) +{ + BiosLinkerLoaderEntry entry; + const BiosLinkerFileEntry *source_file = + bios_linker_find_file(linker, src_file); + + assert(source_file); + assert(src_offset < source_file->blob->len); + memset(&entry, 0, sizeof entry); + strncpy(entry.wr_pointer.dest_file, dest_file, + sizeof entry.wr_pointer.dest_file - 1); + strncpy(entry.wr_pointer.src_file, src_file, + sizeof entry.wr_pointer.src_file - 1); + entry.command = cpu_to_le32(BIOS_LINKER_LOADER_COMMAND_WRITE_POINTER); + entry.wr_pointer.dst_offset = cpu_to_le32(dst_patched_offset); + entry.wr_pointer.src_offset = cpu_to_le32(src_offset); + entry.wr_pointer.size = dst_patched_size; + assert(dst_patched_size == 1 || dst_patched_size == 2 || + dst_patched_size == 4 || dst_patched_size == 8); + + g_array_append_vals(linker->cmd_blob, &entry, sizeof entry); +} diff --git a/include/hw/acpi/bios-linker-loader.h b/include/hw/acpi/bios-linker-loader.h index fa1e5d1..efe17b0 100644 --- a/include/hw/acpi/bios-linker-loader.h +++ b/include/hw/acpi/bios-linker-loader.h @@ -26,5 +26,12 @@ void bios_linker_loader_add_pointer(BIOSLinker *linker, const char *src_file, uint32_t src_offset); +void bios_linker_loader_write_pointer(BIOSLinker *linker, + const char *dest_file, + uint32_t dst_patched_offset, + uint8_t dst_patched_size, + const char *src_file, + uint32_t src_offset); + void bios_linker_loader_cleanup(BIOSLinker *linker); #endif