Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 1 addition & 5 deletions .github/workflows/build.tcl
Original file line number Diff line number Diff line change
@@ -1,13 +1,9 @@
#!/usr/bin/expect

set timeout 60
spawn sh boot/qemu -ci
spawn sh boot/qemu

# Boot up
expect "Selection: "
send "4\r"
expect "bootfile: "
send "2\r"
expect "term% "

proc terminate {status} {
Expand Down
59 changes: 59 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
name: ci

on:
push:
branches: [main]
pull_request:
workflow_dispatch:

concurrency:
group: ci-${{ github.ref }}
cancel-in-progress: true

jobs:
build:
runs-on: ubuntu-latest
timeout-minutes: 180
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0

- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y qemu-system-x86 expect curl bzip2 \
build-essential libx11-dev libxext-dev libxt-dev libfontconfig1-dev

- name: Check out plan9port
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
repository: 9fans/plan9port
path: plan9port

- name: Build plan9port
run: |
cd plan9port
./INSTALL
test -x bin/9660srv && test -x bin/9p || { echo 'plan9port build incomplete: 9660srv/9p missing' >&2; exit 1; }
echo "PLAN9=$PWD" >>$GITHUB_ENV

- name: Enable KVM
run: |
echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666"' \
| sudo tee /etc/udev/rules.d/99-kvm.rules
sudo udevadm control --reload-rules
sudo udevadm trigger --name-match=kvm

- name: Populate the checkout
run: |
export PATH="$PATH:$PLAN9/bin"
./boot/mkdirs
./boot/getbin

- name: Build every architecture
run: ./boot/test build

- name: Smoke 386
run: ./boot/test smoke -386

- name: Smoke amd64
run: ./boot/test smoke -amd64
8 changes: 5 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -26,17 +26,19 @@ bootdisk.img
env
lib/audio
lib/tftpd/faa1159e
mail/box/glenda/mbox
pbsraw
rc/bin/_*
usr/djc
usr/glenda/tmp
sys/doc/**/*.pdf
sys/doc/**/*.ps
sys/lib/dist/bin
sys/lib/dist/pc/multi
sys/lib/firmware
sys/log
sys/src/9k/root/nvram
sys/src/cmd/unix/u9fs/u9fs
usr/djc
usr/glenda/tmp
rc/bin/_*
*.[5678ijqv]
[5678ijqv].*
*.a[5678ijqv]
Expand Down
2 changes: 2 additions & 0 deletions 386/include/ape/_apetypes.h
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
/* 32-bit ABI: leave _BITS64 undefined */

#if !defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN)
#define __BYTE_ORDER __LITTLE_ENDIAN
#endif
Expand Down
1 change: 1 addition & 0 deletions 386/include/u.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ typedef unsigned int uint;
typedef signed char schar;
typedef long long vlong;
typedef unsigned long long uvlong;
typedef long intptr;
typedef unsigned long uintptr;
typedef unsigned long usize;
typedef uint Rune;
Expand Down
124 changes: 89 additions & 35 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,82 +42,136 @@ There are original README.md below.
9legacy
=======

[![CI](https://github.com/0intro/9legacy/actions/workflows/ci.yml/badge.svg)](https://github.com/0intro/9legacy/actions/workflows/ci.yml)

[9legacy](http://9legacy.org/) is a continuation of [Plan 9 from Bell Labs](https://9p.io/plan9).

# Usage
# 1. Usage

`boot/qemu` runs Plan 9 under QEMU with this tree as the guest's root file
system. An edit on the host is an edit in the running system. By default it
serves the tree over a virtio-9p device and boots an ELF kernel with multiboot.
`-9fat` boots the virtio-9p root from a 9fat menu disk instead. `-u9fs` serves
the tree with u9fs over 9P-over-TCP and boots `boot/pxeboot.raw` over tftp
through the PXE loader. That last path is slower, but doesn't depend on the
multiboot ELF or the virtio-9p driver.

## Run Plan 9 on QEMU
Quit QEMU with `Ctrl-a x`.

1. Build empty directory hierarchy
## 1.1. Prepare the tree

Empty directories can't be committed to a Git repository.
Do this once before the first boot.

The following script will build the empty directory hierachy, identically
to the content of the original Plan 9 CD image.
1. Build the empty directories

Run:
Git won't store an empty directory. `boot/mkdirs` creates the ones Plan 9
expects, matching the original CD image.

```
./boot/mkdirs
```

2. Install binaries

This step requires the [9660srv](https://github.com/9fans/plan9port/tree/master/src/cmd/9660srv)
command from [plan9port](https://github.com/9fans/plan9port),
so the CD image will be mounted using the Plan 9 ISO 9660 extension.
2. Install the binaries

The following script will download the last 9legacy CD image and extract
the 386 and amd64 binaries to the root of the Git repository.

Run:
`boot/getbin` downloads the latest 9legacy CD image and copies the 386 and
amd64 binaries, libraries and kernels into the tree. It reads the image with
`9660srv` and `9p` from [plan9port](https://github.com/9fans/plan9port), which
must be installed.

```
./boot/getbin
```

3. Run QEMU
## 1.2. virtio-9p mode

With no arguments `boot/qemu` boots the 386 terminal kernel over virtio-9p, on
the serial console, with four CPUs and QEMU's slirp networking.

The following script will build u9fs from [sys/src/cmd/unix/u9fs](https://github.com/0intro/9legacy/tree/main/sys/src/cmd/unix/u9fs),
if needed, then run QEMU.
```
./boot/qemu # 386 terminal (default)
./boot/qemu -amd64 # amd64 terminal
./boot/qemu -cpu # 386 cpu server
./boot/qemu -amd64 -cpu # amd64 cpu server
./boot/qemu -smp 8 # eight CPUs
```

### 1.2.1. Graphics

Run the following script to build u9fs and run QEMU:
`-vga` opens a window and runs rio at 1920x1080. Change the resolution with
`vgasize` at the top of `boot/qemu`.

```
./boot/qemu
./boot/qemu -vga
./boot/qemu -amd64 -vga
```

## Rebuild boot/pxeboot.raw
### 1.2.2. Boot from the 9fat disk

This Git repository already includes a prebuilt `boot/pxeboot.raw` boot loader.
`boot/qemu -9fat` boots a small 9fat disk that holds every kernel behind a boot
menu. Build the disk once inside a guest with `mk9fat`, then pick a kernel at
the `Selection:` prompt.

This step is necessary only if you want to rebuild `boot/pxeboot.raw`, for example,
after making changes to the boot loader.
```
mk9fat # in the guest, writes boot/9fat.raw
./boot/qemu -9fat
```

1. Reduce the size of 9bootpbs
## 1.3. u9fs mode

Apply the following patch to reduce the size of 9bootpbs:
`boot/qemu -u9fs` is the original mode. It builds u9fs from
[sys/src/cmd/unix/u9fs](https://github.com/0intro/9legacy/tree/main/sys/src/cmd/unix/u9fs),
boots `boot/pxeboot.raw` over tftp, and serves the tree with u9fs over
9P-over-TCP. It boots the stock kernel through the PXE loader.

```
patch -p1 boot/9-pcboot-boot.diff
./boot/qemu -u9fs
```

2. Rebuild 9bootpbs
## 1.4. Rebuild the boot images

On Plan 9, run:
`boot/pxeboot.raw`, the PXE loader for `-u9fs`, is committed. `boot/9fat.raw`,
the menu disk for `-9fat`, is built on demand. `boot/regen` rebuilds both from
the host. It boots a guest and runs `mkbootpbs`, `mkpxeboot` and `mk9fat`.

```
./boot/regen
```

To rebuild `boot/pxeboot.raw` by hand, shrink 9bootpbs and build the loader in a
guest. The boot ramdisk shadows `/boot`, so the diff is read from `/root/boot`:

```
cd / && ape/patch -p1 < /root/boot/9-pcboot-boot.diff
mkbootpbs
mkpxeboot # writes boot/pxeboot.raw
```

Test the new loader with `./boot/qemu -u9fs`.

To rebuild `boot/9fat.raw` by hand, run `mk9fat` in a guest. It lays 9load,
every installed kernel and a plan9.ini boot menu onto the disk, with the root
over virtio-9p.

```
mk9fat
```

3. Rebuild pxeboot.raw
# 2. Test

On Plan 9, run:
`boot/test` drives a guest through a CI task and reports on the serial console.

```
mkpxeboot
boot/test build # boot 386, build every architecture
boot/test smoke -386 # boot 386, compile and run the smoke test
boot/test smoke -amd64 # boot amd64, compile and run the smoke test
```

# Thanks
The smoke test is `usr/glenda/src/smoke/smoke.c`. It checks the compiler and
library, then stresses the allocator, processes, pipes, the file system and the
network. GitHub Actions runs all three on every push and pull request. See
`.github/workflows/ci.yml`.

# 3. Thanks

We thank Russ Cox, who made the scripts to easily boot a Plan 9 file hierarchy on QEMU.
We thank Russ Cox, who made the original scripts to easily boot a Plan 9 file
hierarchy on QEMU.
13 changes: 12 additions & 1 deletion amd64/include/u.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,23 @@ typedef unsigned int uint;
typedef signed char schar;
typedef long long vlong;
typedef unsigned long long uvlong;
typedef long long intptr;
typedef unsigned long long uintptr;
typedef unsigned long usize;
/*
* changing usize width from ulong changes system call binary interface due to
* dubious use of va_arg(list, usize) in 9k/port, thus breaks compatibility with
* binaries in the dump.
*/
typedef unsigned long usize;
typedef uint Rune;
typedef union FPdbleword FPdbleword;
typedef uintptr jmp_buf[2];
#define JMPBUFSP 0
#define JMPBUFPC 1
#define JMPBUFDPC 0
typedef unsigned int mpdigit; /* for /sys/include/mp.h */

/* rarely needed and overused */
typedef unsigned char u8int;
typedef unsigned short u16int;
typedef unsigned int u32int;
Expand Down Expand Up @@ -55,6 +63,7 @@ union FPdbleword
};
};

/* stdarg - little-endian 64-bit */
typedef char* va_list;
#define va_start(list, start) list =\
(sizeof(start) < 8?\
Expand All @@ -70,3 +79,5 @@ typedef char* va_list;
(sizeof(mode) == 4)?\
((list += 8), (mode*)list)[-2]:\
((list += sizeof(mode)), (mode*)list)[-1])

#define _BITS64 /* for ape */
2 changes: 2 additions & 0 deletions arm/include/ape/_apetypes.h
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
/* 32-bit ABI: leave _BITS64 undefined */

#if !defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN)
#define __BYTE_ORDER __LITTLE_ENDIAN
#endif
Expand Down
Loading
Loading