experiments
April 17

Macintosh II, A/UX и "ботинкоклюв"

На дворе 1994й год, Джей и Молчаливый Боб только начинают тусить «у фасада одного неизвестного магазина» в Джерси, а компьютеры Apple продаются с настоящим юниксом вместо MacOS. Просто потому что последнего еще нет на свете.

Увы, но 90е давно закончились, Джей и Боб постарели — внезапно Джею уже за 50 (+двое детей), зато осталась возможность оживить давно умершее и насладиться духом тех удивительных лет.

Что мы сейчас и будем делать.

В работе, с выходом в интернет.

Исходный код доработанной версии эмулятора с поддержкой сети и сборкой под FreeBSD выложен в репозитории на Github.

История

Разумеется я не застал те времена и вообще с продукцией Apple познакомился только через 20 лет. В родном отечестве наверное только Тема Лебедев успел поработать с Macintosh II и реальной (а не эмулируемой) A/UX:

A/UX 3.0 was praised in the August 1992 issue of InfoWorld by the same author, describing it as "an open systems solution with the Macintosh at its heart" where "Apple finally gets Unix right".

Поскольку дело происходило до триумфального возвращения Джобса, компьютер Macintosh II смахивал на самую обычную офисную персоналку от IBM тех лет:

Восстановленный Apple II, процесс восстановления тут.

Начинка правда отличалась от обычных PC, до принятия x86-архитектуры пройдет еще 20 лет:

The Macintosh II is built around the Motorola 68020 processor operating at 16 MHz, teamed with a Motorola 68881 floating-point unit.

Все, кто интересовался историей Apple думаю в курсе, что увольнение Джобса поставило компанию на грань выживания, поскольку без его дизайнерского таланта выехать на одной только инженерной составляющей продукта не получалось.

Применительно к Macintosh II это выглядело как-то так:

Eighteen months after its introduction, the Macintosh II was updated with a more powerful CPU and sold as the Macintosh IIx.[7] In early 1989, the more compact Macintosh IIcx was introduced at a price similar to the original Macintosh II,[8] and by the beginning of 1990 sales stopped altogether.[9]

Бардак, разброд и корпоративная шиза бюрократия, характерная для мелких китайских (и текущих отечественных) производителей начала 2000х, но не для легендарного бренда — тот самый бардак, который Джобс вынужден был разгребать по возвращению в компанию.

Компьютеры Macintosh II и операционную систему A/UX Джобс в итоге «зачистил», а их история закончилась так:

Contrary to all announcements, Apple eventually canceled A/UX 4.0. The final release of A/UX is version 3.1.1 of 1995.[19] Apple had abandoned A/UX completely by 1996.

«Abandoned completely» звучит особенно пикантно, поскольку речь идет о целой операционной системе, со средствами разработки и собственным графическим интерфейсом (MacX).

Эмулятор

Проект «Shoebill» (тот самый «ботинкоклюв» в дословном переводе) за авторством Peter Rutenbar я нашел совершенно случайно, внимание привлекла лаконичная аннотация:

Shoebill is an all-new, BSD-licensed Macintosh II emulator designed from the ground up with the singular goal of running A/UX.

Этот эмулятор был написан для одной единственной цели, эмулирует одну машину (хотя и с разными конфигурациями) и запускает одну ОС.

Что не может не радовать, поскольку столь узкая специализация позволяет проекту не разрастаться вширь до бесконечности, оставаясь в разумных пределах, доступных для поддержки одним разработчиком.

Проект Shoebill достаточно старый, активная разработка шла в 2014-2015м годах и с тех пор ничего нового и радикального не добавлено, несмотря на предупреждение автора:

I just wanted to say that I appreciate some folks are still using Shoebill and submitting issues and pull requests. I wish I could continue working on this project, but there's a likely conflict of interest, and so I've mostly avoided pushing changes. I apologize for being unable to address the many, many bugs in this repo. (Also for anyone unaware, Qemu is now able now to run A/UX 3.x on its emulated Quadra 800.)

