
Signed-off-by: Albert ARIBAUD (3ADEV) albert.aribaud@3adev.fr ---
Makefile | 3 + scripts/Makefile.spl | 11 ++++ tools/.gitignore | 1 + tools/Makefile | 2 + tools/mklpc32xxboot.c | 169 ++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 186 insertions(+) create mode 100644 tools/mklpc32xxboot.c
diff --git a/Makefile b/Makefile index 36a9a28..f5c9da5 100644 --- a/Makefile +++ b/Makefile @@ -1198,6 +1198,9 @@ spl/u-boot-spl: tools prepare spl/sunxi-spl.bin: spl/u-boot-spl @:
+spl/lpc32xx-spl.bin: spl/u-boot-spl + @: + tpl/u-boot-tpl.bin: tools prepare $(Q)$(MAKE) obj=tpl -f $(srctree)/scripts/Makefile.spl all
diff --git a/scripts/Makefile.spl b/scripts/Makefile.spl index ecf3037..4020383 100644 --- a/scripts/Makefile.spl +++ b/scripts/Makefile.spl @@ -158,6 +158,10 @@ ALL-y += $(obj)/sunxi-spl.bin endif endif
+ifdef CONFIG_LPC32XX_SPL +ALL-y += $(obj)/lpc32xx-spl.bin +endif + ifeq ($(CONFIG_SYS_SOC),"at91") ALL-y += boot.bin endif @@ -196,6 +200,13 @@ $(obj)/sunxi-spl.bin: $(obj)/$(SPL_BIN).bin $(call if_changed,mksunxiboot) endif
+ifdef CONFIG_LPC32XX_SPL +quiet_cmd_mklpc32xxboot = MKLPC32XX $@ +cmd_mklpc32xxboot = $(objtree)/tools/mklpc32xxboot $< $@ +$(obj)/lpc32xx-spl.bin: $(obj)/$(SPL_BIN).bin + $(call if_changed,mklpc32xxboot) +endif + quiet_cmd_u-boot-spl = LD $@ cmd_u-boot-spl = (cd $(obj) && $(LD) $(LDFLAGS) $(LDFLAGS_$(@F)) \ $(patsubst $(obj)/%,%,$(u-boot-spl-init)) --start-group \ diff --git a/tools/.gitignore b/tools/.gitignore index 9bc9fec..79a5d75 100644 --- a/tools/.gitignore +++ b/tools/.gitignore @@ -11,6 +11,7 @@ /mkenvimage /mkimage /mkexynosspl +/mklpc32xxboot /mpc86x_clk /mxsboot /mksunxiboot diff --git a/tools/Makefile b/tools/Makefile index e549f8e..6fe21b0 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -135,6 +135,8 @@ HOSTCFLAGS_mxsboot.o := -pedantic
hostprogs-$(CONFIG_SUNXI) += mksunxiboot
+hostprogs-$(CONFIG_LPC32XX_SPL) += mklpc32xxboot + hostprogs-$(CONFIG_NETCONSOLE) += ncb hostprogs-$(CONFIG_SHA1_CHECK_UB_IMG) += ubsha1
diff --git a/tools/mklpc32xxboot.c b/tools/mklpc32xxboot.c new file mode 100644 index 0000000..9f7d72e --- /dev/null +++ b/tools/mklpc32xxboot.c @@ -0,0 +1,169 @@ +/* + * LPC32XX NAND boot image generator + * + * For details on NAND boot, see LPC32XX UM chapter 35 (boot process) + * + * (C) Copyright 2014 DENX Software Engineering GmbH + * Written-by: Albert ARIBAUD albert.aribaud@3adev.fr + * + * SPDX-License-Identifier: GPL-2.0+ + */ +#include <fcntl.h> +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <sys/types.h> +#include <sys/stat.h> + +/* + * NAND page 0 boot header + */ + +struct nand_page_0_boot_header { + uint32_t data[129]; + uint32_t pad[383]; +}; + +/* + * Default ICC (interface configuration data [sic]) if none specified + * in board config + */ + +#ifndef LPC32XX_BOOT_ICR +#define LPC32XX_BOOT_ICR 0x00000096 +#endif + +/* + * Default boot NAND page size if none specified in board config + */ + +#ifndef LPC32XX_BOOT_NAND_PAGESIZE +#define LPC32XX_BOOT_NAND_PAGESIZE 2048 +#endif + +/* + * Default boot NAND pages per sector if none specified in board config + */ + +#ifndef LPC32XX_BOOT_NAND_PAGES_PER_SECTOR +#define LPC32XX_BOOT_NAND_PAGES_PER_SECTOR 64 +#endif + +/* + * Maximum size for boot code is 56K unless defined in board config + */ + +#ifndef LPC32XX_BOOT_CODESIZE +#define LPC32XX_BOOT_CODESIZE (56*1024) +#endif + +/* signature byte for a readable block */ + +#define LPC32XX_BOOT_BLOCK_OK 0xaa + +/* + * Output boot data for both sectors 0 and 1 + */ + +int main(int argc, char *argv[]) +{ + int fd_in, fd_out; + struct nand_page_0_boot_header header; + uint8_t page[LPC32XX_BOOT_NAND_PAGESIZE]; + unsigned file_size_b; + unsigned file_size_p; + int sectors_left, pages_left, bytes_left, bytes_read; + + if (argc < 2) { + printf("\tThis program takes an u-boot-spl.bin file " + "as input and produces an LPC32XX boot image.\n" + "\tUsage: %s input_file output_file\n", argv[0]); + return EXIT_FAILURE; + } + + fd_in = open(argv[1], O_RDONLY); + if (fd_in < 0) { + perror(argv[1]); + return 1; + } + + /* get input file size in bytes */ + file_size_b = lseek(fd_in, 0, SEEK_END); + + /* check maximum size */ + if (file_size_b > LPC32XX_BOOT_CODESIZE) { + fprintf(stderr, "ERROR: File too large!\n"); + return 2; + } + + /* turn filesize from bytes to NAND pages, page 0 included */ + file_size_p = ((file_size_b + (2 * LPC32XX_BOOT_NAND_PAGESIZE) - 1) + / LPC32XX_BOOT_NAND_PAGESIZE); + + /* fill header -- default byte value is 0x00, not 0xFF */ + memset(&header, 0, sizeof(header)); + header.data[0] = (header.data[2] = 0xff & LPC32XX_BOOT_ICR); + header.data[1] = (header.data[3] = 0xff & ~LPC32XX_BOOT_ICR); + header.data[4] = (header.data[6] = (header.data[8] + = (header.data[10] = 0xff & file_size_p))); + header.data[5] = (header.data[7] = (header.data[9] + = (header.data[11] = 0xff & ~file_size_p))); + header.data[12] = (header.data[128] = LPC32XX_BOOT_BLOCK_OK); + + /* open the boot file for writing */ + fd_out = open(argv[2], O_WRONLY | O_CREAT | O_TRUNC, 0666); + if (fd_out < 0) { + perror(argv[2]); + return 3; + } + + /* write sectors 0 then 1 */ + for (sectors_left = 2; sectors_left > 0; sectors_left--) { + /* write header */ + if (write(fd_out, &header, sizeof(header)) != sizeof(header)) { + perror(argv[2]); + return 4; + } + + /* write file, page-wise */ + bytes_left = file_size_b; + lseek(fd_in, 0, SEEK_SET); + while (bytes_left) { + bytes_read = sizeof(page); + if (bytes_read > bytes_left) + bytes_read = bytes_left; + memset(page, 0xFF, sizeof(page)); + if (read(fd_in, page, bytes_read) != bytes_read) { + perror(argv[1]); + return 5; + } + if (write(fd_out, page, sizeof(page)) + != sizeof(page)) { + perror(argv[2]); + return 6; + } + bytes_left -= bytes_read; + } + + /* pad with blank pages */ + memset(page, 0xFF, sizeof(page)); + /* fill sector minus header and SPL */ + pages_left = LPC32XX_BOOT_NAND_PAGES_PER_SECTOR + - file_size_p - 1; + while (pages_left) { + if (write(fd_out, page, sizeof(page)) + != sizeof(page)) { + perror(argv[2]); + return 7; + } + pages_left--; + } + } + + close(fd_in); + close(fd_out); + + return 0; +}