Differences

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

Link to this comparison view

ass:laboratoare:01:tasks:02 [2023/07/12 01:18]
radu.mantu
— (current)
Line 1: Line 1:
-==== 01. [??p] Creating the Firmware Image Package ==== 
  
-This package will contain **bl2**, **bl31** and **bl33**. The Secure OS (**bl32**) is outside the scope of this lab; even if we did bother to include it, it would just //be there//, doing nothing. 
- 
-Following this exercise, we should be able to reach the first step of the booting sequence that //can// be interactive;​ meaning that we'll be able to interact with a shell implemented in **bl33**. 
- 
-=== [??p] Task A - Trusted Firmware-A (bl31) === 
- 
-For this component we'll be using the [[https://​github.com/​nxp-imx/​imx-atf|Trusted Firmware-A]] project. Although it contains reference implementations for the other bootloaders as well, we are going to use it strictly for **bl31**. The other have more complete and widely recognized alternatives available. 
- 
-We recommend reading [[https://​trustedfirmware-a.readthedocs.io/​en/​latest/​getting_started/​initial-build.html|the documentation]] moving forward. Take a close look at [[https://​trustedfirmware-a.readthedocs.io/​en/​latest/​getting_started/​build-options.html|the build options]] in particular. 
- 
-Following a successful build process, you should obtain a **bl31.bin**. 
- 
-<note warning> 
-Normally, we'd be using the [[https://​www.trustedfirmware.org/​projects/​tf-a/​|official TF-A]] but at the moment it seems to have a linker script bug for our platform. Reason why we use the NXP fork of TF-A instead. ​ 
-</​note>​ 
- 
-<note tip> 
-The default target platform is ARM's Fixed Virtual Platform (FVP), a simulator. That is not our platform... \\ 
-To specify that we don't have a **bl32** for it to initialize, pass it ''​SPD=none''​. \\ 
-You don't have to build everything. Just ''​make ... bl31''​. 
-</​note>​ 
- 
-=== [??p] Task B - The firmware === 
- 
-With **bl31** out of the way, we are going to tackle **bl2** next. Remember however, that the main role of **bl2** is to initialize the hardware using the proprietary firmware offered by the chip manufacturer. Without this firmware, we don't even have access to the DRAM memory. 
- 
-Remember that **bl1** is loaded from ROM in the first half of the available SRAM (aka. On-Chip RAM). That SRAM is just 128KB in size, so there'​s not much space. **bl1** then loads **bl2** (but not the remainder of the FIP) in the upper half of SRAM. At this point it's up to **bl2** to enable the 2GB of DRAM and finish loading the rest of the FIP in main memory. 
- 
-For this task, get the latest version of the firmware from [[http://​sources.buildroot.net/​firmware-imx/​|here]]. 
-What we're actually interested in are the following files: 
-  * lpddr4_pmu_train_1d_dmem.bin 
-  * lpddr4_pmu_train_1d_imem.bin 
-  * lpddr4_pmu_train_2d_dmem.bin 
-  * lpddr4_pmu_train_2d_imem.bin 
-  * signed_hdmi_imx8m.bin 
- 
-=== [??p] Task C - U-Boot (bl2, bl33) === 
- 
-For the last two components of our Firmware Package we'll be using [[https://​github.com/​TechNexion/​u-boot-tn-imx|U-Boot]]. Each of them has a very specific purpose. 
- 
-At first, **bl1** will //start// downloading the FIP using the Serial Download Protocol, running on top of a USB connection. Once it finishes loading **bl2** (and the firmware from Task B), it cedes control to it instead. **bl2** will initialize the DRAM using said firmware and then continue where **bl1** left off, finishing the download of the FIP. 
- 
-<note warning> 
-The more astute will notice that once again we're not using the [[https://​github.com/​u-boot/​u-boot|official U-Boot]] project, but instead the TechNexion (i.e. the dev board manuafcturer) fork. As we've mentioned before, **bl2** will have to take over the serial download over USB from **bl1**. However, it can not reuse the drivers that **bl1** was using (it's very common for **bl2** to even override the memory **bl1** was using). So why is this a problem? 
- 
-Since the board we are working on released, U-Boot has seen some improvements with respect to certain drivers that we can't do without. These improvements increased the size of **bl2** to the point that it no longer fits in the board'​s SRAM (remember that **bl2** must fit in 64-128KB of memory). Even with Link Time Optimizations which usually help in this regard, and with attempts at removing useless drivers, it's still <​del>​a pain in the ass</​del>​ challenging to make everything fit. The TechNexion fork has the advantage of being slightly outdated and should give a guarantee that someone tested that the build actually works. 
-</​note>​ 
- 
-When **bl31** runs its course, **bl33** will be called upon. During this phase we'll finally have an interactive shell and multiple drivers to help interact with the board. With this, we can investigate the board'​s hardware, read and potentially override the partitions in the persistent storage and most importantly,​ boot Linux from any number of sources. 
- 
-== Step 1: Generate a default configuration == 
- 
-U-Boot is based on the same build system as the Linux kernel, namely [[https://​www.kernel.org/​doc/​html/​latest/​kbuild/​index.html|Kbuild]]. To get an idea of what functionality it provides, try to run: 
- 
-<code bash> 
-$ make help 
-</​code>​ 
- 
-If you check the ''​configs/''​ directory, you will find a number of board-specific configuration files. These serve as templates, containing the minimal necessary configuration. By running ''​make some_defconfig''​ the Kbuild system will determine what other unspecified options need to be enabled in order for these features to be functional. The result will be saved in a file called ''​.config''​. 
- 
-Generate a ''​.config''​ for your board. Also, don't forget the ''​CROSS_COMPILE''​ variable from **bl31**. It's very common across such projects and Kbuild will actually complain if it believes that you're trying to use a x86 compiler. 
- 
-== Step 2: Modify the configuration == 
- 
-The default configuration that you chose (correctly, hopefully) contains a few erroneous values for the USB driver. Normally these would take some time to dig up from the board'​s / processor'​s documentation;​ we took them from the debug prints of the firmware that was pre-configured on the eMMC :p 
- 
-Open a ncurses-based interface for editing the ''​.config''​ file: 
-<code bash> 
-$ make CROSS_COMPILE=... menuconfig 
-</​code>​ 
- 
-The interface should be fairly intuitive. Use the Arrow keys to navigate the entries, Space to toggle options on or off, Enter to dive into a submenu or open a prompt, and the ''?''​ key to get more information about the currently selected entry. If you see a letter highlighted in a different color, pressing the corresponding key will take you to that option. Note that multiple options can have the same keybind; pressing it will cycle you through to the next occurrence. 
- 
-The search function for a specific option (by name) is the exact same as in **less** or **vim**: ''/​[CONFIG_]MY_OPTION <​Enter>''​. This will generate a list of potential matches, each bearing a numeric index. Press the key corresponding to that index in order to jump to the search result. 
- 
-For now, change the following config variables and save the changes to ''​.config'':​ 
-  * **USB_GADGET_MANUFACTURER:​** ASS 
-  * **USB_GADGET_VENDOR_NUM:​** 0x1fc9 
-  * **USB_GADGET_PRODUCT_NUM:​** 0x012b 
- 
-== Step 3: Build it! == 
- 
-The three files you should obtain are: 
-  * **spl/​u-boot-spl.bin:​** aka. **bl2**. 
-  * **u-boot-nodtb.bin:​** aka. **bl33**. 
-  * **arch/​arm/​dts/​imx8mq-pico-pi.dtb:​** a Device Tree Blob (DTB); see details below. 
- 
-You may be wondering what is up with the DTB file. This file contains a description of the hardware available on the board, as well as hints for determining what driver should be responsible for each component. **bl33** needs at least a minimal description of the available hardware in order to function. Don't expect that U-Boot'​s Device Tree Sources (DTS) will contain information about the HDMI interfaces, for example. Since Linux also needs such a file, we will discuss its format and contents more in depth during the next session. If you are curious to take a look, here is how you can convert the DTB (binary format) to DTS (human-readable format): 
- 
-<code bash> 
-$ dtc -I dtb -O dts ${YOUR_DTB_FILE} | less 
-</​code>​ 
- 
-=== [??p] Task D - Generate the FIP === 
ass/laboratoare/01/tasks/02.1689113927.txt.gz ยท Last modified: 2023/07/12 01:18 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