стоит сказать, что он несет х#йню Qemu — большой и сложный проект с огромным количеством участников, которые постоянно ломают обратную совместимость и выкидывают поддержку устаревших систем.

Проект «Shoebill» же, несмотря на несерьезное отношение даже от своего автора — компактен, что позволяет использовать его для половых утех и извращений разных интересных экспериментов.

Что я сделал, вначале прикрутив сеть а затем портировав эмулятор на FreeBSD.

Сборка

Эмулятор разрабатывался и использовался в основном под MacOS и Windows, поэтому поддержка Linux тут по остаточному принципу.

В этой статье мы занимаемся сборкой под Linux и FreeBSD, поэтому такого красивого интерфейса не увидим:

У нас будет одна только консоль.

Забираем:

git clone https://github.com/pruten/shoebill.git

Несмотря на наличие Makefile в корне, сборка для Linux запускается отдельно, специальным скриптом:

cd sdl-gui
./lin_build.sh

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

При попытке сборки появится ошибка:

sdl.c:497:20: error: ‘sys_errlist’ undeclared (first use in this function)
  497 |                    sys_errlist[errno]);

Которая появляется из-за того что функция sys_errlist давным-давно была объявлена устаревшей а ныне удалена совсем из современных версий glibc.

Поскольку никакой логики, связанной с дальнейшим использованием этой функции обнаружено не было, ее вызов я просто закомментировал, заменив на подстановку errno:

if (f == NULL) {
            printf("Can't open pram_path! [%s] [errno=%s]\n",
                   user_params.pram_path,errno);
        //           sys_errlist[errno]);
            return 0;
}

После этого исправления, сборка проходит и появляется запускаемый бинарник эмулятора:

При попытке запуска он потребует загрузочные образы ROM (загрузочная дискета) и жесткого диска.

Я не стал заморачиваться полной установкой A/UX и взял готовый образ с уже установленной ОС, но если вам интересно пройти процесс целиком — тут и тут есть пошаговые руководства как это сделать.

ROM для Mac II был взят отсюда, хотя он же присутствует в готовой сборке выше.

Все ROM-файлы для старых компьютеров находятся вот в этом архиве с поэтическим названием:

Нужный файл называется 1987-12 - 9779D2C4 - MacII (800k v2).ROM.

Таким образом, целиком команда запуска выглядит как-то так:

./shoebill disk0=disk/AUX_3_1_1GB.dsk rom=./disk/1987-12\ -\ 9779D2C4\ -\ MacII\ \(800k\ v2\).ROM 

Пойдет загрузка системы, сразу в графике:

После завершения проверки диска на ошибки, A/UX перезагрузится и вы узрите пользовательский режим:

Сработает автоматический вход (который можно отключить — см. ниже) и вы попадете в систему как суперпользователь, с полным доступом.

Возвращение фокуса из окна эмулятора в основное окружение происходит по нажатию правой кнопки мыши.

При запуске эмулятор неправильно отображает версию:

Официально последняя версия Shoebill это 0.0.5, но делая релизную сборку, автор забыл обновить версию в ветке master, из которой мы и собирали эмулятор.

Судя по истории коммитов, последние изменения все же находятся в master, так что все в порядке — технически мы собирали незаконченную версию 0.0.6.

Работа с сетью

Без сети фана не бывает, поэтому я постарался оперативно ее добавить.

Официальной поддержки сети в линуксовой версии нет, но мне удалось без особых проблем восстановить логику используя версии для Mac и Windows.

Все доработки необходимо внести в один единственный файл sdl.c, который находится в каталоге sdl-gui.

Вначале добавляем необходимые заголовки (после 34й строки):

#include <sys/ioctl.h>
#include <linux/if.h>
#include <linux/if_tun.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

Затем в метод _setup_shoebill добавляем логику инициализации сети, перед вызовом функции shoebill_start():

..
int tun_fd;
struct ifreq ifr;

