mirror of
https://github.com/edera-dev/sprout.git
synced 2025-12-18 15:00:18 +00:00
initial commit
This commit is contained in:
36
.gitignore
vendored
Normal file
36
.gitignore
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
/target
|
||||
|
||||
# Infrastructure
|
||||
.env
|
||||
.terraform
|
||||
terraform.tfstate
|
||||
terraform.tfstate.backup
|
||||
aws-packer-config.json
|
||||
override.install.sh
|
||||
|
||||
# Ignore the google cloud auth creds created in Actions workflows
|
||||
gha-creds-*.json
|
||||
crane
|
||||
tok
|
||||
|
||||
# IDE
|
||||
/.idea
|
||||
/.vscode
|
||||
|
||||
# Benchmarks
|
||||
/results
|
||||
|
||||
# cli markdown output
|
||||
cli.md
|
||||
|
||||
# precommit hooks
|
||||
.editorconfig
|
||||
.markdownlint-cli2.jsonc
|
||||
.pre-commit-config.yaml
|
||||
.prettierrc
|
||||
.shellcheckrc
|
||||
|
||||
# example outputs
|
||||
/image-cache
|
||||
|
||||
/out
|
||||
141
Cargo.lock
generated
Normal file
141
Cargo.lock
generated
Normal file
@@ -0,0 +1,141 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "bit_field"
|
||||
version = "0.10.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e4b40c7323adcfc0a41c4b88143ed58346ff65a288fc144329c5c45e05d70c6"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.9.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2261d10cca569e4643e526d8dc2e62e433cc8aba21ab764233731f8d369bf394"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9"
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.28"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.101"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ptr_meta"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b9a0cf95a1196af61d4f1cbdab967179516d9a4a4312af1f31948f8f6224a79"
|
||||
dependencies = [
|
||||
"ptr_meta_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ptr_meta_derive"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7347867d0a7e1208d93b46767be83e2b8f978c3dad35f775ac8d8847551d6fe1"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.41"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ce25767e7b499d1b604768e7cde645d14cc8584231ea6b295e9c9eb22c02e1d1"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sprout"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"uefi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.106"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ucs2"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "df79298e11f316400c57ec268f3c2c29ac3c4d4777687955cd3d4f3a35ce7eba"
|
||||
dependencies = [
|
||||
"bit_field",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "uefi"
|
||||
version = "0.35.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "da7569ceafb898907ff764629bac90ac24ba4203c38c33ef79ee88c74aa35b11"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cfg-if",
|
||||
"log",
|
||||
"ptr_meta",
|
||||
"ucs2",
|
||||
"uefi-macros",
|
||||
"uefi-raw",
|
||||
"uguid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "uefi-macros"
|
||||
version = "0.18.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b3dad47b3af8f99116c0f6d4d669c439487d9aaf1c8d9480d686cda6f3a8aa23"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "uefi-raw"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7cad96b8baaf1615d3fdd0f03d04a0b487d857c1b51b19dcbfe05e2e3c447b78"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"uguid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "uguid"
|
||||
version = "2.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ab14ea9660d240e7865ce9d54ecdbd1cd9fa5802ae6f4512f093c7907e921533"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f63a545481291138910575129486daeaf8ac54aee4387fe7906919f7830c7d9d"
|
||||
8
Cargo.toml
Normal file
8
Cargo.toml
Normal file
@@ -0,0 +1,8 @@
|
||||
[package]
|
||||
name = "sprout"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies.uefi]
|
||||
version = "0.35.0"
|
||||
features = ["alloc"]
|
||||
24
Dockerfile
Normal file
24
Dockerfile
Normal file
@@ -0,0 +1,24 @@
|
||||
# syntax=docker/dockerfile:1.7-labs
|
||||
ARG RUST_PROFILE=release
|
||||
ARG RUST_TARGET_SUBDIR=release
|
||||
|
||||
FROM --platform=$BUILDPLATFORM rustlang/rust:nightly-alpine@sha256:b8107fa66d3e5ad7f729d3347c7feedbd3f4b60b01006edce39eb6b994ff00bd AS build
|
||||
RUN apk --no-cache add musl-dev busybox-static
|
||||
ARG RUST_PROFILE
|
||||
RUN adduser -S -s /bin/sh build
|
||||
COPY \
|
||||
--exclude=rust-toolchain.toml \
|
||||
--chown=build:build \
|
||||
. /build
|
||||
WORKDIR /build
|
||||
ARG TARGETPLATFORM
|
||||
ARG RUST_TARGET_SUBDIR
|
||||
RUN if [ "${TARGETPLATFORM}" = "linux/amd64" ] || [ "${TARGETPLATFORM}" = "linux/x86_64" ]; then \
|
||||
rustup target add x86_64-unknown-uefi; cargo build --bin sprout --profile "${RUST_PROFILE}" --target x86_64-unknown-uefi && \
|
||||
cp "target/x86_64-unknown-uefi/${RUST_TARGET_SUBDIR}/sprout.efi" /sprout.efi; fi
|
||||
RUN if [ "${TARGETPLATFORM}" = "linux/arm64" ] || [ "${TARGETPLATFORM}" = "linux/aarch64" ]; then \
|
||||
rustup target add aarch64-unknown-uefi; cargo build --bin sprout --profile "${RUST_PROFILE}" --target aarch64-unknown-uefi && \
|
||||
cp "target/aarch64-unknown-uefi/${RUST_TARGET_SUBDIR}/sprout.efi" /sprout.efi; fi
|
||||
|
||||
FROM scratch AS final
|
||||
COPY --from=build /sprout.efi /sprout.efi
|
||||
1
LICENSE
Normal file
1
LICENSE
Normal file
@@ -0,0 +1 @@
|
||||
This repository is proprietary and owned by Edera, Inc.
|
||||
22
boot/Dockerfile
Normal file
22
boot/Dockerfile
Normal file
@@ -0,0 +1,22 @@
|
||||
FROM --platform=$BUILDPLATFORM debian:trixie@sha256:fd8f5a1df07b5195613e4b9a0b6a947d3772a151b81975db27d47f093f60c6e6 AS build
|
||||
ARG BUILDPLATFORM
|
||||
ARG EFI_NAME
|
||||
RUN export DEBIAN_FRONTEND=noninteractive && apt-get update && apt-get install -y \
|
||||
parted dosfstools mtools && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
WORKDIR /work
|
||||
COPY sprout.efi /work/${EFI_NAME}.EFI
|
||||
COPY kernel.efi /work/KERNEL.EFI
|
||||
RUN truncate -s256MiB sprout.img && \
|
||||
parted --script sprout.img mklabel gpt > /dev/null 2>&1 && \
|
||||
parted --script sprout.img mkpart primary fat32 1MiB 100% > /dev/null 2>&1 && \
|
||||
parted --script sprout.img set 1 esp on > /dev/null 2>&1 && \
|
||||
mkfs.vfat -F32 -n EFI sprout.img && \
|
||||
mmd -i sprout.img ::/EFI && \
|
||||
mmd -i sprout.img ::/EFI/BOOT && \
|
||||
mcopy -i sprout.img ${EFI_NAME}.EFI ::/EFI/BOOT/ && \
|
||||
mcopy -i sprout.img KERNEL.EFI ::/EFI/BOOT/ && \
|
||||
mv sprout.img /sprout.img
|
||||
|
||||
FROM scratch AS final
|
||||
COPY --from=build /sprout.img /sprout.img
|
||||
17
hack/autofix.sh
Executable file
17
hack/autofix.sh
Executable file
@@ -0,0 +1,17 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
cd "$(dirname "${0}")/.." || exit 1
|
||||
|
||||
NATIVE_ARCH="$(uname -m)"
|
||||
[ "${NATIVE_ARCH}" = "arm64" ] && NATIVE_ARCH="aarch64"
|
||||
[ "${NATIVE_ARCH}" = "amd64" ] && NATIVE_ARCH="x86_64"
|
||||
|
||||
if [ "$(uname)" != "Linux" ]; then
|
||||
cargo clippy --workspace --fix --allow-dirty --allow-staged \
|
||||
--target "${NATIVE_ARCH}-unknown-uefi"
|
||||
else
|
||||
cargo clippy --workspace --fix --allow-dirty --allow-staged
|
||||
fi
|
||||
|
||||
./hack/format.sh
|
||||
48
hack/boot.sh
Executable file
48
hack/boot.sh
Executable file
@@ -0,0 +1,48 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
cd "$(dirname "${0}")/.." || exit 1
|
||||
|
||||
. "hack/common.sh"
|
||||
|
||||
./hack/build.sh "${TARGET_ARCH}" "${RUST_PROFILE}"
|
||||
|
||||
clear
|
||||
|
||||
set --
|
||||
|
||||
if [ "${TARGET_ARCH}" = "x86_64" ]; then
|
||||
set -- "${@}" qemu-system-x86_64 -M q35
|
||||
elif [ "${TARGET_ARCH}" = "aarch64" ]; then
|
||||
set -- "${@}" qemu-system-aarch64 -M virt -cpu cortex-a57
|
||||
fi
|
||||
|
||||
set -- "${@}" -smp 2 -m 4096
|
||||
|
||||
if [ "${NO_GRAPHICAL_BOOT}" = "1" ]; then
|
||||
set -- "${@}" -nographic
|
||||
else
|
||||
set -- "${@}" -serial stdio -vga none -device "virtio-gpu,edid=on,xres=1024,yres=768"
|
||||
fi
|
||||
|
||||
rm -f "${FINAL_DIR}/ovmf-boot.fd"
|
||||
cp "${FINAL_DIR}/ovmf.fd" "${FINAL_DIR}/ovmf-boot.fd"
|
||||
if [ "${TARGET_ARCH}" = "aarch64" ]; then
|
||||
dd if=/dev/zero of="${FINAL_DIR}/ovmf-boot.fd" bs=1 count=1 seek=67108863 >/dev/null 2>&1
|
||||
fi
|
||||
# shellcheck disable=SC2086
|
||||
set -- "${@}" \
|
||||
-drive "if=pflash,file=${FINAL_DIR}/ovmf-boot.fd,format=raw,readonly=on" \
|
||||
-device nvme,drive=disk1,serial=cafebabe
|
||||
|
||||
if [ "${DISK_BOOT}" = "1" ]; then
|
||||
set -- "${@}" \
|
||||
-drive "if=none,file=${FINAL_DIR}/sprout.img,format=raw,id=disk1,readonly=on"
|
||||
else
|
||||
set -- "${@}" \
|
||||
-drive "if=none,file=fat:rw:${FINAL_DIR}/efi,format=raw,id=disk1"
|
||||
fi
|
||||
|
||||
set -- "${@}" -name "sprout ${TARGET_ARCH}"
|
||||
|
||||
exec "${@}"
|
||||
72
hack/build.sh
Executable file
72
hack/build.sh
Executable file
@@ -0,0 +1,72 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
cd "$(dirname "${0}")/.." || exit 1
|
||||
|
||||
. "hack/common.sh"
|
||||
|
||||
EFI_NAME="BOOTX64"
|
||||
if [ "${TARGET_ARCH}" = "aarch64" ]; then
|
||||
EFI_NAME="BOOTAA64"
|
||||
fi
|
||||
|
||||
echo "[build] ${TARGET_ARCH} ${RUST_PROFILE}"
|
||||
|
||||
if ! command -v docker >/dev/null 2>&1; then
|
||||
echo "ERROR: docker is required to build sprout." >/dev/stderr
|
||||
exit 1
|
||||
fi
|
||||
|
||||
export DOCKER_CLI_HINTS="0"
|
||||
|
||||
if [ "${SKIP_CLEANUP}" != 1 ]; then
|
||||
rm -rf "${FINAL_DIR}"
|
||||
fi
|
||||
mkdir -p "${FINAL_DIR}"
|
||||
|
||||
if [ "${SKIP_KERNEL_BUILD}" != "1" ] || [ "${SKIP_VM_BUILD}" != "1" ] || [ "${SKIP_SPROUT_BUILD}" != "1" ]; then
|
||||
docker build -t "${DOCKER_PREFIX}/sprout-utils-copy:${DOCKER_TAG}" -f hack/utils/Dockerfile.copy hack
|
||||
fi
|
||||
|
||||
if [ "${SKIP_KERNEL_BUILD}" != "1" ]; then
|
||||
echo "[kernel build] ${TARGET_ARCH} ${RUST_PROFILE}"
|
||||
docker build --platform="${DOCKER_TARGET}" -t "${DOCKER_PREFIX}/sprout-kernel-${TARGET_ARCH}:${DOCKER_TAG}" -f kernel/Dockerfile kernel
|
||||
|
||||
if [ "${KERNEL_BUILD_TAG}" = "1" ]; then
|
||||
docker build --platform="${DOCKER_TARGET}" -t "${DOCKER_PREFIX}/sprout-kernel-build-${TARGET_ARCH}:${DOCKER_TAG}" -f kernel/Dockerfile --target
|
||||
build kernel
|
||||
fi
|
||||
|
||||
docker run --rm -i \
|
||||
--mount="type=image,source=${DOCKER_PREFIX}/sprout-kernel-${TARGET_ARCH}:${DOCKER_TAG},target=/image" \
|
||||
"${DOCKER_PREFIX}/sprout-utils-copy:${DOCKER_TAG}" cat /image/kernel.efi >"${FINAL_DIR}/kernel.efi"
|
||||
fi
|
||||
|
||||
if [ "${SKIP_VM_BUILD}" != "1" ]; then
|
||||
echo "[vm build] ${TARGET_ARCH} ${RUST_PROFILE}"
|
||||
docker build --platform="${DOCKER_TARGET}" -t "${DOCKER_PREFIX}/sprout-ovmf-${TARGET_ARCH}:${DOCKER_TAG}" -f vm/Dockerfile.ovmf "${FINAL_DIR}"
|
||||
docker run --rm -i \
|
||||
--mount="type=image,source=${DOCKER_PREFIX}/sprout-ovmf-${TARGET_ARCH}:${DOCKER_TAG},target=/image" \
|
||||
"${DOCKER_PREFIX}/sprout-utils-copy:${DOCKER_TAG}" cat /image/ovmf.fd >"${FINAL_DIR}/ovmf.fd"
|
||||
fi
|
||||
|
||||
if [ "${SKIP_SPROUT_BUILD}" != "1" ]; then
|
||||
echo "[sprout build] ${TARGET_ARCH} ${RUST_PROFILE}"
|
||||
docker build --platform="${DOCKER_TARGET}" -t "${DOCKER_PREFIX}/sprout-${TARGET_ARCH}:${DOCKER_TAG}" --build-arg="RUST_TARGET_SUBDIR=${RUST_TARGET_SUBDIR}" -f Dockerfile .
|
||||
docker run --rm -i \
|
||||
--mount="type=image,source=${DOCKER_PREFIX}/sprout-${TARGET_ARCH}:${DOCKER_TAG},target=/image" \
|
||||
"${DOCKER_PREFIX}/sprout-utils-copy:${DOCKER_TAG}" cat /image/sprout.efi >"${FINAL_DIR}/sprout.efi"
|
||||
mkdir -p "${FINAL_DIR}/efi/EFI/BOOT"
|
||||
cp "${FINAL_DIR}/sprout.efi" "${FINAL_DIR}/efi/EFI/BOOT/${EFI_NAME}.EFI"
|
||||
if [ -f "${FINAL_DIR}/kernel.efi" ]; then
|
||||
cp "${FINAL_DIR}/kernel.efi" "${FINAL_DIR}/efi/EFI/BOOT/KERNEL.EFI"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "${SKIP_BOOT_BUILD}" != "1" ]; then
|
||||
echo "[boot build] ${TARGET_ARCH} ${RUST_PROFILE}"
|
||||
docker build --platform="${DOCKER_TARGET}" -t "${DOCKER_PREFIX}/sprout-boot-${TARGET_ARCH}:${DOCKER_TAG}" --build-arg "EFI_NAME=${EFI_NAME}" -f boot/Dockerfile "${FINAL_DIR}"
|
||||
docker run --rm -i \
|
||||
--mount="type=image,source=${DOCKER_PREFIX}/sprout-boot-${TARGET_ARCH}:${DOCKER_TAG},target=/image" \
|
||||
"${DOCKER_PREFIX}/sprout-utils-copy:${DOCKER_TAG}" cat /image/sprout.img >"${FINAL_DIR}/sprout.img"
|
||||
fi
|
||||
20
hack/clean.sh
Executable file
20
hack/clean.sh
Executable file
@@ -0,0 +1,20 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
cd "$(dirname "${0}")/.." || exit 1
|
||||
|
||||
. "hack/common.sh"
|
||||
|
||||
delete_image() {
|
||||
IMAGE="${1}"
|
||||
docker image ls -q --no-trunc --filter "reference=${DOCKER_PREFIX}/${IMAGE}" | xargs -rn1 docker image rm
|
||||
}
|
||||
|
||||
cargo clean || true
|
||||
|
||||
if command -v docker >/dev/null 2>&1; then
|
||||
delete_image sprout-utils-copy || true
|
||||
delete_image sprout-ovmf || true
|
||||
delete_image sprout-x86_64 || true
|
||||
delete_image sprout-aarch64 || true
|
||||
fi
|
||||
31
hack/common.sh
Normal file
31
hack/common.sh
Normal file
@@ -0,0 +1,31 @@
|
||||
#!/bin/sh
|
||||
# shellcheck disable=SC2034
|
||||
set -e
|
||||
|
||||
DOCKER_PREFIX="ghcr.io/edera-dev/sprout"
|
||||
DEFAULT_RUST_PROFILE="release"
|
||||
DEFAULT_DOCKER_TAG="latest"
|
||||
|
||||
[ -z "${TARGET_ARCH}" ] && TARGET_ARCH="${1}"
|
||||
{ [ -z "${TARGET_ARCH}" ] || [ "${TARGET_ARCH}" = "native" ]; } && TARGET_ARCH="$(uname -m)"
|
||||
[ -z "${RUST_PROFILE}" ] && RUST_PROFILE="${2}"
|
||||
[ -z "${RUST_PROFILE}" ] && RUST_PROFILE="${DEFAULT_RUST_PROFILE}"
|
||||
|
||||
[ "${TARGET_ARCH}" = "arm64" ] && TARGET_ARCH="aarch64"
|
||||
[ "${TARGET_ARCH}" = "amd64" ] && TARGET_ARCH="x86_64"
|
||||
|
||||
if [ "${TARGET_ARCH}" != "x86_64" ] && [ "${TARGET_ARCH}" != "aarch64" ]; then
|
||||
echo "Unsupported Architecture: ${TARGET_ARCH}" >/dev/stderr
|
||||
exit 1
|
||||
fi
|
||||
|
||||
[ "${RUST_PROFILE}" = "debug" ] && RUST_PROFILE="dev"
|
||||
|
||||
RUST_TARGET_SUBDIR="${RUST_PROFILE}"
|
||||
[ "${RUST_PROFILE}" = "dev" ] && RUST_TARGET_SUBDIR="debug"
|
||||
|
||||
RUST_TARGET="${TARGET_ARCH}-unknown-uefi"
|
||||
|
||||
[ -z "${DOCKER_TAG}" ] && DOCKER_TAG="${DEFAULT_DOCKER_TAG}"
|
||||
DOCKER_TARGET="linux/${TARGET_ARCH}"
|
||||
FINAL_DIR="target/final/${TARGET_ARCH}"
|
||||
7
hack/format.sh
Executable file
7
hack/format.sh
Executable file
@@ -0,0 +1,7 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
cd "$(dirname "${0}")/.." || exit 1
|
||||
|
||||
cargo fmt --all
|
||||
shfmt -w hack/*.sh
|
||||
1
hack/utils/Dockerfile.copy
Normal file
1
hack/utils/Dockerfile.copy
Normal file
@@ -0,0 +1 @@
|
||||
FROM --platform=$BUILDPLATFORM debian:trixie@sha256:fd8f5a1df07b5195613e4b9a0b6a947d3772a151b81975db27d47f093f60c6e6
|
||||
37
kernel/Dockerfile
Normal file
37
kernel/Dockerfile
Normal file
@@ -0,0 +1,37 @@
|
||||
ARG KERNEL_SOURCE_URL=https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.16.9.tar.xz
|
||||
ARG KERNEL_CHECKSUM=sha256:7ac8c8a3cf05476375deaaa85dfcee095a826ffe557b437f43774fc3b64ce58d
|
||||
|
||||
FROM --platform=$BUILDPLATFORM debian:trixie@sha256:fd8f5a1df07b5195613e4b9a0b6a947d3772a151b81975db27d47f093f60c6e6 AS buildenv
|
||||
RUN export DEBIAN_FRONTEND=noninteractive && apt-get update && apt-get install -y \
|
||||
build-essential squashfs-tools python3-yaml \
|
||||
patch diffutils sed mawk findutils zstd \
|
||||
python3 python3-packaging curl rsync cpio \
|
||||
flex bison pahole libssl-dev libelf-dev bc kmod && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
ARG BUILDPLATFORM
|
||||
RUN if [ "${BUILDPLATFORM}" = "linux/amd64" ] || [ "${BUILDPLATFORM}" = "linux/x86_64" ]; then \
|
||||
apt-get update && apt-get install -y linux-headers-amd64 gcc-aarch64-linux-gnu && rm -rf /var/lib/apt/lists/*; fi
|
||||
RUN if [ "${BUILDPLATFORM}" = "linux/arm64" ] || [ "${BUILDPLATFORM}" = "linux/aarch64" ]; then \
|
||||
apt-get update && apt-get install -y linux-headers-arm64 gcc-x86-64-linux-gnu && rm -rf /var/lib/apt/lists/*; fi
|
||||
RUN useradd -ms /bin/sh build
|
||||
COPY --chown=build:build docker-build.sh /build/docker-build.sh
|
||||
USER build
|
||||
WORKDIR /build
|
||||
|
||||
FROM scratch AS source
|
||||
ARG KERNEL_SOURCE_URL
|
||||
ARG KERNEL_CHECKSUM
|
||||
ADD --checksum=${KERNEL_CHECKSUM} ${KERNEL_SOURCE_URL} /src.tar.xz
|
||||
|
||||
FROM --platform=$BUILDPLATFORM buildenv AS build
|
||||
COPY --from=source --chown=build:build /src.tar.xz /build/src.tar.xz
|
||||
RUN mkdir /build/src && tar -C /build/src --strip-components=1 -xf /build/src.tar.xz && rm /build/src.tar.xz
|
||||
ARG BUILDPLATFORM
|
||||
ARG TARGETPLATFORM
|
||||
ENV BUILDPLATFORM=${BUILDPLATFORM}
|
||||
ENV TARGETPLATFORM=${TARGETPLATFORM}
|
||||
WORKDIR /build/src
|
||||
RUN /build/docker-build.sh
|
||||
|
||||
FROM scratch AS final
|
||||
COPY --from=build /build/src/kernel.image /kernel.efi
|
||||
42
kernel/docker-build.sh
Executable file
42
kernel/docker-build.sh
Executable file
@@ -0,0 +1,42 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
TARGET_KARCH=""
|
||||
TARGET_SARCH=""
|
||||
|
||||
MAYBE_CROSS_COMPILE=""
|
||||
|
||||
CURRENT_SARCH="$(uname -m)"
|
||||
|
||||
[ "${CURRENT_SARCH}" = "amd64" ] && CURRENT_SARCH="x86_64"
|
||||
[ "${CURRENT_SARCH}" = "arm64" ] && CURRENT_SARCH="aarch64"
|
||||
|
||||
if [ "${TARGETPLATFORM}" = "linux/aarch64" ] || [ "${TARGETPLATFORM}" = "linux/arm64" ]; then
|
||||
TARGET_KARCH="arm64"
|
||||
TARGET_SARCH="aarch64"
|
||||
if [ "${CURRENT_SARCH}" != "${TARGET_SARCH}" ]; then
|
||||
MAYBE_CROSS_COMPILE="aarch64-linux-gnu-"
|
||||
fi
|
||||
elif [ "${TARGETPLATFORM}" = "linux/x86_64" ] || [ "${TARGETPLATFORM}" = "linux/amd64" ]; then
|
||||
TARGET_KARCH="x86_64"
|
||||
TARGET_SARCH="x86_64"
|
||||
if [ "${CURRENT_SARCH}" != "${TARGET_SARCH}" ]; then
|
||||
MAYBE_CROSS_COMPILE="x86_64-linux-gnu-"
|
||||
fi
|
||||
else
|
||||
echo "Unknown platform: ${TARGETPLATFORM}" >/dev/stderr
|
||||
exit 1
|
||||
fi
|
||||
|
||||
make CROSS_COMPILE="${MAYBE_CROSS_COMPILE}" ARCH="${TARGET_KARCH}" defconfig
|
||||
make CROSS_COMPILE="${MAYBE_CROSS_COMPILE}" ARCH="${TARGET_KARCH}" mod2yesconfig
|
||||
|
||||
./scripts/config -e DRM_VIRTIO_GPU
|
||||
./scripts/config -e FRAMEBUFFER_CONSOLE
|
||||
./scripts/config -e FRAMEBUFFER_CONSOLE_DETECT_PRIMARY
|
||||
|
||||
make "-j$(nproc)" CROSS_COMPILE="${MAYBE_CROSS_COMPILE}" ARCH="${TARGET_KARCH}"
|
||||
|
||||
[ -f "arch/x86/boot/bzImage" ] && cp "arch/x86/boot/bzImage" kernel.image
|
||||
[ -f "arch/arm64/boot/Image.gz" ] && gzip -d < "arch/arm64/boot/Image.gz" > kernel.image
|
||||
exit 0
|
||||
4
rust-toolchain.toml
Normal file
4
rust-toolchain.toml
Normal file
@@ -0,0 +1,4 @@
|
||||
[toolchain]
|
||||
channel = "nightly"
|
||||
components = ["rustfmt", "rust-std", "clippy"]
|
||||
targets = ["x86_64-unknown-uefi", "aarch64-unknown-uefi"]
|
||||
61
src/chainload.rs
Normal file
61
src/chainload.rs
Normal file
@@ -0,0 +1,61 @@
|
||||
use uefi::{
|
||||
CString16,
|
||||
proto::device_path::{
|
||||
DevicePath, LoadedImageDevicePath, PoolDevicePath,
|
||||
text::{AllowShortcuts, DevicePathFromText, DisplayOnly},
|
||||
},
|
||||
};
|
||||
|
||||
fn text_to_device_path(path: &str) -> PoolDevicePath {
|
||||
let path = CString16::try_from(path).expect("unable to convert path to CString16");
|
||||
let device_path_from_text = uefi::boot::open_protocol_exclusive::<DevicePathFromText>(
|
||||
uefi::boot::get_handle_for_protocol::<DevicePathFromText>()
|
||||
.expect("no device path from text protocol"),
|
||||
)
|
||||
.expect("unable to open device path from text protocol");
|
||||
|
||||
device_path_from_text
|
||||
.convert_text_to_device_path(&path)
|
||||
.expect("unable to convert text to device path")
|
||||
}
|
||||
|
||||
pub fn chainload(path: &str) {
|
||||
let sprout_image = uefi::boot::image_handle();
|
||||
let image_device_path_protocol =
|
||||
uefi::boot::open_protocol_exclusive::<LoadedImageDevicePath>(sprout_image)
|
||||
.expect("unable to open loaded image protocol");
|
||||
|
||||
let image_device_path: &DevicePath = &image_device_path_protocol;
|
||||
let mut full_path = image_device_path
|
||||
.node_iter()
|
||||
.filter_map(|item| {
|
||||
let item = item
|
||||
.to_string(DisplayOnly(false), AllowShortcuts(false))
|
||||
.expect("unable to convert device path to string");
|
||||
if item.to_string().contains("(") {
|
||||
Some(item)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.map(|item| item.to_string())
|
||||
.collect::<Vec<_>>()
|
||||
.join("/");
|
||||
full_path.push('/');
|
||||
full_path.push_str(path);
|
||||
|
||||
println!("chainload: {}", full_path);
|
||||
|
||||
let device_path = text_to_device_path(&full_path);
|
||||
|
||||
let image = uefi::boot::load_image(
|
||||
sprout_image,
|
||||
uefi::boot::LoadImageSource::FromDevicePath {
|
||||
device_path: &device_path,
|
||||
boot_policy: uefi::proto::BootPolicy::ExactMatch,
|
||||
},
|
||||
)
|
||||
.expect("failed to load image");
|
||||
uefi::boot::start_image(image).expect("failed to start image");
|
||||
panic!("chainloaded image exited");
|
||||
}
|
||||
10
src/main.rs
Normal file
10
src/main.rs
Normal file
@@ -0,0 +1,10 @@
|
||||
#![feature(uefi_std)]
|
||||
pub mod chainload;
|
||||
pub mod setup;
|
||||
|
||||
const CHAINLOADER_TARGET: &str = "\\EFI\\BOOT\\KERNEL.efi";
|
||||
|
||||
fn main() {
|
||||
setup::init();
|
||||
chainload::chainload(CHAINLOADER_TARGET);
|
||||
}
|
||||
16
src/setup.rs
Normal file
16
src/setup.rs
Normal file
@@ -0,0 +1,16 @@
|
||||
use std::os::uefi as uefi_std;
|
||||
|
||||
pub fn init() {
|
||||
let system_table = uefi_std::env::system_table();
|
||||
let image_handle = uefi_std::env::image_handle();
|
||||
|
||||
// SAFETY: The uefi variables above come from the Rust std.
|
||||
// These variables are nonnull and calling the uefi crates with these values is validated
|
||||
// to be corrected by hand.
|
||||
unsafe {
|
||||
uefi::table::set_system_table(system_table.as_ptr().cast());
|
||||
let handle = uefi::Handle::from_ptr(image_handle.as_ptr().cast())
|
||||
.expect("unable to resolve image handle");
|
||||
uefi::boot::set_image_handle(handle);
|
||||
}
|
||||
}
|
||||
9
vm/Dockerfile.ovmf
Normal file
9
vm/Dockerfile.ovmf
Normal file
@@ -0,0 +1,9 @@
|
||||
FROM alpine:3.22@sha256:4bcff63911fcb4448bd4fdacec207030997caf25e9bea4045fa6c8c44de311d1 AS build
|
||||
ARG TARGETPLATFORM
|
||||
RUN if [ "${TARGETPLATFORM}" = "linux/amd64" ] || [ "${TARGETPLATFORM}" = "linux/x86_64" ]; then \
|
||||
apk --no-cache add ovmf; cp /usr/share/ovmf/bios.bin /ovmf.fd; fi
|
||||
RUN if [ "${TARGETPLATFORM}" = "linux/arm64" ] || [ "${TARGETPLATFORM}" = "linux/aarch64" ]; then \
|
||||
apk --no-cache add aavmf; cp /usr/share/AAVMF/QEMU_EFI.fd /ovmf.fd; fi
|
||||
|
||||
FROM scratch AS final
|
||||
COPY --from=build /ovmf.fd /ovmf.fd
|
||||
Reference in New Issue
Block a user