Message ID | 20201016130850.706377-5-sr@denx.de |
---|---|
State | Superseded |
Delegated to: | Daniel Schwierzeck |
Headers | show |
Series | [1/5] mips: start.S: Add Octeon boot header compatibility | expand |
Am Freitag, den 16.10.2020, 15:08 +0200 schrieb Stefan Roese: > Add a tool to update or insert an Octeon specific header into the U-Boot > image. This is needed e.g. for booting via SPI NOR, eMMC and NAND. > > While working on this, move enum cvmx_board_types_enum and > cvmx_board_type_to_string() to cvmx-bootloader.h and remove the > unreferenced (unsupported) board definition. > > Signed-off-by: Stefan Roese <sr@denx.de> > Cc: Aaron Williams <awilliams@marvell.com> > Cc: Chandrakala Chavva <cchavva@marvell.com> > Cc: Daniel Schwierzeck <daniel.schwierzeck@gmail.com> > --- > .../mach-octeon/include/mach/cvmx-bootinfo.h | 222 --------- > .../include/mach/cvmx-bootloader.h | 172 +++++++ > tools/Makefile | 3 + > tools/update_octeon_header.c | 450 ++++++++++++++++++ > 4 files changed, 625 insertions(+), 222 deletions(-) > create mode 100644 arch/mips/mach-octeon/include/mach/cvmx-bootloader.h > create mode 100644 tools/update_octeon_header.c > > diff --git a/arch/mips/mach-octeon/include/mach/cvmx-bootinfo.h b/arch/mips/mach-octeon/include/mach/cvmx-bootinfo.h > index 337987178f..97438ff787 100644 > --- a/arch/mips/mach-octeon/include/mach/cvmx-bootinfo.h > +++ b/arch/mips/mach-octeon/include/mach/cvmx-bootinfo.h > @@ -125,226 +125,4 @@ struct cvmx_bootinfo { > > #endif /* (CVMX_BOOTINFO_MAJ_VER == 1) */ > > -/* Type defines for board and chip types */ > -enum cvmx_board_types_enum { > - CVMX_BOARD_TYPE_NULL = 0, > - CVMX_BOARD_TYPE_SIM = 1, > - CVMX_BOARD_TYPE_EBT3000 = 2, > - CVMX_BOARD_TYPE_KODAMA = 3, > - CVMX_BOARD_TYPE_NIAGARA = 4, > - CVMX_BOARD_TYPE_NAC38 = 5, /* formerly NAO38 */ > - CVMX_BOARD_TYPE_THUNDER = 6, > - CVMX_BOARD_TYPE_TRANTOR = 7, > - CVMX_BOARD_TYPE_EBH3000 = 8, > - CVMX_BOARD_TYPE_EBH3100 = 9, > - CVMX_BOARD_TYPE_HIKARI = 10, > - CVMX_BOARD_TYPE_CN3010_EVB_HS5 = 11, > - CVMX_BOARD_TYPE_CN3005_EVB_HS5 = 12, > - CVMX_BOARD_TYPE_KBP = 13, > - /* Deprecated, CVMX_BOARD_TYPE_CN3010_EVB_HS5 supports the CN3020 */ > - CVMX_BOARD_TYPE_CN3020_EVB_HS5 = 14, > - CVMX_BOARD_TYPE_EBT5800 = 15, > - CVMX_BOARD_TYPE_NICPRO2 = 16, > - CVMX_BOARD_TYPE_EBH5600 = 17, > - CVMX_BOARD_TYPE_EBH5601 = 18, > - CVMX_BOARD_TYPE_EBH5200 = 19, > - CVMX_BOARD_TYPE_BBGW_REF = 20, > - CVMX_BOARD_TYPE_NIC_XLE_4G = 21, > - CVMX_BOARD_TYPE_EBT5600 = 22, > - CVMX_BOARD_TYPE_EBH5201 = 23, > - CVMX_BOARD_TYPE_EBT5200 = 24, > - CVMX_BOARD_TYPE_CB5600 = 25, > - CVMX_BOARD_TYPE_CB5601 = 26, > - CVMX_BOARD_TYPE_CB5200 = 27, > - /* Special 'generic' board type, supports many boards */ > - CVMX_BOARD_TYPE_GENERIC = 28, > - CVMX_BOARD_TYPE_EBH5610 = 29, > - CVMX_BOARD_TYPE_LANAI2_A = 30, > - CVMX_BOARD_TYPE_LANAI2_U = 31, > - CVMX_BOARD_TYPE_EBB5600 = 32, > - CVMX_BOARD_TYPE_EBB6300 = 33, > - CVMX_BOARD_TYPE_NIC_XLE_10G = 34, > - CVMX_BOARD_TYPE_LANAI2_G = 35, > - CVMX_BOARD_TYPE_EBT5810 = 36, > - CVMX_BOARD_TYPE_NIC10E = 37, > - CVMX_BOARD_TYPE_EP6300C = 38, > - CVMX_BOARD_TYPE_EBB6800 = 39, > - CVMX_BOARD_TYPE_NIC4E = 40, > - CVMX_BOARD_TYPE_NIC2E = 41, > - CVMX_BOARD_TYPE_EBB6600 = 42, > - CVMX_BOARD_TYPE_REDWING = 43, > - CVMX_BOARD_TYPE_NIC68_4 = 44, > - CVMX_BOARD_TYPE_NIC10E_66 = 45, > - CVMX_BOARD_TYPE_MAX, > - > - /* > - * The range from CVMX_BOARD_TYPE_MAX to > - * CVMX_BOARD_TYPE_CUST_DEFINED_MIN is reserved for future > - * SDK use. > - */ > - > - /* > - * Set aside a range for customer boards. These numbers are managed > - * by Cavium. > - */ > - CVMX_BOARD_TYPE_CUST_DEFINED_MIN = 10000, > - CVMX_BOARD_TYPE_CUST_WSX16 = 10001, > - CVMX_BOARD_TYPE_CUST_NS0216 = 10002, > - CVMX_BOARD_TYPE_CUST_NB5 = 10003, > - CVMX_BOARD_TYPE_CUST_WMR500 = 10004, > - CVMX_BOARD_TYPE_CUST_ITB101 = 10005, > - CVMX_BOARD_TYPE_CUST_NTE102 = 10006, > - CVMX_BOARD_TYPE_CUST_AGS103 = 10007, > - CVMX_BOARD_TYPE_CUST_GST104 = 10008, > - CVMX_BOARD_TYPE_CUST_GCT105 = 10009, > - CVMX_BOARD_TYPE_CUST_AGS106 = 10010, > - CVMX_BOARD_TYPE_CUST_SGM107 = 10011, > - CVMX_BOARD_TYPE_CUST_GCT108 = 10012, > - CVMX_BOARD_TYPE_CUST_AGS109 = 10013, > - CVMX_BOARD_TYPE_CUST_GCT110 = 10014, > - CVMX_BOARD_TYPE_CUST_L2_AIR_SENDER = 10015, > - CVMX_BOARD_TYPE_CUST_L2_AIR_RECEIVER = 10016, > - CVMX_BOARD_TYPE_CUST_L2_ACCTON2_TX = 10017, > - CVMX_BOARD_TYPE_CUST_L2_ACCTON2_RX = 10018, > - CVMX_BOARD_TYPE_CUST_L2_WSTRNSNIC_TX = 10019, > - CVMX_BOARD_TYPE_CUST_L2_WSTRNSNIC_RX = 10020, > - CVMX_BOARD_TYPE_CUST_L2_ZINWELL = 10021, > - CVMX_BOARD_TYPE_CUST_DEFINED_MAX = 20000, > - > - /* > - * Set aside a range for customer private use. The SDK won't > - * use any numbers in this range. > - */ > - CVMX_BOARD_TYPE_CUST_PRIVATE_MIN = 20001, > - CVMX_BOARD_TYPE_UBNT_E100 = 20002, > - CVMX_BOARD_TYPE_CUST_DSR1000N = 20006, > - CVMX_BOARD_TYPE_KONTRON_S1901 = 21901, > - CVMX_BOARD_TYPE_CUST_PRIVATE_MAX = 30000, > - > - /* The remaining range is reserved for future use. */ > -}; > - > -enum cvmx_chip_types_enum { > - CVMX_CHIP_TYPE_NULL = 0, > - CVMX_CHIP_SIM_TYPE_DEPRECATED = 1, > - CVMX_CHIP_TYPE_OCTEON_SAMPLE = 2, > - CVMX_CHIP_TYPE_MAX, > -}; > - > -/* > - * Compatibility alias for NAC38 name change, planned to be removed > - * from SDK 1.7 > - */ > -#define CVMX_BOARD_TYPE_NAO38 CVMX_BOARD_TYPE_NAC38 > - > -/* Functions to return string based on type */ > -#define ENUM_BRD_TYPE_CASE(x) \ > - case x: \ > - return(#x + 16) /* Skip CVMX_BOARD_TYPE_ */ > - > -static inline const char *cvmx_board_type_to_string(enum > - cvmx_board_types_enum type) > -{ > - switch (type) { > - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_NULL); > - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_SIM); > - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_EBT3000); > - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_KODAMA); > - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_NIAGARA); > - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_NAC38); > - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_THUNDER); > - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_TRANTOR); > - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_EBH3000); > - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_EBH3100); > - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_HIKARI); > - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CN3010_EVB_HS5); > - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CN3005_EVB_HS5); > - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_KBP); > - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CN3020_EVB_HS5); > - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_EBT5800); > - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_NICPRO2); > - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_EBH5600); > - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_EBH5601); > - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_EBH5200); > - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_BBGW_REF); > - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_NIC_XLE_4G); > - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_EBT5600); > - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_EBH5201); > - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_EBT5200); > - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CB5600); > - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CB5601); > - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CB5200); > - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_GENERIC); > - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_EBH5610); > - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_LANAI2_A); > - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_LANAI2_U); > - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_EBB5600); > - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_EBB6300); > - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_NIC_XLE_10G); > - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_LANAI2_G); > - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_EBT5810); > - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_NIC10E); > - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_EP6300C); > - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_EBB6800); > - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_NIC4E); > - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_NIC2E); > - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_EBB6600); > - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_REDWING); > - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_NIC68_4); > - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_NIC10E_66); > - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_MAX); > - > - /* Customer boards listed here */ > - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_DEFINED_MIN); > - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_WSX16); > - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_NS0216); > - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_NB5); > - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_WMR500); > - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_ITB101); > - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_NTE102); > - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_AGS103); > - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_GST104); > - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_GCT105); > - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_AGS106); > - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_SGM107); > - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_GCT108); > - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_AGS109); > - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_GCT110); > - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_L2_AIR_SENDER); > - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_L2_AIR_RECEIVER); > - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_L2_ACCTON2_TX); > - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_L2_ACCTON2_RX); > - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_L2_WSTRNSNIC_TX); > - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_L2_WSTRNSNIC_RX); > - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_L2_ZINWELL); > - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_DEFINED_MAX); > - > - /* Customer private range */ > - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_PRIVATE_MIN); > - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_UBNT_E100); > - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_DSR1000N); > - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_KONTRON_S1901); > - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_PRIVATE_MAX); > - } > - > - return NULL; > -} > - > -#define ENUM_CHIP_TYPE_CASE(x) \ > - case x: \ > - return(#x + 15) /* Skip CVMX_CHIP_TYPE */ > - > -static inline const char *cvmx_chip_type_to_string(enum > - cvmx_chip_types_enum type) > -{ > - switch (type) { > - ENUM_CHIP_TYPE_CASE(CVMX_CHIP_TYPE_NULL); > - ENUM_CHIP_TYPE_CASE(CVMX_CHIP_SIM_TYPE_DEPRECATED); > - ENUM_CHIP_TYPE_CASE(CVMX_CHIP_TYPE_OCTEON_SAMPLE); > - ENUM_CHIP_TYPE_CASE(CVMX_CHIP_TYPE_MAX); > - } > - > - return "Unsupported Chip"; > -} > - > #endif /* __CVMX_BOOTINFO_H__ */ > diff --git a/arch/mips/mach-octeon/include/mach/cvmx-bootloader.h b/arch/mips/mach-octeon/include/mach/cvmx-bootloader.h > new file mode 100644 > index 0000000000..9abe021452 > --- /dev/null > +++ b/arch/mips/mach-octeon/include/mach/cvmx-bootloader.h > @@ -0,0 +1,172 @@ > +/* SPDX-License-Identifier: GPL-2.0 */ > +/* > + * Copyright (C) 2020 Marvell International Ltd. > + */ > + > +/* > + * Bootloader definitions that are shared with other programs > + */ > + > +#ifndef __CVMX_BOOTLOADER__ > +#define __CVMX_BOOTLOADER__ > + > +/* > + * The bootloader_header_t structure defines the header that is present > + * at the start of binary u-boot images. This header is used to locate > + * the bootloader image in NAND, and also to allow verification of images > + * for normal NOR booting. This structure is placed at the beginning of a > + * bootloader binary image, and remains in the executable code. > + */ > +#define BOOTLOADER_HEADER_MAGIC 0x424f4f54 /* "BOOT" in ASCII */ > + > +#define BOOTLOADER_HEADER_COMMENT_LEN 64 > +#define BOOTLOADER_HEADER_VERSION_LEN 64 > +/* limited by the space to the next exception handler */ > +#define BOOTLOADER_HEADER_MAX_SIZE 0x200 > + > +#define BOOTLOADER_HEADER_CURRENT_MAJOR_REV 1 > +#define BOOTLOADER_HEADER_CURRENT_MINOR_REV 2 > +/* > + * Revision history > + * 1.1 Initial released revision. (SDK 1.9) > + * 1.2 TLB based relocatable image (SDK 2.0) > + */ > + > +#ifndef __ASSEMBLY__ > +struct bootloader_header { > + uint32_t jump_instr; /* > + * Jump to executable code following the > + * header. This allows this header to be > + * (and remain) part of the executable image) > + */ > + uint32_t nop_instr; /* Must be 0x0 */ > + uint32_t magic; /* Magic number to identify header */ > + uint32_t hcrc; /* CRC of all of header excluding this field */ > + > + uint16_t hlen; /* Length of header in bytes */ > + uint16_t maj_rev; /* Major revision */ > + uint16_t min_rev; /* Minor revision */ > + uint16_t board_type; /* Board type that the image is for */ > + > + uint32_t dlen; /* Length of data (following header) in bytes */ > + uint32_t dcrc; /* CRC of data */ > + uint64_t address; /* Mips virtual address */ > + uint32_t flags; > + uint16_t image_type; /* Defined in bootloader_image_t enum */ > + uint16_t resv0; /* pad */ > + > + uint32_t reserved1; > + uint32_t reserved2; > + uint32_t reserved3; > + uint32_t reserved4; > + > + /* Optional, for descriptive purposes */ > + char comment_string[BOOTLOADER_HEADER_COMMENT_LEN]; > + /* Optional, for descriptive purposes */ > + char version_string[BOOTLOADER_HEADER_VERSION_LEN]; > +} __packed; > + > +/* Defines for flag field */ > +#define BL_HEADER_FLAG_FAILSAFE 1 > + > +enum bootloader_image { > + BL_HEADER_IMAGE_UNKNOWN = 0x0, > + BL_HEADER_IMAGE_STAGE2, /* Binary bootloader stage2 image */ > + BL_HEADER_IMAGE_STAGE3, /* Binary bootloader stage3 image */ > + BL_HEADER_IMAGE_NOR, /* Binary bootloader for NOR boot */ > + BL_HEADER_IMAGE_PCIBOOT, /* Binary bootloader for PCI boot */ > + BL_HEADER_IMAGE_UBOOT_ENV, /* Environment for u-boot */ > + /* Bootloader before U-Boot (stage 1/1.5) */ > + BL_HEADER_IMAGE_PRE_UBOOT, > + BL_HEADER_IMAGE_STAGE1, /* NOR stage 1 bootloader */ > + BL_HEADER_IMAGE_MAX, > + /* Range for customer private use. Will not be used by Cavium Inc. */ > + BL_HEADER_IMAGE_CUST_RESERVED_MIN = 0x1000, > + BL_HEADER_IMAGE_CUST_RESERVED_MAX = 0x1fff > +}; > + > +#endif /* __ASSEMBLY__ */ > + > +/* > + * Maximum address searched for NAND boot images and environments. > + * This is used by stage1 and stage2. > + */ > +#define MAX_NAND_SEARCH_ADDR 0x800000 > + > +/* Maximum address to look for start of normal bootloader */ > +#define MAX_NOR_SEARCH_ADDR 0x400000 > + > +/* > + * Defines for RAM based environment set by the host or the previous > + * bootloader in a chain boot configuration. > + */ > + > +#define U_BOOT_RAM_ENV_ADDR 0x1000 > +#define U_BOOT_RAM_ENV_SIZE 0x1000 > +#define U_BOOT_RAM_ENV_CRC_SIZE 0x4 > +#define U_BOOT_RAM_ENV_ADDR_2 (U_BOOT_RAM_ENV_ADDR + U_BOOT_RAM_ENV_SIZE) > +/* Address of environment in L2 cache if booted from cache */ > +#define U_BOOT_CACHE_ENV_ADDR 0x000ff000 > +/* Size of environment in L2 cache */ > +#define U_BOOT_CACHE_ENV_SIZE 0x1000 > + > +/* Board numbers and names */ > + > +/* Type defines for board and chip types */ > +enum cvmx_board_types_enum { > + CVMX_BOARD_TYPE_NULL = 0, > + CVMX_BOARD_TYPE_SIM = 1, > + /* Special 'generic' board type, supports many boards */ > + CVMX_BOARD_TYPE_GENERIC = 28, > + CVMX_BOARD_TYPE_EBB7304 = 76, > + CVMX_BOARD_TYPE_MAX, > + /* NOTE: 256-257 are being used by a customer. */ > + > + /* > + * The range from CVMX_BOARD_TYPE_MAX to > + * CVMX_BOARD_TYPE_CUST_DEFINED_MIN is reserved > + * for future SDK use. > + */ > + > + /* > + * Set aside a range for customer boards. These numbers are managed > + * by Cavium. > + */ > + CVMX_BOARD_TYPE_CUST_DEFINED_MIN = 10000, > + CVMX_BOARD_TYPE_CUST_DEFINED_MAX = 20000, > + > + /* > + * Set aside a range for customer private use. The SDK won't > + * use any numbers in this range. > + */ > + CVMX_BOARD_TYPE_CUST_PRIVATE_MIN = 20001, > + CVMX_BOARD_TYPE_CUST_PRIVATE_MAX = 30000, > +}; > + > +/* Functions to return string based on type */ > +/* Skip CVMX_BOARD_TYPE_ */ > +#define ENUM_BRD_TYPE_CASE(x) case x: return(#x + 16) > + > +static inline const char > +*cvmx_board_type_to_string(enum cvmx_board_types_enum type) > +{ > + switch (type) { > + ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_NULL); > + ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_SIM); > + ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_GENERIC); > + ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_EBB7304); > + ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_MAX); > + > + /* Customer boards listed here */ > + ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_DEFINED_MIN); > + ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_DEFINED_MAX); > + > + /* Customer private range */ > + ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_PRIVATE_MIN); > + ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_PRIVATE_MAX); > + } > + > + return "Unsupported Board"; > +} > + > +#endif /* __CVMX_BOOTLOADER__ */ > diff --git a/tools/Makefile b/tools/Makefile > index 51123fd929..253a6b9706 100644 > --- a/tools/Makefile > +++ b/tools/Makefile > @@ -206,6 +206,9 @@ hostprogs-y += proftool > hostprogs-$(CONFIG_STATIC_RELA) += relocate-rela > hostprogs-$(CONFIG_RISCV) += prelink-riscv > > +hostprogs-$(CONFIG_ARCH_OCTEON) += update_octeon_header > +update_octeon_header-objs := update_octeon_header.o lib/crc32.o > + > hostprogs-y += fdtgrep > fdtgrep-objs += $(LIBFDT_OBJS) common/fdt_region.o fdtgrep.o > > diff --git a/tools/update_octeon_header.c b/tools/update_octeon_header.c > new file mode 100644 > index 0000000000..964036216d > --- /dev/null > +++ b/tools/update_octeon_header.c > @@ -0,0 +1,450 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* > + * Copyright (C) 2020 Marvell International Ltd. > + */ > + > +#include <stdio.h> > +#include <stdint.h> > +#include <stddef.h> > +#include <sys/types.h> > +#include <sys/stat.h> > +#include <fcntl.h> > +#include <unistd.h> > +#include <stdlib.h> > +#include <string.h> > +#include <getopt.h> > +#include <arpa/inet.h> > + > +#include <u-boot/crc.h> > + > +#include "mkimage.h" > + > +#include "../arch/mips/mach-octeon/include/mach/cvmx-bootloader.h" have you tried with just "mach/cvmx-bootloader.h"? I'm afraid this breaks out-of-tree builds. > + > +void usage(void); > + > +/* > + * Do some funky stuff here to get a compile time error if the size of the > + * bootloader_header structure has changed. > + */ > +#define compile_time_assert(cond, msg) char msg[(cond) ? 1 : -1] > +compile_time_assert(sizeof(struct bootloader_header) == 192, > + bootloader_header_size_changed); > + > +#define BUF_SIZE (16 * 1024) > +#define NAME_LEN 100 > + > +#ifndef WOFFSETOF > +/* word offset */ > +#define WOFFSETOF(type, elem) (offsetof(type, elem) / 4) > +#endif > + > +#define cvmx_cpu_to_be64(x) (x) > + > +static int stage2_flag; > +static int stage_1_5_flag; > +static int stage_1_flag; > + > +int lookup_board_type(char *board_name) > +{ > + int i; > + int board_type = 0; > + char *substr = NULL; > + > + /* Detect stage 2 bootloader boards */ > + if (strcasestr(board_name, "_stage2")) { > + debug("Stage 2 bootloader detected from substring %s in name %s\n", > + "_stage2", board_name); > + stage2_flag = 1; > + } else { > + debug("Stage 2 bootloader NOT detected from name \"%s\"\n", > + board_name); > + } > + > + if (strcasestr(board_name, "_stage1")) { > + debug("Stage 1 bootloader detected from substring %s in name %s\n", > + "_stage1", board_name); > + stage_1_flag = 1; > + } > + > + /* Generic is a special case since there are numerous sub-types */ > + if (!strncasecmp("generic", board_name, strlen("generic"))) > + return CVMX_BOARD_TYPE_GENERIC; > + > + /* > + * If we're an eMMC stage 2 bootloader, cut off the _emmc_stage2 > + * part of the name. > + */ > + substr = strcasestr(board_name, "_emmc_stage2"); > + if (substr && (substr[strlen("_emmc_stage2")] == '\0')) { > + /*return CVMX_BOARD_TYPE_GENERIC;*/ > + > + printf(" Converting board name %s to ", board_name); > + *substr = '\0'; > + printf("%s\n", board_name); > + } > + > + /* > + * If we're a NAND stage 2 bootloader, cut off the _nand_stage2 > + * part of the name. > + */ > + substr = strcasestr(board_name, "_nand_stage2"); > + if (substr && (substr[strlen("_nand_stage2")] == '\0')) { > + /*return CVMX_BOARD_TYPE_GENERIC;*/ > + > + printf(" Converting board name %s to ", board_name); > + *substr = '\0'; > + printf("%s\n", board_name); > + } > + > + /* > + * If we're a SPI stage 2 bootloader, cut off the _spi_stage2 > + * part of the name. > + */ > + substr = strcasestr(board_name, "_spi_stage2"); > + if (substr && (substr[strlen("_spi_stage2")] == '\0')) { > + printf(" Converting board name %s to ", board_name); > + *substr = '\0'; > + printf("%s\n", board_name); > + } > + > + for (i = CVMX_BOARD_TYPE_NULL; i < CVMX_BOARD_TYPE_MAX; i++) > + if (!strcasecmp(cvmx_board_type_to_string(i), board_name)) > + board_type = i; > + > + for (i = CVMX_BOARD_TYPE_CUST_DEFINED_MIN; > + i < CVMX_BOARD_TYPE_CUST_DEFINED_MAX; i++) > + if (!strncasecmp(cvmx_board_type_to_string(i), board_name, > + strlen(cvmx_board_type_to_string(i)))) > + board_type = i; > + > + for (i = CVMX_BOARD_TYPE_CUST_PRIVATE_MIN; > + i < CVMX_BOARD_TYPE_CUST_PRIVATE_MAX; i++) > + if (!strncasecmp(cvmx_board_type_to_string(i), board_name, > + strlen(cvmx_board_type_to_string(i)))) > + board_type = i; > + > + return board_type; > +} > + > +/* Getoptions variables must be global */ > +static int failsafe_flag; > +static int pciboot_flag; > +static int env_flag; > + > +int main(int argc, char *argv[]) > +{ > + int fd; > + uint8_t buf[BUF_SIZE]; > + uint32_t data_crc = 0; > + int len; > + int data_len = 0; > + struct bootloader_header header; > + char filename[NAME_LEN]; > + int i; > + int option_index = 0; /* getopt_long stores the option index here. */ > + char board_name[NAME_LEN] = { 0 }; > + char tmp_board_name[NAME_LEN] = { 0 }; > + int c; > + int board_type = 0; > + unsigned long long address = 0; > + ssize_t ret; > + const char *type_str = NULL; > + int hdr_size = sizeof(struct bootloader_header); > + > + debug("header size is: %d bytes\n", hdr_size); > + > + /* Parse command line options using getopt_long */ > + while (1) { > + static struct option long_options[] = { > + /* These options set a flag. */ > + {"failsafe", no_argument, &failsafe_flag, 1}, > + {"pciboot", no_argument, &pciboot_flag, 1}, > + {"nandstage2", no_argument, &stage2_flag, 1}, > + {"spistage2", no_argument, &stage2_flag, 1}, > + {"norstage2", no_argument, &stage2_flag, 1}, > + {"stage2", no_argument, &stage2_flag, 1}, > + {"stage1.5", no_argument, &stage_1_5_flag, 1}, > + {"stage1", no_argument, &stage_1_flag, 1}, > + {"environment", no_argument, &env_flag, 1}, > + /* These options don't set a flag. > + * We distinguish them by their indices. > + */ > + {"board", required_argument, 0, 0}, > + {"text_base", required_argument, 0, 0}, > + {0, 0, 0, 0} > + }; > + > + c = getopt_long(argc, (char *const *)argv, "h", > + long_options, &option_index); > + > + /* Detect the end of the options. */ > + if (c == -1) > + break; > + > + switch (c) { > + /* All long options handled in case 0 */ > + case 0: > + /* If this option set a flag, do nothing else now. */ > + if (long_options[option_index].flag != 0) > + break; > + debug("option(l) %s", long_options[option_index].name); > + if (optarg) > + debug(" with arg %s", optarg); > + debug("\n"); > + > + if (!strcmp(long_options[option_index].name, "board")) { > + if (strlen(optarg) >= NAME_LEN) { > + printf("strncpy() issue detected!"); > + exit(-1); > + } > + strncpy(board_name, optarg, NAME_LEN); > + > + debug("Using user supplied board name: %s\n", > + board_name); > + } else if (!strcmp(long_options[option_index].name, > + "text_base")) { > + address = strtoull(optarg, NULL, 0); > + debug("Address of image is: 0x%llx\n", > + (unsigned long long)address); > + if (!(address & 0xFFFFFFFFULL << 32)) { > + if (address & 1 << 31) { > + address |= 0xFFFFFFFFULL << 32; > + debug("Converting address to 64 bit compatibility space: 0x%llx\n", > + address); > + } > + } > + } > + break; > + > + case 'h': > + case '?': > + /* getopt_long already printed an error message. */ > + usage(); > + return -1; > + > + default: > + abort(); > + } > + } > + > + if (optind < argc) { > + /* > + * We only support one argument - an optional bootloader > + * file name > + */ > + if (argc - optind > 2) { > + debug("non-option ARGV-elements: "); > + while (optind < argc) > + debug("%s ", argv[optind++]); > + debug("\n"); > + usage(); > + return -1; > + } > + } > + > + if (strlen(argv[optind]) >= NAME_LEN) { > + printf("strncpy() issue detected!"); > + exit(-1); > + } > + strncpy(filename, argv[optind], NAME_LEN); > + > + if (board_name[0] == '\0') { > + if (strlen(argv[optind + 1]) >= NAME_LEN) { > + printf("strncpy() issue detected!"); > + exit(-1); > + } > + strncpy(board_name, argv[optind + 1], NAME_LEN); > + } > + > + if (strlen(board_name) >= NAME_LEN) { > + printf("strncpy() issue detected!"); > + exit(-1); > + } > + strncpy(tmp_board_name, board_name, NAME_LEN); > + > + fd = open(filename, O_RDWR); > + if (fd < 0) { > + printf("Unable to open file: %s\n", filename); > + exit(-1); > + } > + > + if (failsafe_flag) > + debug("Setting failsafe flag\n"); > + > + if (strlen(board_name)) { > + int offset = 0; > + > + debug("Supplied board name of: %s\n", board_name); > + > + if (strstr(board_name, "failsafe")) { > + failsafe_flag = 1; > + debug("Setting failsafe flag based on board name\n"); > + } > + /* Skip leading octeon_ if present. */ > + if (!strncmp(board_name, "octeon_", 7)) > + offset = 7; > + > + /* > + * Check to see if 'failsafe' is in the name. If so, set the > + * failsafe flag. Also, ignore extra trailing characters on > + * passed parameter when comparing against board names. > + * We actually use the configuration name from u-boot, so it > + * may have some other variant names. Variants other than > + * failsafe _must_ be passed to this program explicitly > + */ > + > + board_type = lookup_board_type(board_name + offset); > + if (!board_type) { > + /* Retry with 'cust_' prefix to catch boards that are > + * in the customer section (such as nb5) > + */ > + sprintf(tmp_board_name, "cust_%s", board_name + offset); > + board_type = lookup_board_type(tmp_board_name); > + } > + > + /* reset to original value */ > + strncpy(tmp_board_name, board_name, NAME_LEN); > + if (!board_type) { > + /* > + * Retry with 'cust_private_' prefix to catch boards > + * that are in the customer private section > + */ > + sprintf(tmp_board_name, "cust_private_%s", > + board_name + offset); > + board_type = lookup_board_type(tmp_board_name); > + } > + > + if (!board_type) { > + printf("ERROR: unable to determine board type\n"); > + exit(-1); > + } > + debug("Board type is: %d: %s\n", board_type, > + cvmx_board_type_to_string(board_type)); > + } else { > + printf("Board name must be specified!\n"); > + exit(-1); > + } > + > + /* > + * Check to see if there is either an existing header, or that there > + * are zero valued bytes where we want to put the header > + */ > + len = read(fd, buf, BUF_SIZE); > + if (len > 0) { > + /* > + * Copy the header, as the first word (jump instruction, needs > + * to remain the same. > + */ > + memcpy(&header, buf, hdr_size); > + /* > + * Check to see if we have zero bytes (excluding first 4, which > + * are the jump instruction) > + */ > + for (i = 1; i < hdr_size / 4; i++) { > + if (((uint32_t *)buf)[i]) { > + printf("ERROR: non-zero word found %x in location %d required for header, aborting\n", > + ((uint32_t *)buf)[i], i); > + exit(-1); > + } > + } > + debug("Zero bytes found in header location, adding header.\n"); > + > + } else { > + printf("Unable to read from file %s\n", filename); > + exit(-1); > + } > + > + /* Read data bytes and generate CRC */ > + lseek(fd, hdr_size, SEEK_SET); > + > + while ((len = read(fd, buf, BUF_SIZE)) > 0) { > + data_crc = crc32(data_crc, buf, len); > + data_len += len; > + } > + printf("CRC of data: 0x%x, length: %d\n", data_crc, data_len); > + > + /* Now create the new header */ > + header.magic = htonl(BOOTLOADER_HEADER_MAGIC); > + header.maj_rev = htons(BOOTLOADER_HEADER_CURRENT_MAJOR_REV); > + header.min_rev = htons(BOOTLOADER_HEADER_CURRENT_MINOR_REV); > + header.dlen = htonl(data_len); > + header.dcrc = htonl(data_crc); > + header.board_type = htons(board_type); > + header.address = cvmx_cpu_to_be64(address); > + if (failsafe_flag) > + header.flags |= htonl(BL_HEADER_FLAG_FAILSAFE); > + > + debug("Stage 2 flag is %sset\n", stage2_flag ? "" : "not "); > + debug("Stage 1 flag is %sset\n", stage_1_flag ? "" : "not "); > + if (pciboot_flag) > + header.image_type = htons(BL_HEADER_IMAGE_PCIBOOT); > + else if (stage2_flag) > + header.image_type = htons(BL_HEADER_IMAGE_STAGE2); > + else if (stage_1_flag) > + header.image_type = htons(BL_HEADER_IMAGE_STAGE1); > + else if (env_flag) > + header.image_type = htons(BL_HEADER_IMAGE_UBOOT_ENV); > + else if (stage_1_5_flag || stage_1_flag) > + header.image_type = htons(BL_HEADER_IMAGE_PRE_UBOOT); > + else > + header.image_type = htons(BL_HEADER_IMAGE_NOR); > + > + switch (ntohs(header.image_type)) { > + case BL_HEADER_IMAGE_UNKNOWN: > + type_str = "Unknown"; > + break; > + case BL_HEADER_IMAGE_STAGE1: > + type_str = "Stage 1"; > + break; > + case BL_HEADER_IMAGE_STAGE2: > + type_str = "Stage 2"; > + break; > + case BL_HEADER_IMAGE_PRE_UBOOT: > + type_str = "Pre-U-Boot"; > + break; > + case BL_HEADER_IMAGE_STAGE3: > + type_str = "Stage 3"; > + break; > + case BL_HEADER_IMAGE_NOR: > + type_str = "NOR"; > + break; > + case BL_HEADER_IMAGE_PCIBOOT: > + type_str = "PCI Boot"; > + break; > + case BL_HEADER_IMAGE_UBOOT_ENV: > + type_str = "U-Boot Environment"; > + break; > + default: > + if (ntohs(header.image_type) >= BL_HEADER_IMAGE_CUST_RESERVED_MIN && > + ntohs(header.image_type) <= BL_HEADER_IMAGE_CUST_RESERVED_MAX) > + type_str = "Customer Reserved"; > + else > + type_str = "Unsupported"; > + } > + printf("Header image type: %s\n", type_str); > + header.hlen = htons(hdr_size); > + > + /* Now compute header CRC over all of the header excluding the CRC */ > + header.hcrc = crc32(0, (void *)&header, 12); > + header.hcrc = htonl(crc32(header.hcrc, ((void *)&(header)) + 16, > + hdr_size - 16)); > + > + /* Seek to beginning of file */ > + lseek(fd, 0, SEEK_SET); > + > + /* Write header to file */ > + ret = write(fd, &header, hdr_size); > + if (ret < 0) > + perror("write"); > + > + close(fd); > + > + printf("Header CRC: 0x%x\n", ntohl(header.hcrc)); > + return 0; > +} > + > +void usage(void) > +{ > + printf("Usage: update_octeon_header <filename> <board_name> [--failsafe] [--text_base=0xXXXXX]\n"); > +}
Hi Daniel, On 26.10.20 14:31, Daniel Schwierzeck wrote: <snip> >> diff --git a/tools/update_octeon_header.c b/tools/update_octeon_header.c >> new file mode 100644 >> index 0000000000..964036216d >> --- /dev/null >> +++ b/tools/update_octeon_header.c >> @@ -0,0 +1,450 @@ >> +// SPDX-License-Identifier: GPL-2.0 >> +/* >> + * Copyright (C) 2020 Marvell International Ltd. >> + */ >> + >> +#include <stdio.h> >> +#include <stdint.h> >> +#include <stddef.h> >> +#include <sys/types.h> >> +#include <sys/stat.h> >> +#include <fcntl.h> >> +#include <unistd.h> >> +#include <stdlib.h> >> +#include <string.h> >> +#include <getopt.h> >> +#include <arpa/inet.h> >> + >> +#include <u-boot/crc.h> >> + >> +#include "mkimage.h" >> + >> +#include "../arch/mips/mach-octeon/include/mach/cvmx-bootloader.h" > > have you tried with just "mach/cvmx-bootloader.h"? I'm afraid this > breaks out-of-tree builds. No, this does not work. I just started a full world build on Azure and had no build issue with these patches. So there does not seem to be such a OOT build issue AFAICT. BTW: tools/mksunxiboot.c also uses a similar header inclusion: #include "../arch/arm/include/asm/arch-sunxi/spl.h" Thanks, Stefan
diff --git a/arch/mips/mach-octeon/include/mach/cvmx-bootinfo.h b/arch/mips/mach-octeon/include/mach/cvmx-bootinfo.h index 337987178f..97438ff787 100644 --- a/arch/mips/mach-octeon/include/mach/cvmx-bootinfo.h +++ b/arch/mips/mach-octeon/include/mach/cvmx-bootinfo.h @@ -125,226 +125,4 @@ struct cvmx_bootinfo { #endif /* (CVMX_BOOTINFO_MAJ_VER == 1) */ -/* Type defines for board and chip types */ -enum cvmx_board_types_enum { - CVMX_BOARD_TYPE_NULL = 0, - CVMX_BOARD_TYPE_SIM = 1, - CVMX_BOARD_TYPE_EBT3000 = 2, - CVMX_BOARD_TYPE_KODAMA = 3, - CVMX_BOARD_TYPE_NIAGARA = 4, - CVMX_BOARD_TYPE_NAC38 = 5, /* formerly NAO38 */ - CVMX_BOARD_TYPE_THUNDER = 6, - CVMX_BOARD_TYPE_TRANTOR = 7, - CVMX_BOARD_TYPE_EBH3000 = 8, - CVMX_BOARD_TYPE_EBH3100 = 9, - CVMX_BOARD_TYPE_HIKARI = 10, - CVMX_BOARD_TYPE_CN3010_EVB_HS5 = 11, - CVMX_BOARD_TYPE_CN3005_EVB_HS5 = 12, - CVMX_BOARD_TYPE_KBP = 13, - /* Deprecated, CVMX_BOARD_TYPE_CN3010_EVB_HS5 supports the CN3020 */ - CVMX_BOARD_TYPE_CN3020_EVB_HS5 = 14, - CVMX_BOARD_TYPE_EBT5800 = 15, - CVMX_BOARD_TYPE_NICPRO2 = 16, - CVMX_BOARD_TYPE_EBH5600 = 17, - CVMX_BOARD_TYPE_EBH5601 = 18, - CVMX_BOARD_TYPE_EBH5200 = 19, - CVMX_BOARD_TYPE_BBGW_REF = 20, - CVMX_BOARD_TYPE_NIC_XLE_4G = 21, - CVMX_BOARD_TYPE_EBT5600 = 22, - CVMX_BOARD_TYPE_EBH5201 = 23, - CVMX_BOARD_TYPE_EBT5200 = 24, - CVMX_BOARD_TYPE_CB5600 = 25, - CVMX_BOARD_TYPE_CB5601 = 26, - CVMX_BOARD_TYPE_CB5200 = 27, - /* Special 'generic' board type, supports many boards */ - CVMX_BOARD_TYPE_GENERIC = 28, - CVMX_BOARD_TYPE_EBH5610 = 29, - CVMX_BOARD_TYPE_LANAI2_A = 30, - CVMX_BOARD_TYPE_LANAI2_U = 31, - CVMX_BOARD_TYPE_EBB5600 = 32, - CVMX_BOARD_TYPE_EBB6300 = 33, - CVMX_BOARD_TYPE_NIC_XLE_10G = 34, - CVMX_BOARD_TYPE_LANAI2_G = 35, - CVMX_BOARD_TYPE_EBT5810 = 36, - CVMX_BOARD_TYPE_NIC10E = 37, - CVMX_BOARD_TYPE_EP6300C = 38, - CVMX_BOARD_TYPE_EBB6800 = 39, - CVMX_BOARD_TYPE_NIC4E = 40, - CVMX_BOARD_TYPE_NIC2E = 41, - CVMX_BOARD_TYPE_EBB6600 = 42, - CVMX_BOARD_TYPE_REDWING = 43, - CVMX_BOARD_TYPE_NIC68_4 = 44, - CVMX_BOARD_TYPE_NIC10E_66 = 45, - CVMX_BOARD_TYPE_MAX, - - /* - * The range from CVMX_BOARD_TYPE_MAX to - * CVMX_BOARD_TYPE_CUST_DEFINED_MIN is reserved for future - * SDK use. - */ - - /* - * Set aside a range for customer boards. These numbers are managed - * by Cavium. - */ - CVMX_BOARD_TYPE_CUST_DEFINED_MIN = 10000, - CVMX_BOARD_TYPE_CUST_WSX16 = 10001, - CVMX_BOARD_TYPE_CUST_NS0216 = 10002, - CVMX_BOARD_TYPE_CUST_NB5 = 10003, - CVMX_BOARD_TYPE_CUST_WMR500 = 10004, - CVMX_BOARD_TYPE_CUST_ITB101 = 10005, - CVMX_BOARD_TYPE_CUST_NTE102 = 10006, - CVMX_BOARD_TYPE_CUST_AGS103 = 10007, - CVMX_BOARD_TYPE_CUST_GST104 = 10008, - CVMX_BOARD_TYPE_CUST_GCT105 = 10009, - CVMX_BOARD_TYPE_CUST_AGS106 = 10010, - CVMX_BOARD_TYPE_CUST_SGM107 = 10011, - CVMX_BOARD_TYPE_CUST_GCT108 = 10012, - CVMX_BOARD_TYPE_CUST_AGS109 = 10013, - CVMX_BOARD_TYPE_CUST_GCT110 = 10014, - CVMX_BOARD_TYPE_CUST_L2_AIR_SENDER = 10015, - CVMX_BOARD_TYPE_CUST_L2_AIR_RECEIVER = 10016, - CVMX_BOARD_TYPE_CUST_L2_ACCTON2_TX = 10017, - CVMX_BOARD_TYPE_CUST_L2_ACCTON2_RX = 10018, - CVMX_BOARD_TYPE_CUST_L2_WSTRNSNIC_TX = 10019, - CVMX_BOARD_TYPE_CUST_L2_WSTRNSNIC_RX = 10020, - CVMX_BOARD_TYPE_CUST_L2_ZINWELL = 10021, - CVMX_BOARD_TYPE_CUST_DEFINED_MAX = 20000, - - /* - * Set aside a range for customer private use. The SDK won't - * use any numbers in this range. - */ - CVMX_BOARD_TYPE_CUST_PRIVATE_MIN = 20001, - CVMX_BOARD_TYPE_UBNT_E100 = 20002, - CVMX_BOARD_TYPE_CUST_DSR1000N = 20006, - CVMX_BOARD_TYPE_KONTRON_S1901 = 21901, - CVMX_BOARD_TYPE_CUST_PRIVATE_MAX = 30000, - - /* The remaining range is reserved for future use. */ -}; - -enum cvmx_chip_types_enum { - CVMX_CHIP_TYPE_NULL = 0, - CVMX_CHIP_SIM_TYPE_DEPRECATED = 1, - CVMX_CHIP_TYPE_OCTEON_SAMPLE = 2, - CVMX_CHIP_TYPE_MAX, -}; - -/* - * Compatibility alias for NAC38 name change, planned to be removed - * from SDK 1.7 - */ -#define CVMX_BOARD_TYPE_NAO38 CVMX_BOARD_TYPE_NAC38 - -/* Functions to return string based on type */ -#define ENUM_BRD_TYPE_CASE(x) \ - case x: \ - return(#x + 16) /* Skip CVMX_BOARD_TYPE_ */ - -static inline const char *cvmx_board_type_to_string(enum - cvmx_board_types_enum type) -{ - switch (type) { - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_NULL); - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_SIM); - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_EBT3000); - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_KODAMA); - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_NIAGARA); - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_NAC38); - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_THUNDER); - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_TRANTOR); - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_EBH3000); - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_EBH3100); - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_HIKARI); - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CN3010_EVB_HS5); - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CN3005_EVB_HS5); - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_KBP); - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CN3020_EVB_HS5); - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_EBT5800); - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_NICPRO2); - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_EBH5600); - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_EBH5601); - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_EBH5200); - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_BBGW_REF); - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_NIC_XLE_4G); - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_EBT5600); - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_EBH5201); - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_EBT5200); - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CB5600); - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CB5601); - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CB5200); - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_GENERIC); - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_EBH5610); - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_LANAI2_A); - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_LANAI2_U); - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_EBB5600); - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_EBB6300); - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_NIC_XLE_10G); - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_LANAI2_G); - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_EBT5810); - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_NIC10E); - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_EP6300C); - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_EBB6800); - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_NIC4E); - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_NIC2E); - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_EBB6600); - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_REDWING); - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_NIC68_4); - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_NIC10E_66); - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_MAX); - - /* Customer boards listed here */ - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_DEFINED_MIN); - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_WSX16); - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_NS0216); - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_NB5); - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_WMR500); - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_ITB101); - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_NTE102); - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_AGS103); - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_GST104); - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_GCT105); - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_AGS106); - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_SGM107); - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_GCT108); - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_AGS109); - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_GCT110); - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_L2_AIR_SENDER); - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_L2_AIR_RECEIVER); - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_L2_ACCTON2_TX); - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_L2_ACCTON2_RX); - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_L2_WSTRNSNIC_TX); - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_L2_WSTRNSNIC_RX); - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_L2_ZINWELL); - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_DEFINED_MAX); - - /* Customer private range */ - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_PRIVATE_MIN); - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_UBNT_E100); - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_DSR1000N); - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_KONTRON_S1901); - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_PRIVATE_MAX); - } - - return NULL; -} - -#define ENUM_CHIP_TYPE_CASE(x) \ - case x: \ - return(#x + 15) /* Skip CVMX_CHIP_TYPE */ - -static inline const char *cvmx_chip_type_to_string(enum - cvmx_chip_types_enum type) -{ - switch (type) { - ENUM_CHIP_TYPE_CASE(CVMX_CHIP_TYPE_NULL); - ENUM_CHIP_TYPE_CASE(CVMX_CHIP_SIM_TYPE_DEPRECATED); - ENUM_CHIP_TYPE_CASE(CVMX_CHIP_TYPE_OCTEON_SAMPLE); - ENUM_CHIP_TYPE_CASE(CVMX_CHIP_TYPE_MAX); - } - - return "Unsupported Chip"; -} - #endif /* __CVMX_BOOTINFO_H__ */ diff --git a/arch/mips/mach-octeon/include/mach/cvmx-bootloader.h b/arch/mips/mach-octeon/include/mach/cvmx-bootloader.h new file mode 100644 index 0000000000..9abe021452 --- /dev/null +++ b/arch/mips/mach-octeon/include/mach/cvmx-bootloader.h @@ -0,0 +1,172 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2020 Marvell International Ltd. + */ + +/* + * Bootloader definitions that are shared with other programs + */ + +#ifndef __CVMX_BOOTLOADER__ +#define __CVMX_BOOTLOADER__ + +/* + * The bootloader_header_t structure defines the header that is present + * at the start of binary u-boot images. This header is used to locate + * the bootloader image in NAND, and also to allow verification of images + * for normal NOR booting. This structure is placed at the beginning of a + * bootloader binary image, and remains in the executable code. + */ +#define BOOTLOADER_HEADER_MAGIC 0x424f4f54 /* "BOOT" in ASCII */ + +#define BOOTLOADER_HEADER_COMMENT_LEN 64 +#define BOOTLOADER_HEADER_VERSION_LEN 64 +/* limited by the space to the next exception handler */ +#define BOOTLOADER_HEADER_MAX_SIZE 0x200 + +#define BOOTLOADER_HEADER_CURRENT_MAJOR_REV 1 +#define BOOTLOADER_HEADER_CURRENT_MINOR_REV 2 +/* + * Revision history + * 1.1 Initial released revision. (SDK 1.9) + * 1.2 TLB based relocatable image (SDK 2.0) + */ + +#ifndef __ASSEMBLY__ +struct bootloader_header { + uint32_t jump_instr; /* + * Jump to executable code following the + * header. This allows this header to be + * (and remain) part of the executable image) + */ + uint32_t nop_instr; /* Must be 0x0 */ + uint32_t magic; /* Magic number to identify header */ + uint32_t hcrc; /* CRC of all of header excluding this field */ + + uint16_t hlen; /* Length of header in bytes */ + uint16_t maj_rev; /* Major revision */ + uint16_t min_rev; /* Minor revision */ + uint16_t board_type; /* Board type that the image is for */ + + uint32_t dlen; /* Length of data (following header) in bytes */ + uint32_t dcrc; /* CRC of data */ + uint64_t address; /* Mips virtual address */ + uint32_t flags; + uint16_t image_type; /* Defined in bootloader_image_t enum */ + uint16_t resv0; /* pad */ + + uint32_t reserved1; + uint32_t reserved2; + uint32_t reserved3; + uint32_t reserved4; + + /* Optional, for descriptive purposes */ + char comment_string[BOOTLOADER_HEADER_COMMENT_LEN]; + /* Optional, for descriptive purposes */ + char version_string[BOOTLOADER_HEADER_VERSION_LEN]; +} __packed; + +/* Defines for flag field */ +#define BL_HEADER_FLAG_FAILSAFE 1 + +enum bootloader_image { + BL_HEADER_IMAGE_UNKNOWN = 0x0, + BL_HEADER_IMAGE_STAGE2, /* Binary bootloader stage2 image */ + BL_HEADER_IMAGE_STAGE3, /* Binary bootloader stage3 image */ + BL_HEADER_IMAGE_NOR, /* Binary bootloader for NOR boot */ + BL_HEADER_IMAGE_PCIBOOT, /* Binary bootloader for PCI boot */ + BL_HEADER_IMAGE_UBOOT_ENV, /* Environment for u-boot */ + /* Bootloader before U-Boot (stage 1/1.5) */ + BL_HEADER_IMAGE_PRE_UBOOT, + BL_HEADER_IMAGE_STAGE1, /* NOR stage 1 bootloader */ + BL_HEADER_IMAGE_MAX, + /* Range for customer private use. Will not be used by Cavium Inc. */ + BL_HEADER_IMAGE_CUST_RESERVED_MIN = 0x1000, + BL_HEADER_IMAGE_CUST_RESERVED_MAX = 0x1fff +}; + +#endif /* __ASSEMBLY__ */ + +/* + * Maximum address searched for NAND boot images and environments. + * This is used by stage1 and stage2. + */ +#define MAX_NAND_SEARCH_ADDR 0x800000 + +/* Maximum address to look for start of normal bootloader */ +#define MAX_NOR_SEARCH_ADDR 0x400000 + +/* + * Defines for RAM based environment set by the host or the previous + * bootloader in a chain boot configuration. + */ + +#define U_BOOT_RAM_ENV_ADDR 0x1000 +#define U_BOOT_RAM_ENV_SIZE 0x1000 +#define U_BOOT_RAM_ENV_CRC_SIZE 0x4 +#define U_BOOT_RAM_ENV_ADDR_2 (U_BOOT_RAM_ENV_ADDR + U_BOOT_RAM_ENV_SIZE) +/* Address of environment in L2 cache if booted from cache */ +#define U_BOOT_CACHE_ENV_ADDR 0x000ff000 +/* Size of environment in L2 cache */ +#define U_BOOT_CACHE_ENV_SIZE 0x1000 + +/* Board numbers and names */ + +/* Type defines for board and chip types */ +enum cvmx_board_types_enum { + CVMX_BOARD_TYPE_NULL = 0, + CVMX_BOARD_TYPE_SIM = 1, + /* Special 'generic' board type, supports many boards */ + CVMX_BOARD_TYPE_GENERIC = 28, + CVMX_BOARD_TYPE_EBB7304 = 76, + CVMX_BOARD_TYPE_MAX, + /* NOTE: 256-257 are being used by a customer. */ + + /* + * The range from CVMX_BOARD_TYPE_MAX to + * CVMX_BOARD_TYPE_CUST_DEFINED_MIN is reserved + * for future SDK use. + */ + + /* + * Set aside a range for customer boards. These numbers are managed + * by Cavium. + */ + CVMX_BOARD_TYPE_CUST_DEFINED_MIN = 10000, + CVMX_BOARD_TYPE_CUST_DEFINED_MAX = 20000, + + /* + * Set aside a range for customer private use. The SDK won't + * use any numbers in this range. + */ + CVMX_BOARD_TYPE_CUST_PRIVATE_MIN = 20001, + CVMX_BOARD_TYPE_CUST_PRIVATE_MAX = 30000, +}; + +/* Functions to return string based on type */ +/* Skip CVMX_BOARD_TYPE_ */ +#define ENUM_BRD_TYPE_CASE(x) case x: return(#x + 16) + +static inline const char +*cvmx_board_type_to_string(enum cvmx_board_types_enum type) +{ + switch (type) { + ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_NULL); + ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_SIM); + ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_GENERIC); + ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_EBB7304); + ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_MAX); + + /* Customer boards listed here */ + ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_DEFINED_MIN); + ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_DEFINED_MAX); + + /* Customer private range */ + ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_PRIVATE_MIN); + ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_PRIVATE_MAX); + } + + return "Unsupported Board"; +} + +#endif /* __CVMX_BOOTLOADER__ */ diff --git a/tools/Makefile b/tools/Makefile index 51123fd929..253a6b9706 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -206,6 +206,9 @@ hostprogs-y += proftool hostprogs-$(CONFIG_STATIC_RELA) += relocate-rela hostprogs-$(CONFIG_RISCV) += prelink-riscv +hostprogs-$(CONFIG_ARCH_OCTEON) += update_octeon_header +update_octeon_header-objs := update_octeon_header.o lib/crc32.o + hostprogs-y += fdtgrep fdtgrep-objs += $(LIBFDT_OBJS) common/fdt_region.o fdtgrep.o diff --git a/tools/update_octeon_header.c b/tools/update_octeon_header.c new file mode 100644 index 0000000000..964036216d --- /dev/null +++ b/tools/update_octeon_header.c @@ -0,0 +1,450 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2020 Marvell International Ltd. + */ + +#include <stdio.h> +#include <stdint.h> +#include <stddef.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> +#include <stdlib.h> +#include <string.h> +#include <getopt.h> +#include <arpa/inet.h> + +#include <u-boot/crc.h> + +#include "mkimage.h" + +#include "../arch/mips/mach-octeon/include/mach/cvmx-bootloader.h" + +void usage(void); + +/* + * Do some funky stuff here to get a compile time error if the size of the + * bootloader_header structure has changed. + */ +#define compile_time_assert(cond, msg) char msg[(cond) ? 1 : -1] +compile_time_assert(sizeof(struct bootloader_header) == 192, + bootloader_header_size_changed); + +#define BUF_SIZE (16 * 1024) +#define NAME_LEN 100 + +#ifndef WOFFSETOF +/* word offset */ +#define WOFFSETOF(type, elem) (offsetof(type, elem) / 4) +#endif + +#define cvmx_cpu_to_be64(x) (x) + +static int stage2_flag; +static int stage_1_5_flag; +static int stage_1_flag; + +int lookup_board_type(char *board_name) +{ + int i; + int board_type = 0; + char *substr = NULL; + + /* Detect stage 2 bootloader boards */ + if (strcasestr(board_name, "_stage2")) { + debug("Stage 2 bootloader detected from substring %s in name %s\n", + "_stage2", board_name); + stage2_flag = 1; + } else { + debug("Stage 2 bootloader NOT detected from name \"%s\"\n", + board_name); + } + + if (strcasestr(board_name, "_stage1")) { + debug("Stage 1 bootloader detected from substring %s in name %s\n", + "_stage1", board_name); + stage_1_flag = 1; + } + + /* Generic is a special case since there are numerous sub-types */ + if (!strncasecmp("generic", board_name, strlen("generic"))) + return CVMX_BOARD_TYPE_GENERIC; + + /* + * If we're an eMMC stage 2 bootloader, cut off the _emmc_stage2 + * part of the name. + */ + substr = strcasestr(board_name, "_emmc_stage2"); + if (substr && (substr[strlen("_emmc_stage2")] == '\0')) { + /*return CVMX_BOARD_TYPE_GENERIC;*/ + + printf(" Converting board name %s to ", board_name); + *substr = '\0'; + printf("%s\n", board_name); + } + + /* + * If we're a NAND stage 2 bootloader, cut off the _nand_stage2 + * part of the name. + */ + substr = strcasestr(board_name, "_nand_stage2"); + if (substr && (substr[strlen("_nand_stage2")] == '\0')) { + /*return CVMX_BOARD_TYPE_GENERIC;*/ + + printf(" Converting board name %s to ", board_name); + *substr = '\0'; + printf("%s\n", board_name); + } + + /* + * If we're a SPI stage 2 bootloader, cut off the _spi_stage2 + * part of the name. + */ + substr = strcasestr(board_name, "_spi_stage2"); + if (substr && (substr[strlen("_spi_stage2")] == '\0')) { + printf(" Converting board name %s to ", board_name); + *substr = '\0'; + printf("%s\n", board_name); + } + + for (i = CVMX_BOARD_TYPE_NULL; i < CVMX_BOARD_TYPE_MAX; i++) + if (!strcasecmp(cvmx_board_type_to_string(i), board_name)) + board_type = i; + + for (i = CVMX_BOARD_TYPE_CUST_DEFINED_MIN; + i < CVMX_BOARD_TYPE_CUST_DEFINED_MAX; i++) + if (!strncasecmp(cvmx_board_type_to_string(i), board_name, + strlen(cvmx_board_type_to_string(i)))) + board_type = i; + + for (i = CVMX_BOARD_TYPE_CUST_PRIVATE_MIN; + i < CVMX_BOARD_TYPE_CUST_PRIVATE_MAX; i++) + if (!strncasecmp(cvmx_board_type_to_string(i), board_name, + strlen(cvmx_board_type_to_string(i)))) + board_type = i; + + return board_type; +} + +/* Getoptions variables must be global */ +static int failsafe_flag; +static int pciboot_flag; +static int env_flag; + +int main(int argc, char *argv[]) +{ + int fd; + uint8_t buf[BUF_SIZE]; + uint32_t data_crc = 0; + int len; + int data_len = 0; + struct bootloader_header header; + char filename[NAME_LEN]; + int i; + int option_index = 0; /* getopt_long stores the option index here. */ + char board_name[NAME_LEN] = { 0 }; + char tmp_board_name[NAME_LEN] = { 0 }; + int c; + int board_type = 0; + unsigned long long address = 0; + ssize_t ret; + const char *type_str = NULL; + int hdr_size = sizeof(struct bootloader_header); + + debug("header size is: %d bytes\n", hdr_size); + + /* Parse command line options using getopt_long */ + while (1) { + static struct option long_options[] = { + /* These options set a flag. */ + {"failsafe", no_argument, &failsafe_flag, 1}, + {"pciboot", no_argument, &pciboot_flag, 1}, + {"nandstage2", no_argument, &stage2_flag, 1}, + {"spistage2", no_argument, &stage2_flag, 1}, + {"norstage2", no_argument, &stage2_flag, 1}, + {"stage2", no_argument, &stage2_flag, 1}, + {"stage1.5", no_argument, &stage_1_5_flag, 1}, + {"stage1", no_argument, &stage_1_flag, 1}, + {"environment", no_argument, &env_flag, 1}, + /* These options don't set a flag. + * We distinguish them by their indices. + */ + {"board", required_argument, 0, 0}, + {"text_base", required_argument, 0, 0}, + {0, 0, 0, 0} + }; + + c = getopt_long(argc, (char *const *)argv, "h", + long_options, &option_index); + + /* Detect the end of the options. */ + if (c == -1) + break; + + switch (c) { + /* All long options handled in case 0 */ + case 0: + /* If this option set a flag, do nothing else now. */ + if (long_options[option_index].flag != 0) + break; + debug("option(l) %s", long_options[option_index].name); + if (optarg) + debug(" with arg %s", optarg); + debug("\n"); + + if (!strcmp(long_options[option_index].name, "board")) { + if (strlen(optarg) >= NAME_LEN) { + printf("strncpy() issue detected!"); + exit(-1); + } + strncpy(board_name, optarg, NAME_LEN); + + debug("Using user supplied board name: %s\n", + board_name); + } else if (!strcmp(long_options[option_index].name, + "text_base")) { + address = strtoull(optarg, NULL, 0); + debug("Address of image is: 0x%llx\n", + (unsigned long long)address); + if (!(address & 0xFFFFFFFFULL << 32)) { + if (address & 1 << 31) { + address |= 0xFFFFFFFFULL << 32; + debug("Converting address to 64 bit compatibility space: 0x%llx\n", + address); + } + } + } + break; + + case 'h': + case '?': + /* getopt_long already printed an error message. */ + usage(); + return -1; + + default: + abort(); + } + } + + if (optind < argc) { + /* + * We only support one argument - an optional bootloader + * file name + */ + if (argc - optind > 2) { + debug("non-option ARGV-elements: "); + while (optind < argc) + debug("%s ", argv[optind++]); + debug("\n"); + usage(); + return -1; + } + } + + if (strlen(argv[optind]) >= NAME_LEN) { + printf("strncpy() issue detected!"); + exit(-1); + } + strncpy(filename, argv[optind], NAME_LEN); + + if (board_name[0] == '\0') { + if (strlen(argv[optind + 1]) >= NAME_LEN) { + printf("strncpy() issue detected!"); + exit(-1); + } + strncpy(board_name, argv[optind + 1], NAME_LEN); + } + + if (strlen(board_name) >= NAME_LEN) { + printf("strncpy() issue detected!"); + exit(-1); + } + strncpy(tmp_board_name, board_name, NAME_LEN); + + fd = open(filename, O_RDWR); + if (fd < 0) { + printf("Unable to open file: %s\n", filename); + exit(-1); + } + + if (failsafe_flag) + debug("Setting failsafe flag\n"); + + if (strlen(board_name)) { + int offset = 0; + + debug("Supplied board name of: %s\n", board_name); + + if (strstr(board_name, "failsafe")) { + failsafe_flag = 1; + debug("Setting failsafe flag based on board name\n"); + } + /* Skip leading octeon_ if present. */ + if (!strncmp(board_name, "octeon_", 7)) + offset = 7; + + /* + * Check to see if 'failsafe' is in the name. If so, set the + * failsafe flag. Also, ignore extra trailing characters on + * passed parameter when comparing against board names. + * We actually use the configuration name from u-boot, so it + * may have some other variant names. Variants other than + * failsafe _must_ be passed to this program explicitly + */ + + board_type = lookup_board_type(board_name + offset); + if (!board_type) { + /* Retry with 'cust_' prefix to catch boards that are + * in the customer section (such as nb5) + */ + sprintf(tmp_board_name, "cust_%s", board_name + offset); + board_type = lookup_board_type(tmp_board_name); + } + + /* reset to original value */ + strncpy(tmp_board_name, board_name, NAME_LEN); + if (!board_type) { + /* + * Retry with 'cust_private_' prefix to catch boards + * that are in the customer private section + */ + sprintf(tmp_board_name, "cust_private_%s", + board_name + offset); + board_type = lookup_board_type(tmp_board_name); + } + + if (!board_type) { + printf("ERROR: unable to determine board type\n"); + exit(-1); + } + debug("Board type is: %d: %s\n", board_type, + cvmx_board_type_to_string(board_type)); + } else { + printf("Board name must be specified!\n"); + exit(-1); + } + + /* + * Check to see if there is either an existing header, or that there + * are zero valued bytes where we want to put the header + */ + len = read(fd, buf, BUF_SIZE); + if (len > 0) { + /* + * Copy the header, as the first word (jump instruction, needs + * to remain the same. + */ + memcpy(&header, buf, hdr_size); + /* + * Check to see if we have zero bytes (excluding first 4, which + * are the jump instruction) + */ + for (i = 1; i < hdr_size / 4; i++) { + if (((uint32_t *)buf)[i]) { + printf("ERROR: non-zero word found %x in location %d required for header, aborting\n", + ((uint32_t *)buf)[i], i); + exit(-1); + } + } + debug("Zero bytes found in header location, adding header.\n"); + + } else { + printf("Unable to read from file %s\n", filename); + exit(-1); + } + + /* Read data bytes and generate CRC */ + lseek(fd, hdr_size, SEEK_SET); + + while ((len = read(fd, buf, BUF_SIZE)) > 0) { + data_crc = crc32(data_crc, buf, len); + data_len += len; + } + printf("CRC of data: 0x%x, length: %d\n", data_crc, data_len); + + /* Now create the new header */ + header.magic = htonl(BOOTLOADER_HEADER_MAGIC); + header.maj_rev = htons(BOOTLOADER_HEADER_CURRENT_MAJOR_REV); + header.min_rev = htons(BOOTLOADER_HEADER_CURRENT_MINOR_REV); + header.dlen = htonl(data_len); + header.dcrc = htonl(data_crc); + header.board_type = htons(board_type); + header.address = cvmx_cpu_to_be64(address); + if (failsafe_flag) + header.flags |= htonl(BL_HEADER_FLAG_FAILSAFE); + + debug("Stage 2 flag is %sset\n", stage2_flag ? "" : "not "); + debug("Stage 1 flag is %sset\n", stage_1_flag ? "" : "not "); + if (pciboot_flag) + header.image_type = htons(BL_HEADER_IMAGE_PCIBOOT); + else if (stage2_flag) + header.image_type = htons(BL_HEADER_IMAGE_STAGE2); + else if (stage_1_flag) + header.image_type = htons(BL_HEADER_IMAGE_STAGE1); + else if (env_flag) + header.image_type = htons(BL_HEADER_IMAGE_UBOOT_ENV); + else if (stage_1_5_flag || stage_1_flag) + header.image_type = htons(BL_HEADER_IMAGE_PRE_UBOOT); + else + header.image_type = htons(BL_HEADER_IMAGE_NOR); + + switch (ntohs(header.image_type)) { + case BL_HEADER_IMAGE_UNKNOWN: + type_str = "Unknown"; + break; + case BL_HEADER_IMAGE_STAGE1: + type_str = "Stage 1"; + break; + case BL_HEADER_IMAGE_STAGE2: + type_str = "Stage 2"; + break; + case BL_HEADER_IMAGE_PRE_UBOOT: + type_str = "Pre-U-Boot"; + break; + case BL_HEADER_IMAGE_STAGE3: + type_str = "Stage 3"; + break; + case BL_HEADER_IMAGE_NOR: + type_str = "NOR"; + break; + case BL_HEADER_IMAGE_PCIBOOT: + type_str = "PCI Boot"; + break; + case BL_HEADER_IMAGE_UBOOT_ENV: + type_str = "U-Boot Environment"; + break; + default: + if (ntohs(header.image_type) >= BL_HEADER_IMAGE_CUST_RESERVED_MIN && + ntohs(header.image_type) <= BL_HEADER_IMAGE_CUST_RESERVED_MAX) + type_str = "Customer Reserved"; + else + type_str = "Unsupported"; + } + printf("Header image type: %s\n", type_str); + header.hlen = htons(hdr_size); + + /* Now compute header CRC over all of the header excluding the CRC */ + header.hcrc = crc32(0, (void *)&header, 12); + header.hcrc = htonl(crc32(header.hcrc, ((void *)&(header)) + 16, + hdr_size - 16)); + + /* Seek to beginning of file */ + lseek(fd, 0, SEEK_SET); + + /* Write header to file */ + ret = write(fd, &header, hdr_size); + if (ret < 0) + perror("write"); + + close(fd); + + printf("Header CRC: 0x%x\n", ntohl(header.hcrc)); + return 0; +} + +void usage(void) +{ + printf("Usage: update_octeon_header <filename> <board_name> [--failsafe] [--text_base=0xXXXXX]\n"); +}
Add a tool to update or insert an Octeon specific header into the U-Boot image. This is needed e.g. for booting via SPI NOR, eMMC and NAND. While working on this, move enum cvmx_board_types_enum and cvmx_board_type_to_string() to cvmx-bootloader.h and remove the unreferenced (unsupported) board definition. Signed-off-by: Stefan Roese <sr@denx.de> Cc: Aaron Williams <awilliams@marvell.com> Cc: Chandrakala Chavva <cchavva@marvell.com> Cc: Daniel Schwierzeck <daniel.schwierzeck@gmail.com> --- .../mach-octeon/include/mach/cvmx-bootinfo.h | 222 --------- .../include/mach/cvmx-bootloader.h | 172 +++++++ tools/Makefile | 3 + tools/update_octeon_header.c | 450 ++++++++++++++++++ 4 files changed, 625 insertions(+), 222 deletions(-) create mode 100644 arch/mips/mach-octeon/include/mach/cvmx-bootloader.h create mode 100644 tools/update_octeon_header.c