Documentation: Reformat fw_config.md
This doesn't change any text - it just reformats the existing document. - reflow paragraphs to 72 characters - Put examples inside pre-formatted text blocks - Adds spacing before section markers Change-Id: I83925a4469e264da5887334e2584466cef089503 Signed-off-by: Martin Roth <gaumless@gmail.com> Reviewed-on: https://review.coreboot.org/c/coreboot/+/87190 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Nicholas Chin <nic.c3.14@gmail.com>
This commit is contained in:
parent
2dec38c92c
commit
1662396037
1 changed files with 289 additions and 201 deletions
|
|
@ -2,225 +2,284 @@
|
|||
|
||||
## Motivation
|
||||
|
||||
The firmware configuration interface in coreboot is designed to support a wide variety of
|
||||
configuration options in that are dictated by the hardware at runtime. This allows a single
|
||||
BIOS image to be used across a wide variety of devices which may have key differences but are
|
||||
otherwise similar enough to use the same coreboot build target.
|
||||
The firmware configuration interface in coreboot is designed to support
|
||||
a wide variety of configuration options in that are dictated by the
|
||||
hardware at runtime. This allows a single BIOS image to be used across a
|
||||
wide variety of devices which may have key differences but are otherwise
|
||||
similar enough to use the same coreboot build target.
|
||||
|
||||
The initial implementation is designed to take advantage of a bitmask returned by the Embedded
|
||||
Controller on Google ChromeOS devices which allows the manufacturer to use the same firmware
|
||||
image across multiple devices by selecting various options at runtime. See the ChromiumOS
|
||||
The initial implementation is designed to take advantage of a bitmask
|
||||
returned by the Embedded Controller on Google ChromeOS devices which
|
||||
allows the manufacturer to use the same firmware image across multiple
|
||||
devices by selecting various options at runtime. See the ChromiumOS
|
||||
[Firmware Config][1] documentation for more information.
|
||||
|
||||
This firmware configuration interface differs from the CMOS option interface in that this
|
||||
bitmask value is not intended as a user-configurable setting as the configuration values must
|
||||
match the actual hardware. In the case where a user was to swap their hardware this value
|
||||
would need to be updated or overridden.
|
||||
This firmware configuration interface differs from the CMOS option
|
||||
interface in that this bitmask value is not intended as a
|
||||
user-configurable setting as the configuration values must match the
|
||||
actual hardware. In the case where a user was to swap their hardware
|
||||
this value would need to be updated or overridden.
|
||||
|
||||
|
||||
## Device Presence
|
||||
|
||||
One common example of why a firmware configuration interface is important is determining if a
|
||||
device is present in the system. With some bus topologies and hardware mechanisms it is
|
||||
possible to probe and enumerate this at runtime:
|
||||
One common example of why a firmware configuration interface is
|
||||
important is determining if a device is present in the system. With some
|
||||
bus topologies and hardware mechanisms it is possible to probe and
|
||||
enumerate this at runtime:
|
||||
|
||||
- PCI is a self-discoverable bus and is very easy to handle.
|
||||
- I2C devices can often be probed with a combination of bus and address.
|
||||
- The use of GPIOs with external strap to ground or different voltages can be used to detect
|
||||
presence of a device.
|
||||
- The use of GPIOs with external strap to ground or different voltages
|
||||
can be used to detect presence of a device.
|
||||
|
||||
However there are several cases where this is insufficient:
|
||||
|
||||
- I2C peripherals that require different drivers but have the same bus address cannot be
|
||||
uniquely identified at runtime.
|
||||
- A mainboard may be designed with multiple daughter board combinations which contain devices
|
||||
and configurations that cannot be detected.
|
||||
- While presence detect GPIOs are a convenient way for a single device presence, they are
|
||||
unable to distinguish between different devices so it can require a large number of GPIOs to
|
||||
support relatively few options.
|
||||
- I2C peripherals that require different drivers but have the same bus
|
||||
address cannot be uniquely identified at runtime.
|
||||
- A mainboard may be designed with multiple daughter board combinations
|
||||
which contain devices and configurations that cannot be detected.
|
||||
- While presence detect GPIOs are a convenient way for a single device
|
||||
presence, they are unable to distinguish between different devices so
|
||||
it can require a large number of GPIOs to support relatively few
|
||||
options.
|
||||
|
||||
This presence detection can impact different stages of boot:
|
||||
|
||||
|
||||
### ACPI
|
||||
|
||||
Devices that are not present should not provide an ACPI device indicating that they are
|
||||
present or the operating system may not be able to handle it correctly.
|
||||
Devices that are not present should not provide an ACPI device
|
||||
indicating that they are present or the operating system may not be able
|
||||
to handle it correctly.
|
||||
|
||||
The ACPI devices are largely driven by chips defined in the mainboard
|
||||
`devicetree.cb` and the variant overridetree.cb. This means it is
|
||||
important to be able to specify when a device is present or not directly
|
||||
in `devicetree.cb` itself. Otherwise each mainboard needs custom code to
|
||||
parse the tree and disable unused devices.
|
||||
|
||||
The ACPI devices are largely driven by chips defined in the mainboard `devicetree.cb` and
|
||||
the variant overridetree.cb. This means it is important to be able to specify when a device
|
||||
is present or not directly in `devicetree.cb` itself. Otherwise each mainboard needs custom
|
||||
code to parse the tree and disable unused devices.
|
||||
|
||||
### GPIO
|
||||
|
||||
GPIOs with multiple functions may need to be configured correctly depending on the attached
|
||||
device. Given the wide variety of GPIO configuration possibilities it is not feasible to
|
||||
specify all combinations directly in `devicetree.cb` and it is best left to code provided by
|
||||
the mainboard.
|
||||
GPIOs with multiple functions may need to be configured correctly
|
||||
depending on the attached device. Given the wide variety of GPIO
|
||||
configuration possibilities it is not feasible to specify all
|
||||
combinations directly in `devicetree.cb` and it is best left to code
|
||||
provided by the mainboard.
|
||||
|
||||
|
||||
### FSP UPD
|
||||
|
||||
Enabling and disabling devices may require altering FSP UPD values that are provided to the
|
||||
various stages of FSP. These options are also not easy to specify multiple times for
|
||||
different configurations in `devicetree.cb` and can be provided by the mainboard as code.
|
||||
Enabling and disabling devices may require altering FSP UPD values that
|
||||
are provided to the various stages of FSP. These options are also not
|
||||
easy to specify multiple times for different configurations in
|
||||
`devicetree.cb` and can be provided by the mainboard as code.
|
||||
|
||||
|
||||
## Firmware Configuration Interface
|
||||
|
||||
The firmware configuration interface can be enabled by selecting `CONFIG_FW_CONFIG` and also
|
||||
providing a source for the value by defining an additional Kconfig option defined below.
|
||||
The firmware configuration interface can be enabled by selecting
|
||||
`CONFIG_FW_CONFIG` and also providing a source for the value by defining
|
||||
an additional Kconfig option defined below.
|
||||
|
||||
If the firmware configuration interface is disabled via Kconfig then all
|
||||
probe attempts will return true.
|
||||
|
||||
If the firmware configuration interface is disabled via Kconfig then all probe attempts will
|
||||
return true.
|
||||
|
||||
## Firmware Configuration Value
|
||||
|
||||
The 64-bit value used as the firmware configuration bitmask is meant to be determined at runtime
|
||||
but could also be defined at compile time if needed.
|
||||
The 64-bit value used as the firmware configuration bitmask is meant to
|
||||
be determined at runtime but could also be defined at compile time if
|
||||
needed.
|
||||
|
||||
There are two supported sources for providing this information to
|
||||
coreboot.
|
||||
|
||||
There are two supported sources for providing this information to coreboot.
|
||||
|
||||
### CBFS
|
||||
|
||||
The value can be provided with a 64-bit raw value in CBFS that is read by coreboot. The value
|
||||
can be set at build time but also adjusted in an existing image with `cbfstool`.
|
||||
The value can be provided with a 64-bit raw value in CBFS that is read
|
||||
by coreboot. The value can be set at build time but also adjusted in an
|
||||
existing image with `cbfstool`.
|
||||
|
||||
To enable this select the `CONFIG_FW_CONFIG_CBFS` option in the build configuration and add a
|
||||
raw 64-bit value to CBFS with the name of the current prefix at `CONFIG_FW_PREFIX/fw_config`.
|
||||
To enable this select the `CONFIG_FW_CONFIG_CBFS` option in the build
|
||||
configuration and add a raw 64-bit value to CBFS with the name of the
|
||||
current prefix at `CONFIG_FW_PREFIX/fw_config`.
|
||||
|
||||
When `fw_config_probe_device()` or `fw_config_probe()` is called it will
|
||||
look for the specified file in CBFS use the value it contains when
|
||||
matching fields and options.
|
||||
|
||||
When `fw_config_probe_device()` or `fw_config_probe()` is called it will look for the specified
|
||||
file in CBFS use the value it contains when matching fields and options.
|
||||
|
||||
### Embedded Controller
|
||||
|
||||
Google ChromeOS devices support an Embedded Controller interface for reading and writing the
|
||||
firmware configuration value, along with other board-specific information. It is possible for
|
||||
coreboot to read this value at boot on systems that support this feature.
|
||||
Google ChromeOS devices support an Embedded Controller interface for
|
||||
reading and writing the firmware configuration value, along with other
|
||||
board-specific information. It is possible for coreboot to read this
|
||||
value at boot on systems that support this feature.
|
||||
|
||||
This option is selected by default for the mainboards that use it with
|
||||
`CONFIG_FW_CONFIG_CHROME_EC_CBI` and it is not typically necessary to adjust the value. It is
|
||||
possible by enabling the CBFS source and coreboot will look in CBFS first for a valid value
|
||||
before asking the embedded controller.
|
||||
`CONFIG_FW_CONFIG_CHROME_EC_CBI` and it is not typically necessary to
|
||||
adjust the value. It is possible by enabling the CBFS source and
|
||||
coreboot will look in CBFS first for a valid value before asking the
|
||||
embedded controller.
|
||||
|
||||
It is also possible to adjust the value in the embedded controller *(after disabling write
|
||||
protection)* with the `ectool` command in a ChromeOS environment.
|
||||
It is also possible to adjust the value in the embedded controller
|
||||
*(after disabling write protection)* with the `ectool` command in a
|
||||
ChromeOS environment.
|
||||
|
||||
For more information on the firmware configuration field on ChromeOS devices see the Chromium
|
||||
documentation for [Firmware Config][1] and [Board Info][2].
|
||||
For more information on the firmware configuration field on ChromeOS
|
||||
devices see the Chromium documentation for [Firmware Config][1] and
|
||||
[Board Info][2].
|
||||
|
||||
[1]: http://chromium.googlesource.com/chromiumos/docs/+/HEAD/design_docs/firmware_config.md
|
||||
[2]: http://chromium.googlesource.com/chromiumos/docs/+/HEAD/design_docs/cros_board_info.md
|
||||
|
||||
|
||||
## Firmware Configuration Table
|
||||
|
||||
The firmware configuration table itself is defined in the mainboard `devicetree.cb` with
|
||||
special tokens for defining fields and options.
|
||||
The firmware configuration table itself is defined in the mainboard
|
||||
`devicetree.cb` with special tokens for defining fields and options.
|
||||
|
||||
The table itself is enclosed in a `fw_config` token and terminated with `end` and it contains
|
||||
a mix of field and option definitions.
|
||||
The table itself is enclosed in a `fw_config` token and terminated with
|
||||
`end` and it contains a mix of field and option definitions.
|
||||
|
||||
Each field is defined by providing the field name and the start and end bit marking the exact
|
||||
location in the bitmask. Field names must be at least three characters long in order to
|
||||
satisfy the sconfig parser requirements and they must be unique with non-overlapping masks.
|
||||
Each field is defined by providing the field name and the start and end
|
||||
bit marking the exact location in the bitmask. Field names must be at
|
||||
least three characters long in order to satisfy the sconfig parser
|
||||
requirements and they must be unique with non-overlapping masks.
|
||||
|
||||
field <name> <start-bit> <end-bit> [option...] end
|
||||
```text
|
||||
field <name> <start-bit> <end-bit> [option...] end
|
||||
```
|
||||
|
||||
For single-bit fields only one number is needed:
|
||||
|
||||
field <name> <bit> [option...] end
|
||||
```text
|
||||
field <name> <bit> [option...] end
|
||||
```
|
||||
|
||||
A field definition can also contain multiple sets of bit masks, which can be dis-contiguous.
|
||||
They are treated as if they are contiguous when defining option values. This allows for
|
||||
extending fields even after the bits after its current masks are occupied.
|
||||
A field definition can also contain multiple sets of bit masks, which
|
||||
can be dis-contiguous. They are treated as if they are contiguous when
|
||||
defining option values. This allows for extending fields even after the
|
||||
bits after its current masks are occupied.
|
||||
|
||||
field <name> <start-bit0> <end-bit0> | <start-bit1> <end-bit1> | ...
|
||||
```text
|
||||
field <name> <start-bit0> <end-bit0> | <start-bit1> <end-bit1> | ...
|
||||
```
|
||||
|
||||
For example, if more audio options need to be supported:
|
||||
|
||||
field AUDIO 3 3
|
||||
option AUDIO_0 0
|
||||
option AUDIO_1 1
|
||||
end
|
||||
field OTHER 4 4
|
||||
...
|
||||
end
|
||||
```text
|
||||
field AUDIO 3 3
|
||||
option AUDIO_0 0
|
||||
option AUDIO_1 1
|
||||
end
|
||||
field OTHER 4 4
|
||||
...
|
||||
end
|
||||
```
|
||||
|
||||
the following can be done:
|
||||
|
||||
field AUDIO 3 3 | 5 5
|
||||
option AUDIO_FOO 0
|
||||
option AUDIO_BLAH 1
|
||||
option AUDIO_BAR 2
|
||||
option AUDIO_BAZ 3
|
||||
end
|
||||
field OTHER 4 4
|
||||
...
|
||||
end
|
||||
```text
|
||||
field AUDIO 3 3 | 5 5
|
||||
option AUDIO_FOO 0
|
||||
option AUDIO_BLAH 1
|
||||
option AUDIO_BAR 2
|
||||
option AUDIO_BAZ 3
|
||||
end
|
||||
field OTHER 4 4
|
||||
...
|
||||
end
|
||||
```
|
||||
|
||||
In that case, the AUDIO masks are extended like so:
|
||||
|
||||
#define FW_CONFIG_FIELD_AUDIO_MASK 0x28
|
||||
#define FW_CONFIG_FIELD_AUDIO_OPTION_AUDIO_FOO_VALUE 0x0
|
||||
#define FW_CONFIG_FIELD_AUDIO_OPTION_AUDIO_BLAH_VALUE 0x8
|
||||
#define FW_CONFIG_FIELD_AUDIO_OPTION_AUDIO_BAR_VALUE 0x20
|
||||
#define FW_CONFIG_FIELD_AUDIO_OPTION_AUDIO_BAz_VALUE 0x28
|
||||
```c
|
||||
#define FW_CONFIG_FIELD_AUDIO_MASK 0x28
|
||||
#define FW_CONFIG_FIELD_AUDIO_OPTION_AUDIO_FOO_VALUE 0x0
|
||||
#define FW_CONFIG_FIELD_AUDIO_OPTION_AUDIO_BLAH_VALUE 0x8
|
||||
#define FW_CONFIG_FIELD_AUDIO_OPTION_AUDIO_BAR_VALUE 0x20
|
||||
#define FW_CONFIG_FIELD_AUDIO_OPTION_AUDIO_BAz_VALUE 0x28
|
||||
```
|
||||
|
||||
Each `field` definition starts a new block that can be composed of zero or more field options,
|
||||
and it is terminated with `end`.
|
||||
Each `field` definition starts a new block that can be composed of zero
|
||||
or more field options, and it is terminated with `end`.
|
||||
|
||||
Inside the field block the options can be defined by providing the option name and the field
|
||||
value that this option represents when the bit offsets are used to apply a mask and shift.
|
||||
Option names must also be at least three characters for the sconfig parser.
|
||||
Inside the field block the options can be defined by providing the
|
||||
option name and the field value that this option represents when the bit
|
||||
offsets are used to apply a mask and shift. Option names must also be at
|
||||
least three characters for the sconfig parser.
|
||||
|
||||
option <name> <value>
|
||||
```text
|
||||
option <name> <value>
|
||||
```
|
||||
|
||||
It is possible for there to be multiple `fw_config` blocks and for subsequent `field` blocks
|
||||
to add additional `option` definitions to the existing field. These subsequent definitions
|
||||
should not provide the field bitmask as it has already been defined earlier in the file and
|
||||
It is possible for there to be multiple `fw_config` blocks and for
|
||||
subsequent `field` blocks to add additional `option` definitions to the
|
||||
existing field. These subsequent definitions should not provide the
|
||||
field bitmask as it has already been defined earlier in the file and
|
||||
this is just matching an existing field by name.
|
||||
|
||||
field <name> [option...] end
|
||||
```text
|
||||
field <name> [option...] end
|
||||
```
|
||||
|
||||
This allows a baseboard to define the major fields and options in `devicetree.cb` and a board
|
||||
variant to add specific options to fields in or define new fields in the unused bitmask in
|
||||
`overridetree.cb`.
|
||||
This allows a baseboard to define the major fields and options in
|
||||
`devicetree.cb` and a board variant to add specific options to fields in
|
||||
or define new fields in the unused bitmask in `overridetree.cb`.
|
||||
|
||||
It is not possible to redefine a field mask or override the value of an
|
||||
existing option this way, only to add new options to a field or new
|
||||
fields to the table.
|
||||
|
||||
It is not possible to redefine a field mask or override the value of an existing option this
|
||||
way, only to add new options to a field or new fields to the table.
|
||||
|
||||
### Firmware Configuration Table Example
|
||||
|
||||
In this example a baseboard defines a simple boolean feature that is enabled or disabled
|
||||
depending on the value of bit 0, and a field at bits 1-2 that indicates which daughter board
|
||||
is attached.
|
||||
In this example a baseboard defines a simple boolean feature that is
|
||||
enabled or disabled depending on the value of bit 0, and a field at bits
|
||||
1-2 that indicates which daughter board is attached.
|
||||
|
||||
The baseboard itself defines one daughter board and the variant adds two
|
||||
more possibilities. This way each variant can support multiple possible
|
||||
daughter boards in addition to the one that was defined by the
|
||||
baseboard.
|
||||
|
||||
The baseboard itself defines one daughter board and the variant adds two more possibilities.
|
||||
This way each variant can support multiple possible daughter boards in addition to the one
|
||||
that was defined by the baseboard.
|
||||
|
||||
#### devicetree.cb
|
||||
|
||||
fw_config
|
||||
field FEATURE 0
|
||||
option DISABLED 0
|
||||
option ENABLED 1
|
||||
end
|
||||
field DAUGHTER_BOARD 1 2
|
||||
option NONE 0
|
||||
option REFERENCE_DB 1
|
||||
end
|
||||
```text
|
||||
fw_config
|
||||
field FEATURE 0
|
||||
option DISABLED 0
|
||||
option ENABLED 1
|
||||
end
|
||||
field DAUGHTER_BOARD 1 2
|
||||
option NONE 0
|
||||
option REFERENCE_DB 1
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
|
||||
#### overridetree.cb
|
||||
|
||||
fw_config
|
||||
field DAUGHTER_BOARD
|
||||
option VARIANT_DB_ONE 2
|
||||
option VARIANT_DB_TWO 3
|
||||
end
|
||||
```text
|
||||
fw_config
|
||||
field DAUGHTER_BOARD
|
||||
option VARIANT_DB_ONE 2
|
||||
option VARIANT_DB_TWO 3
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
The result of this table defined in `devicetree.cb` is a list of
|
||||
constants that can be used to check if fields match the firmware
|
||||
configuration options determined at runtime with a simple check of the
|
||||
field mask and the option value.
|
||||
|
||||
The result of this table defined in `devicetree.cb` is a list of constants that can be used
|
||||
to check if fields match the firmware configuration options determined at runtime with a
|
||||
simple check of the field mask and the option value.
|
||||
|
||||
#### static.h
|
||||
|
||||
|
|
@ -246,73 +305,96 @@ simple check of the field mask and the option value.
|
|||
#define FW_CONFIG_FIELD_DAUGHTER_BOARD_OPTION_VARIANT_DB_TWO_VALUE 0x00000006
|
||||
```
|
||||
|
||||
|
||||
## Device Probing
|
||||
|
||||
One use of the firmware configuration interface in devicetree is to allow device probing to be
|
||||
specified directly with the devices themselves. A new `probe` token is introduced to allow a
|
||||
device to be probed by field and option name. Multiple `probe` entries may be present for
|
||||
each device and any successful probe will consider the device to be present.
|
||||
One use of the firmware configuration interface in devicetree is to
|
||||
allow device probing to be specified directly with the devices
|
||||
themselves. A new `probe` token is introduced to allow a device to be
|
||||
probed by field and option name. Multiple `probe` entries may be present
|
||||
for each device and any successful probe will consider the device to be
|
||||
present.
|
||||
|
||||
|
||||
### Probing Example
|
||||
|
||||
Continuing with the previous example this device would be considered present if the field
|
||||
`DAUGHTER_BOARD` was set to either `VARIANT_DB_ONE` or `VARIANT_DB_TWO`:
|
||||
Continuing with the previous example this device would be considered
|
||||
present if the field `DAUGHTER_BOARD` was set to either `VARIANT_DB_ONE`
|
||||
or `VARIANT_DB_TWO`:
|
||||
|
||||
|
||||
#### overridetree.cb
|
||||
|
||||
chip drivers/generic/example
|
||||
device generic 0 on
|
||||
probe DAUGHTER_BOARD VARIANT_DB_ONE
|
||||
probe DAUGHTER_BOARD VARIANT_DB_TWO
|
||||
end
|
||||
```text
|
||||
chip drivers/generic/example
|
||||
device generic 0 on
|
||||
probe DAUGHTER_BOARD VARIANT_DB_ONE
|
||||
probe DAUGHTER_BOARD VARIANT_DB_TWO
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
If the field were set to any other option, including `NONE` and
|
||||
`REFERENCE_DB` and any undefined value then the device would be
|
||||
disabled.
|
||||
|
||||
If the field were set to any other option, including `NONE` and `REFERENCE_DB` and any
|
||||
undefined value then the device would be disabled.
|
||||
|
||||
### Probe Overrides
|
||||
|
||||
When a device is declared with a probe in the baseboard `devicetree.cb` and the same device
|
||||
is also present in the `overridetree.cb` then the probing information from the baseboard
|
||||
is discarded and the override device must provide all necessary probing information.
|
||||
When a device is declared with a probe in the baseboard `devicetree.cb`
|
||||
and the same device is also present in the `overridetree.cb` then the
|
||||
probing information from the baseboard is discarded and the override
|
||||
device must provide all necessary probing information.
|
||||
|
||||
In this example a device is listed in the baseboard with `DAUGHTER_BOARD` field probing for
|
||||
`REFERENCE_DB` as a field option, It is also defined as an override device with the field
|
||||
probing for the `VARIANT_DB_ONE` option instead.
|
||||
In this example a device is listed in the baseboard with
|
||||
`DAUGHTER_BOARD` field probing for `REFERENCE_DB` as a field option, It
|
||||
is also defined as an override device with the field probing for the
|
||||
`VARIANT_DB_ONE` option instead.
|
||||
|
||||
In this case only the probe listed in the override is checked and a
|
||||
field option of `REFERENCE_DB` will not mark this device present. If
|
||||
both options are desired then the override device must list both. This
|
||||
allows an override device to remove a probe entry that was defined in
|
||||
the baseboard.
|
||||
|
||||
In this case only the probe listed in the override is checked and a field option of
|
||||
`REFERENCE_DB` will not mark this device present. If both options are desired then the
|
||||
override device must list both. This allows an override device to remove a probe entry that
|
||||
was defined in the baseboard.
|
||||
|
||||
#### devicetree.cb
|
||||
|
||||
chip drivers/generic/example
|
||||
device generic 0 on
|
||||
probe DAUGHTER_BOARD REFERENCE_DB
|
||||
end
|
||||
end
|
||||
```text
|
||||
chip drivers/generic/example
|
||||
device generic 0 on
|
||||
probe DAUGHTER_BOARD REFERENCE_DB
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
|
||||
#### overridetree.cb
|
||||
|
||||
chip drivers/generic/example
|
||||
device generic 0 on
|
||||
probe DAUGHTER_BOARD VARIANT_DB_ONE
|
||||
end
|
||||
end
|
||||
```text
|
||||
chip drivers/generic/example
|
||||
device generic 0 on
|
||||
probe DAUGHTER_BOARD VARIANT_DB_ONE
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
|
||||
### Automatic Device Probing
|
||||
|
||||
At boot time the firmware configuration interface will walk the device tree and apply any
|
||||
probe entries that were defined in `devicetree.cb`. This probing takes effect before the
|
||||
`BS_DEV_ENUMERATE` step during the boot state machine in ramstage.
|
||||
At boot time the firmware configuration interface will walk the device
|
||||
tree and apply any probe entries that were defined in `devicetree.cb`.
|
||||
This probing takes effect before the `BS_DEV_ENUMERATE` step during the
|
||||
boot state machine in ramstage.
|
||||
|
||||
Devices that have a probe list but do do not find a match are disabled by setting
|
||||
`dev->enabled = 0` but the chip `enable_dev()` and device `enable()` handlers will still
|
||||
be executed to allow any device disable code to execute.
|
||||
Devices that have a probe list but do do not find a match are disabled
|
||||
by setting `dev->enabled = 0` but the chip `enable_dev()` and device
|
||||
`enable()` handlers will still be executed to allow any device disable
|
||||
code to execute.
|
||||
|
||||
The result of this probe definition is to provide an array of structures
|
||||
describing each field and option to check.
|
||||
|
||||
The result of this probe definition is to provide an array of structures describing each
|
||||
field and option to check.
|
||||
|
||||
#### fw_config.h
|
||||
|
||||
|
|
@ -325,40 +407,43 @@ field and option to check.
|
|||
* @value: Value of the option within the mask.
|
||||
*/
|
||||
struct fw_config {
|
||||
const char *field_name;
|
||||
const char *option_name;
|
||||
uint64_t mask;
|
||||
uint64_t value;
|
||||
const char *field_name;
|
||||
const char *option_name;
|
||||
uint64_t mask;
|
||||
uint64_t value;
|
||||
};
|
||||
```
|
||||
|
||||
|
||||
#### static.c
|
||||
|
||||
```c
|
||||
STORAGE struct fw_config __devN_probe_list[] = {
|
||||
{
|
||||
.field_name = FW_CONFIG_FIELD_DAUGHTER_BOARD_NAME,
|
||||
.option_name = FW_CONFIG_FIELD_DAUGHTER_BOARD_OPTION_VARIANT_DB_ONE_NAME,
|
||||
.mask = FW_CONFIG_FIELD_DAUGHTER_BOARD_MASK,
|
||||
.value = FW_CONFIG_FIELD_DAUGHTER_BOARD_OPTION_VARIANT_DB_ONE_VALUE
|
||||
},
|
||||
{
|
||||
.field_name = FW_CONFIG_FIELD_DAUGHTER_BOARD_NAME,
|
||||
.option_name = FW_CONFIG_FIELD_DAUGHTER_BOARD_OPTION_VARIANT_DB_TWO_NAME,
|
||||
.mask = FW_CONFIG_FIELD_DAUGHTER_BOARD_MASK,
|
||||
.value = FW_CONFIG_FIELD_DAUGHTER_BOARD_OPTION_VARIANT_DB_TWO_VALUE
|
||||
},
|
||||
{ }
|
||||
{
|
||||
.field_name = FW_CONFIG_FIELD_DAUGHTER_BOARD_NAME,
|
||||
.option_name = FW_CONFIG_FIELD_DAUGHTER_BOARD_OPTION_VARIANT_DB_ONE_NAME,
|
||||
.mask = FW_CONFIG_FIELD_DAUGHTER_BOARD_MASK,
|
||||
.value = FW_CONFIG_FIELD_DAUGHTER_BOARD_OPTION_VARIANT_DB_ONE_VALUE
|
||||
},
|
||||
{
|
||||
.field_name = FW_CONFIG_FIELD_DAUGHTER_BOARD_NAME,
|
||||
.option_name = FW_CONFIG_FIELD_DAUGHTER_BOARD_OPTION_VARIANT_DB_TWO_NAME,
|
||||
.mask = FW_CONFIG_FIELD_DAUGHTER_BOARD_MASK,
|
||||
.value = FW_CONFIG_FIELD_DAUGHTER_BOARD_OPTION_VARIANT_DB_TWO_VALUE
|
||||
},
|
||||
{ }
|
||||
};
|
||||
```
|
||||
|
||||
|
||||
### Runtime Probing
|
||||
|
||||
The device driver probing allows for seamless integration with the mainboard but it is only
|
||||
effective in ramstage and for specific devices declared in devicetree.cb. There are other
|
||||
situations where code may need to probe or check the value of a field in romstage or at other
|
||||
points in ramstage. For this reason it is also possible to use the firmware configuration
|
||||
interface directly.
|
||||
The device driver probing allows for seamless integration with the
|
||||
mainboard but it is only effective in ramstage and for specific devices
|
||||
declared in devicetree.cb. There are other situations where code may
|
||||
need to probe or check the value of a field in romstage or at other
|
||||
points in ramstage. For this reason it is also possible to use the
|
||||
firmware configuration interface directly.
|
||||
|
||||
```c
|
||||
/**
|
||||
|
|
@ -372,18 +457,21 @@ bool fw_config_probe(const struct fw_config *match);
|
|||
|
||||
The argument provided to this function can be created from a macro for easy use:
|
||||
|
||||
FW_CONFIG(field, option)
|
||||
```text
|
||||
FW_CONFIG(field, option)
|
||||
```
|
||||
|
||||
This example has a mainboard check if a feature is disabled and set an FSP UPD before memory
|
||||
training. This example expects that the default value of this `register` is set to `true` in
|
||||
`devicetree.cb` and this code is disabling that feature before FSP is executed.
|
||||
This example has a mainboard check if a feature is disabled and set an
|
||||
FSP UPD before memory training. This example expects that the default
|
||||
value of this `register` is set to `true` in `devicetree.cb` and this
|
||||
code is disabling that feature before FSP is executed.
|
||||
|
||||
```c
|
||||
#include <fw_config.h>
|
||||
|
||||
void mainboard_memory_init_params(FSPM_UPD *mupd)
|
||||
{
|
||||
if (fw_config_probe(FW_CONFIG(FEATURE, DISABLED))
|
||||
mupd->ExampleFeature = false;
|
||||
if (fw_config_probe(FW_CONFIG(FEATURE, DISABLED))
|
||||
mupd->ExampleFeature = false;
|
||||
}
|
||||
```
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue