vak: (Daemon)
Вот как выглядит современный bashc под NetBSD на древнем cx486. Неплохо работает, даже удобнее чем deco.

vak: (Daemon)
Почему NetBSD часто тормозит на i486 процессоре? Выяснились две причины: шифрование свопа и нехватка энтропии.

Не знаю, кто придумал включить по умолчанию шифрование страниц, откачиваемых в своп. Без аппаратной поддержки шифрования это убивает производительность напрочь. Отключается легко: достаточно добавить строчку "vm.swap_encrypt=0" в файл /etc/sysctl.conf.

С энтропией ситуация сложнее. При загрузке ядро NetBSD выдает строчку, означающую, что дело плохо.
WARNING: system needs entropy for security; see entropy(7)
За последние 10 лет мы привыкли к защищённым протоколам типа HTTPS и SSH, и не интересуемся деталями. А им для работы нужен качественный источник случайности. Иначе протокол станет слишком предсказуемым, а значит хакеры могут взломать его, легко подобрав ключ.

Когда вы подключаетесь к веб-сайту через HTTPS, ваш браузер и сервер выполняют «рукопожатие», чтобы согласовать секретный ключ шифрования. Если этот ключ генерируется с использованием низкой энтропии (предсказуемые данные), хакеру не нужно «взламывать» шифрование; ему достаточно угадать ключ. Стандартный 128-битный ключ имеет много возможных комбинаций. Если ваша система обладает высокой энтропией, хакеру придется перебрать почти все из них (что займет миллиарды лет). Если ваша энтропия низкая, ему, возможно, потребуется перебрать всего несколько тысяч.

В процессе передачи с каждым сообщением отправляется дополнительная случайная строка, чтобы гарантировать, что даже если вы отправите одну и ту же команду дважды (например, «Заплатить 10 долларов»), зашифрованные данные будут выглядеть совершенно по-разному каждый раз. Без высокой энтропии эти одноразовые числа могут повторяться или следовать определенному шаблону. Злоумышленник может записать старое зашифрованное сообщение и «воспроизвести» его позже, чтобы обмануть сервер.

Откуда протокол берёт эту энтропию? В ядре операционной системы имеется специальный буфер, где хранится некоторый запас, обычно несколько тысяч качественных случайных бит. Установление каждого нового HTTPS-соединения потребляет примерно от 256 до 512 бит (от 32 до 64 байт) из этого запаса, то есть порядка 10%. На каждый передаваемый пакет тоже нужно немного случайности, но там уже работает псевдослучайный генератор. В активных системах (особенно на серверах или небольших устройствах IoT) запас энтропии может опустеть, если нужно быстро сгенерировать слишком много ключей. Система может замереть и ждать, пока не будет собрано больше случайных данных. Источником служит или специальный аппаратный генератор шума (TRNG), встроенный в современный процессор, или драйверы некоторых периферийных устройств. Скажем, можно отслеживать микроизменения времени, необходимого жесткому диску для поиска данных.

Мы не замечаем проблемы энтропии, потому что на современных устройствах генераторы шума встроены в процессор. На древнем же компьютере ничего такого нет, и поэтому вход по SSH на мой Cx486 занимает 78 секунд. Время уходит на сбор энтропии и генерацию одноразового ключа для защищённого сеанса.

Энтропию в ядро можно легко добавлять, просто записывая случайные данные в /dev/urandom. Вопрос, откуда брать качественную случайность. Скажем, можно соорудить девайс на микроконтроллере RP2350 и подключить его на COM порт. В этом чипе есть блок TRNG, способный выдавать 7500 случайных бит в секунду. Это примерно 938 байт/сек. Хватит с запасом на все потребности.
vak: (Daemon)
В ядре NetBSD есть хитрый параметр "options CYRIX_CACHE_WORKS". Если его поставить, ядро включит L1 кэш процессора Cyrix. И оно действительно помогло. Дуремарки заметно поднялись: 54 супротив прежних 31. Хотя до досовских 110 далеко.
DureMark 1.0 Results
=======================
Iterations      : 300
Execution Time  : 5.5 sec
List Workload   : 39.4%
Matrix Workload : 19.2%
State Workload  : 41.4%
-----------------------
Total Score     : 54.25 DureMark
Путь был непростым, однако. Чтобы изменить параметр, надо пересобрать ядро. Проделать это на самом компьютере не представляется возможным. Без кэша он настолько тормозной, что пересборка займёт месяц. Следовательно, надо ставить ровно такую же версию NetBSD на виртуальную машину.

До сих пор я возился с NetBSD версии 4.0.1, выпуска 2008 года. Более поздние не лезут в 16 мегабайт памяти. Но эта версия давно не поддерживается, и пакеты к ней я надыбал только на bitsavers.org. При отсутствии пакетов на официальном сайте установка полноценной системы, нужной для сборки ядра, превращается в головоломку с неизвестным исходом.

Нужна свежая версия NetBSD 10.1, а значит необходимо добавить памяти в компьютер. Четыре восьмибитных SIMM, если помните. В пятницу память пришла с Ебея, заодно пришла и 2-гигибайтная SD карточка industrial. Установка системы на неё заняла всю субботу.

Возиться с флопиками необязательно. Чтобы запустить установку, надо под ДОСом скачать два файла: dosboot.com и netbsd-INSTALL.gz. Второй файл распаковать под именем install и вызвать "dosboot install". Остальное будет подгружаться по сети, благо сетевая карточка NE2000 настроена и работает. Процесс установки подробно описан в главе №3 "Example installation" документа netbsd-en.pdf.

