From nobody Sun Feb 8 19:59:47 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1488435697325103.84506769180689; Wed, 1 Mar 2017 22:21:37 -0800 (PST) Received: from localhost ([::1]:50608 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cjK7L-0001TE-Mn for importer@patchew.org; Thu, 02 Mar 2017 01:21:35 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:44155) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cjK6F-0001So-RD for qemu-devel@nongnu.org; Thu, 02 Mar 2017 01:20:29 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1cjK6B-000338-Er for qemu-devel@nongnu.org; Thu, 02 Mar 2017 01:20:27 -0500 Received: from mail.kernel.org ([198.145.29.136]:51016) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1cjK6B-00031M-3o for qemu-devel@nongnu.org; Thu, 02 Mar 2017 01:20:23 -0500 Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 2FEC220320; Thu, 2 Mar 2017 06:20:21 +0000 (UTC) Received: from redhat.com (pool-96-237-235-121.bstnma.fios.verizon.net [96.237.235.121]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 7399C202E5; Thu, 2 Mar 2017 06:20:19 +0000 (UTC) Date: Thu, 2 Mar 2017 08:20:18 +0200 From: "Michael S. Tsirkin" To: qemu-devel@nongnu.org Message-ID: <1488435591-17882-2-git-send-email-mst@redhat.com> References: <1488435591-17882-1-git-send-email-mst@redhat.com> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <1488435591-17882-1-git-send-email-mst@redhat.com> X-Mailer: git-send-email 2.8.0.287.g0deeb61 X-Mutt-Fcc: =sent X-Virus-Scanned: ClamAV using ClamSMTP X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x [fuzzy] X-Received-From: 198.145.29.136 Subject: [Qemu-devel] [PULL 01/15] 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: Peter Maydell , Laszlo Ersek , Ben Warren , Igor Mammedov Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" 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 Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- include/hw/acpi/bios-linker-loader.h | 7 ++++ hw/acpi/bios-linker-loader.c | 66 ++++++++++++++++++++++++++++++++= ++-- 2 files changed, 70 insertions(+), 3 deletions(-) diff --git a/include/hw/acpi/bios-linker-loader.h b/include/hw/acpi/bios-li= nker-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); =20 +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 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; =20 + /* + * 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; =20 enum { - BIOS_LINKER_LOADER_COMMAND_ALLOCATE =3D 0x1, - BIOS_LINKER_LOADER_COMMAND_ADD_POINTER =3D 0x2, - BIOS_LINKER_LOADER_COMMAND_ADD_CHECKSUM =3D 0x3, + BIOS_LINKER_LOADER_COMMAND_ALLOCATE =3D 0x1, + BIOS_LINKER_LOADER_COMMAND_ADD_POINTER =3D 0x2, + BIOS_LINKER_LOADER_COMMAND_ADD_CHECKSUM =3D 0x3, + BIOS_LINKER_LOADER_COMMAND_WRITE_POINTER =3D 0x4, }; =20 enum { @@ -278,3 +294,47 @@ void bios_linker_loader_add_pointer(BIOSLinker *linker, =20 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 =3D + 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 =3D cpu_to_le32(BIOS_LINKER_LOADER_COMMAND_WRITE_POINTER= ); + entry.wr_pointer.dst_offset =3D cpu_to_le32(dst_patched_offset); + entry.wr_pointer.src_offset =3D cpu_to_le32(src_offset); + entry.wr_pointer.size =3D dst_patched_size; + assert(dst_patched_size =3D=3D 1 || dst_patched_size =3D=3D 2 || + dst_patched_size =3D=3D 4 || dst_patched_size =3D=3D 8); + + g_array_append_vals(linker->cmd_blob, &entry, sizeof entry); +} --=20 MST