[PATCH 1/5] mips: start.S: Add Octeon boot header compatibility

classic Classic list List threaded Threaded
10 messages Options
Reply | Threaded
Open this post in threaded view
|

[PATCH 1/5] mips: start.S: Add Octeon boot header compatibility

Stefan Roese
Octeon has a specific boot header, when booted via SPI NOR, NAND or MMC.
Here the only 2 instructions are allowed in the first few bytes of the
image. And these instructions need to be one branch and a nop. This
patch adds the necessary nop after the nop, to that the common MIPS
image is compatible with this Octeon header.

The tool to patch the Octeon boot header into the image will be send in
a follow-up patch.

Signed-off-by: Stefan Roese <[hidden email]>
Cc: Aaron Williams <[hidden email]>
Cc: Chandrakala Chavva <[hidden email]>
Cc: Daniel Schwierzeck <[hidden email]>
---
 arch/mips/cpu/start.S | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/arch/mips/cpu/start.S b/arch/mips/cpu/start.S
index d0c412236d..6de2470cc2 100644
--- a/arch/mips/cpu/start.S
+++ b/arch/mips/cpu/start.S
@@ -75,8 +75,13 @@
 
 ENTRY(_start)
  /* U-Boot entry point */
+ /*
+ * Octeon needs special handling here, as the binary might be
+ * patched to add a boot header for SPI, NAND or MMC booting. Only
+ * one branch plus nop is allowed here.
+ */
  b reset
- mtc0 zero, CP0_COUNT # clear cp0 count for most accurate boot timing
+ nop
 
 #if defined(CONFIG_MIPS_INSERT_BOOT_CONFIG)
  /*
@@ -123,6 +128,7 @@ ENTRY(_start)
 #endif
 
 reset:
+ mtc0 zero, CP0_COUNT # clear cp0 count for most accurate boot timing
 #if __mips_isa_rev >= 6
  mfc0 t0, CP0_CONFIG, 5
  and t0, t0, MIPS_CONF5_VP
--
2.28.0

Reply | Threaded
Open this post in threaded view
|

[PATCH 2/5] mips: octeon: Fix Octeon DDR driver to use the correct struct

Stefan Roese
Don't use "platdata_auto_alloc_size" but "priv_auto_alloc_size" instead
to auto allocate the private data struct, which is referenced via
dev_get_priv() in this driver. This fixes an ugly bug detected while
trying to boot via SPI NOR.

Signed-off-by: Stefan Roese <[hidden email]>
Cc: Aaron Williams <[hidden email]>
Cc: Chandrakala Chavva <[hidden email]>
Cc: Daniel Schwierzeck <[hidden email]>
---
 drivers/ram/octeon/octeon_ddr.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/ram/octeon/octeon_ddr.c b/drivers/ram/octeon/octeon_ddr.c
index 757436b9d3..aaff9c3687 100644
--- a/drivers/ram/octeon/octeon_ddr.c
+++ b/drivers/ram/octeon/octeon_ddr.c
@@ -2724,5 +2724,5 @@ U_BOOT_DRIVER(octeon_ddr) = {
  .of_match = octeon_ids,
  .ops = &octeon_ops,
  .probe = octeon_ddr_probe,
- .platdata_auto_alloc_size = sizeof(struct ddr_priv),
+ .priv_auto_alloc_size = sizeof(struct ddr_priv),
 };
--
2.28.0

Reply | Threaded
Open this post in threaded view
|

[PATCH 3/5] mips: octeon: Report full DDR size in dram_init() to gd->ram_size

Stefan Roese
In reply to this post by Stefan Roese
With this patch, gd->ram_size now holds to full RAM size detected by the
DDR init code. It introduces the get_effective_memsize() function to
report the maximum usable RAM size in U-Boot to the system instead.

Signed-off-by: Stefan Roese <[hidden email]>
Cc: Aaron Williams <[hidden email]>
Cc: Chandrakala Chavva <[hidden email]>
Cc: Daniel Schwierzeck <[hidden email]>
---
 arch/mips/mach-octeon/dram.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/arch/mips/mach-octeon/dram.c b/arch/mips/mach-octeon/dram.c
index 6dc08e19da..4679260f17 100644
--- a/arch/mips/mach-octeon/dram.c
+++ b/arch/mips/mach-octeon/dram.c
@@ -33,7 +33,7 @@ int dram_init(void)
  return ret;
  }
 
- gd->ram_size = min_t(size_t, ram.size, UBOOT_RAM_SIZE_MAX);
+ gd->ram_size = ram.size;
  debug("SDRAM base=%lx, size=%lx\n",
       (unsigned long)ram.base, (unsigned long)ram.size);
  } else {
@@ -72,6 +72,11 @@ void board_add_ram_info(int use_default)
  }
 }
 
+phys_size_t get_effective_memsize(void)
+{
+ return UBOOT_RAM_SIZE_MAX;
+}
+
 ulong board_get_usable_ram_top(ulong total_size)
 {
  if (IS_ENABLED(CONFIG_RAM_OCTEON)) {
--
2.28.0

Reply | Threaded
Open this post in threaded view
|

[PATCH 4/5] mips: octeon: bootoctlinux: Use gd->ram_size instead of ram_get_info()

Stefan Roese
In reply to this post by Stefan Roese
Using ram_get_info() is complicated and does not work after relocation.
Now that gd->ram_size holds the full RAM size, let's use it instead and
remove the ram_get_size logic completely.

Signed-off-by: Stefan Roese <[hidden email]>
Cc: Aaron Williams <[hidden email]>
Cc: Chandrakala Chavva <[hidden email]>
Cc: Daniel Schwierzeck <[hidden email]>
---
 arch/mips/mach-octeon/bootoctlinux.c | 21 +++------------------
 1 file changed, 3 insertions(+), 18 deletions(-)

diff --git a/arch/mips/mach-octeon/bootoctlinux.c b/arch/mips/mach-octeon/bootoctlinux.c
index 75d7e83bd7..26136902f3 100644
--- a/arch/mips/mach-octeon/bootoctlinux.c
+++ b/arch/mips/mach-octeon/bootoctlinux.c
@@ -9,7 +9,6 @@
 #include <dm.h>
 #include <elf.h>
 #include <env.h>
-#include <ram.h>
 
 #include <asm/io.h>
 #include <linux/compat.h>
@@ -370,8 +369,6 @@ int do_bootoctlinux(struct cmd_tbl *cmdtp, int flag, int argc,
  struct cvmx_coremask avail_coremask;
  int first_core;
  int core;
- struct ram_info ram;
- struct udevice *dev;
  const u64 *nmi_code;
  int num_dwords;
  u8 node_mask = 0x01;
@@ -470,19 +467,6 @@ int do_bootoctlinux(struct cmd_tbl *cmdtp, int flag, int argc,
  */
  cvmx_coremask_or(&coremask_to_run, &coremask_to_run, &core_mask);
 
