Framework laptops are capable of being debugged and programmed from a variety of interfaces. This document describes all of them and offers some tips on what hardware is needed.
Here's a short list:
EC & CPU UARTs can be accessed without opening the DUT (Device Under Test, aka the framework laptop) up by connecting to the USB Type-C ports on the right of the device (side with the power button).
The USB Type-C port needs to be told to go to debug accessory mode (see USB Type-C Cable and Connector Specifications, section "Chapter B, Debug Accessory Mode"). Then the UART TX and RX can be connected to the SBU lines (see below section for pinout).
The one of the ports is going to have EC UART (generally top right port of a 13 inch), another has the CPU UART.
Note: Inserting the debugger into the DUT in the flipped orientation will swap RX and TX, resulting in not much happening.
Note 2: This is similar to Chrome OS CCD, but not quite. Chromebooks use D+ & D- USB from the GSC over the SBU lines instead of simple UART signals.
Note 3: If you happen to have a Chrome OS Servo v4
there's a way it can be configured to do this kind of UART debugging,
despite UART not being common on chromebooks. That feature was added to debug
some Android phones. If you're still interested in this method,
dut-control sbu_uart_sel:uart is what you're looking for, and
perhaps dut-control sbu_flip_sel:on.
Thank you @DHowett for the blog post that inspired this document and tool incubation.
One needs a USB Type-C Male breakout board and some kind of UART interface (FTDI or any other 3.3V UART breakout / cable will probably work fine).
Note: A female breakout board does not work as Type-C cables do not pass both CC signals.
| Type C Male (toward DUT) | UART Interface Board (eg: FTDI) |
|---|---|
| A5 (CC1) | 5.1 kΩ resistor to GND (Note 1) |
| B5 (CC2) | 5.1 kΩ resistor to GND |
| A8 (SBU 1) dut uart TX (Note 3) | 1k (Note 2) resistor to debugger TX |
| B8 (SBU 2) dut uart RX | 1k resistor to debugger RX |
| A4, A9, B4, B9 (VBUS) | Do not inject power into this from an interface board! The DUT will also be sourcing 5V on this, use only as a signal that the DUT is alive. |
| A1, A12, B1, B12 (GND) | GND |
Note 1: The table above describes the Rd/Rd (both pullup to GND) configuration, this makes the DUT provide voltage on VBUS (useful in some cases if you want to power sections of a debug card).
Note 2: The 1k resistor is for safety and power sequencing (eg: not killing either the DUT or the interface board if it's off while the other is on, or if the RX/TX is flipped). Feel free to substitute with something else (or 0 ohm) in a pinch.
Note 3: On a laptop, A8 (SBU 1) (aka dut TX) pin is on the same side of the Type-C port as the keyboard (aka C panel). B9 (SBU 2) (aka dut RX) is toward the bottom of the device (D panel)
For this you'll need to connect to various connectors on the board. You will have to open the DUT (and cope with the blinking red LEDs due to chassis intrusion). Most likely the connectors themselves will not be populated on production boards so you will have to solder them yourself. See each connector for part numbers.
This connector provides a way to program/debug the EC, see the EC booting, then see the CPU boot logs.
While the EC is very chatty and even offers a console, the CPU will probably not say anything unless the software (firmware and/or OS) is told to use the serial port.
This connector is usually placed near the EC chip, usually bottom right area of the board, near the keyboard connector and possibly even near the BIOS chip. This area of the board is usually farther away from the main CPU, memory, storage and beefy power stuff for space reasons.
This connector generally comes unpopulated on mass production boards, one needs to buy and solder it to make use of the signals.
10 pin connector, 0.5mm pitch, flat flex cable:
Pinout:
- 3VL_EC
- UART_0_CRXD_DTXD
- EC_JTAG_TMS
- EC_JTAG_TCK
- EC_JTAG_TDO
- ECTX_DRX
- ECRX_DTX
- UART_0_CTXD_DRXD
- EC_RST#
- GND
Warning: Do not inject voltage on any pins when the device on the other side (EC or CPU, as applicable) is off. Doing so will cause current leaks that will cause troubles using the debugger and at worst might damange the DUT.
All EC pins are referenced to the 3VL_EC rail (and also happens to be
3.3V on every device we made so far).
EC_RST# is an OD rail with a pullup on the DUT. Do not output high on
this rail as it might cause a short when the board gets reset in other ways.
CPU UARTs unfortunatelly do not have a voltage reference pin. In order to avoid leaks we generally implemented a pattern of open drain level shifters on the DUT side. All you have to do to use these pins safely is use an open drain for DEBUG_TX_DUT_RX and a hiz input (without a debugger pullup) for DEBUG_RX_DUT_TX. The CPU UART pins are generally 3.3V. In a pinch they can be used directly with a uart interface, but those pins should only be connected after CPU turns on, and disconnected before a shutdown or a reboot.
This connector can be used to reflash the BIOS chip. This is useful for SOC BIOS/Firmware developers (eg: coreboot) and perhaps even unbricking from a failed BIOS upgrade.
Note: While one can reflash the BIOS with this connector the CPU might not always boot any BIOS (eg: self signed coreboot).
This connector is usually placed near the BIOS chip. It's labeled on the silkscreen using the "JSPI" label.
This connector generally comes unpopulated on mass production boards, one needs to buy and solder it to make use of the signals.
6 pin connector, 0.5mm pitch, flat flex cable:
- Connector, Digikey (H125824CT-ND)
- Flex Cable, Digikey (WM25052-ND) (ignore the 10 pin picture on molex's website, it's 6 pin)
Pinout:
- GND
- SOC_SPI_0_CLK
- SOC_SPI_0_MISO
- SOC_SPI_0_MOSI
- SOC_SPI_0_CS#
- SPI_VCC
All SPI pins are referenced to the SPI_VCC rail. SPI_VCC is generally what powers the spi flash chip as well.
| Board | SPI_VCC |
|---|---|
| Dogwood | 1.8V |
| Lilac | 1.8V |
| Marigold | 1.8V |
| Azalea | 1.8V |
| Lotus | 1.8V |
| Tulip | 1.8V |
| ADL | 3.3V |
| Sunflower | 3.3V |
| Iris | 3.3V |
| Banshee | 3.3V |
| TGL | 3.3V |
On later boards we have guaranteed to have 33 ohm resistors between the SPI flash and the CPU, meaning if a debugger is used, the debugger will win a drive fight.
Injecting VCC into the motherboard is not recommended. The CPU should be turned on, kept in a quiet state, then the SPI flash programmed based on the voltage reference. Turning on either SPI_VCC or raising the voltage of any of the SPI pins while the CPU is off causes leaks that might damage hardware.
This connector can be used to flash and debug the PD chips. Unless you're really into USB Type-C and have the Cypress SDK ready you probably don't care about this.
This connector is generally placed near the top of the board (though possibly under a heatsink, particularly on the 16 inch). Usually on each side of the device near the type-C ports.
This connector generally comes unpopulated on mass production boards, one needs to buy and solder it to make use of the signals.
6 pin connector, 0.5mm pitch, flat flex cable:
- Connector, Digikey (H125824CT-ND)
- Flex Cable, Digikey (WM25052-ND) (ignore the 10 pin picture on molex's website, it's 6 pin)
Pinout:
- VCC
- GND
- XRES
- SWD_CLK
- SWD_IO
Once connected to the EC UART (either open case or closed case, see above), the
Embedded Controller's command prompt can be reached. The UART settings are
115200 8N1.
help will give a list of available commands. help $command for help
specific to a certain command.
Interesting commands:
powerbtn- simulates button pressapshutdown- forces CPU offversion- gives the EC version (generally matches BIOS version)
Once connected to the CPU UART (either open case or closed case, see above) the port can be used for a variety of uses:
Once the Advanced > Serial Console BIOS option is enabled, a new /dev/ttyS4
device will show up under Linux (at least on AMD systems).
This serial device is useful to manage a linux system even in cases where doing it over the display is less desired (ex: debugging crashes, lights out management over the text console without KVMs involving screen output)
console=ttyS4,115200 can be added to the kernel command line (just before an
entry of console=tty0, otherwise you might not see any more output on the
normal screen). This way the kernel will output any messages to the UART
console as well. loglevel=9 is also useful for debugging the kernel messages
while doing this. If there's someone listening on the other end of the UART
port any kernel crashes or restarts might be easier to root cause.
One can login to the linux system via this UART console, a
getty can be started:
sudo systemctl enable --now getty@ttyS4.service
Note: the getty will use the currently configured baud rate. If you're already using the kernel console instructions above, this will be 115200, otherwise you might have to adjust the systemd job for the desired serial settings.
Once the service is enabled a login prompt will appear on the uart console. With the appropriate authetication the system can be managed over the UART console with no other graphics or networking running.
The BIOS settings can be managed through the CPU UART console by enabling
Advanced > Console Redirect Configuration > Console Serial Redirect.
It's also worth double-checking if the
Advanced > Console Redirect Configuration > MMIO_UART0 (FCH) > PortEnable
setting is set to Enabled.
Once that's done, the BIOS should be visible as soon as the next reboot on the UART console. The uart settings of the serial monitor match the settings configured in the bios, the default is 115200 8N1.
Normal boot keys like F2 and F12 should also work to interrupt the boot process.