uboot/doc/uImage.FIT/x86-fit-boot.txt
<<
>>
Prefs
   1Booting Linux on x86 with FIT
   2=============================
   3
   4Background
   5----------
   6
   7(corrections to the text below are welcome)
   8
   9Generally Linux x86 uses its own very complex booting method. There is a setup
  10binary which contains all sorts of parameters and a compressed self-extracting
  11binary for the kernel itself, often with a small built-in serial driver to
  12display decompression progress.
  13
  14The x86 CPU has various processor modes. I am no expert on these, but my
  15understanding is that an x86 CPU (even a really new one) starts up in a 16-bit
  16'real' mode where only 1MB of memory is visible, moves to 32-bit 'protected'
  17mode where 4GB is visible (or more with special memory access techniques) and
  18then to 64-bit 'long' mode if 64-bit execution is required.
  19
  20Partly the self-extracting nature of Linux was introduced to cope with boot
  21loaders that were barely capable of loading anything. Even changing to 32-bit
  22mode was something of a challenge, so putting this logic in the kernel seemed
  23to make sense.
  24
  25Bit by bit more and more logic has been added to this post-boot pre-Linux
  26wrapper:
  27
  28- Changing to 32-bit mode
  29- Decompression
  30- Serial output (with drivers for various chips)
  31- Load address randomisation
  32- Elf loader complete with relocation (for the above)
  33- Random number generator via 3 methods (again for the above)
  34- Some sort of EFI mini-loader (1000+ glorious lines of code)
  35- Locating and tacking on a device tree and ramdisk
  36
  37To my mind, if you sit back and look at things from first principles, this
  38doesn't make a huge amount of sense. Any boot loader worth its salts already
  39has most of the above features and more besides. The boot loader already knows
  40the layout of memory, has a serial driver, can decompress things, includes an
  41ELF loader and supports device tree and ramdisks. The decision to duplicate
  42all these features in a Linux wrapper caters for the lowest common
  43denominator: a boot loader which consists of a BIOS call to load something off
  44disk, followed by a jmp instruction.
  45
  46(Aside: On ARM systems, we worry that the boot loader won't know where to load
  47the kernel. It might be easier to just provide that information in the image,
  48or in the boot loader rather than adding a self-relocator to put it in the
  49right place. Or just use ELF?
  50
  51As a result, the x86 kernel boot process is needlessly complex. The file
  52format is also complex, and obfuscates the contents to a degree that it is
  53quite a challenge to extract anything from it. This bzImage format has become
  54so prevalent that is actually isn't possible to produce the 'raw' kernel build
  55outputs with the standard Makefile (as it is on ARM for example, at least at
  56the time of writing).
  57
  58This document describes an alternative boot process which uses simple raw
  59images which are loaded into the right place by the boot loader and then
  60executed.
  61
  62
  63Build the kernel
  64----------------
  65
  66Note: these instructions assume a 32-bit kernel. U-Boot also supports directly
  67booting a 64-bit kernel by jumping into 64-bit mode first (see below).
  68
  69You can build the kernel as normal with 'make'. This will create a file called
  70'vmlinux'. This is a standard ELF file and you can look at it if you like:
  71
  72$ objdump -h vmlinux
  73
  74vmlinux:     file format elf32-i386
  75
  76Sections:
  77Idx Name          Size      VMA       LMA       File off  Algn
  78  0 .text         00416850  81000000  01000000  00001000  2**5
  79                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
  80  1 .notes        00000024  81416850  01416850  00417850  2**2
  81                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  82  2 __ex_table    00000c50  81416880  01416880  00417880  2**3
  83                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA
  84  3 .rodata       00154b9e  81418000  01418000  00419000  2**5
  85                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA
  86  4 __bug_table   0000597c  8156cba0  0156cba0  0056dba0  2**0
  87                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA
  88  5 .pci_fixup    00001b80  8157251c  0157251c  0057351c  2**2
  89                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA
  90  6 .tracedata    00000024  8157409c  0157409c  0057509c  2**0
  91                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA
  92  7 __ksymtab     00007ec0  815740c0  015740c0  005750c0  2**2
  93                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA
  94  8 __ksymtab_gpl 00004a28  8157bf80  0157bf80  0057cf80  2**2
  95                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA
  96  9 __ksymtab_strings 0001d6fc  815809a8  015809a8  005819a8  2**0
  97                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  98 10 __init_rodata 00001c3c  8159e0a4  0159e0a4  0059f0a4  2**2
  99                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA
 100 11 __param       00000ff0  8159fce0  0159fce0  005a0ce0  2**2
 101                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA
 102 12 __modver      00000330  815a0cd0  015a0cd0  005a1cd0  2**2
 103                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA
 104 13 .data         00063000  815a1000  015a1000  005a2000  2**12
 105                  CONTENTS, ALLOC, LOAD, RELOC, DATA
 106 14 .init.text    0002f104  81604000  01604000  00605000  2**2
 107                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
 108 15 .init.data    00040cdc  81634000  01634000  00635000  2**12
 109                  CONTENTS, ALLOC, LOAD, RELOC, DATA
 110 16 .x86_cpu_dev.init 0000001c  81674cdc  01674cdc  00675cdc  2**2
 111                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA
 112 17 .altinstructions 0000267c  81674cf8  01674cf8  00675cf8  2**0
 113                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA
 114 18 .altinstr_replacement 00000942  81677374  01677374  00678374  2**0
 115                  CONTENTS, ALLOC, LOAD, READONLY, CODE
 116 19 .iommu_table  00000014  81677cb8  01677cb8  00678cb8  2**2
 117                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA
 118 20 .apicdrivers  00000004  81677cd0  01677cd0  00678cd0  2**2
 119                  CONTENTS, ALLOC, LOAD, RELOC, DATA
 120 21 .exit.text    00001a80  81677cd8  01677cd8  00678cd8  2**0
 121                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
 122 22 .data..percpu 00007880  8167a000  0167a000  0067b000  2**12
 123                  CONTENTS, ALLOC, LOAD, RELOC, DATA
 124 23 .smp_locks    00003000  81682000  01682000  00683000  2**2
 125                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA
 126 24 .bss          000a1000  81685000  01685000  00686000  2**12
 127                  ALLOC
 128 25 .brk          00424000  81726000  01726000  00686000  2**0
 129                  ALLOC
 130 26 .comment      00000049  00000000  00000000  00686000  2**0
 131                  CONTENTS, READONLY
 132 27 .GCC.command.line 0003e055  00000000  00000000  00686049  2**0
 133                  CONTENTS, READONLY
 134 28 .debug_aranges 0000f4c8  00000000  00000000  006c40a0  2**3
 135                  CONTENTS, RELOC, READONLY, DEBUGGING
 136 29 .debug_info   0440b0df  00000000  00000000  006d3568  2**0
 137                  CONTENTS, RELOC, READONLY, DEBUGGING
 138 30 .debug_abbrev 0022a83b  00000000  00000000  04ade647  2**0
 139                  CONTENTS, READONLY, DEBUGGING
 140 31 .debug_line   004ead0d  00000000  00000000  04d08e82  2**0
 141                  CONTENTS, RELOC, READONLY, DEBUGGING
 142 32 .debug_frame  0010a960  00000000  00000000  051f3b90  2**2
 143                  CONTENTS, RELOC, READONLY, DEBUGGING
 144 33 .debug_str    001b442d  00000000  00000000  052fe4f0  2**0
 145                  CONTENTS, READONLY, DEBUGGING
 146 34 .debug_loc    007c7fa9  00000000  00000000  054b291d  2**0
 147                  CONTENTS, RELOC, READONLY, DEBUGGING
 148 35 .debug_ranges 00098828  00000000  00000000  05c7a8c8  2**3
 149                  CONTENTS, RELOC, READONLY, DEBUGGING
 150
 151There is also the setup binary mentioned earlier. This is at
 152arch/x86/boot/setup.bin and is about 12KB in size. It includes the command
 153line and various settings need by the kernel. Arguably the boot loader should
 154provide all of this also, but setting it up is some complex that the kernel
 155helps by providing a head start.
 156
 157As you can see the code loads to address 0x01000000 and everything else
 158follows after that. We could load this image using the 'bootelf' command but
 159we would still need to provide the setup binary. This is not supported by
 160U-Boot although I suppose you could mostly script it. This would permit the
 161use of a relocatable kernel.
 162
 163All we need to boot is the vmlinux file and the setup.bin file.
 164
 165
 166Create a FIT
 167------------
 168
 169To create a FIT you will need a source file describing what should go in the
 170FIT. See kernel.its for an example for x86 and also instructions on setting
 171the 'arch' value for booting 64-bit kernels if desired. Put this into a file
 172called image.its.
 173
 174Note that setup is loaded to the special address of 0x90000 (a special address
 175you just have to know) and the kernel is loaded to 0x01000000 (the address you
 176saw above). This means that you will need to load your FIT to a different
 177address so that U-Boot doesn't overwrite it when decompressing. Something like
 1780x02000000 will do so you can set CONFIG_SYS_LOAD_ADDR to that.
 179
 180In that example the kernel is compressed with lzo. Also we need to provide a
 181flat binary, not an ELF. So the steps needed to set things are are:
 182
 183   # Create a flat binary
 184   objcopy -O binary vmlinux vmlinux.bin
 185
 186   # Compress it into LZO format
 187   lzop vmlinux.bin
 188
 189   # Build a FIT image
 190   mkimage -f image.its image.fit
 191
 192(be careful to run the mkimage from your U-Boot tools directory since it
 193will have x86_setup support.)
 194
 195You can take a look at the resulting fit file if you like:
 196
 197$ dumpimage -l image.fit
 198FIT description: Simple image with single Linux kernel on x86
 199Created:         Tue Oct  7 10:57:24 2014
 200 Image 0 (kernel)
 201  Description:  Vanilla Linux kernel
 202  Created:      Tue Oct  7 10:57:24 2014
 203  Type:         Kernel Image
 204  Compression:  lzo compressed
 205  Data Size:    4591767 Bytes = 4484.15 kB = 4.38 MB
 206  Architecture: Intel x86
 207  OS:           Linux
 208  Load Address: 0x01000000
 209  Entry Point:  0x00000000
 210  Hash algo:    sha1
 211  Hash value:   446b5163ebfe0fb6ee20cbb7a8501b263cd92392
 212 Image 1 (setup)
 213  Description:  Linux setup.bin
 214  Created:      Tue Oct  7 10:57:24 2014
 215  Type:         x86 setup.bin
 216  Compression:  uncompressed
 217  Data Size:    12912 Bytes = 12.61 kB = 0.01 MB
 218  Hash algo:    sha1
 219  Hash value:   a1f2099cf47ff9816236cd534c77af86e713faad
 220 Default Configuration: 'config-1'
 221 Configuration 0 (config-1)
 222  Description:  Boot Linux kernel
 223  Kernel:       kernel
 224
 225
 226Booting the FIT
 227---------------
 228
 229To make it boot you need to load it and then use 'bootm' to boot it. A
 230suitable script to do this from a network server is:
 231
 232   bootp
 233   tftp image.fit
 234   bootm
 235
 236This will load the image from the network and boot it. The command line (from
 237the 'bootargs' environment variable) will be passed to the kernel.
 238
 239If you want a ramdisk you can add it as normal with FIT. If you want a device
 240tree then x86 doesn't normally use those - it has ACPI instead.
 241
 242
 243Why Bother?
 244-----------
 245
 2461. It demystifies the process of booting an x86 kernel
 2472. It allows use of the standard U-Boot boot file format
 2483. It allows U-Boot to perform decompression - problems will provide an error
 249message and you are still in the boot loader. It is possible to investigate.
 2504. It avoids all the pre-loader code in the kernel which is quite complex to
 251follow
 2525. You can use verified/secure boot and other features which haven't yet been
 253added to the pre-Linux
 2546. It makes x86 more like other architectures in the way it boots a kernel.
 255You can potentially use the same file format for the kernel, and the same
 256procedure for building and packaging it.
 257
 258
 259References
 260----------
 261
 262In the Linux kernel, Documentation/x86/boot.txt defines the boot protocol for
 263the kernel including the setup.bin format. This is handled in U-Boot in
 264arch/x86/lib/zimage.c and arch/x86/lib/bootm.c.
 265
 266Various files in the same directory as this file describe the FIT format.
 267
 268
 269--
 270Simon Glass
 271sjg@chromium.org
 2727-Oct-2014
 273