Thread (26 messages) flat view 26 messages, 9 authors, 2015-11-04

[PATCH v3 0/4] SysFS driver for QEMU fw_cfg device

From: mark.rutland@arm.com (Mark Rutland)
Date: 2015-10-05 10:01:04
Also in: linux-api, lkml, qemu-devel

On Sat, Oct 03, 2015 at 07:28:05PM -0400, Gabriel L. Somlo wrote:
From: "Gabriel Somlo" <redacted>

Allow access to QEMU firmware blobs, passed into the guest VM via
the fw_cfg device, through SysFS entries. Blob meta-data (e.g. name,
size, and fw_cfg key), as well as the raw binary blob data may be
accessed.

The SysFS access location is /sys/firmware/qemu_fw_cfg/... and was
selected based on overall similarity to the type of information
exposed under /sys/firmware/dmi/entries/...
What is the intended use of these?

Some of the keys in the example look like they'd come from other sources
(e.g. the *-tables entries), while others look like kernel/bootloader
configuration options (e.g. etc/boot-fail-wait, bootorder) -- I'm
concerned about redundancy here.
NEW (since v2): Using ACPI to detect the presence and details of the
fw_cfg virtual hardware device.

    Device Tree has been suggested by Ard as a comment on v2 of this
    patch, but after some deliberation I decided to go with ACPI,
    since it's supported on both x86 and some (uefi-enabled) versions
    of aarch64. I really don't see how I'd reasonably use *both* DT (on
    ARM) *and* ACPI (on x86), and after all I'm mostly concerned with
    x86, but originally wanted to maximize portability (which is where
    the register probing in earlier versions came from).
There are defintitely going to be arm64 VMs that don't use ACPI, so we
may need DT support depending on what the intended use is.

I'm not sure I follow what the difficulty with supporting DT in addition
to ACPI is? It looks like all you need is a compatible string and a reg
entry.

Thanks,
Mark.
    A patch set generating an ACPI device node for qemu's fw_cfg is
    currently under review on the qemu-devel list:

    http://lists.nongnu.org/archive/html/qemu-devel/2015-09/msg06946.html
    (sorry, gmane appears down at the moment...)

In consequence:

	- Patch 1/4 is mostly the same as in v2;
	- Patch 2/4 switches device initialization from register
	  probing to using ACPI; this is a separate patch only to
	  illustrate the transition from probing to ACPI, and I'm
	  assuming it will end up squashed on top of patch 1/4 in
	  the final version.

	- Patches 3/4 and 4/4 add a "human-readable" directory
	  hierarchy built from tokenizing fw_cfg blob names into
	  '/'-separated components, with symlinks to each 'by_key'
	  blob folder (same as in earlier versions). At Greg's
	  suggestion I tried to build this folder hierarchy and
	  leaf symlinks using udev rules, but so far I haven't been
	  successful in figuring that out. If udev turns out to 
	  be applicable after all, these two patches can be dropped
	  from this series.

In other words, patches 1 and 2 give us the following "by_key" listing
of blobs contained in the qemu fw_cfg device (example pulled from a PC
qemu guest running Fedora 22), with the value of each "name" attribute
shown on the right:

$ tree /sys/firmware/qemu_fw_cfg/
/sys/firmware/qemu_fw_cfg/
|-- by_key
|   |-- 32
|   |   |-- key
|   |   |-- name			("etc/boot-fail-wait")
|   |   |-- raw
|   |   `-- size
|   |-- 33
|   |   |-- key
|   |   |-- name			("etc/smbios/smbios-tables")
|   |   |-- raw
|   |   `-- size
|   |-- 34
|   |   |-- key
|   |   |-- name			("etc/smbios/smbios-anchor")
|   |   |-- raw
|   |   `-- size
|   |-- 35
|   |   |-- key
|   |   |-- name			("etc/e820")
|   |   |-- raw
|   |   `-- size
|   |-- 36
|   |   |-- key
|   |   |-- name			("genroms/kvmvapic.bin")
|   |   |-- raw
|   |   `-- size
|   |-- 37
|   |   |-- key
|   |   |-- name			("etc/system-states")
|   |   |-- raw
|   |   `-- size
|   |-- 38
|   |   |-- key
|   |   |-- name			("etc/acpi/tables")
|   |   |-- raw
|   |   `-- size
|   |-- 39
|   |   |-- key
|   |   |-- name			("etc/table-loader")
|   |   |-- raw
|   |   `-- size
|   |-- 40
|   |   |-- key
|   |   |-- name			("etc/tpm/log")
|   |   |-- raw
|   |   `-- size
|   |-- 41
|   |   |-- key
|   |   |-- name			("etc/acpi/rsdp")
|   |   |-- raw
|   |   `-- size
|   `-- 42
|       |-- key
|       |-- name			("bootorder")
|       |-- raw
|       `-- size
|
...

