lspci

package: pciutils

title: lspci(8)

summary: list all PCI devices

text:
# lspci(8)

## NAME
lspci - list all PCI devices

## SYNOPSIS
lspci [options]

## DESCRIPTION
lspci is a utility for displaying information about PCI buses in the system and devices connected to them.

By default, it shows a brief list of devices. Use the options described below to request either a more verbose output or output intended for parsing by other programs.

If you are going to report bugs in PCI device drivers or in lspci itself, please include output of "lspci -vvx" or even better "lspci -vvxxx" (however, see below for possible caveats).

Some parts of the output, especially in the highly verbose modes, are probably intelligible only to experienced PCI hackers. For exact definitions of the fields, please consult either the PCI specifications or the header.h and /usr/include/linux/pci.h include files.

Access to some parts of the PCI configuration space is restricted to root on many operating systems, so the features of lspci available to normal users are limited. However, lspci tries its best to display as much as available and mark all other information with <access denied> text.

## OPTIONS

### Basic display modes
-m

Dump PCI device data in a backward-compatible machine readable form. See below for details.

-mm

Dump PCI device data in a machine readable form for easy parsing by scripts. See below for details.

-t

Show a tree-like diagram containing all buses, bridges, devices and connections between them.

### Display options
-v

Be verbose and display detailed information about all devices.

-vv

Be very verbose and display more details. This level includes everything deemed useful.

-vvv

Be even more verbose and display everything we are able to parse, even if it doesn't look interesting at all (e.g., undefined memory regions).

-k

Show kernel drivers handling each device and also kernel modules capable of handling it. Turned on by default when -v is given in the normal mode of output. (Currently works only on Linux with kernel 2.6 or newer.)

-x

Show hexadecimal dump of the standard part of the configuration space (the first 64 bytes or 128 bytes for CardBus bridges).

-xxx

Show hexadecimal dump of the whole PCI configuration space. It is available only to root as several PCI devices crash when you try to read some parts of the config space (this behavior probably doesn't violate the PCI standard, but it's at least very stupid). However, such devices are rare, so you needn't worry much.

-xxxx

Show hexadecimal dump of the extended (4096-byte) PCI configuration space available on PCI-X 2.0 and PCI Express buses.

-b

Bus-centric view. Show all IRQ numbers and addresses as seen by the cards on the PCI bus instead of as seen by the kernel.

-D

Always show PCI domain numbers. By default, lspci suppresses them on machines which have only domain 0.

-P

Identify PCI devices by path through each bridge, instead of by bus number.

-PP

Identify PCI devices by path through each bridge, showing the bus number as well as the device number.

### Options to control resolving IDs to names
-n

Show PCI vendor and device codes as numbers instead of looking them up in the PCI ID list.

-nn

Show PCI vendor and device codes as both numbers and names.

-q

Use DNS to query the central PCI ID database if a device is not found in the local pci.ids file. If the DNS query succeeds, the result is cached in $XDG_CACHE_HOME/pci-ids and it is recognized in subsequent runs even if -q is not given any more. Please use this switch inside automated scripts only with caution to avoid overloading the database servers.

-qq

Same as -q, but the local cache is reset.

-Q

Query the central database even for entries which are recognized locally. Use this if you suspect that the displayed entry is wrong.

### Options for selection of devices
-s [[[[<domain>]:]<bus>]:][<device>][.[<func>]]

Show only devices in the specified domain (in case your machine has several host bridges, they can either share a common bus number space or each of them can address a PCI domain of its own; domains are numbered from 0 to ffff), bus (0 to ff), device (0 to 1f) and function (0 to 7). Each component of the device address can be omitted or set to "*", both meaning "any value". All numbers are hexadecimal. E.g., "0:" means all devices on bus 0, "0" means all functions of device 0 on any bus, "0.3" selects third function of device 0 on all buses and ".4" shows only the fourth function of each device.

-d [<vendor>]:[<device>][:<class>[:<prog-if>]]

Show only devices with specified vendor, device, class ID, and programming interface. The IDs are given in hexadecimal and may be omitted or given as "*", both meaning "any value". The class ID can contain "x" characters which stand for "any digit".

When -s and -d are combined, only devices that match both criteria are selected. When the same option is used multiple times, the rightmost one overrides the others and a warning is produced.

### Other options
-i <file>

Use <file> as the PCI ID list instead of /usr/share/misc/pci.ids.

-p <file>

Use <file> as the map of PCI IDs handled by kernel modules. By default, lspci uses /lib/modules/kernel_version/modules.pcimap. Applies only to Linux systems with recent enough module tools.

-M

Invoke bus mapping mode which performs a thorough scan of all PCI devices, including those behind misconfigured bridges, etc. This option gives meaningful results only with a direct hardware access mode, which usually requires root privileges. By default, the bus mapper scans domain. You can use the -s option to select a different domain.

--version

Shows lspci version. This option should be used stand-alone.

