Compare commits

...

9 Commits

Author SHA1 Message Date
8733755888 Implement basic build script in python 2025-11-20 22:28:50 +02:00
6fd5770acc IMplement more of the build script 2025-11-04 20:56:56 +02:00
3f69f3d343 Start writing the python build script 2025-11-03 22:20:00 +02:00
17c7e1d431 Not working, saving for today 2025-11-02 22:01:36 +02:00
ac442e9f7c Initial rust setup 2025-11-02 17:45:28 +02:00
6f50aeb405 :3 2025-11-02 17:41:22 +02:00
883917d784 Add kernel config command 2025-11-02 17:38:51 +02:00
13ddec78a4 Finally figured out how to provide direct path to config
Honestly reading the code is the best docs
2025-11-02 17:35:51 +02:00
138abd5634 :3 2025-11-02 17:26:10 +02:00
15 changed files with 7100 additions and 9 deletions

2
.cargo/config.toml Normal file
View File

@@ -0,0 +1,2 @@
[build]
target-dir="build/"

2
.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
/build
/linux/.config.old

4
.gitmodules vendored
View File

@@ -3,3 +3,7 @@
path = linux/kernel
url = https://github.com/torvalds/linux.git
shallow = true
[submodule "linux/busybox"]
path = linux/busybox
url = https://git.busybox.net/busybox/
shallow = true

7
Cargo.lock generated Normal file
View File

@@ -0,0 +1,7 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 4
[[package]]
name = "embnux-init"
version = "0.1.0"

View File

@@ -1,3 +1,3 @@
[workspace]
resolver="2"
members=[]
members=["embnux-init"]

View File

@@ -1,22 +1,27 @@
MAKEFILE_DIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST))))
BUILD_DIR ?= $(MAKEFILE_DIR)build
ARCH ?= x86
ARCH ?= x86_64
KERNEL_FILE_NAME ?= bzImage
INITRAMFS_FILE = $(BUILD_DIR)/linux/initramfs.cpio
KERNEL_FILE = $(BUILD_DIR)/linux/kernel/arch/$(ARCH)/boot/$(KERNEL_FILE_NAME)
export BUILD_DIR
export ARCH
export KERNEL_FILE_NAME
KERNEL_PATH = $(BUILD_DIR)/arch/$(ARCH)/boot/$(bzImage)
kernel:
$(MAKE) -C $(MAKEFILE_DIR)/linux kernel
all: $(KERNEL_PATH)
initramfs:
$(MAKE) -C $(MAKEFILE_DIR)/linux initramfs -B
$(KERNEL_PATH):
@mkdir -p $(BUILD_DIR)/linux/kernel
cp $(MAKEFILE_DIR)/linux/.config $(BUILD_DIR)/linux/kernel/.config
$(MAKE) -C $(MAKEFILE_DIR)/linux/kernel O=$(BUILD_DIR)/linux/kernel
kernel-config:
$(MAKE) -C $(MAKEFILE_DIR)/linux kernel-config
qemu:
qemu-system-x86_64 -kernel $(KERNEL_FILE) -initrd $(INITRAMFS_FILE) -append "rdinit=/usr/sbin/init console=ttyS0" -serial mon:stdio
clean:

6
embnux-init/Cargo.toml Normal file
View File

@@ -0,0 +1,6 @@
[package]
name = "embnux-init"
version = "0.1.0"
edition = "2024"
[dependencies]

3
embnux-init/src/main.rs Normal file
View File

@@ -0,0 +1,3 @@
fn main() {
println!("Hello, world!");
}

1242
linux/.busybox-config Normal file

File diff suppressed because it is too large Load Diff

5487
linux/.kernel-config Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -2705,6 +2705,7 @@ CONFIG_SERIAL_8250_PERICOM=y
# CONFIG_SERIAL_UARTLITE is not set
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_CONSOLE_POLL=y
# CONFIG_SERIAL_JSM is not set
# CONFIG_SERIAL_LANTIQ is not set
# CONFIG_SERIAL_SCCNXP is not set
@@ -5182,7 +5183,13 @@ CONFIG_DEBUG_FS_ALLOW_ALL=y
# CONFIG_DEBUG_FS_DISALLOW_MOUNT is not set
# CONFIG_DEBUG_FS_ALLOW_NONE is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_KGDB is not set
CONFIG_KGDB=y
CONFIG_KGDB_HONOUR_BLOCKLIST=y
CONFIG_KGDB_SERIAL_CONSOLE=y
# CONFIG_KGDB_TESTS is not set
# CONFIG_KGDB_LOW_LEVEL_TRAP is not set
# CONFIG_KGDB_KDB is not set
CONFIG_ARCH_HAS_EARLY_DEBUG=y
CONFIG_ARCH_HAS_UBSAN=y
# CONFIG_UBSAN is not set
CONFIG_HAVE_ARCH_KCSAN=y

