mail archive of the barebox mailing list
 help / color / mirror / Atom feed
From: Ahmad Fatoum <a.fatoum@pengutronix.de>
To: barebox@lists.infradead.org
Cc: David Picard <david.picard@clermont.in2p3.fr>,
	Ahmad Fatoum <a.fatoum@pengutronix.de>
Subject: [PATCH 2/3] Documentation: devel: architecture: detail first/second stage handling
Date: Fri,  4 Jul 2025 16:38:02 +0200	[thread overview]
Message-ID: <20250704143803.2740813-3-a.fatoum@pengutronix.de> (raw)
In-Reply-To: <20250704143803.2740813-1-a.fatoum@pengutronix.de>

barebox is at mercy of the BootROM in relation to how its first/second
stages need to be structured. In the optimal case, the user need not
about it, but when issues arises, it becomes very important to know
_where_ the issue occurs.

Let's add some general background information about that.

Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
 Documentation/devel/architecture.rst | 136 +++++++++++++++++++++++++--
 1 file changed, 129 insertions(+), 7 deletions(-)

diff --git a/Documentation/devel/architecture.rst b/Documentation/devel/architecture.rst
index 83556095098a..b557ec830dc7 100644
--- a/Documentation/devel/architecture.rst
+++ b/Documentation/devel/architecture.rst
@@ -60,19 +60,141 @@ addressed, it will unpack barebox proper there and call it with the
 necessary arguments: an initial memory region and the FDT.
 
 If this is not feasible, the PBL will contain drivers to chain load
-barebox proper from the storage medium. As this is usually the same
-storage medium the PBL itself was loaded from, shortcuts can often
-be taken: e.g. a SD-Card could already be in the correct mode, so the
-PBL driver can just read the blocks without having to reinitialize
-the SD-card.
+barebox proper from the storage medium, usually the same
+storage medium the PBL itself was loaded from.
 
 barebox images
 ==============
 
 In a typical build, the barebox build process generates multiple images
-(:ref:`multi_image`).  All enabled PBLs are each linked with the same
-barebox proper binary and then the resulting images are processed to be
+(:ref:`multi_image`).  Normally, all enabled PBLs are each linked with the
+same barebox proper binary and then the resulting images are processed to be
 in the format expected by the loader.
 
 The loader is often a BootROM, but maybe another first stage bootloader
 or a hardware debugger.
