diff mbox series

[29/31] tools: mtk_image: split the code of generating NAND header into a new file

Message ID 229679cb5bf2e96cd0d046b560a30d5e81227ef9.1659581119.git.weijie.gao@mediatek.com
State Superseded
Delegated to: Tom Rini
Headers show
Series Add support for MediaTek MT7981/MT7986 SoCs | expand

Commit Message

Weijie Gao (高惟杰) Aug. 4, 2022, 3:36 a.m. UTC
The predefined NAND headers take too much spaces in the mtk_image.c.
Moving them into a new file can significantly improve the readability of
both mtk_image.c and the new mtk_nand_headers.c.

This is a preparation for adding more NAND headers.

Signed-off-by: Weijie Gao <weijie.gao@mediatek.com>
---
 tools/Makefile           |   1 +
 tools/mtk_image.c        | 304 ++++++---------------------------------
 tools/mtk_image.h        |  25 ----
 tools/mtk_nand_headers.c | 286 ++++++++++++++++++++++++++++++++++++
 tools/mtk_nand_headers.h |  52 +++++++
 5 files changed, 379 insertions(+), 289 deletions(-)
 create mode 100644 tools/mtk_nand_headers.c
 create mode 100644 tools/mtk_nand_headers.h

+#endif /* _MTK_NAND_HEADERS_H */

Comments

Simon Glass Aug. 4, 2022, 1:57 p.m. UTC | #1
Hi Weijie,

On Wed, 3 Aug 2022 at 21:37, Weijie Gao <weijie.gao@mediatek.com> wrote:
>
> The predefined NAND headers take too much spaces in the mtk_image.c.
> Moving them into a new file can significantly improve the readability of
> both mtk_image.c and the new mtk_nand_headers.c.
>
> This is a preparation for adding more NAND headers.
>
> Signed-off-by: Weijie Gao <weijie.gao@mediatek.com>
> ---
>  tools/Makefile           |   1 +
>  tools/mtk_image.c        | 304 ++++++---------------------------------
>  tools/mtk_image.h        |  25 ----
>  tools/mtk_nand_headers.c | 286 ++++++++++++++++++++++++++++++++++++
>  tools/mtk_nand_headers.h |  52 +++++++
>  5 files changed, 379 insertions(+), 289 deletions(-)
>  create mode 100644 tools/mtk_nand_headers.c
>  create mode 100644 tools/mtk_nand_headers.h

Reviewed-by: Simon Glass <sjg@chromium.org>

[..]

> new file mode 100644
> index 0000000000..691db85005
> --- /dev/null
> +++ b/tools/mtk_nand_headers.h
> @@ -0,0 +1,52 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * MediaTek BootROM NAND header definitions
> + *
> + * Copyright (C) 2022 MediaTek Inc.
> + * Author: Weijie Gao <weijie.gao@mediatek.com>
> + */
> +
> +#ifndef _MTK_NAND_HEADERS_H
> +#define _MTK_NAND_HEADERS_H
> +
> +#include <stdint.h>
> +#include <stdbool.h>
> +
> +struct nand_header_info {
> +       uint32_t page_size;
> +       uint32_t spare_size;
> +       uint32_t gfh_offset;
> +};
> +
> +/* AP BROM Header for NAND */

Where is this documented?

> +union nand_boot_header {
> +       struct {
> +               char name[12];
> +               char version[4];
> +               char id[8];
> +               uint16_t ioif;
> +               uint16_t pagesize;
> +               uint16_t addrcycles;
> +               uint16_t oobsize;
> +               uint16_t pages_of_block;
> +               uint16_t numblocks;
> +               uint16_t writesize_shift;
> +               uint16_t erasesize_shift;
> +               uint8_t dummy[60];
> +               uint8_t ecc_parity[28];
> +       };
> +
> +       uint8_t data[0x80];
> +};
> +
> +#define NAND_BOOT_NAME         "BOOTLOADER!"
> +#define NAND_BOOT_VERSION      "V006"
> +#define NAND_BOOT_ID           "NFIINFO"
> +
> +const union nand_boot_header *mtk_nand_header_find(const char *name);
> +uint32_t mtk_nand_header_size(const union nand_boot_header *hdr_nand);
> +int mtk_nand_header_info(const void *ptr, struct nand_header_info *info);
> +bool is_mtk_nand_header(const void *ptr);
> +uint32_t mtk_nand_header_put(const union nand_boot_header *hdr_nand, void
>  *ptr);

Please comment each of these.

> +
> +#endif /* _MTK_NAND_HEADERS_H */
> --
> 2.17.1
>

Regards,
SImon
Daniel Golle Aug. 5, 2022, 6:26 p.m. UTC | #2
Hi Weijie,

please see one comment in-line below:

On Thu, Aug 04, 2022 at 11:36:50AM +0800, Weijie Gao wrote:
> The predefined NAND headers take too much spaces in the mtk_image.c.
> Moving them into a new file can significantly improve the readability of
> both mtk_image.c and the new mtk_nand_headers.c.
> 
> This is a preparation for adding more NAND headers.
> 
> Signed-off-by: Weijie Gao <weijie.gao@mediatek.com>
> ---
>  tools/Makefile           |   1 +
>  tools/mtk_image.c        | 304 ++++++---------------------------------
>  tools/mtk_image.h        |  25 ----
>  tools/mtk_nand_headers.c | 286 ++++++++++++++++++++++++++++++++++++
>  tools/mtk_nand_headers.h |  52 +++++++
>  5 files changed, 379 insertions(+), 289 deletions(-)
>  create mode 100644 tools/mtk_nand_headers.c
>  create mode 100644 tools/mtk_nand_headers.h
> 
> diff --git a/tools/Makefile b/tools/Makefile
> index 9f2339666a..4f27ed1ab1 100644
> --- a/tools/Makefile
> +++ b/tools/Makefile
> @@ -147,6 +147,7 @@ dumpimage-mkimage-objs := aisimage.o \
>  			gpimage.o \
>  			gpimage-common.o \
>  			mtk_image.o \
> +			mtk_nand_headers.o \
>  			$(ECDSA_OBJS-y) \
>  			$(RSA_OBJS-y) \
>  			$(AES_OBJS-y)
> diff --git a/tools/mtk_image.c b/tools/mtk_image.c
> index dcd6525f32..3701d1564a 100644
> --- a/tools/mtk_image.c
> +++ b/tools/mtk_image.c
> @@ -12,216 +12,7 @@
>  #include <u-boot/sha256.h>
>  #include "imagetool.h"
>  #include "mtk_image.h"
> -
> -/* NAND header for SPI-NAND with 2KB page + 64B spare */
> -static const union nand_boot_header snand_hdr_2k_64_data = {
> -	.data = {
> -		0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
> -		0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
> -		0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
> -		0x00, 0x00, 0x00, 0x08, 0x03, 0x00, 0x40, 0x00,
> -		0x40, 0x00, 0x00, 0x08, 0x10, 0x00, 0x16, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x7B, 0xC4, 0x17, 0x9D,
> -		0xCA, 0x42, 0x90, 0xD0, 0x98, 0xD0, 0xE0, 0xF7,
> -		0xDB, 0xCD, 0x16, 0xF6, 0x03, 0x73, 0xD2, 0xB8,
> -		0x93, 0xB2, 0x56, 0x5A, 0x84, 0x6E, 0x00, 0x00
> -	}
> -};
> -
> -/* NAND header for SPI-NAND with 2KB page + 120B/128B spare */
> -static const union nand_boot_header snand_hdr_2k_128_data = {
> -	.data = {
> -		0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
> -		0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
> -		0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
> -		0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x70, 0x00,
> -		0x40, 0x00, 0x00, 0x08, 0x10, 0x00, 0x16, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x90, 0x28, 0xED, 0x13,
> -		0x7F, 0x12, 0x22, 0xCD, 0x3D, 0x06, 0xF1, 0xB3,
> -		0x6F, 0x2E, 0xD9, 0xA0, 0x9D, 0x7A, 0xBD, 0xD7,
> -		0xB3, 0x28, 0x3C, 0x13, 0xDB, 0x4E, 0x00, 0x00
> -	}
> -};
> -
> -/* NAND header for SPI-NAND with 4KB page + 256B spare */
> -static const union nand_boot_header snand_hdr_4k_256_data = {
> -	.data = {
> -		0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
> -		0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
> -		0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
> -		0x00, 0x00, 0x00, 0x10, 0x05, 0x00, 0xE0, 0x00,
> -		0x40, 0x00, 0x00, 0x08, 0x10, 0x00, 0x16, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x47, 0xED, 0x0E, 0xC3,
> -		0x83, 0xBF, 0x41, 0xD2, 0x85, 0x21, 0x97, 0x57,
> -		0xC4, 0x2E, 0x6B, 0x7A, 0x40, 0xE0, 0xCF, 0x8F,
> -		0x37, 0xBD, 0x17, 0xB6, 0xC7, 0xFE, 0x00, 0x00
> -	}
> -};
> -
> -/* NAND header for Parallel NAND 1Gb with 2KB page + 64B spare */
> -static const union nand_boot_header nand_hdr_1gb_2k_64_data = {
> -	.data = {
> -		0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
> -		0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
> -		0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
> -		0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x40, 0x00,
> -		0x40, 0x00, 0x00, 0x04, 0x0B, 0x00, 0x11, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x12, 0x28, 0x1C, 0x12,
> -		0x8F, 0xFD, 0xF8, 0x32, 0x6F, 0x6D, 0xCF, 0x6C,
> -		0xDA, 0x21, 0x70, 0x8C, 0xDA, 0x0A, 0x22, 0x82,
> -		0xAA, 0x59, 0xFA, 0x7C, 0x42, 0x2D, 0x00, 0x00
> -	}
> -};
> -
> -/* NAND header for Parallel NAND 2Gb with 2KB page + 64B spare */
> -static const union nand_boot_header nand_hdr_2gb_2k_64_data = {
> -	.data = {
> -		0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
> -		0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
> -		0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
> -		0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x40, 0x00,
> -		0x40, 0x00, 0x00, 0x08, 0x0B, 0x00, 0x11, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x20, 0x9C, 0x3D, 0x2D,
> -		0x7B, 0x68, 0x63, 0x52, 0x2E, 0x04, 0x63, 0xF1,
> -		0x35, 0x4E, 0x44, 0x3E, 0xF8, 0xAC, 0x9B, 0x95,
> -		0xAB, 0xFE, 0xE4, 0xE1, 0xD5, 0xF9, 0x00, 0x00
> -	}
> -};
> -
> -/* NAND header for Parallel NAND 4Gb with 2KB page + 64B spare */
> -static const union nand_boot_header nand_hdr_4gb_2k_64_data = {
> -	.data = {
> -		0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
> -		0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
> -		0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
> -		0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x40, 0x00,
> -		0x40, 0x00, 0x00, 0x10, 0x0B, 0x00, 0x11, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0xE3, 0x0F, 0x86, 0x32,
> -		0x68, 0x05, 0xD9, 0xC8, 0x13, 0xDF, 0xC5, 0x0B,
> -		0x35, 0x3A, 0x68, 0xA5, 0x3C, 0x0C, 0x73, 0x87,
> -		0x63, 0xB0, 0xBE, 0xCC, 0x84, 0x47, 0x00, 0x00
> -	}
> -};
> -
> -/* NAND header for Parallel NAND 2Gb with 2KB page + 128B spare */
> -static const union nand_boot_header nand_hdr_2gb_2k_128_data = {
> -	.data = {
> -		0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
> -		0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
> -		0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
> -		0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x70, 0x00,
> -		0x40, 0x00, 0x00, 0x08, 0x0B, 0x00, 0x11, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x01, 0xA5, 0xE9, 0x5A,
> -		0xDF, 0x58, 0x62, 0x41, 0xD6, 0x26, 0x77, 0xBC,
> -		0x76, 0x1F, 0x27, 0x4E, 0x4F, 0x6C, 0xC3, 0xF0,
> -		0x36, 0xDE, 0xD9, 0xB3, 0xFF, 0x93, 0x00, 0x00
> -	}
> -};
> -
> -/* NAND header for Parallel NAND 4Gb with 2KB page + 128B spare */
> -static const union nand_boot_header nand_hdr_4gb_2k_128_data = {
> -	.data = {
> -		0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
> -		0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
> -		0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
> -		0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x70, 0x00,
> -		0x40, 0x00, 0x00, 0x10, 0x0B, 0x00, 0x11, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> -		0x00, 0x00, 0x00, 0x00, 0xC2, 0x36, 0x52, 0x45,
> -		0xCC, 0x35, 0xD8, 0xDB, 0xEB, 0xFD, 0xD1, 0x46,
> -		0x76, 0x6B, 0x0B, 0xD5, 0x8B, 0xCC, 0x2B, 0xE2,
> -		0xFE, 0x90, 0x83, 0x9E, 0xAE, 0x2D, 0x00, 0x00
> -	}
> -};
> -
> -static const struct nand_header_type {
> -	const char *name;
> -	const union nand_boot_header *data;
> -} nand_headers[] = {
> -	{
> -		.name = "2k+64",
> -		.data = &snand_hdr_2k_64_data
> -	}, {
> -		.name = "2k+120",
> -		.data = &snand_hdr_2k_128_data
> -	}, {
> -		.name = "2k+128",
> -		.data = &snand_hdr_2k_128_data
> -	}, {
> -		.name = "4k+256",
> -		.data = &snand_hdr_4k_256_data
> -	}, {
> -		.name = "1g:2k+64",
> -		.data = &nand_hdr_1gb_2k_64_data
> -	}, {
> -		.name = "2g:2k+64",
> -		.data = &nand_hdr_2gb_2k_64_data
> -	}, {
> -		.name = "4g:2k+64",
> -		.data = &nand_hdr_4gb_2k_64_data
> -	}, {
> -		.name = "2g:2k+128",
> -		.data = &nand_hdr_2gb_2k_128_data
> -	}, {
> -		.name = "4g:2k+128",
> -		.data = &nand_hdr_4gb_2k_128_data
> -	}
> -};
> +#include "mtk_nand_headers.h"
>  
>  static const struct brom_img_type {
>  	const char *name;
> @@ -264,6 +55,7 @@ static uint32_t crc32tbl[256];
>  
>  /* NAND header selected by user */
>  static const union nand_boot_header *hdr_nand;
> +static uint32_t hdr_nand_size;
>  
>  /* GFH header + 2 * 4KB pages of NAND */
>  static char hdr_tmp[sizeof(struct gfh_header) + 0x2000];
> @@ -402,12 +194,7 @@ static int mtk_brom_parse_imagename(const char
>  *imagename)
>  	}
>  
>  	/* parse nand header type */
> -	for (i = 0; i < ARRAY_SIZE(nand_headers); i++) {
> -		if (!strcmp(nand_headers[i].name, nandinfo)) {
> -			hdr_nand = nand_headers[i].data;
> -			break;
> -		}
> -	}
> +	hdr_nand = mtk_nand_header_find(nandinfo);
>  
>  	/* parse device header offset */
>  	if (hdr_offs && hdr_offs[0])
> @@ -432,6 +219,8 @@ static int mtk_brom_parse_imagename(const char
>  *imagename)
>  		return -EINVAL;
>  	}
>  
> +	hdr_nand_size = mtk_nand_header_size(hdr_nand);