// открытие tun/tap устройства, с недавних пор оно в Linux одно 
// и универсальное
if ((tun_fd = open("/dev/net/tun", O_RDWR)) < 0) {
        perror("Failed to open TUN device");
        exit(1);
}
// заполнение структуры для инициализации	
char tun_name[IFNAMSIZ];
strcpy(tun_name, "tap0");

// Configure the TUN device
memset(&ifr, 0, sizeof(ifr));
ifr.ifr_flags = IFF_TAP | IFF_NO_PI |  IFF_UP;   
strncpy(ifr.ifr_name, tun_name, IFNAMSIZ);
// вызов SYSCALL для настройки устройства
if (ioctl(tun_fd, TUNSETIFF, (void *)&ifr) < 0) {
        perror("Failed to configure TUN device");
        close(tun_fd);
        exit(1);
}

printf("TAP device name: %s\n", ifr.ifr_name);
// MAC-адрес
uint8_t ethernet_addr[6] = {0x22, 0x33, 0x55, 0x77, 0xbb, 0xdd};
// внутренняя инициализация виртуальной сетевой карты    
shoebill_install_ethernet_card(&config, 13, ethernet_addr,tun_fd); 
..

Такая логика не позволит использовать эмулятор без предварительной настройки сети (см. ниже), поэтому в финальной версии код немного переделан — добавлен пропуск инициализации при отсутствии tun/tap- устройства.

При запуске эмулятора теперь будет показано название TAP-устройства, так что не ошибетесь.

Перед использованием эмулятора, необходимо выполнить ряд шагов на хосте - для создания виртуального TAP-устройства и включения его в сеть.

Все шаги необходимо выполнять с правами root.

На стороне хоста создаем мост и tap-интерфейс:

brctl addbr auxbr
ip tuntap add mode tap tap0
ifconfig tap0 up
brctl addif auxbr tap0
ifconfig auxbr 10.0.2.1 netmask 255.255.255.0

Этого хватит для базовой настройки сети между хостом и гостевой системой, но если вы хотите выходить в интернет непосредственно из A/UX — нужно выполнить дополнительные шаги:

brctl setfd auxbr 0
sysctl net.ipv4.ip_forward=1
iptables --table nat -A POSTROUTING --out-interface wlan0 -j MASQUERADE

Где wlan0 это название вашего внешнего интерфейса (где есть доступ к интернету), у меня на машине он называется wlp0s20f3.

Выполнив все эти шаги, запускаем эмулятор и открываем Command Shell:

В консоли пишем:

newconfig

Появится диалог настройки сети, нажимаем y:

Вводим имя хоста (естественно по-английски), домен пропускаем просто нажав Enter:

Следующим шагом вводим IP-адрес и маску:

10.0.2.2
255.255.255.0

И нажимаем Enter для подтверждения:

Тут индеец "Острый Глаз" немного ошибся и ввел неправильный IP-адрес, не обращайте внимание.

DHCP не поддерживается в A/UX, поскольку его тогда еще не придумали:

DHCP was first defined in October 1993.[5][6]

Система попросит ее перезагрузить, после чего сетевой интерфейс ae0 должен быть виден в системе:

Тут тоже будет отображаться IP-адрес 10.0.2.2

Должен работать ping как с хоста в гостевую A/UX:

Так и из A/UX к хосту:

Для продолжения сетевой оргии, включаем маршрутизацию уже на стороне A/UX:

Теперь с учетом описанной выше настройки на хосте, должны уходить пинги и наружу:

8.8.8.8 это IP-адрес одного из очень известных серверов Google.

Включаем DNS:

Ну разве не прелесть?

Чтобы сохранить настройку маршрутизации между перезагрузками, стоит добавить установку маршрута по-умолчанию в скрипт запуска:

echo /usr/etc/route add default 10.0.2.1 1 >> /etc/rc

Работает ftp:

Порт для FreeBSD

Для сборки на FreeBSD используется тот же самый скрипт lin_build.sh в каталоге sdl_gui, но немного измененный:

Во-первых изменен путь в заголовке с /bin/bash на /usr/local/bin/bash , во вторых в качестве компилятора указан gcc13:

CC=gcc13

