Differences

This shows you the differences between two versions of the page.

Link to this comparison view

ass:laboratoare:02:tasks:01 [2023/07/18 12:33]
radu.mantu
ass:laboratoare:02:tasks:01 [2024/08/06 15:05] (current)
florin.stancu [01. Preparing the Linux μImage]
Line 1: Line 1:
-==== 01. Preparing the Flattened ​μImage ​Tree ====+==== 01. Preparing the Linux μImage ====
  
 There are three vital components that are required to successfully boot Linux on ARM: There are three vital components that are required to successfully boot Linux on ARM:
Line 12: Line 12:
 === Task A - Linux kernel === === Task A - Linux kernel ===
  
-Clone the kernel from the official ​github repo. Since you've built U-Boot previously, ​you should be somewhat familiar with the Kbuild systemGenerate the default ARM configuration file and compile ​the kernel.+Clone the kernel from the [[https://github.com/​torvalds/​linux/​|official GitHub ​repo]], using the ''​v6.6'' tag. 
 +We recommend ​you to use [[https://​stackoverflow.com/​questions/​1778088/​how-do-i-clone-a-single-branch-in-git|this git cloning technique]] to avoid fetching ​the entire git history (requiring several GBs of disk space).
  
-Note that the kernel image you will be including in the FIP is called **Image**. Unlike **vmlinux** which is an ELF file (i.e.: contains useless sections, including ​//.debuginfo// if you want to debug the kernel), **Image** is a boot executable image, made specifically ​for you to jump straight in and start executingAfter the build process finalizes**find** ​the **Image** file within ​the Linux repo.+Since you've built U-Boot previously, you should ​be somewhat familiar with the Kbuild systemStart by generating the build configuration from its [[https://github.com/​torvalds/linux/tree/​v6.6/​arch/​arm64/​configs|default configuration template]]. Optionally, run a ''​menuconfig'' ​to inspect ​the Linux kernel ​options available. 
 + 
 +<note warning>​ 
 +You must set the ''​ARCH''​ argument to the appropriate architecture ​**AT ALL TIMES** when invoking linux'​s ''​make''​! \\ 
 +Check out the subdirectories in ''​linux/​arch/'' ​for possible values\\ 
 +Also, do not forget about the ''​CROSS_COMPILE''​ environment variable (export it inside your Makefile & terminal). 
 +</​note>​ 
 + 
 +In order to build the kernel imagesimply ''​make''​ with the required variables (see the warning above!).
  
 <note tip> <note tip>
-Paralellize the build process using ''​make -j'',​ unless you want to waste an hour for Linux to build. \\ +Paralellize the build process using ''​make -j <​num_CPUs>​'',​ unless you want to waste an hour for Linux to build. \\
-Do not forget about the ''​CROSS_COMPILE''​ argument. \\ +
-Set the ''​ARCH''​ argument to the appropriate architecture. Check out the subdirectories in ''​linux/​arch/''​ for possible values.+
 </​note>​ </​note>​
 +
 +Note that the kernel image you will be including in the FIP is called **Image**. Unlike **vmlinux** which is an ELF file (i.e.: contains useless sections, including //​.debuginfo//​ if you want to debug the kernel), **Image** is a boot executable image, made specifically for you to jump straight in and start executing. After the build process finalizes, find the **Image** file within the ''<​linux-kernel-src>/​arch/​arm64/​boot/''​ output directory.
 +
 +While waiting for the build, explore the Linux source using your favorite code editor (especially [[https://​github.com/​torvalds/​linux/​tree/​v6.6/​arch/​arm64/​boot/​dts/​freescale|the device trees]])!
  
 <note tip> <note tip>
 +**Useful tip for kernel development** (if you wish to browse / modify the kernel code): \\
 After you finish an initial build of the kernel, consider running the following script: After you finish an initial build of the kernel, consider running the following script:
  
Line 29: Line 41:
 </​code>​ </​code>​
  
-This will generate a ''​compile_commands.json''​ file that contains the **gcc** invocation cmdline. Any half decent ​language server ​will be able to (automatically) parse this file and deduce the include paths and definitions used. This will enable features like [[https://​neovim.io/​doc/​user/​lsp.html#​vim.lsp.buf.definition()|go-to-definition]] between different source files and much more.+This will generate a ''​compile_commands.json''​ file that contains the **gcc** invocation cmdline. Any half decent ​LSP-based IDE (VSCode, [[http://​lunarvim.org/​|LunarVim]]) ​will be able to (automatically) parse this file and deduce the include paths and definitions used. This will enable features like [[https://​neovim.io/​doc/​user/​lsp.html#​vim.lsp.buf.definition()|go-to-definition]] between different source files and much more.
  
 Note that this script only works on the current project. For a more generic tool, try [[https://​github.com/​rizsotto/​Bear|bear]]. Be warned though that its LD_PRELOAD hooking of ''​exec()''​ calls (needed to extract the cmdargs) interferes with the [[https://​www.gnu.org/​software/​automake/​|Automake]] configuration stage. Note that this script only works on the current project. For a more generic tool, try [[https://​github.com/​rizsotto/​Bear|bear]]. Be warned though that its LD_PRELOAD hooking of ''​exec()''​ calls (needed to extract the cmdargs) interferes with the [[https://​www.gnu.org/​software/​automake/​|Automake]] configuration stage.
Line 36: Line 48:
 === Task B - Flattened Device Tree === === Task B - Flattened Device Tree ===
  
-Luckily, the FDT for our platform is also included in Linux. It's name should be **imx8mq-pico-pi.dtb**.+Luckily, the FDT for our platform is also included in Linux. It's name should be ''​imx8mq-pico-pi.dtb''​ (generated from its source counterpart,​ [[https://​github.com/​torvalds/​linux/​blob/​v6.6/​arch/​arm64/​boot/​dts/​freescale/​imx8mq-pico-pi.dts|imx8mq-pico-pi.dts]]).
  
 If for some reason it wasn't built alongside the kernel Image, check out the ''​dtbs''​ make target. If for some reason it wasn't built alongside the kernel Image, check out the ''​dtbs''​ make target.
Line 48: Line 60:
 Buildroot on the other hand is geared towards simplicity and ease of use. Being based on Kbuild and Makefile (same as Linux and U-Boot) makes it instantly familiar to most developers. And even if you are new to this, while Yocto requires you to read entire [[https://​www.goodreads.com/​search?​q=yocto|books]] in order to utilize it properly, Buildroot can be summed up in a 1k LoC Makefile. Buildroot on the other hand is geared towards simplicity and ease of use. Being based on Kbuild and Makefile (same as Linux and U-Boot) makes it instantly familiar to most developers. And even if you are new to this, while Yocto requires you to read entire [[https://​www.goodreads.com/​search?​q=yocto|books]] in order to utilize it properly, Buildroot can be summed up in a 1k LoC Makefile.
  
-== Step 1: Download Buildroot ==+== Download Buildroot ==
  
 Clone the official [[https://​github.com/​buildroot/​buildroot.git|Buildroot repo]]. Clone the official [[https://​github.com/​buildroot/​buildroot.git|Buildroot repo]].
  
-== Step 2: Create the configuration ==+== Create the configuration ==
  
 Find an existing defconfig for our platform (the **imx8mq**) and take a look at what it contains. Notice how the following config options are enabled: Find an existing defconfig for our platform (the **imx8mq**) and take a look at what it contains. Notice how the following config options are enabled:
Line 63: Line 75:
  
 Yes, Buildroot also integrates the bootloaders into its build system. However, keeping the components separate makes it easier to appply patches and debug problems. What we want from Buildroot is a minimal root filesystem and nothing more. So, after generating ''​.config'',​ enter ''​menuconfig''​ and make a few changes: Yes, Buildroot also integrates the bootloaders into its build system. However, keeping the components separate makes it easier to appply patches and debug problems. What we want from Buildroot is a minimal root filesystem and nothing more. So, after generating ''​.config'',​ enter ''​menuconfig''​ and make a few changes:
 +
   * Disable all components that we've already integrated in our build environment (starting with the ones above).   * Disable all components that we've already integrated in our build environment (starting with the ones above).
-  * Use an **external, custom, pre-installed toolchain**.+  * Use an **external, custom, pre-installed toolchain** ​(remember ''​CROSS_COMPILE''?​ check the menu for it!).
   * Use **systemd** as the init system instead of **BusyBox**.   * Use **systemd** as the init system instead of **BusyBox**.
-  ​Use **bash** as the default shell instead of **sh**. +    ​Make sure **systemd-logind** is included in the build, or you may have [[https://​lore.kernel.org/​all/​b49c7676-1864-d838-fcf7-7a1208d6ba78@benettiengineering.com/​T/​|this problem]]. 
-  * Set //"root"// as password for the root user. +  * Choose ​**bash** as the default shell instead of **sh**. 
-  * Include a text editor ​package ​(e.g.: **vim** or **nano**).+  * Enable password login for the //root// user, then set a password
 +  * Include a text editor ​PACKAGE ​(e.g.: **vim** or **nano**)
 +  * Include the **coreutils** PACKAGE.
   * Generate an **uncompressed CPIO** image from the output file system (see the Note below).   * Generate an **uncompressed CPIO** image from the output file system (see the Note below).
 +
 +<​note>​
 +Note how the the configuration variables are prefixed with ''​BR2_'',​ packages with ''​BR2_PACKAGE_''​ and so on!
 +</​note>​
  
 <​note>​ <​note>​
Line 149: Line 168:
 </​solution>​ </​solution>​
  
-== Step 3: Build it! ==+== Build & inspect the rootfs ​==
  
 Not much to it, really. Once everything'​s done, check out the ''​output/''​ directory. What does it contain? Where is your CPIO archive? Not much to it, really. Once everything'​s done, check out the ''​output/''​ directory. What does it contain? Where is your CPIO archive?
Line 161: Line 180:
 Create a staging directory and copy everything that we've obtained from the previous three tasks. Then, create an Image Tree Source (ITS) file. We'll be referring to it as ''​linux.its''​ but the name doesn'​t really matter. What matters is the content: Create a staging directory and copy everything that we've obtained from the previous three tasks. Then, create an Image Tree Source (ITS) file. We'll be referring to it as ''​linux.its''​ but the name doesn'​t really matter. What matters is the content:
  
-<spoiler linux.its>​ <​code>​+<spoiler linux.its>​ 
 +<​code>​
 /dts-v1/; /dts-v1/;
  
Line 206: Line 226:
             fdt = "​fdt";​             fdt = "​fdt";​
             ramdisk = "​initrd";​             ramdisk = "​initrd";​
-            loadables = "​fdt",​ "​ramdisk";​ 
         };         };
     };     };
 }; };
-</​code>​ </​spoiler>​+</​code>​ 
 +</​spoiler>​ 
 +\\
  
 Let's unpack this: Let's unpack this:
- * The file starts with ''/​dts-v1/;'',​ identifying it as a Device Tree Source. +  ​* The file starts with ''/​dts-v1/;'',​ identifying it as a Device Tree Source. 
- * Next, we have a root ''/''​ node with two child nodes: ''​images''​ and ''​configurations''​. +  * Next, we have a root ''/''​ node with two child nodes: ''​images''​ and ''​configurations''​. 
-   ​* ''​images''​ contains the description of each binary that will need to be loaded by U-Boot when processing the FIT. +    * ''​images''​ contains the description of each binary that will need to be loaded by U-Boot when processing the FIT. 
-     ​* Each image entry contains an [[https://​git.kernel.org/​pub/​scm/​utils/​dtc/​dtc.git/​commit/?​id=e37ec7d5889fa04047daaa7a4ff55150ed7954d4|incbin]] directive that tells **mkimage** to copy paste the contents of the specified file into the output DTB. +      * Each image entry contains an [[https://​git.kernel.org/​pub/​scm/​utils/​dtc/​dtc.git/​commit/?​id=e37ec7d5889fa04047daaa7a4ff55150ed7954d4|incbin]] directive that tells **mkimage** to copy paste the contents of the specified file into the output DTB. 
-     ​* Each image also contains a ''​load''​ property, specifying the address where the ''​data''​ will be placed. +      * Each image also contains a ''​load''​ property, specifying the address where the ''​data''​ will be placed. 
-     ​* In addition to ''​load'',​ the kernel image also has an ''​entry''​ property specifying where U-Boot will jump when relinquishing control to the Linux kernel. +      * In addition to ''​load'',​ the kernel image also has an ''​entry''​ property specifying where U-Boot will jump when relinquishing control to the Linux kernel. 
-   ​* ''​configurations''​ contains sets of image configurations that can be chained. +    * ''​configurations''​ contains sets of image configurations that can be chained. 
-     ​* The only configuration we have is also the ''​default'':​ ''​normal-boot''​. +      * The only configuration we have is also the ''​default'':​ ''​normal-boot''​. 
-     ​* Notice how it has pre-defined attributes for ''​kernel'',​ ''​fdt'',​ ''​ramdisk''​. These are not simple binary blobs; instead, they each have a role to play in the boot sequence. E.g., U-Boot will know to take the ''​load''​ address of the ''​fdt''​ image and pass it via a certain register (decided by convention) to the ''​kernel'',​ informing it where in memory to look for the FDT.+      * Notice how it has pre-defined attributes for ''​kernel'',​ ''​fdt'',​ ''​ramdisk''​. These are not simple binary blobs; instead, they each have a role to play in the boot sequence. E.g., U-Boot will know to take the ''​load''​ address of the ''​fdt''​ image and pass it via a certain register (decided by convention) to the ''​kernel'',​ informing it where in memory to look for the FDT.
  
 Note how we replaced the ''​load''​ and ''​entry''​ addresses with placeholders such as //XXX//. Replace these with whatever addresses you want such as the binaries do not overlap once U-Boot starts loading them. Note how we replaced the ''​load''​ and ''​entry''​ addresses with placeholders such as //XXX//. Replace these with whatever addresses you want such as the binaries do not overlap once U-Boot starts loading them.
Line 241: Line 262:
 $ mkimage -f linux.its linux.itb $ mkimage -f linux.its linux.itb
 </​code>​ </​code>​
 +
ass/laboratoare/02/tasks/01.1689672820.txt.gz · Last modified: 2023/07/18 12:33 by radu.mantu
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0