The Neutron bootloader reads per-build settings from build.cfg at the project root. A script gen_config.py turns that file into:

  • internal/config.h — C macros used by the bootloader
  • build.mk — Makefile variables (e.g. KERNEL_FILENAME, EMBED_KERNEL)

You do not edit these generated files by hand; change build.cfg and run make (or python3 gen_config.py) to regenerate them.

build.cfg format

build.cfg is a text file of key-value pairs, one per line. Lines starting with # are comments. Empty lines are ignored. Keys are case-sensitive.

  • Strings are written in double quotes, e.g. kernel_filename = "ATOM.BIN".
  • Numbers can be decimal or hex (e.g. 0x100000, 0x400000).
  • Booleans are true or false.
  • Enums (e.g. log level) use the values listed below.

Supported keys

KeyTypeDefaultDescription
kernel_filenamestring"ATOM.BIN"Filename of the packed kernel on the FAT32 root. Use 8.3 uppercase for best compatibility.
kernel_staging_addrhex0x100000Physical address where the kernel file is read into memory. Must be in RAM and not overlap the bootloader.
kernel_load_addrhex0x200000Physical address where the NKRN payload is copied and where the bootloader jumps. Must match the kernel link address.
kernel_max_sizehex or decimal0x400000 (4 MiB)Maximum payload size in bytes. The bootloader rejects images larger than this.
log_levelenuminfoquiet, info, or debug. Controls how much is printed over UART (when the C code uses it).
ansi_colorsbooltrueIf true, use ANSI escape codes for colours in serial output; if false, config.h defines empty strings for the colour macros.
banner_textstring"Neutron Bootloader v1.0.0"Line shown in the boot banner (after ” ~ ”).
bootloader_versionstring"Neutron-1.0"String written into boot_info_t.bootloader_version (max 15 characters plus NUL).
kernel_versionstring"v1.0"Kernel version string to be packed into the NKRN header and written to boot_info_t.kernel_version. Format: “vMAJOR.MINOR” (e.g. “v1.0”, “v2.3”). Max 15 characters plus NUL.
embed-kernelboolfalseIf true, the packed kernel is embedded into kernel8.img and the bootloader boots without SD/FAT32. If false, the kernel is loaded from the SD card.

Example build.cfg

The following matches the current build.cfg structure (all keys and embed-kernel option):

# Neutron Bootloader - Build Configuration
# Edit this file to customize bootloader behaviour per build.
# Run 'make' to regenerate internal/config.h from this file.
 
# Kernel image filename on FAT32 root (8.3 uppercase recommended)
kernel_filename = "CUSTOM.BIN"
 
# Staging address: where the kernel file is read into memory (must be in RAM)
kernel_staging_addr = 0x100000
 
# Load/entry address: where payload is copied and where we jump (must match kernel link address)
kernel_load_addr = 0x200000
 
# Maximum kernel image size in bytes (payload only, after NKRN header)
kernel_max_size = 0x400000
 
# Log level: quiet | info | debug
log_level = quiet
 
# Use ANSI colour codes for serial output (true | false)
ansi_colors = true
 
# Banner line shown at boot (string)
banner_text = "Neutron Bootloader  v1.2.0"
 
# Bootloader version string written into boot_info_t (max 15 chars + NUL)
bootloader_version = "Neutron-1.2.0"
 
# Kernel version string packed into the NKRN header and written into boot_info_t
# Format: "vMAJOR.MINOR"  (e.g. "v1.0", "v2.3")
kernel_version = "v1.0"
 
# If true, embed the packed kernel into kernel8.img and boot without
# accessing the SD card / FAT32 filesystem. If false, load from SD.
embed-kernel = false

Kernel embedding (build.mk)

This is an auto-generated script and must not be changed by hand

  • Generated by gen_config.py from build.cfg; do not edit by hand.
  • Included by the main Makefile (-include build.mk) so Make gets the current config.
  • Defines several variables:
    • KERNEL_FILENAME - Name of the packed kernel on the FAT32 root (e.g. ATOM.BIN, CUSTOM.BIN). Used for mcopy when building sd.img.
    • KERNEL_VERSION - Kernel version string (e.g. “v1.0”) from build.cfg.
    • KERNEL_VERSION_MAJOR and KERNEL_VERSION_MINOR - Parsed integer versions used by pack_kernel.py.
    • EMBED_KERNEL - 1 = embed kernel in kernel8.img and skip SD; 0 = load from SD and build sd.img by default.

Refreshed when build.cfg changes; make all depends on build.mk so Make re-execs and picks up the new values in the same run.

C macros (internal/config.h)

After generation, the following are available in C (when the bootloader does #include "config.h"):

  • Addresses and size: CFG_KERNEL_FILENAME, CFG_KERNEL_STAGING_ADDR, CFG_KERNEL_LOAD_ADDR, CFG_KERNEL_MAX_SIZE
  • Logging: CFG_LOG_LEVEL (0 = quiet, 1 = info, 2 = debug), and CFG_LOG_QUIET, CFG_LOG_INFO, CFG_LOG_DEBUG
  • Colours: CFG_ANSI_COLORS (0 or 1). When 1, CFG_ANSI_RESET, CFG_ANSI_BOLD, CFG_ANSI_GREEN, CFG_ANSI_CYAN, CFG_ANSI_YELLOW, CFG_ANSI_RED are the escape sequences; when 0, they are empty strings.
  • Strings: CFG_BANNER_TEXT, CFG_BOOTLOADER_VERSION, CFG_KERNEL_VERSION (e.g. “v1.0”)
  • Kernel version: CFG_KERNEL_VERSION_MAJOR and CFG_KERNEL_VERSION_MINOR (parsed from kernel_version in build.cfg, e.g. “v1.0” → major=1, minor=0)
  • Embed: CFG_EMBED_KERNEL (0 = load from SD, 1 = use embedded kernel in kernel8.img)

When to regenerate config.h

  • Automatically: The Makefile generates internal/config.h and build.mk when you run make bootloader or make all if build.cfg is newer than them, or if they are missing.
  • By hand: Run python3 gen_config.py from the project root. Use python3 gen_config.py --verbose to print the output path.

Matching the kernel and SD image

  • The kernel filename in build.cfg must match the file name you put on the FAT32 partition (e.g. if you set kernel_filename = "MYOS.BIN", copy your packed kernel to the SD root as MYOS.BIN).
  • The kernel load address in build.cfg must match the address your kernel is linked for (e.g. the test kernel uses 0x200000 in test_kernel/linker/kernel.ld). When packing with pack_kernel.py, use --load and --entry to match (e.g. --load 0x200000 --entry 0x200000).
  • With embed-kernel = false, the SD image created by make sd-image copies K_BIN (default bin/atom.bin) to the image using the name from kernel_filename (e.g. ATOM.BIN or CUSTOM.BIN). The Makefile uses the same value for mcopy, so changing kernel_filename in build.cfg is enough.
  • With embed-kernel = true, no SD image is built by default; the kernel is embedded into kernel8.img and the bootloader does not access the SD card.