190268b87SSimon GlassBooting Linux on x86 with FIT
290268b87SSimon Glass=============================
390268b87SSimon Glass
490268b87SSimon GlassBackground
590268b87SSimon Glass----------
690268b87SSimon Glass
790268b87SSimon Glass(corrections to the text below are welcome)
890268b87SSimon Glass
990268b87SSimon GlassGenerally Linux x86 uses its own very complex booting method. There is a setup
1090268b87SSimon Glassbinary which contains all sorts of parameters and a compressed self-extracting
1190268b87SSimon Glassbinary for the kernel itself, often with a small built-in serial driver to
1290268b87SSimon Glassdisplay decompression progress.
1390268b87SSimon Glass
1490268b87SSimon GlassThe x86 CPU has various processor modes. I am no expert on these, but my
1590268b87SSimon Glassunderstanding is that an x86 CPU (even a really new one) starts up in a 16-bit
1690268b87SSimon Glass'real' mode where only 1MB of memory is visible, moves to 32-bit 'protected'
1790268b87SSimon Glassmode where 4GB is visible (or more with special memory access techniques) and
1890268b87SSimon Glassthen to 64-bit 'long' mode if 64-bit execution is required.
1990268b87SSimon Glass
2090268b87SSimon GlassPartly the self-extracting nature of Linux was introduced to cope with boot
2190268b87SSimon Glassloaders that were barely capable of loading anything. Even changing to 32-bit
2290268b87SSimon Glassmode was something of a challenge, so putting this logic in the kernel seemed
2390268b87SSimon Glassto make sense.
2490268b87SSimon Glass
2590268b87SSimon GlassBit by bit more and more logic has been added to this post-boot pre-Linux
2690268b87SSimon Glasswrapper:
2790268b87SSimon Glass
2890268b87SSimon Glass- Changing to 32-bit mode
2990268b87SSimon Glass- Decompression
3090268b87SSimon Glass- Serial output (with drivers for various chips)
3190268b87SSimon Glass- Load address randomisation
3290268b87SSimon Glass- Elf loader complete with relocation (for the above)
3390268b87SSimon Glass- Random number generator via 3 methods (again for the above)
3490268b87SSimon Glass- Some sort of EFI mini-loader (1000+ glorious lines of code)
3590268b87SSimon Glass- Locating and tacking on a device tree and ramdisk
3690268b87SSimon Glass
3790268b87SSimon GlassTo my mind, if you sit back and look at things from first principles, this
3890268b87SSimon Glassdoesn't make a huge amount of sense. Any boot loader worth its salts already
3990268b87SSimon Glasshas most of the above features and more besides. The boot loader already knows
4090268b87SSimon Glassthe layout of memory, has a serial driver, can decompress things, includes an
4190268b87SSimon GlassELF loader and supports device tree and ramdisks. The decision to duplicate
4290268b87SSimon Glassall these features in a Linux wrapper caters for the lowest common
4390268b87SSimon Glassdenominator: a boot loader which consists of a BIOS call to load something off
4490268b87SSimon Glassdisk, followed by a jmp instruction.
4590268b87SSimon Glass
4690268b87SSimon Glass(Aside: On ARM systems, we worry that the boot loader won't know where to load
4790268b87SSimon Glassthe kernel. It might be easier to just provide that information in the image,
4890268b87SSimon Glassor in the boot loader rather than adding a self-relocator to put it in the
4990268b87SSimon Glassright place. Or just use ELF?
5090268b87SSimon Glass
5190268b87SSimon GlassAs a result, the x86 kernel boot process is needlessly complex. The file
5290268b87SSimon Glassformat is also complex, and obfuscates the contents to a degree that it is
5390268b87SSimon Glassquite a challenge to extract anything from it. This bzImage format has become
5490268b87SSimon Glassso prevalent that is actually isn't possible to produce the 'raw' kernel build
5590268b87SSimon Glassoutputs with the standard Makefile (as it is on ARM for example, at least at
5690268b87SSimon Glassthe time of writing).
5790268b87SSimon Glass
5890268b87SSimon GlassThis document describes an alternative boot process which uses simple raw
5990268b87SSimon Glassimages which are loaded into the right place by the boot loader and then
6090268b87SSimon Glassexecuted.
6190268b87SSimon Glass
6290268b87SSimon Glass
6390268b87SSimon GlassBuild the kernel
6490268b87SSimon Glass----------------
6590268b87SSimon Glass
66dc396210SSimon GlassNote: these instructions assume a 32-bit kernel. U-Boot also supports directly
67dc396210SSimon Glassbooting a 64-bit kernel by jumping into 64-bit mode first (see below).
6890268b87SSimon Glass
6990268b87SSimon GlassYou can build the kernel as normal with 'make'. This will create a file called
7090268b87SSimon Glass'vmlinux'. This is a standard ELF file and you can look at it if you like:
7190268b87SSimon Glass
7290268b87SSimon Glass$ objdump -h vmlinux
7390268b87SSimon Glass
7490268b87SSimon Glassvmlinux:     file format elf32-i386
7590268b87SSimon Glass
7690268b87SSimon GlassSections:
7790268b87SSimon GlassIdx Name          Size      VMA       LMA       File off  Algn
7890268b87SSimon Glass  0 .text         00416850  81000000  01000000  00001000  2**5
7990268b87SSimon Glass                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
8090268b87SSimon Glass  1 .notes        00000024  81416850  01416850  00417850  2**2
8190268b87SSimon Glass                  CONTENTS, ALLOC, LOAD, READONLY, CODE
8290268b87SSimon Glass  2 __ex_table    00000c50  81416880  01416880  00417880  2**3
8390268b87SSimon Glass                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA
8490268b87SSimon Glass  3 .rodata       00154b9e  81418000  01418000  00419000  2**5
8590268b87SSimon Glass                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA
8690268b87SSimon Glass  4 __bug_table   0000597c  8156cba0  0156cba0  0056dba0  2**0
8790268b87SSimon Glass                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA
8890268b87SSimon Glass  5 .pci_fixup    00001b80  8157251c  0157251c  0057351c  2**2
8990268b87SSimon Glass                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA
9090268b87SSimon Glass  6 .tracedata    00000024  8157409c  0157409c  0057509c  2**0
9190268b87SSimon Glass                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA
9290268b87SSimon Glass  7 __ksymtab     00007ec0  815740c0  015740c0  005750c0  2**2
9390268b87SSimon Glass                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA
9490268b87SSimon Glass  8 __ksymtab_gpl 00004a28  8157bf80  0157bf80  0057cf80  2**2
9590268b87SSimon Glass                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA
9690268b87SSimon Glass  9 __ksymtab_strings 0001d6fc  815809a8  015809a8  005819a8  2**0
9790268b87SSimon Glass                  CONTENTS, ALLOC, LOAD, READONLY, DATA
9890268b87SSimon Glass 10 __init_rodata 00001c3c  8159e0a4  0159e0a4  0059f0a4  2**2
9990268b87SSimon Glass                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA
10090268b87SSimon Glass 11 __param       00000ff0  8159fce0  0159fce0  005a0ce0  2**2
10190268b87SSimon Glass                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA
10290268b87SSimon Glass 12 __modver      00000330  815a0cd0  015a0cd0  005a1cd0  2**2
10390268b87SSimon Glass                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA
10490268b87SSimon Glass 13 .data         00063000  815a1000  015a1000  005a2000  2**12
10590268b87SSimon Glass                  CONTENTS, ALLOC, LOAD, RELOC, DATA
10690268b87SSimon Glass 14 .init.text    0002f104  81604000  01604000  00605000  2**2
10790268b87SSimon Glass                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
10890268b87SSimon Glass 15 .init.data    00040cdc  81634000  01634000  00635000  2**12
10990268b87SSimon Glass                  CONTENTS, ALLOC, LOAD, RELOC, DATA
11090268b87SSimon Glass 16 .x86_cpu_dev.init 0000001c  81674cdc  01674cdc  00675cdc  2**2
11190268b87SSimon Glass                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA
11290268b87SSimon Glass 17 .altinstructions 0000267c  81674cf8  01674cf8  00675cf8  2**0
11390268b87SSimon Glass                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA
11490268b87SSimon Glass 18 .altinstr_replacement 00000942  81677374  01677374  00678374  2**0
11590268b87SSimon Glass                  CONTENTS, ALLOC, LOAD, READONLY, CODE
11690268b87SSimon Glass 19 .iommu_table  00000014  81677cb8  01677cb8  00678cb8  2**2
11790268b87SSimon Glass                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA
11890268b87SSimon Glass 20 .apicdrivers  00000004  81677cd0  01677cd0  00678cd0  2**2
11990268b87SSimon Glass                  CONTENTS, ALLOC, LOAD, RELOC, DATA
12090268b87SSimon Glass 21 .exit.text    00001a80  81677cd8  01677cd8  00678cd8  2**0
12190268b87SSimon Glass                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
12290268b87SSimon Glass 22 .data..percpu 00007880  8167a000  0167a000  0067b000  2**12
12390268b87SSimon Glass                  CONTENTS, ALLOC, LOAD, RELOC, DATA
12490268b87SSimon Glass 23 .smp_locks    00003000  81682000  01682000  00683000  2**2
12590268b87SSimon Glass                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA
12690268b87SSimon Glass 24 .bss          000a1000  81685000  01685000  00686000  2**12
12790268b87SSimon Glass                  ALLOC
12890268b87SSimon Glass 25 .brk          00424000  81726000  01726000  00686000  2**0
12990268b87SSimon Glass                  ALLOC
13090268b87SSimon Glass 26 .comment      00000049  00000000  00000000  00686000  2**0
13190268b87SSimon Glass                  CONTENTS, READONLY
13290268b87SSimon Glass 27 .GCC.command.line 0003e055  00000000  00000000  00686049  2**0
13390268b87SSimon Glass                  CONTENTS, READONLY
13490268b87SSimon Glass 28 .debug_aranges 0000f4c8  00000000  00000000  006c40a0  2**3
13590268b87SSimon Glass                  CONTENTS, RELOC, READONLY, DEBUGGING
13690268b87SSimon Glass 29 .debug_info   0440b0df  00000000  00000000  006d3568  2**0
13790268b87SSimon Glass                  CONTENTS, RELOC, READONLY, DEBUGGING
13890268b87SSimon Glass 30 .debug_abbrev 0022a83b  00000000  00000000  04ade647  2**0
13990268b87SSimon Glass                  CONTENTS, READONLY, DEBUGGING
14090268b87SSimon Glass 31 .debug_line   004ead0d  00000000  00000000  04d08e82  2**0
14190268b87SSimon Glass                  CONTENTS, RELOC, READONLY, DEBUGGING
14290268b87SSimon Glass 32 .debug_frame  0010a960  00000000  00000000  051f3b90  2**2
14390268b87SSimon Glass                  CONTENTS, RELOC, READONLY, DEBUGGING
14490268b87SSimon Glass 33 .debug_str    001b442d  00000000  00000000  052fe4f0  2**0
14590268b87SSimon Glass                  CONTENTS, READONLY, DEBUGGING
14690268b87SSimon Glass 34 .debug_loc    007c7fa9  00000000  00000000  054b291d  2**0
14790268b87SSimon Glass                  CONTENTS, RELOC, READONLY, DEBUGGING
14890268b87SSimon Glass 35 .debug_ranges 00098828  00000000  00000000  05c7a8c8  2**3
14990268b87SSimon Glass                  CONTENTS, RELOC, READONLY, DEBUGGING
15090268b87SSimon Glass
15190268b87SSimon GlassThere is also the setup binary mentioned earlier. This is at
15290268b87SSimon Glassarch/x86/boot/setup.bin and is about 12KB in size. It includes the command
15390268b87SSimon Glassline and various settings need by the kernel. Arguably the boot loader should
15490268b87SSimon Glassprovide all of this also, but setting it up is some complex that the kernel
15590268b87SSimon Glasshelps by providing a head start.
15690268b87SSimon Glass
15790268b87SSimon GlassAs you can see the code loads to address 0x01000000 and everything else
15890268b87SSimon Glassfollows after that. We could load this image using the 'bootelf' command but
15990268b87SSimon Glasswe would still need to provide the setup binary. This is not supported by
16090268b87SSimon GlassU-Boot although I suppose you could mostly script it. This would permit the
16190268b87SSimon Glassuse of a relocatable kernel.
16290268b87SSimon Glass
16390268b87SSimon GlassAll we need to boot is the vmlinux file and the setup.bin file.
16490268b87SSimon Glass
16590268b87SSimon Glass
16690268b87SSimon GlassCreate a FIT
16790268b87SSimon Glass------------
16890268b87SSimon Glass
16990268b87SSimon GlassTo create a FIT you will need a source file describing what should go in the
170dc396210SSimon GlassFIT. See kernel.its for an example for x86 and also instructions on setting
171dc396210SSimon Glassthe 'arch' value for booting 64-bit kernels if desired. Put this into a file
172dc396210SSimon Glasscalled image.its.
17390268b87SSimon Glass
17490268b87SSimon GlassNote that setup is loaded to the special address of 0x90000 (a special address
17590268b87SSimon Glassyou just have to know) and the kernel is loaded to 0x01000000 (the address you
17690268b87SSimon Glasssaw above). This means that you will need to load your FIT to a different
17790268b87SSimon Glassaddress so that U-Boot doesn't overwrite it when decompressing. Something like
17890268b87SSimon Glass0x02000000 will do so you can set CONFIG_SYS_LOAD_ADDR to that.
17990268b87SSimon Glass
18090268b87SSimon GlassIn that example the kernel is compressed with lzo. Also we need to provide a
18190268b87SSimon Glassflat binary, not an ELF. So the steps needed to set things are are:
18290268b87SSimon Glass
18390268b87SSimon Glass   # Create a flat binary
18490268b87SSimon Glass   objcopy -O binary vmlinux vmlinux.bin
18590268b87SSimon Glass
18690268b87SSimon Glass   # Compress it into LZO format
18790268b87SSimon Glass   lzop vmlinux.bin
18890268b87SSimon Glass
18990268b87SSimon Glass   # Build a FIT image
19090268b87SSimon Glass   mkimage -f image.its image.fit
19190268b87SSimon Glass
19290268b87SSimon Glass(be careful to run the mkimage from your U-Boot tools directory since it
19390268b87SSimon Glasswill have x86_setup support.)
19490268b87SSimon Glass
19590268b87SSimon GlassYou can take a look at the resulting fit file if you like:
19690268b87SSimon Glass
19790268b87SSimon Glass$ dumpimage -l image.fit
19890268b87SSimon GlassFIT description: Simple image with single Linux kernel on x86
19990268b87SSimon GlassCreated:         Tue Oct  7 10:57:24 2014
200*83840405SAndre Przywara Image 0 (kernel)
20190268b87SSimon Glass  Description:  Vanilla Linux kernel
20290268b87SSimon Glass  Created:      Tue Oct  7 10:57:24 2014
20390268b87SSimon Glass  Type:         Kernel Image
20490268b87SSimon Glass  Compression:  lzo compressed
20590268b87SSimon Glass  Data Size:    4591767 Bytes = 4484.15 kB = 4.38 MB
20690268b87SSimon Glass  Architecture: Intel x86
20790268b87SSimon Glass  OS:           Linux
20890268b87SSimon Glass  Load Address: 0x01000000
20990268b87SSimon Glass  Entry Point:  0x00000000
21090268b87SSimon Glass  Hash algo:    sha1
21190268b87SSimon Glass  Hash value:   446b5163ebfe0fb6ee20cbb7a8501b263cd92392
212*83840405SAndre Przywara Image 1 (setup)
21390268b87SSimon Glass  Description:  Linux setup.bin
21490268b87SSimon Glass  Created:      Tue Oct  7 10:57:24 2014
21590268b87SSimon Glass  Type:         x86 setup.bin
21690268b87SSimon Glass  Compression:  uncompressed
21790268b87SSimon Glass  Data Size:    12912 Bytes = 12.61 kB = 0.01 MB
21890268b87SSimon Glass  Hash algo:    sha1
21990268b87SSimon Glass  Hash value:   a1f2099cf47ff9816236cd534c77af86e713faad
220*83840405SAndre Przywara Default Configuration: 'config-1'
221*83840405SAndre Przywara Configuration 0 (config-1)
22290268b87SSimon Glass  Description:  Boot Linux kernel
223*83840405SAndre Przywara  Kernel:       kernel
22490268b87SSimon Glass
22590268b87SSimon Glass
22690268b87SSimon GlassBooting the FIT
22790268b87SSimon Glass---------------
22890268b87SSimon Glass
22990268b87SSimon GlassTo make it boot you need to load it and then use 'bootm' to boot it. A
23090268b87SSimon Glasssuitable script to do this from a network server is:
23190268b87SSimon Glass
23290268b87SSimon Glass   bootp
23390268b87SSimon Glass   tftp image.fit
23490268b87SSimon Glass   bootm
23590268b87SSimon Glass
23690268b87SSimon GlassThis will load the image from the network and boot it. The command line (from
23790268b87SSimon Glassthe 'bootargs' environment variable) will be passed to the kernel.
23890268b87SSimon Glass
23990268b87SSimon GlassIf you want a ramdisk you can add it as normal with FIT. If you want a device
24090268b87SSimon Glasstree then x86 doesn't normally use those - it has ACPI instead.
24190268b87SSimon Glass
24290268b87SSimon Glass
24390268b87SSimon GlassWhy Bother?
24490268b87SSimon Glass-----------
24590268b87SSimon Glass
24690268b87SSimon Glass1. It demystifies the process of booting an x86 kernel
24790268b87SSimon Glass2. It allows use of the standard U-Boot boot file format
24890268b87SSimon Glass3. It allows U-Boot to perform decompression - problems will provide an error
24990268b87SSimon Glassmessage and you are still in the boot loader. It is possible to investigate.
25090268b87SSimon Glass4. It avoids all the pre-loader code in the kernel which is quite complex to
25190268b87SSimon Glassfollow
25290268b87SSimon Glass5. You can use verified/secure boot and other features which haven't yet been
25390268b87SSimon Glassadded to the pre-Linux
25490268b87SSimon Glass6. It makes x86 more like other architectures in the way it boots a kernel.
25590268b87SSimon GlassYou can potentially use the same file format for the kernel, and the same
25690268b87SSimon Glassprocedure for building and packaging it.
25790268b87SSimon Glass
25890268b87SSimon Glass
25990268b87SSimon GlassReferences
26090268b87SSimon Glass----------
26190268b87SSimon Glass
26290268b87SSimon GlassIn the Linux kernel, Documentation/x86/boot.txt defines the boot protocol for
26390268b87SSimon Glassthe kernel including the setup.bin format. This is handled in U-Boot in
26490268b87SSimon Glassarch/x86/lib/zimage.c and arch/x86/lib/bootm.c.
26590268b87SSimon Glass
26690268b87SSimon GlassVarious files in the same directory as this file describe the FIT format.
26790268b87SSimon Glass
26890268b87SSimon Glass
26990268b87SSimon Glass--
27090268b87SSimon GlassSimon Glass
27190268b87SSimon Glasssjg@chromium.org
27290268b87SSimon Glass7-Oct-2014
273