### PCI access options
The PCI utilities use the PCI library to talk to PCI devices (see pcilib(7) for details). You can use the following options to influence its behavior:

-A <method>

The library supports a variety of methods to access the PCI hardware. By default, it uses the first access method available, but you can use this option to override this decision. See -A help for a list of available methods and their descriptions.

-O <param>=<value>

The behavior of the library is controlled by several named parameters. This option allows one to set the value of any of the parameters. Use -O help for a list of known parameters and their default values.

-H1

Use direct hardware access via Intel configuration mechanism 1. (This is a shorthand for -A intel-conf1.)

-H2

Use direct hardware access via Intel configuration mechanism 2. (This is a shorthand for -A intel-conf2.)

-F <file>

Instead of accessing real hardware, read the list of devices and values of their configuration registers from the given file produced by an earlier run of lspci -x. If file is a single dash (-), read the contents from stdin.

This is very useful for analysis of user-supplied bug reports, because you can display the hardware configuration in any way you want without disturbing the user with requests for more dumps.

-G

Increase debug level of the library.

## MACHINE READABLE OUTPUT
If you intend to process the output of lspci automatically, please use one of the machine-readable output formats (-m, -vm, -vmm) described in this section. All other formats are likely to change between versions of lspci.

All numbers are always printed in hexadecimal. If you want to process numeric IDs instead of names, please add the -n switch.

### Simple format (-m)
In the simple format, each device is described on a single line, which is formatted as parameters suitable for passing to a shell script, i.e., values separated by whitespaces, quoted and escaped if necessary. Some of the arguments are positional: slot, class, vendor name, device name, subsystem vendor name and subsystem name (the last two are empty if the device has no subsystem); the remaining arguments are option-like:

-rrev

Revision number.

-pprogif

Programming interface.

The relative order of positional arguments and options is undefined. New options can be added in future versions, but they will always have a single argument not separated from the option by any spaces, so they can be easily ignored if not recognized.

