summaryrefslogtreecommitdiff
path: root/docs/misc/efi.pandoc
blob: 11c1ac3346009b09a49af5e7dba568745d0bd559 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
For x86, building xen.efi requires gcc 4.5.x or above (4.6.x or newer
recommended, as 4.5.x was probably never really tested for this purpose) and
binutils 2.22 or newer.  Additionally, the binutils build must be configured to
include support for the x86_64-pep emulation (i.e.
`--enable-targets=x86_64-pep` or an option of equivalent effect should be
passed to the configure script).

For arm64, the PE/COFF header is open-coded in assembly, so no toolchain
support for PE/COFF is required.  Also, the PE/COFF header co-exists with the
normal Image format, so a single binary may be booted as an Image file or as an
EFI application.  When booted as an EFI application, Xen requires a
configuration file as described below unless a bootloader, such as GRUB, has
loaded the modules and describes them in the device tree provided to Xen.  If a
bootloader provides a device tree containing modules then any configuration
files are ignored, and the bootloader is responsible for populating all
relevant device tree nodes.
The property "xen,uefi-cfg-load" can be specified in the /chosen node to force
Xen to load the configuration file even if multiboot modules are found.

Once built, `make install-xen` will place the resulting binary directly into
the EFI boot partition, provided `EFI_VENDOR` is set in the environment (and
`EFI_MOUNTPOINT` is overridden as needed, should the default of `/boot/efi` not
match your system). When built with debug info, the binary can be quite large.
Setting `INSTALL_EFI_STRIP=1` in the environment will cause it to be stripped
of debug info in the process of installing. `INSTALL_EFI_STRIP` can also be set
to any combination of options suitable to pass to `strip`, in case the default
ones don't do. The xen.efi binary will also be installed in `/usr/lib64/efi/`,
unless `EFI_DIR` is set in the environment to override this default. This
binary will not be stripped in the process.

The binary itself will require a configuration file (names with the `.efi`
extension of the binary's name replaced by `.cfg`, and - until an existing
file is found - trailing name components dropped at `.`, `-`, and `_`
separators will be tried) to be present in the same directory as the binary.
(To illustrate the name handling, a binary named `xen-4.2-unstable.efi` would
try `xen-4.2-unstable.cfg`, `xen-4.2.cfg`, `xen-4.cfg`, and `xen.cfg` in
order.) One can override this with a command line option (`-cfg=<filename>`).
This configuration file and EFI commandline are only used for booting directly
from EFI firmware, or when using an EFI loader that does not support
the multiboot2 protocol.  When booting using GRUB or another multiboot aware
loader the EFI commandline is ignored and all information is passed from
the loader to Xen using the multiboot protocol.

The configuration file consists of one or more sections headed by a section
name enclosed in square brackets, with individual values specified in each
section. A section named `[global]` is treated specially to allow certain
settings to apply to all other sections (or to provide defaults for certain
settings in case individual sections don't specify them). This file (for now)
needs to be of ASCII type and not e.g. UTF-8 or UTF-16. A typical file would
thus look like this (`#` serving as comment character):

    **************************example begin******************************

    [global]
    default=sle11sp2

    [sle11sp2]
    options=console=vga,com1 com1=57600 loglvl=all noreboot
    kernel=vmlinuz-3.0.31-0.4-xen [domain 0 command line options]
    ramdisk=initrd-3.0.31-0.4-xen

    **************************example end********************************

The individual values used here are:

###`default=<name>`

Specifies the section to use for booting, if none was specified on the command
line; only meaningful in the `[global]` section. This isn't required; if
absent, section headers will be ignored and for each value looked for the
first instance within the file will be used.

###`options=<text>`

Specifies the options passed to the hypervisor, see [Xen Hypervisor Command
Line Options](xen-command-line.html).

###`kernel=<filename>[ <options>]`

Specifies the Dom0 kernel binary and the options to pass to it.

The options should in general be the same as is used when booting
natively, e.g. including `root=...` etc.

Check your bootloader (e.g. grub) configuration or `/proc/cmdline` for
the native configuration.

###`ramdisk=<filename>`

Specifies a Linux-style initial RAM disk image to load.

Other values to specify are:

###`video=gfx-<xres>[x<yres>[x<depth>]]`

Specifies a video mode to select if available. In case of problems, the
`-basevideo` command line option can be used to skip altering video modes.

###`xsm=<filename>`

Specifies an XSM module to load.

###`ucode=<filename>`

Specifies a CPU microcode blob to load. (x86 only)

###`dtb=<filename>`

Specifies a device tree file to load.  The platform firmware may provide a
DTB in an EFI configuration table, so this field is optional in that
case. A dtb specified in the configuration file will override a device tree
provided in the EFI configuration table. (ARM only)

###`chain=<filename>`

Specifies an alternate configuration file to use in case the specified section
(and in particular its `kernel=` setting) can't be found in the default (or
specified) configuration file. This is only meaningful in the [global] section
and really not meant to be used together with the `-cfg=` command line option.

