A minimal, single-stage bootloader for the AM335x (BeagleBone Black) written from scratch in C and ARM assembly. No U-Boot, no external dependencies — just bare metal.
ROM (chip) ──► Bootloader (SRAM 110KB) ──► Kernel (DDR @ 0x80000000)
The bootloader runs entirely from the AM335x internal SRAM and performs:
- Watchdog timer disable
- Clock configuration (DDR PLL @ 400MHz)
- UART0 initialization (115200 8N1)
- DDR3 memory init (256MB) with self-test
- MMC/SD card initialization and raw sector read
- Kernel image loading and validation
- Kernel handoff with boot parameters
- Full exception handling (Data Abort, Prefetch Abort, Undefined Instruction)
├── src/
│ ├── arch/arm/start.S # Entry point, vector table, CPU mode setup
│ ├── main.c # Boot flow orchestration
│ ├── clock.c # PLL and clock configuration
│ ├── ddr.c # DDR3 controller initialization
│ ├── mmc.c # MMC/SD card driver
│ ├── uart.c # UART serial driver
│ └── utils.c # Utility functions (delay, memcpy, memset)
├── include/
│ ├── am335x.h # AM335x register definitions
│ ├── boot.h # Function prototypes
│ └── types.h # Type definitions
├── linker/
│ └── bootloader.ld # Linker script (SRAM @ 0x402F0400)
├── tools/
│ └── gp_header.py # GP header generator for AM335x ROM
└── Makefile
Environment
- OS: Ubuntu 24.04+ (or equivalent Linux distro)
- Python: 3.x
- Toolchain:
arm-none-eabi-gcc,arm-none-eabi-binutils
Install dependencies on Ubuntu:
sudo apt update
sudo apt install -y gcc-arm-none-eabi binutils-arm-none-eabi python3Verify toolchain:
arm-none-eabi-gcc --version
arm-none-eabi-objcopy --version
python3 --versionmake # Build → outputs MLO
make clean # Clean build artifacts
make size # Show binary size# Format SD card with FAT32 partition (must be bootable)
# Copy MLO to the root of the FAT32 partition
cp build/MLO /media/sdcard/The AM335x ROM looks for a file named MLO on the first FAT32 partition of the SD card.
- ROM bootloader (built into AM335x silicon) initializes minimal hardware, finds
MLOon SD card, loads it into SRAM at0x402F0400 - This bootloader takes over: sets up vector table, exception stacks, disables watchdog, inits clocks/DDR/UART/MMC
- Reads kernel image from SD card raw sectors into DDR at
0x80000000 - Validates kernel image header and jumps to execution address
- SoC: Texas Instruments AM335x (ARM Cortex-A8)
- Board: BeagleBone Black
- RAM: 256MB DDR3 @ 400MHz
- Boot media: microSD card