restructure build scripts

This commit is contained in:
Steve Biedermann
2025-11-23 10:24:48 +01:00
parent b1ebd61763
commit e5c4ef7e74
13 changed files with 156 additions and 67 deletions

View File

@@ -2,4 +2,4 @@
target = "aarch64-unknown-none-softfloat"
[target.aarch64-unknown-none-softfloat]
runner = "./qemu-runner.sh"
runner = "scripts/qemu-runner.sh"

1
.gitignore vendored
View File

@@ -1,3 +1,4 @@
/target
/build
.gdb_history
*.img

View File

@@ -66,12 +66,10 @@ x86) before running on bare metal.
## Building and Running
### Prerequisites
You will need QEMU for aarch64 emulation, dosfstools to create the virtual file system
and gcc-aarch64-linux-gnu to compile bash for the image.
You will need QEMU for aarch64 emulation and dosfstools to create the virtual file system.
```bash
# Install QEMU (Ubuntu/Debian), dosfstools and gcc-aarch64-linux-gnu
sudo apt install qemu-system-aarch64 dosfstools gcc-aarch64-linux-gnu
sudo apt install qemu-system-aarch64 dosfstools
```
Additionally you will need a version of the [aarch64-none-elf](https://developer.arm.com/Tools%20and%20Software/GNU%20Toolchain) toolchain installed.
@@ -87,6 +85,27 @@ Run the following command
nix shell nixpkgs#pkgsCross.aarch64-embedded.stdenv.cc nixpkgs#pkgsCross.aarch64-embedded.stdenv.cc.bintools
```
### Preparing the image
First, run the following script to prepare the binaries for the image:
```bash
./scripts/build-deps.sh
```
This will download and build the necessary dependencies for the kernel and put them
into the `build` directory.
Once that is done, you can create the image using the following command:
```bash
sudo ./scripts/create-image.sh
```
This will create an image file named `moss.img` in the root directory of the project,
format it as VFAT 32 and create the necessary files and directories for the kernel.
This script needs to run with sudo to mount the image through a loop device,
which is required to properly create the image for the kernel to work.
### Running via QEMU
To build the kernel and launch it in QEMU:

View File

@@ -1,49 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
IMG="test.img"
MOUNT="/mnt/moss"
if [ -f "$IMG" ]; then
echo "initrd file $IMG already exists. Skipping."
exit 0
fi
dd if=/dev/zero of="$IMG" bs=1M count=128
mkfs.vfat -F 32 "$IMG"
if ! mountpoint -q "$MOUNT"; then
mount -o loop "$IMG" "$MOUNT"
fi
if [ ! -d /tmp/bash ]; then
git clone https://github.com/bminor/bash.git /tmp/bash
fi
pushd /tmp/bash
if [ ! -f "/tmp/bash/bash" ]; then
./configure --without-bash-malloc --enable-static-link --host=aarch64-linux-gnu CC=aarch64-linux-gnu-gcc
make
fi
if [ ! -f "$MOUNT/bin/bash" ]; then
sudo mkdir -p "$MOUNT/bin"
sudo cp bash "$MOUNT/bin"
fi
popd
# busybox -- I couldn't get this to build. I ended up restoring to a third-party static binary which isn't ideal but it get's things running.
pushd "/tmp"
if [ ! -f "$MOUNT/bin/busybox-aarch64-linux-gnu" ]; then
wget https://github.com/shutingrz/busybox-static-binaries-fat/raw/refs/heads/main/busybox-aarch64-linux-gnu
chmod +x busybox-aarch64-linux-gnu
sudo cp busybox-aarch64-linux-gnu "$MOUNT/bin"
fi
popd
sudo mkdir -p "$MOUNT/dev"
if mountpoint -q "$MOUNT"; then
umount "$MOUNT"
fi

View File

@@ -1,11 +0,0 @@
#!/usr/bin/env bash
set -e
ELF="$1"
BIN="${ELF%.elf}.bin"
./mkrootfs-aarch64.sh
# Convert to binary format
aarch64-none-elf-objcopy -O binary "$ELF" "$BIN"
qemu-system-aarch64 -M virt,gic-version=3 -initrd test.img -cpu cortex-a72 -m 2G -smp 4 -nographic -s -kernel "$BIN"

49
scripts/build-deps.sh Executable file
View File

@@ -0,0 +1,49 @@
#!/usr/bin/env bash
set -euo pipefail
base="$( cd "$( dirname "${BASH_SOURCE[0]}" )"/.. && pwd )"
mkdir -p "$base/build/bin"
rm -f "$base/build/bin"/*
pushd "$base/build" &>/dev/null || exit 1
if [ ! -f "aarch64-linux-musl-cross.tgz" ]
then
wget https://musl.cc/aarch64-linux-musl-cross.tgz
tar -xzf aarch64-linux-musl-cross.tgz
fi
popd &>/dev/null || exit 1
build=${build:-$(ls $base/scripts/deps)}
export PATH="$base/build/aarch64-linux-musl-cross/bin:$PATH"
for script in "$base/scripts/deps/"*
do
[ -e "$script" ] || continue # skip if no file exists
[ -x "$script" ] || continue # skip if not executable
filename=$(basename "$script")
if [[ "$filename" == _* ]]
then
echo "Skipping: $filename"
continue
fi
# skip if not in build list
if ! grep -qw "$filename" <<< "$build";
then
echo "Skipping: $filename"
continue
fi
echo "Preparing: $filename"
# make sure each script is run in the base directory
pushd "$base" &>/dev/null || exit 1
bash "$script"
popd &>/dev/null || exit 1
done

27
scripts/create-image.sh Executable file
View File

@@ -0,0 +1,27 @@
#!/usr/bin/env bash
set -euo pipefail
base="$( cd "$( dirname "${BASH_SOURCE[0]}" )"/.. && pwd )"
pushd "$base" &>/dev/null || exit 1
img="$base/moss.img"
mount="$base/build/mount"
mkdir -p "$mount"
dd if=/dev/zero of="$img" bs=1M count=128
mkfs.vfat -F 32 "$img"
if ! mountpoint -q "$mount"; then
mount -o loop "$img" "$mount"
fi
mkdir -p "$mount/bin"
mkdir -p "$mount/dev"
cp "$base/build/bin"/* "$mount/bin"
if mountpoint -q "$mount"; then
umount "$mount"
fi
popd &>/dev/null || exit 1

6
scripts/deps/README.md Normal file
View File

@@ -0,0 +1,6 @@
Every executable file in this directory is executed by `build-deps.sh`.
When writing a new script you can assume you are in the root directory of the project.
Downloads, git repos, etc. should be placed in the `build` directory.
The built binaries should be placed in the `build/bin` directory.

24
scripts/deps/bash Executable file
View File

@@ -0,0 +1,24 @@
#!/usr/bin/env bash
set -euo pipefail
bash_repo="${bash_repo:-https://git.savannah.gnu.org/git/bash.git}"
bash_tag="${bash_tag:-bash-5.3}"
stdlib="${stdlib:-musl}"
pushd "build" &>/dev/null || exit 1
if [ ! -d "bash" ]; then
git clone --depth 1 --branch "$bash_tag" "$bash_repo" "bash"
else
pushd "bash" &>/dev/null || exit 1
git pull
popd &>/dev/null || exit 1
fi
pushd "bash" &>/dev/null || exit 1
./configure --without-bash-malloc --enable-static-link --host="aarch64-linux-$stdlib" CC="aarch64-linux-$stdlib-gcc"
make
mv bash ../bin/bash
popd &>/dev/null || exit 1
popd &>/dev/null || exit 1

12
scripts/deps/busybox Executable file
View File

@@ -0,0 +1,12 @@
#!/usr/bin/env bash
set -euo pipefail
# busybox -- I couldn't get this to build. I ended up restoring to a third-party static binary which isn't ideal but it get's things running.
pushd "build" &>/dev/null || exit 1
wget https://github.com/shutingrz/busybox-static-binaries-fat/raw/refs/heads/main/busybox-aarch64-linux-gnu
chmod +x busybox-aarch64-linux-gnu
mv busybox-aarch64-linux-gnu bin/busybox
popd &>/dev/null || exit 1
popd &>/dev/null || exit 1

11
scripts/qemu-runner.sh Executable file
View File

@@ -0,0 +1,11 @@
#!/usr/bin/env bash
set -e
base="$( cd "$( dirname "${BASH_SOURCE[0]}" )"/.. && pwd )"
elf="$1"
bin="${elf%.elf}.bin"
# Convert to binary format
aarch64-none-elf-objcopy -O binary "$elf" "$bin"
qemu-system-aarch64 -M virt,gic-version=3 -initrd moss.img -cpu cortex-a72 -m 2G -smp 4 -nographic -s -kernel "$bin"

View File

@@ -126,7 +126,7 @@ fn arch_init_stage2(frame: *mut ExceptionState) -> *mut ExceptionState {
cpu_messenger_init(cpu_count());
kmain(
"--init=/bin/sh --rootfs=fat32fs --automount=/dev,devfs".to_string(),
"--init=/bin/bash --rootfs=fat32fs --automount=/dev,devfs".to_string(),
frame,
);

View File

@@ -95,7 +95,7 @@ async fn launch_init(opts: KOptions) {
let mount_point = VFS
.resolve_path(path, VFS.root_inode())
.await
.unwrap_or_else(|e| panic!("Could not find automount path: {e}"));
.unwrap_or_else(|e| panic!("Could not find automount path: {}. {e}", path.as_str()));
VFS.mount(mount_point, fs, None)
.await