### Verbose format (-vmm)
The verbose output is a sequence of records separated by blank lines. Each record describes a single device by a sequence of lines, each line containing a single `tag: value' pair. The tag and the value are separated by a single tab character. Neither the records nor the lines within a record are in any particular order. Tags are case-sensitive.

The following tags are defined:

Slot

The name of the slot where the device resides ([domain:]bus:device.function). This tag is always the first in a record.

Class

Name of the class.

Vendor

Name of the vendor.

Device

Name of the device.

SVendor

Name of the subsystem vendor (optional).

SDevice

Name of the subsystem (optional).

PhySlot

The physical slot where the device resides (optional, Linux only).

Rev

Revision number (optional).

ProgIf

Programming interface (optional).

Driver

Kernel driver currently handling the device (optional, Linux only).

Module

Kernel module reporting that it is capable of handling the device (optional, Linux only). Multiple lines with this tag can occur.

NUMANode

NUMA node this device is connected to (optional, Linux only).

IOMMUGroup

IOMMU group that this device is part of (optional, Linux only).

New tags can be added in future versions, so you should silently ignore any tags you don't recognize.

### Backward-compatible verbose format (-vm)
In this mode, lspci tries to be perfectly compatible with its old versions. It's almost the same as the regular verbose format, but the Device tag is used for both the slot and the device name, so it occurs twice in a single record. Please avoid using this format in any new code.

## FILES
/usr/share/misc/pci.ids

A list of all known PCI IDs (vendors, devices, classes and subclasses). Maintained at https://pci-ids.ucw.cz/, use the update-pciids utility to download the most recent version.

/usr/share/misc/pci.ids.gz

If lspci is compiled with support for compression, this file is tried before pci.ids.

$XDG_CACHE_HOME/pci-ids

All IDs found in the DNS query mode are cached in this file.

## BUGS
Sometimes, lspci is not able to decode the configuration registers completely. This usually happens when not enough documentation was available to the authors. In such cases, it at least prints the <?> mark to signal that there is potentially something more to say. If you know the details, patches will be of course welcome.

Access to the extended configuration space is currently supported only by the linux_sysfs back-end.

## SEE ALSO
setpci(8), pci.ids(5), update-pciids(8), pcilib(7)

## AUTHOR
The PCI Utilities are maintained by Martin Mares <mj@ucw.cz>.


pcilmr

title: pcilmr(8)

summary: margin PCIe Links

text:
# pcilmr(8)

## NAME
pcilmr - margin PCIe Links

## SYNOPSIS
pcilmr [--margin] [<common options>] <link port> [<link options>] [<link port> [<link options>] ...]

pcilmr --full [<common options>]

pcilmr --scan

## CONFIGURATION
List of the requirements for links and system settings to run the margining test.

BIOS settings (depends on the system, relevant for server baseboards with Xeon CPUs):

•

Turn off PCIe Leaky Bucket Feature, Re-Equalization and Link Degradation;

•

Set Error Thresholds to 0;

•

Intel VMD for NVMe SSDs - in case of strange behavior of the pcilmr, try to run it with the VMD turned off.

Device (link) requirements:

Configured by the user before running the utility, the utility does not change them:

•

The current Link data rate must be 16.0 GT/s or higher (right now utility supports 16 GT/s and 32 GT/s Links);

•

Link Downstream Component must be at D0 Power Management State.

Configured by the utility during operation, utility set them to their original state after receiving the results:

•

The ASPM must be disabled in both the Downstream Port and Upstream Port;

•

The Hardware Autonomous Speed Disable bit of the Link Control 2 register must be Set in both the Downstream Port and Upstream Port;

•

The Hardware Autonomous Width Disable bit of the Link Control register must be Set in both the Downstream Port and Upstream Port.

## DESCRIPTION
pcilmr utility allows you to take advantage of the PCIe Lane Margining at the Receiver capability which is mandatory for all Ports supporting a data rate of 16.0 GT/s or higher, including Pseudo Ports (Retimers). Lane Margining at Receiver enables system software to obtain the margin information of a given Receiver while the Link is in the L0 state. The margin information includes both voltage and time, in either direction from the current Receiver position. Margining support for timing is required, while support for voltage is optional at 16.0 GT/s and required at 32.0 GT/s and higher data rates. Also, independent time margining and independent voltage margining is optional.

Utility allows to get an approximation of the eye margin diagram in the form of a rhombus (by four points). Lane Margining at the Receiver capability enables users to margin PCIe links without a hardware debugger and without the need to stop the target system. Utility can be useful to debug link issues due to receiver margins.

pcilmr requires root privileges (to access Extended Configuration Space), but during our testing there were no problems with the devices and they successfully returned to their normal initial state after the end of testing.

## RESULTS GRADING
The PCIe specification provides reference values for the eye diagram, which are also used by the pcilmr to evaluate the results, but it seems that it makes sense to contact the manufacturer of a particular device for references.

The utility uses values set in PCIe Base Spec Rev. 5.0 Section 8.4.2 as the default eye width and height minimum references. Recommended values were taken from the PCIe Architecture PHY Test Spec Rev 5.0 (Transmitter Electrical Compliance).

Reference grading values currently used by the utility are presented in the table below:

16 GT/s (Gen 4)

32 GT/s (Gen 5)

EW

EH

EW

EH

Min

18.75 ps 30% UI

15 mV

9.375 ps 30% UI

15 mV

Rec

23.75 ps 38% UI

21 mV

10.157 ps 33% UI

19.75 mV

pcilmr uses full eye width and height values to grade lanes. However, it is possible that device supports only one side margining. In such cases by default utility will calculate EW or EH as a double one side result.

If info for specific device is available, you can configure grading criteria and tweak utility behavior in one-side only cases for your device using -g link specific option (see below).

## HARDWARE QUIRKS SUPPORT
Thanks to testing or directly from the manufacturer's documentation, we know that some devices require special treatment during the margining. Utility detects such devices based on their Vendor ID - Device ID pair. Right now the list of special devices is hardcoded in margin_hw file. For such devices utility can automatically adjust port margining parameters or grading options.

For example, for Ice Lake CPUs RC ports pcilmr will change device MaxVoltageOffset value and will force the use of 'one side is the whole' grading mode.

## OPTIONS

### Device Specifier
You can specify Downstream or Upstream Port of the Link.

<device/component>

[<domain>:]<bus>:<dev>.<func> (see lspci(8))

### Utility Modes
--margin <downstream component> ...

Margin selected Links.

--full

Margin all ready for testing (in a meaning similar to the --scan option) Links in the system (one by one).

--scan

Scan for Links with negotiated speed 16 GT/s or higher. Mark "Ready" those of them in which at least one of the Link sides have Margining Ready bit set meaning that these Links are ready for testing and you can run utility on them.

### Margining Common (for all specified links) options
-c Print Device Lane Margining Capabilities only. Do not run margining.

-e <errors>

Specify Error Count Limit for margining.

Default: 4.

-o <directory>

Save margining results in csv form into the specified directory. Utility will generate file with the name in form of "lmr_<port>_Rx#_<timestamp>.csv" for each successfully tested receiver.

-d <time>

Specify dwell time in seconds for the margining step.

Default: 1 s

### Margining Link specific options
-l <lane>[,<lane>...]

Specify lanes for margining.

Remember that Device may use Lane Reversal for Lane numbering. However, utility uses logical lane numbers in arguments and for logging. Utility will automatically determine Lane Reversal and tune its calls.

Default: all link lanes.

-r <recvn>[,<recvn>...]

Specify Receivers to select margining targets.

Default: all available Receivers (including Retimers).

-p <parallel_lanes>

Specify number of lanes to margin simultaneously.

According to spec it's possible for Receiver to margin up to MaxLanes + 1 lanes simultaneously, but during testing, performing margining on several lanes simultaneously led to results that were different from sequential margining, so this feature requires additional verification and -p option right now is for experiments mostly.

Default: 1.

Use only one of -T/-t options at the same time (same for -V/-v).

Without these options utility will use MaxSteps from Device capabilities as test limit.

-T

Time Margining will continue until the Error Count is no more than an Error Count Limit. Use this option to find Link limit.

-t <steps>

Specify maximum number of steps for Time Margining.

-V

Same as -T option, but for Voltage.

-v <steps>

Specify maximum number of steps for Voltage Margining.

-g <recvn>t=<criteria>{%|ps}[,f]

<recvn>t=f[,<criteria>{%|ps}]

<recvn>v=<criteria>[,f]

<recvn>v=f[,<criteria>]

Specify pass/fail grading criteria for eye width (timing - t) or height (voltage - v) for one of the link receivers. For EW you must choose one of the units (% UI or ps), for EH mV is used.

Additional flag f is for situations when port doesn't support two side independent margining. In such cases by default utility will calculate EW or EH as a double one side result. You can add f flag for -g option to tell the utility that the result in one direction is actually the measurement of the full eye and it does not need to be multiplied. This is so called 'one side is the whole' grading mode.

## EXAMPLES
Utility syntax example:

pcilmr -o csv ab:0.0 -r 1,6 -g 1t=20% -g 1v=f,30 52:0.0 -l 0,1,2 -TV

Examples of collected results on different systems.

## SEE ALSO
lspci(8), PCI Express Base Specification (Lane Margining at Receiver)

branch: sisyphus


setpci

title: setpci(8)

summary: configure PCI devices

text:
# setpci(8)

## NAME
setpci - configure PCI devices

## SYNOPSIS
setpci [options] devices operations...

## DESCRIPTION
setpci is a utility for querying and configuring PCI devices.

All numbers are entered in hexadecimal notation.

Root privileges are necessary for almost all operations, excluding reads of the standard header of the configuration space on some operating systems. Please see lspci(8) for details on access rights.

## OPTIONS

### General options
-v

Tells setpci to be verbose and display detailed information about configuration space accesses.

-f

Tells setpci not to complain when there's nothing to do (when no devices are selected). This option is intended for use in widely-distributed configuration scripts where it's uncertain whether the device in question is present in the machine or not.

-D

`Demo mode' -- don't write anything to the configuration registers. It's useful to try setpci -vD to verify that your complex sequence of setpci operations does what you think it should do.

-r

Avoids bus scan if each operation selects a specific device (uses the -s selector with specific domain, bus, slot, and function). This is faster, but if the device does not exist, it fails instead of matching an empty set of devices.

--version

Show setpci version. This option should be used stand-alone.

--help

Show detailed help on available options. This option should be used stand-alone.

--dumpregs

Show a list of all known PCI registers and capabilities. This option should be used stand-alone.

### PCI access options
The PCI utilities use the PCI library to talk to PCI devices (see pcilib(7) for details). You can use the following options to influence its behavior:

-A <method>

The library supports a variety of methods to access the PCI hardware. By default, it uses the first access method available, but you can use this option to override this decision. See -A help for a list of available methods and their descriptions.

-O <param>=<value>

The behavior of the library is controlled by several named parameters. This option allows one to set the value of any of the parameters. Use -O help for a list of known parameters and their default values.

-H1

Use direct hardware access via Intel configuration mechanism 1. (This is a shorthand for -A intel-conf1.)

-H2

Use direct hardware access via Intel configuration mechanism 2. (This is a shorthand for -A intel-conf2.)

-G

Increase debug level of the library.

## DEVICE SELECTION
Before each sequence of operations you need to select which devices you wish that operation to affect.

-s [[[[<domain>]:]<bus>]:][<slot>][.[<func>]]

Consider only devices in the specified domain (in case your machine has several host bridges, they can either share a common bus number space or each of them can address a PCI domain of its own; domains are numbered from 0 to ffff), bus (0 to ff), slot (0 to 1f) and function (0 to 7). Each component of the device address can be omitted or set to "*", both meaning "any value". All numbers are hexadecimal. E.g., "0:" means all devices on bus 0, "0" means all functions of device 0 on any bus, "0.3" selects third function of device 0 on all buses and ".4" matches only the fourth function of each device.

-d [<vendor>]:[<device>][:<class>[:<prog-if>]]

Select devices with specified vendor, device, class ID, and programming interface. The IDs are given in hexadecimal and may be omitted or given as "*", both meaning "any value". The class ID can contain "x" characters which stand for "any digit".

When -s and -d are combined, only devices that match both criteria are selected. When the same option is used multiple times, the rightmost one overrides the others and a warning is produced.

## OPERATIONS
There are two kinds of operations: reads and writes. To read a register, just specify its name. Writes have the form name=value,value... where each value is either a hexadecimal number or an expression of type data:mask where both data and mask are hexadecimal numbers. In the latter case, only the bits corresponding to binary ones in the mask are changed (technically, this is a read-modify-write operation).

There are several ways to identify a register:

