Xen ARM with Virtualization Extensions/Multiboot

= Background =
In order to boot Xen on a system it is necessary to load several binaries and pass them to the Xen kernel at boot time. These are:
* Xen itself (primary boot image)
* A domain 0 kernel image
* An (optional) domain 0 ramdisk
* A DTB describing the hardware platform
* ...
On x86 this is achieved using the Multiboot Specification. However multiboot1 is very x86 specific. multiboot2 is cross platform but doesn't currently support ARM. Both are more complicated than what is needed on ARM. See https://wiki.linaro.org/AndrePrzywara/Multiboot for a summary.
= Multiboot on ARM Specification =
== FDT Based Protocol ==
A proposal exists for a simpler Device Tree based system.
This is described in http://xenbits.xen.org/gitweb/?p=xen.git;a=blob;f=docs/misc/arm/device-tree/booting.txt;h=08ed7751859dbe2d2c32d86d7df371057d7b45a4;hb=HEAD
Andre Przywara has proposed some modifications to the above which make it more
generic, see: http://thread.gmane.org/gmane.linux.linaro.announce.boot/326
The specific compatible strings to be used need to be defined, I've used
something vaguely sensible sounding below. Note These have now been updated based on the discussion in http://lists.linaro.org/pipermail/linaro-uefi/2014-June/000302.html.
== Scope == 
Although the need for this specification was driven by the needs of Xen on ARM it is not intended that the protocol be Xen specific.
== GrUB ==
Linaro is working towards using GrUB as the standard bootloader on therefore it is necessary to have some grub syntax which can be used to cause the multiboot nodes to be added to the chosen node of the DTB.
The grub syntax should be compatible with what the existing x86 tools
(e.g. update-grub) generate. On my Debian x86 system such a stanza looks
like:
 menuentry 'Debian GNU/Linux, with Xen 4.1-amd64 and Linux 3.10-3-amd64' --class debian --class gnu-linux --class gnu --class os --class xen {
 insmod part_msdos
 insmod ext2
 set root='(hd0,msdos1)'
 search --no-floppy --fs-uuid --set=root c4291ab1-d3ad-4c70-ab97-e6c8cca0af2b
 echo 'Loading Xen 4.1-amd64 ...'
 multiboot /xen-4.1-amd64.gz placeholder 
 echo 'Loading Linux 3.10-3-amd64 ...'
 module /vmlinuz-3.10-3-amd64 placeholder root=/dev/mapper/disks-root ro resume=/dev/mapper/disks-swap quiet
 echo 'Loading initial ramdisk ...'
 module /initrd.img-3.10-3-amd64
 }
The relevant commands here are the "multiboot" and "module" commands.
Note: on x86 these commands relate to the x86 multiboot version 1
support. This is very x86 specific and will never be supported on ARM.
multiboot2 (which supports multiple architectures, but doesn't include
ARM) has it's own separate "multiboot2" command and it is reasonable to
assume that any future revisions of multiboot which might incorporate
ARM support will have their own unique keyword. Hence there is no
concern about a clash with the multiboot command name.
=== Command: multiboot ===
 multiboot [KERNEL] [COMMAND LINE...]
Specifies a kernel to be loaded which expects to be passed a DTB containing a set of modules in the /chosen node as defined in the multiboot device tree bindings.
 
[KERNEL] is the path to the kernel binary.
 
All remaining arguments should be passed as the command line ("/chosen/bootargs") to the kernel.
 
(NB: "placeholder" in the above example is a weird x86-ism, Xen will ignore it, there is no need to special case it in grub on ARM)
=== Command: module ===
Syntax:
 module [PATH] [COMMAND LINE...]
Specifies a module to be loaded and passed via a module node under /chosen. This option may be used multiple times to pass multiple modules.
[PATH] is the path to the binary to be loaded. It shall be loaded into RAM at an address to be referenced as described in the multiboot device tree bindings.
 
The remainder of the command line shall be used as the module's "bootargs" property.
 
Each module will be given a default compatibility property based on the order in which the modules are added.
 
The first module specified in this way will be:
* compatible = "multiboot,kernel", "multiboot,module"
The second module specified in this way will be:
* compatible = "multiboot,ramdisk", "multiboot,module"
All subsequent modules will be:
* compatible = "multiboot,module"
Possible extension:
Allow the module command to take an optional:
 --type <compatible-string>
argument before [PATH].
 
This would override default compatible string for this module. May be given multiple times, the strings will be listed in the compatible property in the order given. Note that this means that the generic "multiboot,module" would need to be specified separately if desired.
 
Modules which are given an explicit compatibility do not "consume" a default. So:
 module --type foo <...>
 module <...>
 module <...>
Would result in the modules having:
* 1st: compatible = "foo" 
* 2nd: compatible = "multiboot,kernel", "multiboot,module"
* 3rd: compatible = "multiboot,ramdisk", "multiboot,module"
and not:
* 1st: compatible = "foo" 
* 2nd: compatible = "multiboot,ramdisk", "multiboot,module"
* 3rd: compatible = "multiboot,module"
 
In addition even if --type is used to specify something which is also a default it will not be consumed. Thus:
 module --type "multiboot,ramdisk" --type "multiboot,module" <...>
 module <...>
 module <...>
results in:
* 1st: compatible = "multiboot,ramdisk", "multiboot,module"
* 2nd: compatible = "multiboot,kernel", "multiboot,module"
* 3rd: compatible = "multiboot,ramdisk", "multiboot,module"
and not
* 1st: compatible = "multiboot,ramdisk", "multiboot,module"
* 2nd: compatible = "multiboot,kernel", "multiboot,module"
* 3rd: compatible = "multiboot,module"
== Compatible strings ==
The default compatible string is "multiboot,module". Every module should normally have this as the fallback compatibility string.
Other available strings:
; "multiboot,kernel"
: This module contains an OS kernel (not this is being passed as data to the actual multiboot kernel). Neither the format of this kernel nor the boot protocol required to launch it is specified (in particular it is not required that kernels passed in this way understand multiboot themselves). It is up to the multiboot kernel to probe e.g. for magic numbers and determine this for itself. More specific compatibility strings should be defined and used when a kernel image cannot be probed (i.e it lacks a magic number or is very generic) or has special boot requirements.
; "multiboot,ramdisk"
: This module contains a ramdisk to be passed to an OS kernel. It is defined by the individual multiboot kernel implementation how this is used e.g. whether it is consumed by the multiboot kernel itself or matched to a "multiboot,kernel" module and passed on using a protocol specific to that kernel.
In addition a multiboot capable kernel may also define its own compatibility strings for additional modules which it understands or for special cases of the above.
== Changes ==
* 2014-06-66
** Switched to "multiboot,kernel", "multiboot,ramdisk" and "multiboot,module" in place of "multiboot,linux-zimage", "multiboot,linux-ramdisk" and "boot,module".
** Clarify the scope. moving the preamble about Xen's requirements into a background section.
** Added more information on the compatibility strings.