maharmstone/moxnox: NT-like POSIX-compatible working system · GitHub


Moxnox is an NT-like, POSIX-compatible passion OS which runs on btrfs and is
able to self-hosting. That means:

  • Its design, reminiscent of the selection of syscalls, is modelled after that of Windows
    NT…
  • …but on the similar time, it needs to be able to working software program written for
    Unix-like methods, offered that they’ve been recompiled for it, and comes
    with a full GNU base system
  • It is mature sufficient which you could construct Moxnox on Moxnox
  • And it runs on all people’s favorite Linux filesystem

Version 1.0 is round 130,000 strains of C++, and runs on amd64 and aarch64.

The btrfs code works for primary functions, however has not been battle-hardened.
Please do not attempt to mount something however throwaway filesystems.

To check Moxnox in qemu, obtain moxnox-amd64-1.0.img.gz and moxnox-kernel-amd64-1.0.efi. Run gunzip moxnox-amd64-1.0.img.gz to decompress the picture.

Then:

qemu-system-x86_64 -M q35 -enable-kvm -cpu host -m 1024 
-smp cores=4,threads=1 
-kernel moxnox-kernel-amd64-1.0.efi 
-append "root=/dev/sda" 
-device ich9-ahci,id=ahci -drive id=disk,file=moxnox-amd64-1.0.img,if=none 
-device ide-hd,drive=disk,bus=ahci.0 
-nic consumer,mannequin=virtio-net-pci 
-device qemu-xhci 
-device usb-kbd,id=kbd 
-device usb-tablet,id=pill 
-serial stdio

You might want to enhance the reminiscence from 1024 MB in case you are making an attempt something
strenuous, like self-hosting.

For ARM, one thing just like the beneath ought to work:

qemu-system-aarch64 -M virt -cpu cortex-a76 -m 1024 
-smp cores=4,threads=1 
-kernel moxnox-kernel-aarch64-1.0.efi 
-append "root=/dev/sda" 
-device ich9-ahci,id=ahci -drive id=disk,file=moxnox-aarch64-1.0.img,if=none 
-device ide-hd,drive=disk,bus=ahci.0 
-nic consumer,mannequin=virtio-net-pci 
-drive if=pflash,unit=0,file=/usr/share/qemu/edk2-aarch64-code.fd,readonly=on 
-device qemu-xhci 
-device usb-kbd,id=kbd 
-device usb-tablet,id=pill 
-serial stdio

First, use gparted or much like create a brand new partition. 32 GB needs to be
lots. I’m calling it /dev/nvme0n1p99 beneath – do not get this unsuitable.

Make positive you will have a latest variations of btrfs-progs, as we do not assist some
of the default settings utilized by the older variations.

Prepare the basis drive:

# mkfs.btrfs /dev/nvme0n1p99
# mkdir /mnt/moxnox
# mount /dev/nvme0n1p99 /mnt/moxnox
# cd /mnt/moxnox
# wget https://github.com/maharmstone/moxnox/releases/download/v1.0/moxnox-amd64-1.0.tar.gz
# tar -xvzf moxnox-amd64-1.0.tar.gz
# rm moxnox-amd64-1.0.tar.gz
# cd
# umount /mnt/moxnox

Copy the kernel:

# mount /boot/efi
# cd /boot/efi
# wget https://github.com/maharmstone/moxnox/releases/download/v1.0/moxnox-kernel-amd64-1.0.efi

To set up the boot entry, do one thing like:

# efibootmgr -c -d /dev/nvme0n1 -p 1 -L "Moxnox" -l 'moxnox-kernel-amd64-1.0.efi' -u 'root=/dev/nvme0n1p99'

efibootmgr likes to alter the boot order afterwards, this in all probability will not be
what you need. The names of block gadgets needs to be roughly the identical on
Linux and Moxnox.

The “EFI” file is definitely a polyglot file that additionally conforms to the Linux boot
protocol, so it ought to additionally work on non-EFI GRUB. I’ve not examined this.
How to set this up is left as an train for the reader.

For amd64, every thing is compiled for x86-64-v3, which covers roughly
something manufactured since 2015 or so. Moxnox routinely makes use of and permits
AVX512 if it detects it. For qemu, it’s good to specify the q35 machine kind;
the default computer machine is historic, and does not have PCI Express. microvm
works too.

For aarch64, we’re utilizing LSE atomics, which require ARMv8.1. That means the
Raspberry Pi 5, however not any earlier fashions. Moxnox solely helps ACPI, not
Device Tree, so for the Pi additionally, you will want https://github.com/worproject/rpi5-uefi.
Unfortunately there isn’t a raspi5 machine kind in qemu, however I’ve had success
with virt, and sbsa-ref works too.

Device assist:

  • Block gadgets: NVMe, SATA, SDHCI (i.e. SD playing cards), virtio-block, USB mass
    storage
  • Network playing cards: virtio-net, RTL8168, RTL8125
  • Input gadgets: USB HID, PS/2 keyboard, PS/2 mouse, virtio-input
  • Graphics: virtio-gpu, GOP framebuffer, VBE, VGA textual content console (move textual content=80x25
    on non-UEFI boots)
  • Serial ports: virtio-console, x86 serial port, PL011 ARM serial port
  • USB: XHCI

The best method to construct is to drag the Docker containers maharmstone/moxnox-ci-amd64
or maharmstone/moxnox-ci-aarch64, which include the cross-compilers for
x86_64-pc-moxnox or aarch64-pc-moxnox.

Then within the container:

$ git clone https://github.com/maharmstone/moxnox
$ cd moxnox

CMake will compile whichever of the submodules are checked out. For a minimal
system:

$ git submodule replace --init --depth 1 ports/acpica/repo ports/freetype/repo ports/gnu-efi/repo ports/harfbuzz/repo ports/libpng/repo ports/mingw-w64/repo ports/zlib/repo ports/musl/repo ports/tre/repo

For the entire ports, which could take some time:

$ git submodule replace --init --recursive

Then:

$ mkdir construct
$ cd construct
$ cmake -DCMAKE_TOOLCHAIN_FILE=amd64.cmake -GNinja ..

or

$ cmake -DCMAKE_TOOLCHAIN_FILE=clang-aarch64-native.cmake -GNinja ..

Make positive you specify Ninja – we want this as we’re utilizing C++ modules. CMake
defaults to Unix Makefiles, which do not work.

Finally:

gcc, llvm, and rust will not be compiled except explicitly requested as a result of
their dimension. hexyl and ripgrep additionally should be specified explicitly as a result of
their dependency on rust.

To construct on Moxnox, as above, however you do not want a toolchain file: cmake -GNinja ...
gcc, rust, hexyl, and ripgrep cannot but be compiled in Moxnox, however
every thing else works (ultimately). You might have numerous RAM and much more
endurance. If CMake complains about rust-libc, just be sure you do not have
the Rust submodules checked out.

The kernel and first-party applications are licensed beneath the GPL. The first-party
DLLs are licensed beneath the LGPL. The contents of the modules listing are
MIT.

See the ports submodules for particulars of their explicit licences.

Current ports:

  • bash
  • binutils
  • bison
  • bzip2
  • cairo
  • cmake
  • coreutils
  • curl
  • diffutils
  • expat
  • file
  • findutils
  • flex
  • freetype
  • gawk
  • gcc (amd64 solely)
  • git
  • gmp
  • gperf
  • grep
  • gzip
  • harfbuzz
  • hexyl
  • jsoncpp
  • much less
  • libarchive
  • libiconv
  • libpng
  • librhash
  • libuv
  • llvm
  • m4
  • make
  • mako
  • markupsafe
  • mesa
  • mpc
  • mpfr
  • nano
  • ncurses
  • netcat
  • ninja
  • openssh
  • openssl
  • patch
  • perl
  • pixman
  • python
  • pyyaml
  • readline
  • ripgrep
  • rust
  • sed
  • tar
  • vim
  • wget
  • xz
  • zlib
  • zstd

Loads – however this is model 1.0. In explicit:

  • A GUI
  • Support for various timezones
  • Support for various keyboard layouts
  • Locales and non-UTF-8 character units
  • Any type of safety
  • Multiple customers and teams

For efficiency points and comparable:

  • The userspace heap allocator might be loads faster (that is the bottleneck
    when self-hosting)
  • TCP is sluggish, as a result of we do not negotiate an MSS and preserve to the default 64KB
    window
  • We should be doing early writeback on reminiscence strain
  • There needs to be an LRU system to drop clear pages from the web page cache…
  • …made worse by the truth that the dentry cache by no means will get pruned, so inodes
    keep open till deleted

And clearly there needs to be extra ports and {hardware} assist.

