Skip to content
FreeDOSHow-To Published Updated 8 min readViews unavailable

Building the FreeDOS Kernel: Validate the 2046 CPU and FAT Matrix

Build FreeDOS Kernel 2046 from pinned source, select CPU and FAT targets, inspect toolchain drift, and validate boot artifacts in an isolated checkout.

Building a FreeDOS kernel is not the same task as compiling an ordinary DOS application. The source tree builds several system components, selects a compiler and CPU/FAT configuration, then produces kernel images that still need a controlled boot test. A successful make all is evidence that one source and toolchain combination compiled; it is not proof that every published CPU/filesystem variant is correct or that the resulting image is interchangeable with an official release package.

This walkthrough uses the FreeDOS Kernel 2046 release and its source tag ke2046, which resolves to commit 5ffb5502d39a10a30f5b8a9e8beeba0bf30245d3. Pinning that identity matters because the project has multiple build paths and its documentation does not all describe the same point in time. The release page identifies 2046 as version 2.46, while the README at the corresponding source commit still says 2045. Treat the release and source commit as the identity of the build, and record the discrepancy instead of inferring a binary’s version from an old README alone.

Start from an identifiable, disposable source tree

Clone the release tag into a new directory rather than reusing a checkout that contains personal files or other work:

git clone --depth 1 --branch ke2046 https://github.com/FDOS/kernel.git freedos-kernel-ke2046
cd freedos-kernel-ke2046
git rev-parse HEAD
git status --short

For the reviewed release, git rev-parse HEAD should print 5ffb5502d39a10a30f5b8a9e8beeba0bf30245d3; git status --short should be empty before you start. If you use the source archive instead of Git, retain the exact archive name and a trusted checksum when the project publishes one. A hash that you calculate yourself is useful for identifying your local bytes, but it does not authenticate their origin without a separately trusted expected value.

The distinction between the source tag and release binaries is operationally useful. The 2046 release page publishes separate _86 and _386 artifacts, and separates f16 from f32: its release notes say f16 supports FAT12/FAT16 while f32 adds FAT32 support. These are different build targets, not a claim that one image automatically detects and supports every CPU and filesystem combination. Match the artifact or source build to the target machine and the volume format you intend to use.

Select one compiler and one target configuration

The source Makefile describes Linux builds through make all and Windows builds through mingw32-make all. Its Linux configuration template is config.m; copy it to config.mak if no local configuration exists, then inspect the compiler paths and options before building. The template exposes XCPU and XFAT; the source build scripts recognize CPU values such as 86, 186, and 386, and FAT values 16 and 32. This guide focuses on the documented Linux path, not the separate DOS-hosted BUILD.BAT workflow.

For a Linux host with the required Open Watcom, NASM, and packaging tools installed and configured, one explicit lane is:

( set -C; cat config.m > config.mak ) || {
    printf '%s\n' 'config.mak already exists or could not be created; refusing to continue.' >&2
    exit 1
}
# Review config.mak and set the actual compiler/tool paths before building.
make all COMPILER=owlinux XCPU=386 XFAT=32

The subshell scopes set -C (noclobber) to this copy operation; the shell refuses to open an existing config.mak for output, and the command stops if the copy cannot be created. The checked-in config.m is a template, and the Makefile includes config.mak when present. The upstream CI setup currently uses both the IA-16 GCC cross-compiler path (COMPILER=gcc) and Open Watcom (COMPILER=owlinux). It obtains Open Watcom from a moving Current-build snapshot URL, so that CI recipe is evidence of a supported build lane, not by itself a bit-for-bit reproducibility guarantee. Record the actual archive, compiler, assembler, linker, packer, host distribution, configuration file, and full command used for your build.

The legacy docs/build.txt remains useful for the broad command structure, but it explicitly dates its recommended Open Watcom and NASM versions to May 2009. Do not copy those old tool-version recommendations into a current build plan without checking the pinned release’s Makefiles and CI setup. A versioned source commit does not freeze externally downloaded tools, package repositories, environment variables, or compiler defaults.