Установка шла медленно и печально, ведь кэш пока не работает. Параллельно я поставил эту же версию NetBSD на мак под симулятором UTM (обёртка над QEMU). Пришлось напрячься, изучить файл конфигурации ядра, чтобы убрать всё ненужное, но не зацепить чувствительное. Благо, можно начать с имеющейся конфигурации GENERIC_TINY. Вот такое получилось.
Я прямо как в молодость вернулся: те же самые ощущения, что 32 года назад, когда я возился с конфигурациями и исходниками ядра FreeBSD. 😀

Компилируем ядро под NetBSD 10.1 в виртуальной машине, после чего записываем на досовскую SD карточку, где в файлe AUTOEXEC.BAT командой dosboot оно и грузится. Дешёво и сердито.

Забавная вышла ситуёвина. Допотопный компьютер с 5-дюймовым флоповодом, отстойнейшим процессором Cyrix 486, и на нём распоследний юникс NetBSD.

vak: (Знайка)
Я поставил Си компилятор под NetBSD на древнем компьютере PC 486 и скомпилил старый добрый Dhrystone.
$ ./dhrystone

Dhrystone Benchmark, Version 2.1 (Language: C)
...
Nanoseconds for one run through Dhrystone: 123707.4
Million Dhrystones per Second: 0.008
DMIPS: 4.6
Это в 1700 раз медленнее, чем Raspberry Pi 4, или в 800 раз медленнее Raspberry Pi 3B.
vak: (Daemon)
Чтобы влезть в 16 мегабайт памяти, пришлось откатиться до версии NetBSD 4.0.1 (2008 год).

Установщик удобный, но надо иметь навыки работы с таблицы разделов на диске. Пакеты ставятся по сети через HTTP.



Первый вход в систему после установки.



Подробности конфигурации периферии можно видеть из dmesg. Настроил SSH в обе стороны - есть некоторые устарелости, но в целом работает.
$ /sbin/dmesg
Copyright (c) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
    2006, 2007
    The NetBSD Foundation, Inc.  All rights reserved.
Copyright (c) 1982, 1986, 1989, 1991, 1993
    The Regents of the University of California.  All rights reserved.

NetBSD 4.0.1 (GENERIC) #0: Tue Oct  7 22:58:48 PDT 2008
        builds@wb30:/home/builds/ab/netbsd-4-0-1-RELEASE/i386/200810080053Z-obj/home/builds/ab/netbsd-4-0-1-RELEASE/src/sys/arch/i386/compile/GENERIC
total memory = 15996 KB
rbus: rbus_min_start set to 0x20000000
avail memory = 5532 KB
timecounter: Timecounters tick every 10.000 msec
timecounter: Timecounter "i8254" frequency 1193182 Hz quality 100
mainbus0 (root)
ACPI Error (tbxfroot-0775): No valid RSDP was found [20060217]
ACPI Exception (tbxfroot-0531): AE_NOT_FOUND, RSDP structure not found - Flags=8 [20060217]
ACPI Exception (tbxface-0162): AE_NO_ACPI_TABLES, Could not get the RSDP [20060217]
ACPI Exception (tbxface-0211): AE_NO_ACPI_TABLES, Could not load tables [20060217]
ACPI: unable to load tables: AE_NO_ACPI_TABLES
cpu0 at mainbus0: (uniprocessor)
cpu0: Cyrix 486DLC (486-class)
WARNING: CYRIX 486DLC CACHE UNCHANGED.
isa0 at mainbus0
lpt2 at isa0 port 0x3bc-0x3bf irq : polled
ne0 at isa0 port 0x280-0x29f irq 9
ne0: NE2000 Ethernet
ne0: Ethernet address 00:40:05:fa:24:77
com0 at isa0 port 0x3f8-0x3ff irq 4: ns8250 or ns16450, no fifo
com1 at isa0 port 0x2f8-0x2ff irq 3: ns8250 or ns16450, no fifo
pckbc0 at isa0 port 0x60-0x64
pckbd0 at pckbc0 (kbd slot)
pckbc0: using irq 1 for kbd slot
wskbd0 at pckbd0: console keyboard
attimer0 at isa0 port 0x40-0x43: AT Timer
wdc0 at isa0 port 0x1f0-0x1f7 irq 14
atabus0 at wdc0 channel 0
vga0 at isa0 port 0x3b0-0x3df iomem 0xa0000-0xbffff
wsdisplay0 at vga0 kbdmux 1: console (80x25, vt100 emulation), using wskbd0
wsmux1: connecting to wsdisplay0
pcppi0 at isa0 port 0x61
pcppi0: children must have an explicit unit
midi0 at pcppi0: PC speaker (CPU-intensive output)
sysbeep0 at pcppi0
isapnp0 at isa0 port 0x279: ISA Plug 'n Play device support
npx0 at isa0 port 0xf0-0xff
npx0: using exception 16
fdc0 at isa0 port 0x3f0-0x3f7 irq 6 drq 2
pcppi0: attached to attimer0
isapnp0: no ISA Plug 'n Play devices found
timecounter: Timecounter "clockinterrupt" frequency 100 Hz quality 0
fd0 at fdc0 drive 0: 1.44MB, 80 cyl, 2 head, 18 sec
fd1 at fdc0 drive 1: 1.2MB, 80 cyl, 2 head, 15 sec
Kernelized RAIDframe activated
wd0 at atabus0 drive 0: <FC-1307 SD to CF Adapter V1.4>
wd0: drive supports 1-sector PIO transfers, LBA addressing
wd0: 1910 MB, 3880 cyl, 16 head, 63 sec, 512 bytes/sect x 3911680 sectors
wd0: drive supports PIO mode 4, DMA mode 2, Ultra-DMA mode 5 (Ultra/100)
boot device: <unknown>
root device: wd0a
dump device (default wd0b): 
file system (default generic): 
root on wd0a dumps on wd0b
root file system type: ffs
init path (default /sbin/init): 
init: trying /sbin/init
wsdisplay0: screen 1 added (80x25, vt100 emulation)
wsdisplay0: screen 2 added (80x25, vt100 emulation)
wsdisplay0: screen 3 added (80x25, vt100 emulation)
wsdisplay0: screen 4 added (80x25, vt100 emulation)
$ _
vak: (Daemon)
Стефано Маринелли делится 20-летним опытом внедрения и сопровождения юниксных систем и сервисов.

