~/trunk/src/platform/ec
directory inside the chroot.build
directory or at least the board you're working on: rm -rf build/<board>
or make clobber
to prevent compilation errors.The main source code for fingerprint sensor functionality lives in the common/fpsensor
directory. The driver code for specific sensors lives in the driver/fingerprint
directory.
The following “boards” (specified by the BOARD
environment variable when building the EC code) are for fingerprint:
MCU | Sensor | Firmware (EC “board”) | Dev Board | Nucleo Board |
---|---|---|---|---|
STM32H743 (Cortex-M7) | FPC 1145 | dartmonkey (aka nocturne_fp , nami_fp ) | Icetower v3 (Previously Dragontalon) | Nucleo H743ZI2 |
STM32F412 (Cortex-M4) | FPC 1025 | bloonchipper (aka hatch_fp ) | Dragonclaw v0.3 | Nucleo F412ZG |
RAM and Flash details for each board are in the Fingerprint MCU RAM and Flash document.
Sensor | Fingerprint Template Size |
---|---|
FPC 1145 | ~48 KB |
FPC 1025 | ~5 KB |
If you have access to a shell on your Chromebook, you can use ChromeOS Config to determine the FPMCU that it contains:
(dut) $ cros_config /fingerprint board
Alternatively, if you have a Chromium OS build, you can use ChromeOS Config in the chroot to determine the FPMCU:
(chroot) $ cros_config_host -c /build/<BOARD>/usr/share/chromeos-config/yaml/config.yaml -m <MODEL> get /fingerprint board
Makefile
target options(chroot) ~/trunk/src/platform/ec $ make help
Replace <BOARD_NAME>
in the command below with the fingerprint MCU that you are targeting (e.g., nocturne_fp
, dartmonkey
, bloonchipper
).
(chroot) ~/trunk/src/platform/ec $ make BOARD=<BOARD_NAME> -j
Use V=1
to see the complete compiler output (all flags).
(chroot) ~/trunk/src/platform/ec $ make V=1 BOARD=nocturne_fp -j
Before uploading a change to Gerrit via repo upload
, you'll need to build all the boards in the EC codebase to make sure your changes do not break any others.
repo upload
will warn you and prevent you from uploading.(chroot) ~/trunk/src/platform/ec $ make buildall -j
See the Unit Tests documentation for details on how to run the unit tests.
(chroot) ~/trunk/src/platform/ec $ make BOARD=nocturne_fp utils-host -j
host_command
fuzz test(chroot) ~/trunk/src/platform/ec $ make run-host_command_fuzz
timberslide
is a simple daemon that collects logs from the FPMCU and writes them to disk. timberslide
reads from sysfs, where the kernel driver periodically dumps the FPMCU console output. timberslide
writes the resulting logs to /var/log/cros_fp.log
. There are multiple instances of timberslide
that run; one for each MCU running the EC codebase.
(dut)$ start timberslide LOG_PATH=/sys/kernel/debug/cros_fp/console_log
(dut)$ stop timberslide LOG_PATH=/sys/kernel/debug/cros_fp/console_log
(dut)$ timberslide --device_log=/sys/kernel/debug/cros_fp/console_log
If timberslide
is not running you can just cat
the logs directly from the kernel:
(dut)$ cat /sys/kernel/debug/cros_fp/console_log
fp_updater.sh
and bio_fw_updater
fp_updater.sh
and bio_fw_updater
are wrappers around flashrom
and require already-functioning RO firmware running on the FPMCU. It’s meant to be used in production to update the RW firmware. fp_updater.sh
was used prior to M77; bio_fw_updater
replaces it.
It's also possible to use the updater to update the RO firmware if you disable both HW and SW write protect, which we use for updating development devices that do not have write protect enabled (dogfood devices, EVT, etc.)
In production, only the RW portion of the firmware can be updated (unless the user disables hardware write protection).
flash_fp_mcu
flash_fp_mcu
enables spidev and toggles some GPIOs to put the FPMCU (STM32) into bootloader mode. At that point it uses stm32mon
to rewrite the entire flash (both RO and RW). The FPMCU can only be put into bootloader mode when hardware write protection is disabled, which means flash_fp_mcu
can only be used when hardware write protection is disabled.
flash_fp_mcu
is available in the Chromium OS test image.
stm32mon
stm32mon
is a tool used to send commands to the STM32 bootloader. We use it for development (through flash_fp_mcu
) to erase and flash the entire chip.
stm32mon
is available in the Chromium OS test image.
The RO
section of the fingerprint firmware contains the public portion of the key used to sign the RW firmware. The RO firmware uses the public key to validate the signature of the RW firmware before jumping to it. It is not possible to update the public key stored in the RO firmware once a device has been shipped (i.e., once hardware write protection is enabled).
Different keys are used to sign the firmware during development and production. The dev
key is used for local builds and development and is not private; it is called dev_key.pem
and located in the “board” directory for the given FPMCU (e.g., board/nocturne_fp/dev_key.pem
). After doing a build, the ec.bin
in the build
directory (e.g., build/nocturne_fp/ec.bin
) will be signed with the dev
key.
The two other types of keys are premp
and mp
, which stand for “pre-mass production” and “mass production”, respectively. Both the premp
and mp
keys are only available to the buildbots as part of the official build. The premp
is typically used during bringup of new hardware to validate the signing flow of the buildbots, while the mp
key is used for PVT and production devices.
Switching keys is only possible when the RO
firmware is not write protected, since the public portion of the keypair is stored in the RO
firmware.
For testing, you can generate a new key by using the following openssl command:
openssl genrsa -3 -out board/$BOARD/dev_key.pem 3072
futility
is used to sign EC firmware. There’s a wrapper script around it for signing called sign_official_build.sh
.
The output of futility show
will show a Public Key File
and Signature
section, each of which have an ID
field. This ID lets you match the key to the signature in case there is more than one. It’s just a sha1sum of the public key, so it lets you uniquely identify the key being used.
If you have the key (e.g., in PEM format), you can compute the ID
with the futility show
command:
(chroot) $ futility show ./path/to/key.pem
If you are building the hatch_fp
“board” on your local machine (which signs the resulting ec.bin
with the dev
key, you can check the ID
with:
(chroot)$ futility show board/hatch_fp/dev_key.pem
Private Key file: board/hatch_fp/dev_key.pem Key length: 3072 Key sha1sum: 61382804da86b4156d666cc9a976088f8b647d44
(chroot)$ futility show build/hatch_fp/ec.bin
Public Key file: build/hatch_fp/ec.bin Vboot API: 2.1 Desc: "" Signature Algorithm: 7 RSA3072EXP3 Hash Algorithm: 2 SHA256 Version: 0x00000001 ID: 61382804da86b4156d666cc9a976088f8b647d44 Signature: build/hatch_fp/ec.bin Vboot API: 2.1 Desc: "" Signature Algorithm: 7 RSA3072EXP3 Hash Algorithm: 2 SHA256 Total size: 0x1b8 (440) ID: 61382804da86b4156d666cc9a976088f8b647d44 Data size: 0x2864c (165452) Signature verification succeeded.
Asked on chromeos-chatty-firmware about adding an EC command to show the Key ID (fingerprint) from the RO version. This would make it a lot easier during both development and testing.
See Measuring Power for instructions on how to measure power with the fingerprint development boards.
(chroot) $ dut-control -t 60 ppvar_fp_mw ppvar_fp_mv ppvar_mcu_mw ppvar_mcu_mv pp1800_fp_mw pp1800_fp_mv
Firmware Version: bloonchipper_v2.0.4277-9f652bb3-RO_v2.0.21769-3757a66-RW.bin
(chroot) $ dut-control fpmcu_slp:off
@@ NAME COUNT AVERAGE STDDEV MAX MIN @@ sample_msecs 2379 25.2017 3.1648 38.4002 19.7706 @@ pp1800_fp_mv 2379 1792.0303 0.4911 1800.0000 1792.0000 @@ pp1800_fp_mw 2379 0.0000 0.0000 0.0000 0.0000 @@ ppvar_fp_mv 2379 3268.7314 1.6473 3272.0000 3264.0000 @@ ppvar_fp_mw 2379 0.7081 0.5254 3.1751 0.1000 @@ ppvar_mcu_mv 2379 3256.0000 0.0000 3256.0000 3256.0000 @@ ppvar_mcu_mw 2379 16.0525 0.1395 17.1917 15.8893
(chroot) $ dut-control fpmcu_slp:on
@@ NAME COUNT AVERAGE STDDEV MAX MIN @@ sample_msecs 2359 25.4208 3.2038 38.8474 19.5994 @@ pp1800_fp_mv 2359 1792.0712 0.7514 1800.0000 1792.0000 @@ pp1800_fp_mw 2359 0.0000 0.0000 0.0000 0.0000 @@ ppvar_fp_mv 2359 3270.5553 1.9529 3276.0000 3268.0000 @@ ppvar_fp_mw 2359 0.6903 0.5118 3.1751 0.1000 @@ ppvar_mcu_mv 2359 3256.0000 0.0000 3256.0000 3256.0000 @@ ppvar_mcu_mw 2359 0.5296 0.3512 7.0330 0.2605
(chroot) $ dut-control -t 60 ppvar_fp_mw ppvar_fp_mv ppvar_mcu_mw ppvar_mcu_mv pp1800_fp_mw pp1800_fp_mv
Firmware Version: dartmonkey_v2.0.2887-311310808-RO_v2.0.21761-e1e012ee3-RW.bin
(chroot) $ dut-control fpmcu_slp:off
@@ NAME COUNT AVERAGE STDDEV MAX MIN @@ sample_msecs 1047 57.2882 6.6254 78.7930 43.7489 @@ pp1800_fp_mv 1047 1809.7788 0.3202 1810.5469 1808.5938 @@ pp1800_fp_mw 1047 1.1289 0.0526 1.2805 0.9614 @@ ppvar_fp_mv 1047 3238.2607 0.3740 3239.2578 3237.3047 @@ ppvar_fp_mw 1047 0.0331 0.0523 0.2764 0.0000 @@ ppvar_mcu_mv 1047 3238.4156 0.3826 3239.2578 3237.3047 @@ ppvar_mcu_mw 1047 42.6689 0.3530 43.5451 41.6941
(chroot) $ dut-control fpmcu_slp:on
@@ NAME COUNT AVERAGE STDDEV MAX MIN @@ sample_msecs 1032 58.1142 6.0990 74.6982 43.6194 @@ pp1800_fp_mv 1032 1809.7634 0.3269 1810.5469 1809.0820 @@ pp1800_fp_mw 1032 1.1320 0.0529 1.2819 0.9604 @@ ppvar_fp_mv 1032 3243.6192 0.4019 3245.1172 3242.1875 @@ ppvar_fp_mw 1032 0.0324 0.0524 0.3164 0.0000 @@ ppvar_mcu_mv 1032 3243.7285 0.4072 3244.6289 3241.2109 @@ ppvar_mcu_mw 1032 4.4560 0.2319 5.4980 2.5824
In order to use the fingerprint sensor with a given ChromeOS board, a few things need to be configured for the ChromeOS board.
The biod USE
flag needs to be enabled for the ChromeOS board. This USE
flag determines whether the biod
daemon is built and installed.
To enable the USE
flag, update the make.defaults
for the ChromeOS board. See the make.defaults
for the Hatch board as an example.
After enabling the biod
USE
flag and building the biod
package for your target ChromeOS board, the biod
binary should be in the build directory:
(chroot) $ emerge-<BOARD> biod
(chroot) $ ls /build/<BOARD>/usr/bin/biod /build/<BOARD>/usr/bin/biod
FPMCU_FIRMWARE
should be set to the set of fingerprint firmware that should be built and installed for the ChromeOS board.
FPMCU_FIRMWARE
is a USE_EXPAND
variable, defined in the base make.defaults
.
The biod
ebuild uses the resulting USE
flags to determine which FPMCU release firmware to build and the chromeos-firmware-fpmcu
ebuild uses the resulting USE
flags to determine which firmware to install to the rootfs in /opt/google/biod/fw
.
Possible values for FPMCU_FIRMWARE
can be found by looking at the FIRMWARE_EC_BOARD
values in the chromeos-fpmcu-release*
ebuilds, which correspond to the FPMCU hardware.
See the Hatch baseboard make.defaults
for an example.
Once you have added the FPMCU_FIRMWARE
flag and rebuilt the chromeos-firmware-fpmcu
ebuild, the firmware will show up in the the chroot:
(chroot) $ emerge-<BOARD> chromeos-firmware-fpmcu
(chroot) $ ls /build/<BOARD>/opt/google/biod/fw bloonchipper_v2.0.2626-3c315108.bin dartmonkey_v2.0.2887-311310808.bin
The above output assumes you selected the bloonchipper
and dartmonkey
firmware by setting FPMCU_FIRMWARE="bloonchipper dartmonkey"
. The actual version numbers displayed will not necessarily match since the firmware is constantly updated.
With “unibuild”, the same OS image (build) for a given ChromeOS board is used across multiple devices. Often there will be some devices that have a fingerprint sensor, some that do not, and even different sensors for the same board.
Determining what fingerprint hardware is on a given ChromeOS board is thus done at runtime, using ChromeOS Config.
The fingerprint
config needs to be in the model.yaml
for the given ChromeOS board. The ChromeOS Config fingerprint section describes the attributes for the fingerprint
config in more detail.
The ec_extras
attribute needs to be set to the list of fingerprint firmware that should be built as part of the build.
See the model.yaml
for the Hatch board as an example.
Instead of crafting the model.yaml
by hand, newer boards are moving to the ChromeOS Project Configuration model, where the config is generated using Starlark. The common create_fingerprint
function can be used across models to configure the fingerprint settings. See the Morphius config.star
for an example of how to call create_fingerprint
. After you modify a config.star
file you will need to regenerate the config. If you need to change many projects (e.g., modifying create_fingerprint
), you can use the CLFactory
tool.
Once you have updated the config, you can test your changes by running cros_config
. The ChromeOS Config documentation has a section on testing properties that describes this in more detail.
The fingerprint sensor may only be included on certain SKUs for a given device. The fingerprint code uses ChromeOS Config to determine whether a device has a fingerprint sensor or not. For each SKU, there is an associated fingerprint config. ChromeOS Config determines the SKU information (and thus the fingerprint config) from CBI Info. The SKU for a given device can be found by viewing chrome://system/#platform_identity_sku
.
The kernel driver responsible for handling communication between the AP and FPMCU is called cros_ec
and is enabled with CONFIG_CROS_EC
in the Linux kernel. FPMCUs that are connected via SPI use cros_ec_spi.c
, while FPMCUs that are connected via UART use cros_ec_uart.c
.