Add com(4) terminal and console support.
Implement com(4) interrupt support for receiving data. Add termios terminal support to the com(4) driver with tcsetattr(2) support for configuring the hardware serial settings. Add kernel(7) --console option which can be used to initialize the com(4) driver early for the kernel console with the specified serial settings and window size. Add kernel(7) --text option for overriding the TERM environment variable. Add kernel(7) --disable-logo option for disabling writing the the operating system logo to the console on boot. Add advanced bootloader option to select booting to a serial console on com1. Add bootloader variables and hooks to customize this behavior. Add tix-iso-bootconfig(8) --console, --grub-serial, --serial, and --serial-console options as a convenince to opt into booting to the serial console by default. Add tix-iso-bootconfig(8) --kernel-options option for forwarding additional options to the kernel. The logterminal driver used for tty1 currently assumes that it controls the kernel log, which is not true when com(4) is used as the console, therefore the tty1 driver is currently disabled if a serial console is selected, as a temporary workaround.
This commit is contained in:
parent
47c55f31c2
commit
e57c84c5e6
18 changed files with 896 additions and 147 deletions
build-aux
kernel
share/man
tix
|
@ -153,6 +153,16 @@ echo "require sshd optional" > boot/grub/init/local-sshd
|
|||
|
||||
exec > boot/grub/grub.cfg
|
||||
|
||||
cat << EOF
|
||||
function hook_initialize_terminal {
|
||||
insmod all_video
|
||||
if loadfont unicode; then
|
||||
insmod gfxterm
|
||||
terminal_output gfxterm
|
||||
fi
|
||||
}
|
||||
EOF
|
||||
|
||||
for hook in \
|
||||
advanced_menu_post \
|
||||
advanced_menu_pre \
|
||||
|
@ -198,12 +208,6 @@ find . | grep -Eq '\.gz$' && echo "insmod gzio"
|
|||
find . | grep -Eq '\.xz$' && echo "insmod xzio"
|
||||
|
||||
cat << EOF
|
||||
insmod all_video
|
||||
if loadfont unicode; then
|
||||
insmod gfxterm
|
||||
terminal_output gfxterm
|
||||
fi
|
||||
|
||||
set version="$version"
|
||||
set machine="$machine"
|
||||
set base_menu_title="Sortix \$version for \$machine"
|
||||
|
@ -213,6 +217,7 @@ set title_sysinstall='new installation'
|
|||
set title_sysupgrade='upgrade existing installation'
|
||||
set timeout=10
|
||||
set default="0"
|
||||
set console=
|
||||
if [ -e /boot/random.seed ]; then
|
||||
no_random_seed=
|
||||
else
|
||||
|
@ -224,6 +229,8 @@ set enable_dhclient=true
|
|||
set enable_gui=true
|
||||
set enable_ntpd=false
|
||||
set enable_sshd=false
|
||||
set kernel_options=
|
||||
set serial_console=--console=com1
|
||||
|
||||
export version
|
||||
export machine
|
||||
|
@ -234,6 +241,7 @@ export title_sysinstall
|
|||
export title_sysupgrade
|
||||
export timeout
|
||||
export default
|
||||
export console
|
||||
export no_random_seed
|
||||
export enable_src
|
||||
export enable_network_drivers
|
||||
|
@ -241,6 +249,8 @@ export enable_dhclient
|
|||
export enable_gui
|
||||
export enable_ntpd
|
||||
export enable_sshd
|
||||
export kernel_options
|
||||
export serial_console
|
||||
EOF
|
||||
|
||||
if [ -n "$ports" ]; then
|
||||
|
@ -327,7 +337,7 @@ esac
|
|||
cat << EOF
|
||||
hook_kernel_pre
|
||||
echo -n "Loading /$kernel ($(human_size $kernel)) ... "
|
||||
multiboot /$kernel --firmware=\$grub_platform \$no_random_seed \$enable_network_drivers "\$@"
|
||||
multiboot /$kernel \$console --firmware=\$grub_platform \$no_random_seed \$enable_network_drivers \$kernel_options "\$@"
|
||||
echo done
|
||||
hook_kernel_post
|
||||
if ! \$enable_dhclient; then
|
||||
|
@ -418,6 +428,8 @@ if [ -e /boot/grub/hooks.cfg ]; then
|
|||
. /boot/grub/hooks.cfg
|
||||
fi
|
||||
|
||||
hook_initialize_terminal
|
||||
|
||||
. /boot/grub/main.cfg
|
||||
EOF
|
||||
|
||||
|
@ -484,6 +496,19 @@ else
|
|||
}
|
||||
fi
|
||||
|
||||
if [ "\$console" = "\$serial_console" ]; then
|
||||
menuentry "Disable serial console" {
|
||||
console=
|
||||
configfile /boot/grub/advanced.cfg
|
||||
}
|
||||
else
|
||||
menuentry "Enable serial console" {
|
||||
console="$serial_console"
|
||||
enable_gui=false
|
||||
configfile /boot/grub/advanced.cfg
|
||||
}
|
||||
fi
|
||||
|
||||
if "\$enable_src"; then
|
||||
menuentry "Disable loading source code" {
|
||||
enable_src=false
|
||||
|
|
566
kernel/com.cpp
566
kernel/com.cpp
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2011, 2012, 2014, 2015, 2016 Jonas 'Sortie' Termansen.
|
||||
* Copyright (c) 2011-2012, 2014-2016, 2023-2024 Jonas 'Sortie' Termansen.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
|
@ -17,10 +17,16 @@
|
|||
* Handles communication to COM serial ports.
|
||||
*/
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <termios.h>
|
||||
|
||||
#include <sortix/fcntl.h>
|
||||
#include <sortix/stat.h>
|
||||
|
@ -38,6 +44,7 @@
|
|||
#include <sortix/kernel/thread.h>
|
||||
|
||||
#include "com.h"
|
||||
#include "tty.h"
|
||||
|
||||
extern "C" unsigned char nullpage[4096];
|
||||
|
||||
|
@ -90,6 +97,10 @@ static const uint8_t IER_LOW_POWER = 1 << 5;
|
|||
|
||||
static const unsigned BASE_BAUD = 1843200 / 16;
|
||||
|
||||
static const speed_t DEFAULT_SPEED = B38400;
|
||||
static const size_t DEFAULT_COLUMNS = 80;
|
||||
static const size_t DEFAULT_ROWS = 25;
|
||||
|
||||
static const unsigned int UART_8250 = 1;
|
||||
static const unsigned int UART_16450 = 2;
|
||||
static const unsigned int UART_16550 = 3;
|
||||
|
@ -136,17 +147,78 @@ static inline bool CanWriteByte(uint16_t port)
|
|||
return inport8(port + LSR) & LSR_THRE;
|
||||
}
|
||||
|
||||
class DevCOMPort : public AbstractInode
|
||||
static bool IsValidSpeed(speed_t speed)
|
||||
{
|
||||
return speed && speed <= 115200 && !(115200 % speed);
|
||||
}
|
||||
|
||||
static void ConfigurePort(uint16_t port, const struct termios* tio,
|
||||
bool enable_interrupts)
|
||||
{
|
||||
uint16_t divisor = 115200 / tio->c_ispeed;
|
||||
outport8(port + FCR, 0);
|
||||
outport8(port + LCR, LCR_DLAB);
|
||||
outport8(port + DLL, divisor & 0xFF);
|
||||
outport8(port + DLM, divisor >> 8);
|
||||
uint8_t lcr = 0;
|
||||
if ( (tio->c_cflag & CSIZE) == CS5 )
|
||||
lcr |= LCR_WLEN5;
|
||||
else if ( (tio->c_cflag & CSIZE) == CS6 )
|
||||
lcr |= LCR_WLEN6;
|
||||
else if ( (tio->c_cflag & CSIZE) == CS7 )
|
||||
lcr |= LCR_WLEN7;
|
||||
else if ( (tio->c_cflag & CSIZE) == CS8 )
|
||||
lcr |= LCR_WLEN8;
|
||||
if ( tio->c_cflag & CSTOPB )
|
||||
lcr |= LCR_STOP;
|
||||
if ( tio->c_cflag & PARENB )
|
||||
lcr |= LCR_PARITY;
|
||||
if ( tio->c_cflag & PARENB )
|
||||
{
|
||||
lcr |= LCR_PARITY;
|
||||
if ( !(tio->c_cflag & PARODD) )
|
||||
lcr |= LCR_EPAR;
|
||||
}
|
||||
outport8(port + LCR, lcr);
|
||||
uint8_t mcr = 0x2 /* RTS */;
|
||||
if ( tio->c_cflag & CREAD )
|
||||
mcr |= 0x1 /* DTR */;
|
||||
outport8(port + MCR, mcr);
|
||||
uint8_t ier = enable_interrupts ? 1 : 0;
|
||||
outport8(port + IER, ier);
|
||||
}
|
||||
|
||||
class DevCOMPort : public TTY
|
||||
{
|
||||
public:
|
||||
DevCOMPort(dev_t dev, uid_t owner, gid_t group, mode_t mode, uint16_t port);
|
||||
DevCOMPort(dev_t dev, uid_t owner, gid_t group, mode_t mode, uint16_t port,
|
||||
const char* name);
|
||||
virtual ~DevCOMPort();
|
||||
virtual int ioctl(ioctx_t* ctx, int cmd, uintptr_t arg);
|
||||
virtual int sync(ioctx_t* ctx);
|
||||
virtual ssize_t read(ioctx_t* ctx, uint8_t* buf, size_t count);
|
||||
virtual ssize_t write(ioctx_t* ctx, const uint8_t* buf, size_t count);
|
||||
virtual void tty_output(const unsigned char* buffer, size_t length);
|
||||
virtual bool Reconfigure(const struct termios* new_tio);
|
||||
|
||||
public:
|
||||
void ImportConsole(const struct termios* console_tio,
|
||||
const struct winsize* console_size);
|
||||
bool Initialize(int interrupt);
|
||||
bool EmergencyIsImpaired();
|
||||
bool EmergencyRecoup();
|
||||
void EmergencyReset();
|
||||
|
||||
private:
|
||||
static void InterruptHandler(struct interrupt_context*, void*);
|
||||
static void InterruptWorkHandler(void* context);
|
||||
void OnInterrupt();
|
||||
void InterruptWork();
|
||||
|
||||
private:
|
||||
kthread_mutex_t port_lock;
|
||||
kthread_mutex_t reconfigure_lock;
|
||||
struct interrupt_handler irq_registration;
|
||||
struct interrupt_work interrupt_work;
|
||||
struct winsize ws;
|
||||
uint16_t port;
|
||||
uint8_t pending_input_byte;
|
||||
bool has_pending_input_byte;
|
||||
|
@ -154,24 +226,98 @@ private:
|
|||
};
|
||||
|
||||
DevCOMPort::DevCOMPort(dev_t dev, uid_t owner, gid_t group, mode_t mode,
|
||||
uint16_t port)
|
||||
uint16_t port, const char* name) : TTY(dev, 0, mode,
|
||||
owner, group, name)
|
||||
{
|
||||
inode_type = INODE_TYPE_STREAM;
|
||||
this->port = port;
|
||||
this->port_lock = KTHREAD_MUTEX_INITIALIZER;
|
||||
this->stat_uid = owner;
|
||||
this->stat_gid = group;
|
||||
this->type = S_IFCHR;
|
||||
this->stat_mode = (mode & S_SETABLE) | this->type;
|
||||
this->dev = dev;
|
||||
this->ino = (ino_t) this;
|
||||
this->reconfigure_lock = KTHREAD_MUTEX_INITIALIZER;
|
||||
this->has_pending_input_byte = false;
|
||||
tio.c_ispeed = DEFAULT_SPEED;
|
||||
tio.c_ospeed = DEFAULT_SPEED;
|
||||
memset(&ws, 0, sizeof(ws));
|
||||
ws.ws_col = DEFAULT_COLUMNS;
|
||||
ws.ws_row = DEFAULT_ROWS;
|
||||
interrupt_work.handler = InterruptWorkHandler;
|
||||
interrupt_work.context = this;
|
||||
}
|
||||
|
||||
DevCOMPort::~DevCOMPort()
|
||||
{
|
||||
}
|
||||
|
||||
void DevCOMPort::ImportConsole(const struct termios* console_tio,
|
||||
const struct winsize* console_size)
|
||||
{
|
||||
tio.c_cflag = console_tio->c_cflag;
|
||||
tio.c_ispeed = console_tio->c_ispeed;
|
||||
tio.c_ospeed = console_tio->c_ospeed;
|
||||
ws = *console_size;
|
||||
}
|
||||
|
||||
bool DevCOMPort::Initialize(int interrupt)
|
||||
{
|
||||
|
||||
ConfigurePort(port, &tio, true);
|
||||
irq_registration.handler = DevCOMPort::InterruptHandler;
|
||||
irq_registration.context = this;
|
||||
Interrupt::RegisterHandler(interrupt, &irq_registration);
|
||||
return true;
|
||||
}
|
||||
|
||||
void DevCOMPort::InterruptHandler(struct interrupt_context*, void* user)
|
||||
{
|
||||
((DevCOMPort*) user)->OnInterrupt();
|
||||
}
|
||||
|
||||
void DevCOMPort::OnInterrupt()
|
||||
{
|
||||
if ( !IsLineReady(port) )
|
||||
return;
|
||||
Interrupt::ScheduleWork(&interrupt_work);
|
||||
}
|
||||
|
||||
void DevCOMPort::InterruptWorkHandler(void* context)
|
||||
{
|
||||
((DevCOMPort*) context)->InterruptWork();
|
||||
}
|
||||
|
||||
void DevCOMPort::InterruptWork()
|
||||
{
|
||||
ScopedLock lock1(&termlock);
|
||||
ScopedLock lock2(&port_lock);
|
||||
while ( IsLineReady(port) )
|
||||
{
|
||||
unsigned char byte = inport8(port + RXR);
|
||||
if ( tio.c_cflag & CREAD )
|
||||
ProcessByte(byte);
|
||||
}
|
||||
}
|
||||
|
||||
int DevCOMPort::ioctl(ioctx_t* ctx, int cmd, uintptr_t arg)
|
||||
{
|
||||
ScopedLock lock(&termlock);
|
||||
if ( hungup )
|
||||
return errno = EIO, -1;
|
||||
if ( cmd == TIOCGWINSZ )
|
||||
{
|
||||
struct winsize* user_ws = (struct winsize*) arg;
|
||||
if ( !ctx->copy_to_dest(user_ws, &ws, sizeof(ws)) )
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
else if ( cmd == TIOCSWINSZ )
|
||||
{
|
||||
const struct winsize* user_ws = (const struct winsize*) arg;
|
||||
if ( !ctx->copy_from_src(&ws, user_ws, sizeof(ws)) )
|
||||
return -1;
|
||||
winch();
|
||||
return 0;
|
||||
}
|
||||
lock.Reset();
|
||||
return TTY::ioctl(ctx, cmd, arg);
|
||||
}
|
||||
|
||||
int DevCOMPort::sync(ioctx_t* /*ctx*/)
|
||||
{
|
||||
ScopedLock lock(&port_lock);
|
||||
|
@ -179,57 +325,9 @@ int DevCOMPort::sync(ioctx_t* /*ctx*/)
|
|||
return 0;
|
||||
}
|
||||
|
||||
ssize_t DevCOMPort::read(ioctx_t* ctx, uint8_t* dest, size_t count)
|
||||
void DevCOMPort::tty_output(const unsigned char* buffer, size_t length)
|
||||
{
|
||||
ScopedLock lock(&port_lock);
|
||||
|
||||
for ( size_t i = 0; i < count; i++ )
|
||||
{
|
||||
unsigned long attempt = 0;
|
||||
while ( !has_pending_input_byte && !IsLineReady(port) )
|
||||
{
|
||||
attempt++;
|
||||
if ( attempt <= 10 )
|
||||
continue;
|
||||
if ( attempt <= 15 && !(ctx->dflags & O_NONBLOCK) )
|
||||
{
|
||||
kthread_mutex_unlock(&port_lock);
|
||||
kthread_yield();
|
||||
kthread_mutex_lock(&port_lock);
|
||||
continue;
|
||||
}
|
||||
if ( i )
|
||||
return (ssize_t) i;
|
||||
if ( ctx->dflags & O_NONBLOCK )
|
||||
return errno = EWOULDBLOCK, -1;
|
||||
if ( Signal::IsPending() )
|
||||
return errno = EINTR, -1;
|
||||
kthread_mutex_unlock(&port_lock);
|
||||
kthread_yield();
|
||||
kthread_mutex_lock(&port_lock);
|
||||
}
|
||||
|
||||
uint8_t value = has_pending_input_byte ?
|
||||
pending_input_byte :
|
||||
inport8(port + RXR);
|
||||
if ( !ctx->copy_to_dest(dest + i, &value, sizeof(value)) )
|
||||
{
|
||||
has_pending_input_byte = true;
|
||||
pending_input_byte = value;
|
||||
return i ? (ssize_t) i : -1;
|
||||
}
|
||||
|
||||
has_pending_input_byte = false;
|
||||
}
|
||||
|
||||
return (ssize_t) count;
|
||||
}
|
||||
|
||||
ssize_t DevCOMPort::write(ioctx_t* ctx, const uint8_t* src, size_t count)
|
||||
{
|
||||
ScopedLock lock(&port_lock);
|
||||
|
||||
for ( size_t i = 0; i < count; i++ )
|
||||
for ( size_t i = 0; i < length; i++ )
|
||||
{
|
||||
unsigned long attempt = 0;
|
||||
while ( !CanWriteByte(port) )
|
||||
|
@ -237,7 +335,7 @@ ssize_t DevCOMPort::write(ioctx_t* ctx, const uint8_t* src, size_t count)
|
|||
attempt++;
|
||||
if ( attempt <= 10 )
|
||||
continue;
|
||||
if ( attempt <= 15 && !(ctx->dflags & O_NONBLOCK) )
|
||||
if ( attempt <= 15 )
|
||||
{
|
||||
kthread_mutex_unlock(&port_lock);
|
||||
kthread_yield();
|
||||
|
@ -245,24 +343,299 @@ ssize_t DevCOMPort::write(ioctx_t* ctx, const uint8_t* src, size_t count)
|
|||
continue;
|
||||
}
|
||||
if ( i )
|
||||
return (ssize_t) i;
|
||||
if ( ctx->dflags & O_NONBLOCK )
|
||||
return errno = EWOULDBLOCK, -1;
|
||||
return;
|
||||
// TODO: This is problematic.
|
||||
if ( Signal::IsPending() )
|
||||
return errno = EINTR, -1;
|
||||
{
|
||||
errno = EINTR;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t value;
|
||||
if ( !ctx->copy_from_src(&value, src + i, sizeof(value)) )
|
||||
return i ? (ssize_t) i : -1;
|
||||
outport8(port + TXR, value);
|
||||
outport8(port + TXR, buffer[i]);
|
||||
}
|
||||
|
||||
return (ssize_t) count;
|
||||
}
|
||||
|
||||
bool DevCOMPort::Reconfigure(const struct termios* new_tio) // termlock held
|
||||
{
|
||||
if ( !IsValidSpeed(new_tio->c_ispeed) || !IsValidSpeed(new_tio->c_ospeed) )
|
||||
return errno = EINVAL, false;
|
||||
if ( new_tio->c_ispeed != new_tio->c_ospeed )
|
||||
return errno = EINVAL, false;
|
||||
if ( tio.c_ispeed != new_tio->c_ispeed ||
|
||||
tio.c_ospeed != new_tio->c_ospeed ||
|
||||
tio.c_cflag != new_tio->c_cflag )
|
||||
{
|
||||
// Detect if a panic happens midway.
|
||||
ScopedLock lock(&reconfigure_lock);
|
||||
ConfigurePort(port, new_tio, true);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DevCOMPort::EmergencyIsImpaired()
|
||||
{
|
||||
if ( !kthread_mutex_trylock(&termlock) )
|
||||
return true;
|
||||
kthread_mutex_unlock(&termlock);
|
||||
if ( !kthread_mutex_trylock(&port_lock) )
|
||||
return true;
|
||||
kthread_mutex_unlock(&port_lock);
|
||||
if ( !kthread_mutex_trylock(&reconfigure_lock) )
|
||||
return true;
|
||||
kthread_mutex_unlock(&reconfigure_lock);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DevCOMPort::EmergencyRecoup()
|
||||
{
|
||||
kthread_mutex_trylock(&termlock);
|
||||
kthread_mutex_unlock(&termlock);
|
||||
kthread_mutex_trylock(&port_lock);
|
||||
kthread_mutex_unlock(&port_lock);
|
||||
kthread_mutex_trylock(&reconfigure_lock);
|
||||
kthread_mutex_unlock(&reconfigure_lock);
|
||||
if ( !kthread_mutex_trylock(&reconfigure_lock) )
|
||||
return false;
|
||||
kthread_mutex_unlock(&reconfigure_lock);
|
||||
return true;
|
||||
}
|
||||
|
||||
void DevCOMPort::EmergencyReset()
|
||||
{
|
||||
kthread_mutex_trylock(&termlock);
|
||||
kthread_mutex_unlock(&termlock);
|
||||
kthread_mutex_trylock(&port_lock);
|
||||
kthread_mutex_unlock(&port_lock);
|
||||
kthread_mutex_trylock(&reconfigure_lock);
|
||||
kthread_mutex_unlock(&reconfigure_lock);
|
||||
ConfigurePort(port, &tio, false);
|
||||
}
|
||||
|
||||
static size_t console_device;
|
||||
static struct termios console_tio;
|
||||
static uint16_t console_port;
|
||||
static kthread_mutex_t console_lock = KTHREAD_MUTEX_INITIALIZER;
|
||||
static bool console_imported;
|
||||
static struct winsize console_size;
|
||||
|
||||
static Ref<DevCOMPort> com_devices[1 + NUM_COM_PORTS];
|
||||
|
||||
static void ConsoleWriteByte(unsigned char byte)
|
||||
{
|
||||
size_t attempt = 0;
|
||||
while ( !CanWriteByte(console_port) )
|
||||
{
|
||||
attempt++;
|
||||
if ( attempt <= 10 )
|
||||
continue;
|
||||
if ( attempt <= 15 )
|
||||
{
|
||||
kthread_mutex_unlock(&console_lock);
|
||||
kthread_yield();
|
||||
kthread_mutex_lock(&console_lock);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
outport8(console_port + TXR, byte);
|
||||
}
|
||||
|
||||
static size_t ConsoleWrite(void* /*ctx*/, const char* buf, size_t len)
|
||||
{
|
||||
ScopedLock lock(&console_lock);
|
||||
if ( console_imported )
|
||||
{
|
||||
ioctx_t ctx; SetupKernelIOCtx(&ctx);
|
||||
Ref<DevCOMPort> com = com_devices[console_device];
|
||||
const uint8_t* buffer = (const uint8_t*) buf;
|
||||
size_t done = 0;
|
||||
while ( done < len )
|
||||
{
|
||||
ssize_t amount = com->write(&ctx, buffer + done, len - done);
|
||||
if ( amount < 0 )
|
||||
break; // TODO: Block all signals.
|
||||
done += amount;
|
||||
}
|
||||
return done;
|
||||
}
|
||||
for ( size_t i = 0; i < len; i++ )
|
||||
{
|
||||
if ( buf[i] == '\n' )
|
||||
ConsoleWriteByte('\r');
|
||||
ConsoleWriteByte(buf[i]);
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
static size_t ConsoleWidth(void* /*ctx*/)
|
||||
{
|
||||
if ( console_imported )
|
||||
{
|
||||
ioctx_t ctx; SetupKernelIOCtx(&ctx);
|
||||
Ref<DevCOMPort> com = com_devices[console_device];
|
||||
struct winsize ws;
|
||||
com->ioctl(&ctx, TIOCGWINSZ, (uintptr_t) &ws);
|
||||
return ws.ws_col;
|
||||
}
|
||||
return console_size.ws_col;
|
||||
}
|
||||
|
||||
static size_t ConsoleHeight(void* /*ctx*/)
|
||||
{
|
||||
if ( console_imported )
|
||||
{
|
||||
ioctx_t ctx; SetupKernelIOCtx(&ctx);
|
||||
Ref<DevCOMPort> com = com_devices[console_device];
|
||||
struct winsize ws;
|
||||
com->ioctl(&ctx, TIOCGWINSZ, (uintptr_t) &ws);
|
||||
return ws.ws_row;
|
||||
}
|
||||
return console_size.ws_row;
|
||||
}
|
||||
|
||||
static void ConsoleGetCursor(void* /*ctx*/, size_t* column, size_t* row)
|
||||
{
|
||||
// TODO: Conceptually this does not make sense.
|
||||
*column = 0;
|
||||
*row = 0;
|
||||
}
|
||||
|
||||
static bool ConsoleSync(void* /*ctx*/)
|
||||
{
|
||||
ScopedLock lock(&console_lock);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void ConsoleInvalidate(void* /*ctx*/)
|
||||
{
|
||||
ScopedLock lock(&console_lock);
|
||||
}
|
||||
|
||||
bool ConsoleEmergencyIsImpaired(void* /*ctx*/)
|
||||
{
|
||||
if ( !kthread_mutex_trylock(&console_lock) )
|
||||
return true;
|
||||
kthread_mutex_unlock(&console_lock);
|
||||
if ( console_imported )
|
||||
{
|
||||
Ref<DevCOMPort> com = com_devices[console_device];
|
||||
return com->EmergencyIsImpaired();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ConsoleEmergencyRecoup(void* /*ctx*/)
|
||||
{
|
||||
kthread_mutex_trylock(&console_lock);
|
||||
kthread_mutex_unlock(&console_lock);
|
||||
if ( console_imported )
|
||||
{
|
||||
Ref<DevCOMPort> com = com_devices[console_device];
|
||||
return com->EmergencyRecoup();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void ConsoleEmergencyReset(void* /*ctx*/)
|
||||
{
|
||||
kthread_mutex_trylock(&console_lock);
|
||||
kthread_mutex_unlock(&console_lock);
|
||||
if ( console_imported )
|
||||
{
|
||||
Ref<DevCOMPort> com = com_devices[console_device];
|
||||
com->EmergencyReset();
|
||||
}
|
||||
}
|
||||
|
||||
void InitializeConsole(const char* console)
|
||||
{
|
||||
assert(!strncmp(console, "com", 3));
|
||||
assert(isdigit((unsigned char) console[3]));
|
||||
char* end;
|
||||
unsigned long device = strtoul(console + 3, &end, 10);
|
||||
if ( device < 1 || NUM_COM_PORTS < device )
|
||||
PanicF("Invalid console: %s", console);
|
||||
console_device = device;
|
||||
struct termios tio;
|
||||
memset(&tio, 0, sizeof(tio));
|
||||
console_tio.c_ispeed = DEFAULT_SPEED;
|
||||
console_tio.c_cflag = CS8;
|
||||
memset(&console_size, 0, sizeof(console_size));
|
||||
console_size.ws_col = DEFAULT_COLUMNS;
|
||||
console_size.ws_row = DEFAULT_ROWS;
|
||||
if ( *end == ',' )
|
||||
{
|
||||
end++;
|
||||
if ( *end != ',' )
|
||||
{
|
||||
unsigned long value = strtoul(end, &end, 10);
|
||||
if ( !IsValidSpeed(value) )
|
||||
PanicF("Invalid console options: %s", console);
|
||||
console_tio.c_ispeed = value;
|
||||
console_tio.c_cflag = 0;
|
||||
if ( *end == 'o' )
|
||||
console_tio.c_cflag |= PARENB | PARODD;
|
||||
else if ( *end == 'e' )
|
||||
console_tio.c_cflag |= PARENB;
|
||||
else if ( *end != 'n' )
|
||||
PanicF("Invalid console options: %s", console);
|
||||
end++;
|
||||
if ( *end == '5' )
|
||||
console_tio.c_cflag |= CS5;
|
||||
else if ( *end == '6' )
|
||||
console_tio.c_cflag |= CS6;
|
||||
else if ( *end == '7' )
|
||||
console_tio.c_cflag |= CS7;
|
||||
else if ( *end == '8' )
|
||||
console_tio.c_cflag |= CS8;
|
||||
else
|
||||
PanicF("Invalid console options: %s", console);
|
||||
end++;
|
||||
}
|
||||
if ( *end == ',' )
|
||||
{
|
||||
end++;
|
||||
unsigned long width = strtoul(end, &end, 10);
|
||||
if ( !width || *end != 'x' )
|
||||
PanicF("Invalid console options: %s", console);
|
||||
end++;
|
||||
unsigned long height = strtoul(end, &end, 10);
|
||||
if ( !height || *end )
|
||||
PanicF("Invalid console options: %s", console);
|
||||
console_size.ws_col = width;
|
||||
console_size.ws_row = height;
|
||||
}
|
||||
}
|
||||
else if ( *end )
|
||||
PanicF("Invalid console: %s", console);
|
||||
console_tio.c_ospeed = console_tio.c_ispeed;
|
||||
|
||||
const uint16_t* bioscom_ports = (const uint16_t*) (nullpage + 0x400);
|
||||
if ( !(console_port = bioscom_ports[device - 1]) )
|
||||
PanicF("No such hardware device detected: %s", console);
|
||||
outport8(console_port + IER, 0x0);
|
||||
ConfigurePort(console_port, &console_tio, false);
|
||||
|
||||
Log::fallback_framebuffer = NULL;
|
||||
Log::device_callback = ConsoleWrite;
|
||||
Log::device_writeraw = ConsoleWrite;
|
||||
Log::device_width = ConsoleWidth;
|
||||
Log::device_height = ConsoleHeight;
|
||||
Log::device_get_cursor = ConsoleGetCursor;
|
||||
Log::device_sync = ConsoleSync;
|
||||
Log::device_invalidate = ConsoleInvalidate;
|
||||
Log::emergency_device_is_impaired = ConsoleEmergencyIsImpaired;
|
||||
Log::emergency_device_recoup = ConsoleEmergencyRecoup;
|
||||
Log::emergency_device_reset = ConsoleEmergencyReset;
|
||||
Log::emergency_device_callback = ConsoleWrite;
|
||||
Log::emergency_device_writeraw = ConsoleWrite;
|
||||
Log::emergency_device_width = ConsoleWidth;
|
||||
Log::emergency_device_height = ConsoleHeight;
|
||||
Log::emergency_device_get_cursor = ConsoleGetCursor;
|
||||
Log::emergency_device_sync = ConsoleSync;
|
||||
|
||||
snprintf(Log::console_tty, sizeof(Log::console_tty), "/dev/com%lu", device);
|
||||
}
|
||||
|
||||
void Init(const char* devpath, Ref<Descriptor> slashdev)
|
||||
{
|
||||
uint16_t com_ports[1 + NUM_COM_PORTS];
|
||||
|
@ -282,21 +655,6 @@ void Init(const char* devpath, Ref<Descriptor> slashdev)
|
|||
|
||||
ioctx_t ctx; SetupKernelIOCtx(&ctx);
|
||||
|
||||
for ( size_t i = 1; i <= NUM_COM_PORTS; i++ )
|
||||
{
|
||||
uint16_t port = com_ports[i];
|
||||
if ( !port )
|
||||
continue;
|
||||
uint8_t interrupts = 0;
|
||||
outport8(port + FCR, 0);
|
||||
outport8(port + LCR, 0x80);
|
||||
outport8(port + DLL, 0xC);
|
||||
outport8(port + DLM, 0x0);
|
||||
outport8(port + LCR, 0x3); // 8n1
|
||||
outport8(port + MCR, 0x3); // DTR + RTS
|
||||
outport8(port + IER, interrupts);
|
||||
}
|
||||
|
||||
for ( size_t i = 1; i <= NUM_COM_PORTS; i++ )
|
||||
{
|
||||
if ( !com_ports[i] )
|
||||
|
@ -304,13 +662,27 @@ void Init(const char* devpath, Ref<Descriptor> slashdev)
|
|||
com_devices[i] = Ref<DevCOMPort>();
|
||||
continue;
|
||||
}
|
||||
com_devices[i] = Ref<DevCOMPort>(new DevCOMPort(slashdev->dev, 0, 0, 0660, com_ports[i]));
|
||||
if ( !com_devices[i] )
|
||||
PanicF("Unable to allocate device for COM port %zu", i);
|
||||
char name[3 + sizeof(size_t) * 3];
|
||||
snprintf(name, sizeof(name), "com%zu", i);
|
||||
if ( LinkInodeInDir(&ctx, slashdev, name, com_devices[i]) != 0 )
|
||||
PanicF("Unable to link %s/%s to COM port driver.", devpath, name);
|
||||
char ttyname[TTY_NAME_MAX+1];
|
||||
snprintf(ttyname, sizeof(ttyname), "com%zu", i);
|
||||
Ref<DevCOMPort> com(
|
||||
new DevCOMPort(slashdev->dev, 0, 0, 0660, com_ports[i], ttyname));
|
||||
if ( !com )
|
||||
PanicF("Unable to allocate device for %s", ttyname);
|
||||
com_devices[i] = com;
|
||||
if ( i == console_device )
|
||||
{
|
||||
ScopedLock lock(&console_lock);
|
||||
com->ImportConsole(&console_tio, &console_size);
|
||||
}
|
||||
int interrupt = i == 1 || i == 3 ? Interrupt::IRQ4 : Interrupt::IRQ3;
|
||||
com->Initialize(interrupt);
|
||||
if ( i == console_device )
|
||||
{
|
||||
ScopedLock lock(&console_lock);
|
||||
console_imported = true;
|
||||
}
|
||||
if ( LinkInodeInDir(&ctx, slashdev, ttyname, com) != 0 )
|
||||
PanicF("Unable to link %s/%s.", devpath, ttyname);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2011, 2012, 2014 Jonas 'Sortie' Termansen.
|
||||
* Copyright (c) 2011, 2012, 2014, 2024 Jonas 'Sortie' Termansen.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
|
@ -26,6 +26,7 @@
|
|||
namespace Sortix {
|
||||
namespace COM {
|
||||
|
||||
void InitializeConsole(const char* console);
|
||||
void Init(const char* devpath, Ref<Descriptor> slashdev);
|
||||
|
||||
} // namespace COM
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2011, 2012, 2013, 2014, 2015, 2016 Jonas 'Sortie' Termansen.
|
||||
* Copyright (c) 2011-2016, 2024 Jonas 'Sortie' Termansen.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
|
@ -26,6 +26,8 @@
|
|||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <sortix/limits.h>
|
||||
|
||||
typedef struct multiboot_info multiboot_info_t;
|
||||
|
||||
namespace Sortix {
|
||||
|
@ -38,6 +40,8 @@ class TextBufferHandle;
|
|||
namespace Sortix {
|
||||
namespace Log {
|
||||
|
||||
extern char console_tty[TTY_NAME_MAX+1];
|
||||
|
||||
extern uint8_t* fallback_framebuffer;
|
||||
extern size_t fallback_framebuffer_bpp;
|
||||
extern size_t fallback_framebuffer_pitch;
|
||||
|
@ -130,6 +134,7 @@ void Center(const char* string);
|
|||
void BeginReplace();
|
||||
void CancelReplace();
|
||||
void FinishReplace(TextBuffer* textbuf);
|
||||
void InitializeConsole(const char* console);
|
||||
|
||||
} // namespace Log
|
||||
} // namespace Sortix
|
||||
|
|
|
@ -117,8 +117,10 @@ static void SystemIdleThread(void* user);
|
|||
static int argc;
|
||||
static char** argv;
|
||||
static multiboot_info_t* bootinfo;
|
||||
static const char* console = "tty1";
|
||||
static bool enable_em = true;
|
||||
static bool enable_network_drivers = true;
|
||||
static char* term = (char*) "TERM=sortix";
|
||||
|
||||
static char* cmdline_tokenize(char** saved)
|
||||
{
|
||||
|
@ -198,10 +200,6 @@ extern "C" void KernelInit(unsigned long magic, multiboot_info_t* bootinfo_p)
|
|||
// Initialize the kernel log.
|
||||
Log::Init(bootinfo);
|
||||
|
||||
// Display the logo.
|
||||
Log::PrintF("\e[37;41m\e[2J");
|
||||
Log::Center(BRAND_LOGO);
|
||||
|
||||
char* cmdline = NULL;
|
||||
if ( bootinfo->flags & MULTIBOOT_INFO_CMDLINE && bootinfo->cmdline )
|
||||
{
|
||||
|
@ -265,6 +263,7 @@ extern "C" void KernelInit(unsigned long magic, multiboot_info_t* bootinfo_p)
|
|||
argv[argc] = NULL;
|
||||
|
||||
// Add new once-only options to sysinstall's normalize_kernel_options.
|
||||
bool enable_logo = true;
|
||||
bool no_random_seed = false;
|
||||
for ( int i = 0; i < argc; i++ )
|
||||
{
|
||||
|
@ -285,10 +284,16 @@ extern "C" void KernelInit(unsigned long magic, multiboot_info_t* bootinfo_p)
|
|||
HaltKernel();
|
||||
}
|
||||
}
|
||||
else if ( !strncmp(arg, "--console=", strlen("--console=")) )
|
||||
console = arg + strlen("--console=");
|
||||
else if ( !strcmp(arg, "--disable-em") )
|
||||
enable_em = false;
|
||||
else if ( !strcmp(arg, "--enable-em") )
|
||||
enable_em = true;
|
||||
else if ( !strcmp(arg, "--disable-logo") )
|
||||
enable_logo = false;
|
||||
else if ( !strcmp(arg, "--enable-logo") )
|
||||
enable_logo = true;
|
||||
else if ( !strcmp(arg, "--disable-network-drivers") )
|
||||
enable_network_drivers = false;
|
||||
else if ( !strcmp(arg, "--enable-network-drivers") )
|
||||
|
@ -309,6 +314,12 @@ extern "C" void KernelInit(unsigned long magic, multiboot_info_t* bootinfo_p)
|
|||
PanicF("Unsupported firmware option: %s", firmware);
|
||||
}
|
||||
}
|
||||
else if ( !strncmp(arg, "--term=", strlen("--term=")) )
|
||||
{
|
||||
const char* value = arg + strlen("--term=");
|
||||
if ( asprintf(&term, "TERM=%s", value) < 0 )
|
||||
Panic("malloc");
|
||||
}
|
||||
else
|
||||
{
|
||||
Log::PrintF("\r\e[J");
|
||||
|
@ -325,6 +336,16 @@ extern "C" void KernelInit(unsigned long magic, multiboot_info_t* bootinfo_p)
|
|||
argv[argc] = NULL;
|
||||
}
|
||||
|
||||
// Initialize the console.
|
||||
Log::InitializeConsole(console);
|
||||
|
||||
// Display the logo.
|
||||
if ( enable_logo )
|
||||
{
|
||||
Log::PrintF("\e[37;41m\e[J");
|
||||
Log::Center(BRAND_LOGO);
|
||||
}
|
||||
|
||||
// Initialize the interrupt handler table and enable interrupts.
|
||||
Interrupt::Init();
|
||||
|
||||
|
@ -556,12 +577,15 @@ static void BootThread(void* /*user*/)
|
|||
Panic("Could not symlink /dev/ptmx -> pts/ptmx");
|
||||
|
||||
// Register the kernel terminal as /dev/tty1.
|
||||
Ref<Inode> tty1(new LogTerminal(slashdev->dev, 0666, 0, 0,
|
||||
keyboard, kblayout, "tty1"));
|
||||
if ( !tty1 )
|
||||
Panic("Could not allocate a kernel terminal");
|
||||
if ( LinkInodeInDir(&ctx, slashdev, "tty1", tty1) != 0 )
|
||||
Panic("Unable to link /dev/tty1 to kernel terminal.");
|
||||
if ( !strcmp(Log::console_tty, "/dev/tty1") )
|
||||
{
|
||||
Ref<Inode> tty1(new LogTerminal(slashdev->dev, 0666, 0, 0,
|
||||
keyboard, kblayout, "tty1"));
|
||||
if ( !tty1 )
|
||||
Panic("Could not allocate a kernel terminal");
|
||||
if ( LinkInodeInDir(&ctx, slashdev, "tty1", tty1) != 0 )
|
||||
Panic("Unable to link /dev/tty1 to kernel terminal.");
|
||||
}
|
||||
|
||||
// Register the mouse as /dev/mouse.
|
||||
Ref<Inode> mousedev(new PS2MouseDevice(slashdev->dev, 0666, 0, 0, mouse));
|
||||
|
@ -737,12 +761,12 @@ static void InitThread(void* /*user*/)
|
|||
|
||||
Ref<DescriptorTable> dtable = process->GetDTable();
|
||||
|
||||
Ref<Descriptor> tty1 = root->open(&ctx, "/dev/tty1", O_READ | O_WRITE);
|
||||
if ( !tty1 )
|
||||
PanicF("/dev/tty1: %m");
|
||||
if ( tty1->ioctl(&ctx, TIOCSCTTY, 0) < 0 )
|
||||
PanicF("/dev/tty1: ioctl: TIOCSCTTY: %m");
|
||||
tty1.Reset();
|
||||
Ref<Descriptor> tty = root->open(&ctx, Log::console_tty, O_READ | O_WRITE);
|
||||
if ( !tty )
|
||||
PanicF("%s: %m", Log::console_tty);
|
||||
if ( tty->ioctl(&ctx, TIOCSCTTY, 0) < 0 )
|
||||
PanicF("%s: ioctl: TIOCSCTTY: %m", Log::console_tty);
|
||||
tty.Reset();
|
||||
|
||||
Ref<Descriptor> tty_stdin = root->open(&ctx, "/dev/tty", O_READ);
|
||||
if ( !tty_stdin || dtable->Allocate(tty_stdin, 0) != 0 )
|
||||
|
@ -787,7 +811,7 @@ static void InitThread(void* /*user*/)
|
|||
Log::PrintF("\r\e[m\e[J");
|
||||
|
||||
int envc = 1;
|
||||
const char* envp[] = { "TERM=sortix", NULL };
|
||||
const char* envp[] = { term, NULL };
|
||||
struct thread_registers regs;
|
||||
assert((((uintptr_t) ®s) & (alignof(regs)-1)) == 0);
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2011-2017 Jonas 'Sortie' Termansen.
|
||||
* Copyright (c) 2011-2017, 2024 Jonas 'Sortie' Termansen.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
|
@ -18,6 +18,7 @@
|
|||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
|
||||
|
@ -29,6 +30,7 @@
|
|||
#include <sortix/kernel/pci-mmio.h>
|
||||
#include <sortix/kernel/textbuffer.h>
|
||||
|
||||
#include "com.h"
|
||||
#include "lfbtextbuffer.h"
|
||||
#include "multiboot.h"
|
||||
#include "textterminal.h"
|
||||
|
@ -37,6 +39,8 @@
|
|||
namespace Sortix {
|
||||
namespace Log {
|
||||
|
||||
char console_tty[TTY_NAME_MAX+1];
|
||||
|
||||
uint8_t* fallback_framebuffer = NULL;
|
||||
size_t fallback_framebuffer_bpp = 0;
|
||||
size_t fallback_framebuffer_pitch = 0;
|
||||
|
@ -262,5 +266,16 @@ void FinishReplace(TextBuffer* textbuf)
|
|||
((TextTerminal*) Log::device_pointer)->FinishReplace(textbuf);
|
||||
}
|
||||
|
||||
void InitializeConsole(const char* console)
|
||||
{
|
||||
if ( !strcmp(console, "tty1") )
|
||||
snprintf(console_tty, sizeof(console_tty), "/dev/%s", console);
|
||||
else if ( !strncmp(console, "com", 3) &&
|
||||
isdigit((unsigned char) console[3]) )
|
||||
COM::InitializeConsole(console);
|
||||
else
|
||||
PanicF("Unknown console: %s", console);
|
||||
}
|
||||
|
||||
} // namespace Log
|
||||
} // namespace Sortix
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2012, 2013, 2014, 2015, 2016, 2021 Jonas 'Sortie' Termansen.
|
||||
* Copyright (c) 2012-2016, 2021, 2024 Jonas 'Sortie' Termansen.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
|
@ -157,6 +157,12 @@ void LogTerminal::tty_output(const unsigned char* buffer, size_t length)
|
|||
}
|
||||
}
|
||||
|
||||
bool LogTerminal::Reconfigure(const struct termios* new_tio) // termlock held
|
||||
{
|
||||
(void) new_tio;
|
||||
return true;
|
||||
}
|
||||
|
||||
int LogTerminal::sync(ioctx_t* /*ctx*/)
|
||||
{
|
||||
ScopedLock lock(&termlock);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2012, 2014, 2015, 2016 Jonas 'Sortie' Termansen.
|
||||
* Copyright (c) 2012, 2014, 2015, 2016, 2024 Jonas 'Sortie' Termansen.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
|
@ -44,6 +44,7 @@ public:
|
|||
|
||||
protected:
|
||||
virtual void tty_output(const unsigned char* buffer, size_t length);
|
||||
virtual bool Reconfigure(const struct termios* new_tio);
|
||||
|
||||
private:
|
||||
void ProcessKeystroke(int kbkey);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2015, 2016, 2021, 2022 Jonas 'Sortie' Termansen.
|
||||
* Copyright (c) 2015, 2016, 2021, 2022, 2024 Jonas 'Sortie' Termansen.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
|
@ -465,6 +465,7 @@ public:
|
|||
|
||||
protected:
|
||||
virtual void tty_output(const unsigned char* buffer, size_t length);
|
||||
virtual bool Reconfigure(const struct termios* new_tio);
|
||||
|
||||
private:
|
||||
short PollMasterEventStatus();
|
||||
|
@ -594,6 +595,12 @@ void PTY::tty_output(const unsigned char* buffer, size_t length) // termlock hel
|
|||
}
|
||||
}
|
||||
|
||||
bool PTY::Reconfigure(const struct termios* new_tio) // termlock held
|
||||
{
|
||||
(void) new_tio;
|
||||
return true;
|
||||
}
|
||||
|
||||
short PTY::PollMasterEventStatus()
|
||||
{
|
||||
short status = 0;
|
||||
|
|
|
@ -230,13 +230,17 @@ int TTY::settermmode(ioctx_t* /*ctx*/, unsigned int termmode)
|
|||
new_oflag |= OCRNL;
|
||||
else
|
||||
new_oflag &= ~OCRNL;
|
||||
bool oldnoutf8 = old_lflag & ISORTIX_32BIT;
|
||||
bool newnoutf8 = new_lflag & ISORTIX_32BIT;
|
||||
if ( oldnoutf8 != newnoutf8 )
|
||||
bool old_no_utf8 = old_lflag & ISORTIX_32BIT;
|
||||
bool new_no_utf8 = new_lflag & ISORTIX_32BIT;
|
||||
struct termios new_tio = tio;
|
||||
new_tio.c_cflag = new_cflag;
|
||||
new_tio.c_lflag = new_lflag;
|
||||
new_tio.c_oflag = new_oflag;
|
||||
if ( !Reconfigure(&new_tio) )
|
||||
return -1;
|
||||
tio = new_tio;
|
||||
if ( old_no_utf8 != new_no_utf8 )
|
||||
memset(&read_ps, 0, sizeof(read_ps));
|
||||
tio.c_cflag = new_cflag;
|
||||
tio.c_lflag = new_lflag;
|
||||
tio.c_oflag = new_oflag;
|
||||
if ( !(tio.c_lflag & ICANON) )
|
||||
CommitLineBuffer();
|
||||
return 0;
|
||||
|
@ -822,7 +826,7 @@ int TTY::tcsetattr(ioctx_t* ctx, int actions, const struct termios* io_tio)
|
|||
{
|
||||
ScopedLock lock(&termlock);
|
||||
if ( hungup )
|
||||
return errno = EIO, -1;
|
||||
return -1;
|
||||
if ( !RequireForeground(SIGTTOU) )
|
||||
return -1;
|
||||
switch ( actions )
|
||||
|
@ -830,15 +834,17 @@ int TTY::tcsetattr(ioctx_t* ctx, int actions, const struct termios* io_tio)
|
|||
case TCSANOW: break;
|
||||
case TCSADRAIN: break;
|
||||
case TCSAFLUSH: linebuffer.Flush(); break;
|
||||
default: return errno = EINVAL, -1;
|
||||
default: return -1;
|
||||
}
|
||||
tcflag_t old_lflag = tio.c_lflag;
|
||||
if ( !ctx->copy_from_src(&tio, io_tio, sizeof(tio)) )
|
||||
struct termios new_tio;
|
||||
if ( !ctx->copy_from_src(&new_tio, io_tio, sizeof(new_tio)) )
|
||||
return -1;
|
||||
tcflag_t new_lflag = tio.c_lflag;
|
||||
bool oldnoutf8 = old_lflag & ISORTIX_32BIT;
|
||||
bool newnoutf8 = new_lflag & ISORTIX_32BIT;
|
||||
if ( oldnoutf8 != newnoutf8 )
|
||||
bool old_no_utf8 = tio.c_lflag & ISORTIX_32BIT;
|
||||
bool new_no_utf8 = new_tio.c_lflag & ISORTIX_32BIT;
|
||||
if ( !Reconfigure(&new_tio) )
|
||||
return -1;
|
||||
tio = new_tio;
|
||||
if ( old_no_utf8 != new_no_utf8 )
|
||||
memset(&read_ps, 0, sizeof(read_ps));
|
||||
if ( !(tio.c_lflag & ICANON) )
|
||||
CommitLineBuffer();
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2012, 2014, 2015, 2016 Jonas 'Sortie' Termansen.
|
||||
* Copyright (c) 2012, 2014, 2015, 2016, 2024 Jonas 'Sortie' Termansen.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
|
@ -86,6 +86,7 @@ protected:
|
|||
tty_output((const unsigned char*) str, strlen(str));
|
||||
}
|
||||
virtual void tty_output(const unsigned char* buffer, size_t length) = 0;
|
||||
virtual bool Reconfigure(const struct termios* new_tio) = 0;
|
||||
|
||||
protected:
|
||||
void ProcessUnicode(uint32_t unicode);
|
||||
|
|
23
share/man/man4/com.4
Normal file
23
share/man/man4/com.4
Normal file
|
@ -0,0 +1,23 @@
|
|||
.Dd December 16, 2024
|
||||
.Dt COM 4
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm com
|
||||
.Nd uart 8250 serial port terminal driver
|
||||
.Sh SYNOPSIS
|
||||
.Nm /dev/com Ns Ar X
|
||||
.Sh DESCRIPTION
|
||||
.Nm
|
||||
is a terminal driver for the UART 8250 serial port and compatible devices.
|
||||
.Pp
|
||||
The serial ports are detected using the BIOS Data Area.
|
||||
.Pp
|
||||
.Nm
|
||||
supports being the
|
||||
.Xr kernel 7
|
||||
console as described in its
|
||||
.Fl \-console
|
||||
option.
|
||||
.Sh SEE ALSO
|
||||
.Xr tty 4 ,
|
||||
.Xr kernel 7
|
|
@ -166,6 +166,46 @@ which will instead boot to a plain
|
|||
.Pa /dev/tty1
|
||||
terminal.
|
||||
.Pp
|
||||
The kernel console can be changed to the primary serial port terminal by
|
||||
selecting
|
||||
.Sy Enable serial console .
|
||||
You can use the
|
||||
.Xr release-iso-modification 7
|
||||
procedure to customize the serial port settings (speed, bits, parity), window
|
||||
size, and the
|
||||
.Ev TERM
|
||||
environment variable ahead of time.
|
||||
Otherwise it will default to a speed of 38400 with 8 bits and no parity, with a
|
||||
80x25 window size, and the default
|
||||
.Ev TERM
|
||||
variable.
|
||||
You can change the settings appropriately after boot using the
|
||||
.Xr stty 7
|
||||
.Sy ispeed , ospeed , cols ,
|
||||
and
|
||||
.Sy rows
|
||||
commands, followed by
|
||||
.Sy export TERM=terminal
|
||||
to select your terminal.
|
||||
The installation remembers the
|
||||
.Xr kernel 7
|
||||
.Fl \-console
|
||||
and
|
||||
.Fl \-term
|
||||
options it was booted with.
|
||||
If you wish for the installed GRUB bootloader to use the serial line, choose
|
||||
the
|
||||
.Sy chroot
|
||||
option at the end of the installation, and then set the
|
||||
.Sy GRUB_SERIAL_COMMAND
|
||||
and
|
||||
.Sy GRUB_TERMINAL
|
||||
variables appropriately per the GRUB documentation in the
|
||||
.Pa /etc/grub
|
||||
file and run the
|
||||
.Xr update-grub 8
|
||||
command.
|
||||
.Pp
|
||||
The network drivers can be disabled by navigating to the advanced menu and
|
||||
selecting
|
||||
.Sy Disable network drivers .
|
||||
|
|
|
@ -6,12 +6,16 @@
|
|||
.Nd operating system kernel
|
||||
.Sh SYNOPSIS
|
||||
.Pa /boot/sortix.bin
|
||||
.Op Fl \-console Ns = Ns Ar terminal
|
||||
.Op Fl \-disable-em
|
||||
.Op Fl \-enable-em
|
||||
.Op Fl \-disable-network-drivers
|
||||
.Op Fl \-disable-logo
|
||||
.Op Fl \-enable-em
|
||||
.Op Fl \-enable-network-drivers
|
||||
.Op Fl \-enable-logo
|
||||
.Op Fl \-firmware Ns = Ns Oo Sy bios "|" Sy efi "|" pc Oc
|
||||
.Op Fl \-no-random-seed
|
||||
.Op Fl \-term Ns = Ns Ar terminal
|
||||
.Op Fl \-
|
||||
.Op Ar init ...
|
||||
.Sh DESCRIPTION
|
||||
|
@ -51,10 +55,57 @@ otherwise.
|
|||
.Pp
|
||||
The options are as follows:
|
||||
.Bl -tag -width "12345678"
|
||||
.It Fl \-console Ns = Ns Ar terminal
|
||||
Use the
|
||||
.Ar terminal
|
||||
as the console and the session for
|
||||
.Xr init 8
|
||||
along with options for initializing the terminal.
|
||||
The choices are:
|
||||
.Bl -tag -width "12345678"
|
||||
.It Sy com Ns Ar n Ns Oo , Ns Oo BBBBPN Oc Ns Oo Ns , Ns Ar columns Ns Sy x Ns Ar rows Oc Oc
|
||||
Use the
|
||||
.Xr com 4
|
||||
serial line; optionally initializing it with the speed
|
||||
.Ar BBBB ,
|
||||
with the parity
|
||||
.Ar P
|
||||
being either
|
||||
.Sy n
|
||||
for no parity,
|
||||
.Sy o
|
||||
for odd parity,
|
||||
or
|
||||
.Sy e
|
||||
for even parity, and
|
||||
.Ar N
|
||||
is the number of bits per character;
|
||||
and optionally initializing the terminal window size to the selected
|
||||
.Ar columns
|
||||
and
|
||||
.Ar rows
|
||||
or 80x25 by default.
|
||||
The
|
||||
.Fl \-term
|
||||
option is useful to select the
|
||||
.Ev TERM
|
||||
environment variable.
|
||||
.Pp
|
||||
This choice currently disables the
|
||||
.Sy tty1
|
||||
terminal because its logterminal driver needs a major restructuring.
|
||||
.It Sy tty1
|
||||
Use the
|
||||
.Sy tty1
|
||||
virtual terminal as the console.
|
||||
This terminal is the default console.
|
||||
.El
|
||||
.It Fl \-disable-em
|
||||
Don't initialize the
|
||||
.Xr em 4
|
||||
driver.
|
||||
.It Fl \-disable-logo
|
||||
Don't display the operating system boot on the console during boot.
|
||||
.It Fl \-disable-network-drivers
|
||||
Don't initialize any network drivers.
|
||||
This option ensures the booted system is not networked.
|
||||
|
@ -62,6 +113,9 @@ This option ensures the booted system is not networked.
|
|||
Do initialize the
|
||||
.Xr em 4
|
||||
driver.
|
||||
.It Fl \-enable-logo
|
||||
Display the operating system boot on the console during boot.
|
||||
This is the default behavior.
|
||||
.It Fl \-enable-network-drivers
|
||||
Do initialize network drivers.
|
||||
This is the default behavior.
|
||||
|
@ -77,6 +131,17 @@ value is a synonym for
|
|||
Don't warn if no random seed file was loaded by the bootloader (usually from
|
||||
.Pa /boot/random.seed ) .
|
||||
This option is useful for live environments where this situation is unavoidable.
|
||||
.It Fl \-term Ns = Ns Ar terminal
|
||||
Set the
|
||||
.Ev TERM
|
||||
environment variable to the selected
|
||||
.Ar terminal .
|
||||
This option is useful in combination with selecting a serial line as the
|
||||
.Fl \-console.
|
||||
The default
|
||||
.Ev TERM
|
||||
is
|
||||
.Sy sortix .
|
||||
.El
|
||||
.Pp
|
||||
The kernel accepts multiboot modules from the bootloader, which are processed
|
||||
|
|
|
@ -67,6 +67,10 @@ Secondly, it loads
|
|||
(if it exists)
|
||||
which can take any actions it wants and customize the default configuration.
|
||||
.Pp
|
||||
Third, the
|
||||
.Sy hook_initialize_terminal
|
||||
hook is run to initialize the bootloader input and output.
|
||||
.Pp
|
||||
Finally, it loads
|
||||
.Pa /boot/grub/main.cfg
|
||||
to display the menu menu.
|
||||
|
@ -256,6 +260,13 @@ The main menu uses this title verbatim, while the other menus will append
|
|||
" when constructing
|
||||
.Sy menu_title.
|
||||
(Default: "Sortix $version for $machine")
|
||||
.It Sy console
|
||||
Optionally contains
|
||||
.Fl \-console
|
||||
and
|
||||
.Fl \-term
|
||||
options to forward to the
|
||||
.Xr kernel 7 .
|
||||
.It Sy default
|
||||
Select this bootloader menu option number by default (counting from 0).
|
||||
If the selected menu option itself is a submenu, it can be appended with a
|
||||
|
@ -289,6 +300,9 @@ Whether to start the
|
|||
.Xr sshd 8
|
||||
daemon.
|
||||
(Default: false)
|
||||
.It Sy kernel_options
|
||||
Optionally contains additional options for the
|
||||
.Xr kernel 7 .
|
||||
.It Sy machine
|
||||
The machine type this release was built for.
|
||||
.It Sy menu_title
|
||||
|
@ -312,6 +326,14 @@ and not if set to
|
|||
.Sy false .
|
||||
(Default:
|
||||
.Sy true )
|
||||
.It Sy serial_console
|
||||
When the serial console is enabled in the advanced menu, this variable contains
|
||||
the
|
||||
.Fl \-console
|
||||
and
|
||||
.Fl \-term
|
||||
options to forward to the
|
||||
.Xr kernel 7 .
|
||||
.It Sy timeout
|
||||
The time in seconds before the default menu entry (according to the
|
||||
.Sy default
|
||||
|
@ -453,6 +475,9 @@ The following hooks are run by the GRUB bootloader configuration:
|
|||
After the advanced menu entries have been emitted.
|
||||
.It Sy hook_advanced_menu_pre
|
||||
Before the advanced menu entries are emitted.
|
||||
.It Sy hook_initialize_terminal
|
||||
After having loaded the hook configuration file, when it's time to configure
|
||||
the bootloader input and output.
|
||||
.It Sy hook_initrd_post
|
||||
After the initrd is loaded.
|
||||
.It Sy hook_kernel_post
|
||||
|
|
|
@ -536,6 +536,22 @@ tix-iso-liveconfig --autoinstall=autoupgrade.conf liveconfig
|
|||
tix-iso-bootconfig --liveconfig=liveconfig --default=2 bootconfig
|
||||
tix-iso-add sortix.iso bootconfig
|
||||
.Ed
|
||||
.Ss Boot to Console Instead of GUI By Default
|
||||
To customize a release so it boots to a console instead of the GUI:
|
||||
.Bd -literal
|
||||
tix-iso-bootconfig --disable-gui bootconfig
|
||||
tix-iso-add sortix.iso bootconfig
|
||||
.Ed
|
||||
.Ss Boot to Serial Console using Qemu
|
||||
To boot to a serial terminal with a custom serial settings and a custom terminal
|
||||
window size of 118 colums by 256 rows and a specific
|
||||
.Ev TERM
|
||||
variable inside the qemu virtual machine:
|
||||
.Bd -literal
|
||||
tix-iso-bootconfig --serial="com1,9600n8,118x56 --term=xterm-256color" bootconfig
|
||||
tix-iso-add sortix.iso bootconfig
|
||||
qemu-system-x86_64 -serial mon:stdio -cdrom sortix.iso
|
||||
.Ed
|
||||
.Sh SEE ALSO
|
||||
.Xr xorriso 1 ,
|
||||
.Xr development 7 ,
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
set -e
|
||||
|
||||
append_title="modified by $(id -un)@$(hostname)"
|
||||
console=
|
||||
default=
|
||||
directory=
|
||||
enable_append_title=true
|
||||
|
@ -28,8 +29,12 @@ enable_network_drivers=
|
|||
enable_ntpd=
|
||||
enable_src=
|
||||
enable_sshd=
|
||||
grub_serial=
|
||||
kernel_options=
|
||||
init_target=
|
||||
liveconfig=
|
||||
serial=
|
||||
serial_console=
|
||||
operand=1
|
||||
random_seed=false
|
||||
timeout=
|
||||
|
@ -53,6 +58,8 @@ for argument do
|
|||
--) dashdash=yes ;;
|
||||
--append-title=*) append_title=$parameter ;;
|
||||
--append-title) previous_option=append_title ;;
|
||||
--console=*) console=$parameter ;;
|
||||
--console) previous_option=console ;;
|
||||
--default=*) default=$parameter ;;
|
||||
--default) previous_option=default ;;
|
||||
--disable-append-title) enable_append_title=false ;;
|
||||
|
@ -69,11 +76,19 @@ for argument do
|
|||
--enable-ntpd) enable_ntpd=true ;;
|
||||
--enable-src) enable_src=true ;;
|
||||
--enable-sshd) enable_sshd=true ;;
|
||||
--grub-serial=*) grub_serial=$parameter ;;
|
||||
--grub-serial) previous_option=grub_serial ;;
|
||||
--kernel-options=*) kernel_options=$parameter ;;
|
||||
--kernel-options) previous_option=kernel_options ;;
|
||||
--init-target=*) init_target=$parameter ;;
|
||||
--init-target) previous_option=init_target ;;
|
||||
--liveconfig=*) liveconfig=$parameter ;;
|
||||
--liveconfig) previous_option=liveconfig ;;
|
||||
--random-seed) random_seed=true ;;
|
||||
--serial=*) serial=$parameter ;;
|
||||
--serial) previous_option=serial ;;
|
||||
--serial-console=*) serial_console=$parameter ;;
|
||||
--serial-console) previous_option=serial_console ;;
|
||||
--timeout=*) timeout=$parameter ;;
|
||||
--timeout) previous_option=timeout ;;
|
||||
-*) echo "$0: unrecognized option $argument" >&2
|
||||
|
@ -95,6 +110,13 @@ if test -n "$previous_option"; then
|
|||
exit 1
|
||||
fi
|
||||
|
||||
if test -n "$serial"; then
|
||||
enable_gui=false
|
||||
console="$serial"
|
||||
grub_serial="$serial"
|
||||
serial_console="$serial"
|
||||
fi
|
||||
|
||||
if test -z "$directory"; then
|
||||
echo "$0: No directory was specified" >&2
|
||||
exit 1
|
||||
|
@ -107,17 +129,17 @@ human_size() {
|
|||
|
||||
print_enable_default() {
|
||||
if [ "$1" = true ]; then
|
||||
printf " enable_%s=--enable-%s\n" "$2" "$3"
|
||||
printf "enable_%s=--enable-%s\n" "$2" "$3"
|
||||
elif [ "$1" = false ]; then
|
||||
printf " enable_%s=--disable-%s\n" "$2" "$3"
|
||||
printf "enable_%s=--disable-%s\n" "$2" "$3"
|
||||
fi
|
||||
}
|
||||
|
||||
print_enable_default_bool() {
|
||||
if [ "$1" = true ]; then
|
||||
printf " enable_%s=true\n" "$2"
|
||||
printf "enable_%s=true\n" "$2"
|
||||
elif [ "$1" = false ]; then
|
||||
printf " enable_%s=false\n" "$2"
|
||||
printf "enable_%s=false\n" "$2"
|
||||
fi
|
||||
}
|
||||
|
||||
|
@ -152,9 +174,15 @@ mkdir -p -- "$directory/boot/grub"
|
|||
(if [ -e "$directory/boot/liveconfig.tar.xz" ]; then
|
||||
printf 'insmod xzio\n'
|
||||
fi
|
||||
if [ -n "$console" ]; then
|
||||
printf 'console="--console=%s"\n' "$console"
|
||||
fi
|
||||
if [ -n "$default" ]; then
|
||||
printf 'default="%s"\n' "$default"
|
||||
fi
|
||||
if [ -n "$serial_console" ]; then
|
||||
printf 'serial_console="--console=%s"\n' "$serial_console"
|
||||
fi
|
||||
if [ -n "$timeout" ]; then
|
||||
printf 'timeout="%s"\n' "$timeout"
|
||||
fi
|
||||
|
@ -170,10 +198,30 @@ mkdir -p -- "$directory/boot/grub"
|
|||
print_enable_default_bool "$enable_src" src src
|
||||
print_enable_default_bool "$enable_sshd" sshd sshd
|
||||
print_enable_default_bool "$enable_ntpd" ntpd ntpd
|
||||
if [ -n "$kernel_options" ]; then
|
||||
printf 'kernel_options="%s"\n' "$kernel_options"
|
||||
fi
|
||||
if $enable_append_title; then
|
||||
printf "base_menu_title=\"\$base_menu_title - \"'%s'\n" \
|
||||
"$(printf '%s\n' "$append_title" | sed "s/'/'\\\\''/g")"
|
||||
fi
|
||||
if [ -n "$grub_serial" ]; then
|
||||
device=$(expr "X$grub_serial" : 'Xcom\([0-9]\+\).*' || true)
|
||||
device=$(expr "$device" - 1 || true)
|
||||
settings=$(expr "X$grub_serial" : 'Xcom[0-9]\+,\([^,]*\)\(,.*\)\?' || true)
|
||||
speed=$(expr "X$settings" : 'X\([0-9]*\)[noe][5678]' || true)
|
||||
parity=$(expr "X$settings" : 'X[0-9]*\([noe]\)[5678]' || true)
|
||||
case "$parity" in n) parity=no;; o) parity=odd;; e) parity=even;; esac
|
||||
bits=$(expr "X$settings" : 'X[0-9]*[noe]\([5678]\)' || true)
|
||||
cat << EOF
|
||||
function hook_initialize_terminal {
|
||||
serial --unit=$device ${speed+--speed=$speed} ${parity+--parity=$parity} \
|
||||
${bits+--word=$bits}
|
||||
terminal_input serial
|
||||
terminal_output serial
|
||||
}
|
||||
EOF
|
||||
fi
|
||||
if [ -n "$init_target" ]; then
|
||||
printf 'function hook_menu_pre {\n'
|
||||
printf ' menuentry "Sortix (%s)" {\n' "$init_target"
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl \-append-title Ns = Ns Ar text
|
||||
.Op Fl \-console Ns = Ns Ar terminal
|
||||
.Op Fl \-default Ns = Ns Ar default-boot-menu-option
|
||||
.Op Fl \-disable-append-title
|
||||
.Op Fl \-disable-dhclient
|
||||
|
@ -22,9 +23,13 @@
|
|||
.Op Fl \-enable-ntpd
|
||||
.Op Fl \-enable-src
|
||||
.Op Fl \-enable-sshd
|
||||
.Op Fl \-grub-serial Ns = Ns Ar terminal
|
||||
.Op Fl \-kernel-options Ns = Ns Ar options
|
||||
.Op Fl \-init-target Ns = Ns Ar target
|
||||
.Op Fl \-liveconfig Ns = Ns Ar liveconfig-directory
|
||||
.Op Fl \-random-seed
|
||||
.Op Fl \-serial Ns = Ns Ar terminal
|
||||
.Op Fl \-serial-console Ns = Ns Ar terminal
|
||||
.Op Fl \-timeout Ns = Ns Ar boot-menu-timeout
|
||||
.Ar output-directory
|
||||
.Sh DESCRIPTION
|
||||
|
@ -83,6 +88,20 @@ The bootloader menu title is appended to by default, but can be disabled with
|
|||
and re-enabled with
|
||||
.Fl \-enable-append-title ,
|
||||
whichever comes last takes precedence.
|
||||
.It Fl \-console Ns = Ns Ar terminal
|
||||
Forward the
|
||||
.Fl \-console
|
||||
option to the
|
||||
.Xr kernel 7
|
||||
to select the
|
||||
.Ar terminal
|
||||
to use as the console and the settings to initialize it.
|
||||
.Pp
|
||||
The
|
||||
.Ev TERM
|
||||
variable can be overridden by suffixing the quoted argument with a space
|
||||
followed by
|
||||
.Fl \-term Ns = Ns Ar terminal .
|
||||
.It Fl \-default Ns = Ns Ar default-boot-menu-option
|
||||
Select bootloader menu option number
|
||||
.Ar default-boot-menu-option
|
||||
|
@ -205,6 +224,18 @@ GRUB variable to
|
|||
causing the bootloader to load additional configuration that turns on the
|
||||
.Xr sshd 8
|
||||
daemon on boot.
|
||||
.It Fl \-grub-serial Ns = Ns Ar terminal
|
||||
Use the serial
|
||||
.Ar terminal
|
||||
for GRUB's menu in the format of the
|
||||
.Xr kernel 7
|
||||
.Fl \-console
|
||||
option.
|
||||
.It Fl \-kernel-options Ns = Ns Ar options
|
||||
Forward these additional
|
||||
.Ar options
|
||||
to the the
|
||||
.Xr kernel 7 .
|
||||
.It Fl \-init-target Ns = Ns Ar target
|
||||
Add a new first menu entry that boots the
|
||||
.Ar target
|
||||
|
@ -277,6 +308,34 @@ If a release .iso has been made from
|
|||
it should be securely erased when no longer useful.
|
||||
If a release .iso has been burned to a physical media, it should be securely
|
||||
erased when no longer useful.
|
||||
.It Fl \-serial Ns = Ns Ar terminal
|
||||
Boot entirely using the serial
|
||||
.Xr terminal
|
||||
as specified in the format of the
|
||||
.Xr kernel 7
|
||||
.Fl \-console option.
|
||||
This option is a shorthand equivalent to setting the
|
||||
.Fl \-console ,
|
||||
.Fl \-grub-console ,
|
||||
.Fl \-serial-console ,
|
||||
and
|
||||
.Fl \-disable-gui
|
||||
options.
|
||||
.It Fl \-serial-console Ns = Ns Ar terminal
|
||||
Whenever the serial console is enabled in the advanced bootloader menu, forward
|
||||
this
|
||||
.Fl \-console
|
||||
option to the
|
||||
.Xr kernel 7
|
||||
to select the
|
||||
.Ar terminal
|
||||
to use as the console and the settings to initialize it.
|
||||
.Pp
|
||||
The
|
||||
.Ev TERM
|
||||
variable can be overridden by suffixing the quoted argument with a space
|
||||
followed by
|
||||
.Fl \-term Ns = Ns Ar terminal .
|
||||
.It Fl \-timeout Ns = Ns Ar boot-menu-timeout
|
||||
Pick the default bootloader menu option after
|
||||
.Ar boot-menu-timeout
|
||||
|
@ -378,6 +437,16 @@ To customize a release so it boots to a console instead of the GUI:
|
|||
tix-iso-bootconfig --disable-gui bootconfig
|
||||
tix-iso-add sortix.iso bootconfig
|
||||
.Ed
|
||||
.Ss Boot to Serial Console using Qemu
|
||||
To boot to a serial terminal with a custom serial settings and a custom terminal
|
||||
window size of 118 colums by 256 rows and a specific
|
||||
.Ev TERM
|
||||
variable inside the qemu virtual machine:
|
||||
.Bd -literal
|
||||
tix-iso-bootconfig --serial="com1,9600n8,118x56 --term=xterm-256color" bootconfig
|
||||
tix-iso-add sortix.iso bootconfig
|
||||
qemu-system-x86_64 -serial mon:stdio -cdrom sortix.iso
|
||||
.Ed
|
||||
.Sh SEE ALSO
|
||||
.Xr xorriso 1 ,
|
||||
.Xr kernel 7 ,
|
||||
|
|
Loading…
Add table
Reference in a new issue