Console Guide

Configure serial console access and host logging on OpenBMC.

Table of Contents

  1. Overview
  2. Components
    1. obmc-console-server
    2. obmc-console-client
    3. hostlogger
  3. Hardware Configuration
    1. Serial Port Types
    2. ASPEED VUART
    3. Nuvoton Serial
  4. Setup & Configuration
    1. Build-Time Configuration (Yocto)
    2. Console Server Configuration
    3. Multiple Console Support
    4. Runtime Configuration
  5. Accessing the Console
    1. Via WebUI
    2. Via SSH
    3. Via IPMI SOL
    4. Via Redfish
    5. Via obmc-console-client
  6. SOL Configuration
    1. IPMI SOL Settings
    2. SOL Baud Rates
    3. Redfish SOL Configuration
  7. Host Logger Configuration
    1. Enable Host Logger
    2. Configure Host Logger
    3. systemd Service
    4. View Host Logs
  8. Console Escape Sequences
    1. obmc-console-client
    2. SSH Session
    3. IPMI SOL
  9. Multiple Host Consoles
    1. Access Each Console
  10. Multi-UART Muxing
    1. Mux Configuration
    2. Per-Console D-Bus Interface
    3. Mux Switching via Connect()
    4. Connect/Disconnect Log Markers
    5. D-Bus Console Interface
  11. Troubleshooting
    1. No Console Output
    2. Console Frozen
    3. Garbled Text
    4. SOL Connection Failed
    5. Permission Denied
  12. Security Considerations
    1. Access Control
    2. SOL Encryption
    3. Console Logging Security
  13. Enabling/Disabling Console
    1. Build-Time Disable
    2. Runtime Disable
    3. Disable SOL via IPMI
  14. Deep Dive
    1. Console Server Multiplexing Architecture
    2. IPMI SOL Protocol Details
    3. Escape Sequence Processing
    4. Host Logger Ring Buffer
    5. Source Code Reference
  15. References

Overview

Serial Console provides text-mode access to the host system through the BMC, enabling boot monitoring, BIOS configuration, and command-line access when graphical interfaces are unavailable.

---
title: Console Architecture
---
flowchart TB
    subgraph clients["Clients"]
        direction LR
        webui["WebUI<br/>Console"]
        ssh["SSH<br/>Console"]
        sol["IPMI SOL<br/>ipmitool"]
    end

    bmcweb["bmcweb<br/>WebSocket: /console/default"]

    subgraph console["obmc-console"]
        direction LR
        server["Console Server<br/>(multiplexer)"]
        hostlogger["hostlogger<br/>(persistent logging)"]
    end

    serial["/dev/ttyS*, /dev/ttyVUART*"]

    host["Host System<br/>(Serial console)"]

    clients --> bmcweb --> console --> serial --> host
ASCII-art version (for comparison)
┌─────────────────────────────────────────────────────────────────┐
│                    Console Architecture                         │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│  ┌─────────────────────────────────────────────────────────────┐│
│  │                      Clients                                ││
│  │                                                             ││
│  │   ┌────────────┐  ┌────────────┐  ┌────────────┐            ││
│  │   │  WebUI     │  │  SSH       │  │  IPMI SOL  │            ││
│  │   │  Console   │  │  Console   │  │  ipmitool  │            ││
│  │   └─────┬──────┘  └─────┬──────┘  └─────┬──────┘            ││
│  └─────────┼───────────────┼───────────────┼───────────────────┘│
│            │               │               │                    │
│  ┌─────────┴───────────────┴───────────────┴───────────────────┐│
│  │                        bmcweb                               ││
│  │              WebSocket: /console/default                    ││
│  └─────────────────────────┬───────────────────────────────────┘│
│                            │                                    │
│  ┌─────────────────────────┴───────────────────────────────────┐│
│  │                     obmc-console                            ││
│  │                                                             ││
│  │   ┌─────────────────┐  ┌─────────────────────────────────┐  ││
│  │   │  Console Server │  │  hostlogger                     │  ││
│  │   │  (multiplexer)  │  │  (persistent logging)           │  ││
│  │   └────────┬────────┘  └─────────────────────────────────┘  ││
│  └────────────┼────────────────────────────────────────────────┘│
│               │                                                 │
│  ┌────────────┴────────────────────────────────────────────────┐│
│  │                   Serial Port Interface                     ││
│  │             (/dev/ttyS*, /dev/ttyVUART*)                    ││
│  └────────────────────────┬────────────────────────────────────┘│
│                           │                                     │
│  ┌────────────────────────┴────────────────────────────────────┐│
│  │                      Host System                            ││
│  │                   (Serial console)                          ││
│  └─────────────────────────────────────────────────────────────┘│
└─────────────────────────────────────────────────────────────────┘

