Linux Console

About Kernel Boot Parameters

Kernel boot parameters are text strings which are interpreted by the system to change specific behaviors and enable or disable certain features.

The Linux kernel accepts certain 'command-line options' or 'boot time parameters' at the moment it is started.
In general, this is used to supply the kernel with information about hardware parameters that the kernel would not be able to determine on its own, or to avoid/override the values that the kernel would otherwise detect.

The list of valid parameters may change between different kernel versions: https://www.kernel.org/doc/html/latest/admin-guide/kernel-parameters.html

Temporarily Add a Kernel Boot Parameter for Testing

  • As the system starts to boot repeated tap the Esc key in order to force the "GNU GRUB" menu to appear.
  • Once the "GNU GRUB" menu appears highlight the desired entry and press the e key to enter edit mode.
  • Modify the linux parameters
  • Press Ctrl+X to boot the system using the parameters you've added.
The parameter(s) you've added to the linux line are only temporary: They will affect this boot session, but once you restart the system they will no longer be in effect.

Permanently Add a Kernel Boot Parameter

  • Modify /etc/default/grub
  • Find "GRUB_CMDLINE_LINUX_DEFAULT" then edit that line.
  • Update Grub
  • Enter the command
    
    sudo update-grub 
    	

Linux Serial Console

To use a serial port as console you need to compile the support into your kernel - by default it is not compiled in.
For PC style serial ports it’s the config option next to menu option:

Character devices 
  ‣ Serial drivers 
    ‣ 8250/16550 and compatible serial support 
      ‣ Console on 8250/16550 and compatible serial port
You must compile serial support into the kernel and not as a module.

It is possible to specify multiple devices for console output.
You can define a new kernel command line option to select which device(s) to use for console output.
The format of this option is:

  
console=device,options
  • device
    • tty0 for the foreground virtual console
    • ttyX for any other virtual console
    • ttySx for a serial port
    • lp0 for the first parallel port
    • ttyUSB0 for the first USB serial device
  • options
  • depend on the driver.
    For the serial port this defines the baudrate/parity/bits/flow control of the port, in the format BBBBPNF, where:
    • BBBB is the speed
    • P is parity (n/o/e)
    • N is number of bits
    • F is flow control ('r' for RTS)
    Default is 9600n8. The maximum baudrate is 115200.
You can specify multiple console= options on the kernel command line. Output will appear on all of them.
The last device will be used when you open /dev/console. So, for example:
  
console=ttyS1,9600 console=tty0
defines that opening /dev/console will get you the current foreground virtual console, and kernel messages will appear on both the (foreground) VGA console and the 2nd serial port (ttyS1 or COM2) at 9600 baud.
Note that you can only define one console per device type (serial, video).

If no console device is specified, the first device found capable of acting as a system console will be used. At this time, the system first looks for a VGA card and then for a serial port.
So if you don’t have a VGA card in your system the first serial port will automatically become the console.

The official /dev/console is now character device 5,1.

VGA console

For VGA consoles, the console parameter takes the following form:

console=ttyX
X is the device number, for example 0, 1, or 2.
Choosing X=0 selects the foreground virtual console, master tty device tty0.

Serial Port

For a serial port to work properly it first must be given both an IO address and an IRQ.
  • For old hardware (of mid 1990s)
  • Jumpers on a card or a saved BIOS setting does it.
  • For newer hardware
  • The BIOS or Linux must set them at boot-time, and the new hardware doesn't remember how it was set once it's powered down.
Enabling the serial port hardware is to give it both an IRQ and an IO address via software.
Without an IO address, it can't be used. Without an IRQ it will need to use inefficient polling methods for which one must set the IRQ to 0 in the serial driver.

How to check if the serial device is working

If there is a USB serial adapter connected, and the serial port is configured for console, the serial port divers will report the receive and transmit byte counts on each port.
Compare the Rx and Tx counts before the test and then after the failure.

$ sudo cat /proc/tty/driver/usbserial
usbserinfo:1.0 driver:2.0
0: module:pl2303 name:"pl2303" vendor:067b product:2303 num_ports:1 port:0 path:usb-0000:00:14.0-1.3

$ sudo cat /proc/tty/driver/serial
serinfo:1.0 driver revision:
0: uart:16550A port:000003F8 irq:4 tx:483 rx:0 RTS|DTR
1: uart:16550A port:000002F8 irq:3 tx:0 rx:0
2: uart:unknown port:000003E8 irq:4
3: uart:unknown port:000002E8 irq:3
4: uart:16550A mmio:0x4017000000 irq:16 tx:0 rx:0
5: uart:unknown port:00000000 irq:0
6: uart:unknown port:00000000 irq:0
7: uart:unknown port:00000000 irq:0
8: uart:unknown port:00000000 irq:0
9: uart:unknown port:00000000 irq:0
10: uart:unknown port:00000000 irq:0
11: uart:unknown port:00000000 irq:0
12: uart:unknown port:00000000 irq:0
13: uart:unknown port:00000000 irq:0
14: uart:unknown port:00000000 irq:0
15: uart:unknown port:00000000 irq:0
16: uart:unknown port:00000000 irq:0
17: uart:unknown port:00000000 irq:0
18: uart:unknown port:00000000 irq:0
19: uart:unknown port:00000000 irq:0
20: uart:unknown port:00000000 irq:0
21: uart:unknown port:00000000 irq:0
22: uart:unknown port:00000000 irq:0
23: uart:unknown port:00000000 irq:0
24: uart:unknown port:00000000 irq:0
25: uart:unknown port:00000000 irq:0
26: uart:unknown port:00000000 irq:0
27: uart:unknown port:00000000 irq:0
28: uart:unknown port:00000000 irq:0
29: uart:unknown port:00000000 irq:0
30: uart:unknown port:00000000 irq:0
31: uart:unknown port:00000000 irq:0

The Startup Screen Shows Wrong IRQs for the Serial Ports

For non-PnP ports, Linux does not do any IRQ detection on startup.
The serial module only does serial device detection.
Even Linux boot messages show serial port's IRQ setting on the screen, you may need to use setserial to tell Linux the IRQ you are using.

For a serial port to work properly it first must be given both an IO address and an IRQ.
The driver must of course know both the IO address and IRQ so that it can talk to the serial port chip.
This IO-IRQ pair must be set in both the hardware and told to the serial driver.
An easy way for a driver to do this is for the driver to ask the kernel to enable the device and then the kernel tells the driver what IO/IRQ it has used.
When Linux starts, an effort is made to detect and configure (low-level) the serial ports. Exactly what happens depends on your BIOS, hardware, Linux distribution, kernel version, etc.

If you're having problems with the serial ports, then you may need to do low-level configuring.
If the driver has the wrong IO address it will try to send data to a non-existing serial port --or even worse, to some other device.
If it has the wrong IRQ the driver will not get interrupt service requests from the serial port, resulting in a very slow or no response.

What the driver thinks is not necessarily how the hardware is actually set.
Ways to determine what the driver thinks:

  • Boot messages
  • The data shown by the BIOS messages (which you see at first before Linux is booted) are what is initially set in the hardware.
  • /proc
    • /proc/ioports
    • will show the IO addresses that the drivers are using.
    • /proc/interrupts
    • shows the IRQs that are used by drivers of currently running processes (that have devices open). It shows how many interrupts have actually be issued.
    • /proc/tty/driver/serial
    • shows much of the above, plus the number of bytes that have been received and sent (even if the device is not now open).
  • setserial
  • ACPI table: Serial Port Console Redirection Table (SPCR)
  • ACPI BIOS adds a node to ACPI table about the serial port.
    Microsoft Serial Port Console Redirection table.
    This table is used to indicate whether a serial port or a non-legacy UART interface is available for use.
    On a system where the BIOS or system firmware uses the serial port for console input/output, this table should be used to convey information about the settings.
    This table must be located in system memory with other ACPI tables, and it must be referenced in the ACPI RSDT table.
    This table contains pointers to all the other System Description Tables.
    
    $ sudo apt install acpica-tools
    $ sudo acpidump > acpi.log
    $ acpixtract acpi.log
    $ iasl -d *.dat 
    $ grep COM *
    acpi.log:   13300: 46 0A 04 43 4F 4D 30 8A 52 42 55 46 0A 10 43 4F  F..COM0.RBUF..CO
    acpi.log:   13320: 42 52 47 0C 00 00 6E 00 00 43 4F 4D 30 70 72 53  BRG...n..COM0prS
    acpi.log:   13330: 42 52 47 0C 00 00 6D 00 00 43 4F 4D 31 70 53 47  BRG...m..COM1pSG
    acpi.log:   33240: 54 50 4C 54 0A 06 70 0D 57 43 4F 4D 35 30 38 45  TPLT..p.WCOM508E
    acpi.log:   339A0: 50 4C 54 0A 06 70 0D 57 43 4F 4D 35 30 38 45 00  PLT..p.WCOM508E.
    acpi.log:   34100: 4C 54 0A 06 70 0D 57 43 4F 4D 35 30 38 45 00 5F  LT..p.WCOM508E._
    Binary file dsdt.dat matches
    dsdt.dsl:                    Name (_HID, EisaId ("PNP0501") /* 16550A-compatible COM Serial Port */)  // _HID: Hardware ID
    dsdt.dsl:                    Name (_HID, EisaId ("PNP0501") /* 16550A-compatible COM Serial Port */)  // _HID: Hardware ID
    dsdt.dsl:                CreateDWordField (RBUF, \_SB.PCI0.GPI0._CRS._Y2C._BAS, COM0)  // _BAS: Base Address
    dsdt.dsl:                CreateDWordField (RBUF, \_SB.PCI0.GPI0._CRS._Y2D._BAS, COM1)  // _BAS: Base Address
    dsdt.dsl:                COM0 = (SBRG + 0x006E0000)
    dsdt.dsl:                COM1 = (SBRG + 0x006D0000)
    dsdt.dsl:                    _HID = "WCOM508E"
    dsdt.dsl:                    _HID = "WCOM508E"
    dsdt.dsl:                    _HID = "WCOM508E"
    dsdt.dsl:                    _HID = "WCOM508E"
            
            

Cannot share interrupt used for console's serial port

When used for a console the serial port cannot share an interrupt with another device.
The IBM PC devices are usually installed as shown:

Device	   Interrupt	Port
/dev/ttyS0	  4	        0x3f8
/dev/ttyS1	  3	        0x2f8
/dev/ttyS2	  4	        0x3e8
/dev/ttyS3	  3	        0x2e8
If you use the serial port /dev/ttyS0 for the console then you should avoid sharing interrupt 4 by not installing a serial port /dev/ttyS2 in your PC.
If /dev/ttyS2 cannot be physically removed then disable it using the setserial command,

# Disable /dev/ttyS2 so interrupt 4 is not shared,
# then /dev/ttyS0 can be used as a serial console.
setserial /dev/ttyS2 uart none port 0x0 irq 0

Syntax for kernel serial parameters

It is possible to specify multiple devices for console output.
You can define a new kernel command line option to select which device(s) to use for console output.

console=device,options
  • device
    • tty0
    • for the foreground virtual console
    • ttyX
    • for any other virtual console
    • ttySx
    • for a serial port
    • lp0
    • for the first parallel port
    • ttyUSB0
    • for the first USB serial device
  • option
  • depend on the driver.
    For the serial port this defines the baudrate/parity/bits/flow control of the port, in the format
    
      	BBBBPNF
        
    where
    • BBBB
    • is the speed, the maximum baudrate is 115200.
    • P
    • is parity (n/o/e),
    • N
    • is number of bits,
    • F
    • is flow control ('r' for RTS).
    Default is 9600n8.

Using Setserial

setserial is a program used for the user to communicate with the serial device driver.
setserial deals with the lower-level configuring of the serial port, it can't set or configure the serial port hardware: It can't set the IRQ or port addresses into the hardware.
In olden days, when the IRQ and port address was set by jumpers on the serial card, one would use setserial to tell the driver how these jumpers were set.
Thus the name setserial is somewhat of a misnomer since it doesn't set the I/O address nor IRQ in the hardware, it just "sets" them in the driver software.

Testing a COM Port

To test if the computer COM port is functioning correctly, you can do a simple loopback test.
A loopback test can verify the operation of serial communication by sending and receiving data from the same serial port.
Loopback tests can be used for RS-232, RS-422, and RS-485 serial communication.

  • RS-232
  • On an RS-232 port, connect the transmit (TXD) signal to the receive (RXD) signal.
    Refer to the pins below based on your connector type. The connections are indicated in grey.
    • DB-9 (female)
    • Pin 3 to 2 (TXD to RXD)
    • DB-25 (female)
    • Pin 2 to 3 (TXD to RXD)
    • RJ-50
    • It is not recommended to use the RJ-50 connector by itself to perform a loopback test due to the small separation between pins. If you use a RJ-50 to DB-9 serial cable (Part Number 182845-XX), a loopback test can be performed using the pins for a DB-9 connector.
  • RS-422/485 (4-Wire)
  • RS-422/485 (2-Wire Auto)
While pins 2 and 3 are shorted, use the computer keyboard to type some characters (letters and numbers). These characters should appear in the terminal window.

Enable Linux Serial Console login

when you have no other way to access a device, configure one of the COM ports of the Server as a Serial listening port then connect the server through it.

How to setup simple terminal access (with a few tweaks) via RS232C serial ports on Ubuntu ?

  • make sure that your operating system recognizes serial ports in your hardware
  • 
    $ dmesg | grep ttyS
    [    0.000000] Command line: BOOT_IMAGE=/boot/vmlinuz-5.4.0-71-generic root=UUID=0fcfd15f-994b-4e46-84ac-c6e371211a5a ro console=tty1 console=ttyS0
    [    0.034075] Kernel command line: BOOT_IMAGE=/boot/vmlinuz-5.4.0-71-generic root=UUID=0fcfd15f-994b-4e46-84ac-c6e371211a5a ro console=tty1 console=ttyS0
    [   16.533060] printk: console [ttyS0] enabled
    [   34.053473] 00:01: ttyS0 at I/O 0x3f8 (irq = 4, base_baud = 115200) is a 16550A
    [   34.161693] 00:02: ttyS1 at I/O 0x2f8 (irq = 3, base_baud = 115200) is a 16550A
    [   65.992372] dw-apb-uart.1: ttyS4 at MMIO 0x4017001000 (irq = 16, base_baud = 6250000) is a 16550A    
        
  • connect serial cable between systems
  • If one system is DCE ( typically a modem, DSU/CSU ), a generic RS-232 cable can be used between the DTE and DCE.
    The Receive Data signal is an input to DTE, but an output from DCE.
    If both systems are DTE( a dumb terminal or the serial port on a computer/workstation), you need a null modem cable.
  • Enable Serial port at boot
    • make sure that kernel command line includes the correct console parameters
    • 
      $ cat /proc/cmdline
      BOOT_IMAGE=/boot/vmlinuz-5.4.0-71-generic root=UUID=0fcfd15f-994b-4e46-84ac-c6e371211a5a ro console=tty1 console=ttyS0     
              
    • Make sure the baud rate setting on the target COM port
    • 
      $ sudo stty -F /dev/ttyS0
      speed 9600 baud; line = 0;
      min = 1; time = 0;
      -brkint -icrnl -imaxbel iutf8
      -isig -icanon -iexten -echo -echoe -echok -echoctl -echoke
              
      You can set the serial port baud rate you want:
      
      $ sudo stty -F /dev/ttyS0 speed 9600
              
    • make sure that getty is enabled for desired serial port
    • A getty is is a program that opens a tty port, prompts for a login name, and runs the /bin/login command.
      • If the getty service are not enabled for the required serial ports
      • 
        $ sudo systemctl status getty@ttyS0
        * getty@ttyS0.service - Getty on ttyS0
             Loaded: loaded (/lib/systemd/system/getty@.service; disabled; vendor preset: enabled)
             Active: inactive (dead)
               Docs: man:agetty(8)
                     man:systemd-getty-generator(8)
                     http://0pointer.de/blog/projects/serial-console.html
        $ sudo systemctl status getty@ttyS1
        * getty@ttyS1.service - Getty on ttyS1
             Loaded: loaded (/lib/systemd/system/getty@.service; disabled; vendor preset: enabled)
             Active: inactive (dead)
               Docs: man:agetty(8)
                     man:systemd-getty-generator(8)
                     http://0pointer.de/blog/projects/serial-console.html
                	
        To enable it:
        
        $ sudo systemctl enable getty@ttyS0
        Created symlink /etc/systemd/system/getty.target.wants/getty@ttyS0.service -> /lib/systemd/system/getty@.service.
        $ sudo systemctl enable getty@ttyS1
        Created symlink /etc/systemd/system/getty.target.wants/getty@ttyS0.service -> /lib/systemd/system/getty@.service.
                	
      • If the serial port is connected after getty service is started
      • 
        $ sudo systemctl status getty@ttyS0
        ...
        Apr 14 04:45:32 ubuntu systemd[1]: getty@ttyS0.service: Start request repeated too quickly.
        Apr 14 04:45:32 ubuntu systemd[1]: getty@ttyS0.service: Failed with result 'start-limit-hit'.
        Apr 14 04:45:32 ubuntu systemd[1]: Failed to start Getty on ttyS0.
        
        Re-start the service after the serial port is connected:
           
        $ sudo systemctl restart getty@ttyS0
        $ sudo systemctl status getty@ttyS0
        ...
        Apr 14 05:36:41 ubuntu systemd[1]: Started Getty on ttyS0.
        
      If the getty service are not enabled for the required serial ports,
  • Tuning the login
    • console login prompt
    • /etc/issue:
      
      Ubuntu 20.04.2 LTS \n \l        
              
      It uses escape sequences defined in the agetty manpage to add some useful information, such as the serial port number, line speed, and how many users are currently logged on.

The difference between a serial-getty@.service and a getty@.service?

It's enough to look at the difference between files getty@.service and serial-getty@.service, which you can find at /lib/systemd/system on your system.

The main one is the ExecStart= command invoked by each unit:

  • getty@.service invokes this command
  • 
    ExecStart=-/sbin/agetty -o '-p -- \\u' --noclear %I $TERM
    
  • serial-getty@.service invokes this command
  • 
    ExecStart=-/sbin/agetty -o '-p -- \\u' --keep-baud 115200,38400,9600 %I $TERM
    
    The command used in serial-getty@.service passes agetty the --keep-baud argument, in order to configure the serial port speed.
systemd takes its console configuration from the kernel, typically from the console= argument in the kernel command line (this is implemented by systemd-getty-generator, so see its documentation for more details.)

Gettys on Serial Consoles (and Elsewhere)

The Framebuffer Console

How to increase TTY console resolution

The default TTY console resolution is normally 800x600.
To increase TTY console resolution, it is necessary to change the configuration of the relevant GRUB boot loader settings within the /etc/default/grub.
  • Reboot your system into GRUB menu. Press c key to enter GRUB's command line.
  • Display various stuff how grub recognizes your display.
  • 
    grub> set pager=1
    grub> insmod videoinfo
    grub> videoinfo
    	
  • Reboot your system or enter the system, set the resolution in grub
  • /etc/default/grub:
    
    # The resolution used on graphical terminal
    # note that you can use only modes which your graphic card supports via VBE
    # you can see them in real GRUB with the command `vbeinfo'
    #GRUB_GFXMODE=640x480
    
    	

GNU GRUB Manual 2.04: GRUB environment variables

gfxmode

If this variable is set, it sets the resolution used on the ‘gfxterm’ graphical terminal. Note that you can only use modes which your graphics card supports via VESA BIOS Extensions (VBE), so for example native LCD panel resolutions may not be available. The default is ‘auto’, which selects a platform-specific default that should look reasonable. Supported modes can be listed by ‘videoinfo’ command in GRUB.

The resolution may be specified as a sequence of one or more modes, separated by commas (‘,’) or semicolons (‘;’); each will be tried in turn until one is found. Each mode should be either ‘auto’, ‘widthxheight’, or ‘widthxheightxdepth’.

gfxpayload

If this variable is set, it controls the video mode in which the Linux kernel starts up, replacing the ‘vga=’ boot option (see linux). It may be set to ‘text’ to force the Linux kernel to boot in normal text mode, ‘keep’ to preserve the graphics mode set using ‘gfxmode’, or any of the permitted values for ‘gfxmode’ to set a particular graphics mode (see gfxmode).

Depending on your kernel, your distribution, your graphics card, and the phase of the moon, note that using this option may cause GNU/Linux to suffer from various display problems, particularly during the early part of the boot sequence. If you have problems, set this variable to ‘text’ and GRUB will tell Linux to boot in normal text mode.

The default is platform-specific. On platforms with a native text mode (such as PC BIOS platforms), the default is ‘text’. Otherwise the default may be ‘auto’ or a specific video mode.

This variable is often set by ‘GRUB_GFXPAYLOAD_LINUX

gfxterm_font

If this variable is set, it names a font to use for text on the ‘gfxterm’ graphical terminal. Otherwise, ‘gfxterm’ may use any available font.

留言

熱門文章