RPi4B: an example of what RAM u-boot reserves during operation [patch included]

Mark Millard marklmi at yahoo.com
Tue Oct 13 00:32:31 UTC 2020



On 2020-Oct-12, at 11:19, Mark Millard <marklmi at yahoo.com> wrote:

> U-Boot> bdinfo
> boot_params = 0x0000000000000100
> . . .
> lmb_dump_all:
>    memory.cnt             = 0x2
>    memory.size            = 0x0
>    memory.reg[0x0].base   = 0x0
>                   .size   = 0x3e000000
>    memory.reg[0x1].base   = 0x40000000
>                   .size   = 0xbc000000
> 
>    reserved.cnt           = 0x2
>    reserved.size          = 0x0
>    reserved.reg[0x0].base = 0x0
>                     .size = 0x1000
>    reserved.reg[0x1].base = 0x3db47b30
>                     .size = 0x4b84d0
> . . .
> 
> That:
> 
>    reserved.reg[0x0].base = 0x0
>                     .size = 0x1000
> 
> means that armstub8-gic.bin is not fully
> protected at this point in u-boot's execution.
> 
> Basically boot_fdt_add_mem_rsv_regions is all that
> is used currently and it does not take into account
> CONFIG_RPI_EFI_NR_SPIN_PAGES=2 :
> 
> /**
> * boot_fdt_add_mem_rsv_regions - Mark the memreserve and reserved-memory
> * sections as unusable
> * @lmb: pointer to lmb handle, will be used for memory mgmt
> * @fdt_blob: pointer to fdt blob base address
> *
> * Adds the and reserved-memorymemreserve regions in the dtb to the lmb block.
> * Adding the memreserve regions prevents u-boot from using them to store the
> * initrd or the fdt blob.
> */
> void boot_fdt_add_mem_rsv_regions(struct lmb *lmb, void *fdt_blob)
> {
>        uint64_t addr, size;
>        int i, total, ret;
>        int nodeoffset, subnode;
>        struct fdt_resource res;
> 
>        if (fdt_check_header(fdt_blob) != 0)
>                return;
> 
>        /* process memreserve sections */
>        total = fdt_num_mem_rsv(fdt_blob);
>        for (i = 0; i < total; i++) {
>                if (fdt_get_mem_rsv(fdt_blob, i, &addr, &size) != 0)
>                        continue;
>                boot_fdt_reserve_region(lmb, addr, size);
>        }
> 
>        /* process reserved-memory */
>        nodeoffset = fdt_subnode_offset(fdt_blob, 0, "reserved-memory");
>        if (nodeoffset >= 0) {
>                subnode = fdt_first_subnode(fdt_blob, nodeoffset);
>                while (subnode >= 0) {
>                        /* check if this subnode has a reg property */
>                        ret = fdt_get_resource(fdt_blob, subnode, "reg", 0,
>                                               &res);
>                        if (!ret && fdtdec_get_is_enabled(fdt_blob, subnode)) {
>                                addr = res.start;
>                                size = res.end - res.start + 1;
>                                boot_fdt_reserve_region(lmb, addr, size);
>                        }
> 
>                        subnode = fdt_next_subnode(fdt_blob, subnode);
>                }
>        }
> }
> 
> 

The patch later below causes u-boot to protect
the first 2 pages during its operations, not
just the first page (just 1 indicated by the
firmware's supplied fdt):

U-Boot> bdinfo
lmb_dump_all:
. . .
    reserved.cnt           = 0x2
    reserved.size          = 0x0
    reserved.reg[0x0].base = 0x0
                     .size = 0x2000
    reserved.reg[0x1].base = 0x3db47b30
                     .size = 0x4b84d0
. . .

u-boot's code does not deal with merging overlaps,
just adjacent ranges. So the new code covers just
base 0x1000u size 0x1000u as reserved, leaving how
base 0x0u size 0x1000u was covered as it was.

The patch looks like (up to whitespace variance via
email handling):

# diff -u board/raspberrypi/rpi/rpi.c.orig board/raspberrypi/rpi/rpi.c
--- board/raspberrypi/rpi/rpi.c.orig    2020-10-05 08:15:32.000000000 -0700
+++ board/raspberrypi/rpi/rpi.c 2020-10-12 17:12:10.371941000 -0700
@@ -12,6 +12,7 @@
 #include <fdt_simplefb.h>
 #include <init.h>
 #include <lcd.h>
+#include <lmb.h>
 #include <memalign.h>
 #include <mmc.h>
 #include <asm/gpio.h>
@@ -494,4 +495,28 @@
 #endif
 
        return 0;
+}
+
+void board_lmb_reserve(struct lmb *lmb)
+{
+#ifdef CONFIG_EFI_LOADER
+       /*
+        * NOTE: lmb_reserve (and more) does not deal with overlaps with
+        *       pre-existing reservations.
+        *       But board_lmb_reserve is called before the original
+        *       first-page is added. So use knowledge of what will happen
+        *       later to avoid overlaps.
+        */
+
+       phys_addr_t base = 0x0u;
+       phys_addr_t size = CONFIG_RPI_EFI_NR_SPIN_PAGES << EFI_PAGE_SHIFT;
+
+       if (size <= EFI_PAGE_SIZE) return;
+
+       /* Avoid future overlap */
+       base += EFI_PAGE_SIZE;
+       size -= EFI_PAGE_SIZE;
+
+       lmb_reserve(lmb, base, size);
+#endif
 }

ft_board_setup already used CONFIG_RPI_EFI_NR_SPIN_PAGES based on
only checking CONFIG_EFI_LOADER, so I did the same above.

===
Mark Millard
marklmi at yahoo.com
( dsl-only.net went
away in early 2018-Mar)



More information about the freebsd-arm mailing list