usb: canokey fixes.

ui: better tab labels, cocoa fix,
 docs: convert fw_cfg to rst.
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEoDKM/7k6F6eZAf59TLbY7tPocTgFAmLCndwACgkQTLbY7tPo
 cTjNHA/+MT56crVXnjMTdgBRLOuq0cxYnIUptN0JPKx9DTJzdlXEyT+zYD7iIzUt
 W0xbOrTLVzU9hfJVh9/5V2HuFmc1eAhfl0BDTzd1TT0kdH6LyUkz5RWgotzo3nvH
 7tnl/sBy48a7diSyQn6K2s8r35ubrX1GNJiJcCLWdVEqvzKKWDEqebs02PxbN/OJ
 9UG9xtkM/QQ1+h74jq5BGKXf08xOhOZIjO274Sn5zievBC9JU6RVkCOlUXiBdk51
 +vNTfKt3c864cstryXSTknYWyVv7zKzCqr7xR7c+fgbt3cN/HmLkM9LGytDMEDl/
 IC0CtKiRN316GgVHHMDT8v8X2dVHNH9ZEEoXRKIbc5jD/tetJw7IIEO7blJphdpV
 WE4/bRpJwYVW9UHzig9rPRxsHLs3NSZbNCQEbGUvAbZzS2kq9hnDa/BBtFSYaf+X
 RIwR7rY7WhENfSrus1jR5rfWRU7n+q+fcNIFZetUakH1V6Idb0xQir3eM/yM6sBC
 nzQSzzLsd3Mwh2ahbnLZ1HkyybZV692usVylKsFLVwcUhCvk+VHccOF31QfrxO/j
 ogVzTYYtfrGM5kaknueIMg7XAhjQ04Av70+0b886kZawB3ZE5Ccare2TztHq1jcG
 dMdEm7DLaDRm2RXa9NtcbxsIrS0DT2EuFcBnQ1mHMCGql4MidzE=
 =Bhbw
 -----END PGP SIGNATURE-----

Merge tag 'kraxel-20220704-pull-request' of https://gitlab.com/kraxel/qemu into staging

usb: canokey fixes.
ui: better tab labels, cocoa fix,
docs: convert fw_cfg to rst.

# -----BEGIN PGP SIGNATURE-----
#
# iQIzBAABCgAdFiEEoDKM/7k6F6eZAf59TLbY7tPocTgFAmLCndwACgkQTLbY7tPo
# cTjNHA/+MT56crVXnjMTdgBRLOuq0cxYnIUptN0JPKx9DTJzdlXEyT+zYD7iIzUt
# W0xbOrTLVzU9hfJVh9/5V2HuFmc1eAhfl0BDTzd1TT0kdH6LyUkz5RWgotzo3nvH
# 7tnl/sBy48a7diSyQn6K2s8r35ubrX1GNJiJcCLWdVEqvzKKWDEqebs02PxbN/OJ
# 9UG9xtkM/QQ1+h74jq5BGKXf08xOhOZIjO274Sn5zievBC9JU6RVkCOlUXiBdk51
# +vNTfKt3c864cstryXSTknYWyVv7zKzCqr7xR7c+fgbt3cN/HmLkM9LGytDMEDl/
# IC0CtKiRN316GgVHHMDT8v8X2dVHNH9ZEEoXRKIbc5jD/tetJw7IIEO7blJphdpV
# WE4/bRpJwYVW9UHzig9rPRxsHLs3NSZbNCQEbGUvAbZzS2kq9hnDa/BBtFSYaf+X
# RIwR7rY7WhENfSrus1jR5rfWRU7n+q+fcNIFZetUakH1V6Idb0xQir3eM/yM6sBC
# nzQSzzLsd3Mwh2ahbnLZ1HkyybZV692usVylKsFLVwcUhCvk+VHccOF31QfrxO/j
# ogVzTYYtfrGM5kaknueIMg7XAhjQ04Av70+0b886kZawB3ZE5Ccare2TztHq1jcG
# dMdEm7DLaDRm2RXa9NtcbxsIrS0DT2EuFcBnQ1mHMCGql4MidzE=
# =Bhbw
# -----END PGP SIGNATURE-----
# gpg: Signature made Mon 04 Jul 2022 01:29:24 PM +0530
# gpg:                using RSA key A0328CFFB93A17A79901FE7D4CB6D8EED3E87138
# gpg: Good signature from "Gerd Hoffmann (work) <kraxel@redhat.com>" [undefined]
# gpg:                 aka "Gerd Hoffmann <gerd@kraxel.org>" [undefined]
# gpg:                 aka "Gerd Hoffmann (private) <kraxel@gmail.com>" [undefined]
# gpg: WARNING: This key is not certified with a trusted signature!
# gpg:          There is no indication that the signature belongs to the owner.
# Primary key fingerprint: A032 8CFF B93A 17A7 9901  FE7D 4CB6 D8EE D3E8 7138