Filenames must be specified relative to the location of the EFI binary.

Extra options to be passed to Xen can also be specified on the command line,
following a `--` separator option.

## Unified Xen kernel image

The "Unified" kernel image can be generated by adding additional
sections to the Xen EFI executable with objcopy, similar to how
[systemd-boot uses the stub to add them to the Linux kernel](https://wiki.archlinux.org/index.php/systemd-boot#Preparing_a_unified_kernel_image)

The sections for the xen configuration file, the dom0 kernel, dom0 initrd,
XSM and CPU microcode should be added after the Xen `.pad` section, the
ending address of which can be located with:

```
objdump -h xen.efi \
	| perl -ane '/\.pad/ && printf "0x%016x\n", hex($F[2]) + hex($F[3])'
```

For all the examples the `.pad` section ended at 0xffff82d041000000.
All the sections are optional (`.config`, `.kernel`, `.ramdisk`, `.xsm`,
`.ucode` (x86) and `.dtb` (ARM)) and the order does not matter.
The virtual addresses do not need to be contiguous, although they should not
be overlapping and should all be greater than the last virtual address of the
hypervisor components.

```
objcopy \
	--add-section .config=xen.cfg \
	--change-section-vma .config=0xffff82d041000000
	--add-section .ucode=ucode.bin \
	--change-section-vma .ucode=0xffff82d041010000 \
	--add-section .xsm=xsm.cfg \
	--change-section-vma .xsm=0xffff82d041080000 \
	--add-section .kernel=vmlinux \
	--change-section-vma .kernel=0xffff82d041100000 \
	--add-section .ramdisk=initrd.img \
	--change-section-vma .ramdisk=0xffff82d042000000 \
	xen.efi \
	xen.unified.efi
```

The unified executable can be signed with sbsigntool to make
it usable with UEFI secure boot:

```
sbsign \
	--key signing.key \
	--cert cert.pem \
	--output xen.signed.efi \
	xen.unified.efi
```
## UEFI boot and Dom0 modules on ARM

When booting using UEFI on ARM, it is possible to specify the Dom0 modules
directly from the device tree without using the Xen configuration file, here an
example:

chosen {
	#size-cells = <0x1>;
	#address-cells = <0x1>;
	xen,xen-bootargs = "[Xen boot arguments]"

	module@1 {
		compatible = "multiboot,kernel", "multiboot,module";
		xen,uefi-binary = "vmlinuz-3.0.31-0.4-xen";
		bootargs = "[domain 0 command line options]";
	};

	module@2 {
		compatible = "multiboot,ramdisk", "multiboot,module";
		xen,uefi-binary = "initrd-3.0.31-0.4-xen";
	};
}

## UEFI boot and dom0less on ARM

Dom0less feature is supported by ARM and it is possible to use it when Xen is
started as an EFI application.
The way to specify the domU domains is by Device Tree as specified in the
[dom0less](dom0less.html) documentation page under the "Device Tree
configuration" section, but instead of declaring the reg property in the boot
module, the user must specify the "xen,uefi-binary" property containing the name
of the binary file that has to be loaded in memory.
The UEFI stub will load the binary in memory and it will add the reg property
accordingly.

An example here:

domU1 {
	#address-cells = <1>;
	#size-cells = <1>;
	compatible = "xen,domain";
	memory = <0 0x20000>;
	cpus = <1>;
	vpl011;

	module@1 {
		compatible = "multiboot,kernel", "multiboot,module";
		xen,uefi-binary = "vmlinuz-3.0.31-0.4-xen";
		bootargs = "console=ttyAMA0";
	};
	module@2 {
		compatible = "multiboot,ramdisk", "multiboot,module";
		xen,uefi-binary = "initrd-3.0.31-0.4-xen";
	};
	module@3 {
		compatible = "multiboot,device-tree", "multiboot,module";
		xen,uefi-binary = "passthrough.dtb";
	};
};

## How to boot different Xen setup using UEFI

These are the different ways to boot a Xen system from UEFI:

 - Boot Xen and Dom0 (minimum required)
 - Boot Xen and DomU(s) (true dom0less, only on ARM)
 - Boot Xen, Dom0 and DomU(s) (only on ARM)

### Boot Xen and Dom0

This configuration can be started using the Xen configuration file in the
example above.

### Boot Xen and DomU(s)

This configuration needs the domU domain(s) specified in the /chosen node,
examples of how to do that are provided by the documentation about dom0less
and the example above shows how to use the "xen,uefi-binary" property to use the
UEFI stub for module loading.
When adding DomU modules to device tree, also add the property
xen,uefi-cfg-load under chosen for Xen to load the Xen config file.
Otherwise, Xen will skip the config file and rely on device tree alone.
When using the Xen configuration file in conjunction with the device tree, you
can specify the Xen boot arguments in the configuration file with the "options="
keyword or in the device tree with the "xen,xen-bootargs" property, but be
aware that the Xen configuration file value has a precedence over the DT value.

Example 1 of how to boot a true dom0less configuration:

Xen configuration file: skipped.

Device tree:

```
chosen {
	#size-cells = <0x1>;
	#address-cells = <0x1>;
	xen,xen-bootargs = "<Xen command line>"

	domU1 {
		#size-cells = <0x1>;
		#address-cells = <0x1>;
		compatible = "xen,domain";
		cpus = <0x1>;
		memory = <0x0 0xc0000>;
		vpl011;

		module@1 {
			compatible = "multiboot,kernel", "multiboot,module";
			xen,uefi-binary = "Image-domu1.bin";
			bootargs = "console=ttyAMA0 root=/dev/ram0 rw";
		};
	};
	domU2 {
		#size-cells = <0x1>;
		#address-cells = <0x1>;
		compatible = "xen,domain";
		cpus = <0x1>;
		memory = <0x0 0x100000>;
		vpl011;

		module@2 {
			compatible = "multiboot,kernel", "multiboot,module";
			xen,uefi-binary = "Image-domu2.bin";
			bootargs = "console=ttyAMA0 root=/dev/ram0 rw";
		};
	};
};
```

Example 2 of how to boot a true dom0less configuration:

Xen configuration file:

```
[global]
default=xen

[xen]
options=<Xen command line>
dtb=<optional DTB>
```

Device tree:

```
chosen {
	#size-cells = <0x1>;
	#address-cells = <0x1>;
	xen,uefi-cfg-load;

	domU1 {
		#size-cells = <0x1>;
		#address-cells = <0x1>;
		compatible = "xen,domain";
		cpus = <0x1>;
		memory = <0x0 0xc0000>;
		vpl011;

		module@1 {
			compatible = "multiboot,kernel", "multiboot,module";
			xen,uefi-binary = "Image-domu1.bin";
			bootargs = "console=ttyAMA0 root=/dev/ram0 rw";
		};
	};
	domU2 {
		#size-cells = <0x1>;
		#address-cells = <0x1>;
		compatible = "xen,domain";
		cpus = <0x1>;
		memory = <0x0 0x100000>;
		vpl011;

		module@2 {
			compatible = "multiboot,kernel", "multiboot,module";
			xen,uefi-binary = "Image-domu2.bin";
			bootargs = "console=ttyAMA0 root=/dev/ram0 rw";
		};
	};
};
```

### Boot Xen, Dom0 and DomU(s)

This configuration is a mix of the two configuration above, to boot this one
the configuration file can be processed or the Dom0 modules can be read from
the device tree.

Here the first example:

Xen configuration file:

```
[global]
default=xen

[xen]
options=<Xen command line>
kernel=vmlinuz-3.0.31-0.4-xen [domain 0 command line options]
ramdisk=initrd-3.0.31-0.4-xen
dtb=<optional DTB>
```

Device tree:

```
chosen {
	#size-cells = <0x1>;
	#address-cells = <0x1>;
	xen,uefi-cfg-load;

	domU1 {
		#size-cells = <0x1>;
		#address-cells = <0x1>;
		compatible = "xen,domain";
		cpus = <0x1>;
		memory = <0x0 0xc0000>;
		vpl011;

		module@1 {
			compatible = "multiboot,kernel", "multiboot,module";
			xen,uefi-binary = "Image-domu1.bin";
			bootargs = "console=ttyAMA0 root=/dev/ram0 rw";
		};
	};
};
```

Here the second example:

Device tree:

```
chosen {
	#size-cells = <0x1>;
	#address-cells = <0x1>;
	xen,xen-bootargs = "[Xen boot arguments]"

	module@1 {
		compatible = "multiboot,kernel", "multiboot,module";
		xen,uefi-binary = "vmlinuz-3.0.31-0.4-xen";
		bootargs = "[domain 0 command line options]";
	};

	module@2 {
		compatible = "multiboot,ramdisk", "multiboot,module";
		xen,uefi-binary = "initrd-3.0.31-0.4-xen";
	};

	domU1 {
		#size-cells = <0x1>;
		#address-cells = <0x1>;
		compatible = "xen,domain";
		cpus = <0x1>;
		memory = <0x0 0xc0000>;
		vpl011;

		module@1 {
			compatible = "multiboot,kernel", "multiboot,module";
			xen,uefi-binary = "Image-domu1.bin";
			bootargs = "console=ttyAMA0 root=/dev/ram0 rw";
		};
	};
};
```