mirror of
https://github.com/edera-dev/sprout.git
synced 2025-12-19 00:50: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