Post by David WoodhouseNo, I was avoiding the nvram variables altogether. This is an
"appliance" disk, with Grub installed at /efi/boot/bootx64.efi, with
no NvVars file on its EFI partition, which works fine when I just run
'qemu -hda efidisk.img'. I go into the boot menu, elect to boot from
the 'EFI Hard Drive' option that appears there, and it works. It does
not appear in the menu when it's attached as virtio, and that is based
*purely* on the device path of the block device. Nothing else.
It's getting clearer. The device path (excluding directories and the
filename) for IDE looks like:
PciRoot(0x0)/Pci(0x1,0x1)/Ata(Primary,Master,0x0)/HD(...)
whereas for virtio-blk it is
PciRoot(0x0)/Pci(0x6,0x3)/HD(...)
In the IDE case, there's an Ata(...) DP node:
- type: MESSAGING_DEVICE_PATH,
- subtype: MSG_ATAPI_DP,
for which BdsGetBootTypeFromDevicePath() returns
BDS_EFI_MESSAGE_ATAPI_BOOT (before reaching the HD(...) node).
That in turn makes BdsLibEnumerateAllBootOption() auto-generate a boot
option (= call to BdsLibBuildOptionFromHandle()).
... I'm not sure how to fix this (if at all):
(a) Is it a bug in the virtio-blk driver, not to produce such a child
device path node? When I was writing the driver and reading the driver
writers' guide & the UEFI spec, it seemed like producing an extra child
node was not necessary.
(b) If it *is* a bug in the virtio-blk driver, then a node of what
type/subtype should be appended, so that BdsLibEnumerateAllBootOption()
is happy with it? It is
- neither BDS_EFI_ACPI_FLOPPY_BOOT,
- nor BDS_EFI_MESSAGE_ATAPI_BOOT,
- nor BDS_EFI_MESSAGE_SATA_BOOT,
- nor BDS_EFI_MESSAGE_USB_DEVICE_BOOT,
- nor BDS_EFI_MESSAGE_SCSI_BOOT.
BDS_EFI_MESSAGE_MISC_BOOT would be an option. For that a child node of
type MESSAGING_DEVICE_PATH would be necessary. Available subtypes are:
- MSG_ATAPI_DP (mapped to BDS_EFI_MESSAGE_ATAPI_BOOT)
- MSG_SCSI_DP (mapped to BDS_EFI_MESSAGE_SCSI_BOOT)
- MSG_FIBRECHANNEL_DP
- MSG_FIBRECHANNELEX_DP
- MSG_1394_DP
- MSG_USB_DP (mapped to BDS_EFI_MESSAGE_USB_DEVICE_BOOT)
- MSG_USB_CLASS_DP
- MSG_USB_WWID_DP
- MSG_DEVICE_LOGICAL_UNIT_DP
- MSG_SATA_DP (mapped to BDS_EFI_MESSAGE_SATA_BOOT)
- MSG_I2O_DP
- MSG_MAC_ADDR_DP (mapped to BDS_EFI_MESSAGE_MAC_BOOT)
- MSG_IPv4_DP (mapped to BDS_EFI_MESSAGE_MAC_BOOT)
- MSG_IPv6_DP (mapped to BDS_EFI_MESSAGE_MAC_BOOT)
- MSG_INFINIBAND_DP
- MSG_UART_DP
- MSG_VENDOR_DP
- MSG_SASEX_DP
- MSG_ISCSI_DP
- MSG_VLAN_DP (mapped to BDS_EFI_MESSAGE_MAC_BOOT)
The not yet mapped subtypes are:
- MSG_FIBRECHANNEL_DP
- MSG_FIBRECHANNELEX_DP
- MSG_1394_DP
- MSG_USB_CLASS_DP
- MSG_USB_WWID_DP
- MSG_DEVICE_LOGICAL_UNIT_DP
- MSG_I2O_DP
- MSG_INFINIBAND_DP
- MSG_UART_DP
- MSG_VENDOR_DP
- MSG_SASEX_DP
- MSG_ISCSI_DP
The only subtype I can imagine is MSG_VENDOR_DP.
So, we could be tempted to answer question (b) with "append a node with
type/subtype = MESSAGING_DEVICE_PATH/MSG_VENDOR_DP". However, from UEFI
2.3.1+errC:
9.3.5.17 Vendor-Defined Messaging Device Path:
--------v--------
The following GUIDs are used with a Vendor-Defined Messaging Device Path
to describe the transport protocol for use with PC-ANSI, VT-100,
VT-100+, and VT-UTF8 terminals. Device paths can be constructed with
this node as the last node in the device path. The rest of the device
path describes the physical device that is being used to transmit and
receive data. The PC-ANSI, VT- 100, VT-100+, and VT-UTF8 GUIDs define
the format of the data that is being sent though the physical device.
Additional GUIDs can be generated to describe additional transport
protocols.
--------^--------
I don't think this fits virtio-blk.
Regarding question (a), I'll have to check in the specs (help
appreciated!) whether virtio-blk is required to produce a messaging
device path node at all. I can't (yet?) see why a messaging DP node
before the final HD(...) is a requirement.
... The UEFI 2.3.1+errC spec says in 9.3.5 Messaging Device Path:
--------v--------
This Device Path is used to describe the connection of devices outside
the resource domain of the system. This Device Path can describe
physical messaging information like SCSI ID, or abstract information
like networking protocol IP addresses.
--------^--------
In the DWG-2.3.1, section 3.9 says:
--------v--------
Messaging device path node: Used to describe devices on
industry-standard buses that are not directly accessible through
processor memory or processor I/O cycles. These devices are accessed by
the processor through one or more hardware bridge devices that translate
one industry-standard bus type to another industry-standard bus type.
This type of device path is used to describe devices such as SCSI, Fibre
Channel, 1394, USB, I2O, InfiniBand®, UARTs, and network agents.
--------^--------
These don't hold for virtio-blk. The virtio-blk device is in fact a PCI
device, and I recall that I approached the driver as one for an
individual PCI bus/dev/func that provides the block IO interface. (The
related DP node type is HARDWARE_DEVICE_PATH/HW_PCI_DP, which is printed
as Pci(...).) According to my comments in the driver, I was following
the following specs:
--------v--------
Specs relevant in the specific sense:
- UEFI Spec 2.3.1 + Errata C, 13.4 EFI PCI I/O Protocol
- Driver Writer's Guide for UEFI 2.3.1 v1.01, 18 PCI Driver Design
Guidelines, 18.3 PCI drivers.
--------^--------
UEFI 2.3.1+errC, 9.4.4 Hardware vs. Messaging Device Path Rules:
--------v--------
Hardware Device Paths are used to define paths on buses that have a
standard enumeration algorithm and that relate directly to the coherency
domain of the system. The coherency domain is defined as a global set of
resources that is visible to at least one processor in the system. In a
typical system this would include the processor memory space, IO space,
and PCI configuration space.
Messaging Device Paths are used to define paths on buses that have a
standard enumeration algorithm, but are not part of the global coherency
domain of the system. SCSI and Fibre Channel are examples of this kind
of bus. The Messaging Device Path can also be used to describe virtual
connections over network-style devices. An example would be the TCPI/IP
address of an internet connection.
Thus Hardware Device Path is used if the bus produces resources that
show up in the coherency resource domain of the system. A Message Device
Path is used if the bus consumes resources from the coherency domain and
produces resources out side the coherency domain of the system.
--------^--------
This puts virtio-blk firmly in hardware device path domain, as it is
accessed via PCI IO space and (pseudo-)physical memory.
... So why does BdsLibEnumerateAllBootOption() insist on a messaging
device path node? I guess the idea captured in there is that a device
hanging off a messaging device path is *conceptually* "removable", and
BdsLibEnumerateAllBootOption() wants to auto-generate boot options for
removable devices.
I think this isn't a bug in virtio-blk. I believe
BdsLibEnumerateAllBootOption() and BdsGetBootTypeFromDevicePath() face
an unexpected case where a system can be booted purely through PCI IO
space access.
Post by David WoodhouseBut since we're speaking of nvram, my plan for fixing that is probably
to use qemu's fw_cfg. I believe that fw_cfg "files" are actually
writeable from the guest, so we could use *that* for storing nvram
variables instead of the NvVars file on the EFI partition which, as
discussed, only works before the OS might have it mounted.
(fw_cfg entries seem to be writable indeed, with an optional qemu
callback to be invoked once the last byte in the entry is written.
Resizing of entries doesn't appear possible from a cursory look.)
Laszlo