From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [216.205.24.124]) by mx.groups.io with SMTP id smtpd.web08.13689.1603805201883177219 for ; Tue, 27 Oct 2020 06:26:42 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=NdyCNKBU; spf=pass (domain: redhat.com, ip: 216.205.24.124, mailfrom: lersek@redhat.com) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1603805201; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=xJSxhnSpwJhGIf5w9dbGR+FsJe579qw/Wq5NiEsM2Bw=; b=NdyCNKBUbJ6ZOvHw8XiaC9bGlcE/tSkNIaQEMO3BMfgy8LMnwxGFxC7APo96nCxTpFzRuy LwyiqQNyTzxg5F0eNQ1KPs0PyB7FBfAHGTEyVqv2attbP5IiWStvEIGba6c/siUya+R4ya +TQ2GIkHj02U7z9aNIT6PFlmbHMJMpI= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-469-1HmvTKwSOBmfXtKWuFMq1g-1; Tue, 27 Oct 2020 09:26:35 -0400 X-MC-Unique: 1HmvTKwSOBmfXtKWuFMq1g-1 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 62FE3809DDA; Tue, 27 Oct 2020 13:26:34 +0000 (UTC) Received: from lacos-laptop-7.usersys.redhat.com (ovpn-114-132.ams2.redhat.com [10.36.114.132]) by smtp.corp.redhat.com (Postfix) with ESMTP id 79D726EF5F; Tue, 27 Oct 2020 13:26:33 +0000 (UTC) Subject: Re: [edk2-devel] OVMF/QEMU shell based unit tests and writing to a virtual disk To: devel@edk2.groups.io, spbrogan@outlook.com, discuss@edk2.groups.io References: From: "Laszlo Ersek" Message-ID: Date: Tue, 27 Oct 2020 14:26:32 +0100 MIME-Version: 1.0 In-Reply-To: X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=lersek@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Type: text/plain; charset=utf-8 Content-Language: en-US Content-Transfer-Encoding: 8bit On 10/22/20 20:55, Sean wrote: > Laszlo and others familiar with QEMU, > > I am trying to write automation that boots QEMU/OVMF and then runs EFI > applications and those efi applications then use the UEFI shell apis to > write back to the disk their state.  I am seeing very inconsistent > results with sometimes it working fine while other times the disk > contents are invalid.  If i run multiple tests it seems like the first > two work while the 3rd seems to start failing but overall it seems random. > > Failing means: >     Disk contents corrupted but present. >     Disk contents wrong size (short). >     Files that show written in UEFI shell never show up on host. > > I am trying to determine if this is a known limitation with QEMU or a > bug i need to track down in the unit test code. > > My setup: > > This is on a Windows 10 x64 host.  I am running current 5.1 version of > QEMU. > > My script creates a folder in the Windows NTFS file system.  Copies the > EFI executables and startup.nsh files to it.  Then starts QEMU with the > following additional parameter. > >  -drive file=fat:rw:{VirtualDrive},format=raw,media=disk This is the problem. Don't use the fat / vvfat block driver for anything meaningful. I don't even have to look at particulars; as "fat" ("vvfat") is known to be a hack. In particular write operations should not be relied on (either guest->host or host->guest directions). Don't expect this QEMU feature to work as a "semihosting" (esp. "live semihosting") solution. What's important to understand about "vvfat" is that it attempts to *re-compose* a filesystem view from block-level operations. *De-composing* file operations into block operations is an everyday occurrence (that's what filesystem drivers do everywhere). But the write direction of vvfat attempts to do the *inverse* -- it seeks to recognize block operations and to synthesize file operations from them. If you get lucky, it sometimes even works. Instead, please use a regular virtual disk image in the QEMU configuration. This disk image should not be accessed concurrently by QEMU (= the guest) and other host-side utilities. In other words, first format / populate the disk image on the host side, then launch QEMU. Then in the guest UEFI shell, terminate the guest with the "reset -s" command. Finally, once QEMU has exited, use host-side utilities to fetch the results from the virtual disk image. On the host side (on a Linux installation anyway), I tend to use the "mtools" package (such as "mcopy" etc), for manipulating the contents of disk image files. Or, more frequently, the "guestfish" program (which is extremely capable). https://libguestfs.org/guestfish.1.html I don't know if equivalents exist on Windows. Now, another option (on Linux anyway) is to loop-mount a "raw" virtual disk image. This is not recommended, as it directly exposes the host kernel's filesystem driver(s) to metadata produced by the guest. It could trigger security issues in the host kernel. (This is exactly what guestfish avoids, by running a separate Linux guest -- called the "libguestfs appliance" -- on top of the virtual disk image. The guestfish command interpreter on the host side exchanges commands and data with the appliance over virtio-serial. If the metadata on the disk image is malicious, it will break / exploit the *guest* kernel in the appliance. The host-side component, the guestfish command interpreter, only has to sanity-check the virtio-serial exchanges.) ... Earlier I've looked into "virtio-fs" support for OVMF: https://virtio-fs.gitlab.io/ https://www.redhat.com/archives/virtio-fs/2019-August/msg00349.html however, it's very complex, and the wire format (the opcodes) are extremely low-level and Linux specific. To the point where they directly mirror Linux VFS system calls, and (due to lack of documentation) I don't even understand what a big bunch of the opcodes *do*. Earlier I had given some thought to a mapping between EFI_SIMPLE_FILE_SYSTEM_PROTOCOL / EFI_FILE_PROTOCOL and the virtio-fs opcodes, but when I did that, it looked like a bad fit. Virtio-fs seems to aim at serializing *Linux guest* filesystem operations as tightly as possble for host-side processing, and that seemed like a big obstacle for a *UEFI guest* mapping. In particular, EFI_SIMPLE_FILE_SYSTEM_PROTOCOL / EFI_FILE_PROTOCOL don't really expect data and/or meta-data to change "under their feet" (-> due to asynchronous host-side modifications). For a while I was hopeful to expose such changes via the EFI_MEDIA_CHANGED return value. But -- alas, I forget the details -- it seemed to turn out that the virtio-fs interfaces wouldn't really let the EFI_SIMPLE_FILE_SYSTEM_PROTOCOL driver, to be provided by OVMF, even *detect* the situations when it should return EFI_SIMPLE_FILE_SYSTEM_PROTOCOL. So, the virtio-fs driver for OVMF has been postponed indefinitely, and the best I can recommend at the moment is to use a regular virtual disk image file. Remember that QEMU (= guest), and the other (host-side) utilities for manipulating the disk image, should be strictly serialized (they should mutually exclude each other). Thanks Laszlo > > VirtualDrive is the Windows file path of the said mentioned folder. > > > If interested you should be able to reproduce the results by pulling my > branch and/or you can review the above. > > You can see the operations here: > > PR: https://github.com/microsoft/mu_tiano_platforms/pull/1 > > My Branch: > https://github.com/spbrogan/mu_tiano_platforms/tree/personal/sebrogan/shellunittests > > > Or if interested you can reproduce it by following steps defined here: > > https://github.com/spbrogan/mu_tiano_platforms/blob/personal/sebrogan/shellunittests/Platforms/QemuQ35Pkg/Docs/building.md > > > and more details here > https://github.com/spbrogan/mu_tiano_platforms/blob/personal/sebrogan/shellunittests/Platforms/QemuQ35Pkg/Plugins/QemuRunner/ReadMe.md > > > After building qemu with the right parameters for your environment you > can run --flashonly MARK_STARTUP_NSH=TRUE > RUN_UNIT_TESTS=TRUE > > For example in my environment it looks like > stuart_build -c Platforms\QemuQ35Pkg\PlatformBuild.py > TOOL_CHAIN_TAG=VS2019 --flashonly RUN_UNIT_TESTS=TRUE MAKE_STARTUP_NSH=TRUE > > > Anyway if i recall correctly last year when we talked briefly about > automation there was some concern that this would happen. Any > information and/or ideas would be greatly appreciated. > > Thanks > Sean > > > > > > > > > > > >