- Tell its address in hexadecimal.

- Spell its name. Setpci knows the names of all registers in the standard configuration headers. Use `setpci --dumpregs' to get the complete list. See PCI bus specifications for the precise meaning of these registers or consult header.h or /usr/include/pci/pci.h for a brief sketch.

- If the register is a part of a PCI capability, you can specify the name of the capability to get the address of its first register. See the names starting with `CAP_' or `ECAP_' in the --dumpregs output.

- If the name of the capability is not known to setpci, you can refer to it by its number in the form CAPid or ECAPid, where id is the numeric identifier of the capability in hexadecimal.

- Each of the previous formats can be followed by +offset to add an offset (a hex number) to the address. This feature can be useful for addressing of registers living within a capability, or to modify parts of standard registers.

- To choose how many bytes (1, 2, or 4) should be transferred, you should append a width specifier .B, .W, or .L. The width can be omitted if you are referring to a register by its name and the width of the register is well known.

- Finally, if a capability exists multiple times you can choose which one to target using @number. Indexing starts at 0.

All names of registers and width specifiers are case-insensitive.

## EXAMPLES
COMMAND

asks for the word-sized command register.

4.w

is a numeric address of the same register.

COMMAND.l

asks for a 32-bit word starting at the location of the command register, i.e., the command and status registers together.

VENDOR_ID+1.b

specifies the upper byte of the vendor ID register (remember, PCI is little-endian).

CAP_PM+2.w

corresponds to the second word of the power management capability.

ECAP108.l

asks for the first 32-bit word of the extended capability with ID 0x108.

## SEE ALSO
lspci(8), pcilib(7)

## AUTHOR
The PCI Utilities are maintained by Martin Mares <mj@ucw.cz>.


pccardctl

package: pcmciautils

title: pccardctl(8)

summary: PCMCIA card control utility

text:
# pccardctl(8)

## NAME
pccardctl - PCMCIA card control utility

lspcmcia - display extended PCMCIA debugging information

## SYNOPSIS
pccardctl [-V] [-v ...] command [socket]

lspcmcia [-V] [-v ...] [socket]

## DESCRIPTION
pccardctl is used to monitor and control the state of PCMCIA sockets. If a socket number is specified, the command will be applied to just one socket; otherwise, all sockets will be affected.

If pccardctl is executed by root, all commands are available. If it is executed by an unpriviledged user, only the informational commands are accessible.

lspcmcia is an alias for pccardctl ls, provided for convenience.

## COMMANDS
status

Display the current socket status flags.

config

Display the socket configuration, including power settings, interrupt and I/O window settings, and configuration registers. --not yet implemented

ident

Display card identification information, including product identification strings, manufacturer ID codes, and function ID codes. Not yet implemented for cardbus cards. Use lspci instead.

info

Much like the ident command, but its output is formatted as a series of Bourne-stype shell variable definitions for use in scripts. Not yet implemented for cardbus cards.

ls

Display extended debugging information about the PCMCIA sockets and devices present in the system.

suspend

Shut down and then disable power for a socket.

resume

Restore power to a socket, and re-configure for use.

eject

Notify all client drivers that this card will be ejected, then cut power to the socket.

insert

Notify all client drivers that this card has just been inserted.

## OPTIONS
-V

Show version information and exit.

-v

Increase the verbosity of the ls command. Giving this option twice increases verbosity further.

## AUTHOR
Daniel Ritz - daniel.ritz@gmx.ch

based upon the original cardctl man page by

David Hinds - dahinds@users.sourceforge.net


pcr-oracle

package: pcr-oracle

title: pcr-oracle(8)

summary: predict TPM PCR values and seal secrets

text:
# pcr-oracle(8)

## NAME
pcr-oracle - predict TPM PCR values and seal secrets

## SYNOPSIS
pcr-oracle [options] action ...

## DESCRIPTION
This utility can be used to predict TPM PCR values at a specific time during system boot, create a PCR policy for these values, and seal a secret to that.

In simple prediction mode, pcr-oracle will compute expected hash values for a subset of PCRs, and write them to standard output. The most common use case will probably be to base the prediction on the TPM event log that was generated by the firmware during the most recent boot. However, there are other modes as well.

In sealing mode, pcr-oracle will seal a given secret (such as a LUKS device password) to either a set of PCR values, or to an authorized PCR policy.

### PCR Policies vs Authorized Policies
The simplest approach to sealing a secret against an expected system state using the TPM is to create what is called a "PCR Policy". This policy essentially requires a given set of PCRs to contain a specific set of values. This policy can be used to "seal" a secret, ie encrypt it using a key only the TPM has access to.

At some point, for example during the boot process, the boot loader will attempt to unseal this sealed secret. If the TPM's PCRs contain the expected values at this point in time, unsealing will succeed. If they do not contain the expected values, unsealing will either fail, or produce gibberish.

