docs: point md files in master to main/HEAD

Master md files are out of date. Point to main branch in case someone
lands in master branch from an old link.

BUG=b:180952272,b:180921286
BRANCH=None
TEST=Preview changes with gerrit

Exempt-From-Owner-Approval: fixing docs
Change-Id: I6583b6c7fc21248eb49a6cd71e077fbdb5de2435
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2727846
Reviewed-by: Sean Abraham <seanabraham@chromium.org>
Reviewed-by: Rob Barnes <robbarnes@google.com>
Auto-Submit: Sean Abraham <seanabraham@chromium.org>
Tested-by: Sean Abraham <seanabraham@chromium.org>
This commit is contained in:
Sean Abraham 2021-03-01 15:13:48 -07:00
parent ef6a915de0
commit 1e800ac838
57 changed files with 219 additions and 10061 deletions

6
.vscode/README.md vendored
View File

@ -1,3 +1,5 @@
# VSCode Setting
*** note
**Warning: This document is old & has moved. Please update any links:**<br>
https://chromium.googlesource.com/chromiumos/platform/ec/+/HEAD/.vscode/README.md
***
See [docs/ide-support.md](/docs/ide-support.md).

645
README.md
View File

@ -1,642 +1,5 @@
# Embedded Controller (EC)
*** note
**Warning: This document is old & has moved. Please update any links:**<br>
https://chromium.googlesource.com/chromiumos/platform/ec/+/HEAD/README.md
***
[TOC]
## Introduction
The Chromium OS project includes open source software for embedded controllers
(EC) used in recent ARM and x86 based Chromebooks. This software includes a
lightweight, multitasking OS with modules for power sequencing, keyboard
control, thermal control, battery charging, and verified boot. The EC software
is written in C and supports [a variety of micro-controllers](https://chromium.googlesource.com/chromiumos/platform/ec/+/master/chip/).
This document is a guide to help make you familiar with the EC code, current
features, and the process for submitting code patches.
For more see the Chrome OS Embedded Controller
[presentation](https://docs.google.com/presentation/d/1Xa_Z6SjW-soPvkugAR8__TEJFrJpzoZUa9HNR14Sjs8/pub?start=false&loop=false&delayms=3000)
and [video](http://youtu.be/Ie7LRGgCXC8) from the
[2014 Firmware Summit](http://dev.chromium.org/chromium-os/2014-firmware-summit).
## What you will need
1. A Chromebook with a compatible EC. This includes the Samsung Chromebook
(XE303C12) and all Chromebooks shipped after the Chromebook Pixel 2013
(inclusive). See the
[Chrome OS devices](http://dev.chromium.org/chromium-os/developer-information-for-chrome-os-devices)
page for a list.
1. A Linux development environment. Ubuntu 14.04 Trusty (x86_64) is well
supported. Linux in a VM may work if you have a powerful host machine.
1. A [servo debug board](http://dev.chromium.org/chromium-os/servo) (and
header) is highly recommended for serial console and JTAG access to the EC.
1. A sense of adventure!
## Terminology
### EC
EC (aka Embedded Controller) can refer to many things in the Chrome OS
documentation due to historical reasons. If you just see the term "EC", it
probably refers to "the" EC (i.e. the first one that existed). Most Chrome OS
devices have an MCU, known as "the EC" that controls lots of things (key
presses, turning the AP on/off). The OS that was written for "the" EC is now
running on several different MCUs on Chrome OS devices with various tweaks
(e.g. the FPMCU, the touchpad one that can do palm rejection, etc.). It's quite
confusing, so try to be specific and use terms like FPMCU to distinguish the
fingerprint MCU from "the EC".
See the [EC Acronyms and Technologies](./docs/ec_terms.md) for a more complete
glossary.
## Getting the EC code
The code for the EC is open source and is included in the Chromium OS
development environment (`~/trunk/src/platform/ec/</code>`).
See[ http://www.chromium.org/chromium-os/quick-start-guide](http://dev.chromium.org/chromium-os/quick-start-guide)
for build setup instructions. If you want instant gratification, you can fetch
the source code directly. However, you will need the tool-chain provided by the
Chromium OS development environment to build a binary.
```bash
git clone https://chromium.googlesource.com/chromiumos/platform/ec
```
The source code can also be browsed on the web at:
https://chromium.googlesource.com/chromiumos/platform/ec/
## Code Overview
The following is a quick overview of the top-level directories in the EC
repository:
**baseboard** - Code and configuration details shared by a collection of board
variants. Tightly linked with the `board` directory described below.
**board** - Board specific code and configuration details. This includes the
GPIO map, battery parameters, and set of tasks to run for the device.
**build** - Build artifacts are generated here. Be sure to delete this and
rebuild when switching branches and before "emerging" (see Building an EC binary
below). make clobber is a convenient way to clean up before building.
**chip** - IC specific code for interfacing with registers and hardware blocks
(adc, jtag, pwm, uart etc…)
**core** - Lower level code for task and memory management.
**common** - A mix of upper-level code that is shared across boards. This
includes the charge state machine, fan control, and the keyboard driver (among
other things).
**driver** - Low-level drivers for light sensors, charge controllers,
I2C/onewire LED controllers, and I2C temperature sensors.
**include** - Header files for core and common code.
**util** - Host utilities and scripts for flashing the EC. Also includes
“ectool” used to query and send commands to the EC from userspace.
**test** - Unit tests for EC components. These can be run locally in
a mock "host" environment or compiled for a target board.
If building for a target board, the test must be flashed and
run manually on the device.
All unit tests and fuzzers are build/run using the local
host environment during a `buildall`.
To run all unit tests locally, run `make runhosttests -j`.
To build a specific unit test for a specific board, run
`make test-<test_name> BOARD=<board_name>`.
Please contribute new tests if writing new functionality.
Please run `make help` for more detail.
**fuzz** - Fuzzers for EC components. These fuzzers are expected to
run in the mock host environment. They follow the same rules
as unit tests, as thus use the same commands to build and run.
## Firmware Branches
Each Chrome device has a firmware branch created when the read-only firmware is
locked down prior to launch. This is done so that updates can be made to the
read-write firmware with a minimal set of changes from the read-only. Some
Chrome devices only have build targets on firmware branches and not on
cros/master. Run “`git branch -a | grep firmware`” to locate the firmware branch
for your board. Note that for devices still under development, the board
configuration may be on the branch for the platform reference board.
To build EC firmware on a branch, just check it out and build it:
```bash
git checkout cros/firmware-falco_peppy-4389.B
```
To make changes on a branch without creating a whole new development environment
(chroot), create a local tracking branch:
```bash
git branch --track firmware-falco_peppy-4389.B cros/firmware-falco_peppy-4389.B
git checkout firmware-falco_peppy-4389.B
make clobber
# <make changes, test, and commit them>
repo upload --cbr .
# (The --cbr means "upload to the current branch")
```
Here is a useful command to see commit differences between branches (change the
branch1...branch2 as needed):
```bash
git log --left-right --graph --cherry-pick --oneline branch1...branch2
```
For example, to see the difference between cros/master and the HEAD of the
current branch:
```bash
git log --left-right --graph --cherry-pick --oneline cros/master...HEAD
# Note: Use three dots “...” or it wont work!
```
## Building an EC binary
Note: The EC is normally built from within the Chromium OS development chroot to
use the correct toolchain.
Building directly from the EC repository:
```bash
cros_sdk
cd ~/trunk/src/platform/ec
make -j BOARD=<boardname>
```
Where **<boardname>** is replaced by the name of the board you want to build an
EC binary for. For example, the boardname for the Chromebook Pixel is “link”.
The make command will generate an EC binary at `build/<boardname>/ec.bin`. The
`-j` tells make to build multi-threaded which can be much faster on a multi-core
machine.
### Building via emerge (the build file used when you build Chrome OS):
(optional) Run this command if you want to build from local source instead of
the most recent stable version:
```bash
cros_workon-<boardname> start chromeos-ec
```
Build the EC binary:
```
emerge-<boardname> chromeos-ec
```
Please be careful if doing both local `make`s and running emerge. The emerge can
pick up build artifacts from the build subdirectory. Its best to delete the
build directory before running emerge with `make clobber`.
The generated EC binary from emerge is found at:
```
(chroot) $ /build/<boardname>/firmware/ec.bin
```
The ebuild file used by Chromium OS is found
[here](https://chromium.googlesource.com/chromiumos/overlays/chromiumos-overlay/+/master/chromeos-base/chromeos-ec/chromeos-ec-9999.ebuild):
```bash
(chroot) $ ~/trunk/src/third_party/chromiumos-overlay/chromeos-base/chromeos-ec/chromeos-ec-9999.ebuild
```
## Flashing an EC binary to a board
### Flashing via the servo debug board
If you get an error, you may not have set up the dependencies for servo
correctly. The EC (on current Chromebooks) must be powered either by external
power or a charged battery for re-flashing to succeed. You can re-flash via
servo even if your existing firmware is bad.
```bash
(chroot) $ sudo emerge openocd
```
```bash
(chroot) $ ~/trunk/src/platform/ec/util/flash_ec --board=<boardname> [--image=<path/to/ec.bin>]
```
Note: This command will fail if write protect is enabled.
If you build your own EC firmware with the `make BOARD=<boardname>` command the
firmware image will be at:
```bash
(chroot) $ ~/trunk/src/platform/ec/build/<boardname>/ec.bin
```
If you build Chrome OS with `build_packages` the firmware image will be at:
```bash
(chroot) $ /build/<boardname>/firmware/ec.bin
```
Specifying `--image` is optional. If you leave off the `--image` argument, the
`flash_ec` script will first look for a locally built `ec.bin` followed by one
generated by `emerge`.
### Flashing on-device via flashrom
Assuming your devices boots, you can flash it using the `flashrom` utility. Copy
your binary to the device and run:
```bash
(chroot) $ flashrom -p ec -w <path-to/ec.bin>
```
Note: `-p internal:bus=lpc` also works on x86 boards...but why would you want to
remember and type all that?
## Preventing the RW EC firmware from being overwritten by Software Sync at boot
A feature called "Software Sync" keeps a copy of the read-write (RW) EC firmware
in the RW part of the system firmware image. At boot, if the RW EC firmware
doesn't match the copy in the system firmware, the ECs RW section is
re-flashed. While this is great for normal use as it makes updating the EC and
system firmware a unified operation, it can be a challenge for EC firmware
development. To disable software sync a flag can be set in the system firmware.
Run the following commands from a shell on the device to disable Software Sync
and turn on other developer-friendly flags (note that write protect must be
disabled for this to work):
```bash
(chroot) $ /usr/share/vboot/bin/set_gbb_flags.sh 0x239
```
```bash
(chroot) $ reboot
```
This turns on the following flags:
* `GBB_FLAG_DEV_SCREEN_SHORT_DELAY`
* `GBB_FLAG_FORCE_DEV_SWITCH_ON`
* `GBB_FLAG_FORCE_DEV_BOOT_USB`
* `GBB_FLAG_DISABLE_FW_ROLLBACK_CHECK`
* `GBB_FLAG_DISABLE_EC_SOFTWARE_SYNC`
The `GBB` (Google Binary Block) flags are defined in the
[vboot_reference source](https://chromium.googlesource.com/chromiumos/platform/vboot_reference/+/master/firmware/include/gbb_header.h).
A varying subset of these flags are implemented and/or relevant for any
particular board.
## Using the EC serial console
The EC has an interactive serial console available only through the UART
connected via servo. This console is essential to developing and debugging the
EC.
Find the serial device of the ec console (on your workstation):
```bash
(chroot) $ dut-control ec_uart_pty
```
Connect to the console:
```bash
(chroot) $ socat READLINE /dev/pts/XX
```
Where `XX` is the device number. Use `cu`, `minicom`, or `screen` if you prefer
them over `socat`.
### Useful EC console commands:
**help** - get a list of commands. help <command> to get help on a specific
command.
**chan** - limit logging message to specific tasks (channels). Useful if youre
looking for a specific error or warning and dont want spam from other tasks.
**battfake** - Override the reported battery charge percentage. Good for testing
low battery conditions (LED behavior for example). Set “battfake -1” to go back
to the actual value.
**fanduty** - Override automatic fan control. “fanduty 0” turns the fan off.
“autofan” switches back to automated control.
**hcdebug** - Display the commands that the host sends to the EC, in varying
levels of detail (see include/ec_commands.h for the data structures).
## Host commands
The way in which messages are exchanged between the AP and EC is
[documented separately](./docs/ap-ec-comm.md).
## Software Features
### Tasks
Most code run on the EC after initialization is run in the context of a task
(with the rest in interrupt handlers). Each task has a fixed stack size and
there is no heap (malloc). All variable storage must be explicitly declared at
build-time. The EC (and system) will reboot if any task has a stack overflow.
Tasks typically have a top-level loop with a call to task_wait_event() or
usleep() to set a delay in uSec before continuing. A watchdog will trigger if a
task runs for too long. The watchdog timeout varies by EC chip and the clock
speed the EC is running at.
The list of tasks for a board is specified in ec.tasklist in the `board/$BOARD/`
sub-directory. Tasks are listed in priority order with the lowest priority task
listed first. A task runs until it exits its main function or puts itself to
sleep. The highest priority task that wants to run is scheduled next. Tasks can
be preempted at any time by an interrupt and resumed after the handler is
finished.
The console `taskinfo` command will print run-time stats on each task:
```
> taskinfo
Task Ready Name Events Time (s) StkUsed
0 R << idle >> 00000000 32.975554 196/256
1 R HOOKS 00000000 0.007835 192/488
2 VBOOTHASH 00000000 0.042818 392/488
3 POWERLED 00000000 0.000096 120/256
4 CHARGER 00000000 0.029050 392/488
5 CHIPSET 00000000 0.017558 400/488
6 HOSTCMD 00000000 0.379277 328/488
7 R CONSOLE 00000000 0.042050 348/640
8 KEYSCAN 00000000 0.002988 292/488
```
The `StkUsed` column reports the largest size the stack for each task grew since
reset (or sysjump).
### Hooks
Hooks allow you to register a function to be run when specific events occur;
such as the host suspending or external power being applied:
```
DECLARE_HOOK(HOOK_AC_CHANGE, ac_change_callback, HOOK_PRIO_DEFAULT);
```
Registered functions are run in the HOOKS task. Registered functions are called
in priority order if more than one callback needs to be run. There are also
hooks for running functions periodically: `HOOK_TICK` (fires every
`HOOK_TICK_INVERVAL` ms which varies by EC chip) and `HOOK_SECOND`. See
hook_type in
[include/hooks.h](https://chromium.googlesource.com/chromiumos/platform/ec/+/master/include/hooks.h)
for a complete list.
### Deferred Functions
Deferred functions allow you to call a function after a delay specified in uSec
without blocking. Deferred functions run in the HOOKS task. Here is an example
of an interrupt handler. The deferred function allows the handler itself to be
lightweight. Delaying the deferred call by 30 mSec also allows the interrupt to
be debounced.
```
static int debounced_gpio_state;
static void some_interrupt_deferred(void)
{
int gpio_state = gpio_get_level(GPIO_SOME_SIGNAL);
if (gpio_state == debounced_gpio_state)
return;
debounced_gpio_state = gpio_state;
dispense_sandwich(); /* Or some other useful action. */
}
/* A function must be explicitly declared as being deferrable. */
DECLARE_DEFERRED(some_interrupt_deferred);
void some_interrupt(enum gpio_signal signal)
{
hook_call_deferred(some_interrupt_deferred, 30 * MSEC);
}
```
### Shared Memory Buffer
While there is no heap, there is a shared memory buffer that can be borrowed
temporarily (ideally before a context switch). The size of the buffer depends on
the EC chip being used. The buffer can only be used by one task at a time. See
[common/shared_mem.c](https://chromium.googlesource.com/chromiumos/platform/ec/+/master/common/shared_mem.c)
for more information. At present (May 2014), this buffer is only used by debug
commands.
## Making Code Changes
If you see a bug or want to make an improvement to the EC code please file an
issue at [crbug.com/new](http://crbug.com/new). It's best to discuss the change
you want to make first on an issue report to make sure the EC maintainers are
on-board before digging into the fun part (writing code).
In general, make more, smaller changes that solve single problems rather than
bigger changes that solve multiple problems. Smaller changes are easier and
faster to review. When changing common code shared between boards along with
board specific code, please split the shared code change into its own change
list (CL). The board specific CL can depend on the shared code CL.
### Coding style
The EC code follows the
[Linux Kernel style guide](https://www.kernel.org/doc/html/latest/process/coding-style.html).
Please adopt the same style used in the existing code. Use tabs, not spaces, 80
column lines etc...
Other style notes:
1. Globals should either be `static` or `const`. Use them for persistent state
within a file or for constant data (such as the GPIO list in board.c). Do
not use globals to pass information between modules without accessors. For
module scope, accessors are not needed.
1. If you add a new `#define` config option to the code, please document it in
[include/config.h](https://chromium.googlesource.com/chromiumos/platform/ec/+/master/include/config.h)
with an `#undef` statement and descriptive comment.
1. The Chromium copyright header must be included at the top of new files in
all contributions to the Chromium project:
```
/* Copyright <year> The Chromium OS Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
```
### Submitting changes
Prior to uploading a new change for review, please run the EC unit tests with:
```bash
(chroot) $ make -j buildall
```
```bash
(chroot) $ make -j tests
```
These commands will build and run unit tests in an emulator on your host.
Pre-submit checks are run when you try to upload a change-list. If you wish to
run these checks manually first, commit your change locally then run the
following command from within the chroot and while in the `src/platform/ec`
directory:
```bash
(chroot) $ ~/trunk/src/repohooks/pre-upload.py
```
The pre-submit checks include checking the commit message. Commit messages must
have a `BUG`, `BRANCH`, and `TEST` line along with `Signed-off-by: First Last
<name@company.com>`. The signed-off-by line is a statement that you have written
this code and it can be contributed under the terms of the `LICENSE` file.
Please refer to existing commits (`git log`) to see the proper format for the
commit message. If you have configured git properly, running `git commit` with
the `-s` argument will add the Signed-off-by line for you.
## Debugging
While adding `printf` statements can be handy, there are some other options for
debugging problems during development.
### Serial Console
There may already be a message on the serial console that indicates your
problem. If you dont have a servo connected, the `ectool console` command will
show the current contents of the console buffer (the buffers size varies by EC
chip). This log persists across warm resets of the host but is cleared if the EC
resets. The `ectool console` command will only work when the EC is not write
protected.
If you have interactive access to the serial console via servo, you can use the
read word `rw` and write word `ww` commands to peek and poke the EC's RAM. You
may need to refer to the datasheet for your EC chip or the disassembled code to
find the memory address you need. There are other handy commands on the serial
console to read temperatures, view the state of tasks (taskinfo) which may help.
Type `help` for a list.
### Panicinfo
The EC may save panic data which persists across resets. Use the “`ectool
panicinfo`” command or console “`panicinfo`” command to view the saved data:
```
Saved panic data: (NEW)
=== HANDLER EXCEPTION: 05 ====== xPSR: 6100001e ===
r0 :00000001 r1 :00000f15 r2 :4003800c r3 :000000ff
r4 :ffffffed r5 :00000799 r6 :0000f370 r7 :00000000
r8 :00000001 r9 :00000003 r10:20002fe0 r11:00000000
r12:00000008 sp :20000fd8 lr :000012e1 pc :0000105e
```
The most interesting information are the program counter (`pc`) and the link
register (return address, `lr`) as they give you an indication of what code the
EC was running when the panic occurred. `HANDLER EXCEPTIONS` indicate the panic
occurred while servicing an interrupt. `PROCESS EXCEPTIONS` occur in regular
tasks. If you see “Imprecise data bus error” listed, the program counter value
is incorrect as the panic occurred when flushing a write buffer. If using a
cortex-m based EC, add `CONFIG_DEBUG_DISABLE_WRITE_BUFFER` to your board.h to
disable write buffering (with a performance hit) to get a “Precise bus error”
with an accurate program counter value.
### Assembly Code
If you have a program counter address you need to make sense of, you can
generate the assembly code for the EC by checking out the code at the matching
commit for your binary (`ectool version`) and running:
```bash
(chroot) $ make BOARD=$board dis
```
This outputs two files with assembly code:
```
build/$board/RO/ec.RO.dis
build/$board/RW/ec.RW.dis
```
which (in the case of the LM4 and STM32) are essentially the same, but the RW
addresses are offset.
## Write Protect
See [Firmware Write Protection].
## EC Version Strings
The read-only and read-write sections of the EC firmware each have a version
string. This string tells you the branch and last change at which the firmware
was built. On a running machine, run `ectool version` from a shell to see
version information:
```
RO version: peppy_v1.5.103-7abb4f7
RW version: peppy_v1.5.129-cd1a1e9
Firmware copy: RW
Build info: peppy_v1.5.129-cd1a1e9 2014-03-07 17:18:27 @build120-m2
```
You can also run the `version` command on the EC serial console for a similar
output.
The format of the version string is:
```
<board>_<branch number>.<number of commits since the branch tag was created>-<git hash of most recent change>
```
If the version is: `rambi_v1.6.68-a6608c8`:
* board name = rambi
* branch number = v1.6 (which is for the firmware-rambi branch)
* number of commits on this branch (since the tag was added) = 68
* latest git hash = a6608c8
The branch numbers (as of May 2014) are:
* v1.0.0 cros/master
* v1.1.0 cros/master
* v1.2.0 cros/firmware-link-2695.2.B
* v1.3.0 cros/firmware-snow-2695.90.B
* v1.4.0 cros/firmware-skate-3824.129.B
* v1.5.0 cros/firmware-4389.71.B
* v1.6.0 cros/firmware-rambi-5216.B
Hack command to check the branch tags:
```
git tag
for hash in $(git for-each-ref --format='%(objectname)' refs/tags/); do
git branch -a --contains $hash | head -1;
done
```
(If anyone can come up with something prettier, make a CL).
Run `util/getversion.sh` to see the current version string. The board name is
passed as an environment variable `BOARD`:
```bash
(chroot) $ BOARD="cheese" ./util/getversion.sh
```
```
cheese_v1.1.1755-4da9520
```
[Firmware Write Protection]: ./docs/write_protection.md

View File

@ -1,39 +1,5 @@
/* Copyright 2019 The Chromium OS Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
*** note
**Warning: This document is old & has moved. Please update any links:**<br>
https://chromium.googlesource.com/chromiumos/platform/ec/+/HEAD/baseboard/intelrvp/README.md
***
This folder is for the baseboard for the board specific files which use Intel
Reference Validation Platform (RVP) for developing the EC and other peripherals
which can be hooked on EC or RVP.
This baseboard follows the Intel Modular Embedded Controller Card (MECC)
specification for pinout and these pin definitions remain same on all the
RVPs. Chrome MECC spec is standardized for Icelake and successor RVPs hence
this baseboard code is applicable to Icelake and its successors only.
Following hardware features are supported on MECC header by RVP and can be
validated by software by MECC.
MECC version 0.9 features
1. Power to MECC is provide by RVP (battery + DC Jack + Type C)
2. Power control pins for Intel SOC are added
3. Servo V2 header need to be added by MECC
4. Google H1 chip need to be added by MECC (optional for EC vendors)
5. 2 Type-C port support (SRC/SNK/BC1.2/MUX/Rerimer)
6. 6 Temperature sensors
7. 4 ADC
8. 4 I2C Channels
9. 1 Fan control
MECC version 1.0 features
1. Power to MECC is provide by RVP (battery + DC Jack + Type C)
2. Power control pins for Intel SOC are added
3. Servo V2 header need to be added by MECC
4. Google H1 chip need to be added by MECC (optional for EC vendors)
5. 4 Type-C port support (SRC/SNK/BC1.2/MUX/Rerimer) as Add In Card (AIC)
on RVP
6. Optional 2 Type-C port routed to MECC for integrated TCPC support
7. 6 I2C Channels
8. 2 SMLINK Channels
9. 2 I3C channels

View File

@ -1,85 +1,5 @@
# Nucleo F412ZG
*** note
**Warning: This document is old & has moved. Please update any links:**<br>
https://chromium.googlesource.com/chromiumos/platform/ec/+/HEAD/board/nucleo-f412zg/README.md
***
This is a simpler EC example for the ST Nucleo F412ZG
development board.
# Quick Start
The Nucleo dev boards have lots of developer friendly features,
like an in-circuit debugger/programmer/UART-bridge, programmable
LEDs, and a button, to name a few.
The built-in debugger can be connected to using a Micro USB cable.
It provides three great interfaces to the host.
1. Mass storage interface for drag-drop programming
2. Full ST-Link in-circuit debugger
3. UART bridge for logs/consoles
We will use a few of these interfaces below to program and interact
with out Nucleo dev board.
## Build
```bash
make BOARD=nucleo-f412zg -j
```
## Program
The easiest way to flash the Nucleo board is to Copy-Paste/Drag-Drop
the firmware image onto the exposed mass storage drive.
Open a file browser and `Copy` the file in `build/nucleo-f412zg/ec.bin`.
Now, find the removable storage that the Nucleo device has presented,
and `Paste` the file into the directory.
## Interact
After the Nucelo finishes programming, you can open the EC console.
On GNU/Linux, this is mapped to `/dev/ttyACM0`.
Install `minicom` and issue the following command:
```bash
minicom -D/dev/ttyACM0
```
# Unit Testing
A fun EC feature is that unit tests can be run on-device.
This is made possible by an alternative build rule that generates a
test image per unit test. These test images use a unit test specific taskset
and console command to trigger them.
## Create
To enable an existing unit test, add it to the [build.mk](build.mk)'s
`test-list-y` variable.
See the main [README.md](/README.md) on how to write a new unit test.
## Build
To build all unit test images for this board, run the following command:
```bash
make BOARD=nucleo-f412zg tests
```
You can build a specific unit test image by changing `tests` to `test-aes`,
for the `aes` unit test.
## Flash
Copy/paste the `build/nucleo-f412zg/${TEST}/${TEST}.bin` file to the
Nucleo's mass storage drive, where `${TEST}` is the name of the unit test,
like `aes`.
## Run
1. Connect to UART console
```bash
minicom -D/dev/ttyACM0
```
2. Run the `runtest` command

View File

@ -1,85 +1,5 @@
# Nucleo H743ZI
*** note
**Warning: This document is old & has moved. Please update any links:**<br>
https://chromium.googlesource.com/chromiumos/platform/ec/+/HEAD/board/nucleo-h743zi/README.md
***
This is a simpler EC example for the ST Nucleo H743ZI
development board.
# Quick Start
The Nucleo dev boards have lots of developer friendly features,
like an in-circuit debugger/programmer/UART-bridge, programmable
LEDs, and a button, to name a few.
The built-in debugger can be connected to using a Micro USB cable.
It provides three great interfaces to the host.
1. Mass storage interface for drag-drop programming
2. Full ST-Link in-circuit debugger
3. UART bridge for logs/consoles
We will use a few of these interfaces below to program and interact
with out Nucleo dev board.
## Build
```bash
make BOARD=nucleo-h743zi -j
```
## Program
The easiest way to flash the Nucleo board is to Copy-Paste/Drag-Drop
the firmware image onto the exposed mass storage drive.
Open a file browser and `Copy` the file in `build/nucleo-h743zi/ec.bin`.
Now, find the removable storage that the Nucleo device has presented,
and `Paste` the file into the directory.
## Interact
After the Nucelo finishes programming, you can open the EC console.
On GNU/Linux, this is mapped to `/dev/ttyACM0`.
Install `minicom` and issue the following command:
```bash
minicom -D/dev/ttyACM0
```
# Unit Testing
A fun EC feature is that unit tests can be run on-device.
This is made possible by an alternative build rule that generates a
test image per unit test. These test images use a unit test specific taskset
and console command to trigger them.
## Create
To enable an existing unit test, add it to the [build.mk](build.mk)'s
`test-list-y` variable.
See the main [README.md](/README.md) on how to write a new unit test.
## Build
To build all unit test images for this board, run the following command:
```bash
make BOARD=nucleo-h743zi tests
```
You can build a specific unit test image by changing `tests` to `test-aes`,
for the `aes` unit test.
## Flash
Copy/paste the `build/nucleo-h743zi/${TEST}/${TEST}.bin` file to the
Nucleo's mass storage drive, where `${TEST}` is the name of the unit test,
like `aes`.
## Run
1. Connect to UART console
```bash
minicom -D/dev/ttyACM0
```
2. Run the `runtest` command

View File

@ -1,151 +1,5 @@
USB PD chip evaluation configuration
====================================
This board configuration implements a USB Power Delivery TCPM
in order to evaluate various TCPC chips.
The code tries to follow the preliminary USB PD interface standard but for TCPC chip implementing proprietary I2C protocol, a new TCPM file can be implemented as explained in the [Updating the code](#Updating-the-code) section below.
Building
--------
### ChromiumOS chroot
All the following instructions have been verified in a ChromiumOS chroot.
You can find how to set one up on the Chromium development wiki:
[http://dev.chromium.org/chromium-os/quick-start-guide](http://dev.chromium.org/chromium-os/quick-start-guide)
### Build the TCPM code
`cd src/platform/ec`
`make BOARD=pdeval-stm32f072`
Updating the code
-----------------
### TCPC Communication code
Please duplicate [driver/tcpm/tcpci.c](../../driver/tcpm/tcpci.c) into **driver/tcpm/##chip#name##.c**.
Then update the control logic through I2C there.
In order for your new code to compile, you need to update [driver/build.mk](../../driver/build.mk) with the new file :
`driver-$(CONFIG_USB_PD_TCPM_##CHIP#NAME##)+=tcpm/##chip#name##.o`
then document the new `CONFIG_USB_PD_TCPM_` variable in the [include/config.h](../../include/config.h) file and define it in the board configuration in [board/pdeval-stm32f072/board.h](board.h).
### Board configuration
In [board/pdeval-stm32f072/board.h](board.h), you can update `CONFIG_USB_PD_PORT_MAX_COUNT` to the actual number of ports on your board.
You also need to create/delete the corresponding `PD_Cx` tasks in [board/pdeval-stm32f072/ec.tasklist](ec.tasklist).
By default, the firmware is using I2C1 with SCL/SDA on pins PB6 and PB7, running with a 100kHz clock, and tries to talk to TCPCs at i2c slave addresses 0x9c and 0x9e.
To change the pins or speed, you need to edit `i2c_ports` in [board/pdeval-stm32f072/board.c](board.c), update `I2C_PORT_TCPC` in [board/pdeval-stm32f072/board.h](board.h) with the right controller number, and change the pin mux in [board/pdeval-stm32f072/gpio.inc](gpio.inc). To change TCPC i2c slave addresses, update `TCPC1_I2C_ADDR` and `TCPC2_I2C_ADDR` in [board/pdeval-stm32f072/board.h](board.h).
The I2C bus needs pull-up resistors on SCL/SDA. If your setup doesn't have external pull-ups on those lines, you can activate the chip internal pull-ups (but they are a bit weak for I2C) by editing [board/pdeval-stm32f072/gpio.inc](gpio.inc) and updating the alternate mode configuration flags with `GPIO_PULL_UP` e.g. :
`ALTERNATE(PIN_MASK(B, 0x00c0), 1, MODULE_I2C, GPIO_PULL_UP) /* I2C MASTER:PB6/7 */`
An interrupt line, PA1, is configured to be used for the TCPC to get the attention of the TCPM. The GPIO is configured to trigger an interrupt on the falling edge and will call `tcpc_alert()`, which must be implemented in **driver/tcpm/<vendor>.c**, and should determine the cause of the interrupt and take action. The GPIO can be changed in [board/pdeval-stm32f072/gpio.inc](gpio.inc).
Flashing and Running
--------------------
### Flashing the firmware binary
To flash through JTAG with OpenOCD, you can just run:
`sudo make flash BOARD=pdeval-stm32f072`
Note: you need to do that with your USB mini-B cable is connected to the **USB ST-LINK** plug on the discovery board.
### Connecting to the firmware console
Connect a USB cable to the **USB USER** mini-B receptacle on the board.
`lsusb` should show you a device with the following ID : 18d1:500f
You can get a console over USB by issuing the following command on a Linux computer:
`echo '18d1 500f' | sudo tee /sys/bus/usb-serial/drivers/generic/new_id`
Testing
-------
Currently, the TCPM is expecting to have a GPIO to detect VBUS, but to minimize the HW setup with the discovery board the alternative is to fake VBUS detection using either the **USER** button on the discovery board, or the `vbus` console command, both of which toggle the state of VBUS detected. For example, to make get a PD contract with a power adapter, plug in the adapter and then toggle VBUS on. When a PD contract above 6V is made, LED5 on the discovery board will light. To disconnect, toggle VBUS off.
EC command line commands
- `help` List all available EC console commands
- `vbus` Toggle VBUS on/off
- `pd <port> state` Print PD protocol state information
- `pd <port> swap data` Request data role swap on port
- `pd <port> swap power` Request power role swap on port
- `i2cscan` Scan i2c bus for any responsive devices
- `i2cxfer` Perform an i2c transaction
On the console, you will the PD state machine transitioning through its states with traces like `C0 st5`.
You can always the human readable name of the current state by doing `pd 0 state` returning something like :
`Port C0 CC1, Ena - Role: SNK-UFP State: SNK_DISCOVERY, Flags: 0x0608`
else the numbering of the state is defined in [include/usb_pd.h](../../include/us_pd.h) by the `PD_STATE_` constants.
It should be by default :
```
[0] DISABLED
[1] SUSPENDED
[2] SNK_DISCONNECTED
[3] SNK_DISCONNECTED_DEBOUNCE
[4] SNK_HARD_RESET_RECOVER
[5] SNK_DISCOVERY
[6] SNK_REQUESTED
[7] SNK_TRANSITION
[8] SNK_READY
[9] SNK_SWAP_INIT
[10] SNK_SWAP_SNK_DISABLE
[11] SNK_SWAP_SRC_DISABLE
[12] SNK_SWAP_STANDBY
[13] SNK_SWAP_COMPLETE
[14] SRC_DISCONNECTED
[15] SRC_DISCONNECTED_DEBOUNCE
[16] SRC_ACCESSORY
[17] SRC_HARD_RESET_RECOVER
[18] SRC_STARTUP
[19] SRC_DISCOVERY
[20] SRC_NEGOCIATE
[21] SRC_ACCEPTED
[22] SRC_POWERED
[23] SRC_TRANSITION
[24] SRC_READY
[25] SRC_GET_SINK_CAP
[26] DR_SWAP
[27] SRC_SWAP_INIT
[28] SRC_SWAP_SNK_DISABLE
[29] SRC_SWAP_SRC_DISABLE
[30] SRC_SWAP_STANDBY
[31] SOFT_RESET
[32] HARD_RESET_SEND
[33] HARD_RESET_EXECUTE
[34] BIST_RX
[35] BIST_TX
```
Known Issues
------------
1. This doc is not finished yet ...
2. You might need a ChromeOS chroot ...
Troubleshooting
---------------
1. OpenOCD is not finding the device.
1. Check that your USB mini-B cable is connected to the **USB ST-LINK** plug on the discovery board.
2. What color is the LD1 LED on the board ?
1. On the I2C bus, SDA/SCL lines are staying always low
1. You might be missing some pull-up resistors on the bus.
1. Check the [Board configuration](#Board-configuration) section if you cannot add external pull-ups.
1. You got black smoke
1. Time to buy a new one.
*** note
**Warning: This document is old & has moved. Please update any links:**<br>
https://chromium.googlesource.com/chromiumos/platform/ec/+/HEAD/board/pdeval-stm32f072/PD_evaluation.md
***

View File

@ -1,176 +1,5 @@
<!--
Copyright 2018 The Chromium OS Authors. All rights reserved.
Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file.
-->
*** note
**Warning: This document is old & has moved. Please update any links:**<br>
https://chromium.googlesource.com/chromiumos/platform/ec/+/HEAD/board/servo_micro/ccd.md
***
# Case-Closed Debug in Chromebooks and Servo Micro
The Servo debug/test-automation connector has been required on all
chromebooks. It has proved essential to performing the required testing to meet
the six week OS release cycle, for bringing up new systems and qualifying new
components. In newer form-factors it is becoming hard to fit the Servo connector
(and related flex) and in some designs the thermal solution stops working when
the connector is used. The secure Case-Closed Debugging solution provides the
same capabilities and can take advantage of the Debug Mode detection available
on the USB-C connector. This application note gives an overview of Case-Closed
Debug (CCD) but does not address the related security issues.
## Introduction to Case-Closed Debug
Case-Closed Debug provides the same set of features as are available on the Servo connector:
* Access to console UART connections to AP, EC and on some systems a third MCU
* Ability to reprogram firmware/BIOS SPI flash used by the AP
* Ability to reprogram SPI flash used by the EC or use a firmware update mode
to reprogram the internal flash on the EC (using UART or I2C)
* GPIOs for holding the EC (and thus entire system) or AP in reset
* Act as master on a debug I2C that is primarily used for power
measurements. This bus normally contains INA voltage/current monitors and
temperature monitors that will not be populated on final MP systems.
* JTAG/SWD could be provided but has not been implemented on any existing system.
When the Servo connector is used these interfaces are presented on well defined
pins of the board-to-board connector and a flex is used to attach to the
external Servo controller. The height needed for the mated board-to-board
connector is not available in newer slim designs, and the disruption caused by
the flex may interfere with thermal solutions. In a system using Case-Closed
Debug the interfaces are gathered by a part on the board into a single USB
interface that can come out of the system on an existing connector. In
particular, the USB-C connector has two SideBand Use pins (SBU1, SBU2) that can
be used for the debug USB while the main link on the connector continues to be
available. (The SBU pins are also used by some Alternate Modes, so the connector
cannot be used for video out at the same time as debugging.)
## Servo Micro: Using CCD with existing boards
The Servo Micro implements the CCD functions in a way that can connect to
existing boards and thus can also serve as an easy introduction to the CCD
implementation. The debug USB interface is expanded by a STM32F072 into an
existing Servo flex connector that can be plugged into the target board.
![block diagram](servo_micro.png)
The Servo Micro includes the voltage level buffering between the microcontroller
and the device under test (DUT), making use of the DUT supplied reference
voltages. To allow use with all the existing designs a third UART (not on the
original Servo connector, but on some designs) can be connected to either the
JTAG pins or the SPI pins. It is capable of providing the SPI flash supply
voltages.
The schematics for Servo Micro are available [as a
pdf](servo_micro_sch_20180404.pdf).
Servo Micro has a USB micro-B connector and acts as a USB device.
Schematic sheet 2 shows the STM32 powered from the uB connector. The UART3 pins
can also be used as GPIO pins when driving the JTAG interface. As a useful but
non-compliant hack if the ID pin on the uB is low then Q4 will force the STM32
to boot in programming mode. This allows initial programming of the part with
USB DFU using an illegal USB-A plug to USB-A plug cable and a USB-A receptacle
to uB plug adapter. Alternatively the initial programming can be done using a
UART connection on CN2.
Schematic sheet 3 shows the I2C GPIO expander and the buffers for JTAG/SWD. The
buffers adapt to the voltage needed on the DUT that is provided on
`PPDUT_JTAG_VREF`. In the SWD case the TDI becomes the bidirectional SWDIO but the
STM32 continues to use a discrete input and output pin. The DUT signal is
received through U55 and a selection made with U1 to determine if to forward TDO
from the DUT or the TDI/SWDIO. Because of the shared pins on the STM32 the JTAG
interface can alternatively be used to connect UART3 to the DUT for a few
chromebook models.
Schematic sheet 4 shows the buffers for the SPI interfaces. Again the
`PPDUT_SPIn_VREF` sets the voltage level required from the DUT. However, I61 and
I62 (which are expanded on sheets 7 and 8) allow the Servo Micro to supply 3.3V
or 1.8V for cases where the DUT does not provide the reference (care is needed
to select the correct voltage for the given DUT). Only one of the SPI interfaces
can be used at any time, so the buffers are also used to select which connects
to the STM32 SPI pins. Certain chromebook models connect the UART3 in place of
SPI1 which is enabled using U5 to select between the STM32 UART3 (TX,RX) and SPI
(CLK, MISO).
Schematic sheet 5 shows the buffers for the UART interfaces. The
`PPDUT_UARTn_VREF` sets the voltage level required from the DUT.
Schematic sheet 6 shows the board-to-board connector that mates with the servo
connector on the DUT.
Schematic sheets 7 and 8 are the expansion of blocks I61 and I62 on sheet 4. The
load switches are carefully selected to have reverse blocking (protecting
against a DUT providing a voltage or both being enabled).
The code for the STM32 in Servo Micro is open source as the
[`servo_micro`](../../board/servo_micro)
board in the [Chromium EC
codebase](https://chromium.googlesource.com/chromiumos/platform/ec/). Essentially
it is a USB device that provides the standard control endpoint and 7 function
endpoints defined in
[`board.h`](board.h).
<!-- does not work in emacs/markdown preview but should in gitlies -->
``` c
#define USB_EP_USART4_STREAM 1
#define USB_EP_UPDATE 2
#define USB_EP_SPI 3
#define USB_EP_CONSOLE 4
#define USB_EP_I2C 5
#define USB_EP_USART3_STREAM 6
#define USB_EP_USART2_STREAM 7
```
The USART endpoints use the simple `GOOGLE_SERIAL` vendor class to connect the
STM32 UARTs. The CONSOLE endpoint also uses `GOOGLE_STREAM` to connect to the
console of the code running on the STM32. `GOOGLE_STREAM` provides simple byte
streams on the IN and OUT of the endpoint and host support is included in the
standard Linux `drivers/usb/serial/usb-serial-simple.c`
The SPI endpoint is described in
[`chip/stm32/usb_spi.h`](../../chip/stm32/usb_spi.h) and provides a simple
connection to the SPI port. The host support is provided as a [driver in
flashrom](https://chromium.googlesource.com/chromiumos/third_party/flashrom/+/master/raiden_debug_spi.c).
The I2C endpoint is described in [`include/usb_i2c.h`](../../include/usb_i2c.h)
and provides a simple connection to the I2C bus. The host support is provided in
the [hdctools servo
support](https://chromium.googlesource.com/chromiumos/third_party/hdctools/+/master/servo/stm32i2c.py).
The GPIO endpoint is cryptically described in
[`chip/stm32/usb_gpio.h`](../../chip/stm32/usb_gpio.h) and provides simple access
to set/clear and read the GPIO pins. The host support is provided in the
[hdctools servo
support](https://chromium.googlesource.com/chromiumos/third_party/hdctools/+/master/servo/stm32gpio.py).
The UPDATE endpoint is not part of CCD. It provides a method for updating the
STM32 without needing the special boot modes. This uses the [Chromium EC update
over
USB](../../docs/usb_updater.md)
method. The STM32 runs the code in
[`common/usb_update.c`](../../common/usb_update.c).
The host side code is in
[`extra/usb_updater/usb_updater2.c`](../../extra/usb_updater/usb_updater2.c)
and the
[`extra/usb_updater`](../../extra/usb_updater/)
directory contains additional scripts.
## Using CCD on new designs
New chromebook designs implement the CCD in a similar way to Servo Micro. There
are two changes to the Servo Micro:
* The USB microB connector is replaced with the USB connection being carried
on the SBU pins of one of the devices USB-C ports. This will only be
activated when the USB-C port detects a debug accessory or a debug alternate
mode is entered. Use of the debug connection precludes use of the Display
Port alternate mode (which also uses the SBU pins) but allows full USB3 and
USB2 functions including both host and gadget mode.
* The system security chip will normally lock out debug access. Using secure
transactions, user authorization and proof of user physical presence it can
unlock various degrees of debug access.
The full details are part of the Cr50 firmware specification.

View File

@ -1,87 +1,5 @@
# Common Mocks
This directory holds mock implementations for use in fuzzers and tests.
*** note
**Warning: This document is old & has moved. Please update any links:**<br>
https://chromium.googlesource.com/chromiumos/platform/ec/+/HEAD/common/mock/README.md
***
Each mock is given some friendly build name, like ROLLBACK or FP_SENSOR.
This name is defined in [common/mock/build.mk](build.mk) and referenced
from unit tests and fuzzers' `.mocklist` file.
## Creating a new mock
* Add the mock source to [common/mock](/common/mock) and the
optional header file to [include/mock](/include/mock).
Header files are only necessary if you want to expose additional
[mock control](#mock-controls) functions/variables.
See the [Design Patterns](#design-patterns) section
for more detail on design patterns.
* Add a new entry in [common/mock/build.mk](build.mk)
that is conditioned on your mock's name.
If a unit test or fuzzer requests this mock, the build system will
set the variable `HAS_MOCK_<BUILD_NAME>` to `y` at build time.
This variable is used to conditionally include the mock source
in [common/mock/build.mk](build.mk).
Example line from [common/mock/build.mk](build.mk):
```make
# Mocks
mock-$(HAS_MOCK_ROLLBACK) += mock/rollback_mock.o
```
## Using a mock
Unit tests and fuzzers can request a particular mock by adding an entry to
their `.mocklist` file. The mocklist file is similar to a `.tasklist`
file, where it is named according to the test/fuzz's name followed by
`.mocklist`, like `fpsensor.mocklist`.
The mocklist file is optional, so you may need to create one.
Example `.mocklist`:
```c
/* Copyright 2019 The Chromium OS Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#define CONFIG_TEST_MOCK_LIST \
MOCK(ROLLBACK) \
MOCK(FP_SENSOR)
```
If you need additional [mock control](#mock-controls) functionality,
you may need to include the mock's header file, which is prepended
with `mock/` in the include line.
For example, to control the return values of the rollback mock:
```c
#include "mock/rollback_mock.h"
void yourfunction() {
mock_ctrl_rollback.get_secret_fail = true;
}
```
## Mock Controls
Mocks can change their behavior by exposing "mock controls".
We do this, most commonly, by exposing an additional global struct
per mock that acts as the settings for the mock implementation.
The mock user can then modify fields of the struct to change the mock's behavior.
For example, the `fp_sensor_init_return` field may control what value
the mocked `fp_sensor_init` function returns.
The declaration for these controls are specified in the mock's header file,
which resides in [include/mock](/include/mock).
## Design Patterns
* When creating mock controls, consider placing all your mock parameters in
one externally facing struct, like in
[fp_sensor_mock.h](/include/mock/fp_sensor_mock.h).
The primary reason for this is to allow the mock to be easily used
by a fuzzer (write random bytes into the struct with memcpy).
* When following the above pattern, please provide a macro for resetting
default values for this struct, like in
[fp_sensor_mock.h](/include/mock/fp_sensor_mock.h).
This allows unit tests to quickly reset the mock state/parameters
before each unrelated unit test.

View File

@ -1,153 +1,5 @@
# Application Processor to EC communication
*** note
**Warning: This document is old & has moved. Please update any links:**<br>
https://chromium.googlesource.com/chromiumos/platform/ec/+/HEAD/docs/ap-ec-comm.md
***
[TOC]
## Overview
The Application Processor (sometimes called the host) communicates with the EC
by issuing *host commands*, which are identified by a command ID and version
number, and then reading a response. When a host command is issued through
`ectool`, two or three software components are involved:
* `ectool`, the user-space binary,
* normally the `cros-ec` Kernel driver, and
* the code on the EC itself. This can be thought of as two parts:
* a chip-specific driver for the appropriate transport, and
* the generic host command handling code (mostly in the [host command task]).
We'll go into detail of each of these, as well as the traffic on the wire, in
the following sections.
### `ectool`
`ectool` contains wrapper functions for the host commands exposed by the EC,
providing a CLI. They call one of the transport-specific `ec_command`
implementations in the `util/comm-*.c` files to send and receive from the EC.
### EC kernel driver
In most cases, `ectool` communicates via the [`cros-ec` Kernel driver], rather
than directly from userspace. It sends raw commands to the Kernel driver, which
sends them on to the EC, bypassing a lot of the other Kernel driver
functionality.
There are other CrOS EC-related Kernel drivers, which use host commands to act
as adapters to existing Linux APIs. For example, sensors from the EC are mapped
to the Linux [Industrial I/O] system.
### On the wire
Now we come to the protocol itself. All transactions take this general form:
* Host writes the request packet, consisting of:
* a transport-specific header;
* a `struct ec_host_request` containing the command ID, data length, and a
checksum; and
* zero or more bytes of parameters for the command, the format of which
depends on the command.
* Host reads the response to its request, consisting of:
* a transport-specific header;
* a `struct ec_host_response` containing the result code, data length, and a
checksum; and
* zero or more bytes of response from the command, again with a
command-specific format.
### On the EC
The host packet is received on the EC by some chip-specific code which checks
its transport-specific header, then passes it on to the common host command code,
starting at `host_packet_receive`. The common code validates the packet and
then sends it on to the handler function (annotated with the
`DECLARE_HOST_COMMAND` macro), which runs in the `HOSTCMD` task. The handler can
set a response by modifying its arguments struct, which is sent back to the host
via the chip-specific code.
While this is happening, the EC needs to indicate to the host that it is busy
processing and not yet ready to give a response. How it does this depends on the
transport method used (see [Transport-specific details] below).
## Versions
There are two different concepts of "version" involved in host commands: version
of the overarching protocol, and versions of individual commands.
### Protocol versions
There have been three protocol versions so far, and this document describes
version 3. Version 1 was superseded by 2 before it shipped, so no devices use
it anymore. Version 2 is generally deprecated, but you might still encounter it
occasionally.
Which version is in use can be determined using the `EC_CMD_GET_PROTOCOL_INFO`
command. This was only introduced in version 3, however, so if errors,
`EC_CMD_HELLO` should be sent in version 2. If the hello command succeeds, the
EC speaks version 2.
### Command versions
Individual commands also have versions, independent of the protocol version
they're being called with. Different versions of a command may have different
parameter or response formats. `EC_CMD_GET_CMD_VERSIONS` returns the versions of
the given command supported by the EC. These version numbers start at 0.
## Transport-specific details
Although the command and response formats are the same across all transports,
some details of how they are transmitted differ, which may be of interest when
implementing the EC side of the protocol on a new chip.
### I<sup>2</sup>C
I<sup>2</sup>C is very flexible with its timing, so when the EC receives a
packet from the host, it should stretch the clock, holding it low until it is
ready for the host to read the response.
If the host tries to read more bytes than were in the response, the EC should
respond with an obvious filler byte (such as 0xEC). For example, if a command
that normally returns 50 bytes errors, its response will only be 8 bytes (the
size of the response struct). The host will probably try to read 50 bytes
anyway, so the EC should send the 8 bytes of the struct followed by 42 copies of
the filler byte.
### SPI
The SPI bus is similar to I<sup>2</sup>C, but with two major exceptions. First,
there's a minimum speed on the SPI bus. If slave devices don't respond quickly
enough, the master will assume they're broken and give up. Second, every
transaction is bidirectional. When bits are being clocked from master to slave
on the MOSI line, the master will simultaneously read bits in the other
direction on the MISO line.
Hardware devices can usually handle this, and often some hardware-based flow
control used to "stretch" the transaction by a bit or byte if the slave device
needs a little extra time to respond to the master's demands.
When exchanging messages with the EC on the SPI bus, the EC's host commands are
communicated using our own software flow-control scheme, because most of the
embedded controllers either aren't fast enough or don't have any support for
hardware flow-control.
It works like this: When the AP sends a byte to the EC, if the EC doesn't have a
response queued up in advance, a default byte is returned. The EC
preconfigures that default response byte to indicate its status (ready, busy,
waiting for more input, etc.). Once the AP has sent a complete command message,
it continues clocking bytes to the EC (which the EC ignores) and just looks at
the response byte that comes back. Once the EC has parsed the AP's command and
is ready to reply, it sends a "start of frame" byte, followed by the actual
response. The AP continues to read and ignore bytes from the EC until it sees
the start of frame byte, and then it knows that the EC's response is starting
with the next byte.
Once the response packet has been read, any additional reads should return
`EC_SPI_PAST_END`.
### LPC or eSPI
The EC should set `EC_LPC_STATUS_PROCESSING` in its command status register
after receiving a host packet and before it has a response ready.
[`cros-ec` Kernel driver]: https://chromium.googlesource.com/chromiumos/third_party/kernel/+/refs/heads/chromeos-4.19/drivers/mfd/cros_ec_dev.c
[Industrial I/O]: https://www.kernel.org/doc/html/v4.14/driver-api/iio/index.html
[host command task]: https://chromium.googlesource.com/chromiumos/platform/ec/+/refs/heads/master/common/host_command.c
[Transport-specific details]: #Transport_specific-details

View File

@ -1,2 +1,5 @@
The has been moved into a [different
branch](https://chromium.googlesource.com/chromiumos/platform/ec/+/cr50_stab/docs/case_closed_debugging.md)
*** note
**Warning: This document is old & has moved. Please update any links:**<br>
https://chromium.googlesource.com/chromiumos/platform/ec/+/HEAD/docs/case_closed_debugging.md
***

View File

@ -1,2 +1,5 @@
The has been moved into a [different
branch](https://chromium.googlesource.com/chromiumos/platform/ec/+/cr50_stab/docs/case_closed_debugging_cr50.md)
*** note
**Warning: This document is old & has moved. Please update any links:**<br>
https://chromium.googlesource.com/chromiumos/platform/ec/+/HEAD/docs/case_closed_debugging_cr50.md
***

View File

@ -1,2 +1,5 @@
The has been moved into a [different
branch](https://chromium.googlesource.com/chromiumos/platform/ec/+/cr50_stab/docs/ccd_howtos.md)
*** note
**Warning: This document is old & has moved. Please update any links:**<br>
https://chromium.googlesource.com/chromiumos/platform/ec/+/HEAD/docs/ccd_howtos.md
***

View File

@ -1,34 +1,5 @@
# Code Coverage
*** note
**Warning: This document is old & has moved. Please update any links:**<br>
https://chromium.googlesource.com/chromiumos/platform/ec/+/HEAD/docs/code_coverage.md
***
Provides an overview of how to use code coverage tools when running the unit
tests in the EC codebase.
[TOC]
## Availability
Code coverage is only available for host-based unit tests, as opposed to
manual tests that run on target hardware.
## Building for code coverage
To build host-based unit tests for code coverage, invoke `make` with the
`coverage` target, as follows:
`make coverage -j`
This target will compile and link the unit tests with `--coverage` flag (which
pulls in the `gcov` libraries), run the tests, and then process the profiling
data into a code coverage report using the `lcov` and `genhtml` tools.
The coverage report top-level page is `build/coverage/coverage_rpt/index.html`.
### Noise in the build output
When building for code coverage, you may see multiple warnings of the form
`geninfo: WARNING: no data found for /mnt/host/source/src/platform/ec/core/host/cpu.h`
and
`genhtml: WARNING: function data mismatch at /mnt/host/source/src/platform/ec/common/math_util.c:134`
These warnings can be ignored. (FYI, the "function data mismatch" warnings
appear to be caused in part by using relative paths instead of absolute paths.)

View File

@ -1,54 +1,5 @@
# Code Reviews
*** note
**Warning: This document is old & has moved. Please update any links:**<br>
https://chromium.googlesource.com/chromiumos/platform/ec/+/HEAD/docs/code_reviews.md
***
The `platform/ec` repository makes use of a code review system that tries to
evenly distribute code reviews among available reviewers.
[TOC]
## How to request a review
Add `cros-ec-reviewers@google.com` to the reviewer line in Gerrit. A background
job will come around and replace the `cros-ec-reviewers@google.com` address with
the next available reviewer in the EC reviewer rotation. This typically takes on
the order of minutes.
Optionally, you can click the [FIND OWNERS] button in the UI, and select
`cros-ec-reviewers@google.com`.
## When to use review system
If you are modifying code in `common/`, `chip/`, or `core/`, feel free to use
the `cros-ec-reviewers@google.com` system. It is **never** a requirement to use
`cros-ec-reviewers@google.com`. You can always request a review from a specific
person.
## Responsibilities of reviewers
If the selected reviewer is unfamiliar with code in a CL, then that reviewer
should at least ensure that EC style and paradigms are being followed. Once EC
styles and paradigms are being followed, then the reviewer can give a +1 and add
the appropriate domain expert for that section of code.
Reviewers should try to give an initial response within 1 business day of
receiving a review request. Thereafter, they should try to respond to new
comments by the author within 1 business day.
## Review guidelines
Authors and reviewers should follow the Chrome OS firmware review
[guidelines][2] while publishing and reviewing code.
## How can I join the rotation?
Add your name to the [list of reviewers][1].
## Reference
* [Chrome OS firmware review guidelines][2]
* [Coreboot Gerrit Guidelines][3]
* [Google small CL guidelines][5]
[1]: http://google3/chrome/crosinfra/gwsq/ec_reviewers
[2]: http://chromium.googlesource.com/chromiumos/docs/+/master/firmware_code_reviews.md
[3]: https://doc.coreboot.org/getting_started/gerrit_guidelines.html
[5]: https://google.github.io/eng-practices/review/developer/small-cls.html

View File

@ -1,253 +1,5 @@
# Configure AP Power Sequencing
*** note
**Warning: This document is old & has moved. Please update any links:**<br>
https://chromium.googlesource.com/chromiumos/platform/ec/+/HEAD/docs/configuration/ap_power_sequencing.md
***
This section details the configuration related to managing the system power
states (G3, S5, S3, S0, S0iX, etc). This includes the following tasks:
- Selecting the AP chipset type.
- Configure output GPIOs that enable voltage rails.
- Configure input GPIOs that monitor the voltage rail status (power good
signals).
- Configure input GPIOs that monitor the AP sleep states.
- Pass through power sequencing signals from the board to the AP, often with
delays or other sequencing control.
## Config options
The AP chipset options are grouped together in [config.h]. Select exactly one of
the available AP chipset options (e.g. `CONFIG_CHIPSET_APOLLOLAKE`,
`CONFIG_CHIPSET_BRASWELL`, etc). If the AP chipset support is not available,
select `CONFIG_CHIPSET_ECDRIVEN` to enable basic support for handling S3 and S0
power states.
After selecting the chipset, search for additional options that start with
`CONFIG_CHIPSET*` and evaluate whether each option is appropriate to add to
`baseboard.h` or `board.h`.
Finally, evaluate the `CONFIG_POWER_` options for use on your board. In
particular, the `CONFIG_POWER_BUTTON`, and `CONFIG_POWER_COMMON` should be
defined.
The `CONFIG_BRINGUP` option is especially useful option during the initial power
up of a new board. This option is discussed in more detail in the [Testing and
Debugging](#Testing-and-Debugging) section.
## Feature Parameters
None needed in this section.
## GPIOs and Alternate Pins
### EC Outputs to the board
The board should connect the enable signal of one or more voltage rails to the
EC. These enable signals will vary based on the AP type, but are typically
active high signals. For Intel Ice Lake chipsets, this includes enable signals
for the primary 3.3V and primary 5V rails.
```c
GPIO(EN_PP3300_A, PIN(A, 3), GPIO_OUT_LOW)
GPIO(EN_PP5000, PIN(A, 4), GPIO_OUT_LOW)
```
### EC Outputs to AP
For boards with an x86 AP, the following signals can be connected between the EC
and AP/PCH. Create `GPIO()` entries for any signals used on your board.
- `GPIO_PCH_PWRBTN_L` - Output from the EC that proxies the status of the EC
input `GPIO_POWER_BUTTON_L` (driven by the H1). Only used when
`CONFIG_POWER_BUTTON_X86` is defined.
- `GPIO_PCH_RSMRST_L` - Output from the EC that proxies the status of the EC
input `GPIO_RSMRST_L_PGOOD` (driven by the PMIC or voltage regulators on the
board).
- `GPIO_PCH_SYS_PWROK` - Output from the EC that indicates when the system power
is good and the AP can power up.
- `GPIO_PCH_WAKE_L` - Output from the EC, driven low when there is a wake event.
### Power Signal Interrupts
For each power signal defined in the `power_signal_list[]` array, define a
`GPIO_INT()` entry that connects to the `power_signal_interrupt`. The interrupts
are configured to trigger on both rising edge and falling edge.
The example below shows the power signals used with Ice Lake processors.
```c
GPIO_INT(SLP_S0_L, PIN(D, 5), GPIO_INT_BOTH, power_signal_interrupt)
GPIO_INT(SLP_S3_L, PIN(A, 5), GPIO_INT_BOTH, power_signal_interrupt)
GPIO_INT(SLP_S4_L, PIN(D, 4), GPIO_INT_BOTH, power_signal_interrupt)
GPIO_INT(PG_EC_ALL_SYS_PWRGD, PIN(F, 4), GPIO_INT_BOTH, power_signal_interrupt)
GPIO_INT(PP5000_A_PG_OD, PIN(D, 7), GPIO_INT_BOTH, power_signal_interrupt)
```
See the [GPIO](./gpio.md) documentation for additional details on the GPIO
macros.
## Data structures
- `const struct power_signal_info power_signal_list[]` - This array defines the
signals from the AP and from the power subsystem on the board that control the
power state. For some Intel chipsets, including Apollo Lake and Ice Lake, this
power signal list is already defined by the corresponding chipset file under
the `./power` directory.
## Tasks
The `CHIPSET` task monitors and handles the power state changes. This task
should always be enabled with a priority higher than the `CHARGER` task, but
lower than the `HOSTCMD` and `CONSOLE` tasks.
```c
TASK_NOTEST(CHIPSET, chipset_task, NULL, LARGER_TASK_STACK_SIZE) \
```
The `POWERBTN` and task should be enabled when using x86 based AP chipsets. The
typical priority is higher than the `CONSOLE` task, but lower than the `KEYSCAN`
task.
```c
TASK_ALWAYS(POWERBTN, power_button_task, NULL, LARGER_TASK_STACK_SIZE) \
```
## Testing and Debugging
During the first power on of prototype devices, it is recommended to enable
`CONFIG_BRINGUP`. This option prevents the EC from automatically powering on the
AP. You can use the EC console commands `gpioget` and `gpioset` to manually
check power good signals and enable power rails in a controlled manner. This
option also enables extra debug to log all power signal transitions to the EC
console. With `CONFIG_BRINGUP` enabled, you can trigger the automatic power
sequencing by running the `powerbtn` from the EC console.
The EC console displays the following text when `CONFIG_BRINGUP` is enabled:
```
WARNING: BRINGUP BUILD
```
Once you manually press the power button, or execute the `powerbtn` command, the
EC console displays both the power state changes and the detected transitions of
all power signals. An example is shown below.
```
> powerbtn
Simulating 200 ms power button press.
[6.790816 power button pressed]
[6.791133 PB pressed]
[6.791410 PB task 1 = pressed]
[6.791755 PB PCH pwrbtn=LOW]
[6.792049 PB task 10 = was-off, wait 199362]
RTC: 0x000067bc (26556.00 s)
[6.792786 power state 5 = G3->S5, in 0x0000]
[6.793190 Set EN_PP3300_A: 1]
[6.793905 SW 0x03]
[6.817627 Set PCH_DSW_PWROK: 1]
[6.818007 Pass thru GPIO_DSW_PWROK: 1]
[6.818351 Set EN_PP5000_A: 1]
RTC: 0x000067bc (26556.00 s)
[6.903830 power state 1 = S5, in 0x0029]
[6.918735 Pass through GPIO_RSMRST_L_PGOOD: 1]
i2c 7 recovery! error code is 13, current state is 0
Simulating power button release.
> [6.991576 power button released]
[6.992009 PB task 10 = was-off]
[6.992376 PB released]
[6.992635 PB task 6 = released]
[6.992958 PB PCH pwrbtn=HIGH]
[6.993256 PB task 0 = idle, wait -1]
[6.993806 PB released]
[6.994149 PB task 6 = released]
[6.994512 PB PCH pwrbtn=HIGH]
[6.994812 PB task 0 = idle, wait -1]
[6.995768 SW 0x01]
3 signal changes:
6.807298 +0.000000 DSW_PWROK => 1
6.903417 +0.096119 SLP_SUS_L => 1
6.908471 +0.005054 PG_EC_RSMRST_ODL => 1
1 signal changes:
7.909941 +0.000000 SLP_S0_L => 1
[9.026429 Fan 0 stalled!]
RTC: 0x000067bf (26559.00 s)
[9.124643 power state 6 = S5->S3, in 0x003f]
i2c 3 recovery! error code is 13, current state is 0
[9.126543 mux config:2, port:1, res:1]
[9.127109 PD:S5->S3]
RTC: 0x000067bf (26559.00 s)
[9.127985 power state 2 = S3, in 0x003f]
RTC: 0x000067bf (26559.00 s)
[9.128640 power state 7 = S3->S0, in 0x003f]
```
This example shows successful power on of the AP as the AP transitions from the G3
state all the way to the S0 state.
The console messages shown in brackets `[]` include a timestamp. This timestamp
records when the corresponding console message was printed.
The power signal changes are preceded by the message `<N> signal changes:`.
Power signal changes are recorded at interrupt priority into a special buffer
and are not displayed in real time. Instead, printing of the buffer is deferred
until the EC is no longer executing at interrupt priority. This causes the power
signal changes shown on the console to be out of order with respect to the other
EC messages.
The power signal changes include a timestamp to help you correlate when the
actual power signal changed compared to other messages. From the example above,
the first power signal change recorded is the `DSW_PWROK` signal transitioning
from 0 to 1, and this is recorded at timestamp `6.807298`. Using the regular EC
console timestamp, you can reconstruct the real power sequence to look like the
following:
```
> powerb
Simulating 200 ms power button press.
[6.790816 power button pressed]
[6.791133 PB pressed]
[6.791410 PB task 1 = pressed]
[6.791755 PB PCH pwrbtn=LOW]
[6.792049 PB task 10 = was-off, wait 199362]
RTC: 0x000067bc (26556.00 s)
[6.792786 power state 5 = G3->S5, in 0x0000]
[6.793190 Set EN_PP3300_A: 1]
[6.793905 SW 0x03]
6.807298 +0.000000 DSW_PWROK => 1 // Manually re-ordered entry
[6.817627 Set PCH_DSW_PWROK: 1]
[6.818007 Pass thru GPIO_DSW_PWROK: 1]
[6.818351 Set EN_PP5000_A: 1]
RTC: 0x000067bc (26556.00 s)
6.903417 +0.096119 SLP_SUS_L => 1 // Manually re-ordered entry
[6.903830 power state 1 = S5, in 0x0029]
6.908471 +0.005054 PG_EC_RSMRST_ODL => 1 // Manually re-ordered entry
[6.918735 Pass through GPIO_RSMRST_L_PGOOD: 1]
i2c 7 recovery! error code is 13, current state is 0
Simulating power button release.
> [6.991576 power button released]
[6.992009 PB task 10 = was-off]
[6.992376 PB released]
[6.992635 PB task 6 = released]
[6.992958 PB PCH pwrbtn=HIGH]
[6.993256 PB task 0 = idle, wait -1]
[6.993806 PB released]
[6.994149 PB task 6 = released]
[6.994512 PB PCH pwrbtn=HIGH]
[6.994812 PB task 0 = idle, wait -1]
[6.995768 SW 0x01]
1 signal changes:
7.909941 +0.000000 SLP_S0_L => 1
[9.026429 Fan 0 stalled!]
RTC: 0x000067bf (26559.00 s)
[9.124643 power state 6 = S5->S3, in 0x003f]
i2c 3 recovery! error code is 13, current state is 0
[9.126543 mux config:2, port:1, res:1]
[9.127109 PD:S5->S3]
RTC: 0x000067bf (26559.00 s)
[9.127985 power state 2 = S3, in 0x003f]
RTC: 0x000067bf (26559.00 s)
[9.128640 power state 7 = S3->S0, in 0x003f]
```
*TODO ([b/147808790](http://issuetracker.google.com/147808790)) Add
documentation specific to each x86 processor type.*
[config.h]: ../new_board_checklist.md#config_h

View File

@ -1,38 +1,5 @@
# Configure CrOS Board Information (CBI)
*** note
**Warning: This document is old & has moved. Please update any links:**<br>
https://chromium.googlesource.com/chromiumos/platform/ec/+/HEAD/docs/configuration/cbi.md
***
If your board includes an EEPROM to store [CBI], then this feature must be
enabled and configured. Note that the [I2C buses] must be configured and working
before enabling CBI.
## Config options
Add the following config options to `baseboard.h` or `board.h`.
- `CONFIG_BOARD_VERSION_CBI`
- `CONFIG_CROS_BOARD_INFO`
## Feature Parameters
- `I2C_ADDR_EEPROM_FLAGS <7-bit addr>` - Defines the 7-bit slave address for the
EEPROM containing CBI.
## GPIOs and Alternate Pins
None needed - the I2C pins should be configured automatically when initializing
the I2C buses.
## Data Structures
None required by this feature.
## Tasks
None required by this feature.
## Testing and Debugging
Refer to the [I2C debugging information] to verify communication with the CBI EEPROM.
[CBI]: https://chromium.googlesource.com/chromiumos/docs/+/master/design_docs/cros_board_info.md
[I2C buses]: ./i2c.md
[I2C debugging information]: ./i2c.md#

View File

@ -1,73 +1,5 @@
# Configure AP to EC Communication
*** note
**Warning: This document is old & has moved. Please update any links:**<br>
https://chromium.googlesource.com/chromiumos/platform/ec/+/HEAD/docs/configuration/config_ap_to_ec_comm.md
***
This document provides details on how to configure the AP to EC communication
channel used on your board. The [AP to EC Communication] document provides
details a system level of the operation of this feature.
## Config options
Configure the AP to EC communication channel, picking exactly one of the
following options.
- `CONFIG_HOSTCMD_SPS` - [SPI slave](./ec_terms.md#spi) (SPS) interface
- `CONFIG_HOSTCMD_HECI` - HECI interface
- `CONFIG_HOSTCMD_LPC` - [LPC](./ec_terms.md#lpc) bus
- `CONFIG_HOSTCMD_ESPI` - [eSPI](./ec_terms.md#espi) bus
In [config.h], search for options that start with the same name as your selected
communication interface. Override defaults as needed.
## Feature Parameters
None needed in this section.
## GPIOs and Alternate Pins
The EC code requires the following signals between the AP and the EC to be
defined by each board variant.
- `GPIO_ENTERING_RW` - Output from the EC, active high signal indicates when the
EC code transitions from RO to RW code.
```c
GPIO(EC_ENTERING_RW, PIN(E, 3), GPIO_OUT_LOW)
```
- `GPIO_SYS_RESET_L` - Output from the EC, active low signal used to put the AP
into reset.
```c
GPIO(SYS_RST_ODL, PIN(C, 5), GPIO_ODR_HIGH)
```
Create `ALTERNATE()` entries for all EC signals used for AP communication. This
step can be skipped for any pins that default to communication channel
functionality.
See the [GPIO](./gpio.md) documentation for additional details on
the GPIO macros.
## Data structures
None needed in this section.
## Tasks
The `HOSTCMD` task is responsible for processing commands sent by the AP and is
always required. The typical priority is higher than the `CHIPSET` task, but
lower than the `CONSOLE` task.
```c
TASK_ALWAYS(HOSTCMD, host_command_task, NULL, LARGER_TASK_STACK_SIZE, 0) \
```
## Testing and Debugging
For Nuvoton EC chipsets, the file [./chip/npcx/registers.h] provides a
collection of `DEBUG_*` macros that can be used to enable extra console messages
related to a specific interface. For AP to EC communication, the `DEBUG_LPC`
and `DEBUG_ESPI` macros can help troubleshoot communication issues.
[./chip/npcx/registers.h]: ../../chip/npcx/registers.h
[AP to EC Communication]: ../ap-ec-comm.md
[config.h]: ../new_board_checklist.md#config_h

View File

@ -1,113 +1,5 @@
# Configure EC Chipset
*** note
**Warning: This document is old & has moved. Please update any links:**<br>
https://chromium.googlesource.com/chromiumos/platform/ec/+/HEAD/docs/configuration/ec_chipset.md
***
## Config options
The EC chipset is selected using board specific make file [build.mk]. The
following configuration options specify the type and size of flash memory used
by the EC.
- `CONFIG_SPI_FLASH_REGS` - Should always be defined when using internal or
external SPI flash.
- `CONFIG_SPI_FLASH` - Define only if your board uses an external flash.
- `CONFIG_SPI_FLASH_<device_type>` - Select exactly one the supported flash
devices to compile in the required driver. This is needed even when using
the internal SPI flash of the EC chipset.
- Additional EC Chipset options are prefixed with `CONFIG_HIBERNATE*` and
should be evaluated for relevance on your board.
## Feature Parameters
- `CONFIG_FLASH_SIZE <bytes>` - Set to the size of the internal flash of the
EC. Must be defined to link the final image.
- `CONFIG_SPI_FLASH_PORT <port>` - Only used if your board as an external
flash.
## GPIOs and Alternate Pins
Configure the signals which will wakeup the EC from hibernate or deep sleep.
Typical wakeup sources include:
- `GPIO_LID_OPEN` - An active high signal that indicates the lid has been
opened. The source of the signal is typically from a [GMR](../ec_terms.md#gmr)
or Hall-Effect sensor. The `GPIO_INT()` entry for this signal should be
connected to the `lid_interrupt()` routine.
- `GPIO_AC_PRESENT` - A signal from the battery charger that indicates the
device is connected to AC power. This signal is connected to the
`power_interrupt()` routine.
- `GPIO_POWER_BUTTON_L` - An active low signal from the power switch. This signal is connected to the `power_button_interrupt()` routine.
- `GPIO_EC_RST_ODL` - On some Nuvoton EC chipsets, the reset signal is
dual-routed to both a dedicated reset pin and a GPIO. In this case, no
interrupt handler needs to be registered to the GPIO signal, but the GPIO pin
must still be configured to wake on both edge types. The GPIO pin should also
be locked prevent the pin configuration from changing after the EC read-only
code runs.
See the [GPIO](./gpio.md) documentation for additional details on the GPIO
macros.
## Data structures
- `const enum gpio_signal hibernate_wake_pins[]` - add all GPIO signals that
should trigger a wakeup of the EC.
- `const int hibernate_wake_pins_used = ARRAY_SIZE(hibernate_wake_pins);` -
configures the number of wake signals used on the board.
All ChromeOS wake sources are documented on the ChromeOS partner site in the
[Wake Sources and Battery Life] section. The EC specific wake sources are found
under the Deep Sleep and Shipping states and include:
- Power button
- AC insert
- Lid open
## Tasks
None required by this feature.
## Testing and Debugging
## Example
For the Volteer reference board, the following wake sources are defined in
[gpio.inc]. Note that configuration of `GPIO(EC_RST_ODL)` is located after all
`GPIO_INT()` entries required by the board.
```c
/* Wake Source interrupts */
GPIO_INT(EC_LID_OPEN, PIN(D, 2), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, lid_interrupt)
GPIO_INT(EC_WP_L, PIN(A, 1), GPIO_INT_BOTH, switch_interrupt)
GPIO_INT(H1_EC_PWR_BTN_ODL, PIN(0, 1), GPIO_INT_BOTH, power_button_interrupt)
GPIO_INT(ACOK_OD, PIN(0, 0), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, extpower_interrupt)
/* EC_RST_ODL - PSL input but must be locked */
GPIO(EC_RST_ODL, PIN(0, 2), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH | GPIO_LOCKED)
```
For the NPCx7 chipset, the alternate function must also be configured to connect
the wakeup pins to the PSL (power switch logic).
```c
/* GPIOD2 = EC_LID_OPEN */
ALTERNATE(PIN_MASK(D, BIT(2)), 0, MODULE_PMU, 0)
/* GPIO00 = ACOK_OD,
GPIO01 = H1_EC_PWR_BTN_ODL
GPIO02 = EC_RST_ODL */
ALTERNATE(PIN_MASK(0, BIT(0) | BIT(1) | BIT(2)), 0, MODULE_PMU, 0)
```
The final step is to add the hibernate signals array to Volteer [baseboard.c] file:
```c
/* Wake up pins */
const enum gpio_signal hibernate_wake_pins[] = {
GPIO_LID_OPEN,
GPIO_ACOK_OD,
GPIO_POWER_BUTTON_L,
GPIO_EC_RST_ODL,
};
const int hibernate_wake_pins_used = ARRAY_SIZE(hibernate_wake_pins);
```
[gpio.inc]: ../../board/volteer/gpio.inc
[baseboard.c]: ../../baseboard/volteer/baseboard.c
[build.mk]: ../new_board_checklist.md#board_build_mk
[Wake Sources and Battery Life]: https://chromeos.google.com/partner/dlm/docs/latest-requirements/chromebook.html#wake-sources-and-battery-life

View File

@ -1,155 +1,5 @@
# GPIO Configuration
*** note
**Warning: This document is old & has moved. Please update any links:**<br>
https://chromium.googlesource.com/chromiumos/platform/ec/+/HEAD/docs/configuration/gpio.md
***
GPIO setup is done for every board variant, but never for the baseboard, by
configuring the file `./board/<board>/gpio.inc`. This file configures all the
the pins on the EC chipset through the following macros.
- `GPIO(<name>, ...)` - Configures simple GPIO input and outputs
- `GPIO_INT(<name>, ...)` - Configures GPIO inputs that connect to an interrupt
service routine. Historically these entries are defined first, but this no
longer required.
- `ALTERNATE(...)` - Configures a pin for an alternate function (e.g I2C, ADC,
SPI, etc)
- `UNIMPLEMENTED(<name>, ...)` - Creates a fake GPIO entry
The `GPIO()`, `GPIO_INT()`, and `UNIMPLEMENTED()` macros create a C enumeration
of the form `GPIO_<name>` that can be used in the code. As noted in [GPIO
Naming](../new_board_checklist.md#GPIO-Naming), the `<name>` parameter should
always match the schematic net name.
## `GPIO()` macro
### Prototype
`GPIO(name, pin, flags)`
- `name` - Defines the schematic net name, which is expanded to the enumeration
`GPIO_name` by the macro.
- `pin` - Use the `PIN(group,pin)` macro to define the GPIO group and pin
number. Note that on a few EC chipsets, the PIN macro is just `PIN(pin)`.
- `flags` - Define attributes of the pin (direction, pullup/pulldown, open
drain, voltage level, etc). All supported flags are found following the
`GPIO_FLAG_NONE` definition in [./include/gpio.h](../../include/gpio.h).
### Example
![GPIO Example]
```c
GPIO(EC_ENTERING_RW, PIN(E, 3), GPIO_OUT_LOW)
```
The EC common code requires the enum `GPIO_ENTERING_RW` to be defined, so you
should also map the net name to the EC name in the `board.h` file.
```c
#define GPIO_ENTERING_RW GPIO_EC_ENTERING_RW
```
## `GPIO_INT()` macro
### Prototype
`GPIO_INT(name, pin, flags, signal)`
- `name` - Defines the schematic net name, which is expanded to the enumeration
`GPIO_name` by the macro.
- `pin` - Same definition as `GPIO()` macro.
- `flags` - Same definition as `GPIO()` macro. Should always have one of the
`GPIO_INT_*` flags set.
- `signal` - Interrupt service routine called when the pin asserts according to
the flags set.
### Example
![GPIO_INT Example]
```c
GPIO_INT(EC_LID_OPEN, PIN(D, 2), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, lid_interrupt)
```
The EC common code requires the enum `GPIO_LID_OPEN` to be defined, so you als
need to map the net name to the EC name in the `board.h` file.
```c
#define GPIO_LID_OPEN GPIO_EC_LID_OPEN
```
## `ALTERNATE()` macro
### Prototype
`ALTERNATE(pinmask, function, module, flags)`
- `pinmask` - Defines a set of pins in the same GPIO group to assign to a
different function.
- `function` - A chip-specific function number. Only used if the EC chipset
provides multiple alternate functions in addition to GPIO (e.g. pin can be
UART, I2C, SPI, or GPIO). The permitted values for this parameter vary based
on the EC chipset type.
- STM32 - 0 to 7
- Maxim - 1 to 3
- Microchip - 0 to 3
- MediaTek - 0 to 7
- All others (Nuvton, ITE, TI Stellaris, ) only support one alternate
function per pin, so this parameter should be set to 0.
- `module` - One of the enum module_id values defined in
[./include/module_id.h](../../include/module_id.h).
- `flags` - Same definition as `GPIO()` macro.
### Notes
At runtime there are two mechanisms for switching a pin between GPIO mode and
alternate function mode.
- `gpio_config_module(enum module_id id, int enable)` - Configures all pins
matching the module enumeration `id`.
- `gpio_config_pin(enum module_id id, enum gpio_signal signal, int enable)` -
Configures a single pin matching the GPIO enumeration `signal`.
For both routines, if `enable` is 1, then the corresponding pins are configured
for alternate mode operation. If `enable` is 0, then the corresponding pins are
configure for GPIO mode.
`gpio_config_module()` is automatically called at runtime for all enabled
interfaces (I2C, SPI, UART, etc). You can use `gpio_config_pin()` to temporarily
configure a pin for GPIO operation, and to restore the original alternate
function. The I2C bus error recovery employs this mechanism to temporarily
driver the I2C SCL and SDA signals to known states, without interference by the
I2C controller in the EC chipset.
The general recipe for overriding alternate functions is shown below.
```c
/* Disconnect I2C1_SDA pin from I2C controller */
gpio_config_pin(MODULE_I2C, GPIO_I2C1_SDA, 0);
/* Setup I2C1_SDA as an GPIO open drain output and drive initial state low */
gpio_set_flags(GPIO_I2C1_SDA, GPIO_ODR_LOW);
/* Set GPIO high (or low) as required */
gpio_set_level (GPIO_I2C1_SDA, 1);
/* Restore I2C1_SDA pin to I2C function */'
gpio_config_pin(MODULE_I2C, GPIO_I2C1_SDA, 1);
```
### Example
![ALTERNATE Example]
```c
ALTERNATE(PIN_MASK(B, BIT(4) | BIT(5)), 0, MODULE_I2C, (GPIO_INPUT | GPIO_SEL_1P8V))
```
<!-- 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/18cWTYQRRCpypYDOLlvKQJTObwcj6wOjUga02B0oZXBg -->
[GPIO Example]: ../images/gpio_example.png
<!-- https://docs.google.com/drawings/d/1X6p5XfB6BBmUUKCrwOg56Bz6LZj9P_WPQXsOdk-OIiI -->
[GPIO_INT Example]: ../images/gpio_int_example.png
<!-- https://docs.google.com/drawings/d/1-kroVezQuA_KdQLzqYPs8u94EBg37z3k6lKzkSLRv-0 -->
[ALTERNATE Example]: ../images/alternate_example.png

View File

@ -1,204 +1,5 @@
# Configure I2C Buses
*** note
**Warning: This document is old & has moved. Please update any links:**<br>
https://chromium.googlesource.com/chromiumos/platform/ec/+/HEAD/docs/configuration/i2c.md
***
## Config options
The I2C options are prefixed with `CONFIG_I2C*`. Evaluate whether each option is
appropriate to add to your board.
A typical EC and board should at a minimum set `CONFIG_I2C` and
`CONFIG_I2C_CONTROLLER`.
## Feature Parameters
The following parameters control the behavior of the I2C library. [config.h]
defines a reasonable default value, but you may need to change the default value
for your board.
- `CONFIG_I2C_CHIP_MAX_TRANSFER_SIZE <bytes>`
- `CONFIG_I2C_NACK_RETRY_COUNT <count>`
- `CONFIG_I2C_EXTRA_PACKET_SIZE <bytes>` - Only used on STM32 EC's if
`CONFIG_HOSTCMD_I2C_ADDR_FLAGS` is defined.
## GPIOs and Alternate Pins
In the gpio.inc file, you need to define a GPIO for the clock (SCL) and data
(SDA) pin used on each active I2C bus. The corresponding GPIOs are then included
in the `i2c_ports[]` array. This permits the I2C library to perform common bus
recovery actions using bit-banging without involvement by the EC-specific I2C
device driver.
You also need to define the alternate function assignment for all I2C pins using
the `ALTERNATE()` macro. This step can be skipped for any pins that default to
I2C functionality.
Note that many I2C buses only support 1.8V operation. This is determined by I2C
devices connected to the bus. In this case you need to include `GPIO_SEL_1P8V`
as part of the `flags` field in both the `GPIO()` and `ALTERNATE()` macros. I2C
bus 0 in the example below demonstrates configuring the SCL and SDA pins for
1.8V operation.
See the [GPIO](./gpio.md) documentation for additional details on the GPIO
macros.
## Data Structures
- `const struct i2c_port_t i2c_ports[]` - This array should be defined in your
baseboard.c or board.c file. This array defines the mapping of internal I2C
port numbers used by the I2C library to the physical I2C ports connected to
the EC.
- `const unsigned int i2c_port_used = ARRAY_SIZE(i2c_ports)` - Defines the
number of internal I2C ports accessible by the I2C library.
## Tasks
None required by this feature.
## Testing and Debugging
### Console Commands
- `i2cscan` - Provides a quick look of all I2C devices found on all configured
buses.
- `i2cxfer` - Allows you to read and write individual registers on an I2C
device.
For runtime troubleshooting of an I2C device, enable and the [I2C
tracing](../i2c-debugging.md) module to log all I2C transactions initiated by
the EC code.
## Example
The image below shows the I2C bus assignment for the Volteer reference board.
![I2C Example]
The `gpio.inc` file for Volteer defines both `GPIO()` and `ALTERNATE()` entries for
all I2C buses used in the design.
```c
/* I2C pins - Alternate function below configures I2C module on these pins */
GPIO(EC_I2C0_SENSOR_SCL, PIN(B, 5), GPIO_INPUT | GPIO_SEL_1P8V)
GPIO(EC_I2C0_SENSOR_SDA, PIN(B, 4), GPIO_INPUT | GPIO_SEL_1P8V)
GPIO(EC_I2C1_USB_C0_SCL, PIN(9, 0), GPIO_INPUT)
GPIO(EC_I2C1_USB_C0_SDA, PIN(8, 7), GPIO_INPUT)
GPIO(EC_I2C2_USB_C1_SCL, PIN(9, 2), GPIO_INPUT)
GPIO(EC_I2C2_USB_C1_SDA, PIN(9, 1), GPIO_INPUT)
GPIO(EC_I2C3_USB_1_MIX_SCL, PIN(D, 1), GPIO_INPUT)
GPIO(EC_I2C3_USB_1_MIX_SDA, PIN(D, 0), GPIO_INPUT)
GPIO(EC_I2C5_POWER_SCL, PIN(3, 3), GPIO_INPUT)
GPIO(EC_I2C5_POWER_SDA, PIN(3, 6), GPIO_INPUT)
GPIO(EC_I2C7_EEPROM_SCL, PIN(B, 3), GPIO_INPUT)
GPIO(EC_I2C7_EEPROM_SDA, PIN(B, 2), GPIO_INPUT)
/* Alternate functions GPIO definitions */
ALTERNATE(PIN_MASK(B, BIT(5) | BIT(4)), 0, MODULE_I2C, (GPIO_INPUT | GPIO_SEL_1P8V)) /* I2C0 */
ALTERNATE(PIN_MASK(9, BIT(0) | BIT(2) | BIT(1)), 0, MODULE_I2C, 0) /* I2C1 SCL / I2C2 */
ALTERNATE(PIN_MASK(8, BIT(7)), 0, MODULE_I2C, 0) /* I2C1 SDA */
ALTERNATE(PIN_MASK(D, BIT(1) | BIT(0)), 0, MODULE_I2C, 0) /* I2C3 */
ALTERNATE(PIN_MASK(3, BIT(3) | BIT(6)), 0, MODULE_I2C, 0) /* I2C5 */
ALTERNATE(PIN_MASK(B, BIT(3) | BIT(2)), 0, MODULE_I2C, 0) /* I2C7 */
```
The `i2c_ports[]` array requires the `.port` field to be assigned to an EC
chipset specific enumeration. For the NPCx7 I2C bus names are defined in
[./chip/npcx/registers.h]. The Volteer `baseboard.h` file creates a mapping
from the schematic net name to the NPCx7 I2C bus enumeration.
```c
#define CONFIG_I2C
#define I2C_PORT_SENSOR NPCX_I2C_PORT0_0
#define I2C_PORT_USB_C0 NPCX_I2C_PORT1_0
#define I2C_PORT_USB_C1 NPCX_I2C_PORT2_0
#define I2C_PORT_USB_1_MIX NPCX_I2C_PORT3_0
#define I2C_PORT_POWER NPCX_I2C_PORT5_0
#define I2C_PORT_EEPROM NPCX_I2C_PORT7_0
```
The last piece for I2C configuration is to create the `i2c_ports[]` array using
the macros and enumerations added to `baseboard.h` and `gpio.inc`.
```c
/* I2C port map configuration */
const struct i2c_port_t i2c_ports[] = {
{
.name = "sensor",
.port = I2C_PORT_SENSOR,
.kbps = 400,
.scl = GPIO_EC_I2C0_SENSOR_SCL,
.sda = GPIO_EC_I2C0_SENSOR_SDA,
.flags = 0,
},
{
.name = "usb_c0",
.port = I2C_PORT_USB_C0,
/*
* I2C buses used for PD communication must be set for 400 kbps
* or greater. Set to the maximum speed supported by all devices.
*/
.kbps = 1000,
.scl = GPIO_EC_I2C1_USB_C0_SCL,
.sda = GPIO_EC_I2C1_USB_C0_SDA,
},
{
.name = "usb_c1",
.port = I2C_PORT_USB_C1,
/*
* I2C buses used for PD communication must be set for 400 kbps
* or greater. Set to the maximum speed supported by all devices.
*/
.scl = GPIO_EC_I2C2_USB_C1_SCL,
.sda = GPIO_EC_I2C2_USB_C1_SDA,
},
{
.name = "usb_1_mix",
.port = I2C_PORT_USB_1_MIX,
.kbps = 100,
.scl = GPIO_EC_I2C3_USB_1_MIX_SCL,
.sda = GPIO_EC_I2C3_USB_1_MIX_SDA,
},
{
.name = "power",
.port = I2C_PORT_POWER,
.kbps = 100,
.scl = GPIO_EC_I2C5_POWER_SCL,
.sda = GPIO_EC_I2C5_POWER_SDA,
},
{
.name = "eeprom",
.port = I2C_PORT_EEPROM,
.kbps = 400,
.scl = GPIO_EC_I2C7_EEPROM_SCL,
.sda = GPIO_EC_I2C7_EEPROM_SDA,
},
};
const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports);
```
The `.flags` field is optional when using the default I2C bus setup. See
[./include/i2c.h] for the full list of supported flags.
The flag `I2C_PORT_FLAG_DYNAMIC_SPEED` allows the I2C bus frequency to be
changed at runtime. The typical use case is to set the I2C bus frequency to
different speeds based on the BOARD_VERSION in [CBI]. For example board version
1 supports 100 kbps operation but board version 2 and greater supports 400 kbps
operation. `I2C_PORT_FLAG_DYNAMIC_SPEED` is not used to change the I2C bus
frequency on the fly depending on the addressed slave device.
An example of changing the I2C bus frequency from the [Kodama
board](../../board/kodama/board.c) is shown below.
```c
static void board_i2c_init(void)
{
if (board_get_version() < 2)
i2c_set_freq(1, I2C_FREQ_100KHZ);
}
DECLARE_HOOK(HOOK_INIT, board_i2c_init, HOOK_PRIO_INIT_I2C);
```
[config.h]: ../new_board_checklist.md#config_h
[./chip/npcx/registers.h]: ../../chip/npcx/registers.h
[./include/i2c.h]: ../../include/i2c.h
[I2C Example]: ../images/i2c_example.png
[CBI]: https://chromium.googlesource.com/chromiumos/docs/+/master/design_docs/cros_board_info.md

View File

@ -1,91 +1,5 @@
## Configure Keyboard
*** note
**Warning: This document is old & has moved. Please update any links:**<br>
https://chromium.googlesource.com/chromiumos/platform/ec/+/HEAD/docs/configuration/keyboard.md
***
## Config options
Keyboard options start with `CONFIG_KEYBOARD*`. Evaluate whether each option is
appropriate to add to `baseboard.h` or `board.h`.
Your board should select only one of these options to configure the protocol
used to send keyboard events to the AP.
- `CONFIG_KEYBOARD_PROTOCOL_8042` - Systems with an x86 AP use the 8042
protocol.
- `CONFIG_KEYBOARD_PROTOCOL_MKBP` - Systems without an x86 AP (e.g. ARM)
typically use the MKBP protocol.
## Feature Parameters
- `CONFIG_KEYBOARD_KSO_BASE <pin>` - Evaluate whether this parameter is required
by your board.
## GPIOs and Alternate Pins
Define `ALTERNATE()` pin entries for all keyboard matrix signals, to connect the
signals to the keyboard controller of the EC chipset.
Note that KSO_02 is purposely not configured for for alternate mode. See the [H1
Special Requirements](#H1-Special-Requirements) below for details.
```c
/* Example Keyboard pin setup */
#define GPIO_KB_INPUT (GPIO_INPUT | GPIO_PULL_UP)
ALTERNATE(PIN_MASK(3, 0x03), 0, MODULE_KEYBOARD_SCAN, GPIO_KB_INPUT) /* KSI_00-01 */
ALTERNATE(PIN_MASK(2, 0xFC), 0, MODULE_KEYBOARD_SCAN, GPIO_KB_INPUT) /* KSI_02-07 */
ALTERNATE(PIN_MASK(2, 0x03), 0, MODULE_KEYBOARD_SCAN, GPIO_ODR_HIGH) /* KSO_00-01 */
ALTERNATE(PIN_MASK(1, 0x7F), 0, MODULE_KEYBOARD_SCAN, GPIO_ODR_HIGH) /* KSO_03-09 */
ALTERNATE(PIN_MASK(0, 0xF0), 0, MODULE_KEYBOARD_SCAN, GPIO_ODR_HIGH) /* KSO_10-13 */
ALTERNATE(PIN_MASK(8, 0x04), 0, MODULE_KEYBOARD_SCAN, GPIO_ODR_HIGH) /* KSO_14 */
```
See the [GPIO](./gpio.md) documentation for additional details on the GPIO
macros.
## Data structures
- `struct keyboard_scan_config keyscan_config` - This must be defined if the
`CONFIG_KEYBOARD_BOARD_CONFIG` option is defined.
## Tasks
The `KEYSCAN` task monitors the keyboard matrix for new key presses and is
required by this feature. The priority is set as one of the highest priority
tasks in the system, typically only below the `PD_Cn` and `PD_INT_Cn` tasks.
```c
TASK_NOTEST(KEYSCAN, keyboard_scan_task, NULL, TASK_STACK_SIZE) \
```
The `KEYPROTO` task handles sending and receiving 8042 protocol messages from
the AP and is required when `CONFIG_KEYBOARD_PROTOCOL_8042` is used. The typical
priority is lower than the `HOSTCMD` task.
```c
TASK_NOTEST(KEYPROTO, keyboard_protocol_task, NULL, TASK_STACK_SIZE) \
```
## Additional Notes
- If you're including keyboard support, you should also define
`CONFIG_CMD_KEYBOARD` to enable keyboard debug commands from the EC console.
- `CONFIG_KEYBOARD_PROTOCOL_MKBP` automatically enables `CONFIG_MKBP_EVENT`.
- Boards that enable `CONFIG_KEYBOARD_PROTOCOL_8042` will often also define
`CONFIG_MKBP_EVENT` for sensor events. In this case only motion sensor data is
reported using the MKBP protocol, keyboard events are provided using the 8042
protocol. Refer to [Configuring Sensors](./motion_sensors.md) for more
information.
### H1 Special Requirements
On Boards that use the H1 secure microcontroller, one KSI (keyboard scan input)
signal and one KSO (keyboard scan output) signal are routed through the H1
microcontroller. There are additional GPIO and configuration options that must
be enabled in this case.
- The KSO_02/COL2 signal is always inverted. Explicitly configure the GPIO to
default low.
```c
GPIO(KBD_KSO2, PIN(1, 7), GPIO_OUT_LOW) /* KSO_02 inverted */
```
- Add the define `CONFIG_KEYBOARD_COL2_INVERTED` to `baseboard.h` or `board.h`.
- If required by the board, define one of the following options to configure the
KSI pin routed to the H1 microcontroller.
- `CONFIG_KEYBOARD_PWRBTN_ASSERTS_KSI2`
- `CONFIG_KEYBOARD_PWRBTN_ASSERTS_KSI3`

View File

@ -1,92 +1,5 @@
# Configure LEDs
*** note
**Warning: This document is old & has moved. Please update any links:**<br>
https://chromium.googlesource.com/chromiumos/platform/ec/+/HEAD/docs/configuration/leds.md
***
LEDs provide status about the following:
- Dedicated battery state/charging state
- Chromebook power
- Adapter power
- Left side USB-C port (battery state/charging state)
- Right side USB-C port (battery state/charging state)
- Recovery mode
- Debug mode
LEDs can be configured as simple GPIOs, with on/off control only, or as PWM with
adjustment brightness and color.
## Config options
In [config.h], search for options that start with `CONFIG_LED*` and evaluate
whether each option is appropriate to add to `baseboard.h` or `board.h`.
- `CONFIG_LED_COMMON` - Should be defined for both GPIO and PWM style LEDs.
- `CONFIG_LED_ONOFF_STATES` - used for GPIO controlled LEDs
- `CONFIG_LED_PWM` - used for PWM controlled LEDs. You must also define
`CONFIG_PWM` when using PWM controlled LEDs.
## Feature Parameters
- `CONFIG_LED_PWM_COUNT <count>` - Must be defined when using PWM LEDs
Override the following parameters when using PWM LEDs if you don't want to use
the recommended LED color settings.
- `CONFIG_LED_PWM_CHARGE_COLOR <ec_led_color>`
- `CONFIG_LED_PWM_NEAR_FULL_COLOR <ec_led_color>`
- `CONFIG_LED_PWM_CHARGE_ERROR_COLOR <ec_led_color>`
- `CONFIG_LED_PWM_SOC_ON_COLOR <ec_led_color>`
- `CONFIG_LED_PWM_SOC_SUSPEND_COLOR <ec_led_color>`
- `CONFIG_LED_PWM_LOW_BATT_COLOR <ec_led_color>`
## GPIOs and Alternate Pins
For GPIO based LEDs, create `GPIO()` entries for all signals that connect to
platform LEDs. The default state of the pins should be set so that the LED is
off (typically high output).
For PWM LEDs, configure the `ALTERNATE()` macro, setting the module type to
`MODULE_PWM`.
## Data structures
For GPIO based LEDs:
- `struct led_descriptor led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES]` -
Must be defined when `CONFIG_LED_ONOFF_STATES` is used. Defines the LED states
for the platform for various charging states.
For PWM based LEDs:
- `const enum ec_led_id supported_led_ids[]` - Defines the LED type for all PWM
LEDs in the system. See [./include/ec_commands.h] for a description of the
supported LED types.
- `struct pwm_led led_color_map[]` - Defines the PWM intensity of the individual
LEDs to generate the corresponding color. This table allows for custom tuning
of the LED brightness and color.
- `const struct pwm_channels[]` - Configures the PWM module, refer to the
[Configuring PWM](./pwm.md) section for details.
See the [GPIO](./gpio.md) documentation for additional details on the GPIO
macros.
## Tasks
None required by this feature.
## Testing and Debugging
### Console Commands
- `pwmduty` - *TODO* add description.
- `gpioset` - For GPIO based LEDs, this command lets you directly change the
state of the LED.
- `gpioget` - For GPIO based LEDs, this reads current state of the pin. If the
current state does not track changes made with `gpioset`, check your board for
stuck at high or stuck at low condition.
If you're having problems with a PWM LED, try reconfiguring the pin as a GPIO to
verify the board operation independent of the PWM module.
## LED Driver Chips
LED driver chips are used to control the LCD panel backlight. The backlight
control is separate from the platform LEDs.
[config.h]: ../new_board_checklist.md#config_h
[./include/ec_commands.h]: ../../include/ec_commands.h

View File

@ -1,52 +1,5 @@
# Configure Motion Sensors
EC sensors are used for the following capabilities:
- Accelerometers in base and lid measure lid angle to toggle between laptop and
tablet modes.
- Ambient light sensors control display backlight level.
- All sensor types, including gyroscope, e-compass, and pressure, are used by
Android apps.
- Special sync sensor type, synchronizes sensor events with AP.
*TODO* - there is good content available in the most recent [Chrome EC] overview
presentation that can be added here.
## Config options
*TODO*
## Feature Parameters
*TODO*
## GPIOs and Alternate Pins
*TODO*
- `GPIO_EC_INT_L` - Output from the EC, driven low to indicate an event on the
EC is ready for servicing by the AP.
## Data Structures
*TODO*
## Tasks
*TODO*
## Testing and Debugging
*TODO*
### Console Commands
*TODO*
## Example
*TODO*
[Chrome EC]: https://docs.google.com/presentation/d/1Y3PwNSnCQoCqDfL5rYqfaBP_ZqbMOTw_x83_ry4cro8/view#slide=id.g63bdbcea4b_0_27
*** note
**Warning: This document is old & has moved. Please update any links:**<br>
https://chromium.googlesource.com/chromiumos/platform/ec/+/HEAD/docs/configuration/motion_sensors.md
***

View File

@ -1,51 +1,5 @@
# EC Feature Configuration Template
*** note
**Warning: This document is old & has moved. Please update any links:**<br>
https://chromium.googlesource.com/chromiumos/platform/ec/+/HEAD/docs/configuration/template.md
***
*Short description of the EC feature and the capabilities provided*
## Config options
In [config.h], search for options that start with `CONFIG_<feature>*` and
evaluate whether each option is appropriate to add to `baseboard.h` or
`board.h`.
*Note - Avoid documenting `CONFIG_` options in the markdown as `config.h`
contains the authoritative definition.*
## Feature Parameters
*Detail `CONFIG_*` options that must be assigned to a value for this EC feature
to compile and operate.*
## GPIOs and Alternate Pins
*Document any hard-coded GPIO enumeration names required by the EC feature.*
*For pins that require an alternate function, note the module required by the EC
feature.*
## Data Structures
*Document any data structures that must be defined in the board.c or baseboard.c
files in order for the EC feature to compile and operate.*
*Document any functions that must be implemented in the board.c and baseboard.c
files.*
## Tasks
*Document any EC tasks that must be enabled by the feature.*
## Testing and Debugging
*Provide any tips for testing and debugging the EC feature.*
### Console Commands
*Document an EC console commands related to the feature.*
## Example
*Optional - provide code snippets from a working board to walk the user through
all code that must be created to enable this feature.*
[config.h]: ../new_board_checklist.md#config_h

View File

@ -1,329 +1,5 @@
# Chromium OS Embedded Controller Runtime
*** note
**Warning: This document is old & has moved. Please update any links:**<br>
https://chromium.googlesource.com/chromiumos/platform/ec/+/HEAD/docs/core_runtime.md
***
## Design Principles
1. Never do at runtime what you can do at compile time The goal is saving flash
space and computations. Compile-time configuration until you really need to
switch at runtime.
2. Real-time: guarantee low latency (eg < 20 us) no interrupt disabling ...
bounded code in interrupt handlers.
3. Keep it simple: design for the subset of microcontroller we use targeted at
32-bit single core CPU for small systems : 4kB to 64kB data RAM, possibly
execute-in-place from flash.
## Execution Contexts
This is a pre-emptible runtime with static tasks. It has only 2 possible
execution contexts:
- the regular [tasks](#tasks)
- the [interrupt handlers](#interrupts)
The initial startup is an exception as described in the
[dedicated paragraph](#startup).
### Tasks
The tasks are statically defined at compile-time. They are described for each
*board* in the [board/$board/ec.tasklist](../board/host/ec.tasklist) file.
They also have a static fixed priority implicitly defined at compile-time by
their order in the [ec.tasklist](../board/host/ec.tasklist) file (the top-most
one being the lowest priority aka *task* *1*). As a consequence, two different
tasks cannot have the same priority.
In order to store its context, each task has its own stack whose (*small*) size
is defined at compile-time in the [ec.tasklist](../board/host/ec.tasklist) file.
A task can normally be preempted at any time by either interrupts or higher
priority tasks, see the [preemption section](#scheduling-and-preemption) for
details and the [locking section](#locking-and-atomicity) for the few cases
where you need to avoid it.
### Interrupts
The hardware interrupt requests are connected to the interruption handling *C*
routines declared by the `DECLARE_IRQ` macros, through some chip/core specific
mechanisms (e.g. depending on whether we have a vectored interrupt controller,
slave interrupt controllers...)
The interrupts can be nested (ie interrupted by a higher priority interrupt).
All the interrupt vectors are assigned a priority as defined in their
`DECLARE_IRQ` macro. The number of available priority level is
architecture-specific (e.g. 4 on Cortex-M0, 8 on Cortex-M3/M4) and several
interrupt handlers can have the same priority. An interrupt handler can only be
interrupted by a handler having a priority **strictly** **greater** than its
own.
In most cases, the exceptions (e.g data/prefetch aborts, software interrupt) can
be seen as interrupts with a priority strictly greater than all IRQ vectors. So
they can interrupt any IRQ handler using the same nesting mechanism. All fatal
exceptions should ultimately lead to a reboot.
### Events
Each task has a *pending* events bitmap[1] implemented as a 32-bit word. Several
events are pre-defined for all tasks, the most significant bits on the 32-bit
bitmap are reserved for them : the timer pending event on bit 31
([see the corresponding section](#time)), the requested task wake (bit 29),
the event to kick the waiters on a mutex (bit 30), along with a few hardware
specific events. The 19 least significant bits are available for task-specific
meanings.
Those event bits are used in inter-task communication and scheduling mechanism,
other tasks **and** interrupt handlers can atomically set them to request
specific actions from the task. Therefore, the presence of pending events in a
task bitmap has an impact on its scheduling as described in the
[scheduling section](#scheduling-and-preemption). These requests are done using
the `task_set_event()` and `task_wake()` primitives.
The two typical use-cases are:
- a task sends a message to another task (simply use some common memory
structures [see explanation](#single-address-space) and want it to process
it now.
- a hardware IRQ occurred, and we need to do some long processing to respond
to it (e.g. an I2C transaction). The associated interrupt handler cannot do
it (for latency reason), so it will raise an event to ask a task to do it.
The task code chooses to consume them (or a subset of them) when it's running
through the `task_wait_event()` and `task_wait_event_mask()` primitives.
### Scheduling and Preemption
The system has a global bitmap[1] called `tasks_ready` containing one bit per
task and indicating whether it is *ready* *to* *run* (ie want/need to be
scheduled). The task ready bit can only be cleared when it's calling itself one
of the functions explicitly triggering a re-scheduling (e.g. `task_wait_event()`
or `task_set_event()`) **and** it has no pending event. The task ready bit is
set by any task or interrupt handler setting an event bit for the task (ie
`task_set_event()`).
The scheduling is based on (and *only* on) the `tasks_ready` bitmap (which is
derived from all the events bitmap of the tasks as explained above).
Then, the scheduling policy to find which task should run is just finding the
most significant bit set in the tasks_ready bitmap and schedule the
corresponding task.
Important note: the re-scheduling happens **only** when we are exiting the
interrupt context. It is done in a non-preemptible context (likely with the
highest priority). Indeed, a re-scheduling is actually needed only when the
highest priority task ready has changed. There are 3 distinct cases where this
can happen:
- an interrupt handler sets a new event for a task. In this case,
`task_set_event` will detect that it is executed in interrupt context and
record in the `need_resched_or_profiling` variable that it might need to
re-schedule at interrupt return. When the current interrupt is going to
return, it will see this bit and decide to take the slow path making a new
scheduling decision and eventually a context switch instead of the fast path
returning to the interrupt task.
- a task sets an event on another task. The runtime will trigger a software
interrupt to force a re-scheduling at its exit.
- the running task voluntarily relinquish its current execution rights by
calling `task_wait_event()` or a similar function. This will call the
software interrupt similarly to the previous case.
On the re-scheduling path, if the highest-priority ready task is not matching
the currently running one, it will perform a context-switch by saving all the
processor registers on the current task stack, switch the stack pointer to the
newly scheduled task, and restore the registers from the previously saved
context from there.
### Hooks and Deferred Functions
The lowest priority task (ie Task 1, aka TASK_ID_HOOKS) is reserved to execute
repetitive actions and future actions deferred in time without blocking the
current task or creating a dedicated task (whose stack memory allocation would
be wasting precious RAM).
The HOOKS task has a list of deferred functions and their next deadline. Every
time it is waken up, it runs through the list and calls the ones whose deadline
is expired. Before going back to sleep, it arms a timer to the closest deadline.
The deferred functions can be created using the `DECLARED_DEFERRED()` macro.
Similarly, the HOOK_SECOND and HOOK_TICK hooks are called periodically by the
HOOKS task loop (the *tick* duration is platform-defined and shorter than the
second).
Note: be specially careful about priority inversions when accessing resources
protected by a mutex (e.g. a shared I2C controller) in a deferred function.
Indeed being the lowest priority task, it might be de-scheduled for long time
and starve higher priority tasks trying to access the resource given there is no
priority boosting implemented for this case. Also, be careful about long delays
(> x 100us) in hook or deferred function handlers, since those will starve other
hooks of execution time. It is better to implement a state machine where you set
up a subsequent call to a deferred function than have a long delay in your
handler.
### Watchdog
The system is always protected against misbehaving tasks and interrupt handlers
by a hardware watchdog rebooting the CPU when it is not attended.
The watchdog is petted in the HOOKS task, typically by declaring a HOOK_TICK
doing it as regular intervals. Given this is the lowest priority task, this
guarantees that all tasks are getting some run time during the watchdog period.
Note: that's also why one should not sprinkle its code with `watchdog_reload()`
to paper over long-running routine issues.
To help debug bad sequences triggering watchdog reboots, most platforms
implement a warning mechanism defined under `CONFIG_WATCHDOG_HELP`. It's a timer
firing at the middle of the watchdog period if it hasn't been petted by then,
and dumping on the console the current state of the execution mainly to help
find a stuck task or handler. The normal execution is resumed though after this
alert.
### Startup
The startup sequence goes through the following steps:
- the assembly entry routine clears the .bss (uninitialized data), copies the
initialized data (and optionally the code if we are not executing from
flash), sets a stack pointer.
- we can jump to the `main()` C routine at this point.
- then we go through the hardware pre-init (before we have all the clocks to
run the peripherals normal) and init routines, in this rough order: memory
protection if any, gpios in their default state, prepare the interrupt
controller, set the clocks, then timers, enable interrupts, init the debug
UART and the watchdog.
- finally, start tasks.
For the tasks startup, initially only the HOOKS task is marked as ready, so it
is the first to start and can call all the HOOK_INIT handlers performing
initializations before actually executing any real task code. Then all tasks are
marked as ready, and the highest priority one is given the control.
During all the startup sequence until the control is given the first task, we
are using a special stack called 'system stack' which will be later re-used as
the interrupts and exception stack.
To prepare the first context switch, the code in `task_pre_init()` is stuffing
all the tasks stacks with a *fake* saved context whose program counter contains
the task start address, and the stack pointer is pointing to its reserved stack
space.
### Locking and Atomicity
The two main concurrency primitives are lightweight atomic variables and heavier
mutexes.
The atomic variables are 32-bit integers (which can usually be loaded/stored
atomically on the architecture we are supporting). The `atomic.h` headers
include primitives to do atomically various bit and arithmetic operations using
either load-linked/load-exclusive, store-conditional/store-exclusive or simple
depending on what is available.
The mutexes are actually statically allocated binary semaphores. In case of
contention, they will make the waiting task sleep (removing its ready bit) and
use the [event mechanism](#events) to wake-up the other waiters on unlocking.
Note: the mutexes are NOT triggering any priority boosting to avoid the priority
inversion phenomenon.
Given the runtime is running on single core CPU, spinlocks would be equivalent
to masking interrupts with `interrupt_disable()` spinlocks, but it's strongly
discouraged to avoid harming the real-time characteristics of the runtime.
## Time
### Time Keeping
In the runtime, the time is accounted everywhere using a **64-bit**
**microsecond** count since the microcontroller **cold** **boot**.
Note: The runtime has no notion of wall-time/date, even though a few platforms
have an RTC inside the microcontroller.
These microsecond timestamps are implemented in the code using the `timestamp_t`
type, and the current timestamp is returned by the `get_time()` function.
The time-keeping is preferably implemented using a 32-bit hardware free running
counter at 1Mhz plus a 32-bit word in memory keeping track of the high word of
the 64-bit absolute time. This word is incremented by the 32-bit timer rollback
interrupt.
Note: as a consequence of this implementation, when the 64-bit timestamp is read
in interrupt context in a handler having a higher priority than the timer IRQ
(which is somewhat rare), the high 32-bit word might be incoherent (off by one).
### Timer Event
The runtime offers *one* (and only one) timer per task. All the task timers are
multiplexed on a single hardware timer. (can be just a *match* *interrupt* on
the free running counter mentioned in the [previous paragraph](#time-keeping))
Every time a timer is armed or expired, the runtime finds the task timer having
the closest deadline and programs it in the hardware to get an interrupt. At the
same time, it sets the TASK_EVENT_TIMER event in all tasks whose timer deadline
has expired. The next deadline is computed in interrupt context.
Note: given each task has a **single** timer which is also used to wake-up the
task when `task_wait_event()` is called with a timeout, one needs to be careful
when using directly the `timer_arm()` function because there is an eventuality
that this timer is still running on the next `task_wait_event()` call, the call
will fail due to the lack of available timer.
## Memory
### Single Address Space
There is no memory isolation between tasks (ie they all live in the same address
space). Some architectures implement memory protection mechanism albeit only to
differentiate executable area (eg `.code`) from writable area (eg `.bss` or
`.data`) as there is a **single** **privilege** level for all execution
contexts.
As all the memory is implicitly shared between the task, the inter-task
communication can be done by simply writing the data structures in memory and
using events to wake the other task (given we properly thought the concurrent
accesses on those structures).
### Heap
The data structure should be statically allocated at compile time.
Note: there is no dynamic allocator available (e.g. `malloc()`), not due to
impossibility to create one but to avoid the negative side effects of having
one: ie poor/unpredictable real-time behavior and possible leaks leading to a
long-tail of failures.
- TODO: talk about shared memory
- TODO: where/how we store *panic* *memory* and *sysjump* *parameters*.
### Stacks
Each task has its own stack, in addition there is a system stack used for
startup and interrupts/exceptions.
Note 1: Each task stack is relatively small (e.g. 512 bytes), so one needs to be
careful about stack usage when implementing features.
Note 2: At the same time, the total size of RAM used by stacks is a big chunk of
the total RAM consumption, so their sizes need to be carefully tuned. (please
refer to the [debugging paragraph](#debugging) for additional input on this
topic.
## Firmware Code Organization and Multiple Copies
- TODO: Details the classical RO / RW partitions and how we sysjump.
## Power Management
- TODO: talk about the idle task + WFI (note: interrupts are disabled!)
- TODO: more about low power idle and the sleep-disable bitmap
- TODO: adjusting the microsecond timer at wake-up
## Debugging
- TODO: our main tool: serial console ... (but non-blocking / discard
overflow, cflush DO/DONT)
- TODO: else JTAG stop and go: careful with watchdog and timer
- TODO: panics and software panics
- TODO: stack size tuning and canarying
- TODO: Address the rest of the comments from https://crrev.com/c/445941
\[1]: bitmap: array of bits.

View File

@ -1,432 +1,5 @@
# Detachable Base Verified Boot
*** note
**Warning: This document is old & has moved. Please update any links:**<br>
https://chromium.googlesource.com/chromiumos/platform/ec/+/HEAD/docs/detachable_base_verified_boot.md
***
Authors: rspangler@google.com, drinkcat@google.com
Last Updated: 2016-11-16
Original: http://go/detachable-base-vboot
[TOC]
## Introduction
### What's a Base?
Detachable Chromebooks such as `Poppy` have a tablet-like `Lid` and a detachable
keyboard `Base`. Effectively, the `Base` is a USB keyboard+trackpad which plugs
into the `Lid`.
The `Lid` contains most of the components, including:
* AP
* ECDisplay
* Storage
* Battery
The `Base` connects to the `Lid` via USB pogo pins, and contains:
* EC ([STM32F072]). To minimize confusion with the main EC in the `Lid`, this
will always be called the `BaseEC`.
* Matrixed keyboard
* Touchpad
The `Base` always gets its power from the `Lid` USB port. This means that
attaching the base always triggers a power-on reset.
### Verified Boot Requirements
The `BaseEC` will be responsible for handling user input from the keyboard and
touchpad. This means that a compromised `BaseEC` could implement a keylogger. To
prevent this, we will use verified boot to protect the `BaseEC` firmware.
We need a way to securely update the `BaseEC` firmware from the AP. We cannot
use EC Software Sync as implemented on existing Chromebooks (and as still used
in the `Lid`) because the `Base` cannot trust that it is talking to an official
`Lid` firmware/OS. All the Base knows is that _something_ on the other end of
USB is trying to send it an update. So the BaseEC will need to do its own public
key verification of the firmware update. This includes rollback protection.
Updating the `BaseEC` firmware should not require rebooting the lid. This means
the update will take place after the OS has already booted on the lid. Ideally,
it should also not require the user to detach/reattach the base during the
update process. If the update takes longer than a few seconds, we should tell
the user, because the keyboard and trackpad will be unavailable during the
update.
The solution should also have low (or no) BOM cost, and minimal flash size
requirement.
## Proposal
`BaseEC` RO region includes a public key, whose private counterpart is kept
safely on our signers. On boot, RO checks RW signature (RW image is signed by
our signers), and will only jump to RW if the signature is valid.
We also include a rollback region (RB) to implement rollback protection (and
prevent rollback to a correctly signed, but compromised, RW). This region can
only be updated by RO.
We also devise a scheme to update RW firmware (the details are documented in
[EC Update over USB]).
Note: This proposal is very specific to the STM32 flash architecture. Other ECs
(particularly ones with external SPI flash) may need additional external logic
and/or a I2C EEPROM to hold the rollback info block.
### Flash
STM32F072 has 128KB flash, with 2KB erase sectors and 4KB protection blocks.
We will divide flash into three sections:
* `BaseEC`-RO firmware.
* Not updatable in production.
* Only capable of USB update, not keyboard/trackpad.
* Contains public key to verify RW image (RSA-3072).
* `BaseEC`-RW firmware.
* Fully functional.
* Updatable from AP.
* Signature (SHA-256 + RSA-3072).
* `BaseEC`-RB: Rollback info block (4KB).
* Contains minimum RW version that RO will accept to jump to.
* Updatable from RO.
Each of those sections can be locked independently: In production, RO is always
locked, and only RO can write to RB (RO will always make sure to lock RB before
jumping to RW).
Flash protection is a little entertaining on STM32:
* The flash protection bits for the \*next\* boot are stored in a non-volatile
`WRPx` register (in EC code, this is abstracted as
`EC_FLASH_PROTECT_[REGION]_AT_BOOT` flags)..
* On chip reset, `WRPx` is copied into a read-only `FLASH_WRPR` register; that
controls which blocks are protected for this boot. This is abstracted as
`EC_FLASH_PROTECT_[REGION]_NOW` in the EC code.
### Rollback Info Block
The Rollback Info Block (aka "RB") is a 4KB block of flash.
It has two 2KB erase sectors. We will ping-pong writes to those sectors, so that
interrupting power during an erase-write cannot cause data loss. If both sectors
are valid, the stricter (i.e. the highest value) of the 2 sectors is used.
We will use the RB to hold the following:
* Minimum **RW rollback firmware** version: a 32-bit integer. Used for
rollback protection. This number is independent of the actual EC version,
and is stored a 32-bit integer as part of the `BaseEC`-RW region (see
[CL:452815] for a possible implementation)
* A magic signature that indicates that the RB section is valid.
### RO Verified Boot Flow
#### Write-Protect RO think test before this handles corrupt RW.
Write protect of RO firmware works the same way it does now:
* Early RO code looks at a write protect (WP) GPIO and a global PSTATE
variable (part of the RO image itself). When we switch to RO that contains
the MP key, we set the PSTATE to locked.
* If both of those are set:
* RO code sets `EC_FLASH_PROTECT_RO_AT_BOOT` to protect itself. This
ensures RO code is never writable past this point.
* If `_AT_BOOT` flags protects more than the current write protect range
(`_NOW` flags), RO reboots so that changes take effect.
* Otherwise, someone has physically disconnected WP. Set `WRPx=0` to unprotect
all flash and reboot.
#### Check if AP Wants To Update RW
Next, RO needs to find out if the AP wants to update RW. RO initializes USB and
starts a 1 second timer to give the AP an opportunity to send a command before
RO jumps to RW. This delay gives us a way to regain control of the base, if the
previous RW firmware is properly signed but bad/nonfunctional.
That command can be:
* `STOP_IN_RO`: Yes, I might want to update you. Stick around.
* `UNLOCK_RW`: Tells EC to unlock RW region, if it is currently locked, so
that it can be reprogrammed. This also locks RB region. EC reboots if
needed.
* `JUMP_TO_RW`: No, I don't want to update you. Go ahead and jump to your RW
code if it verifies.
RO will start verifying RW while it waits for the AP to send it a command or for
the timeout. If a command is received, RO will stop the 1-second timer, and wait
for more commands from the AP. This allows the AP to update RW.
Verifying RW will take ~200 ms, and the AP should be able to send a command to
the base within ~100 ms of it appearing on USB, so this check should not cause
any delay to the base's boot process.
#### Verify RW
RO calculates the hash of RW.
* Use the public key stored in RO to check if the hash matches the RSA-signed
RW signature. On failure, go back to waiting for an update from the AP.
* Check the RW rollback version against the stored minimum version in RB. If
the RW version is too low, fail. Go back to waiting for an update from the
AP.
* If RO is protected, then also set `EC_FLASH_PROTECT_RW_AT_BOOT` so that RW
will be protected on the next boot, the reboot.
#### Roll Forward
If `EC_FLASH_PROTECT_ROLLBACK_NOW` is set (RB is protected), do not attempt to
roll forward. We know RW firmware is properly signed, but not if it's
functional.
If `EC_FLASH_PROTECT_ROLLBACK_NOW` is not set (RB is unprotected), \_and\_ the
RW signature is correct, then update RB:
* Erase/write the older sector of RB.
* Set the stored minimum version to the RW rollback version.
* If RO is protected, then also set `EC_FLASH_PROTECT_ROLLBACK_NOW` so that RB
will be protected on the next boot.
#### Jump to RW
If the 1-second timer for the AP to send a command to RO has not expired, RO
waits for it to expire or the AP to send a command, whichever happens first.
If RB or RW is unprotected (`EC_FLASH_PROTECT_RW/ROLLBACK_NOW` are not set),
protect it and reboot (we never want RW to be able to update RB on its own).
Otherwise, jump to RW firmware.
### RW Verified Boot Flow
RW firmware provides the keyboard and trackpad functionality.
#### AP Wants To Update RW
At some point the AP may want to update RW. To do so, it sends `UNLOCK_RW`
command, to ask RW to unlock itself and reboot, then follow the update steps
above.
#### AP Wants to Roll Forward RW
After the update, the base boots to the new RW firmware. At that point, the AP
knows the new RW firmware is good enough to talk to, so it tells RW to prepare
for roll forward.
* `UNLOCK_ROLLBACK` command: RW unprotects RB.
* On next boot (not necessarily urgent, but can be forced), RO will update RB
according to the steps above.
### Write Protect GPIO
The `BaseEC` needs a write protect (WP) GPIO signal to decide whether to keep RO
firmware protected or not. This is the same requirement as on existing ECs.
In an assembled base, the WP signal will be physically asserted. De-asserting
the signal requires disassembling the base and disconnecting something.
Typically, the `BaseEC` will apply a weak pull-up to the WP GPIO; the presence
of the WP screw/flex will short the pin to ground.
#### RO Updates During Development
If RO is unprotected (i.e. during development), RW can also update it.
If the key is \_not\_ the same (dev->premp, premp->mp updates) we can't update
RW first (it won't verify). These steps should work though, if current RW is
recent enough and stable enough to update RO:
* Make sure RW is active
* Update RO, reboot
* Update RW from RO
If the key is the same, we can update RW first.
### Signer, image format, and verification process
Memory map:
RO | RB | RW
------------------------------------------------- | --- | ---
`...` \| `Public key` \| `...` \| `FMAP` \| `...` | | `EC code and data` \| `Blank (0xff)` \| `Signature`
* RO contains an embedded RSA public key (`vb21_packed_key` format), at a
variable location.
* RW contains a signature (`vb21_signature`), packed at the end of the RW
region.
* The signature also contains the actual length of the EC code and image
(ignoring 0xff padding)
* RO validates signature against the provided length, then checks that the
rest of the RW region (up to the signature itself) is filled with ones
(padding).
* This speeds up verification significantly, as SHA-256 is an
expensive process.
* RO contains an FMAP that allows futility to find the RO key, RW region, and
RW signature location.
For re-signing, `futility` (rwsig type) does this:
* Look for FMAP to find RO public key RW region, and RW signature locations.
* Resign RW region, using the length provided in existing RW signature.
* Replace RO public key with the one used for signing.
`vb21_packed_key` (public key) has a field for key version, that we can use to
increment from dev keys, to premp, and final mp keys. BaseEC will need to report
the key version, to avoid incorrect updates.
## Example Boot / Update Flows
The base starts in the following state:
* Powered off
* WP GPIO is asserted
* PSTATE is set to protect RO firmware
* RW firmware is valid, and currently version M
* `EC_FLASH_PROTECT_[REGION]_AT_BOOT/_NOW` protects RO+RW+RB (that is,
everything)
All AP operations are done from the `Lid` OS.
Base updates will interrupt keyboard/trackpad functionality, so the user should
be informed when an update is taking place.
Reboots of the `Base` do not cause or require reboots of the `Lid`, do not
require action on the part of the user, and will not be visible to the user
(other than the previously noted lack of functionality).
### Power On, No Update
Step | RW | RB contents | `_AT_BOOT` | `_NOW`
--------------------------------------------------------------------------------------------- | --- | ----------- | ---------- | ------
(initial state) | M | 1/blank | RO/RW/RB | RO/RW/RB
1. RO waits 1 second for an update request from AP | | | |
2. RO verifies RW signature => RW is good | | | |
3. RO notes that `_AT_BOOT` and `_NOW` already protect everything, so no reboot is necessary. | | | |
4. RO jumps to RW | | | |
### Updating RW
Assume AP now has a new `BaseEC`-RW, version N>M. The base is already running RW
version M. In this card, the rollback version in both version is identical
("1"), so RB does not require an update.
Step | RW | RB contents | `_AT_BOOT` | `_NOW`
------------------------------------------------------- | --- | ----------- | -------------- | ------
RW is running | M | 1/blank | RO/RW/RB | RO/RW/RB
AP tells RW to prepare for an update (UNLOCK_RW) | | | |
RW unsets `EC_FLASH_PROTECT_RW_AT_BOOT` to unprotect RW | | | **RO/\_\_/RB** |
RW reboots to update `EC_FLASH_PROTECT_RW_NOW` | | | | **RO/\_\_/RB**
The next base boot is where the update takes place:
Step | RW | RB contents | `_AT_BOOT` | `_NOW`
---------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----- | ----------- | ------------ | ------
RO waits 2 seconds for an update request from the AP | M | 1/blank | RO/\_\_/RB | RO/\_\_/RB
AP tells RO an update is coming (`STOP_IN_RO`) | | | |
AP tells the user that a base update is taking place. UI should say: "Please don't be surprised that your keyboard and trackpad won't work for a few seconds..." | | | |
AP writes RW version N | **N** | | |
AP tells RO to reboot (`IMMEDIATE_RESET`) | | | |
RO reboots, verifies RW signature => RW is good | | | |
RO checks RW rollback version N (1) and sees it's greater or equal than RB rollback version 1. So, RW is good. | | | |
RO sets `RW_AT_BOOT` to protect RW on the next boot. | | | **RO/RW/RB** |
RO reboots | | | | **RO/RW/RB**
The next base boot is where we first run the new RW firmware.
### Roll forward
Now let's assume we followed the steps above, and we now have a RW version O
that has rollback version 2.
Step | RW | RB contents | `_AT_BOOT` | `_NOW`
-------------------------------------------------------------------------------------------------------------- | ----- | ----------- | -------------- | ------
RO verifies RW signature => RW is good | **O** | 1/blank | RO/RW/RB | RO/RW/RB
RO checks RW rollback version O (2) and sees it's greater or equal than RB rollback version 1. So, RW is good. | | | |
RO jumps to RW | | | |
AP is satisfied that the base works, so it tells RW to prepare for a | | | |
roll-forward (`UNLOCK_ROLLBACK`) | | | |
RW unsets `ROLLBACK_AT_BOOT` | | | **RO/RW/\_\_** |
RW may reboot (or just wait for next reattach) | | | | **RO/RW/\_\_**
On next boot, RB will be updated:
Step | RW | RB contents | `_AT_BOOT` | `_NOW`
----------------------------------------------------------------------------------------------------------------------------------------- | --- | ----------- | ------------ | ------
RO verifies RW signature => RW is good | O | 1/blank | RO/RW/\_\_ | RO/RW/\_\_
RO sees that RB is unprotected, and sees RW rollback version O (2) and sees is greater than RB rollback version 1. So RB needs an update. | | | |
RO updates RB's second block | O | **1/2** | |
RO sets `ROLLBACK_AT_BOOT` to protect RB on the next boot. | | | **RO/RW/RB** |
RO reboots. | | | | **RO/RW/RB**
## Details
### STM32 Flash Protection
At a high level, flash protection works on the STM32F072 chip works in the
following manner:
* 128KB flash total flash, organized as 32 independently protectable 4KB
blocks. Each block has 2 independently erasable 2KB sectors.
* `FLASH_WRPR` is the register controlling flash write protect of these
blocks. It is not directly writable. In EC common code, these bits are
abstracted as `EC_FLASH_PROTECT_[REGION]_NOW`.
* Instead, there is a non-volatile register called `WRPx`, which is stored in
a separate information block of flash. This is always writable. In EC common
code, these bits are abstracted as `EC_FLASH_PROTECT_[REGION]_AT_BOOT`. On
chip reset, `WRPx` is copied to the `FLASH_WRPR` register.
Here's the interesting part. The only way to change read-only firmware is to
change `WRPx` and then reset the chip, so that `WRPx` is copied into
`FLASH_WRPR`. At that point, read-only firmware could be writable. But that same
reset also transfers control back to the read-only firmware. If the read-only
firmware doesn't want to be writable, all it has to do is change `WRPx` back to
protect itself, and then reboot again. We do that already on all devices which
use the STM32 chips.
Flash protection works similarly on other STM32F chips, if we need to move to a
larger or more capable EC for the base to support a more complex base.
### Flash Contents
The 128KB `BaseEC` flash will be divided into three parts.
* Read-only firmware (`Base`-EC-RO, or just "RO" in this document)
* ~40KB
* Minimal functionality, so it can be small.
* Verifies the rewritable firmware.
* Updates the rewritable firmware over USB.
* Does NOT have keyboard or trackpad support.
* Includes the `Base-EC` root key.
* Rewritable firmware (`Base-EC`-RW, or just "RW" in this document)
* ~84KB
* Supports keyboard and trackpad.
* Trackpad drivers may be non-trivial in size.
* Future bases may include type-C ports, sensors, or batteries, all of
which will increase RW size.
* As with the main EC, it is unlikely we will have space for multiple
copies of RW (so, no RW-A and RW-B).
* Updates the read-only firmware over USB (pre-production devices only).
* Rollback block (`Base-EC`-RB, or just "RB" in this document)
* 4KB (one protection block)
* Contains rollback version information for RW
* Only writable by RO.
* Updates alternate between the 2 2KB erase sectors. We only erase one of
them at a time, so an interrupted erase/write will not cause data loss.
Adding the RB will decrease the total amount of flash available for RO and RW,
but doesn't require any additional external components. This is acceptable
because RO will be smaller (since it only has update/verify functionality).
### Verification Speed
On a STM32F072 chip running at 48 MHz,
* SHA-256 of a 64KB RW image takes 200 ms (~3 ms/KB)
* Reducing RW image size reduces verification time almost proportionally
(even if we need to check that the rest of the image is erased).
* RSA-2048 (exponent 3) signature verification takes ~50 ms
* RSA-3072 (exponent 3) signature verification takes ~100 ms
[STM32F072]: http://www.st.com/content/ccc/resource/technical/document/reference_manual/c2/f8/8a/f2/18/e6/43/96/DM00031936.pdf/files/DM00031936.pdf
[EC Update over USB]: ./usb_updater.md
[CL:452815]: https://chromium-review.googlesource.com/c/452815/2

View File

@ -1,326 +1,5 @@
# EC-3PO: The EC console interpreter
[TOC]
## Introduction
Today, the Chromium OS Embedded Controller (EC) has a very rich debug console
that is very helpful and has features including command history, editing,
timestamps, channels and much more. However, all of these features currently use
up valuable flash space that a number of our boards desperately need. We
constantly run into this problem where boards are running out of space and
people have to hack out a lot of code just so the image will fit. It's been
occurring with more frequency lately and I imagine it will continue to occur as
we add more features to our EC code base. What we could do instead is move all
of that console functionality out to a separate utility and turn the EC console
into a binary mode which would only speak in host command packets and debug
output packets. EC-3PO would serve as the interpreter translating from the
traditional EC console that we all know and love to host command packets sent
down to the EC and vice versa.
## Benefits
The benefits to be gained are numerous and can all occur without changing
people's existing workflow. The only slight impact might be that we instruct
people to `emerge hdctools` every so often. All people would notice would be
that the EC images would be getting smaller and/or more console features.
### Testing & FAFT
Currently, [FAFT](https://www.chromium.org/for-testers/faft) runs its tests
while trying to parse strings from the EC console. This method can be fairly
fragile as debug output can be interleaved with the console input. A lot of
items could be improved by switching to this host command packet interface.
* Communicating in packets makes testing easier and more robust.
* When FAFT is running, the EC could be in a binary mode where it only
communicates in host command packets. These packets are easier to parse,
create, and filter on.
* With filtering, you get the added bonus of not having unwanted debug output.
* It allows us to really test the host command interface which is how the EC
talks to the AP anyways.
* Better testing of existing host command handlers.
* By speaking in host command packets, we can reuse the existing host command
handlers which is nice since we'll be using the same handlers that are used
to respond to the AP.
* FAFT would no longer have to worry about the console dropping characters.
* We can add error checking to the interpreter which would automatically retry
errors. This alleviates FAFT from trying to check if the EC had properly
received a line of input. (Ctrl+L)
With better and more reliable tests, we can improve the quality of our EC
codebase.
### Space Savings
By moving the console functionality off of the EC, we would be able to shave off
a considerable amount of bytes from the EC images. People wouldn't have to worry
as much about creating a debug console print with the fear of bloating up the
image size. Smaller stack requirements by changing `printf` formatting to only
count bytes while moving common strings off the EC. Additionally, most of these
savings will come for free as it will apply to every EC with a console. We won't
be restricted by the type of chip.
### A richer EC console
* We could do things like on-the-fly console channel filtering.
* Coloring specific channels such as "mark all USB PD messages in green".
* Adding colors in general.
* Adding temporary console commands.
* Longer command history which survives EC reboot
* Searching command history
* Redirecting debug output to log files (which causes no interleaving of command
and debug output)
* Bang commands (`!foo`)
### Better debuggability
Sometimes, there will be an issue with the EC (or believed to be an EC issue)
such as the keyboard locking up on certain keys or rows. At times like that, it
would be nice to have an EC console to see what's going on. Other times maybe
having a servo connected might make the issue not present itself.
* We could do cool things like having an EC console without having to hook up
servo.
* Run `ectool` from the chroot using a PTY interface.
## Deployment Strategy
There are many facets to this feature, but here's a deployment strategy which
will gradually take us from the current EC console today, to a future where the
console is completely removed from the EC. The goal will be to make this change
as transparent as possible to developers.
### Phase 1: Insertion
_[[Merged to ToT](https://crrev.com/c/320629) on 2016-02-07]_
Phase 1 will most likely consist of getting EC-3PO in place in between servo and
the EC while not modifying the behavior of the console too much. In this phase,
we can replicate the console interface and achieve the following things.
* Replicate command editing.
* Save command history.
* Add error checking to the console commands.
### Phase 2: Assimilation
Phase 2 will start to introduce the host command packet communication.
* Printing will be done via packets and assembled in EC-3PO.
* Console commands now are sent using the host command packets.
* This will be incremental as console commands are converted.
* Add debug output filtering and redirection/logging.
### Phase 3: Expansion
Phase 3 will expand the feature set of EC-3PO.
* Add PTY interface to `ectool`.
* Add on-device console without `servod`.
* Colored output.
* Command history search.
* Bang commands (`!foo`)
## High Level Design & Highlights
![Diagram with three boxes. EC-3PO with an incoming PTY communicates with the
Serial Driver over another PTY. The Serial Driver communicates with the EC
UART.](./images/ec-3po-high-level-design.png)
### EC Interface
Each host command is a 16-bit command value. Commands which take parameters or
return response data specify `struct`s for that data. See
[`include/ec_commands.h`](https://chromium.googlesource.com/chromiumos/platform/ec/+/refs/heads/master/include/ec_commands.h)
for the current format of request and replies. Currently, there are no changes
made to the format of the host request and response structures.
On the EC, we essentially need to create a UART host command handler. This
handler will be watching the console input for a byte sequence to switch into
this host command mode. The starting sequence for an incoming host command
packet will be `0xDA`, a byte signifying `EC_COMMAND_PROTOCOL_3`. Once this byte
is seen, the EC will transition to its "host command processing mode" and
receive the host command. It will then process the host command, send the binary
host response, and then transition back into normal mode. Ideally, there should
be some locking of the UART to prevent other writes while this is taking place.
By the end of the assimilation (Phase 2), there would be no "normal mode" and
everything would be in the binary host command mode.
### Host Interface
The host interface is where the bulk of the work will be. This will be
converting from the received host commands to console prints as well as
converting the console inputs to host commands. It will also be responsible for
replicating the console. This includes things like moving back and forth for
command editing.
The interpreter should also open a PTY and `dut-control` should return this PTY
as the `ec_uart_pty`. This is to ensure that the change is as transparent as
possible to developers.
### Features
The following are an explanation of a few of the planned features.
#### Command Error Checking
EC-3PO and the EC can perform error checking when sending the commands to the
EC. This feature would be implemented prior to switching to the binary format.
The interpreter can package the command in the following manner.
* 2 Ampersands
* 2 hex digits representing the length of the command
* 2 hex digits representing the CRC-8 of the command
* 1 Ampersand
* The command itself
* 2 newline characters.
This is robust because no commands currently start with `&`. If the EC does not
see `&&`', then one of the ampersands has been dropped. If the EC doesn't see
an ampersand after 4 hex digits, it either dropped a hex digit or the ampersand.
Two newlines, so dropping one of those is alright. Once the EC gets the command
and newline, it can verify the command string hasn't been corrupted.
In the event that the command string was corrupted, the EC can return an error
string back of `&&EE`. If the translator reads a line with at least one
ampersand followed by one "E", then an error had occurred and the translator can
simply retry the console command. This creates a reliable input to the console,
a great win for FAFT.
#### PTY interface to `ectool`
Once the UART host command handler is functional, we could add the UART as one
of the interfaces to `ectool`. This would allow `ectool` to be run from the
chroot simply by having `ectool` communicate over the PTY. Since `ectool`
communicates using host commands anyways, everything should just work™. The
benefits of this include faster development of `ectool` and host commands as
well as a more robust interface for FAFT.
#### On-device EC console without Servo
Once the transition is complete and the console speaks entirely in host
commands, it's no longer necessary to have the console talk solely over the
UART. EC-3PO, or a variant, could exist as a standalone application that could
be bundled in the system image, just like `ectool`. It would then send and
receive host commands using the same interface that `ectool` uses whether it be
LPC or I2C. This would essentially give us a console without having to hook up
servo.
Note for security reasons, this must be locked down to only allow a subset of
commands and debug output when the system is ready to ship.
#### Replacing `cprintf()`
All prints will need to become packets. In these packets will contain the format
string, but all `cprintf()` has to do is parse to format string to determine how
many bytes the parameters take up. Then, `cprintf()` will send the format string
and the parameters to EC-3PO which will create the proper string using that
information. That makes `cprintf()` on the EC smaller and use less stack space
than it would have used for formatting.
We could also have a table of common format strings which the EC could just
provide an index and the parameters.
## Internal Design
EC-3PO is a Python package which aims to migrate the rich debug console from the
EC itself to the host. It is composed of two modules: console and interpreter.
![Diagram of EC-3PO internal design. Within an outer box labelled EC-3PO are the
Console and Interpreter modules. A bidirectional command pipe links the two, and
a debug pipe goes from the Interpreter to the
Console.](./images/ec-3po-internal-design.png)
### Console module
The console module provides the interactive console interface between the user
and the interpreter. It handles the presentation of the EC console including
editing methods as well as session-persistent command history.
The console runs in an infinite loop listening for activity on three things
using the `select()` system call: the PTY served to the user, the command pipe,
and the debug pipe. The debug pipe is a unidirectional pipe from the interpreter
to the console. From this pipe are debug prints that originate from the attached
EC and the console currently writes these strings as is to the user PTY. The
command pipe is bidirectional and is used between the console and the
interpreter for command traffic. An example transaction would be a host command
request and response.
#### Enhanced EC image negotiation
When the user transmits a character on the PTY, the console begins to scan every
byte and perform the appropriate actions. Since not every EC image will support
these enhanced features, the console must perform an interrogation to determine
what behaviour to take. If the interrogation mode is set to auto, this
negotiation takes place every time the enter key is pressed. The interrogation
is very simple 2 way handshake. The console sends down a byte, `EC_SYN` and
waits a timeout period to receive a byte, `EC_ACK`. This timeout period is 300ms
for non-enhanced EC images and 1 second for enhanced EC images. Enhanced EC
images will try to immediately respond to an `EC_SYN` with an `EC_ACK` to
indicate to EC-3PO that the current EC images is enhanced. The non-enhanced EC
image timeout period is intended to be short because non-enhanced EC images will
never reply to the `EC_SYN`. By keeping this timeout short, we are essentially
inserting a slight pause after each command. However, this timeout is long
enough for an enhanced EC image to send its reply of `EC_ACK`. Once the `EC_ACK`
is received by the console, the console increases the timeout to 1 second for
stability purposes just in case the enhanced EC image takes a bit longer to send
its reply for some reason. This negotiation allows EC-3PO to behave correctly
for both enhanced and non-enhanced EC images.
If a user knows that they are not using an enhanced EC image, they can disable
the interrogation by issuing a OOBM command. This will cause the console to
never initiate a negotiation, eliminating the delay. See the "interrogate"
command in the Out of Band Management section for usage.
#### Enhanced vs. Non-Enhanced EC images
All EC images which don't explicitly enable the new features (or were built
before the features were implemented in the code base) are non-enhanced images.
Non-enhanced EC images will be handling the presentation of the console
including editing methods (and history if enabled). Therefore, the EC-3PO
console and interpreter behave as a simple pipe for this case forwarding
everything straight to the EC to handle. For the enhanced EC images, all console
presentation (including editing methods) is handled locally by the EC-3PO
console. Enhanced EC images will also support all of the other features
discussed in this document.
#### Out of Band Management
The interactive console also has an Out of Band Management (OOBM) interface.
This allows commands to be entered that can alter the behavior of the console
and interpreter during runtime. From the console, one can bring up the OOBM
prompt by pressing %' . These were originally added for debug purposes.
##### Supported Commands
* `loglevel <integer>`
* Allows setting the effective loglevel of the console and interpreter.
* `interrogate <never | always | auto> [enhanced]`
* Allows control of when and how often interrogation occurs.
### Interpreter module
The interpreter provides the interpretation layer between the EC UART and the
user. Similar to the console module, the interpreter starts an infinite loop of
servicing the user and the EC by means of a `select()` system call. It receives
commands through its command pipe, formats the commands for the EC, and sends
the command to the EC. It also presents data from the EC to either be displayed
via the interactive console module or some other consumer.
The interpreter also keeps track of whether the EC image it's communicating with
is enhanced or not. This is required so that the interpreter can communicate
correctly with the EC. For enhanced EC images, the interpreter will pack
incoming commands in a particular format. This could be the "packed plaintext"
form or the binary host command format. With the packed plaintext form, the
interpreter also supports command retrying by monitoring the response of the EC
and automatically retrying the command with no input from the user.
### Other users
Since the interpreter communicates using pipes, it's not necessary that the user
use the console module. For example, FAFT could directly connect to the
interpreter and send down commands and receive command responses instead of
having to deal with the PTY and instead just deal with python objects.
*** note
**Warning: This document is old & has moved. Please update any links:**<br>
https://chromium.googlesource.com/chromiumos/platform/ec/+/HEAD/docs/ec-3po-design.md
***

View File

@ -1,82 +1,5 @@
# EC-3PO
*** note
**Warning: This document is old & has moved. Please update any links:**<br>
https://chromium.googlesource.com/chromiumos/platform/ec/+/HEAD/docs/ec-3po.md
***
[TOC]
## What is EC-3PO?
EC-3PO is the console interpreter that will one day replace the EC console that
we have today. EC-3PO aims to migrate our rich debug console from the EC itself
to the host. This allows us to maintain our rich debug console without
impacting our EC image sizes while also allowing us to add new features.
For more information, see [the design doc](./ec-3po-design.md).
## How do I use EC-3PO?
If you're using `servod` to connect to your EC, chances are you're already using
it. EC-3PO was grafted into `servod` on Feb 7th 2016. If you're not running
`servod`, you can run EC-3PO manually by running `console.py` in the
`util/ec3po` directory from the EC checkout. You will need to provide the PTY
that you get from elsewhere though.
To obtain the EC console PTY, inside the chroot run:
```shell
$ dut-control ec_uart_pty
```
**NOTE: It's important to use `dut-control` to query the PTY instead of just
eyeballing the `servod` output.** The former PTY (now known as
`raw_ec_uart_pty`) will be sending raw binary data. Trying to use that console
with an enhanced EC image will definitely fail and you won't be able to
send/receive any commands.
Then use your favorite serial terminal program to connect to the PTY. Since
`servod` is run as root, you'll need to run your serial terminal program as root
as well using `sudo`. This is because the permissions have changed from 666 to
660.
EC-3PO has been tested with `minicom`, `screen`, `socat`, and `cu`. However, if
you're using `cu` you'll have to do the following to get it to work because
apparently, `cu` wants group write permissions. On Ubuntu at least, the PTY is
created with the `tty` group. If on your machine it's not, then just replace
`tty` with whatever group it's created with.
1. Create a `tty` group if you don't have one already.
1. Add root to the `tty` group.
1. Rerun `cu` with `sudo` and it should work now.
## Why does the console seem "laggier" than before?
This is because there's a ~300ms delay after entering each console command. This
is due to the interrogation that the console interpreter performs to determine
if the EC image it's currently talking to is enhanced or not. Debug prints
coming from the EC should be the same speed. Since most people aren't currently
using the enhanced EC images, you can go ahead and run this command if the 300ms
delay is unbearable.
To disable the delay:
1. Open the EC console.
1. Press `%`
1. Enter `interrogate never`
1. Then press enter.
\**For `socat` users, due to the line buffered nature, you'll have to just enter
`%interrogate never`. Notice the lack of the space character between `%` and the
command.*
The interrogation delay should now be gone and you can have your 300ms/cmd back.
## How do I try out this "enhanced" EC image you speak of?
You simply add this to your board.h file.
```c
#define CONFIG_EXPERIMENTAL_CONSOLE
```
## I can't open the EC console
Make sure you try with `sudo`. If you're using `cu`, make sure root is a member
of the group of the created PTY.

View File

@ -1,239 +1,5 @@
# EC Acronyms and Technologies
*** note
**Warning: This document is old & has moved. Please update any links:**<br>
https://chromium.googlesource.com/chromiumos/platform/ec/+/HEAD/docs/ec_terms.md
***
## Glossary
* **8042 Interface**{#8042}
Interface for sending keyboard events to the [AP](#ap) and for receiving
commands from the AP. Only supported by x86 based APs.
* **ACCEL - Accelerometer**{#accel}
A sensor that measures acceleration, typically over 3-axis. Nominally
provides information about the orientation of a device. On Chromebook 2-in-1
devices, there is an accelerometer in the base and one in the lid. Combining
the measurements from both accelerometers allows for a precise calculation
of the lid angle, used to switch between tablet and laptop mode.
* **ACCELGYRO - Accelerometer/Gyroscope**{#accelgyro}
A combination [accelerometer](#accel) and [gyroscope](#gyro) sensor that
provides more precise orientation information by measuring both linear and
rotational motion.
* **ADC - Analog to Digital Converter**{#adc}
A sensor that converts an analog voltage to a digital reading.
* **ALS - Ambient Light Sensor**{#als}
A sensor that measures the ambient light present. Used to automatically
control the screen and keyboard backlight level.
* **AP - Application Processor**{#ap}
The processor on the board that boots and runs ChromeOS.
* **BAR - Barometer**{#bar}
A sensor that measures atmospheric pressure.
* **BC12 - Battery Charging**{#bc12}
A device that implements the USB Battery Charging specification, version
1.2. The complete [BC 1.2 Specification] is available from the USB
Implementers Forum.
* **CBI - CROS Board Information**{#cbi}
A collection of properties describing the board. This includes board
version, SKU, model name, and other fields. More details are found in the
[CrOS Board Info] documentation.
* **CEC - Consumer Electronics Control**{#cec}
A one-wire bidirectional bus. More details are on the [CEC Wikipedia page].
* **DPTF - Dynamic Power and Thermal Framework (Intel)**{#dptf}
Intel's platform based power and thermal management. See the [DPTF Readme]
for details on the implementation used in ChromeOS.
* **EC - Embedded Controller**{#ec}
The [MCU](#mcu) used to control the keyboard, battery charging, USB port
switching, sensor management, and other functions, offloading these tasks
from the [AP](#ap).
* **EC-3PO**{#ec-3po}
A replacement of the current UART-based console which moves much of the code
off the EC into a host tool, reducing the amount of flash space required.
* **E-Mark - Electronically Marked Cable** {#emark}
See the [USB-C documentation](./usb-c.md#emark) for more details.
* **eSPI - Enhanced Serial Peripheral Interface (Intel)**{#espi}
Intel's synchronous communication interface between the [AP](#ap) and the
[EC](#ec). Supports quad I/O mode and clock speeds up to 66 Mhz, providing
bandwidth up to 264 Mbps. The full [eSPI Specification] is available from
Intel.
* **FAFT - Fully Automated Firmware Tests**{#faft}
A collection of tests and related infrastructure that exercise and verify
capabilities of Chrome OS. See the [FAFT design doc] and [chromium.org
documentation](https://www.chromium.org/for-testers/faft) for more details.
Replaced [SAFT](#saft).
* **GMR - Giant Magnetoresistance Sensor** {#gmr}
A sensor device that detects a magnetic field. These sensors differ from
[MAG](#mag) sensors, in that they only detect magnetic fields in close
proximity to the sensor. On Chromebooks, GMR sensors are used to detect when
the lid is opened. On convertible Chromebooks, the GMR sensor also detects
tablet mode when lid the is opened a full 360 degrees.
* **GPIO - General Purpose Input/Output**{#gpio}
An individual signal that can independently controlled and read. GPIOs are
used to enable/disable power rails, drive reset signals, and receive
interrupts from devices connected to the EC. GPIOs may also be connected
to [I/O expanders](#ioexpander).
* **GYRO - Gyroscope**{#gyro}
A sensor that measures angular momentum, providing information about
rotational motion of the device.
* **I/O Expander**{#ioexpander}
An [I2C](#i2c) peripheral device that provides additional GPIO signals
(anywhere from 8 - 32 signals). GPIOs behind an I/O expander are written
and read using I2C register accesses from the I2C controller in the EC.
* **I2C - Inter-Integrated Circuit**{#i2c}
A 2-wire synchronous communication bus, consisting of a clock signal and a
bidirectional data signal. An I2C bus typically contains one controller
device and one or more peripheral devices. The I2C standard defines
supported clock speeds of 100 KHz and 400 KHz. The full [I2C Specification]
is available from NXP (formerly Phillips).
* **LED - Light Emitting Diode**{#led}
A Light Emitting Diode is a semiconductor that emits light when current
flows through it.
* **LPC - [Low Pin Count bus]**{#lpc}
Legacy communication bus between the [AP](#ap) and [EC](#ec). Runs at 33
MHz, providing a 133 Mbps bandwidth connection. Replaced by the
[eSPI](#espi) interface.
* **MAG - Magnetometer**{#mag}
A digital compass sensor, providing orientation for navigation.
* **MCU - Microcontroller Unit**{#mcu}
A small integrated chip containing a CPU core, on-chip ROM, on-chip RAM.
Also contains multiple peripheral interfaces, including GPIO, I2C buses, SPI
buses, ADC, PWM, etc.
* **MKBP - Matrix Keyboard Protocol**{#mkbp}
Message based protocol for communicating asynchronous events from the
[EC](#ec) to the [AP](#ap). Events are not limited to keyboard events with
the sensor subsystem as one of the main users. An EC board implementation
can be configured to send keyboard events through MKBP or using the [8042
interface](#8042). This is the [EC MKBP driver] implementation.
* **MST - Multi Stream Transport**{#mst}
Part of the Display Port 1.2 standard, used to drive multiple independent
video streams from a single display port. The EC code is typically
responsible for enabling and disabling the MST hub chipset.
* **OOBM - Out of Band Management**{#oobm}
A command in the [EC-3PO protocol](#ec-3po) that allows commands to be
entered to alter the behaviour of the console and interpreter during
runtime.
* **PD - USB Power Delivery**{#pd}
See the [USB-C documentation](./usb-c.md#pd) for more details.
* **PMIC - Power Management IC**{#pmic}
An integrated circuit used to turn power rails on and off.
* **PPC - USB Power Path Controller**{#ppc}
See the [USB-C documentation](./usb-c.md#ppc) for more details.
* **PWM - Pulse Width Modulation**{#pwm}
Method of varying the duty cycle of a signal to control another device. A
typical application is to control fan speeds or the brightness of a
backlight.
* **SAFT - Semi-Automated Firmware Tests**{#saft}
A suite of tests for firmware, succeeded by [FAFT](#faft). See the
[chromium.org documentation](https://www.chromium.org/for-testers/saft) for
more details.
* **SPI - Serial Peripheral Interconnect**{#spi}
A 4-wire synchronous communication bus consisting of the signals CLK
(clock), SDO (Serial Data Out), SDI (Serial Data In), and CS (chip-select,
one per SPI peripheral). The SDO and SDI pins are defined from the
perspective of the device: the SPI controller's SDO pin connects to the SPI
peripheral's SDI pin and vice-versa. Clock speeds over 100 MHz are
supported. SPI communication involves the following sequence:
* SPI controller asserts CS.
* SPI controller transmits one or bytes on its SDO signal, received by the
SPI peripheral on its SDI signal.
* SPI peripheral transmits zero or more bytes on its SDO signal, received
by the SPI controller on its SDI signal.
* SPI controller de-asserts CS.
The specific contents of a SPI frame varies based on the SPI peripheral
type.
* **SVDM - Structured Vendor Defined Messages**{#svdm}
See the [USB-C documentation](./usb-c.md#svdm) for more details.
* **TCPC - USB Type-C Port Controller**{#tcpc}
See the [USB-C documentation](./usb-c.md#tcpc) for more details.
* **UART - Universal Asynchronous Receiver Transceiver**{#uart}
Also known as a serial port. An asynchronous communication channel between
two devices with a dedicated receive pin, transmit pin, and ground. Optional
hardware flow control signals require additional connections between the
devices. Standard transmission rates are slow (up to 115200 bits per
second). Typical use is to provide a debug console to the EC. [RS-232] is
the protocol standard used by UARTs.
* **VCONN - Connector Voltage** {#vconn}
See the [USB-C documentation](./usb-c.md#vconn) for more details.
[BC 1.2 Specification]: <https://www.usb.org/document-library/battery-charging-v12-spec-and-adopters-agreement>
[CrOS Board Info]: <https://chromium.googlesource.com/chromiumos/docs/+/master/design_docs/cros_board_info.md>
[CEC Wikipedia page]: <https://en.wikipedia.org/wiki/Consumer_Electronics_Control>
[DPTF Readme]: <https://github.com/intel/dptf/blob/master/README.txt>
[eSPI Specification]: <https://www.intel.com/content/dam/support/us/en/documents/software/chipset-software/327432-004_espi_base_specification_rev1.0.pdf>
[FAFT design doc]: <https://chromium.googlesource.com/chromiumos/third_party/autotest/+/refs/heads/master/docs/faft-design-doc.md>
[I2C Specification]: <https://www.nxp.com/docs/en/user-guide/UM10204.pdf>
[RS-232]: <https://en.wikipedia.org/wiki/RS-232>
[EC MKBP driver]: <https://chromium.googlesource.com/chromiumos/platform/ec/+/refs/heads/master/common/keyboard_mkbp.c>
[Low Pin Count bus]: https://en.wikipedia.org/wiki/Low_Pin_Count

View File

@ -1,772 +1,5 @@
# Fingerprint Authentication on Chrome OS
*** note
**Warning: This document is old & has moved. Please update any links:**<br>
https://chromium.googlesource.com/chromiumos/platform/ec/+/HEAD/docs/fingerprint/fingerprint-authentication-design-doc.md
***
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, dont be tied to a
specific technology ([Arm TrustZone], [Intel SGX]).
* Support Androids [fingerprint authentication framework] so users can for
example authorise payments in Android apps with their fingerprint. The
fingerprint implementation needs to comply with Androids [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 organisations resources via the
victims 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 users fingerprints even if they have exploited the
software running on the AP.
* To protect the users privacy, fingerprint data must not be accessible
without the users consent, even by Google. Typically it will protected by
the users 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.
Its 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 users [cryptohome]
but not synced/backed up to the cloud. They are thus encrypted with a key
(`User_Key`) derived from the users password, preventing 3rd parties (including
Google) from accessing the fingerprint templates if the user hasnt 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 SBPs 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 SBPs 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 users 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 SBPs 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 SBPs 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 APs 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 SBPs secret and the TPMs 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 wont 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 users 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 wasnt adding real entropy.
##### AEAD (AES-GCM) Encryption {#aead}
To encrypt the FP templates with `HW_Key` we use BoringSSLs implementation of
AES-GCM128.
###### Initialisation Vector
The encryption operations are done by the R/W firmware that doesnt have write
access to the Flash, so it cant 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 users 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 SBPs firmware into a permanent exploit
by replacing the SBPs 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
cant 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 wouldnt 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 doesnt parse that input -its 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 auditors [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 isnt 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 were 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 victims 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 its not a persistent exploit, a rogue enrolled fingerprint would
persist.
* The victims 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/+/refs/heads/master/system_api/dbus/biod/
[biod upstart script]: https://chromium.googlesource.com/chromiumos/platform2/+/master/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/+/master/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/+/master/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/+/master/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/+/master/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/+/master/common/shmalloc.c
[matching algorithm]: https://en.wikipedia.org/wiki/Fingerprint#Algorithms
[mount_encrypted]: https://chromium.googlesource.com/chromiumos/platform2/+/master/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/+/master/sandboxing.md
[seccomp filter]: https://chromium.googlesource.com/chromiumos/platform2/+/master/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”]: http://go/bio_tpm_seed
<!-- 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

View File

@ -1,171 +1,5 @@
# Fingerprint Debugging
This document describes how to attach a debugger with SWD in order to debug the
FPMCU.
[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].
* [Servo Micro].
## Software Required
* [JLink Software] \(when using [J-Trace] or other Segger debug probes).
* Any tool that supports connecting `gdbserver`. This document will assume
[CLion] and was tested with `JLink_Linux_V684a_x86_64`.
* Alternatively, you can use [Ozone] a standalone debugger from Segger.
## Connecting SWD
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].
**Warning: This document is old & has moved. Please update any links:**<br>
https://chromium.googlesource.com/chromiumos/platform/ec/+/HEAD/docs/fingerprint/fingerprint-debugging.md
***
<!-- 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] |
## Powering the Board
[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=dragonclaw
```
It's also possible to power through J-Trace, though this can only supply the MCU
with power (3.3V), not a sensor using 1.8V.
## Using JLink gdbserver
Start the JLink gdbserver for the appropriate MCU type:
* Dragonclaw / [Nucleo STM32F412ZG]: `STM32F412CG`
* Dragontalon / [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/
[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
<!-- 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

View File

@ -1,657 +1,5 @@
# 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.
**Warning: This document is old & has moved. Please update any links:**<br>
https://chromium.googlesource.com/chromiumos/platform/ec/+/HEAD/docs/fingerprint/fingerprint-dev-for-partners.md
***
*** 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_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 youre 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 dont 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 SSHed 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
![Dragonclaw in 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/+/refs/heads/master/util/comm-servo-spi.c#15
[servo]: https://chromium.googlesource.com/chromiumos/third_party/hdctools/+/master/README.md
[developer mode]: https://chromium.googlesource.com/chromiumos/docs/+/master/debug_buttons.md#firmware-keyboard-interface
[hardware write protection]: https://chromium.googlesource.com/chromiumos/platform/ec/+/refs/heads/master/docs/write_protection.md
[have the prerequisites]: https://chromium.googlesource.com/chromiumos/docs/+/master/developer_guide.md#Prerequisites
[get the source]: https://chromium.googlesource.com/chromiumos/docs/+/master/developer_guide.md#get-the-source
[enter the `chroot`]: https://chromium.googlesource.com/chromiumos/docs/+/master/developer_guide.md#building-chromium-os
[Chromium OS Contributing Guide]: https://chromium.googlesource.com/chromiumos/docs/+/master/contributing.md
[Servo Micro Info]: https://chromium.googlesource.com/chromiumos/third_party/hdctools/+/master/docs/servo_micro.md
[Set your editor]: https://chromium.googlesource.com/chromiumos/docs/+/master/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/+/master/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/+/master/git_and_gerrit_intro.md
[Installing Chromium]: https://chromium.googlesource.com/chromiumos/docs/+/master/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 -->
[Dragonclaw in CQ Prototype Environment]: ../images/Dragonclaw_in_CQ_Prototype_Environment.jpg

View File

@ -1,97 +1,5 @@
# Chrome OS Fingerprint Sensor: Quick Factory Guide
*** note
**Warning: This document is old & has moved. Please update any links:**<br>
https://chromium.googlesource.com/chromiumos/platform/ec/+/HEAD/docs/fingerprint/fingerprint-factory-quick-guide.md
***
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 doesnt 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/+/refs/heads/master/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/+/refs/heads/master/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)

View File

@ -1,502 +1,5 @@
# 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 FPMCUs 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.
**Warning: This document is old & has moved. Please update any links:**<br>
https://chromium.googlesource.com/chromiumos/platform/ec/+/HEAD/docs/fingerprint/fingerprint-factory-requirements.md
***
<!-- 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. Its 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, its 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 FPCs 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 FPMCUs `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 FPCs 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/+/refs/heads/master/docs/write_protection.md#Software-Write-Protect
[hardware write protect]: https://chromium.googlesource.com/chromiumos/platform/ec/+/master/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/+/master/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/+/master/util/flash_fp_mcu
[Fingerprint flashing documentation]: ./fingerprint.md#factory-rma-dev-updates
[Chrome OS Config]: https://chromium.googlesource.com/chromiumos/platform2/+/master/chromeos-config/README.md
[updating Chrome OS Config]: ./fingerprint.md#update-chromeos-config

View File

@ -1,111 +1,5 @@
# Fingerprint Firmware Testing Instructions for Partners
*** note
**Warning: This document is old & has moved. Please update any links:**<br>
https://chromium.googlesource.com/chromiumos/platform/ec/+/HEAD/docs/fingerprint/fingerprint-firmware-testing-for-partners.md
***
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 youre 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/+/master/docs/servo.md
[developer mode]: https://chromium.googlesource.com/chromiumos/docs/+/master/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/+/master/docs/servo_v4.md
[have the prerequisites]: https://chromium.googlesource.com/chromiumos/docs/+/master/developer_guide.md#Prerequisites
[get the source]: https://chromium.googlesource.com/chromiumos/docs/+/master/developer_guide.md#get-the-source

View File

@ -1,513 +1,5 @@
# 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.
**Warning: This document is old & has moved. Please update any links:**<br>
https://chromium.googlesource.com/chromiumos/platform/ec/+/HEAD/docs/fingerprint/fingerprint.md
***
<!-- 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. Its 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 (cant 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. Theres 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.
[Its 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`
```
@@ NAME COUNT AVERAGE STDDEV MAX MIN
@@ sample_msecs 128 469.05 33.79 641.75 399.90
@@ pp1800_dx_fp_mv 128 1802.06 3.50 1808.00 1800.00
@@ pp1800_dx_fp_mw 128 0.00 0.00 0.00 0.00
@@ pp3300_dx_fp_mv 128 3296.00 0.00 3296.00 3296.00
@@ pp3300_dx_fp_mw 128 0.00 0.03 0.26 0.00
@@ pp3300_dx_mcu_mv 128 3288.00 0.00 3288.00 3288.00
@@ pp3300_dx_mcu_mw 128 24.20 0.00 24.20 24.20
```
### Dragontalon
<!-- mdformat off(b/139308852) -->
*** note
**NOTE**: The sensor doesn't work on Dragontalon, so the measurements below show
zero for the sensor.
***
<!-- mdformat on -->
```bash
(chroot) $ dut-control -t 60 pp3300_h7_mv pp3300_h7_mw pp1800_fpc_mv pp1800_fpc_mw
```
**Firmware Version**: `dartmonkey_v2.0.4017-9c45fb4b3`
```
@@ NAME COUNT AVERAGE STDDEV MAX MIN
@@ sample_msecs 1502 39.96 13.14 379.43 22.31
@@ pp1800_fpc_mv 1502 0.00 0.00 0.00 0.00
@@ pp1800_fpc_mw 1502 0.00 0.00 0.00 0.00
@@ pp3300_h7_mv 1502 3288.00 0.00 3288.00 3288.00
@@ pp3300_h7_mw 1502 8.20 0.51 18.08 7.67
```
## 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.
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.
[`common/fpsensor`]: https://chromium.googlesource.com/chromiumos/platform/ec/+/master/common/fpsensor/
[`driver/fingerprint`]: https://chromium.googlesource.com/chromiumos/platform/ec/+/master/driver/fingerprint
[`nocturne_fp`]: https://chromium.googlesource.com/chromiumos/platform/ec/+/refs/heads/master/board/nocturne_fp/
[`nami_fp`]: https://chromium.googlesource.com/chromiumos/platform/ec/+/refs/heads/master/board/nami_fp/
[`hatch_fp`]: https://chromium.googlesource.com/chromiumos/platform/ec/+/refs/heads/master/board/hatch_fp/
[`bloonchipper`]: https://chromium.googlesource.com/chromiumos/platform/ec/+/refs/heads/master/board/bloonchipper/
[`dartmonkey`]: https://chromium.googlesource.com/chromiumos/platform/ec/+/refs/heads/master/board/dartmonkey/
[hardware write protection]: ../write_protection.md
[`flash_fp_mcu`]: https://chromium.googlesource.com/chromiumos/platform/ec/+/master/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/+/master/futility/
[`sign_official_build.sh`]: https://chromium.googlesource.com/chromiumos/platform/vboot_reference/+/master/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/+/refs/heads/master/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/+/master/board/nocturne_fp/dev_key.pem
[`timberslide`]: https://chromium.googlesource.com/chromiumos/platform2/+/master/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/+/master/README.md#building-test-image
[Chrome OS Config]: https://chromium.googlesource.com/chromiumos/platform2/+/master/chromeos-config/README.md
[Chrome OS Config fingerprint]: https://chromium.googlesource.com/chromiumos/platform2/+/refs/heads/master/chromeos-config/README.md#fingerprint
[section on testing properties]: https://chromium.googlesource.com/chromiumos/platform2/+/refs/heads/master/chromeos-config/README.md#adding-and-testing-new-properties
[Chrome OS board]: https://chromium.googlesource.com/chromiumos/docs/+/master/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/+/refs/heads/master/profiles/base/make.defaults#17
[hatch model.yaml]: https://chrome-internal.googlesource.com/chromeos/overlays/overlay-hatch-private/+/master/chromeos-base/chromeos-config-bsp-hatch-private/files/model.yaml
[`ec_extras` attribute]: https://chromium.googlesource.com/chromiumos/platform2/+/refs/heads/master/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/+/refs/heads/master/chromeos-base/chromeos-firmware-fpmcu/chromeos-firmware-fpmcu-9999.ebuild
[firmware ebuild]: https://chrome-internal.googlesource.com/chromeos/overlays/chromeos-overlay/+/refs/heads/master/chromeos-base/chromeos-firmware-fpmcu/chromeos-firmware-fpmcu-9999.ebuild#40
[`chromeos-fpmcu-release*` ebuilds]: https://chromium.googlesource.com/chromiumos/overlays/chromiumos-overlay/+/master/sys-firmware
[internal manifest]: https://chromium.googlesource.com/chromiumos/docs/+/master/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

View File

@ -1,129 +1,5 @@
# Get Started Building EC Images (Quickly)
*** note
**Warning: This document is old & has moved. Please update any links:**<br>
https://chromium.googlesource.com/chromiumos/platform/ec/+/HEAD/docs/getting_started_quickly.md
***
[TOC]
The
[Chromium OS Developer Guide](https://chromium.googlesource.com/chromiumos/docs/+/master/developer_guide.md)
and [README](../README.md) walk through the steps needed to fetch and build
Chromium OS source. These steps can be followed to retrieve and build EC source
as well. On the other hand, if your sole interest is building an EC image, the
general developer guide contains some extra unneeded steps.
The fastest possible way to build an EC image is to skip the Chromium OS chroot
install entirely. The following steps have been tested on an Ubuntu 15.10 (Wily
Werewolf) 64-bit host machine. Other distros / versions may be used, but
toolchain incompatibilities may require extra debug.
## Building
1. Install build / dev tools:
```bash
sudo apt-get install git libftdi-dev libusb-dev libncurses5-dev gcc-arm-none-eabi
```
1. Sync the cros-ec git repo:
```bash
git clone https://chromium.googlesource.com/chromiumos/platform/ec
```
1. Build your EC image:
```bash
HOSTCC=x86_64-linux-gnu-gcc make BOARD=$board
```
## External Dependencies
Most boards are buildable, but some will fail due to dependencies on external
binaries (such as [`futility`](#building-futility)). Also, some related tools
(such as `flash_ec` and `servod`) must be run from the Chromium OS chroot. Here
is a set of steps to setup a minimal development environment to build EC images
from the Chromium OS chroot:
1. Create a folder for your chroot:
```bash
mkdir cros-src; cd cros-src
```
1. Run
```bash
repo init -u https://chromium.googlesource.com/chromiumos/manifest.git --repo-url https://chromium.googlesource.com/external/repo.git -g minilayout
```
1. Edit `.repo/manifest.xml`, and add `groups="minilayout"` to the platform/ec
project, so the line becomes:
```
<project path="src/platform/ec" name="chromiumos/platform/ec" groups="minilayout" />
```
1. Run `repo sync`:
```bash
repo sync -j <number of cores on your workstatsion>
```
1. Enter the chroot and enter your password for `sudo` if prompted:
```bash
./chromite/bin/cros_sdk
```
1. Set up your board:
```bash
./setup_board --board=$BOARD
```
(ex. `./setup_board --board=glados`)
1. Build EC:
```bash
./build_packages --board=$BOARD chromeos-ec
```
1. Now, EC images for any board can be built with:
```bash
cd ~/trunk/src/platform/ec; make BOARD=$board -j
```
## Building `futility` outside the chroot {#building-futility}
If you want to build the `futility` host tool outside the normal Chrome OS
chroot self-contained environment, you can try the following
1. Install futility build dependencies:
```bash
sudo apt-get install uuid-dev liblzma-dev libyaml-dev libssl-dev
```
1. Get the vboot reference sources:
```bash
git clone https://chromium.googlesource.com/chromiumos/platform/vboot_reference
```
1. Build it:
```bash
cd vboot_reference ; make
```
1. Install it in `/usr/local/bin`:
```bash
sudo make install
```
1. Add `/usr/local/bin` to your default `PATH`:
```bash
export PATH="${PATH}:/usr/local/bin"
```

View File

@ -1,54 +1,5 @@
I²C Debugging Tips
==================
*** note
**Warning: This document is old & has moved. Please update any links:**<br>
https://chromium.googlesource.com/chromiumos/platform/ec/+/HEAD/docs/i2c-debugging.md
***
The EC codebase has functionality to help you debug I²C errors without
pulling out the scope. Some of the debug functionality is disabled by
default to save space, but can be enabled with the `CONFIG_I2C_DEBUG`
option.
Tracing
-------
You can use the `i2ctrace` command to monitor (ranges of) addresses:
```
i2ctrace [list
| disable <id>
| enable <port> <address>
| enable <port> <address-low> <address-high>]
```
For example:
```
> i2ctrace enable 0 0x10 0x30
> i2ctrace enable 1 0x20
> i2ctrace list
id port address
-- ---- -------
0 0 0x10 to 0x30
1 1 0x40 to 0x50
... debug spam may follow ...
i2c: 1:0x20 wr 0x10 rd 0x01 0x00
i2c: 1:0x20 wr 0x10 0x01 0x00
...
> i2ctrace disable 1
> i2ctrace list
id port address
-- ---- -------
0 0 0x10 to 0x30
```
A maximum of 8 debug entries are supported at a single time.
Note that `i2ctrace enable` will merge debug entries when possible:
```
> i2ctrace enable 0 0x10 0x30
> i2ctrace enable 0 0x40 0x50
> i2ctrace enable 0 0x31 0x3f
> i2ctrace list
id port address
-- ---- -------
0 0 0x10 to 0x50
```

View File

@ -1,57 +1,5 @@
# IDE Support
*** note
**Warning: This document is old & has moved. Please update any links:**<br>
https://chromium.googlesource.com/chromiumos/platform/ec/+/HEAD/docs/ide-support.md
***
[TOC]
## Odd File Types
EC uses a few odd file types/names. Some are included from other header files
and used to generate data structures, thus it is important for your IDE to index
them.
Patterns | Vague Type
----------------------------------------------------- | ----------
`README.*` | Text
`Makefile.rules`, `Makefile.toolchain` | Makefile
`gpio.wrap` | C Header
`gpio.inc` | C Header
`*.tasklist`, `*.irqlist`, `*.mocklist`, `*.testlist` | C Header
## IDE Configuration Primitives
Due to the way most EC code has been structured, you can typically only safely
inspect a configuration for a single image (RO or RW) for a single board. Thus,
you need to specify the specific board/image pair when requesting defines and
includes.
Command | Description
-------------------------------------------- | ------------------------------
`make print-defines BOARD=$BOARD BLD=RW/RO` | List compiler injected defines
`make print-includes BOARD=$BOARD BLD=RW/RO` | List compiler include paths
## VSCode
You can use the `ide-config.sh` tool to generate a VSCode configuration that
includes selectable sub-configurations for every board/image pair.
1. From the root `ec` directory, do the following:
```bash
mkdir -p .vscode
./util/ide-config.sh vscode all:RW all:RO | tee .vscode/c_cpp_properties.json
```
2. Open VSCode and navigate to some C source file.
3. Run `C/C++ Reset IntelliSense Database` from the `Ctrl-Shift-P` menu
4. Select the config in the bottom right, next to the `Select Language Mode`.
You will only see this option when a C/C++ file is open. Additionally, you
can select a configuration by pressing `Ctrl-Shift-P` and selecting the
`C/C++ Select a Configuration...` option.
5. Add the EC specific file associations and style settings. Do the following
to copy the default settings to `.vscode/settings.json`:
```bash
cp .vscode/settings.json.default .vscode/settings.json
```

View File

@ -1,428 +1,5 @@
# Configuring the EC for Low-Battery Startup
Near the bottom of charge, starting up a ChromeOS device can be a tricky
proposition. Several features interact to make it difficult to reliably turn on
the machine without browning out. Over the years, a variety of configuration
options have been written to maximize ChromeOS's compatibility with the basic
user expectation,
"I plugged it in, therefore it should turn on."
When creating a new board configuration, this document should aid the engineer
in navigating and choosing correct values for these options.
The first section describes the various features which interact with each other
to create a complex environment for the EC during boot, especially at a low
state of charge.
Second, we'll provide some reference configurations which cover many
Chromebooks' use cases.
Finally, we'll close out with a detailed review of the configuration parameters
which are available.
## Interacting Features
### Battery and Charging Circuit
For the most part, ChromeOS device power systems are much like other laptop
battery power systems. A variable-voltage rail is connected to the battery via
a series of cutoff MOSFETs. Several system power rails derive their power from
the system's variable-voltage rail. Mains power is delivered to the
variable-voltage system rail by a buck/boost charging circuit. Mains power is
itself rectified, isolated, and stepped down by an external power supply.
During most of the battery charge, the charger operates in current mode, acting
as a constant current source that delivers current to the variable-voltage rail.
Load transients are served by the capacitance on the rail and the battery. By
superposition, load transients during the charge don't necessarily draw current
from the battery, they may just reduce the current flow into the battery.
References to AC power in the EC codebase are actually references to an external
power supply's DC source. External supplies that are actually USB-PD-speaking
battery packs are indistinguishable from AC/DC adapters as far as the EC is
concerned. Variables and functions which refer to external supplies all refer
to them as 'AC', though.
### Source Current Negotiation
A device may draw power from an AC adapter via a few methods.
#### USB BC1.2 Current Sources
BC1.2 negotiation is usually managed entirely by an external IC. Once it is
complete, the EC limits itself to 2.4A max. Additionally, the charger may be
configured to switch to an input voltage regulation mode if the input voltage
begins to sag too low.
Ideally, the input source provides a voltage droop, such that it is not quite
overloaded at the input voltage regulation setpoint of about 4.5V. Thus, 4.5V
serves as a reasonable reference voltage for the charger to use when it is in an
input voltage-regulation mode.
In effect, the EC limits to both a maximum current of 2.4A and minimum voltage
of 4.5V, for about 12W of power draw from a BC1.2 source.
See also `driver/bc12/max14637.c:bc12_detect()`.
#### USB-PD Sources
High-current power supplies are negotiated via the USB Type C Current Source and
USB Power Delivery specifications (PD). PD sources must support Type-C Current
Source, but the reverse is not true. Both types of current sources are managed
via the PD protocol module in the EC codebase.
Type-C Current Source capabilities of up to 15W (3A, 5V) are advertised via
analog signaling alone. Via digital communication in the PD protocol, much
higher power states may be negotiated. However, higher power states also
usually run at a higher voltage state as well. Any time the voltage level is
changing, the power sink (the ChromeOS device) must lower its power consumption
during the transient. The standby current level is governed by
`CONFIG_CHARGER_INPUT_CURRENT`.
PD port partners are capable of both soft and hard resets. Hard resets will
cause a dead-bus state for a brief interval before PD can renegotiate, from
scratch, because it is intended to emulate a cable disconnect. Therefore, a
hard reset without a connected battery will brownout the Chromebook.
### Locked and Unlocked Firmware
The Verified Boot implementation normally limits the complexity of the code
which executes in the locked Read-Only firmware package. The consequences for
the EC are:
- Locked RO EC firmware does not process any digital PD messages at all, it only
recognizes the analog advertisement of USB Current Source (15W max).
- Installation of user-provided firmware is supported, but the write-protect pin
must be cleared to enable it.
- On recent systems, write-protect is cleared by removing the system battery.
### ChromeOS `powerd`
The power management daemon provided by ChromeOS displays a "low-power charger"
warning message via the system tray whenever the charger is limited to less than
20W. Therefore, if a USB-PD source is restricted to analog signaling, or a
BC1.2 source is connected, the user gets alerted to the situation.
Systems that can run on very little power may be rapidly charged with a 15W
charger, while a high power system may require a 40W state or more for a decent
battery charging user experience. Therefore, a board's overlay may override the
warning threshold by replacing `/usr/share/power_manager/usb_min_ac_watts` in
the board's filesystem.
See also `platform2/power_manager/` source code.
### Cell Imbalance
Under normal conditions, the battery pack is equipped with a management IC which
is solely responsible for the safety of the battery, measurement of the state of
charge, and the balance of its cells. Examples include (but are not limited to)
the TI BQ40Z50 and Renesas RAJ240.
However, after very long periods of rest without a battery charging cycle, the
natural self-discharge rate of each cell will cause them to diverge somewhat
from each other.
Some IC's can be configured to report a pack total state of charge of zero if
any one cell's voltage is below a certain threshold. However, many do not.
Therefore, after an extended rest period, one cell can be very close to the cell
undervoltage cutoff threshold, even though the pack as a whole is considered to
be at 3% charge or more.
### Power Profile During Boot
The power profile during the boot sequence is substantially different than that
seen during typical use. Dynamic voltage and frequency scaling of the AP is
partially governed by the temperature of the processor core. As the processor
gets hotter, it will reduce its maximum core voltage and frequency to settle out
at some maximum design junction temperature for the core. For passively cooled
devices, the profile may also be chosen to limit the external case temperature.
At startup, the case and core are cold. The bootloaders and kernel are also
optimized to boot as fast as possible for a responsive user experience. So, the
power drawn during the boot is much higher than that seen during typical
productivity and entertainment tasks.
### Depthcharge Power Verification
After verification and optional update of the EC's RW firwmare, Depthcharge will
poll the EC to verify that it is allowed to proceed to boot to the kernel.
It does this by polling via the:
- `EC_CMD_CHARGE_STATE` host command.
- `CHARGE_STATE_CMD_GET_PARAM` subcommand.
- `CS_PARAM_LIMIT_POWER` parameter.
When the EC returns 0, power draw by the AP is unlimited and depthcharge resumes
the boot. If the EC fails to return 0 in three seconds, depthcharge shuts down.
See also vb2ex_ec_vboot_done() in Depthcharge, and option
`CONFIG_CHARGER_LIMIT_POWER_THRESH_CHG_MW` in the EC. By default, this option
is not set, and the EC immediately allows the boot to proceed.
## Example Low-Battery Boot Sequences and Configurations
Most ChromeOS devices power needs will be met by one of the following templates.
### Low-Power Device
Low-power devices require 15W or less of power to boot the AP. The battery pack
is robust enough to support the device during brief intervals of PD negotiation
without browning out.
```
#define CONFIG_CHARGER_INPUT_CURRENT 512
#define CONFIG_CHARGER_MIN_BAT_PCT_FOR_POWER_ON 1
```
A detailed boot sequence under this configuration, with a low battery and
available AC power via a USB-PD charger:
1. EC ROM bootloader loads and jumps to the EC's read-only firmware image.
1. RO firmware negotiates a 15W state via Current Source analog signaling and
begins charging the battery with it.
1. RO firmware verifies conditions to begin booting the AP:
- Battery state of charge > 1%
- OR charger power greater or equal to 15W (met by Current Source analog
signaling).
1. AP firmware performs verification of the EC's RW image, upgrades it if
necessary, and sysjumps the EC to it.
1. AP firmware queries the charge state limit power flag via EC-host command,
and the EC immediately responds that it is clear.
1. Depthcharge continues the boot.
1. In parallel with kernel loading and Linux's boot, the EC performs PD
negotiation. Charger power lowers to 2.5W for up to 500ms as the source
transitions from vSafe5V to its highest supported voltage (15V or 20V
are typical). During this transition time some power is drawn from the
battery.
1. After PD negotiation is complete, the EC raises the charger current
limit to the negotiated limit (45W is typical).
### Low-Power Device Startup With Marginal Battery Compatibility
Similar in configuration to the low-power device startup, this system enables
additional options to maximize its compatibility with marginal batteries near
the bottom of charge. The Grunt family is an exemplar. This system will
complete software sync with less than 15W of power, but may require more power
to boot the kernel and get to the login screen.
```
/* Limit battery impact during PD voltage changes. */
#define CONFIG_CHARGER_INPUT_CURRENT 512
/* Distrust the battery SOC measurement a bit. */
#define CONFIG_CHARGER_MIN_BAT_PCT_FOR_POWER_ON 3
/*
* Require PD negotiation to be complete prior to booting Linux, but don't
* care about how much power we negotiate.
*/
#define CONFIG_CHARGER_LIMIT_POWER_THRESH_CHG_MW 15001
/* Extra paranoia about imbalanced cells. */
#define CONFIG_BATTERY_MEASURE_IMBALANCE
```
Additionally, in order to take advantage of cell imbalance detection, the system
battery must support per-cell voltage measurement.
A detailed boot sequence under this configuration, with a low battery and
available AC power:
1. EC ROM bootloader loads and jumps to the EC's read-only firmware image.
1. RO firmware negotiates a 15W state via Current Source analog signaling and
begins charging the battery with it.
1. RO firmware verifies conditions to begin booting the AP:
- battery state of charge >= 3% AND cell imbalance < 200 mV
- OR battery state of charge >= 5%
- OR charger power greater or equal to 15W (met by Current Source analog
signaling).
1. AP firmware performs verification of the EC's RW image, upgrades it if
necessary, and sysjumps the EC to it.
1. AP firmware polls the charge state limit power flag via EC-host command for
up to 3 seconds, in 50ms intervals. The EC will return `1` (power limited)
so long as the charger power is < 15.001W and the battery is less than 3%.
1. Meanwhile, the EC performs PD negotiation. Charger power lowers to 2.5W
for up to 500ms as the source transitions from vSafe5V to its highest
supported voltage (15V or 20V are typical).
1. After negotiation is complete, the EC raises the charger current limit
to the negotiated limit (45W is typical).
1. The EC returns 0 (unlimited) on the next `LIMIT_POWER` request.
1. Depthcharge continues to boot Linux.
### High-Power Boot Device Startup
A "high-power device" in this case is one that requires significantly more than
15W of power to boot the AP. These devices may complete software sync at 15W or
less. Very briefly drawing current out of the battery does not cause a
brownout.
Example configuration:
```
#define CONFIG_CHARGER_INPUT_CURRENT 512
#define CONFIG_CHARGER_MIN_BAT_PCT_FOR_POWER_ON 3
#define CONFIG_CHARGER_MIN_POWER_MW_FOR_POWER_ON 15000
#define CONFIG_CHARGER_LIMIT_POWER_THRESH_CHG_MW 27000
```
Where the low-power device specified a threshold that just barely
requires PD negotiation to happen before booting, this device has a definite
minimum power to boot Linux (27W). A detailed boot sequence under this
configuration, with a low battery and available AC power:
1. EC ROM bootloader loads and jumps to the EC's read-only firmware image.
1. RO firmware negotiates a 15W state via Current Source analog signaling and
begins charging the battery with it.
1. RO firmware verifies conditions to begin booting the AP:
- battery state of charge >= 3%
- OR charger power greater or equal to 15W (met by Current Source analog
signaling).
1. AP firmware performs verification of the EC's RW image, upgrades it if
necessary, and sysjumps the EC to it.
1. AP firmware polls the charge state limit power flag via EC-host command for
up to 3 seconds, in 50ms intervals. The EC will return `1` (power limited)
so long as the charger power is < 27W and the battery is less than 3%.
1. Meanwhile, the EC performs PD negotiation. Charger power lowers to 2.5W
for up to 500ms as the source transitions from vSafe5V to its highest
supported voltage (15V or 20V are typical).
1. After negotiation is complete, the EC raises the charger current limit
to the negotiated limit (45W is typical).
1. The EC returns 0 (unlimited) on the next `LIMIT_POWER` request.
1. Depthcharge continues to boot Linux.
### High-Power SwSync Device Startup
Like the high-power boot device startup, these devices draw less than 15W during
most of the software sync process, but may briefly exceed 15W during short
intervals of software sync. However, there is substantial risk of brownout
during those intervals unless the battery is charged up a bit first. Therefore,
they strictly require 1% battery capacity to perform software sync.
Additionally, this configuration requires PD negotiation to be complete prior to
performing a no-battery boot. Nami is an exemplar.
Example configuration:
```
#define CONFIG_CHARGER_INPUT_CURRENT 512
#define CONFIG_CHARGER_MIN_BAT_PCT_FOR_POWER_ON_WITH_AC 1
#define CONFIG_CHARGER_MIN_POWER_MW_FOR_POWER_ON_WITH_BATT 15000
#define CONFIG_CHARGER_MIN_BAT_PCT_FOR_POWER_ON 3
#define CONFIG_CHARGER_MIN_POWER_MW_FOR_POWER_ON 27000
#define CONFIG_CHARGER_LIMIT_POWER_THRESH_BAT_PCT 3
#define CONFIG_CHARGER_LIMIT_POWER_THRESH_CHG_MW 27000
```
1. EC ROM bootloader loads and jumps to the EC's read-only firmware image.
1. RO firmware negotiates a 15W state via Current Source analog signaling and
begins charging the battery with it.
1. RO firmware verifies conditions to begin booting the AP:
- Battery state of charge is greater than 1% AND charger power is greater
than 15W (met after a minute or so of charging on analog signaling)
- OR Battery state of charge is greater than 3%
- OR Charger power is greater than 27W (met after PD negotiation in
unlocked RO firmware).
1. AP firmware performs verification of the EC's RW image, upgrades it if
necessary, and sysjumps the EC to it.
1. AP firmware polls the charge state limit power flag via EC-host command for
up to 3 seconds, in 50ms intervals. The EC will return `1` (power limited)
so long as the charger power is < 27W and the battery is less than 3%.
1. Meanwhile, the EC performs PD negotiation. Charger power lowers to 2.5W
for up to 500ms as the source transitions from vSafe5V to its highest
supported voltage (15V or 20V are typical).
1. After negotiation is complete, the EC raises the charger current limit
to the negotiated limit (45W is typical).
1. The EC returns 0 (unlimited) on the next `LIMIT_POWER` request.
1. Depthcharge continues to boot Linux.
## Configuration Option Details
### `CONFIG_CHARGER_INPUT_CURRENT`
Required.
The lowest current limit programmed into the charger. This determines both the
default level used on startup, and the value used during the voltage transients
in PD negotiation.
It should not be higher than 512 mA unless the device ships with a discrete
power supply. Raising this term above 512 mA is contrary to USB-PD. It may be
lowered in order to improve compatibility with marginal BC1.2 chargers.
### `CONFIG_CHARGER_MIN_BAT_PCT_FOR_POWER_ON`
Required.
The minimum battery state of charge to start up the AP, in percent of full
charge.
#### `CONFIG_CHARGER_MIN_POWER_MW_FOR_POWER_ON`
Default: 15000 (15W)
The minimum charger power level to start the AP even when the battery is less
than `CHARGER_MIN_BAT_PCT_FOR_POWER_ON`, in milliwatts.
### `CONFIG_BATTERY_MEASURE_IMBALANCE`
Optional. Only set this option if one or more batteries shipped with this board
support per-cell battery voltage measurement.
When enabled, the EC will query the attached battery for its per-cell voltages.
If the cell voltage is excessively imbalanced at a low state of charge, the boot
is inhibited.
#### `CONFIG_CHARGER_MIN_BAT_PCT_IMBALANCED_POWER_ON`
Default: 5%. Above this battery state of charge, cell voltage balance is
ignored.
#### `CONFIG_BATTERY_MAX_IMBALANCE_MV`
Default: 200 mV. If the difference between the highest and lowest cell exceeds
this value, then the pack is considered to be imbalanced.
Note that lithium chemistry cells will almost always read similar voltages. It
is only near the top and bottom of charge that the slope of dV/dQ increases
enough for small cell imbalances to be visible as a voltage difference.
### `CONFIG_CHARGER_LIMIT_POWER_THRESH_CHG_MW`
Optional.
The minimum charger power level to allow Depthcharge to start up the kernel,
even when the battery state of charge is less than
`CHARGER_LIMIT_POWER_THRESH_BAT_PCT`, in milliwatts.
When this term is `#undef`ined (the default), kernel startup is immediately
allowed.
#### `CONFIG_CHARGER_LIMIT_POWER_THRESH_BAT_PCT`
Optional.
The minimum battery state of charge to allow Depthcharge to start up the kernel.
When using this feature, start with `CONFIG_CHARGER_MIN_BAT_PCT_FOR_POWER_ON`
### `CONFIG_CHARGER_MIN_BAT_PCT_FOR_POWER_ON_WITH_AC`
Optional.
Similar to `MIN_BAT_PCT_FOR_POWER_ON`, but used to define a secondary threshold
for this feature.
#### `CONFIG_CHARGER_MIN_POWER_MW_FOR_POWER_ON_WITH_BATT`
Optional.
Similar to `CONFIG_CHARGER_MIN_POWER_MW_FOR_POWER_ON`, this is the minimum
charger power needed to boot even when the battery is less than
`CONFIG_CHARGER_MIN_BAT_PCT_FOR_POWER_ON_WITH_AC`
*** note
**Warning: This document is old & has moved. Please update any links:**<br>
https://chromium.googlesource.com/chromiumos/platform/ec/+/HEAD/docs/low_battery_startup.md
***

View File

@ -1,172 +1,5 @@
# Creating a new EC board
*** note
**Warning: This document is old & has moved. Please update any links:**<br>
https://chromium.googlesource.com/chromiumos/platform/ec/+/HEAD/docs/new_board_checklist.md
***
[TOC]
## Overview
This document describes the high-level steps needed to create a new EC board. If
you're creating a new board based on existing baseboard, you can jump straight
to the relevant link found under [Configuring EC
Features](#Configure-EC-Features) and focus on known board changes.
## Conventions
### Key Files
Before you get started, it's important to understand the role of a few key files
in the EC codebase.
- [`include/config.h`](../include/config.h) {#config_h} - Contains the list of
top-level configuration options for the Chrome EC codebase. Each configuration
option is documented inline and is considered the authoritative definition.
- `baseboard/<name>/` - This directory contains header files and source files
shared by all boards in a baseboard family.
- `baseboard.h` - Contains the EC configuration options shared by all
devices in the baseboard family.
- `baseboard.c` - Contains code shared by all devices in the baseboard
family.
- `build.mk` - The board family makefile specifies C source files compiled
into all boards in the baseboard family.
- `board/<board>` - Files in this directory are only built for a single board.
- `board.h` - EC configuration options specific to a single board.
- `board.c` - Code built only on this board.
- `build.mk` {#board_build_mk} - The board makefile defines the EC chipset family, defines the
baseboard name, and specifies the C source files that are compiled.
- `gpio.inc` - This C header file defines the interrupts, GPIOs, and
alternate function selection for all pins on the EC chipset.
- `ec.tasklist` - This C header defines the lists of tasks that are enabled
on the board. See the main EC documentation more details on [EC tasks].
### GPIO Naming
Many drivers and libraries in the common EC code rely on board variants defining
an exact GPIO signal name. Examples include the `GPIO_LID_OPEN`,
`GPIO_ENTERING_RW`, and `GPIO_SYS_RESET_L` signals. The net names in schematics
often do not match these names exactly. When this occurs, best practice is that
all the `GPIO_INT()`, `GPIO()`, `ALTERNATE()`, and `UNIMPLEMENTED()` definitions
in `gpio.inc` use the schematic net name. You then create `#define` macros in
`board.h` to map the net names to the EC common names.
Below is an example configuration for the SYS_RESET_L signal. The schematic net
name of this signal is EC_RST_ODL and the signal connects to the EC chipset pin
GPIO02.
```c
/* From gpio.inc */
GPIO(EC_RST_ODL, PIN(0, 2), GPIO_ODR_HIGH)
/* From board.h */
/* Map the schematic net name to the required EC name */
#define GPIO_SYS_RESET_L GPIO_EC_RST_ODL
```
Please see the [GPIO](./configuration/gpio.md) documentation for additional
details on the GPIO macros.
## How to use this document
Each of the following sections details a single feature set that may need to be
modified or configured for your new board. The feature sets are organized so
they can be implemented with a reasonably sized change list, and can be worked
on independently.
Each configuration feature document includes the following sub-tasks:
- **Config Options** - This section details the `CONFIG_*` options relevant to
the feature. Use the documentation found in [config.h] to determine whether
each option should be enabled (using #define) or disabled (using #undef) in
the relevant `baseboard.h` or `board.h` file.
- **Feature Parameters** - This section details parameters that control the
operation of the feature. Similar to the config options, feature parameters
are defined in [config.h] and prefixed with `CONFIG_*`. However, feature
parameters are assigned a default value, which can be overridden in by
`baseboard.h` or `board.h` using an `#undef/#define` pair.
```c
#undef CONFIG_UART_TX_BUF_SIZE
#define CONFIG_UART_TX_BUF_SIZE 4096
```
- **GPIOs and Alternate Pins** - This section details signals and pins relevant
to the feature. Add the required `GPIO_INT()`, `GPIO()`, `ALTERNATE()`, and
`UNIMPLEMENTED()` definitions to `gpio.inc`, making sure to follow the [GPIO
naming conventions].
- **Data Structures** - This section details the data structures required to
configure the feature for correct operation. Add the data structures to
`baseboard.c` or `board.c`. Note that most data structures required by the
common EC code should be declared `const` to save on RAM usage.
- **Tasks** - This section details the tasks that the EC feature requires for
operation.
- **Testing and Debugging** - This section details strategies for testing the EC
feature set and for debugging issues. This section also documents EC console
commands related to the feature set.
- **Example** - When present, this section walks through a complete example for
configuring an EC feature based on an existing board implementation.
## Create the new EC board
The first step when creating a new EC board, is to create the required files in
the `./baseboard` and `./board` directories. When adding a new board for an
existing baseboard family, use the python script [new_variant.py] to
automatically copy the `./board` directory from an existing EC board to get you
started. The [new_variant.py] script performs additional operations not directly
related to the EC code, including copying coreboot files and modifying the yaml
files. If you want to copy the EC board files only, you can directly call the
[create_initial_ec_image.sh] script. The instructions for running this script
are found in the corresponding [README.md] documentation.
The [new_variant.py] script also verifies the new EC board compiles and prepares
a changelist to upload to Gerrit. You should upload this changelist unmodified
for review and submission (you may need to run `make buildall -k` to satisfy
the EC pre-submit tests).
The next step is to review the following sections to make any needed
modifications to your new board files, test the changes, and upload the changes
for review.
### Creating a new reference board
If you are creating a new reference board, it is recommended that you manually
create new directories under the `./baseboard` and `./board` directories and
populate these directories with the minimum set of files required compile the EC
board. The initial changelists for the Hatch and Volteer reference boards
provide good examples for how to start.
* [Volteer EC skeleton build]
* [Hatch EC skeleton build]
After submitting the skeleton builds, review the following sections and add each
feature set as required by your design.
## Configure EC Features
The checklist below provides an overview of EC features that must be configured
for correct operation of a Chromebook. The "Needed for Power On" column
indicates which features are critical for board bringup. These features take
priority and should be ready before the first prototypes arrive. Use the
documentation link for details about the code changes required to implement each
feature.
| EC Feature | Needed for Power On |
| :--------- | ------------------: |
| [Configure EC Chipset](./configuration/ec_chipset.md) | yes |
| [Configure AP to EC Communication](./configuration/config_ap_to_ec_comm.md) | yes |
| [Configure AP Power Sequencing](./configuration/ap_power_sequencing.md) | yes |
| [Configure USB-C](./usb-c.md) | yes |
| [Configure Charger (TODO)](./configuration/template.md) | yes |
| [Configure I2C Buses](./configuration/i2c.md) | no |
| [Configure CrOS Board Information (CBI)](./configuration/cbi.md) | no |
| [Configure Keyboard](./configuration/keyboard.md) | no |
| [Configure LEDs](./configuration/leds.md) | no |
| [Configure Motion Sensors (TODO)](./configuration/motion_sensors.md) | no |
| [Configure BC1.2 Charger Detector (TODO)](./configuration/template.md) | no |
| [Configure Battery (TODO)](./configuration/template.md) | no |
After finishing the changes required for all EC features, it is recommended that
you make one final pass over all the GPIOs and pin assignments used on your
board. Refer to the [GPIO](./configuration/gpio.md) documentation for details.
[README.md]:https://chromium.googlesource.com/chromiumos/platform/dev-util/+/master/contrib/variant/README.md
[new_variant.py]:https://chromium.googlesource.com/chromiumos/platform/dev-util/+/master/contrib/variant/new_variant.py
[create_initial_ec_image.sh]:https://chromium.googlesource.com/chromiumos/platform/dev-util/+/master/contrib/variant/create_initial_ec_image.sh
[Volteer EC skeleton build]:https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/1758532
[Hatch EC skeleton build]:https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/1377569/
[config.h]: ./new_board_checklist.md#config_h
[EC tasks]: ../README.md#Tasks
[GPIO naming conventions]: ./new_board_checklist.md#GPIO-Naming

View File

@ -1,10 +1,5 @@
# Dragonclaw Fingerprint Development Board Schematics
*** note
**Warning: This document is old & has moved. Please update any links:**<br>
https://chromium.googlesource.com/chromiumos/platform/ec/+/HEAD/docs/schematics/dragonclaw/README.md
***
The schematics are in the [HTML file][schematic] and viewable with any browser.
Note that you'll need to download and save the HTML file from
[this link][schematic]; you cannot view it directly from the server.
The layout file is in the [`.brd`] file.
[`.brd`]: https://raw.githubusercontent.com/coreboot/chrome-ec/master/docs/schematics/dragonclaw/dragonclaw_v0.2.brd
[schematic]: https://raw.githubusercontent.com/coreboot/chrome-ec/master/docs/schematics/dragonclaw/dragonclaw_v0.2.html

View File

@ -1,71 +1,5 @@
# Sitemap
*** note
**Warning: This document is old & has moved. Please update any links:**<br>
https://chromium.googlesource.com/chromiumos/platform/ec/+/HEAD/docs/sitemap.md
***
## Getting Started
* [Getting Started Quickly](./getting_started_quickly.md)
* [Core Runtime](./core_runtime.md)
* [Write Protection](./write_protection.md)
* [EC Acronyms and Technologies](./ec_terms.md)
## EC Bringup
* [New Board Checklist](./new_board_checklist.md)
## Case Closed Debugging (CCD)
* [Case Closed Debugging Overview][1]
* [Google Security Chip Case Closed Debugging][2]
* [Tutorials][3]
## Verified Boot Troubleshooting
* [Cr50 Verified Boot Troubleshooting][4]
## Fingerprint MCU (FPMCU)
* [Fingerprint MCU (FPMCU)](./fingerprint/fingerprint.md)
* [FPMCU Development for Partners](./fingerprint/fingerprint-dev-for-partners.md)
* [FPMCU Firmware Testing for Partners](./fingerprint/fingerprint-firmware-testing-for-partners.md)
* [FPMCU Debugging](./fingerprint/fingerprint-debugging.md)
* [Fingerprint Authentication Design Doc](./fingerprint/fingerprint-authentication-design-doc.md)
* [Fingerprint Factory Requirements](./fingerprint/fingerprint-factory-requirements.md)
* [Fingerprint Quick Factory Guide](./fingerprint/fingerprint-factory-quick-guide.md)
* [Dragonclaw Schematics and Layout](./schematics/dragonclaw)
## Testing
* [Unit Tests](./unit_tests.md)
* [Porting EC unit tests to Ztest](./ztest.md)
* [Code Coverage](./code_coverage.md)
## Updaters
* [USB Updater](./usb_updater.md)
## USB
* [USB-C Power Delivery and Alternate Modes](./usb-c.md)
* [USB-A and USB-C Policies for Sourcing Power](./usb_power.md)
* [USB-C Power Delivery TCPMv2](./usb-tcpmv2.md)
## Verified Boot
* [Detachable Base Verified Boot](./detachable_base_verified_boot.md)
## EC-3PO
* [EC-3PO overview](./ec-3po.md)
* [EC-3PO design doc](./ec-3po-design.md)
## Miscellaneous
* [Low Battery Startup](./low_battery_startup.md)
* [I2C tracing via console commands](./i2c-debugging.md)
* [Application Processor to EC communication](./ap-ec-comm.md)
* [Code Reviews](./code_reviews.md)
* [IDE Support](./ide-support.md)
[1]:https://chromium.googlesource.com/chromiumos/platform/ec/+/cr50_stab/docs/case_closed_debugging.md
[2]:https://chromium.googlesource.com/chromiumos/platform/ec/+/cr50_stab/docs/case_closed_debugging_cr50.md
[3]:https://chromium.googlesource.com/chromiumos/platform/ec/+/cr50_stab/docs/ccd_howtos.md
[4]:https://chromium.googlesource.com/chromiumos/platform/ec/+/cr50_stab/docs/cr50_vboot_troubleshooting.md

View File

@ -1,219 +1,5 @@
# Unit Tests
Provides an overview of how to write and run the unit tests in the EC codebase.
[TOC]
## Running Unit Tests {#running}
The unit tests run on the host machine using the [`host` board].
List available unit tests:
```bash
(chroot) ~/trunk/src/platform/ec $ make print-host-tests
```
Build and run a specific unit test (the `host_command` test in this example):
```bash
(chroot) ~/trunk/src/platform/ec $ make run-host_command
```
Build and run all unit tests:
```bash
(chroot) ~/trunk/src/platform/ec $ make runhosttests -j
```
## Writing Unit Tests
Unit tests live in the [`test`] subdirectory of the CrOS EC codebase.
All new unit tests should be written to use the Zephyr Ztest
[API](https://docs.zephyrproject.org/latest/guides/test/ztest.html).
If you are making significant changes to an existing test, you should also
look at porting the test from the EC test API to the Ztest API.
Using the Ztest API makes the unit tests suitable for submitting upstream to
the Zephyr project, and reduces the porting work when the EC transitions to
the Zephyr RTOS.
### File headers
Include [`test_util.h`] and any other required includes. In this example,
the function being tested is defined in the test, but a real unit test would
include the header file for the module that defines `some_function`.
`test/my_test.c`:
```c
#include <stdbool.h>
#include "test_util.h"
static bool some_function(void)
{
return true;
}
```
[`test_util.h`] includes `ztest.h` if `CONFIG_ZEPHYR` is defined,
or defines a mapping from the `zassert` macros to the EC
`TEST_ASSERT` macros if `CONFIG_ZEPHYR` is not defined.
### Test cases
Define the test cases. Use the `EC_TEST_RETURN` return type on these functions.
```c
/* Write a function with the following signature: */
test_static EC_TEST_RETURN test_my_function(void)
{
/* Run some code */
bool condition = some_function();
/* Check that the expected condition is correct. */
zassert_true(condition, NULL);
return EC_SUCCESS;
}
```
`test/my_test.c`:
```c
/* Write a function with the following signature: */
test_static EC_TEST_RETURN test_my_function(void)
{
/* Run some code */
bool condition = some_function();
/* Check that the expected condition is correct. */
TEST_EQ(condition, true, "%d");
return EC_SUCCESS;
}
```
The only difference between those two versions of `test/my_test.c` is the
assertion:
```c
zassert_true(condition, NULL);
```
versus
```c
TEST_EQ(condition, true, "%d");
```
### Specify the test cases to run
The EC test API enumerates the test cases using `RUN_TEST` in the `run_test`
function, while the Ztest API enumerates the test cases using `ztest_unit_test`
inside another macro for the test suite, inside of `test_main`.
`test/my_test.c`:
```c
#ifdef CONFIG_ZEPHYR
void test_main(void)
{
ztest_test_suite(test_my_unit,
ztest_unit_test(test_my_function));
ztest_run_test_suite(test_my_unit);
}
#else
/* The test framework will call the function named "run_test" */
void run_test(int argc, char **argv)
{
/* Each unit test can be run using the RUN_TEST macro: */
RUN_TEST(test_my_function);
/* Report the results of all the tests at the end. */
test_print_result();
}
#endif /* CONFIG_ZEPHYR */
```
### Task List
EC unit tests can run additional tasks besides the main test thread. The EC unit
test implementation provides a phtreads-based implementation of the EC task API.
We do not yet support running additional tasks in Ztest-based tests.
In the [`test`] subdirectory, create a `tasklist` file for your test that lists
the tasks that should run as part of the test:
`test/my_test.tasklist`:
```c
/*
* No test task in this case, but you can use `TASK_TEST` macro to specify one.
*/
#define CONFIG_TEST_TASK_LIST
```
### Makefile
Add the test to the `Makefile` so that it can build as an EC unit test:
`test/build.mk`:
```Makefile
test-list-host += my_test
```
and
```Makefile
my_test-y=my_test.o
```
Make sure you test shows up in the "host" tests:
```bash
(chroot) $ make print-host-tests | grep my_test
host-my_test
run-my_test
```
### Build and Run
Build and run the test as an EC unit test:
```bash
(chroot) $ make run-my_test
```
For building the test as a Zephyr Ztest unit test, follow the instructions in
[Porting EC unit tests to Ztest](./ztest.md) to build the unit test for
Zephyr's "native_posix" host-based target.
*** note
**TIP**: Unit tests should be independent from each other as much as possible.
This keeps the test (and any system state) simple to reason about and also
allows running unit tests in parallel. You can use the
[`before_test` hook][`test_util.h`] to reset the state before each test is run.
**Warning: This document is old & has moved. Please update any links:**<br>
https://chromium.googlesource.com/chromiumos/platform/ec/+/HEAD/docs/unit_tests.md
***
## Mocks
We do not yet support mocks for Zephyr Ztest-based tests.
[Mocks][`mock`] enable you to simulate behavior for parts of the system that
you're not directly testing. They can also be useful for testing specific edge
cases that are hard to exercise during normal use (e.g., error conditions).
See the [Mock README] for details.
### Mock Time
When writing unit tests that rely on a clock, it's best not to rely on a real
hardware clock. It's very difficult to enforce exact timing with a real clock,
which leads to test flakiness (and developers ignoring tests since they're flaky
). Instead, use the [Mock Timer] to adjust the time during the test.
[`mock`]: /include/mock
[Mock Timer]: /include/mock/timer_mock.h
[`test`]: /test
[`host` board]: /board/host/
[`test_util.h`]: /include/test_util.h
[Mock README]: /common/mock/README.md

View File

@ -1,216 +1,5 @@
# EC Implementation of USB-C Power Delivery and Alternate Modes
*** note
**Warning: This document is old & has moved. Please update any links:**<br>
https://chromium.googlesource.com/chromiumos/platform/ec/+/HEAD/docs/usb-c.md
***
USB-C PD requires a complex state machine as USB-C PD can operate in many
different modes. This includes but isn't limited to:
* Negotiated power contracts. Either side of the cable can source or sink
power up to 100W (if supported by device).
* Reversed cable mode. This requires a mux to switch the signals before
getting to the SoC (or AP).
* Debug accessory mode, e.g. [Case Closed Debugging (CCD)]
* Multiple uses for the 4 differential pair signals including
* USB SuperSpeed mode (up to 4 lanes for USB data)
* DisplayPort Alternate Mode (up to 4 lanes for DisplayPort data)
* Dock Mode (2 lanes for USB data, and 2 lanes for DisplayPort)
* Audio Accessory mode. (1 lane is used for L and R analog audio signal)
For a more complete list of USB-C Power Delivery features, see the
[USB-C PD spec][USB PD Spec Id].
This document covers various touch points to consider for USB-C PD and Alternate
Modes in the EC codebase.
[TOC]
## Glossary
* PD {#pd}
* Power Delivery. Protocol over USB-C connector that allows up to 100W of
power. Not supported on USB-A or USB-B connectors. A good overview of
USB PD is found in the [Introduction to USB Power Delivery] application
note.
* TCPC {#tcpc}
* Type-C Port Controller. Typically a separate IC connected through I2C,
sometimes embedded within the EC as a hardware sub module. The TCPC
interprets physical layer signals on CC lines and Vbus, and sends that
information to the TCPM to decide what action to take. In older designs,
there was a separate EC (running this codebase) that acted as the TCPC
that communicated with the main EC (also running this codebase), which
acted as the TCPM. More info in the official
[TCPC spec][USB TCPM Spec Id].
* TCPM {#tcpm}
* Type-C Port Manager. Manages the state of the USB-C connection. Makes
decisions about what state to transition to. This is the code running on
the EC itself.
* PE {#pe}
* Policy Engine. According to the [TypeC spec][USB TC Spec Id], the policy
engine is the state machine that decides how the USB-C connection
progresses through different states and which USB-C PD features are
available, such as Try.SRC
* TC {#tc}
* Type-C physical layer.
* PPC {#ppc}
* Power Path Controller. An optional, separate IC that isolates various
USB-C signals from each other and the rest of the board. This IC should
prevent shorts and over current/voltage scenarios for Vbus. Some PPCs
will protect signals other than Vbus as well.
* SSMUX {#ssmux}
* SuperSpeed Mux. This is typically the same IC as the TCPC; it enables
the mirrored orientation of the USB-C cable to go to the correct pins on
SoC. Also, allows the SuperSpeed signal to be used for different
purposes, such as USB data or DisplayPort.
* SVDM {#svdm}
* Structured Vendor Defined Messages are a class of [USB PD](#pd) messages
to enable non-power related communication between port partners. SVDMs
are used to negotiate and set the display port mode on a USB-C
connection.
* DRP {#drp}
* Dual Role Power Port. A USB-C port that can act as either a power Source
or power Sink.
* UFP {#ufp}
* Upstream Facing Port. The USB data role that is typical for a peripheral
(e.g. HID keyboard).
* DFP {#dfp}
* Downstream Facing Port. The USB Data role that is typical for a host
machine (e.g. device running ChromeOS).
* E-Mark {#emark}
* Electronically marked cable. A USB-C cable that contains an embedded
chip in the cable, used to identify the capabilities of the cable.
* VCONN {#vconn}
* Connector Voltage. A dedicated power supply rail for [E-Mark](#emark)
cables and other accessory functions (such as display dongles, and
docks). VCONN re-uses one of the CC1/CC2 signals to provide 5 volt, 1
watt, of power.
## Different PD stacks
Right now platform/ec has two different implementations of USB-C PD stack.
1. The older implementation is mainly contained within
[`usb_pd_protocol.c`](../common/usb_pd_protocol.c) and
[`usb_pd_policy.c`](../common/usb_pd_policy.c)
2. The newer implementation is found under [`common/usbc`](../common/usbc) and
is broken up into multiple different files and state machines
* Policy engine state machine files, `usb_pe_*_sm.c`.
* Protocol engine state machine file, `usb_prl_*_sm.c`.
* State machine framework file, `usb_sm.c`.
* Type-C physical layer state machine files, `usb_tc_*_sm.c`.
* USB-C PD Task file, `usbc_task.c`.
The older implementation supports firmware for device types other than
Chromebooks. For example, the older stack supports the Zinger, which is the
USB-C charging device that shipped with Samus, the Google Chromebook Pixel 2.
The Zinger implements the charger only side of the USB PD protocol.
To use the newer USB-C PD stack implementation, see
[TCPMv2 Overview](usb-tcpmv2.md).
## Implementation Considerations
In both older and newer implementations, the following details apply:
* For each USB-C port, there must be two tasks: `PD_C#` and `PD_INT_C#`, where
`#` is the port number starting from `0`.
* The `PD_C#` task runs the state machine (old or new) for the port and
communicates with the TCPC, MUX, and PPC. This task needs a large task
stack.
* The `PD_INT_C#` tasks run at a higher priority than the state machine
task, and its sole job is to receive interrupts from the TCPC as quickly
as possible then send appropriate messages to other tasks (including
`PD_C#`). This task shouldn't need much stack space, but the i2c
recovery code requires a decent amount of stack space so it ends up
needing a fair amount too.
* Saving PD state between EC jumps
* PD communication is disabled in locked RO images (normal state for
customer devices). When the jump from RO to RW happens relatively
quickly (e.g. there is not a long memory training step), then there
aren't many problems when RW takes over and negotiates higher PD
contracts.
* To support factory use cases that don't have a battery (and are
therefore unlocked), PD communication is enabled in unlocked RO. This
allows systems without software sync enabled to get a higher power
contract than 15W in RO.
* We save and restore PD state between RO -> RW and RW -> RO jump to allow
us to maintain a higher negotiated power through the full jump and
re-initialization process. For example, for each port we save the power
role, data role, and Vconn sourcing state in battery-backed or
non-volatile RAM. This allows the firmware image that is initializing to
restore an existing SNK contract (Chromebook as SNK) without cutting
power. We don't cut the power from the external supplier because we
issue a SoftReset (leaves Vbus intact) instead of a HardReset (drops
Vbus) in this contract resume case.
* Both use cases where we actually are able to restore the PD contract
require an unlocked RO (e.g. factory) otherwise RO cannot communicate
via PD and will drop the higher PD contract (by applying Rp/Rp on the CC
lines temporarily)
* The RO->RW use case is for an unlocked (e.g. factory) device that
negotiated power and we want to keep that contract after we jump to
RW in the normal software sync boot process. This is especially
useful when there is no battery and Vbus is our only power source.
* The RW->RO use case happens when we are performing auxiliary FW
upgrades during software sync and BIOS instructs the EC to jump back
to RO. We'll also try to maintain contracts over an EC reset when
unlocked.
## Configuration
There are many `CONFIG_*` options and driver structs that are needed in the
board.h and board.c implementation.
### TCPC Config
The `tcpc_config` array of `tcpc_config_t` structs defined in `board.c` (or
baseboard equivalent) should be defined for every board. The index in the
`tcpc_config` array corresponds to the USB-C port number. This struct should
point to the specific TCPC driver that corresponds to the TCPC that is being
used on that port. The i2c port and address for the TCPC are also specified
here.
### SSMUX Config
The `usb_muxes` array of `usb_mux` structs defined in `board.c` (or baseboard
equivalent) should be defined for every board. Normally the standard
`tcpci_tcpm_usb_mux_driver` driver works, especially if TCPC and MUX are the
same IC.
If the signal strength for the high-speed data lines needs to be tuned for a
specific hardware layout, the `board_init` field on the `usb_mux` is called
every time the mux is woken up from a low power state and should be used for
setting custom board tuning parameters.
### PPC Config
Some boards have an additional IC that sits between the physical USB-C connector
and the rest of the board. The PPC IC gates whether the Vbus line is an input or
output signal, based on i2c settings or gpio pins. A PPC also typically provides
over voltage and over current protection on multiple USB-C pins.
The `ppc_chips` array of `ppc_config_t` structs defined in `board.c` (or
baseboard equivalent) sets the appropriate driver and i2c port/address for the
PPC IC.
### Useful Config Options
Many USB-C policies and features are gated by various `CONFIG_*` options that
should be defined in `board.h` (or baseboard equivalent).
Most USB-C options will start with `CONFIG_USB_PD_` or `CONFIG_USBC_`. For their
full descriptions see [config.h][config header link]
## Interactions with other tasks
TODO(https://crbug.com/974302): mention `USB_CHG_P#` and `CHARGER`
## Upgrading FW for TCPCs
TODO(https://crbug.com/974302): Mention how this works even though it is in depthcharge.
Probing now. Need new driver in depthcharge
[Case Closed Debugging (CCD)]: https://chromium.googlesource.com/chromiumos/platform/ec/+/cr50_stab/docs/case_closed_debugging_cr50.md
[Introduction to USB Power Delivery]: https://www.microchip.com/wwwAppNotes/AppNotes.aspx?appnote=en575003
[USB PD Spec Id]: https://www.usb.org/document-library/usb-power-delivery
[USB TC Spec Id]: https://www.usb.org/document-library/usb-type-cr-cable-and-connector-specification-revision-20-august-2019
[USB TCPM Spec Id]: https://www.usb.org/document-library/usb-type-ctm-port-controller-interface-specification
[config header link]: ../include/config.h

View File

@ -1,185 +1,5 @@
# EC USB-C Power Delivery TCPMv2 Overview
*** note
**Warning: This document is old & has moved. Please update any links:**<br>
https://chromium.googlesource.com/chromiumos/platform/ec/+/HEAD/docs/usb-tcpmv2.md
***
As the original USB-C Power Delivery (PD) solution for the ChromeOS Embedded Controller has aged, it has grown to the point where it is difficult to add new features and address bugs. A new PD stack (generally referred to as TCPMv2) has been introduced to the codebase for use moving forward. It implements a layered, state-based design which tracks more closely with the USB Type-C and USB PD specifications.
[TOC]
## Enabling TCPMv2
Boards may enable TCPMv2 by adding the following defines:
* `CONFIG_USB_PD_TCPMV2`Configures the board to use the new stack.
* `CONFIG_USB_DRP_ACC_TRYSRC`: Configures the type of state machine to run (in this case, a DRP which performs Try.SRC behavior). Currently available are DRP and charge-through Vconn-powered device options
* `CONFIG_USB_PD_DECODE_SOP`: Sets up messaging for SOP and SOP, which is strongly encouraged in the TCPMv2 code moving forward
* `CONFIG_USB_PID 0x1234`: Sets the USB Product Identifier. This will be shared for all boards within one reference design, and new PIDs may be requested by sending an email to the ChromeOS FW Team.
* `CONFIG_USB_PD_REV30`: The TCPMv2 stack defaults to PD2.0 operation but defining this macro enables PD3.0 functionality.
Other configurations to specify behaviors within the task still apply (ex. `CONFIG_USB_PD_ALT_MODE_DFP` and `CONFIG_USB_PD_TCPC_LOW_POWER`).
## State Machine Framework
The basis of the TCPMv2 state machines is a generic state machine framework. This framework can be found in common/usbc/usb\_sm.c. For each state, there may be defined:
* Entry: Called upon entering a state
* Run: Called while steady in a state
* Exit: Called upon leaving a state
* Parent: Superstate. Enters, exits, and runs alongside the child state. Only enters and exits when transitioning between states which do not share the parent.
All fields are optional and may be set to NULL. A new state is transitioned to with a call into set\_state(), which exits the old state and parents and enters the new parents and state. States may be changed with set\_state() in any entry or run function, but any call from an exit function is ignored since exit is only called when a change is already in progress. While in a state, run\_state() executes the run function for the current state and parents. If set\_state() is called from either an entry function or a run function, the remaining run or entry functions are stopped.
Below is a graphical example of what some states may look like. States 1 and 2 share Parent State 1, while State 3 has Parent State of 2.
![Example States](images/TCPMv2-ExampleStates.png "Example States")
Translated into code, this would be something like below (note it is not necessary that the states be a part of an array, but the TCPMv2 code generally organizes the states in this way):
```
static const struct usb_state test_states[] = {
[PARENT_1] = {
.entry = parent_1_entry,
.run = parent_1_run,
.exit = parent_1_exit,
},
[PARENT_2] = {
.entry = parent_2_entry,
.run = parent_2_run,
.exit = parent_2_exit,
},
[STATE_1] = {
.entry = state_1_entry,
.run = state_1_run,
.exit = state_1_exit,
.parent = &test_states[PARENT_1],
},
[STATE_2] = {
.entry = state_2_entry,
.run = state_2_run,
.exit = state_2_exit,
.parent = &test_states[PARENT_1],
},
[STATE_3] = {
.entry = state_3_entry,
.run = state_3_run,
.exit = state_3_exit,
.parent = &test_states[PARENT_2],
},
};
```
For this example, each test state is written simply to produce a print of its function name. The two exceptions are:
* parent\_1\_run() calls set\_state() into STATE\_2 when called a second time
* state\_2\_entry() calls set\_state() into STATE\_3
Graphically, this is represented below:
![Example Transitions](images/TCPMv2-ExampleTransitions.png "Example state transitions and resulting called functions")
And the following code output is produced:
```
Calling run_state()
state_1_run
parent_1_run
Calling run_state()
state_1_run
state_1_run calling set_state() to state 2
state_1_exit
state_2_entry
state_2_entry calling set_state() to state 3
state_2_exit
parent_1_exit
parent_2_entry
state_3_entry
Calling run_state()
state_3_run
parent_2_run
```
## TCPMv2 PD Task
The TCPMv2 PD task is built upon state machines using the above framework and is located in common/usbc/usbc\_task.c. It is separated into three layers which track with the USB Type-C and USB PD specification states and run in a loop with 5 ms periods between executions. A graphical representation of these layers is below.
![PD Task Loop](images/TCPMv2-TaskLoop.png "PD task loop state machine calls")
The task is designed such that the Type-C (TC) layer could run independently for any application which doesnt wish to enable PD messaging. Boards define their appropriate Policy Engine (PE) and TC state machines through their selection of a CONFIG\_USB\_\* define, with current options supporting both Dual-Role Ports (DRPs) and Charge-Through Vconn-Powered Device (CTVPD). All boards use the same Protocol Layer (PRL) code.
## TCPMv2 Layers
### Overview
The three state machines mentioned above interact with each other and the EC drivers in order to orchestrate all Type-C connection behavior. Graphically, they are represented below.
![PD Task Layers](images/TCPMv2-TaskLayers.png "PD task layer interactions")
Layers communicate with each other using atomic operations on flags and shared buffers. Functions calling into each layer are clearly named to indicate the layer they are acting on, and anything calling into the PD task should be doing so through pd\_\* named functions.
Some specific examples of how this communication works between layers is below. If a port partner sends in a Vconn\_swap request, then:
* PRL will communicate that a message was received to the PE layer through pe\_message\_received(), which sets PE\_FLAGS\_MSG\_RECEIVED and indicates the receive buffer has a message
* PE asks with the TC whether the board is sourcing Vconn with tc\_is\_vconn\_src() which checks TC\_FLAGS\_VCONN\_ON
* PE tells the PRL to send an ACCEPT message to the port partner through prl\_send\_ctrl\_msg() which fills in shared message information and sets PRL\_FLAGS\_MSG\_XMIT
* PRL lets the PE know that the message transmit was successful through pe\_message\_sent() which sets PE\_FLAGS\_TX\_COMPLETE
* TC tells the PE layer that the Vconn swap completed with pe\_vconn\_swap\_complete() which sets PE\_FLAGS\_VCONN\_SWAP\_COMPLETE
### Type-C Layer
Defined in the USB Type-C specification, this layer is responsible for basic connection. It takes care of setting the CC lines, detecting and debouncing the partner CC lines, and performs most of the interactions needed with the PPC and USB mux. Once the TC layer has gotten the connection to the point of being Attached.SNK or Attached.SRC, it will enable the PRL and PE layers accordingly.
### Protocol Layer
A part of the USB PD specification, the protocol layer is responsible for the actual sending and receiving of PD messages with the TCPCs. The layer is actually composed of 4 separate state machines running one after the other. These state machines are:
* Chunked receive (RCH): passes messages up to the PE and requests chunks when chunking
* Chunked transmit (TCH): receives messages from the PE and waits for chunk requests when chunking
* Protocol transmit (PRL\_TX): passes messages to the TCPCs and handles PD 3.0 collision avoidance
* Protocol hard reset (PRL\_HR): responds to or transmits hard resets, resets PRL layer variables, notifies PE of hard reset receipt or sent
### Policy Engine Layer
The PE layer states are defined as a part of the USB PD specification. State names are meant to track very closely with the specification so they can be easily searchable and understood. The PEs primary responsibility is to send and process PD messages in order to implement the ports policy.
## Best Practices
* Always call return after set\_state(). Once the state has been changed, nothing further should be done in the current state.
* Never call set\_state() from an exit function. The call will be ignored as there is already a state transition taking place.
* Never call set\_state() from outside the PD task. The task may be waiting in any number of locations and the context should not change around it while it does so.
* Always use flags to communicate between layers, and to communicate with the PD task from other tasks. Flags should be accessed through atomic operations.
* Always use pd\_\* functions to access the PD task from other tasks.
* Always write unit tests as code is added, to verify new code works and protect against regressions as development continues.

View File

@ -1,250 +1,5 @@
# USB Power Considerations
*** note
**Warning: This document is old & has moved. Please update any links:**<br>
https://chromium.googlesource.com/chromiumos/platform/ec/+/HEAD/docs/usb_power.md
***
Users want to be able to charge external devices using their Chromebook USB
ports, e.g. charge a phone from their Chromebook. We want to provide a fast
charging experience to end-users, so we prefer to offer high power charging when
possible.
[TOC]
## Summary of Design Requirements
For explanations of calculations see rest of doc.
### Total System Power
Total current needed for external USB devices at 5V:
```
((Number of Type-C Ports) * (1800mA)) + 1500mA +
((Number of Type-A Ports) * (900mA)) + 600mA§
```
§ The additional 600mA can be omitted if BC1.2 is not supported for Type-A
### Daughter Board Considerations
If a daughter board has 1 Type-A (supporting BC 1.2) and 1 Type-C, the max
potential current load at 5V is `Type-A Vbus (1500mA) + Type-C Vbus (3000mA) +
Type-C Vconn (300mA) = 4800mA`
* The DB ribbon cables need to be able to carry enough current to supply 24W
(4.8A * 5V) of power to the DB.
* This may be on a single or multiple power rails depending on hardware
design.
* The ground path on the ribbon cable from the DB also needs to be able to
carry enough current to match the power rails.
## USB Type-A Ports
For Type-A ports, the [BC 1.2 Specification] adds higher power modes on top of
the [USB 3.2 Specification]. While BC 1.2 support isn't required, it is
preferred, as it allows end-users to charge their devices more quickly.
[BC 1.2 Specification] defines multiple modes of operation including, but not
limited to:
* CDP - Charging Downstream Port
* Allows USB Data. Provides guaranteed 1.5A @ 5V power.
* ChromeOS device can act as a CDP.
* SDP - Standard Downstream Port
* Allows USB Data. Provides guaranteed current defined by USB
Specifications
* For USB3, provides guaranteed current of 0.9A @ 5V.
* For USB2, provides guaranteed current of 0.5A @ 5V.
* ChromeOS device can act as a SDP.
* DCP - Dedicated Charging Port
* No USB Data. Provides max of 1.5A @ 5V power.
* ChromeOS device **will not** act as a DCP.
For detection logic of each mode (e.g. on the D+ and D- pins) and nuance of
power/current power requirements, see full [BC 1.2 Specification].
Without BC 1.2 support, the max power requirements match that of a Standard
Downstream Port (SDP) as defined by various specification (e.g.
[USB 3.2 Specification]).
### ChromeOS as Source - Policy for Type-A
If BC 1.2 is supported on a ChromeOS device, then the first Type-A port in use
will act as a CDP, providing a maximum current of 1.5A while also enabling USB
data. All other Type-A ports will only be SDP, providing a maximum current of
900mA.
Note that the CDP Type-A port allocation is dynamic; the first Type-A port to
draw more than 900mA gets to be the CDP, with a maximum current of 1.5A. Then
all other Type-A ports get downgraded to the lower, 900mA current limit (i.e.
SDP) while the first Type-A port maintains a current draw of more than 900mA. In
practice, this means that the first Type-A device plugged in gets to consume
1.5A and any Type-A device inserted after that will only get 900mA.
Once the Type-A device drawing 1.5A stops pulling more than 900mA or is
physically removed, then the extra 600mA (as well as CDP advertisement) becomes
available to any Type-A port. In practice, Type-A devices only determine current
limits when they are first inserted, so any Type-A device that is still plugged
in when the 1.5A device is removed will not notice that it can pull more
current. This means that the first Type-A device **inserted** after removing the
original 1.5A device gets access to 1.5A.
The allocation of the one CDP Type-A port is unaffected by user interaction with
Type-C ports. Once a Type-A port has been claimed as CDP, inserting a Type-C
device will not revoke the CDP status of the Type-A port.
For example, the below sequence of events illustrates the above Type-A policy if
BC 1.2 is supported:
1. Insert Type-A phone first
* Since no other Type-A port is currently supplying more than 900mA, this
port can supply 1.5A as the CDP.
* Phone pulls 1.5A; other Type-A ports are now marked as SDPs limiting
current to 900mA, each.
* Current state: `phone @ 1.5A`.
2. Insert Type-A mouse second
* Mouse is only allowed 900mA since port is SDP.
* Current state: `phone @ 1.5A` and `mouse @ 900mA`.
3. Remove phone
* High-current port status is relinquished. Now first Type-A port to draw
more than 900mA will claim the one high-current port status (as the
CDP).
* Mouse does not realize that more power is available since most Type-A
devices only determine their current limits upon connection.
* Current state: `mouse @ 900ma`.
4. Insert Type-A battery pack
* Since no other Type-A port is currently supplying more than 900mA, this
port can supply 1.5A as the CDP.
* Battery pack pulls 1.5A; other Type-A ports are now marked as SDPs
limiting current to 900mA, each.
* Current state: `mouse @ 900ma` and `battery pack @ 1.5A`.
The total current needed for all Type-A ports at 5V is:
```
if (BC1.2_Supported)
(# Type-A Ports)*(900mA) + 600mA
else
(# Type-A Ports)*(900mA)
```
## USB Type-C Ports
USB Type-C allows for dynamic negotiation of high power contracts; this is
accomplished through varying CC resistors and/or USB-C Power Delivery (PD). More
in-depth information can be found in the [USB Type-C Specification] \(section
4.5.2.3) and the [USB PD Specification]. CC resistor contracts can range from
500mA/5V to 3A/5V, while PD contracts can range from 0mA/3.3V to 5A/20V.
### ChromeOS as Source - Policy for Type-C
**Note:** Behavior outlined in this .md file reflects future-planned behavior,
and is not present in the codebase currently.
ChromeOS devices currently source power to external USB devices at 5V with a
typical current of 1.5A for each Type-C port. In certain scenarios, a
Type-C port can source up to 3A @ 5V.
ChromeOS prefers that the first PD-capable Type-C device **that requires 3A**
should get 3A guaranteed at 5V. Once the maximum supported number of PD-capable
Type-C device has claimed 3A, then other PD-capable Type-C devices will only be
offered a maximum of 1.5A.
If there are no PD-capable Type-C devices requiring 3A, then the first non-PD
device will be given 3A until a PD-capable device **that requires 3A** is
inserted. Devices will indicate they require 3A in their sink capabilities,
and this will be used as the trigger to let the EC know to offer that port a
3A source contract. This policy is laid out in the following flow chart.
![Partner Attach](images/usb_power_on_attach.png "Partner Attach")
When a device that is currently claiming 3A is removed, then the next oldest
PD-capable device is offered 3A. If no PD-capable devices require 3A,
then the oldest non-PD capable device is given 3A through a CC resistor change.
![Partner Detach](images/usb_power_on_detach.png "Partner Detach")
Inserting a Type-A device does not affect the power assignment for Type-C ports;
only Type-C devices affect the power of Type-C ports.
For example, the below sequence of events illustrates the above Type-C policy
with a board with a maximum number of 1 3A-ports supported:
1. A non-PD capable Type-C keyboard is inserted first
* Keyboard will be offered 1.5A initially
* Current state: `keyboard @ 1.5A`.
2. Partner is established to be non-PD through reaching PE\_SRC\_Disabled.
* Since there are no other PD-capable devices and this is the first
device, offer this device 3A via CC resistor change.
* Current state: `keyboard @ 3A`.
3. A non-PD capable Type-C mouse is inserted second
* It will be offered 1.5A since there is already another non-PD device
claiming 3A.
* Current state: `keyboard @ 3A` and `mouse @ 1.5A`.
4. A PD-capable Type-C dock is inserted third
* Initially negotiate for 1.5A.
* Since this is a PD device, query its operational current through
requesting Sink Capabilities.
* Dock does not want high power from Chromebook; dock continues to receive
1.5A.
* Keyboard gets to maintain higher 3A current supply.
* Current state: `keyboard @ 3A` and `mouse @ 1.5A` and `dock @ 1.5A`.
5. A PD-capable Type-C phone is inserted fourth
* Phone is initially offered 1.5A.
* Since this is a PD device, query its operational current through
requesting Sink Capabilities.
* The phone reports it wants 3A.
* Since PD devices are preferred for 3A, the non-PD keyboard will be
downgraded from 3A to 1.5A via a CC resistor change.
* After tSinkAdj (60 ms), phone is offered 3A through new Source
Capabilities.
* Current state: `keyboard @ 1.5A` and `mouse @ 1.5A` and `dock @ 1.5A`
and `phone @ 3A`.
6. A PD-capable Type-C tablet is inserted fifth
* Tablet is initially offered 1.5A.
* Since this is a PD device, query its operational current through
requesting Sink Capabilities.
* Tablet would like 3A, but the board has reached its maximum number of
supported 3A ports. Note this port's desired current for later.
* Current state: `keyboard @ 1.5A` and `mouse @ 1.5A` and `dock @ 1.5A`
and `phone @ 3A` and `tablet @ 1.5A`.
7. The PD-capable phone is removed
* The next oldest PD-capable device is offered 3A: the tablet
* Current state: `keyboard @ 1.5A` and `mouse @ 1.5A` and `dock @ 1.5A`
and `tablet @ 3A`.
8. The PD-capable tablet is removed
* The next oldest PD-capable device requiring 3A is offered 3A. If there
are no PD-capable devices requiring 3A, then the oldest non-PD capable
device is given 3A.
* The dock only requires 1.5A, so keyboard is given 3A via CC resistor
change.
* Current state: `keyboard @ 3A` and `mouse @ 1.5A` and `dock @ 1.5A`
9. The non-PD capable keyboard is removed
* The next oldest PD-capable device requiring 3A is offered 3A.. If there
are no PD-capable devices requiring 3A, then the next oldest non-PD capable
device is given 3A.
* The dock only requires 1.5A, so mouse is given 3A via CC
resistor change.
* Current state: `mouse @ 3A` and `dock @ 1.5A`.
10. The non-PD capable mouse is removed
* The dock does not require 3A.
* Current state: `dock @ 1.5A`.
Note: Not all released Chromebooks implement the above policy due to
pre-existing hardware design constraints.
Type-C ports also need to provide an additional 300mA @ 5V (1.5W) for Vconn on
every port. Note: the 1.5W for Vconn may also be supplied at other voltages,
such as 455mA @ 3.3V instead.
The total current needed for all Type-C ports at 5V is:
```
((Number of Type-C Ports) * (1500mA + 300mA)) + 1500mA
```
The total maximum current needed for a single Type-C port at 5V is `(3000mA +
300mA) = 3.3A`. This max current for a single port is especially relevant for
sizing the daughter board ribbon cable appropriately.
[BC 1.2 Specification]: <https://www.usb.org/document-library/battery-charging-v12-spec-and-adopters-agreement>
[USB 3.2 Specification]: <https://www.usb.org/document-library/usb-32-specification-released-september-22-2017-and-ecns>
[USB PD Specification]: https://www.usb.org/document-library/usb-power-delivery
[USB Type-C Specification]: https://www.usb.org/document-library/usb-type-cr-cable-and-connector-specification-revision-14-march-29-2019

View File

@ -1,202 +1,5 @@
EC update over USB
==================
*** note
**Warning: This document is old & has moved. Please update any links:**<br>
https://chromium.googlesource.com/chromiumos/platform/ec/+/HEAD/docs/usb_updater.md
***
chip/g (Cr50) and common code (hammer, servo_micro/v4) update over USB protocols
share a lot in terms of protocol and ideas, but use different code bases.
chip/g EC-side implementation is found in `chip/g/*upgrade*`, and the
userspace tool which provides updates over USB among with supporting other
features and interfaces is found in `extra/usb_updater/gsctool.c`.
Common code uses implementations in `common/*update*.c` and
`include/*update*.h`, and `extra/usb_updater/usb_updater2.c` for the userspace
updater.
Cr50-specific notes
-------------------
The Cr50 firmware image consists of multiple sections, of interest to the
USB updater are the RO and RW code sections, two of each. When firmware update
session is established, the Cr50 device reports locations of backup RW and RO
sections (those not currently used by the device).
Based on this information the updater carves out the appropriate sections from
the full Cr50 firmware binary image and sends them to the device for
programming into flash. Once the new sections are programmed and the device
is restarted, the new RO and RW are used if they pass verification and are
logically newer than the existing sections.
There are two ways to communicate with the Cr50 device: USB and `/dev/tpm0`
(when `gsctool` is running on a chromebook with the Cr50 device). Originally
different protocols were used to communicate over different channels,
starting with version 3 the same protocol is used.
Common-code notes
-----------------
For non-Cr50 or chip/g devices (common code), the layout is a bit different,
as devices usually have a single RO and a single RW, where RO is truly read-only
in production, and verifies RW before jumping to it.
For testing and development, `usb_updater2` is provided, while production code
will use `hammerd` (in `src/platform/hammerd`) to update the device.
Update protocol
---------------
The host (either a local AP or a workstation) is the master of the firmware
update protocol, it sends data to the Cr50 device, which processes it and
responds.
The encapsulation format is different between the `/dev/tpm0` and USB cases:
4 bytes 4 bytes 4 bytes variable size
+-----------+--------------+---------------+----------~~--------------+
+ total size| block digest | dest address | data |
+-----------+--------------+---------------+----------~~--------------+
\ \ /
\ \ /
\ +----- FW update PDU sent over /dev/tpm0 -----------+
\ /
+--------- USB frame, requires total size field ------------+
The update protocol data units (PDUs) are passed over `/dev/tpm0`, the
encapsulation includes integrity verification and destination address of
the data (more of this later). `/dev/tpm0` transactions pretty much do not
have size limits, whereas the USB data is sent in chunks of the size
determined when the USB connection is set up. This is why USB requires an
additional encapsulation into frames to communicate the PDU size to the
client side so that the PDU can be reassembled before passing to the
programming function.
In general, the protocol consists of two phases: connection establishment
and actual image transfer.
The very first PDU of the transfer session is used to establish the
connection. The first PDU does not have any data, and the `dest address`
field is set to zero. Receiving such a PDU signals the programming function
that the host intends to transfer a new image.
The response to the first PDU varies depending on the protocol version.
Note that protocol versions before 5 are described here for completeness,
but are not supported any more.
Version 1 is used over `/dev/tpm0`. The response is either 4 or 1 bytes in
size. The 4 byte response is the *base address* of the backup RW section,
and there is no support for RO updates. The one byte response is an error
indication, possibly reporting flash erase failure, command format error, etc.
Version 2 is used over USB. The response is 8 bytes in size. The first four
bytes are either the *base address* of the backup RW section (still no RO
updates), or an error code, the same as in Version 1. The second 4 bytes
are the protocol version number (set to 2).
All versions above 2 behave the same over `/dev/tpm0` and USB.
Version 3 response is 16 bytes in size. The first 4 bytes are the error code
the second 4 bytes are the protocol version (set to 3) and then 4 byte
*offset* of the RO section followed by the 4 byte *offset* of the RW section.
Version 4 response in addition to version 3 provides header revision fields
for active RO and RW images running on the target.
Once the connection is established, the image to be programmed into flash
is transferred to the Cr50 in 1K PDUs. In versions 1 and 2 the address in
the header is the absolute address to place the block to, in version 3 and
later it is the offset into the flash.
Protocol version 5 includes RO and RW key ID information into the first PDU
response. The key ID could be used to tell between prod and dev signing
modes, among other things.
Protocol version 6 does not change the format of the first PDU response,
but it indicates the target's ability to channel TPM vendor commands
through USB connection.
Common-code updater also uses protocol version 6, but has a fairly different
`first_response_pdu` header, indicated by setting `1` in the higher 16-bit for
the protocol version field (`header_type`). The response includes fields
such as maximum PDU size (which is not fixed to 1KB like for Cr50), flash
protection status, version string, and a minimum rollback version.
Details can be found in `include/update_fw.h`.
### State machine (update over USB)
This describes the EC-side state machine for update over USB.
IDLE state:
* If host sends update start PDU (a command without any payload, digest = 0
and base = 0):
* Reply with `first_update_pdu` block. Go to OUTSIDE_BLOCK state.
* If host sends a vendor command (see below), execute that, reply, and stay
in IDLE state. Note that vendor commands are only accepted in IDLE state.
OUTSIDE_BLOCK (preparing to receive start of PDU):
* If no data is received in 5 seconds, go back to IDLE state.
* If host sends `UPDATE_DONE` command (by setting `dest address` to
`0xb007ab1e`), go back to IDLE state.
* If host sends a valid block start with a valid address, copy the rest
of the payload and go to INSIDE_BLOCK state.
INSIDE_BLOCK (in a middle of a PDU):
* If no data is received in 5 seconds, go back to IDLE state.
* Copy data to a buffer.
* If buffer is full (i.e. matches the total expected PDU size), write the
data and go to OUTSIDE_BLOCK.
* Else, stay in INSIDE_BLOCK.
### Vendor commands (channeled TPM command, Cr50)
When channeling TPM vendor commands the USB frame looks as follows:
4 bytes 4 bytes 4 bytes 2 bytes variable size
+-----------+--------------+---------------+-----------+------~~~-------+
+ total size| block digest | EXT_CMD | vend. sub.| data |
+-----------+--------------+---------------+-----------+------~~~-------+
Where `Vend. sub` is the vendor subcommand, and data field is subcommand
dependent. The target tells between update PDUs and encapsulated vendor
subcommands by looking at the `EXT_CMD` value - it is set to `0xbaccd00a` and
as such is guaranteed not to be a valid update PDU destination address.
These commands cannot exceed the USB packet size (typically 64 bytes), as
no reassembly is performed for such frames.
The vendor command response size is not fixed, it is subcommand dependent.
The Cr50 device responds to each update PDU with a confirmation which is 4
bytes in size in protocol version 2, and 1 byte in size in all other
versions. Zero value means success, non-zero value is the error code
reported by Cr50.
Again, vendor command responses are subcommand specific.
### Vendor commands (common code)
Vendor commands for command code look very similar to the TPM vendor commands
above, except that we use `UPDATE_EXTRA_CMD` (`b007ab1f`) instead of `EXT_CMD`,
and `Vend. sub.` have a limit set of values (unless otherwise noted, commands
take no parameter, and reply with a single 1-byte status code):
* UPDATE_EXTRA_CMD_IMMEDIATE_RESET (0): Tell EC to reboot immediately.
* UPDATE_EXTRA_CMD_JUMP_TO_RW (1): Tell EC (in RO) to jump to RW, if the
signature verifies.
* UPDATE_EXTRA_CMD_STAY_IN_RO (2): Tell EC (in RO), to stay in RO, and not
jump to RW automatically. After this command is sent, a reset is necessary
for the EC to accept to jump to RW again.
* UPDATE_EXTRA_CMD_UNLOCK_RW (3): Tell EC to unlock RW on next reset.
* UPDATE_EXTRA_CMD_UNLOCK_ROLLBACK (4): Tell EC to unlock ROLLBACK on next reset.
* UPDATE_EXTRA_CMD_INJECT_ENTROPY (5): Inject entropy into the device-specific
unique identifier (takes at least CONFIG_ROLLBACK_SECRET_SIZE=32 bytes of
data).
* UPDATE_EXTRA_CMD_PAIR_CHALLENGE (6): Tell EC to answer a X25519 challenge
for pairing. Takes in a `struct pair_challenge` as data, answers with a
`struct pair_challenge_response`.

View File

@ -1,307 +1,5 @@
# Firmware Write Protection
[TOC]
This is a somewhat tricky topic since write protection implementations can
differ between chips, and the hardware write protection has changed over time,
so please edit or open a bug if something is not clear.
## Terminology
## RO and RW
MCUs running the EC code have read-only (RO) and read-write (RW) firmware.
Coming out of reset, the MCU boots into its RO firmware.
In the case of the EC, the RO firmware boots the host and asks it to verify a
hash of the RW firmware (software sync). If the RW firmware is invalid, it is
updated from a copy in the host's RW firmware.
In the case of the FPMCU, the RO firmware uses the public key embedded in it to
validate the signature of the RW firmware. If the RW firmware is invalid it does
not jump to the RW firmware.
Once the RW firmware is validated, the MCU jumps to it (without rebooting). The
RO firmware is locked in the factory and is never changed. The RW firmware can
be updated later by pushing a new system firmware containing an updated RW
region.
Note that both the RO and RW firmware regions are normally protected once write
protect has been turned on.
In the case of the EC, the RW region is unprotected at MCU boot until it has
been verified by the host. The RW region is protected before the Linux kernel is
loaded.
In the case of the FPMCU, the RW region is protected before jumping the RO
firmware jumps to it.
## Hardware Write Protect {#hw_wp}
On modern Chrome OS devices, the Cr50 (aka GSC / TPM) provides a "hardware write
protect" GPIO that is connected to the AP SPI flash, EC SPI flash, EEPROM, and
FPMCU via a [GPIO][write_protect_gpio]. This "hardware write protect" can only
be disabled with [Servo] or [SuzyQ] (["CCD open"]) and corresponds to
[`OverrideWP`] in ccd. Disabling this write protect disables it for everything
connected to this signal.
In the case of the FPMCU, the hardware write protect GPIO is tied to the STM32
`BOOT0` pin, which is what tells the MCU to enter the STM32 bootloader mode.
You may see various references to a
[write protect screw in documentation][wp_screw]. Older Chrome OS devices had a
write protect screw that had to be physically removed. More details on this
history can be found here: http://go/cros-wp-status.
Another way of disabling hardware write protection is to remove the battery;
this method is mainly used during bringup.
Additional reference:
https://www.google.com/chromeos/partner/fe/docs/cpfe/firmwaretestmanual.html#hardware-write-protect
## Changing Hardware Write Protection
Modifying the state of hardware write protection (via Cr50 GPIO) can be done if
the ["CCD open"] process has been completed.
<!-- mdformat off(b/139308852) -->
*** note
`servod` *must* be running for `dut-control` to work. See the [Servo] page for
details.
**Warning: This document is old & has moved. Please update any links:**<br>
https://chromium.googlesource.com/chromiumos/platform/ec/+/HEAD/docs/write_protection.md
***
<!-- mdformat on -->
### Enable Hardware Write Protection
```bash
(chroot)$ dut-control fw_wp_state:force_on
```
### Disable Hardware Write Protection
```bash
(chroot)$ dut-control fw_wp_state:force_off
```
### Enable/Disable Hardware Write Protection via Cr50 Console
You can use the following commands from the [Cr50 console]:
```bash
wp disable
```
```bash
wp enable
```
```bash
wp follow_batt_pres
```
## Software Write Protect
Software-based write protect state stored in non-volatile memory. If hardware
write protect is enabled, software write protect can be enabled but cant be
disabled. If hardware write protect is disabled, software write protect can be
enabled or disabled (note that some implementations require an EC reset to
disable software write protect).
The underlying mechanism implementing software write protect may differ between
EC chips. However, the common requirements are that software write protect can
only be disabled when hardware write protect is off and that the RO firmware
must be protected before jumping to RW firmware if protection is enabled.
Additional reference:
https://www.google.com/chromeos/partner/fe/docs/cpfe/firmwaretestmanual.html#software-write-protect
## Changing Software Write Protection
<!-- mdformat off(b/139308852) -->
*** note
*NOTE*: You cannot disable software write protect if hardware write protect is
enabled.
***
<!-- mdformat on -->
Software write protection can be toggled with `ectool --name=cros_fp
flashprotect enable/disable`, which sends the `EC_CMD_FLASH_PROTECT` command
toggling `EC_FLASH_PROTECT_RO_AT_BOOT` (changing `--name` to target different
ECs).
### Changing Software Write Protection with ectool
#### ectool flashprotect
Print out current flash protection state.
```
Flash protect flags: 0x0000000f wp_gpio_asserted ro_at_boot ro_now all_now
Valid flags: 0x0000003f wp_gpio_asserted ro_at_boot ro_now all_now STUCK INCONSISTENT
Writable flags: 0x00000000
```
`Flash protect flags` - Current flags that are set.
`Valid flags` - All the options for flash protection.
`Writable flags` - The flags that currently can be changed. (In this case, no
flags can be changed).
Flags:
* `wp_gpio_asserted` - Whether the hardware write protect GPIO is currently
asserted (read only).
* `ro_at_boot` - Whether the EC will write protect the RO firmware on the next
boot of the EC.
* `ro_now` - Protect the read-only portion of flash immediately. Requires
hardware WP be enabled.
* `all_now` - Protect the entire flash (including RW) immediately. Requires
hardware WP be enabled.
* `STUCK` - Flash protection settings have been fused and cant be cleared
(should not happen during normal operation. Read only.)
* `INCONSISTENT` - One or more banks of flash is not protected when it should
be (should not happen during normal operation. Read only.).
#### ectool flashprotect enable
Set `ro_at_boot` flag. The next time the EC is reset it will protect the flash.
Note that this requires a cold reset.
#### ectool flashprotect enable now
Set `ro_at_boot` `ro_now all_now` flags and immediately protect the flash. Note
that this will fail if hardware write protect is disabled.
#### ectool flashprotect disable
Clear `ro_at_boot` flag. This can only be cleared if the EC booted without
hardware write protect enabled.
Note that you must reset the EC to clear write protect after removing the screw.
If the `ro_at_boot` flag set, and the EC resets with the HW gpio disabled, the
EC will leave the flash unprotected (`ro_now` and `all_now` flags are not set)
but leave `ro_at_boot` flag set.
### Changing Software Write Protection with flashrom
#### View the current state of software write protection
```bash
(chroot) $ flashrom -p ec --wp-status
```
```
WP: status: 0x00
WP: status.srp0: 0
WP: write protect is disabled.
WP: write protect range: start=0x00000000, len=0x00000000
```
#### Enable software write protection
This is immediate. The protection range indicates the RO region of the firmware.
```bash
(chroot) $ flashrom -p ec --wp-enable
```
```
SUCCESS
```
```bash
(chroot) $ flashrom -p ec --wp-status
```
```
WP: status: 0x80
WP: status.srp0: 1
WP: write protect is enabled.
WP: write protect range: start=0x00000000, len=0x0001f800
```
#### Disable software write protection
Disable can only be done with hardware write protect disabled.
```bash
(chroot) $ flashrom -p ec --wp-disable
```
```
FAILED: RO_AT_BOOT is not clear.
FAILED
```
Reboot with [hardware write protection](#hw_wp) disabled. Note that protection
is still enabled, but the protection range is zero.
```bash
(chroot) $ flashrom -p ec --wp-status
```
```
WP: status: 0x80
WP: status.srp0: 1
WP: write protect is enabled.
WP: write protect range: start=0x00000000, len=0x00000000
```
```bash
(chroot) $ flashrom -p ec --wp-disable
```
```
SUCCESS
```
## system_is_locked()
The [`system_is_locked()`] function in the EC code returns false if the HW write
protect GPIO is disabled, or the read-only firmware is not protected.
One way this is used in the FPMCU source is to compile test or debug
functionality into the firmware. Guarding the test functionality with
`system_is_locked` allows us to execute the test code in automated testing by
disabling the hardware write protection; this means we can run the automated
tests against the exact same firmware we ship, rather than a different version
that has test functionality compiled in or out.
## RDP1 {#rdp1}
Stands for Readout Protection Level 1.
Protects user flash memory against a debugger (JTAG/SWD) or potential malicious
code stored in RAM by disabling access (a bus error is generated when read
access is requested). Otherwise (no debugger connected and no boot in RAM set),
all read/program/erase operations from/to flash are allowed.
When switching to a lower level of RDP (i.e., setting to 0), the user flash
memory is mass erased (set to all `0xFF`).
Note that this completely destroys *all* of the firmware, including the RO
section.
### Additional References
https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/1222094
## EC Flash Read/Write Command Write Protection Checks
The EC code command handlers (`command_flash_erase`, `command_flash_write`,
etc.) return an error if `EC_FLASH_PROTECT_ALL_NOW` is set.
["CCD open"]: https://chromium.googlesource.com/chromiumos/platform/ec/+/cr50_stab/docs/case_closed_debugging_cr50.md#Open-CCD
[Cr50 console]: https://chromium.googlesource.com/chromiumos/platform/ec/+/cr50_stab/docs/case_closed_debugging_cr50.md#Consoles
[Servo]: https://chromium.googlesource.com/chromiumos/third_party/hdctools/+/refs/heads/master/README.md
[`OverrideWP`]: https://chromium.googlesource.com/chromiumos/platform/ec/+/cr50_stab/docs/case_closed_debugging_cr50.md
[`system_is_locked()`]: https://chromium.googlesource.com/chromiumos/platform/ec/+/aaba1d5efd51082d143ce2ac64e6caf9cb14d5e5/common/system.c#195
[wp_screw]: https://www.chromium.org/chromium-os/firmware-porting-guide/firmware-ec-write-protection
[write_protect_gpio]: https://chromium.googlesource.com/chromiumos/platform/ec/+/aaba1d5efd51082d143ce2ac64e6caf9cb14d5e5/include/ec_commands.h#1599
[SuzyQ]: https://chromium.googlesource.com/chromiumos/third_party/hdctools/+/HEAD/docs/ccd.md#SuzyQ-SuzyQable

View File

@ -1,168 +1,5 @@
[TOC]
*** note
**Warning: This document is old & has moved. Please update any links:**<br>
https://chromium.googlesource.com/chromiumos/platform/ec/+/HEAD/docs/zephyr_shim.md
***
# Objective
Allow a subset of the platform/ec code to be built as part of the Zephyr-based
EC without needing to land code into upstream zephyr, or our zephyr-chrome
repository.
# Background
Now that Google has joined [Zephyr OS](https://www.zephyrproject.org/), the EC
team is moving toward it instead of platform/ec code on embedded controllers for
future Chrome OS devices. See the
[originally proposed idea](https://goto.google.com/cros-ec-rtos) and a more
specific [Zephyr process doc](https://goto.google.com/zephyr-structure) of what
future development on Zephyr will look like.
Simply put, we want to move to Zephyr OS to use an open-source embedded OS that
has a vibrant community. The embedded OS scene for the industry is very
fragmented, with various parties using their own custom solution. We see the
strong open-source community at Zephyr as potentially helping to consolidate
efforts in the embedded controller space. It will also benefit our partners
(both chip vendors and OEMs) since they should only have to support one embedded
OS (i.e., Zephyr) for both their Chrome OS and Windows based devices.
Migrating to use Zephyr fully is going to take a few years. We do not want to
diverge from the active development happening on platform/ec code. We
potentially want to ship a product using Zephyr before the migration is
complete.
# Design ideas
In order to reuse `platform/ec` development , we shim "active" `platform/ec`
code as a
[Zephyr Module](https://docs.zephyrproject.org/latest/guides/modules.html). This
requires us to add some Zephyr specific code in a `zephyr` directory in the
`platform/ec` codebase. Once we release a Zephyr-based EC, then we can turn down
platform/ec for future development and work on migrating the platform/ec-module
code out of the module directory and into a first-class Zephyr code format -- in
the local
[Chrome Zephyr repo](https://chromium.googlesource.com/chromiumos/platform/zephyr-chrome/+/refs/heads/master)
and ultimately [upstream](https://github.com/zephyrproject-rtos/zephyr).
For platform/ec code that is stable and not under active development, the Zephyr
team may port that code to Zephyr, thus skipping the shimming process.
## Subsystems of interest
### With Shim
We shim the following subsystems (non-exhaustive).
* USB-C: TCPC, PPC, MUX, TCPMv2
* Charge Manager
* SoC Power Sequencing
* Sensors, if Intels HID-based solution is delayed in getting to Zephyr
upstream
### Little-to-No Shim
We adopt upstream Zephyr or skip the shimming process (non-exhaustive).
* CBI and dependent EEPROM code
* The format is stable. We pull in the list of CBI tags from platform/ec
though
* EFS2, Vboot, RO/RW split
* Adjusting flash layout would be difficult to shim, and the concept is
very stable.
* We may shim some core EFS2 logic
* Host command framework
* Sensors, if Intels HID-based solution getts to Zephyr upstream and passes
CTS
* Keyboard and keycode scanning support
* We may shim the newer Vivaldi feature.
* Console support
* We allow individual console commands via DECLARE\_CONSOLE\_COMMAND to be
shimmed to Zephyr. These convert commands to work with Zephyr's shell
subsystem.
* I2C
## New content in platform/ec
Add the `src/platform/ec/zephyr` folder with:
* [Module integration files](https://docs.zephyrproject.org/latest/guides/modules.html#build-system-integration),
e.g., module.yml, CMakeLists.txt, and KConfig.
* **module.yml** is the required entry point (must be located at
_zephyr/module.yml_ in the repository) for Zephyr modules, and declares
the location of Kconfig and CMakeLists.txt files used by the Zephyr
build system.
* **CMakeLists.txt** replicates build logic for the files being shimmed,
outside of the platform/ec Makefile.
* **Kconfig** will declare any CONFIG\_\* options which are important to
expose from platform/ec code to the Zephyr build.
* Shim code to translate platform/ec code into Zephyr code
* For example, redefine platform/ecs
[`DECLARE_HOST_COMMAND`](https://source.chromium.org/chromiumos/chromiumos/codesearch/+/master:src/platform/ec/include/host_command.h;l=256;drc=514923bc59f5a3435dbb7cbf348735ed41889ffe)
to map to Zephyr's upstream
[`EC_HOST_CMD_HANDLER`](https://github.com/zephyrproject-rtos/zephyr/blob/d7468bf836b75c29980441f294a61eae6bf4bc75/include/ec_host_cmd.h#L73)
macro. This allows us to compile select platform/ec files in the Zephyr
build.
## Namespace Collisions
One significant issue of mixing Zephyr headers with our existing EC code is that
we currently have many names colliding with the Zephyr code. For example,
Zephyr's atomic functions also are named `atomic_add`, `atomic_or`, ...,
however, have a different API from our EC's atomic functions. This is critical,
since atomic operations are often used in `static inline` functions placed in
header files.
In some cases, we are able to hack around these collisions by creating macros
and functions which are compatible with both Zephyr and our EC's usages. For
example, we can create a modified `IS_ENABLED` which accepts both defined to
nothing usages (CrOS EC `config.h` style), and defined to `1` usages (Zephyr
Kconfig style).
However, long term, we may find this to be a continual cause of issues, and
creating hacks for every colliding macro or function may be unsustainable. We
propose _gradually_ introducing a namespace prefix to the `platform/ec`
codebase, for example `crec_`. We can begin at the critical areas of namespace
collision (e.g., atomics) and continue to improve the naming convention with
time.
## New CQ check
As long as code from platform/ec is part of the zephyr
[ebuild](http://cs/chromeos_public/src/third_party/chromiumos-overlay/chromeos-base/chromeos-zephyr-2_3/chromeos-zephyr-2_3-9999.ebuild),
then we need to run the Zephyr CQ checks on any platform/ec CLs in addition to
the normal platform/ec CQ checks. This ensures that platform/ec changes arent
breaking the Zephyr builds and requiring the Zephyr team to debug recent
changes.
For local builds, we can run `emerge-betty chromeos-zephyr-2_3` or `zmake`
utility to check that an EC CL has not broken anything on the Zephyr side.
We will work with the CI team to enable this.
# Alternatives Considered
## Translate code and mirror into the zephyr-chrome repository
We could potentially write a script which, via a series of find/replace
operations, translates a platform/ec module to use Zephyr functions, macros, and
paradigms. On a frequent basis, we would translate all modules of interest in
the platform/ec repository and land an "uprev" change in the zephyr-chrome
repository.
The main disadvantage of this technique is that we can't get any CQ coverage
when platform/ec CLs land that the modules will continue to work in Zephyr.
Additionally, the translator script would be delicate and probably require
frequent maintenance.
However, this technique does have some benefits. With modules directly
translated to code in the Zephyr paradigm, the process of upstreaming a shimmed
module to ZephyrOS would be significantly easier. Additionally, it would require
no shim code in platform/ec.
## Don't do any code sharing
One option is to avoid shimming in any platform/ec code and allow the Zephyr
team to re-implement features in upstream zephyr, or our local zephyr-chrome
repository.
Disregarding the infeasible amount of work required to complete this option, the
platform/ec repository has a far faster development pace as there are many more
contributors, and the Zephyr features would quickly lose parity during the time
frame that we are launching both Zephyr-based and platform/ec-based devices.

View File

@ -1,166 +1,5 @@
# Porting EC unit tests to Ztest
[TOC]
This HOWTO shows the process for porting the EC's `base32` unit test to
Zephyr's Ztest framework. All of the work is done in `src/platform/ec`.
See [Test Framework - Zephyr Project Documentation](https://docs.zephyrproject.org/1.12.0/subsystems/test/ztest.html#quick-start-unit-testing) for details about Zephyr's Ztest framework.
See [chromium:2492527](https://crrev.com/c/2492527) for an example of
porting an EC unit test to the Ztest API.
## Determine source files being tested
Determine which C files the unit test requires by finding the test in
`test/test_config.h`:
```
#ifdef TEST_BASE32
#define CONFIG_BASE32
#endif
```
Locate the `CONFIG` item(s) in `common/build.mk`:
```
common-$(CONFIG_BASE32)+=base32.o
```
So for the `base32` test, we only need to shim `common/base32.c`.
Add the C files to `zephyr/shim/CMakeLists.txt`, in the "Shimmed modules"
section:
```
# Shimmed modules
zephyr_sources_ifdef(CONFIG_PLATFORM_EC "${PLATFORM_EC}/common/base32.c")
```
Refer to [zephyr: shim in base32.c](https://crrev.com/c/2468631).
## Create test directory
Create a new directory for the unit test in `zephyr/test/base32`.
Create `zephyr/test/base32/prj.conf` with these contents:
```
CONFIG_ZTEST=y
CONFIG_PLATFORM_EC=y
```
Create `zephyr/test/base32/CMakeLists.txt` with these contents:
```
cmake_minimum_required(VERSION 3.13.1)
project(base32)
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
target_sources(app PRIVATE ${PLATFORM_EC}/test/base32.c)
```
### Modify test source code
In the unit test, wrap `run_test` in the `#else` portion of an
`#ifdef CONFIG_ZEPHYR`. Create `test_main` in the `#ifdef` portion.
Copy the contents of `run_test` into `test_main`. You will need to keep the
list of test cases in sync between the two functions.
Change `RUN_TEST` to `ztest_unit_test` and add the `ztest_test_suite` wrapper
plus the call to `ztest_run_test_suite`.
```
/*
* Define the test cases to run. We need to do this twice, once in the format
* that Ztest uses, and again in the format the the EC test framework uses.
* If you add a test to one of them, make sure to add it to the other.
*/
#ifdef CONFIG_ZEPHYR
void test_main(void)
{
ztest_test_suite(test_base32_lib,
ztest_unit_test(test_crc5),
ztest_unit_test(test_encode),
ztest_unit_test(test_decode));
ztest_run_test_suite(test_base32_lib);
}
#else
void run_test(int argc, char **argv)
{
test_reset();
RUN_TEST(test_crc5);
RUN_TEST(test_encode);
RUN_TEST(test_decode);
test_print_result();
}
#endif /* CONFIG_ZEPHYR */
```
Each function that is called by `ztest_unit_test` needs to change its
return type to `EC_TEST_RETURN`. Keep the `return EC_SUCCESS;` at the end
of the test function. If there are any `return` statements that return
something other than `EC_SUCCESS`, you should use `ztest_test_fail` inside
another `ifdef CONFIG_ZEPHYR` block.
Change the `TEST_ASSERT` macros to `zassert` macros. There are plans to
automate this process, but for now, it's a manual process involving some
intelligent find-and-replace.
* `TEST_ASSERT(n)` to `zassert_true(n, NULL)`
* `TEST_EQ(a, b, fmt)` to `zassert_equal(a, b, fmt ## ", " ## fmt, a, b)`
* e.g. `TEST_EQ(a, b, "%d")` becomes `zassert_equal(a, b, "%d, %d", a, b)`
* `TEST_NE(a, b, fmt)` to `zassert_not_equal(a, b, fmt ## ", " ## fmt, a, b)`
* `TEST_LT(a, b, fmt)` to `zassert_true(a < b, fmt ## ", " ## fmt, a, b)`
* `TEST_LE(a, b, fmt)` to `zassert_true(a <= b, fmt ## ", " ## fmt, a, b)`
* `TEST_GT(a, b, fmt)` to `zassert_true(a > b, fmt ## ", " ## fmt, a, b)`
* `TEST_GE(a, b, fmt)` tp `zassert_true(a >= b, fmt ## ", " ## fmt, a, b)`
* `TEST_BITS_SET(a, bits)` to `zassert_true(a & (int)bits == (int)bits, "%u, %u", a & (int)bits, (int)bits)`
* `TEST_BITS_CLEARED(a, bits)` to `zassert_true(a & (int)bits == 0, "%u, 0", a & (int)bits)`
* `TEST_ASSERT_ARRAY_EQ(s, d, n)` to `zassert_mem_equal(s, d, b, NULL)`
* `TEST_CHECK(n)` to `zassert_true(n, NULL)`
* `TEST_NEAR(a, b, epsilon, fmt)` to `zassert_true(fabs(a-b) < epsilon, "%f, %f, %f", a, b, epsilon)`
* Currently, every usage of `TEST_NEAR` involves floating point values
* `TEST_ASSERT_ABS_LESS(n, t)` to `zassert_true(abs(n) < t, "%d, %d", n, t)`
* Currently, every usage of `TEST_ASSERT_ANS_LESS` involves signed integers.
There isn't a good replacement for `TEST_ASSERT_MEMSET(d, c, n)`, but it is
only used in two tests, `printf.c` and `utils.c`. If you need this test,
you'll need to code up a loop over the `n` bytes starting at `d`, and
`zassert_equal` that each byte is equal to `c`.
Also note that some tests use constructs like `TEST_ASSERT(var == const)`,
which would have been better write as `TEST_EQ(var, const)`. These should be
rewritten to use `zassert_equal`.
Refer to
[test: Allow EC unit test to use Ztest API](https://crrev.com/c/2492527) for
the changes to the base32.c source code.
## Build and run
Use `cmake` and `ninja` to build the test:
```
(cr) $ export ZEPHYR_BASE=/mnt/host/source/src/third_party/zephyr/main/v2.4
(cr) $ cd /mnt/host/source/src/platform/ec
(cr) $ cmake -S zephyr/test/base32 -B build/base32 \
-D ZEPHYR_MODULES=/mnt/host/source/src/platform/ec \
-D ZEPHYR_TOOLCHAIN_VARIANT=host -D BOARD=native_posix -G Ninja
(cr) $ ninja -C build/base32
(cr) $ build/base32/zephyr/zephyr.exe
UART_0 connected to pseudotty: /dev/pts/1
*** Booting Zephyr OS build zephyr-v2.4.0-1-g63b2330a85cd ***
Running test suite test_base32_lib
===================================================================
START - test_crc5
PASS - test_crc5
===================================================================
START - test_encode
PASS - test_encode
===================================================================
START - test_decode
PASS - test_decode
===================================================================
Test suite test_base32_lib succeeded
===================================================================
PROJECT EXECUTION SUCCESSFUL
(cr) $
```
*** note
**Warning: This document is old & has moved. Please update any links:**<br>
https://chromium.googlesource.com/chromiumos/platform/ec/+/HEAD/docs/ztest.md
***

View File

@ -1,102 +1,5 @@
Stack Size Analysis Tool for EC Firmware
========================================
*** note
**Warning: This document is old & has moved. Please update any links:**<br>
https://chromium.googlesource.com/chromiumos/platform/ec/+/HEAD/extra/stack_analyzer/README.md
***
This tool does static analysis on EC firmwares to get the maximum stack usage of
each function and task. The maximum stack usage of a function includes the stack
used by itself and the functions it calls.
Usage
-----
Make sure the firmware of your target board has been built.
In `src/platform/ec`, run
```
make BOARD=${BOARD} SECTION=${SECTION} ANNOTATION=${ANNOTATION} analyzestack
```
The `${SECTION}` can be `RO` or `RW`. The `${ANNOTATION}` is a optional
annotation file, see the example_annotation.yaml, by default,
board/$BOARD/analyzestack.yaml is used.
Output
------
For each task, it will output the result like below,
```
Task: PD_C1, Max size: 1156 (932 + 224), Allocated size: 640
Call Trace:
pd_task (160) [common/usb_pd_protocol.c:1644] 1008a6e8
-> pd_task[common/usb_pd_protocol.c:1808] 1008ac8a
- handle_request[common/usb_pd_protocol.c:1191]
- handle_data_request[common/usb_pd_protocol.c:798]
-> pd_task[common/usb_pd_protocol.c:2672] 1008c222
-> [annotation]
pd_send_request_msg.lto_priv.263 (56) [common/usb_pd_protocol.c:653] 1009a0b4
-> pd_send_request_msg.lto_priv.263[common/usb_pd_protocol.c:712] 1009a22e0
```
The `pd_task` uses 160 bytes on the stack and calls `pd_send_request_msg.lto_priv.263`.
The callsites to the next function will be shown like below,
```
-> pd_task[common/usb_pd_protocol.c:1808] 1008ac8a
- handle_request[common/usb_pd_protocol.c:1191]
- handle_data_request[common/usb_pd_protocol.c:798]
-> pd_task[common/usb_pd_protocol.c:2672] 1008c222
-> [annotation]
```
This means one callsite to the next function is at `usb_pd_protocol.c:798`,
but it is inlined to the current function and you can follow the trace:
`usb_pd_protocol.c:1808 -> usb_pd_protocol.c:1191 -> usb_pd_protocol.c:798` to
find the callsite. The second callsite is at `usb_pd_protocol.c:2672`. And the
third one is added by annotation.
The unresolved indirect callsites have the similar format to the above.
Annotating Indirect Call
------------------------
To annotate an indirect call like this,
```
Unresolved indirect callsites:
pd_transmit
-> pd_transmit[common/usb_pd_protocol.c:407] 802c9c8
- tcpm_transmit[driver/tcpm/tcpm.h:142]
```
It is an indirect call in the `tcpm_transmit`, which is inlined to the `pd_transmit`.
You can add a annotation like the below to eliminate it.
```
add:
tcpm_transmit[driver/tcpm/tcpm.h:142]:
- anx74xx_tcpm_transmit
```
The source `tcpm_transmit[driver/tcpm/tcpm.h:142]` must be a full signature (function_name[path:line number]).
So the resolver can know which indirect call you want to annotate and eliminate (even if it is inlined).
Annotating arrays (hooks, console commands, host commands)
----------------------------------------------------------
When a callsite calls a number of functions based on values from an constant
array (in `.rodata` section), one can use the following syntax:
```
hook_task[common/hooks.c:197]:
- { name: __deferred_funcs, stride: 4, offset: 0 }
- { name: __hooks_second, stride: 8, offset: 0 }
- { name: __hooks_tick, stride: 8, offset: 0 }
```
Where `name` is the symbol name for the start of the array (the end of the array
is `<name>_end`), stride is the array element size, and offset is the offset of
the function pointer in the structure. For example, above, `__deferred_funcs` is
a simple array of function pointers, while `__hooks_tick` is an array of
`struct hook_data` (size 8, pointer at offset 0):
```
struct hook_data {
/* Hook processing routine. */
void (*routine)(void);
/* Priority; low numbers = higher priority. */
int priority;
};
```

View File

@ -1,18 +1,5 @@
# tigertool
*** note
**Warning: This document is old & has moved. Please update any links:**<br>
https://chromium.googlesource.com/chromiumos/platform/ec/+/HEAD/extra/tigertool/README.md
***
tigertool.py is a commandline utility to control the tigertail USB-C mux.
It supports changing the mux status to port A, B, or off.
You can set a serial number to use multiple tigertails at once.
## Usage
Typical usage to set the mux port<br>
```./tigertail.py -m [A|B|off] -s [serialno]```<br>
Reboot the tigertail<br>
```./tigertail.py --reboot```<br>
Set the serial number, when only one tigertail is plugged<br>
```./tigertail.py --setserialno=[serialno]```<br>
Tigertail can support up to 20V 3A on the mux and passes through all
USB-C lines except SBU.

View File

@ -1,213 +1,5 @@
# Sweetberry USB power monitoring
*** note
**Warning: This document is old & has moved. Please update any links:**<br>
https://chromium.googlesource.com/chromiumos/platform/ec/+/HEAD/extra/usb_power/powerlog.README.md
***
This tool allows high speed monitoring of power rails via a special USB
endpoint. Currently this is implemented for the Sweetberry board.
To use on a board, you'll need two config files, one describing the board, a
`.board` file, and one describing the particular rails you want to monitor in
this session, a `.scenario` file.
## Converting from servo_ina configs
- Method 1 (not limited to chroot)
Many configs can be found for the servo_ina_board in `hdctools/servo/data/`.
Sweetberry is plug compatible with servo_ina headers, and config files can be
converted with the following tool:
```
./convert_servo_ina.py <board>_r0_loc.py
```
This will generate `<board>_r0_loc.board` and `<board>_r0_loc.scenario`
locally, which can be used with `powerlog.py`.
- Method 2 (recommended for Chrome OS developers, requires chroot)
If you are using `powerlog.py` within the chroot, copy `<board>_r0_loc.py` to
`src/third_party/hdctools/servo/data`, then add this line to file:
```python
config_type = 'sweetberry'
```
And run command in chroot:
```
(Anywhere in chroot, just ONCE) cros_workon --host start dev-util/hdctools
```
Then every time you make a change to `<board>_r0_loc.py`, run:
```
(Anywhere in chroot) sudo emerge dev-util/hdctools
```
The command will install the corresponding `.board` and `.scenario` file in
the chroot. To use `powerlog.py` use the command:
```
(Anywhere in chroot) powerlog -b <board>_r0_loc.board -c <board>_r0_loc.scenario
```
There is no need to specify the absolute path to the `.board` and `.scenario`
file, once they are installed into the chroot. If there is any changes to
`<board>_r0_loc.py`, you need to `sudo emerge dev-util/hdctools` again.
## Board files
Board files contain a list of rails, supporting 48 channels each on up to two
Sweetberries. For each rail you must specify a name, sense resistor value, and
channel number. You can optionally list expected voltage and net name.
The format is as follows, in json:
example.board:
```json
[
{ "name": "railname",
"rs": <sense resistor value in ohms>,
"sweetberry": <"A" for main Sweetberry, "B" for a secondary Sweetberry>,
"channel": <0-47 according to board schematic>,
"v": <optional expected bus voltage in volts>,
"net": <optional schematic net name>
},
{...}
]
```
## Scenario files
Scenario files contain the set of rails to monitor in this session. The file
format is simply a list of rail names from the board file.
Optionally, you can specify the type of measurement, from the set of
`"POWER"`, `"BUSV"`, `"CURRENT"`, `"SHUNTV"`. If not specified, the default is
power.
example.scenario:
```json
[
"railname",
"another_railname",
["railname", "BUSV"],
["railname", "CURRENT"],
...
]
```
## Output
`powerlog.py` will output a csv formatted log to stdout, at timing intervals
specified on the command line. Currently values below `-t 10000` do not work
reliably but further updates should allow faster updating.
An example run of:
```
./powerlog.py -b board/marlin/marlin.board -c board/marlin/marlin_short.scenario -t 100000
```
Will result in:
```
ts:32976us, VBAT uW, VDD_MEM uW, VDD_CORE uW, VDD_GFX uW, VDD_1V8_PANEL uW
0.033004, 12207.03, 4882.81, 9155.27, 2441.41, 0.00
0.066008, 12207.03, 3662.11, 9155.27, 2441.41, 0.00
0.099012, 12207.03, 3662.11, 9155.27, 2441.41, 0.00
...
```
The output format is as follows:
- `ts:32976us`
Timestamps either zero based or synced to system clock, in seconds. The column
header indicates the selected sampling interval. Since the INA231 has specific
hardware defines sampling options, this will be the closest supported option
lower than the requested `-t` value on the command line.
- `VBAT uW`
Microwatt reading from this rail, generated on the INA by integrating the
voltage/amperage on the sense resistor over the sampling time, and multiplying
by the sampled bus voltage.
- `... uW`
Further microwatt entry columns for each rail specified in your scenario file.
- `... xX`
Measurement in uW, mW, mV, uA, uV as per config.
## Calculate stats and store data and stats
When appropriate flag is set, powerlog.py is capable of calculating statistics
and storing statistics and raw data.
- Example 1
```
./powerlog.py -b board/eve_dvt2_loc/eve_dvt2_loc.board -c board/eve_dvt2_loc/eve_dvt2_loc.scenario --save_stats [<directory>]
```
If `<directory>` is specified, this will save stats as:
`<directory>/sweetberry<timestemp>/summary.txt`.
If `<directory>` does not exist, it will be created.
If `<directory>` is not specified but the flag is set, this will save stats
under the directory which `powerlog.py` is in:
`<directory of powerlog.py>/sweetberry<timestemp>/summary.txt`.
If `--save_stats` flag is not set, stats will not be saved.
- Example 2
```
./powerlog.py -b board/eve_dvt2_loc/eve_dvt2_loc.board -c board/eve_dvt2_loc/eve_dvt2_loc.scenario --save_raw_data [<directory>]
```
If `<directory>` is specified, this will save raw data in:
`<directory>/sweetberry<timestemp>/raw_data/`.
If `<directory>` does not exist, it will be created.
If `<directory>` is not specified but the flag is set, this will save raw data
under the directory which `powerlog.py` is in:
`<directory of powerlog.py>/sweetberry<timestemp>/raw_data/`.
If `--save_raw_data` flag is not set, raw data will not be saved.
- Example 3:
```
./powerlog.py -b board/eve_dvt2_loc/eve_dvt2_loc.board -c board/eve_dvt2_loc/eve_dvt2_loc.scenario --save_stats_json [<directory>]
```
If `<directory>` is specified, this will save MEANS in json as:
`<directory>/sweetberry<timestemp>/summary.json`.
If `<directory>` does not exist, it will be created.
If `<directory>` is not specified but the flag is set, this will save MEANS in
json under the directory which `powerlog.py` is in:
`<directory of powerlog.py>/sweetberry<timestemp>/summary.json`.
If `--save_stats` flag is not set, stats will not be saved.
`--save_stats_json` is designed for `power_telemetry_logger` for easy reading
and writing.
## Making developer changes to `powerlog.py`
`powerlog.py` is installed in chroot, and the developer can import `powerlog` or
use `powerlog` directly anywhere within chroot. Anytime the developer makes a
change to `powerlog.py`, the developer needs to re-install `powerlog.py` so that
anything that imports `powerlog` does not break. The following is how the
developer installs `powerlog.py` during development.
Run command in chroot:
```
(Anywhere in chroot, just ONCE) cros_workon --host start chromeos-base/ec-devutils
(Anywhere in chroot, every time powerlog.py is changed) sudo emerge chromeos-base/ec-devutils
```

View File

@ -1,6 +1,5 @@
Case Closed Debugging Serial Consoles over USB
==============================================
*** note
**Warning: This document is old & has moved. Please update any links:**<br>
https://chromium.googlesource.com/chromiumos/platform/ec/+/HEAD/extra/usb_serial/README.md
***
Please see the documentation in [case_closed_debugging doc][1]
[1]:https://chromium.googlesource.com/chromiumos/platform/ec/+/cr50_stab/docs/case_closed_debugging.md

View File

@ -1,167 +1,5 @@
# incbin
*** note
**Warning: This document is old & has moved. Please update any links:**<br>
https://chromium.googlesource.com/chromiumos/platform/ec/+/HEAD/third_party/incbin/README.md
***
Include binary files in your C/C++ applications with ease
## Example
``` c
#include "incbin.h"
INCBIN(Icon, "icon.png");
// This translation unit now has three symbols
// const unsigned char gIconData[];
// const unsigned char *const gIconEnd; // a marker to the end, take the address to get the ending pointer
// const unsigned int gIconSize;
// Reference in other translation units like this
INCBIN_EXTERN(Icon);
// This translation unit now has three extern symbols
// Use `extern "C"` in case of writing C++ code
// extern const unsigned char gIconData[];
// extern const unsigned char *const gIconEnd; // a marker to the end, take the address to get the ending pointer
// extern const unsigned int gIconSize;
```
## Portability
Known to work on the following compilers
* GCC
* Clang
* PathScale
* Intel
* Solaris & Sun Studio
* Green Hills
* SNC (ProDG)
* Diab C++ (WindRiver)
* XCode
* ArmCC
* RealView
* ImageCraft
* Stratus VOS C
* TinyCC
* cparser & libfirm
* LCC
* MSVC _See MSVC below_
If your compiler is not listed, as long as it supports GCC inline assembler, this
should work.
## MISRA
INCBIN can be used in MISRA C setting. However it should be independently checked
due to its use of inline assembly to achieve what it does. Independent verification
of the header has been done several times based on commit: 7e327a28ba5467c4202ec37874beca7084e4b08c
## Alignment
The data included by this tool will be aligned on the architectures word boundary
unless some variant of SIMD is detected, then it's aligned on a byte boundary that
respects SIMD convention just incase your binary data may be used in vectorized
code. The table of the alignments for SIMD this header recognizes is as follows:
| SIMD | Alignment |
|-----------------------------------------|-----------|
| SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2 | 16 |
| Neon | 16 |
| AVX, AVX2 | 32 |
| AVX512 | 64 |
## Prefix
By default, `incbin.h` emits symbols with a `g` prefix. This can be adjusted by
defining `INCBIN_PREFIX` before including `incbin.h` with a desired prefix. For
instance
``` c
#define INCBIN_PREFIX g_
#include "incbin.h"
INCBIN(test, "test.txt");
// This translation unit now has three symbols
// const unsigned char g_testData[];
// const unsigned char *const g_testEnd;
// const unsigned int g_testSize;
```
You can also choose to have no prefix by defining the prefix with nothing, for example:
``` c
#define INCBIN_PREFIX
#include "incbin.h"
INCBIN(test, "test.txt");
// This translation unit now has three symbols
// const unsigned char testData[];
// const unsigned char *const testEnd;
// const unsigned int testSize;
```
## Style
By default, `incbin.h` emits symbols with `CamelCase` style. This can be adjusted
by defining `INCBIN_STYLE` before including `incbin.h` to change the style. There
are two possible styles to choose from
* INCBIN_STYLE_CAMEL (CamelCase)
* INCBIN_STYLE_SNAKE (snake_case)
For instance:
``` c
#define INCBIN_STYLE INCBIN_STYLE_SNAKE
#include "incbin.h"
INCBIN(test, "test.txt");
// This translation unit now has three symbols
// const unsigned char gtest_data[];
// const unsigned char *const gtest_end;
// const unsigned int gtest_size;
```
Combining both the style and prefix allows for you to adjust `incbin.h` to suite
your existing style and practices.
## Overriding Linker Output section
By default, `incbin.h` emits into the read-only linker output section used on
the detected platform. If you need to override this for whatever reason, you
can manually specify the linker output section.
For example, to emit data into program memory for
[esp8266/Arduino](github.com/esp8266/Arduino):
``` c
#define INCBIN_OUTPUT_SECTION ".irom.text"
#include "incbin.h"
INCBIN(Foo, "foo.txt");
// Data is emitted into program memory that never gets copied to RAM
```
## Explanation
`INCBIN` is a macro which uses the inline assembler provided by almost all
compilers to include binary files. It achieves this by utilizing the `.incbin`
directive of the inline assembler. It then uses the assembler to calculate the
size of the included binary and exports two global symbols that can be externally
referenced in other translation units which contain the data and size of the
included binary data respectively.
## MSVC
Supporting MSVC is slightly harder as MSVC lacks an inline assembler which can
include data. To support this we ship a tool which can process source files
containing `INCBIN` macro usage and generate an external source file containing
the data of all of them combined. This file is named `data.c` by default.
Just include it into your build and use the `incbin.h` to reference data as
needed. It's suggested you integrate this tool as part of your projects's
pre-build events so that this can be automated. A more comprehensive list of
options for this tool can be viewed by invoking the tool with `-help`
If you're using a custom prefix, be sure to specify the prefix on the command
line with `-p <prefix>` so that everything matches up; similarly, if you're
using a custom style, be sure to specify the style on the command line with
`-S <style>` as well.
## Miscellaneous
Documentation for the API is provided by the header using Doxygen notation.
For licensing information see UNLICENSE.

View File

@ -1,119 +1,5 @@
# Reflashing an ITE EC
*** note
**Warning: This document is old & has moved. Please update any links:**<br>
https://chromium.googlesource.com/chromiumos/platform/ec/+/HEAD/util/iteflash.md
***
This doc: [http://go/cros-ite-ec-reflash](https://goto.google.com/cros-ite-ec-reflash)
<br>
First written: 2019-04-02
<br>
Last updated: 2019-04-03
Familiarity with [Chromium OS](https://www.chromium.org/chromium-os) [Embedded Controller (EC) development](../README.md) is assumed.
[TOC]
## Background
### Terminology
**ITE EC** refers to the [ITE](http://www.ite.com.tw/) [IT8320](http://www.ite.com.tw/en/product/view?mid=96) [Embedded Controller (EC)](https://en.wikipedia.org/wiki/Embedded_controller) microcontroller when used as a Chromium OS / Chrome OS EC.
**CrOS** refers to Chromium OS, Chrome OS, or both, depending on the context. The distinction between Chromium OS and Chrome OS is largely immaterial to this document.
**Servo** refers to a debug board providing direct debug access to various circuits on a Chrome OS device motherboard. As of this writing, the most common [servos](https://www.chromium.org/chromium-os/servo) used by CrOS developers are [CR50 (CCD)](https://www.chromium.org/chromium-os/ccd), [Servo Micro](https://www.chromium.org/chromium-os/servo/servomicro), and [Servo v2](https://www.chromium.org/chromium-os/servo/servo-v2). (Note that [Servo v4](https://www.chromium.org/chromium-os/servo/servov4) is **not** a Servo in this sense. It is a USB hub with a microcontroller that proxies Servo functionality from either CR50 or Servo Micro.) See also [Case-Closed Debug in Chromebooks and Servo Micro](https://chromium.googlesource.com/chromiumos/platform/ec/+/master/board/servo_micro/ccd.md).
### How ITE EC reflashing works
An ITE EC is reflashed using a Servo by:
1. Sending special non-I2C waveforms over its I2C clock and data lines, to enable a debug mode / direct firmware update (DFU) mode.
1. Communicating with it using I2C, including transferring the actual EC image over I2C.  The ITE EC will only respond over I2C after receiving the special waveforms.
### Further reading
Googlers, and Partners involved in ITE EC projects, see [The State of ITE CrOS EC Reflashing](https://docs.google.com/document/d/1fs29eBvwKrOWYozLZXTg7ObwAO5dyM4Js2Vq301EwAU/preview). That document is not public, do not request access if you lack it.
## How to reflash
### Prerequisites for CR50 CCD
This section applies whether using CR50 CCD via [Servo v4](https://www.chromium.org/chromium-os/servo/servov4) or [SuzyQ aka SuzyQable](https://www.sparkfun.com/products/14746).
CR50 MP minimum firmware version: `0.3.15`
<br>
CR50 pre-PVT minimum firmware version: `0.4.15`
Googlers, to upgrade CR50 firmware if needed see [How to use CCD on CR50](https://docs.google.com/document/d/1MqDAoBsmGTmrFi-WNOoC5R-UFeuQK37_9kaEdCFU8QE/preview). That document is not public, do not request access if you lack it.
The CR50 CCD capabilities must be set to `always`. To achieve this:
1. Open CCD.
* root shell: `$ gsctool -o`
* CR50 console: `ccd open`
1. Reset CCD to `factory` mode.
* CR50 console: `ccd reset factory`
Reflashing with CR50 also requires the [i2c-pseudo kernel module](#i2c-pseudo), unless using the [CR50 CCD sans servod](#ccd-sans-servod) alternative method.
### Prerequisites for Servo Micro
This section applies whether the [Servo Micro](https://www.chromium.org/chromium-os/servo/servomicro) is connected directly to your development host, or through a [Servo v4](https://www.chromium.org/chromium-os/servo/servov4).
Servo Micro minimum firmware version: `servo_micro_v2.3.5`
To upgrade Servo Micro firmware if needed:
1. Enter the chroot.
* `$ cros_sdk`
1. Run servo_updater.
* `$ sudo servo_updater --board=servo_micro`
If that still results in too old of a firmware version, use `repo sync` and `update_chroot` to update your CrOS development environment, then try again.
Reflashing with Servo Micro also requires the [i2c-pseudo kernel module](#i2c-pseudo).
### Installing i2c-pseudo {#i2c-pseudo}
1. Install the `i2c-pseudo` Linux kernel module. (Do this **outside** of the chroot!)
* `$ cd src/platform/ec/extra/i2c_pseudo`
* `$ ./install`
If the above fails, your system may be missing packages necessary for building kernel modules. Consult your Linux distribution's documentation and support forums. After installing any packages that might be missing, simply try the install script again.
You will need to reinstall `i2c-pseudo` after each kernel upgrade.
There is an intention to [upstream i2c-pseudo](https://issuetracker.google.com/129565355), though even if accepted upstream, it may or may not become included with common Linux distribution kernels.
### Common reflash instructions
These instructions apply when using any kind of Servo, including those with no special prerequisites (such as [Servo v2](https://www.chromium.org/chromium-os/servo/servo-v2) with its Yoshi flex cable connected to the DUT).
1. Enter the chroot (for servod).
* `$ cros_sdk --no-ns-pid`
1. Start servod.
* `$ sudo servod --board=<servod_board_name>`
* For some boards the servod board name is different than the EC codebase board name used below!
1. Enter the chroot (for flash_ec).
* `$ cros_sdk`
1. Build the EC image for your board.
* `$ cd ~/trunk/src/platform/ec`
* `$ board=<board_name>`
* `$ make -j BOARD="$board"`
1. Run flash_ec from the util directory.
* `$ util/flash_ec --board="$board" --image=build/"$board"/ec.bin`
## CR50 CCD sans servod alternative {#ccd-sans-servod}
This section applies whether using CR50 CCD via [Servo v4](https://www.chromium.org/chromium-os/servo/servov4) or [SuzyQ aka SuzyQable](https://www.sparkfun.com/products/14746).
When using CR50 CCD, it is possible to reflash without servod, which _must not_ be running when using this method.
1. Enter the chroot.
* `$ cros_sdk`
1. Build the EC image for your board.
* `$ cd ~/trunk/src/platform/ec`
* `$ board=<board_name>`
* `$ make -j BOARD="$board"`
1. Run iteflash from the build/\<board\>/util directory.
* `$ build/"$board"/util/iteflash --i2c-interface=ccd --i2c-mux --send-waveform=1 --erase --write=build/"$board"/ec.bin`
WARNING: The `--i2c-mux` flag is only required for some ITE EC boards. For boards without an I2C mux between CR50 and the EC, that flag _must not_ be specified. (This is handled for you when using `flash_ec` + `servod` because the latter has knowledge of which boards are expected to have the I2C mux.)