-
Notifications
You must be signed in to change notification settings - Fork 0
Boot Floppy Builder
Ant task that creates GRUB-bootable FAT disk images by wrapping the boot image in a FAT filesystem with GRUB stage1/stage2 bootloaders.
BootFloppyBuilder (org.jnode.build.BootFloppyBuilder) is an Ant task that creates bootable disk images. Despite its name, it does not create actual floppy disks — it creates file-backed block devices formatted as FAT filesystems with GRUB embedded in the boot sector. The actual build uses its subclass BootDiskBuilder, which extends BootFloppyBuilder to create partitioned hard disk images with an MBR.
The boot disk builder sits in the build pipeline after Build---BootImageBuilder-Internals (which creates the raw boot image binary) and before the optional Boot-CD-ROM-Builder (which wraps the disk image in an ISO-9660 CD-ROM).
The pipeline is:
BootImageBuilder → bootimage.bin
→ gzip → jnode.kernel.gz
→ BootDiskBuilder → FAT disk image with GRUB (jnode.disk)
→ create-cdrom → ISO-9660 CD-ROM image (jnode.iso)
| Class / File | Role |
|---|---|
builder/src/builder/org/jnode/build/BootFloppyBuilder.java |
Base Ant task: creates 1.44 MB FAT floppy image with GRUB |
builder/src/builder/org/jnode/build/BootDiskBuilder.java |
Subclass: creates partitioned hard disk image with MBR, IBM partition table, and .pln VMware descriptor |
fs/src/fs/org/jnode/fs/fat/GrubFatFormatter.java |
Formats device as FAT, embeds GRUB stage1 (boot sector) and stage2 |
fs/src/fs/org/jnode/fs/fat/GrubBootSector.java |
GRUB boot sector structure and patching |
fs/src/fs/org/jnode/fs/fat/FatType.java |
FAT type enumeration (FAT12, FAT16, FAT32) |
fs/src/fs/org/jnode/fs/fat/FatFileSystem.java |
FAT filesystem implementation used to copy files onto the image |
all/build-x86.xml |
Ant build file defining the boot-disk target that invokes BootDiskBuilder |
BootFloppyBuilder extends org.apache.tools.ant.Task and creates a 1.44 MB floppy image (1440 × 1024 bytes):
public class BootFloppyBuilder extends Task {
private File destFile;
private String stage1ResourceName;
private String stage2ResourceName;
private ArrayList<FileSet> fileSets;
public void execute() throws BuildException {
if (isExecuteNeeded()) {
createImage();
}
}
protected void createImage() throws IOException, DriverException, FileSystemException {
// Create file-backed block device
final FileDevice newFd = new FileDevice(destFile, "rw");
newFd.setLength(getDeviceLength()); // 1.44 MB
// Format as GRUB-bootable FAT
formatDevice(newFd);
// Copy files onto the FAT filesystem
final Device sysDev = getSystemDevice(newFd);
final BlockDeviceAPI sysDevApi = sysDev.getAPI(BlockDeviceAPI.class);
copySystemFiles(sysDev);
sysDevApi.flush();
}
protected long getDeviceLength() {
return 1440 * 1024; // 1.44 MB floppy
}
protected GrubFatFormatter createFormatter() {
return new GrubFatFormatter(0, stage1ResourceName, stage2ResourceName);
}
}Key behaviors:
-
Incremental build check:
isExecuteNeeded()compares the destination file's last-modified timestamp against the source files. If the output is newer, the task is skipped. -
GRUB embedding:
GrubFatFormatterformats the device as FAT, then writes GRUB stage1 into the boot sector and stage2 starting at sector 1. -
File copying: Copies file sets (kernel, GRUB menu, initjars) onto the FAT filesystem using
FatFileSystem.
BootDiskBuilder extends BootFloppyBuilder and creates a partitioned hard disk image:
| Aspect | BootFloppyBuilder | BootDiskBuilder |
|---|---|---|
| Device size | Fixed 1.44 MB | Configurable via geometry (cylinders/heads/sectors) |
| Partition table | None (whole-disk FAT) | MBR with IBM partition table (FAT16 <32M) |
| FAT type | FAT12 (floppy) | FAT16 <32M |
| System device | Root device itself | Partition 0 (via MappedFSBlockDeviceSupport) |
| Formatter | GrubFatFormatter(0, stage1, stage2) |
GrubFatFormatter(bps, spc, geom, FatType.FAT16, 1, stage1, stage2) |
| Extra output | None |
.pln file (VMware disk descriptor for VirtualBox/VMware) |
| Geometry | Implicit (1.44MB floppy) | Explicit Geometry(cylinders, heads, sectors)
|
BootDiskBuilder's formatDevice() creates an MBR with an IBM partition table, formats partition 0, and fixes up the stage2 sector reference in the MBR. It also writes a .pln file with cylinder/head/sector geometry for VMware/VirtualBox.
GrubFatFormatter handles GRUB embedding:
public class GrubFatFormatter {
// Two constructors:
// 1. Floppy variant: uses FatFormatter.fat144FloppyFormatter
// 2. Hard-disk variant: uses FatFormatter.HDFormatter with custom geometry
public void format(BlockDeviceAPI device) throws IOException {
// 1. Format device as FAT via FatFormatter
// 2. Write GRUB stage2 to sector 1+
// 3. Patch stage2 with:
// - Boot sector offset
// - Install partition number
// - Optional config file path
}
private void createBootSector() {
// Load GRUB stage1 (512 bytes) from classpath resource
// Load GRUB stage2 from classpath resource
// Write stage1 to boot sector
}
}GRUB stage1 (512 bytes) is written to the boot sector. Stage2 is written starting at sector 1 and is patched with the boot sector offset and partition number so it can find the kernel.
The boot-disk target in all/build-x86.xml:
<target name="boot-disk" depends="java-image" unless="no.bootdisk">
<taskdef name="bootdisk" classname="org.jnode.build.BootDiskBuilder"
classpathref="cp-x86" />
<property name="bootdisk.dir" value="${my-build.dir}/${jnode.bits}bits/bootdisk" />
<mkdir dir="${bootdisk.dir}" />
<mkdir dir="${bootdisk.dir}/boot/grub" />
<copy file="${jnode.kernel}" todir="${bootdisk.dir}" />
<copy file="${grub.menu}" todir="${bootdisk.dir}/boot/grub" />
<copy todir="${bootdisk.dir}">
<fileset dir="${initjars.dir}">
<include name="default.jgz"/>
<include name="full.jgz"/>
</fileset>
</copy>
<bootdisk destfile="${jnode.disk}"
stage1ResourceName="${grub.stage1.name}"
stage2ResourceName="${grub.stage2.name}"
plnfile="${jnode.disk.pln}"
geometry="${jnode.disk.geometry}">
<fileset dir="${bootdisk.dir}" />
</bootdisk>
</target>The target:
- Depends on
java-image(which runs BootImageBuilder to create the boot image) - Can be skipped by setting the
no.bootdiskproperty - Copies the kernel (
jnode.kernel), GRUB menu, and initjars (default.jgz,full.jgz) into a staging directory - Invokes the
<bootdisk>task with the staging directory as a fileset
BootFloppyBuilder and BootImageBuilder serve different purposes:
| Aspect | BootFloppyBuilder | BootImageBuilder |
|---|---|---|
| Inheritance |
extends Task (Ant task) |
extends AbstractBootImageBuilder |
| Purpose | Creates a FAT filesystem image with GRUB | Compiles Java + native code into a bootable binary |
| Output | FAT-formatted disk image | Raw boot image binary (kernel + Java heap) |
| GRUB | Embeds GRUB stage1/stage2 into FAT boot sector | No GRUB; uses Multiboot header |
| FAT filesystem | Yes — creates FAT, copies files | No — emits raw native stream |
| JIT compilation | None | Pre-compiles Java classes using L1/L2 JIT |
| Relationship | Post-processing: wraps boot image in FAT | Creates the boot image that gets placed into FAT |
The Boot-CD-ROM-Builder creates ISO-9660 CD-ROM images. The boot disk image created by BootDiskBuilder can be wrapped into an ISO using the create-cdrom macro:
BootDiskBuilder → jnode.disk (FAT disk image)
→ create-cdrom → jnode.iso (ISO-9660 CD-ROM)
The cd-x86-lite and cd-x86_64-lite Ant targets orchestrate this pipeline.
-
Naming mismatch: The class is called "BootFloppyBuilder" but its own Javadoc says "in fact, it's not a floppy but a cdrom image in the iso format". In practice, BootFloppyBuilder creates a 1.44MB FAT floppy image, while BootDiskBuilder creates a partitioned hard disk image. Neither creates an ISO directly — that's done by the
create-cdrommacro. -
BootDiskBuilder is what's actually used: The Ant build system uses
BootDiskBuilder(the subclass), notBootFloppyBuilderdirectly. The<bootdisk>taskdef points toorg.jnode.build.BootDiskBuilder. -
no.bootdiskproperty: Theboot-disktarget can be skipped by setting this property, which is available as an install script option inall/conf-source/script.xml. - GRUB stage1/stage2 are classpath resources: The GRUB bootloader binaries are loaded from the classpath (default names: "stage1", "stage2"). They must be available on the build classpath.
- Incremental build: BootFloppyBuilder checks timestamps before executing. If the destination file is newer than all source files, the task is skipped.
-
VMware .pln file: BootDiskBuilder writes a
.plnfile with cylinder/head/sector geometry. This is used by VMware/VirtualBox to create the correct virtual disk geometry. - FAT16 vs FAT12: BootFloppyBuilder uses FAT12 (floppy format), while BootDiskBuilder uses FAT16 <32M (hard disk format). The formatter is selected based on the constructor parameters.
-
Partition 0 is the system partition: BootDiskBuilder's
getSystemDevice()returns partition 0 (viaMappedFSBlockDeviceSupport), not the root device. This is where the FAT filesystem and GRUB are placed.
- Build-System — Hub page for the JNode build system
- Build---BootImageBuilder-Internals — Boot image creation (runs before BootFloppyBuilder)
- Boot-CD-ROM-Builder — ISO-9660 CD-ROM creation (wraps boot disk image)
- Boot-Sequence — How the boot image created here is loaded at runtime
- FAT-Filesystem — FAT filesystem implementation used to copy files onto the disk image
- Partition-Tables — IBM partition table format used by BootDiskBuilder