Components

obmc-console-server

  • Multiplexes serial port to multiple clients
  • Provides Unix socket interface
  • Handles console access control

obmc-console-client

  • Command-line console access
  • Connects to console-server socket

hostlogger

  • Captures console output persistently
  • Stores in rotating log files
  • Available via Redfish API

Hardware Configuration

Serial Port Types

Type Description Device Path
Physical UART Hardware serial port /dev/ttyS0, /dev/ttyS1
Virtual UART LPC/VUART interface /dev/ttyVUART0
PTY Pseudo-terminal (testing) /dev/pts/*

ASPEED VUART

ASPEED BMCs use Virtual UART for LPC-based console:

// Device tree configuration
&vuart {
    status = "okay";
};

Nuvoton Serial

// Device tree for serial ports
&serial1 {
    status = "okay";
};

Setup & Configuration

Build-Time Configuration (Yocto)

# In your machine .conf or local.conf

# Include console packages
IMAGE_INSTALL:append = " \
    obmc-console \
    phosphor-hostlogger \
"

# Configure console device in machine config
OBMC_CONSOLE_HOST_TTY ?= "ttyVUART0"

# For physical serial port:
# OBMC_CONSOLE_HOST_TTY ?= "ttyS2"

Console Server Configuration

Configuration file: /etc/obmc-console/server.ttyVUART0.conf

# Console server configuration

# Socket directory
socket-id = default

# Console device
console-id = default

# Baud rate
baud = 115200

# Local echo (for testing)
#local-echo = true

# Logfile (if not using hostlogger)
#logfile = /var/log/obmc-console.log

Multiple Console Support

# /etc/obmc-console/server.ttyS0.conf
socket-id = host0
console-id = host0
baud = 115200

# /etc/obmc-console/server.ttyS1.conf
socket-id = host1
console-id = host1
baud = 115200

Runtime Configuration

# Check console service status
systemctl status obmc-console-server@ttyVUART0

# View console logs
journalctl -u obmc-console-server@ttyVUART0 -f

# Restart console service
systemctl restart obmc-console-server@ttyVUART0

Accessing the Console

Via WebUI

  1. Login to WebUI at https://<bmc-ip>/
  2. Navigate to OperationsSerial over LAN Console
  3. Terminal opens in browser window
  4. Type commands to interact with host

Via SSH

# Direct console access via SSH
ssh -t root@bmc-ip /usr/bin/obmc-console-client

# With specific console ID
ssh -t root@bmc-ip /usr/bin/obmc-console-client -i host0

Via IPMI SOL

# Activate SOL session
ipmitool -I lanplus -H bmc-ip -U root -P 0penBmc sol activate

# Deactivate SOL session
ipmitool -I lanplus -H bmc-ip -U root -P 0penBmc sol deactivate

# SOL configuration
ipmitool -I lanplus -H bmc-ip -U root -P 0penBmc sol info

Via Redfish

# Get console URL
curl -k -u root:0penBmc \
    https://localhost/redfish/v1/Managers/bmc

# Look for SerialConsole property
# WebSocket endpoint: wss://bmc-ip/console/default

Via obmc-console-client

# On the BMC directly
obmc-console-client

# Specify console ID
obmc-console-client -i default

# Exit: Ctrl+] or ~.

SOL Configuration

IPMI SOL Settings

# Get SOL configuration
ipmitool -I lanplus -H bmc-ip -U root -P 0penBmc sol info

# Set SOL parameters
# Enable SOL
ipmitool -I lanplus -H bmc-ip -U root -P 0penBmc sol set enabled true

# Set baud rate
ipmitool -I lanplus -H bmc-ip -U root -P 0penBmc sol set volatile-bit-rate 115.2

# Set non-volatile baud rate
ipmitool -I lanplus -H bmc-ip -U root -P 0penBmc sol set non-volatile-bit-rate 115.2

# Set privilege level
ipmitool -I lanplus -H bmc-ip -U root -P 0penBmc sol set privilege-level operator

SOL Baud Rates

Value Rate
6 9600
7 19200
8 38400
9 57600
10 115200

Redfish SOL Configuration

# Get network protocol settings
curl -k -u root:0penBmc \
    https://localhost/redfish/v1/Managers/bmc/NetworkProtocol

# Note: SOL is typically configured via IPMI
# Redfish Serial Console is different from IPMI SOL

Host Logger Configuration

Enable Host Logger

# In Yocto build
IMAGE_INSTALL:append = " phosphor-hostlogger"

Configure Host Logger

# Configuration file
cat /etc/hostlogger.conf

# Common settings:
# - Buffer size
# - Log rotation
# - Flush interval

systemd Service

# /lib/systemd/system/phosphor-hostlogger@.service
[Unit]
Description=Host Console Logger for %i
After=obmc-console-server@%i.service

[Service]
ExecStart=/usr/bin/hostlogger -i %i
Restart=always

[Install]
WantedBy=multi-user.target

View Host Logs

# Via Redfish
curl -k -u root:0penBmc \
    https://localhost/redfish/v1/Systems/system/LogServices/HostLogger/Entries

# Local files (if configured)
ls /var/log/host*

# Via journal
journalctl -u phosphor-hostlogger@ttyVUART0

Console Escape Sequences

obmc-console-client

Sequence Action
~. Disconnect
~? Show help
~^Z Suspend
~~ Send literal ~

SSH Session

Sequence Action
~. Disconnect (SSH + console)
Enter ~. Disconnect properly

IPMI SOL

Sequence Action
~. Deactivate SOL
~^Z Suspend SOL
~B Send break

Multiple Host Consoles

For systems with multiple hosts:

# Configuration for each host
# /etc/obmc-console/server.host0.conf
socket-id = host0
console-id = host0

# /etc/obmc-console/server.host1.conf
socket-id = host1
console-id = host1

Access Each Console

# Via WebUI - select from dropdown
# Via SSH
ssh -t root@bmc-ip /usr/bin/obmc-console-client -i host0
ssh -t root@bmc-ip /usr/bin/obmc-console-client -i host1

# Via IPMI - use channel parameter
ipmitool -I lanplus -H bmc-ip -U root -P 0penBmc -c 1 sol activate

Multi-UART Muxing

Unlike Multiple Host Consoles – which gives each host its own dedicated serial port – multi-UART muxing shares one physical port between several UARTs that sit behind a GPIO mux, exposing only one of them at a time. A single obmc-console-server process drives the shared tty and switches the mux GPIOs to select the active console.

Use Multiple Host Consoles when each host has independent wiring; use Multi-UART Muxing when several UARTs share the same BMC port and a mux chip selects between them.

Mux Configuration

Two configuration keys control muxing (see the upstream mux-support.md):

  • mux-gpios (global, top of the config file) – the GPIO line name(s) that drive the mux. The order of the listed GPIOs forms the LSB-first bit representation of the number taken from each console’s mux-index.
  • mux-index (per console) – the numeric mux value that selects this console. Each console lives in a section whose name matches its console-id.
# /etc/obmc-console/server.conf  (started as: obmc-console-server --config server.conf /dev/ttyS0)

# Global: GPIO(s) that select which UART is active
mux-gpios = MUX_CTL

[host1]
mux-index = 0
logfile = /var/log/console-host1.log

[host2]
mux-index = 1
logfile = /var/log/console-host2.log

Per-Console D-Bus Interface

Each muxed console is published as its own D-Bus service named after the console-id:

busctl list | grep xyz.openbmc_project.Console
# xyz.openbmc_project.Console.host1  ...  obmc-console-server  root ...
# xyz.openbmc_project.Console.host2  ...  obmc-console-server  root ...

busctl introspect xyz.openbmc_project.Console.host1 \
    /xyz/openbmc_project/console/host1
# xyz.openbmc_project.Console.Access  interface  -  -
# .Connect                            method     -  h

Mux Switching via Connect()

Mux control is implicit: switching happens when a client connects. Calling Connect() on a console (or simply attaching obmc-console-client -i host1) makes the server switch the mux GPIOs to that console’s mux-index, then start forwarding bytes. Any client attached to another console is disconnected.

# Selecting host1 asserts the mux GPIOs for host1 and drops host2
busctl call xyz.openbmc_project.Console.host1 \
    /xyz/openbmc_project/console/host1 \
    xyz.openbmc_project.Console.Access Connect

Concretely, connecting to host1 causes the previously active host2 to (1) stop forwarding bytes and (2) print a disconnect log to its clients; then host1 (1) switches the mux via the GPIOs, (2) prints a connect log to its clients, and (3) resumes forwarding.

Connect/Disconnect Log Markers

So a log reader can see why a console went quiet, the server writes a marker line to all clients of a console whenever the mux switches:

[obmc-console] %Y-%m-%d %H:%M:%S UTC CONNECTED
[obmc-console] %Y-%m-%d %H:%M:%S UTC DISCONNECTED

These markers are a convenience only – anything on the other side of the UART could print the same text, and the exact format is not guaranteed to stay fixed. Do not parse them as a reliable connection signal.

D-Bus Console Interface

Beyond the muxing Access interface, obmc-console-server (in console-dbus.c) exposes a xyz.openbmc_project.Console.UART interface on /xyz/openbmc_project/console/<console-id> with a writable Baud property (type t, uint64). Writing it re-applies the tty’s termios at runtime – no service restart needed:

# Read the current baud rate
busctl get-property xyz.openbmc_project.Console.default \
    /xyz/openbmc_project/console/default \
    xyz.openbmc_project.Console.UART Baud

# Change baud rate live (re-applies termios on the underlying tty)
busctl set-property xyz.openbmc_project.Console.default \
    /xyz/openbmc_project/console/default \
    xyz.openbmc_project.Console.UART Baud t 57600

The xyz.openbmc_project.Console.Access interface’s Connect() method takes no arguments and returns a Unix file descriptor (h). The server creates a socket pair, hands the client end back over D-Bus, and closes its own end – giving the caller a direct byte stream to the console without going through the on-disk Unix socket path.

# Returns a connected fd for the default console
busctl call xyz.openbmc_project.Console.default \
    /xyz/openbmc_project/console/default \
    xyz.openbmc_project.Console.Access Connect

Troubleshooting

No Console Output

# Check if console server is running
systemctl status obmc-console-server@ttyVUART0

# Check device exists
ls -la /dev/ttyVUART0

# Check permissions
stat /dev/ttyVUART0

# Check serial port configuration
stty -F /dev/ttyVUART0 -a

# Verify baud rate matches host
stty -F /dev/ttyVUART0 115200

Console Frozen

# Restart console server
systemctl restart obmc-console-server@ttyVUART0

# Kill stuck clients
pkill obmc-console-client

# Check for hardware issues
dmesg | grep -i uart

Garbled Text

# Baud rate mismatch - verify settings match
# Host BIOS/OS must use same baud rate as BMC

# Common baud rates to try:
stty -F /dev/ttyVUART0 9600
stty -F /dev/ttyVUART0 19200
stty -F /dev/ttyVUART0 38400
stty -F /dev/ttyVUART0 57600
stty -F /dev/ttyVUART0 115200

SOL Connection Failed

# Check IPMI service
systemctl status phosphor-ipmi-net

# Verify SOL is enabled
ipmitool -I lanplus -H bmc-ip -U root -P 0penBmc sol info

# Check for active sessions
ipmitool -I lanplus -H bmc-ip -U root -P 0penBmc session info all

# Force deactivate stale session
ipmitool -I lanplus -H bmc-ip -U root -P 0penBmc sol deactivate

Permission Denied

# Check user permissions
# User needs Operator or Administrator role

# Verify via Redfish
curl -k -u user:password \
    https://localhost/redfish/v1/AccountService/Accounts/user

Security Considerations

Access Control

# Console access requires authentication
# Recommended role: Operator or Administrator

# View user roles
curl -k -u root:0penBmc \
    https://localhost/redfish/v1/AccountService/Accounts

SOL Encryption

IPMI SOL uses RMCP+ encryption:

# Check cipher suite
ipmitool -I lanplus -H bmc-ip -U root -P 0penBmc -C 17 sol activate

# Cipher 17 = AES-CBC-128 + HMAC-SHA256 (recommended)

Console Logging Security

# Console logs may contain sensitive data
# Configure retention policy
# Restrict access to log files

# File permissions
chmod 600 /var/log/hostlogger/*

Enabling/Disabling Console

Build-Time Disable

# Remove console packages
IMAGE_INSTALL:remove = "obmc-console phosphor-hostlogger"

Runtime Disable

# Stop console service
systemctl stop obmc-console-server@ttyVUART0
systemctl disable obmc-console-server@ttyVUART0

# Stop hostlogger
systemctl stop phosphor-hostlogger@ttyVUART0
systemctl disable phosphor-hostlogger@ttyVUART0

Disable SOL via IPMI

ipmitool -I lanplus -H bmc-ip -U root -P 0penBmc sol set enabled false

Deep Dive

Advanced implementation details for console developers.

Console Server Multiplexing Architecture

┌────────────────────────────────────────────────────────────────────────────┐
│                   obmc-console Multiplexer Architecture                    │
├────────────────────────────────────────────────────────────────────────────┤
│                                                                            │
│  SERIAL DEVICE                                                             │
│  ─────────────                                                             │
│  /dev/ttyVUART0 (or /dev/ttyS*)                                            │
│        │                                                                   │
│        │ termios settings: 115200 8N1                                      │
│        v                                                                   │
│  ┌─────────────────────────────────────────────────────────────────────┐   │
│  │                    obmc-console-server                              │   │
│  │                                                                     │   │
│  │  ┌───────────────────────────────────────────────────────────────┐  │   │
│  │  │  TTY Handler                                                  │  │   │
│  │  │                                                               │  │   │
│  │  │  // Open serial port with correct settings                    │  │   │
│  │  │  fd = open("/dev/ttyVUART0", O_RDWR | O_NOCTTY);              │  │   │
│  │  │  tcgetattr(fd, &termios);                                     │  │   │
│  │  │  cfsetispeed(&termios, B115200);                              │  │   │
│  │  │  cfsetospeed(&termios, B115200);                              │  │   │
│  │  │  termios.c_cflag = CS8 | CREAD | CLOCAL;  // 8N1              │  │   │
│  │  │  tcsetattr(fd, TCSANOW, &termios);                            │  │   │
│  │  └───────────────────────────────────────────────────────────────┘  │   │
│  │                          │                                          │   │
│  │                          │ epoll multiplexing                       │   │
│  │                          v                                          │   │
│  │  ┌───────────────────────────────────────────────────────────────┐  │   │
│  │  │  Event Loop (main.c)                                          │  │   │
│  │  │                                                               │  │   │
│  │  │  epoll_fd = epoll_create1(0);                                 │  │   │
│  │  │  epoll_ctl(epoll_fd, EPOLL_CTL_ADD, tty_fd, &ev_tty);         │  │   │
│  │  │  epoll_ctl(epoll_fd, EPOLL_CTL_ADD, socket_fd, &ev_sock);     │  │   │
│  │  │                                                               │  │   │
│  │  │  while (running) {                                            │  │   │
│  │  │      n = epoll_wait(epoll_fd, events, MAX_EVENTS, -1);        │  │   │
│  │  │      for (i = 0; i < n; i++) {                                │  │   │
│  │  │          if (events[i].data.fd == tty_fd) {                   │  │   │
│  │  │              // Data from host → broadcast to all clients     │  │   │
│  │  │              handle_tty_data();                               │  │   │
│  │  │          } else if (events[i].data.fd == socket_fd) {         │  │   │
│  │  │              // New client connection                         │  │   │
│  │  │              accept_client();                                 │  │   │
│  │  │          } else {                                             │  │   │
│  │  │              // Data from client → write to tty               │  │   │
│  │  │              handle_client_data(events[i].data.fd);           │  │   │
│  │  │          }                                                    │  │   │
│  │  │      }                                                        │  │   │
│  │  │  }                                                            │  │   │
│  │  └───────────────────────────────────────────────────────────────┘  │   │
│  │                          │                                          │   │
│  │            ┌─────────────┼─────────────┐                            │   │
│  │            │             │             │                            │   │
│  │            v             v             v                            │   │
│  │  ┌──────────────┐ ┌──────────────┐ ┌──────────────┐                 │   │
│  │  │ Unix Socket  │ │ Unix Socket  │ │ Unix Socket  │                 │   │
│  │  │ Client 1     │ │ Client 2     │ │ Client 3     │                 │   │
│  │  │ (SSH)        │ │ (WebUI)      │ │ (hostlogger) │                 │   │
│  │  └──────────────┘ └──────────────┘ └──────────────┘                 │   │
│  │                                                                     │   │
│  └─────────────────────────────────────────────────────────────────────┘   │
│                                                                            │
│  UNIX SOCKET: /var/run/obmc-console.sock (or /run/obmc-console/ttyVUART0)  │
│                                                                            │
└────────────────────────────────────────────────────────────────────────────┘

IPMI SOL Protocol Details

┌────────────────────────────────────────────────────────────────────────────┐
│                          IPMI SOL Packet Format                            │
├────────────────────────────────────────────────────────────────────────────┤
│                                                                            │
│  SOL PAYLOAD FORMAT (within RMCP+ session)                                 │
│  ─────────────────────────────────────────                                 │
│                                                                            │
│  ┌────────────────────────────────────────────────────────────────────┐    │
│  │  RMCP+ Session Header                                              │    │
│  │  ┌─────────────┬─────────────┬─────────────┬────────────────────┐  │    │
│  │  │ Auth Type   │ Payload Type│ Session ID  │ Sequence Number    │  │    │
│  │  │ (1 byte)    │ (1 byte)    │ (4 bytes)   │ (4 bytes)          │  │    │
│  │  │ 0x06 (RMCP+)│ 0x01 (SOL)  │             │                    │  │    │
│  │  └─────────────┴─────────────┴─────────────┴────────────────────┘  │    │
│  └────────────────────────────────────────────────────────────────────┘    │
│                                                                            │
│  ┌────────────────────────────────────────────────────────────────────┐    │
│  │  SOL Payload Header (4 bytes)                                      │    │
│  │                                                                    │    │
│  │  ┌─────────────────────────────────────────────────────────────┐   │    │
│  │  │ Byte 0: Packet Sequence Number (4 bits ack, 4 bits send)    │   │    │
│  │  │         ┌───┬───┬───┬───┬───┬───┬───┬───┐                   │   │    │
│  │  │         │ 7 │ 6 │ 5 │ 4 │ 3 │ 2 │ 1 │ 0 │                   │   │    │
│  │  │         ├───┴───┴───┴───┼───┴───┴───┴───┤                   │   │    │
│  │  │         │  Ack Seq Num  │ Packet Seq Num│                   │   │    │
│  │  │         └───────────────┴───────────────┘                   │   │    │
│  │  │                                                             │   │    │
│  │  │ Byte 1: Accepted Character Count                            │   │    │
│  │  │         Number of characters accepted from last packet      │   │    │
│  │  │                                                             │   │    │
│  │  │ Byte 2: Operation/Status                                    │   │    │
│  │  │         ┌───┬───┬───┬───┬───┬───┬───┬───┐                   │   │    │
│  │  │         │ 7 │ 6 │ 5 │ 4 │ 3 │ 2 │ 1 │ 0 │                   │   │    │
│  │  │         └───┴───┴───┴───┴───┴───┴───┴───┘                   │   │    │
│  │  │         Bit 0: Nack packet                                  │   │    │
│  │  │         Bit 1: Ring WOR (Wake on Ring)                      │   │    │
│  │  │         Bit 2: Break detected                               │   │    │
│  │  │         Bit 3: Transmit overrun                             │   │    │
│  │  │         Bit 4: SOL deactivating                             │   │    │
│  │  │         Bit 5: Character transfer unavail                   │   │    │
│  │  │         Bit 6: SOL deactivating                             │   │    │
│  │  │         Bit 7: Reserved                                     │   │    │
│  │  │                                                             │   │    │
│  │  │ Byte 3: Reserved                                            │   │    │
│  │  └─────────────────────────────────────────────────────────────┘   │    │
│  └────────────────────────────────────────────────────────────────────┘    │
│                                                                            │
│  ┌────────────────────────────────────────────────────────────────────┐    │
│  │  SOL Character Data (variable length, max ~255 bytes)              │    │
│  │                                                                    │    │
│  │  Serial console data (text from/to host)                           │    │
│  └────────────────────────────────────────────────────────────────────┘    │
│                                                                            │
│  SOL FLOW CONTROL:                                                         │
│  ─────────────────                                                         │
│                                                                            │
│  Client                                       BMC                          │
│     │                                          │                           │
│     │  Activate SOL (payload type 0x01)        │                           │
│     │  ──────────────────────────────────────> │                           │
│     │                                          │                           │
│     │  SOL Data (seq=1, console output)        │                           │
│     │  <────────────────────────────────────── │                           │
│     │                                          │                           │
│     │  SOL Ack (ack_seq=1, accepted=N)         │                           │
│     │  ──────────────────────────────────────> │                           │
│     │                                          │                           │
│     │  SOL Data (seq=1, keyboard input)        │                           │
│     │  ──────────────────────────────────────> │                           │
│     │                                          │                           │
│     │  SOL Ack (ack_seq=1)                     │                           │
│     │  <────────────────────────────────────── │                           │
│     │                                          │                           │
│                                                                            │
└────────────────────────────────────────────────────────────────────────────┘

Escape Sequence Processing

┌────────────────────────────────────────────────────────────────────────────┐
│                      Console Escape Sequence Handling                      │
├────────────────────────────────────────────────────────────────────────────┤
│                                                                            │
│  ESCAPE SEQUENCE STATE MACHINE                                             │
│  ─────────────────────────────                                             │
│                                                                            │
│  ┌──────────────┐       '~'        ┌──────────────┐                        │
│  │              │─────────────────>│              │                        │
│  │    NORMAL    │                  │ ESCAPE_START │                        │
│  │              │<─────────────────│              │                        │
│  └──────┬───────┘    other char    └──────┬───────┘                        │
│         │                                 │                                │
│         │ all other                       │ '.'                            │
│         │ characters                      v                                │
│         │                          ┌──────────────┐                        │
│         │                          │  DISCONNECT  │                        │
│         │                          │              │                        │
│         │                          │  Close conn  │                        │
│         v                          └──────────────┘                        │
│  ┌──────────────┐                                                          │
│  │   FORWARD    │                  ┌──────────────┐                        │
│  │  TO SERIAL   │                  │    BREAK     │<─── '~' then 'B'       │
│  └──────────────┘                  │              │                        │
│                                    │  Send break  │                        │
│                                    │  to serial   │                        │
│                                    └──────────────┘                        │
│                                                                            │
│  ESCAPE SEQUENCES (obmc-console-client):                                   │
│  ──────────────────────────────────────                                    │
│                                                                            │
│  │ Sequence │ Action                                      │                │
│  │──────────│─────────────────────────────────────────────│                │
│  │ ~.       │ Disconnect from console                     │                │
│  │ ~B       │ Send serial break signal                    │                │
│  │ ~?       │ Show help message                           │                │
│  │ ~~       │ Send literal '~' character                  │                │
│  │ ~^Z      │ Suspend client (if in terminal)             │                │
│                                                                            │
│  IMPLEMENTATION (console-client.c):                                        │
│  ─────────────────────────────────                                         │
│                                                                            │
│  enum escape_state { ESC_NONE, ESC_TILDE };                                │
│                                                                            │
│  void process_input(char *buf, size_t len) {                               │
│      for (i = 0; i < len; i++) {                                           │
│          char c = buf[i];                                                  │
│                                                                            │
│          if (escape_state == ESC_NONE) {                                   │
│              if (c == '~' && last_was_newline) {                           │
│                  escape_state = ESC_TILDE;                                 │
│                  continue;                                                 │
│              }                                                             │
│          } else if (escape_state == ESC_TILDE) {                           │
│              escape_state = ESC_NONE;                                      │
│              switch (c) {                                                  │
│                  case '.':                                                 │
│                      disconnect();                                         │
│                      return;                                               │
│                  case 'B':                                                 │
│                      send_break();                                         │
│                      continue;                                             │
│                  case '~':                                                 │
│                      // Forward literal ~                                  │
│                      break;                                                │
│                  default:                                                  │
│                      // Not escape, forward ~ and char                     │
│                      forward_char('~');                                    │
│                      break;                                                │
│              }                                                             │
│          }                                                                 │
│          forward_char(c);                                                  │
│          last_was_newline = (c == '\n' || c == '\r');                      │
│      }                                                                     │
│  }                                                                         │
│                                                                            │
└────────────────────────────────────────────────────────────────────────────┘

Host Logger Ring Buffer

┌────────────────────────────────────────────────────────────────────────────┐
│                    phosphor-hostlogger Implementation                      │
├────────────────────────────────────────────────────────────────────────────┤
│                                                                            │
│  RING BUFFER ARCHITECTURE                                                  │
│  ───────────────────────                                                   │
│                                                                            │
│  ┌─────────────────────────────────────────────────────────────────────┐   │
│  │  Console Data Stream                                                │   │
│  │                                                                     │   │
│  │  obmc-console-server → Unix socket → hostlogger                     │   │
│  └────────────────────────────────┬────────────────────────────────────┘   │
│                                   │                                        │
│                                   v                                        │
│  ┌─────────────────────────────────────────────────────────────────────┐   │
│  │  Ring Buffer (in memory)                                            │   │
│  │                                                                     │   │
│  │  struct RingBuffer {                                                │   │
│  │      char data[BUFFER_SIZE];    // e.g., 64KB                       │   │
│  │      size_t write_pos;          // Next write position              │   │
│  │      size_t read_pos;           // Current read position            │   │
│  │      size_t total_written;      // Total bytes ever written         │   │
│  │  };                                                                 │   │
│  │                                                                     │   │
│  │  ┌───────────────────────────────────────────────────────────────┐  │   │
│  │  │ ... old data ... │ write_pos │ ... space ... │ read_pos ...   │  │   │
│  │  └───────────────────────────────────────────────────────────────┘  │   │
│  │                         ↑                            │              │   │
│  │                         │                            │              │   │
│  │                    New data appended            Oldest data         │   │
│  │                    (wraps around)               (overwritten)       │   │
│  └─────────────────────────────────────────────────────────────────────┘   │
│                                   │                                        │
│                                   │ Periodic flush / rotation              │
│                                   v                                        │
│  ┌─────────────────────────────────────────────────────────────────────┐   │
│  │  Persistent Log Files                                               │   │
│  │                                                                     │   │
│  │  /var/log/hostlogger/                                               │   │
│  │  ├── host_console.log        (current, up to 100KB)                 │   │
│  │  ├── host_console.log.1      (rotated)                              │   │
│  │  ├── host_console.log.2      (rotated)                              │   │
│  │  └── host_console.log.3      (oldest, deleted when 4 created)       │   │
│  │                                                                     │   │
│  │  Rotation policy:                                                   │   │
│  │    - Max file size: 100KB (configurable)                            │   │
│  │    - Max files: 4 (configurable)                                    │   │
│  │    - Rotate on size limit reached                                   │   │
│  └─────────────────────────────────────────────────────────────────────┘   │
│                                                                            │
│  REDFISH LOG ENTRIES                                                       │
│  ───────────────────                                                       │
│                                                                            │
│  GET /redfish/v1/Systems/system/LogServices/HostLogger/Entries             │
│                                                                            │
│  {                                                                         │
│      "@odata.id": ".../Entries/1",                                         │
│      "EntryType": "Oem",                                                   │
│      "OemRecordFormat": "Host Logger Entry",                               │
│      "Message": "Linux version 5.10.0 (gcc version 10.2.0)...",            │
│      "Created": "2024-01-15T10:30:00+00:00",                               │
│      "Severity": "OK"                                                      │
│  }                                                                         │
│                                                                            │
│  Line parsing:                                                             │
│    - Split on newline                                                      │
│    - Each line becomes one Redfish entry                                   │
│    - Timestamp from when line was received                                 │
│    - Severity: OK for normal, Warning for errors                           │
│                                                                            │
└────────────────────────────────────────────────────────────────────────────┘

Source Code Reference

Key implementation files in obmc-console and phosphor-hostlogger:

File Description
obmc-console/console-server.c Main multiplexer and TTY handler
obmc-console/console-socket.c Unix socket client management
obmc-console/console-client.c Client with escape sequence handling
obmc-console/config.c Configuration file parsing
phosphor-hostlogger/src/host_logger.cpp Ring buffer and log rotation
phosphor-hostlogger/src/dbus_loop.cpp D-Bus integration for Redfish

References


Tested on: OpenBMC master, QEMU romulus


Back to top

OpenBMC Guide Tutorial is not affiliated with the OpenBMC project. Content is provided for educational purposes.

This site uses Just the Docs, a documentation theme for Jekyll.