~/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 v4 | Nucleo F412ZG |
| NPCX99FP (Cortex-M4) | FPC 1025 | helipilot | Quincy v3 | N/A |
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
ChromeOS devices with a Ti50 GSC can connect to the FPMCU console through CCD.
Access to the console is controlled with the UartGscRxFpmcuTx and UartGscTxFpmcuRx capabilities. Follow the CCD Open instructions to configure access.
The FPMCU console is configured as USB interface number 6. With a SuzyQ or Servo v4 plugged in to the ChromeOS device, you should see /dev/ttyUSB6, which you can connect to using your favorite terminal program:
(outside) screen /dev/ttyUSB6
Alternatively, you can use the usb_console tool.
If you run servod, it provides access to the console over a pty. You can find the name of the pty with the following commands and then use your favorite terminal program:
Raw console:
(outside) dut-control -- raw_fpmcu_uart_pty
EC3P0 console:
(outside) dut-control -- fpmcu_uart_pty
fp_updater.sh and bio_fw_updaterfp_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_mcuflash_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.
stm32monstm32mon 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 pp3300_fp_mw pp3300_fp_mv pp3300_mcu_mw pp3300_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 474 126.5655 10.8408 194.7887 99.1549 @@ pp1800_fp_mv 474 1824.5350 0.3807 1825.6836 1823.7305 @@ pp1800_fp_mw 474 0.0239 0.0397 0.3177 0.0000 @@ pp3300_fp_mv 474 3271.7625 0.4338 3273.4375 3270.0195 @@ pp3300_fp_mw 474 0.0608 0.1013 0.8886 0.0000 @@ pp3300_mcu_mv 474 3271.7852 0.4396 3273.4375 3270.5078 @@ pp3300_mcu_mw 474 20.8023 0.2471 21.5990 19.6064
(chroot) $ dut-control fpmcu_slp:on
@@ NAME COUNT AVERAGE STDDEV MAX MIN @@ sample_msecs 477 125.9021 9.9399 183.9058 98.8910 @@ pp1800_fp_mv 477 1824.5228 0.3376 1825.6836 1823.7305 @@ pp1800_fp_mw 477 0.0219 0.0344 0.2285 0.0000 @@ pp3300_fp_mv 477 3271.5591 0.4193 3272.9492 3270.5078 @@ pp3300_fp_mw 477 0.0646 0.0953 0.6885 0.0000 @@ pp3300_mcu_mv 477 3271.6533 0.4335 3272.9492 3270.5078 @@ pp3300_mcu_mw 477 1.3446 1.9869 44.4578 0.5694
(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.