+
+Ideally, a single image is all that's needed to boot into barebox.
+Depending on BootROM, this may not be possible, because the BootROM hardcodes
+assumptions about the image that it loads. This is often the case with
+BootROMs that boot from a file system (often FAT): They expect a ``BOOT.BIN``
+file, ``MLO`` or similarly named file that does not exceed a fixed file size,
+because that file needs to be loaded into the small on-chip SRAM available on
+the SoC. In such cases, most barebox functionality will be located in a separate
+image, e.g. ``barebox.bin``, which is loaded by ``BOOT.BIN``, once DRAM has
+been successfully set up.
+
+There are two ways we generate such small first stage bootloaders in barebox:
+
+Old way: ≥ 2 configs
+---------------------
+
+The old way is to have a dedicated barebox first stage config that builds a
+very small non-interactive barebox for use as first stage.
+Due to size constraints, the first stage config is usually board-specific, while
+the second-stage config can target multiple boards at once.
+
+In this setup, each of the first and second stage each consist of their own
+prebootloader and barebox proper.
+
+* first stage prebootloader: Does DRAM setup and extracts first stage
+  barebox proper into DRAM.
+
+* first stage barebox proper: runs in DRAM and chainloads the second stage binary.
+
+* first stage prebootloader: is already running in DRAM, so it doesn't need to do
+  any hardware setup and instead directly extract second stage barebox proper
+
+* second stage barebox proper: your usual barebox experience, which can have an
+  interactive shell and boot an operating system
+
+An Example for this is ``am335x_mlo_defconfig``.
+
+New way: single config
+----------------------
+
+The new way avoids having a dedicated barebox first stage config by doing both
+the low level first stage setup and the chainloading from the same barebox
+prebootloader. Despite the prebootloader lacking nearly all driver frameworks found
+in barebox proper this is often made possible by reusing the hardware set up
+by the BootROM:
+
+BootROMs usually don't deinitialize hardware before jumping to the first stage
+bootloader. That means that the barebox prebootloader could just keep reusing
+the pre-configured SD-Card and host controller for example and issue read block
+commands right away without having to reinitialize the SD-card.
+
+In this setup, only one prebootloader binary will be built. Depending on
+the bootflow defined by the BootROM, it may be executed more than once however:
+
+BootROM loads directly into DRAM
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Some BootROMs have built-in support for executing multiple programs and
+loading them to different locations. In that case, a full second stage
+barebox binary can be loaded as second stage with the first stage RAM
+setup handled outside barebox.
+
+An example for Mask ROM loading one image into SRAM and another afterwards
+into DRAM are the boards in ``rockchip_v8_defconfig``: A DRAM setup blob
+is loaded as first stage followed by barebox directly into DRAM as second
+stage.
+
+A slightly different example are what most boards in ``imx_v7_defconfig``
+are doing: The i.MX bootrom can execute the bytecode located in the DCD
+(Device Configuration Data) table that's part of the bootloader header.
+This byte code has simple memory read/write and control flow primitives
+that are sufficient to setup a DDR2/DDR3 DRAM, so that barebox can be
+loaded into it right away.
+
+The option of being loaded into SRAM first and chainloading from there
+is also available, but not used frequently for the 32-bit i.MX platforms.
+For the 64-bit platforms with (LP)DDR4, the RAM controller setup is
+too complex to express with DCD opcodes, leading to the approach described
+below.
+
+BootROM loads into SRAM from offset
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+For BootROMs, where the first stage bootloader is loaded from a raw offset
+on the boot medium, the barebox image is usually a single binary, which
+is processed as follows:
+
+* The BootROM reads the first X bytes containing the prebootloader (and
+  some truncated barebox proper content) into the on-chip SRAM and executes
+  it.
+
+* The prebootloader will set up DRAM and then chainload the whole of barebox
+  proper into it. The offset and size of barebox proper are compiled into
+  the PBL, so it knows where to look.
+
+* The prebootloader will then invoke itself again, but this time while running
+  from DRAM. The re-executed prebootloader detects that it's running in DRAM
+  or at a lower exception level and will then proceed to extract barebox
+  proper to the end of the initial memory region and execute it.
+
+And example for this is the ``imx_v8_defconfig``.
+
+.. note:: Some SoCs like the i.MX8M Nano and Plus provide a boot API in ROM
+  that can be used by the prebootloader to effortlessly chainload the second stage
+  cutting down complexity in the prebootloader greatly. Thanks BootROM authors!
+
+BootROM loads into SRAM from file
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+When the BootROM expects a file, it most often does a size check,
+necessitating a second binary for the whole of barebox proper.
+
+The boot flow then looks as follows:
+
+* The BootROM reads the first binary, which includes only the prebootloader
+  from the file system into on-chip SRAM and executes it
+
+* The prebootloader will set up DRAM and then load the second binary
+  into it. It has no knowledge of its offsets and sizes, but gets that
+  information out of the FAT filesystem.
+
+* The second stage binary contains both its own prebootloader and a barebox
+  binary. The second stage prebootloader does not need to do any special
+  hardware setup, so it will proceed to extract barebox proper to the end of
+  the initial memory region and execute it.
-- 
2.39.5




  parent reply	other threads:[~2025-07-04 14:48 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-07-04 14:38 [PATCH 0/3] Documentation: devel: add new troubleshooting Ahmad Fatoum
2025-07-04 14:38 ` [PATCH 1/3] Documentation: devel: porting: split out architecture intro Ahmad Fatoum
2025-07-04 14:38 ` Ahmad Fatoum [this message]
2025-07-04 14:38 ` [PATCH 3/3] Documentation: devel: troubleshooting: add new chapter Ahmad Fatoum

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20250704143803.2740813-3-a.fatoum@pengutronix.de \
    --to=a.fatoum@pengutronix.de \
    --cc=barebox@lists.infradead.org \
    --cc=david.picard@clermont.in2p3.fr \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox