Hi, On Fri Jan 3, 2025 at 9:58 PM UTC, Jonas Karlman via groups.io wrote: > GXBB BL1 only tries to read boot image from sector 0 on eMMC and sector > 1 on SD-card. GXL and newer read boot image from sector 1 on both eMMC > and SD-card. > > Vendor BL2 have solved the issue with different offsets by considering > where BL2 was loaded from to adjust the offset where BL3 is read from. > > This provide a different solution to create a boot image that can be > booted from both eMMC and SD-card and where the offset for reading next > stage loader can be shared for both boot options. > > Inject code, that relocate the payload located at 0x1200 offset in TZRAM > to the expected offset of 0x1000, into the padding area at offset 0x200 > when a normal GXBB boot image is created. A special GXBB eMMC header can > then be created that have the payload offset point to this relocate > code, BL1 will jump to this relocate code when booted from eMMC instead > of the normal payload start. One effect of this is that the payload size > limit must be reduced by 512 bytes on GXBB. > > Example of how to use it: > # Create a normal boot image > tools/mkimage -T amlimage -n gxbb -d u-boot-spl.bin bl2.bin > > # Create a boot image with a special eMMC header > tools/mkimage -T amlimage -n emmc -d bl2.bin bl2-emmc.bin > > # Write normal boot image to sector 1 of eMMC/SD-card > dd if=bl2.bin of=/path/to/dev bs=512 seek=1 > > # Write eMMC header, 112 bytes, to start of eMMC > dd if=bl2-emmc.bin of=/path/to/dev bs=1 count=112 > > Or with binman using something like: > binman { > multiple-images; > > u-boot-gxbb-sd { > filename = "u-boot-gxbb-sd.bin"; > pad-byte = <0xff>; > > mkimage { > filename = "bl2.bin"; > args = "-n", "gxbb", "-T", "amlimage"; > > u-boot-spl { > }; > }; > }; > > u-boot-gxbb-emmc { > filename = "u-boot-gxbb-emmc.bin"; > pad-byte = <0xff>; > > mkimage { > filename = "bl2-emmc.bin"; > args = "-n", "emmc", "-T", "amlimage"; > > blob-ext { > filename = "bl2.bin"; > } > }; > }; > }; > > Signed-off-by: Jonas Karlman <jo...@kwiboo.se> > ---
Acked-by: Ferass El Hafidi <fundersc...@postmarketos.org> > tools/amlimage-gxbb-relocate.c | 79 ++++++++++++++++++++++++++++++++++ > tools/amlimage.c | 37 ++++++++++++++++ > 2 files changed, 116 insertions(+) > create mode 100644 tools/amlimage-gxbb-relocate.c > > diff --git a/tools/amlimage-gxbb-relocate.c b/tools/amlimage-gxbb-relocate.c > new file mode 100644 > index 000000000000..3503805c460e > --- /dev/null > +++ b/tools/amlimage-gxbb-relocate.c > @@ -0,0 +1,79 @@ > +// SPDX-License-Identifier: GPL-2.0-or-later > +// Copyright Contributors to the U-Boot project. > + > +/* > + * The following commands can be used to reproduce the gxbb_relocate > + * byte array in amlimage.c > + * > + * Start U-Boot CI docker container from U-Boot source code root folder: > + * docker run --rm -v $(pwd):/build -u uboot -it > docker.io/trini/u-boot-gitlab-ci-runner:jammy-20240911.1-08Dec2024 > + * > + * Run the following commands inside the docker container: > + * export PATH=/opt/gcc-13.2.0-nolibc/aarch64-linux/bin:$PATH > + * cd /build/tools > + * > + * Generate assembly code for the c code in this file: > + * aarch64-linux-gcc -nostdlib -ffreestanding -Os -S -o > amlimage-gxbb-relocate.S amlimage-gxbb-relocate.c > + * > + * Manually remove 'mov x16, x2' and replace 'x16' with 'x2' on the last > line. > + * > + * Compile assembly code and extract the AArch64 binary code: > + * aarch64-linux-as -o amlimage-gxbb-relocate.o amlimage-gxbb-relocate.S > + * aarch64-linux-objcopy -O binary -j .text amlimage-gxbb-relocate.o > amlimage-gxbb-relocate.bin > + * > + * Print binary code as a byte array that can be copied into amlimage.c > + * hexdump -ve '1/1 "0x%.2x, "' amlimage-gxbb-relocate.bin | fold -w 72 && > echo > + * > + * Remember to update assembly code below when byte array is updated. > + */ > + > +#include <stdint.h> > + > +#define TZRAM_BASE 0xd9000000 > +#define PAYLOAD_OFFSET 0x200 > +#define BL2_OFFSET 0x1000 > +#define BL2_BASE (void *)(TZRAM_BASE + BL2_OFFSET) > +#define BL2_SIZE 0xb000 > + > +void _start(uint64_t x0, uint64_t x1) > +{ > + void (*bl2)(uint64_t, uint64_t) = BL2_BASE; > + uint64_t i, *dst = BL2_BASE, *src = BL2_BASE + PAYLOAD_OFFSET; > + > + /* memmove payload from 0x1200 to 0x1000 offset in TZRAM */ > + for (i = 0; i < BL2_SIZE / sizeof(*src); i++) > + *(dst + i) = *(src + i); > + > + /* goto entry point with x0 and x1 reg intact */ > + bl2(x0, x1); > +} > + > +/* > + .arch armv8-a > + .file "amlimage-gxbb-relocate.c" > + .text > + .align 2 > + .global _start > + .type _start, %function > +_start: > +.LFB0: > + .cfi_startproc > + mov x2, 4608 > + movk x2, 0xd900, lsl 16 > + add x3, x2, 45056 > +.L2: > + sub x4, x2, #32768 > + add x2, x2, 8 > + ldr x5, [x2, -8] > + str x5, [x4, 32256] > + cmp x2, x3 > + bne .L2 > + mov x2, 4096 > + movk x2, 0xd900, lsl 16 > + br x2 > + .cfi_endproc > +.LFE0: > + .size _start, .-_start > + .ident "GCC: (GNU) 13.2.0" > + .section .note.GNU-stack,"",@progbits > +*/ > diff --git a/tools/amlimage.c b/tools/amlimage.c > index 9af795602e69..43be1636ed11 100644 > --- a/tools/amlimage.c > +++ b/tools/amlimage.c > @@ -51,6 +51,7 @@ struct amlimage_variant { > .payload_size = size, } } > > static const struct amlimage_variant variants[] = { > + VARIANT("emmc", 1, 0, 0xb000 + PAYLOAD_OFFSET), > VARIANT("gxbb", 1, 0, 0xb000), > VARIANT("gxl", 1, 1, 0xb000), > VARIANT("gxm", 1, 1, 0xb000), > @@ -176,6 +177,17 @@ static void amlimage_set_header(void *buf, struct stat > *sbuf, int ifd, > hdr->data_offset = hdr->digest_offset + SHA256_SUM_LEN; > hdr->data_size = hdr->total_size - hdr->data_offset; > > + /* Adjust offset and size in GXBB eMMC header */ > + if (!strcmp("emmc", params->imagename)) { > + hdr->total_size -= PAYLOAD_OFFSET; > + /* Use offset to relocate code relative to eMMC header */ > + hdr->payload_offset = 0x400 - HEADER_OFFSET; > + hdr->payload_size = hdr->total_size - hdr->payload_offset; > + /* Use 0x200 offset to exclude MBR from the data range */ > + hdr->data_offset = 0x200 - HEADER_OFFSET; > + hdr->data_size = hdr->total_size - hdr->data_offset; > + } > + > sha256_starts(&ctx); > /* Header and data is used as input for sha256 digest */ > sha256_update(&ctx, (void *)hdr, hdr->header_size); > @@ -203,6 +215,22 @@ static int amlimage_check_image_type(uint8_t type) > return EXIT_FAILURE; > } > > +/* > + * AArch64 binary code to relocate payload when booting from eMMC on GXBB. > + * > + * Payload is relocated from offset 0x1200 to 0x1000 in TZRAM, similar to: > + * memmove(0xd9001000, 0xd9001200, 0xb000) > + * goto 0xd9001000 > + * > + * See amlimage-gxbb-relocate.c on how to reproduce the following byte array. > + */ > +static const uint8_t gxbb_relocate[] = { > + 0x02, 0x40, 0x82, 0xd2, 0x02, 0x20, 0xbb, 0xf2, 0x43, 0x2c, 0x40, 0x91, > + 0x44, 0x20, 0x40, 0xd1, 0x42, 0x20, 0x00, 0x91, 0x45, 0x80, 0x5f, 0xf8, > + 0x85, 0x00, 0x3f, 0xf9, 0x5f, 0x00, 0x03, 0xeb, 0x61, 0xff, 0xff, 0x54, > + 0x02, 0x00, 0x82, 0xd2, 0x02, 0x20, 0xbb, 0xf2, 0x40, 0x00, 0x1f, 0xd6, > +}; > + > static int amlimage_vrec_header(struct image_tool_params *params, > struct image_type_params *tparams) > { > @@ -213,6 +241,10 @@ static int amlimage_vrec_header(struct image_tool_params > *params, > /* Use payload offset as header size, datafile will be appended */ > tparams->header_size = PAYLOAD_OFFSET; > > + /* Only prepend 512 bytes for GXBB eMMC header */ > + if (!strcmp("emmc", variant->name)) > + tparams->header_size = 0x200; > + > tparams->hdr = calloc(1, tparams->header_size); > if (!tparams->hdr) { > fprintf(stderr, "%s: Can't alloc header: %s\n", > @@ -223,6 +255,11 @@ static int amlimage_vrec_header(struct image_tool_params > *params, > /* Start with a copy of the variant header */ > memcpy(tparams->hdr + HEADER_OFFSET, hdr, hdr->header_size); > > + /* Insert relocate code to move payload from 0x1200 to 0x1000 on GXBB */ > + if (!strcmp("gxbb", variant->name)) > + memcpy(tparams->hdr + 0x200, > + gxbb_relocate, sizeof(gxbb_relocate)); > + > /* Pad up to payload size of the variant header */ > return hdr->payload_size - params->file_size; > }