vak: (Daemon)
Дэйв Пламмер выставил на продажу один из своих PDP-11/73. Установлен юникс BSD 2.11, интернет, все дела. Гляньте, вдруг кому сгодится.

(фейсбук)
I'm selling one of my PDP-11/73s with "all my good parts" to cover the costs of the 11/24 I'm building. Basically, it's an infallible system as long as I stay one PDP ahead of things 🙂

Plug it in, turn it on - boot 211BSD UNIX already custom configured, serve WWW pages, FTP, Telnet, and more. This is your chance to own a maxed-out and completely turnkey, ready-to-run PDP-11 UNIX Workstation. You could also install and run RT-11 or RSX-11, but this machine has been carefully set up and configured with 211BSD UNIX, including all networking features.

This machine represents a collection of my very best PDP-11 components, including:

• DEC M8190 CPU
• DEC M8637 Fast PMI Memory (x2) for a total of 4M installed, the max permitted
• DEC M3104 Eight Port Serial Multiplex - Connect up to 9 total terminals (plus Ethernet sessions)
• DEC M7555 MFM and Floppy Controller
• Emulex UC07 SCSI Controller - Supports tapes, drives, jaz, and more, up to 6 devices - Boot multiple systems
• DEC M7516 Ethernet Adapter - The faster/better DELQA NIC
• DEC RX50 Dual Floppy Drive - Tested and mounted as /mnt/flopppy0 and /mnt/floppy1 for each file interchange
• Seagate ST43400N - 3GB SCSI Drive - Contains /root, /swap, /usr, and /data partitions

It's all housed in a rare and very nice DEC BA23 chassis and tower pedestal case with front cover plate.
vak: (Daemon)
Один крутой чувак из Австралии взялся развивать 2.11BSD для архитектуры i386.

github.com/TheSledgeHammer/2.11BSD_X44
vak: (Daemon)
За последние три дня я могучим рывком, броском, пинком и нахрапом закончил таки переделку RetroBSD под компилятор Clang. Теперь не нужно бегать искать GCC для mips32. Ставите стандартный Clang и вперёд. Инструкция по сборке лежит в корневом файле README. Для запуска на симуляторе годится обновлённый QEMU для pic32. Если кому понадобится старая версия с GCC - она лежит в бранче gcc.

Поддержку устаревшего хардвера я убрал. Оставил только две платы, обе имеются в продаже:Из минусов: потеряны две фичи.
  • MIPS16e - компактная система команд - не поддерживается компилятором Clang. Формально она там есть, но код генерится совершенно нерабочий. Так что приходится довольствоваться стандартным набором инструкций. Из-за этого некоторые "толстые" приложения не лезут в память, к примеру компилятор SmallerC.
  • Не удаётся собрать библиотеку libc.а в формате a.out для того же компилятора SmallerC. Потому что имеющийся ассемблер mips32 не понимает некоторые навороченные конструкции, порождаемые компилятором Clang. Надо будет допиливать.
Но в целом система фурычит довольно неплохо. Открывается путь для переноса на другие платформы: esp32, stm32, riscv и другие.
vak: (Daemon)
Хотите взглянуть, как грузится RetroBSD с точки зрения последовательности системных вызовов? Стартует /sbin/iuit, из-под него /bin/sh выполняет скрипт /etc/rc, проверяет файловую систему, запускает cron и в конце концов getty. Я сделал флажок в QEMU для pic32, чтобы трассировать системные вызовы. Вывод слегка обработал вручную, вот результат.

gist.github.com/sergev/c0c21f47220e2d3ec6eee4b5b076ec0f
vak: (Daemon)
Внезапно выяснилось, что в RetroBSD была старая ошибка, из-за которой он не запускался на QEMU. Инструкция ERET попадала в delay-слот условного перехода. Строго говоря, это неопределённое поведение. В железе на PIC32 оно работает, но симулятор такого не прощает. Поправил, теперь всё с порядке.
$ qemu-pic32 -machine pic32mx7-max32 -nographic -monitor none -serial stdio -bios boot-max32.hex -kernel unix.hex -sd retrobsd.img
Board: chipKIT Max32
Processor: M4K
RAM size: 128 kbytes
Load file: 'boot-max32.hex', 6720 bytes
Load file: 'unix.hex', 141140 bytes
Card0 image 'retrobsd.img', 102401 kbytes

