MILO, the Alpha Linux Miniloader, is a boot loader and minimal firmware for Alpha systems. It initializes the machine, loads Linux, and provides the PALcode that Linux runs on. 1) It is used on systems with the ARC or AlphaBIOS firmware, whose PALcode is designed for Windows NT and cannot run Linux. 2) Systems with the SRM console boot Linux with aboot instead, which is simpler. 3)
MILO is therefore needed only on systems without an SRM console. The Alpha XL, the Alpha XLT, and the AlphaPC 164UX (Ruffian) can boot Linux only with MILO, 4) as can the AlphaPC 164RX, for which no SRM console was released. 5) Current kernels require an EV56 (21164A) or later processor, which rules out the Alpha XL 233, 266, and 300; the XL 366 and 433 have 21164A processors. 6) MILO does not support multiprocessor systems or 21264 systems. 7) 8)
MILO's last release, 2.2-18, dates from July 2001 and is based on Linux 2.2. 9) It cannot boot kernels from Linux 2.6.23 on, which have a PT_NOTE program header. The source repository, https://github.com/alphalinux/milo, fixed this in 2026, so a current kernel needs a MILO built from it. 10) No current kernel has been reported booting through MILO, with a repository build or otherwise.
MILO reads the kernel from ext2 (or ext3, read as ext2), and from FAT, ISO 9660, or ReiserFS if built with them, but not from ext4 or XFS; see Known issues. An initrd must fit below MILO in the first 13 MiB of memory, and cannot be used at all with a kernel built without CONFIG_ALPHA_LEGACY_START_ADDRESS; see initrd. The simplest kernel for MILO therefore has the drivers for its root file system built in and no initrd.
The MILO image for each system is: 11)
| System | Code name | MILO image |
|---|---|---|
| AlphaStation 600, AlphaStation 500, Alpha XL 300/366/433 | Alcor, XLT | xlt-alcor |
| AlphaStation 200, 205, 250, 255, 300, 400 | Avanti | avanti |
| Alpha XL 233/266 | XL | xl |
| Digital Personal Workstation | Miata | miata |
| AXPpci33, Multia | Noname, UDB | udb-noname |
| AlphaPC 64 | Cabriolet | cabrio |
| AlphaPC 164 | PC164 | pc164 |
| AlphaPC 164LX | LX164 | lx164 |
| AlphaPC 164SX | SX164 | sx164 |
| EB164 | EB164 | eb164 |
| EB64+ | EB64+ | eb64p |
| EB66+ | EB66+ | eb66p |
| EB66 | EB66 | eb66 |
| AlphaPC 164UX, 164BX | Ruffian | ruffian 12) 13) |
The Noname, EB64+, EB66 and EB66+, Cabriolet, Alcor, AlphaStation 500, PC164, LX164, SX164, and Miata can boot Linux either with MILO or from SRM. 14) Digital listed no MILO image for the Jensen, the AlphaServer 1000, 1000A, 1200, 2000, 2100, 4000, and 4100, or the AlphaBook 1, all of which have SRM. 15)
ldmilo.exe instead of linload.exe. 16) ldmilo was written by Deskstation, and requires the MILO file to be named milo. 17) Digital's images for it were ldmilo-ruffian-981020 and milo-ruffian-981020. 18)
MILO must be built from the repository for the system's platform (see Building), since no released binary can boot a current kernel. The loader that ARC or AlphaBIOS runs to start MILO, linload.exe, was only ever distributed as a binary, 24) and the Ruffian's ldmilo.exe came from Deskstation. 25)
A disk that boots Linux through MILO is set up as follows:
/boot file system; see Known issues for the file system limits.
The alphalinux/milo repository contains releases 2.2-9 to 2.2-18 as imported commits, followed by work from 2026. That work vendors the Linux 2.2.26 sources, so that no external kernel tree is needed, and fixes building with a current cross-compiler. 29) make config selects the platform, and make then builds MILO with the cross-compiler named by CROSS_COMPILE, by default alpha-unknown-linux-gnu-. 30)
make config first asks for the path to the kernel sources, which is no longer used, then for the system type, and then for options such as serial console echo, its port and speed, and the file systems to include (ext2 by default; FAT, ReiserFS, and ISO 9660 are off). 31) 32) make oldconfig reuses an existing .config. A build for the Ruffian, for example: 33)
git clone https://github.com/alphalinux/milo.git cd milo make config # choose "Ruffian" as the Alpha system type make CROSS_COMPILE=alpha-linux-gnu- # or CROSS_COMPILE= on an Alpha
Every platform produces milo, the image loaded by linload.exe or ldmilo.exe. Most also produce milo.dd for an SRM boot floppy, and some also produce milo.rom or the flash utility fmu.gz, or both; the Ruffian build produces only milo and mboot. 34)
The released MILO 2.2 was instead built against a separately configured generic Linux 2.2 kernel, at least 2.2.18, without modules or sysctl support. 35) By 2007, that source could not be built with a current toolchain. 36)
MILO can be loaded from ARC, AlphaBIOS, the SRM console, an evaluation board Debug Monitor, a fail-safe boot block floppy, or flash. 37) The build produces milo for booting from ARC or AlphaBIOS, milo.dd for writing to a floppy and booting from SRM, and milo.rom for flashing. 38)
ARC and AlphaBIOS run linload.exe, which passes the memory size and boot selection from the firmware to MILO and switches to MILO's PALcode. 39) linload.exe was built with the Windows NT ARC firmware tree and Microsoft tools, and its source was never released. 40) 41)
OSLOADFILENAME names the MILO image, so several MILO versions can be kept on the same partition. 44)linload.exe version must match MILO, or MILO gets the memory size wrong. 45) Version 1.3 or later is needed with more than 128 MiB of memory 46) and with AlphaBIOS: earlier versions load MILO at a fixed address, which crashes AlphaBIOS, while 1.3 searches the memory map for a free location. 1.3 also accepts a directory for OSLOADFILENAME, for AlphaBIOS versions that only accept a directory. 47) The Alpha XLT 366 needs the latest version. 48)
On systems that also have SRM, milo.dd can be written to a floppy with dd and booted with boot dva0. 52) Booting Linux directly with aboot is simpler. 53)
On the AlphaPC 64, Noname, EB66+, EB164, and AlphaPC 164, MILO could also be written to flash with its Flash Management Utility and started directly. 54) MILO relies on the previous console for some hardware initialization, and Digital stopped supporting flashing it in 1998. 55)
A kernel is booted with boot device:file followed by the kernel arguments, e.g.: 56) 57)
MILO> boot sda2:vmlinux.gz root=/dev/sda3 MILO> boot sda2:vmlinux.gz root=/dev/sda3 console=ttyS0
MILO 2.2-17 and later load an initial ramdisk given with initrd=path on the command line. 68) The path has no device, since MILO only has one device open at a time. 69)
MILO runs at 13 MiB (0xd00000) and places the initrd directly below itself; if the initrd would reach down into the kernel, MILO refuses to load it. 70) 71) A kernel built with CONFIG_ALPHA_LEGACY_START_ADDRESS starts at 3 MiB, leaving less than 10 MiB for the kernel and initrd together. A kernel without it starts at 16 MiB, above MILO, so MILO cannot load any initrd for it. 72) A kernel for a MILO system therefore needs either a small initrd and the legacy start address, or no initrd, with the drivers for the root file system built in.
MILO 2.2 reads a configuration file similar to lilo.conf when given boot with only a device, e.g. boot sda2:. 73) 74) It looks for /etc/milo.conf, then /milo.cfg. 75)
With /boot on sda2 and the root file system on sda3, paths are relative to sda2:
timeout = 50 image = /vmlinux.gz label = linux root = /dev/sda3 append = "console=ttyS0"
timeout is in tenths of a second. It boots the first image; 0 means no time limit. 76)command runs a MILO command when the file is read, or, inside an image section, just before booting that image. It can be repeated. 77)image starts a section, with label (case sensitive), root, append, and device. The image can include a device, e.g. sda1:/vmlinux.gz. 78)boot sda2: followed by a label boots that image. 79)
miloctl edits the parameter block inside a MILO image file (not the copy in memory): 80)
cmd=command sets a startup command, run when MILO is about to show its prompt, with one second to abort it. OSLOADOPTIONS overrides it. A typical startup command is boot sda2:, which reads milo.conf.mem=size overrides the memory size in MiB.+S and +V set the SERIAL_OUTPUT and VERBOSE flags, which are off by default.
For example, miloctl -v /dev/fd0 +S +V enables output to the serial port during startup on a MILO floppy. 81) A startup command and milo.conf can be combined by using the startup command only to point to milo.conf. 82) Linux itself needs console=ttyS0 to use the serial port; see Using the SRM Console: Serial console for the cabling and terminal settings.
The MILO 2.2 commands are: 83)
| Command | Description |
|---|---|
ls [path] | List files in a directory |
cd path | Change the current directory |
boot [path [arguments]] | Boot a kernel |
read [dev:] block | Read a block from a device |
run path | Run a standalone program |
show | Display all known devices and file systems |
sleep seconds | Wait |
pci | Display the PCI configuration |
set [variable value], unset variable | Set, display, or delete variables |
setenv, unsetenv, resetenv | Set or delete variables stored in NVRAM, instead of set and unset on systems with NVRAM support |
bootopt num | Select the firmware to start at power-on (Cabriolet, EB66+, EB164, and PC164 only) |
help | Print the command summary |
b sda2:vmlinux.gz root=/dev/sda3. 86)| more to a command pages its output. 87)| Variable | Description |
|---|---|
MEMORY_SIZE | Memory size in MiB |
BOOT_DEV, BOOT_FILE, BOOT_STRING | Default boot device, kernel file, and kernel arguments |
AUTOBOOT, AUTOBOOT_TIMEOUT | Boot at power-on, after a timeout in seconds |
SCSIn_HOSTID | Host ID of the nth SCSI controller (default 7) |
PCI_LATENCY | PCI bus master latency (default 32, maximum 255) |
CPU_CLOCK | CPU speed in MHz, for systems that report it wrongly |
VERBOSE | Print more information |
set MEMORY_SIZE is the usual workaround when MILO detects the wrong memory size. 95)mke2fs uses 256-byte inodes, and 4 KiB blocks on all but small file systems, so /boot should be a small ext2 file system created with mke2fs -t ext2 -b 1024 -I 128. 101) Alternatively, the kernel can be kept on the FAT partition next to MILO. 102)SERIAL_OUTPUT flag is set (see miloctl) or a character has been received on the port. 103) 104) 105) A modem or other device on COM1 can therefore fill the screen with O> and block input. 106) 107)wtint call, which Nikita Schmidt added only for the Avanti. 113)MILO consists of PALcode, memory and video setup, block device drivers taken unmodified from the Linux kernel it is built against, its own file system code, a user interface, and the code that builds the HWRPB for Linux. 114) MILO does not configure network devices. 115)
MILO's PALcode is based on the sample PALcode in Digital Semiconductor's Evaluation Board System Developers Kit (EBSDK). 116) The loader that starts MILO from ARC switches from the Windows NT PALcode to MILO's. 117) Each board has its own PALcode. Systems not built by Digital Semiconductor, such as the Avanti and Mikasa, use modified evaluation board PALcode. 118)
The EBSDK PALcode is less complete than the SRM PALcode: Digital supplied it as-is, for informational purposes, and recommended SRM wherever it was available. 119) It lacks access to the performance counters and support for the prefetch code generated by Compaq's C compiler, 120) ECC error reporting, 121) and the PAL calls needed by NetBSD and OpenBSD. 122) MILO also does not provide the SRM console callbacks. 123)
On many systems, the MILO and SRM PALcode deliver interrupts differently, so kernels built for one would not boot from the other. 124) On the Noname, UDB, Avanti, and Platform 2000, the same kernel boots from both. 125) Generic kernels run from either. 126)
MILO uses a VGA card if one is present, otherwise a TGA card. 127) VGA cards are initialized by running their x86 BIOS in an emulator. 128)
MILO builds the HWRPB and memory cluster descriptions that tell Linux the system type and the available memory. 129) Because it must describe the system itself, there is a separate MILO for each platform. 130) MILO sets the system serial number to MILO- followed by the version, e.g. MILO-2.0.35-c7, which lets Linux tools detect that MILO was used, 131) and each CPU's serial number to Linux_is_Great!. 132) 133) The kernel itself checks the MILO prefix of the system serial number to tell whether it was booted from SRM. 134) The UP1000's APB loader also uses MILO-0000. 135)
MILO leaves a compressed copy of itself in memory. When Linux reboots, it returns to that copy, which boots the same kernel with the same command after a 30 second timeout. 136) It is not possible to return to ARC. 137)
MILO's LICENSE file contains three licenses: Digital's PALcode license, which allows use only in products with an Alpha processor; a license for the BIOS emulation libraries, which forbids modifying them; and the GNU GPL. 138) Most MILO source files carry a separate Digital notice that permits use, copying, modification, and distribution. 139) The LICENSE file and the source headers are therefore inconsistent about which parts are under the GPL. 140) linload.exe is not free, since it uses parts of the Windows NT SDK. 141)
David A. Rusling of Digital's European Semiconductor Applications Engineering group in Reading, England, wrote MILO and its Flash Management Utility. 142) 143) MILO was first released publicly in BLADE 0.2 on 9 August 1995, as a console firmware replacement for systems without SRM support. 144) Jay Estabrook took over MILO in 1997, when Rusling moved to StrongARM work. 145) Nikita Schmidt at University College Dublin maintained a separate branch from 1998 to 2000, which added /etc/milo.conf, a startup command stored in the image, and the miloctl tool, and was used by Debian, Red Hat, and SuSE. 146) 147)
Stefan Reinauer of SuSE ported Schmidt's sources to Linux 2.2 as MILO 2.2 in November 1999. 148) 149) Release 2.2-17 added initrd support and fixes for Linux 2.4, 150) and the last release, 2.2-18 in July 2001, support for the UDB flash ROM and ReiserFS. 151) An attempt to port MILO to Linux 2.4 hung during PCI initialization on all machines. 152)
Once Windows NT for Alpha was discontinued, MILO was only needed on systems without SRM. 153) Reinauer stopped working on MILO in 2004, 154) and development resumed in the alphalinux repository in 2026. 155)
The following sources conflict with each other or with the account given above. They are listed here for further investigation.
| Document | Part number | Date |
|---|---|---|
| Alpha Miniloader Howto, v0.85 | April 1997 | |
| README.milo (MILO 2.2) | ||
| milo.conf(5) and miloctl(8) | ||
| ChangeLog (MILO 2.2) | ||
| milo-list archive (1999 to 2001) |
README, Linux-Alpha archive, ftp.digital.com, 19 Dec 1996
READ.ME, Miniloader directory, Linux-Alpha archive, ftp.digital.com, 26 Nov 1996