View File

@@ -1,4 +1,67 @@
MAKEFILE_DIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST))))
BUILD_DIR ?= $(MAKEFILE_DIR)build
ARCH ?= x86
KERNEL_FILE_NAME ?= bzImage
KERNEL_PATH = $(BUILD_DIR)/arch/$(ARCH)/boot/$(bzImage)
KERNEL_BUILD_DIR=$(BUILD_DIR)/linux/kernel
BUSYBOX_BUILD_DIR=$(BUILD_DIR)/linux/busybox
BUSYBOX_BUILD_FILE=$(BUSYBOX_BUILD_DIR)/busybox
INITRAMFS_DIR=$(BUILD_DIR)/linux/initramfs
INITRAMFS_FILE_TMP=$(BUILD_DIR)/linux/initramfs.cpio
INITRAMFS_FILE=$(BUILD_DIR)/linux/initramfs.cpio.gz
.PHONY: initramfs initramfs_initiial initramfs_clean busybox all kernel __busybox_install
all: $(INITRAMFS_FILE)
initramfs:initramfs_clean initramfs_initiial __busybox_install $(INITRAMFS_FILE)
kernel: $(KERNEL_PATH)
busybox: $(BUSYBOX_BUILD_FILE)
$(KERNEL_PATH):
@mkdir -p $(KERNEL_BUILD_DIR)
$(MAKE) -C $(MAKEFILE_DIR)/kernel O=$(KERNEL_BUILD_DIR) KCONFIG_CONFIG="$(MAKEFILE_DIR)/.kernel-config"
kernel-config:
$(MAKE) -C $(MAKEFILE_DIR)/kernel O=$(KERNEL_BUILD_DIR) KCONFIG_CONFIG="$(MAKEFILE_DIR)/.kernel-config" menuconfig
$(BUSYBOX_BUILD_FILE):
@mkdir -p $(BUSYBOX_BUILD_DIR)
cp $(MAKEFILE_DIR)/.busybox-config $(BUSYBOX_BUILD_DIR)/.config
$(MAKE) -C $(MAKEFILE_DIR)/busybox O=$(BUSYBOX_BUILD_DIR) KCONFIG_CONFIG="$(MAKEFILE_DIR)/.busybox-config"
__busybox_install:
$(MAKE) -C $(MAKEFILE_DIR)/busybox O=$(BUSYBOX_BUILD_DIR) KCONFIG_CONFIG="$(MAKEFILE_DIR)/.busybox-config" CONFIG_PREFIX=$(INITRAMFS_DIR) install
$(INITRAMFS_FILE): initramfs_clean initramfs_initiial __busybox_install
find $(INITRAMFS_DIR) | cpio -o -H newc > $(INITRAMFS_FILE_TMP)
# gzip -f $(INITRAMFS_FILE_TMP)
initramfs_clean:
@rm -rf $(INITRAMFS_DIR)
initramfs_initiial: #$(BUSYBOX_BUILD_FILE)
mkdir -p $(INITRAMFS_DIR)
mkdir -p $(INITRAMFS_DIR)/{etc,mnt,proc,run,srv,tmp,var,boot,dev,home,media,opt,root,sbin,sys,usr/bin,usr/lib}
bash -c "pushd $(INITRAMFS_DIR); ln -s usr/bin bin; popd"
bash -c "pushd $(INITRAMFS_DIR); ln -s usr/lib lib; popd"
echo "#!/bin/sh" >> $(INITRAMFS_DIR)/init
echo "mount -t proc none /proc" >> $(INITRAMFS_DIR)/init
echo "mount -t sysfs none /sys" >> $(INITRAMFS_DIR)/init
echo "echo 'Successfully booted'" >> $(INITRAMFS_DIR)/init
echo "exec /bin/sh" >> $(INITRAMFS_DIR)/init
chmod +x $(INITRAMFS_DIR)/init
chmod +x $(INITRAMFS_DIR)/sbin/init

1
linux/busybox Submodule

Submodule linux/busybox added at b99a529177

4
pyproject.toml Normal file
View File

@@ -0,0 +1,4 @@
[tool.pylsp.plugins.pycodestyle]
enabled = true
ignore = ["E501", "W291"] # ignore line length & trailing whitespace

258
x.py Executable file
View File

@@ -0,0 +1,258 @@
#!/usr/bin/env python
import sys
import subprocess
import threading
import os
from datetime import datetime
__FILENAME = ""
MAX_JOBS = max(1, len(os.sched_getaffinity(0)) - 2)
TS_VRB = 2
CWD = os.path.dirname(os.path.abspath(__file__))
BUILD_D = f"{CWD}/build"
INITRAMFS_DIR = f"{BUILD_D}/linux/initramfs"
INITRAMFS_FILE_TMP = f"{BUILD_D}/linux/initramfs.cpio"
INITRAMFS_FILE = f"{BUILD_D}/linux/initramfs.cpio.gz"
KERNEL_FILE = F"{BUILD_D}/linux/KernelImage"
def shift(arr):
if not arr:
return None # or raise IndexError if you prefer
return arr.pop(0)
def timestamp(dt=datetime.now(), fmt="hours"):
return f"{dt.hour:0>2}:{dt.minute:0>2}:{dt.second:0>2}"
def run(*cmds, parallel=False, tag=None, interactive=False, chdir=None):
threads = []
def run_single(cmd, tag, chdir):
env = os.environ.copy()
env["MAKE_TERMOUT"] = "true"
env["MAKE_TERMERR"] = "true"
start_time = datetime.now()
print(f"{f"{timestamp(start_time)} | " if TS_VRB > 0 else ""}CMD: {cmd}")
with subprocess.Popen(
cmd, shell=True,
stdout=None if interactive else subprocess.PIPE,
stderr=None if interactive else subprocess.STDOUT,
cwd=chdir if chdir else None,
# text=None if interactive else True,
) as proc:
if not interactive:
for line in proc.stdout:
dt = datetime.now()
if tag:
print(f"{f"{timestamp(dt)} | " if TS_VRB >
0 else ""}stdout ({tag}): ", flush=True, end='')
else:
print(f"{f"{timestamp(dt)} | " if TS_VRB >
0 else ""}stdout: ", flush=True, end='')
sys.stdout.buffer.write(line)
sys.stdout.buffer.flush()
proc.wait()
if proc.returncode != 0:
print(f"ERROR: Command '{
cmd}' exited with code {proc.returncode}")
exit(1)
for i, command in enumerate(cmds):
current_tag = tag if len(cmds) <= 1 else (
f"{tag}-{i}" if tag else None)
if parallel:
t = threading.Thread(
target=run_single, args=(command, current_tag, chdir))
t.start()
threads.append(t)
else:
run_single(command, current_tag, chdir)
for t in threads:
t.join()
def todo(reason):
print(f"ERROR: Unimplemented {reason}")
exit(1)
def cmd_configure(args):
def cmd_help():
print(f"Usage: {__FILENAME} configure [component]")
print("Components:")
print(" help - Show this help")
print(" kernel - The linux kernel")
print(" busybox - Busybox")
# $(MAKE) -C $(MAKEFILE_DIR)/kernel O=$(KERNEL_BUILD_DIR) KCONFIG_CONFIG="$(MAKEFILE_DIR)/.kernel-config" menuconfig
subc = shift(args)
if not subc or subc == "help":
cmd_help()
exit(1)
elif subc == "kernel":
run(f"make -C {CWD}/linux/kernel O={BUILD_D}/linux/kernel KCONFIG_CONFIG='{
CWD}/linux/.kernel-config' menuconfig", interactive=True)
elif subc == "busybox":
run(f"make -C {CWD}/linux/busybox O={BUILD_D}/linux/busybox KCONFIG_CONFIG='{
CWD}/linux/.busybox-config' menuconfig", interactive=True)
else:
print(f"ERROR: Unknown component {subc}")
cmd_help()
exit(1)
def cmd_build(args):
def cmd_help():
print(f"Usage: {__FILENAME} build [component]")
print("Components:")
print(" help - Show this help")
print(" all - Builds everything")
print(" linux - Everything bellow")
print(" kernel - The linux kernel")
print(" busybox - Busybox")
print(" initramfs - Busybox")
print(" rust - Builds all of the rust components")
print(" img - Rebuilds the image")
def build_init():
run(
f"mkdir -p {BUILD_D}/linux/kernel",
f"mkdir -p {BUILD_D}/linux/busybox",
parallel=True
)
def build_kernel(args):
run(f"make -C {CWD}/linux/kernel O={BUILD_D}/linux/kernel KCONFIG_CONFIG='{
CWD}/linux/.kernel-config' -j{MAX_JOBS}", tag="kernel")
run(f"cp {
BUILD_D}/linux/kernel/arch/x86_64/boot/bzImage {KERNEL_IMAGE}")
def build_busybox(args):
run(
f"cp {CWD}/linux/.busybox-config {
BUILD_D}/linux/busybox/.config",
f"make -C {CWD}/linux/busybox O={BUILD_D}/linux/busybox KCONFIG_CONFIG='{
CWD}/linux/.busybox-config' -j{MAX_JOBS}",
tag="busybox"
)
def build_rust(args):
todo("build_rust")
def build_initramfs(args):
run(f"rm -rf {INITRAMFS_DIR}")
run(f"mkdir -p {INITRAMFS_DIR}/{{etc,mnt,proc,run,srv,tmp,var,boot,dev,home,media,opt,root,sbin,sys,usr/bin,usr/lib}}")
run("ln -s usr/bin bin",
"ln -s usr/lib lib",
chdir=INITRAMFS_DIR)
init_script =\
"#!/bin/sh\\n" +\
"mount -t proc none /proc\\n" +\
"mount -t sysfs none /sys\\n" +\
"echo 'Successfully booted'\\n" +\
"exec /bin/sh\\n"
run(f"echo {init_script} > {INITRAMFS_DIR}/init")
# run(
# f"chmod +x {INITRAMFS_DIR}/init",
# f"chmod +x {INITRAMFS_DIR}/sbin/init"
# )
run(
f"make -C {CWD}/linux/busybox O={BUILD_D}/linux/busybox KCONFIG_CONFIG='{
CWD}/linux/.busybox-config' -j{MAX_JOBS} CONFIG_PREFIX={INITRAMFS_DIR} install",
)
run(
f"find {INITRAMFS_DIR} | cpio -o -H newc > {INITRAMFS_FILE_TMP}",
f"gzip -f {INITRAMFS_FILE_TMP}"
)
def build_image(args):
# for the later bootable.img or whatever file
todo("build_image")
cmd = shift(args)
if not cmd or cmd == "help":
cmd_help()
exit(1)
elif cmd == "all":
build_init()
build_kernel(args)
build_busybox(args)
build_rust(args)
build_image(args)
elif cmd == "linux":
build_init()
build_kernel(args)
build_busybox(args)
elif cmd == "kernel":
build_init()
build_kernel(args)
elif cmd == "busybox":
build_init()
build_busybox(args)
elif cmd == "rust":
build_init()
build_rust(args)
elif cmd == "img":
build_init()
build_image(args)
elif cmd == "initramfs":
build_initramfs(args)
else:
print(f"ERROR: Unknown component '{cmd}'")
cmd_help()
exit(1)
def cmd_qemu(args):
run(f"qemu-system-x86_64 -kernel {KERNEL_FILE} -initrd {INITRAMFS_FILE} -append \"rdinit=/usr/sbin/init console=ttyS0\" -serial mon:stdio")
AVAILABLE_SUBCOMMANDS = {
"help": help,
"configure": cmd_configure,
"build": cmd_build,
"qemu": cmd_qemu,
}
def help():
print(f"Usage: {__FILENAME} [subcommand]")
print("Subcommands:")
print(" help - Show this help")
print(" configure - Configure components")
print(" build - Compile/build components")
print(" qemu - Run a vm with the current build")
if __name__ == "__main__":
args = sys.argv
__FILENAME = shift(args)
cmd = shift(args)
if not cmd:
help()
exit(1)
cmd_v = AVAILABLE_SUBCOMMANDS[cmd]
if not cmd_v:
print(f"ERROR: Unknown subcommand '{cmd}'")
help()
exit(1)
(cmd_v)(args)
exit(0)