serial debugging howto


The kernel team has been working to remove cruft from the Chromium OS kernel configs. Since there are no Chromebooks with a serial port, serial port drivers were removed from the stock configuration, which is a minor inconvenience for those who still do a lot of debugging using the serial port.

A quick howto was e-mailed some time ago [ Link ] for using mini-PCIe serial cards, but the information is somewhat limited in scope and is worth correcting and modernizing. There are several ways to accomplish what is described here, please feel free to chip in.

This HOWTO assumes you have built a bootable Chromium OS image and are not afraid to edit some config files. We'll assume the target platform is 32-bit "x86-generic"

Enable serial port in Linux configuration

Use the pcserial USE flag when building your kernel:

chromium-os$ USE=pcserial cros_workon_make --board="${BOARD}" chromeos-kernel

For Exynos-based systems, add the samsung_serial USE flag:

chromium-os$ USE=samsung_serial cros_workon_make --board="${BOARD}" chromeos-kernel

Modify kernel command-line options

NOTE: this section is likely out-of-date as you can now use the --enable_serial=<serial options> flag with build_image.sh. 

<serial options> is ttySAC3,115200n8 for exynos-based systems

You'll need change some kernel command-line parameters to get meaningful output. IMHO, the easiest way to do this is to update the command-line options in the script which builds the kernel for your Chomium OS image, located in src/scripts/build_kernel_image.sh. This way your command-line options will be applied no matter if you're booting using the Chrome OS model, or using other boot methods such as legacy bootloader or EFI bootloader.

Look for a section of the kernel build script where content is being added to a new file called "boot.config". You'll need to remove the "quiet" option and adjust the loglevel (I suggest 7). You will also need to add the appropriate console= option, such as "console=ttyS0,115200n8". It is okay to have multiple console= options.

Here is an example:
  cat <<EOF | cat - "${FLAGS_working_dir}/boot.config" \
    > "${FLAGS_working_dir}/config.txt"
quiet                      <--- remove this
loglevel=1                 <--- remove this
loglevel=7                 <--- add this
console=<serial options>     <--- add this
earlyprintk=<serial options> <--- add this (optional)
console=tty2
init=/sbin/init
add_efi_memmap
boot=local
noresume
noswap
i915.modeset=1
cros_secure
kern_guid=%U
tpm_tis.force=1
tpm_tis.interrupts=0
nmi_watchdog=panic,lapic
EOF


A few words about the console= option...
The console= option is described in detail in kernel-parameters.txt in the Kernel source tree (src/third_party/kernel/files/Documentation/kernel-parameters.txt, or on-line).

On most x86 platforms, ttyS0 will refer to the southbridge's UART accessed via ports specified in Super IO configuration space. However, for add-in PCIe cards you may need to specify a MMIO address to access the UART. For example, "console=uart8250,mmio,0x50401000,115200n8".

See Appendix A below for more details.

Build Chromium OS image using your custom kernel config

Set the pcserial USE flag when calling build_packages:

USE=pcserial build_packages

Adding serial login support

Set the tty_console_* flag to start a console at boot,

USE="tty_console_ttyS0" ./build_packages --board=${BOARD}

Alternatively, you can create your own script:

/etc/init/ttyS0.conf:

start on startup
stop on starting halt or starting reboot
respawn
exec /sbin/agetty -L -w 115200 ttyS0 linux

Appendix A: How to find alternate IO and MMIO addresses for your UART

If you already have UART support but simply do not know what options to pass to the kernel, you may examine a few sources to figure it out.

Method 1: Look at /proc/iomem
localhost ~ # cat /proc/iomem | grep serial
    50401000-50401007 : serial

note: for two port pci-serial cards you will see two entries like this:
    e0801000-e0801008 : serial
    e0801200-e0801207 : serial
and the each range will correspond to the two different serial ports

Method 2: Look at PCI device config
localhost chronos # lspci | grep -i serial
02:00.0 Serial controller: NetMos Technology PCIe 9901 Multi-I/O Controller

localhost chronos # lspci -v -s 02:00.0
02:00.0 Serial controller: NetMos Technology PCIe 9901 Multi-I/O Controller (prog-if 02 [16550])
        Subsystem: Device a000:1000
        Flags: bus master, fast devsel, latency 0, IRQ 16
        I/O ports at 2000 [size=8]
        Memory at c0401000 (32-bit, non-prefetchable) [size=4K]
        Memory at c0400000 (32-bit, non-prefetchable) [size=4K]
        Capabilities: [80] Power Management version 3
        Capabilities: [88] MSI: Enable- Count=1/32 Maskable- 64bit+
        Capabilities: [c0] Express Legacy Endpoint, MSI 00
        Kernel driver in use: serial

Method 3: Look at dmesg for lines such as this:
[    0.676698] Serial: 8250/16550 driver, 4 ports, IRQ sharing enabled
[    0.678173] serial 0000:04:00.3: PCI INT D -> GSI 18 (level, low) -> IRQ 18
[    0.678716] 1 ports detected on Oxford PCI Express device
[    0.678910] ttyS0: detected caps 00000700 should be 00000100
[    0.679365] 0000:04:00.3: ttyS0 at MMIO 0x50401000 (irq = 18) is a 16C950/954
[    0.679899] console [ttyS0] enabled, bootconsole disabled
Comments