This call has to be guarded and only happen in case of NAND or SNAND,
otherwise we get segfault because of NULL pointer here in case of
non-NAND boot media.

> +
>  	return 0;
>  }
>  
> @@ -468,7 +257,7 @@ static int mtk_image_vrec_header(struct
>  image_tool_params *params,
>  	}
>  
>  	if (hdr_media == BRLYT_TYPE_NAND || hdr_media == BRLYT_TYPE_SNAND)
> -		tparams->header_size = 2 * le16_to_cpu(hdr_nand->pagesize);
> +		tparams->header_size = hdr_nand_size;
>  	else
>  		tparams->header_size = sizeof(struct gen_device_header);
>  
> @@ -566,16 +355,17 @@ static int mtk_image_verify_gen_header(const uint8_t
>  *ptr, int print)
>  
>  static int mtk_image_verify_nand_header(const uint8_t *ptr, int print)
>  {
> -	union nand_boot_header *nh = (union nand_boot_header *)ptr;
>  	struct brom_layout_header *bh;
> +	struct nand_header_info info;
>  	struct gfh_header *gfh;
>  	const char *bootmedia;
> +	int ret;
>  
> -	if (strncmp(nh->version, NAND_BOOT_VERSION, sizeof(nh->version)) ||
> -	    strcmp(nh->id, NAND_BOOT_ID))
> -		return -1;
> +	ret = mtk_nand_header_info(ptr, &info);
> +	if (ret < 0)
> +		return ret;
>  
> -	bh = (struct brom_layout_header *)(ptr + le16_to_cpu(nh->pagesize));
> +	bh = (struct brom_layout_header *)(ptr + info.page_size);
>  
>  	if (strcmp(bh->name, BRLYT_NAME))
>  		return -1;
> @@ -586,34 +376,23 @@ static int mtk_image_verify_nand_header(const uint8_t
>  *ptr, int print)
>  		if (le32_to_cpu(bh->type) == BRLYT_TYPE_NAND)
>  			bootmedia = "Parallel NAND";
>  		else if (le32_to_cpu(bh->type) == BRLYT_TYPE_SNAND)
> -			bootmedia = "Serial NAND";
> +			bootmedia = "Serial NAND (SNFI/AP)";
>  		else
>  			return -1;
>  	}
>  
>  	if (print) {
> -		printf("Boot Media: %s\n", bootmedia);
> -
> -		if (le32_to_cpu(bh->type) == BRLYT_TYPE_NAND) {
> -			uint64_t capacity =
> -				(uint64_t)le16_to_cpu(nh->numblocks) *
> -				(uint64_t)le16_to_cpu(nh->pages_of_block) *
> -				(uint64_t)le16_to_cpu(nh->pagesize) * 8;
> -			printf("Capacity:     %dGb\n",
> -			       (uint32_t)(capacity >> 30));
> -		}
> +		printf("Boot Media:   %s\n", bootmedia);
>  
> -		if (le16_to_cpu(nh->pagesize) >= 1024)
> -			printf("Page Size:    %dKB\n",
> -			       le16_to_cpu(nh->pagesize) >> 10);
> +		if (info.page_size >= 1024)
> +			printf("Page Size:    %dKB\n", info.page_size >> 10);
>  		else
> -			printf("Page Size:    %dB\n",
> -			       le16_to_cpu(nh->pagesize));
> +			printf("Page Size:    %dB\n", info.page_size);
>  
> -		printf("Spare Size:   %dB\n", le16_to_cpu(nh->oobsize));
> +		printf("Spare Size:   %dB\n", info.spare_size);
>  	}
>  
> -	gfh = (struct gfh_header *)(ptr + 2 * le16_to_cpu(nh->pagesize));
> +	gfh = (struct gfh_header *)(ptr + info.gfh_offset);
>  
>  	return mtk_image_verify_gfh(gfh, GFH_FLASH_TYPE_NAND, print);
>  }
> @@ -713,7 +492,7 @@ static int mtk_image_verify_header(unsigned char *ptr,
>  int image_size,
>  	if (image_get_magic(hdr) == IH_MAGIC)
>  		return mtk_image_verify_mt7621_header(ptr, 0);
>  
> -	if (!strcmp((char *)ptr, NAND_BOOT_NAME))
> +	if (is_mtk_nand_header(ptr))
>  		return mtk_image_verify_nand_header(ptr, 0);
>  	else
>  		return mtk_image_verify_gen_header(ptr, 0);
> @@ -739,7 +518,7 @@ static void mtk_image_print_header(const void *ptr)
>  		return;
>  	}
>  
> -	if (!strcmp((char *)ptr, NAND_BOOT_NAME))
> +	if (is_mtk_nand_header(ptr))
>  		mtk_image_verify_nand_header(ptr, 1);
>  	else
>  		mtk_image_verify_gen_header(ptr, 1);
> @@ -870,36 +649,33 @@ static void mtk_image_set_gen_header(void *ptr, off_t
>  filesize,
>  static void mtk_image_set_nand_header(void *ptr, off_t filesize,
>  				      uint32_t loadaddr)
>  {
> -	union nand_boot_header *nh = (union nand_boot_header *)ptr;
>  	struct brom_layout_header *brlyt;
>  	struct gfh_header *gfh;
> -	uint32_t payload_pages;
> -	int i;
> +	uint32_t payload_pages, nand_page_size;
>  
> -	/* NAND device header, repeat 4 times */
> -	for (i = 0; i < 4; i++)
> -		memcpy(nh + i, hdr_nand, sizeof(union nand_boot_header));
> +	/* NAND header */
> +	nand_page_size = mtk_nand_header_put(hdr_nand, ptr);
>  
> -	/* BRLYT header */
> -	payload_pages = (filesize + le16_to_cpu(hdr_nand->pagesize) - 1) /
> -			le16_to_cpu(hdr_nand->pagesize);
> -	brlyt = (struct brom_layout_header *)
> -		(ptr + le16_to_cpu(hdr_nand->pagesize));
> -	put_brom_layout_header(brlyt, hdr_media);
> -	brlyt->header_size = cpu_to_le32(2);
> -	brlyt->total_size = cpu_to_le32(payload_pages);
> -	brlyt->header_size_2 = brlyt->header_size;
> -	brlyt->total_size_2 = brlyt->total_size;
> -	brlyt->unused = cpu_to_le32(1);
> +	if (nand_page_size) {
> +		/* BRLYT header */
> +		payload_pages = (filesize + nand_page_size - 1) /
> +				nand_page_size;
> +		brlyt = (struct brom_layout_header *)(ptr + nand_page_size);
> +		put_brom_layout_header(brlyt, hdr_media);
> +		brlyt->header_size = cpu_to_le32(2);
> +		brlyt->total_size = cpu_to_le32(payload_pages);
> +		brlyt->header_size_2 = brlyt->header_size;
> +		brlyt->total_size_2 = brlyt->total_size;
> +		brlyt->unused = cpu_to_le32(1);
> +	}
>  
>  	/* GFH header */
> -	gfh = (struct gfh_header *)(ptr + 2 * le16_to_cpu(hdr_nand->pagesize));
> -	put_ghf_header(gfh, filesize, 2 * le16_to_cpu(hdr_nand->pagesize),
> -		       loadaddr, GFH_FLASH_TYPE_NAND);
> +	gfh = (struct gfh_header *)(ptr + hdr_nand_size);
> +	put_ghf_header(gfh, filesize, hdr_nand_size, loadaddr,
> +		       GFH_FLASH_TYPE_NAND);
>  
>  	/* Generate SHA256 hash */
> -	put_hash((uint8_t *)gfh,
> -		 filesize - 2 * le16_to_cpu(hdr_nand->pagesize) - SHA256_SUM_LEN);
> +	put_hash((uint8_t *)gfh, filesize - hdr_nand_size - SHA256_SUM_LEN);
>  }
>  
>  static void mtk_image_set_mt7621_header(void *ptr, off_t filesize,
> diff --git a/tools/mtk_image.h b/tools/mtk_image.h
> index d868545a33..fad9372100 100644
> --- a/tools/mtk_image.h
> +++ b/tools/mtk_image.h
> @@ -26,31 +26,6 @@ union gen_boot_header {
>  #define SF_BOOT_NAME		"SF_BOOT"
>  #define SDMMC_BOOT_NAME		"SDMMC_BOOT"
>  
> -/* Header for NAND */
> -union nand_boot_header {
> -	struct {
> -		char name[12];
> -		char version[4];
> -		char id[8];
> -		uint16_t ioif;
> -		uint16_t pagesize;
> -		uint16_t addrcycles;
> -		uint16_t oobsize;
> -		uint16_t pages_of_block;
> -		uint16_t numblocks;
> -		uint16_t writesize_shift;
> -		uint16_t erasesize_shift;
> -		uint8_t dummy[60];
> -		uint8_t ecc_parity[28];
> -	};
> -
> -	uint8_t data[0x80];
> -};
> -
> -#define NAND_BOOT_NAME		"BOOTLOADER!"
> -#define NAND_BOOT_VERSION	"V006"
> -#define NAND_BOOT_ID		"NFIINFO"
> -
>  /* BootROM layout header */
>  struct brom_layout_header {
>  	char name[8];
> diff --git a/tools/mtk_nand_headers.c b/tools/mtk_nand_headers.c
> new file mode 100644
> index 0000000000..12f827c39f
> --- /dev/null
> +++ b/tools/mtk_nand_headers.c
> @@ -0,0 +1,286 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * MediaTek BootROM NAND header definitions
> + *
> + * Copyright (C) 2022 MediaTek Inc.
> + * Author: Weijie Gao <weijie.gao@mediatek.com>
> + */
> +
> +#include <stdint.h>
> +#include <string.h>
> +#include "imagetool.h"
> +#include "mtk_image.h"
> +#include "mtk_nand_headers.h"
> +
> +/* NAND header for SPI-NAND with 2KB page + 64B spare */
> +static const union nand_boot_header snand_hdr_2k_64_data = {
> +	.data = {
> +		0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
> +		0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
> +		0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
> +		0x00, 0x00, 0x00, 0x08, 0x03, 0x00, 0x40, 0x00,
> +		0x40, 0x00, 0x00, 0x08, 0x10, 0x00, 0x16, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x7B, 0xC4, 0x17, 0x9D,
> +		0xCA, 0x42, 0x90, 0xD0, 0x98, 0xD0, 0xE0, 0xF7,
> +		0xDB, 0xCD, 0x16, 0xF6, 0x03, 0x73, 0xD2, 0xB8,
> +		0x93, 0xB2, 0x56, 0x5A, 0x84, 0x6E, 0x00, 0x00
> +	}
> +};
> +
> +/* NAND header for SPI-NAND with 2KB page + 120B/128B spare */
> +static const union nand_boot_header snand_hdr_2k_128_data = {
> +	.data = {
> +		0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
> +		0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
> +		0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
> +		0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x70, 0x00,
> +		0x40, 0x00, 0x00, 0x08, 0x10, 0x00, 0x16, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x90, 0x28, 0xED, 0x13,
> +		0x7F, 0x12, 0x22, 0xCD, 0x3D, 0x06, 0xF1, 0xB3,
> +		0x6F, 0x2E, 0xD9, 0xA0, 0x9D, 0x7A, 0xBD, 0xD7,
> +		0xB3, 0x28, 0x3C, 0x13, 0xDB, 0x4E, 0x00, 0x00
> +	}
> +};
> +
> +/* NAND header for SPI-NAND with 4KB page + 256B spare */
> +static const union nand_boot_header snand_hdr_4k_256_data = {
> +	.data = {
> +		0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
> +		0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
> +		0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
> +		0x00, 0x00, 0x00, 0x10, 0x05, 0x00, 0xE0, 0x00,
> +		0x40, 0x00, 0x00, 0x08, 0x10, 0x00, 0x16, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x47, 0xED, 0x0E, 0xC3,
> +		0x83, 0xBF, 0x41, 0xD2, 0x85, 0x21, 0x97, 0x57,
> +		0xC4, 0x2E, 0x6B, 0x7A, 0x40, 0xE0, 0xCF, 0x8F,
> +		0x37, 0xBD, 0x17, 0xB6, 0xC7, 0xFE, 0x00, 0x00
> +	}
> +};
> +
> +/* NAND header for Parallel NAND 1Gb with 2KB page + 64B spare */
> +static const union nand_boot_header nand_hdr_1gb_2k_64_data = {
> +	.data = {
> +		0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
> +		0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
> +		0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
> +		0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x40, 0x00,
> +		0x40, 0x00, 0x00, 0x04, 0x0B, 0x00, 0x11, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x12, 0x28, 0x1C, 0x12,
> +		0x8F, 0xFD, 0xF8, 0x32, 0x6F, 0x6D, 0xCF, 0x6C,
> +		0xDA, 0x21, 0x70, 0x8C, 0xDA, 0x0A, 0x22, 0x82,
> +		0xAA, 0x59, 0xFA, 0x7C, 0x42, 0x2D, 0x00, 0x00
> +	}
> +};
> +
> +/* NAND header for Parallel NAND 2Gb with 2KB page + 64B spare */
> +static const union nand_boot_header nand_hdr_2gb_2k_64_data = {
> +	.data = {
> +		0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
> +		0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
> +		0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
> +		0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x40, 0x00,
> +		0x40, 0x00, 0x00, 0x08, 0x0B, 0x00, 0x11, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x20, 0x9C, 0x3D, 0x2D,
> +		0x7B, 0x68, 0x63, 0x52, 0x2E, 0x04, 0x63, 0xF1,
> +		0x35, 0x4E, 0x44, 0x3E, 0xF8, 0xAC, 0x9B, 0x95,
> +		0xAB, 0xFE, 0xE4, 0xE1, 0xD5, 0xF9, 0x00, 0x00
> +	}
> +};
> +
> +/* NAND header for Parallel NAND 4Gb with 2KB page + 64B spare */
> +static const union nand_boot_header nand_hdr_4gb_2k_64_data = {
> +	.data = {
> +		0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
> +		0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
> +		0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
> +		0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x40, 0x00,
> +		0x40, 0x00, 0x00, 0x10, 0x0B, 0x00, 0x11, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0xE3, 0x0F, 0x86, 0x32,
> +		0x68, 0x05, 0xD9, 0xC8, 0x13, 0xDF, 0xC5, 0x0B,
> +		0x35, 0x3A, 0x68, 0xA5, 0x3C, 0x0C, 0x73, 0x87,
> +		0x63, 0xB0, 0xBE, 0xCC, 0x84, 0x47, 0x00, 0x00
> +	}
> +};
> +
> +/* NAND header for Parallel NAND 2Gb with 2KB page + 128B spare */
> +static const union nand_boot_header nand_hdr_2gb_2k_128_data = {
> +	.data = {
> +		0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
> +		0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
> +		0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
> +		0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x70, 0x00,
> +		0x40, 0x00, 0x00, 0x08, 0x0B, 0x00, 0x11, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x01, 0xA5, 0xE9, 0x5A,
> +		0xDF, 0x58, 0x62, 0x41, 0xD6, 0x26, 0x77, 0xBC,
> +		0x76, 0x1F, 0x27, 0x4E, 0x4F, 0x6C, 0xC3, 0xF0,
> +		0x36, 0xDE, 0xD9, 0xB3, 0xFF, 0x93, 0x00, 0x00
> +	}
> +};
> +
> +/* NAND header for Parallel NAND 4Gb with 2KB page + 128B spare */
> +static const union nand_boot_header nand_hdr_4gb_2k_128_data = {
> +	.data = {
> +		0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
> +		0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
> +		0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
> +		0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x70, 0x00,
> +		0x40, 0x00, 0x00, 0x10, 0x0B, 0x00, 0x11, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0xC2, 0x36, 0x52, 0x45,
> +		0xCC, 0x35, 0xD8, 0xDB, 0xEB, 0xFD, 0xD1, 0x46,
> +		0x76, 0x6B, 0x0B, 0xD5, 0x8B, 0xCC, 0x2B, 0xE2,
> +		0xFE, 0x90, 0x83, 0x9E, 0xAE, 0x2D, 0x00, 0x00
> +	}
> +};
> +
> +static const struct nand_header_type {
> +	const char *name;
> +	const union nand_boot_header *data;
> +} nand_headers[] = {
> +	{
> +		.name = "2k+64",
> +		.data = &snand_hdr_2k_64_data
> +	}, {
> +		.name = "2k+120",
> +		.data = &snand_hdr_2k_128_data
> +	}, {
> +		.name = "2k+128",
> +		.data = &snand_hdr_2k_128_data
> +	}, {
> +		.name = "4k+256",
> +		.data = &snand_hdr_4k_256_data
> +	}, {
> +		.name = "1g:2k+64",
> +		.data = &nand_hdr_1gb_2k_64_data
> +	}, {
> +		.name = "2g:2k+64",
> +		.data = &nand_hdr_2gb_2k_64_data
> +	}, {
> +		.name = "4g:2k+64",
> +		.data = &nand_hdr_4gb_2k_64_data
> +	}, {
> +		.name = "2g:2k+128",
> +		.data = &nand_hdr_2gb_2k_128_data
> +	}, {
> +		.name = "4g:2k+128",
> +		.data = &nand_hdr_4gb_2k_128_data
> +	}
> +};
> +
> +const union nand_boot_header *mtk_nand_header_find(const char *name)
> +{
> +	uint32_t i;
> +
> +	for (i = 0; i < ARRAY_SIZE(nand_headers); i++) {
> +		if (!strcmp(nand_headers[i].name, name))
> +			return nand_headers[i].data;
> +	}
> +
> +	return NULL;
> +}
> +
> +uint32_t mtk_nand_header_size(const union nand_boot_header *hdr_nand)
> +{
> +	return 2 * le16_to_cpu(hdr_nand->pagesize);
> +}
> +
> +static int mtk_nand_header_ap_info(const void *ptr,
> +				   struct nand_header_info *info)
> +{
> +	union nand_boot_header *nh = (union nand_boot_header *)ptr;
> +
> +	if (strncmp(nh->version, NAND_BOOT_VERSION, sizeof(nh->version)) ||
> +	    strcmp(nh->id, NAND_BOOT_ID))
> +		return -1;
> +
> +	info->page_size = le16_to_cpu(nh->pagesize);
> +	info->spare_size = le16_to_cpu(nh->oobsize);
> +	info->gfh_offset = 2 * info->page_size;
> +
> +	return 0;
> +}
> +
> +int mtk_nand_header_info(const void *ptr, struct nand_header_info *info)
> +{
> +	if (!strcmp((char *)ptr, NAND_BOOT_NAME))
> +		return mtk_nand_header_ap_info(ptr, info);
> +
> +	return -1;
> +}
> +
> +bool is_mtk_nand_header(const void *ptr)
> +{
> +	struct nand_header_info info;
> +
> +	if (mtk_nand_header_info(ptr, &info) >= 0)
> +		return true;
> +
> +	return false;
> +}
> +
> +uint32_t mtk_nand_header_put(const union nand_boot_header *hdr_nand, void
>  *ptr)
> +{
> +	union nand_boot_header *nh = (union nand_boot_header *)ptr;
> +	int i;
> +
> +	/* NAND device header, repeat 4 times */
> +	for (i = 0; i < 4; i++)
> +		memcpy(nh + i, hdr_nand, sizeof(union nand_boot_header));
> +
> +	return le16_to_cpu(hdr_nand->pagesize);
> +}
> diff --git a/tools/mtk_nand_headers.h b/tools/mtk_nand_headers.h
> new file mode 100644
> index 0000000000..691db85005
> --- /dev/null
> +++ b/tools/mtk_nand_headers.h
> @@ -0,0 +1,52 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * MediaTek BootROM NAND header definitions
> + *
> + * Copyright (C) 2022 MediaTek Inc.
> + * Author: Weijie Gao <weijie.gao@mediatek.com>
> + */
> +
> +#ifndef _MTK_NAND_HEADERS_H
> +#define _MTK_NAND_HEADERS_H
> +
> +#include <stdint.h>
> +#include <stdbool.h>
> +
> +struct nand_header_info {
> +	uint32_t page_size;
> +	uint32_t spare_size;
> +	uint32_t gfh_offset;
> +};
> +
> +/* AP BROM Header for NAND */
> +union nand_boot_header {
> +	struct {
> +		char name[12];
> +		char version[4];
> +		char id[8];
> +		uint16_t ioif;
> +		uint16_t pagesize;
> +		uint16_t addrcycles;
> +		uint16_t oobsize;
> +		uint16_t pages_of_block;
> +		uint16_t numblocks;
> +		uint16_t writesize_shift;
> +		uint16_t erasesize_shift;
> +		uint8_t dummy[60];
> +		uint8_t ecc_parity[28];
> +	};
> +
> +	uint8_t data[0x80];
> +};
> +
> +#define NAND_BOOT_NAME		"BOOTLOADER!"
> +#define NAND_BOOT_VERSION	"V006"
> +#define NAND_BOOT_ID		"NFIINFO"
> +
> +const union nand_boot_header *mtk_nand_header_find(const char *name);
> +uint32_t mtk_nand_header_size(const union nand_boot_header *hdr_nand);
> +int mtk_nand_header_info(const void *ptr, struct nand_header_info *info);
> +bool is_mtk_nand_header(const void *ptr);
> +uint32_t mtk_nand_header_put(const union nand_boot_header *hdr_nand, void
>  *ptr);
> +
> +#endif /* _MTK_NAND_HEADERS_H */
> -- 
> 2.17.1
>
Weijie Gao (高惟杰) Aug. 8, 2022, 3:23 a.m. UTC | #3
On Thu, 2022-08-04 at 07:57 -0600, Simon Glass wrote:
> Hi Weijie,
> 
> On Wed, 3 Aug 2022 at 21:37, Weijie Gao <weijie.gao@mediatek.com>
> wrote:
> > 
> > The predefined NAND headers take too much spaces in the
> > mtk_image.c.
> > Moving them into a new file can significantly improve the
> > readability of
> > both mtk_image.c and the new mtk_nand_headers.c.
> > 
> > This is a preparation for adding more NAND headers.
> > 
> > Signed-off-by: Weijie Gao <weijie.gao@mediatek.com>
> > ---
> >  tools/Makefile           |   1 +
> >  tools/mtk_image.c        | 304 ++++++-----------------------------
> > ----
> >  tools/mtk_image.h        |  25 ----
> >  tools/mtk_nand_headers.c | 286
> > ++++++++++++++++++++++++++++++++++++
> >  tools/mtk_nand_headers.h |  52 +++++++
> >  5 files changed, 379 insertions(+), 289 deletions(-)
> >  create mode 100644 tools/mtk_nand_headers.c
> >  create mode 100644 tools/mtk_nand_headers.h
> 
> Reviewed-by: Simon Glass <sjg@chromium.org>
> 
> [..]
> 
> > new file mode 100644
> > index 0000000000..691db85005
> > --- /dev/null
> > +++ b/tools/mtk_nand_headers.h
> > @@ -0,0 +1,52 @@
> > +/* SPDX-License-Identifier: GPL-2.0+ */
> > +/*
> > + * MediaTek BootROM NAND header definitions
> > + *
> > + * Copyright (C) 2022 MediaTek Inc.
> > + * Author: Weijie Gao <weijie.gao@mediatek.com>
> > + */
> > +
> > +#ifndef _MTK_NAND_HEADERS_H
> > +#define _MTK_NAND_HEADERS_H
> > +
> > +#include <stdint.h>
> > +#include <stdbool.h>
> > +
> > +struct nand_header_info {
> > +       uint32_t page_size;
> > +       uint32_t spare_size;
> > +       uint32_t gfh_offset;
> > +};
> > +
> > +/* AP BROM Header for NAND */
> 
> Where is this documented?

This wasn't documented. The bootrom doesn't know the configuration
of the nand device. It has to read the first page to retrive necessary
information from this header.

> 
> > +union nand_boot_header {
> > +       struct {
> > +               char name[12];
> > +               char version[4];
> > +               char id[8];
> > +               uint16_t ioif;
> > +               uint16_t pagesize;
> > +               uint16_t addrcycles;
> > +               uint16_t oobsize;
> > +               uint16_t pages_of_block;
> > +               uint16_t numblocks;
> > +               uint16_t writesize_shift;
> > +               uint16_t erasesize_shift;
> > +               uint8_t dummy[60];
> > +               uint8_t ecc_parity[28];
> > +       };
> > +
> > +       uint8_t data[0x80];
> > +};
> > +
> > +#define NAND_BOOT_NAME         "BOOTLOADER!"
> > +#define NAND_BOOT_VERSION      "V006"
> > +#define NAND_BOOT_ID           "NFIINFO"
> > +
> > +const union nand_boot_header *mtk_nand_header_find(const char
> > *name);
> > +uint32_t mtk_nand_header_size(const union nand_boot_header
> > *hdr_nand);
> > +int mtk_nand_header_info(const void *ptr, struct nand_header_info
> > *info);
> > +bool is_mtk_nand_header(const void *ptr);
> > +uint32_t mtk_nand_header_put(const union nand_boot_header
> > *hdr_nand, void
> >  *ptr);
> 
> Please comment each of these.

OK.

> 
> > +
> > +#endif /* _MTK_NAND_HEADERS_H */
> > --
> > 2.17.1
> > 
> 
> Regards,
> SImon
Weijie Gao (高惟杰) Aug. 8, 2022, 3:26 a.m. UTC | #4
On Fri, 2022-08-05 at 20:26 +0200, Daniel Golle wrote:
> Hi Weijie,
> 
> please see one comment in-line below:
> 
> On Thu, Aug 04, 2022 at 11:36:50AM +0800, Weijie Gao wrote:
> > The predefined NAND headers take too much spaces in the
> > mtk_image.c.
> > Moving them into a new file can significantly improve the
> > readability of
> > both mtk_image.c and the new mtk_nand_headers.c.
> > 
> > This is a preparation for adding more NAND headers.
> > 
> > Signed-off-by: Weijie Gao <weijie.gao@mediatek.com>
> > ---
> >  tools/Makefile           |   1 +
> >  tools/mtk_image.c        | 304 ++++++-----------------------------
> > ----
> >  tools/mtk_image.h        |  25 ----
> >  tools/mtk_nand_headers.c | 286
> > ++++++++++++++++++++++++++++++++++++
> >  tools/mtk_nand_headers.h |  52 +++++++
> >  5 files changed, 379 insertions(+), 289 deletions(-)
> >  create mode 100644 tools/mtk_nand_headers.c
> >  create mode 100644 tools/mtk_nand_headers.h
> > 
> > diff --git a/tools/Makefile b/tools/Makefile
> > index 9f2339666a..4f27ed1ab1 100644
> > --- a/tools/Makefile
> > +++ b/tools/Makefile
> > @@ -147,6 +147,7 @@ dumpimage-mkimage-objs := aisimage.o \
> >  			gpimage.o \
> >  			gpimage-common.o \
> >  			mtk_image.o \
> > +			mtk_nand_headers.o \
> >  			$(ECDSA_OBJS-y) \
> >  			$(RSA_OBJS-y) \
> >  			$(AES_OBJS-y)
> > diff --git a/tools/mtk_image.c b/tools/mtk_image.c
> > index dcd6525f32..3701d1564a 100644
> > --- a/tools/mtk_image.c
> > +++ b/tools/mtk_image.c
> > @@ -12,216 +12,7 @@
> >  #include <u-boot/sha256.h>
> >  #include "imagetool.h"
> >  #include "mtk_image.h"
> > -
> > -/* NAND header for SPI-NAND with 2KB page + 64B spare */
> > -static const union nand_boot_header snand_hdr_2k_64_data = {
> > -	.data = {
> > -		0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
> > -		0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
> > -		0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
> > -		0x00, 0x00, 0x00, 0x08, 0x03, 0x00, 0x40, 0x00,
> > -		0x40, 0x00, 0x00, 0x08, 0x10, 0x00, 0x16, 0x00,
> > -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > -		0x00, 0x00, 0x00, 0x00, 0x7B, 0xC4, 0x17, 0x9D,
> > -		0xCA, 0x42, 0x90, 0xD0, 0x98, 0xD0, 0xE0, 0xF7,
> > -		0xDB, 0xCD, 0x16, 0xF6, 0x03, 0x73, 0xD2, 0xB8,
> > -		0x93, 0xB2, 0x56, 0x5A, 0x84, 0x6E, 0x00, 0x00
> > -	}
> > -};
> > -
> > -/* NAND header for SPI-NAND with 2KB page + 120B/128B spare */
> > -static const union nand_boot_header snand_hdr_2k_128_data = {
> > -	.data = {
> > -		0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
> > -		0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
> > -		0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
> > -		0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x70, 0x00,
> > -		0x40, 0x00, 0x00, 0x08, 0x10, 0x00, 0x16, 0x00,
> > -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > -		0x00, 0x00, 0x00, 0x00, 0x90, 0x28, 0xED, 0x13,
> > -		0x7F, 0x12, 0x22, 0xCD, 0x3D, 0x06, 0xF1, 0xB3,
> > -		0x6F, 0x2E, 0xD9, 0xA0, 0x9D, 0x7A, 0xBD, 0xD7,
> > -		0xB3, 0x28, 0x3C, 0x13, 0xDB, 0x4E, 0x00, 0x00
> > -	}
> > -};
> > -
> > -/* NAND header for SPI-NAND with 4KB page + 256B spare */
> > -static const union nand_boot_header snand_hdr_4k_256_data = {
> > -	.data = {
> > -		0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
> > -		0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
> > -		0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
> > -		0x00, 0x00, 0x00, 0x10, 0x05, 0x00, 0xE0, 0x00,
> > -		0x40, 0x00, 0x00, 0x08, 0x10, 0x00, 0x16, 0x00,
> > -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > -		0x00, 0x00, 0x00, 0x00, 0x47, 0xED, 0x0E, 0xC3,
> > -		0x83, 0xBF, 0x41, 0xD2, 0x85, 0x21, 0x97, 0x57,
> > -		0xC4, 0x2E, 0x6B, 0x7A, 0x40, 0xE0, 0xCF, 0x8F,
> > -		0x37, 0xBD, 0x17, 0xB6, 0xC7, 0xFE, 0x00, 0x00
> > -	}
> > -};
> > -
> > -/* NAND header for Parallel NAND 1Gb with 2KB page + 64B spare */
> > -static const union nand_boot_header nand_hdr_1gb_2k_64_data = {
> > -	.data = {
> > -		0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
> > -		0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
> > -		0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
> > -		0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x40, 0x00,
> > -		0x40, 0x00, 0x00, 0x04, 0x0B, 0x00, 0x11, 0x00,
> > -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > -		0x00, 0x00, 0x00, 0x00, 0x12, 0x28, 0x1C, 0x12,
> > -		0x8F, 0xFD, 0xF8, 0x32, 0x6F, 0x6D, 0xCF, 0x6C,
> > -		0xDA, 0x21, 0x70, 0x8C, 0xDA, 0x0A, 0x22, 0x82,
> > -		0xAA, 0x59, 0xFA, 0x7C, 0x42, 0x2D, 0x00, 0x00
> > -	}
> > -};
> > -
> > -/* NAND header for Parallel NAND 2Gb with 2KB page + 64B spare */
> > -static const union nand_boot_header nand_hdr_2gb_2k_64_data = {
> > -	.data = {
> > -		0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
> > -		0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
> > -		0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
> > -		0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x40, 0x00,
> > -		0x40, 0x00, 0x00, 0x08, 0x0B, 0x00, 0x11, 0x00,
> > -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > -		0x00, 0x00, 0x00, 0x00, 0x20, 0x9C, 0x3D, 0x2D,
> > -		0x7B, 0x68, 0x63, 0x52, 0x2E, 0x04, 0x63, 0xF1,
> > -		0x35, 0x4E, 0x44, 0x3E, 0xF8, 0xAC, 0x9B, 0x95,
> > -		0xAB, 0xFE, 0xE4, 0xE1, 0xD5, 0xF9, 0x00, 0x00
> > -	}
> > -};
> > -
> > -/* NAND header for Parallel NAND 4Gb with 2KB page + 64B spare */
> > -static const union nand_boot_header nand_hdr_4gb_2k_64_data = {
> > -	.data = {
> > -		0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
> > -		0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
> > -		0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
> > -		0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x40, 0x00,
> > -		0x40, 0x00, 0x00, 0x10, 0x0B, 0x00, 0x11, 0x00,
> > -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > -		0x00, 0x00, 0x00, 0x00, 0xE3, 0x0F, 0x86, 0x32,
> > -		0x68, 0x05, 0xD9, 0xC8, 0x13, 0xDF, 0xC5, 0x0B,
> > -		0x35, 0x3A, 0x68, 0xA5, 0x3C, 0x0C, 0x73, 0x87,
> > -		0x63, 0xB0, 0xBE, 0xCC, 0x84, 0x47, 0x00, 0x00
> > -	}
> > -};
> > -
> > -/* NAND header for Parallel NAND 2Gb with 2KB page + 128B spare */
> > -static const union nand_boot_header nand_hdr_2gb_2k_128_data = {
> > -	.data = {
> > -		0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
> > -		0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
> > -		0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
> > -		0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x70, 0x00,
> > -		0x40, 0x00, 0x00, 0x08, 0x0B, 0x00, 0x11, 0x00,
> > -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > -		0x00, 0x00, 0x00, 0x00, 0x01, 0xA5, 0xE9, 0x5A,
> > -		0xDF, 0x58, 0x62, 0x41, 0xD6, 0x26, 0x77, 0xBC,
> > -		0x76, 0x1F, 0x27, 0x4E, 0x4F, 0x6C, 0xC3, 0xF0,
> > -		0x36, 0xDE, 0xD9, 0xB3, 0xFF, 0x93, 0x00, 0x00
> > -	}
> > -};
> > -
> > -/* NAND header for Parallel NAND 4Gb with 2KB page + 128B spare */
> > -static const union nand_boot_header nand_hdr_4gb_2k_128_data = {
> > -	.data = {
> > -		0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
> > -		0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
> > -		0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
> > -		0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x70, 0x00,
> > -		0x40, 0x00, 0x00, 0x10, 0x0B, 0x00, 0x11, 0x00,
> > -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > -		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > -		0x00, 0x00, 0x00, 0x00, 0xC2, 0x36, 0x52, 0x45,
> > -		0xCC, 0x35, 0xD8, 0xDB, 0xEB, 0xFD, 0xD1, 0x46,
> > -		0x76, 0x6B, 0x0B, 0xD5, 0x8B, 0xCC, 0x2B, 0xE2,
> > -		0xFE, 0x90, 0x83, 0x9E, 0xAE, 0x2D, 0x00, 0x00
> > -	}
> > -};
> > -
> > -static const struct nand_header_type {
> > -	const char *name;
> > -	const union nand_boot_header *data;
> > -} nand_headers[] = {
> > -	{
> > -		.name = "2k+64",
> > -		.data = &snand_hdr_2k_64_data
> > -	}, {
> > -		.name = "2k+120",
> > -		.data = &snand_hdr_2k_128_data
> > -	}, {
> > -		.name = "2k+128",
> > -		.data = &snand_hdr_2k_128_data
> > -	}, {
> > -		.name = "4k+256",
> > -		.data = &snand_hdr_4k_256_data
> > -	}, {
> > -		.name = "1g:2k+64",
> > -		.data = &nand_hdr_1gb_2k_64_data
> > -	}, {
> > -		.name = "2g:2k+64",
> > -		.data = &nand_hdr_2gb_2k_64_data
> > -	}, {
> > -		.name = "4g:2k+64",
> > -		.data = &nand_hdr_4gb_2k_64_data
> > -	}, {
> > -		.name = "2g:2k+128",
> > -		.data = &nand_hdr_2gb_2k_128_data
> > -	}, {
> > -		.name = "4g:2k+128",
> > -		.data = &nand_hdr_4gb_2k_128_data
> > -	}
> > -};
> > +#include "mtk_nand_headers.h"
> >  
> >  static const struct brom_img_type {
> >  	const char *name;
> > @@ -264,6 +55,7 @@ static uint32_t crc32tbl[256];
> >  
> >  /* NAND header selected by user */
> >  static const union nand_boot_header *hdr_nand;
> > +static uint32_t hdr_nand_size;
> >  
> >  /* GFH header + 2 * 4KB pages of NAND */
> >  static char hdr_tmp[sizeof(struct gfh_header) + 0x2000];
> > @@ -402,12 +194,7 @@ static int mtk_brom_parse_imagename(const char
> >  *imagename)
> >  	}
> >  
> >  	/* parse nand header type */
> > -	for (i = 0; i < ARRAY_SIZE(nand_headers); i++) {
> > -		if (!strcmp(nand_headers[i].name, nandinfo)) {
> > -			hdr_nand = nand_headers[i].data;
> > -			break;
> > -		}
> > -	}
> > +	hdr_nand = mtk_nand_header_find(nandinfo);
> >  
> >  	/* parse device header offset */
> >  	if (hdr_offs && hdr_offs[0])
> > @@ -432,6 +219,8 @@ static int mtk_brom_parse_imagename(const char
> >  *imagename)
> >  		return -EINVAL;
> >  	}
> >  
> > +	hdr_nand_size = mtk_nand_header_size(hdr_nand);
> 
> This call has to be guarded and only happen in case of NAND or SNAND,
> otherwise we get segfault because of NULL pointer here in case of
> non-NAND boot media.

I'll fix this.

> 
> > +
> >  	return 0;
> >  }
> >  
> > @@ -468,7 +257,7 @@ static int mtk_image_vrec_header(struct
> >  image_tool_params *params,
> >  	}
> >  
> >  	if (hdr_media == BRLYT_TYPE_NAND || hdr_media ==
> > BRLYT_TYPE_SNAND)
> > -		tparams->header_size = 2 * le16_to_cpu(hdr_nand-
> > >pagesize);
> > +		tparams->header_size = hdr_nand_size;
> >  	else
> >  		tparams->header_size = sizeof(struct
> > gen_device_header);
> >  
> > @@ -566,16 +355,17 @@ static int mtk_image_verify_gen_header(const
> > uint8_t
> >  *ptr, int print)
> >  
> >  static int mtk_image_verify_nand_header(const uint8_t *ptr, int
> > print)
> >  {
> > -	union nand_boot_header *nh = (union nand_boot_header
> > *)ptr;
> >  	struct brom_layout_header *bh;
> > +	struct nand_header_info info;
> >  	struct gfh_header *gfh;
> >  	const char *bootmedia;
> > +	int ret;
> >  
> > -	if (strncmp(nh->version, NAND_BOOT_VERSION, sizeof(nh-
> > >version)) ||
> > -	    strcmp(nh->id, NAND_BOOT_ID))
> > -		return -1;
> > +	ret = mtk_nand_header_info(ptr, &info);
> > +	if (ret < 0)
> > +		return ret;
> >  
> > -	bh = (struct brom_layout_header *)(ptr + le16_to_cpu(nh-
> > >pagesize));
> > +	bh = (struct brom_layout_header *)(ptr + info.page_size);
> >  
> >  	if (strcmp(bh->name, BRLYT_NAME))
> >  		return -1;
> > @@ -586,34 +376,23 @@ static int mtk_image_verify_nand_header(const
> > uint8_t
> >  *ptr, int print)
> >  		if (le32_to_cpu(bh->type) == BRLYT_TYPE_NAND)
> >  			bootmedia = "Parallel NAND";
> >  		else if (le32_to_cpu(bh->type) ==
> > BRLYT_TYPE_SNAND)
> > -			bootmedia = "Serial NAND";
> > +			bootmedia = "Serial NAND (SNFI/AP)";
> >  		else
> >  			return -1;
> >  	}
> >  
> >  	if (print) {
> > -		printf("Boot Media: %s\n", bootmedia);
> > -
> > -		if (le32_to_cpu(bh->type) == BRLYT_TYPE_NAND) {
> > -			uint64_t capacity =
> > -				(uint64_t)le16_to_cpu(nh-
> > >numblocks) *
> > -				(uint64_t)le16_to_cpu(nh-
> > >pages_of_block) *
> > -				(uint64_t)le16_to_cpu(nh-
> > >pagesize) * 8;
> > -			printf("Capacity:     %dGb\n",
> > -			       (uint32_t)(capacity >> 30));
> > -		}
> > +		printf("Boot Media:   %s\n", bootmedia);
> >  
> > -		if (le16_to_cpu(nh->pagesize) >= 1024)
> > -			printf("Page Size:    %dKB\n",
> > -			       le16_to_cpu(nh->pagesize) >> 10);
> > +		if (info.page_size >= 1024)
> > +			printf("Page Size:    %dKB\n",
> > info.page_size >> 10);
> >  		else
> > -			printf("Page Size:    %dB\n",
> > -			       le16_to_cpu(nh->pagesize));
> > +			printf("Page Size:    %dB\n",
> > info.page_size);
> >  
> > -		printf("Spare Size:   %dB\n", le16_to_cpu(nh-
> > >oobsize));
> > +		printf("Spare Size:   %dB\n", info.spare_size);
> >  	}
> >  
> > -	gfh = (struct gfh_header *)(ptr + 2 * le16_to_cpu(nh-
> > >pagesize));
> > +	gfh = (struct gfh_header *)(ptr + info.gfh_offset);
> >  
> >  	return mtk_image_verify_gfh(gfh, GFH_FLASH_TYPE_NAND,
> > print);
> >  }
> > @@ -713,7 +492,7 @@ static int mtk_image_verify_header(unsigned
> > char *ptr,
> >  int image_size,
> >  	if (image_get_magic(hdr) == IH_MAGIC)
> >  		return mtk_image_verify_mt7621_header(ptr, 0);
> >  
> > -	if (!strcmp((char *)ptr, NAND_BOOT_NAME))
> > +	if (is_mtk_nand_header(ptr))
> >  		return mtk_image_verify_nand_header(ptr, 0);
> >  	else
> >  		return mtk_image_verify_gen_header(ptr, 0);
> > @@ -739,7 +518,7 @@ static void mtk_image_print_header(const void
> > *ptr)
> >  		return;
> >  	}
> >  
> > -	if (!strcmp((char *)ptr, NAND_BOOT_NAME))
> > +	if (is_mtk_nand_header(ptr))
> >  		mtk_image_verify_nand_header(ptr, 1);
> >  	else
> >  		mtk_image_verify_gen_header(ptr, 1);
> > @@ -870,36 +649,33 @@ static void mtk_image_set_gen_header(void
> > *ptr, off_t
> >  filesize,
> >  static void mtk_image_set_nand_header(void *ptr, off_t filesize,
> >  				      uint32_t loadaddr)
> >  {
> > -	union nand_boot_header *nh = (union nand_boot_header
> > *)ptr;
> >  	struct brom_layout_header *brlyt;
> >  	struct gfh_header *gfh;
> > -	uint32_t payload_pages;
> > -	int i;
> > +	uint32_t payload_pages, nand_page_size;
> >  
> > -	/* NAND device header, repeat 4 times */
> > -	for (i = 0; i < 4; i++)
> > -		memcpy(nh + i, hdr_nand, sizeof(union
> > nand_boot_header));
> > +	/* NAND header */
> > +	nand_page_size = mtk_nand_header_put(hdr_nand, ptr);
> >  
> > -	/* BRLYT header */
> > -	payload_pages = (filesize + le16_to_cpu(hdr_nand-
> > >pagesize) - 1) /
> > -			le16_to_cpu(hdr_nand->pagesize);
> > -	brlyt = (struct brom_layout_header *)
> > -		(ptr + le16_to_cpu(hdr_nand->pagesize));
> > -	put_brom_layout_header(brlyt, hdr_media);
> > -	brlyt->header_size = cpu_to_le32(2);
> > -	brlyt->total_size = cpu_to_le32(payload_pages);
> > -	brlyt->header_size_2 = brlyt->header_size;
> > -	brlyt->total_size_2 = brlyt->total_size;
> > -	brlyt->unused = cpu_to_le32(1);
> > +	if (nand_page_size) {
> > +		/* BRLYT header */
> > +		payload_pages = (filesize + nand_page_size - 1) /
> > +				nand_page_size;
> > +		brlyt = (struct brom_layout_header *)(ptr +
> > nand_page_size);
> > +		put_brom_layout_header(brlyt, hdr_media);
> > +		brlyt->header_size = cpu_to_le32(2);
> > +		brlyt->total_size = cpu_to_le32(payload_pages);
> > +		brlyt->header_size_2 = brlyt->header_size;
> > +		brlyt->total_size_2 = brlyt->total_size;
> > +		brlyt->unused = cpu_to_le32(1);
> > +	}
> >  
> >  	/* GFH header */
> > -	gfh = (struct gfh_header *)(ptr + 2 *
> > le16_to_cpu(hdr_nand->pagesize));
> > -	put_ghf_header(gfh, filesize, 2 * le16_to_cpu(hdr_nand-
> > >pagesize),
> > -		       loadaddr, GFH_FLASH_TYPE_NAND);
> > +	gfh = (struct gfh_header *)(ptr + hdr_nand_size);
> > +	put_ghf_header(gfh, filesize, hdr_nand_size, loadaddr,
> > +		       GFH_FLASH_TYPE_NAND);
> >  
> >  	/* Generate SHA256 hash */
> > -	put_hash((uint8_t *)gfh,
> > -		 filesize - 2 * le16_to_cpu(hdr_nand->pagesize) -
> > SHA256_SUM_LEN);
> > +	put_hash((uint8_t *)gfh, filesize - hdr_nand_size -
> > SHA256_SUM_LEN);
> >  }
> >  
> >  static void mtk_image_set_mt7621_header(void *ptr, off_t filesize,
> > diff --git a/tools/mtk_image.h b/tools/mtk_image.h
> > index d868545a33..fad9372100 100644
> > --- a/tools/mtk_image.h
> > +++ b/tools/mtk_image.h
> > @@ -26,31 +26,6 @@ union gen_boot_header {
> >  #define SF_BOOT_NAME		"SF_BOOT"
> >  #define SDMMC_BOOT_NAME		"SDMMC_BOOT"
> >  
> > -/* Header for NAND */
> > -union nand_boot_header {
> > -	struct {
> > -		char name[12];
> > -		char version[4];
> > -		char id[8];
> > -		uint16_t ioif;
> > -		uint16_t pagesize;
> > -		uint16_t addrcycles;
> > -		uint16_t oobsize;
> > -		uint16_t pages_of_block;
> > -		uint16_t numblocks;
> > -		uint16_t writesize_shift;
> > -		uint16_t erasesize_shift;
> > -		uint8_t dummy[60];
> > -		uint8_t ecc_parity[28];
> > -	};
> > -
> > -	uint8_t data[0x80];
> > -};
> > -
> > -#define NAND_BOOT_NAME		"BOOTLOADER!"
> > -#define NAND_BOOT_VERSION	"V006"
> > -#define NAND_BOOT_ID		"NFIINFO"
> > -
> >  /* BootROM layout header */
> >  struct brom_layout_header {
> >  	char name[8];
> > diff --git a/tools/mtk_nand_headers.c b/tools/mtk_nand_headers.c
> > new file mode 100644
> > index 0000000000..12f827c39f
> > --- /dev/null
> > +++ b/tools/mtk_nand_headers.c
> > @@ -0,0 +1,286 @@
> > +// SPDX-License-Identifier: GPL-2.0+
> > +/*
> > + * MediaTek BootROM NAND header definitions
> > + *
> > + * Copyright (C) 2022 MediaTek Inc.
> > + * Author: Weijie Gao <weijie.gao@mediatek.com>
> > + */
> > +
> > +#include <stdint.h>
> > +#include <string.h>
> > +#include "imagetool.h"
> > +#include "mtk_image.h"
> > +#include "mtk_nand_headers.h"
> > +
> > +/* NAND header for SPI-NAND with 2KB page + 64B spare */
> > +static const union nand_boot_header snand_hdr_2k_64_data = {
> > +	.data = {
> > +		0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
> > +		0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
> > +		0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
> > +		0x00, 0x00, 0x00, 0x08, 0x03, 0x00, 0x40, 0x00,
> > +		0x40, 0x00, 0x00, 0x08, 0x10, 0x00, 0x16, 0x00,
> > +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +		0x00, 0x00, 0x00, 0x00, 0x7B, 0xC4, 0x17, 0x9D,
> > +		0xCA, 0x42, 0x90, 0xD0, 0x98, 0xD0, 0xE0, 0xF7,
> > +		0xDB, 0xCD, 0x16, 0xF6, 0x03, 0x73, 0xD2, 0xB8,
> > +		0x93, 0xB2, 0x56, 0x5A, 0x84, 0x6E, 0x00, 0x00
> > +	}
> > +};
> > +
> > +/* NAND header for SPI-NAND with 2KB page + 120B/128B spare */
> > +static const union nand_boot_header snand_hdr_2k_128_data = {
> > +	.data = {
> > +		0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
> > +		0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
> > +		0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
> > +		0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x70, 0x00,
> > +		0x40, 0x00, 0x00, 0x08, 0x10, 0x00, 0x16, 0x00,
> > +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +		0x00, 0x00, 0x00, 0x00, 0x90, 0x28, 0xED, 0x13,
> > +		0x7F, 0x12, 0x22, 0xCD, 0x3D, 0x06, 0xF1, 0xB3,
> > +		0x6F, 0x2E, 0xD9, 0xA0, 0x9D, 0x7A, 0xBD, 0xD7,
> > +		0xB3, 0x28, 0x3C, 0x13, 0xDB, 0x4E, 0x00, 0x00
> > +	}
> > +};
> > +
> > +/* NAND header for SPI-NAND with 4KB page + 256B spare */
> > +static const union nand_boot_header snand_hdr_4k_256_data = {
> > +	.data = {
> > +		0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
> > +		0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
> > +		0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
> > +		0x00, 0x00, 0x00, 0x10, 0x05, 0x00, 0xE0, 0x00,
> > +		0x40, 0x00, 0x00, 0x08, 0x10, 0x00, 0x16, 0x00,
> > +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +		0x00, 0x00, 0x00, 0x00, 0x47, 0xED, 0x0E, 0xC3,
> > +		0x83, 0xBF, 0x41, 0xD2, 0x85, 0x21, 0x97, 0x57,
> > +		0xC4, 0x2E, 0x6B, 0x7A, 0x40, 0xE0, 0xCF, 0x8F,
> > +		0x37, 0xBD, 0x17, 0xB6, 0xC7, 0xFE, 0x00, 0x00
> > +	}
> > +};
> > +
> > +/* NAND header for Parallel NAND 1Gb with 2KB page + 64B spare */
> > +static const union nand_boot_header nand_hdr_1gb_2k_64_data = {
> > +	.data = {
> > +		0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
> > +		0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
> > +		0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
> > +		0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x40, 0x00,
> > +		0x40, 0x00, 0x00, 0x04, 0x0B, 0x00, 0x11, 0x00,
> > +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +		0x00, 0x00, 0x00, 0x00, 0x12, 0x28, 0x1C, 0x12,
> > +		0x8F, 0xFD, 0xF8, 0x32, 0x6F, 0x6D, 0xCF, 0x6C,
> > +		0xDA, 0x21, 0x70, 0x8C, 0xDA, 0x0A, 0x22, 0x82,
> > +		0xAA, 0x59, 0xFA, 0x7C, 0x42, 0x2D, 0x00, 0x00
> > +	}
> > +};
> > +
> > +/* NAND header for Parallel NAND 2Gb with 2KB page + 64B spare */
> > +static const union nand_boot_header nand_hdr_2gb_2k_64_data = {
> > +	.data = {
> > +		0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
> > +		0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
> > +		0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
> > +		0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x40, 0x00,
> > +		0x40, 0x00, 0x00, 0x08, 0x0B, 0x00, 0x11, 0x00,
> > +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +		0x00, 0x00, 0x00, 0x00, 0x20, 0x9C, 0x3D, 0x2D,
> > +		0x7B, 0x68, 0x63, 0x52, 0x2E, 0x04, 0x63, 0xF1,
> > +		0x35, 0x4E, 0x44, 0x3E, 0xF8, 0xAC, 0x9B, 0x95,
> > +		0xAB, 0xFE, 0xE4, 0xE1, 0xD5, 0xF9, 0x00, 0x00
> > +	}
> > +};
> > +
> > +/* NAND header for Parallel NAND 4Gb with 2KB page + 64B spare */
> > +static const union nand_boot_header nand_hdr_4gb_2k_64_data = {
> > +	.data = {
> > +		0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
> > +		0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
> > +		0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
> > +		0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x40, 0x00,
> > +		0x40, 0x00, 0x00, 0x10, 0x0B, 0x00, 0x11, 0x00,
> > +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +		0x00, 0x00, 0x00, 0x00, 0xE3, 0x0F, 0x86, 0x32,
> > +		0x68, 0x05, 0xD9, 0xC8, 0x13, 0xDF, 0xC5, 0x0B,
> > +		0x35, 0x3A, 0x68, 0xA5, 0x3C, 0x0C, 0x73, 0x87,
> > +		0x63, 0xB0, 0xBE, 0xCC, 0x84, 0x47, 0x00, 0x00
> > +	}
> > +};
> > +
> > +/* NAND header for Parallel NAND 2Gb with 2KB page + 128B spare */
> > +static const union nand_boot_header nand_hdr_2gb_2k_128_data = {
> > +	.data = {
> > +		0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
> > +		0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
> > +		0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
> > +		0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x70, 0x00,
> > +		0x40, 0x00, 0x00, 0x08, 0x0B, 0x00, 0x11, 0x00,
> > +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +		0x00, 0x00, 0x00, 0x00, 0x01, 0xA5, 0xE9, 0x5A,
> > +		0xDF, 0x58, 0x62, 0x41, 0xD6, 0x26, 0x77, 0xBC,
> > +		0x76, 0x1F, 0x27, 0x4E, 0x4F, 0x6C, 0xC3, 0xF0,
> > +		0x36, 0xDE, 0xD9, 0xB3, 0xFF, 0x93, 0x00, 0x00
> > +	}
> > +};
> > +
> > +/* NAND header for Parallel NAND 4Gb with 2KB page + 128B spare */
> > +static const union nand_boot_header nand_hdr_4gb_2k_128_data = {
> > +	.data = {
> > +		0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
> > +		0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
> > +		0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
> > +		0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x70, 0x00,
> > +		0x40, 0x00, 0x00, 0x10, 0x0B, 0x00, 0x11, 0x00,
> > +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +		0x00, 0x00, 0x00, 0x00, 0xC2, 0x36, 0x52, 0x45,
> > +		0xCC, 0x35, 0xD8, 0xDB, 0xEB, 0xFD, 0xD1, 0x46,
> > +		0x76, 0x6B, 0x0B, 0xD5, 0x8B, 0xCC, 0x2B, 0xE2,
> > +		0xFE, 0x90, 0x83, 0x9E, 0xAE, 0x2D, 0x00, 0x00
> > +	}
> > +};
> > +
> > +static const struct nand_header_type {
> > +	const char *name;
> > +	const union nand_boot_header *data;
> > +} nand_headers[] = {
> > +	{
> > +		.name = "2k+64",
> > +		.data = &snand_hdr_2k_64_data
> > +	}, {
> > +		.name = "2k+120",
> > +		.data = &snand_hdr_2k_128_data
> > +	}, {
> > +		.name = "2k+128",
> > +		.data = &snand_hdr_2k_128_data
> > +	}, {
> > +		.name = "4k+256",
> > +		.data = &snand_hdr_4k_256_data
> > +	}, {
> > +		.name = "1g:2k+64",
> > +		.data = &nand_hdr_1gb_2k_64_data
> > +	}, {
> > +		.name = "2g:2k+64",
> > +		.data = &nand_hdr_2gb_2k_64_data
> > +	}, {
> > +		.name = "4g:2k+64",
> > +		.data = &nand_hdr_4gb_2k_64_data
> > +	}, {
> > +		.name = "2g:2k+128",
> > +		.data = &nand_hdr_2gb_2k_128_data
> > +	}, {
> > +		.name = "4g:2k+128",
> > +		.data = &nand_hdr_4gb_2k_128_data
> > +	}
> > +};
> > +
> > +const union nand_boot_header *mtk_nand_header_find(const char
> > *name)
> > +{
> > +	uint32_t i;
> > +
> > +	for (i = 0; i < ARRAY_SIZE(nand_headers); i++) {
> > +		if (!strcmp(nand_headers[i].name, name))
> > +			return nand_headers[i].data;
> > +	}
> > +
> > +	return NULL;
> > +}
> > +
> > +uint32_t mtk_nand_header_size(const union nand_boot_header
> > *hdr_nand)
> > +{
> > +	return 2 * le16_to_cpu(hdr_nand->pagesize);
> > +}
> > +
> > +static int mtk_nand_header_ap_info(const void *ptr,
> > +				   struct nand_header_info *info)
> > +{
> > +	union nand_boot_header *nh = (union nand_boot_header
> > *)ptr;
> > +
> > +	if (strncmp(nh->version, NAND_BOOT_VERSION, sizeof(nh-
> > >version)) ||
> > +	    strcmp(nh->id, NAND_BOOT_ID))
> > +		return -1;
> > +
> > +	info->page_size = le16_to_cpu(nh->pagesize);
> > +	info->spare_size = le16_to_cpu(nh->oobsize);
> > +	info->gfh_offset = 2 * info->page_size;
> > +
> > +	return 0;
> > +}
> > +
> > +int mtk_nand_header_info(const void *ptr, struct nand_header_info
> > *info)
> > +{
> > +	if (!strcmp((char *)ptr, NAND_BOOT_NAME))
> > +		return mtk_nand_header_ap_info(ptr, info);
> > +
> > +	return -1;
> > +}
> > +
> > +bool is_mtk_nand_header(const void *ptr)
> > +{
> > +	struct nand_header_info info;
> > +
> > +	if (mtk_nand_header_info(ptr, &info) >= 0)
> > +		return true;
> > +
> > +	return false;
> > +}
> > +
> > +uint32_t mtk_nand_header_put(const union nand_boot_header
> > *hdr_nand, void
> >  *ptr)
> > +{
> > +	union nand_boot_header *nh = (union nand_boot_header
> > *)ptr;
> > +	int i;
> > +
> > +	/* NAND device header, repeat 4 times */
> > +	for (i = 0; i < 4; i++)
> > +		memcpy(nh + i, hdr_nand, sizeof(union
> > nand_boot_header));
> > +
> > +	return le16_to_cpu(hdr_nand->pagesize);
> > +}
> > diff --git a/tools/mtk_nand_headers.h b/tools/mtk_nand_headers.h
> > new file mode 100644
> > index 0000000000..691db85005
> > --- /dev/null
> > +++ b/tools/mtk_nand_headers.h
> > @@ -0,0 +1,52 @@
> > +/* SPDX-License-Identifier: GPL-2.0+ */
> > +/*
> > + * MediaTek BootROM NAND header definitions
> > + *
> > + * Copyright (C) 2022 MediaTek Inc.
> > + * Author: Weijie Gao <weijie.gao@mediatek.com>
> > + */
> > +
> > +#ifndef _MTK_NAND_HEADERS_H
> > +#define _MTK_NAND_HEADERS_H
> > +
> > +#include <stdint.h>
> > +#include <stdbool.h>
> > +
> > +struct nand_header_info {
> > +	uint32_t page_size;
> > +	uint32_t spare_size;
> > +	uint32_t gfh_offset;
> > +};
> > +
> > +/* AP BROM Header for NAND */
> > +union nand_boot_header {
> > +	struct {
> > +		char name[12];
> > +		char version[4];
> > +		char id[8];
> > +		uint16_t ioif;
> > +		uint16_t pagesize;
> > +		uint16_t addrcycles;
> > +		uint16_t oobsize;
> > +		uint16_t pages_of_block;
> > +		uint16_t numblocks;
> > +		uint16_t writesize_shift;
> > +		uint16_t erasesize_shift;
> > +		uint8_t dummy[60];
> > +		uint8_t ecc_parity[28];
> > +	};
> > +
> > +	uint8_t data[0x80];
> > +};
> > +
> > +#define NAND_BOOT_NAME		"BOOTLOADER!"
> > +#define NAND_BOOT_VERSION	"V006"
> > +#define NAND_BOOT_ID		"NFIINFO"
> > +
> > +const union nand_boot_header *mtk_nand_header_find(const char
> > *name);
> > +uint32_t mtk_nand_header_size(const union nand_boot_header
> > *hdr_nand);
> > +int mtk_nand_header_info(const void *ptr, struct nand_header_info
> > *info);
> > +bool is_mtk_nand_header(const void *ptr);
> > +uint32_t mtk_nand_header_put(const union nand_boot_header
> > *hdr_nand, void
> >  *ptr);
> > +
> > +#endif /* _MTK_NAND_HEADERS_H */
> > -- 
> > 2.17.1
> >
diff mbox series

Patch

diff --git a/tools/Makefile b/tools/Makefile
index 9f2339666a..4f27ed1ab1 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -147,6 +147,7 @@  dumpimage-mkimage-objs := aisimage.o \
 			gpimage.o \
 			gpimage-common.o \
 			mtk_image.o \
+			mtk_nand_headers.o \
 			$(ECDSA_OBJS-y) \
 			$(RSA_OBJS-y) \
 			$(AES_OBJS-y)
diff --git a/tools/mtk_image.c b/tools/mtk_image.c
index dcd6525f32..3701d1564a 100644
--- a/tools/mtk_image.c
+++ b/tools/mtk_image.c
@@ -12,216 +12,7 @@ 
 #include <u-boot/sha256.h>
 #include "imagetool.h"
 #include "mtk_image.h"
-
-/* NAND header for SPI-NAND with 2KB page + 64B spare */
-static const union nand_boot_header snand_hdr_2k_64_data = {
-	.data = {
-		0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
-		0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
-		0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
-		0x00, 0x00, 0x00, 0x08, 0x03, 0x00, 0x40, 0x00,
-		0x40, 0x00, 0x00, 0x08, 0x10, 0x00, 0x16, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x7B, 0xC4, 0x17, 0x9D,
-		0xCA, 0x42, 0x90, 0xD0, 0x98, 0xD0, 0xE0, 0xF7,
-		0xDB, 0xCD, 0x16, 0xF6, 0x03, 0x73, 0xD2, 0xB8,
-		0x93, 0xB2, 0x56, 0x5A, 0x84, 0x6E, 0x00, 0x00
-	}
-};
-
-/* NAND header for SPI-NAND with 2KB page + 120B/128B spare */
-static const union nand_boot_header snand_hdr_2k_128_data = {
-	.data = {
-		0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
-		0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
-		0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
-		0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x70, 0x00,
-		0x40, 0x00, 0x00, 0x08, 0x10, 0x00, 0x16, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x90, 0x28, 0xED, 0x13,
-		0x7F, 0x12, 0x22, 0xCD, 0x3D, 0x06, 0xF1, 0xB3,
-		0x6F, 0x2E, 0xD9, 0xA0, 0x9D, 0x7A, 0xBD, 0xD7,
-		0xB3, 0x28, 0x3C, 0x13, 0xDB, 0x4E, 0x00, 0x00
-	}
-};
-
-/* NAND header for SPI-NAND with 4KB page + 256B spare */
-static const union nand_boot_header snand_hdr_4k_256_data = {
-	.data = {
-		0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
-		0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
-		0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
-		0x00, 0x00, 0x00, 0x10, 0x05, 0x00, 0xE0, 0x00,
-		0x40, 0x00, 0x00, 0x08, 0x10, 0x00, 0x16, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x47, 0xED, 0x0E, 0xC3,
-		0x83, 0xBF, 0x41, 0xD2, 0x85, 0x21, 0x97, 0x57,
-		0xC4, 0x2E, 0x6B, 0x7A, 0x40, 0xE0, 0xCF, 0x8F,
-		0x37, 0xBD, 0x17, 0xB6, 0xC7, 0xFE, 0x00, 0x00
-	}
-};
-
-/* NAND header for Parallel NAND 1Gb with 2KB page + 64B spare */
-static const union nand_boot_header nand_hdr_1gb_2k_64_data = {
-	.data = {
-		0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
-		0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
-		0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
-		0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x40, 0x00,
-		0x40, 0x00, 0x00, 0x04, 0x0B, 0x00, 0x11, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x12, 0x28, 0x1C, 0x12,
-		0x8F, 0xFD, 0xF8, 0x32, 0x6F, 0x6D, 0xCF, 0x6C,
-		0xDA, 0x21, 0x70, 0x8C, 0xDA, 0x0A, 0x22, 0x82,
-		0xAA, 0x59, 0xFA, 0x7C, 0x42, 0x2D, 0x00, 0x00
-	}
-};
-
-/* NAND header for Parallel NAND 2Gb with 2KB page + 64B spare */
-static const union nand_boot_header nand_hdr_2gb_2k_64_data = {
-	.data = {
-		0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
-		0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
-		0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
-		0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x40, 0x00,
-		0x40, 0x00, 0x00, 0x08, 0x0B, 0x00, 0x11, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x20, 0x9C, 0x3D, 0x2D,
-		0x7B, 0x68, 0x63, 0x52, 0x2E, 0x04, 0x63, 0xF1,
-		0x35, 0x4E, 0x44, 0x3E, 0xF8, 0xAC, 0x9B, 0x95,
-		0xAB, 0xFE, 0xE4, 0xE1, 0xD5, 0xF9, 0x00, 0x00
-	}
-};
-
-/* NAND header for Parallel NAND 4Gb with 2KB page + 64B spare */
-static const union nand_boot_header nand_hdr_4gb_2k_64_data = {
-	.data = {
-		0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
-		0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
-		0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
-		0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x40, 0x00,
-		0x40, 0x00, 0x00, 0x10, 0x0B, 0x00, 0x11, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0xE3, 0x0F, 0x86, 0x32,
-		0x68, 0x05, 0xD9, 0xC8, 0x13, 0xDF, 0xC5, 0x0B,
-		0x35, 0x3A, 0x68, 0xA5, 0x3C, 0x0C, 0x73, 0x87,
-		0x63, 0xB0, 0xBE, 0xCC, 0x84, 0x47, 0x00, 0x00
-	}
-};
-
-/* NAND header for Parallel NAND 2Gb with 2KB page + 128B spare */
-static const union nand_boot_header nand_hdr_2gb_2k_128_data = {
-	.data = {
-		0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
-		0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
-		0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
-		0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x70, 0x00,
-		0x40, 0x00, 0x00, 0x08, 0x0B, 0x00, 0x11, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x01, 0xA5, 0xE9, 0x5A,
-		0xDF, 0x58, 0x62, 0x41, 0xD6, 0x26, 0x77, 0xBC,
-		0x76, 0x1F, 0x27, 0x4E, 0x4F, 0x6C, 0xC3, 0xF0,
-		0x36, 0xDE, 0xD9, 0xB3, 0xFF, 0x93, 0x00, 0x00
-	}
-};
-
-/* NAND header for Parallel NAND 4Gb with 2KB page + 128B spare */
-static const union nand_boot_header nand_hdr_4gb_2k_128_data = {
-	.data = {
-		0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
-		0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
-		0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
-		0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x70, 0x00,
-		0x40, 0x00, 0x00, 0x10, 0x0B, 0x00, 0x11, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0xC2, 0x36, 0x52, 0x45,
-		0xCC, 0x35, 0xD8, 0xDB, 0xEB, 0xFD, 0xD1, 0x46,
-		0x76, 0x6B, 0x0B, 0xD5, 0x8B, 0xCC, 0x2B, 0xE2,
-		0xFE, 0x90, 0x83, 0x9E, 0xAE, 0x2D, 0x00, 0x00
-	}
-};
-
-static const struct nand_header_type {
-	const char *name;
-	const union nand_boot_header *data;
-} nand_headers[] = {
-	{
-		.name = "2k+64",
-		.data = &snand_hdr_2k_64_data
-	}, {
-		.name = "2k+120",
-		.data = &snand_hdr_2k_128_data
-	}, {
-		.name = "2k+128",
-		.data = &snand_hdr_2k_128_data
-	}, {
-		.name = "4k+256",
-		.data = &snand_hdr_4k_256_data
-	}, {
-		.name = "1g:2k+64",
-		.data = &nand_hdr_1gb_2k_64_data
-	}, {
-		.name = "2g:2k+64",
-		.data = &nand_hdr_2gb_2k_64_data
-	}, {
-		.name = "4g:2k+64",
-		.data = &nand_hdr_4gb_2k_64_data
-	}, {
-		.name = "2g:2k+128",
-		.data = &nand_hdr_2gb_2k_128_data
-	}, {
-		.name = "4g:2k+128",
-		.data = &nand_hdr_4gb_2k_128_data
-	}
-};
+#include "mtk_nand_headers.h"
 
 static const struct brom_img_type {
 	const char *name;
@@ -264,6 +55,7 @@  static uint32_t crc32tbl[256];
 
 /* NAND header selected by user */
 static const union nand_boot_header *hdr_nand;
+static uint32_t hdr_nand_size;
 
 /* GFH header + 2 * 4KB pages of NAND */
 static char hdr_tmp[sizeof(struct gfh_header) + 0x2000];
@@ -402,12 +194,7 @@  static int mtk_brom_parse_imagename(const char
 *imagename)
 	}
 
 	/* parse nand header type */
-	for (i = 0; i < ARRAY_SIZE(nand_headers); i++) {
-		if (!strcmp(nand_headers[i].name, nandinfo)) {
-			hdr_nand = nand_headers[i].data;
-			break;
-		}
-	}
+	hdr_nand = mtk_nand_header_find(nandinfo);
 
 	/* parse device header offset */
 	if (hdr_offs && hdr_offs[0])
@@ -432,6 +219,8 @@  static int mtk_brom_parse_imagename(const char
 *imagename)
 		return -EINVAL;
 	}
 
+	hdr_nand_size = mtk_nand_header_size(hdr_nand);
+
 	return 0;
 }
 
@@ -468,7 +257,7 @@  static int mtk_image_vrec_header(struct
 image_tool_params *params,
 	}
 
 	if (hdr_media == BRLYT_TYPE_NAND || hdr_media == BRLYT_TYPE_SNAND)
-		tparams->header_size = 2 * le16_to_cpu(hdr_nand->pagesize);
+		tparams->header_size = hdr_nand_size;
 	else
 		tparams->header_size = sizeof(struct gen_device_header);
 
@@ -566,16 +355,17 @@  static int mtk_image_verify_gen_header(const uint8_t
 *ptr, int print)
 
 static int mtk_image_verify_nand_header(const uint8_t *ptr, int print)
 {
-	union nand_boot_header *nh = (union nand_boot_header *)ptr;
 	struct brom_layout_header *bh;
+	struct nand_header_info info;
 	struct gfh_header *gfh;
 	const char *bootmedia;
+	int ret;
 
-	if (strncmp(nh->version, NAND_BOOT_VERSION, sizeof(nh->version)) ||
-	    strcmp(nh->id, NAND_BOOT_ID))
-		return -1;
+	ret = mtk_nand_header_info(ptr, &info);
+	if (ret < 0)
+		return ret;
 
-	bh = (struct brom_layout_header *)(ptr + le16_to_cpu(nh->pagesize));
+	bh = (struct brom_layout_header *)(ptr + info.page_size);
 
 	if (strcmp(bh->name, BRLYT_NAME))
 		return -1;
@@ -586,34 +376,23 @@  static int mtk_image_verify_nand_header(const uint8_t
 *ptr, int print)
 		if (le32_to_cpu(bh->type) == BRLYT_TYPE_NAND)
 			bootmedia = "Parallel NAND";
 		else if (le32_to_cpu(bh->type) == BRLYT_TYPE_SNAND)
-			bootmedia = "Serial NAND";
+			bootmedia = "Serial NAND (SNFI/AP)";
 		else
 			return -1;
 	}
 
 	if (print) {
-		printf("Boot Media: %s\n", bootmedia);
-
-		if (le32_to_cpu(bh->type) == BRLYT_TYPE_NAND) {
-			uint64_t capacity =
-				(uint64_t)le16_to_cpu(nh->numblocks) *
-				(uint64_t)le16_to_cpu(nh->pages_of_block) *
-				(uint64_t)le16_to_cpu(nh->pagesize) * 8;
-			printf("Capacity:     %dGb\n",
-			       (uint32_t)(capacity >> 30));
-		}
+		printf("Boot Media:   %s\n", bootmedia);
 
-		if (le16_to_cpu(nh->pagesize) >= 1024)
-			printf("Page Size:    %dKB\n",
-			       le16_to_cpu(nh->pagesize) >> 10);
+		if (info.page_size >= 1024)
+			printf("Page Size:    %dKB\n", info.page_size >> 10);
 		else
-			printf("Page Size:    %dB\n",
-			       le16_to_cpu(nh->pagesize));
+			printf("Page Size:    %dB\n", info.page_size);
 
-		printf("Spare Size:   %dB\n", le16_to_cpu(nh->oobsize));
+		printf("Spare Size:   %dB\n", info.spare_size);
 	}
 
-	gfh = (struct gfh_header *)(ptr + 2 * le16_to_cpu(nh->pagesize));
+	gfh = (struct gfh_header *)(ptr + info.gfh_offset);
 
 	return mtk_image_verify_gfh(gfh, GFH_FLASH_TYPE_NAND, print);
 }
@@ -713,7 +492,7 @@  static int mtk_image_verify_header(unsigned char *ptr,
 int image_size,
 	if (image_get_magic(hdr) == IH_MAGIC)
 		return mtk_image_verify_mt7621_header(ptr, 0);
 
-	if (!strcmp((char *)ptr, NAND_BOOT_NAME))
+	if (is_mtk_nand_header(ptr))
 		return mtk_image_verify_nand_header(ptr, 0);
 	else
 		return mtk_image_verify_gen_header(ptr, 0);
@@ -739,7 +518,7 @@  static void mtk_image_print_header(const void *ptr)
 		return;
 	}
 
-	if (!strcmp((char *)ptr, NAND_BOOT_NAME))
+	if (is_mtk_nand_header(ptr))
 		mtk_image_verify_nand_header(ptr, 1);
 	else
 		mtk_image_verify_gen_header(ptr, 1);
@@ -870,36 +649,33 @@  static void mtk_image_set_gen_header(void *ptr, off_t
 filesize,
 static void mtk_image_set_nand_header(void *ptr, off_t filesize,
 				      uint32_t loadaddr)
 {
-	union nand_boot_header *nh = (union nand_boot_header *)ptr;
 	struct brom_layout_header *brlyt;
 	struct gfh_header *gfh;
-	uint32_t payload_pages;
-	int i;
+	uint32_t payload_pages, nand_page_size;
 
-	/* NAND device header, repeat 4 times */
-	for (i = 0; i < 4; i++)
-		memcpy(nh + i, hdr_nand, sizeof(union nand_boot_header));
+	/* NAND header */
+	nand_page_size = mtk_nand_header_put(hdr_nand, ptr);
 
-	/* BRLYT header */
-	payload_pages = (filesize + le16_to_cpu(hdr_nand->pagesize) - 1) /
-			le16_to_cpu(hdr_nand->pagesize);
-	brlyt = (struct brom_layout_header *)
-		(ptr + le16_to_cpu(hdr_nand->pagesize));
-	put_brom_layout_header(brlyt, hdr_media);
-	brlyt->header_size = cpu_to_le32(2);
-	brlyt->total_size = cpu_to_le32(payload_pages);
-	brlyt->header_size_2 = brlyt->header_size;
-	brlyt->total_size_2 = brlyt->total_size;
-	brlyt->unused = cpu_to_le32(1);
+	if (nand_page_size) {
+		/* BRLYT header */
+		payload_pages = (filesize + nand_page_size - 1) /
+				nand_page_size;
+		brlyt = (struct brom_layout_header *)(ptr + nand_page_size);
+		put_brom_layout_header(brlyt, hdr_media);
+		brlyt->header_size = cpu_to_le32(2);
+		brlyt->total_size = cpu_to_le32(payload_pages);
+		brlyt->header_size_2 = brlyt->header_size;
+		brlyt->total_size_2 = brlyt->total_size;
+		brlyt->unused = cpu_to_le32(1);
+	}
 
 	/* GFH header */
-	gfh = (struct gfh_header *)(ptr + 2 * le16_to_cpu(hdr_nand->pagesize));
-	put_ghf_header(gfh, filesize, 2 * le16_to_cpu(hdr_nand->pagesize),
-		       loadaddr, GFH_FLASH_TYPE_NAND);
+	gfh = (struct gfh_header *)(ptr + hdr_nand_size);
+	put_ghf_header(gfh, filesize, hdr_nand_size, loadaddr,
+		       GFH_FLASH_TYPE_NAND);
 
 	/* Generate SHA256 hash */
-	put_hash((uint8_t *)gfh,
-		 filesize - 2 * le16_to_cpu(hdr_nand->pagesize) - SHA256_SUM_LEN);
+	put_hash((uint8_t *)gfh, filesize - hdr_nand_size - SHA256_SUM_LEN);
 }
 
 static void mtk_image_set_mt7621_header(void *ptr, off_t filesize,
diff --git a/tools/mtk_image.h b/tools/mtk_image.h
index d868545a33..fad9372100 100644
--- a/tools/mtk_image.h
+++ b/tools/mtk_image.h
@@ -26,31 +26,6 @@  union gen_boot_header {
 #define SF_BOOT_NAME		"SF_BOOT"
 #define SDMMC_BOOT_NAME		"SDMMC_BOOT"
 
-/* Header for NAND */
-union nand_boot_header {
-	struct {
-		char name[12];
-		char version[4];
-		char id[8];
-		uint16_t ioif;
-		uint16_t pagesize;
-		uint16_t addrcycles;
-		uint16_t oobsize;
-		uint16_t pages_of_block;
-		uint16_t numblocks;
-		uint16_t writesize_shift;
-		uint16_t erasesize_shift;
-		uint8_t dummy[60];
-		uint8_t ecc_parity[28];
-	};
-
-	uint8_t data[0x80];
-};
-
-#define NAND_BOOT_NAME		"BOOTLOADER!"
-#define NAND_BOOT_VERSION	"V006"
-#define NAND_BOOT_ID		"NFIINFO"
-
 /* BootROM layout header */
 struct brom_layout_header {
 	char name[8];
diff --git a/tools/mtk_nand_headers.c b/tools/mtk_nand_headers.c
new file mode 100644
index 0000000000..12f827c39f
--- /dev/null
+++ b/tools/mtk_nand_headers.c
@@ -0,0 +1,286 @@ 
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * MediaTek BootROM NAND header definitions
+ *
+ * Copyright (C) 2022 MediaTek Inc.
+ * Author: Weijie Gao <weijie.gao@mediatek.com>
+ */
+
+#include <stdint.h>
+#include <string.h>
+#include "imagetool.h"
+#include "mtk_image.h"
+#include "mtk_nand_headers.h"
+
+/* NAND header for SPI-NAND with 2KB page + 64B spare */
+static const union nand_boot_header snand_hdr_2k_64_data = {
+	.data = {
+		0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
+		0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
+		0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
+		0x00, 0x00, 0x00, 0x08, 0x03, 0x00, 0x40, 0x00,
+		0x40, 0x00, 0x00, 0x08, 0x10, 0x00, 0x16, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x7B, 0xC4, 0x17, 0x9D,
+		0xCA, 0x42, 0x90, 0xD0, 0x98, 0xD0, 0xE0, 0xF7,
+		0xDB, 0xCD, 0x16, 0xF6, 0x03, 0x73, 0xD2, 0xB8,
+		0x93, 0xB2, 0x56, 0x5A, 0x84, 0x6E, 0x00, 0x00
+	}
+};
+
+/* NAND header for SPI-NAND with 2KB page + 120B/128B spare */
+static const union nand_boot_header snand_hdr_2k_128_data = {
+	.data = {
+		0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
+		0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
+		0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
+		0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x70, 0x00,
+		0x40, 0x00, 0x00, 0x08, 0x10, 0x00, 0x16, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x90, 0x28, 0xED, 0x13,
+		0x7F, 0x12, 0x22, 0xCD, 0x3D, 0x06, 0xF1, 0xB3,
+		0x6F, 0x2E, 0xD9, 0xA0, 0x9D, 0x7A, 0xBD, 0xD7,
+		0xB3, 0x28, 0x3C, 0x13, 0xDB, 0x4E, 0x00, 0x00
+	}
+};
+
+/* NAND header for SPI-NAND with 4KB page + 256B spare */
+static const union nand_boot_header snand_hdr_4k_256_data = {
+	.data = {
+		0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
+		0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
+		0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
+		0x00, 0x00, 0x00, 0x10, 0x05, 0x00, 0xE0, 0x00,
+		0x40, 0x00, 0x00, 0x08, 0x10, 0x00, 0x16, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x47, 0xED, 0x0E, 0xC3,
+		0x83, 0xBF, 0x41, 0xD2, 0x85, 0x21, 0x97, 0x57,
+		0xC4, 0x2E, 0x6B, 0x7A, 0x40, 0xE0, 0xCF, 0x8F,
+		0x37, 0xBD, 0x17, 0xB6, 0xC7, 0xFE, 0x00, 0x00
+	}
+};
+
+/* NAND header for Parallel NAND 1Gb with 2KB page + 64B spare */
+static const union nand_boot_header nand_hdr_1gb_2k_64_data = {
+	.data = {
+		0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
+		0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
+		0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
+		0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x40, 0x00,
+		0x40, 0x00, 0x00, 0x04, 0x0B, 0x00, 0x11, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x12, 0x28, 0x1C, 0x12,
+		0x8F, 0xFD, 0xF8, 0x32, 0x6F, 0x6D, 0xCF, 0x6C,
+		0xDA, 0x21, 0x70, 0x8C, 0xDA, 0x0A, 0x22, 0x82,
+		0xAA, 0x59, 0xFA, 0x7C, 0x42, 0x2D, 0x00, 0x00
+	}
+};
+
+/* NAND header for Parallel NAND 2Gb with 2KB page + 64B spare */
+static const union nand_boot_header nand_hdr_2gb_2k_64_data = {
+	.data = {
+		0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
+		0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
+		0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
+		0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x40, 0x00,
+		0x40, 0x00, 0x00, 0x08, 0x0B, 0x00, 0x11, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x20, 0x9C, 0x3D, 0x2D,
+		0x7B, 0x68, 0x63, 0x52, 0x2E, 0x04, 0x63, 0xF1,
+		0x35, 0x4E, 0x44, 0x3E, 0xF8, 0xAC, 0x9B, 0x95,
+		0xAB, 0xFE, 0xE4, 0xE1, 0xD5, 0xF9, 0x00, 0x00
+	}
+};
+
+/* NAND header for Parallel NAND 4Gb with 2KB page + 64B spare */
+static const union nand_boot_header nand_hdr_4gb_2k_64_data = {
+	.data = {
+		0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
+		0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
+		0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
+		0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x40, 0x00,
+		0x40, 0x00, 0x00, 0x10, 0x0B, 0x00, 0x11, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0xE3, 0x0F, 0x86, 0x32,
+		0x68, 0x05, 0xD9, 0xC8, 0x13, 0xDF, 0xC5, 0x0B,
+		0x35, 0x3A, 0x68, 0xA5, 0x3C, 0x0C, 0x73, 0x87,
+		0x63, 0xB0, 0xBE, 0xCC, 0x84, 0x47, 0x00, 0x00
+	}
+};
+
+/* NAND header for Parallel NAND 2Gb with 2KB page + 128B spare */
+static const union nand_boot_header nand_hdr_2gb_2k_128_data = {
+	.data = {
+		0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
+		0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
+		0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
+		0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x70, 0x00,
+		0x40, 0x00, 0x00, 0x08, 0x0B, 0x00, 0x11, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x01, 0xA5, 0xE9, 0x5A,
+		0xDF, 0x58, 0x62, 0x41, 0xD6, 0x26, 0x77, 0xBC,
+		0x76, 0x1F, 0x27, 0x4E, 0x4F, 0x6C, 0xC3, 0xF0,
+		0x36, 0xDE, 0xD9, 0xB3, 0xFF, 0x93, 0x00, 0x00
+	}
+};
+
+/* NAND header for Parallel NAND 4Gb with 2KB page + 128B spare */
+static const union nand_boot_header nand_hdr_4gb_2k_128_data = {
+	.data = {
+		0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
+		0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
+		0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
+		0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x70, 0x00,
+		0x40, 0x00, 0x00, 0x10, 0x0B, 0x00, 0x11, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0xC2, 0x36, 0x52, 0x45,
+		0xCC, 0x35, 0xD8, 0xDB, 0xEB, 0xFD, 0xD1, 0x46,
+		0x76, 0x6B, 0x0B, 0xD5, 0x8B, 0xCC, 0x2B, 0xE2,
+		0xFE, 0x90, 0x83, 0x9E, 0xAE, 0x2D, 0x00, 0x00
+	}
+};
+
+static const struct nand_header_type {
+	const char *name;
+	const union nand_boot_header *data;
+} nand_headers[] = {
+	{
+		.name = "2k+64",
+		.data = &snand_hdr_2k_64_data
+	}, {
+		.name = "2k+120",
+		.data = &snand_hdr_2k_128_data
+	}, {
+		.name = "2k+128",
+		.data = &snand_hdr_2k_128_data
+	}, {
+		.name = "4k+256",
+		.data = &snand_hdr_4k_256_data
+	}, {
+		.name = "1g:2k+64",
+		.data = &nand_hdr_1gb_2k_64_data
+	}, {
+		.name = "2g:2k+64",
+		.data = &nand_hdr_2gb_2k_64_data
+	}, {
+		.name = "4g:2k+64",
+		.data = &nand_hdr_4gb_2k_64_data
+	}, {
+		.name = "2g:2k+128",
+		.data = &nand_hdr_2gb_2k_128_data
+	}, {
+		.name = "4g:2k+128",
+		.data = &nand_hdr_4gb_2k_128_data
+	}
+};
+
+const union nand_boot_header *mtk_nand_header_find(const char *name)
+{
+	uint32_t i;
+
+	for (i = 0; i < ARRAY_SIZE(nand_headers); i++) {
+		if (!strcmp(nand_headers[i].name, name))
+			return nand_headers[i].data;
+	}
+
+	return NULL;
+}
+
+uint32_t mtk_nand_header_size(const union nand_boot_header *hdr_nand)
+{
+	return 2 * le16_to_cpu(hdr_nand->pagesize);
+}
+
+static int mtk_nand_header_ap_info(const void *ptr,
+				   struct nand_header_info *info)
+{
+	union nand_boot_header *nh = (union nand_boot_header *)ptr;
+
+	if (strncmp(nh->version, NAND_BOOT_VERSION, sizeof(nh->version)) ||
+	    strcmp(nh->id, NAND_BOOT_ID))
+		return -1;
+
+	info->page_size = le16_to_cpu(nh->pagesize);
+	info->spare_size = le16_to_cpu(nh->oobsize);
+	info->gfh_offset = 2 * info->page_size;
+
+	return 0;
+}
+
+int mtk_nand_header_info(const void *ptr, struct nand_header_info *info)
+{
+	if (!strcmp((char *)ptr, NAND_BOOT_NAME))
+		return mtk_nand_header_ap_info(ptr, info);
+
+	return -1;
+}
+
+bool is_mtk_nand_header(const void *ptr)
+{
+	struct nand_header_info info;
+
+	if (mtk_nand_header_info(ptr, &info) >= 0)
+		return true;
+
+	return false;
+}
+
+uint32_t mtk_nand_header_put(const union nand_boot_header *hdr_nand, void
 *ptr)
+{
+	union nand_boot_header *nh = (union nand_boot_header *)ptr;
+	int i;
+
+	/* NAND device header, repeat 4 times */
+	for (i = 0; i < 4; i++)
+		memcpy(nh + i, hdr_nand, sizeof(union nand_boot_header));
+
+	return le16_to_cpu(hdr_nand->pagesize);
+}
diff --git a/tools/mtk_nand_headers.h b/tools/mtk_nand_headers.h
new file mode 100644
index 0000000000..691db85005
--- /dev/null
+++ b/tools/mtk_nand_headers.h
@@ -0,0 +1,52 @@ 
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * MediaTek BootROM NAND header definitions
+ *
+ * Copyright (C) 2022 MediaTek Inc.
+ * Author: Weijie Gao <weijie.gao@mediatek.com>
+ */
+
+#ifndef _MTK_NAND_HEADERS_H
+#define _MTK_NAND_HEADERS_H
+
+#include <stdint.h>
+#include <stdbool.h>
+
+struct nand_header_info {
+	uint32_t page_size;
+	uint32_t spare_size;
+	uint32_t gfh_offset;
+};
+
+/* AP BROM Header for NAND */
+union nand_boot_header {
+	struct {
+		char name[12];
+		char version[4];
+		char id[8];
+		uint16_t ioif;
+		uint16_t pagesize;
+		uint16_t addrcycles;
+		uint16_t oobsize;
+		uint16_t pages_of_block;
+		uint16_t numblocks;
+		uint16_t writesize_shift;
+		uint16_t erasesize_shift;
+		uint8_t dummy[60];
+		uint8_t ecc_parity[28];
+	};
+
+	uint8_t data[0x80];
+};
+
+#define NAND_BOOT_NAME		"BOOTLOADER!"
+#define NAND_BOOT_VERSION	"V006"
+#define NAND_BOOT_ID		"NFIINFO"
+
+const union nand_boot_header *mtk_nand_header_find(const char *name);
+uint32_t mtk_nand_header_size(const union nand_boot_header *hdr_nand);
+int mtk_nand_header_info(const void *ptr, struct nand_header_info *info);
+bool is_mtk_nand_header(const void *ptr);
+uint32_t mtk_nand_header_put(const union nand_boot_header *hdr_nand, void
 *ptr);
+