Additionally, patches 3 and 4 (mostly 4) give us the following
"user friendly" directory hierarchy as a complement to the above,
based on tokenizing each blob name into symlink-tipped (sub)directories:

...
|-- by_name
|   |-- bootorder -> ../by_key/42
|   |-- etc
|   |   |-- acpi
|   |   |   |-- rsdp -> ../../../by_key/41
|   |   |   `-- tables -> ../../../by_key/38
|   |   |-- boot-fail-wait -> ../../by_key/32
|   |   |-- e820 -> ../../by_key/35
|   |   |-- smbios
|   |   |   |-- smbios-anchor -> ../../../by_key/34
|   |   |   `-- smbios-tables -> ../../../by_key/33
|   |   |-- system-states -> ../../by_key/37
|   |   |-- table-loader -> ../../by_key/39
|   |   `-- tpm
|   |       `-- log -> ../../../by_key/40
|   `-- genroms
|       `-- kvmvapic.bin -> ../../by_key/36
`-- rev

The trick is to figure out how to replace patches 3 and 4 with a
udev rule that would read the contents of each "name" attribute,
and build the "by_name" hierarchy and symlinks in userspace.

I tried:

$ udevadm info -a -p /sys/firmware/qemu_fw_cfg/by_key/33

  looking at device '/firmware/qemu_fw_cfg/by_key/33':
    KERNEL=="33"
    SUBSYSTEM==""
    DRIVER==""
    ATTR{key}=="33"
    ATTR{name}=="etc/smbios/smbios-tables"
    ATTR{size}=="388"

  looking at parent device '/firmware/qemu_fw_cfg/by_key':
    KERNELS=="by_key"
    SUBSYSTEMS==""
    DRIVERS==""

  looking at parent device '/firmware/qemu_fw_cfg':
    KERNELS=="qemu_fw_cfg"
    SUBSYSTEMS==""
    DRIVERS==""
    ATTRS{rev}=="1"

Then I tried creating a file, /usr/lib/udev/rules.d/99-qemu-fw-cfg.rules
containing the following line:

KERNELS=="qemu_fw_cfg", ATTRS{rev}=="1", SYMLINK="%p/%s{name}"

but NOTHING happens when I insert/remove qemu_fw_cfg.ko.  I also tried:

KERNELS=="qemu_fw_cfg", ATTRS{rev}=="1", PROGRAM="/foo %k"

where "/foo" basically did "echo $* > /tmp/bar", but no /tmp/bar file ever
showed up as a consequence of inserting/removing the qemu_fw_cfg.ko module.

At this point, I need help figuring out whether udev is really what would
get the second, user-friendly, "by_name" /sysfs directory tree created,
and how I'd go about that...

Thanks much,
  --Gabriel

Gabriel Somlo (4):
  firmware: introduce sysfs driver for QEMU's fw_cfg device
  firmware: use acpi to detect QEMU fw_cfg device for sysfs fw_cfg
    driver
  kobject: export kset_find_obj() for module use
  firmware: create directory hierarchy for sysfs fw_cfg entries

 .../ABI/testing/sysfs-firmware-qemu_fw_cfg         | 213 ++++++++
 drivers/firmware/Kconfig                           |  10 +
 drivers/firmware/Makefile                          |   1 +
 drivers/firmware/qemu_fw_cfg.c                     | 575 +++++++++++++++++++++
 lib/kobject.c                                      |   1 +
 5 files changed, 800 insertions(+)
 create mode 100644 Documentation/ABI/testing/sysfs-firmware-qemu_fw_cfg
 create mode 100644 drivers/firmware/qemu_fw_cfg.c

-- 
2.4.3
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help