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