From patchwork Wed Oct 28 14:10:03 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Roese X-Patchwork-Id: 1389298 X-Patchwork-Delegate: daniel.schwierzeck@googlemail.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=denx.de Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=denx.de header.i=@denx.de header.a=rsa-sha256 header.s=phobos-20191101 header.b=BbfHiapZ; dkim-atps=neutral Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4CLr8Z1qxLz9sVX for ; Thu, 29 Oct 2020 01:11:09 +1100 (AEDT) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 40246824EC; Wed, 28 Oct 2020 15:10:24 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=none (p=none dis=none) header.from=denx.de Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=denx.de; s=phobos-20191101; t=1603894224; bh=BDLfXLkIzzf+7pqONSWkDwZXMTGorWEbss/pQ4CIrLQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=BbfHiapZl8R4MJLn/9aA/sUYnSr0Xg1BT8R0evSX2cf3yoFq2I/Mh4yAXjuKWALZv GuwJjYRhwp966LzHCPWLGgKpYVFRWmLLvIZR9Ir2kftLpw99DcWJTENGeHLT54afX5 tjJPc9cevxxFFg2UdHDdGNHIJy4sKL7zk/Yx8C06djDJ81O3B0J/6udxCM4GENB3Ge L5pwUYWraM3wxbSja5Bq2svHOdevVCP5vgf9x9H0MLRr+D/0UQScp9VWLrDkmFJ1qg dtQrXegLzHVqiSBiZcvqkEUAJNbKCclgy50xLWgrt5oDsth59r50RXjwBUmF6/04x3 MQgKWGZZDgSAw== Received: by phobos.denx.de (Postfix, from userid 109) id E73E8824A8; Wed, 28 Oct 2020 15:10:14 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,SPF_HELO_NONE, URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.2 Received: from mx2.mailbox.org (mx2.mailbox.org [80.241.60.215]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 2A7EC823F4 for ; Wed, 28 Oct 2020 15:10:10 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=none (p=none dis=none) header.from=denx.de Authentication-Results: phobos.denx.de; spf=none smtp.mailfrom=sr@denx.de Received: from smtp2.mailbox.org (smtp2.mailbox.org [80.241.60.241]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange ECDHE (P-384) server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by mx2.mailbox.org (Postfix) with ESMTPS id DD8C2A0BD9; Wed, 28 Oct 2020 15:10:09 +0100 (CET) Received: from smtp2.mailbox.org ([80.241.60.241]) by hefe.heinlein-support.de (hefe.heinlein-support.de [91.198.250.172]) (amavisd-new, port 10030) with ESMTP id R0gbqhgIfs_2; Wed, 28 Oct 2020 15:10:04 +0100 (CET) From: Stefan Roese To: u-boot@lists.denx.de Cc: Aaron Williams , Chandrakala Chavva , Daniel Schwierzeck Subject: [PATCH 5/5 v2] mips: octeon: tools: Add update_octeon_header tool Date: Wed, 28 Oct 2020 15:10:03 +0100 Message-Id: <20201028141003.3062021-5-sr@denx.de> In-Reply-To: <20201028141003.3062021-1-sr@denx.de> References: <20201028141003.3062021-1-sr@denx.de> MIME-Version: 1.0 X-MBO-SPAM-Probability: X-Rspamd-Score: -1.17 / 15.00 / 15.00 X-Rspamd-Queue-Id: 8E74F1707 X-Rspamd-UID: 90ad3c X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.34 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.102.3 at phobos.denx.de X-Virus-Status: Clean 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 Cc: Aaron Williams Cc: Chandrakala Chavva Cc: Daniel Schwierzeck --- v2: - No change - Azure build success here: https://dev.azure.com/sr0718/u-boot/_build/results?buildId=59&view=results .../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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#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 [--failsafe] [--text_base=0xXXXXX]\n"); +}