summaryrefslogtreecommitdiff
path: root/docs/fingerprint
diff options
context:
space:
mode:
authorJack Rosenthal <jrosenth@chromium.org>2021-11-04 12:11:58 -0600
committerCommit Bot <commit-bot@chromium.org>2021-11-05 04:22:34 +0000
commit252457d4b21f46889eebad61d4c0a65331919cec (patch)
tree01856c4d31d710b20e85a74c8d7b5836e35c3b98 /docs/fingerprint
parent08f5a1e6fc2c9467230444ac9b582dcf4d9f0068 (diff)
downloadchrome-ec-stabilize-14695.85.B-ish.tar.gz
In the interest of making long-term branch maintenance incur as little technical debt on us as possible, we should not maintain any files on the branch we are not actually using. This has the added effect of making it extremely clear when merging CLs from the main branch when changes have the possibility to affect us. The follow-on CL adds a convenience script to actually pull updates from the main branch and generate a CL for the update. BUG=b:204206272 BRANCH=ish TEST=make BOARD=arcada_ish && make BOARD=drallion_ish Signed-off-by: Jack Rosenthal <jrosenth@chromium.org> Change-Id: I17e4694c38219b5a0823e0a3e55a28d1348f4b18 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3262038 Reviewed-by: Jett Rink <jettrink@chromium.org> Reviewed-by: Tom Hughes <tomhughes@chromium.org>
Diffstat (limited to 'docs/fingerprint')
-rw-r--r--docs/fingerprint/OWNERS1
-rw-r--r--docs/fingerprint/fingerprint-authentication-design-doc.md772
-rw-r--r--docs/fingerprint/fingerprint-debugging.md254
-rw-r--r--docs/fingerprint/fingerprint-dev-for-partners.md657
-rw-r--r--docs/fingerprint/fingerprint-factory-quick-guide.md97
-rw-r--r--docs/fingerprint/fingerprint-factory-requirements.md502
-rw-r--r--docs/fingerprint/fingerprint-firmware-testing-for-partners.md112
-rw-r--r--docs/fingerprint/fingerprint-tpm-seed.md324
-rw-r--r--docs/fingerprint/fingerprint.md590
9 files changed, 0 insertions, 3309 deletions
diff --git a/docs/fingerprint/OWNERS b/docs/fingerprint/OWNERS
deleted file mode 100644
index ba92c193e0..0000000000
--- a/docs/fingerprint/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-include ../../common/fpsensor/OWNERS
diff --git a/docs/fingerprint/fingerprint-authentication-design-doc.md b/docs/fingerprint/fingerprint-authentication-design-doc.md
deleted file mode 100644
index 7db552405a..0000000000
--- a/docs/fingerprint/fingerprint-authentication-design-doc.md
+++ /dev/null
@@ -1,772 +0,0 @@
-# Fingerprint Authentication on Chrome OS
-
-Authors: norvez@google.com, vpalatin@google.com
-
-Reviewers: kerrnel@google.com, mnissler@google.com
-
-Last Updated: 2019-01-14
-
-[TOC]
-
-## Objective
-
-### Goals
-
-* Let users securely unlock their device with just their fingerprint
-* Reuse the same architecture on all future platforms, don’t be tied to a
- specific technology ([Arm TrustZone], [Intel SGX]).
-* Support Android’s [fingerprint authentication framework] so users can for
- example authorise payments in Android apps with their fingerprint. The
- fingerprint implementation needs to comply with Android’s [CDD].
-
-### Non-goals
-
-* Let users log in with their fingerprint
- * Users will have to use other authentication methods (e.g. password or
- PIN) to log into their account.
- * Once logged in, users will be able to unlock the screen with their
- fingerprint
-
-## Background
-
-To unlock their Chromebook users have to enter their password or a PIN.
-[Windows] and [macOS] let the user authenticate with their fingerprint for
-faster unlocking, we want to bring that capability to Chrome OS.
-
-### Fingerprint matching basics
-
-#### Fingerprint enrollment
-
-When a user wants to register their finger for fingerprint authentication, they
-go through the _enrollment_ operation. They are asked to touch the sensor
-multiple times with different parts of their fingerprint. The
-[matching algorithm] uses the images captured during enrollment to build a model
-of that fingerprint (known as a _template_).
-
-#### Fingerprint matching
-
-When the user puts their finger on the sensor, an image of the fingerprint is
-captured and compared to the fingerprint templates of the enrolled fingerprints
-to determine if the fingerprint matches one of the templates.
-
-#### Template update (TU)
-
-When the matching algorithm determines that a fingerprint matches a template
-with a high level of certainty, it can (and normally will) use that fingerprint
-image to update the template to improve the accuracy of future matching
-operations.
-
-### Threat model
-
-There are two main objectives for potential attackers:
-
-* Large scale collection of biometric data from users by opportunistic
- attackers
- * This attack is only valuable remotely. In case an attacker has physical
- access to the device they are already able to collect fingerprint data
- left by the user on the device itself without having to attack the
- software.
-* Target a specific user, typically with physical access to the device in
- order to either:
- * Allow the attacker to enroll their own fingerprint to unlock the device
- at will later on (the “abusive partner” model).
- * Spoof positive fingerprint matches to let the rest of the system believe
- that a user has successfully identified, for example to break [2FA]
- \("spy" trying to gain access to an organisation’s resources via the
- victim’s computer).
-
-### Privacy and security
-
-* Biometric data is particularly sensitive, so all operations on fingerprint
- data must happen in a _Secure Biometric Processor_ (**SBP**). Attackers must
- not gain access to the user’s fingerprints even if they have exploited the
- software running on the AP.
-* To protect the user’s privacy, fingerprint data must not be accessible
- without the user’s consent, even by Google. Typically it will protected by
- the user’s password.
-* Fingerprint data must not leave the device.
-* For added security, only the specific Chromebook used to enroll the
- fingerprint can use it. Other Chromebooks, even of the same model, must not
- be able to use the enrolled fingerprint.
-
-### Scalability
-
-For Eve, we [considered][Old Design Doc] using SGX as the SBP. However the
-complexity of the solution makes that option unattractive, both because of the
-amount of dev work required and because of the large resulting attack surface.
-It’s also exclusive to Intel, we would have to develop a completely different
-architecture for other platforms, which would add more dev work and increase the
-attack surface again.
-
-## Overview {#overview}
-
-Devices have a dedicated microcontroller (MCU) running a firmware based on the
-[Chromium OS EC] codebase that is used as the _Secure Biometric Processor_
-(**SBP**), where all enrollment and matching operations take place. Even if
-attackers gained control of the AP, they still would not be able to access the
-fingerprint (FP) data since it never leaves the SBP unencrypted.
-
-The SBP controls the sensor directly over a dedicated SPI bus. The SBP is
-connected to the host with a different SPI bus, the host has no direct access to
-the FP data coming from the sensor.
-
-Enrolled templates for a particular user are stored in the user’s [cryptohome]
-but not synced/backed up to the cloud. They are thus encrypted with a key
-(`User_Key`) derived from the user’s password, preventing 3rd parties (including
-Google) from accessing the fingerprint templates if the user hasn’t entered
-their password.
-
-On top of that, enrolled templates are also encrypted by a device-specific
-`HW_Key`. `HW_Key` is derived from a secret that has been randomly generated by
-the SBP, which prevents decrypting the templates on another device.
-
-### Architecture
-
-![Fingerprint Architecture]
-
-### Typical workflows
-
-#### FP enrollment
-
-1. User starts the enrollment flow from the Settings UI.
-1. SBP starts the enrollment operation.
-1. SBP captures a number of FP images (exact number depends on the sensor,
- typically 3-4 to 10-12) and builds the template in the SBP’s volatile memory
-1. SBP encrypts the template with `HW_Key` and sends the encrypted template to
- the AP.
-1. AP encrypts the template with `User_Key` and saves it to non-volatile
- storage.
-1. User goes back to step 1 to enroll another finger. A user can typically
- enroll 3 to 5 fingers, depending on how many templates the SBP can hold in
- its internal volatile storage at the same time.
-
-#### User login
-
-1. User logs in by typing their password.
-1. FP templates of that user go through the first level of decryption, with
- `User_Key`.
-1. FP templates are uploaded to the SBP.
-1. FP templates go through the second level of decryption in the SBP, with
- `HW_Key`.
-1. Deciphered FP templates are kept in the SBP’s volatile memory, ready to use
- for matching operations.
-
-#### Screen unlocking operation
-
-1. User touches the sensor with their finger.
-1. SBP verifies that the FP image matches one of the user’s templates.
-1. SBP wakes up the AP and sends a “FP matched” message to the AP
-1. The AP unlocks the screen.
-1. Matcher updates the template in the SBP’s volatile memory.
-1. SBP encrypts the updated template with `HW_Key` and sends the encrypted
- template to the AP.
-1. AP encrypts the template with `User_Key` and saves it to non-volatile
- storage.
-
-## Detailed Design {#detailed-design}
-
-### FP template encryption {#template-encryption}
-
-FP templates are encrypted "twice". First, the templates are encrypted by the
-SBP with a hardware-bound key that is unique to this SBP and that only the SBP
-knows. On top of that, the AP also encrypts the FP templates with a key bound to
-the user password.
-
-#### User-bound encryption
-
-The FP templates are stored in a "[cryptohome daemon store folder]" which is
-encrypted by [cryptohome] with a key tied to the user password. We plan to
-replace this post-launch with a mechanism similar to
-[Authentication-Time User Secrets]. Separate design doc to come.
-
-#### Hardware-bound encryption
-
-FP templates are AES-encrypted with `HW_Key`. `HW_Key` is bound to this specific
-SBP so encrypted templates can only be deciphered by this specific SBP. To
-ensure that a powerwash/recovery/WP toggle/.../ makes the encryption key
-impossible to recover, `HW_Key` also depends on a secret held by the TPM.
-
-We use an AEAD cipher (AES-GCM) to detect if the encrypted templates have been
-tampered with by an attacker controlling the AP.
-
-##### SBP secret generation
-
-The SBP generates a new 128-bit random number `SBP_Src_Key` every time the user
-goes through recovery or powerwashes the device. The [clobber-state] script
-sends a command to the SBP to make it immediately regenerate a new `SBP_Src_Key`
-immediately after requesting a TPM clear.
-
-`SBP_Src_Key` is stored by the SBP’s internal Flash and never shared with the
-AP.
-
-##### TPM-held Secret
-
-To avoid potential bugs where `SBP_Src_Key` would not always be made
-unrecoverable in some corner cases of recovery or powerwash, we make the
-encryption key `HW_Key` depend on a secret that is held by the TPM and deleted
-every time the TPM is cleared, for example if someone attempts to do a
-"[ccd open]" to disable the hardware WP.
-
-The following is a summary of the mechanism, see the specific design doc
-[TPM Seed for Fingerprint MCU] for details.
-
-The TPM already holds a "[system key]" `Cros_Sys_Key` in NVRAM space that is
-used to derive the encryption key of the stateful partition. That "system key"
-can only be read once per boot, typically by [mount_encrypted].
-
-We modify mount_encrypted so that right after reading the seed, it derives a key
-`TPM_Seed`:
-
-```
-TPM_Seed = HMAC-SHA256(Cros_Sys_Key, "biod")
-```
-
-`TPM_Seed` is then uploaded to the SBP where it will part of the
-[Input Key Material (IKM)] and immediately cleared from the AP’s memory, while
-the attack surface is very small (e.g. no network connections, stateful
-partition not yet mounted) to prevent attackers from accessing it.
-
-##### `HW_Key` derivation {#hw-key-derivation}
-
-The `HW_Key` 128-bit AES key for every FP template on the device is derived from
-the SBP’s secret and the TPM’s secret to ensure uniqueness. Therefore, even two
-identical devices would have different encryption keys. The user ID is also used
-as an input for key derivation, so 2 users on the same device won’t share
-encryption keys either. Summing up, the key used to encrypt a template depends
-on:
-
-* Device-bound `TPM_Seed`, randomly generated on recovery/powerwash
-* SBP-specific `SBP_Src_Key`, randomly generated on recovery/powerwash
-* User ID on the device
-* Encryption salt, randomly generated before every encryption
-
-###### Salt for key derivation
-
-Every time we update a template, we generate a new random 128-bit salt.
-
-The salt is not required to be secret, so we store `User_Salt` in cleartext next
-to the user’s encrypted FP templates on the disk.
-
-On user login, biod sends the salt and the encrypted FP templates to the SBP.
-biod also sends the User ID to the SBP. The SBP derives the AES key using [HKDF]
-with HMAC-SHA256:
-
-```
-HW_Key = HKDF(HMAC-SHA256, SBP_Src_Key, TPM_Seed, User_Salt, User_ID)
-```
-
-At that point, the SBP [authenticates and deciphers](#aead) the FP templates.
-The SBP then generates a new 128-bit salt `User_Salt_New` randomly and derives a
-new AES key:
-
-```
-HW_Key_New = HKDF(HMAC-SHA256, SBP_Src_Key, TPM_Seed, User_Salt_New, User_ID)
-```
-
-Updated FP templates are then encrypted with `HW_Key_New` before being stored on
-the host, along with the new salt `User_Salt_New`.
-
-*Note*: The SBP has a unique serial number hwID that could also be used as an
-additional input to the KDF (though it never changes). The entropy is pretty low
-and though not easily accessible an attacker who had stolen the device could
-gain access to it. After consulting with the security team, using the hwID was
-deemed unnecessary since it wasn’t adding real entropy.
-
-##### AEAD (AES-GCM) Encryption {#aead}
-
-To encrypt the FP templates with `HW_Key` we use BoringSSL’s implementation of
-AES-GCM128.
-
-###### Initialisation Vector
-
-The encryption operations are done by the R/W firmware that doesn’t have write
-access to the Flash, so it can’t keep track of IVs that could have already been
-used during previous boots since it has no way to persist state. Instead, the
-SBP will generate a random 96-bit IV every time it needs to encrypt a template
-with `HW_Key` before sending it back to the host for storage. This only happens
-every time a user successfully matches their finger, which assuming 1 match
-every second for 10 years would result in 3600\*24\*365\*10 < 350,000,000, so
-the risk of reusing an IV is acceptable. To ensure that a compromised host could
-not try to generate too many messages to find collisions, the SBP rate-limits
-the number of encryption operations to 1 per second.
-
-The IV will be stored on the host with the salt, the encrypted templates and the
-16-byte tag for authentication.
-
-###### Authentication Tag
-
-To authenticate the encrypted templates, we use a 128-bit tag that we store in
-clear text with the encrypted template.
-
-Authentication of the encrypted templates prevents attackers from generating
-random templates to try to attack directly the matching libraries rather than
-the AES-GCM128 implementation. It also prevents attackers from trying to pass
-their own template instead of the user’s FP template.
-
-###### Encryption Flowchart
-
-Encryption of the FP template in the SBP before the ciphered data is sent to the
-AP for storage.
-
-![Encryption Flowchart]
-
-###### Decryption Flowchart
-
-Decryption of the ciphered FP template coming from the AP when the user logs in.
-
-![Decryption Flowchart]
-
-#### FP template disk format
-
-Encrypted templates are stored in a “[cryptohome daemon store folder]” that is
-only mounted/decrypted when the user has logged in. The templates are stored as
-JSON files with the following fields:
-
-```JSON
-{
- "biomanager": “CrosFpBiometricsManager” string
- "version": integer describing the version of the file format. Set to 1 at launch
- "data": Base64-encoded string containing the `HW_Key`-encrypted template
- "label": user-configurable human-readable string listed in the UI
- "record_id": UUID of that template generated at enrollment time
-}
-```
-
-##### `HW_Key`-encrypted template format
-
-The content of the "data" field is the encrypted template that can be deciphered
-by the SBP.
-
-Field Name | Field description | Field size (bytes) | Field offset (bytes)
----------- | --------------------------------------------------------------------- | ------------------ | --------------------
-Version | Number describing the version of the file format. Set to 3 at launch. | 2 | 0
-Reserved | Reserved bytes, set to 0 | 2 | 2
-Nonce | Randomly-generated IV | 12 | 4
-Salt | Randomly-generated salt | 16 | 16
-Tag | AES-GCM Authentication Tag | 16 | 32
-Template | Encrypted template | 47552 | 48
-
-When the user logs in, the cryptohome daemon store folder of that user is
-mounted and the JSON files become available to biod. For every enrolled finger,
-biod sends the `HW_Key`-encrypted template to the SBP. The SBP
-[derives `HW_Key`](#hw-key-derivation) for that template and deciphers the
-template.
-
-### Protection of the SBP
-
-To access the unencrypted data and/or `HW_Key`, attackers have 3 main options:
-
-* Temporarily gain read or even execution access in the SBP through a firmware
- bug
- * Would allow an attacker to gain access to the clear text FP data and/or
- the encryption key
- * Mitigation strategy in [Prevent RW exploits](#prevent-rw-exploits)
-* Turn a temporary compromise of the SBP’s firmware into a permanent exploit
- by replacing the SBP’s firmware with a firmware controlled by the attacker
- * Would allow an attacker to gain access to the clear text FP data and/or
- the encryption key
- * Would allow an attacker to spoof positive FP matches, defeating 2FA
- * Mitigation in [Verified firmware](#verified-firmware)
-* Use physical access and control of WP to load a compromised firmware to the
- SBP
- * Mitigation in [Control WP/BOOT0](#control-wp-boot0)
-
-#### Verified firmware {#verified-firmware}
-
-To verify the integrity of the firmware we use a mechanism similar to the one
-used to protect the EC in detachable keyboards as described in
-[Detachable Base Verified Boot].
-
-The SBP has a minimalistic RO firmware that contains the public part of an
-RSA-3072 exponent 3 key pair. The corresponding private key is only accessible
-by the Chrome OS signers and is used to sign SBP firmwares. On boot the RO
-firmware verifies the signature of the RW firmware. If the RW signature is
-valid, the RO firmware protects itself by setting the WP bit of the Flash then
-jumps to RW.
-
-##### Anti-rollback
-
-On top of verifying the signature of the RW firmware, the RO firmware must
-verify that the RW firmware is not an outdated version with known
-vulnerabilities. This is required to prevent attackers from loading valid but
-vulnerable RW firmwares. This is achieved with an anti-rollback mechanism as
-described in
-[Detachable Base Verified Boot][Detachable Base Verified Boot Anti-Rollback].
-
-###### Nocturne-specific anti-rollback
-
-On nocturne, the SBP is an STM32H7 MCU, with 128K Flash blocks. We still need 2
-pingpong RB blocks to prevent data loss, so the Flash map looks like this:
-
-Name | Size
-------------------- | -------
-RO firmware | 128 KB
-Blank | 640 KB
-RB1 + `SBP_Src_Key` | 128 KB
-RB2 + `SBP_Src_Key` | 128 KB
-RW firmware | 1024 KB
-
-The Nocturne SBP uses the same Flash block for the anti-rollback mechanism and
-`SBP_Src_Key`. Most of the anti-rollback mechanism is identical to the one
-described in
-[Detachable Base Verified Boot][Detachable Base Verified Boot Anti-Rollback],
-and the key is similar to the entropy/secret stored for
-[Detachable Base Swap Detection].
-
-The rollback minimum version is updated whenever RO has verified RW signature,
-and the RW rollback version is larger than what is stored in the RB block.
-
-When re-keying is desired, `SBP_Src_Key` is updated by doing the following
-operation:
-
-```
-SHA256(SBP_Src_Key || entropy)
-```
-
-where `entropy` is generated from STM32H7 True Random Number Generator (see
-[RM0433] Chapter 33 for details). Since there are 2 rollback blocks, and we
-ping-pong between them, re-keying should involve updating `SBP_Src_Key` twice,
-so that both blocks are erased, and no remnant of the previous key is left over.
-
-#### Prevent RW exploits {#prevent-rw-exploits}
-
-Even non-persistent exploits in the RW firmware would be problematic if the
-attacker was able to read the content of the memory or the Flash, e.g. via a
-buffer overflow, since they could gain access to the clear text FP data and/or
-the encryption key. If the attacker was also able to execute code in RW, they
-would be able to spoof positive FP matches.
-
-##### Attack through host command interface {#attack-host-command}
-
-The AP can send a number of commands to the SBP, for example to wait for a match
-or to update the RW firmware. In case of a vulnerability in the protocol an
-attacker with (potentially remote) access to the AP<->SBP SPI bus could send bad
-specially crafted commands to the SBP and potentially gain read, write or even
-execute permissions in the SBP.
-
-###### Mitigation strategies
-
-* Limit the size of the API exposed by the SBP to the AP
-* Fuzz the host command interface
-
-##### Attack through crafted templates uploaded to the SBP {#template-attack}
-
-The AP partially deciphers (with `User_Key`) the templates stored on the disk
-then sends the `HW_Key`-encrypted templates to the SBP where they will be
-deciphered and then passed to the matching algorithm. An attacker could submit a
-carefully crafted template to the SBP that would exploit holes in the closed
-source matching algorithm library.
-
-###### Mitigation strategies
-
-We use AEAD to decipher and authenticate the templates received from the AP,
-they are not passed directly to the matching library. Bad templates will be
-intercepted by the decryption code.
-
-##### RAM noexec
-
-Even if an attacker gained some level of access to the SBP, the RAM is not
-executable so it would be hard for the attacker to execute compromised code, for
-example to spoof successful authentication and break 2FA or to attempt to turn
-into a persistent compromission of the SBP by writing a new compromised firmware
-to Flash.
-
-#### Control WP/BOOT0 {#control-wp-boot0}
-
-The BOOT0 pin of the MCU is gated by the WP controlled by Haven. Since toggling
-the WP bit from Haven requires physical access to the device, remote attackers
-can’t toggle the BOOT0 pin to make the MCU start in bootloader mode and
-read/write the Flash from the AP.
-
-However, with physical access (> 5 minutes) an attacker could disable the WP
-signal from Haven and toggle the BOOT0 pin to start the MCU in bootloader mode.
-
-##### Flash protected with RDP Level 1
-
-We will set the Flash in [Global Read-out Protection (RDP) mode Level 1]. This
-means that attackers with physical access who would manage to start the MCU in
-bootloader mode would not be able to read `SBP_Src_Key` from the Flash.
-Attackers would still be able to read the content of the RAM and registers but
-at that point the MCU would just have rebooted and the RAM would be empty.
-
-If the attacker attempted to write their own code to the Flash (for example to
-replace RO), RDP Level 1 would only allow that after a complete erasure of the
-Flash that would wipe `SBP_Src_Key`, preventing the user from decrypting FP
-templates.
-
-*Note*: An attacker with that level of access could in theory replace the RO
-firmware with their own firmware. This would however have wiped enrolled
-fingers, giving the user an indication that their device might have been
-tampered with. This wouldn’t give access to existing FP templates or images to
-the attacker, only future enrollments.
-
-##### RMA
-
-To ensure that a device is clean after e.g. refurbishing, the RMA procedure
-would require that the operator disabled the WP bit from Haven and toggled BOOT0
-to switch to bootloader mode. After that a known good RO and RW firmware can be
-written to the Flash and the operator will reenable the WP bit from Haven.
-
-## Security Considerations
-
-### Security boundaries
-
-#### Chrome to system services
-
-Biod and Chrome communicate over D-Bus (defined [here][biod D-Bus API]).
-
-* Chrome lets biod know when the user has signed in, so biod can load the
- templates to the [SBP](#overview).
-* Biod lets Chrome know when the SBP has detected a positive or negative match
- so Chrome can unlock the screen.
-* Chrome tells biod to start/end enrolling a finger.
-* Chrome tells biod to start/end authentication (matching) mode.
-
-#### Kernel to firmware
-
-The SBP uses the `cros_ec` interface, same as the EC. There are additional
-SBP-specific host commands that the AP can send to the SBP, see
-[Attack through host command interface](#attack-host-command).
-
-### Privileges
-
-#### Sandboxing
-
-Biod uses Minijail ([upstart script][biod upstart script]) for [sandboxing], and
-has a [seccomp filter].
-
-### Untrusted input
-
-Encrypted templates are read from the stateful partition where they could be
-corrupted or tampered with. Biod itself doesn’t parse that input -it’s still
-encrypted by the SBP- and merely marshalls the data around to and from the SBP.
-To ensure the integrity of the input, we use [AEAD] with an
-[implementation][AEAD implementation] based on BoringSSL.
-
-The encrypted templates are wrapped inside JSON files that could be corrupted or
-tampered with. Biod does parse and interpret some fields of those JSON files.
-That input is [fuzzed].
-
-### Sensitive data
-
-The SBP handles biometric data, see the [Detailed Design](#detailed-design)
-section that describes how we keep that data protected from attackers.
-
-### Attack surface
-
-#### Libraries
-
-* Biod uses libbrillo and libchrome
-* The SBP firmware is based on the cros_ec code already used in the EC. Two
- significant additions:
- * Parts of BoringSSL (AES and AES-GCM) ported to cros_ec
- * 3rd-party proprietary blob used for matching, see
- [Closed source blobs in the SBP](#closed-source-blobs).
-
-#### Remote attacks
-
-Neither biod nor the SBP are exposed directly to remote attackers. Since biod
-communicates with Chrome over D-Bus, and attacker who had compromised Chrome
-could start sending D-Bus commands to biod.
-
-#### Closed source blobs in the SBP {#closed-source-blobs}
-
-The enrollment/matching and image capture libraries are provided by a 3rd-party
-vendor in binary form. That proprietary blob went through a security audit by a
-3rd party auditor (see the auditor’s [report][Security Audit Report].
-
-On top of the security audit of the 3rd-party proprietary code, we limit the
-attack surface of those libraries by not directly exposing them to user input.
-Data (e.g. FP templates) that is fed to those libraries isn’t directly coming
-from untrusted user input, it is sanitized by the opensource glue logic and
-wrappers. For example, we use AEAD to ensure that the encrypted data that is
-deciphered before being passed to the 3rd-party libraries has been generated by
-the SBP itself. For more details, see section
-[Attack through crafted templates uploaded to the SBP](#template-attack).
-
-### Implementation robustness
-
-#### biod (userspace daemon)
-
-##### Multi-threading/multi-process
-
-biod uses `base::MessageLoopForIO`, no custom multi-thread or multi-process
-implementation.
-
-##### State machine implementation
-
-biod has 3 main states:
-
-* Idle
-* Waiting for a match: controlled by the [AuthSession] object
-* Enrolling a new fingerprint: controlled by the [EnrollSession] object.
-
-#### cros_fp (SBP firmware)
-
-##### Multi-threading/multi-process
-
-We use the [primitives][EC primitives] of the Chromium OS EC: tasks, hooks, and
-deferred functions.
-
-##### Memory allocation
-
-Most buffers (e.g. for FP images and templates) are [statically allocated]. The
-vendor libraries do require some dynamic memory allocation, we provide
-[wrappers functions] that use the [malloc/free memory module for Chrome EC].
-
-##### State machine implementation
-
-There is one main [state machine] that configures the matching/enrollment code
-to be ready for a match or to enroll a finger.
-
-### Cryptography
-
-See detailed discussion in the ["FP template encryption"](#template-encryption)
-section.
-
-### Metrics {#metrics}
-
-Metrics related to security that we’re collecting through UMA:
-
-* `Ash.Login.Lock.AuthMethod.Used.ClamShellMode` to know if FP is used to
- authenticate
-* `Ash.Login.Lock.AuthMethod.Used.TabletMode` to know if FP is used to
- authenticate
-* `Fingerprint.Unlock.AuthSuccessful` tracks whether FP authentication was
- successful or not
-* `Fingerprint.Unlock.AttemptsCountBeforeSuccess` tracks how many attempts it
- takes for users to unlock with their fingerprint
-* `Fingerprint.UnlockEnabled` tracks whether FP unlocking is enabled or not
-* `Fingerprint.Unlock.EnrolledFingerCount` reports the number of fingers that
- users have enrolled
-
-Complete list of metrics collected via UMA:
-[New UKM collection review - CrOS FP Unlock]
-
-### Potential attacks
-
-#### Enroll a rogue fingerprint
-
-An attacker with physical access to the device could enroll their own
-fingerprint under the victim’s account and use it to unlock the device at-will
-in the future.
-
-* Enrollment UI requires the user password before telling biod to start an
- enrollment session, so the attacker would need some form of exploit to
- bypass Chrome and trigger the enrollment. We plan to replace this
- post-launch with a mechanism similar to [Authentication-Time User Secrets].
- Separate design doc to come.
-* Even if it’s not a persistent exploit, a rogue enrolled fingerprint would
- persist.
-* The victim’s fingerprint data would still be secure.
-* The enrollment UI shows how many fingers are enrolled.
-
-## Privacy Considerations
-
-### Fingerprint data is kept locally on the device
-
-The raw fingerprint images themselves never leave the SBP. The fingerprint
-templates are kept on the local storage (encrypted both with the `HW_Key` and
-the `User_Key`) of the device and not synced to the cloud, encrypted or not.
-
-### Fingerprint data decryption requires the user password
-
-The fingerprint templates are stored in a "[cryptohome daemon store folder]"
-which is only mounted when the user logs in. To do so, they must have entered
-their password.
-
-### FP matching is not used for login, only unlocking
-
-Before using their fingerprint to unlock the device the user must have logged
-in, typically with the Google Account password.
-
-### Lock screen will display a FP icon if enabled
-
-If a user has enabled FP unlocking, a FP icon will be associated to that user on
-the lock screen. This potentially lets others know that a user has enabled FP
-unlocking. This seems reasonable when the small resulting decrease in privacy is
-weighed against the fact that adding an icon greatly improves UX.
-
-### Metrics collection
-
-We collect anonymous metrics through [UMA], see section [Metrics](#metrics) for
-details.
-
-### Logs
-
-Biod, the SBP, and Chrome have logs related to the fingerprint process.
-[Privacy fields for Fingerprints] lists the log entries and their privacy
-implications. Full [PDD is here].
-
-#### Biod
-
-The log files are in `/var/log/biod/`.
-
-#### SBP
-
-The log file is `/var/log/cros_fp.log`.
-
-<!-- Links -->
-
-[2FA]: https://en.wikipedia.org/wiki/Multi-factor_authentication
-[AEAD implementation]: https://chromium.googlesource.com/chromiumos/platform/ec/+/aed008f87c3c880edecf7608ab24eaa4bee1bc46/common/fpsensor.c#574
-[AEAD]: https://en.wikipedia.org/wiki/Authenticated_encryption
-[Arm TrustZone]: https://www.arm.com/products/security-on-arm/trustzone
-[Authentication-Time User Secrets]: http://go/authentication-time-user-secrets
-[AuthSession]: https://chromium.googlesource.com/chromiumos/platform2/+/eae39a9ad1239f8fbfa8164255578b306ff6ba5c/biod/biometrics_manager.h#96
-[biod D-Bus API]: https://chromium.googlesource.com/chromiumos/platform2/+/HEAD/system_api/dbus/biod/
-[biod upstart script]: https://chromium.googlesource.com/chromiumos/platform2/+/HEAD/biod/init/biod.conf
-[ccd open]: https://chromium.googlesource.com/chromiumos/platform/ec/+/cr50_stab/docs/case_closed_debugging_cr50.md#Open-CCD
-[CDD]: https://source.android.com/compatibility/android-cdd#7_3_10_fingerprint_sensor
-[Chromium OS EC]: https://chromium.googlesource.com/chromiumos/platform/ec/+/HEAD/README.md
-[clobber-state]: https://chromium.googlesource.com/chromiumos/platform2/+/962ab1bc481db0cf504b5449eb3a3d5008ea7601/init/clobber_state.cc#475
-[cryptohome daemon store folder]: https://chromium.googlesource.com/chromiumos/docs/+/HEAD/sandboxing.md#securely-mounting-cryptohome-daemon-store-folders
-[cryptohome]: https://www.chromium.org/chromium-os/chromiumos-design-docs/protecting-cached-user-data
-[Detachable Base Swap Detection]: https://docs.google.com/document/d/1WYdkkSAL_RHVc5mUXnAvBBfAeM7Wj3ABa1dbeTdvm74/edit#heading=h.g74ijelumqop
-[Detachable Base Verified Boot Anti-Rollback]: http://go/detachable-base-vboot#heading=h.fimcm174ok3
-[Detachable Base Verified Boot]: http://go/detachable-base-vboot#heading=h.dolfbdpggye6
-[EC primitives]: https://chromium.googlesource.com/chromiumos/platform/ec/+/HEAD/README.md#Software-Features
-[EnrollSession]: https://chromium.googlesource.com/chromiumos/platform2/+/eae39a9ad1239f8fbfa8164255578b306ff6ba5c/biod/biometrics_manager.h#92
-[fingerprint authentication framework]: https://developer.android.com/about/versions/marshmallow/android-6.0.html#fingerprint-authentication
-[fuzzed]: https://chromium.googlesource.com/chromiumos/platform2/+/HEAD/biod/biod_storage_fuzzer.cc
-[Global Read-out Protection (RDP) mode Level 1]: https://www.st.com/content/ccc/resource/technical/document/application_note/b4/14/62/81/18/57/48/05/DM00075930.pdf/files/DM00075930.pdf/jcr:content/translations/en.DM00075930.pdf
-[HKDF]: https://tools.ietf.org/html/rfc5869
-[Input Key Material (IKM)]: https://en.wikipedia.org/wiki/HKDF
-[Intel SGX]: https://software.intel.com/en-us/sgx
-[macOS]: https://support.apple.com/en-us/HT207054
-[malloc/free memory module for Chrome EC]: https://chromium.googlesource.com/chromiumos/platform/ec/+/HEAD/common/shmalloc.c
-[matching algorithm]: https://en.wikipedia.org/wiki/Fingerprint#Algorithms
-[mount_encrypted]: https://chromium.googlesource.com/chromiumos/platform2/+/HEAD/cryptohome/mount_encrypted
-[New UKM collection review - CrOS FP Unlock]: https://docs.google.com/document/d/1qjDCMcBcrhSeg_uwyEIRsXHKmzUTJahcg6a4YVhkuLo
-[Old Design Doc]: https://docs.google.com/document/d/1MdPRmCDkVg1HO9DdbvPT5fDZS2ICg5ys9_ok_K95EEU
-[PDD is here]: http://go/cros-fingerprint-pdd
-[Privacy fields for Fingerprints]: https://docs.google.com/spreadsheets/d/1jLfnuhfbrImpoxuj92OkAxS_GGrm7QkpQhsUQCkO9ec
-[Privacy fields for Fingerprints]: https://docs.google.com/spreadsheets/d/1jLfnuhfbrImpoxuj92OkAxS_GGrm7QkpQhsUQCkO9ec/
-[RM0433]: https://www.st.com/content/ccc/resource/technical/document/reference_manual/group0/c9/a3/76/fa/55/46/45/fa/DM00314099/files/DM00314099.pdf/jcr:content/translations/en.DM00314099.pdf
-[sandboxing]: https://chromium.googlesource.com/chromiumos/docs/+/HEAD/sandboxing.md
-[seccomp filter]: https://chromium.googlesource.com/chromiumos/platform2/+/HEAD/biod/init/seccomp/biod-seccomp-amd64.policy
-[Security Audit Report]: https://drive.google.com/a/google.com/file/d/0B1HHKpeDpzYnMDdocGxwWUhpckpWM0hMU0tPa2ZjdEFnLU53/
-[state machine]: https://chromium.googlesource.com/chromiumos/platform/ec/+/90d177e3f0ae729bea7e24934a3c6ef9f2520d45/common/fpsensor.c#252
-[statically allocated]: https://chromium.googlesource.com/chromiumos/platform/ec/+/90d177e3f0ae729bea7e24934a3c6ef9f2520d45/common/fpsensor.c#57
-[system key]: https://chromium.googlesource.com/chromiumos/platform2/+/23b79133514ac2cd986bce21c398fb6658bda248/cryptohome/mount_encrypted/encryption_key.h#125
-[UMA]: http://go/uma
-[Windows]: https://www.microsoft.com/en-us/windows/windows-hello
-[wrappers functions]: https://chrome-internal.googlesource.com/chromeos/platform/ec-private/+/9ebb3f10c611afff695f679aaeed1a35551a116b/fpc_sensor_pal.c#52
-[TPM Seed for Fingerprint MCU]: ../fingerprint/fingerprint-tpm-seed.md
-
-<!-- Images -->
-
-<!-- If you make changes to the docs below make sure to regenerate the PNGs by
- appending "export/png" to the Google Drive link. -->
-
-<!-- https://docs.google.com/drawings/d/1-JUWTF7sUTND29BfhDvIudzX_S6g-iwoxG1InPedmVw -->
-
-[Decryption Flowchart]: ../images/cros_fingerprint_decryption_flowchart.png
-
-<!-- https://drive.google.com/open?id=1uUprgLsTUZZ2G2QWRYcRn6zBAh6ejvJagVRD7eZQv-k -->
-
-[Encryption Flowchart]: ../images/cros_fingerprint_encryption_flowchart.png
-
-<!-- https://docs.google.com/drawings/d/1DFEdxfDXEtYY3LNOOJFAxVw2A7rKouH98tnb1yiXLAA -->
-
-[Fingerprint Architecture]: ../images/cros_fingerprint_architecture_diagram.png
diff --git a/docs/fingerprint/fingerprint-debugging.md b/docs/fingerprint/fingerprint-debugging.md
deleted file mode 100644
index c77874e7bb..0000000000
--- a/docs/fingerprint/fingerprint-debugging.md
+++ /dev/null
@@ -1,254 +0,0 @@
-# Fingerprint Debugging
-
-This document describes how to attach a debugger with SWD in order to debug the
-FPMCU with [`gdb`](#gdb) or to [flash the FPMCU](#flash).
-
-[TOC]
-
-## Overview
-
-### SWD
-
-`SWD` (Single Wire Debug) was introduced by ARM with the Cortex-M family to
-reduce the pin count required by JTAG. JTAG requires 5 pins, but SWD can be done
-with only 3 pins. Furthermore, one of the freed up pins can be repurposed for
-tracing.
-
-See [CoreSight Connectors] for details on the three standard types of connectors
-used for JTAG and SWD for ARM devices.
-
-## Hardware Required
-
-* JTAG/SWD Debugger Probe: Any debug probe that supports SWD will work, but
- this document assumes that you're using a
- [Segger J-Trace PRO for Cortex-M][J-Trace].
-* [Dragonclaw v0.2 Development board][FPMCU dev board] or
- [Icetower v0.1 Development board][FPMCU dev board].
-* [Servo Micro].
-
-## Software Required
-
-* [JLink Software] \(when using [J-Trace] or other Segger debug probes). This
- is the only software required for flashing.
-* In order to perform breakpoint debugging, you will need a tool that supports
- connecting `gdbserver`. This document will assume [CLion] \(Googlers see
- [CLion for Chrome OS]) and was tested with `JLink_Linux_V684a_x86_64`.
- Alternatively, you can use [Ozone], a standalone debugger from Segger.
-
-## JLink Software {#software}
-
-Download the [JLink Software], choosing the `J-Link Software and Documentation
-pack for Linux, TGZ archive, 64-bit` version. This version is recommended
-because it's simple to extract the tarball into a directory that is accessible
-to the Chrome OS chroot. The instructions in this document assume that you have
-extracted the tarball in
-`~/chromiumos/src/platform/ec/JLink_Linux_V684a_x86_64`.
-
-## Connecting SWD {#connect-swd}
-
-### Dragonclaw v0.2
-
-The connector for SWD is `J4` on Dragonclaw v0.2.
-
-<!-- mdformat off(b/139308852) -->
-*** note
-**NOTE**: Pay attention to the location of pin 1 (red wire) in the
-photos below so that you connect with the correct orientation.
-
-`SW2` on the bottom of Dragonclaw must be set to `CORESIGHT`.
-
-If you want to connect a 20-Pin ARM Standard JTAG Connector (0.10" / 2.54 mm),
-you can use the following [adapter][JTAG to SWD Adapter] and [cable][SWD Cable].
-***
-<!-- mdformat on -->
-
-Dragonclaw v0.2 with 20-pin SWD (0.05" / 1.27mm) on J4. Only half the pins are connected. |
------------------------------------------------------------------------------------------ |
-![Dragonclaw with 20-pin SWD] |
-
-Dragonclaw v0.2 with 10-pin SWD (0.05" / 1.27mm) on J4. |
-------------------------------------------------------- |
-![Dragonclaw with 10-pin SWD] |
-
-### Icetower v0.1
-
-The connector for SWD is `J4` on Icetower v0.1.
-
-`SW2` on Icetower must be set to `CORESIGHT` (not `SERVO`).
-
-Icetower v0.1 with 20-pin SWD (0.05" / 1.27mm) on J4. |
------------------------------------------------------ |
-![Icetower with 20-pin SWD] |
-
-## Powering the Board {#power}
-
-[Servo Micro] can provide both the 3.3V for the MCU and 1.8V for the sensor.
-
-Run the following to start `servod`, which will enable power to these rails by
-default:
-
-```bash
-(chroot) $ sudo servod --board=<BOARD>
-```
-
-where `<BOARD>` is the board you are working with
-([`dartmonkey` or `bloonchipper`][fingerprint hardware]).
-
-Theoretically, it's also possible to power through J-Trace, though the
-[power pin] on J-Trace only outputs 5V, whereas the MCU runs at 3.3V and the
-sensor runs at 1.8V. The pin is also not connected on the current designs.
-
-## Flashing the FPMCU with JLink {#flash}
-
-* Install the [JLink Software](#software).
-* [Connect SWD](#connect-swd).
-* [Power the board with servo](#power).
-* Start the JLink server:
-
-```bash
-(chroot) $ cd ~/trunk/src/platform/ec
-```
-
-```bash
-# JLinkRemoteServerCLExe will listen on port 19020 (among others) by default.
-# This can be overridden with the -Port argument.
-(outside) $ ./JLink_Linux_V684a_x86_64/JLinkRemoteServerCLExe -select USB
-```
-
-You should see the following:
-
-```bash
-SEGGER J-Link Remote Server V6.84a
-Compiled Sep 7 2020 18:28:13
-
-'q' to quit '?' for help
-
-Connected to J-Link with S/N 123456
-
-Waiting for client connections...
-```
-
-* Build the FPMCU image:
-
-```bash
-(chroot) $ cd ~/trunk/src/platform/ec
-```
-
-```bash
-(chroot) $ make BOARD=<BOARD> -j
-```
-
-replacing `<BOARD>` with [`bloonchipper` or `dartmonkey`][fingerprint hardware].
-
-* Run the [`flash_jlink.py`] script:
-
-```bash
-(chroot) $ ~/trunk/src/platform/ec/util/flash_jlink.py --board <BOARD> --image ./build/<BOARD>/ec.bin
-```
-
-replacing `<BOARD>` with [`bloonchipper` or `dartmonkey`][fingerprint hardware].
-
-## Using JLink gdbserver {#gdb}
-
-Start the JLink gdbserver for the appropriate MCU type:
-
-* Dragonclaw / [Nucleo STM32F412ZG]: `STM32F412CG`
-* Icetower / [Nucleo STM32H743ZI]: `STM32H743ZI`
-
-```bash
-(outside) $ ./JLink_Linux_V684a_x86_64/JLinkGDBServerCLExe -select USB -device STM32F412CG -endian little -if SWD -speed auto -noir -noLocalhostOnly
-```
-
-You should see the port that `gdbserver` is running on in the output:
-
-```bash
-Connecting to J-Link...
-J-Link is connected.
-Firmware: J-Trace PRO V2 Cortex-M compiled Dec 13 2019 11:19:22
-Hardware: V2.00
-S/N: XXXXX
-Feature(s): RDI, FlashBP, FlashDL, JFlash, GDB
-Checking target voltage...
-Target voltage: 3.30 V
-Listening on TCP/IP port 2331 <--- gdbserver port
-Connecting to target...
-Connected to target
-Waiting for GDB connection...
-```
-
-Configure your editor to use this [`.gdbinit`], taking care to set the correct
-environment variables for the `BOARD` and `GDBSERVER` being used. For CLion, if
-you want to use a `.gdbinit` outside of your `HOME` directory, you'll need to
-[configure `~/.gdbinit`].
-
-In your editor, specify the IP address and port for `gdbserver`:
-
-```
-127.0.0.1:2331
-```
-
-You will also want to provide the symbol files:
-
-* RW image: `build/<board>/RW/ec.RW.elf`
-* RO image: `build/<board>/RO.ec.RO.elf`
-
-Also, since we're compiling the firmware in the chroot, but your editor is
-running outside of the chroot, you'll want to remap the source code path to
-account for this:
-
-* "Remote source" is the path inside the chroot:
- `/home/<username>/trunk/src/platform/ec`
-* "Local source" is the path outside the chroot:
- `${HOME}/chromiumos/src/platform/ec`
-
-To debug with CLion, you will create a new [GDB Remote Debug Configuration]
-called `EC Debug`, with:
-
-* `'target remote' args` (gdbserver IP and port from above): `127.0.0.1:2331`
-* `Symbol file` (RW or RO ELF): `/path/to/build/<board>/RW/ec.RW.elf`
-* `Path mapping`: Add remote to local source path mapping as described above.
-
-After configuring this if you select the `EC Debug` target in CLion and
-[click the debug icon][CLion Start Remote Debug], CLion and JLink will handle
-automatically flashing the ELF file and stepping through breakpoints in the
-code. Even if not debugging, this may help with your iterative development flow
-since the JLink tool can flash very quickly since it performs a differential
-flash. Note that you still need to recompile after making changes to the source
-code before launching the debugger.
-
-## Using Ozone
-
-Ozone is a free standalone debugger provided by Segger that works with the
-[J-Trace]. You may want to use it if you need more powerful debug features than
-gdbserver can provide. For example, Ozone has a register mapping for the MCUs we
-use, so you can easily inspect CPU registers. It can also be automated with a
-scripting language and show code coverage when used with a [J-Trace] that is
-connected to the trace pins on a board. Note that the Dragonclaw v0.2 uses an
-STM32F412 package that does not have the synchronous trace pins, but the
-[Nucleo STM32F412ZG] does have the trace pins.
-
-[CoreSight Connectors]: http://www2.keil.com/coresight/coresight-connectors
-[FPMCU dev board]: ./fingerprint-dev-for-partners.md#fpmcu-dev-board
-[J-Trace]: https://www.segger.com/products/debug-probes/j-trace/models/j-trace/
-[JLink Software]: https://www.segger.com/downloads/jlink/#J-LinkSoftwareAndDocumentationPack
-[Servo Micro]: ./fingerprint-dev-for-partners.md#Servo-Micro
-[JTAG to SWD Adapter]: https://www.adafruit.com/product/2094
-[SWD Cable]: https://www.adafruit.com/product/1675
-[Ozone]: https://www.segger.com/products/development-tools/ozone-j-link-debugger/
-[CLion]: https://www.jetbrains.com/clion/
-[CLion for Chrome OS]: http://go/clion-for-chromeos
-[GDB Remote Debug Configuration]: https://www.jetbrains.com/help/clion/remote-debug.html#remote-config
-[CLion Start Remote Debug]: https://www.jetbrains.com/help/clion/remote-debug.html#start-remote-debug
-[Nucleo STM32F412ZG]: https://www.st.com/en/evaluation-tools/nucleo-f412zg.html
-[Nucleo STM32H743ZI]: https://www.st.com/en/evaluation-tools/nucleo-h743zi.html
-[`.gdbinit`]: /util/gdbinit
-[configure `~/.gdbinit`]: https://www.jetbrains.com/help/clion/configuring-debugger-options.html#gdbinit-lldbinit
-[power pin]: https://www.segger.com/products/debug-probes/j-link/technology/interface-description/
-[fingerprint hardware]: ./fingerprint.md#hardware
-[`flash_jlink.py`]: https://chromium.googlesource.com/chromiumos/platform/ec/+/HEAD/util/flash_jlink.py
-
-<!-- Images -->
-
-[Dragonclaw with 20-pin SWD]: ../images/dragonclaw_with_20_pin_swd.jpg
-[Dragonclaw with 10-pin SWD]: ../images/dragonclaw_with_10_pin_swd.jpg
-[Icetower with 20-pin SWD]: ../images/icetower_with_20_pin_swd.jpg
diff --git a/docs/fingerprint/fingerprint-dev-for-partners.md b/docs/fingerprint/fingerprint-dev-for-partners.md
deleted file mode 100644
index 2d9332db5b..0000000000
--- a/docs/fingerprint/fingerprint-dev-for-partners.md
+++ /dev/null
@@ -1,657 +0,0 @@
-# FPMCU Development for Partners
-
-This document is intended to help partners (sensor vendors, MCU vendors, etc)
-that are currently (or interested in) developing fingerprint solutions for
-Chromebooks. The document assumes that you're using Linux to do the development;
-preferably a recent version of Ubuntu or Debian. Some partners have had success
-developing in a VM, but please note that we don't test that configuration.
-
-See the [FPMCU documentation] for additional development information.
-
-[TOC]
-
-## Hardware Required for Standalone Development (no Chromebook)
-
-The following hardware components can be used to set up a standalone development
-environment for FPMCU development (i.e., it does not rely on a Chromebook).
-Development for other [EC]s is often done in a similar manner, but some of them
-have their own standalone development or evaluation kits that don't require the
-use of [servo].
-
-You will need an [FPMCU reference board](#fpmcu-dev-board) and a
-[servo debugger](#servo).
-
-### FPMCU board {#fpmcu-dev-board}
-
-The Fingerprint MCU (FPMCU) board has the MCU that handles all
-fingerprint-related functionality (matching, encryption, etc). The fingerprint
-sensor itself connects to the FPMCU board.
-
-This FPMCU board is the Dragonclaw Rev 0.2. |
-------------------------------------------- |
-![Dragonclaw board] |
-
-Download the [Dragonclaw schematics, layout, and BOM][dragonclaw schematics].
-
-<!-- mdformat off(b/139308852) -->
-*** note
-**Googlers**: You can pick up the Dragonclaw development board at Chromestop.
-**Partners**: You can request a Dragonclaw development board from Google.
-***
-
-*** note
-Dragonclaw Rev 0.2 needs a [rework](#dragonclaw-rev-0.2-rework) for the FPC
-sensor to work while being powered through Servo. All of the boards at Chromestop
-have already been reworked.
-***
-<!-- mdformat on -->
-
-This FPMCU board is the Dartmonkey Rev 0.1. |
-------------------------------------------- |
-![Dartmonkey board] |
-
-### Servo
-
-Servo is a general purpose debug board that connects to a header on the FPMCU
-board. Among other things, the servo supplies power to the FPMCU and can be used
-to program the FPMCU, interact with the EC console, take power measurements, and
-debug a running program. It supports SPI, UART, I2C, as well as JTAG/SWD.
-
-There are two different servo debugger setups supported, the
-[Servo Micro](#servo-micro) and the [Servo V2 + Yoshi](#servo-v2-yoshi). The
-servo micro is recommended for its simplicity. It lacks builtin JTAG/SWD support
-for single step debugging, but Dragonclaw v0.2 has an
-[SWD connector](#servo-micro-swd) that can be used.
-
-[Servo Micro](#servo-micro) | [ServoV2 + Yoshi](#servo-v2-yoshi)
---------------------------- | ----------------------------------
-![Servo Micro] | ServoV2 ![Servo v2] Yoshi Flex ![Standard Yoshi Flex]
-
-<!-- mdformat off(b/139308852) -->
-*** note
-For more information about both servos, see [servo].
-***
-<!-- mdformat on -->
-
-### Servo Micro
-
-Unlike the Servo V2, the newer servo micro does not require any adapters to
-interface with the FPMCU board.
-
-As you can see below, one end connects to the FPMCU board and the other connect
-to the developer's computer over micro USB.
-
-![Servo Micro with Dragonclaw]
-
-<!-- mdformat off(b/139308852) -->
-*** note
-For more information about Servo Micro, see [Servo Micro Info].
-***
-<!-- mdformat on -->
-
-#### Using SWD (Optional) {#servo-micro-swd}
-
-Instructions for setup are described in [Fingerprint Debugging].
-
-### Servo V2 + Yoshi
-
-Servo V2 is the original full featured debugger. It requires a
-[Yoshi Flex Cable](#yoshi-flex-cable) to interface with the FPMCU.
-
-![Servo v2]
-
-<!-- mdformat off(b/139308852) -->
-*** note
-NOTE: More information on servo can be found in the [servo] documentation.
-***
-<!-- mdformat on -->
-
-#### Yoshi Flex Cable
-
-The Yoshi Flex cable is used to connect Servo v2 to the FPMCU board. The
-standard cable does not work with SWD, but a simple rework can be performed to
-support SWD.
-
-Standard Yoshi Flex | Yoshi Flex Reworked to Support SWD
----------------------- | -------------------------------------
-![Standard Yoshi Flex] | ![Yoshi Flex Reworked to Support SWD]
-
-Rework steps:
-
-* Remove R18 and R19
-* Wire from Pin 6 of U21 to right side of R18
-* Wire from Pin 6 of U21 to right side of R19
-
-#### Micro USB Cable
-
-A micro USB cable is needed to connect the the servo v2 board to your host Linux
-development machine.
-
-* [Micro USB Cable]
-
-#### Servo V2 Hardware Setup
-
-1. Connect the Yoshi Flex cable to servo, paying attention to the pin
- numbering.
-
- ![Connect Yoshi Flex] ![Another Yoshi Flex image]
-
-2. Connect the other end of the Yoshi Flex cable to the servo header on the
- FPMCU board.
-
- ![Connect Yoshi Flex to FPMCU board] ![Another image]
-
-3. Connect the fingerprint sensor to the header on the FPMCU board.
-
-4. Connect the micro USB cable to servo's `HOST_IN` port. The other end of the
- USB cable should be plugged into your host development machine.
-
- ![Connect USB to Servo]
-
-5. Optional: Connect SWD Debugger
-
- If you want to use SWD for debugging, connect your debugger to the `JTAG`
- header on servo v2.
-
- ![Connect SWD Debugger]
-
-## Software Setup
-
-### Get the Chromium OS source code
-
-* First, make sure you [have the prerequisites].
-* Then [get the source].
-* Create and [enter the `chroot`].
- * You can stop after the `enter the chroot` step.
-
-### Build the [EC]\ (embedded controller) codebase
-
-Open **two** terminals and enter the chroot in each:
-
-```bash
-# from a terminal on your machine
-(outside chroot) $ cd ~/chromiumos/src
-
-# enter the chroot (the flag is important)
-(outside chroot) $ cros_sdk --no-ns-pid
-```
-
-<!-- mdformat off(b/139308852) -->
-*** note
-NOTE: More information on servo can be found in the [servo] documentation.
-***
-<!-- mdformat on -->
-
-In one of the terminals, build and start `servod`
-
-Build and install `servod` in the chroot:
-
-```bash
-(chroot) $ sudo emerge hdctools
-```
-
-<!-- mdformat off(b/139308852) -->
-*** note
-In all of the following commands, replace `<BOARD>` in the command with
-`bloonchipper` or `dartmonkey` depending on the development board you are using.
-***
-<!-- mdformat on -->
-
-Run `servod`:
-
-```bash
-(chroot) $ sudo servod --board=<BOARD>
-```
-
-You should see something like this. Leave it running:
-
-```bash
-2019-04-11 15:21:53,715 - servod - INFO - Start
-2019-04-11 15:21:53,765 - servod - INFO - Found servo, vid: 0x18d1 pid: 0x5002 sid: 911416-00789
-2019-04-11 15:21:53,766 - servod - INFO - Found XML overlay for board zerblebarn
-2019-04-11 15:21:53,766 - SystemConfig - INFO - Loading XML config (/usr/lib64/python2.7/site-packages/servo/data/servo_v2_r1.xml, None, 0)
-2019-04-11 15:21:53,767 - SystemConfig - INFO - Loading XML config (/usr/lib64/python2.7/site-packages/servo/data/servo_v2_r0.xml, None, 0)
-2019-04-11 15:21:53,771 - SystemConfig - INFO - Loading XML config (/usr/lib64/python2.7/site-packages/servo/data/common.xml, None, 0)
-2019-04-11 15:21:53,772 - SystemConfig - INFO - Loading XML config (/usr/lib64/python2.7/site-packages/servo/data/power_tools.xml, None, 0)
-2019-04-11 15:21:53,774 - SystemConfig - INFO - Loading XML config (/usr/lib64/python2.7/site-packages/servo/data/keyboard.xml, None, 0)
-2019-04-11 15:21:53,775 - SystemConfig - INFO - Loading XML config (/usr/lib64/python2.7/site-packages/servo/data/uart_common.xml, None, 0)
-2019-04-11 15:21:53,777 - SystemConfig - INFO - Loading XML config (/usr/lib64/python2.7/site-packages/servo/data/ftdii2c_cmd.xml, None, 0)
-2019-04-11 15:21:53,777 - SystemConfig - INFO - Loading XML config (/usr/lib64/python2.7/site-packages/servo/data/usb_image_management.xml, None, 0)
-2019-04-11 15:21:53,784 - SystemConfig - INFO - Loading XML config (/usr/lib64/python2.7/site-packages/servo/data/servo_zerblebarn_overlay.xml, None, 0)
-2019-04-11 15:21:53,785 - SystemConfig - INFO - Loading XML config (/usr/lib64/python2.7/site-packages/servo/data/servoflex_v2_r0_p50.xml, None, 0)
-2019-04-11 15:21:53,792 - Servod - INFO - Initializing interface 1 to ftdi_empty
-2019-04-11 15:21:53,792 - Servod - INFO - Initializing interface 2 to ftdi_i2c
-2019-04-11 15:21:53,795 - Servod - INFO - Initializing interface 3 to ftdi_uart
-2019-04-11 15:21:53,799 - Servod - INFO - /dev/pts/8
-2019-04-11 15:21:53,799 - Servod - INFO - Initializing interface 4 to ftdi_uart
-2019-04-11 15:21:53,802 - Servod - INFO - /dev/pts/9
-2019-04-11 15:21:53,802 - Servod - INFO - Use the next FTDI part @ pid = 0x5003
-2019-04-11 15:21:53,802 - Servod - INFO - Initializing interface 5 to ftdi_empty
-2019-04-11 15:21:53,802 - Servod - INFO - Use the next FTDI part @ pid = 0x5003
-2019-04-11 15:21:53,802 - Servod - INFO - Initializing interface 6 to ftdi_empty
-2019-04-11 15:21:53,802 - Servod - INFO - Use the next FTDI part @ pid = 0x5003
-2019-04-11 15:21:53,802 - Servod - INFO - Initializing interface 7 to ftdi_uart
-2019-04-11 15:21:53,805 - Servod - INFO - /dev/pts/10
-2019-04-11 15:21:53,805 - Servod - INFO - Use the next FTDI part @ pid = 0x5003
-2019-04-11 15:21:53,805 - Servod - INFO - Initializing interface 8 to ftdi_uart
-2019-04-11 15:21:53,808 - Servod - INFO - /dev/pts/11
-2019-04-11 15:21:53,808 - Servod - INFO - Initializing interface 9 to ec3po_uart
-2019-04-11 15:21:53,811 - PD/Cr50 - EC3PO Interface - INFO - -------------------- PD/Cr50 console on: /dev/pts/12
-2019-04-11 15:21:53,811 - Servod - INFO - Initializing interface 10 to ec3po_uart
-2019-04-11 15:21:53,812 - EC - EC3PO Interface - INFO - -------------------- EC console on: /dev/pts/14
-2019-04-11 15:21:54,316 - Servod - INFO - Initialized i2c_mux to rem
-2019-04-11 15:21:54,317 - Servod - INFO - Initialized i2c_mux_en to on
-2019-04-11 15:21:54,319 - Servod - INFO - Initialized pch_disable to off
-2019-04-11 15:21:54,320 - Servod - INFO - Initialized jtag_buf_on_flex_en to off
-2019-04-11 15:21:54,321 - Servod - INFO - Initialized cold_reset to off
-2019-04-11 15:21:54,322 - Servod - INFO - Initialized warm_reset to off
-2019-04-11 15:21:54,323 - Servod - INFO - Initialized spi1_buf_on_flex_en to off
-2019-04-11 15:21:54,324 - Servod - INFO - Initialized spi_hold to off
-2019-04-11 15:21:54,326 - Servod - INFO - Initialized pwr_button to release
-2019-04-11 15:21:54,327 - Servod - INFO - Initialized lid_open to yes
-2019-04-11 15:21:54,328 - Servod - INFO - Initialized spi2_buf_on_flex_en to off
-2019-04-11 15:21:54,330 - Servod - INFO - Initialized rec_mode to off
-2019-04-11 15:21:54,331 - Servod - INFO - Initialized fw_up to off
-2019-04-11 15:21:54,332 - Servod - INFO - Initialized usb_mux_sel1 to dut_sees_usbkey
-2019-04-11 15:21:54,333 - Servod - INFO - Initialized prtctl4_pwren to on
-2019-04-11 15:21:54,334 - Servod - INFO - Initialized uart3_en to on
-2019-04-11 15:21:54,334 - Servod - INFO - Initialized dut_hub_pwren to on
-2019-04-11 15:21:54,335 - Servod - INFO - Initialized kbd_en to off
-2019-04-11 15:21:54,337 - Servod - INFO - Initialized spi1_vref to pp3300
-2019-04-11 15:21:54,338 - Servod - INFO - Initialized spi2_vref to pp1800
-2019-04-11 15:21:54,339 - Servod - INFO - Initialized uart2_en to on
-2019-04-11 15:21:54,340 - Servod - INFO - Initialized uart1_en to on
-2019-04-11 15:21:54,341 - Servod - INFO - Initialized jtag_buf_en to off
-2019-04-11 15:21:54,342 - Servod - INFO - Initialized fw_wp_en to off
-2019-04-11 15:21:54,343 - Servod - INFO - Initialized sd_vref_sel to off
-2019-04-11 15:21:54,343 - Servod - INFO - Initialized ec_ec3po_interp_connect to on
-2019-04-11 15:21:54,344 - Servod - INFO - Initialized uart3_vref to off
-2019-04-11 15:21:54,345 - Servod - INFO - Initialized jtag_vref_sel0 to pp3300
-2019-04-11 15:21:54,346 - Servod - INFO - Initialized jtag_vref_sel1 to pp3300
-2019-04-11 15:21:54,346 - Servod - INFO - Initialized fpmcu_ec3po_interp_connect to on
-2019-04-11 15:21:54,349 - ServoDeviceWatchdog - INFO - Watchdog setup for devices: set([(6353, 20482, '911416-00789')])
-2019-04-11 15:21:54,351 - servod - INFO - Listening on localhost port 9999
-```
-
-In the other terminal, build and flash the firmware:
-
-Navigate to the EC source:
-
-```bash
-(chroot) $ cd ../platform/ec
-```
-
-Build the firmware:
-
-```bash
-(chroot) $ make BOARD=<BOARD> -j
-```
-
-The resulting file will be in `build/<BOARD>/ec.bin`
-
-Flash the firmware file:
-
-```bash
-(chroot) $ ./util/flash_ec --board=<BOARD> --image=./build/<BOARD>/ec.bin
-```
-
-Prepare a serial terminal in your chroot:
-
-```bash
-(chroot) $ sudo emerge screen
-```
-
-Connect to the UART pty:
-
-```bash
-(chroot) $ sudo screen $(dut-control raw_fpmcu_console_uart_pty | cut -d: -f2)
-```
-
-Press enter key several times (may need to wait up to 20 seconds). Then you will
-see a prompt:
-
-```
->
-```
-
-At this point you are connected to the MCU's serial (UART) console. You can list
-all of the available console commands with "help":
-
-```
-> help
-```
-
-```bash
-Known commands:
-  chan           fpcapture      hcdebugsherase     fpenroll       history        spixfer        waitms
-  flashinfo      fpmatch        hostevent      sysinfo
-  flashread      gettime        md             sysjump
-  flashwp        gpioget        panicinfo      syslock
-  flashwrite     gpioset        reboot         taskinfo
-HELP LIST = more info; HELP CMD = help on CMD.
-```
-
-Start a fingerprint enrollment:
-
-```
-> fpenroll
-```
-
-### Measuring Power {#measure-power}
-
-The Dragonclaw reference board has an onboard INA that monitors the voltage and
-power draw of the MCU and FP Sensor independently.
-
-Signal Name | Description
---------------- | -------------------------------------
-`pp3300_dx_mcu` | 3.3V supplying the MCU
-`pp3300_dx_fp` | 3.3V supplying the fingerprint sensor
-`pp1800_dx_fp` | 1.8V supplying the fingerprint sensor
-
-You can monitor all power and voltages by using the following command:
-
-```bash
-(chroot) $ watch -n0.5 dut-control pp3300_dx_mcu_mv pp3300_dx_fp_mv pp1800_dx_fp_mv pp3300_dx_mcu_mw pp3300_dx_fp_mw pp1800_dx_fp_mw
-```
-
-You can get a summary of the power over `N` seconds with:
-
-```bash
-(chroot) $ dut-control -t N pp3300_dx_mcu_mv pp3300_dx_fp_mv pp1800_dx_fp_mv pp3300_dx_mcu_mw pp3300_dx_fp_mw pp1800_dx_fp_mw
-```
-
-<!-- mdformat off(b/139308852) -->
-*** note
-The `_mv` suffix denotes millivolt and `_mw` suffix denotes milliwatt.
-***
-
-*** note
-See [Power Measurement Documentation] for more information.
-***
-<!-- mdformat on -->
-
-### Toggling Hardware Write Protect
-
-When using a fingerprint development board connected to servo, you can toggle
-hardware write protect for testing.
-
-**NOTE**: `servod` must be running.
-
-Check the state of hardware write protect:
-
-```bash
-(chroot) $ dut-control fw_wp_en
-```
-
-Enable hardware write protect:
-
-```bash
-(chroot) $ dut-control fw_wp_en:on
-```
-
-Disable hardware write protect:
-
-```bash
-(chroot) $ dut-control fw_wp_en:off
-```
-
-### Contributing Changes
-
-#### Using Gerrit and git
-
-If you’re not familiar with `git`, Gerrit (code review) and `repo`, here are
-some docs to help you get started:
-
-* [Git and Gerrit Intro for Chromium OS]: Useful to get started as quickly as
- possible, but does not explain how `git` works under the hood.
-* [Set your editor]: Use your favorite editor when writing `git` commit
- messages.
-* [Chromium OS Contributing Guide]: Detailed overview of contributing changes
- to Chromium OS and the workflow we use.
-* [Git: Concepts and Workflow]: Good overview of how `git` actually works.
-* [Gerrit: Concepts and Workflow]: Good overview of how Gerrit works; assumes
- you understand `git` basics.
-* [Life of a patch]: Android workflow, but similar to Chrome OS.
-
-The Gerrit dashboard that will show your pending reviews (and ones we have for
-you):
-
-* [Public Gerrit]
-* [Internal Gerrit]
-
-#### Registering for a chromium.org *Internal* Account
-
-If your partnership agreement requires non-public code sharing you will need to
-register for an account on the [Internal Gerrit]. Refer to the
-[Gerrit Credentials Setup] page for details. Once you register for an internal
-account, your contact at Google can make sure you have the necessary permissions
-to access the private repository.
-
-<!-- mdformat off(b/139308852) -->
-*** note
-**NOTE**: In order to use a private repository you will have to manually add it
-to the repo manifest file before running `repo sync`. Check with your contact
-at Google for the exact values to use below:
-
-**`(outside) $ ~/chromiumos/.repo/manifests/default.xml`**
-
-```xml
-<project remote="cros-internal"
- path="CHECK WITH GOOGLE"
- groups="firmware"
- name="CHECK WITH GOOGLE" />
-```
-
-**`(outside) $ ~/chromiumos/.repo/manifests/remote.xml`**
-
-```xml
-<remote name="cros-internal"
- fetch="https://chrome-internal.googlesource.com"
- review="https://chrome-internal-review.googlesource.com" />
-```
-***
-<!-- mdformat on -->
-
-### Tracking Issues and Communication
-
-Development issue tracking and communication is done through the
-[Partner Issue Tracker]. You will use your [Partner Domain] account to access
-the [Partner Issue Tracker]. If you do not already have a [Partner Domain]
-account, please request one from your Google contact.
-
-In order to make sure that you receive email notifications for issues, please
-make sure that you [set up email forwarding] and set your
-[notification settings] appropriately. Communication should primarily be done
-through the [Partner Issue Tracker] and not email so that it can be more easily
-tracked by multiple people and a record is preserved for posterity.
-
-[Partner Issue Tracker]: https://developers.google.com/issue-tracker/guides/partner-access
-[Partner Domain]: https://developers.google.com/issue-tracker/guides/partner-domains
-[set up email forwarding]: https://developers.google.com/issue-tracker/guides/partner-domains#email_forwarding
-[notification settings]: https://developers.google.com/issue-tracker/guides/set-notification-preferences
-
-## Working with Chromebooks
-
-Chromebooks have an FPMCU (e.g., Dragonclaw) board attached to the motherboard.
-You can use the device to run `ectool` commands and test the fingerprint sensor
-from the UI.
-
-### Developer Mode and Write Protection
-
-Make sure that your fingerprint-equipped Chrome OS device is in [developer mode]
-with a *test* image flashed and [hardware write protection] disabled. Using the
-test image will allow you to SSH into the device and disabling hardware write
-protection allows you to have full access to flashing the FPMCU firmware.
-
-See [Installing Chromium] for details on flashing test images and enabling
-[developer mode].
-
-### Connecting
-
-In general, most of our development is done by connecting to the DUT (device
-under test) via SSH. We usually connect the DUT to ethernet (e.g., via USB-C to
-Ethernet converter), but WiFi should also work (assuming corporate firewall
-restrictions don’t block SSH port 22). To get the IP address, tap the
-battery/time icon in the lower right corner. Then tap on “Ethernet” followed by
-the gear icon in the upper right.
-
-```bash
-(chroot) $ ssh root@<IP_ADDRESS>
-Password: test0000
-```
-
-Once you have SSH’ed into the DUT, you should be able to run `ectool` commands.
-
-**Example**: Capture a "test_reset" image from the sensor and write it to a
-[PNM] file (viewable with the ImageMagick `display` command):
-
-```bash
-(device) $ ectool --name=cros_fp fpmode capture test_reset; ectool --name=cros_fp waitevent 5 500; ectool --name=cros_fp fpframe > /tmp/test_reset.pnm
-```
-
-Alternatively, you can access a shell via the UI on device by pressing
-`CTRL+ALT+F2` (third key on top row). Log in with `root` and `test0000`.
-
-### Flashing FPMCU from DUT
-
-Copy the firmware to the DUT:
-
-```bash
-(chroot) $ scp ./build/bloonchipper/ec.bin <DUT_IP>:/tmp/ec.bin
-```
-
-From the DUT, flash the firmware you copied:
-
-```bash
-(device) $ flash_fp_mcu /tmp/ec.bin
-```
-
-## Commit-queue Prototype Environment
-
-![CQ Prototype Environment]
-
-## Troubleshooting
-
-### Dragonclaw Rev 0.2 Rework {#dragonclaw-rev-0.2-rework}
-
-<!-- mdformat off(b/139308852) -->
-*** note
-**NOTE**: All Dragonclaw v0.2 boards have been reworked, so it is not necessary
-to perform the rework yourself.
-***
-<!-- mdformat on -->
-
-Dragonclaw **Rev 0.2** has two load switches (`U4` and `U6`) that enable the
-1.8V power rail from the servo connector or motherboard connector. However, this
-switch is not compatible with 1.8V, so will always output 0V.
-
-The [rework document][Dragonclaw Rev 0.2 1.8V Rework] describes replacing these
-two switches with ones compatible with 1.8V.
-
-### Dragonclaw Rev 0.1 Servo Fix
-
-Dragonclaw **Rev 0.1** has a known issue with UART and JTAG. Most notably, this
-issue causes servo micro to fail to program the FPMCU over UART.
-
-This issue can be fixed with the following rework steps:
-
-* Connect servo header pin 13 to pin 18
-* Connect servo header pin 13 to pin 29
-
-![Dragonclaw servo fix diagram]
-
-### Verify that servo and debugger are connected to USB {#servo-connected}
-
-Check whether servo is enumerating on USB. If you are using a debugger
-(Lauterbach, J-Link, etc), also check to make sure it enumerates. Depending on
-the debugger being used, it may need to be powered with an external power
-supply.
-
-```bash
-(chroot) $ lsusb
-
-Bus 002 Device 003: ID 0897:0004 Lauterbach # ← This is my Lauterbach (debugger)
-Bus 001 Device 013: ID 18d1:5002 Google Inc. # ← This is servo
-```
-
-### "No servos found" when running servod
-
-If you get the following message, make sure that
-[servo is connected to USB](#servo-connected). You may also want to try
-restarting your machine (or VM).
-
-```bash
-(chroot) $ sudo servod --board=bloonchipper
-2019-04-12 14:53:42,236 - servod - INFO - Start
-2019-04-12 14:53:42,270 - servod - ERROR - No servos found
-```
-
-### Losing characters in servo UART console
-
-Make sure that this interface is disabled:
-
-```bash
-(chroot) $ dut-control usbpd_ec3po_interp_connect:off
-```
-
-### FPMCU console commands
-
-* Once the console is working you can use `help` to see the commands.
-* There should be fingerprint commands that start with `fp` (see `fpsensor.c`
- in the [EC] code).
-
-<!-- Links -->
-
-[EC]: https://chromium.googlesource.com/chromiumos/platform/ec
-[ectool_servo_spi]: https://chromium.googlesource.com/chromiumos/platform/ec/+/HEAD/util/comm-servo-spi.c#15
-[servo]: https://chromium.googlesource.com/chromiumos/third_party/hdctools/+/HEAD/README.md
-[developer mode]: https://chromium.googlesource.com/chromiumos/docs/+/HEAD/debug_buttons.md#firmware-keyboard-interface
-[hardware write protection]: https://chromium.googlesource.com/chromiumos/platform/ec/+/HEAD/docs/write_protection.md
-[have the prerequisites]: https://chromium.googlesource.com/chromiumos/docs/+/HEAD/developer_guide.md#Prerequisites
-[get the source]: https://chromium.googlesource.com/chromiumos/docs/+/HEAD/developer_guide.md#get-the-source
-[enter the `chroot`]: https://chromium.googlesource.com/chromiumos/docs/+/HEAD/developer_guide.md#building-chromium-os
-[Chromium OS Contributing Guide]: https://chromium.googlesource.com/chromiumos/docs/+/HEAD/contributing.md
-[Servo Micro Info]: https://chromium.googlesource.com/chromiumos/third_party/hdctools/+/HEAD/docs/servo_micro.md
-[Set your editor]: https://chromium.googlesource.com/chromiumos/docs/+/HEAD/developer_guide.md#Set-your-editor
-[Life of a patch]: https://source.android.com/setup/contribute/life-of-a-patch
-[Git: Concepts and Workflow]: https://docs.google.com/presentation/d/1IQCRPHEIX-qKo7QFxsD3V62yhyGA9_5YsYXFOiBpgkk/
-[Gerrit: Concepts and Workflow]: https://docs.google.com/presentation/d/1C73UgQdzZDw0gzpaEqIC6SPujZJhqamyqO1XOHjH-uk/
-[Public Gerrit]: https://chromium-review.googlesource.com
-[Power Measurement Documentation]: https://chromium.googlesource.com/chromiumos/third_party/hdctools/+/HEAD/docs/power_measurement.md
-[Internal Gerrit]: https://chrome-internal-review.googlesource.com
-[Gerrit Credentials Setup]: https://www.chromium.org/chromium-os/developer-guide/gerrit-guide
-[Micro USB Cable]: https://www.monoprice.com/product?p_id=9762
-[PNM]: https://en.wikipedia.org/wiki/Netpbm_format
-[Git and Gerrit Intro for Chromium OS]: https://chromium.googlesource.com/chromiumos/docs/+/HEAD/git_and_gerrit_intro.md
-[Installing Chromium]: https://chromium.googlesource.com/chromiumos/docs/+/HEAD/developer_guide.md#installing-chromium-os-on-your-device
-[FPMCU documentation]: ./fingerprint.md
-[Fingerprint Debugging]: ./fingerprint-debugging.md
-[dragonclaw schematics]: ../schematics/dragonclaw
-
-<!-- Images -->
-
-[Servo Micro]: ../images/servo_micro.jpg
-[Servo Micro with Dragonclaw]: ../images/servomicro_dragonclaw.jpg
-[Servo v2]: ../images/servo_v2.jpg
-[Standard Yoshi Flex]: ../images/yoshi_flex.jpg
-[Yoshi Flex Reworked to Support SWD]: ../images/yoshi_flex_swd_rework.jpg
-[Dragonclaw board]: ../images/dragonclaw_rev_0.2.jpg
-[Dragonclaw servo fix diagram]: ../images/dragonclaw_servo_fix.jpg
-[Connect USB to Servo]: ../images/servo_v2_with_micro_usb.jpg
-[Connect Yoshi Flex]: ../images/servo_v2_with_yoshi_flex.jpg
-[Another Yoshi Flex image]: ../images/servo_v2_with_yoshi_flex2.jpg
-[Connect Yoshi Flex to FPMCU board]: ../images/dragonclaw_yoshi_flex_header.jpg
-[Another image]: ../images/dragonclaw_yoshi_flex_header2.jpg
-[Connect SWD Debugger]: ../images/servo_v2_jtag_header.jpg
-[Dartmonkey board]: ../images/dartmonkey.jpg
-
-<!-- If you make changes to the docs below make sure to regenerate the JPEGs by
- appending "export/pdf" to the Google Drive link. -->
-
-<!-- https://docs.google.com/drawings/d/1YhOUD-Qf69NUdugT6n0cX7o7CWvb5begcdmJwv7ch6I -->
-
-[Dragonclaw Rev 0.2 1.8V Rework]: https://github.com/coreboot/chrome-ec/blob/master/docs/images/dragonclaw_rev_0.2_1.8v_load_switch_rework.pdf
-
-<!-- https://docs.google.com/drawings/d/1w2qbb4AsSxY-KTK2vXZ6TKeWHveWvS3Dkgh61ocu0wc -->
-
-[CQ Prototype Environment]: ../images/CQ_Prototype_Environment.jpg
diff --git a/docs/fingerprint/fingerprint-factory-quick-guide.md b/docs/fingerprint/fingerprint-factory-quick-guide.md
deleted file mode 100644
index c9478bf99a..0000000000
--- a/docs/fingerprint/fingerprint-factory-quick-guide.md
+++ /dev/null
@@ -1,97 +0,0 @@
-# Chrome OS Fingerprint Sensor: Quick Factory Guide
-
-The goal of this document is to outline how ODM partners can make use of the
-existing Chrome OS factory scripts to meet Chrome OS FPS factory requirements.
-
-[TOC]
-
-## Factory Requirements
-
-### Flash firmware for fingerprint sensor microcontroller (FPMCU)
-
-FPMCU firmware must be flashed before fingerprint functional test is run. ODM
-partners may work with the module house to preflash FPMCU firmware before
-factory SMT. However, this way ODM partners have to coordinate with the module
-house to make sure the preflash FPMCU firmware blob is extracted from the FSI
-release image (from /opt/google/biod/fw/). If the FPMCU firmware doesn’t match
-the FPMCU firmware blob checked into the release image, the end users will see
-the ‘critical update’ screen in their out-of-box experience, because
-bio\_fw\_updater tries to update FPMCU firmware at boot time. This is a bad user
-experience we want to avoid. Most importantly, in PVT/MP build, only the FPMCU
-firmware in the release image would be signed by MP key. So you **MUST** ensure
-FPMCU is flashed with the MP-signed firmware blob extracted from FSI, before
-shipping the devices.
-
-As opposed to pre-flashing FPMCU in the module house, ODM partners are
-encouraged to make use of
-[update\_fpmcu\_firmware.py](https://chromium.googlesource.com/chromiumos/platform/factory/+/e5e903d0a0d8327dd8b9e47d2c808fd845ed73a4/py/test/pytests/update_fpmcu_firmware.py)
-to update FPMCU firmware in the factory flow. This script can detect fingerprint
-MCU board name, find the right FPMCU firmware blob for the DUT from the release
-partition, and then flash FPMCU by flash\_fp\_mcu tool. Please note that this
-script may take more than 30 secs to complete, which is slow.
-
-Since bio\_fw\_update has been disabled in factory test image via
-[crrev/c/1913645](https://chromium-review.googlesource.com/c/chromiumos/platform2/+/1913645),
-in the factory flow, the FPMCU firmware should not be overwritten by
-boot-update-firmware service during reboot.
-
-### Run fingerprint sensor functional test
-
-Please add
-[fingerprint\_mcu.py](https://chromium.git.corp.google.com/chromiumos/platform/factory/+/a283609cd8446ba4a4b75c2e1d84c9ba24ea8422/py/test/pytests/fingerprint_mcu.py)
-to your device test list. A more detailed description about this test can be
-found
-[here](https://chromium.googlesource.com/chromiumos/platform/ec/+/HEAD/docs/fingerprint/fingerprint-factory-requirements.md).
-
-### Initialize FPMCU entropy in factory finalization
-
-The support for FPMCU entropy initialization has been integrated into the
-factory finalization script. So FPMCU entropy should be automatically
-initialized in factory finalization, if a FPMCU is found on DUT. Note that FPMCU
-entropy initialization would fail if rollback\_block\_id is not equal to zero,
-which means the entropy has been initialized before. It is usually caused by
-biod trying to initialize FPMCU entropy and increment rollback\_block\_id at
-boot time. Since we have disabled biod and bio\_crypto\_init in factory test
-image via
-[crrev/c/1910290](https://chromium-review.googlesource.com/c/chromiumos/platform/factory/+/1910290),
-we expect rollback\_block\_id would stay zero during the factory flow, and FPMCU
-entropy initialization should succeed in factory finalization. So just run
-factory finalization as any other CrOS boards.
-
-### Enable FPMCU software write protection (SWWP) in factory finalization in PVT/MP
-
-The support for FPMCU SWWP has been integrated into factory finalization script.
-So FPMCU SWWP should be automatically enabled in factory finalization together
-with AP/EC SWWP when write\_protection arg is set to true and a FPMCU is found
-on DUT. Just run factory finalization as any other CrOS boards.
-
-### Reset entropy for factory re-finalization (in case of RMA or OQC)
-
-For the boards that have been finalized, FPMCU entropy has been initialized. So
-running re-finalization for those boards are expected to fail at FPMCU entropy
-initialization. Before running re-finalization for those boards, ODM partners
-have to remove hardware write protection (HWWP) and then run
-[update\_fpmcu\_firmware.py](https://chromium.googlesource.com/chromiumos/platform/factory/+/d399a0a1bdeb7249de2721b269e7365e4486e23c/py/test/pytests/update_fpmcu_firmware.py)
-to reset rollback\_block\_id and entropy. So the follow-up re-finalization
-(which re-initialize entropy) can succeed.
-
-## References
-
-* CrOS fingerprint factory requirements:
- [doc link](https://chromium.googlesource.com/chromiumos/platform/ec/+/HEAD/docs/fingerprint/fingerprint-factory-requirements.md)
-* The summary of CLs:
- * Add a factory script to update FPMCU firmware:
- [crrev/c/1918679](https://chromium-review.googlesource.com/c/chromiumos/platform/factory/+/1918679),
- [crrev/c/1913493](https://chromium-review.googlesource.com/c/chromiumos/platform/factory/+/1913493),
- [crrev/c/1927149](https://chromium-review.googlesource.com/c/chromiumos/platform/factory/+/1927149),
- [crrev/c/1984618](https://chromium-review.googlesource.com/c/chromiumos/platform/factory/+/1984618),
- [crrev/c/2036574](https://chromium-review.googlesource.com/c/chromiumos/platform/factory/+/2036574)
- * Disable FPS-related services that will interfere with the factory flow:
- [crrev/c/1913645](https://chromium-review.googlesource.com/c/chromiumos/platform2/+/1913645),
- [crrev/c/1910290](https://chromium-review.googlesource.com/c/chromiumos/platform/factory/+/1910290)
- * Support FPMCU in factory finalization:
- [crrev/c/1868795](https://chromium-review.googlesource.com/c/chromiumos/platform/factory/+/1868795),
- [crrev/c/1902267](https://chromium-review.googlesource.com/c/chromiumos/platform/factory/+/1902267),
- [crrev/c/1900503](https://chromium-review.googlesource.com/c/chromiumos/platform/factory/+/1900503),
- [crrev/c/1925927](https://chromium-review.googlesource.com/c/chromiumos/platform/factory/+/1925927),
- [crrev/c/1948163](https://chromium-review.googlesource.com/c/chromiumos/platform/factory/+/1948163)
diff --git a/docs/fingerprint/fingerprint-factory-requirements.md b/docs/fingerprint/fingerprint-factory-requirements.md
deleted file mode 100644
index 0fc99e2740..0000000000
--- a/docs/fingerprint/fingerprint-factory-requirements.md
+++ /dev/null
@@ -1,502 +0,0 @@
-# Chrome OS Fingerprint Factory Requirements
-
-This document provides an overview of factory requirements and testing for the
-fingerprint sensor.
-
-[TOC]
-
-## Contact
-
-For questions regarding this document, please contact the
-[Chrome OS Fingerprint Team].
-
-## Terminology
-
-* `AP`: Application Processor.
-* `FPMCU`: Fingerprint Microcontroller.
-* `FATP`: Final Assembly, Test, and Pack
-* `FP sensor`: Fingerprint sensor. Directly connected to the FPMCU, not the
- AP.
-* `firmware`: Software that runs on the FPMCU.
-* `finalization`: Process that is run in the factory before the device being
- built leaves the factory.
-* `entropy`: Cryptographically secure random bytes stored in FPMCU flash. Used
- for encrypting/decrypting fingerprint templates.
-* `software write protect`: Prevents the RO portion of the FPMCU’s flash from
- being overwritten. Full details in [EC docs][Software Write Protect].
-* `ITS`: In-Device Test Specification.
-* `MTS`: Module Test Specification.
-* `MQT`: Module Quality Test.
-* `MQT2`: Module Quality Test 2.
-
-## Documents
-
-* [FPC1025: Module Test Specification]
-* [FPC1145: Module Test Specification]
-* [FPC In-Device Test Specification]
-* [Factory Fingerprint Sensor Testing for `nocturne` ]
-
-## FPMCU Firmware Location
-
-The binaries for the FPMCU firmware are located in `/opt/google/biod/fw`. Now
-that Chrome OS supports unibuild, there may be multiple firmware binaries in the
-directory since multiple sensors may be used across a single "board" (e.g., the
-`hatch` board can use either `bloonchipper` or `dartmonkey`).
-
-The correct firmware type to use for a given board can be discovered with the
-[Chrome OS Config] tool:
-
-```bash
-(dut) $ cros_config /fingerprint board
-dartmonkey
-```
-
-OR
-
-```bash
-(chroot) $ cros_config_host -c /build/<BOARD>/usr/share/chromeos-config/yaml/config.yaml -m <MODEL> get /fingerprint board
-dartmonkey
-```
-
-The corresponding firmware for the above command would be
-`/opt/google/biod/fw/dartmonkey_*.bin`.
-
-<!-- mdformat off(b/139308852) -->
-*** note
-**NOTE**: If you get an empty response when running the above commands, the
-Chrome OS Config settings may not have been updated for the Chrome OS board.
-See the instructions on [updating Chrome OS Config] for fingerprint.
-***
-<!-- mdformat on -->
-
-Note that the fingerprint team continuously releases updates to the firmware, so
-SIEs should watch for version changes in ToT if they are maintaining a separate
-factory branch.
-
-## Flashing the FPMCU
-
-When the FPMCU is completely blank a low-level flashing tool must be used to
-program an initial version of the FPMCU firmware. It’s possible to use the
-[`flash_fp_mcu`] script as this low-level flashing tool, though since it
-requires the AP and is not necessarily robust against failures, it is not
-recommended for mass-production. More details about [`flash_fp_mcu`] are in the
-[Fingerprint flashing documentation].
-
-The initial version of the FPMCU firmware should be flashed either by the module
-house or by the factory. Once an initial version of the FPMCU firmware has been
-flashed (i.e., the FPMCU is not blank), the `bio_fw_updater` tool runs on
-startup and handles updating the FPMCU firmware to match the version that is in
-the rootfs. Note that this update process can take around 30 seconds; if that
-length of time is an issue then the factory or module house should pre-flash the
-latest firmware beforehand.
-
-<!-- mdformat off(b/139308852) -->
-*** note
-**NOTE**: If the FPMCU is not flashed in the factory as part of development
-builds (EVT, etc.), it's possible for developers (or Chromestop) to manually
-run [`flash_fp_mcu`], as long as they can disable [hardware write protect].
-Obviously this only applies during development, not mass production.
-***
-<!-- mdformat on -->
-
-## biod and timberslide
-
-Since `biod` communicates with the FPMCU, it’s best to disable it when running
-the fingerprint factory tests. This can be done with upstart:
-
-```bash
-(dut) $ stop biod
-```
-
-Once testing is complete `biod` should be restarted (or you can reboot the
-device).
-
-`timberslide` is the daemon that periodically sends commands to the FPMCU to
-read the latest FPMCU logs. It writes the results to `/var/log/cros_fp.log`. It
-should be fine to leave running during tests, though it should be stopped before
-running the [`flash_fp_mcu`] script, since that script erases the entire FPMCU:
-
-```bash
-(dut) $ stop timberslide LOG_PATH=/sys/kernel/debug/cros_fp/console_log
-```
-
-## Factory Tests
-
-### Fingerprint Sensor (standalone module)
-
-When using an FPC sensor (e.g., FPC 1025, FPC 1145), the fingerprint sensor
-itself must be tested by the module manufacturer with FPC’s tools. FPC provides
-a Module Test Tool (MTT), which requires additional hardware (FPC Module Test
-Card). FPC also provides design drawings for the rubber stamp. The stamp,
-test-fixture and test station need to be implemented by the OEM/ODM/Module House
-(often only module house).
-
-The `MTS` _must_ be followed by the module manufacturer, but Google does not
-provide direct support for this testing. FPC is the main point of contact.
-
-The module testing procedure is documented in the following:
-
-[FPC1025: Module Test Specification]
-
-[FPC1145: Module Test Specification]
-
-### Fingerprint Sensor + FPMCU (in device)
-
-In-device tests are run during the `FATP` process once the device has been fully
-assembled. Google provides source code for these tests in
-[`fingerprint_mcu.py`].
-
-Hardware Required: Chrome OS DUT before finalization.
-
-Documentation: [FPC In-Device Test Specification]
-
-#### Test Image Checkerboard and Inverted Checkerboard Test (CB/ICB)
-
-##### Purpose
-
-Capture a checkerboard (and inverted checkerboard) pattern and verify that the
-values of the individual pixels do not deviate from the median.
-
-##### Implementation
-
-Use `ectool` to capture the first checkerboard pattern image:
-
-```bash
-(dut) $ ectool --name=cros_fp fpmode capture pattern0; ectool --name=cros_fp waitevent 5 500
-FP mode: (0x20000008) capture
-MKBP event 5 data: 00 00 00 80
-```
-
-Copy the first checkerboard image to a file:
-
-```bash
-(dut) $ ectool --name=cros_fp fpframe > /tmp/pattern0.pnm
-```
-
-Use `ectool` to capture the second checkerboard pattern image:
-
-```bash
-(dut) $ ectool --name=cros_fp fpmode capture pattern1; ectool --name=cros_fp waitevent 5 500
-FP mode: (0x30000008) capture
-MKBP event 5 data: 00 00 00 80
-```
-
-Copy the second checkerboard image to a different file:
-
-```bash
-(dut) $ ectool --name=cros_fp fpframe > /tmp/pattern1.pnm
-```
-
-Perform median analysis on the resulting image as described in the `MTS`
-document. The factory toolkit does this in
-[`fingerprint_mcu.py`][Checkerboard Test].
-
-<!-- mdformat off(b/139308852) -->
-*** note
-**TIP**: You can view the `.pnm` files generated by the commands below on your
-Linux desktop with ImageMagick: `display /path/to/file.pnm`.
-***
-<!-- mdformat on -->
-
-##### Success/Failure
-
-The median pixel value (type 1 and type 2), pixel errors, finger detect zone
-errors, and pixel error deviation limit must fall within the acceptance criteria
-limits specified in "4.3.5 Acceptance Criteria Test Image CB / iCB" in the `MTS`
-document for the sensor being tested.
-
-#### Hardware Reset Test (aka IRQ test)
-
-##### Purpose
-
-Perform a hardware reset of the sensor and test that the IRQ line is asserted
-after 5 ms. See "Section 4.1 Reset test pattern procedure" and "2.8 HW Reset" in
-the FPC `MTS` document for the sensor being tested.
-
-##### Implementation
-
-This is implemented by the FPMCU on every boot. The results can be checked with
-the `ectool` command. The factory toolkit does this in
-[`fpmcu_utils.py`][GetSensorIdErrors].
-
-##### Success/Failure
-
-The `Error flags` line of the `fpinfo` `ectool` command must be empty.
-
-```bash
-(dut) $ ectool --name=cros_fp fpinfo
-
-Fingerprint sensor: vendor 20435046 product 9 model 1401 version 1
-Image: size 56x192 8 bpp
-Error flags:
-Dead pixels: UNKNOWN
-Templates: version 4 size 47616 count 0/5 dirty bitmap 0
-```
-
-#### Hardware ID (HWID) check
-
-##### Purpose
-
-Ensure that communications between the sensor and the FPMCU are working and that
-the correct sensor has been assembled.
-
-##### Implementation
-
-`ectool` can be used to request the hardware ID, which can be compared with the
-expected hardware ID. The factory toolkit does this in
-[`fpmcu_utils.py`][GetSensorId].
-
-##### Success/Failure
-
-The `Fingerprint sensor` line of the `fpinfo` `ectool` command must show the
-expected ID and the `Error flags` line must be empty:
-
-```bash
-(dut) $ ectool --name=cros_fp fpinfo
-
-Fingerprint sensor: vendor 20435046 product 9 model 1401 version 1 # FPC 1145
-Image: size 56x192 8 bpp
-Error flags:
-Dead pixels: UNKNOWN
-Templates: version 4 size 47616 count 0/5 dirty bitmap 0
-```
-
-#### Reset Pixel (RP)
-
-##### Purpose
-
-Capture a white image, compare the individual pixel values and ensure that the
-deviation to the median is within the specified range.
-
-##### Implementation
-
-Capture the test image with `ectool` and analyze the output. The factory toolkit
-does this in [`fingerprint_mcu.py`][ProcessResetPixelImage].
-
-Switch to correct capture mode and wait:
-
-```bash
-(dut) $ ectool --name=cros_fp fpmode capture test_reset; ectool --name=cros_fp waitevent 5 500
-FP mode: (0x50000008) capture
-MKBP event 5 data: 00 00 00 80
-```
-
-Retrieve the test image:
-
-```bash
-(dut) $ ectool --name=cros_fp fpframe > /tmp/test_reset.pnm
-```
-
-##### Success/Failure
-
-A pixel is considered to be a bad pixel ("reset pixel error") if the value read
-out deviates more than a defined value from the median. The median value and the
-max number of pixels that have "reset pixel error" are defined in section "Reset
-Pixel" (4.4 or 4.5) of the MTS for the given sensor.
-
-#### Module Quality Test (or Module Quality Test 2) with Rubber Stamp Zebra (Optional)
-
-##### Purpose
-
-The Module Quality Test (`MQT`) uses a rubber stamp with a "zebra" pattern to
-characterize module performance and image quality after the top layer (including
-stack-up) is applied. Although this test is optional, OEMs are strongly
-encouraged to perform it.
-
-##### Implementation
-
-Capture the image when the rubber stamp is applied:
-
-```bash
-(dut) $ ectool --name=cros_fp fpmode capture qual
-FP mode: (0x40000008) capture
-```
-
-Wait for the capture to be finished, timeout after 10s:
-
-```bash
-(dut) $ ectool --name=cros_fp waitevent 5 10000
-MKBP event 5 data: 00 00 00 80
-```
-
-Copy the raw captured from to the AP:
-
-```bash
-(dut) $ ectool --name=cros_fp fpframe raw > /tmp/fp.raw
-```
-
-Run the analysis tool on the captured frame:
-
-```bash
-(dut) $ /usr/local/opt/fpc/fputils.py --mqt /tmp/fp.raw
-Error, MQT status : (5)
-MQT failed (-1)
-```
-
-The factory toolkit does this in [`fingerprint_mcu.py`][rubber_finger_present].
-
-##### Success/Failure
-
-See "Section 5.1.5" Acceptance Criteria for `MQT2` or "Section 5.2.5 Acceptance
-Criteria" in the MTS for the given sensor.
-
-## Finalization
-
-The finalization process must perform two tasks:
-
-1. Initialize the FPMCU’s `entropy`.
-1. When building for PVT or mass production, enable `software write protect`.
-
-### Initialize FPMCU Entropy
-
-The `bio_wash` tool is intended to support both the first time factory
-initialization and RMA, depending on the flag. When run with the
-`--factory_init` argument (`bio_wash --factory_init`), it will ensure that the
-`entropy` is set. If the `entropy` has already been set it will do nothing.
-
-A side-effect of running `bio_wash` is that the `rollback_id` changes (`ectool
---name=cros_fp rollbackinfo`). Initially when the firmware is first flashed, the
-`rollback_id` should be zero. After `entropy` is initialized the `rollback_id`
-should be set to 1.
-
-Note that for new devices coming out of the factory we expect `rollback_id` to
-be 1, which indicates that the entropy has been set exactly once.
-
-### Enable Software Write Protect
-
-`Software write protect` must be enabled for PVT and mass production devices. It
-ensures that the RO portion of the FPMCU firmware cannot be overwritten, so it
-is critical for FPMCU security.
-
-The following commands will enable software write protection:
-
-```bash
-(dut) $ ectool --name=cros_fp flashprotect enable # enable
-(dut) $ sleep 2
-(dut) $ ectool --name=cros_fp reboot_ec # reboot so it takes effect
-(dut) $ sleep 2
-```
-
-To validate that software write protection has taken effect, run the following:
-
-```bash
-(dut) $ ectool --name=cros_fp flashprotect # get flashprotect state
-
-# output should match below
-Flash protect flags: 0x0000000b wp_gpio_asserted ro_at_boot ro_now
-Valid flags: 0x0000003f wp_gpio_asserted ro_at_boot ro_now all_now STUCK INCONSISTENT
-Writable flags: 0x00000004 all_now
-```
-
-If software write protection is not enabled, you will see the following instead:
-
-```bash
-(dut) $ ectool --name=cros_fp flashprotect # get flashprotect state
-
-# not protected
-Flash protect flags: 0x00000000
-Valid flags: 0x0000003f wp_gpio_asserted ro_at_boot ro_now all_now STUCK INCONSISTENT
-Writable flags: 0x00000001 ro_at_boot
-```
-
-Capturing a raw frame from the sensor will only work when software write
-protection is not enabled, so the test should check the following command works
-*before* write protection is enabled and then fails *after* write protection is
-enabled:
-
-```bash
-(dut) $ ectool --name=cros_fp fpframe raw
-
-# write protection disabled, exit code 0 and output will be raw bytes
-
-# write protection enabled, exit code 1 and output will be
-EC result 4 (ACCESS_DENIED)
-Failed to get FP sensor frame
-```
-
-## RMA Process
-
-As part of the RMA process, the `entropy` needs to be reset so that the new
-device owner has a new unique encryption key.
-
-The `bio_wash` tool is intended to support both the first time factory
-initialization and RMA, depending on the flag. When run without any arguments
-(`bio_wash`), it will forcibly reset the entropy.
-
-The RMA process should either run `bio_wash` without any arguments or re-flash
-the FPMCU firmware and then run `bio_wash --factory_init` to make sure that the
-entropy has been reset.
-
-## Miscellaneous Commands for Test Implementations
-
-### FPMCU Image Version
-
-```bash
-(dut) $ ectool --name=cros_fp version
-
-RO version: nocturne_fp_v2.2.64-58cf5974e
-RW version: nocturne_fp_v2.2.110-b936c0a3c
-Firmware copy: RW
-Build info: nocturne_fp_v2.2.110-b936c0a3c 2018-11-02 14:16:46 @swarm-cros-461
-Tool version: v2.0.2144-1524c164f 2019-09-09 06:50:36 @chromeos-ci-legacy-us-central2-d-x32-7-3ay8
-```
-
-### Capture Raw Images
-
-Put your finger on the sensor, then run:
-
-```bash
-(dut) $ ectool --name=cros_fp fpmode capture vendor
-```
-
-Wait for the capture to be finished, timeout after 10s:
-
-```bash
-(dut) $ ectool --name=cros_fp waitevent 5 10000
-MKBP event 5 data: 00 00 00 80
-```
-
-Remove the finger from the sensor, then start the retrieval of the frame from
-the MCU to the AP:
-
-```bash
-(dut) $ ectool --name=cros_fp fpframe raw > /tmp/fp.raw
-```
-
-To convert the images from FPC’s proprietary format to PNG, you will need to
-have `cros deploy`’d `libfputils-nocturne`, which will install the required
-utilities in `/opt/fpc`.
-
-<!-- mdformat off(b/139308852) -->
-*** note
-**NOTE**: As of 2019-05-21, the `libfputils` library only works for the FPC 1145
-sensor (in nocturne), not the FPC 1025 sensor (hatch).
-***
-<!-- mdformat on -->
-
-Convert the buffer in proprietary format into png:
-
-```bash
-(dut) $ /opt/fpc/fputils.py /tmp/fp.raw --png
-Extraction found 2 images
-Wrote /tmp/fp.0.png (14085 bytes)
-Wrote /tmp/fp.1.png (14025 bytes)
-```
-
-[Software Write Protect]: https://chromium.googlesource.com/chromiumos/platform/ec/+/HEAD/docs/write_protection.md#Software-Write-Protect
-[hardware write protect]: https://chromium.googlesource.com/chromiumos/platform/ec/+/HEAD/docs/write_protection.md#hw_wp
-[FPC1025: Module Test Specification]: http://go/cros-fingerprint-fpc1025-module-test-spec
-[FPC1145: Module Test Specification]: http://go/cros-fingerprint-fpc1145-module-test-spec
-[FPC In-Device Test Specification]: http://go/cros-fingerprint-fpc-indevice-test-spec
-[`fingerprint_mcu.py`]: https://chromium.googlesource.com/chromiumos/platform/factory/+/HEAD/py/test/pytests/fingerprint_mcu.py
-[Checkerboard Test]: https://chromium.googlesource.com/chromiumos/platform/factory/+/d23ebc7eeb074760e8a720e3acac4cfe4073b2ae/py/test/pytests/fingerprint_mcu.py#166
-[GetSensorIdErrors]: https://chromium.googlesource.com/chromiumos/platform/factory/+/d23ebc7eeb074760e8a720e3acac4cfe4073b2ae/py/test/utils/fpmcu_utils.py#73
-[GetSensorId]: https://chromium.googlesource.com/chromiumos/platform/factory/+/d23ebc7eeb074760e8a720e3acac4cfe4073b2ae/py/test/utils/fpmcu_utils.py#65
-[ProcessResetPixelImage]: https://chromium.googlesource.com/chromiumos/platform/factory/+/d23ebc7eeb074760e8a720e3acac4cfe4073b2ae/py/test/pytests/fingerprint_mcu.py#268
-[rubber_finger_present]: https://chromium.googlesource.com/chromiumos/platform/factory/+/d23ebc7eeb074760e8a720e3acac4cfe4073b2ae/py/test/pytests/fingerprint_mcu.py#330
-[Chrome OS Fingerprint Team]: http://go/cros-fingerprint-docs
-[Factory Fingerprint Sensor Testing for `nocturne`]: http://go/fingerprint-factory-testing-nocturne
-[`flash_fp_mcu`]: https://chromium.googlesource.com/chromiumos/platform/ec/+/HEAD/util/flash_fp_mcu
-[Fingerprint flashing documentation]: ./fingerprint.md#factory-rma-dev-updates
-[Chrome OS Config]: https://chromium.googlesource.com/chromiumos/platform2/+/HEAD/chromeos-config/README.md
-[updating Chrome OS Config]: ./fingerprint.md#update-chromeos-config
diff --git a/docs/fingerprint/fingerprint-firmware-testing-for-partners.md b/docs/fingerprint/fingerprint-firmware-testing-for-partners.md
deleted file mode 100644
index 3432bb0aac..0000000000
--- a/docs/fingerprint/fingerprint-firmware-testing-for-partners.md
+++ /dev/null
@@ -1,112 +0,0 @@
-# Fingerprint Firmware Testing Instructions for Partners
-
-This document is intended to help partners (sensor vendors, MCU vendors, etc)
-run the Chrome OS fingerprint team's firmware tests, as part of the AVL process.
-The document assumes that you‘re using Linux to do the development; preferably a
-recent version of Ubuntu or Debian. It may be possible to use a virtual machine,
-but that is not a configuration we test.
-
-[TOC]
-
-## Hardware Requirements
-
-You will need a Chromebook with the fingerprint sensor and fingerprint MCU
-(FPMCU), and a [servo debugger].
-
-### Chromebook with fingerprint sensor
-
-The Chromebook needs to be in [developer mode] and running a test image so that
-the test can ssh into it. The fingerprint firmware tests will run a series of
-bash commands, including flashing the FPMCU firmware and rebooting the
-Chromebook. You do not need [CCD] because servo will handle the firmware write
-protection for you.
-
-### Servo
-
-Servo is a general purpose debug board used in many automated tests in Chromium
-OS. Among other things, servo enables the tests to toggle hardware write
-protect.
-
-While there are multiple versions of servo, for firmware tests we strongly
-recommend [Servo V4] as that's the simplest and most often used in autotests.
-This document will assume you are using Servo V4.
-
-### Hardware Setup
-
-* Connect the "HOST" side of Servo V4 to your host machine (which should have
- a Chromium OS chroot).
-* Connect the other side of Servo V4 to a USB port on the Chromebook with
- fingerprint sensor.
-* Connect the "DUT POWER" side of Servo V4 to power supply.
-* Make sure the USB cable from the host machine to Servo V4 is in data
- transfer mode (i.e. if there's an LED, it should be yellow instead of
- green).
-* Make sure the you can ssh into the Chromebook from the chroot on the host
- machine.
-
-## Software Setup
-
-### Get the Chromium OS source code.
-
-* First, make sure you [have the prerequisites].
-* Then [get the source].
-
-### Build the autotest codebase
-
-```bash
-# from a terminal on your machine
-(outside chroot) $ cd ~/chromiumos/src
-
-# enter the chroot (the flag is important)
-(outside chroot) $ cros_sdk --no-ns-pid
-
-# build autotest for the board to be tested
-(chroot) $ emerge-<BOARD> autotest
-```
-
-### Start servod
-
-```bash
-(chroot) $ sudo servod --board=<BOARD>
-```
-
-At this point the servod daemon should be running and listening to port 9999 by
-default. If it isn't, check the hardware connection.
-
-## Run a Single Fingerprint Firmware Test
-
-Use another terminal and enter the chroot like before:
-
-```bash
-(outside chroot) $ cd ~/chromiumos/src
-(outside chroot) $ cros_sdk --no-ns-pid
-```
-
-To run a single test, use this command in your chroot:
-
-```bash
-test_that --board=<BOARD> <IP> <test name>
-```
-
-For example:
-
-```bash
-test_that --board=nocturne <IP> firmware_Fingerprint.ReadFlash
-```
-
-## Run the Entire Fingerprint Firmware Test Suite
-
-To run the entire suite, use this command in your chroot:
-
-```bash
-test_that --board=<BOARD> <IP> suite:fingerprint
-```
-
-<!-- Links -->
-
-[servo debugger]: https://chromium.googlesource.com/chromiumos/third_party/hdctools/+/HEAD/docs/servo.md
-[developer mode]: https://chromium.googlesource.com/chromiumos/docs/+/HEAD/developer_mode.md
-[CCD]: https://chromium.googlesource.com/chromiumos/platform/ec/+/refs/heads/cr50_stab/docs/case_closed_debugging.md
-[Servo V4]: https://chromium.googlesource.com/chromiumos/third_party/hdctools/+/HEAD/docs/servo_v4.md
-[have the prerequisites]: https://chromium.googlesource.com/chromiumos/docs/+/HEAD/developer_guide.md#Prerequisites
-[get the source]: https://chromium.googlesource.com/chromiumos/docs/+/HEAD/developer_guide.md#get-the-source
diff --git a/docs/fingerprint/fingerprint-tpm-seed.md b/docs/fingerprint/fingerprint-tpm-seed.md
deleted file mode 100644
index 904fb7243a..0000000000
--- a/docs/fingerprint/fingerprint-tpm-seed.md
+++ /dev/null
@@ -1,324 +0,0 @@
-# TPM Seed for Fingerprint MCU
-
-Authors: pmalani@google.com, norvez@google.com
-
-Reviewers: semenzato@google.com, apronin@google.com, mnissler@google.com and
-others
-
-Last Updated: 2018-11-01
-
-[TOC]
-
-## Objective
-
-Increase security for Fingerprint (FP) templates by using a TPM-sourced seed in
-addition to internal FPMCU entropy while encrypting FP templates. The
-TPM-sourced seed will be derived from the system key which is loaded from the
-TPM during boot in mount-encrypted.
-
-## Background
-
-Fingerprint authorization in Chrome OS, relies on encrypted FP templates which
-are stored in each user’s mount directory. These templates are created and
-encrypted by the FPMCU during FP enrollment, before being sent back to the AP
-(Application Processor). When the user logs in, these templates are sent to the
-FPMCU where they get decrypted and loaded.
-
-The encryption is performed in the FPMCU using entropy which is internal to the
-MCU and never leaves the MCU. That way, even if the templates are somehow
-obtained by and attacker from the user mount directory, they cannot be
-decrypted, since the attacker will not have access to the MCU entropy. This
-entropy gets reset on every powerwash/recovery.
-
-The complete design doc is [Fingerprint Authentication on Chrome OS].
-
-## Requirements and Scale
-
-The solution proposed should exhibit the following attributes:
-
-* Strengthens security of FP templates.
-* Does not compromise the security of other sub-systems.
-* Works fast and doesn’t affect time to boot, or reduce boot-time stability.
-
-## Design Ideas
-
-In addition to FPMCU entropy, we include a TPM-sourced seed (derived from the
-system key) while performing template encryption. The TPM system key gets
-regenerated during powerwash/recovery, so in the event that the FP templates are
-accessed due to a runtime exploit, a power-wash / recovery from the user will
-ensure:
-
-* The raw templates cannot be decrypted, since the TPM-seed would have been
- lost irrevocably.
-* Since a new TPM-seed is generated (since a new system key is created), old
- templates can’t be re-used, even if the attacker could somehow gain access
- to the FP MCU entropy.
-
-The overall design consists of two components:
-
-* Generating a TPM-seed and sending it to the Biometric sensor managers.
-* The Bio sensor managers sending the seed to the FPMCU and programming it
- into the encryption / decryption operations of FP templates.
-
-### TPM seed generation {#seed-generation}
-
-![TPM Seed Diagram]
-
-The TPM seed generation would proceed as follows:
-
-1. During mount-encrypted execution, after the `System_key` is loaded, the
- TPM-backed system key will be HMAC-ed with a simple salt (the string
- `biod`):
-
- ```
- TPM_Seed = HMAC_SHA256(System_key, "biod")
- ```
-
-2. The resulting 256-bit seed (called `TPM_Seed`) will be maintained in a
- `brillo::SecureBlob`.
-
-3. The `TPM_seed` will be saved into a tmpfs file
- (`/run/biod_crypto_init/seed`) for consumption by `bio_crypto_init`. This
- file's ownership will be set up such that only user/group `biod` can access
- it.
-
-4. `bio_crypto_init` (the binary which sends the seed to the FPMCU) will be
- spawned after mount-encrypted completes. This is ensured by setting the
- `bio_crypto_init` upstart rules to depend on `starting boot-services`
-
-5. On the `bio_crypto_init` side, the `TPM_seed` will be retrieved from the
- tmpfs file and forwarded to the FP MCU via the various BiometricManagers.
- Immediately after reading from the tmpfs file, `bio_crypto_init` will nuke
- (write all 0’s and then delete) the tmpfs file.
-
-6. The upstart rules of biod will be modified such that it will start after
- `bio_crypto_init` stops (this modification can be made in the `.conf` file
- of biod)
-
-#### IPC Mechanism {#ipc}
-
-(For a discussion of various alternatives, please see the
-[Alternatives Considered] section)
-
-The IPC mechanism selected should have the following features:
-
-* Allow to quickly pass the `TPM_seed` between mount-encrypted and
- `bio_crypto_init`.
-* Minimize the presence of extra/asynchronously deleted copies of the
- `TPM_seed` buffer in kernel and memory. This is crucial to minimize the risk
- of access to this seed.
-
-The currently proposed method of passing the `TPM_seed` is to use a **file in
-tmpfs**. The sequence would be as follows:
-
-* mount-encrypted will write the `TPM_Seed` to a file in `/run`
- (`/run/bio_crypto_init/seed`). `/run` is a tmpfs created by the OS for use
- by various system services.
-* `bio_crypto_init` will read the `TPM_Seed` from the known tmpfs file.
-* As soon as `bio_crypto_init` reads the `TPM_Seed`, it will first overwrite
- (`/run/biod_crypto_init/seed`) with all 0s, and immediately after will
- delete `/run/biod_crypto_init/seed`.
-* `bio_crypto_init` can then instantiate its BiometricManager classes and send
- the data to the FP MCU. This way, even if the sending of data fails, there
- will not be any stray copy of the `TPM_seed` in a process’s memory, or in
- tmpfs.
-
-##### Advantages
-
-* No/minimal buffering of copies of `TPM_Seed` in kernel.
-* No need to create and pass FDs between mount-encrypted and
- `bio_crypto_init`.
-
-##### Disadvantages
-
-* If `bio_crypto_init` crashes / fails to start, the tmpfs file remains in the
- system, i.e cleanup of tmpfs is reliant on `bio_crypto_init`.
-
-### Programming TPM_Seed into MCU
-
-#### Entropy addition v/s programming TPM Seed
-
-When a device boots up for the first time after going through
-recovery/powerwash, biod will force an "Add Entropy" step. This involves:
-
-* rebooting the FP MCU to RO
-* Performing an entropy addition step
-* Rebooting the FP MCU to RW
-* Verifying that the entropy addition has taken place (by checking the block
- ID of the rollback info on the MCU).
-
-Unfortunately, since the `TPM_Seed` will be stored in MCU RAM, the reboot of the
-FPMCU will lead to the `TPM_Seed` being lost until the next boot. In the absence
-of a `TPM_Seed`, all FPMCU operations will fail (until the next boot). There is
-no opportunity to reprogram the `TPM_Seed`, because that must take place during
-mount-encrypted, which must necessarily run before `biod` starts.
-
-There are two proposals to work around this issue. The one eventually selected
-has been included here, and the other alternative has been placed in the
-[Alternatives Considered] section.
-
-##### Make bio_crypto_init solely set the TPM_Seed (don't perform entropy_add)
-
-In this method, `bio_crypto_init` will not perform any reboot on the MCU, and
-solely program the `TPM_Seed`. This would mean that if a device was to boot for
-a first time without having done any previous powerwash/recovery, the first boot
-would not have FP functionality. FP functionality would be regained on all
-subsequent boot (since the entropy would have been added/initialized by then).
-
-The downside of this approach is a poor user experience.
-
-The benefit is a simple implementation of the `bio_crypto_init` tool, which will
-consequently also take less time to execute (booting to RO/RW are time consuming
-operations).
-
-In practice all devices leaving the factory floor would have `bio_wash
---factory_init` done on them during finalisation to initialise the entropy, and
-so this shouldn't affect a large majority of end users.
-
-### Signaling biod to start
-
-In order to avoid races which might occur because both `bio_crypto_init` and
-`biod` will try to access the `BiometricManagers`' hardware. We need to ensure
-that `biod` only starts after `bio_crypto_init` ends.
-
-To accomplish this, `biod.conf` will be modified to include a dependency on
-`bio_crypto_init` to start the daemon. So, the relevant portion of `biod.conf`
-will now be:
-
-```
-start on started system-services and started uinput and stopped bio_crypto_init
-```
-
-### Formula to calculate IKM used for encryption in MCU
-
-In the FPMCU we will use the concatenation of `TPM_Seed` and [`SBP_Src_Key`] as
-Input Key Material (IKM) to derive an encryption key. Combined with a random
-salt, the pseudo random key (PRK) would be derived as:
-
-```
-PRK = HMAC_SHA256(Random_Salt, SBP_Src_Key || TPM_Seed)
-```
-
-## Alternatives Considered {#alt-considered}
-
-A few alternatives are being considered for the IPC Mechanism
-
-#### pipe/socketpair
-
-##### Disadvantages
-
-* The data written to pipes is buffered in internal kernel buffers till it is
- read out from the other end of the pipe/socketpair. In the case of a
- `bio_crypto_init` crashing, this will leave a copy in the internal kernel
- buffers. Question: How long before those internal buffers get cleared in the
- case of the pipe not being read from?
-
-#### Anonymous file (memfd_create) / Anonymous mmap
-
-##### Disadvantages
-
-* Question: When all references to the anonymous file are dropped, are the
- contents of the anonymous file re-allocated, overwritten, or is the
- corresponding inode simply destroyed (and the data blocks still stick around
- and are reallocated lazily ?)
-
-There was also another alternative considered for the sequence of programming
-the TPM seed and initializing the FPMCU: make `bio_crypto_init` add entropy and
-then set TPM.
-
-## Security Considerations
-
-### Security boundaries
-
-* A new minijailed process (`bio_crypto_init`) is run when `starting
- boot-services` is signaled.
-* An IPC takes place between mount-encrypted and `bio_crypto_init` via a tmpfs
- file. The reading and deletion of the tmpfs file is detailed in the
- [IPC Mechanism] section.
-
-### Privileges
-
-* `bio_crypto_init` runs minijail-ed and runs with user/group `biod`. Only the
- files required for its functioning (i.e., the tmpfs file `/run/`, the
- devnode to access the FPMCU, log directory inside
- `/var/log/bio_crypto_init`) are mounted and visible inside the sandbox. See
- the [minijail0 arguments] for a full explanation.
-
-### Untrusted input
-
-* The only input is the `System_key` which is retrieved from the TPM anyway
- during mount-encrypted execution. Thus, no additional or new input is being
- fed to the feature.
-* Additionally, the derived TPM-seed is saved in a tmpfs file which has a
- user/group ownership as `biod` so only users `root` or `biod` can access the
- file. Since `bio_crypto_init` runs only during `starting boot-services` and
- the process along with the conf file ensures that the file is deleted after
- execution, there is no additional threat of the `/tmp` file being corrupted.
-
-### Sensitive data
-
-* The feature involves the storage of a `TPM_Seed` derived from the
- `System_key` from TPM, in a file on tmpfs (the file is zeroed and deleted
- once read by `bio_crypto_init`).
-
-### Attack surface
-
-* In the event of the contents of the tmp file being read, the `TPM_Seed`
- would not be of much use to the attacker, since the use of `HMAC_SHA256`
- means the attacker would still not have access to the system key (brute
- force trial of HMAC 256 would be required to guess the system salt required
- to produce the TPM-seed).
-* In the unlikely event of the contents of the tmp file being modified before
- they are programmed into the FPMCU, FP unlock would fail (since the
- encrypted templates would not longer be decrypted correctly, since the FPMCU
- encryption key would have changed). The FP templates encryption key is a
- combination of both the `TPM_seed` as well as the internal `SBP_Src_Key`
- combined with a random salt, and since only the encrypted templates are
- stored on the rootfs, the templates would simply be rendered useless. A
- powerwash/recovery can help restore functionality of FP unlock, but new
- templates would have to be registered.
-* This code should not be accessible to remote attackers.
-
-### Implementation robustness
-
-* `bio_crypto_init` uses two processes. A child process is spawned by
- `bio_crypto_init` and the FPMCU programming is done on the child process.
- The parent process waits for the child process to complete, or kills the
- process if it exceeds a timeout limit. This ensures that the process doesn't
- hang indefinitely.
-* The feature uses tmpfs (`/run/bio_crypto_init/seed`) as an IPC mechanism to
- transfer the `TPM_Seed` between mount-encrypted and `bio_crypto_init`.
- Please see the [Alternatives Considered] and [Design Ideas] section
- regarding rationale behind choosing tmpfs vis a vis socketpair/pipe.
-
-### Cryptography
-
-* `HMAC_SHA256` is used to derived `TPM_Seed` from the `System_key` as
- described in section [TPM seed generation].
-
-* `HMAC_SHA256` is also used to derive the FPMCU’s encryption key. This is the
- same as it was earlier; the only change is that source key has been updated
- to also include the `TPM_Seed`.
-
-## Privacy Considerations
-
-This implementation should not have any adverse implications on Privacy (over
-and above existing functionality on Chrome OS). This provides security hardening
-for the fingerprint templates to prevent their retrieval and mis-use.
-
-[Fingerprint Authentication on Chrome OS]: ../fingerprint/fingerprint-authentication-design-doc.md
-[`SBP_Src_Key`]: ../fingerprint/fingerprint-authentication-design-doc.md#sbp-secret-generation
-[IPC Mechanism]: #ipc
-[minijail0 arguments]: https://source.chromium.org/chromiumos/chromiumos/codesearch/+/main:src/platform2/biod/init/bio_crypto_init.conf;l=36;drc=1fcefaa166e868069ad1b81091333ff75e0657f6
-[Design Ideas]: #design-ideas
-[TPM seed generation]: #seed-generation
-[Alternatives Considered]: #alt-considered
-
-<!-- Images -->
-
-<!-- If you make changes to the docs below make sure to regenerate the PNGs by
- appending "export/png" to the Google Drive link. -->
-
-<!-- https://docs.google.com/drawings/d/1d0ocdnEjsO26c3usP1FwgTZ7VwEr-4ydnC0WMhOnbLY -->
-
-[TPM Seed Diagram]: ../images/cros_fingerprint_tpm_seed.png
diff --git a/docs/fingerprint/fingerprint.md b/docs/fingerprint/fingerprint.md
deleted file mode 100644
index 39785f5afb..0000000000
--- a/docs/fingerprint/fingerprint.md
+++ /dev/null
@@ -1,590 +0,0 @@
-# Fingerprint Firmware (FPMCU)
-
-[TOC]
-
-<!-- mdformat off(b/139308852) -->
-*** note
-NOTE: The build commands assume you are in the `~/trunk/src/platform/ec`
-directory inside the chroot.
-***
-<!-- mdformat on -->
-
-<!-- mdformat off(b/139308852) -->
-*** note
-WARNING: When switching branches in the EC codebase, you probably want to nuke
-the `build` directory or at least the board you're working on: `rm -rf
-build/<board>` or `make clobber` to prevent compilation errors.
-***
-<!-- mdformat on -->
-
-## Software
-
-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.
-
-## Hardware {#hardware}
-
-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`<br>(aka `nocturne_fp`, `nami_fp`) | [Icetower v0.2] <br>(Previously Dragontalon) | [Nucleo H743ZI2]
-[STM32F412] \(Cortex-M4) | [FPC 1025] | `bloonchipper`<br>(aka `hatch_fp`) | [Dragonclaw v0.2] | [Nucleo F412ZG]
-
-### Sensor Template Sizes
-
-Sensor | Fingerprint Template Size
----------- | --------------------------------
-[FPC 1145] | [~48 KB][FPC 1145 Template Size]
-[FPC 1025] | [~5 KB][FPC 1025 Template Size]
-
-### Determining Hardware {#chromeos-config-fingerprint}
-
-If you have access to a shell on your Chromebook, you can use [Chrome OS Config]
-to determine the FPMCU that it contains:
-
-```bash
-(dut) $ cros_config /fingerprint board
-```
-
-Alternatively, if you have a Chromium OS build, you can use [Chrome OS Config]
-in the chroot to determine the FPMCU:
-
-```bash
-(chroot) $ cros_config_host -c /build/<BOARD>/usr/share/chromeos-config/yaml/config.yaml -m <MODEL> get /fingerprint board
-```
-
-<!-- mdformat off(b/139308852) -->
-*** note
-**NOTE**: If you get an empty response when running these commands, the
-[Chrome OS Config] properties for fingerprint may not have been set up yet. See
-the [section on updating Chrome OS Config](#update-chromeos-config).
-***
-<!-- mdformat on -->
-
-## Building FPMCU Firmware Locally
-
-### See `Makefile` target options
-
-```bash
-(chroot) ~/trunk/src/platform/ec $ make help
-```
-
-### Build
-
-Replace `<BOARD_NAME>` in the command below with the fingerprint MCU that you
-are targeting (e.g., `nocturne_fp`, `dartmonkey`, `bloonchipper`).
-
-```bash
-(chroot) ~/trunk/src/platform/ec $ make BOARD=<BOARD_NAME> -j
-```
-
-### Verbose Build output
-
-Use `V=1` to see the complete compiler output (all flags).
-
-```bash
-(chroot) ~/trunk/src/platform/ec $ make V=1 BOARD=nocturne_fp -j
-```
-
-## Building all EC firmware (before "repo upload")
-
-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.
-
-<!-- mdformat off(b/139308852) -->
-*** note
-NOTE: If you forget to do this, do not worry. `repo upload` will warn you and
-prevent you from uploading.
-***
-<!-- mdformat on -->
-
-```bash
-(chroot) ~/trunk/src/platform/ec $ make buildall -j
-```
-
-## Building and running unit tests
-
-See the [Unit Tests] documentation for details on how to [run the unit tests].
-
-## Build ectool
-
-```bash
-(chroot) ~/trunk/src/platform/ec $ make BOARD=nocturne_fp utils-host -j
-```
-
-## Build and run the `host_command` fuzz test
-
-```bash
-(chroot) ~/trunk/src/platform/ec $ make run-host_command_fuzz
-```
-
-## Logs
-
-[`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][cros_ec_debugfs]. [`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.
-
-### Starting timberslide
-
-```bash
-(dut)$ start timberslide LOG_PATH=/sys/kernel/debug/cros_fp/console_log
-```
-
-### Stopping timberslide
-
-```bash
-(dut)$ stop timberslide LOG_PATH=/sys/kernel/debug/cros_fp/console_log
-```
-
-### Manually running timberslide
-
-```bash
-(dut)$ timberslide --device_log=/sys/kernel/debug/cros_fp/console_log
-```
-
-### Reading logs from kernel
-
-If [`timberslide`] is not running you can just `cat` the logs directly from the
-kernel:
-
-```bash
-(dut)$ cat /sys/kernel/debug/cros_fp/console_log
-```
-
-## Production Updates (Auto-Update)
-
-### `fp_updater.sh` and `bio_fw_updater`
-
-<!-- mdformat off(b/139308852) -->
-*** note
-**NOTE**: The auto-update process requires a working version of the firmware
-running on the FPMCU. See [Fingerprint Factory Requirements] for details on
-flashing in the factory.
-***
-<!-- mdformat on -->
-
-[`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]).
-
-## Factory / RMA / Development Updates {#factory-rma-dev-updates}
-
-### `flash_fp_mcu`
-
-<!-- mdformat off(b/139308852) -->
-*** note
-**NOTE**: This tool is really just for us to use during development or during
-the RMA flow (must go through finalization again in that case). We never update
-RO in the field (can’t by design). See [Fingerprint Factory Requirements] for
-details on flashing in the factory.
-***
-<!-- mdformat on -->
-
-[`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].
-
-## Keys
-
-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.
-
-### Generate Key
-
-For testing, you can generate a new key by using the following openssl command:
-
-```bash
-openssl genrsa -3 -out board/$BOARD/dev_key.pem 3072
-```
-
-### Resources
-
-* https://sites.google.com/a/google.com/chromeos/resources/engineering/releng/signer-documentation
-* https://sites.google.com/a/google.com/chromeos/paygen---payload
-* https://b.corp.google.com/issues/77882970
-
-## Signing
-
-[`futility`] is used to sign EC firmware. There’s a wrapper script around it for
-signing called [`sign_official_build.sh`].
-
-### Key ID
-
-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,][vboot_key_id] so it lets you
-[uniquely identify the key being used][vb2_public_key].
-
-If you have the key (e.g., in PEM format), you can compute the `ID` with the
-`futility show` command:
-
-```bash
-(chroot) $ futility show ./path/to/key.pem
-```
-
-#### Example
-
-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:
-
-```bash
-(chroot)$ futility show board/hatch_fp/dev_key.pem
-```
-
-```
-Private Key file: board/hatch_fp/dev_key.pem
- Key length: 3072
- Key sha1sum: 61382804da86b4156d666cc9a976088f8b647d44
-```
-
-```bash
-(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.
-```
-
-### Showing Key ID (fingerprint) for running FW
-
-[Asked on chromeos-chatty-firmware][chatty-firmware-q] 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.
-
-## Power
-
-See [Measuring Power] for instructions on how to measure power with the
-fingerprint development boards.
-
-### Dragonclaw v0.2
-
-```bash
-(chroot) $ dut-control -t 60 pp3300_dx_mcu_mv pp3300_dx_fp_mv pp1800_dx_fp_mv pp3300_dx_mcu_mw pp3300_dx_fp_mw pp1800_dx_fp_mw
-```
-
-**Firmware Version**:
-`bloonchipper_v2.0.4277-9f652bb3-RO_v2.0.7314-3dfc5ff6-RW.bin`
-
-#### MCU is idle
-
-```
-(chroot) $ dut-control fpmcu_slp_alt:off
-```
-
-```
-@@ NAME COUNT AVERAGE STDDEV MAX MIN
-@@ sample_msecs 113 533.56 40.91 658.52 447.06
-@@ pp1800_dx_fp_mv 113 1800.00 0.00 1800.00 1800.00
-@@ pp1800_dx_fp_mw 113 0.00 0.00 0.00 0.00
-@@ pp3300_dx_fp_mv 113 3280.00 0.00 3280.00 3280.00
-@@ pp3300_dx_fp_mw 113 0.01 0.05 0.26 0.00
-@@ pp3300_dx_mcu_mv 113 3280.00 0.00 3280.00 3280.00
-@@ pp3300_dx_mcu_mw 113 24.67 0.00 24.67 24.67
-```
-
-#### MCU in low power mode (suspend)
-
-```
-(chroot) $ dut-control fpmcu_slp_alt:on
-```
-
-```
-@@ NAME COUNT AVERAGE STDDEV MAX MIN
-@@ sample_msecs 115 526.56 36.79 607.60 426.58
-@@ pp1800_dx_fp_mv 115 1800.00 0.00 1800.00 1800.00
-@@ pp1800_dx_fp_mw 115 0.00 0.00 0.00 0.00
-@@ pp3300_dx_fp_mv 115 3287.30 2.25 3288.00 3280.00
-@@ pp3300_dx_fp_mw 115 0.00 0.02 0.26 0.00
-@@ pp3300_dx_mcu_mv 115 3280.97 2.62 3288.00 3280.00
-@@ pp3300_dx_mcu_mw 115 4.02 0.64 10.76 3.94
-```
-
-### Icetower v0.1
-
-<!-- mdformat off(b/139308852) -->
-*** note
-**NOTE**: Icetower v0.1 has a hardware bug in the INA connections, so you cannot
-measure the 1.8V fingerprint sensor rail. See http://b/178098140.
-
-Additionally, before https://crrev.com/c/2689101, the sleep GPIOs were not
-configured correctly, so the change needs to be cherry-picked in order to
-measure releases before that point.
-***
-<!-- mdformat on -->
-
-```bash
-(chroot) $ dut-control -t 60 pp3300_dx_mcu_mv pp3300_dx_fp_mv pp3300_dx_mcu_mw pp3300_dx_fp_mw
-```
-
-**Firmware Version**:
-`dartmonkey_v2.0.2887-311310808-RO_v2.0.7304-441100b93-RW.bin`
-
-#### MCU is idle
-
-```
-(chroot) $ dut-control fpmcu_slp_alt:off
-```
-
-```
-@@ NAME COUNT AVERAGE STDDEV MAX MIN
-@@ sample_msecs 178 337.13 20.91 404.32 289.82
-@@ pp3300_dx_fp_mv 178 3256.00 0.00 3256.00 3256.00
-@@ pp3300_dx_fp_mw 178 0.00 0.00 0.00 0.00
-@@ pp3300_dx_mcu_mv 178 3248.00 0.00 3248.00 3248.00
-@@ pp3300_dx_mcu_mw 178 45.17 0.09 45.21 44.95
-```
-
-#### MCU in low power mode (suspend)
-
-```
-(chroot) $ dut-control fpmcu_slp_alt:on
-```
-
-```
-@@ NAME COUNT AVERAGE STDDEV MAX MIN
-@@ sample_msecs 174 345.60 31.93 457.62 283.00
-@@ pp3300_dx_fp_mv 174 3264.00 0.00 3264.00 3264.00
-@@ pp3300_dx_fp_mw 174 0.00 0.00 0.00 0.00
-@@ pp3300_dx_mcu_mv 174 3260.69 3.94 3264.00 3256.00
-@@ pp3300_dx_mcu_mw 174 5.47 0.10 5.48 4.17
-```
-
-## Chrome OS Build (portage / ebuild)
-
-In order to use the fingerprint sensor with a given [Chrome OS board], a few
-things need to be configured for the [Chrome OS board].
-
-### Enable biod USE flag
-
-The biod [`USE` flag] needs to be enabled for the [Chrome OS board]. This `USE`
-flag
-[determines whether the `biod` daemon is built and installed][biod chromium-os].
-
-To enable the `USE` flag, update the `make.defaults` for the [Chrome OS board].
-See the [`make.defaults` for the Hatch board][hatch make.defaults] as an
-example.
-
-#### Verifying biod is installed in the rootfs
-
-After enabling the `biod` [`USE` flag] and building the `biod` package for your
-target [Chrome OS board], the `biod` binary should be in the build directory:
-
-```bash
-(chroot) $ emerge-<BOARD> biod
-```
-
-```bash
-(chroot) $ ls /build/<BOARD>/usr/bin/biod
-/build/<BOARD>/usr/bin/biod
-```
-
-### Update FPMCU_FIRMWARE
-
-`FPMCU_FIRMWARE` should be set to the set of fingerprint firmware that should be
-built and installed for the [Chrome OS board].
-
-`FPMCU_FIRMWARE` is a [`USE_EXPAND` variable][`USE` flag],
-[defined in the base `make.defaults`][FPMCU_FIRMWARE make.defaults].
-
-The `biod` ebuild uses the resulting [`USE` flags] to
-[determine which FPMCU release firmware to build][biod release firmware] and the
-[`chromeos-firmware-fpmcu` ebuild] uses the resulting [`USE` flags] to
-[determine which firmware to install][firmware ebuild] 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](#hardware).
-
-See the [Hatch baseboard `make.defaults`] for an example.
-
-#### Verifying FPMCU firmware is installed in the rootfs
-
-Once you have added the `FPMCU_FIRMWARE` flag and rebuilt the
-[`chromeos-firmware-fpmcu` ebuild], the firmware will show up in the the chroot:
-
-<!-- mdformat off(b/139308852) -->
-*** note
-**NOTE**: This requires access to the [internal manifest].
-***
-<!-- mdformat on -->
-
-```bash
-(chroot) $ emerge-<BOARD> chromeos-firmware-fpmcu
-```
-
-```bash
-(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.
-
-### Update Chrome OS Config {#update-chromeos-config}
-
-With "unibuild", the same OS image (build) for a given [Chrome OS 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 [Chrome OS board] is thus
-done at runtime, using [Chrome OS Config].
-
-The `fingerprint` config needs to be in the `model.yaml` for the given
-[Chrome OS board]. The [Chrome OS 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][hatch model.yaml] as an example.
-
-Instead of crafting the `model.yaml` by hand, newer boards are moving to the
-[Chrome OS 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`](#chromeos-config-fingerprint). The Chrome OS Config
-documentation has a [section on testing properties] that describes this in more
-detail.
-
-### SKUs
-
-The fingerprint sensor may only be included on certain SKUs for a given device.
-The fingerprint code uses [Chrome OS Config] to determine whether a device has a
-fingerprint sensor or not. For each SKU, there is an associated
-[fingerprint config][Chrome OS Config fingerprint]. [Chrome OS Config]
-determines the [SKU information][Chrome OS Config SKU] (and thus the
-[fingerprint config][Chrome OS Config fingerprint]) from [CBI Info]. The SKU for
-a given device can be found by viewing `chrome://system/#platform_identity_sku`.
-
-[`common/fpsensor`]: https://chromium.googlesource.com/chromiumos/platform/ec/+/HEAD/common/fpsensor/
-[`driver/fingerprint`]: https://chromium.googlesource.com/chromiumos/platform/ec/+/HEAD/driver/fingerprint
-[`nocturne_fp`]: https://chromium.googlesource.com/chromiumos/platform/ec/+/HEAD/board/nocturne_fp/
-[`nami_fp`]: https://chromium.googlesource.com/chromiumos/platform/ec/+/HEAD/board/nami_fp/
-[`hatch_fp`]: https://chromium.googlesource.com/chromiumos/platform/ec/+/HEAD/board/hatch_fp/
-[`bloonchipper`]: https://chromium.googlesource.com/chromiumos/platform/ec/+/HEAD/board/bloonchipper/
-[`dartmonkey`]: https://chromium.googlesource.com/chromiumos/platform/ec/+/HEAD/board/dartmonkey/
-[hardware write protection]: ../write_protection.md
-[`flash_fp_mcu`]: https://chromium.googlesource.com/chromiumos/platform/ec/+/HEAD/util/flash_fp_mcu
-[`stm32mon`]: https://chromium.googlesource.com/chromiumos/platform/ec/+/e1f3f89e7ea7945adddd0c2e6838f5e59856cff2/util/stm32mon.c#14
-[`futility`]: https://chromium.googlesource.com/chromiumos/platform/vboot_reference/+/HEAD/futility/
-[`sign_official_build.sh`]: https://chromium.googlesource.com/chromiumos/platform/vboot_reference/+/HEAD/scripts/image_signing/sign_official_build.sh
-[vboot_key_id]: https://chromium.googlesource.com/chromiumos/platform/vboot_reference/+/e7db36856ce418552637d1981c173d22dfe5bf39/firmware/2lib/include/2id.h#5
-[vb2_public_key]: https://chromium.googlesource.com/chromiumos/platform/vboot_reference/+/e7db36856ce418552637d1981c173d22dfe5bf39/firmware/2lib/include/2rsa.h#14
-[chatty-firmware-q]: https://groups.google.com/a/google.com/d/msg/chromeos-chatty-firmware/ZSg423wsFPg/26UbdGwjFQAJ
-[`fp_updater.sh`]: http://go/cros-fp-updater-nocturne-source
-[`bio_fw_updater`]: https://chromium.googlesource.com/chromiumos/platform2/+/HEAD/biod/tools
-[`flashrom`]: https://chromium.googlesource.com/chromiumos/third_party/flashrom/
-[STM32F412]: https://www.st.com/resource/en/reference_manual/dm00180369.pdf
-[STM32H743]: https://www.st.com/resource/en/reference_manual/dm00314099.pdf
-[`board/nocturne_fp/dev_key.pem`]: https://chromium.googlesource.com/chromiumos/platform/ec/+/HEAD/board/nocturne_fp/dev_key.pem
-[`timberslide`]: https://chromium.googlesource.com/chromiumos/platform2/+/HEAD/timberslide
-[cros_ec_debugfs]: https://chromium.googlesource.com/chromiumos/third_party/kernel/+/9db44685934a2e4bc9180ea2de87a6c429672395/drivers/platform/chrome/cros_ec_debugfs.c
-[Fingerprint Factory Requirements]: ./fingerprint-factory-requirements.md
-[Chromium OS test image]: https://chromium.googlesource.com/chromiumos/platform/factory/+/HEAD/README.md#building-test-image
-[Chrome OS Config]: https://chromium.googlesource.com/chromiumos/platform2/+/HEAD/chromeos-config/README.md
-[Chrome OS Config fingerprint]: https://chromium.googlesource.com/chromiumos/platform2/+/HEAD/chromeos-config/README.md#fingerprint
-[section on testing properties]: https://chromium.googlesource.com/chromiumos/platform2/+/HEAD/chromeos-config/README.md#adding-and-testing-new-properties
-[Chrome OS board]: https://chromium.googlesource.com/chromiumos/docs/+/HEAD/developer_guide.md#Select-a-board
-[biod chromium-os]: https://chromium.googlesource.com/chromiumos/overlays/chromiumos-overlay/+/4ea72b588af3394cb9fd1c330dcf726472183dfd/virtual/target-chromium-os/target-chromium-os-1.ebuild#154
-[hatch make.defaults]: https://chromium.googlesource.com/chromiumos/overlays/board-overlays/+/2f075f0e7ce09d3eb460f3c529da463a6201276c/overlay-hatch/profiles/base/make.defaults#22
-[Hatch baseboard `make.defaults`]: https://chrome-internal.googlesource.com/chromeos/overlays/baseboard-hatch-private/+/HEAD/profiles/base/make.defaults#17
-[hatch model.yaml]: https://chrome-internal.googlesource.com/chromeos/overlays/overlay-hatch-private/+/HEAD/chromeos-base/chromeos-config-bsp-hatch-private/files/model.yaml
-[`ec_extras` attribute]: https://chromium.googlesource.com/chromiumos/platform2/+/HEAD/chromeos-config/README.md#build_targets
-[FPMCU_FIRMWARE make.defaults]: https://chromium.googlesource.com/chromiumos/overlays/chromiumos-overlay/+/4ea72b588af3394cb9fd1c330dcf726472183dfd/profiles/base/make.defaults#157
-[`USE` flag]: https://devmanual.gentoo.org/general-concepts/use-flags/index.html
-[`USE` flags]: https://devmanual.gentoo.org/general-concepts/use-flags/index.html
-[biod release firmware]: https://chromium.googlesource.com/chromiumos/overlays/chromiumos-overlay/+/4ea72b588af3394cb9fd1c330dcf726472183dfd/chromeos-base/biod/biod-9999.ebuild#49
-[`chromeos-firmware-fpmcu` ebuild]: https://chrome-internal.googlesource.com/chromeos/overlays/chromeos-overlay/+/HEAD/chromeos-base/chromeos-firmware-fpmcu/chromeos-firmware-fpmcu-9999.ebuild
-[firmware ebuild]: https://chrome-internal.googlesource.com/chromeos/overlays/chromeos-overlay/+/HEAD/chromeos-base/chromeos-firmware-fpmcu/chromeos-firmware-fpmcu-9999.ebuild#40
-[`chromeos-fpmcu-release*` ebuilds]: https://chromium.googlesource.com/chromiumos/overlays/chromiumos-overlay/+/HEAD/sys-firmware
-[internal manifest]: https://chromium.googlesource.com/chromiumos/docs/+/HEAD/developer_guide.md#get-the-source-code
-[Unit Tests]: ../unit_tests.md
-[run the unit tests]: ../unit_tests.md#running
-[Measuring Power]: ./fingerprint-dev-for-partners.md#measure-power
-[dragonclaw]: ./fingerprint-dev-for-partners.md#fpmcu-dev-board
-[FPC 1145]: ../../driver/fingerprint/fpc/libfp/fpc1145_private.h
-[FPC 1025]: ../../driver/fingerprint/fpc/bep/fpc1025_private.h
-[FPC 1145 Template Size]: https://chromium.googlesource.com/chromiumos/platform/ec/+/127521b109be8aac352e80e319e46ed123360408/driver/fingerprint/fpc/libfp/fpc1145_private.h#46
-[FPC 1025 Template Size]: https://chromium.googlesource.com/chromiumos/platform/ec/+/127521b109be8aac352e80e319e46ed123360408/driver/fingerprint/fpc/bep/fpc1025_private.h#44
-[Dragonclaw v0.2]: ./fingerprint-dev-for-partners.md#fpmcu-dev-board
-[Icetower v0.2]: ./fingerprint-dev-for-partners.md#fpmcu-dev-board
-[Nucleo F412ZG]: https://www.digikey.com/en/products/detail/stmicroelectronics/NUCLEO-F412ZG/6137573
-[Nucleo H743ZI2]: https://www.digikey.com/en/products/detail/stmicroelectronics/NUCLEO-H743ZI2/10130892
-[CBI Info]: https://chromium.googlesource.com/chromiumos/docs/+/HEAD/design_docs/cros_board_info.md
-[Chrome OS Config SKU]: https://chromium.googlesource.com/chromiumos/platform2/+/HEAD/chromeos-config/README.md#identity
-[Chrome OS Project Configuration]: https://chromium.googlesource.com/chromiumos/config/+/HEAD/README.md
-[Starlark]: https://docs.bazel.build/versions/master/skylark/language.html
-[`create_fingerprint`]: https://chromium.googlesource.com/chromiumos/config/+/e1fa0d7f56eb3dd6e9378e4326de086ada46b7d3/util/hw_topology.star#444
-[Morphius `config.star`]: https://chrome-internal.googlesource.com/chromeos/project/zork/morphius/+/593b657a776ed6b320c826916adc9cd845faf709/config.star#85
-[regenerate the config]: https://chromium.googlesource.com/chromiumos/config/+/HEAD/README.md#making-configuration-changes-for-your-project
-[`CLFactory`]: https://chromium.googlesource.com/chromiumos/config/+/HEAD/README.md#making-bulk-changes-across-repos