* tag 'kraxel-20220704-pull-request' of https://gitlab.com/kraxel/qemu:
  hw: canokey: Remove HS support as not compliant to the spec
  docs/system/devices/usb/canokey: remove limitations on qemu-xhci
  hw/usb/canokey: fix compatibility of qemu-xhci
  hw/usb/canokey: Fix CCID ZLP
  ui/cocoa: Fix clipboard text release
  ui/console: allow display device to be labeled with given id
  Convert fw_cfg.rst to reStructuredText syntax
  Rename docs/specs/fw_cfg.txt to .rst

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
Richard Henderson 2022-07-04 14:57:21 +05:30
commit dfe2382f06
7 changed files with 189 additions and 110 deletions

View file

@ -1,7 +1,9 @@
===========================================
QEMU Firmware Configuration (fw_cfg) Device
===========================================
= Guest-side Hardware Interface =
Guest-side Hardware Interface
=============================
This hardware interface allows the guest to retrieve various data items
(blobs) that can influence how the firmware configures itself, or may
@ -9,7 +11,8 @@ contain tables to be installed for the guest OS. Examples include device
boot order, ACPI and SMBIOS tables, virtual machine UUID, SMP and NUMA
information, kernel/initrd images for direct (Linux) kernel booting, etc.
== Selector (Control) Register ==
Selector (Control) Register
---------------------------
* Write only
* Location: platform dependent (IOport or MMIO)
@ -30,10 +33,12 @@ of 1 means the item's data can be overwritten by writes to the data
register. In other words, configuration write mode is enabled when
the selector value is between 0x4000-0x7fff or 0xc000-0xffff.
NOTE: As of QEMU v2.4, writes to the fw_cfg data register are no
.. NOTE::
As of QEMU v2.4, writes to the fw_cfg data register are no
longer supported, and will be ignored (treated as no-ops)!
NOTE: As of QEMU v2.9, writes are reinstated, but only through the DMA
.. NOTE::
As of QEMU v2.9, writes are reinstated, but only through the DMA
interface (see below). Furthermore, writeability of any specific item is
governed independently of Bit14 in the selector key value.
@ -45,17 +50,19 @@ items are accessed with a selector value between 0x0000-0x7fff, and
architecture specific configuration items are accessed with a selector
value between 0x8000-0xffff.
== Data Register ==
Data Register
-------------
* Read/Write (writes ignored as of QEMU v2.4, but see the DMA interface)
* Location: platform dependent (IOport [*] or MMIO)
* Location: platform dependent (IOport [#]_ or MMIO)
* Width: 8-bit (if IOport), 8/16/32/64-bit (if MMIO)
* Endianness: string-preserving
[*] On platforms where the data register is exposed as an IOport, its
port number will always be one greater than the port number of the
selector register. In other words, the two ports overlap, and can not
be mapped separately.
.. [#]
On platforms where the data register is exposed as an IOport, its
port number will always be one greater than the port number of the
selector register. In other words, the two ports overlap, and can not
be mapped separately.
The data register allows access to an array of bytes for each firmware
configuration data item. The specific item is selected by writing to
@ -74,91 +81,103 @@ An N-byte wide read of the data register will return the next available
N bytes of the selected firmware configuration item, as a substring, in
increasing address order, similar to memcpy().
== Register Locations ==
Register Locations
------------------
=== x86, x86_64 Register Locations ===
x86, x86_64
* Selector Register IOport: 0x510
* Data Register IOport: 0x511
* DMA Address IOport: 0x514
Selector Register IOport: 0x510
Data Register IOport: 0x511
DMA Address IOport: 0x514
Arm
* Selector Register address: Base + 8 (2 bytes)
* Data Register address: Base + 0 (8 bytes)
* DMA Address address: Base + 16 (8 bytes)
=== Arm Register Locations ===
ACPI Interface
--------------
Selector Register address: Base + 8 (2 bytes)
Data Register address: Base + 0 (8 bytes)
DMA Address address: Base + 16 (8 bytes)
== ACPI Interface ==
The fw_cfg device is defined with ACPI ID "QEMU0002". Since we expect
The fw_cfg device is defined with ACPI ID ``QEMU0002``. Since we expect
ACPI tables to be passed into the guest through the fw_cfg device itself,
the guest-side firmware can not use ACPI to find fw_cfg. However, once the
firmware is finished setting up ACPI tables and hands control over to the
guest kernel, the latter can use the fw_cfg ACPI node for a more accurate
inventory of in-use IOport or MMIO regions.
== Firmware Configuration Items ==
Firmware Configuration Items
----------------------------
=== Signature (Key 0x0000, FW_CFG_SIGNATURE) ===
Signature (Key 0x0000, ``FW_CFG_SIGNATURE``)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The presence of the fw_cfg selector and data registers can be verified
by selecting the "signature" item using key 0x0000 (FW_CFG_SIGNATURE),
by selecting the "signature" item using key 0x0000 (``FW_CFG_SIGNATURE``),
and reading four bytes from the data register. If the fw_cfg device is
present, the four bytes read will contain the characters "QEMU".
present, the four bytes read will contain the characters ``QEMU``.
If the DMA interface is available, then reading the DMA Address
Register returns 0x51454d5520434647 ("QEMU CFG" in big-endian format).
Register returns 0x51454d5520434647 (``QEMU CFG`` in big-endian format).
=== Revision / feature bitmap (Key 0x0001, FW_CFG_ID) ===
Revision / feature bitmap (Key 0x0001, ``FW_CFG_ID``)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
A 32-bit little-endian unsigned int, this item is used to check for enabled
features.
- Bit 0: traditional interface. Always set.
- Bit 1: DMA interface.
=== File Directory (Key 0x0019, FW_CFG_FILE_DIR) ===
- Bit 0: traditional interface. Always set.
- Bit 1: DMA interface.
File Directory (Key 0x0019, ``FW_CFG_FILE_DIR``)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. highlight:: c
Firmware configuration items stored at selector keys 0x0020 or higher
(FW_CFG_FILE_FIRST or higher) have an associated entry in a directory
(``FW_CFG_FILE_FIRST`` or higher) have an associated entry in a directory
structure, which makes it easier for guest-side firmware to identify
and retrieve them. The format of this file directory (from fw_cfg.h in
the QEMU source tree) is shown here, slightly annotated for clarity:
and retrieve them. The format of this file directory (from ``fw_cfg.h`` in
the QEMU source tree) is shown here, slightly annotated for clarity::
struct FWCfgFiles { /* the entire file directory fw_cfg item */
uint32_t count; /* number of entries, in big-endian format */
struct FWCfgFile f[]; /* array of file entries, see below */
};
struct FWCfgFiles { /* the entire file directory fw_cfg item */
uint32_t count; /* number of entries, in big-endian format */
struct FWCfgFile f[]; /* array of file entries, see below */
};
struct FWCfgFile { /* an individual file entry, 64 bytes total */
uint32_t size; /* size of referenced fw_cfg item, big-endian */
uint16_t select; /* selector key of fw_cfg item, big-endian */
uint16_t reserved;
char name[56]; /* fw_cfg item name, NUL-terminated ascii */
};
struct FWCfgFile { /* an individual file entry, 64 bytes total */
uint32_t size; /* size of referenced fw_cfg item, big-endian */
uint16_t select; /* selector key of fw_cfg item, big-endian */
uint16_t reserved;
char name[56]; /* fw_cfg item name, NUL-terminated ascii */
};
=== All Other Data Items ===
All Other Data Items
~~~~~~~~~~~~~~~~~~~~
Please consult the QEMU source for the most up-to-date and authoritative list
of selector keys and their respective items' purpose, format and writeability.
=== Ranges ===
Ranges
~~~~~~
Theoretically, there may be up to 0x4000 generic firmware configuration
items, and up to 0x4000 architecturally specific ones.
=============== ===========
Selector Reg. Range Usage
--------------- -----------
=============== ===========
0x0000 - 0x3fff Generic (0x0000 - 0x3fff, generally RO, possibly RW through
the DMA interface in QEMU v2.9+)
the DMA interface in QEMU v2.9+)
0x4000 - 0x7fff Generic (0x0000 - 0x3fff, RW, ignored in QEMU v2.4+)
0x8000 - 0xbfff Arch. Specific (0x0000 - 0x3fff, generally RO, possibly RW
through the DMA interface in QEMU v2.9+)
through the DMA interface in QEMU v2.9+)
0xc000 - 0xffff Arch. Specific (0x0000 - 0x3fff, RW, ignored in v2.4+)
=============== ===========
In practice, the number of allowed firmware configuration items depends on the
machine type/version.
= Guest-side DMA Interface =
Guest-side DMA Interface
========================
If bit 1 of the feature bitmap is set, the DMA interface is present. This does
not replace the existing fw_cfg interface, it is an add-on. This interface
@ -171,68 +190,74 @@ addresses can be triggered with just one write, whereas operations with
64-bit addresses can be triggered with one 64-bit write or two 32-bit writes,
starting with the most significant half (at offset 0).
In this register, the physical address of a FWCfgDmaAccess structure in RAM
should be written. This is the format of the FWCfgDmaAccess structure:
In this register, the physical address of a ``FWCfgDmaAccess`` structure in RAM
should be written. This is the format of the ``FWCfgDmaAccess`` structure::
typedef struct FWCfgDmaAccess {
uint32_t control;
uint32_t length;
uint64_t address;
} FWCfgDmaAccess;
typedef struct FWCfgDmaAccess {
uint32_t control;
uint32_t length;
uint64_t address;
} FWCfgDmaAccess;
The fields of the structure are in big endian mode, and the field at the lowest
address is the "control" field.
address is the ``control`` field.
The "control" field has the following bits:
- Bit 0: Error
- Bit 1: Read
- Bit 2: Skip
- Bit 3: Select. The upper 16 bits are the selected index.
- Bit 4: Write
The ``control`` field has the following bits:
When an operation is triggered, if the "control" field has bit 3 set, the
- Bit 0: Error
- Bit 1: Read
- Bit 2: Skip
- Bit 3: Select. The upper 16 bits are the selected index.
- Bit 4: Write
When an operation is triggered, if the ``control`` field has bit 3 set, the
upper 16 bits are interpreted as an index of a firmware configuration item.
This has the same effect as writing the selector register.
If the "control" field has bit 1 set, a read operation will be performed.
"length" bytes for the current selector and offset will be copied into the
physical RAM address specified by the "address" field.
If the ``control`` field has bit 1 set, a read operation will be performed.
``length`` bytes for the current selector and offset will be copied into the
physical RAM address specified by the ``address`` field.
If the "control" field has bit 4 set (and not bit 1), a write operation will be
performed. "length" bytes will be copied from the physical RAM address
specified by the "address" field to the current selector and offset. QEMU
If the ``control`` field has bit 4 set (and not bit 1), a write operation will be
performed. ``length`` bytes will be copied from the physical RAM address
specified by the ``address`` field to the current selector and offset. QEMU
prevents starting or finishing the write beyond the end of the item associated
with the current selector (i.e., the item cannot be resized). Truncated writes
are dropped entirely. Writes to read-only items are also rejected. All of these
write errors set bit 0 (the error bit) in the "control" field.
write errors set bit 0 (the error bit) in the ``control`` field.
If the "control" field has bit 2 set (and neither bit 1 nor bit 4), a skip
If the ``control`` field has bit 2 set (and neither bit 1 nor bit 4), a skip
operation will be performed. The offset for the current selector will be
advanced "length" bytes.
advanced ``length`` bytes.
To check the result, read the "control" field:
error bit set -> something went wrong.
all bits cleared -> transfer finished successfully.
otherwise -> transfer still in progress (doesn't happen
today due to implementation not being async,
but may in the future).
To check the result, read the ``control`` field:
= Externally Provided Items =
Error bit set
Something went wrong.
All bits cleared
Transfer finished successfully.
Otherwise
Transfer still in progress
(doesn't happen today due to implementation not being async,
but may in the future).
Externally Provided Items
=========================
Since v2.4, "file" fw_cfg items (i.e., items with selector keys above
FW_CFG_FILE_FIRST, and with a corresponding entry in the fw_cfg file
``FW_CFG_FILE_FIRST``, and with a corresponding entry in the fw_cfg file
directory structure) may be inserted via the QEMU command line, using
the following syntax:
the following syntax::
-fw_cfg [name=]<item_name>,file=<path>
Or
Or::
-fw_cfg [name=]<item_name>,string=<string>
Since v5.1, QEMU allows some objects to generate fw_cfg-specific content,
the content is then associated with a "file" item using the 'gen_id' option
in the command line, using the following syntax:
in the command line, using the following syntax::
-object <generator-type>,id=<generated_id>,[generator-specific-options] \
-fw_cfg [name=]<item_name>,gen_id=<generated_id>
@ -241,24 +266,24 @@ See QEMU man page for more documentation.
Using item_name with plain ASCII characters only is recommended.
Item names beginning with "opt/" are reserved for users. QEMU will
Item names beginning with ``opt/`` are reserved for users. QEMU will
never create entries with such names unless explicitly ordered by the
user.
To avoid clashes among different users, it is strongly recommended
that you use names beginning with opt/RFQDN/, where RFQDN is a reverse
that you use names beginning with ``opt/RFQDN/``, where RFQDN is a reverse
fully qualified domain name you control. For instance, if SeaBIOS
wanted to define additional names, the prefix "opt/org.seabios/" would
wanted to define additional names, the prefix ``opt/org.seabios/`` would
be appropriate.
For historical reasons, "opt/ovmf/" is reserved for OVMF firmware.
For historical reasons, ``opt/ovmf/`` is reserved for OVMF firmware.
Prefix "opt/org.qemu/" is reserved for QEMU itself.
Prefix ``opt/org.qemu/`` is reserved for QEMU itself.
Use of names not beginning with "opt/" is potentially dangerous and
Use of names not beginning with ``opt/`` is potentially dangerous and
entirely unsupported. QEMU will warn if you try.
Use of names not beginning with "opt/" is tolerated with 'gen_id' (that
Use of names not beginning with ``opt/`` is tolerated with 'gen_id' (that
is, the warning is suppressed), but you must know exactly what you're
doing.

View file

@ -20,3 +20,4 @@ guest hardware that is specific to QEMU.
acpi_nvdimm
acpi_erst
sev-guest-firmware
fw_cfg

View file

@ -146,16 +146,6 @@ multiple CanoKey QEMU running, namely you can not
Also, there is no lock on canokey-file, thus two CanoKey QEMU instance
can not read one canokey-file at the same time.
Another limitation is that this device is not compatible with ``qemu-xhci``,
in that this device would hang when there are FIDO2 packets (traffic on
interrupt endpoints). If you do not use FIDO2 then it works as intended,
but for full functionality you should use old uhci/ehci bus and attach canokey
to it, for example
.. parsed-literal::
|qemu_system| -device piix3-usb-uhci,id=uhci -device canokey,bus=uhci.0
References
==========

View file

@ -56,7 +56,6 @@ static const USBDesc desc_canokey = {
.iSerialNumber = STR_SERIALNUMBER,
},
.full = &desc_device_canokey,
.high = &desc_device_canokey,
.str = desc_strings,
};
@ -103,17 +102,23 @@ int canokey_emu_transmit(
pbuf, size);
key->ep_in_size[ep_in] += size;
key->ep_in_state[ep_in] = CANOKEY_EP_IN_READY;
/*
* wake up controller if we NAKed IN token before
* Note: this is a quirk for CanoKey CTAPHID
*/
if (ep_in == CANOKEY_EMU_EP_CTAPHID) {
usb_wakeup(usb_ep_get(&key->dev, USB_TOKEN_IN, ep_in), 0);
}
/*
* ready for more data in device loop
*
* Note: this is a quirk for CanoKey CTAPHID
* because it calls multiple emu_transmit in one device_loop
* but w/o data_in it would stuck in device_loop
* This has no side effect for CCID as it is strictly
* OUT then IN transfer
* However it has side effect for Control transfer
* This has side effect for CCID since CCID can send ZLP
* This also has side effect for Control transfer
*/
if (ep_in != 0) {
if (ep_in == CANOKEY_EMU_EP_CTAPHID) {
canokey_emu_data_in(ep_in);
}
return 0;
@ -209,6 +214,22 @@ static void canokey_handle_data(USBDevice *dev, USBPacket *p)
key->ep_out_size[ep_out] = out_len;
canokey_emu_data_out(ep_out, NULL);
}
/*
* Note: this is a quirk for CanoKey CTAPHID
*
* There is one code path that uses this device loop
* INTR IN -> useful data_in and useless device_loop -> NAKed
* INTR OUT -> useful device loop -> transmit -> wakeup
* (useful thanks to both data_in and data_out having been called)
* the next INTR IN -> actual data to guest
*
* if there is no such device loop, there would be no further
* INTR IN, no device loop, no transmit hence no usb_wakeup
* then qemu would hang
*/
if (ep_in == CANOKEY_EMU_EP_CTAPHID) {
canokey_emu_device_loop(); /* may call transmit multiple times */
}
break;
case USB_TOKEN_IN:
if (key->ep_in_pos[ep_in] == 0) { /* first time IN */

View file

@ -463,6 +463,7 @@ bool qemu_console_is_visible(QemuConsole *con);
bool qemu_console_is_graphic(QemuConsole *con);
bool qemu_console_is_fixedsize(QemuConsole *con);
bool qemu_console_is_gl_blocked(QemuConsole *con);
bool qemu_console_is_multihead(DeviceState *dev);
char *qemu_console_get_label(QemuConsole *con);
int qemu_console_get_index(QemuConsole *con);
uint32_t qemu_console_get_head(QemuConsole *con);

View file

@ -1894,16 +1894,18 @@ static void cocoa_clipboard_notify(Notifier *notifier, void *data)
static void cocoa_clipboard_request(QemuClipboardInfo *info,
QemuClipboardType type)
{
NSAutoreleasePool *pool;
NSData *text;
switch (type) {
case QEMU_CLIPBOARD_TYPE_TEXT:
pool = [[NSAutoreleasePool alloc] init];
text = [[NSPasteboard generalPasteboard] dataForType:NSPasteboardTypeString];
if (text) {
qemu_clipboard_set_data(&cbpeer, info, type,
[text length], [text bytes], true);
[text release];
}
[pool release];
break;
default:
break;

View file

@ -2313,11 +2313,50 @@ bool qemu_console_is_gl_blocked(QemuConsole *con)
return con->gl_block;
}
bool qemu_console_is_multihead(DeviceState *dev)
{
QemuConsole *con;
Object *obj;
uint32_t f = 0xffffffff;
uint32_t h;
QTAILQ_FOREACH(con, &consoles, next) {
obj = object_property_get_link(OBJECT(con),
"device", &error_abort);
if (DEVICE(obj) != dev) {
continue;
}
h = object_property_get_uint(OBJECT(con),
"head", &error_abort);
if (f == 0xffffffff) {
f = h;
} else if (h != f) {
return true;
}
}
return false;
}
char *qemu_console_get_label(QemuConsole *con)
{
if (con->console_type == GRAPHIC_CONSOLE) {
if (con->device) {
return g_strdup(object_get_typename(con->device));
DeviceState *dev;
bool multihead;
dev = DEVICE(con->device);
multihead = qemu_console_is_multihead(dev);
if (multihead) {
return g_strdup_printf("%s.%d", dev->id ?
dev->id :
object_get_typename(con->device),
con->head);
} else {
return g_strdup_printf("%s", dev->id ?
dev->id :
object_get_typename(con->device));
}
}
return g_strdup("VGA");
} else {