И gcc13 в FreeBSD это прямо и есть запускаемый бинарник компилятора:

Одного исправления скрипта сборки достаточно для того чтобы успешно собрать эмулятор:

Теперь добавляем поддержку сети.

Поддержка сети

На удивление повторить доработку с TAP-устройством оказалось даже проще чем в Linux, ниже описаны правки именно для FreeBSD, но в конечной версии и те и другие сведены в одну кодовую базу с переключением по #ifdef.

Точно также как и в линуксовой редакции, нужно добавить два блока в файл sdl.c из каталога sdl_gui.

Блок с заголовочными файлами (строка 34):

#include <fcntl.h>

а также блок с кодом в функции _setup_shoebill (строка 460), перед вызовом метода shoebill_start():

..
int tun_fd;

// Open the TUN device
if ((tun_fd = open("/dev/tap0", O_RDWR)) < 0) {
        perror("Failed to open TUN device");
        exit(1);
}
// MAC адрес
uint8_t ethernet_addr[6] = {0x22, 0x33, 0x55, 0x77, 0xbb, 0xdd};
// вызов внутренней инициализации устройства    
shoebill_install_ethernet_card(&config, 13, ethernet_addr,tun_fd);   
..  

Настройка сети со стороны хоста выглядит следующим образом (выполнять необходимо также с правами root):

sysctl net.link.tap.up_on_open=1
ifconfig bridge0 create
ifconfig tap0 create
ifconfig bridge0 addm tap0 wlan0
ifconfig tap0 inet 10.0.2.1/24 up

В работе:

Кто еще вам покажет такую прелесть?

Проблема с курсором

Вам может встретиться неприятный баг, когда курсор «задваивается», а попытка освобождения фокуса окна эмулятора не отрабатывает.

К сожалению проблема связана с особенностями работы библиотеки SDL и поправить ее из клиентского приложения не получится:

Btw, speaking about cursors, I’ve also found an oddity, which affects
all the supported platforms:
I think that if SDL emulates the cursor (so, uses SW cursor), and the
video surface is a HWSURFACE, then SDL_UpdateRects() will not draw the
cursor, because that branch of the ‘if’ has no logic to handle SW cursor.

Возникает эффект при отсутствии аппаратного ускорения:

Которое в актуальной версии FreeBSD (14.2) на момент написания статьи отваливается при переключении TTY.

Баг плавающий, возникает не всегда и по идее может появиться и в Linux-версии.

Настройка A/UX

Немного расскажу и покажу что есть внутри этой замечательной системы из далекого прошлого.

Для начала тут есть цвета:

Включаются они нажатием по яблоку в левом верхнем углу, затем пункт меню Control Panels -> Monitors.

К сожалению настройка слетает после перезагрузки A/UX и как ее сохранять пока не придумал.

Отключение автоматического входа

Если вам надоело каждый раз автоматически попадать на рабочий стол из под root, то эту опцию можно отключить:

First, you should disable the automatic login feature. Delete the "Autologin" file from /mac/sys/Login System Folder/Preferences. Apple Knowledge Base Article 17627. This will force people to log in using a username and password.

Надо удалить файл c названием Autologin в каталоге /mac/sys/Login System Folder/Preferences:

Затем в консоли введите passwd и запустится стандартный для UNIX-системы диалог смены пароля, для текущего пользователя (root).

Следующим шагом введите adduser , запустится диалог создания нового пользователя.

Поскольку мы убрали автоматический вход, после перезагрузки будет ожидать приглашение на ввод логина и пароля:

Как видите еще в 1994м году компанию Apple сильно #бала длина вашего пароля:

Ну и собственно вот так это выглядит из-под обычного пользователя:

После отключения автоматического входа, система будет просить пароль root для перезагрузки или выключения:

Удивительная система.

Эпилог

Оказалось, что Apple II и Macintosh II - две разные машины, а не разные названия одного и того же, о чем я не знал когда дорабатывал эмулятор.

Хотя ни того ни другого в живую я никогда не видел, увы.

Поэтому статью пришлось переименовать.