How appropriate is it with NT?

The contract is that the syscalls and low-level interfaces match these of NT,
however not the daemons or how the kernel itself is structured. This is in distinction
to what ReactOS goals to do, which is a precise recreation of Windows.

So:

  • Binaries are PE format fairly than ELF, and have a .exe or .dll extension
  • C++ exceptions are performed by SEH
  • POSIX indicators are performed by Asynchronous Procedure Calls
  • All the non-kernel kernel-like stuff will get performed in ntdll.dll
  • The rcx, rdx, r8, r9 calling conference matches that of Windows
  • And its C eccentricities match these of Windows: sizeof(lengthy) == sizeof(int32_t),
    sizeof(wchar_t) == sizeof(char16_t), sizeof(lengthy double) == sizeof(double).

There’s an terrible lot of stuff in NT, however the attention-grabbing stuff that is lacking
is tokens, the Registry, and I/O completion ports.

NT has a fancy system the place there is a digital filesystem nevertheless it’s hidden
(except you utilize winobj), with the true path of a file hanging off the identify of
its block gadget (so C:WindowsSystem32 may really be DeviceHarddiskVolume1WindowsSystem32).
I’ve not replicated any of that. Paths are POSIX-like: slashes fairly than
backslashes, / as the basis filesystem, and mounted directories. Unlike actual
Windows, NtCreateFile resolves . and .., to work higher with the dentry cache.

Other issues I’ve intentionally not copied are the assorted types of transactions,
which have been a product of their time, and the concept of paged kernel reminiscence, which
causes extra issues than it solves.

How appropriate is it with POSIX?

We have carried out 642 of the ~1,200 capabilities in POSIX 2024. This is the huge
majority of what is utilized in apply, with gnulib papering over a number of the
cracks. Unlike Windows, fork is there. I’ve used musl for its mathematical
and cryptographic capabilities, and mingw for printf and another issues,
and tre for its regexes.

The POSIX capabilities are cut up over ucrtbase, iphlpapi, and ws2_32, as on
Windows, with something that Windows does not implement put in mnposix.

I’ve borrowed liberally from Linux’s greatest concepts: the dentry cache, giant folios,
mapping the entire of bodily reminiscence, evdev.

Other POSIX shortcomings:

  • AF_UNIX is half-complete. socketpair works, together with for SCM_RIGHTS (ssh
    makes use of this), however the regular client-server code does not work
  • mkfifo creates an inode, however I/O to it doesn’t get redirected to a buffer
    because it should do
  • APCs (i.e. indicators) solely get delivered when a thread returns from a syscall.
    So a program doing whereas (true) { } is at the moment unkillable.

There’s nothing that routinely begins daemons but, so manually.

First generate the host key:

There’s no passwords but, so you’ll need so as to add a /root/.ssh/authorized_keys
file to be able to join. If you will have hassle, double-check that /root is
owned by root, as sshd will ignore this file in any other case.

Then begin sshd utilizing its full path:

Can this run Windows applications?

No. Or a minimum of, not but.

We intentionally don’t implement any Win32 DLLs, bar a number of capabilities in
kernelbase that the mingw runtime needs. A future enchancment can be to
strip these out solely, then port throughout Wine’s variations of the Win32 DLLs.
Some components of Wine, like wineserver and ntdll, we might not want as we’re
already taking good care of it ourselves.

None of the substantive code was written by AI.

I used AI to assist with the mechanical components of porting (e.g. translating
autotools to CMake, changing ioctl calls with tcgetwinsize, translating
the C structs into Rust), in addition to to write down a number of the smoke assessments (e.g.
cairo-test, mesa-test).

Where Claude actually shines although is in reviewing your personal commits. You give it
a hash, and it tells you concerning the foolish reminiscence leak or impasse that you just left
in, earlier than you can also make a idiot of your self.

For funsies. Plus the one method of actually studying how one thing works is to
have a go at writing it your self.

Also, the NT kernel is criminally underrated, and just about unknown to
hobbyists. It had options that Linux took years and years to give you its
personal design for, reminiscent of eventfd and pidfd.

It’s a disgrace that Windows retains shying away from full POSIX compatibility. They
had a half-complete model within the early days, then extra lately had WSL1, solely
to then abandon it. And Nano Server was one other cool concept, solely once more to be
itself deserted. So that is my tackle what I want Windows had been like.



Source link