- /* Get RAM size */
- ret = uclass_get_device(UCLASS_RAM, 0, &dev);
- if (ret) {
- debug("DRAM init failed: %d\n", ret);
- return ret;
- }
-
- ret = ram_get_info(dev, &ram);
- if (ret) {
- debug("Cannot get DRAM size: %d\n", ret);
- return ret;
- }
-
  /*
  * Load kernel ELF image, or try binary if ELF is not detected.
  * This way the much smaller vmlinux.bin can also be started but
@@ -498,7 +482,7 @@ int do_bootoctlinux(struct cmd_tbl *cmdtp, int flag, int argc,
 
  /* Init bootmem list for Linux kernel booting */
  if (!cvmx_bootmem_phy_mem_list_init(
-    ram.size, OCTEON_RESERVED_LOW_MEM_SIZE,
+    gd->ram_size, OCTEON_RESERVED_LOW_MEM_SIZE,
     (void *)CKSEG0ADDR(BOOTLOADER_BOOTMEM_DESC_SPACE))) {
  printf("FATAL: Error initializing free memory list\n");
  return 0;
@@ -517,7 +501,8 @@ int do_bootoctlinux(struct cmd_tbl *cmdtp, int flag, int argc,
  if (core == first_core)
  cvmx_bootinfo_array[core].flags |= BOOT_FLAG_INIT_CORE;
 
- cvmx_bootinfo_array[core].dram_size = ram.size / (1024 * 1024);
+ cvmx_bootinfo_array[core].dram_size = gd->ram_size /
+ (1024 * 1024);
 
  cvmx_bootinfo_array[core].dclock_hz = gd->mem_clk * 1000000;
  cvmx_bootinfo_array[core].eclock_hz = gd->cpu_clk;
--
2.28.0

Reply | Threaded
Open this post in threaded view
|

[PATCH 5/5] mips: octeon: tools: Add update_octeon_header tool

Stefan Roese
In reply to this post by 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 <[hidden email]>
Cc: Aaron Williams <[hidden email]>
Cc: Chandrakala Chavva <[hidden email]>
Cc: Daniel Schwierzeck <[hidden email]>
---
 .../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"
+
+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");
+}
--
2.28.0

Reply | Threaded
Open this post in threaded view
|

Re: [PATCH 1/5] mips: start.S: Add Octeon boot header compatibility

Mark Kettenis-2
In reply to this post by Stefan Roese
> From: Stefan Roese <[hidden email]>
> Date: Fri, 16 Oct 2020 15:08:46 +0200
>
> Octeon has a specific boot header, when booted via SPI NOR, NAND or MMC.
> Here the only 2 instructions are allowed in the first few bytes of the
> image. And these instructions need to be one branch and a nop. This
> patch adds the necessary nop after the nop, to that the common MIPS
> image is compatible with this Octeon header.
>
> The tool to patch the Octeon boot header into the image will be send in
> a follow-up patch.

Since the moved instruction is no longer in a delay slot, you should
probably remove the extra space before the instruction.

Cheers,

Mark

> Signed-off-by: Stefan Roese <[hidden email]>
> Cc: Aaron Williams <[hidden email]>
> Cc: Chandrakala Chavva <[hidden email]>
> Cc: Daniel Schwierzeck <[hidden email]>
> ---
>  arch/mips/cpu/start.S | 8 +++++++-
>  1 file changed, 7 insertions(+), 1 deletion(-)
>
> diff --git a/arch/mips/cpu/start.S b/arch/mips/cpu/start.S
> index d0c412236d..6de2470cc2 100644
> --- a/arch/mips/cpu/start.S
> +++ b/arch/mips/cpu/start.S
> @@ -75,8 +75,13 @@
>  
>  ENTRY(_start)
>   /* U-Boot entry point */
> + /*
> + * Octeon needs special handling here, as the binary might be
> + * patched to add a boot header for SPI, NAND or MMC booting. Only
> + * one branch plus nop is allowed here.
> + */
>   b reset
> - mtc0 zero, CP0_COUNT # clear cp0 count for most accurate boot timing
> + nop
>  
>  #if defined(CONFIG_MIPS_INSERT_BOOT_CONFIG)
>   /*
> @@ -123,6 +128,7 @@ ENTRY(_start)
>  #endif
>  
>  reset:
> + mtc0 zero, CP0_COUNT # clear cp0 count for most accurate boot timing
>  #if __mips_isa_rev >= 6
>   mfc0 t0, CP0_CONFIG, 5
>   and t0, t0, MIPS_CONF5_VP
> --
> 2.28.0
>
>
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH 5/5] mips: octeon: tools: Add update_octeon_header tool

Daniel Schwierzeck-2
In reply to this post by Stefan Roese
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 <[hidden email]>
> Cc: Aaron Williams <[hidden email]>
> Cc: Chandrakala Chavva <[hidden email]>
> Cc: Daniel Schwierzeck <[hidden email]>
> ---
>  .../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");
> +}
--
- Daniel

Reply | Threaded
Open this post in threaded view
|

Re: [PATCH 1/5] mips: start.S: Add Octeon boot header compatibility

Daniel Schwierzeck-2
In reply to this post by Stefan Roese
Am Freitag, den 16.10.2020, 15:08 +0200 schrieb Stefan Roese:

> Octeon has a specific boot header, when booted via SPI NOR, NAND or MMC.
> Here the only 2 instructions are allowed in the first few bytes of the
> image. And these instructions need to be one branch and a nop. This
> patch adds the necessary nop after the nop, to that the common MIPS
> image is compatible with this Octeon header.
>
> The tool to patch the Octeon boot header into the image will be send in
> a follow-up patch.
>
> Signed-off-by: Stefan Roese <[hidden email]>
> Cc: Aaron Williams <[hidden email]>
> Cc: Chandrakala Chavva <[hidden email]>
> Cc: Daniel Schwierzeck <[hidden email]>
> ---
>  arch/mips/cpu/start.S | 8 +++++++-
>  1 file changed, 7 insertions(+), 1 deletion(-)
>
> diff --git a/arch/mips/cpu/start.S b/arch/mips/cpu/start.S
> index d0c412236d..6de2470cc2 100644
> --- a/arch/mips/cpu/start.S
> +++ b/arch/mips/cpu/start.S
> @@ -75,8 +75,13 @@
>  
>  ENTRY(_start)
>   /* U-Boot entry point */
> + /*
> + * Octeon needs special handling here, as the binary might be
> + * patched to add a boot header for SPI, NAND or MMC booting. Only
> + * one branch plus nop is allowed here.
> + */

I'd prefer a shorter and more imperative comment within one multi-line
comment block, e.g.

/*
 * U-Boot entry point.
 * Do not add instructions to the branch delay slot! Some SoC's
 * like Octeon might patch the final U-Boot binary at this location
 * with additional boot headers.
 */

>   b reset
> - mtc0 zero, CP0_COUNT # clear cp0 count for most accurate boot timing
> + nop
>  
>  #if defined(CONFIG_MIPS_INSERT_BOOT_CONFIG)
>   /*
> @@ -123,6 +128,7 @@ ENTRY(_start)
>  #endif
>  
>  reset:
> + mtc0 zero, CP0_COUNT # clear cp0 count for most accurate boot timing

the extra indentation of one space is only required for instructions in
delay slots and needs to be removed.

>  #if __mips_isa_rev >= 6
>   mfc0 t0, CP0_CONFIG, 5
>   and t0, t0, MIPS_CONF5_VP
--
- Daniel

Reply | Threaded
Open this post in threaded view
|

Re: [PATCH 1/5] mips: start.S: Add Octeon boot header compatibility

Stefan Roese
On 26.10.20 14:42, Daniel Schwierzeck wrote:

> Am Freitag, den 16.10.2020, 15:08 +0200 schrieb Stefan Roese:
>> Octeon has a specific boot header, when booted via SPI NOR, NAND or MMC.
>> Here the only 2 instructions are allowed in the first few bytes of the
>> image. And these instructions need to be one branch and a nop. This
>> patch adds the necessary nop after the nop, to that the common MIPS
>> image is compatible with this Octeon header.
>>
>> The tool to patch the Octeon boot header into the image will be send in
>> a follow-up patch.
>>
>> Signed-off-by: Stefan Roese <[hidden email]>
>> Cc: Aaron Williams <[hidden email]>
>> Cc: Chandrakala Chavva <[hidden email]>
>> Cc: Daniel Schwierzeck <[hidden email]>
>> ---
>>   arch/mips/cpu/start.S | 8 +++++++-
>>   1 file changed, 7 insertions(+), 1 deletion(-)
>>
>> diff --git a/arch/mips/cpu/start.S b/arch/mips/cpu/start.S
>> index d0c412236d..6de2470cc2 100644
>> --- a/arch/mips/cpu/start.S
>> +++ b/arch/mips/cpu/start.S
>> @@ -75,8 +75,13 @@
>>  
>>   ENTRY(_start)
>>   /* U-Boot entry point */
>> + /*
>> + * Octeon needs special handling here, as the binary might be
>> + * patched to add a boot header for SPI, NAND or MMC booting. Only
>> + * one branch plus nop is allowed here.
>> + */
>
> I'd prefer a shorter and more imperative comment within one multi-line
> comment block, e.g.
>
> /*
>   * U-Boot entry point.
>   * Do not add instructions to the branch delay slot! Some SoC's
>   * like Octeon might patch the final U-Boot binary at this location
>   * with additional boot headers.
>   */

Even better. Will change in v2.

>>   b reset
>> - mtc0 zero, CP0_COUNT # clear cp0 count for most accurate boot timing
>> + nop
>>  
>>   #if defined(CONFIG_MIPS_INSERT_BOOT_CONFIG)
>>   /*
>> @@ -123,6 +128,7 @@ ENTRY(_start)
>>   #endif
>>  
>>   reset:
>> + mtc0 zero, CP0_COUNT # clear cp0 count for most accurate boot timing
>
> the extra indentation of one space is only required for instructions in
> delay slots and needs to be removed.

Yes, thanks for catching.

Thanks,
Stefan
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH 5/5] mips: octeon: tools: Add update_octeon_header tool

Stefan Roese
In reply to this post by Daniel Schwierzeck-2
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