If you need a CPU/FAT compatibility matrix, build each combination in its own clean checkout or fully clobber generated state between runs. Reusing object files after changing XCPU, XFAT, compiler, or build flags can make the result ambiguous because ordinary make dependencies do not necessarily encode every changed command-line setting. At minimum, keep a matrix such as:

Lane XCPU XFAT Intended question
8086-class, FAT12/16 86 16 Does the low-CPU target build for FAT12/16 use?
8086-class, FAT32 86 32 Does the FAT32-enabled target build for the intended low-CPU class?
80386-class, FAT12/16 386 16 Does the 386 target build without FAT32 support?
80386-class, FAT32 386 32 Does the 386 FAT32-enabled target build?

The table is a test plan, not a promise that every compiler supports every cell identically. Confirm target names and restrictions against the release notes and the exact compiler makefiles; do not infer supported hardware solely from a filename abbreviation.

Keep upstream CI’s cleanup behavior in the right boundary

The project CI scripts provide valuable examples, but they are not harmless inspection commands. ci_build.sh removes _output and invokes git clean -x -d -f before build lanes. That forced cleanup deletes untracked and ignored files other than the explicitly excluded paths. Run it only inside a disposable clone or CI worktree after confirming there is nothing valuable there. Do not use it in a checkout containing local drafts, logs, generated files, or unrelated work. The individual top-level make clean and make clobber targets also remove generated outputs; understand the target before running it.

The CI prerequisite script installs assembler, UPX, QEMU, and the IA-16 toolchain, then fetches the Open Watcom snapshot used by that workflow. If you build manually, provision these tools in an isolated environment and note their exact versions. Avoid treating an unpinned package name or a rolling snapshot URL as a reproducible toolchain lockfile.

Test the image that you actually built

The upstream ci_test.sh checks for a particular set of generated images and delegates boot tests to test/test.sh. That harness assembles a small floppy image and boots it in QEMU with a 10-second timeout. Its TEST.COM program asks DOS to create RESULT.TXT with INT 21h/AH=3Ch, writes the seven-byte success marker with AH=40h, and checks for a short write or DOS error before the harness reads the result back. This is a useful boot-plus-basic-file-I/O smoke test of the selected build path. It is not hardware certification, a full DOS compatibility suite, proof of filesystem integrity under failure, or evidence for a CPU/FAT variant that was not built and exercised.

For a manual evaluation, boot the generated KERNEL.SYS in a disposable VM using a copy of a disk image. Keep writable host-shared folders and passthrough storage disconnected unless the test specifically requires them. Record the QEMU version and machine settings, boot messages, kernel version string, and any test image checksum. Never replace the kernel in your only working FreeDOS installation to see whether a custom build starts.

The CI test script’s lane selection is also narrower than the release’s full artifact list. Use it to understand the project’s automated checks, but inspect its required filenames and test arguments before claiming coverage. A passing boot test means that the tested image reached the harness’s expected state under that VM configuration. It does not establish that every DOS program, storage controller, redirector, or physical BIOS behaves the same way.

Preserve enough evidence to reproduce the result

For each build, save the source tag and resolved commit, compiler and assembler versions, host OS/architecture, configuration file, XCPU/XFAT values, command line, exit status, and build log. Hash the resulting files and label hashes as local artifact identity unless a trusted upstream checksum is available:

git rev-parse HEAD
sha256sum bin/*.sys

Compare only like with like: same source commit, build configuration, tools, and packaging steps. A different hash can reflect compiler or packaging differences and is not automatically a defect; a matching hash is meaningful only when the inputs and trust path are understood. Keep the original artifact separate from any image installed in a VM, and snapshot the VM before boot testing so a failed experiment can be rolled back without changing the build evidence.

The strongest useful conclusion is deliberately scoped: “This exact commit built with these tools and settings, and this exact image passed this QEMU test.” That statement is actionable and reproducible. “The FreeDOS kernel builds” or “all FreeDOS systems support it” goes far beyond one compiler lane and one virtual boot.

Related:

Sources:

Comments