2.11 BSD Unix for PIC32, revision G512 build 3:
Compiled 2025-02-07 by vak@bumba:
/home/vak/Project/BSD/retrobsd/sys/pic32/max32
cpu: 795F512L 80 MHz, bus 80 MHz
oscillator: HS crystal, PLL div 1:2 mult x20
spi2: pins sdi=RG7/sdo=RG8/sck=RG6
uart1: pins rx=RF2/tx=RF8, interrupts 26/27/28, console
uart2: pins rx=RF4/tx=RF5, interrupts 40/41/42
uart4: pins rx=RD14/tx=RD15, interrupts 67/68/69
sd0: port SPI2, pin cs=RC14
gpio0: portA, pins ii---ii-iiiioiii
gpio1: portB, pins iiiiiiiiiiiiiiii
gpio2: portC, pins i-ii-------iiii-
gpio3: portD, pins --iiiiiiiiiiiiii
gpio4: portE, pins ------iiiiiiiiii
gpio5: portF, pins --ii--------i-ii
gpio6: portG, pins iiii--i-----iiii
adc: 15 channels
pwm: 5 channels
sd0: type I, size 102400 kbytes, speed 10 Mbit/sec
sd0a: partition type b7, sector 2, size 102400 kbytes
sd0b: partition type b8, sector 204802, size 2048 kbytes
sd0c: partition type b7, sector 208898, size 102400 kbytes
phys mem = 128 kbytes
user mem = 96 kbytes
root dev = (0,1)
swap dev = (0,2)
root size = 102400 kbytes
swap size = 2048 kbytes
/dev/sd0a: 1444 files, 12342 used, 89657 free
Starting daemons: update cron

2.11 BSD UNIX (pic32) (console)

login: root
Password:
Welcome to RetroBSD!
erase ^?, kill ^U, intr ^C

# date
Sun Jan 24 23:08:07 PST 2016

# df
Filesystem 1K-blocks Used Avail Capacity Mounted on
/dev/sd0a 101999 12345 89654 12% /

# ps aux
USER PID NICE SZ TTY TIME COMMAND
root 0 0 3 ? 0:00 swapper
root 1 0 35 ? 0:00 init -
root 10 0 7 ? 0:00 update
root 12 0 54 ? 0:00 cron
root 13 0 39 0 0:00 -sh
root 17 0 42 0 0:00 ps aux

# ls /bin
[ crontab hostname pagesize size uucico
adb date id passwd sl uuclean
adc-demo dc iostat pdc sleep uucp
aout dd join picoc smux uudecode
apropos df kill portio sort uuencode
ar diff la pr split uulog
as diskspeed last printenv strip uuname
awk du lcc printf stty uupoll
basename echo lcpp ps su uuq
basic ed ld pwd sum uusend
bc egrep ln pwm sx uusnap
cal emg login ranlib sync uux
calendar env lol rb sysctl uuxqt
cat expr ls re sz vi
cb false mail renice tail vmstat
cc fgrep make renumber tar w
chat-server file man retroforth tee wall
chflags find md5 rev telnet wc
chfn fold med rm test web-client
chgrp forth mesg rmail time web-server
chmod fstat mkdir rmdir tip whatis
chpass glcdtest more rx touch whereis
chsh globdump msec rz tr who
cmp globread mv sb true whoami
col globwrite nice scc tsort write
comm grep nm scm tty xargs
compress groups nohup sed uname zcat
cp head ntpdate setty uncompress
cpp hostid od sh uniq

# cd /share/examples/asm
# make clean
rm -f *.o ashello echo *.dis *~

# cat ashello.S
/*
* This is an example of MIPS assembly program for RetroBSD.
*
* To compile this program, type:
* cc -c ashello.S
* ld ashello.o -o ashello
*/
#include <syscall.h>

.data // begin data segment
hello: .ascii "Hello, assembly world!\n" // a string

.text // begin code segment
.globl start // entry point for ld
start:
li $a0, 0 // arg 1: stdout fd
la $a1, hello // arg 2: string address
li $a2, 23 // arg 3: string length
syscall SYS_write // call the kernel: write()
nop // returns here on error
nop // skips two words on success

li $a0, 0 // arg 1: exit status
syscall SYS_exit // call the kernel: exit()
// no return

# make ashello
cc -c ashello.S
ld ashello.o -o ashello

# ./ashello
Hello, assembly world!

# cd /share/examples/c
# make clean
rm -f *.o *~ hello stdarg skeleton primelist primesum test1 test2 test3 gpio adc rain q8 tetris lcd6

# cat hello.c
#include <stdio.h>

int main()
{
printf ("Hello, C World!\n");
return 0;
}

# make hello
cc -o hello hello.c

# ./hello
Hello, C World!

# halt
killing processes... done
syncing disks... done
halted
Обратите внимание: работают ассемблер и Си компилятор.
vak: (Daemon)
Нашёлся умный человек, подсказал как собрать на нынешнем Debian 12 (bookworm) симулятор pic32, который я сварганил десять лет назад. Приятно вспомнить.

Главная хитрость - установить Python 2.7. Официально делать это крайне не рекомендуется, но оно работает, как ни странно.
wget http://ftp.debian.org/debian/pool/main/libf/libffi/libffi7_3.3-6_amd64.deb
wget http://ftp.debian.org/debian/pool/main/o/openssl/libssl1.1_1.1.1w-0+deb11u1_amd64.deb
wget http://ftp.debian.org/debian/pool/main/p/python2.7/libpython2.7-minimal_2.7.18-8+deb11u1_amd64.deb
wget http://ftp.debian.org/debian/pool/main/p/python2.7/python2.7-minimal_2.7.18-8+deb11u1_amd64.deb
wget http://ftp.debian.org/debian/pool/main/p/python2.7/libpython2.7-stdlib_2.7.18-8+deb11u1_amd64.deb
wget http://ftp.debian.org/debian/pool/main/p/python2.7/python2.7_2.7.18-8+deb11u1_amd64.deb
sudo dpkg -i libffi7_3.3-6_amd64.deb \
libssl1.1_1.1.1w-0+deb11u1_amd64.deb \
libpython2.7-minimal_2.7.18-8+deb11u1_amd64.deb \
python2.7-minimal_2.7.18-8+deb11u1_amd64.deb \
libpython2.7-stdlib_2.7.18-8+deb11u1_amd64.deb \
python2.7_2.7.18-8+deb11u1_amd64.deb
Теперь соберём и установим QEMU для pic32:
sudo apt install libpixman-1-dev libfdt-dev zlib1g-dev libglib2.0-dev libsdl1.2-dev
git clone https://github.com/sergev/qemu.git
mkdir qemu-build
cd qemu-build
../qemu/configure --prefix=/usr/local/qemu-mips \
--target-list=mipsel-softmmu \
--python=/usr/bin/python2.7 \
--disable-werror
make CFLAGS="-O3 -Wno-error -isystem /usr/include/glib-2.0 -isystem /usr/lib/$(uname -m)-linux-gnu/glib-2.0/include" -j "$(nproc)"
make install
Бинарник QEMU будет установлен как /usr/local/qemu-mips/bin/qemu-system-mipsel. Запустим LiteBSD:
wget https://raw.githubusercontent.com/wiki/sergev/qemu/binaries/boot-wifire.hex
wget https://raw.githubusercontent.com/wiki/sergev/qemu/binaries/vmunix.hex
wget https://raw.githubusercontent.com/wiki/sergev/qemu/binaries/litebsd.zip
unzip litebsd.zip
/usr/local/qemu-mips/bin/qemu-system-mipsel \
-machine pic32mz-wifire \
-nographic \
-monitor none \
-serial vc \
-serial vc \
-serial vc \
-serial stdio \
-bios "boot-wifire.hex" \
-kernel "vmunix.hex" \
-sd "litebsd.img"
Стартует классический юникс 30-летней давности:
Board: chipKIT WiFire
Processor: microAptivP
RAM size: 512 kbytes
Load file: 'boot-wifire.hex', 6916 bytes
Load file: 'vmunix.hex', 522408 bytes
Card0 image 'litebsd.img', 339969 kbytes
Copyright (c) 1982, 1986, 1989, 1991, 1993
The Regents of the University of California. All rights reserved.

4.4BSD-Lite build 13 compiled 2015-01-20
sergev@ubuntu-sergev:LiteBSD/sys/compile/WIFIRE.pic32
cpu: PIC32MZ2048ECG100 rev A4, 200 MHz
oscillator: system PLL div 1:6 mult x50
real mem = 512 kbytes
avail mem = 344 kbytes
using 18 buffers containing 73728 bytes of memory
spi1 at pins sdi=D14/sdo=C1/sck=D1
spi2 at pins sdi=F0/sdo=D11/sck=G6
spi3 at pins sdi=B10/sdo=C4/sck=B14
spi4 at pins sdi=F5/sdo=G0/sck=D10
uart1 at pins rx=F1/tx=D15, interrupts 112/113/114
uart4 at pins rx=F2/tx=F8, interrupts 170/171/172, console
sd0 at port spi3, pin cs=C3
sd0: type I, size 339968 kbytes, speed 12 Mbit/sec
sd0a: partition type b7, sector 2, size 204800 kbytes
sd0b: partition type b8, sector 409602, size 32768 kbytes
sd0c: partition type b7, sector 475138, size 102400 kbytes
bpf: sl0 attached
bpf: lo0 attached
WARNING: preposterous clock chip time -- CHECK AND RESET THE DATE!

starting file system checks.
/dev/rsd0a: file system is clean; not checking
starting network
clearing /tmp
standard daemons: update.
Wed Dec 10 21:07:36 PST 2014

4.4BSD-Lite (bsd.net) (tty4)

login: _
Заходите как root, без пароля. Остановить систему можно командой halt -q.
vak: (Daemon)
Хотите вспомнить молодость? Запустить FreeBSD 1.0, историческую версию 1993 года. Или FreeBSD 2.0.5, версию 1995 года. Нынче это легко делается с помощью современного симулятора QEMU. Он ставится на Ubuntu командой "sudo apt install qemu-system-x86", а на маке "brew install qemu".

Установка юникса в то время требовала много ручной работы. Я подготовил образы дисков с уже установленной минимальной системой, и с настроенной сетью.

FreeBSD 1.0

Скачиваем файл FreeBSD-1.0-qemu.tar.xz. Извлекаем файлы, запускаем:
qemu-system-i386 \
-cpu 486 \
-m 64M \
-rtc base=localtime \
-hda freebsd1.0.qcow \
-netdev user,id=ed1,ipv6=off,hostfwd=tcp::2222-:22 \
-device ne2k_isa,netdev=ed1,mac=00:00:0d:31:04:11,irq=5
Входим как root, без пароля. Смотрим версию ядра, размеры файловых систем, версию компилятора. Останавливается машина командой halt.

FreeBSD 2.0.5

Именно на этой версии большинство народа из моего поколения получало первый юниксный опыт. Скачиваем файл FreeBSD-2.0.5-qemu.tar.xz. Здесь я сделал сразу четыре диска, хотя наполнен только один. Можете размечать их, монтировать и использовать под свои дела.
qemu-system-i386 \
-cpu pentium \
-m 128M \
-rtc base=localtime \
-hda freebsd2.0.5.qcow \
-hdb hdb.qcow \
-hdc hdc.qcow \
-hdd hdd.qcow \
-netdev user,id=ed1,ipv6=off,hostfwd=tcp::2222-:22 \
-device ne2k_isa,netdev=ed1,mac=00:00:0d:31:04:11,irq=5

Сеть настроена. Можете вспоминать, как и откуда скачивать пакеты по FTP и как их устанавливать. 😀

[personal profile] dmarck, заметь: ни тебе rtld, ни ASLR.
vak: (Daemon)
Подрихтовал ещё немного тулзу, и таки добился своего. Можем теперь наблюдать интимные подробности работы динамического загрузчика.

Пример состоит из двух частей, обе написаны на ассемблере.
  • Главная программа foobar.S выдаёт пару текстовых сообщений, вызывая функцию say() из динамической библиотеки. Затем завершается системным вызовом _exit().
  • Бибилиотека lib.S реализует функцию say(), которая выполняет системный вызов write().
Всё это на процессоре arm32 под FreeBSD.



Компилируем, запускаем. Работу динамического загрузчика я сократил для ясности. Инструкции главной программы выделены зелёным, инструкции библиотечной функции сиреневым. Видно, как при первом вызове функции say() её адрес ещё не готов. Активируется динамический загрузчик, находит адрес функции и уходит в неё. При втором вызове say() переход происходит напрямую. Вставка-переходник say@plt занимает три машинных команды.
$ cpp foobar.S | as -o foobar.o -
$ cpp lib.S | as -o lib.o -
$ ld -shared -o lib.so lib.o
$ ld -o foobar foobar.o lib.so
$ export LD_LIBRARY_PATH=.
$ bintrace ./foobar
Starting program: ./foobar
        sp = 0xbfbfeb50
        lr = 0x20025538
      cpsr = 0x10
----------------------------------------------------------- dynamic loader
0x20025538:  e1a0600d   mov r6, sp
        r6 = 0xbfbfeb50
...
(initialize dynamic loader)
...
0x20025590:  e1a0f003   mov pc, r3
----------------------------------------------------------- 00010158 <_start>:
0x00010158:  e300017c   movw r0, #0x17c
        r0 = 0x17c
0x0001015c:  e3400001   movt r0, #1
        r0 = 0x1017c
0x00010160:  ebfffff9   bl #0x1014c
        lr = 0x10164
----------------------------------------------------------- 0001014c <say@plt>:
0x0001014c:  e28fc600   add ip, pc, #0, #12
       r12 = 0x10154
0x00010150:  e28cca01   add ip, ip, #0x1000
       r12 = 0x11154
0x00010154:  e5bcf0c4   ldr pc, [ip, #0xc4]!
       r12 = 0x11218
----------------------------------------------------------- 00010138 <.plt>:
0x00010138:  e52de004   str lr, [sp, #-4]!
        sp = 0xbfbfeb4c
0x0001013c:  e59fe004   ldr lr, [pc, #4]
        lr = 0x10c4
0x00010140:  e08fe00e   add lr, pc, lr
        lr = 0x1120c
0x00010144:  e5bef008   ldr pc, [lr, #8]!
        lr = 0x11214
----------------------------------------------------------- into dynamic loader
0x200255a0:  e92d0c3f   push {r0, r1, r2, r3, r4, r5, sl, fp}
        sp = 0xbfbfeb2c
...
(find symbol 'say' in lib.so)
...
0x200255d4:  e1a0f00c   mov pc, ip
----------------------------------------------------------- 000000d4 <say>:
0x200170d4:  e92d4080   push {r7, lr}
        sp = 0xbfbfeb48
0x200170d8:  e1a01000   mov r1, r0
        r1 = 0x1017c
0x200170dc:  e3a00001   mov r0, #1
        r0 = 0x1
0x200170e0:  e3a02004   mov r2, #4
        r2 = 0x4
0x200170e4:  e3a07004   mov r7, #4
        r7 = 0x4
0x200170e8:  ef000000   svc #0
foo
        r0 = 0x4
        r1 = 0
0x200170ec:  e8bd8080   pop {r7, pc}
        r7 = 0
        sp = 0xbfbfeb50
----------------------------------------------------------- back to _start
0x00010164:  e3000180   movw r0, #0x180
        r0 = 0x180
0x00010168:  e3400001   movt r0, #1
        r0 = 0x10180
0x0001016c:  ebfffff6   bl #0x1014c
        lr = 0x10170
----------------------------------------------------------- 0001014c <say@plt>:
0x0001014c:  e28fc600   add ip, pc, #0, #12
       r12 = 0x10154
0x00010150:  e28cca01   add ip, ip, #0x1000
       r12 = 0x11154
0x00010154:  e5bcf0c4   ldr pc, [ip, #0xc4]!
       r12 = 0x11218
----------------------------------------------------------- 000000d4 <say>:
0x200170d4:  e92d4080   push {r7, lr}
        sp = 0xbfbfeb48
0x200170d8:  e1a01000   mov r1, r0
        r1 = 0x10180
0x200170dc:  e3a00001   mov r0, #1
        r0 = 0x1
0x200170e0:  e3a02004   mov r2, #4
0x200170e4:  e3a07004   mov r7, #4
        r7 = 0x4
0x200170e8:  ef000000   svc #0
bar
        r0 = 0x4
        r1 = 0
0x200170ec:  e8bd8080   pop {r7, pc}
        r7 = 0
        sp = 0xbfbfeb50
----------------------------------------------------------- back to _start
0x00010170:  e3a07001   mov r7, #1
        r7 = 0x1
0x00010174:  e3a00000   mov r0, #0
        r0 = 0
0x00010178:  ef000000   svc #0
Process exited normally.
vak: (Daemon)
Коммерческие операционки перестали поддерживать 32-битные версии, но Линукс и BSD пока не сдаются. В частности, FreeBSD продолжает выпускать образы установщиков и поддерживать репозиторий пакетов для 32-битных ARM процессоров.

Для проверки сего факта я запустил FreeBSD на Олинуксино lime2. Всё работает как ожидается, только порт Ethernet поднять не удалось. Не знаю уж в чём там проблема, ведь под Линуксом порт работает. Может в U-Boot что подконфигурить надо, но мне лень искать.

Запишу здесь процесс для памяти.

(1) Скачать образ диска FreeBSD:
wget https://download.freebsd.org/releases/ISO-IMAGES/14.2/FreeBSD-14.2-RELEASE-arm-armv7-GENERICSD.img.xz
(2) Записать на карточку microSD посредством утилиты balenaEtcher или ещё как-нибудь.

(3) Скачать пакет с загрузчиком U-Boot для платы A20 Olinuxino Lime2:
wget https://pkg.freebsd.org/FreeBSD:14:aarch64/latest/All/u-boot-olinuxino-lime2-2024.07.pkg
(4) Добыть оттуда бинарник загрузчика:
tar xf u-boot-olinuxino-lime2-2024.07.pkg 
mv usr/local/share/u-boot/u-boot-olinuxino-lime2/u-boot-sunxi-with-spl.bin .
(5) Записать загрузчик на ту же карточку microSD поверх образа FreeBSD. Здесь замените /dev/diskN на девайс карточки в вашей системе:
dd if=u-boot-sunxi-with-spl.bin of=/dev/diskN bs=1k seek=8 conv=sync
После этого грузитесь с карточки и заходите в систему с консольного порта, юзер root, пароль root. 
vak: (Daemon)
Я таки смог запустить трассировку на архитектуре ARM32. Для этого пришлось научиться ставить FreeBSD на виртуальном Cortex-A15 под симулятором QEMU.
$ bintrace ./demo-arm32-freebsd
Starting program: ./demo-arm32-freebsd
sp = 0xbfbfeb58
lr = 0x10054
cpsr = 0x10
0x00010054: e3a07004 mov r7, #4
r7 = 0x4
0x00010058: e3a00001 mov r0, #1
r0 = 0x1
0x0001005c: e3001078 movw r1, #0x78
r1 = 0x78
0x00010060: e3401001 movt r1, #1
r1 = 0x10078
0x00010064: e3a0200d mov r2, #0xd
r2 = 0xd
0x00010068: ef000000 svc #0
Hello world!
r0 = 0xd
r1 = 0
0x0001006c: e3a07001 mov r7, #1
r7 = 0x1
0x00010070: e3a00000 mov r0, #0
r0 = 0
0x00010074: ef000000 svc #0
Process exited normally.
vak: (Daemon)
Поддержка архитектуры RISC-V в FreeBSD всё ещё в процессе разработки. Но уже можно запустить ядро на симуляторе QEMU. Вот как это делается.
wget https://download.freebsd.org/snapshots/VM-IMAGES/15.0-CURRENT/riscv64/Latest/FreeBSD-15.0-CURRENT-riscv-riscv64-ufs.raw.xz
xz --decompress FreeBSD-15.0-CURRENT-riscv-riscv64-ufs.raw.xz
qemu-img convert -f raw -O qcow2 FreeBSD-15.0-CURRENT-riscv-riscv64-ufs.raw FreeBSD-15.0-CURRENT-riscv-riscv64-ufs.qcow
qemu-img resize FreeBSD-15.0-CURRENT-riscv-riscv64-ufs.qcow 16G

qemu-system-riscv64 \
-machine virt \
-nographic \
-m 2048M \
-smp 2 \
-bios fw_jump.elf \
-kernel u-boot.bin \
-drive file=FreeBSD-15.0-CURRENT-riscv-riscv64-ufs.qcow,if=none,id=hd0 \
-device virtio-blk-device,drive=hd0 \
-netdev user,id=net0,ipv6=off,hostfwd=tcp::8022-:22 \
-device virtio-net-device,netdev=net0
Вход как root без пароля. Пакетов для RISC-V ещё нету, как я понимаю, поэтому командой pkg ничего установить не удаётся.

Протокол загрузки:
vak: (Daemon)
Всё оказалось просто. Вот исходники глючащей функции: git.musl-libc.org/cgit/musl/tree/src/math/log10l.c

Суть в ифдефах:
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
long double log10l(long double x)
{
return log10(x);
}
#elif LDBL_MANT_DIG == 64 && LDBL_MAX_EXP == 16384

...собственно реализация функции...

#elif LDBL_MANT_DIG == 113 && LDBL_MAX_EXP == 16384
// TODO: broken implementation to make things compile
long double log10l(long double x)
{
return log10(x);
}
#endif
В нашем случае срабатывает именно последний вариант, когда в мантиссе 113 бит и максимальная экспонента равна 16384.

И такого добра там навалом.
$ git clone https://git.musl-libc.org/git/musl
$ cd musl/src/math
$ grep TODO:\ broken *.c
acoshl.c:// TODO: broken implementation to make things compile
asinhl.c:// TODO: broken implementation to make things compile
coshl.c:// TODO: broken implementation to make things compile
erfl.c:// TODO: broken implementation to make things compile
expl.c:// TODO: broken implementation to make things compile
expm1l.c:// TODO: broken implementation to make things compile
lgammal.c:// TODO: broken implementation to make things compile
log10l.c:// TODO: broken implementation to make things compile
log1pl.c:// TODO: broken implementation to make things compile
log2l.c:// TODO: broken implementation to make things compile
logl.c:// TODO: broken implementation to make things compile
powl.c:// TODO: broken implementation to make things compile
sinhl.c:// TODO: broken implementation to make things compile
tanhl.c:// TODO: broken implementation to make things compile
tgammal.c:// TODO: broken implementation to make things compile
То есть никто не тестировал эту библиотеку на компиляторе со 128-битным long double. Тут чинить и чинить.

UPD: правильные реализации можно найти в OpenLibm, к примеру: github.com/JuliaMath/openlibm/blob/master/ld128/e_log10l.c
vak: (Daemon)
Установил Chimera Linux на старенький макбук десятилетней давности. Процесс несложный: записываем ISO образ на флешку и с неё грузимся. Дальше по той же инструкции. Всё работает кроме Wi-Fi. Наверное надо драйвер подгрузить.





Update: с драйвером WiFi всё плохо.
$ lspci
...
02:00.0 Network controller: Broadcom Inc. and subsidiaries BCM4360 802.11ac Dual Band Wireless Network Adapter (rev 03)
Этот чип поддерживается в Линуксе драйвером broadcom-sta. Но чип этот старенький, драйвером никто не занимается и привинчивать к Химере не станет. Проще воткнуть отдельный USB WiFi адаптер, к примеру AC1200.

Отличный ноубук кстати. Хоть и старый, но весьма приятный в работе. Единственное - батарейка заряжается только до 63%.

vak: (Daemon)
Меня неожиданно порадовал этот проект. Не знаю как пойдёт, но у него потенциально большое будущее. Попробую пояснить почему.

Что такое современная опенсорсная операционная система? Это сообщество + ядро + /bin/init + libc + пакеты приложений. Так по пунктам и буду рассуждать.

1. Новая операционная система общего назначения, строящая по принципам скорее BSD чем GNU. То есть сathedral супротив bazaar, в терминах Эрика Рэймонда. За последние десять лет движение BSD стало как-то утрачивать энергию. Здесь есть шанс на возрождение.

2. Используется ядро Linux вместо FreeBSD/NetBSD/OpenBSD. У Линукса огромное преимущество в драйверах и поддержке со стороны бизнеса. Всякий производитель процессоров или компьютерных плат нынче предоставляет версию линукса в драйверами. Для BSD нет смысла пытаться догнать уходящий поезд. Проще к нему присоединиться.

3. Ядро это только половина юникса, а вторую половину, возможно более важную для юзера, определяет набор системных процессов. В классике это был /bin/init, а нынче всё чаще systemd. И то, и другое имеет серьёзные проблемы. Здесь эти проблемы решено рубить радикальным образом, опираясь на современные идеи. Новый подход dinit выглядит весьма неплохо.

4. Теоретически приложения общаются с ядром через системные вызовы, а на практике через набор библиотек нижнего уровня. Условно говоря, это libc, libc++ и прочие. В мире GNU оно всё стандартизовалось вокруг glibc. И это проблема, так как сделано оно там не лучшим образом. Громоздко, часто неэффективно, а переделывать уже поздно: субстанция слиплась и затвердела. 😀 Здесь же за основу взяты библиотеки из мира BSD. Они написаны более качественно, понятно, а главное эффективно и компактно.

5. Установка приложений из централизованных репозиториев и беспроблемное обновление их (и самой операционной системы) по ходу жизни - критически важная часть функциональности. Иначе никто не будет такой системой пользоваться. Те же Debian и Ubuntu обязаны популярностью именно своей системе пакетов и обновлений. Был даже проект kFreeBSD, с ядром BSD и пакетами в формате Debian (не выжил). Многое там сделано по уму, но спроектировано 30 лет назад, тяжеловесное и переусложнённое. Здесь же, в Chimera Linux, взята другая технология пакетов "apk-tools", современная, но хорошо отработанная в Alpine Linux. Однако система сборки пакетов сделана новая, на основе Python. Выгляди намного проще и надёжнее.

Я установил виртуальную Химеру на макбуке, закачал и собрал несколько своих проектов - всё отлично, всё нравится. Поглядим, как дальше у проекта будет судьба складываться. Если кого интересует готовый образ установленной Химеры для UTM - скажите, дам скачать. Ужатый файл размером 1.1 Гбайт.