Synopsis #
A serial login and a serial system console are different facilities. A login begins after the kernel and init are running. A recovery console must also carry the earlier firmware, loader, and kernel stages that need to be diagnosed. Each stage can select a different device, speed, or console policy.
Build the path from observed hardware and firmware behavior rather than copying a device name or I/O address. Retain a working video, provider, or hardware-management console until a cold-boot serial test has succeeded. A boot-path diagnosis can then use the last stage visible on that tested path.
Define the required recovery boundary #
Decide which stages must remain accessible:
| Required stage | Facility that must support it |
|---|---|
| Firmware setup and boot selection | Firmware serial redirection, a baseboard management controller, or another hardware console |
| FreeBSD loader menu and prompt | A loader-supported UART or firmware console |
| Early kernel messages and debugger | A UART selected as a kernel console |
| Single-user recovery | The active system console and the policy in /etc/ttys |
| Multi-user login | An enabled getty entry for the verified terminal line |
A serial login alone is sufficient for routine administration but not for a loader failure. Firmware redirection alone can disappear when the loader or kernel takes control.
Identify the electrical and device path #
Confirm the target’s hardware manual, voltage level, connector pinout, cable type, and supported bit rate. RS-232, TTL-level UARTs, and vendor-specific management headers are not electrically interchangeable. A null-modem connection and a straight-through connection also wire transmit and receive signals differently.
A USB-to-serial adapter on the controlling computer can connect to a real UART on the target. A USB serial adapter attached to the target normally appears only after the target kernel has enumerated USB, so it cannot be assumed to carry firmware or loader output. Embedded USB device mode is another distinct arrangement and applies only to hardware and boot code that support it.
On a running target, preserve read-only evidence:
$ grep -i uart /var/run/dmesg.boot
$ pciconf -lv
# conscontrol list
The uart messages identify interfaces that the running kernel attached. They do not prove that the firmware and loader can use the same interface. Device unit numbers and call-in or call-out node names are assigned from detected hardware and must not be inferred from connector labels such as COM1.
Test the controlling terminal first #
Connect the cable while the existing console remains available. Configure the terminal emulator for the firmware or hardware-documented speed, character size, parity, stop bits, and flow-control mode. Both 9600 and 115200 bits per second with 8 data bits, no parity, and one stop bit are common, but the initial value depends on the platform, firmware redirection, loader, and existing configuration. At the loader prompt, show comconsole_speed reports the selected loader value. Keep the controlling terminal matched to the stage being observed.
From another FreeBSD system, cu(1) can open the detected call-out device. Replace the path and speed with values observed on that controlling system:
# cu -l /dev/detected-callout-device -s documented-speed
No output can distinguish a wrong speed, wrong cable, wrong port, absent firmware redirection, or a target that has not transmitted anything. Record which stage first produces readable output instead of changing several layers at once.
Establish firmware and loader output #
Enable firmware serial redirection only through the target’s documented firmware or management interface. Record the original setting and retain local console access. Some UEFI implementations already redirect the EFI console to serial; selecting an additional loader serial console can then duplicate characters.
At the FreeBSD loader prompt, inspect the detected console before making a persistent change:
show console
show comconsole_speed
The available console names and UART-selection variables are architecture-specific. On systems where comconsole is supported, a temporary set console=... at the loader prompt can test a serial or multiple-console selection for that boot. Use only console names documented by the installed loader(8) and loader.conf(5), and match the already verified speed.
After a successful temporary test, place only the verified variables in /boot/loader.conf. The persistent-settings guide
explains why loader settings belong there. Multiple consoles are preferable during qualification because a serial error does not simultaneously remove the video or EFI recovery path.
Verify the kernel boundary #
Loader output does not prove that the kernel has selected the UART. During the test boot, confirm that early kernel messages continue on serial and compare the console list after startup:
# conscontrol list
$ grep -i uart /var/run/dmesg.boot
When the loader works but kernel output stops, inspect the installed uart(4), loader(8), and platform loader manual pages before setting hw.uart.console or port-location variables. Memory-mapped, PCI, ACPI-described, and legacy I/O UARTs use different location data. A guessed address can remove the only working console.
Add a login only when required #
Kernel console output does not require a serial getty. Add a login prompt only if authenticated multi-user access over the serial line is part of the design. Select the exact /etc/ttys entry that corresponds to the verified call-in terminal and use a gettytab(5) capability whose speed matches the console.
The onifconsole flag enables a line only when it is an active kernel console. The secure flag on the selected ttyu* getty entry is a trust decision that permits direct root login on that line. It does not encrypt serial traffic or authenticate a console-server operator. For a remotely reachable console, prefer named access at the console server, strong authentication, narrow network exposure, and an insecure terminal classification unless direct root access is an explicit physical-security decision.
The special console entry is a separate decision. Marking console as insecure causes init to request the root password before entering single-user mode; changing only the ttyu* entry does not establish that behavior. Loss of that password can then block single-user recovery. Keep an alternate console available while testing either entry and record the intended direct-login and single-user policies separately.
After a checked /etc/ttys change, ask init to reread it without rebooting:
# init q
Confirm that ordinary console output, single-user access policy, and any intended login behave separately.
Test recovery and rollback #
Perform a maintenance-window test with another recovery path present:
- Capture firmware output from power-on.
- Interrupt the loader and run read-only commands.
- Boot once in verbose mode and confirm continuous kernel output.
- Boot once into single-user mode and verify the expected password policy.
- Complete a normal boot and test an ordinary login only if it was enabled.
- Repeat from a cold boot and through any remote console server or VPN used during an outage.
Keep secrets out of terminal scrollback and console-server logs. Treat control of the serial channel as physical console access.
If the persistent selection fails, use the retained video, EFI, management, or installation-media console to override the loader setting for one boot. Remove or correct only the added /boot/loader.conf variables and /etc/ttys entry, run init q when applicable, and repeat the temporary test. Do not rewrite boot blocks or guess UART hints as a universal recovery step.