While regular PCR policies are sound and simple, they are not very flexible, unfortunately. For example, transparently handling updates of the boot loader is rather difficult because we would first have to retrieve the secret before we're able to re-seal it to the future set of PCR values. This is where Authorized Policies come in.

TPM Authorized Policies provide a mechanism by which a secret is not sealed to a set of specific PCR values, but to a list of PCR indices, and a public RSA key. This combination (PCR indices and public key) is called an Authorized Policy.

The owner of the system can then use the secret RSA key to "authorize" a specific set of PCR values, which is in essence a digital signature.

When unsealing the secret during system boot, the boot loader would present the TPM with the original Authorized Policy, and the signed set of PCR values. The TPM then essentially compares the current set of PCR values (as selected by the policy) to the authorized set of values, and verify the authorization's signature using the public key from the policy. If the PCR values match, and the signature checks out, it will be able to unseal the secret.

The benefit of this approach is that you can now seal the secret (such as a LUKS password) once - and when we later update the boot loader, shim loader etc, we just have to authorize the new set of PCR values using the RSA secret key.

### Policy File Formats
To make things a little more complex, different file formats are being used to store policies and sealed secrets, depending on the implementation. The current standard is the so-called TPM2.0 key file format described in https://www.hansenpartnership.com/draft-bottomley-tpm2-keys.html. This format combines key material and policies into a single, ASN.1 encoded file.

In addition, file formats have been used in the past that stored TPM object in a native format defined in the TPM specification.

Finally, the systemd-boot implementation for unlocking disk partitions stores policies in a JSON formatted file, which can be fed to the systemd-cryptenroll tool. This file will contain any number of signed policies that we want systemd-cryptsetup to recognize during boot time. Each entry contains the list of PCRs that compose the PCR policy, a finger print of the public key, the hash of the policy and the signature (in base64) of the PCR policy.

pcr-oracle supports all three implementations. The target implementation can be selected using the --target-platform option, which accepts tpm2.0, systemd and oldgrub as arguments, respectively.

The default format is tpm2.0.

### RSA Key File Formats
By default, pcr-oracle stores private RSA keys as PEM files and public RSA keys in native TPM encoded format. This behavior can be tuned, however. When it detects a file name that has a .pem extension, it will automatically assume that the caller expects the file to be in PEM format.

In addition, you can explicitly force a specific file format by prefixing the entire path by either pem: opr native:, respectively.

## ACTIONS
The pcr-oracle command supports the following actions:

self-test

Perform a TPM self-test to verify the chip exists and works.

rsa-test

Check whether the TPM supports a given RSA key length. The desired key length is given using the --rsa-bits option.

predict

Try to predict a specific set of PCR values.

create-authorized-policy

Create a PCR authorized policy. Optionally, a new RSA key can be generated.

store-public-key

Given a private key, extract the public portion and write it to a separate file. This is useful when a secret key has been generated while creating the authorized policy.

seal-secret

Read a secret piece of data from a file, and seal it against a TPM policy (either a PCR policy or an authorized policy). Note that the TPM is limited in the maximum amount of secret data it can seal; it's probably safe to assume a limit of 128 bytes.

sign

When using an authorized policy, predict a set of PCR values and sign them using an RSA key.

unseal-secret

This action exists primarily for test purposes. Given a sealed secret and (optionally) a signed policy, unseal the secret and write it to the specified output file.

## EXAMPLES
This section illustrates the use of pcr-oracle in different scenarios through HOWTO examples.

### TPM Self-test
To perform a TPM self-test, simply execute pcr-oracle like this:

```
# pcr-oracle self-test
```

The reason this subcommand exists is that it allows an installer to set up full disk encryption without having to pull in all of tpm-tools.

### TPM RSA key size test
To perform a TPM RSA key size test, simply execute pcr-oracle like this:

```
# pcr-oracle --rsa-bits 2048 rsa-test
```

This subcommand allows external programs, such as fde-tools, to find out the largest supported RSA key size.

### Prediction Mode
In prediction mode, pcr-oracle is invoked like this:

```
# pcr-oracle --from eventlog \

        --before --stop-event grub-command=tpm2_key_protector_init \

        predict 0,2,4,7,9
```

This would create a PCR prediction for registers 0, 2, 3, 7, and 9 by scanning the current TPM event log until the point where grub executes a command called tpm2_key_protector_init.

As it processes the log, it will recompute the hash values for certain events to match the latest changes that were made to the system. For instance, for EFI Boot Variable events, it will consult the current value of a EFI variable and rehash it. The same holds for EFI Boot Service Application events for grub2 or shim; or for EFI GPT events.

In the example above, pcr-oracle will print the predicted values to standard output. If you want to process these values with a tool from the tpm2.0-tools package, you may prefer binary output, which you can select by invoking the tool with --format binary.

### Sealing Against PCR Policies
In order to seal a secret againt a predicted set of PCRs, one would typically invoke pcr-oracle like this:

```
# pcr-oracle --from eventlog \

        --target-platform oldgrub \

        --before --stop-event grub-command=tpm2_key_protector_init \

        --input secret --output sealed \

        seal-secret 0,2,4,7,9
```

Note that the size of the secret to be sealed must not exceed 128 bytes.

The reverse operation looks like this:

```
# pcr-oracle --input sealed --output recovered \

        --target-platform oldgrub \

        unseal-secret 0,2,4,7,9
```

This will instruct the TPM to unseal the given sealed data, computing the policy hash using the current values of the indicated PCRs.

### Sealing Against Authorized Policies
The following sequence of commands seals a secret against an authorized policy, and then authorized a set of PCR values by signing them into a signed policy:

```
# pcr-oracle \

        --target-platform oldgrub \

        --private-key policy-key.pem \

        --auth authorized.policy \

        create-authorized-policy 0,2,4,7,9
# pcr-oracle \

        --target-platform oldgrub \

        --auth authorized.policy \

        --input file-containing-secret \

        --output sealed-secret \

        seal-secret
# pcr-oracle \

        --target-platform oldgrub \

        --private-key policy-key.pem \

        --from eventlog \

        --before --stop-event grub-command=tpm2_key_protector_init \

        --output signed.policy \

        sign 0,2,4,7,9
```

The first of these commands creates the authorized policy and writes it to a file named authorized.policy. This file, along with the public portion of the RSA key, needs to be stored somewhere in a location that is accessible at the time we need to unlock the LUKS key.

The second command seals the secret against this policy. The clear text is stored in file-containing-secret, the encrypted secret is stored in sealed-secret.

Finally, the third command uses the prediction logic of pcr-oracle to predict a specific set of PCR values, in exactly the same way described in the section above on prediction mode. It then uses the given RSA key to sign these values and store the result in signed.policy.

Depending on the boot loader used, it may be helpful to provide the public portion of the RSA key in a format that is trivial to handle. For instance, it would be overkill to add DER parsing of RSA keys to grub. In a case like that, you want the key to be available in a form that can be fed to the TPM chip more or less directly. pcr-oracle supports this via its store-public-key subcommand:

```
# pcr-oracle \

        --private-key policy-key.pem \

        --public-key policy-pubkey \

        store-public-key
```

This command will read the RSA private key from the PEM file, and write the public key as a TPM2B_PUBLIC object to the indicated output file policy-pubkey.

Alternatively, if you want the public key to be stored as PEM formatted key, simply specify the file name of the public key with a .pem extension:

```
# pcr-oracle \

        --private-key policy-key.pem \

        --public-key policy-pubkey.pem \

        store-public-key
```

For details, please see section RSA Key File Formats.

### Using the TPM2.0 Policy File Format
The following will seal a secret against PCR 0,2,4,7, and write the result to sealed-pcr.tpm using the new tpm2.0 format:

```
# pcr-oracle \
	--target-platform=tpm2.0 \
	--input secret \
	--output sealed-pcr.tpm \
	seal-secret 0,2,4,7
```

To seal a secret for an authorized policy:

```
# pcr-oracle \
	--target-platform=tpm2.0 \
	--auth authorized.policy \
	--input secret \
	--output sealed-auth.tpm \
	seal-secret
```

To sign the policy against PCR 0,2,4,7 for sealed-auth.tpm:

```
# pcr-oracle \
	--target-platform=tpm2.0 \
	--policy-name "sealing test" \
	--private-key policy-key.pem \
	--input sealed-auth.tpm \
	--output sealed-auth-signed.tpm \
	sign 0,2,4,7
```

### Generating a Signed Policy for Systemd
When using systemd-boot instead of grub2, you would create an authorized policy as above, and seal your secret LUKS key against that. The main difference is in the way the signed policy is stored:

```
# pcr-oracle \
	--target-platform=systemd \
	--private-key policy-key.pem \
	--from eventlog \
	--output tpm2-pcr-signature.json \
	sign 0,2,4,7,9,12
```

This will predict a set of PCR values, sign them using the specified private key, and then store the signature in tpm2-pcr-signature.json. Note that this command will not overwrite the JSON file, it will update it by adding a new entry. If there already is an entry for the predicted set of PCR values, this will merely update the public key fingerprint and signature.

These policies can then be enrolled for future system boots using systemd-cryptenroll:

```
# systemd-cryptenroll \
	--tpm2-device=auto \
	--tpm2-public-key=public-key.pem \
	--tpm2-public-key-pcrs="0,2,4,7,9,12" 	--tpm2-signature=tpm2-pcr-signature.json \
	/dev/sda3
```

### Creating and Replaying Test Cases
Firmwares tend to be buggy, like every piece of code, and UEFI firmwares are no different. In order to create a broad base of test cases to validate pcr-oracle against, it comes with support for creating and replaying test cases.

A test case is mostly a dump of the data that pcr-oracle processes when re-hashing the events from the TPM event log. This includes the content of UEFI variables such as Boot entries, variables related to Secure Boot, GPT headers, full copies of any EFI Applications loaded during bootup (such as shim.efi, grub.efi), and hashes for other files loaded by the boot loader (such as grub.cfg, or the kernel and initrd).

The following command will create a test case and store it in a directory tree at /tmp/pcr-oracle.test:

```
# pcr-oracle --from eventlog --verify current -d \

        --create-testcase /tmp/pcr-oracle.test \

        predict all
```

If you want to submit your test case, please use tar to archive the test case and create an issue in the github issue tracker at github.com/okirch/pcr-oracle.

To replay a test case, you can do this:

```
# pcr-oracle --from eventlog --verify current -d \

        --replay-testcase /tmp/pcr-oracle.test \

        predict all
```

## OPTIONS
--from source

In prediction mode, specify a source from which to initialize the PCRs. This can be one of eventlog, current, or zero.

With eventlog, the tool scans the TPM event log and re-compute the event hashes based on the current state of the system.

Specifying a source of zero will start prediction with all PCRs cleared. Specifying a source of current will start prediction with all PCRs set to the current values of the system's TPM.

--algorithm hash-alg

By default, pcr-oracle will operate on PCR registers that use the sha256 hash algorithm. Using this option, you can select a different hash algorithm, assuming the chip supports it. For backward compatibility with version 1 of the specification, all TPMv2 chips also support sha1, but using that is not recommended.

--format fmt

In prediction mode, pcr-oracle will write the predicted PCR values to standard output in a human readable format. Using this option, you can select different output formats.

A format of binary will write the predicted values as a binary octet stream, all values concatenated together. This format can be used with tools like tpm2_policypcr(1).Aformatoftpm2-toolswilluseareporting format this is similar to the one that the tpm2-tools produce as output. The default behavior is selected by format plain.

--stop-event event-desc

Specify at which point to stop processing the TPM event log, and report the predicted PCR values. The format of event-desc is an event type, followed by a =, followed by a string argument.

Currently, only two event types are supported, grub-command and grub-file. These correspond to the IPL event emitted by grub when executing a command, or reading a file, respectively.

For a grub command event, the string argument is the name of the command, without any arguments. For a grub file event, the string argument is a file name or a (partial) file path. Path tail matching is performed, i.e. an event for reading EFI/BOOT/grub.cfg can be matched by specifying a stop event for grub.cfg, BOOT/grub.cfg, or EFI/BOOT/grub.cfg, respectively.

--before

When a stop event has been given, report predicted PCR values before processing the event. This is the default behavior.

--after

When a stop event has been given, report predicted PCR values after processing the event. This may be useful, for example, if you don't measure grub's command events (tracked in PCR8) but only its file load events (tracked in PCR9). In this case, it would be totally sufficient to stop processing after grub loaded grub.cfg from the EFI System Partition.

--boot-entry id

In a systemd-boot environment, the values of PCR registers also depend on the contents of the kernel and initrd image, as well as the kernel command line options. After a kernel update or an initrd rebuild, these values will change. So when predicting PCR values in this case, pcr-oracle needs to be instructed to refer to the future kernel rather than the current one.

This is what the --boot-entry option is for. It takes one argument, which is either an ID (in the sense of systemd-boot IDs), or auto. When the latter is given, pcr-oracle will make a best guess as to what kernel image will be used on next boot.

--authorized-policy path

Specify the location of the authorized policy. In conjunction with the create-authorized-policy action, the newly created policy is written to this location. For subsequent actions, such as seal, the policy will be read from this location.

--private-key path

Specify the RSA secret key to be used with authorized policies. For notes on the file format, please see section RSA Key File Formats.

--public-key path

Specify an RSA public key to be used with authorized policies. For notes on the file format, please see section RSA Key File Formats.

--rsa-generate-key

When used while creating an authorized policy, a signature, or when storing the public key, this will generate the RSA private key "on the fly". This should not be different from what openssl genrsa does; the only reason this switch exists is that it may save you from increasing the footprint of your installed system (by not having to install the openssl command line utilities, for example).

--rsa-bits bits

By default, RSA 2048 is used as the algorithm to create the public and private key and configure the storage root key(SRK) in TPM. This option allows the user to specify the larger RSA key size. The supported key sizes are: 2048, 3072, and 4096 bits.

--tpm-eventlog path

By default, the tool will read the current TPM event log. It is possible to process an event log generated on a different system by specifying it with this option.

--target-platform name

Write key and policy information using file format(s) compatible with the specified target implementation. Please see the section Policy File Formats for more information.

--policy-name name

For the tpm2.0 format, there is an extra field, Name, for the authorized polices. This option is only valid when sigining the sealed key in tpm2.0 format. The Name is optional and only used for display purposes. If the user doesn't specify a name, the default name is 'default'.

## SEE ALSO
tpm2_policypcr(1), tpm2_policyauthorize(1), tpm2_create(1).

## AUTHOR
pcr-oracle was written by Olaf Kirch with significant contributions from Gary Lin, Michael Chang and Alberto Planas.