All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH v2 00/18] arm: mvebu: Add gdsys ControlCenter-Compact board
@ 2017-01-11 15:00 Mario Six
  2017-01-11 15:00 ` [U-Boot] [PATCH v2 01/18] pci: mvebu: Fix Armada 38x support Mario Six
                   ` (17 more replies)
  0 siblings, 18 replies; 55+ messages in thread
From: Mario Six @ 2017-01-11 15:00 UTC (permalink / raw)
  To: u-boot

This patch series adds support for the Guntermann & Drunck
ControlCenter-Compact board.

To this extent, some bugs in the mvebu PCI driver are fixed, a GPIO driver is
added, support for the Marvell 88E1680 is added, the TPM library is extended,
the kwbimage generation is streamlined, a board function for manipulating the
device tree is added, and secure boot for the mvebu architecture is
implemented.

Dirk Eibach (3):
  pci: mvebu: Fix Armada 38x support
  net: phy: Support Marvell 88E1680
  arm: mvebu: Add gdsys ControlCenter-Compact board

Mario Six (14):
  mvebu: Add board_pex_config()
  dm: Add callback to modify the device tree
  lib: tpm: Add command to flush resources
  core: device: Add dev_get_by_ofname function
  gpio: Add gpio_request_simple function
  tools: kwbimage: Fix dest addr
  tools: kwbimage: Fix style violations
  tools: kwbimage: Fix arithmetic with void pointers
  tools: kwbimage: Reduce scope of variables
  tools: kwbimage: Remove unused parameter
  tools: kwbimage: Factor out add_binary_header_v1
  tools: kwbimage: Refactor line parsing and fix error
  arm: mvebu: Implement secure boot
  controlcenterdc: Make secure boot available

Reinhard Pfau (1):
  arm: mvebu: spl.c: Remove useless gd declaration

 Makefile                                    |    3 +-
 arch/arm/Kconfig                            |    1 +
 arch/arm/dts/Makefile                       |    3 +-
 arch/arm/dts/armada-38x-controlcenterdc.dts |  643 ++++++++++++++++
 arch/arm/mach-mvebu/Kconfig                 |   39 +
 arch/arm/mach-mvebu/Makefile                |    1 +
 arch/arm/mach-mvebu/efuse.c                 |  264 +++++++
 arch/arm/mach-mvebu/include/mach/cpu.h      |    2 +
 arch/arm/mach-mvebu/include/mach/efuse.h    |   69 ++
 arch/arm/mach-mvebu/include/mach/soc.h      |    1 +
 arch/arm/mach-mvebu/serdes/a38x/ctrl_pex.c  |    8 +
 arch/arm/mach-mvebu/serdes/a38x/ctrl_pex.h  |    2 +
 arch/arm/mach-mvebu/spl.c                   |    2 -
 board/gdsys/a38x/.gitignore                 |    1 +
 board/gdsys/a38x/Kconfig                    |   36 +
 board/gdsys/a38x/MAINTAINERS                |    7 +
 board/gdsys/a38x/Makefile                   |   44 ++
 board/gdsys/a38x/controlcenterdc.c          |  273 +++++++
 board/gdsys/a38x/dt_helpers.c               |   25 +
 board/gdsys/a38x/dt_helpers.h               |   14 +
 board/gdsys/a38x/hre.c                      |  516 +++++++++++++
 board/gdsys/a38x/hre.h                      |   38 +
 board/gdsys/a38x/hydra.c                    |  138 ++++
 board/gdsys/a38x/hydra.h                    |   14 +
 board/gdsys/a38x/ihs_phys.c                 |  349 +++++++++
 board/gdsys/a38x/ihs_phys.h                 |    2 +
 board/gdsys/a38x/keyprogram.c               |  158 ++++
 board/gdsys/a38x/keyprogram.h               |   14 +
 board/gdsys/a38x/kwbimage.cfg.in            |   40 +
 board/gdsys/a38x/spl.c                      |   21 +
 board/gdsys/p1022/controlcenterd-id.c       |    9 -
 cmd/tpm.c                                   |   70 ++
 common/board_f.c                            |   10 +
 configs/controlcenterdc_defconfig           |   57 ++
 doc/README.armada-secureboot                |  373 +++++++++
 doc/driver-model/fdt-fixup.txt              |  132 ++++
 drivers/core/device.c                       |    7 +
 drivers/gpio/gpio-uclass.c                  |   17 +
 drivers/net/phy/marvell.c                   |   54 ++
 drivers/pci/pci_mvebu.c                     |   25 +-
 drivers/tpm/Kconfig                         |    6 +
 dts/Kconfig                                 |   10 +
 include/asm-generic/gpio.h                  |   22 +
 include/common.h                            |    1 +
 include/configs/controlcenterdc.h           |  235 ++++++
 include/dm/device.h                         |    8 +
 include/tpm.h                               |   45 ++
 lib/tpm.c                                   |   29 +
 tools/Makefile                              |    6 +-
 tools/kwbimage.c                            | 1111 +++++++++++++++++++++++----
 tools/kwbimage.h                            |   37 +
 51 files changed, 4806 insertions(+), 186 deletions(-)
 create mode 100644 arch/arm/dts/armada-38x-controlcenterdc.dts
 create mode 100644 arch/arm/mach-mvebu/efuse.c
 create mode 100644 arch/arm/mach-mvebu/include/mach/efuse.h
 create mode 100644 board/gdsys/a38x/.gitignore
 create mode 100644 board/gdsys/a38x/Kconfig
 create mode 100644 board/gdsys/a38x/MAINTAINERS
 create mode 100644 board/gdsys/a38x/Makefile
 create mode 100644 board/gdsys/a38x/controlcenterdc.c
 create mode 100644 board/gdsys/a38x/dt_helpers.c
 create mode 100644 board/gdsys/a38x/dt_helpers.h
 create mode 100644 board/gdsys/a38x/hre.c
 create mode 100644 board/gdsys/a38x/hre.h
 create mode 100644 board/gdsys/a38x/hydra.c
 create mode 100644 board/gdsys/a38x/hydra.h
 create mode 100644 board/gdsys/a38x/ihs_phys.c
 create mode 100644 board/gdsys/a38x/ihs_phys.h
 create mode 100644 board/gdsys/a38x/keyprogram.c
 create mode 100644 board/gdsys/a38x/keyprogram.h
 create mode 100644 board/gdsys/a38x/kwbimage.cfg.in
 create mode 100644 board/gdsys/a38x/spl.c
 create mode 100644 configs/controlcenterdc_defconfig
 create mode 100644 doc/README.armada-secureboot
 create mode 100644 doc/driver-model/fdt-fixup.txt
 create mode 100644 include/configs/controlcenterdc.h

--
2.9.0

^ permalink raw reply	[flat|nested] 55+ messages in thread

* [U-Boot] [PATCH v2 01/18] pci: mvebu: Fix Armada 38x support
  2017-01-11 15:00 [U-Boot] [PATCH v2 00/18] arm: mvebu: Add gdsys ControlCenter-Compact board Mario Six
@ 2017-01-11 15:00 ` Mario Six
  2017-01-18 15:56   ` Stefan Roese
  2017-02-01 11:40   ` Stefan Roese
  2017-01-11 15:00 ` [U-Boot] [PATCH v2 02/18] net: phy: Support Marvell 88E1680 Mario Six
                   ` (16 subsequent siblings)
  17 siblings, 2 replies; 55+ messages in thread
From: Mario Six @ 2017-01-11 15:00 UTC (permalink / raw)
  To: u-boot

From: Dirk Eibach <dirk.eibach@gdsys.cc>

Armada 38x has four PCI ports, not three.

The optimization in pci_init_board() seems to assume that every port has
three lanes. This is obviously wrong, and breaks support for Armada 38x.

Signed-off-by: Dirk Eibach <dirk.eibach@gdsys.cc>
Signed-off-by: Mario Six <mario.six@gdsys.cc>
---
Changes in v2:

None
---
 arch/arm/mach-mvebu/include/mach/soc.h |  1 +
 drivers/pci/pci_mvebu.c                | 25 +++++++++++++------------
 2 files changed, 14 insertions(+), 12 deletions(-)

diff --git a/arch/arm/mach-mvebu/include/mach/soc.h b/arch/arm/mach-mvebu/include/mach/soc.h
index 0f69f33..0900e40 100644
--- a/arch/arm/mach-mvebu/include/mach/soc.h
+++ b/arch/arm/mach-mvebu/include/mach/soc.h
@@ -67,6 +67,7 @@
 #define MVEBU_REG_PCIE_BASE	(MVEBU_REGISTER(0x40000))
 #define MVEBU_AXP_USB_BASE      (MVEBU_REGISTER(0x50000))
 #define MVEBU_USB20_BASE	(MVEBU_REGISTER(0x58000))
+#define MVEBU_REG_PCIE0_BASE	(MVEBU_REGISTER(0x80000))
 #define MVEBU_AXP_SATA_BASE	(MVEBU_REGISTER(0xa0000))
 #define MVEBU_SATA0_BASE	(MVEBU_REGISTER(0xa8000))
 #define MVEBU_NAND_BASE		(MVEBU_REGISTER(0xd0000))
diff --git a/drivers/pci/pci_mvebu.c b/drivers/pci/pci_mvebu.c
index 0f44970..da0aa29 100644
--- a/drivers/pci/pci_mvebu.c
+++ b/drivers/pci/pci_mvebu.c
@@ -91,25 +91,26 @@ static void __iomem *mvebu_pcie_membase = (void __iomem *)MBUS_PCI_MEM_BASE;
 #if defined(CONFIG_ARMADA_38X)
 #define PCIE_BASE(if)					\
 	((if) == 0 ?					\
-	 MVEBU_REG_PCIE_BASE + 0x40000 :		\
-	 MVEBU_REG_PCIE_BASE + 0x4000 * (if))
+	 MVEBU_REG_PCIE0_BASE :				\
+	 (MVEBU_REG_PCIE_BASE + 0x4000 * (if - 1)))

 /*
  * On A38x MV6820 these PEX ports are supported:
  *  0 - Port 0.0
- *  1 - Port 0.1
- *  2 - Port 0.2
+ *  1 - Port 1.0
+ *  2 - Port 2.0
+ *  3 - Port 3.0
  */
-#define MAX_PEX 3
+#define MAX_PEX 4
 static struct mvebu_pcie pcie_bus[MAX_PEX];

 static void mvebu_get_port_lane(struct mvebu_pcie *pcie, int pex_idx,
 				int *mem_target, int *mem_attr)
 {
-	u8 port[] = { 0, 1, 2 };
-	u8 lane[] = { 0, 0, 0 };
-	u8 target[] = { 8, 4, 4 };
-	u8 attr[] = { 0xe8, 0xe8, 0xd8 };
+	u8 port[] = { 0, 1, 2, 3 };
+	u8 lane[] = { 0, 0, 0, 0 };
+	u8 target[] = { 8, 4, 4, 4 };
+	u8 attr[] = { 0xe8, 0xe8, 0xd8, 0xb8 };

 	pcie->port = port[pex_idx];
 	pcie->lane = lane[pex_idx];
@@ -351,9 +352,9 @@ void pci_init_board(void)
 		mvebu_get_port_lane(pcie, i, &mem_target, &mem_attr);

 		/* Don't read at all from pci registers if port power is down */
-		if (pcie->lane == 0 && SELECT(soc_ctrl, pcie->port) == 0) {
-			i += 3;
-			debug("%s: skipping port %d\n", __func__, pcie->port);
+		if (SELECT(soc_ctrl, pcie->port) == 0) {
+			if (pcie->lane == 0)
+				debug("%s: skipping port %d\n", __func__, pcie->port);
 			continue;
 		}

--
2.9.0

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [U-Boot] [PATCH v2 02/18] net: phy: Support Marvell 88E1680
  2017-01-11 15:00 [U-Boot] [PATCH v2 00/18] arm: mvebu: Add gdsys ControlCenter-Compact board Mario Six
  2017-01-11 15:00 ` [U-Boot] [PATCH v2 01/18] pci: mvebu: Fix Armada 38x support Mario Six
@ 2017-01-11 15:00 ` Mario Six
  2017-01-18 15:57   ` Stefan Roese
                     ` (2 more replies)
  2017-01-11 15:00 ` [U-Boot] [PATCH v2 03/18] mvebu: Add board_pex_config() Mario Six
                   ` (15 subsequent siblings)
  17 siblings, 3 replies; 55+ messages in thread
From: Mario Six @ 2017-01-11 15:00 UTC (permalink / raw)
  To: u-boot

From: Dirk Eibach <dirk.eibach@gdsys.cc>

Add support for Marvell 88E1680 Integrated Octal
10/100/1000 Mbps Energy Efficient Ethernet Transceiver.

Signed-off-by: Dirk Eibach <dirk.eibach@gdsys.cc>
Signed-off-by: Mario Six <mario.six@gdsys.cc>
---
Changes in v2:

* Switched to usage of pre-defined constant names where possible
* Added error handling for genphy_config_aneg call
---
 drivers/net/phy/marvell.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 54 insertions(+)

diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c
index 4eeb0f6..c3058a4 100644
--- a/drivers/net/phy/marvell.c
+++ b/drivers/net/phy/marvell.c
@@ -480,6 +480,49 @@ static int m88e1310_config(struct phy_device *phydev)
 	return genphy_config_aneg(phydev);
 }

+static int m88e1680_config(struct phy_device *phydev)
+{
+	/*
+	 * As per Marvell Release Notes - Alaska V 88E1680 Rev A2
+	 * Errata Section 4.1
+	 */
+	u16 reg;
+	int res;
+
+	/* Matrix LED mode (not neede if single LED mode is used */
+	phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1118_PHY_PAGE, 0x0004);
+	reg = phy_read(phydev, MDIO_DEVAD_NONE, 27);
+	reg |= (1 << 5);
+	phy_write(phydev, MDIO_DEVAD_NONE, 27, reg);
+
+	/* QSGMII TX amplitude change */
+	phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1118_PHY_PAGE, 0x00fd);
+	phy_write(phydev, MDIO_DEVAD_NONE,  8, 0x0b53);
+	phy_write(phydev, MDIO_DEVAD_NONE,  7, 0x200d);
+	phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1118_PHY_PAGE, 0x0000);
+
+	/* EEE initialization */
+	phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1118_PHY_PAGE, 0x00ff);
+	phy_write(phydev, MDIO_DEVAD_NONE, 17, 0xb030);
+	phy_write(phydev, MDIO_DEVAD_NONE, 16, 0x215c);
+	phy_write(phydev, MDIO_DEVAD_NONE, 22, 0x00fc);
+	phy_write(phydev, MDIO_DEVAD_NONE, 24, 0x888c);
+	phy_write(phydev, MDIO_DEVAD_NONE, 25, 0x888c);
+	phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1118_PHY_PAGE, 0x0000);
+	phy_write(phydev, MDIO_DEVAD_NONE,  0, 0x9140);
+
+	res = genphy_config_aneg(phydev);
+	if (res < 0)
+		return res;
+
+	/* soft reset */
+	reg = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR);
+	reg |= BMCR_RESET;
+	phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, reg);
+
+	return 0;
+}
+
 static struct phy_driver M88E1011S_driver = {
 	.name = "Marvell 88E1011S",
 	.uid = 0x1410c60,
@@ -580,6 +623,16 @@ static struct phy_driver M88E1310_driver = {
 	.shutdown = &genphy_shutdown,
 };

+static struct phy_driver M88E1680_driver = {
+	.name = "Marvell 88E1680",
+	.uid = 0x1410ed0,
+	.mask = 0xffffff0,
+	.features = PHY_GBIT_FEATURES,
+	.config = &m88e1680_config,
+	.startup = &genphy_startup,
+	.shutdown = &genphy_shutdown,
+};
+
 int phy_marvell_init(void)
 {
 	phy_register(&M88E1310_driver);
@@ -592,6 +645,7 @@ int phy_marvell_init(void)
 	phy_register(&M88E1011S_driver);
 	phy_register(&M88E1510_driver);
 	phy_register(&M88E1518_driver);
+	phy_register(&M88E1680_driver);

 	return 0;
 }
--
2.9.0

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [U-Boot] [PATCH v2 03/18] mvebu: Add board_pex_config()
  2017-01-11 15:00 [U-Boot] [PATCH v2 00/18] arm: mvebu: Add gdsys ControlCenter-Compact board Mario Six
  2017-01-11 15:00 ` [U-Boot] [PATCH v2 01/18] pci: mvebu: Fix Armada 38x support Mario Six
  2017-01-11 15:00 ` [U-Boot] [PATCH v2 02/18] net: phy: Support Marvell 88E1680 Mario Six
@ 2017-01-11 15:00 ` Mario Six
  2017-01-18 15:58   ` Stefan Roese
  2017-02-01 11:40   ` Stefan Roese
  2017-01-11 15:00 ` [U-Boot] [PATCH v2 04/18] arm: mvebu: spl.c: Remove useless gd declaration Mario Six
                   ` (14 subsequent siblings)
  17 siblings, 2 replies; 55+ messages in thread
From: Mario Six @ 2017-01-11 15:00 UTC (permalink / raw)
  To: u-boot

Allow boards to do some initialization when PCIe comes up.

Signed-off-by: Dirk Eibach <dirk.eibach@gdsys.cc>
Signed-off-by: Mario Six <mario.six@gdsys.cc>
---
Changes in v2:

* Switched usage of __attribute(...) to __weak to simplify weak function
  declaration
---
 arch/arm/mach-mvebu/serdes/a38x/ctrl_pex.c | 8 ++++++++
 arch/arm/mach-mvebu/serdes/a38x/ctrl_pex.h | 2 ++
 2 files changed, 10 insertions(+)

diff --git a/arch/arm/mach-mvebu/serdes/a38x/ctrl_pex.c b/arch/arm/mach-mvebu/serdes/a38x/ctrl_pex.c
index 98c447c..9e5b647 100644
--- a/arch/arm/mach-mvebu/serdes/a38x/ctrl_pex.c
+++ b/arch/arm/mach-mvebu/serdes/a38x/ctrl_pex.c
@@ -13,6 +13,11 @@
 #include "ctrl_pex.h"
 #include "sys_env_lib.h"

+__weak void board_pex_config(void)
+{
+	/* nothing in this weak default implementation */
+}
+
 int hws_pex_config(const struct serdes_map *serdes_map, u8 count)
 {
 	u32 pex_idx, tmp, next_busno, first_busno, temp_pex_reg,
@@ -77,6 +82,9 @@ int hws_pex_config(const struct serdes_map *serdes_map, u8 count)

 	/* Support gen1/gen2 */
 	DEBUG_INIT_FULL_S("Support gen1/gen2\n");
+
+	board_pex_config();
+
 	next_busno = 0;
 	mdelay(150);

diff --git a/arch/arm/mach-mvebu/serdes/a38x/ctrl_pex.h b/arch/arm/mach-mvebu/serdes/a38x/ctrl_pex.h
index 5f7e2c7..ca8a4d2 100644
--- a/arch/arm/mach-mvebu/serdes/a38x/ctrl_pex.h
+++ b/arch/arm/mach-mvebu/serdes/a38x/ctrl_pex.h
@@ -83,4 +83,6 @@ int pex_local_bus_num_set(u32 pex_if, u32 bus_num);
 int pex_local_dev_num_set(u32 pex_if, u32 dev_num);
 u32 pex_config_read(u32 pex_if, u32 bus, u32 dev, u32 func, u32 reg_off);

+void board_pex_config(void);
+
 #endif
--
2.9.0

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [U-Boot] [PATCH v2 04/18] arm: mvebu: spl.c: Remove useless gd declaration
  2017-01-11 15:00 [U-Boot] [PATCH v2 00/18] arm: mvebu: Add gdsys ControlCenter-Compact board Mario Six
                   ` (2 preceding siblings ...)
  2017-01-11 15:00 ` [U-Boot] [PATCH v2 03/18] mvebu: Add board_pex_config() Mario Six
@ 2017-01-11 15:00 ` Mario Six
  2017-01-18 15:58   ` Stefan Roese
  2017-02-01 11:40   ` Stefan Roese
  2017-01-11 15:00 ` [U-Boot] [PATCH v2 05/18] dm: Add callback to modify the device tree Mario Six
                   ` (13 subsequent siblings)
  17 siblings, 2 replies; 55+ messages in thread
From: Mario Six @ 2017-01-11 15:00 UTC (permalink / raw)
  To: u-boot

From: Reinhard Pfau <pfau@gdsys.de>

ddaa905 ("arm: mvebu: Add DM (driver model) support") removed the
assignment of the gd pointer, but kept the (now superfluous) declaration
of the gd pointer.

Remove this declaration.

Signed-off-by: Reinhard Pfau <pfau@gdsys.de>
---
Changes in v2:

None
---
 arch/arm/mach-mvebu/spl.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/arch/arm/mach-mvebu/spl.c b/arch/arm/mach-mvebu/spl.c
index e1c9cdb..3cf02a5 100644
--- a/arch/arm/mach-mvebu/spl.c
+++ b/arch/arm/mach-mvebu/spl.c
@@ -13,8 +13,6 @@
 #include <asm/arch/cpu.h>
 #include <asm/arch/soc.h>

-DECLARE_GLOBAL_DATA_PTR;
-
 static u32 get_boot_device(void)
 {
 	u32 val;
--
2.9.0

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [U-Boot] [PATCH v2 05/18] dm: Add callback to modify the device tree
  2017-01-11 15:00 [U-Boot] [PATCH v2 00/18] arm: mvebu: Add gdsys ControlCenter-Compact board Mario Six
                   ` (3 preceding siblings ...)
  2017-01-11 15:00 ` [U-Boot] [PATCH v2 04/18] arm: mvebu: spl.c: Remove useless gd declaration Mario Six
@ 2017-01-11 15:00 ` Mario Six
  2017-01-18 16:03   ` Stefan Roese
  2017-01-11 15:00 ` [U-Boot] [PATCH v2 06/18] lib: tpm: Add command to flush resources Mario Six
                   ` (12 subsequent siblings)
  17 siblings, 1 reply; 55+ messages in thread
From: Mario Six @ 2017-01-11 15:00 UTC (permalink / raw)
  To: u-boot

Certain boards come in different variations by way of utilizing daughter
boards, for example. These boards might contain additional chips, which
are added to the main board's busses, e.g. I2C.

The device tree support for such boards would either, quite naturally,
employ the overlay mechanism to add such chips to the tree, or would use
one large default device tree, and delete the devices that are actually
not present.

Regardless of approach, even on the U-Boot level, a modification of the
device tree is a prerequisite to have such modular families of boards
supported properly.

Therefore, we add an option to make the U-Boot device tree (the actual
copy later used by the driver model) writeable, and add a callback
method that allows boards to modify the device tree at an early stage,
at which, hopefully, also the application of device tree overlays will
be possible.

Signed-off-by: Mario Six <mario.six@gdsys.cc>
---
Changes in v2:

* Switched from usage of globally writeable global data pointer to a locally
  writeable pointer passed to board_fix_fdt
* Added comments for board_fix_fdt in include/common.h
* Added documentation for pre-relocation device tree manipulation
---
 common/board_f.c               |  10 ++++
 doc/driver-model/fdt-fixup.txt | 132 +++++++++++++++++++++++++++++++++++++++++
 dts/Kconfig                    |  10 ++++
 include/common.h               |   1 +
 4 files changed, 153 insertions(+)
 create mode 100644 doc/driver-model/fdt-fixup.txt

diff --git a/common/board_f.c b/common/board_f.c
index cc8aee7..e877bf9 100644
--- a/common/board_f.c
+++ b/common/board_f.c
@@ -767,6 +767,13 @@ static int setup_reloc(void)
 	return 0;
 }

+#ifdef CONFIG_OF_BOARD_FIXUP
+static int fix_fdt(void)
+{
+	return board_fix_fdt((void *)gd->fdt_blob);
+}
+#endif
+
 /* ARM calls relocate_code from its crt0.S */
 #if !defined(CONFIG_ARM) && !defined(CONFIG_SANDBOX)

@@ -1037,6 +1044,9 @@ static init_fnc_t init_sequence_f[] = {
 #ifdef CONFIG_SYS_EXTBDINFO
 	setup_board_extra,
 #endif
+#ifdef CONFIG_OF_BOARD_FIXUP
+	fix_fdt,
+#endif
 	INIT_FUNC_WATCHDOG_RESET
 	reloc_fdt,
 	setup_reloc,
diff --git a/doc/driver-model/fdt-fixup.txt b/doc/driver-model/fdt-fixup.txt
new file mode 100644
index 0000000..70344bd
--- /dev/null
+++ b/doc/driver-model/fdt-fixup.txt
@@ -0,0 +1,132 @@
+Pre-relocation device tree manipulation
+=======================================
+
+Contents:
+
+1. Purpose
+2. Implementation
+3. Example
+4. Work to be done
+
+1. Purpose
+----------
+
+In certain markets, it is beneficial for manufacturers of embedded devices to
+offer certain ranges of products, where the functionality of the devices within
+one series either don't differ greatly from another, or can be thought of as
+"extensions" of each other, where one device only differs from another in the
+addition of a small number of features (e.g. an additional output connector).
+
+To realize this in hardware, one method is to have a motherboard, and several
+possible daughter boards that can be attached to this mother board. Different
+daughter boards then either offer the slightly different functionality, or the
+addition of the daughter board to the device realizes the "extension" of
+functionality to the device described previously.
+
+For the software, we obviously want to reuse components for all these
+variations of the device. This means that the software somehow needs to cope
+with the situation that certain ICs may or may not be present on any given
+system, depending on which daughter boards are connected to the motherboard.
+
+In the Linux kernel, one possible solution to this problem is to employ the
+device tree overlay mechanism: There exists one "base" device tree, which
+features only the components guaranteed to exist in all varieties of the
+device. At the start of the kernel, the presence and type of the daughter
+boards is then detected, and the corresponding device tree overlays are applied
+to support the components on the daughter boards.
+
+Note that the components present on every variety of the board must, of course,
+provide a way to find out if and which daughter boards are installed for this
+mechanism to work.
+
+In the U-Boot boot loader, support for device tree overlays has recently been
+integrated, and is used on some boards to alter the device tree that is later
+passed to Linux. But since U-Boot's driver model, which is device tree-based as
+well, is being used in more and more drivers, the same problem of altering the
+device tree starts cropping up in U-Boot itself as well.
+
+An additional problem with the device tree in U-Boot is that it is read-only,
+and the current mechanisms don't allow easy manipulation of the device tree
+after the driver model has been initialized. While migrating to a live device
+tree (at least after the relocation) would greatly simplify the solution of
+this problem, it is a non-negligible task to implement it, an a interim
+solution is needed to address the problem at least in the medium-term.
+
+Hence, we propose a solution to this problem by offering a board-specific
+call-back function, which is passed a writeable pointer to the device tree.
+This function is called before the device tree is relocated, and specifically
+before the main U-Boot's driver model is instantiated, hence the main U-Boot
+"sees" all modifications to the device tree made in this function. Furthermore,
+we have the pre-relocation driver model at our disposal at this stage, which
+means that we can query the hardware for the existence and variety of the
+components easily.
+
+2. Implementation
+-----------------
+
+To take advantage of the pre-relocation device tree manipulation mechanism,
+boards have to implement the function board_fix_fdt, which has the following
+signature:
+
+int board_fix_fdt (void *rw_fdt_blob)
+
+The passed-in void pointer is a writeable pointer to the device tree, which can
+be used to manipulate the device tree using e.g. functions from
+include/fdt_support.h. The return value should either be 0 in case of
+successful execution of the device tree manipulation or something else for a
+failure. Note that returning a non-null value from the function will
+unrecoverably halt the boot process, as with any function from init_sequence_f
+(in common/board_f.c).
+
+Furthermore, the Kconfig option OF_BOARD_FIXUP has to be set for the function
+to be called:
+
+Device Tree Control
+-> [*] Board-specific manipulation of Device Tree
+
++----------------------------------------------------------+
+| WARNING: The actual manipulation of the device tree has  |
+| to be the _last_ set of operations in board_fix_fdt!     |
+| Since the pre-relocation driver model does not adapt to  |
+| changes made to the device tree either, its references   |
+| into the device tree will be invalid after manipulating  |
+| it, and unpredictable behavior might occur when          |
+| functions that rely on them are executed!                |
++----------------------------------------------------------+
+
+Hence, the recommended layout of the board_fixup_fdt call-back function is the
+following:
+
+int board_fix_fdt(void *rw_fdt_blob)
+{
+	/* Collect information about device's hardware and store them in e.g.
+	   local variables */
+
+	/* Do device tree manipulation using the values previously collected */
+
+	/* Return 0 on successful manipulation and non-zero otherwise */
+}
+
+If this convention is kept, both an "additive" approach, meaning that nodes for
+detected components are added to the device tree, as well as a "subtractive"
+approach, meaning that nodes for absent components are removed from the tree,
+as well as a combination of both approaches should work.
+
+3. Example
+----------
+
+The controlcenterdc board (board/gdsys/a38x/controlcenterdc.c) features a
+board_fix_fdt function, in which six GPIO expanders (which might be present or
+not, since they are on daughter boards) on a I2C bus are queried for, and
+subsequently deactivated in the device tree if they are not present.
+
+Note that the dm_i2c_simple_probe function does not use the device tree, hence
+it is safe to call it after the tree has already been manipulated.
+
+4. Work to be done
+------------------
+
+* The application of device tree overlay should be possible in board_fixup_fdt,
+  but has not been tested at this stage.
+
+2017-01-06, Mario Six <mario.six@gdsys.cc>
diff --git a/dts/Kconfig b/dts/Kconfig
index 4b7d8b1..3f64eda 100644
--- a/dts/Kconfig
+++ b/dts/Kconfig
@@ -14,6 +14,16 @@ config OF_CONTROL
 	  This feature provides for run-time configuration of U-Boot
 	  via a flattened device tree.

+config OF_BOARD_FIXUP
+	bool "Board-specific manipulation of Device Tree"
+	help
+	  In certain circumstances it is necessary to be able to modify
+	  U-Boot's device tree (e.g. to delete device from it). This option
+	  make the Device Tree writeable and provides a board-specific
+	  "board_fix_fdt" callback (called during pre-relocation time), which
+	  enables the board initialization to modifiy the Device Tree. The
+	  modified copy is subsequently used by U-Boot after relocation.
+
 config SPL_OF_CONTROL
 	bool "Enable run-time configuration via Device Tree in SPL"
 	depends on SPL && OF_CONTROL
diff --git a/include/common.h b/include/common.h
index a8d833b..a64f249 100644
--- a/include/common.h
+++ b/include/common.h
@@ -502,6 +502,7 @@ extern ssize_t spi_write (uchar *, int, uchar *, int);

 /* $(BOARD)/$(BOARD).c */
 int board_early_init_f (void);
+int board_fix_fdt (void *rw_fdt_blob); /* manipulate the U-Boot fdt before its relocation */
 int board_late_init (void);
 int board_postclk_init (void); /* after clocks/timebase, before env/serial */
 int board_early_init_r (void);
--
2.9.0

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [U-Boot] [PATCH v2 06/18] lib: tpm: Add command to flush resources
  2017-01-11 15:00 [U-Boot] [PATCH v2 00/18] arm: mvebu: Add gdsys ControlCenter-Compact board Mario Six
                   ` (4 preceding siblings ...)
  2017-01-11 15:00 ` [U-Boot] [PATCH v2 05/18] dm: Add callback to modify the device tree Mario Six
@ 2017-01-11 15:00 ` Mario Six
  2017-01-18 16:07   ` Stefan Roese
                     ` (2 more replies)
  2017-01-11 15:00 ` [U-Boot] [PATCH v2 07/18] core: device: Add dev_get_by_ofname function Mario Six
                   ` (11 subsequent siblings)
  17 siblings, 3 replies; 55+ messages in thread
From: Mario Six @ 2017-01-11 15:00 UTC (permalink / raw)
  To: u-boot

This patch adds a function to the TPM library, which allows U-Boot to
flush resources, e.g. keys, from the TPM.

Signed-off-by: Mario Six <mario.six@gdsys.cc>
---
Changes in v2:

* Added U-Boot command for resource flushing ("tpm flush"), and made the
  command and the library function deactivate-able via config
---
 board/gdsys/p1022/controlcenterd-id.c |  9 -----
 cmd/tpm.c                             | 70 +++++++++++++++++++++++++++++++++++
 drivers/tpm/Kconfig                   |  6 +++
 include/tpm.h                         | 45 ++++++++++++++++++++++
 lib/tpm.c                             | 29 +++++++++++++++
 5 files changed, 150 insertions(+), 9 deletions(-)

diff --git a/board/gdsys/p1022/controlcenterd-id.c b/board/gdsys/p1022/controlcenterd-id.c
index 2c6c698..1648f13 100644
--- a/board/gdsys/p1022/controlcenterd-id.c
+++ b/board/gdsys/p1022/controlcenterd-id.c
@@ -43,15 +43,6 @@
 #define CCDM_AUTO_FIRST_STAGE
 #endif

-/* enums from TCG specs */
-enum {
-	/* capability areas */
-	TPM_CAP_NV_INDEX	= 0x00000011,
-	TPM_CAP_HANDLE		= 0x00000014,
-	/* resource types */
-	TPM_RT_KEY	= 0x00000001,
-};
-
 /* CCDM specific contants */
 enum {
 	/* NV indices */
diff --git a/cmd/tpm.c b/cmd/tpm.c
index 312503f..625fc43 100644
--- a/cmd/tpm.c
+++ b/cmd/tpm.c
@@ -646,6 +646,64 @@ TPM_COMMAND_NO_ARG(tpm_end_oiap)

 #endif /* CONFIG_TPM_AUTH_SESSIONS */

+#ifdef CONFIG_TPM_FLUSH_RESOURCES
+static int do_tpm_flush(cmd_tbl_t *cmdtp, int flag, int argc,
+			char * const argv[])
+{
+	int type = 0;
+
+	if (argc != 2)
+		return CMD_RET_USAGE;
+
+	if (strcasecmp(argv[1], "key"))
+		type = TPM_RT_KEY;
+	else if (strcasecmp(argv[1], "auth"))
+		type = TPM_RT_AUTH;
+	else if (strcasecmp(argv[1], "hash"))
+		type = TPM_RT_HASH;
+	else if (strcasecmp(argv[1], "trans"))
+		type = TPM_RT_TRANS;
+	else if (strcasecmp(argv[1], "context"))
+		type = TPM_RT_CONTEXT;
+	else if (strcasecmp(argv[1], "counter"))
+		type = TPM_RT_COUNTER;
+	else if (strcasecmp(argv[1], "delegate"))
+		type = TPM_RT_DELEGATE;
+	else if (strcasecmp(argv[1], "daa_tpm"))
+		type = TPM_RT_DAA_TPM;
+	else if (strcasecmp(argv[1], "daa_v0"))
+		type = TPM_RT_DAA_V0;
+	else if (strcasecmp(argv[1], "daa_v1"))
+		type = TPM_RT_DAA_V1;
+
+	if (strcasecmp(argv[2], "all")) {
+		uint16_t res_count;
+		uint8_t buf[288];
+		uint8_t *ptr;
+		int err;
+		uint i;
+
+		/* fetch list of already loaded resources in the TPM */
+		err = tpm_get_capability(TPM_CAP_HANDLE, type, buf,
+					 sizeof(buf));
+		if (err)
+			return -1;
+		res_count = get_unaligned_be16(buf);
+		ptr = buf + 2;
+		for (i = 0; i < res_count; ++i, ptr += 4)
+			tpm_flush_specific(get_unaligned_be32(ptr), type);
+	} else {
+		uint32_t handle = simple_strtoul(argv[2], NULL, 0);
+
+		if (!handle)
+			return -1;
+		tpm_flush_specific(cpu_to_be32(handle), type);
+	}
+
+	return 0;
+}
+#endif /* CONFIG_TPM_FLUSH_RESOURCES */
+
 #define MAKE_TPM_CMD_ENTRY(cmd) \
 	U_BOOT_CMD_MKENT(cmd, 0, 1, do_tpm_ ## cmd, "", "")

@@ -701,6 +759,10 @@ static cmd_tbl_t tpm_commands[] = {
 	U_BOOT_CMD_MKENT(get_pub_key_oiap, 0, 1,
 			 do_tpm_get_pub_key_oiap, "", ""),
 #endif /* CONFIG_TPM_AUTH_SESSIONS */
+#ifdef CONFIG_TPM_FLUSH_RESOURCES
+	U_BOOT_CMD_MKENT(flush, 0, 1,
+			 do_tpm_flush, "", ""),
+#endif /* CONFIG_TPM_FLUSH_RESOURCES */
 };

 static int do_tpm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
@@ -750,6 +812,14 @@ U_BOOT_CMD(tpm, CONFIG_SYS_MAXARGS, 1, do_tpm,
 "  get_capability cap_area sub_cap addr count\n"
 "    - Read <count> bytes of TPM capability indexed by <cap_area> and\n"
 "      <sub_cap> to memory address <addr>.\n"
+#ifdef CONFIG_TPM_FLUSH_RESOURCES
+"Resource management functions\n"
+"  flush resource_type id\n"
+"    - flushes a resource of type <resource_type> (may be one of key, auth,\n"
+"      hash, trans, context, counter, delegate, daa_tpm, daa_v0, daa_v1),\n"
+"      and id <id> from the TPM. Use an <id> of \"all\" to flush all\n"
+"      resources of that type.\n"
+#endif /* CONFIG_TPM_FLUSH_RESOURCES */
 #ifdef CONFIG_TPM_AUTH_SESSIONS
 "Storage functions\n"
 "  loadkey2_oiap parent_handle key_addr key_len usage_auth\n"
diff --git a/drivers/tpm/Kconfig b/drivers/tpm/Kconfig
index 7ab34ce..3490ee0 100644
--- a/drivers/tpm/Kconfig
+++ b/drivers/tpm/Kconfig
@@ -82,4 +82,10 @@ config TPM_ST33ZP24_SPI
 	  to the device using the standard TPM Interface Specification (TIS)
 	  protocol

+config TPM_FLUSH_RESOURCES
+	bool "Enable TPM resource flushing support"
+	depends on TPM
+	help
+	  Enable support to flush specific resources (e.g. keys) from the TPM.
+	  The functionality is available via the 'tpm' command as well.
 endmenu
diff --git a/include/tpm.h b/include/tpm.h
index 9a6585d..800f29c 100644
--- a/include/tpm.h
+++ b/include/tpm.h
@@ -47,6 +47,42 @@ enum tpm_nv_index {
 	TPM_NV_INDEX_DIR	= 0x10000001,
 };

+enum tpm_resource_type {
+	TPM_RT_KEY	= 0x00000001,
+	TPM_RT_AUTH	= 0x00000002,
+	TPM_RT_HASH	= 0x00000003,
+	TPM_RT_TRANS	= 0x00000004,
+	TPM_RT_CONTEXT	= 0x00000005,
+	TPM_RT_COUNTER	= 0x00000006,
+	TPM_RT_DELEGATE	= 0x00000007,
+	TPM_RT_DAA_TPM	= 0x00000008,
+	TPM_RT_DAA_V0	= 0x00000009,
+	TPM_RT_DAA_V1	= 0x0000000A,
+};
+
+enum tpm_capability_areas {
+	TPM_CAP_ORD		= 0x00000001,
+	TPM_CAP_ALG		= 0x00000002,
+	TPM_CAP_PID		= 0x00000003,
+	TPM_CAP_FLAG		= 0x00000004,
+	TPM_CAP_PROPERTY	= 0x00000005,
+	TPM_CAP_VERSION		= 0x00000006,
+	TPM_CAP_KEY_HANDLE	= 0x00000007,
+	TPM_CAP_CHECK_LOADED	= 0x00000008,
+	TPM_CAP_SYM_MODE	= 0x00000009,
+	TPM_CAP_KEY_STATUS	= 0x0000000C,
+	TPM_CAP_NV_LIST		= 0x0000000D,
+	TPM_CAP_MFR		= 0x00000010,
+	TPM_CAP_NV_INDEX	= 0x00000011,
+	TPM_CAP_TRANS_ALG	= 0x00000012,
+	TPM_CAP_HANDLE		= 0x00000014,
+	TPM_CAP_TRANS_ES	= 0x00000015,
+	TPM_CAP_AUTH_ENCRYPT	= 0x00000017,
+	TPM_CAP_SELECT_SIZE	= 0x00000018,
+	TPM_CAP_DA_LOGIC	= 0x00000019,
+	TPM_CAP_VERSION_VAL	= 0x0000001A,
+};
+
 #define TPM_NV_PER_GLOBALLOCK		(1U << 15)
 #define TPM_NV_PER_PPWRITE		(1U << 0)
 #define TPM_NV_PER_READ_STCLEAR		(1U << 31)
@@ -594,4 +630,13 @@ uint32_t tpm_get_permanent_flags(struct tpm_permanent_flags *pflags);
  */
 uint32_t tpm_get_permissions(uint32_t index, uint32_t *perm);

+/**
+ * Flush a resource with a given handle and type from the TPM
+ *
+ * @param key_handle           handle of the resource
+ * @param resource_type                type of the resource
+ * @return return code of the operation
+ */
+uint32_t tpm_flush_specific(uint32_t key_handle, uint32_t resource_type);
+
 #endif /* __TPM_H */
diff --git a/lib/tpm.c b/lib/tpm.c
index 88f2406..fb12214 100644
--- a/lib/tpm.c
+++ b/lib/tpm.c
@@ -645,6 +645,35 @@ uint32_t tpm_get_permissions(uint32_t index, uint32_t *perm)
 	return 0;
 }

+#ifdef CONFIG_TPM_FLUSH_RESOURCES
+uint32_t tpm_flush_specific(uint32_t key_handle, uint32_t resource_type)
+{
+	const uint8_t command[18] = {
+		0x00, 0xc1,             /* TPM_TAG */
+		0x00, 0x00, 0x00, 0x12, /* parameter size */
+		0x00, 0x00, 0x00, 0xba, /* TPM_COMMAND_CODE */
+		0x00, 0x00, 0x00, 0x00, /* key handle */
+		0x00, 0x00, 0x00, 0x00, /* resource type */
+	};
+	const size_t key_handle_offset = 10;
+	const size_t resource_type_offset = 14;
+	uint8_t buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
+	size_t response_length = sizeof(response);
+	uint32_t err;
+
+	if (pack_byte_string(buf, sizeof(buf), "sdd",
+			     0, command, sizeof(command),
+			     key_handle_offset, key_handle,
+			     resource_type_offset, resource_type))
+		return TPM_LIB_ERROR;
+
+	err = tpm_sendrecv_command(buf, response, &response_length);
+	if (err)
+		return err;
+	return 0;
+}
+#endif /* CONFIG_TPM_FLUSH_RESOURCES */
+
 #ifdef CONFIG_TPM_AUTH_SESSIONS

 /**
--
2.9.0

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [U-Boot] [PATCH v2 07/18] core: device: Add dev_get_by_ofname function
  2017-01-11 15:00 [U-Boot] [PATCH v2 00/18] arm: mvebu: Add gdsys ControlCenter-Compact board Mario Six
                   ` (5 preceding siblings ...)
  2017-01-11 15:00 ` [U-Boot] [PATCH v2 06/18] lib: tpm: Add command to flush resources Mario Six
@ 2017-01-11 15:00 ` Mario Six
  2017-01-18 16:23   ` Stefan Roese
  2017-01-11 15:00 ` [U-Boot] [PATCH v2 08/18] gpio: Add gpio_request_simple function Mario Six
                   ` (10 subsequent siblings)
  17 siblings, 1 reply; 55+ messages in thread
From: Mario Six @ 2017-01-11 15:00 UTC (permalink / raw)
  To: u-boot

On boards that use DM, it is sometimes convenient and quicker to get a device
via its device tree path, since the devices used in the board initialization
routines are usually known beforehand.

This patch adds such a convenience function.

Signed-off-by: Mario Six <mario.six@gdsys.cc>
---
Changes in v2:

New in v2
---
 drivers/core/device.c | 7 +++++++
 include/dm/device.h   | 8 ++++++++
 2 files changed, 15 insertions(+)

diff --git a/drivers/core/device.c b/drivers/core/device.c
index ed553d7..39d30b3 100644
--- a/drivers/core/device.c
+++ b/drivers/core/device.c
@@ -627,6 +627,13 @@ const char *dev_get_uclass_name(struct udevice *dev)
 	return dev->uclass->uc_drv->name;
 }

+void dev_get_by_ofname(char *ofname, struct udevice *dev)
+{
+	int offset = fdt_path_offset(gd->fdt_blob, ofname);
+
+	device_get_global_by_of_offset(offset, &dev);
+}
+
 fdt_addr_t dev_get_addr_index(struct udevice *dev, int index)
 {
 #if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)
diff --git a/include/dm/device.h b/include/dm/device.h
index 9948bd4..402482c 100644
--- a/include/dm/device.h
+++ b/include/dm/device.h
@@ -340,6 +340,14 @@ enum uclass_id device_get_uclass_id(struct udevice *dev);
 const char *dev_get_uclass_name(struct udevice *dev);

 /**
+ * dev_get_by_ofname() - find a device via its device tree path
+ *
+ * @ofname: Device tree path to use ("/path1/path2/...")
+ * @dev:    The found device or NULL
+ */
+void dev_get_by_ofname(char *ofname, struct udevice *dev);
+
+/**
  * device_get_child() - Get the child of a device by index
  *
  * Returns the numbered child, 0 being the first. This does not use
--
2.9.0

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [U-Boot] [PATCH v2 08/18] gpio: Add gpio_request_simple function
  2017-01-11 15:00 [U-Boot] [PATCH v2 00/18] arm: mvebu: Add gdsys ControlCenter-Compact board Mario Six
                   ` (6 preceding siblings ...)
  2017-01-11 15:00 ` [U-Boot] [PATCH v2 07/18] core: device: Add dev_get_by_ofname function Mario Six
@ 2017-01-11 15:00 ` Mario Six
  2017-01-18 16:34   ` Stefan Roese
  2017-01-11 15:00 ` [U-Boot] [PATCH v2 09/18] tools: kwbimage: Fix dest addr Mario Six
                   ` (9 subsequent siblings)
  17 siblings, 1 reply; 55+ messages in thread
From: Mario Six @ 2017-01-11 15:00 UTC (permalink / raw)
  To: u-boot

For board initialization, usage of GPIOs is sometimes needed, e.g. to
initialize certain devices such as FPGAs. But since there currently is no
device associated to the board itself, initialization routines have to
cumbersomely get GPIOs via gpio_request_by_name_nodev.

This patch adds a convenience function aimed at such scenarios, which wraps the
gpio_request_by_name_nodev and some error checking. The GPIO is identified via
its compatible string in the device tree.

Signed-off-by: Mario Six <mario.six@gdsys.cc>
---
Changes in v2:

New in v2
---
 drivers/gpio/gpio-uclass.c | 17 +++++++++++++++++
 include/asm-generic/gpio.h | 22 ++++++++++++++++++++++
 2 files changed, 39 insertions(+)

diff --git a/drivers/gpio/gpio-uclass.c b/drivers/gpio/gpio-uclass.c
index 4559739..197d987 100644
--- a/drivers/gpio/gpio-uclass.c
+++ b/drivers/gpio/gpio-uclass.c
@@ -751,6 +751,23 @@ int gpio_request_list_by_name(struct udevice *dev, const char *list_name,
 					       flags);
 }

+bool gpio_request_simple(char *name, struct gpio_desc *gpio)
+{
+	int node = fdt_node_offset_by_compatible(gd->fdt_blob, 0, name);
+	int ret;
+
+	if (node < 0)
+		return false;
+
+	ret = gpio_request_by_name_nodev(gd->fdt_blob, node, "gpios", 0, gpio,
+					 0);
+
+	if (ret < 0)
+		return false;
+
+	return dm_gpio_is_valid(gpio);
+}
+
 int gpio_get_list_count(struct udevice *dev, const char *list_name)
 {
 	int ret;
diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h
index 4aa0004..5c3e599 100644
--- a/include/asm-generic/gpio.h
+++ b/include/asm-generic/gpio.h
@@ -457,6 +457,28 @@ int gpio_request_list_by_name(struct udevice *dev, const char *list_name,
 			      int flags);

 /**
+ * gpio_request_simple() - Simple wrapper function to request GPIO via
+ *                         fdt compatible name
+ *
+ * Convenience method to get useable GPIO description information from a device
+ * tree declaration such as:
+ *
+ *   fpga_ready_gpio {
+ *       compatible = "generic,fpga-ready-gpio";
+ *       gpios = <&PCA22 27 0>;
+ *   };
+ *
+ * This is convenient for setting and reading GPIOs from board files (where no
+ * associated device is in play).
+ *
+ * @name: The fdt compatible string of the GPIO in question
+ * @gpio: Return the GPIO description information of the GPIO in question
+ *
+ * @return true if the operation succeeded, false if not
+ */
+bool gpio_request_simple(char *name, struct gpio_desc *gpio);
+
+/**
  * dm_gpio_request() - manually request a GPIO
  *
  * Note: This function should only be used for testing / debugging. Instead.
--
2.9.0

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [U-Boot] [PATCH v2 09/18] tools: kwbimage: Fix dest addr
  2017-01-11 15:00 [U-Boot] [PATCH v2 00/18] arm: mvebu: Add gdsys ControlCenter-Compact board Mario Six
                   ` (7 preceding siblings ...)
  2017-01-11 15:00 ` [U-Boot] [PATCH v2 08/18] gpio: Add gpio_request_simple function Mario Six
@ 2017-01-11 15:00 ` Mario Six
  2017-01-18 16:36   ` Stefan Roese
  2017-02-01 11:41   ` Stefan Roese
  2017-01-11 15:00 ` [U-Boot] [PATCH v2 10/18] tools: kwbimage: Fix style violations Mario Six
                   ` (8 subsequent siblings)
  17 siblings, 2 replies; 55+ messages in thread
From: Mario Six @ 2017-01-11 15:00 UTC (permalink / raw)
  To: u-boot

To enable secure boot, we need to jump back into the BootROM to continue
the SoC's boot process instead of letting the SPL load and run the main
U-Boot image.

But, since the u-boot-spl.img (including the 64 byte header) is loaded
by the SoC as the main image, we need to compensate for the header
length to get a correct entry point.

Thus, we subtract the header size from the destination address, so that
the execution address points at the actual entry point of the image.

The current boards ignore both parameters anyway, so this change shouldn't
concern them.

Signed-off-by: Mario Six <mario.six@gdsys.cc>
---
Changes in v2:

None
---
 tools/kwbimage.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/tools/kwbimage.c b/tools/kwbimage.c
index 69844d9..e04d319 100644
--- a/tools/kwbimage.c
+++ b/tools/kwbimage.c
@@ -410,7 +410,8 @@ static void *image_create_v1(size_t *imagesz, struct image_tool_params *params,
 		cpu_to_le32(payloadsz - headersz + sizeof(uint32_t));
 	main_hdr->headersz_lsb = cpu_to_le16(headersz & 0xFFFF);
 	main_hdr->headersz_msb = (headersz & 0xFFFF0000) >> 16;
-	main_hdr->destaddr     = cpu_to_le32(params->addr);
+	main_hdr->destaddr     = cpu_to_le32(params->addr)
+				 - sizeof(image_header_t);
 	main_hdr->execaddr     = cpu_to_le32(params->ep);
 	main_hdr->srcaddr      = cpu_to_le32(headersz);
 	main_hdr->ext          = hasext;
--
2.9.0

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [U-Boot] [PATCH v2 10/18] tools: kwbimage: Fix style violations
  2017-01-11 15:00 [U-Boot] [PATCH v2 00/18] arm: mvebu: Add gdsys ControlCenter-Compact board Mario Six
                   ` (8 preceding siblings ...)
  2017-01-11 15:00 ` [U-Boot] [PATCH v2 09/18] tools: kwbimage: Fix dest addr Mario Six
@ 2017-01-11 15:00 ` Mario Six
  2017-01-18 16:37   ` Stefan Roese
  2017-02-01 11:41   ` Stefan Roese
  2017-01-11 15:00 ` [U-Boot] [PATCH v2 11/18] tools: kwbimage: Fix arithmetic with void pointers Mario Six
                   ` (7 subsequent siblings)
  17 siblings, 2 replies; 55+ messages in thread
From: Mario Six @ 2017-01-11 15:00 UTC (permalink / raw)
  To: u-boot

Fix some style violations:

- nine instances of missing blank lines after declarations
- one overly long line
- one split string (which also rewords an error message more concisely)
- two superfluous else

Signed-off-by: Mario Six <mario.six@gdsys.cc>
---
Changes in v2:

None
---
 tools/kwbimage.c | 25 +++++++++++++++++--------
 1 file changed, 17 insertions(+), 8 deletions(-)

diff --git a/tools/kwbimage.c b/tools/kwbimage.c
index e04d319..0e7c96a 100644
--- a/tools/kwbimage.c
+++ b/tools/kwbimage.c
@@ -103,6 +103,7 @@ struct image_cfg_element {
 static const char *image_boot_mode_name(unsigned int id)
 {
 	int i;
+
 	for (i = 0; boot_modes[i].name; i++)
 		if (boot_modes[i].id == id)
 			return boot_modes[i].name;
@@ -112,6 +113,7 @@ static const char *image_boot_mode_name(unsigned int id)
 int image_boot_mode_id(const char *boot_mode_name)
 {
 	int i;
+
 	for (i = 0; boot_modes[i].name; i++)
 		if (!strcmp(boot_modes[i].name, boot_mode_name))
 			return boot_modes[i].id;
@@ -122,6 +124,7 @@ int image_boot_mode_id(const char *boot_mode_name)
 int image_nand_ecc_mode_id(const char *nand_ecc_mode_name)
 {
 	int i;
+
 	for (i = 0; nand_ecc_modes[i].name; i++)
 		if (!strcmp(nand_ecc_modes[i].name, nand_ecc_mode_name))
 			return nand_ecc_modes[i].id;
@@ -359,14 +362,14 @@ static size_t image_headersz_v1(struct image_tool_params *params,

 #if defined(CONFIG_SYS_U_BOOT_OFFS)
 	if (headersz > CONFIG_SYS_U_BOOT_OFFS) {
-		fprintf(stderr, "Error: Image header (incl. SPL image) too big!\n");
+		fprintf(stderr,
+			"Error: Image header (incl. SPL image) too big!\n");
 		fprintf(stderr, "header=0x%x CONFIG_SYS_U_BOOT_OFFS=0x%x!\n",
 			(int)headersz, CONFIG_SYS_U_BOOT_OFFS);
 		fprintf(stderr, "Increase CONFIG_SYS_U_BOOT_OFFS!\n");
 		return 0;
-	} else {
-		headersz = CONFIG_SYS_U_BOOT_OFFS;
 	}
+	headersz = CONFIG_SYS_U_BOOT_OFFS;
 #endif

 	/*
@@ -514,11 +517,13 @@ static int image_create_config_parse_oneline(char *line,
 	keyword = strtok_r(line, deliminiters, &saveptr);
 	if (!strcmp(keyword, "VERSION")) {
 		char *value = strtok_r(NULL, deliminiters, &saveptr);
+
 		el->type = IMAGE_CFG_VERSION;
 		el->version = atoi(value);
 	} else if (!strcmp(keyword, "BOOT_FROM")) {
 		char *value = strtok_r(NULL, deliminiters, &saveptr);
 		int ret = image_boot_mode_id(value);
+
 		if (ret < 0) {
 			fprintf(stderr,
 				"Invalid boot media '%s'\n", value);
@@ -528,16 +533,19 @@ static int image_create_config_parse_oneline(char *line,
 		el->bootfrom = ret;
 	} else if (!strcmp(keyword, "NAND_BLKSZ")) {
 		char *value = strtok_r(NULL, deliminiters, &saveptr);
+
 		el->type = IMAGE_CFG_NAND_BLKSZ;
 		el->nandblksz = strtoul(value, NULL, 16);
 	} else if (!strcmp(keyword, "NAND_BADBLK_LOCATION")) {
 		char *value = strtok_r(NULL, deliminiters, &saveptr);
+
 		el->type = IMAGE_CFG_NAND_BADBLK_LOCATION;
 		el->nandbadblklocation =
 			strtoul(value, NULL, 16);
 	} else if (!strcmp(keyword, "NAND_ECC_MODE")) {
 		char *value = strtok_r(NULL, deliminiters, &saveptr);
 		int ret = image_nand_ecc_mode_id(value);
+
 		if (ret < 0) {
 			fprintf(stderr,
 				"Invalid NAND ECC mode '%s'\n", value);
@@ -547,6 +555,7 @@ static int image_create_config_parse_oneline(char *line,
 		el->nandeccmode = ret;
 	} else if (!strcmp(keyword, "NAND_PAGE_SIZE")) {
 		char *value = strtok_r(NULL, deliminiters, &saveptr);
+
 		el->type = IMAGE_CFG_NAND_PAGESZ;
 		el->nandpagesz = strtoul(value, NULL, 16);
 	} else if (!strcmp(keyword, "BINARY")) {
@@ -800,8 +809,8 @@ static int kwbimage_check_image_types(uint8_t type)
 {
 	if (type == IH_TYPE_KWBIMAGE)
 		return EXIT_SUCCESS;
-	else
-		return EXIT_FAILURE;
+
+	return EXIT_FAILURE;
 }

 static int kwbimage_verify_header(unsigned char *ptr, int image_size,
@@ -874,9 +883,9 @@ static int kwbimage_generate(struct image_tool_params *params,
 static int kwbimage_check_params(struct image_tool_params *params)
 {
 	if (!strlen(params->imagename)) {
-		fprintf(stderr, "Error:%s - Configuration file not specified, "
-			"it is needed for kwbimage generation\n",
-			params->cmdname);
+		char *msg = "Configuration file for kwbimage creation omitted";
+
+		fprintf(stderr, "Error:%s - %s\n", params->cmdname, msg);
 		return CFG_INVALID;
 	}

--
2.9.0

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [U-Boot] [PATCH v2 11/18] tools: kwbimage: Fix arithmetic with void pointers
  2017-01-11 15:00 [U-Boot] [PATCH v2 00/18] arm: mvebu: Add gdsys ControlCenter-Compact board Mario Six
                   ` (9 preceding siblings ...)
  2017-01-11 15:00 ` [U-Boot] [PATCH v2 10/18] tools: kwbimage: Fix style violations Mario Six
@ 2017-01-11 15:00 ` Mario Six
  2017-01-18 16:38   ` Stefan Roese
  2017-02-01 11:41   ` Stefan Roese
  2017-01-11 15:00 ` [U-Boot] [PATCH v2 12/18] tools: kwbimage: Reduce scope of variables Mario Six
                   ` (6 subsequent siblings)
  17 siblings, 2 replies; 55+ messages in thread
From: Mario Six @ 2017-01-11 15:00 UTC (permalink / raw)
  To: u-boot

Arithmetic with void pointers, e.g. a - b where both a and b are void
pointers, is undefined in the C standard. Since we are operating with
byte data here, we switch the void pointers to uint8_t pointers, and add
the necessary casts.

Signed-off-by: Mario Six <mario.six@gdsys.cc>
---
Changes in v2:

None
---
 tools/kwbimage.c | 22 ++++++++++++----------
 1 file changed, 12 insertions(+), 10 deletions(-)

diff --git a/tools/kwbimage.c b/tools/kwbimage.c
index 0e7c96a..edc5d34 100644
--- a/tools/kwbimage.c
+++ b/tools/kwbimage.c
@@ -231,7 +231,7 @@ static void *image_create_v0(size_t *imagesz, struct image_tool_params *params,
 	size_t headersz;
 	struct main_hdr_v0 *main_hdr;
 	struct ext_hdr_v0 *ext_hdr;
-	void *image;
+	uint8_t *image;
 	int has_ext = 0;

 	/*
@@ -258,7 +258,7 @@ static void *image_create_v0(size_t *imagesz, struct image_tool_params *params,

 	memset(image, 0, headersz);

-	main_hdr = image;
+	main_hdr = (struct main_hdr_v0 *)image;

 	/* Fill in the main header */
 	main_hdr->blocksize =
@@ -284,7 +284,8 @@ static void *image_create_v0(size_t *imagesz, struct image_tool_params *params,
 	if (has_ext) {
 		int cfgi, datai;

-		ext_hdr = image + sizeof(struct main_hdr_v0);
+		ext_hdr = (struct ext_hdr_v0 *)
+				(image + sizeof(struct main_hdr_v0));
 		ext_hdr->offset = cpu_to_le32(0x40);

 		for (cfgi = 0, datai = 0; cfgi < cfgn; cfgi++) {
@@ -385,7 +386,7 @@ static void *image_create_v1(size_t *imagesz, struct image_tool_params *params,
 	struct image_cfg_element *e, *binarye;
 	struct main_hdr_v1 *main_hdr;
 	size_t headersz;
-	void *image, *cur;
+	uint8_t *image, *cur;
 	int hasext = 0;
 	int ret;

@@ -405,8 +406,8 @@ static void *image_create_v1(size_t *imagesz, struct image_tool_params *params,

 	memset(image, 0, headersz);

-	cur = main_hdr = image;
-	cur += sizeof(struct main_hdr_v1);
+	main_hdr = (struct main_hdr_v1 *)image;
+	cur = image + sizeof(struct main_hdr_v1);

 	/* Fill the main header */
 	main_hdr->blocksize    =
@@ -437,7 +438,7 @@ static void *image_create_v1(size_t *imagesz, struct image_tool_params *params,

 	binarye = image_find_option(IMAGE_CFG_BINARY);
 	if (binarye) {
-		struct opt_hdr_v1 *hdr = cur;
+		struct opt_hdr_v1 *hdr = (struct opt_hdr_v1 *)cur;
 		uint32_t *args;
 		size_t binhdrsz;
 		struct stat s;
@@ -470,7 +471,7 @@ static void *image_create_v1(size_t *imagesz, struct image_tool_params *params,

 		cur += sizeof(struct opt_hdr_v1);

-		args = cur;
+		args = (uint32_t *)cur;
 		*args = cpu_to_le32(binarye->binary.nargs);
 		args++;
 		for (argi = 0; argi < binarye->binary.nargs; argi++)
@@ -820,7 +821,7 @@ static int kwbimage_verify_header(unsigned char *ptr, int image_size,
 	struct ext_hdr_v0 *ext_hdr;
 	uint8_t checksum;

-	main_hdr = (void *)ptr;
+	main_hdr = (struct main_hdr_v0 *)ptr;
 	checksum = image_checksum8(ptr,
 				   sizeof(struct main_hdr_v0)
 				   - sizeof(uint8_t));
@@ -829,7 +830,8 @@ static int kwbimage_verify_header(unsigned char *ptr, int image_size,

 	/* Only version 0 extended header has checksum */
 	if (image_version((void *)ptr) == 0) {
-		ext_hdr = (void *)ptr + sizeof(struct main_hdr_v0);
+		ext_hdr = (struct ext_hdr_v0 *)
+				(ptr + sizeof(struct main_hdr_v0));
 		checksum = image_checksum8(ext_hdr,
 					   sizeof(struct ext_hdr_v0)
 					   - sizeof(uint8_t));
--
2.9.0

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [U-Boot] [PATCH v2 12/18] tools: kwbimage: Reduce scope of variables
  2017-01-11 15:00 [U-Boot] [PATCH v2 00/18] arm: mvebu: Add gdsys ControlCenter-Compact board Mario Six
                   ` (10 preceding siblings ...)
  2017-01-11 15:00 ` [U-Boot] [PATCH v2 11/18] tools: kwbimage: Fix arithmetic with void pointers Mario Six
@ 2017-01-11 15:00 ` Mario Six
  2017-01-18 16:39   ` Stefan Roese
  2017-02-01 11:41   ` Stefan Roese
  2017-01-11 15:00 ` [U-Boot] [PATCH v2 13/18] tools: kwbimage: Remove unused parameter Mario Six
                   ` (5 subsequent siblings)
  17 siblings, 2 replies; 55+ messages in thread
From: Mario Six @ 2017-01-11 15:00 UTC (permalink / raw)
  To: u-boot

This patch reduces the scope of some variables.

Signed-off-by: Mario Six <mario.six@gdsys.cc>
---
Changes in v2:

None
---
 tools/kwbimage.c | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/tools/kwbimage.c b/tools/kwbimage.c
index edc5d34..4fd9389 100644
--- a/tools/kwbimage.c
+++ b/tools/kwbimage.c
@@ -230,7 +230,6 @@ static void *image_create_v0(size_t *imagesz, struct image_tool_params *params,
 	struct image_cfg_element *e;
 	size_t headersz;
 	struct main_hdr_v0 *main_hdr;
-	struct ext_hdr_v0 *ext_hdr;
 	uint8_t *image;
 	int has_ext = 0;

@@ -282,6 +281,7 @@ static void *image_create_v0(size_t *imagesz, struct image_tool_params *params,

 	/* Generate the ext header */
 	if (has_ext) {
+		struct ext_hdr_v0 *ext_hdr;
 		int cfgi, datai;

 		ext_hdr = (struct ext_hdr_v0 *)
@@ -313,7 +313,6 @@ static size_t image_headersz_v1(struct image_tool_params *params,
 {
 	struct image_cfg_element *binarye;
 	size_t headersz;
-	int ret;

 	/*
 	 * Calculate the size of the header and the size of the
@@ -333,6 +332,7 @@ static size_t image_headersz_v1(struct image_tool_params *params,

 	binarye = image_find_option(IMAGE_CFG_BINARY);
 	if (binarye) {
+		int ret;
 		struct stat s;

 		ret = stat(binarye->binary.file, &s);
@@ -388,7 +388,6 @@ static void *image_create_v1(size_t *imagesz, struct image_tool_params *params,
 	size_t headersz;
 	uint8_t *image, *cur;
 	int hasext = 0;
-	int ret;

 	/*
 	 * Calculate the size of the header and the size of the
@@ -444,6 +443,7 @@ static void *image_create_v1(size_t *imagesz, struct image_tool_params *params,
 		struct stat s;
 		int argi;
 		FILE *bin;
+		int ret;

 		hdr->headertype = OPT_HDR_V1_BINARY_TYPE;

@@ -818,7 +818,6 @@ static int kwbimage_verify_header(unsigned char *ptr, int image_size,
 				  struct image_tool_params *params)
 {
 	struct main_hdr_v0 *main_hdr;
-	struct ext_hdr_v0 *ext_hdr;
 	uint8_t checksum;

 	main_hdr = (struct main_hdr_v0 *)ptr;
@@ -830,6 +829,8 @@ static int kwbimage_verify_header(unsigned char *ptr, int image_size,

 	/* Only version 0 extended header has checksum */
 	if (image_version((void *)ptr) == 0) {
+		struct ext_hdr_v0 *ext_hdr;
+
 		ext_hdr = (struct ext_hdr_v0 *)
 				(ptr + sizeof(struct main_hdr_v0));
 		checksum = image_checksum8(ext_hdr,
--
2.9.0

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [U-Boot] [PATCH v2 13/18] tools: kwbimage: Remove unused parameter
  2017-01-11 15:00 [U-Boot] [PATCH v2 00/18] arm: mvebu: Add gdsys ControlCenter-Compact board Mario Six
                   ` (11 preceding siblings ...)
  2017-01-11 15:00 ` [U-Boot] [PATCH v2 12/18] tools: kwbimage: Reduce scope of variables Mario Six
@ 2017-01-11 15:00 ` Mario Six
  2017-01-18 16:39   ` Stefan Roese
  2017-02-01 11:42   ` Stefan Roese
  2017-01-11 15:00 ` [U-Boot] [PATCH v2 14/18] tools: kwbimage: Factor out add_binary_header_v1 Mario Six
                   ` (4 subsequent siblings)
  17 siblings, 2 replies; 55+ messages in thread
From: Mario Six @ 2017-01-11 15:00 UTC (permalink / raw)
  To: u-boot

The parameter 'params' of the image_headersz_v1 function is never used
by the function.

Hence, remove it.

Signed-off-by: Mario Six <mario.six@gdsys.cc>
---
Changes in v2:

None
---
 tools/kwbimage.c | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/tools/kwbimage.c b/tools/kwbimage.c
index 4fd9389..87587f8 100644
--- a/tools/kwbimage.c
+++ b/tools/kwbimage.c
@@ -308,8 +308,7 @@ static void *image_create_v0(size_t *imagesz, struct image_tool_params *params,
 	return image;
 }

-static size_t image_headersz_v1(struct image_tool_params *params,
-				int *hasext)
+static size_t image_headersz_v1(int *hasext)
 {
 	struct image_cfg_element *binarye;
 	size_t headersz;
@@ -393,7 +392,7 @@ static void *image_create_v1(size_t *imagesz, struct image_tool_params *params,
 	 * Calculate the size of the header and the size of the
 	 * payload
 	 */
-	headersz = image_headersz_v1(params, &hasext);
+	headersz = image_headersz_v1(&hasext);
 	if (headersz == 0)
 		return NULL;

@@ -855,7 +854,7 @@ static int kwbimage_generate(struct image_tool_params *params,
 		alloc_len = sizeof(struct main_hdr_v0) +
 			sizeof(struct ext_hdr_v0);
 	} else {
-		alloc_len = image_headersz_v1(params, NULL);
+		alloc_len = image_headersz_v1(NULL);
 	}

 	hdr = malloc(alloc_len);
--
2.9.0

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [U-Boot] [PATCH v2 14/18] tools: kwbimage: Factor out add_binary_header_v1
  2017-01-11 15:00 [U-Boot] [PATCH v2 00/18] arm: mvebu: Add gdsys ControlCenter-Compact board Mario Six
                   ` (12 preceding siblings ...)
  2017-01-11 15:00 ` [U-Boot] [PATCH v2 13/18] tools: kwbimage: Remove unused parameter Mario Six
@ 2017-01-11 15:00 ` Mario Six
  2017-01-18 16:40   ` Stefan Roese
  2017-02-01 11:42   ` Stefan Roese
  2017-01-11 15:00 ` [U-Boot] [PATCH v2 15/18] tools: kwbimage: Refactor line parsing and fix error Mario Six
                   ` (3 subsequent siblings)
  17 siblings, 2 replies; 55+ messages in thread
From: Mario Six @ 2017-01-11 15:00 UTC (permalink / raw)
  To: u-boot

In preparation of adding the creation of secure headers, we factor the
add_binary_header_v1 function out of the image_create_v1 function.

Signed-off-by: Mario Six <mario.six@gdsys.cc>
---
Changes in v2:

None
---
 tools/kwbimage.c | 146 ++++++++++++++++++++++++++++++-------------------------
 1 file changed, 79 insertions(+), 67 deletions(-)

diff --git a/tools/kwbimage.c b/tools/kwbimage.c
index 87587f8..6cd4c34 100644
--- a/tools/kwbimage.c
+++ b/tools/kwbimage.c
@@ -369,6 +369,7 @@ static size_t image_headersz_v1(int *hasext)
 		fprintf(stderr, "Increase CONFIG_SYS_U_BOOT_OFFS!\n");
 		return 0;
 	}
+
 	headersz = CONFIG_SYS_U_BOOT_OFFS;
 #endif

@@ -379,10 +380,85 @@ static size_t image_headersz_v1(int *hasext)
 	return ALIGN_SUP(headersz, 4096);
 }

+int add_binary_header_v1(uint8_t *cur)
+{
+	struct image_cfg_element *binarye;
+	struct opt_hdr_v1 *hdr = (struct opt_hdr_v1 *)cur;
+	uint32_t *args;
+	size_t binhdrsz;
+	struct stat s;
+	int argi;
+	FILE *bin;
+	int ret;
+
+	binarye = image_find_option(IMAGE_CFG_BINARY);
+
+	if (!binarye)
+		return 0;
+
+	hdr->headertype = OPT_HDR_V1_BINARY_TYPE;
+
+	bin = fopen(binarye->binary.file, "r");
+	if (!bin) {
+		fprintf(stderr, "Cannot open binary file %s\n",
+			binarye->binary.file);
+		return -1;
+	}
+
+	fstat(fileno(bin), &s);
+
+	binhdrsz = sizeof(struct opt_hdr_v1) +
+		(binarye->binary.nargs + 2) * sizeof(uint32_t) +
+		s.st_size;
+
+	/*
+	 * The size includes the binary image size, rounded
+	 * up to a 4-byte boundary. Plus 4 bytes for the
+	 * next-header byte and 3-byte alignment at the end.
+	 */
+	binhdrsz = ALIGN_SUP(binhdrsz, 4) + 4;
+	hdr->headersz_lsb = cpu_to_le16(binhdrsz & 0xFFFF);
+	hdr->headersz_msb = (binhdrsz & 0xFFFF0000) >> 16;
+
+	cur += sizeof(struct opt_hdr_v1);
+
+	args = (uint32_t *)cur;
+	*args = cpu_to_le32(binarye->binary.nargs);
+	args++;
+	for (argi = 0; argi < binarye->binary.nargs; argi++)
+		args[argi] = cpu_to_le32(binarye->binary.args[argi]);
+
+	cur += (binarye->binary.nargs + 1) * sizeof(uint32_t);
+
+	ret = fread(cur, s.st_size, 1, bin);
+	if (ret != 1) {
+		fprintf(stderr,
+			"Could not read binary image %s\n",
+			binarye->binary.file);
+		return -1;
+	}
+
+	fclose(bin);
+
+	cur += ALIGN_SUP(s.st_size, 4);
+
+	/*
+	 * For now, we don't support more than one binary
+	 * header, and no other header types are
+	 * supported. So, the binary header is necessarily the
+	 * last one
+	 */
+	*((uint32_t *)cur) = 0x00000000;
+
+	cur += sizeof(uint32_t);
+
+	return 0;
+}
+
 static void *image_create_v1(size_t *imagesz, struct image_tool_params *params,
 			     int payloadsz)
 {
-	struct image_cfg_element *e, *binarye;
+	struct image_cfg_element *e;
 	struct main_hdr_v1 *main_hdr;
 	size_t headersz;
 	uint8_t *image, *cur;
@@ -434,72 +510,8 @@ static void *image_create_v1(size_t *imagesz, struct image_tool_params *params,
 	if (e)
 		main_hdr->flags = e->debug ? 0x1 : 0;

-	binarye = image_find_option(IMAGE_CFG_BINARY);
-	if (binarye) {
-		struct opt_hdr_v1 *hdr = (struct opt_hdr_v1 *)cur;
-		uint32_t *args;
-		size_t binhdrsz;
-		struct stat s;
-		int argi;
-		FILE *bin;
-		int ret;
-
-		hdr->headertype = OPT_HDR_V1_BINARY_TYPE;
-
-		bin = fopen(binarye->binary.file, "r");
-		if (!bin) {
-			fprintf(stderr, "Cannot open binary file %s\n",
-				binarye->binary.file);
-			return NULL;
-		}
-
-		fstat(fileno(bin), &s);
-
-		binhdrsz = sizeof(struct opt_hdr_v1) +
-			(binarye->binary.nargs + 2) * sizeof(uint32_t) +
-			s.st_size;
-
-		/*
-		 * The size includes the binary image size, rounded
-		 * up to a 4-byte boundary. Plus 4 bytes for the
-		 * next-header byte and 3-byte alignment at the end.
-		 */
-		binhdrsz = ALIGN_SUP(binhdrsz, 4) + 4;
-		hdr->headersz_lsb = cpu_to_le16(binhdrsz & 0xFFFF);
-		hdr->headersz_msb = (binhdrsz & 0xFFFF0000) >> 16;
-
-		cur += sizeof(struct opt_hdr_v1);
-
-		args = (uint32_t *)cur;
-		*args = cpu_to_le32(binarye->binary.nargs);
-		args++;
-		for (argi = 0; argi < binarye->binary.nargs; argi++)
-			args[argi] = cpu_to_le32(binarye->binary.args[argi]);
-
-		cur += (binarye->binary.nargs + 1) * sizeof(uint32_t);
-
-		ret = fread(cur, s.st_size, 1, bin);
-		if (ret != 1) {
-			fprintf(stderr,
-				"Could not read binary image %s\n",
-				binarye->binary.file);
-			return NULL;
-		}
-
-		fclose(bin);
-
-		cur += ALIGN_SUP(s.st_size, 4);
-
-		/*
-		 * For now, we don't support more than one binary
-		 * header, and no other header types are
-		 * supported. So, the binary header is necessarily the
-		 * last one
-		 */
-		*((uint32_t *)cur) = 0x00000000;
-
-		cur += sizeof(uint32_t);
-	}
+	if (add_binary_header_v1(cur))
+		return NULL;

 	/* Calculate and set the header checksum */
 	main_hdr->checksum = image_checksum8(main_hdr, headersz);
--
2.9.0

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [U-Boot] [PATCH v2 15/18] tools: kwbimage: Refactor line parsing and fix error
  2017-01-11 15:00 [U-Boot] [PATCH v2 00/18] arm: mvebu: Add gdsys ControlCenter-Compact board Mario Six
                   ` (13 preceding siblings ...)
  2017-01-11 15:00 ` [U-Boot] [PATCH v2 14/18] tools: kwbimage: Factor out add_binary_header_v1 Mario Six
@ 2017-01-11 15:00 ` Mario Six
  2017-01-18 16:47   ` Stefan Roese
  2017-02-01 11:42   ` Stefan Roese
  2017-01-11 15:01 ` [U-Boot] [PATCH v2 16/18] arm: mvebu: Implement secure boot Mario Six
                   ` (2 subsequent siblings)
  17 siblings, 2 replies; 55+ messages in thread
From: Mario Six @ 2017-01-11 15:00 UTC (permalink / raw)
  To: u-boot

The function image_create_config_parse_oneline is pretty complex, and
since more parameters will be added to support secure booting, we
refactor the function to make it more readable.

Also, when a line contained just a keyword without any parameters,
strtok_r returned NULL, which was then indiscriminately fed into atoi,
causing a segfault. To correct this, we add a NULL check before feeding
the extracted token to atoi, and print an error message in case the
token is NULL.

Signed-off-by: Mario Six <mario.six@gdsys.cc>
---
Changes in v2:

None
---
 tools/kwbimage.c | 177 +++++++++++++++++++++++++++++++++----------------------
 1 file changed, 106 insertions(+), 71 deletions(-)

diff --git a/tools/kwbimage.c b/tools/kwbimage.c
index 6cd4c34..9aa9c74 100644
--- a/tools/kwbimage.c
+++ b/tools/kwbimage.c
@@ -55,22 +55,43 @@ struct nand_ecc_mode nand_ecc_modes[] = {
 #define BINARY_MAX_ARGS 8

 /* In-memory representation of a line of the configuration file */
+
+enum image_cfg_type {
+	IMAGE_CFG_VERSION = 0x1,
+	IMAGE_CFG_BOOT_FROM,
+	IMAGE_CFG_DEST_ADDR,
+	IMAGE_CFG_EXEC_ADDR,
+	IMAGE_CFG_NAND_BLKSZ,
+	IMAGE_CFG_NAND_BADBLK_LOCATION,
+	IMAGE_CFG_NAND_ECC_MODE,
+	IMAGE_CFG_NAND_PAGESZ,
+	IMAGE_CFG_BINARY,
+	IMAGE_CFG_PAYLOAD,
+	IMAGE_CFG_DATA,
+	IMAGE_CFG_BAUDRATE,
+	IMAGE_CFG_DEBUG,
+
+	IMAGE_CFG_COUNT
+} type;
+
+static const char * const id_strs[] = {
+	[IMAGE_CFG_VERSION] = "VERSION",
+	[IMAGE_CFG_BOOT_FROM] = "BOOT_FROM",
+	[IMAGE_CFG_DEST_ADDR] = "DEST_ADDR",
+	[IMAGE_CFG_EXEC_ADDR] = "EXEC_ADDR",
+	[IMAGE_CFG_NAND_BLKSZ] = "NAND_BLKSZ",
+	[IMAGE_CFG_NAND_BADBLK_LOCATION] = "NAND_BADBLK_LOCATION",
+	[IMAGE_CFG_NAND_ECC_MODE] = "NAND_ECC_MODE",
+	[IMAGE_CFG_NAND_PAGESZ] = "NAND_PAGE_SIZE",
+	[IMAGE_CFG_BINARY] = "BINARY",
+	[IMAGE_CFG_PAYLOAD] = "PAYLOAD",
+	[IMAGE_CFG_DATA] = "DATA",
+	[IMAGE_CFG_BAUDRATE] = "BAUDRATE",
+	[IMAGE_CFG_DEBUG] = "DEBUG",
+};
+
 struct image_cfg_element {
-	enum {
-		IMAGE_CFG_VERSION = 0x1,
-		IMAGE_CFG_BOOT_FROM,
-		IMAGE_CFG_DEST_ADDR,
-		IMAGE_CFG_EXEC_ADDR,
-		IMAGE_CFG_NAND_BLKSZ,
-		IMAGE_CFG_NAND_BADBLK_LOCATION,
-		IMAGE_CFG_NAND_ECC_MODE,
-		IMAGE_CFG_NAND_PAGESZ,
-		IMAGE_CFG_BINARY,
-		IMAGE_CFG_PAYLOAD,
-		IMAGE_CFG_DATA,
-		IMAGE_CFG_BAUDRATE,
-		IMAGE_CFG_DEBUG,
-	} type;
+	enum image_cfg_type type;
 	union {
 		unsigned int version;
 		unsigned int bootfrom;
@@ -520,78 +541,94 @@ static void *image_create_v1(size_t *imagesz, struct image_tool_params *params,
 	return image;
 }

+int recognize_keyword(char *keyword)
+{
+	int kw_id;
+
+	for (kw_id = 1; kw_id < IMAGE_CFG_COUNT; ++kw_id)
+		if (!strcmp(keyword, id_strs[kw_id]))
+			return kw_id;
+
+	return 0;
+}
+
 static int image_create_config_parse_oneline(char *line,
 					     struct image_cfg_element *el)
 {
-	char *keyword, *saveptr;
-	char deliminiters[] = " \t";
+	char *keyword, *saveptr, *value1, *value2;
+	char delimiters[] = " \t";
+	int keyword_id, ret, argi;
+	char *unknown_msg = "Ignoring unknown line '%s'\n";

-	keyword = strtok_r(line, deliminiters, &saveptr);
-	if (!strcmp(keyword, "VERSION")) {
-		char *value = strtok_r(NULL, deliminiters, &saveptr);
+	keyword = strtok_r(line, delimiters, &saveptr);
+	keyword_id = recognize_keyword(keyword);

-		el->type = IMAGE_CFG_VERSION;
-		el->version = atoi(value);
-	} else if (!strcmp(keyword, "BOOT_FROM")) {
-		char *value = strtok_r(NULL, deliminiters, &saveptr);
-		int ret = image_boot_mode_id(value);
+	if (!keyword_id) {
+		fprintf(stderr, unknown_msg, line);
+		return 0;
+	}
+
+	el->type = keyword_id;
+
+	value1 = strtok_r(NULL, delimiters, &saveptr);
+
+	if (!value1) {
+		fprintf(stderr, "Parameter missing in line '%s'\n", line);
+		return -1;
+	}
+
+	switch (keyword_id) {
+	case IMAGE_CFG_VERSION:
+		el->version = atoi(value1);
+		break;
+	case IMAGE_CFG_BOOT_FROM:
+		ret = image_boot_mode_id(value1);

 		if (ret < 0) {
-			fprintf(stderr,
-				"Invalid boot media '%s'\n", value);
+			fprintf(stderr, "Invalid boot media '%s'\n", value1);
 			return -1;
 		}
-		el->type = IMAGE_CFG_BOOT_FROM;
 		el->bootfrom = ret;
-	} else if (!strcmp(keyword, "NAND_BLKSZ")) {
-		char *value = strtok_r(NULL, deliminiters, &saveptr);
-
-		el->type = IMAGE_CFG_NAND_BLKSZ;
-		el->nandblksz = strtoul(value, NULL, 16);
-	} else if (!strcmp(keyword, "NAND_BADBLK_LOCATION")) {
-		char *value = strtok_r(NULL, deliminiters, &saveptr);
-
-		el->type = IMAGE_CFG_NAND_BADBLK_LOCATION;
-		el->nandbadblklocation =
-			strtoul(value, NULL, 16);
-	} else if (!strcmp(keyword, "NAND_ECC_MODE")) {
-		char *value = strtok_r(NULL, deliminiters, &saveptr);
-		int ret = image_nand_ecc_mode_id(value);
+		break;
+	case IMAGE_CFG_NAND_BLKSZ:
+		el->nandblksz = strtoul(value1, NULL, 16);
+		break;
+	case IMAGE_CFG_NAND_BADBLK_LOCATION:
+		el->nandbadblklocation = strtoul(value1, NULL, 16);
+		break;
+	case IMAGE_CFG_NAND_ECC_MODE:
+		ret = image_nand_ecc_mode_id(value1);

 		if (ret < 0) {
-			fprintf(stderr,
-				"Invalid NAND ECC mode '%s'\n", value);
+			fprintf(stderr, "Invalid NAND ECC mode '%s'\n", value1);
 			return -1;
 		}
-		el->type = IMAGE_CFG_NAND_ECC_MODE;
 		el->nandeccmode = ret;
-	} else if (!strcmp(keyword, "NAND_PAGE_SIZE")) {
-		char *value = strtok_r(NULL, deliminiters, &saveptr);
-
-		el->type = IMAGE_CFG_NAND_PAGESZ;
-		el->nandpagesz = strtoul(value, NULL, 16);
-	} else if (!strcmp(keyword, "BINARY")) {
-		char *value = strtok_r(NULL, deliminiters, &saveptr);
-		int argi = 0;
+		break;
+	case IMAGE_CFG_NAND_PAGESZ:
+		el->nandpagesz = strtoul(value1, NULL, 16);
+		break;
+	case IMAGE_CFG_BINARY:
+		argi = 0;

-		el->type = IMAGE_CFG_BINARY;
-		el->binary.file = strdup(value);
+		el->binary.file = strdup(value1);
 		while (1) {
-			value = strtok_r(NULL, deliminiters, &saveptr);
+			char *value = strtok_r(NULL, delimiters, &saveptr);
+
 			if (!value)
 				break;
 			el->binary.args[argi] = strtoul(value, NULL, 16);
 			argi++;
 			if (argi >= BINARY_MAX_ARGS) {
 				fprintf(stderr,
-					"Too many argument for binary\n");
+					"Too many arguments for BINARY\n");
 				return -1;
 			}
 		}
 		el->binary.nargs = argi;
-	} else if (!strcmp(keyword, "DATA")) {
-		char *value1 = strtok_r(NULL, deliminiters, &saveptr);
-		char *value2 = strtok_r(NULL, deliminiters, &saveptr);
+		break;
+	case IMAGE_CFG_DATA:
+		value2 = strtok_r(NULL, delimiters, &saveptr);

 		if (!value1 || !value2) {
 			fprintf(stderr,
@@ -599,19 +636,17 @@ static int image_create_config_parse_oneline(char *line,
 			return -1;
 		}

-		el->type = IMAGE_CFG_DATA;
 		el->regdata.raddr = strtoul(value1, NULL, 16);
 		el->regdata.rdata = strtoul(value2, NULL, 16);
-	} else if (!strcmp(keyword, "BAUDRATE")) {
-		char *value = strtok_r(NULL, deliminiters, &saveptr);
-		el->type = IMAGE_CFG_BAUDRATE;
-		el->baudrate = strtoul(value, NULL, 10);
-	} else if (!strcmp(keyword, "DEBUG")) {
-		char *value = strtok_r(NULL, deliminiters, &saveptr);
-		el->type = IMAGE_CFG_DEBUG;
-		el->debug = strtoul(value, NULL, 10);
-	} else {
-		fprintf(stderr, "Ignoring unknown line '%s'\n", line);
+		break;
+	case IMAGE_CFG_BAUDRATE:
+		el->baudrate = strtoul(value1, NULL, 10);
+		break;
+	case IMAGE_CFG_DEBUG:
+		el->debug = strtoul(value1, NULL, 10);
+		break;
+	default:
+		fprintf(stderr, unknown_msg, line);
 	}

 	return 0;
--
2.9.0

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [U-Boot] [PATCH v2 16/18] arm: mvebu: Implement secure boot
  2017-01-11 15:00 [U-Boot] [PATCH v2 00/18] arm: mvebu: Add gdsys ControlCenter-Compact board Mario Six
                   ` (14 preceding siblings ...)
  2017-01-11 15:00 ` [U-Boot] [PATCH v2 15/18] tools: kwbimage: Refactor line parsing and fix error Mario Six
@ 2017-01-11 15:01 ` Mario Six
  2017-01-18 16:58   ` Stefan Roese
                     ` (2 more replies)
  2017-01-11 15:01 ` [U-Boot] [PATCH v2 17/18] arm: mvebu: Add gdsys ControlCenter-Compact board Mario Six
  2017-01-11 15:01 ` [U-Boot] [PATCH v2 18/18] controlcenterdc: Make secure boot available Mario Six
  17 siblings, 3 replies; 55+ messages in thread
From: Mario Six @ 2017-01-11 15:01 UTC (permalink / raw)
  To: u-boot

The patch implements secure booting for the mvebu architecture.

This includes:
- The addition of secure headers and all needed signatures and keys in
  mkimage
- Commands capable of writing the board's efuses to both write the
  needed cryptographic data and enable the secure booting mechanism
- The creation of convenience text files containing the necessary
  commands to write the efuses

The KAK and CSK keys are expected to reside in the files kwb_kak.key and
kwb_csk.key (OpenSSL 2048 bit private keys) in the top-level directory.

Signed-off-by: Reinhard Pfau <reinhard.pfau@gdsys.cc>
Signed-off-by: Mario Six <mario.six@gdsys.cc>
---
Changes in v2:

* Added help text for MVEBU_EFUSE
* Removed superfluous defined(CONFIG_MVEBU_EFUSE) from
  arch/arm/mach-mvebu/Makefile
* Rewrote disable_efuse_program to use clrbits_le32
* Remove superfluous blank lines from arch/arm/mach-mvebu/include/mach/efuse.h
---
 Makefile                                 |   3 +-
 arch/arm/mach-mvebu/Kconfig              |  35 ++
 arch/arm/mach-mvebu/Makefile             |   1 +
 arch/arm/mach-mvebu/efuse.c              | 264 +++++++++++
 arch/arm/mach-mvebu/include/mach/cpu.h   |   2 +
 arch/arm/mach-mvebu/include/mach/efuse.h |  69 +++
 doc/README.armada-secureboot             | 373 ++++++++++++++++
 tools/Makefile                           |   6 +-
 tools/kwbimage.c                         | 744 ++++++++++++++++++++++++++++++-
 tools/kwbimage.h                         |  37 ++
 10 files changed, 1526 insertions(+), 8 deletions(-)
 create mode 100644 arch/arm/mach-mvebu/efuse.c
 create mode 100644 arch/arm/mach-mvebu/include/mach/efuse.h
 create mode 100644 doc/README.armada-secureboot

diff --git a/Makefile b/Makefile
index adc333f..6bd2158 100644
--- a/Makefile
+++ b/Makefile
@@ -957,7 +957,8 @@ MKIMAGEFLAGS_u-boot.kwb = -n $(srctree)/$(CONFIG_SYS_KWD_CONFIG:"%"=%) \
 	-T kwbimage -a $(CONFIG_SYS_TEXT_BASE) -e $(CONFIG_SYS_TEXT_BASE)

 MKIMAGEFLAGS_u-boot-spl.kwb = -n $(srctree)/$(CONFIG_SYS_KWD_CONFIG:"%"=%) \
-	-T kwbimage -a $(CONFIG_SYS_TEXT_BASE) -e $(CONFIG_SYS_TEXT_BASE)
+	-T kwbimage -a $(CONFIG_SYS_TEXT_BASE) -e $(CONFIG_SYS_TEXT_BASE) \
+	$(if $(KEYDIR),-k $(KEYDIR))

 MKIMAGEFLAGS_u-boot.pbl = -n $(srctree)/$(CONFIG_SYS_FSL_PBL_RCW:"%"=%) \
 		-R $(srctree)/$(CONFIG_SYS_FSL_PBL_PBI:"%"=%) -T pblimage
diff --git a/arch/arm/mach-mvebu/Kconfig b/arch/arm/mach-mvebu/Kconfig
index 40476dc..c9609fb 100644
--- a/arch/arm/mach-mvebu/Kconfig
+++ b/arch/arm/mach-mvebu/Kconfig
@@ -1,5 +1,9 @@
 if ARCH_MVEBU

+config HAVE_MVEBU_EFUSE
+	bool
+	default n
+
 config ARMADA_32BIT
 	bool
 	select CPU_V7
@@ -21,6 +25,7 @@ config ARMADA_375
 config ARMADA_38X
 	bool
 	select ARMADA_32BIT
+	select HAVE_MVEBU_EFUSE

 config ARMADA_XP
 	bool
@@ -142,4 +147,34 @@ config SYS_VENDOR
 config SYS_SOC
 	default "mvebu"

+config MVEBU_EFUSE
+	bool "Enable eFuse support"
+	default n
+	depends on HAVE_MVEBU_EFUSE
+	help
+	  Enable support for reading and writing eFuses on mvebu SoCs.
+
+config MVEBU_EFUSE_FAKE
+	bool "Fake eFuse access (dry run)"
+	default n
+	depends on MVEBU_EFUSE
+	help
+	  This enables a "dry run" mode where eFuses are not really programmed.
+	  Instead the eFuse accesses are emulated by writing to and reading
+	  from a memory block.
+	  This is can be used for testing prog scripts.
+
+config SECURED_MODE_IMAGE
+	bool "Build image for trusted boot"
+	default false
+	depends on 88F6820
+	help
+	  Build an image that employs the ARMADA SoC's trusted boot framework
+	  for securely booting images.
+
+config SECURED_MODE_CSK_INDEX
+	int "Index of active CSK"
+	default 0
+	depends on SECURED_MODE_IMAGE
+
 endif
diff --git a/arch/arm/mach-mvebu/Makefile b/arch/arm/mach-mvebu/Makefile
index 65e90c4..d4210af 100644
--- a/arch/arm/mach-mvebu/Makefile
+++ b/arch/arm/mach-mvebu/Makefile
@@ -27,6 +27,7 @@ ifndef CONFIG_SPL_BUILD
 obj-$(CONFIG_ARMADA_375) += ../../../drivers/ddr/marvell/axp/xor.o
 obj-$(CONFIG_ARMADA_38X) += ../../../drivers/ddr/marvell/a38x/xor.o
 obj-$(CONFIG_ARMADA_XP) += ../../../drivers/ddr/marvell/axp/xor.o
+obj-$(CONFIG_MVEBU_EFUSE) += efuse.o
 endif # CONFIG_SPL_BUILD
 obj-y	+= gpio.o
 obj-y	+= mbus.o
diff --git a/arch/arm/mach-mvebu/efuse.c b/arch/arm/mach-mvebu/efuse.c
new file mode 100644
index 0000000..67fcadc
--- /dev/null
+++ b/arch/arm/mach-mvebu/efuse.c
@@ -0,0 +1,264 @@
+/*
+ * Copyright (C) 2015-2016 Reinhard Pfau <reinhard.pfau@gdsys.cc>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <config.h>
+#include <common.h>
+#include <errno.h>
+#include <asm/io.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/efuse.h>
+#include <asm/arch/soc.h>
+#include <linux/mbus.h>
+
+#if defined(CONFIG_MVEBU_EFUSE_FAKE)
+#define DRY_RUN
+#else
+#undef DRY_RUN
+#endif
+
+#define MBUS_EFUSE_BASE 0xF6000000
+#define MBUS_EFUSE_SIZE BIT(20)
+
+#define MVEBU_EFUSE_CONTROL (MVEBU_REGISTER(0xE4008))
+
+enum {
+	MVEBU_EFUSE_CTRL_PROGRAM_ENABLE = (1 << 31),
+};
+
+struct mvebu_hd_efuse {
+	u32 bits_31_0;
+	u32 bits_63_32;
+	u32 bit64;
+	u32 reserved0;
+};
+
+#ifndef DRY_RUN
+static struct mvebu_hd_efuse *efuses =
+	(struct mvebu_hd_efuse *)(MBUS_EFUSE_BASE + 0xF9000);
+#else
+static struct mvebu_hd_efuse efuses[EFUSE_LINE_MAX + 1];
+#endif
+
+static int efuse_initialised;
+
+static struct mvebu_hd_efuse *get_efuse_line(int nr)
+{
+	if (nr < 0 || nr > 63 || !efuse_initialised)
+		return NULL;
+
+	return efuses + nr;
+}
+
+static void enable_efuse_program(void)
+{
+#ifndef DRY_RUN
+	setbits_le32(MVEBU_EFUSE_CONTROL, MVEBU_EFUSE_CTRL_PROGRAM_ENABLE);
+#endif
+}
+
+static void disable_efuse_program(void)
+{
+#ifndef DRY_RUN
+	clrbits_le32(MVEBU_EFUSE_CONTROL, MVEBU_EFUSE_CTRL_PROGRAM_ENABLE);
+#endif
+}
+
+static int do_prog_efuse(struct mvebu_hd_efuse *efuse,
+			 struct efuse_val *new_val, u32 mask0, u32 mask1)
+{
+	struct efuse_val val;
+
+	val.dwords.d[0] = readl(&efuse->bits_31_0);
+	val.dwords.d[1] = readl(&efuse->bits_63_32);
+	val.lock = readl(&efuse->bit64);
+
+	if (val.lock & 1)
+		return -EPERM;
+
+	val.dwords.d[0] |= (new_val->dwords.d[0] & mask0);
+	val.dwords.d[1] |= (new_val->dwords.d[1] & mask1);
+	val.lock |= new_val->lock;
+
+	writel(val.dwords.d[0], &efuse->bits_31_0);
+	mdelay(1);
+	writel(val.dwords.d[1], &efuse->bits_63_32);
+	mdelay(1);
+	writel(val.lock, &efuse->bit64);
+	mdelay(5);
+
+	return 0;
+}
+
+static int prog_efuse(int nr, struct efuse_val *new_val, u32 mask0, u32 mask1)
+{
+	struct mvebu_hd_efuse *efuse;
+	int res = 0;
+
+	res = mvebu_efuse_init_hw();
+	if (res)
+		return res;
+
+	efuse = get_efuse_line(nr);
+	if (!efuse)
+		return -ENODEV;
+
+	if (!new_val)
+		return -EINVAL;
+
+	/* only write a fuse line with lock bit */
+	if (!new_val->lock)
+		return -EINVAL;
+
+	/* according to specs ECC protection bits must be 0 on write */
+	if (new_val->bytes.d[7] & 0xFE)
+		return -EINVAL;
+
+	if (!new_val->dwords.d[0] && !new_val->dwords.d[1] && (mask0 | mask1))
+		return 0;
+
+	enable_efuse_program();
+
+	res = do_prog_efuse(efuse, new_val, mask0, mask1);
+
+	disable_efuse_program();
+
+	return res;
+}
+
+int mvebu_efuse_init_hw(void)
+{
+	int ret;
+
+	if (efuse_initialised)
+		return 0;
+
+	ret = mvebu_mbus_add_window_by_id(
+		CPU_TARGET_SATA23_DFX, 0xA, MBUS_EFUSE_BASE, MBUS_EFUSE_SIZE);
+
+	if (ret)
+		return ret;
+
+	efuse_initialised = 1;
+
+	return 0;
+}
+
+int mvebu_read_efuse(int nr, struct efuse_val *val)
+{
+	struct mvebu_hd_efuse *efuse;
+	int res;
+
+	res = mvebu_efuse_init_hw();
+	if (res)
+		return res;
+
+	efuse = get_efuse_line(nr);
+	if (!efuse)
+		return -ENODEV;
+
+	if (!val)
+		return -EINVAL;
+
+	val->dwords.d[0] = readl(&efuse->bits_31_0);
+	val->dwords.d[1] = readl(&efuse->bits_63_32);
+	val->lock = readl(&efuse->bit64);
+	return 0;
+}
+
+int mvebu_write_efuse(int nr, struct efuse_val *val)
+{
+	return prog_efuse(nr, val, ~0, ~0);
+}
+
+int mvebu_lock_efuse(int nr)
+{
+	struct efuse_val val = {
+		.lock = 1,
+	};
+
+	return prog_efuse(nr, &val, 0, 0);
+}
+
+/*
+ * wrapper funcs providing the fuse API
+ *
+ * we use the following mapping:
+ *   "bank" ->	eFuse line
+ *   "word" ->	0: bits 0-31
+ *		1: bits 32-63
+ *		2: bit 64 (lock)
+ */
+
+static struct efuse_val prog_val;
+static int valid_prog_words;
+
+int fuse_read(u32 bank, u32 word, u32 *val)
+{
+	struct efuse_val fuse_line;
+	int res;
+
+	if (bank < EFUSE_LINE_MIN || bank > EFUSE_LINE_MAX || word > 2)
+		return -EINVAL;
+
+	res = mvebu_read_efuse(bank, &fuse_line);
+	if (res)
+		return res;
+
+	if (word < 2)
+		*val = fuse_line.dwords.d[word];
+	else
+		*val = fuse_line.lock;
+
+	return res;
+}
+
+int fuse_sense(u32 bank, u32 word, u32 *val)
+{
+	/* not supported */
+	return -ENOSYS;
+}
+
+int fuse_prog(u32 bank, u32 word, u32 val)
+{
+	int res = 0;
+
+	/*
+	 * NOTE: Fuse line should be written as whole.
+	 * So how can we do that with this API?
+	 * For now: remember values for word == 0 and word == 1 and write the
+	 * whole line when word == 2.
+	 * This implies that we always require all 3 fuse prog cmds (one for
+	 * for each word) to write a single fuse line.
+	 * Exception is a single write to word 2 which will lock the fuse line.
+	 *
+	 * Hope that will be OK.
+	 */
+
+	if (bank < EFUSE_LINE_MIN || bank > EFUSE_LINE_MAX || word > 2)
+		return -EINVAL;
+
+	if (word < 2) {
+		prog_val.dwords.d[word] = val;
+		valid_prog_words |= (1 << word);
+	} else if ((valid_prog_words & 3) == 0 && val) {
+		res = mvebu_lock_efuse(bank);
+		valid_prog_words = 0;
+	} else if ((valid_prog_words & 3) != 3 || !val) {
+		res = -EINVAL;
+	} else {
+		prog_val.lock = val != 0;
+		res = mvebu_write_efuse(bank, &prog_val);
+		valid_prog_words = 0;
+	}
+
+	return res;
+}
+
+int fuse_override(u32 bank, u32 word, u32 val)
+{
+	/* not supported */
+	return -ENOSYS;
+}
diff --git a/arch/arm/mach-mvebu/include/mach/cpu.h b/arch/arm/mach-mvebu/include/mach/cpu.h
index 66f7680..d241eea 100644
--- a/arch/arm/mach-mvebu/include/mach/cpu.h
+++ b/arch/arm/mach-mvebu/include/mach/cpu.h
@@ -36,7 +36,9 @@ enum cpu_target {
 	CPU_TARGET_ETH01 = 0x7,
 	CPU_TARGET_PCIE13 = 0x8,
 	CPU_TARGET_SASRAM = 0x9,
+	CPU_TARGET_SATA01 = 0xa, /* A38X */
 	CPU_TARGET_NAND = 0xd,
+	CPU_TARGET_SATA23_DFX = 0xe, /* A38X */
 };

 enum cpu_attrib {
diff --git a/arch/arm/mach-mvebu/include/mach/efuse.h b/arch/arm/mach-mvebu/include/mach/efuse.h
new file mode 100644
index 0000000..ef693e6
--- /dev/null
+++ b/arch/arm/mach-mvebu/include/mach/efuse.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2015 Reinhard Pfau <reinhard.pfau@gdsys.cc>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _MVEBU_EFUSE_H
+#define _MVEBU_EFUSE_H
+
+#include <common.h>
+
+struct efuse_val {
+	union {
+		struct {
+			u8 d[8];
+		} bytes;
+		struct {
+			u16 d[4];
+		} words;
+		struct {
+			u32 d[2];
+		} dwords;
+	};
+	u32 lock;
+};
+
+#if defined(CONFIG_ARMADA_38X)
+
+enum efuse_line {
+	EFUSE_LINE_SECURE_BOOT = 24,
+	EFUSE_LINE_PUBKEY_DIGEST_0 = 26,
+	EFUSE_LINE_PUBKEY_DIGEST_1 = 27,
+	EFUSE_LINE_PUBKEY_DIGEST_2 = 28,
+	EFUSE_LINE_PUBKEY_DIGEST_3 = 29,
+	EFUSE_LINE_PUBKEY_DIGEST_4 = 30,
+	EFUSE_LINE_CSK_0_VALID = 31,
+	EFUSE_LINE_CSK_1_VALID = 32,
+	EFUSE_LINE_CSK_2_VALID = 33,
+	EFUSE_LINE_CSK_3_VALID = 34,
+	EFUSE_LINE_CSK_4_VALID = 35,
+	EFUSE_LINE_CSK_5_VALID = 36,
+	EFUSE_LINE_CSK_6_VALID = 37,
+	EFUSE_LINE_CSK_7_VALID = 38,
+	EFUSE_LINE_CSK_8_VALID = 39,
+	EFUSE_LINE_CSK_9_VALID = 40,
+	EFUSE_LINE_CSK_10_VALID = 41,
+	EFUSE_LINE_CSK_11_VALID = 42,
+	EFUSE_LINE_CSK_12_VALID = 43,
+	EFUSE_LINE_CSK_13_VALID = 44,
+	EFUSE_LINE_CSK_14_VALID = 45,
+	EFUSE_LINE_CSK_15_VALID = 46,
+	EFUSE_LINE_FLASH_ID = 47,
+	EFUSE_LINE_BOX_ID = 48,
+
+	EFUSE_LINE_MIN = 0,
+	EFUSE_LINE_MAX = 63,
+};
+
+#endif
+
+int mvebu_efuse_init_hw(void);
+
+int mvebu_read_efuse(int nr, struct efuse_val *val);
+
+int mvebu_write_efuse(int nr, struct efuse_val *val);
+
+int mvebu_lock_efuse(int nr);
+
+#endif
diff --git a/doc/README.armada-secureboot b/doc/README.armada-secureboot
new file mode 100644
index 0000000..157cb5a
--- /dev/null
+++ b/doc/README.armada-secureboot
@@ -0,0 +1,373 @@
+The trusted boot framework on Marvell Armada 38x
+================================================
+
+Contents:
+
+1. Overview of the trusted boot
+2. Terminology
+3. Boot image layout
+4. The secured header
+5. The secured boot flow
+6. Usage example
+7. Work to be done
+8. Bibliography
+
+1. Overview of the trusted boot
+-------------------------------
+
+The Armada's trusted boot framework enables the SoC to cryptographically verify
+a specially prepared boot image. This can be used to establish a chain of trust
+from the boot firmware all the way to the OS.
+
+To achieve this, the Armada SoC requires a specially prepared boot image, which
+contains the relevant cryptographic data, as well as other information
+pertaining to the boot process. Furthermore, a eFuse structure (a
+one-time-writeable memory) need to be configured in the correct way.
+
+Roughly, the secure boot process works as follows:
+
+* Load the header block of the boot image, extract a special "root" public RSA
+  key from it, and verify its SHA-256 hash against a SHA-256 stored in a eFuse
+  field.
+* Load an array of code signing public RSA keys from the header block, and
+  verify its RSA signature (contained in the header block as well) using the
+  "root" RSA key.
+* Choose a code signing key, and use it to verify the header block (excluding
+  the key array).
+* Verify the binary image's signature (contained in the header block) using the
+  code signing key.
+* If all checks pass successfully, boot the image.
+
+The chain of trust is thus as follows:
+
+* The SHA-256 value in the eFuse field verifies the "root" public key.
+* The "root" public key verifies the code signing key array.
+* The selected code signing key verifies the header block and the binary image.
+
+In the special case of building a boot image containing U-Boot as the binary
+image, which employs this trusted boot framework, the following tasks need to
+be addressed:
+
+1. Creation of the needed cryptographic key material.
+2. Creation of a conforming boot image containing the U-Boot image as binary
+   image.
+3. Burning the necessary eFuse values.
+
+(1) will be addressed later, (2) will be taken care of by U-Boot's build
+system (some user configuration is required, though), and for (3) the necessary
+data (essentially a series of U-Boot commands to be entered at the U-Boot
+command prompt) will be created by the build system as well.
+
+The documentation of the trusted boot mode is contained in part 1, chapter
+7.2.5 in the functional specification [1], and in application note [2].
+
+2. Terminology
+--------------
+
+	           CSK - Code Signing Key(s): An array of RSA key pairs, which
+                         are used to sign and verify the secured header and the
+                         boot loader image.
+	           KAK - Key Authentication Key: A RSA key pair, which is used
+                         to sign and verify the array of CSKs.
+	  Header block - The first part of the boot image, which contains the
+			 image's headers (also known as "headers block", "boot
+			 header", and "image header")
+                 eFuse - A one-time-writeable memory.
+               BootROM - The Armada's built-in boot firmware, which is
+                         responsible for verifying and starting secure images.
+	    Boot image - The complete image the SoC's boot firmware loads
+			 (contains the header block and the binary image)
+	   Main header - The header in the header block containing information
+			 and data pertaining to the boot process (used for both
+			 the regular and secured boot processes)
+	  Binary image - The binary code payload of the boot image; in this
+			 case the U-Boot's code (also known as "source image",
+			 or just "image")
+	Secured header - The specialized header in the header block that
+			 contains information and data pertaining to the
+			 trusted boot (also known as "security header")
+     Secured boot mode - A special boot mode of the Armada SoC in which secured
+                         images are verified (non-secure images won't boot);
+                         the mode is activated by setting a eFuse field.
+    Trusted debug mode - A special mode for the trusted boot that allows
+			 debugging of devices employing the trusted boot
+			 framework in a secure manner (untested in the current
+			 implementation).
+Trusted boot framework - The ARMADA SoC's implementation of a secure verified
+                         boot process.
+
+3. Boot image layout
+--------------------
+
++-- Boot image --------------------------------------------+
+|                                                          |
+| +-- Header block --------------------------------------+ |
+| | Main header                                          | |
+| +------------------------------------------------------+ |
+| | Secured header                                       | |
+| +------------------------------------------------------+ |
+| | BIN header(s)                                        | |
+| +------------------------------------------------------+ |
+| | REG header(s)                                        | |
+| +------------------------------------------------------+ |
+| | Padding                                              | |
+| +------------------------------------------------------+ |
+|                                                          |
+| +------------------------------------------------------+ |
+| | Binary image + checksum                              | |
+| +------------------------------------------------------+ |
++----------------------------------------------------------+
+
+4. The secured header
+---------------------
+
+For the trusted boot framework, a additional header is added to the boot image.
+The following data are relevant for the secure boot:
+
+		   KAK: The KAK is contained in the secured header in the form
+		        of a RSA-2048 public key in DER format with a length of
+			524 bytes.
+Header block signature: The RSA signature of the header block (excluding the
+                        CSK array), created using the selected CSK.
+Binary image signature: The RSA signature of the binary image, created using
+                        the selected CSK.
+             CSK array: The array of the 16 CSKs as RSA-2048 public keys in DER
+	                format with a length of 8384 = 16 * 524 bytes.
+   CSK block signature: The RSA signature of the CSK array, created using the
+                        KAK.
+
+NOTE: The JTAG delay, Box ID, and Flash ID header fields do play a role in the
+trusted boot process to enable and configure secure debugging, but they were
+not tested in the current implementation of the trusted boot in U-Boot.
+
+5. The secured boot flow
+------------------------
+
+The steps in the boot flow that are relevant for the trusted boot framework
+proceed as follows:
+
+1) Check if trusted boot is enabled, and perform regular boot if it is not.
+2) Load the secured header, and verify its checksum.
+3) Select the lowest valid CSK from CSK0 to CSK15.
+4) Verify the SHA-256 hash of the KAK embedded in the secured header.
+5) Verify the RSA signature of the CSK block from the secured header with the
+   KAK.
+6) Verify the header block signature (which excludes the CSK block) from the
+   secured header with the selected CSK.
+7) Load the binary image to the main memory and verify its checksum.
+8) Verify the binary image's RSA signature from the secured header with the
+   selected CSK.
+9) Continue the boot process as in the case of the regular boot.
+
+NOTE: All RSA signatures are verified according to the PKCS #1 v2.1 standard
+described in [3].
+
+NOTE: The Box ID and Flash ID are checked after step 6, and the trusted debug
+mode may be entered there, but since this mode is untested in the current
+implementation, it is not described further.
+
+6. Usage example
+----------------
+
+### Create key material
+
+To employ the trusted boot framework, cryptographic key material needs to be
+created. In the current implementation, two keys are needed to build a valid
+secured boot image: The KAK private key and a CSK private key (both have to be
+2048 bit RSA keys in PEM format). Note that the usage of more than one CSK is
+currently not supported.
+
+NOTE: Since the public key can be generated from the private key, it is
+sufficient to store the private key for each key pair.
+
+OpenSSL can be used to generate the needed files kwb_kak.key and kwb_csk.key
+(the names of these files have to be configured, see the next section on
+kwbimage.cfg settings):
+
+openssl genrsa -out kwb_kak.key 2048
+openssl genrsa -out kwb_csk.key 2048
+
+The generated files have to be placed in the U-Boot root directory.
+
+Alternatively, instead of copying the files, symlinks to the private keys can
+be placed in the U-Boot root directory.
+
+WARNING: Knowledge of the KAK or CSK private key would enable an attacker to
+generate secured boot images containing arbitrary code. Hence, the private keys
+should be carefully guarded.
+
+### Create/Modifiy kwbimage.cfg
+
+The Kirkwook architecture in U-Boot employs a special board-specific
+configuration file (kwbimage.cfg), which controls various boot image settings
+that are interpreted by the BootROM, such as the boot medium. The support the
+trusted boot framework, several new options were added to faciliate
+configuration of the secured boot.
+
+The configuration file's layout has been retained, only the following new
+options were added:
+
+		KAK - The name of the KAK RSA private key file in the U-Boot
+                      root directory, without the trailing extension of ".key".
+		CSK - The name of the (active) CSK RSA private key file in the
+		      U-Boot root directory, without the trailing extension of
+		      ".key".
+	     BOX_ID - The BoxID to be used for trusted debugging (a integer
+	              value).
+	   FLASH_ID - The FlashID to be used for trusted debugging (a integer
+	              value).
+	 JTAG_DELAY - The JTAG delay to be used for trusted debugging (a
+	              integer value).
+          CSK_INDEX - The index of the active CSK (a integer value).
+SEC_SPECIALIZED_IMG - Flag to indicate whether to include the BoxID and FlashID
+		      in the image (that is, whether to use the trusted debug
+		      mode or not); no parameters.
+       SEC_BOOT_DEV - The boot device from which the trusted boot is allowed to
+		      proceed, identified via a numeric ID. The tested values
+		      are 0x34 = NOR flash, 0x31 = SDIO/MMC card; for
+		      additional ID values, consult the documentation in [1].
+      SEC_FUSE_DUMP - Dump the "fuse prog" commands necessary for writing the
+		      correct eFuse values to a text file in the U-Boot root
+		      directory. The parameter is the architecture for which to
+		      dump the commands (currently only "a38x" is supported).
+
+The parameter values may be hardcoded into the file, but it is also possible to
+employ a dynamic approach of creating a Autoconf-like kwbimage.cfg.in, then
+reading configuration values from Kconfig options or from the board config
+file, and generating the actual kwbimage.cfg from this template using Makefile
+mechanisms (see board/gdsys/a38x/Makefile as an example for this approach).
+
+### Set config options
+
+To enable the generation of trusted boot images, the corresponding support
+needs to be activated, and a index for the active CSK needs to be selected as
+well.
+
+Furthermore, eFuse writing support has to be activated in order to burn the
+eFuse structure's values (this option is just needed for programming the eFuse
+structure; production boot images may disable it).
+
+ARM architecture
+ -> [*] Build image for trusted boot
+    (0)   Index of active CSK
+ -> [*] Enable eFuse support
+    [ ]   Fake eFuse access (dry run)
+
+### Build and test boot image
+
+The creation of the boot image is done via the usual invocation of make (with a
+suitably set CROSS_COMPILE environment variable, of course). The resulting boot
+image u-boot-spl.kwb can then be tested, if so desired. The hdrparser from [5]
+can be used for this purpose. To build the tool, invoke make in the
+'tools/marvell/doimage_mv' directory of [5], which builds a stand-alone
+hdrparser executable. A test can be conducted by calling hdrparser with the
+produced boot image and the following (mandatory) parameters:
+
+./hdrparser -k 0 -t u-boot-spl.kwb
+
+Here we assume that the CSK index is 0 and the boot image file resides in the
+same directory (adapt accordingly if needed). The tool should report that all
+checksums are valid ("GOOD"), that all signature verifications succeed
+("PASSED"), and, finally, that the overall test was successful
+("T E S T   S U C C E E D E D" in the last line of output).
+
+### Burn eFuse structure
+
++----------------------------------------------------------+
+| WARNING: Burning the eFuse structure is a irreversible   |
+| operation! Should wrong or corrupted values be used, the |
+| board won't boot anymore, and recovery is likely         |
+| impossible!                                              |
++----------------------------------------------------------+
+
+After the build process has finished, and the SEC_FUSE_DUMP option was set in
+the kwbimage.cfg was set, a text file kwb_fuses_a38x.txt should be present in
+the U-Boot top-level directory. It contains all the necessary commands to set
+the eFuse structure to the values needed for the used KAK digest, as well as
+the CSK index, Flash ID and Box ID that were selected in kwbimage.cfg.
+
+Sequentially executing the commands in this file at the U-Boot command prompt
+will write these values to the eFuse structure.
+
+If the SEC_FUSE_DUMP option was not set, the commands needed to burn the fuses
+have to be crafted by hand. The needed fuse lines can be looked up in [1]; a
+rough overview of the process is:
+
+* Burn the KAK public key hash. The hash itself can be found in the file
+  pub_kak_hash.txt in the U-Boot top-level directory; be careful to account for
+  the endianness!
+* Burn the CSK selection, BoxID, and FlashID
+* Enable trusted boot by burning the corresponding fuse (WARNING: this must be
+  the last fuse line written!)
+* Lock the unused fuse lines
+
+The command to employ is the "fuse prog" command previously enabled by setting
+the corresponding configuration option.
+
+For the trusted boot, the fuse prog command has a special syntax, since the
+ARMADA SoC demands that whole fuse lines (64 bit values) have to be written as
+a whole. The fuse prog command itself allows lists of 32 bit words to be
+written at a time, but this is translated to a series of single 32 bit write
+operations to the fuse line, where the individual 32 bit words are identified
+by a "word" counter that is increased for each write.
+
+To work around this restriction, we interpret each line to have three "words"
+(0-2): The first and second words are the values to be written to the fuse
+line, and the third is a lock flag, which is supposed to lock the fuse line
+when set to 1. Writes to the first and second words are memoized between
+function calls, and the fuse line is only really written and locked (on writing
+the third word) if both words were previously set, so that "incomplete" writes
+are prevented. An exception to this is a single write to the third word (index
+2) without previously writing neither the first nor the second word, which
+locks the fuse line without setting any value; this is needed to lock the
+unused fuse lines.
+
+As an example, to write the value 0011223344556677 to fuse line 10, we would
+use the following command:
+
+fuse prog -y 10 0 00112233 44556677 1
+
+Here 10 is the fuse line number, 0 is the index of the first word to be
+written, 00112233 and 44556677 are the values to be written to the fuse line
+(first and second word) and the trailing 1 is the value for the third word
+responsible for locking the line.
+
+A "lock-only" command would look like this:
+
+fuse prog -y 11 2 1
+
+Here 11 is the fuse number, 2 is the index of the first word to be written
+(notice that we only write to word 2 here; the third word for fuse line
+locking), and the 1 is the value for the word we are writing to.
+
+WARNING: According to application note [4], the VHV pin of the SoC must be
+connected to a 1.8V source during eFuse programming, but *must* be disconnected
+for normal operation. The AN [4] describes a software-controlled circuit (based
+on a N-channel or P-channel FET and a free GPIO pin of the SoC) to achieve
+this, but a jumper-based circuit should suffice as well. Regardless of the
+chosen circuit, the issue needs to be addressed accordingly!
+
+7. Work to be done
+------------------
+
+* Add the ability to populate more than one CSK
+* Test secure debug
+* Test on Armada XP
+
+8. Bibliography
+---------------
+
+[1] ARMADA(R) 38x Family High-Performance Single/Dual CPU System on Chip
+    Functional Specification; MV-S109094-00, Rev. C; August 2, 2015,
+    Preliminary
+[2] AN-383: ARMADA(R) 38x Families Secure Boot Mode Support; MV-S302501-00
+    Rev.  A; March 11, 2015, Preliminary
+[3] Public-Key Cryptography Standards (PKCS) #1: RSA Cryptography
+    Specifications Version 2.1; February 2003;
+    https://www.ietf.org/rfc/rfc3447.txt
+[4] AN-389: ARMADA(R) VHV Power; MV-S302545-00 Rev. B; January 28, 2016,
+    Released
+[5] Marvell Armada 38x U-Boot support; November 25, 2015;
+    https://github.com/MarvellEmbeddedProcessors/u-boot-marvell
+
+2017-01-05, Mario Six <mario.six@gdsys.cc>
diff --git a/tools/Makefile b/tools/Makefile
index 5b81dde..440686c 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -141,8 +141,12 @@ ifdef CONFIG_SYS_U_BOOT_OFFS
 HOSTCFLAGS_kwbimage.o += -DCONFIG_SYS_U_BOOT_OFFS=$(CONFIG_SYS_U_BOOT_OFFS)
 endif

+ifneq ($(CONFIG_ARMADA_38X)$(CONFIG_ARMADA_39X),)
+HOSTCFLAGS_kwbimage.o += -DCONFIG_KWB_SECURE
+endif
+
 # MXSImage needs LibSSL
-ifneq ($(CONFIG_MX23)$(CONFIG_MX28)$(CONFIG_FIT_SIGNATURE),)
+ifneq ($(CONFIG_MX23)$(CONFIG_MX28)$(CONFIG_ARMADA_38X)$(CONFIG_ARMADA_39X)$(CONFIG_FIT_SIGNATURE),)
 HOSTLOADLIBES_mkimage += \
 	$(shell pkg-config --libs libssl libcrypto 2> /dev/null || echo "-lssl -lcrypto")

diff --git a/tools/kwbimage.c b/tools/kwbimage.c
index 9aa9c74..93797c9 100644
--- a/tools/kwbimage.c
+++ b/tools/kwbimage.c
@@ -1,30 +1,47 @@
 /*
  * Image manipulator for Marvell SoCs
- *  supports Kirkwood, Dove, Armada 370, and Armada XP
+ *  supports Kirkwood, Dove, Armada 370, Armada XP, and Armada 38x
  *
  * (C) Copyright 2013 Thomas Petazzoni
  * <thomas.petazzoni@free-electrons.com>
  *
  * SPDX-License-Identifier:	GPL-2.0+
  *
- * Not implemented: support for the register headers and secure
- * headers in v1 images
+ * Not implemented: support for the register headers in v1 images
  */

 #include "imagetool.h"
 #include <limits.h>
 #include <image.h>
+#include <stdarg.h>
 #include <stdint.h>
 #include "kwbimage.h"

+#ifdef CONFIG_KWB_SECURE
+#include <openssl/rsa.h>
+#include <openssl/pem.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#endif
+
 static struct image_cfg_element *image_cfg;
 static int cfgn;
+#ifdef CONFIG_KWB_SECURE
+static int verbose_mode;
+#endif

 struct boot_mode {
 	unsigned int id;
 	const char *name;
 };

+/*
+ * SHA2-256 hash
+ */
+struct hash_v1 {
+	uint8_t hash[32];
+};
+
 struct boot_mode boot_modes[] = {
 	{ 0x4D, "i2c"  },
 	{ 0x5A, "spi"  },
@@ -70,6 +87,16 @@ enum image_cfg_type {
 	IMAGE_CFG_DATA,
 	IMAGE_CFG_BAUDRATE,
 	IMAGE_CFG_DEBUG,
+	IMAGE_CFG_KAK,
+	IMAGE_CFG_CSK,
+	IMAGE_CFG_CSK_INDEX,
+	IMAGE_CFG_JTAG_DELAY,
+	IMAGE_CFG_BOX_ID,
+	IMAGE_CFG_FLASH_ID,
+	IMAGE_CFG_SEC_COMMON_IMG,
+	IMAGE_CFG_SEC_SPECIALIZED_IMG,
+	IMAGE_CFG_SEC_BOOT_DEV,
+	IMAGE_CFG_SEC_FUSE_DUMP,

 	IMAGE_CFG_COUNT
 } type;
@@ -88,6 +115,16 @@ static const char * const id_strs[] = {
 	[IMAGE_CFG_DATA] = "DATA",
 	[IMAGE_CFG_BAUDRATE] = "BAUDRATE",
 	[IMAGE_CFG_DEBUG] = "DEBUG",
+	[IMAGE_CFG_KAK] = "KAK",
+	[IMAGE_CFG_CSK] = "CSK",
+	[IMAGE_CFG_CSK_INDEX] = "CSK_INDEX",
+	[IMAGE_CFG_JTAG_DELAY] = "JTAG_DELAY",
+	[IMAGE_CFG_BOX_ID] = "BOX_ID",
+	[IMAGE_CFG_FLASH_ID] = "FLASH_ID",
+	[IMAGE_CFG_SEC_COMMON_IMG] = "SEC_COMMON_IMG",
+	[IMAGE_CFG_SEC_SPECIALIZED_IMG] = "SEC_SPECIALIZED_IMG",
+	[IMAGE_CFG_SEC_BOOT_DEV] = "SEC_BOOT_DEV",
+	[IMAGE_CFG_SEC_FUSE_DUMP] = "SEC_FUSE_DUMP"
 };

 struct image_cfg_element {
@@ -110,6 +147,14 @@ struct image_cfg_element {
 		struct ext_hdr_v0_reg regdata;
 		unsigned int baudrate;
 		unsigned int debug;
+		const char *key_name;
+		int csk_idx;
+		uint8_t jtag_delay;
+		uint32_t boxid;
+		uint32_t flashid;
+		bool sec_specialized_img;
+		unsigned int sec_boot_dev;
+		const char *name;
 	};
 };

@@ -178,6 +223,32 @@ image_count_options(unsigned int optiontype)
 	return count;
 }

+#if defined(CONFIG_KWB_SECURE)
+
+static int image_get_csk_index(void)
+{
+	struct image_cfg_element *e;
+
+	e = image_find_option(IMAGE_CFG_CSK_INDEX);
+	if (!e)
+		return -1;
+
+	return e->csk_idx;
+}
+
+static bool image_get_spezialized_img(void)
+{
+	struct image_cfg_element *e;
+
+	e = image_find_option(IMAGE_CFG_SEC_SPECIALIZED_IMG);
+	if (!e)
+		return false;
+
+	return e->sec_specialized_img;
+}
+
+#endif
+
 /*
  * Compute a 8-bit checksum of a memory area. This algorithm follows
  * the requirements of the Marvell SoC BootROM specifications.
@@ -245,6 +316,493 @@ static uint8_t baudrate_to_option(unsigned int baudrate)
 	}
 }

+#if defined(CONFIG_KWB_SECURE)
+static void kwb_msg(const char *fmt, ...)
+{
+	if (verbose_mode) {
+		va_list ap;
+
+		va_start(ap, fmt);
+		vfprintf(stdout, fmt, ap);
+		va_end(ap);
+	}
+}
+
+static int openssl_err(const char *msg)
+{
+	unsigned long ssl_err = ERR_get_error();
+
+	fprintf(stderr, "%s", msg);
+	fprintf(stderr, ": %s\n",
+		ERR_error_string(ssl_err, 0));
+
+	return -1;
+}
+
+static int kwb_load_rsa_key(const char *keydir, const char *name, RSA **p_rsa)
+{
+	char path[PATH_MAX];
+	RSA *rsa;
+	FILE *f;
+
+	if (!keydir)
+		keydir = ".";
+
+	snprintf(path, sizeof(path), "%s/%s.key", keydir, name);
+	f = fopen(path, "r");
+	if (!f) {
+		fprintf(stderr, "Couldn't open RSA private key: '%s': %s\n",
+			path, strerror(errno));
+		return -ENOENT;
+	}
+
+	rsa = PEM_read_RSAPrivateKey(f, 0, NULL, "");
+	if (!rsa) {
+		openssl_err("Failure reading private key");
+		fclose(f);
+		return -EPROTO;
+	}
+	fclose(f);
+	*p_rsa = rsa;
+
+	return 0;
+}
+
+static int kwb_load_cfg_key(struct image_tool_params *params,
+			    unsigned int cfg_option, const char *key_name,
+			    RSA **p_key)
+{
+	struct image_cfg_element *e_key;
+	RSA *key;
+	int res;
+
+	*p_key = NULL;
+
+	e_key = image_find_option(cfg_option);
+	if (!e_key) {
+		fprintf(stderr, "%s not configured\n", key_name);
+		return -ENOENT;
+	}
+
+	res = kwb_load_rsa_key(params->keydir, e_key->key_name, &key);
+	if (res < 0) {
+		fprintf(stderr, "Failed to load %s\n", key_name);
+		return -ENOENT;
+	}
+
+	*p_key = key;
+
+	return 0;
+}
+
+static int kwb_load_kak(struct image_tool_params *params, RSA **p_kak)
+{
+	return kwb_load_cfg_key(params, IMAGE_CFG_KAK, "KAK", p_kak);
+}
+
+static int kwb_load_csk(struct image_tool_params *params, RSA **p_csk)
+{
+	return kwb_load_cfg_key(params, IMAGE_CFG_CSK, "CSK", p_csk);
+}
+
+static int kwb_compute_pubkey_hash(struct pubkey_der_v1 *pk,
+				   struct hash_v1 *hash)
+{
+	EVP_MD_CTX *ctx;
+	unsigned int key_size;
+	unsigned int hash_size;
+	int ret = 0;
+
+	if (!pk || !hash || pk->key[0] != 0x30 || pk->key[1] != 0x82)
+		return -EINVAL;
+
+	key_size = (pk->key[2] << 8) + pk->key[3] + 4;
+
+	ctx = EVP_MD_CTX_create();
+	if (!ctx)
+		return openssl_err("EVP context creation failed");
+
+	EVP_MD_CTX_init(ctx);
+	if (!EVP_DigestInit(ctx, EVP_sha256())) {
+		ret = openssl_err("Digest setup failed");
+		goto hash_err_ctx;
+	}
+
+	if (!EVP_DigestUpdate(ctx, pk->key, key_size)) {
+		ret = openssl_err("Hashing data failed");
+		goto hash_err_ctx;
+	}
+
+	if (!EVP_DigestFinal(ctx, hash->hash, &hash_size)) {
+		ret = openssl_err("Could not obtain hash");
+		goto hash_err_ctx;
+	}
+
+	EVP_MD_CTX_cleanup(ctx);
+
+hash_err_ctx:
+	EVP_MD_CTX_destroy(ctx);
+	return ret;
+}
+
+static int kwb_import_pubkey(RSA **key, struct pubkey_der_v1 *src, char *keyname)
+{
+	RSA *rsa;
+	const unsigned char *ptr;
+
+	if (!key || !src)
+		goto fail;
+
+	ptr = src->key;
+	rsa = d2i_RSAPublicKey(key, &ptr, sizeof(src->key));
+	if (!rsa) {
+		openssl_err("error decoding public key");
+		goto fail;
+	}
+
+	return 0;
+fail:
+	fprintf(stderr, "Failed to decode %s pubkey\n", keyname);
+	return -EINVAL;
+}
+
+static int kwb_export_pubkey(RSA *key, struct pubkey_der_v1 *dst, FILE *hashf,
+			     char *keyname)
+{
+	int size_exp, size_mod, size_seq;
+	uint8_t *cur;
+	char *errmsg = "Failed to encode %s\n";
+
+	if (!key || !key->e || !key->n || !dst) {
+		fprintf(stderr, "export pk failed: (%p, %p, %p, %p)",
+			key, key->e, key->n, dst);
+		fprintf(stderr, errmsg, keyname);
+		return -EINVAL;
+	}
+
+	/*
+	 * According to the specs, the key should be PKCS#1 DER encoded.
+	 * But unfortunately the really required encoding seems to be different;
+	 * it violates DER...! (But it still conformes to BER.)
+	 * (Length always in long form w/ 2 byte length code; no leading zero
+	 * when MSB of first byte is set...)
+	 * So we cannot use the encoding func provided by OpenSSL and have to
+	 * do the encoding manually.
+	 */
+
+	size_exp = BN_num_bytes(key->e);
+	size_mod = BN_num_bytes(key->n);
+	size_seq = 4 + size_mod + 4 + size_exp;
+
+	if (size_mod > 256) {
+		fprintf(stderr, "export pk failed: wrong mod size: %d\n",
+			size_mod);
+		fprintf(stderr, errmsg, keyname);
+		return -EINVAL;
+	}
+
+	if (4 + size_seq > sizeof(dst->key)) {
+		fprintf(stderr, "export pk failed: seq too large (%d, %lu)\n",
+			4 + size_seq, sizeof(dst->key));
+		fprintf(stderr, errmsg, keyname);
+		return -ENOBUFS;
+	}
+
+	cur = dst->key;
+
+	/* PKCS#1 (RFC3447) RSAPublicKey structure */
+	*cur++ = 0x30;		/* SEQUENCE */
+	*cur++ = 0x82;
+	*cur++ = (size_seq >> 8) & 0xFF;
+	*cur++ = size_seq & 0xFF;
+	/* Modulus */
+	*cur++ = 0x02;		/* INTEGER */
+	*cur++ = 0x82;
+	*cur++ = (size_mod >> 8) & 0xFF;
+	*cur++ = size_mod & 0xFF;
+	BN_bn2bin(key->n, cur);
+	cur += size_mod;
+	/* Exponent */
+	*cur++ = 0x02;		/* INTEGER */
+	*cur++ = 0x82;
+	*cur++ = (size_exp >> 8) & 0xFF;
+	*cur++ = size_exp & 0xFF;
+	BN_bn2bin(key->e, cur);
+
+	if (hashf) {
+		struct hash_v1 pk_hash;
+		int i;
+		int ret = 0;
+
+		ret = kwb_compute_pubkey_hash(dst, &pk_hash);
+		if (ret < 0) {
+			fprintf(stderr, errmsg, keyname);
+			return ret;
+		}
+
+		fprintf(hashf, "SHA256 = ");
+		for (i = 0 ; i < sizeof(pk_hash.hash); ++i)
+			fprintf(hashf, "%02X", pk_hash.hash[i]);
+		fprintf(hashf, "\n");
+	}
+
+	return 0;
+}
+
+int kwb_sign(RSA *key, void *data, int datasz, struct sig_v1 *sig, char *signame)
+{
+	EVP_PKEY *evp_key;
+	EVP_MD_CTX *ctx;
+	unsigned int sig_size;
+	int size;
+	int ret = 0;
+
+	evp_key = EVP_PKEY_new();
+	if (!evp_key)
+		return openssl_err("EVP_PKEY object creation failed");
+
+	if (!EVP_PKEY_set1_RSA(evp_key, key)) {
+		ret = openssl_err("EVP key setup failed");
+		goto err_key;
+	}
+
+	size = EVP_PKEY_size(evp_key);
+	if (size > sizeof(sig->sig)) {
+		fprintf(stderr, "Buffer to small for signature (%d bytes)\n",
+			size);
+		ret = -ENOBUFS;
+		goto err_key;
+	}
+
+	ctx = EVP_MD_CTX_create();
+	if (!ctx) {
+		ret = openssl_err("EVP context creation failed");
+		goto err_key;
+	}
+	EVP_MD_CTX_init(ctx);
+	if (!EVP_SignInit(ctx, EVP_sha256())) {
+		ret = openssl_err("Signer setup failed");
+		goto err_ctx;
+	}
+
+	if (!EVP_SignUpdate(ctx, data, datasz)) {
+		ret = openssl_err("Signing data failed");
+		goto err_ctx;
+	}
+
+	if (!EVP_SignFinal(ctx, sig->sig, &sig_size, evp_key)) {
+		ret = openssl_err("Could not obtain signature");
+		goto err_ctx;
+	}
+
+	EVP_MD_CTX_cleanup(ctx);
+	EVP_MD_CTX_destroy(ctx);
+	EVP_PKEY_free(evp_key);
+
+	return 0;
+
+err_ctx:
+	EVP_MD_CTX_destroy(ctx);
+err_key:
+	EVP_PKEY_free(evp_key);
+	fprintf(stderr, "Failed to create %s signature\n", signame);
+	return ret;
+}
+
+int kwb_verify(RSA *key, void *data, int datasz, struct sig_v1 *sig,
+	       char *signame)
+{
+	EVP_PKEY *evp_key;
+	EVP_MD_CTX *ctx;
+	int size;
+	int ret = 0;
+
+	evp_key = EVP_PKEY_new();
+	if (!evp_key)
+		return openssl_err("EVP_PKEY object creation failed");
+
+	if (!EVP_PKEY_set1_RSA(evp_key, key)) {
+		ret = openssl_err("EVP key setup failed");
+		goto err_key;
+	}
+
+	size = EVP_PKEY_size(evp_key);
+	if (size > sizeof(sig->sig)) {
+		fprintf(stderr, "Invalid signature size (%d bytes)\n",
+			size);
+		ret = -EINVAL;
+		goto err_key;
+	}
+
+	ctx = EVP_MD_CTX_create();
+	if (!ctx) {
+		ret = openssl_err("EVP context creation failed");
+		goto err_key;
+	}
+	EVP_MD_CTX_init(ctx);
+	if (!EVP_VerifyInit(ctx, EVP_sha256())) {
+		ret = openssl_err("Verifier setup failed");
+		goto err_ctx;
+	}
+
+	if (!EVP_VerifyUpdate(ctx, data, datasz)) {
+		ret = openssl_err("Hashing data failed");
+		goto err_ctx;
+	}
+
+	if (!EVP_VerifyFinal(ctx, sig->sig, sizeof(sig->sig), evp_key)) {
+		ret = openssl_err("Could not verify signature");
+		goto err_ctx;
+	}
+
+	EVP_MD_CTX_cleanup(ctx);
+	EVP_MD_CTX_destroy(ctx);
+	EVP_PKEY_free(evp_key);
+
+	return 0;
+
+err_ctx:
+	EVP_MD_CTX_destroy(ctx);
+err_key:
+	EVP_PKEY_free(evp_key);
+	fprintf(stderr, "Failed to verify %s signature\n", signame);
+	return ret;
+}
+
+int kwb_sign_and_verify(RSA *key, void *data, int datasz, struct sig_v1 *sig,
+			char *signame)
+{
+	if (kwb_sign(key, data, datasz, sig, signame) < 0)
+		return -1;
+
+	if (kwb_verify(key, data, datasz, sig, signame) < 0)
+		return -1;
+
+	return 0;
+}
+
+
+int kwb_dump_fuse_cmds_38x(FILE *out, struct secure_hdr_v1 *sec_hdr)
+{
+	struct hash_v1 kak_pub_hash;
+	struct image_cfg_element *e;
+	unsigned int fuse_line;
+	int i, idx;
+	uint8_t *ptr;
+	uint32_t val;
+	int ret = 0;
+
+	if (!out || !sec_hdr)
+		return -EINVAL;
+
+	ret = kwb_compute_pubkey_hash(&sec_hdr->kak, &kak_pub_hash);
+	if (ret < 0)
+		goto done;
+
+	fprintf(out, "# burn KAK pub key hash\n");
+	ptr = kak_pub_hash.hash;
+	for (fuse_line = 26; fuse_line <= 30; ++fuse_line) {
+		fprintf(out, "fuse prog -y %u 0 ", fuse_line);
+
+		for (i = 4; i-- > 0;)
+			fprintf(out, "%02hx", (ushort)ptr[i]);
+		ptr += 4;
+		fprintf(out, " 00");
+
+		if (fuse_line < 30) {
+			for (i = 3; i-- > 0;)
+				fprintf(out, "%02hx", (ushort)ptr[i]);
+			ptr += 3;
+		} else {
+			fprintf(out, "000000");
+		}
+
+		fprintf(out, " 1\n");
+	}
+
+	fprintf(out, "# burn CSK selection\n");
+
+	idx = image_get_csk_index();
+	if (idx < 0 || idx > 15) {
+		ret = -EINVAL;
+		goto done;
+	}
+	if (idx > 0) {
+		for (fuse_line = 31; fuse_line < 31 + idx; ++fuse_line)
+			fprintf(out, "fuse prog -y %u 0 00000001 00000000 1\n",
+				fuse_line);
+	} else {
+		fprintf(out, "# CSK index is 0; no mods needed\n");
+	}
+
+	e = image_find_option(IMAGE_CFG_BOX_ID);
+	if (e) {
+		fprintf(out, "# set box ID\n");
+		fprintf(out, "fuse prog -y 48 0 %08x 00000000 1\n", e->boxid);
+	}
+
+	e = image_find_option(IMAGE_CFG_FLASH_ID);
+	if (e) {
+		fprintf(out, "# set flash ID\n");
+		fprintf(out, "fuse prog -y 47 0 %08x 00000000 1\n", e->flashid);
+	}
+
+	fprintf(out, "# enable secure mode ");
+	fprintf(out, "(must be the last fuse line written)\n");
+
+	val = 1;
+	e = image_find_option(IMAGE_CFG_SEC_BOOT_DEV);
+	if (!e) {
+		fprintf(stderr, "ERROR: secured mode boot device not given\n");
+		ret = -EINVAL;
+		goto done;
+	}
+
+	if (e->sec_boot_dev > 0xff) {
+		fprintf(stderr, "ERROR: secured mode boot device invalid\n");
+		ret = -EINVAL;
+		goto done;
+	}
+
+	val |= (e->sec_boot_dev << 8);
+
+	fprintf(out, "fuse prog -y 24 0 %08x 0103e0a9 1\n", val);
+
+	fprintf(out, "# lock (unused) fuse lines (0-23)s\n");
+	for (fuse_line = 0; fuse_line < 24; ++fuse_line)
+		fprintf(out, "fuse prog -y %u 2 1\n", fuse_line);
+
+	fprintf(out, "# OK, that's all :-)\n");
+
+done:
+	return ret;
+}
+
+static int kwb_dump_fuse_cmds(struct secure_hdr_v1 *sec_hdr)
+{
+	int ret = 0;
+	struct image_cfg_element *e;
+
+	e = image_find_option(IMAGE_CFG_SEC_FUSE_DUMP);
+	if (!e)
+		return 0;
+
+	if (!strcmp(e->name, "a38x")) {
+		FILE *out = fopen("kwb_fuses_a38x.txt", "w+");
+
+		kwb_dump_fuse_cmds_38x(out, sec_hdr);
+		fclose(out);
+		goto done;
+	}
+
+	ret = -ENOSYS;
+
+done:
+	return ret;
+}
+
+#endif
+
 static void *image_create_v0(size_t *imagesz, struct image_tool_params *params,
 			     int payloadsz)
 {
@@ -381,6 +939,14 @@ static size_t image_headersz_v1(int *hasext)
 			*hasext = 1;
 	}

+#if defined(CONFIG_KWB_SECURE)
+	if (image_get_csk_index() >= 0) {
+		headersz += sizeof(struct secure_hdr_v1);
+		if (hasext)
+			*hasext = 1;
+	}
+#endif
+
 #if defined(CONFIG_SYS_U_BOOT_OFFS)
 	if (headersz > CONFIG_SYS_U_BOOT_OFFS) {
 		fprintf(stderr,
@@ -476,14 +1042,129 @@ int add_binary_header_v1(uint8_t *cur)
 	return 0;
 }

+#if defined(CONFIG_KWB_SECURE)
+
+int export_pub_kak_hash(RSA *kak, struct secure_hdr_v1 *secure_hdr)
+{
+	FILE *hashf;
+	int res;
+
+	hashf = fopen("pub_kak_hash.txt", "w");
+
+	res = kwb_export_pubkey(kak, &secure_hdr->kak, hashf, "KAK");
+
+	fclose(hashf);
+
+	return res < 0 ? 1 : 0;
+}
+
+int kwb_sign_csk_with_kak(struct image_tool_params *params,
+			  struct secure_hdr_v1 *secure_hdr, RSA *csk)
+{
+	RSA *kak = NULL;
+	RSA *kak_pub = NULL;
+	int csk_idx = image_get_csk_index();
+	struct sig_v1 tmp_sig;
+
+	if (csk_idx >= 16) {
+		fprintf(stderr, "Invalid CSK index %d\n", csk_idx);
+		return 1;
+	}
+
+	if (kwb_load_kak(params, &kak) < 0)
+		return 1;
+
+	if (export_pub_kak_hash(kak, secure_hdr))
+		return 1;
+
+	if (kwb_import_pubkey(&kak_pub, &secure_hdr->kak, "KAK") < 0)
+		return 1;
+
+	if (kwb_export_pubkey(csk, &secure_hdr->csk[csk_idx], NULL, "CSK") < 0)
+		return 1;
+
+	if (kwb_sign_and_verify(kak, &secure_hdr->csk,
+				sizeof(secure_hdr->csk) +
+				sizeof(secure_hdr->csksig),
+				&tmp_sig, "CSK") < 0)
+		return 1;
+
+	if (kwb_verify(kak_pub, &secure_hdr->csk,
+		       sizeof(secure_hdr->csk) +
+		       sizeof(secure_hdr->csksig),
+		       &tmp_sig, "CSK (2)") < 0)
+		return 1;
+
+	secure_hdr->csksig = tmp_sig;
+
+	return 0;
+}
+
+int add_secure_header_v1(struct image_tool_params *params, uint8_t *ptr,
+			 int payloadsz, size_t headersz, uint8_t *image,
+			 struct secure_hdr_v1 *secure_hdr)
+{
+	struct image_cfg_element *e_jtagdelay;
+	struct image_cfg_element *e_boxid;
+	struct image_cfg_element *e_flashid;
+	RSA *csk = NULL;
+	unsigned char *image_ptr;
+	size_t image_size;
+	struct sig_v1 tmp_sig;
+	bool specialized_img = image_get_spezialized_img();
+
+	kwb_msg("Create secure header content\n");
+
+	e_jtagdelay = image_find_option(IMAGE_CFG_JTAG_DELAY);
+	e_boxid = image_find_option(IMAGE_CFG_BOX_ID);
+	e_flashid = image_find_option(IMAGE_CFG_FLASH_ID);
+
+	if (kwb_load_csk(params, &csk) < 0)
+		return 1;
+
+	secure_hdr->headertype = OPT_HDR_V1_SECURE_TYPE;
+	secure_hdr->headersz_msb = 0;
+	secure_hdr->headersz_lsb = cpu_to_le16(sizeof(struct secure_hdr_v1));
+	if (e_jtagdelay)
+		secure_hdr->jtag_delay = e_jtagdelay->jtag_delay;
+	if (e_boxid && specialized_img)
+		secure_hdr->boxid = cpu_to_le32(e_boxid->boxid);
+	if (e_flashid && specialized_img)
+		secure_hdr->flashid = cpu_to_le32(e_flashid->flashid);
+
+	if (kwb_sign_csk_with_kak(params, secure_hdr, csk))
+		return 1;
+
+	image_ptr = ptr + headersz;
+	image_size = payloadsz - headersz;
+
+	if (kwb_sign_and_verify(csk, image_ptr, image_size,
+				&secure_hdr->imgsig, "image") < 0)
+		return 1;
+
+	if (kwb_sign_and_verify(csk, image, headersz, &tmp_sig, "header") < 0)
+		return 1;
+
+	secure_hdr->hdrsig = tmp_sig;
+
+	kwb_dump_fuse_cmds(secure_hdr);
+
+	return 0;
+}
+#endif
+
 static void *image_create_v1(size_t *imagesz, struct image_tool_params *params,
-			     int payloadsz)
+			     uint8_t *ptr, int payloadsz)
 {
 	struct image_cfg_element *e;
 	struct main_hdr_v1 *main_hdr;
+#if defined(CONFIG_KWB_SECURE)
+	struct secure_hdr_v1 *secure_hdr = NULL;
+#endif
 	size_t headersz;
 	uint8_t *image, *cur;
 	int hasext = 0;
+	uint8_t *next_ext = NULL;

 	/*
 	 * Calculate the size of the header and the size of the
@@ -502,7 +1183,9 @@ static void *image_create_v1(size_t *imagesz, struct image_tool_params *params,
 	memset(image, 0, headersz);

 	main_hdr = (struct main_hdr_v1 *)image;
-	cur = image + sizeof(struct main_hdr_v1);
+	cur = image;
+	cur += sizeof(struct main_hdr_v1);
+	next_ext = &main_hdr->ext;

 	/* Fill the main header */
 	main_hdr->blocksize    =
@@ -531,9 +1214,28 @@ static void *image_create_v1(size_t *imagesz, struct image_tool_params *params,
 	if (e)
 		main_hdr->flags = e->debug ? 0x1 : 0;

+#if defined(CONFIG_KWB_SECURE)
+	if (image_get_csk_index() >= 0) {
+		/*
+		 * only reserve the space here; we fill the header later since
+		 * we need the header to be complete to compute the signatures
+		 */
+		secure_hdr = (struct secure_hdr_v1 *)cur;
+		cur += sizeof(struct secure_hdr_v1);
+		next_ext = &secure_hdr->next;
+	}
+#endif
+	*next_ext = 1;
+
 	if (add_binary_header_v1(cur))
 		return NULL;

+#if defined(CONFIG_KWB_SECURE)
+	if (secure_hdr && add_secure_header_v1(params, ptr, payloadsz,
+					       headersz, image, secure_hdr))
+		return NULL;
+#endif
+
 	/* Calculate and set the header checksum */
 	main_hdr->checksum = image_checksum8(main_hdr, headersz);

@@ -645,6 +1347,36 @@ static int image_create_config_parse_oneline(char *line,
 	case IMAGE_CFG_DEBUG:
 		el->debug = strtoul(value1, NULL, 10);
 		break;
+	case IMAGE_CFG_KAK:
+		el->key_name = strdup(value1);
+		break;
+	case IMAGE_CFG_CSK:
+		el->key_name = strdup(value1);
+		break;
+	case IMAGE_CFG_CSK_INDEX:
+		el->csk_idx = strtol(value1, NULL, 0);
+		break;
+	case IMAGE_CFG_JTAG_DELAY:
+		el->jtag_delay = strtoul(value1, NULL, 0);
+		break;
+	case IMAGE_CFG_BOX_ID:
+		el->boxid = strtoul(value1, NULL, 0);
+		break;
+	case IMAGE_CFG_FLASH_ID:
+		el->flashid = strtoul(value1, NULL, 0);
+		break;
+	case IMAGE_CFG_SEC_SPECIALIZED_IMG:
+		el->sec_specialized_img = true;
+		break;
+	case IMAGE_CFG_SEC_COMMON_IMG:
+		el->sec_specialized_img = false;
+		break;
+	case IMAGE_CFG_SEC_BOOT_DEV:
+		el->sec_boot_dev = strtoul(value1, NULL, 0);
+		break;
+	case IMAGE_CFG_SEC_FUSE_DUMP:
+		el->name = strdup(value1);
+		break;
 	default:
 		fprintf(stderr, unknown_msg, line);
 	}
@@ -804,7 +1536,7 @@ static void kwbimage_set_header(void *ptr, struct stat *sbuf, int ifd,
 		break;

 	case 1:
-		image = image_create_v1(&headersz, params, sbuf->st_size);
+		image = image_create_v1(&headersz, params, ptr, sbuf->st_size);
 		break;

 	default:
diff --git a/tools/kwbimage.h b/tools/kwbimage.h
index 01c2f1f..20f4d0d 100644
--- a/tools/kwbimage.h
+++ b/tools/kwbimage.h
@@ -114,6 +114,43 @@ struct opt_hdr_v1 {
 };

 /*
+ * Public Key data in DER format
+ */
+struct pubkey_der_v1 {
+	uint8_t key[524];
+};
+
+/*
+ * Signature (RSA 2048)
+ */
+struct sig_v1 {
+	uint8_t sig[256];
+};
+
+/*
+ * Structure of secure header (Armada 38x)
+ */
+struct secure_hdr_v1 {
+	uint8_t  headertype;		/* 0x0 */
+	uint8_t  headersz_msb;		/* 0x1 */
+	uint16_t headersz_lsb;		/* 0x2 - 0x3 */
+	uint32_t reserved1;		/* 0x4 - 0x7 */
+	struct pubkey_der_v1 kak;	/* 0x8 - 0x213 */
+	uint8_t  jtag_delay;		/* 0x214 */
+	uint8_t  reserved2;		/* 0x215 */
+	uint16_t reserved3;		/* 0x216 - 0x217 */
+	uint32_t boxid;			/* 0x218 - 0x21B */
+	uint32_t flashid;		/* 0x21C - 0x21F */
+	struct sig_v1 hdrsig;		/* 0x220 - 0x31F */
+	struct sig_v1 imgsig;		/* 0x320 - 0x41F */
+	struct pubkey_der_v1 csk[16];	/* 0x420 - 0x24DF */
+	struct sig_v1 csksig;		/* 0x24E0 - 0x25DF */
+	uint8_t  next;			/* 0x25E0 */
+	uint8_t  reserved4;		/* 0x25E1 */
+	uint16_t reserved5;		/* 0x25E2 - 0x25E3 */
+};
+
+/*
  * Various values for the opt_hdr_v1->headertype field, describing the
  * different types of optional headers. The "secure" header contains
  * informations related to secure boot (encryption keys, etc.). The
--
2.9.0

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [U-Boot] [PATCH v2 17/18] arm: mvebu: Add gdsys ControlCenter-Compact board
  2017-01-11 15:00 [U-Boot] [PATCH v2 00/18] arm: mvebu: Add gdsys ControlCenter-Compact board Mario Six
                   ` (15 preceding siblings ...)
  2017-01-11 15:01 ` [U-Boot] [PATCH v2 16/18] arm: mvebu: Implement secure boot Mario Six
@ 2017-01-11 15:01 ` Mario Six
  2017-01-18 17:09   ` Stefan Roese
  2017-01-11 15:01 ` [U-Boot] [PATCH v2 18/18] controlcenterdc: Make secure boot available Mario Six
  17 siblings, 1 reply; 55+ messages in thread
From: Mario Six @ 2017-01-11 15:01 UTC (permalink / raw)
  To: u-boot

From: Dirk Eibach <dirk.eibach@gdsys.cc>

The gdsys ControlCenter Digital board is based on a Marvell Armada 38x
SOC.

It boots from SPI-Flash but can be configured to boot from SD-card for
factory programming and testing.

On board peripherals include:
- 2 x GbE
- Xilinx Kintex-7 FPGA connected via PCIe
- mSATA
- USB3 host
- Atmel TPM

Signed-off-by: Dirk Eibach <dirk.eibach@gdsys.cc>
Signed-off-by: Mario Six <mario.six@gdsys.cc>
---
Changes in v2:

* Renamed DTS and board name to include armada-38x
* Renamed 38x directory to a38x
* Removed leftover dummy test Kconfig variable from board/gdsys/38x/Kconfig
* Removed unneeded check for build target in board/gdsys/38x/Makefile
* Removed duplicated board/gdsys/38x/README
* Switched MIIPHY to new GPIO API
* Removed checkboard function
* Fixed multi-line comment in board/gdsys/controlcenterdc.c
* Switched to usage of ARRAY_SIZE in board/gdsys/controlcenterdc.c
* Factored out hydra.{c,h} and ihs_phys.{c,h} from
  board/gdsys/controlcenterdc.c and removed ifdefs
* Removed unaddressed TODO from HRE
---
 arch/arm/Kconfig                            |   1 +
 arch/arm/dts/Makefile                       |   3 +-
 arch/arm/dts/armada-38x-controlcenterdc.dts | 643 ++++++++++++++++++++++++++++
 arch/arm/mach-mvebu/Kconfig                 |   4 +
 board/gdsys/a38x/.gitignore                 |   1 +
 board/gdsys/a38x/Kconfig                    |  36 ++
 board/gdsys/a38x/MAINTAINERS                |   7 +
 board/gdsys/a38x/Makefile                   |  44 ++
 board/gdsys/a38x/controlcenterdc.c          | 273 ++++++++++++
 board/gdsys/a38x/dt_helpers.c               |  25 ++
 board/gdsys/a38x/dt_helpers.h               |  14 +
 board/gdsys/a38x/hre.c                      | 516 ++++++++++++++++++++++
 board/gdsys/a38x/hre.h                      |  38 ++
 board/gdsys/a38x/hydra.c                    | 138 ++++++
 board/gdsys/a38x/hydra.h                    |  14 +
 board/gdsys/a38x/ihs_phys.c                 | 349 +++++++++++++++
 board/gdsys/a38x/ihs_phys.h                 |   2 +
 board/gdsys/a38x/keyprogram.c               | 158 +++++++
 board/gdsys/a38x/keyprogram.h               |  14 +
 board/gdsys/a38x/kwbimage.cfg.in            |  12 +
 board/gdsys/a38x/spl.c                      |  21 +
 configs/controlcenterdc_defconfig           |  57 +++
 include/configs/controlcenterdc.h           | 235 ++++++++++
 23 files changed, 2604 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm/dts/armada-38x-controlcenterdc.dts
 create mode 100644 board/gdsys/a38x/.gitignore
 create mode 100644 board/gdsys/a38x/Kconfig
 create mode 100644 board/gdsys/a38x/MAINTAINERS
 create mode 100644 board/gdsys/a38x/Makefile
 create mode 100644 board/gdsys/a38x/controlcenterdc.c
 create mode 100644 board/gdsys/a38x/dt_helpers.c
 create mode 100644 board/gdsys/a38x/dt_helpers.h
 create mode 100644 board/gdsys/a38x/hre.c
 create mode 100644 board/gdsys/a38x/hre.h
 create mode 100644 board/gdsys/a38x/hydra.c
 create mode 100644 board/gdsys/a38x/hydra.h
 create mode 100644 board/gdsys/a38x/ihs_phys.c
 create mode 100644 board/gdsys/a38x/ihs_phys.h
 create mode 100644 board/gdsys/a38x/keyprogram.c
 create mode 100644 board/gdsys/a38x/keyprogram.h
 create mode 100644 board/gdsys/a38x/kwbimage.cfg.in
 create mode 100644 board/gdsys/a38x/spl.c
 create mode 100644 configs/controlcenterdc_defconfig
 create mode 100644 include/configs/controlcenterdc.h

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 0ed36cd..3ddc4c2 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1028,6 +1028,7 @@ source "board/freescale/mx53loco/Kconfig"
 source "board/freescale/mx53smd/Kconfig"
 source "board/freescale/s32v234evb/Kconfig"
 source "board/freescale/vf610twr/Kconfig"
+source "board/gdsys/a38x/Kconfig"
 source "board/gumstix/pepper/Kconfig"
 source "board/h2200/Kconfig"
 source "board/hisilicon/hikey/Kconfig"
diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
index 3ee608b..75632d8 100644
--- a/arch/arm/dts/Makefile
+++ b/arch/arm/dts/Makefile
@@ -79,7 +79,8 @@ dtb-$(CONFIG_ARCH_MVEBU) +=			\
 	armada-xp-gp.dtb			\
 	armada-xp-maxbcm.dtb			\
 	armada-xp-synology-ds414.dtb		\
-	armada-xp-theadorable.dtb
+	armada-xp-theadorable.dtb		\
+	armada-38x-controlcenterdc.dtb

 dtb-$(CONFIG_ARCH_UNIPHIER) += \
 	uniphier-ld11-ref.dtb \
diff --git a/arch/arm/dts/armada-38x-controlcenterdc.dts b/arch/arm/dts/armada-38x-controlcenterdc.dts
new file mode 100644
index 0000000..36f65c3
--- /dev/null
+++ b/arch/arm/dts/armada-38x-controlcenterdc.dts
@@ -0,0 +1,643 @@
+/*
+ * Device Tree file for the Guntermann & Drunck ControlCenter-Compact board
+ *
+ * Copyright (C) 2016 Mario Six <mario.six@gdsys.cc>
+ *
+ * based on the Device Tree file for Marvell Armada 388 evaluation board
+ * (DB-88F6820), which is
+ *
+ * Copyright (C) 2014 Marvell
+ *
+ * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+/dts-v1/;
+
+#include "armada-388.dtsi"
+
+&gpio0 {
+	u-boot,dm-pre-reloc;
+};
+
+&gpio1 {
+	u-boot,dm-pre-reloc;
+};
+
+&uart0 {
+	u-boot,dm-pre-reloc;
+};
+
+&uart1 {
+	u-boot,dm-pre-reloc;
+};
+
+/ {
+	model = "Controlcenter Digital Compact";
+	compatible = "marvell,a385-db", "marvell,armada388",
+		"marvell,armada385", "marvell,armada380";
+
+	chosen {
+		bootargs = "console=ttyS1,115200 earlyprintk";
+		stdout-path = "/soc/internal-regs/serial at 12100";
+	};
+
+	aliases {
+		ethernet0 = &eth0;
+		ethernet2 = &eth2;
+		mdio-gpio0 = &MDIO0;
+		mdio-gpio1 = &MDIO1;
+		mdio-gpio2 = &MDIO2;
+		spi0 = &spi0;
+		spi1 = &spi1;
+		i2c0 = &I2C0;
+		i2c1 = &I2C1;
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x00000000 0x10000000>; /* 256 MB */
+	};
+
+	clocks {
+		sc16isclk: sc16isclk {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <11059200>;
+		};
+	};
+
+	soc {
+		ranges = <MBUS_ID(0xf0, 0x01) 0 0xf1000000 0x100000
+			  MBUS_ID(0x01, 0x1d) 0 0xfff00000 0x100000>;
+
+		internal-regs {
+			spi0: spi at 10600 {
+				status = "okay";
+				sc16is741: sc16is741 at 0 {
+					compatible = "nxp,sc16is741";
+					reg = <0>;
+					clocks = <&sc16isclk>;
+					spi-max-frequency = <4000000>;
+					interrupt-parent = <&gpio0>;
+					interrupts = <11 IRQ_TYPE_EDGE_FALLING>;
+					gpio-controller;
+					#gpio-cells = <2>;
+				};
+			};
+
+			spi1: spi at 10680 {
+				status = "okay";
+				u-boot,dm-pre-reloc;
+				spi-flash at 0 {
+					#address-cells = <1>;
+					#size-cells = <1>;
+					compatible = "n25q016a";
+					reg = <0>; /* Chip select 0 */
+					spi-max-frequency = <108000000>;
+				};
+				spi-flash at 1 {
+					#address-cells = <1>;
+					#size-cells = <1>;
+					compatible = "n25q128a11";
+					reg = <1>; /* Chip select 1 */
+					spi-max-frequency = <108000000>;
+					u-boot,dm-pre-reloc;
+				};
+			};
+
+			I2C0: i2c at 11000 {
+				status = "okay";
+				clock-frequency = <1000000>;
+				u-boot,dm-pre-reloc;
+				PCA21: pca9698 at 21 {
+					compatible = "nxp,pca9698";
+					reg = <0x21>;
+					#gpio-cells = <2>;
+					gpio-controller;
+				};
+				PCA22: pca9698 at 22 {
+					compatible = "nxp,pca9698";
+					u-boot,dm-pre-reloc;
+					reg = <0x22>;
+					#gpio-cells = <2>;
+					gpio-controller;
+				};
+				PCA23: pca9698 at 23 {
+					compatible = "nxp,pca9698";
+					reg = <0x23>;
+					#gpio-cells = <2>;
+					gpio-controller;
+				};
+				PCA24: pca9698 at 24 {
+					compatible = "nxp,pca9698";
+					reg = <0x24>;
+					#gpio-cells = <2>;
+					gpio-controller;
+				};
+				PCA25: pca9698 at 25 {
+					compatible = "nxp,pca9698";
+					reg = <0x25>;
+					#gpio-cells = <2>;
+					gpio-controller;
+				};
+				PCA26: pca9698 at 26 {
+					compatible = "nxp,pca9698";
+					reg = <0x26>;
+					#gpio-cells = <2>;
+					gpio-controller;
+				};
+			};
+
+			I2C1: i2c at 11100 {
+				status = "okay";
+				clock-frequency = <400000>;
+				at97sc3205t at 29 {
+					compatible = "atmel,at97sc3204t";
+					reg = <0x29>;
+					u-boot,i2c-offset-len = <0>;
+				};
+				emc2305 at 2d {
+					compatible = "smsc,emc2305";
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <0x2d>;
+					fan at 0 {
+						reg = <0>;
+					};
+					fan at 1 {
+						reg = <1>;
+					};
+					fan at 2 {
+						reg = <2>;
+					};
+					fan at 3 {
+						reg = <3>;
+					};
+					fan at 4 {
+						reg = <4>;
+					};
+				};
+				lm77 at 48 {
+					compatible = "national,lm77";
+					reg = <0x48>;
+				};
+				ads1015 at 49 {
+					compatible = "ti,ads1015";
+					reg = <0x49>;
+				};
+				lm77 at 4a {
+					compatible = "national,lm77";
+					reg = <0x4a>;
+				};
+				ads1015 at 4b {
+					compatible = "ti,ads1015";
+					reg = <0x4b>;
+				};
+				emc2305 at 4c {
+					compatible = "smsc,emc2305";
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <0x4c>;
+					fan at 0 {
+						reg = <0>;
+					};
+					fan at 1 {
+						reg = <1>;
+					};
+					fan at 2 {
+						reg = <2>;
+					};
+					fan at 3 {
+						reg = <3>;
+					};
+					fan at 4 {
+						reg = <4>;
+					};
+				};
+				at24c512 at 54 {
+					compatible = "atmel,24c512";
+					reg = <0x54>;
+					u-boot,i2c-offset-len = <2>;
+				};
+				ds1339 at 68 {
+					compatible = "dallas,ds1339";
+					reg = <0x68>;
+				};
+			};
+
+			serial at 12000 {
+				status = "okay";
+			};
+
+			serial at 12100 {
+				status = "okay";
+			};
+
+			ethernet at 34000 {
+				status = "okay";
+				phy = <&phy1>;
+				phy-mode = "sgmii";
+			};
+
+			usb at 58000 {
+				status = "ok";
+			};
+
+			ethernet at 70000 {
+				status = "okay";
+				phy = <&phy0>;
+				phy-mode = "sgmii";
+			};
+
+			mdio at 72004 {
+				phy0: ethernet-phy at 0 {
+					reg = <1>;
+				};
+
+				phy1: ethernet-phy at 1 {
+					reg = <0>;
+				};
+			};
+
+			sata at a8000 {
+				status = "okay";
+			};
+
+			sdhci at d8000 {
+				broken-cd;
+				wp-inverted;
+				bus-width = <4>;
+				status = "okay";
+				no-1-8-v;
+			};
+
+			usb3 at f0000 {
+				status = "okay";
+			};
+		};
+
+		pcie-controller {
+			status = "okay";
+			/*
+			 * The two PCIe units are accessible through
+			 * standard PCIe slots on the board.
+			 */
+			pcie at 3,0 {
+				/* Port 0, Lane 0 */
+				status = "okay";
+			};
+		};
+
+		MDIO0: mdio0 {
+			compatible = "virtual,mdio-gpio";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			gpios = < /*MDC*/ &gpio0 13 0
+				  /*MDIO*/ &gpio0 14 0>;
+			mv88e1240 at 0 {
+				reg = <0x0>;
+			};
+			mv88e1240 at 1 {
+				reg = <0x1>;
+			};
+			mv88e1240 at 2 {
+				reg = <0x2>;
+			};
+			mv88e1240 at 3 {
+				reg = <0x3>;
+			};
+			mv88e1240 at 4 {
+				reg = <0x4>;
+			};
+			mv88e1240 at 5 {
+				reg = <0x5>;
+			};
+			mv88e1240 at 6 {
+				reg = <0x6>;
+			};
+			mv88e1240 at 7 {
+				reg = <0x7>;
+			};
+			mv88e1240 at 8 {
+				reg = <0x8>;
+			};
+			mv88e1240 at 9 {
+				reg = <0x9>;
+			};
+			mv88e1240 at a {
+				reg = <0xa>;
+			};
+			mv88e1240 at b {
+				reg = <0xb>;
+			};
+			mv88e1240 at c {
+				reg = <0xc>;
+			};
+			mv88e1240 at d {
+				reg = <0xd>;
+			};
+			mv88e1240 at e {
+				reg = <0xe>;
+			};
+			mv88e1240 at f {
+				reg = <0xf>;
+			};
+			mv88e1240 at 10 {
+				reg = <0x10>;
+			};
+			mv88e1240 at 11 {
+				reg = <0x11>;
+			};
+			mv88e1240 at 12 {
+				reg = <0x12>;
+			};
+			mv88e1240 at 13 {
+				reg = <0x13>;
+			};
+			mv88e1240 at 14 {
+				reg = <0x14>;
+			};
+			mv88e1240 at 15 {
+				reg = <0x15>;
+			};
+			mv88e1240 at 16 {
+				reg = <0x16>;
+			};
+			mv88e1240 at 17 {
+				reg = <0x17>;
+			};
+			mv88e1240 at 18 {
+				reg = <0x18>;
+			};
+			mv88e1240 at 19 {
+				reg = <0x19>;
+			};
+			mv88e1240 at 1a {
+				reg = <0x1a>;
+			};
+			mv88e1240 at 1b {
+				reg = <0x1b>;
+			};
+			mv88e1240 at 1c {
+				reg = <0x1c>;
+			};
+			mv88e1240 at 1d {
+				reg = <0x1d>;
+			};
+			mv88e1240 at 1e {
+				reg = <0x1e>;
+			};
+			mv88e1240 at 1f {
+				reg = <0x1f>;
+			};
+		};
+
+		MDIO1: mdio1 {
+			compatible = "virtual,mdio-gpio";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			gpios = < /*MDC*/ &gpio0 25 0
+				  /*MDIO*/ &gpio1 13 0>;
+			mv88e1240 at 0 {
+				reg = <0x0>;
+			};
+			mv88e1240 at 1 {
+				reg = <0x1>;
+			};
+			mv88e1240 at 2 {
+				reg = <0x2>;
+			};
+			mv88e1240 at 3 {
+				reg = <0x3>;
+			};
+			mv88e1240 at 4 {
+				reg = <0x4>;
+			};
+			mv88e1240 at 5 {
+				reg = <0x5>;
+			};
+			mv88e1240 at 6 {
+				reg = <0x6>;
+			};
+			mv88e1240 at 7 {
+				reg = <0x7>;
+			};
+			mv88e1240 at 8 {
+				reg = <0x8>;
+			};
+			mv88e1240 at 9 {
+				reg = <0x9>;
+			};
+			mv88e1240 at a {
+				reg = <0xa>;
+			};
+			mv88e1240 at b {
+				reg = <0xb>;
+			};
+			mv88e1240 at c {
+				reg = <0xc>;
+			};
+			mv88e1240 at d {
+				reg = <0xd>;
+			};
+			mv88e1240 at e {
+				reg = <0xe>;
+			};
+			mv88e1240 at f {
+				reg = <0xf>;
+			};
+			mv88e1240 at 10 {
+				reg = <0x10>;
+			};
+			mv88e1240 at 11 {
+				reg = <0x11>;
+			};
+			mv88e1240 at 12 {
+				reg = <0x12>;
+			};
+			mv88e1240 at 13 {
+				reg = <0x13>;
+			};
+			mv88e1240 at 14 {
+				reg = <0x14>;
+			};
+			mv88e1240 at 15 {
+				reg = <0x15>;
+			};
+			mv88e1240 at 16 {
+				reg = <0x16>;
+			};
+			mv88e1240 at 17 {
+				reg = <0x17>;
+			};
+			mv88e1240 at 18 {
+				reg = <0x18>;
+			};
+			mv88e1240 at 19 {
+				reg = <0x19>;
+			};
+			mv88e1240 at 1a {
+				reg = <0x1a>;
+			};
+			mv88e1240 at 1b {
+				reg = <0x1b>;
+			};
+			mv88e1240 at 1c {
+				reg = <0x1c>;
+			};
+			mv88e1240 at 1d {
+				reg = <0x1d>;
+			};
+			mv88e1240 at 1e {
+				reg = <0x1e>;
+			};
+			mv88e1240 at 1f {
+				reg = <0x1f>;
+			};
+		};
+
+		MDIO2: mdio2 {
+			compatible = "virtual,mdio-gpio";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			gpios = < /*MDC*/ &gpio1 14 0
+				  /*MDIO*/ &gpio0 24 0>;
+			mv88e1240 at 0 {
+				reg = <0x0>;
+			};
+			mv88e1240 at 1 {
+				reg = <0x1>;
+			};
+			mv88e1240 at 2 {
+				reg = <0x2>;
+			};
+			mv88e1240 at 3 {
+				reg = <0x3>;
+			};
+			mv88e1240 at 4 {
+				reg = <0x4>;
+			};
+			mv88e1240 at 5 {
+				reg = <0x5>;
+			};
+			mv88e1240 at 6 {
+				reg = <0x6>;
+			};
+			mv88e1240 at 7 {
+				reg = <0x7>;
+			};
+			mv88e1240 at 8 {
+				reg = <0x8>;
+			};
+			mv88e1240 at 9 {
+				reg = <0x9>;
+			};
+			mv88e1240 at a {
+				reg = <0xa>;
+			};
+			mv88e1240 at b {
+				reg = <0xb>;
+			};
+			mv88e1240 at c {
+				reg = <0xc>;
+			};
+			mv88e1240 at d {
+				reg = <0xd>;
+			};
+			mv88e1240 at e {
+				reg = <0xe>;
+			};
+			mv88e1240 at f {
+				reg = <0xf>;
+			};
+			mv88e1240 at 10 {
+				reg = <0x10>;
+			};
+			mv88e1240 at 11 {
+				reg = <0x11>;
+			};
+			mv88e1240 at 12 {
+				reg = <0x12>;
+			};
+			mv88e1240 at 13 {
+				reg = <0x13>;
+			};
+			mv88e1240 at 14 {
+				reg = <0x14>;
+			};
+			mv88e1240 at 15 {
+				reg = <0x15>;
+			};
+		};
+	};
+
+	cat_gpio_0 {
+		compatible = "generic,cat-gpio-0";
+		gpios = <&PCA23 0x20 0x0>;
+	};
+
+	cat_gpio_1 {
+		compatible = "generic,cat-gpio-1";
+		gpios = <&PCA21 0x20 0x0>;
+	};
+
+	cat_gpio_2 {
+		compatible = "generic,cat-gpio-2";
+		gpios = <&PCA24 0x20 0x0>;
+	};
+
+	cat_gpio_3 {
+		compatible = "generic,cat-gpio-3";
+		gpios = <&PCA25 0x20 0x0>;
+	};
+
+	cat_gpio_4 {
+		compatible = "generic,cat-gpio-4";
+		gpios = <&PCA26 0x20 0x0>;
+	};
+
+	second_octo_gpio_0 {
+		compatible = "generic,second-octo-gpio-0";
+		gpios = <&PCA23 0x27 0x0>;
+	};
+
+	fpga_program_gpio {
+		compatible = "generic,fpga-program-gpio";
+		u-boot,dm-pre-reloc;
+		gpios = <&PCA22 31 0>;
+	};
+
+	fpga_done_gpio {
+		compatible = "generic,fpga-done-gpio";
+		u-boot,dm-pre-reloc;
+		gpios = <&PCA22 19 0>;
+	};
+
+	fpga_ready_gpio {
+		compatible = "generic,fpga-ready-gpio";
+		u-boot,dm-pre-reloc;
+		gpios = <&PCA22 27 0>;
+	};
+
+	cpu-to-fpga-reset {
+		compatible = "generic,cpu-to-fpga-reset";
+		u-boot,dm-pre-reloc;
+		gpios = < &gpio0 6 0 >;
+	};
+
+	leds {
+		compatible = "gpio-leds";
+
+		finder_led {
+			label = "finder-led";
+			gpios = <&PCA22 25 0>;
+		};
+
+		status_led {
+			label = "status-led";
+			gpios = <&gpio0 29 0>;
+		};
+	};
+};
diff --git a/arch/arm/mach-mvebu/Kconfig b/arch/arm/mach-mvebu/Kconfig
index c9609fb..4af040d 100644
--- a/arch/arm/mach-mvebu/Kconfig
+++ b/arch/arm/mach-mvebu/Kconfig
@@ -108,6 +108,10 @@ config TARGET_THEADORABLE
 	bool "Support theadorable Armada XP"
 	select MV78260

+config TARGET_CONTROLCENTERDC
+	bool "Support CONTROLCENTERDC"
+	select 88F6820
+
 endchoice

 config SYS_BOARD
diff --git a/board/gdsys/a38x/.gitignore b/board/gdsys/a38x/.gitignore
new file mode 100644
index 0000000..775b934
--- /dev/null
+++ b/board/gdsys/a38x/.gitignore
@@ -0,0 +1 @@
+kwbimage.cfg
diff --git a/board/gdsys/a38x/Kconfig b/board/gdsys/a38x/Kconfig
new file mode 100644
index 0000000..3fdef64
--- /dev/null
+++ b/board/gdsys/a38x/Kconfig
@@ -0,0 +1,36 @@
+if TARGET_CONTROLCENTERDC
+
+config SYS_BOARD
+	default "a38x"
+
+config SYS_VENDOR
+	default "gdsys"
+
+config SYS_SOC
+	default "mvebu"
+
+config SYS_CONFIG_NAME
+	default "controlcenterdc"
+
+menu "Controlcenter DC board options"
+
+choice
+	prompt "Select boot method"
+
+config SPL_BOOT_DEVICE_SPI
+	bool "SPI"
+
+config SPL_BOOT_DEVICE_MMC
+	bool "MMC"
+	select SPL_LIBDISK_SUPPORT
+
+endchoice
+
+#config SPL_BOOT_DEVICE
+#	int
+#	default 1 if SPL_BOOT_DEVICE_SPI
+#	default 2 if SPL_BOOT_DEVICE_MMC
+
+endmenu
+
+endif
diff --git a/board/gdsys/a38x/MAINTAINERS b/board/gdsys/a38x/MAINTAINERS
new file mode 100644
index 0000000..3cb9b63
--- /dev/null
+++ b/board/gdsys/a38x/MAINTAINERS
@@ -0,0 +1,7 @@
+A38X BOARD
+M:	Dirk Eibach <eibach@gdsys.cc>
+M:	Mario Six <six@gdsys.de>
+S:	Maintained
+F:	board/gdsys/a38x/
+F:	include/configs/controlcenterdc.h
+F:	configs/controlcenterdc_defconfig
diff --git a/board/gdsys/a38x/Makefile b/board/gdsys/a38x/Makefile
new file mode 100644
index 0000000..0c256d3
--- /dev/null
+++ b/board/gdsys/a38x/Makefile
@@ -0,0 +1,44 @@
+#
+# Copyright (C) 2015 Stefan Roese <sr@denx.de>
+# Copyright (C) 2015 Reinhard Pfau <reinhard.pfau@gdsys.cc>
+# Copyright (C) 2016 Mario Six <mario.six@gdsys.cc>
+#
+# SPDX-License-Identifier:	GPL-2.0+
+#
+
+obj-$(CONFIG_TARGET_CONTROLCENTERDC) += controlcenterdc.o hre.o spl.o keyprogram.o dt_helpers.o
+
+ifeq ($(CONFIG_SPL_BUILD),)
+
+obj-$(CONFIG_TARGET_CONTROLCENTERDC) += hydra.o ihs_phys.o
+
+extra-$(CONFIG_TARGET_CONTROLCENTERDC) += kwbimage.cfg
+
+KWB_REPLACE += BOOT_FROM
+ifneq ($(CONFIG_SPL_BOOT_DEVICE_SPI),)
+	KWB_CFG_BOOT_FROM=spi
+endif
+ifneq ($(CONFIG_SPL_BOOT_DEVICE_MMC),)
+	KWB_CFG_BOOT_FROM=sdio
+endif
+
+ifneq ($(CONFIG_SECURED_MODE_IMAGE),)
+KWB_REPLACE += CSK_INDEX
+KWB_CFG_CSK_INDEX = $(CONFIG_SECURED_MODE_CSK_INDEX)
+
+KWB_REPLACE += SEC_BOOT_DEV
+KWB_CFG_SEC_BOOT_DEV=$(patsubst "%",%, \
+	$(if $(findstring BOOT_SPI_NOR_FLASH,$(CONFIG_SPL_BOOT_DEVICE)),0x34) \
+	$(if $(findstring BOOT_SDIO_MMC_CARD,$(CONFIG_SPL_BOOT_DEVICE)),0x31) \
+	)
+
+KWB_REPLACE += SEC_FUSE_DUMP
+KWB_CFG_SEC_FUSE_DUMP = a38x
+endif
+
+$(src)/kwbimage.cfg: $(src)/kwbimage.cfg.in include/autoconf.mk \
+		include/config/auto.conf
+	$(Q)sed -ne '$(foreach V,$(KWB_REPLACE),s/^#@$(V)/$(V) $(KWB_CFG_$(V))/;)p' \
+	<$< >$@
+
+endif
diff --git a/board/gdsys/a38x/controlcenterdc.c b/board/gdsys/a38x/controlcenterdc.c
new file mode 100644
index 0000000..7c747ee
--- /dev/null
+++ b/board/gdsys/a38x/controlcenterdc.c
@@ -0,0 +1,273 @@
+/*
+ * Copyright (C) 2015 Stefan Roese <sr@denx.de>
+ * Copyright (C) 2016 Mario Six <mario.six@gdsys.cc>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <miiphy.h>
+#include <tpm.h>
+#include <asm/io.h>
+#include <asm/arch/cpu.h>
+#include <asm-generic/gpio.h>
+
+#include "../drivers/ddr/marvell/a38x/ddr3_a38x_topology.h"
+#include "../arch/arm/mach-mvebu/serdes/a38x/high_speed_env_spec.h"
+
+#include "keyprogram.h"
+#include "dt_helpers.h"
+#include "hydra.h"
+#include "ihs_phys.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define ETH_PHY_CTRL_REG		0
+#define ETH_PHY_CTRL_POWER_DOWN_BIT	11
+#define ETH_PHY_CTRL_POWER_DOWN_MASK	(1 << ETH_PHY_CTRL_POWER_DOWN_BIT)
+
+#define DB_GP_88F68XX_GPP_OUT_ENA_LOW	0x7fffffff
+#define DB_GP_88F68XX_GPP_OUT_ENA_MID	0xffffefff
+
+#define DB_GP_88F68XX_GPP_OUT_VAL_LOW	0x0
+#define DB_GP_88F68XX_GPP_OUT_VAL_MID	0x00001000
+#define DB_GP_88F68XX_GPP_POL_LOW	0x0
+#define DB_GP_88F68XX_GPP_POL_MID	0x0
+
+/*
+ * Define the DDR layout / topology here in the board file. This will
+ * be used by the DDR3 init code in the SPL U-Boot version to configure
+ * the DDR3 controller.
+ */
+static struct hws_topology_map ddr_topology_map = {
+	0x1, /* active interfaces */
+	/* cs_mask, mirror, dqs_swap, ck_swap X PUPs */
+	{ { { {0x1, 0, 0, 0},
+	      {0x1, 0, 0, 0},
+	      {0x1, 0, 0, 0},
+	      {0x1, 0, 0, 0},
+	      {0x1, 0, 0, 0} },
+	    SPEED_BIN_DDR_1600K,	/* speed_bin */
+	    BUS_WIDTH_16,		/* memory_width */
+	    MEM_4G,			/* mem_size */
+	    DDR_FREQ_533,		/* frequency */
+	    0, 0,			/* cas_l cas_wl */
+	    HWS_TEMP_LOW} },		/* temperature */
+	5,				/* Num Of Bus Per Interface*/
+	BUS_MASK_32BIT			/* Busses mask */
+};
+
+static struct serdes_map serdes_topology_map[] = {
+	{SGMII0, SERDES_SPEED_1_25_GBPS, SERDES_DEFAULT_MODE, 0, 0},
+	{USB3_HOST0, SERDES_SPEED_5_GBPS, SERDES_DEFAULT_MODE, 0, 0},
+	/* SATA tx polarity is inverted */
+	{SATA1, SERDES_SPEED_3_GBPS, SERDES_DEFAULT_MODE, 0, 1},
+	{SGMII2, SERDES_SPEED_1_25_GBPS, SERDES_DEFAULT_MODE, 0, 0},
+	{DEFAULT_SERDES, SERDES_SPEED_3_GBPS, SERDES_DEFAULT_MODE, 0, 0},
+	{PEX2, SERDES_SPEED_5_GBPS, PEX_ROOT_COMPLEX_X1, 0, 0}
+};
+
+int hws_board_topology_load(struct serdes_map **serdes_map_array, u8 *count)
+{
+	*serdes_map_array = serdes_topology_map;
+	*count = ARRAY_SIZE(serdes_topology_map);
+	return 0;
+}
+
+void board_pex_config(void)
+{
+#ifdef CONFIG_SPL_BUILD
+	uint k;
+	struct gpio_desc gpio = {};
+
+	if (gpio_request_simple("generic,fpga-program-gpio", &gpio)) {
+		/* prepare FPGA reconfiguration */
+		dm_gpio_set_dir_flags(&gpio, GPIOD_IS_OUT);
+		dm_gpio_set_value(&gpio, 0);
+
+		/* give lunatic PCIe clock some time to stabilize */
+		mdelay(500);
+
+		/* start FPGA reconfiguration */
+		dm_gpio_set_dir_flags(&gpio, GPIOD_IS_IN);
+	}
+
+	/* wait for FPGA done */
+	if (gpio_request_simple("generic,fpga-done-gpio", &gpio)) {
+		for (k = 0; k < 20; ++k) {
+			if (dm_gpio_get_value(&gpio)) {
+				printf("FPGA done after %u rounds\n", k);
+				break;
+			}
+			mdelay(100);
+		}
+	}
+
+	/* disable FPGA reset */
+	if (gpio_request_simple("generic,cpu-to-fpga-reset", &gpio)) {
+		dm_gpio_set_dir_flags(&gpio, GPIOD_IS_OUT);
+		dm_gpio_set_value(&gpio, 1);
+	}
+
+	/* wait for FPGA ready */
+	if (gpio_request_simple("generic,fpga-ready-gpio", &gpio)) {
+		for (k = 0; k < 2; ++k) {
+			if (!dm_gpio_get_value(&gpio))
+				break;
+			mdelay(100);
+		}
+	}
+#endif
+}
+
+struct hws_topology_map *ddr3_get_topology_map(void)
+{
+	return &ddr_topology_map;
+}
+
+int board_early_init_f(void)
+{
+#ifdef CONFIG_SPL_BUILD
+	/* Configure MPP */
+	writel(0x00111111, MVEBU_MPP_BASE + 0x00);
+	writel(0x40040000, MVEBU_MPP_BASE + 0x04);
+	writel(0x00466444, MVEBU_MPP_BASE + 0x08);
+	writel(0x00043300, MVEBU_MPP_BASE + 0x0c);
+	writel(0x44400000, MVEBU_MPP_BASE + 0x10);
+	writel(0x20000334, MVEBU_MPP_BASE + 0x14);
+	writel(0x40000000, MVEBU_MPP_BASE + 0x18);
+	writel(0x00004444, MVEBU_MPP_BASE + 0x1c);
+
+	/* Set GPP Out value */
+	writel(DB_GP_88F68XX_GPP_OUT_VAL_LOW, MVEBU_GPIO0_BASE + 0x00);
+	writel(DB_GP_88F68XX_GPP_OUT_VAL_MID, MVEBU_GPIO1_BASE + 0x00);
+
+	/* Set GPP Polarity */
+	writel(DB_GP_88F68XX_GPP_POL_LOW, MVEBU_GPIO0_BASE + 0x0c);
+	writel(DB_GP_88F68XX_GPP_POL_MID, MVEBU_GPIO1_BASE + 0x0c);
+
+	/* Set GPP Out Enable */
+	writel(DB_GP_88F68XX_GPP_OUT_ENA_LOW, MVEBU_GPIO0_BASE + 0x04);
+	writel(DB_GP_88F68XX_GPP_OUT_ENA_MID, MVEBU_GPIO1_BASE + 0x04);
+#endif
+
+	return 0;
+}
+
+int board_init(void)
+{
+	/* Address of boot parameters */
+	gd->bd->bi_boot_params = mvebu_sdram_bar(0) + 0x100;
+
+	return 0;
+}
+
+#ifndef CONFIG_SPL_BUILD
+void init_host_phys(struct mii_dev *bus)
+{
+	uint k;
+
+	for (k = 0; k < 2; ++k) {
+		struct phy_device *phydev;
+
+		phydev = phy_find_by_mask(bus, 1 << k,
+					  PHY_INTERFACE_MODE_SGMII);
+
+		if (phydev)
+			phy_config(phydev);
+	}
+}
+
+int ccdc_eth_init(void)
+{
+	uint k;
+	uint octo_phy_mask = 0;
+	int ret;
+	struct mii_dev *bus;
+
+	/* Init SoC's phys */
+	bus = miiphy_get_dev_by_name("ethernet at 34000");
+
+	if (bus)
+		init_host_phys(bus);
+
+	bus = miiphy_get_dev_by_name("ethernet@70000");
+
+	if (bus)
+		init_host_phys(bus);
+
+	/* Init octo phys */
+	octo_phy_mask = calculate_octo_phy_mask();
+
+	printf("IHS PHYS: %08x", octo_phy_mask);
+
+	ret = init_octo_phys(octo_phy_mask);
+
+	if (ret)
+		return ret;
+
+	printf("\n");
+
+	if (!get_fpga()) {
+		puts("fpga was NULL\n");
+		return 1;
+	}
+
+	/* reset all FPGA-QSGMII instances */
+	for (k = 0; k < 80; ++k)
+		writel(1 << 31, get_fpga()->qsgmii_port_state[k]);
+
+	udelay(100);
+
+	for (k = 0; k < 80; ++k)
+		writel(0, get_fpga()->qsgmii_port_state[k]);
+	return 0;
+}
+
+#endif
+
+int board_late_init(void)
+{
+#ifndef CONFIG_SPL_BUILD
+	hydra_initialize();
+#endif
+	return 0;
+}
+
+int board_fix_fdt(void *rw_fdt_blob)
+{
+	struct udevice *bus = NULL;
+	uint k;
+	char name[64];
+
+	dev_get_by_ofname("/soc/internal-regs/i2c at 11000", bus);
+
+	for (k = 0x21; k <= 0x26; k++) {
+		snprintf(name, 64,
+			 "/soc/internal-regs/i2c at 11000/pca9698@%02x", k);
+
+		if (!dm_i2c_simple_probe(bus, k))
+			fdt_disable_by_ofname(rw_fdt_blob, name);
+	}
+
+	return 0;
+}
+
+int last_stage_init(void)
+{
+#ifndef CONFIG_SPL_BUILD
+	ccdc_eth_init();
+#endif
+	if (tpm_init() || tpm_startup(TPM_ST_CLEAR) ||
+	    tpm_continue_self_test()) {
+		return 1;
+	}
+
+	mdelay(37);
+
+	flush_keys();
+	load_and_run_keyprog();
+
+	return 0;
+}
diff --git a/board/gdsys/a38x/dt_helpers.c b/board/gdsys/a38x/dt_helpers.c
new file mode 100644
index 0000000..59f59f7
--- /dev/null
+++ b/board/gdsys/a38x/dt_helpers.c
@@ -0,0 +1,25 @@
+/*
+ * (C) Copyright 2016
+ * Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <i2c.h>
+#include <fdt_support.h>
+
+int fdt_disable_by_ofname(void *rw_fdt_blob, char *ofname)
+{
+	int offset = fdt_path_offset(rw_fdt_blob, ofname);
+
+	return fdt_status_disabled(rw_fdt_blob, offset);
+}
+
+bool dm_i2c_simple_probe(struct udevice *bus, uint chip_addr)
+{
+	struct udevice *dev;
+
+	return !dm_i2c_probe(bus, chip_addr, DM_I2C_CHIP_RD_ADDRESS |
+			     DM_I2C_CHIP_WR_ADDRESS, &dev);
+}
diff --git a/board/gdsys/a38x/dt_helpers.h b/board/gdsys/a38x/dt_helpers.h
new file mode 100644
index 0000000..ec7bd56
--- /dev/null
+++ b/board/gdsys/a38x/dt_helpers.h
@@ -0,0 +1,14 @@
+/*
+ * (C) Copyright 2016
+ * Mario Six, Guntermann & Drunck GmbH, mario.six at gdsys.cc
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#ifndef __DT_HELPERS_H
+#define __DT_HELPERS_H
+
+int fdt_disable_by_ofname(void *rw_fdt_blob, char *ofname);
+bool dm_i2c_simple_probe(struct udevice *bus, uint chip_addr);
+
+#endif /* __DT_HELPERS_H */
diff --git a/board/gdsys/a38x/hre.c b/board/gdsys/a38x/hre.c
new file mode 100644
index 0000000..1689d44
--- /dev/null
+++ b/board/gdsys/a38x/hre.c
@@ -0,0 +1,516 @@
+/*
+ * (C) Copyright 2013
+ * Reinhard Pfau, Guntermann & Drunck GmbH, reinhard.pfau at gdsys.cc
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <fs.h>
+#include <i2c.h>
+#include <mmc.h>
+#include <tpm.h>
+#include <u-boot/sha1.h>
+#include <asm/byteorder.h>
+#include <asm/unaligned.h>
+#include <pca9698.h>
+
+#include "hre.h"
+
+/* other constants */
+enum {
+	ESDHC_BOOT_IMAGE_SIG_OFS	= 0x40,
+	ESDHC_BOOT_IMAGE_SIZE_OFS	= 0x48,
+	ESDHC_BOOT_IMAGE_ADDR_OFS	= 0x50,
+	ESDHC_BOOT_IMAGE_TARGET_OFS	= 0x58,
+	ESDHC_BOOT_IMAGE_ENTRY_OFS	= 0x60,
+};
+
+enum {
+	I2C_SOC_0 = 0,
+	I2C_SOC_1 = 1,
+};
+
+enum access_mode {
+	HREG_NONE	= 0,
+	HREG_RD		= 1,
+	HREG_WR		= 2,
+	HREG_RDWR	= 3,
+};
+
+/* register constants */
+enum {
+	FIX_HREG_DEVICE_ID_HASH	= 0,
+	FIX_HREG_UNUSED1	= 1,
+	FIX_HREG_UNUSED2	= 2,
+	FIX_HREG_VENDOR		= 3,
+	COUNT_FIX_HREGS
+};
+
+static struct h_reg pcr_hregs[24];
+static struct h_reg fix_hregs[COUNT_FIX_HREGS];
+static struct h_reg var_hregs[8];
+
+/* hre opcodes */
+enum {
+	/* opcodes w/o data */
+	HRE_NOP		= 0x00,
+	HRE_SYNC	= HRE_NOP,
+	HRE_CHECK0	= 0x01,
+	/* opcodes w/o data, w/ sync dst */
+	/* opcodes w/ data */
+	HRE_LOAD	= 0x81,
+	/* opcodes w/data, w/sync dst */
+	HRE_XOR		= 0xC1,
+	HRE_AND		= 0xC2,
+	HRE_OR		= 0xC3,
+	HRE_EXTEND	= 0xC4,
+	HRE_LOADKEY	= 0xC5,
+};
+
+/* hre errors */
+enum {
+	HRE_E_OK	= 0,
+	HRE_E_TPM_FAILURE,
+	HRE_E_INVALID_HREG,
+};
+
+static uint64_t device_id;
+static uint64_t device_cl;
+static uint64_t device_type;
+
+static uint32_t platform_key_handle;
+
+static uint32_t hre_tpm_err;
+static int hre_err = HRE_E_OK;
+
+#define IS_PCR_HREG(spec) ((spec) & 0x20)
+#define IS_FIX_HREG(spec) (((spec) & 0x38) == 0x08)
+#define IS_VAR_HREG(spec) (((spec) & 0x38) == 0x10)
+#define HREG_IDX(spec) ((spec) & (IS_PCR_HREG(spec) ? 0x1f : 0x7))
+
+static const uint8_t vendor[] = "Guntermann & Drunck";
+
+/**
+ * @brief get the size of a given (TPM) NV area
+ * @param index	NV index of the area to get size for
+ * @param size	pointer to the size
+ * @return 0 on success, != 0 on error
+ */
+static int get_tpm_nv_size(uint32_t index, uint32_t *size)
+{
+	uint32_t err;
+	uint8_t info[72];
+	uint8_t *ptr;
+	uint16_t v16;
+
+	err = tpm_get_capability(TPM_CAP_NV_INDEX, index,
+		info, sizeof(info));
+	if (err) {
+		printf("tpm_get_capability(CAP_NV_INDEX, %08x) failed: %u\n",
+		       index, err);
+		return 1;
+	}
+
+	/* skip tag and nvIndex */
+	ptr = info + 6;
+	/* skip 2 pcr info fields */
+	v16 = get_unaligned_be16(ptr);
+	ptr += 2 + v16 + 1 + 20;
+	v16 = get_unaligned_be16(ptr);
+	ptr += 2 + v16 + 1 + 20;
+	/* skip permission and flags */
+	ptr += 6 + 3;
+
+	*size = get_unaligned_be32(ptr);
+	return 0;
+}
+
+/**
+ * @brief search for a key by usage auth and pub key hash.
+ * @param auth	usage auth of the key to search for
+ * @param pubkey_digest	(SHA1) hash of the pub key structure of the key
+ * @param[out] handle	the handle of the key iff found
+ * @return 0 if key was found in TPM; != 0 if not.
+ */
+static int find_key(const uint8_t auth[20], const uint8_t pubkey_digest[20],
+		uint32_t *handle)
+{
+	uint16_t key_count;
+	uint32_t key_handles[10];
+	uint8_t buf[288];
+	uint8_t *ptr;
+	uint32_t err;
+	uint8_t digest[20];
+	size_t buf_len;
+	unsigned int i;
+
+	/* fetch list of already loaded keys in the TPM */
+	err = tpm_get_capability(TPM_CAP_HANDLE, TPM_RT_KEY, buf, sizeof(buf));
+	if (err)
+		return -1;
+	key_count = get_unaligned_be16(buf);
+	ptr = buf + 2;
+	for (i = 0; i < key_count; ++i, ptr += 4)
+		key_handles[i] = get_unaligned_be32(ptr);
+
+	/* now search a(/ the) key which we can access with the given auth */
+	for (i = 0; i < key_count; ++i) {
+		buf_len = sizeof(buf);
+		err = tpm_get_pub_key_oiap(key_handles[i], auth, buf, &buf_len);
+		if (err && err != TPM_AUTHFAIL)
+			return -1;
+		if (err)
+			continue;
+		sha1_csum(buf, buf_len, digest);
+		if (!memcmp(digest, pubkey_digest, 20)) {
+			*handle = key_handles[i];
+			return 0;
+		}
+	}
+	return 1;
+}
+
+/**
+ * @brief read CCDM common data from TPM NV
+ * @return 0 if CCDM common data was found and read, !=0 if something failed.
+ */
+static int read_common_data(void)
+{
+	uint32_t size = 0;
+	uint32_t err;
+	uint8_t buf[256];
+	sha1_context ctx;
+
+	if (get_tpm_nv_size(NV_COMMON_DATA_INDEX, &size) ||
+	    size < NV_COMMON_DATA_MIN_SIZE)
+		return 1;
+	err = tpm_nv_read_value(NV_COMMON_DATA_INDEX,
+		buf, min(sizeof(buf), size));
+	if (err) {
+		printf("tpm_nv_read_value() failed: %u\n", err);
+		return 1;
+	}
+
+	device_id = get_unaligned_be64(buf);
+	device_cl = get_unaligned_be64(buf + 8);
+	device_type = get_unaligned_be64(buf + 16);
+
+	sha1_starts(&ctx);
+	sha1_update(&ctx, buf, 24);
+	sha1_finish(&ctx, fix_hregs[FIX_HREG_DEVICE_ID_HASH].digest);
+	fix_hregs[FIX_HREG_DEVICE_ID_HASH].valid = true;
+
+	platform_key_handle = get_unaligned_be32(buf + 24);
+
+	return 0;
+}
+
+/**
+ * @brief get pointer to  hash register by specification
+ * @param spec	specification of a hash register
+ * @return pointer to hash register or NULL if @a spec does not qualify a
+ * valid hash register; NULL else.
+ */
+static struct h_reg *get_hreg(uint8_t spec)
+{
+	uint8_t idx;
+
+	idx = HREG_IDX(spec);
+	if (IS_FIX_HREG(spec)) {
+		if (idx < ARRAY_SIZE(fix_hregs))
+			return fix_hregs + idx;
+		hre_err = HRE_E_INVALID_HREG;
+	} else if (IS_PCR_HREG(spec)) {
+		if (idx < ARRAY_SIZE(pcr_hregs))
+			return pcr_hregs + idx;
+		hre_err = HRE_E_INVALID_HREG;
+	} else if (IS_VAR_HREG(spec)) {
+		if (idx < ARRAY_SIZE(var_hregs))
+			return var_hregs + idx;
+		hre_err = HRE_E_INVALID_HREG;
+	}
+	return NULL;
+}
+
+/**
+ * @brief get pointer of a hash register by specification and usage.
+ * @param spec	specification of a hash register
+ * @param mode	access mode (read or write or read/write)
+ * @return pointer to hash register if found and valid; NULL else.
+ *
+ * This func uses @a get_reg() to determine the hash register for a given spec.
+ * If a register is found it is validated according to the desired access mode.
+ * The value of automatic registers (PCR register and fixed registers) is
+ * loaded or computed on read access.
+ */
+static struct h_reg *access_hreg(uint8_t spec, enum access_mode mode)
+{
+	struct h_reg *result;
+
+	result = get_hreg(spec);
+	if (!result)
+		return NULL;
+
+	if (mode & HREG_WR) {
+		if (IS_FIX_HREG(spec)) {
+			hre_err = HRE_E_INVALID_HREG;
+			return NULL;
+		}
+	}
+	if (mode & HREG_RD) {
+		if (!result->valid) {
+			if (IS_PCR_HREG(spec)) {
+				hre_tpm_err = tpm_pcr_read(HREG_IDX(spec),
+					result->digest, 20);
+				result->valid = (hre_tpm_err == TPM_SUCCESS);
+			} else if (IS_FIX_HREG(spec)) {
+				switch (HREG_IDX(spec)) {
+				case FIX_HREG_DEVICE_ID_HASH:
+					read_common_data();
+					break;
+				case FIX_HREG_VENDOR:
+					memcpy(result->digest, vendor, 20);
+					result->valid = true;
+					break;
+				}
+			} else {
+				result->valid = true;
+			}
+		}
+		if (!result->valid) {
+			hre_err = HRE_E_INVALID_HREG;
+			return NULL;
+		}
+	}
+
+	return result;
+}
+
+static void *compute_and(void *_dst, const void *_src, size_t n)
+{
+	uint8_t *dst = _dst;
+	const uint8_t *src = _src;
+	size_t i;
+
+	for (i = n; i-- > 0; )
+		*dst++ &= *src++;
+
+	return _dst;
+}
+
+static void *compute_or(void *_dst, const void *_src, size_t n)
+{
+	uint8_t *dst = _dst;
+	const uint8_t *src = _src;
+	size_t i;
+
+	for (i = n; i-- > 0; )
+		*dst++ |= *src++;
+
+	return _dst;
+}
+
+static void *compute_xor(void *_dst, const void *_src, size_t n)
+{
+	uint8_t *dst = _dst;
+	const uint8_t *src = _src;
+	size_t i;
+
+	for (i = n; i-- > 0; )
+		*dst++ ^= *src++;
+
+	return _dst;
+}
+
+static void *compute_extend(void *_dst, const void *_src, size_t n)
+{
+	uint8_t digest[20];
+	sha1_context ctx;
+
+	sha1_starts(&ctx);
+	sha1_update(&ctx, _dst, n);
+	sha1_update(&ctx, _src, n);
+	sha1_finish(&ctx, digest);
+	memcpy(_dst, digest, min(n, sizeof(digest)));
+
+	return _dst;
+}
+
+static int hre_op_loadkey(struct h_reg *src_reg, struct h_reg *dst_reg,
+		const void *key, size_t key_size)
+{
+	uint32_t parent_handle;
+	uint32_t key_handle;
+
+	if (!src_reg || !dst_reg || !src_reg->valid || !dst_reg->valid)
+		return -1;
+	if (find_key(src_reg->digest, dst_reg->digest, &parent_handle))
+		return -1;
+	hre_tpm_err = tpm_load_key2_oiap(parent_handle, key, key_size,
+		src_reg->digest, &key_handle);
+	if (hre_tpm_err) {
+		hre_err = HRE_E_TPM_FAILURE;
+		return -1;
+	}
+
+	return 0;
+}
+
+/**
+ * @brief executes the next opcode on the hash register engine.
+ * @param[in,out] ip	pointer to the opcode (instruction pointer)
+ * @param[in,out] code_size	(remaining) size of the code
+ * @return new instruction pointer on success, NULL on error.
+ */
+static const uint8_t *hre_execute_op(const uint8_t **ip, size_t *code_size)
+{
+	bool dst_modified = false;
+	uint32_t ins;
+	uint8_t opcode;
+	uint8_t src_spec;
+	uint8_t dst_spec;
+	uint16_t data_size;
+	struct h_reg *src_reg, *dst_reg;
+	uint8_t buf[20];
+	const uint8_t *src_buf, *data;
+	uint8_t *ptr;
+	int i;
+	void * (*bin_func)(void *, const void *, size_t);
+
+	if (*code_size < 4)
+		return NULL;
+
+	ins = get_unaligned_be32(*ip);
+	opcode = **ip;
+	data = *ip + 4;
+	src_spec = (ins >> 18) & 0x3f;
+	dst_spec = (ins >> 12) & 0x3f;
+	data_size = (ins & 0x7ff);
+
+	debug("HRE: ins=%08x (op=%02x, s=%02x, d=%02x, L=%d)\n", ins,
+	      opcode, src_spec, dst_spec, data_size);
+
+	if ((opcode & 0x80) && (data_size + 4) > *code_size)
+		return NULL;
+
+	src_reg = access_hreg(src_spec, HREG_RD);
+	if (hre_err || hre_tpm_err)
+		return NULL;
+	dst_reg = access_hreg(dst_spec, (opcode & 0x40) ? HREG_RDWR : HREG_WR);
+	if (hre_err || hre_tpm_err)
+		return NULL;
+
+	switch (opcode) {
+	case HRE_NOP:
+		goto end;
+	case HRE_CHECK0:
+		if (src_reg) {
+			for (i = 0; i < 20; ++i) {
+				if (src_reg->digest[i])
+					return NULL;
+			}
+		}
+		break;
+	case HRE_LOAD:
+		bin_func = memcpy;
+		goto do_bin_func;
+	case HRE_XOR:
+		bin_func = compute_xor;
+		goto do_bin_func;
+	case HRE_AND:
+		bin_func = compute_and;
+		goto do_bin_func;
+	case HRE_OR:
+		bin_func = compute_or;
+		goto do_bin_func;
+	case HRE_EXTEND:
+		bin_func = compute_extend;
+do_bin_func:
+		if (!dst_reg)
+			return NULL;
+		if (src_reg) {
+			src_buf = src_reg->digest;
+		} else {
+			if (!data_size) {
+				memset(buf, 0, 20);
+				src_buf = buf;
+			} else if (data_size == 1) {
+				memset(buf, *data, 20);
+				src_buf = buf;
+			} else if (data_size >= 20) {
+				src_buf = data;
+			} else {
+				src_buf = buf;
+				for (ptr = (uint8_t *)src_buf, i = 20; i > 0;
+					i -= data_size, ptr += data_size)
+					memcpy(ptr, data,
+					       min_t(size_t, i, data_size));
+			}
+		}
+		bin_func(dst_reg->digest, src_buf, 20);
+		dst_reg->valid = true;
+		dst_modified = true;
+		break;
+	case HRE_LOADKEY:
+		if (hre_op_loadkey(src_reg, dst_reg, data, data_size))
+			return NULL;
+		break;
+	default:
+		return NULL;
+	}
+
+	if (dst_reg && dst_modified && IS_PCR_HREG(dst_spec)) {
+		hre_tpm_err = tpm_extend(HREG_IDX(dst_spec), dst_reg->digest,
+			dst_reg->digest);
+		if (hre_tpm_err) {
+			hre_err = HRE_E_TPM_FAILURE;
+			return NULL;
+		}
+	}
+end:
+	*ip += 4;
+	*code_size -= 4;
+	if (opcode & 0x80) {
+		*ip += data_size;
+		*code_size -= data_size;
+	}
+
+	return *ip;
+}
+
+/**
+ * @brief runs a program on the hash register engine.
+ * @param code		pointer to the (HRE) code.
+ * @param code_size	size of the code (in bytes).
+ * @return 0 on success, != 0 on failure.
+ */
+int hre_run_program(const uint8_t *code, size_t code_size)
+{
+	size_t code_left;
+	const uint8_t *ip = code;
+
+	code_left = code_size;
+	hre_tpm_err = 0;
+	hre_err = HRE_E_OK;
+	while (code_left > 0)
+		if (!hre_execute_op(&ip, &code_left))
+			return -1;
+
+	return hre_err;
+}
+
+int hre_verify_program(struct key_program *prg)
+{
+	uint32_t crc;
+
+	crc = crc32(0, prg->code, prg->code_size);
+
+	if (crc != prg->code_crc) {
+		printf("HRC crc mismatch: %08x != %08x\n",
+		       crc, prg->code_crc);
+		return 1;
+	}
+	return 0;
+}
diff --git a/board/gdsys/a38x/hre.h b/board/gdsys/a38x/hre.h
new file mode 100644
index 0000000..84ce279
--- /dev/null
+++ b/board/gdsys/a38x/hre.h
@@ -0,0 +1,38 @@
+/*
+ * (C) Copyright 2013
+ * Reinhard Pfau, Guntermann & Drunck GmbH, reinhard.pfau at gdsys.cc
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __HRE_H
+#define __HRE_H
+
+struct key_program {
+	uint32_t magic;
+	uint32_t code_crc;
+	uint32_t code_size;
+	uint8_t code[];
+};
+
+struct h_reg {
+	bool valid;
+	uint8_t digest[20];
+};
+
+/* CCDM specific contants */
+enum {
+	/* NV indices */
+	NV_COMMON_DATA_INDEX	= 0x40000001,
+	/* magics for key blob chains */
+	MAGIC_KEY_PROGRAM	= 0x68726500,
+	MAGIC_HMAC		= 0x68616300,
+	MAGIC_END_OF_CHAIN	= 0x00000000,
+	/* sizes */
+	NV_COMMON_DATA_MIN_SIZE	= 3 * sizeof(uint64_t) + 2 * sizeof(uint16_t),
+};
+
+int hre_verify_program(struct key_program *prg);
+int hre_run_program(const uint8_t *code, size_t code_size);
+
+#endif /* __HRE_H */
diff --git a/board/gdsys/a38x/hydra.c b/board/gdsys/a38x/hydra.c
new file mode 100644
index 0000000..fa50ad2
--- /dev/null
+++ b/board/gdsys/a38x/hydra.c
@@ -0,0 +1,138 @@
+#include <common.h>
+#include <console.h> /* ctrlc */
+#include <asm/io.h>
+
+#include "hydra.h"
+
+enum {
+	HWVER_100 = 0,
+	HWVER_110 = 1,
+	HWVER_120 = 2,
+};
+
+static struct pci_device_id hydra_supported[] = {
+	{ 0x6d5e, 0xcdc1 },
+	{}
+};
+
+static struct ihs_fpga *fpga;
+
+struct ihs_fpga *get_fpga(void)
+{
+	return fpga;
+}
+
+void print_hydra_version(uint index)
+{
+	u32 versions = readl(&fpga->versions);
+	u32 fpga_version = readl(&fpga->fpga_version);
+
+	uint hardware_version = versions & 0xf;
+
+	printf("FPGA%u: mapped to %p\n       ", index, fpga);
+
+	switch (hardware_version) {
+	case HWVER_100:
+		printf("HW-Ver 1.00\n");
+		break;
+
+	case HWVER_110:
+		printf("HW-Ver 1.10\n");
+		break;
+
+	case HWVER_120:
+		printf("HW-Ver 1.20\n");
+		break;
+
+	default:
+		printf("HW-Ver %d(not supported)\n",
+		       hardware_version);
+		break;
+	}
+
+	printf("       FPGA V %d.%02d\n",
+	       fpga_version / 100, fpga_version % 100);
+}
+
+void hydra_initialize(void)
+{
+	uint i;
+	pci_dev_t devno;
+
+	/* Find and probe all the matching PCI devices */
+	for (i = 0; (devno = pci_find_devices(hydra_supported, i)) >= 0; i++) {
+		u32 val;
+
+		/* Try to enable I/O accesses and bus-mastering */
+		val = PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER;
+		pci_write_config_dword(devno, PCI_COMMAND, val);
+
+		/* Make sure it worked */
+		pci_read_config_dword(devno, PCI_COMMAND, &val);
+		if (!(val & PCI_COMMAND_MEMORY)) {
+			puts("Can't enable I/O memory\n");
+			continue;
+		}
+		if (!(val & PCI_COMMAND_MASTER)) {
+			puts("Can't enable bus-mastering\n");
+			continue;
+		}
+
+		/* read FPGA details */
+		fpga = pci_map_bar(devno, PCI_BASE_ADDRESS_0,
+				   PCI_REGION_MEM);
+
+		print_hydra_version(i);
+	}
+}
+
+#define REFL_PATTERN (0xdededede)
+#define REFL_PATTERN_INV (~REFL_PATTERN)
+
+int do_hydrate(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+	uint k = 0;
+	void __iomem *pcie2_base = (void __iomem *)(MVEBU_REG_PCIE_BASE +
+						    0x4000);
+
+	if (!fpga)
+		return -1;
+
+	while (1) {
+		u32 res;
+
+		writel(REFL_PATTERN, &fpga->reflection_low);
+		res = readl(&fpga->reflection_low);
+		if (res != REFL_PATTERN_INV)
+			printf("round %u: read %08x, expected %08x\n",
+			       k, res, REFL_PATTERN_INV);
+		writel(REFL_PATTERN_INV, &fpga->reflection_low);
+		res = readl(&fpga->reflection_low);
+		if (res != REFL_PATTERN)
+			printf("round %u: read %08x, expected %08x\n",
+			       k, res, REFL_PATTERN);
+
+		res = readl(pcie2_base + 0x118) & 0x1f;
+		if (res)
+			printf("FrstErrPtr %u\n", res);
+		res = readl(pcie2_base + 0x104);
+		if (res) {
+			printf("Uncorrectable Error Status 0x%08x\n", res);
+			writel(res, pcie2_base + 0x104);
+		}
+
+		if (!(++k % 10000))
+			printf("round %u\n", k);
+
+		if (ctrlc())
+			break;
+	}
+
+	return 0;
+}
+
+U_BOOT_CMD(
+	hydrate,	1,	0,	do_hydrate,
+	"hydra reflection test",
+	"hydra reflection test"
+);
diff --git a/board/gdsys/a38x/hydra.h b/board/gdsys/a38x/hydra.h
new file mode 100644
index 0000000..26562a5
--- /dev/null
+++ b/board/gdsys/a38x/hydra.h
@@ -0,0 +1,14 @@
+struct ihs_fpga {
+	u32 reflection_low;		/* 0x0000 */
+	u32 versions;			/* 0x0004 */
+	u32 fpga_version;		/* 0x0008 */
+	u32 fpga_features;		/* 0x000c */
+	u32 reserved0[4];		/* 0x0010 */
+	u32 control;			/* 0x0020 */
+	u32 reserved1[375];		/* 0x0024 */
+	u32 qsgmii_port_state[80];	/* 0x0600 */
+};
+
+void print_hydra_version(uint index);
+void hydra_initialize(void);
+struct ihs_fpga *get_fpga(void);
diff --git a/board/gdsys/a38x/ihs_phys.c b/board/gdsys/a38x/ihs_phys.c
new file mode 100644
index 0000000..f11d8c9
--- /dev/null
+++ b/board/gdsys/a38x/ihs_phys.c
@@ -0,0 +1,349 @@
+#include <common.h>
+#include <dm.h>
+#include <miiphy.h>
+#include <asm-generic/gpio.h>
+
+#include "ihs_phys.h"
+#include "dt_helpers.h"
+
+enum {
+	PORTTYPE_MAIN_CAT,
+	PORTTYPE_TOP_CAT,
+	PORTTYPE_16C_16F,
+	PORTTYPE_UNKNOWN
+};
+
+static struct porttype {
+	bool phy_invert_in_pol;
+	bool phy_invert_out_pol;
+} porttypes[] = {
+	{ true, false },
+	{ false, true },
+	{ false, false },
+};
+
+static void ihs_phy_config(struct phy_device *phydev, bool qinpn, bool qoutpn)
+{
+	u16 reg;
+
+	phy_config(phydev);
+
+	/* enable QSGMII autonegotiation with flow control */
+	phy_write(phydev, MDIO_DEVAD_NONE, 22, 0x0004);
+	reg = phy_read(phydev, MDIO_DEVAD_NONE, 16);
+	reg |= (3 << 6);
+	phy_write(phydev, MDIO_DEVAD_NONE, 16, reg);
+
+	/*
+	 * invert QSGMII Q_INP/N and Q_OUTP/N if required
+	 * and perform global reset
+	 */
+	reg = phy_read(phydev, MDIO_DEVAD_NONE, 26);
+	if (qinpn)
+		reg |= (1 << 13);
+	if (qoutpn)
+		reg |= (1 << 12);
+	reg |= (1 << 15);
+	phy_write(phydev, MDIO_DEVAD_NONE, 26, reg);
+
+	/* advertise 1000BASE-T full-duplex only  */
+	phy_write(phydev, MDIO_DEVAD_NONE, 22, 0x0000);
+	reg = phy_read(phydev, MDIO_DEVAD_NONE, 4);
+	reg &= ~0x1e0;
+	phy_write(phydev, MDIO_DEVAD_NONE, 4, reg);
+	reg = phy_read(phydev, MDIO_DEVAD_NONE, 9);
+	reg = (reg & ~0x300) | 0x200;
+	phy_write(phydev, MDIO_DEVAD_NONE, 9, reg);
+
+	/* copper power up */
+	reg = phy_read(phydev, MDIO_DEVAD_NONE, 16);
+	reg &= ~0x0004;
+	phy_write(phydev, MDIO_DEVAD_NONE, 16, reg);
+}
+
+uint calculate_octo_phy_mask(void)
+{
+	uint k;
+	uint octo_phy_mask = 0;
+	struct gpio_desc gpio = {};
+	char name[64];
+
+	/* mark all octo phys that should be present */
+	for (k = 0; k < 5; ++k) {
+		snprintf(name, 64, "generic,cat-gpio-%u", k);
+
+		if (!gpio_request_simple(name, &gpio))
+			continue;
+
+		/* check CAT flag */
+		if (dm_gpio_get_value(&gpio))
+			octo_phy_mask |= (1 << (k * 2));
+		else
+			/* If CAT == 0, there's no second octo phy -> skip */
+			continue;
+
+		snprintf(name, 64, "generic,second-octo-gpio-%u", k);
+
+		if (!gpio_request_simple(name, &gpio)) {
+			/* default: second octo phy is present */
+			octo_phy_mask |= (1 << (k * 2 + 1));
+			continue;
+		}
+
+		if (dm_gpio_get_value(&gpio) == 0)
+			octo_phy_mask |= (1 << (k * 2 + 1));
+	}
+
+	return octo_phy_mask;
+}
+
+int register_miiphy_bus(uint k, struct mii_dev **bus)
+{
+	int retval;
+	struct mii_dev *mdiodev = mdio_alloc();
+	char *name = bb_miiphy_buses[k].name;
+
+	if (!mdiodev)
+		return -ENOMEM;
+	strncpy(mdiodev->name,
+		name,
+		MDIO_NAME_LEN);
+	mdiodev->read = bb_miiphy_read;
+	mdiodev->write = bb_miiphy_write;
+
+	retval = mdio_register(mdiodev);
+	if (retval < 0)
+		return retval;
+	*bus = miiphy_get_dev_by_name(name);
+
+	return 0;
+}
+
+struct porttype *get_porttype(uint octo_phy_mask, uint k)
+{
+	uint octo_index = k * 4;
+
+	if (!k) {
+		if (octo_phy_mask & 0x01)
+			return &porttypes[PORTTYPE_MAIN_CAT];
+		else if (!(octo_phy_mask & 0x03))
+			return &porttypes[PORTTYPE_16C_16F];
+	} else {
+		if (octo_phy_mask & (1 << octo_index))
+			return &porttypes[PORTTYPE_TOP_CAT];
+	}
+
+	return NULL;
+}
+
+int init_single_phy(struct porttype *porttype, struct mii_dev *bus,
+		    uint bus_idx, uint m, uint phy_idx)
+{
+	struct phy_device *phydev = phy_find_by_mask(
+		bus, 1 << (m * 8 + phy_idx),
+		PHY_INTERFACE_MODE_MII);
+
+	printf(" %u", bus_idx * 32 + m * 8 + phy_idx);
+
+	if (!phydev)
+		puts("!");
+	else
+		ihs_phy_config(phydev, porttype->phy_invert_in_pol,
+			       porttype->phy_invert_out_pol);
+
+	return 0;
+}
+
+int init_octo_phys(uint octo_phy_mask)
+{
+	uint bus_idx;
+
+	/* there are up to four octo-phys on each mdio bus */
+	for (bus_idx = 0; bus_idx < bb_miiphy_buses_num; ++bus_idx) {
+		uint m;
+		uint octo_index = bus_idx * 4;
+		struct mii_dev *bus = NULL;
+		struct porttype *porttype = NULL;
+		int ret;
+
+		porttype = get_porttype(octo_phy_mask, bus_idx);
+
+		if (!porttype)
+			continue;
+
+		for (m = 0; m < 4; ++m) {
+			uint phy_idx;
+
+			/**
+			 * Register a bus device if there is@least one phy
+			 * on the current bus
+			 */
+			if (!m && octo_phy_mask & (0xf << octo_index)) {
+				ret = register_miiphy_bus(bus_idx, &bus);
+				if (ret)
+					return ret;
+			}
+
+			if (!(octo_phy_mask & BIT(octo_index + m)))
+				continue;
+
+			for (phy_idx = 0; phy_idx < 8; ++phy_idx)
+				init_single_phy(porttype, bus, bus_idx, m,
+						phy_idx);
+		}
+	}
+
+	return 0;
+}
+
+/*
+ * MII GPIO bitbang implementation
+ * MDC MDIO bus
+ * 13  14   PHY1-4
+ * 25  45   PHY5-8
+ * 46  24   PHY9-10
+ */
+
+struct gpio_mii {
+	int index;
+	struct gpio_desc mdc_gpio;
+	struct gpio_desc mdio_gpio;
+	int mdc_num;
+	int mdio_num;
+	int mdio_value;
+} gpio_mii_set[] = {
+	{ 0, {}, {}, 13, 14, 1 },
+	{ 1, {}, {}, 25, 45, 1 },
+	{ 2, {}, {}, 46, 24, 1 },
+};
+
+static int mii_mdio_init(struct bb_miiphy_bus *bus)
+{
+	struct gpio_mii *gpio_mii = bus->priv;
+	char name[32] = {};
+	struct udevice *gpio_dev1 = NULL;
+	struct udevice *gpio_dev2 = NULL;
+
+	dev_get_by_ofname("/soc/internal-regs/gpio at 18100", gpio_dev1);
+	dev_get_by_ofname("/soc/internal-regs/gpio at 18140", gpio_dev2);
+
+	if (gpio_mii->mdc_num > 31) {
+		gpio_mii->mdc_gpio.dev = gpio_dev2;
+		gpio_mii->mdc_gpio.offset = gpio_mii->mdc_num - 32;
+	} else {
+		gpio_mii->mdc_gpio.dev = gpio_dev1;
+		gpio_mii->mdc_gpio.offset = gpio_mii->mdc_num;
+	}
+	gpio_mii->mdc_gpio.flags = 0;
+	snprintf(name, 32, "bb_miiphy_bus-%d-mdc", gpio_mii->index);
+	dm_gpio_request(&gpio_mii->mdc_gpio, name);
+
+	if (gpio_mii->mdio_num > 31) {
+		gpio_mii->mdio_gpio.dev = gpio_dev2;
+		gpio_mii->mdio_gpio.offset = gpio_mii->mdio_num - 32;
+	} else {
+		gpio_mii->mdio_gpio.dev = gpio_dev1;
+		gpio_mii->mdio_gpio.offset = gpio_mii->mdio_num;
+	}
+	gpio_mii->mdio_gpio.flags = 0;
+	snprintf(name, 32, "bb_miiphy_bus-%d-mdio", gpio_mii->index);
+	dm_gpio_request(&gpio_mii->mdio_gpio, name);
+
+	dm_gpio_set_dir_flags(&gpio_mii->mdc_gpio, GPIOD_IS_OUT);
+	dm_gpio_set_value(&gpio_mii->mdc_gpio, 1);
+
+	return 0;
+}
+
+static int mii_mdio_active(struct bb_miiphy_bus *bus)
+{
+	struct gpio_mii *gpio_mii = bus->priv;
+
+	dm_gpio_set_value(&gpio_mii->mdc_gpio, gpio_mii->mdio_value);
+
+	return 0;
+}
+
+static int mii_mdio_tristate(struct bb_miiphy_bus *bus)
+{
+	struct gpio_mii *gpio_mii = bus->priv;
+
+	dm_gpio_set_dir_flags(&gpio_mii->mdio_gpio, GPIOD_IS_IN);
+
+	return 0;
+}
+
+static int mii_set_mdio(struct bb_miiphy_bus *bus, int v)
+{
+	struct gpio_mii *gpio_mii = bus->priv;
+
+	dm_gpio_set_dir_flags(&gpio_mii->mdio_gpio, GPIOD_IS_OUT);
+	dm_gpio_set_value(&gpio_mii->mdio_gpio, v);
+	gpio_mii->mdio_value = v;
+
+	return 0;
+}
+
+static int mii_get_mdio(struct bb_miiphy_bus *bus, int *v)
+{
+	struct gpio_mii *gpio_mii = bus->priv;
+
+	dm_gpio_set_dir_flags(&gpio_mii->mdio_gpio, GPIOD_IS_IN);
+	*v = (dm_gpio_get_value(&gpio_mii->mdio_gpio));
+
+	return 0;
+}
+
+static int mii_set_mdc(struct bb_miiphy_bus *bus, int v)
+{
+	struct gpio_mii *gpio_mii = bus->priv;
+
+	dm_gpio_set_value(&gpio_mii->mdc_gpio, v);
+
+	return 0;
+}
+
+static int mii_delay(struct bb_miiphy_bus *bus)
+{
+	udelay(1);
+
+	return 0;
+}
+
+struct bb_miiphy_bus bb_miiphy_buses[] = {
+	{
+		.name = "ihs0",
+		.init = mii_mdio_init,
+		.mdio_active = mii_mdio_active,
+		.mdio_tristate = mii_mdio_tristate,
+		.set_mdio = mii_set_mdio,
+		.get_mdio = mii_get_mdio,
+		.set_mdc = mii_set_mdc,
+		.delay = mii_delay,
+		.priv = &gpio_mii_set[0],
+	},
+	{
+		.name = "ihs1",
+		.init = mii_mdio_init,
+		.mdio_active = mii_mdio_active,
+		.mdio_tristate = mii_mdio_tristate,
+		.set_mdio = mii_set_mdio,
+		.get_mdio = mii_get_mdio,
+		.set_mdc = mii_set_mdc,
+		.delay = mii_delay,
+		.priv = &gpio_mii_set[1],
+	},
+	{
+		.name = "ihs2",
+		.init = mii_mdio_init,
+		.mdio_active = mii_mdio_active,
+		.mdio_tristate = mii_mdio_tristate,
+		.set_mdio = mii_set_mdio,
+		.get_mdio = mii_get_mdio,
+		.set_mdc = mii_set_mdc,
+		.delay = mii_delay,
+		.priv = &gpio_mii_set[2],
+	},
+};
+
+int bb_miiphy_buses_num = ARRAY_SIZE(bb_miiphy_buses);
diff --git a/board/gdsys/a38x/ihs_phys.h b/board/gdsys/a38x/ihs_phys.h
new file mode 100644
index 0000000..c4bec4d
--- /dev/null
+++ b/board/gdsys/a38x/ihs_phys.h
@@ -0,0 +1,2 @@
+uint calculate_octo_phy_mask(void);
+int init_octo_phys(uint octo_phy_mask);
diff --git a/board/gdsys/a38x/keyprogram.c b/board/gdsys/a38x/keyprogram.c
new file mode 100644
index 0000000..a4a6f1c
--- /dev/null
+++ b/board/gdsys/a38x/keyprogram.c
@@ -0,0 +1,158 @@
+/*
+ * (C) Copyright 2016
+ * Mario Six, Guntermann & Drunck GmbH, mario.six at gdsys.cc
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <tpm.h>
+#include <malloc.h>
+#include <linux/ctype.h>
+#include <asm/unaligned.h>
+
+#include "hre.h"
+
+int flush_keys(void)
+{
+	u16 key_count;
+	u8 buf[288];
+	u8 *ptr;
+	u32 err;
+	uint i;
+
+	/* fetch list of already loaded keys in the TPM */
+	err = tpm_get_capability(TPM_CAP_HANDLE, TPM_RT_KEY, buf, sizeof(buf));
+	if (err)
+		return -1;
+	key_count = get_unaligned_be16(buf);
+	ptr = buf + 2;
+	for (i = 0; i < key_count; ++i, ptr += 4) {
+		err = tpm_flush_specific(get_unaligned_be32(ptr), TPM_RT_KEY);
+		if (err && err != TPM_KEY_OWNER_CONTROL)
+			return err;
+	}
+
+	return 0;
+}
+
+int decode_hexstr(char *hexstr, u8 **result)
+{
+	int len = strlen(hexstr);
+	int bytes = len / 2;
+	int i;
+	u8 acc = 0;
+
+	if (len % 2 == 1)
+		return 1;
+
+	*result = (u8 *)malloc(bytes);
+
+	for (i = 0; i < len; i++) {
+		char cur = tolower(hexstr[i]);
+		u8 val;
+
+		if ((cur >= 'a' && cur <= 'f') || (cur >= '0' && cur <= '9')) {
+			val = cur - (cur > '9' ? 87 : 48);
+
+			if (i % 2 == 0)
+				acc = 16 * val;
+			else
+				(*result)[i / 2] = acc + val;
+		} else {
+			free(*result);
+			return 1;
+		}
+	}
+
+	return 0;
+}
+
+int extract_subprogram(u8 **progdata, u32 expected_magic,
+		       struct key_program **result)
+{
+	struct key_program *prog = *result;
+	u32 magic, code_crc, code_size;
+
+	magic = get_unaligned_be32(*progdata);
+	code_crc = get_unaligned_be32(*progdata + 4);
+	code_size = get_unaligned_be32(*progdata + 8);
+
+	*progdata += 12;
+
+	if (magic != expected_magic)
+		return -1;
+
+	*result = malloc(sizeof(struct key_program) + code_size);
+
+	if (!*result)
+		return -1;
+
+	prog->magic = magic;
+	prog->code_crc = code_crc;
+	prog->code_size = code_size;
+	memcpy(prog->code, *progdata, code_size);
+
+	*progdata += code_size;
+
+	if (hre_verify_program(prog)) {
+		free(prog);
+		return -1;
+	}
+
+	return 0;
+}
+
+struct key_program *parse_and_check_keyprog(u8 *progdata)
+{
+	struct key_program *result = NULL, *hmac = NULL;
+
+	/* Part 1: Load key program */
+
+	if (extract_subprogram(&progdata, MAGIC_KEY_PROGRAM, &result))
+		return NULL;
+
+	/* Part 2: Load hmac program */
+
+	if (extract_subprogram(&progdata, MAGIC_HMAC, &hmac))
+		return NULL;
+
+	free(hmac);
+
+	return result;
+}
+
+int load_and_run_keyprog(void)
+{
+	char *cmd = NULL;
+	u8 *binprog = NULL;
+	char *hexprog;
+	struct key_program *prog;
+
+	cmd = getenv("loadkeyprogram");
+
+	if (!cmd || run_command(cmd, 0))
+		return 1;
+
+	hexprog = getenv("keyprogram");
+
+	if (decode_hexstr(hexprog, &binprog))
+		return 1;
+
+	prog = parse_and_check_keyprog(binprog);
+	free(binprog);
+
+	if (!prog)
+		return 1;
+
+	if (hre_run_program(prog->code, prog->code_size)) {
+		free(prog);
+		return 1;
+	}
+
+	printf("\nSD code ran successfully\n");
+
+	free(prog);
+
+	return 0;
+}
diff --git a/board/gdsys/a38x/keyprogram.h b/board/gdsys/a38x/keyprogram.h
new file mode 100644
index 0000000..a5ea7d3
--- /dev/null
+++ b/board/gdsys/a38x/keyprogram.h
@@ -0,0 +1,14 @@
+/*
+ * (C) Copyright 2016
+ * Mario Six, Guntermann & Drunck GmbH, mario.six at gdsys.cc
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __KEYPROGRAM_H
+#define __KEYPROGRAM_H
+
+int load_and_run_keyprog(void);
+int flush_keys(void);
+
+#endif /* __KEYPROGRAM_H */
diff --git a/board/gdsys/a38x/kwbimage.cfg.in b/board/gdsys/a38x/kwbimage.cfg.in
new file mode 100644
index 0000000..72e67d7
--- /dev/null
+++ b/board/gdsys/a38x/kwbimage.cfg.in
@@ -0,0 +1,12 @@
+#
+# Copyright (C) 2014 Stefan Roese <sr@denx.de>
+#
+
+# Armada 38x uses version 1 image format
+VERSION		1
+
+# Boot Media configurations
+#@BOOT_FROM
+
+# Binary Header (bin_hdr) with DDR3 training code
+BINARY spl/u-boot-spl.bin 0000005b 00000068
diff --git a/board/gdsys/a38x/spl.c b/board/gdsys/a38x/spl.c
new file mode 100644
index 0000000..2d05a9c
--- /dev/null
+++ b/board/gdsys/a38x/spl.c
@@ -0,0 +1,21 @@
+/*
+ * (C) Copyright 2016
+ * Mario Six, Guntermann & Drunck GmbH, mario.six at gdsys.cc
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <config.h>
+#include <asm/arch/cpu.h>
+
+void spl_board_init(void)
+{
+#if CONFIG_SPL_BOOT_DEVICE == SPL_BOOT_SPI_NOR_FLASH
+	u32 *bootrom_save = (u32 *)CONFIG_SPL_BOOTROM_SAVE;
+	u32 *regs = (u32 *)(*bootrom_save);
+
+	printf("Returning to BootROM (return address %08x)...\n", regs[13]);
+	return_to_bootrom();
+#endif
+}
diff --git a/configs/controlcenterdc_defconfig b/configs/controlcenterdc_defconfig
new file mode 100644
index 0000000..7475ae2
--- /dev/null
+++ b/configs/controlcenterdc_defconfig
@@ -0,0 +1,57 @@
+CONFIG_ARM=y
+CONFIG_ARCH_MVEBU=y
+CONFIG_SPL_GPIO_SUPPORT=y
+CONFIG_SYS_MALLOC_F_LEN=0x2000
+CONFIG_TARGET_CONTROLCENTERDC=y
+CONFIG_SPL_SPI_FLASH_SUPPORT=y
+CONFIG_SPL_SPI_SUPPORT=y
+CONFIG_DEFAULT_DEVICE_TREE="armada-38x-controlcenterdc"
+CONFIG_FIT=y
+CONFIG_FIT_VERBOSE=y
+CONFIG_FIT_SIGNATURE=y
+CONFIG_SYS_CONSOLE_INFO_QUIET=y
+CONFIG_SPL=y
+CONFIG_SPL_SYS_MALLOC_SIMPLE=y
+CONFIG_HUSH_PARSER=y
+# CONFIG_CMD_ELF is not set
+# CONFIG_CMD_GO is not set
+# CONFIG_CMD_IMLS is not set
+# CONFIG_CMD_FLASH is not set
+CONFIG_CMD_MMC=y
+CONFIG_CMD_SF=y
+CONFIG_CMD_USB=y
+CONFIG_CMD_GPIO=y
+# CONFIG_CMD_SETEXPR is not set
+CONFIG_CMD_DHCP=y
+CONFIG_CMD_PING=y
+CONFIG_CMD_CACHE=y
+CONFIG_CMD_TIME=y
+CONFIG_CMD_TPM=y
+CONFIG_CMD_EXT2=y
+CONFIG_CMD_EXT4=y
+CONFIG_OF_BOARD_FIXUP=y
+CONFIG_SPL_OF_TRANSLATE=y
+CONFIG_DM_GPIO=y
+CONFIG_DM_PCA953X=y
+CONFIG_DM_I2C=y
+CONFIG_SYS_I2C_MVTWSI=y
+CONFIG_LED=y
+CONFIG_LED_GPIO=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_MV=y
+CONFIG_SPI_FLASH=y
+CONFIG_SPI_FLASH_STMICRO=y
+CONFIG_DEBUG_UART=y
+CONFIG_DEBUG_UART_BASE=0xd0012000
+CONFIG_DEBUG_UART_CLOCK=250000000
+CONFIG_DEBUG_UART_SHIFT=2
+CONFIG_SYS_NS16550=y
+CONFIG_TPM_ATMEL_TWI=y
+CONFIG_TPM_AUTH_SESSIONS=y
+CONFIG_TPM_FLUSH_RESOURCES=y
+CONFIG_USB=y
+CONFIG_DM_USB=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_STORAGE=y
+CONFIG_TPM=y
+# CONFIG_EFI_LOADER is not set
diff --git a/include/configs/controlcenterdc.h b/include/configs/controlcenterdc.h
new file mode 100644
index 0000000..edc50c1
--- /dev/null
+++ b/include/configs/controlcenterdc.h
@@ -0,0 +1,235 @@
+/*
+ * Copyright (C) 2014 Stefan Roese <sr@denx.de>
+ * Copyright (C) 2016 Mario Six <mario.six@gdsys.cc>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _CONFIG_CONTROLCENTERDC_H
+#define _CONFIG_CONTROLCENTERDC_H
+
+/*
+ * High Level Configuration Options (easy to change)
+ */
+#define CONFIG_CUSTOMER_BOARD_SUPPORT
+
+#define CONFIG_SKIP_LOWLEVEL_INIT	/* disable board lowlevel_init */
+#define CONFIG_DISPLAY_BOARDINFO_LATE
+#define CONFIG_BOARD_LATE_INIT
+#define CONFIG_LAST_STAGE_INIT
+#define CONFIG_SPL_BOARD_INIT
+
+/*
+ * TEXT_BASE needs to be below 16MiB, since this area is scrubbed
+ * for DDR ECC byte filling in the SPL before loading the main
+ * U-Boot into it.
+ */
+#define	CONFIG_SYS_TEXT_BASE	0x00800000
+
+#define CONFIG_SYS_TCLK		250000000	/* 250MHz */
+
+#define CONFIG_LOADADDR 		1000000
+
+#define CONFIG_SYS_NO_FLASH		/* Declare no flash (NOR/SPI) */
+
+/*
+ * Commands configuration
+ */
+#define CONFIG_CMD_ENV
+#define CONFIG_CMD_I2C
+#define CONFIG_CMD_PCI
+#define CONFIG_CMD_SCSI
+#define CONFIG_CMD_SPI
+
+/* SPI NOR flash default params, used by sf commands */
+#define CONFIG_SF_DEFAULT_BUS		1
+#define CONFIG_SF_DEFAULT_SPEED		1000000
+#define CONFIG_SF_DEFAULT_MODE		SPI_MODE_3
+
+/*
+ * SDIO/MMC Card Configuration
+ */
+#define CONFIG_GENERIC_MMC
+#define CONFIG_SYS_MMC_BASE		MVEBU_SDIO_BASE
+
+/*
+ * SATA/SCSI/AHCI configuration
+ */
+#define CONFIG_LIBATA
+#define CONFIG_SCSI
+#define CONFIG_SCSI_AHCI
+#define CONFIG_SCSI_AHCI_PLAT
+#define CONFIG_SYS_SCSI_MAX_SCSI_ID	2
+#define CONFIG_SYS_SCSI_MAX_LUN		1
+#define CONFIG_SYS_SCSI_MAX_DEVICE	(CONFIG_SYS_SCSI_MAX_SCSI_ID * \
+					 CONFIG_SYS_SCSI_MAX_LUN)
+
+/* Partition support */
+#define CONFIG_DOS_PARTITION
+#define CONFIG_EFI_PARTITION
+
+/* Additional FS support/configuration */
+#define CONFIG_SUPPORT_VFAT
+
+/* USB/EHCI configuration */
+#define CONFIG_EHCI_IS_TDI
+
+/* Environment in SPI NOR flash */
+#define CONFIG_ENV_IS_IN_SPI_FLASH
+#define CONFIG_ENV_SPI_BUS		1
+#define CONFIG_ENV_OFFSET		(1 << 20) /* 1MiB in */
+#define CONFIG_ENV_SIZE			(64 << 10) /* 64KiB */
+#define CONFIG_ENV_SECT_SIZE		(256 << 10) /* 256KiB sectors */
+
+#define CONFIG_PHY_MARVELL		/* there is a marvell phy */
+#define PHY_ANEG_TIMEOUT	8000	/* PHY needs a longer aneg time */
+
+/* PCIe support */
+#ifndef CONFIG_SPL_BUILD
+#define CONFIG_PCI
+#define CONFIG_PCI_MVEBU
+#define CONFIG_PCI_PNP
+#define CONFIG_PCI_SCAN_SHOW
+#endif
+
+#define CONFIG_SYS_ALT_MEMTEST
+
+/*
+ * Software (bit-bang) MII driver configuration
+ */
+#define CONFIG_BITBANGMII		/* bit-bang MII PHY management */
+#define CONFIG_BITBANGMII_MULTI
+
+/* SPL */
+/*
+ * Select the boot device here
+ *
+ * Currently supported are:
+ * SPL_BOOT_SPI_NOR_FLASH	- Booting via SPI NOR flash
+ * SPL_BOOT_SDIO_MMC_CARD	- Booting via SDIO/MMC card (partition 1)
+ */
+#define SPL_BOOT_SPI_NOR_FLASH		1
+#define SPL_BOOT_SDIO_MMC_CARD		2
+#define CONFIG_SPL_BOOT_DEVICE		SPL_BOOT_SPI_NOR_FLASH
+
+/* Defines for SPL */
+#define CONFIG_SPL_FRAMEWORK
+#define CONFIG_SPL_SIZE			(160 << 10)
+
+#if defined(CONFIG_SECURED_MODE_IMAGE)
+#define CONFIG_SPL_TEXT_BASE		0x40002614
+#define CONFIG_SPL_MAX_SIZE		(CONFIG_SPL_SIZE - 0x2614)
+#else
+#define CONFIG_SPL_TEXT_BASE		0x40000030
+#define CONFIG_SPL_MAX_SIZE		(CONFIG_SPL_SIZE - 0x30)
+#endif
+
+#define CONFIG_SPL_BSS_START_ADDR	(0x40000000 + CONFIG_SPL_SIZE)
+#define CONFIG_SPL_BSS_MAX_SIZE		(16 << 10)
+
+#ifdef CONFIG_SPL_BUILD
+#define CONFIG_SYS_MALLOC_SIMPLE
+#endif
+
+#define CONFIG_SPL_STACK		(0x40000000 + ((212 - 16) << 10))
+#define CONFIG_SPL_BOOTROM_SAVE		(CONFIG_SPL_STACK + 4)
+
+#define CONFIG_SPL_LIBCOMMON_SUPPORT
+#define CONFIG_SPL_LIBGENERIC_SUPPORT
+#define CONFIG_SPL_SERIAL_SUPPORT
+#define CONFIG_SPL_I2C_SUPPORT
+
+#if CONFIG_SPL_BOOT_DEVICE == SPL_BOOT_SPI_NOR_FLASH
+/* SPL related SPI defines */
+#define CONFIG_SPL_SPI_LOAD
+#define CONFIG_SYS_SPI_U_BOOT_OFFS	0x30000
+#define CONFIG_SYS_U_BOOT_OFFS		CONFIG_SYS_SPI_U_BOOT_OFFS
+#endif
+
+#if CONFIG_SPL_BOOT_DEVICE == SPL_BOOT_SDIO_MMC_CARD
+/* SPL related MMC defines */
+#define CONFIG_SPL_MMC_SUPPORT
+#define CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_PARTITION 1
+#define CONFIG_SYS_MMC_U_BOOT_OFFS		(168 << 10)
+#define CONFIG_SYS_U_BOOT_OFFS			CONFIG_SYS_MMC_U_BOOT_OFFS
+#define CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR	(CONFIG_SYS_U_BOOT_OFFS / 512)
+#ifdef CONFIG_SPL_BUILD
+#define CONFIG_FIXED_SDHCI_ALIGNED_BUFFER	0x00180000	/* in SDRAM */
+#endif
+#endif
+
+/*
+ * Environment Configuration
+ */
+#define CONFIG_ENV_OVERWRITE
+
+#define CONFIG_BAUDRATE 115200
+
+#define CONFIG_HOSTNAME		ccdc
+#define CONFIG_ROOTPATH		"/opt/nfsroot"
+#define CONFIG_BOOTFILE		"ccdc.img"
+
+#define CONFIG_PREBOOT		/* enable preboot variable */
+
+#define CONFIG_EXTRA_ENV_SETTINGS						\
+	"netdev=eth1\0"						\
+	"consoledev=ttyS1\0"							\
+	"u-boot=u-boot.bin\0"							\
+	"bootfile_addr=1000000\0"						\
+	"keyprogram_addr=3000000\0"						\
+	"keyprogram_file=keyprogram.img\0"						\
+	"fdtfile=controlcenterdc.dtb\0"						\
+	"load=tftpboot ${loadaddr} ${u-boot}\0"					\
+	"mmcdev=0:2\0"								\
+	"update=sf probe 1:0;"							\
+		" sf erase 0 +${filesize};"					\
+		" sf write ${fileaddr} 0 ${filesize}\0"				\
+	"upd=run load update\0"							\
+	"fdt_high=0x10000000\0"							\
+	"initrd_high=0x10000000\0"						\
+	"loadkeyprogram=tpm flush_keys;"					\
+		" mmc rescan;"							\
+		" ext4load mmc ${mmcdev} ${keyprogram_addr} ${keyprogram_file};"\
+		" source ${keyprogram_addr}:script at 1\0"				\
+	"gpio1=gpio@22_25\0"							\
+	"gpio2=A29\0"								\
+	"blinkseq='0 0 0 0 2 0 2 2 3 1 3 1 0 0 2 2 3 1 3 3 2 0 2 2 3 1 1 1 "	\
+		  "2 0 2 2 3 1 3 1 0 0 2 0 3 3 3 1 2 0 0 0 3 1 1 1 0 0 0 0'\0"	\
+	"bootfail=for i in ${blinkseq}; do"					\
+		" if test $i -eq 0; then"					\
+		" gpio clear ${gpio1}; gpio set ${gpio2};"			\
+		" elif test $i -eq 1; then"					\
+		" gpio clear ${gpio1}; gpio clear ${gpio2};"			\
+		" elif test $i -eq 2; then"					\
+		" gpio set ${gpio1}; gpio set ${gpio2};"			\
+		" else;"							\
+		" gpio clear ${gpio1}; gpio set ${gpio2};"			\
+		" fi; sleep 0.12; done\0"
+
+#define CONFIG_NFSBOOTCOMMAND								\
+	"setenv bootargs root=/dev/nfs rw "						\
+	"nfsroot=${serverip}:${rootpath} "						\
+	"ip=${ipaddr}:${serverip}:${gatewayip}:${netmask}:${hostname}:${netdev}:off "	\
+	"console=${consoledev},${baudrate} ${othbootargs}; "				\
+	"tftpboot ${bootfile_addr} ${bootfile}; "						\
+	"bootm ${bootfile_addr}"
+
+#define CONFIG_MMCBOOTCOMMAND					\
+	"setenv bootargs root=/dev/mmcblk0p3 rw rootwait "	\
+	"console=${consoledev},${baudrate} ${othbootargs}; "	\
+	"ext2load mmc 0:2 ${bootfile_addr} ${bootfile}; "	\
+	"bootm ${bootfile_addr}"
+
+#define CONFIG_BOOTCOMMAND			\
+	"if env exists keyprogram; then;"	\
+	" setenv keyprogram; run nfsboot;"	\
+        " fi;"					\
+        " run dobootfail"
+
+/*
+ * mv-common.h should be defined after CMD configs since it used them
+ * to enable certain macros
+ */
+#include "mv-common.h"
+
+#endif /* _CONFIG_CONTROLCENTERDC_H */
--
2.9.0

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [U-Boot] [PATCH v2 18/18] controlcenterdc: Make secure boot available
  2017-01-11 15:00 [U-Boot] [PATCH v2 00/18] arm: mvebu: Add gdsys ControlCenter-Compact board Mario Six
                   ` (16 preceding siblings ...)
  2017-01-11 15:01 ` [U-Boot] [PATCH v2 17/18] arm: mvebu: Add gdsys ControlCenter-Compact board Mario Six
@ 2017-01-11 15:01 ` Mario Six
  2017-01-18 17:10   ` Stefan Roese
  17 siblings, 1 reply; 55+ messages in thread
From: Mario Six @ 2017-01-11 15:01 UTC (permalink / raw)
  To: u-boot

Make secure booting available for the controlcenterdc
board (disabled by default).

Signed-off-by: Reinhard Pfau <reinhard.pfau@gdsys.cc>
Signed-off-by: Mario Six <mario.six@gdsys.cc>
---
Changes in v2:

* Moved definition and interpretation of SECURED_MODE_IMAGE and
  SECURED_MODE_CSK_INDEX to previous patch
---
 board/gdsys/a38x/kwbimage.cfg.in | 28 ++++++++++++++++++++++++++++
 1 file changed, 28 insertions(+)

diff --git a/board/gdsys/a38x/kwbimage.cfg.in b/board/gdsys/a38x/kwbimage.cfg.in
index 72e67d7..ebb3d32 100644
--- a/board/gdsys/a38x/kwbimage.cfg.in
+++ b/board/gdsys/a38x/kwbimage.cfg.in
@@ -1,5 +1,6 @@
 #
 # Copyright (C) 2014 Stefan Roese <sr@denx.de>
+# Copyright (C) 2015-2016 Reinhard Pfau <reinhard.pfau@gdsys.cc>
 #

 # Armada 38x uses version 1 image format
@@ -10,3 +11,30 @@ VERSION		1

 # Binary Header (bin_hdr) with DDR3 training code
 BINARY spl/u-boot-spl.bin 0000005b 00000068
+
+# Name of KAK
+KAK	kwb_kak
+
+# Name of (active) CSK
+CSK 	kwb_csk
+
+# BoxID
+BOX_ID	0x1
+
+# FlashID
+FLASH_ID 0x1
+
+# JTAG delay
+JTAG_DELAY 5
+
+# active CSK index
+#@CSK_INDEX
+
+# whether to encode box ID and flash ID into image
+#SEC_SPECIALIZED_IMG
+
+# secured mode boot device
+#@SEC_BOOT_DEV
+
+# secured mode: dump fuse commands
+#@SEC_FUSE_DUMP
--
2.9.0

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [U-Boot] [PATCH v2 01/18] pci: mvebu: Fix Armada 38x support
  2017-01-11 15:00 ` [U-Boot] [PATCH v2 01/18] pci: mvebu: Fix Armada 38x support Mario Six
@ 2017-01-18 15:56   ` Stefan Roese
  2017-02-01 11:40   ` Stefan Roese
  1 sibling, 0 replies; 55+ messages in thread
From: Stefan Roese @ 2017-01-18 15:56 UTC (permalink / raw)
  To: u-boot

On 11.01.2017 16:00, Mario Six wrote:
> From: Dirk Eibach <dirk.eibach@gdsys.cc>
>
> Armada 38x has four PCI ports, not three.
>
> The optimization in pci_init_board() seems to assume that every port has
> three lanes. This is obviously wrong, and breaks support for Armada 38x.
>
> Signed-off-by: Dirk Eibach <dirk.eibach@gdsys.cc>
> Signed-off-by: Mario Six <mario.six@gdsys.cc>

Reviewed-by: Stefan Roese <sr@denx.de>

Thanks,
Stefan

^ permalink raw reply	[flat|nested] 55+ messages in thread

* [U-Boot] [PATCH v2 02/18] net: phy: Support Marvell 88E1680
  2017-01-11 15:00 ` [U-Boot] [PATCH v2 02/18] net: phy: Support Marvell 88E1680 Mario Six
@ 2017-01-18 15:57   ` Stefan Roese
  2017-01-18 22:45     ` Joe Hershberger
  2017-01-18 22:48   ` Joe Hershberger
  2017-02-01 11:40   ` Stefan Roese
  2 siblings, 1 reply; 55+ messages in thread
From: Stefan Roese @ 2017-01-18 15:57 UTC (permalink / raw)
  To: u-boot

On 11.01.2017 16:00, Mario Six wrote:
> From: Dirk Eibach <dirk.eibach@gdsys.cc>
>
> Add support for Marvell 88E1680 Integrated Octal
> 10/100/1000 Mbps Energy Efficient Ethernet Transceiver.
>
> Signed-off-by: Dirk Eibach <dirk.eibach@gdsys.cc>
> Signed-off-by: Mario Six <mario.six@gdsys.cc>
> ---
> Changes in v2:
>
> * Switched to usage of pre-defined constant names where possible
> * Added error handling for genphy_config_aneg call

Reviewed-by: Stefan Roese <sr@denx.de>

Joe, I would like to include this patch with the patch series once
all is fine. Do you see any issues with it? Could I have your
Acked-by and push it via the Marvell git repository?

Thanks,
Stefan

^ permalink raw reply	[flat|nested] 55+ messages in thread

* [U-Boot] [PATCH v2 03/18] mvebu: Add board_pex_config()
  2017-01-11 15:00 ` [U-Boot] [PATCH v2 03/18] mvebu: Add board_pex_config() Mario Six
@ 2017-01-18 15:58   ` Stefan Roese
  2017-02-01 11:40   ` Stefan Roese
  1 sibling, 0 replies; 55+ messages in thread
From: Stefan Roese @ 2017-01-18 15:58 UTC (permalink / raw)
  To: u-boot

On 11.01.2017 16:00, Mario Six wrote:
> Allow boards to do some initialization when PCIe comes up.
>
> Signed-off-by: Dirk Eibach <dirk.eibach@gdsys.cc>
> Signed-off-by: Mario Six <mario.six@gdsys.cc>
> ---
> Changes in v2:
>
> * Switched usage of __attribute(...) to __weak to simplify weak function
>   declaration

Reviewed-by: Stefan Roese <sr@denx.de>

Thanks,
Stefan

^ permalink raw reply	[flat|nested] 55+ messages in thread

* [U-Boot] [PATCH v2 04/18] arm: mvebu: spl.c: Remove useless gd declaration
  2017-01-11 15:00 ` [U-Boot] [PATCH v2 04/18] arm: mvebu: spl.c: Remove useless gd declaration Mario Six
@ 2017-01-18 15:58   ` Stefan Roese
  2017-02-01 11:40   ` Stefan Roese
  1 sibling, 0 replies; 55+ messages in thread
From: Stefan Roese @ 2017-01-18 15:58 UTC (permalink / raw)
  To: u-boot

On 11.01.2017 16:00, Mario Six wrote:
> From: Reinhard Pfau <pfau@gdsys.de>
>
> ddaa905 ("arm: mvebu: Add DM (driver model) support") removed the
> assignment of the gd pointer, but kept the (now superfluous) declaration
> of the gd pointer.
>
> Remove this declaration.
>
> Signed-off-by: Reinhard Pfau <pfau@gdsys.de>
> ---
> Changes in v2:
>
> None

Reviewed-by: Stefan Roese <sr@denx.de>

Thanks,
Stefan

^ permalink raw reply	[flat|nested] 55+ messages in thread

* [U-Boot] [PATCH v2 05/18] dm: Add callback to modify the device tree
  2017-01-11 15:00 ` [U-Boot] [PATCH v2 05/18] dm: Add callback to modify the device tree Mario Six
@ 2017-01-18 16:03   ` Stefan Roese
  0 siblings, 0 replies; 55+ messages in thread
From: Stefan Roese @ 2017-01-18 16:03 UTC (permalink / raw)
  To: u-boot

On 11.01.2017 16:00, Mario Six wrote:
> Certain boards come in different variations by way of utilizing daughter
> boards, for example. These boards might contain additional chips, which
> are added to the main board's busses, e.g. I2C.
>
> The device tree support for such boards would either, quite naturally,
> employ the overlay mechanism to add such chips to the tree, or would use
> one large default device tree, and delete the devices that are actually
> not present.
>
> Regardless of approach, even on the U-Boot level, a modification of the
> device tree is a prerequisite to have such modular families of boards
> supported properly.
>
> Therefore, we add an option to make the U-Boot device tree (the actual
> copy later used by the driver model) writeable, and add a callback
> method that allows boards to modify the device tree at an early stage,
> at which, hopefully, also the application of device tree overlays will
> be possible.
>
> Signed-off-by: Mario Six <mario.six@gdsys.cc>
> ---
> Changes in v2:
>
> * Switched from usage of globally writeable global data pointer to a locally
>   writeable pointer passed to board_fix_fdt
> * Added comments for board_fix_fdt in include/common.h
> * Added documentation for pre-relocation device tree manipulation

Mario, thanks for the extensive documentation in this new version.
I would like to see some review comments from Simon (who is working
on a live DT as I've noticed just today) and perhaps others on this
patch.

Simon, could you please take a look at this?

Thanks,
Stefan

> ---
>  common/board_f.c               |  10 ++++
>  doc/driver-model/fdt-fixup.txt | 132 +++++++++++++++++++++++++++++++++++++++++
>  dts/Kconfig                    |  10 ++++
>  include/common.h               |   1 +
>  4 files changed, 153 insertions(+)
>  create mode 100644 doc/driver-model/fdt-fixup.txt
>
> diff --git a/common/board_f.c b/common/board_f.c
> index cc8aee7..e877bf9 100644
> --- a/common/board_f.c
> +++ b/common/board_f.c
> @@ -767,6 +767,13 @@ static int setup_reloc(void)
>  	return 0;
>  }
>
> +#ifdef CONFIG_OF_BOARD_FIXUP
> +static int fix_fdt(void)
> +{
> +	return board_fix_fdt((void *)gd->fdt_blob);
> +}
> +#endif
> +
>  /* ARM calls relocate_code from its crt0.S */
>  #if !defined(CONFIG_ARM) && !defined(CONFIG_SANDBOX)
>
> @@ -1037,6 +1044,9 @@ static init_fnc_t init_sequence_f[] = {
>  #ifdef CONFIG_SYS_EXTBDINFO
>  	setup_board_extra,
>  #endif
> +#ifdef CONFIG_OF_BOARD_FIXUP
> +	fix_fdt,
> +#endif
>  	INIT_FUNC_WATCHDOG_RESET
>  	reloc_fdt,
>  	setup_reloc,
> diff --git a/doc/driver-model/fdt-fixup.txt b/doc/driver-model/fdt-fixup.txt
> new file mode 100644
> index 0000000..70344bd
> --- /dev/null
> +++ b/doc/driver-model/fdt-fixup.txt
> @@ -0,0 +1,132 @@
> +Pre-relocation device tree manipulation
> +=======================================
> +
> +Contents:
> +
> +1. Purpose
> +2. Implementation
> +3. Example
> +4. Work to be done
> +
> +1. Purpose
> +----------
> +
> +In certain markets, it is beneficial for manufacturers of embedded devices to
> +offer certain ranges of products, where the functionality of the devices within
> +one series either don't differ greatly from another, or can be thought of as
> +"extensions" of each other, where one device only differs from another in the
> +addition of a small number of features (e.g. an additional output connector).
> +
> +To realize this in hardware, one method is to have a motherboard, and several
> +possible daughter boards that can be attached to this mother board. Different
> +daughter boards then either offer the slightly different functionality, or the
> +addition of the daughter board to the device realizes the "extension" of
> +functionality to the device described previously.
> +
> +For the software, we obviously want to reuse components for all these
> +variations of the device. This means that the software somehow needs to cope
> +with the situation that certain ICs may or may not be present on any given
> +system, depending on which daughter boards are connected to the motherboard.
> +
> +In the Linux kernel, one possible solution to this problem is to employ the
> +device tree overlay mechanism: There exists one "base" device tree, which
> +features only the components guaranteed to exist in all varieties of the
> +device. At the start of the kernel, the presence and type of the daughter
> +boards is then detected, and the corresponding device tree overlays are applied
> +to support the components on the daughter boards.
> +
> +Note that the components present on every variety of the board must, of course,
> +provide a way to find out if and which daughter boards are installed for this
> +mechanism to work.
> +
> +In the U-Boot boot loader, support for device tree overlays has recently been
> +integrated, and is used on some boards to alter the device tree that is later
> +passed to Linux. But since U-Boot's driver model, which is device tree-based as
> +well, is being used in more and more drivers, the same problem of altering the
> +device tree starts cropping up in U-Boot itself as well.
> +
> +An additional problem with the device tree in U-Boot is that it is read-only,
> +and the current mechanisms don't allow easy manipulation of the device tree
> +after the driver model has been initialized. While migrating to a live device
> +tree (at least after the relocation) would greatly simplify the solution of
> +this problem, it is a non-negligible task to implement it, an a interim
> +solution is needed to address the problem at least in the medium-term.
> +
> +Hence, we propose a solution to this problem by offering a board-specific
> +call-back function, which is passed a writeable pointer to the device tree.
> +This function is called before the device tree is relocated, and specifically
> +before the main U-Boot's driver model is instantiated, hence the main U-Boot
> +"sees" all modifications to the device tree made in this function. Furthermore,
> +we have the pre-relocation driver model at our disposal at this stage, which
> +means that we can query the hardware for the existence and variety of the
> +components easily.
> +
> +2. Implementation
> +-----------------
> +
> +To take advantage of the pre-relocation device tree manipulation mechanism,
> +boards have to implement the function board_fix_fdt, which has the following
> +signature:
> +
> +int board_fix_fdt (void *rw_fdt_blob)
> +
> +The passed-in void pointer is a writeable pointer to the device tree, which can
> +be used to manipulate the device tree using e.g. functions from
> +include/fdt_support.h. The return value should either be 0 in case of
> +successful execution of the device tree manipulation or something else for a
> +failure. Note that returning a non-null value from the function will
> +unrecoverably halt the boot process, as with any function from init_sequence_f
> +(in common/board_f.c).
> +
> +Furthermore, the Kconfig option OF_BOARD_FIXUP has to be set for the function
> +to be called:
> +
> +Device Tree Control
> +-> [*] Board-specific manipulation of Device Tree
> +
> ++----------------------------------------------------------+
> +| WARNING: The actual manipulation of the device tree has  |
> +| to be the _last_ set of operations in board_fix_fdt!     |
> +| Since the pre-relocation driver model does not adapt to  |
> +| changes made to the device tree either, its references   |
> +| into the device tree will be invalid after manipulating  |
> +| it, and unpredictable behavior might occur when          |
> +| functions that rely on them are executed!                |
> ++----------------------------------------------------------+
> +
> +Hence, the recommended layout of the board_fixup_fdt call-back function is the
> +following:
> +
> +int board_fix_fdt(void *rw_fdt_blob)
> +{
> +	/* Collect information about device's hardware and store them in e.g.
> +	   local variables */
> +
> +	/* Do device tree manipulation using the values previously collected */
> +
> +	/* Return 0 on successful manipulation and non-zero otherwise */
> +}
> +
> +If this convention is kept, both an "additive" approach, meaning that nodes for
> +detected components are added to the device tree, as well as a "subtractive"
> +approach, meaning that nodes for absent components are removed from the tree,
> +as well as a combination of both approaches should work.
> +
> +3. Example
> +----------
> +
> +The controlcenterdc board (board/gdsys/a38x/controlcenterdc.c) features a
> +board_fix_fdt function, in which six GPIO expanders (which might be present or
> +not, since they are on daughter boards) on a I2C bus are queried for, and
> +subsequently deactivated in the device tree if they are not present.
> +
> +Note that the dm_i2c_simple_probe function does not use the device tree, hence
> +it is safe to call it after the tree has already been manipulated.
> +
> +4. Work to be done
> +------------------
> +
> +* The application of device tree overlay should be possible in board_fixup_fdt,
> +  but has not been tested at this stage.
> +
> +2017-01-06, Mario Six <mario.six@gdsys.cc>
> diff --git a/dts/Kconfig b/dts/Kconfig
> index 4b7d8b1..3f64eda 100644
> --- a/dts/Kconfig
> +++ b/dts/Kconfig
> @@ -14,6 +14,16 @@ config OF_CONTROL
>  	  This feature provides for run-time configuration of U-Boot
>  	  via a flattened device tree.
>
> +config OF_BOARD_FIXUP
> +	bool "Board-specific manipulation of Device Tree"
> +	help
> +	  In certain circumstances it is necessary to be able to modify
> +	  U-Boot's device tree (e.g. to delete device from it). This option
> +	  make the Device Tree writeable and provides a board-specific
> +	  "board_fix_fdt" callback (called during pre-relocation time), which
> +	  enables the board initialization to modifiy the Device Tree. The
> +	  modified copy is subsequently used by U-Boot after relocation.
> +
>  config SPL_OF_CONTROL
>  	bool "Enable run-time configuration via Device Tree in SPL"
>  	depends on SPL && OF_CONTROL
> diff --git a/include/common.h b/include/common.h
> index a8d833b..a64f249 100644
> --- a/include/common.h
> +++ b/include/common.h
> @@ -502,6 +502,7 @@ extern ssize_t spi_write (uchar *, int, uchar *, int);
>
>  /* $(BOARD)/$(BOARD).c */
>  int board_early_init_f (void);
> +int board_fix_fdt (void *rw_fdt_blob); /* manipulate the U-Boot fdt before its relocation */
>  int board_late_init (void);
>  int board_postclk_init (void); /* after clocks/timebase, before env/serial */
>  int board_early_init_r (void);
> --
> 2.9.0
>

Viele Gr??e,
Stefan

-- 
DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-51 Fax: (+49)-8142-66989-80 Email: sr at denx.de

^ permalink raw reply	[flat|nested] 55+ messages in thread

* [U-Boot] [PATCH v2 06/18] lib: tpm: Add command to flush resources
  2017-01-11 15:00 ` [U-Boot] [PATCH v2 06/18] lib: tpm: Add command to flush resources Mario Six
@ 2017-01-18 16:07   ` Stefan Roese
  2017-01-19 13:57   ` Simon Glass
  2017-02-01 11:41   ` Stefan Roese
  2 siblings, 0 replies; 55+ messages in thread
From: Stefan Roese @ 2017-01-18 16:07 UTC (permalink / raw)
  To: u-boot

On 11.01.2017 16:00, Mario Six wrote:
> This patch adds a function to the TPM library, which allows U-Boot to
> flush resources, e.g. keys, from the TPM.
>
> Signed-off-by: Mario Six <mario.six@gdsys.cc>
> ---
> Changes in v2:
>
> * Added U-Boot command for resource flushing ("tpm flush"), and made the
>   command and the library function deactivate-able via config
> ---
>  board/gdsys/p1022/controlcenterd-id.c |  9 -----
>  cmd/tpm.c                             | 70 +++++++++++++++++++++++++++++++++++
>  drivers/tpm/Kconfig                   |  6 +++
>  include/tpm.h                         | 45 ++++++++++++++++++++++
>  lib/tpm.c                             | 29 +++++++++++++++
>  5 files changed, 150 insertions(+), 9 deletions(-)
>
> diff --git a/board/gdsys/p1022/controlcenterd-id.c b/board/gdsys/p1022/controlcenterd-id.c
> index 2c6c698..1648f13 100644
> --- a/board/gdsys/p1022/controlcenterd-id.c
> +++ b/board/gdsys/p1022/controlcenterd-id.c
> @@ -43,15 +43,6 @@
>  #define CCDM_AUTO_FIRST_STAGE
>  #endif
>
> -/* enums from TCG specs */
> -enum {
> -	/* capability areas */
> -	TPM_CAP_NV_INDEX	= 0x00000011,
> -	TPM_CAP_HANDLE		= 0x00000014,
> -	/* resource types */
> -	TPM_RT_KEY	= 0x00000001,
> -};
> -
>  /* CCDM specific contants */
>  enum {
>  	/* NV indices */
> diff --git a/cmd/tpm.c b/cmd/tpm.c
> index 312503f..625fc43 100644
> --- a/cmd/tpm.c
> +++ b/cmd/tpm.c
> @@ -646,6 +646,64 @@ TPM_COMMAND_NO_ARG(tpm_end_oiap)
>
>  #endif /* CONFIG_TPM_AUTH_SESSIONS */
>
> +#ifdef CONFIG_TPM_FLUSH_RESOURCES
> +static int do_tpm_flush(cmd_tbl_t *cmdtp, int flag, int argc,
> +			char * const argv[])
> +{
> +	int type = 0;
> +
> +	if (argc != 2)
> +		return CMD_RET_USAGE;
> +
> +	if (strcasecmp(argv[1], "key"))
> +		type = TPM_RT_KEY;
> +	else if (strcasecmp(argv[1], "auth"))
> +		type = TPM_RT_AUTH;
> +	else if (strcasecmp(argv[1], "hash"))
> +		type = TPM_RT_HASH;
> +	else if (strcasecmp(argv[1], "trans"))
> +		type = TPM_RT_TRANS;
> +	else if (strcasecmp(argv[1], "context"))
> +		type = TPM_RT_CONTEXT;
> +	else if (strcasecmp(argv[1], "counter"))
> +		type = TPM_RT_COUNTER;
> +	else if (strcasecmp(argv[1], "delegate"))
> +		type = TPM_RT_DELEGATE;
> +	else if (strcasecmp(argv[1], "daa_tpm"))
> +		type = TPM_RT_DAA_TPM;
> +	else if (strcasecmp(argv[1], "daa_v0"))
> +		type = TPM_RT_DAA_V0;
> +	else if (strcasecmp(argv[1], "daa_v1"))
> +		type = TPM_RT_DAA_V1;
> +
> +	if (strcasecmp(argv[2], "all")) {
> +		uint16_t res_count;
> +		uint8_t buf[288];
> +		uint8_t *ptr;
> +		int err;
> +		uint i;
> +
> +		/* fetch list of already loaded resources in the TPM */
> +		err = tpm_get_capability(TPM_CAP_HANDLE, type, buf,
> +					 sizeof(buf));
> +		if (err)
> +			return -1;
> +		res_count = get_unaligned_be16(buf);
> +		ptr = buf + 2;
> +		for (i = 0; i < res_count; ++i, ptr += 4)
> +			tpm_flush_specific(get_unaligned_be32(ptr), type);
> +	} else {
> +		uint32_t handle = simple_strtoul(argv[2], NULL, 0);
> +
> +		if (!handle)
> +			return -1;
> +		tpm_flush_specific(cpu_to_be32(handle), type);
> +	}
> +
> +	return 0;
> +}
> +#endif /* CONFIG_TPM_FLUSH_RESOURCES */
> +
>  #define MAKE_TPM_CMD_ENTRY(cmd) \
>  	U_BOOT_CMD_MKENT(cmd, 0, 1, do_tpm_ ## cmd, "", "")
>
> @@ -701,6 +759,10 @@ static cmd_tbl_t tpm_commands[] = {
>  	U_BOOT_CMD_MKENT(get_pub_key_oiap, 0, 1,
>  			 do_tpm_get_pub_key_oiap, "", ""),
>  #endif /* CONFIG_TPM_AUTH_SESSIONS */
> +#ifdef CONFIG_TPM_FLUSH_RESOURCES
> +	U_BOOT_CMD_MKENT(flush, 0, 1,
> +			 do_tpm_flush, "", ""),
> +#endif /* CONFIG_TPM_FLUSH_RESOURCES */
>  };
>
>  static int do_tpm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
> @@ -750,6 +812,14 @@ U_BOOT_CMD(tpm, CONFIG_SYS_MAXARGS, 1, do_tpm,
>  "  get_capability cap_area sub_cap addr count\n"
>  "    - Read <count> bytes of TPM capability indexed by <cap_area> and\n"
>  "      <sub_cap> to memory address <addr>.\n"
> +#ifdef CONFIG_TPM_FLUSH_RESOURCES
> +"Resource management functions\n"
> +"  flush resource_type id\n"
> +"    - flushes a resource of type <resource_type> (may be one of key, auth,\n"
> +"      hash, trans, context, counter, delegate, daa_tpm, daa_v0, daa_v1),\n"
> +"      and id <id> from the TPM. Use an <id> of \"all\" to flush all\n"
> +"      resources of that type.\n"
> +#endif /* CONFIG_TPM_FLUSH_RESOURCES */
>  #ifdef CONFIG_TPM_AUTH_SESSIONS
>  "Storage functions\n"
>  "  loadkey2_oiap parent_handle key_addr key_len usage_auth\n"
> diff --git a/drivers/tpm/Kconfig b/drivers/tpm/Kconfig
> index 7ab34ce..3490ee0 100644
> --- a/drivers/tpm/Kconfig
> +++ b/drivers/tpm/Kconfig
> @@ -82,4 +82,10 @@ config TPM_ST33ZP24_SPI
>  	  to the device using the standard TPM Interface Specification (TIS)
>  	  protocol
>
> +config TPM_FLUSH_RESOURCES
> +	bool "Enable TPM resource flushing support"
> +	depends on TPM
> +	help
> +	  Enable support to flush specific resources (e.g. keys) from the TPM.
> +	  The functionality is available via the 'tpm' command as well.
>  endmenu
> diff --git a/include/tpm.h b/include/tpm.h
> index 9a6585d..800f29c 100644
> --- a/include/tpm.h
> +++ b/include/tpm.h
> @@ -47,6 +47,42 @@ enum tpm_nv_index {
>  	TPM_NV_INDEX_DIR	= 0x10000001,
>  };
>
> +enum tpm_resource_type {
> +	TPM_RT_KEY	= 0x00000001,
> +	TPM_RT_AUTH	= 0x00000002,
> +	TPM_RT_HASH	= 0x00000003,
> +	TPM_RT_TRANS	= 0x00000004,
> +	TPM_RT_CONTEXT	= 0x00000005,
> +	TPM_RT_COUNTER	= 0x00000006,
> +	TPM_RT_DELEGATE	= 0x00000007,
> +	TPM_RT_DAA_TPM	= 0x00000008,
> +	TPM_RT_DAA_V0	= 0x00000009,
> +	TPM_RT_DAA_V1	= 0x0000000A,
> +};
> +
> +enum tpm_capability_areas {
> +	TPM_CAP_ORD		= 0x00000001,
> +	TPM_CAP_ALG		= 0x00000002,
> +	TPM_CAP_PID		= 0x00000003,
> +	TPM_CAP_FLAG		= 0x00000004,
> +	TPM_CAP_PROPERTY	= 0x00000005,
> +	TPM_CAP_VERSION		= 0x00000006,
> +	TPM_CAP_KEY_HANDLE	= 0x00000007,
> +	TPM_CAP_CHECK_LOADED	= 0x00000008,
> +	TPM_CAP_SYM_MODE	= 0x00000009,
> +	TPM_CAP_KEY_STATUS	= 0x0000000C,
> +	TPM_CAP_NV_LIST		= 0x0000000D,
> +	TPM_CAP_MFR		= 0x00000010,
> +	TPM_CAP_NV_INDEX	= 0x00000011,
> +	TPM_CAP_TRANS_ALG	= 0x00000012,
> +	TPM_CAP_HANDLE		= 0x00000014,
> +	TPM_CAP_TRANS_ES	= 0x00000015,
> +	TPM_CAP_AUTH_ENCRYPT	= 0x00000017,
> +	TPM_CAP_SELECT_SIZE	= 0x00000018,
> +	TPM_CAP_DA_LOGIC	= 0x00000019,
> +	TPM_CAP_VERSION_VAL	= 0x0000001A,
> +};
> +
>  #define TPM_NV_PER_GLOBALLOCK		(1U << 15)
>  #define TPM_NV_PER_PPWRITE		(1U << 0)
>  #define TPM_NV_PER_READ_STCLEAR		(1U << 31)
> @@ -594,4 +630,13 @@ uint32_t tpm_get_permanent_flags(struct tpm_permanent_flags *pflags);
>   */
>  uint32_t tpm_get_permissions(uint32_t index, uint32_t *perm);
>
> +/**
> + * Flush a resource with a given handle and type from the TPM
> + *
> + * @param key_handle           handle of the resource
> + * @param resource_type                type of the resource
> + * @return return code of the operation
> + */
> +uint32_t tpm_flush_specific(uint32_t key_handle, uint32_t resource_type);
> +
>  #endif /* __TPM_H */
> diff --git a/lib/tpm.c b/lib/tpm.c
> index 88f2406..fb12214 100644
> --- a/lib/tpm.c
> +++ b/lib/tpm.c
> @@ -645,6 +645,35 @@ uint32_t tpm_get_permissions(uint32_t index, uint32_t *perm)
>  	return 0;
>  }
>
> +#ifdef CONFIG_TPM_FLUSH_RESOURCES
> +uint32_t tpm_flush_specific(uint32_t key_handle, uint32_t resource_type)
> +{
> +	const uint8_t command[18] = {
> +		0x00, 0xc1,             /* TPM_TAG */
> +		0x00, 0x00, 0x00, 0x12, /* parameter size */
> +		0x00, 0x00, 0x00, 0xba, /* TPM_COMMAND_CODE */
> +		0x00, 0x00, 0x00, 0x00, /* key handle */
> +		0x00, 0x00, 0x00, 0x00, /* resource type */
> +	};
> +	const size_t key_handle_offset = 10;
> +	const size_t resource_type_offset = 14;
> +	uint8_t buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
> +	size_t response_length = sizeof(response);
> +	uint32_t err;
> +
> +	if (pack_byte_string(buf, sizeof(buf), "sdd",
> +			     0, command, sizeof(command),
> +			     key_handle_offset, key_handle,
> +			     resource_type_offset, resource_type))
> +		return TPM_LIB_ERROR;
> +
> +	err = tpm_sendrecv_command(buf, response, &response_length);
> +	if (err)
> +		return err;
> +	return 0;
> +}

You don't need "err" here. Simpler is this version:

	return tpm_sendrecv_command(buf, response, &response_length);

Other than this:

Reviewed-by: Stefan Roese <sr@denx.de>

Thanks,
Stefan

^ permalink raw reply	[flat|nested] 55+ messages in thread

* [U-Boot] [PATCH v2 07/18] core: device: Add dev_get_by_ofname function
  2017-01-11 15:00 ` [U-Boot] [PATCH v2 07/18] core: device: Add dev_get_by_ofname function Mario Six
@ 2017-01-18 16:23   ` Stefan Roese
  2017-01-19 13:57     ` Simon Glass
  0 siblings, 1 reply; 55+ messages in thread
From: Stefan Roese @ 2017-01-18 16:23 UTC (permalink / raw)
  To: u-boot

On 11.01.2017 16:00, Mario Six wrote:
> On boards that use DM, it is sometimes convenient and quicker to get a device
> via its device tree path, since the devices used in the board initialization
> routines are usually known beforehand.
>
> This patch adds such a convenience function.
>
> Signed-off-by: Mario Six <mario.six@gdsys.cc>
> ---
> Changes in v2:
>
> New in v2
> ---
>  drivers/core/device.c | 7 +++++++
>  include/dm/device.h   | 8 ++++++++
>  2 files changed, 15 insertions(+)
>
> diff --git a/drivers/core/device.c b/drivers/core/device.c
> index ed553d7..39d30b3 100644
> --- a/drivers/core/device.c
> +++ b/drivers/core/device.c
> @@ -627,6 +627,13 @@ const char *dev_get_uclass_name(struct udevice *dev)
>  	return dev->uclass->uc_drv->name;
>  }
>
> +void dev_get_by_ofname(char *ofname, struct udevice *dev)
> +{
> +	int offset = fdt_path_offset(gd->fdt_blob, ofname);
> +
> +	device_get_global_by_of_offset(offset, &dev);
> +}
> +
>  fdt_addr_t dev_get_addr_index(struct udevice *dev, int index)
>  {
>  #if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)
> diff --git a/include/dm/device.h b/include/dm/device.h
> index 9948bd4..402482c 100644
> --- a/include/dm/device.h
> +++ b/include/dm/device.h
> @@ -340,6 +340,14 @@ enum uclass_id device_get_uclass_id(struct udevice *dev);
>  const char *dev_get_uclass_name(struct udevice *dev);
>
>  /**
> + * dev_get_by_ofname() - find a device via its device tree path
> + *
> + * @ofname: Device tree path to use ("/path1/path2/...")
> + * @dev:    The found device or NULL
> + */
> +void dev_get_by_ofname(char *ofname, struct udevice *dev);

I'm not 100% sure if the function naming is perfect here. Usually
these dev_get_xxx function work on a "dev" provided by the caller
and return something else (addr, size). The functions returning a
"device" are called device_get_xxx. And perhaps its also better stick 
with using "struct udevice **devp" as parameter for
consistency as the other device_ functions do.

Simon, what do you think?

Thanks,
Stefan

^ permalink raw reply	[flat|nested] 55+ messages in thread

* [U-Boot] [PATCH v2 08/18] gpio: Add gpio_request_simple function
  2017-01-11 15:00 ` [U-Boot] [PATCH v2 08/18] gpio: Add gpio_request_simple function Mario Six
@ 2017-01-18 16:34   ` Stefan Roese
  0 siblings, 0 replies; 55+ messages in thread
From: Stefan Roese @ 2017-01-18 16:34 UTC (permalink / raw)
  To: u-boot

On 11.01.2017 16:00, Mario Six wrote:
> For board initialization, usage of GPIOs is sometimes needed, e.g. to
> initialize certain devices such as FPGAs. But since there currently is no
> device associated to the board itself, initialization routines have to
> cumbersomely get GPIOs via gpio_request_by_name_nodev.
>
> This patch adds a convenience function aimed at such scenarios, which wraps the
> gpio_request_by_name_nodev and some error checking. The GPIO is identified via
> its compatible string in the device tree.
>
> Signed-off-by: Mario Six <mario.six@gdsys.cc>
> ---
> Changes in v2:
>
> New in v2
> ---
>  drivers/gpio/gpio-uclass.c | 17 +++++++++++++++++
>  include/asm-generic/gpio.h | 22 ++++++++++++++++++++++
>  2 files changed, 39 insertions(+)
>
> diff --git a/drivers/gpio/gpio-uclass.c b/drivers/gpio/gpio-uclass.c
> index 4559739..197d987 100644
> --- a/drivers/gpio/gpio-uclass.c
> +++ b/drivers/gpio/gpio-uclass.c
> @@ -751,6 +751,23 @@ int gpio_request_list_by_name(struct udevice *dev, const char *list_name,
>  					       flags);
>  }
>
> +bool gpio_request_simple(char *name, struct gpio_desc *gpio)
> +{
> +	int node = fdt_node_offset_by_compatible(gd->fdt_blob, 0, name);
> +	int ret;
> +
> +	if (node < 0)
> +		return false;
> +
> +	ret = gpio_request_by_name_nodev(gd->fdt_blob, node, "gpios", 0, gpio,
> +					 0);
> +
> +	if (ret < 0)
> +		return false;
> +
> +	return dm_gpio_is_valid(gpio);
> +}
> +
>  int gpio_get_list_count(struct udevice *dev, const char *list_name)
>  {
>  	int ret;
> diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h
> index 4aa0004..5c3e599 100644
> --- a/include/asm-generic/gpio.h
> +++ b/include/asm-generic/gpio.h
> @@ -457,6 +457,28 @@ int gpio_request_list_by_name(struct udevice *dev, const char *list_name,
>  			      int flags);
>
>  /**
> + * gpio_request_simple() - Simple wrapper function to request GPIO via
> + *                         fdt compatible name
> + *
> + * Convenience method to get useable GPIO description information from a device
> + * tree declaration such as:
> + *
> + *   fpga_ready_gpio {
> + *       compatible = "generic,fpga-ready-gpio";
> + *       gpios = <&PCA22 27 0>;
> + *   };
> + *
> + * This is convenient for setting and reading GPIOs from board files (where no
> + * associated device is in play).
> + *
> + * @name: The fdt compatible string of the GPIO in question
> + * @gpio: Return the GPIO description information of the GPIO in question
> + *
> + * @return true if the operation succeeded, false if not
> + */
> +bool gpio_request_simple(char *name, struct gpio_desc *gpio);

So you have GPIOs that are not directly integrated in some other
device, like its usually the case for some power or reset GPIOs
that are e.g. used in USB DT nodes?

I'm not sure if this DT implementation would be accepted in the
Linux kernel. How do you handle it in Linux?

Thanks,
Stefan

^ permalink raw reply	[flat|nested] 55+ messages in thread

* [U-Boot] [PATCH v2 09/18] tools: kwbimage: Fix dest addr
  2017-01-11 15:00 ` [U-Boot] [PATCH v2 09/18] tools: kwbimage: Fix dest addr Mario Six
@ 2017-01-18 16:36   ` Stefan Roese
  2017-02-01 11:41   ` Stefan Roese
  1 sibling, 0 replies; 55+ messages in thread
From: Stefan Roese @ 2017-01-18 16:36 UTC (permalink / raw)
  To: u-boot

On 11.01.2017 16:00, Mario Six wrote:
> To enable secure boot, we need to jump back into the BootROM to continue
> the SoC's boot process instead of letting the SPL load and run the main
> U-Boot image.
>
> But, since the u-boot-spl.img (including the 64 byte header) is loaded
> by the SoC as the main image, we need to compensate for the header
> length to get a correct entry point.
>
> Thus, we subtract the header size from the destination address, so that
> the execution address points at the actual entry point of the image.
>
> The current boards ignore both parameters anyway, so this change shouldn't
> concern them.
>
> Signed-off-by: Mario Six <mario.six@gdsys.cc>
> ---
> Changes in v2:
>
> None

Reviewed-by: Stefan Roese <sr@denx.de>

Thanks,
Stefan

^ permalink raw reply	[flat|nested] 55+ messages in thread

* [U-Boot] [PATCH v2 10/18] tools: kwbimage: Fix style violations
  2017-01-11 15:00 ` [U-Boot] [PATCH v2 10/18] tools: kwbimage: Fix style violations Mario Six
@ 2017-01-18 16:37   ` Stefan Roese
  2017-02-01 11:41   ` Stefan Roese
  1 sibling, 0 replies; 55+ messages in thread
From: Stefan Roese @ 2017-01-18 16:37 UTC (permalink / raw)
  To: u-boot

On 11.01.2017 16:00, Mario Six wrote:
> Fix some style violations:
>
> - nine instances of missing blank lines after declarations
> - one overly long line
> - one split string (which also rewords an error message more concisely)
> - two superfluous else
>
> Signed-off-by: Mario Six <mario.six@gdsys.cc>
> ---
> Changes in v2:
>
> None

Reviewed-by: Stefan Roese <sr@denx.de>

Thanks,
Stefan

^ permalink raw reply	[flat|nested] 55+ messages in thread

* [U-Boot] [PATCH v2 11/18] tools: kwbimage: Fix arithmetic with void pointers
  2017-01-11 15:00 ` [U-Boot] [PATCH v2 11/18] tools: kwbimage: Fix arithmetic with void pointers Mario Six
@ 2017-01-18 16:38   ` Stefan Roese
  2017-02-01 11:41   ` Stefan Roese
  1 sibling, 0 replies; 55+ messages in thread
From: Stefan Roese @ 2017-01-18 16:38 UTC (permalink / raw)
  To: u-boot

On 11.01.2017 16:00, Mario Six wrote:
> Arithmetic with void pointers, e.g. a - b where both a and b are void
> pointers, is undefined in the C standard. Since we are operating with
> byte data here, we switch the void pointers to uint8_t pointers, and add
> the necessary casts.
>
> Signed-off-by: Mario Six <mario.six@gdsys.cc>
> ---
> Changes in v2:
>
> None

Reviewed-by: Stefan Roese <sr@denx.de>

Thanks,
Stefan

^ permalink raw reply	[flat|nested] 55+ messages in thread

* [U-Boot] [PATCH v2 12/18] tools: kwbimage: Reduce scope of variables
  2017-01-11 15:00 ` [U-Boot] [PATCH v2 12/18] tools: kwbimage: Reduce scope of variables Mario Six
@ 2017-01-18 16:39   ` Stefan Roese
  2017-02-01 11:41   ` Stefan Roese
  1 sibling, 0 replies; 55+ messages in thread
From: Stefan Roese @ 2017-01-18 16:39 UTC (permalink / raw)
  To: u-boot

On 11.01.2017 16:00, Mario Six wrote:
> This patch reduces the scope of some variables.
>
> Signed-off-by: Mario Six <mario.six@gdsys.cc>
> ---
> Changes in v2:
>
> None

Reviewed-by: Stefan Roese <sr@denx.de>

Thanks,
Stefan

^ permalink raw reply	[flat|nested] 55+ messages in thread

* [U-Boot] [PATCH v2 13/18] tools: kwbimage: Remove unused parameter
  2017-01-11 15:00 ` [U-Boot] [PATCH v2 13/18] tools: kwbimage: Remove unused parameter Mario Six
@ 2017-01-18 16:39   ` Stefan Roese
  2017-02-01 11:42   ` Stefan Roese
  1 sibling, 0 replies; 55+ messages in thread
From: Stefan Roese @ 2017-01-18 16:39 UTC (permalink / raw)
  To: u-boot

On 11.01.2017 16:00, Mario Six wrote:
> The parameter 'params' of the image_headersz_v1 function is never used
> by the function.
>
> Hence, remove it.
>
> Signed-off-by: Mario Six <mario.six@gdsys.cc>
> ---
> Changes in v2:
>
> None

Reviewed-by: Stefan Roese <sr@denx.de>

Thanks,
Stefan

^ permalink raw reply	[flat|nested] 55+ messages in thread

* [U-Boot] [PATCH v2 14/18] tools: kwbimage: Factor out add_binary_header_v1
  2017-01-11 15:00 ` [U-Boot] [PATCH v2 14/18] tools: kwbimage: Factor out add_binary_header_v1 Mario Six
@ 2017-01-18 16:40   ` Stefan Roese
  2017-02-01 11:42   ` Stefan Roese
  1 sibling, 0 replies; 55+ messages in thread
From: Stefan Roese @ 2017-01-18 16:40 UTC (permalink / raw)
  To: u-boot

On 11.01.2017 16:00, Mario Six wrote:
> In preparation of adding the creation of secure headers, we factor the
> add_binary_header_v1 function out of the image_create_v1 function.
>
> Signed-off-by: Mario Six <mario.six@gdsys.cc>
> ---
> Changes in v2:
>
> None

Reviewed-by: Stefan Roese <sr@denx.de>

Thanks,
Stefan

^ permalink raw reply	[flat|nested] 55+ messages in thread

* [U-Boot] [PATCH v2 15/18] tools: kwbimage: Refactor line parsing and fix error
  2017-01-11 15:00 ` [U-Boot] [PATCH v2 15/18] tools: kwbimage: Refactor line parsing and fix error Mario Six
@ 2017-01-18 16:47   ` Stefan Roese
  2017-02-01 11:42   ` Stefan Roese
  1 sibling, 0 replies; 55+ messages in thread
From: Stefan Roese @ 2017-01-18 16:47 UTC (permalink / raw)
  To: u-boot

On 11.01.2017 16:00, Mario Six wrote:
> The function image_create_config_parse_oneline is pretty complex, and
> since more parameters will be added to support secure booting, we
> refactor the function to make it more readable.
>
> Also, when a line contained just a keyword without any parameters,
> strtok_r returned NULL, which was then indiscriminately fed into atoi,
> causing a segfault. To correct this, we add a NULL check before feeding
> the extracted token to atoi, and print an error message in case the
> token is NULL.
>
> Signed-off-by: Mario Six <mario.six@gdsys.cc>
> ---
> Changes in v2:
>
> None

Reviewed-by: Stefan Roese <sr@denx.de>

Thanks,
Stefan

^ permalink raw reply	[flat|nested] 55+ messages in thread

* [U-Boot] [PATCH v2 16/18] arm: mvebu: Implement secure boot
  2017-01-11 15:01 ` [U-Boot] [PATCH v2 16/18] arm: mvebu: Implement secure boot Mario Six
@ 2017-01-18 16:58   ` Stefan Roese
  2017-01-19 13:57   ` Simon Glass
  2017-02-01 11:42   ` Stefan Roese
  2 siblings, 0 replies; 55+ messages in thread
From: Stefan Roese @ 2017-01-18 16:58 UTC (permalink / raw)
  To: u-boot

On 11.01.2017 16:01, Mario Six wrote:
> The patch implements secure booting for the mvebu architecture.
>
> This includes:
> - The addition of secure headers and all needed signatures and keys in
>   mkimage
> - Commands capable of writing the board's efuses to both write the
>   needed cryptographic data and enable the secure booting mechanism
> - The creation of convenience text files containing the necessary
>   commands to write the efuses
>
> The KAK and CSK keys are expected to reside in the files kwb_kak.key and
> kwb_csk.key (OpenSSL 2048 bit private keys) in the top-level directory.
>
> Signed-off-by: Reinhard Pfau <reinhard.pfau@gdsys.cc>
> Signed-off-by: Mario Six <mario.six@gdsys.cc>
> ---
> Changes in v2:
>
> * Added help text for MVEBU_EFUSE
> * Removed superfluous defined(CONFIG_MVEBU_EFUSE) from
>   arch/arm/mach-mvebu/Makefile
> * Rewrote disable_efuse_program to use clrbits_le32
> * Remove superfluous blank lines from arch/arm/mach-mvebu/include/mach/efuse.h

Thanks Mario for the nice and extensive documentation that you have
added in this patch version. Really appreciated. I only skimmed
though the patch and will re-test building for some other AXP / A38x
board once I apply this patch series for upstreaming - perhaps
next week. For now:

Reviewed-by: Stefan Roese <sr@denx.de>

Thanks,
Stefan

^ permalink raw reply	[flat|nested] 55+ messages in thread

* [U-Boot] [PATCH v2 17/18] arm: mvebu: Add gdsys ControlCenter-Compact board
  2017-01-11 15:01 ` [U-Boot] [PATCH v2 17/18] arm: mvebu: Add gdsys ControlCenter-Compact board Mario Six
@ 2017-01-18 17:09   ` Stefan Roese
  0 siblings, 0 replies; 55+ messages in thread
From: Stefan Roese @ 2017-01-18 17:09 UTC (permalink / raw)
  To: u-boot

On 11.01.2017 16:01, Mario Six wrote:
> From: Dirk Eibach <dirk.eibach@gdsys.cc>
>
> The gdsys ControlCenter Digital board is based on a Marvell Armada 38x
> SOC.
>
> It boots from SPI-Flash but can be configured to boot from SD-card for
> factory programming and testing.
>
> On board peripherals include:
> - 2 x GbE
> - Xilinx Kintex-7 FPGA connected via PCIe
> - mSATA
> - USB3 host
> - Atmel TPM
>
> Signed-off-by: Dirk Eibach <dirk.eibach@gdsys.cc>
> Signed-off-by: Mario Six <mario.six@gdsys.cc>
> ---
> Changes in v2:
>
> * Renamed DTS and board name to include armada-38x
> * Renamed 38x directory to a38x
> * Removed leftover dummy test Kconfig variable from board/gdsys/38x/Kconfig
> * Removed unneeded check for build target in board/gdsys/38x/Makefile
> * Removed duplicated board/gdsys/38x/README
> * Switched MIIPHY to new GPIO API
> * Removed checkboard function
> * Fixed multi-line comment in board/gdsys/controlcenterdc.c
> * Switched to usage of ARRAY_SIZE in board/gdsys/controlcenterdc.c
> * Factored out hydra.{c,h} and ihs_phys.{c,h} from
>   board/gdsys/controlcenterdc.c and removed ifdefs
> * Removed unaddressed TODO from HRE

Thanks for working on this. A few comment still (I didn't look that
closely in this patch as its still huge):

- Are the DT properties okay also for Linux integration? I assume
   that you plan to use Linux on these board, right?

- Is it perhaps possible to move some (most) of the crypto code
   (hre.c) into some common directory, or is this really board
   specific?

Thanks,
Stefan

^ permalink raw reply	[flat|nested] 55+ messages in thread

* [U-Boot] [PATCH v2 18/18] controlcenterdc: Make secure boot available
  2017-01-11 15:01 ` [U-Boot] [PATCH v2 18/18] controlcenterdc: Make secure boot available Mario Six
@ 2017-01-18 17:10   ` Stefan Roese
  0 siblings, 0 replies; 55+ messages in thread
From: Stefan Roese @ 2017-01-18 17:10 UTC (permalink / raw)
  To: u-boot

On 11.01.2017 16:01, Mario Six wrote:
> Make secure booting available for the controlcenterdc
> board (disabled by default).
>
> Signed-off-by: Reinhard Pfau <reinhard.pfau@gdsys.cc>
> Signed-off-by: Mario Six <mario.six@gdsys.cc>
> ---
> Changes in v2:
>
> * Moved definition and interpretation of SECURED_MODE_IMAGE and
>   SECURED_MODE_CSK_INDEX to previous patch
> ---
>  board/gdsys/a38x/kwbimage.cfg.in | 28 ++++++++++++++++++++++++++++
>  1 file changed, 28 insertions(+)

Don't you need to change something in the defconfig to enable secure
boot on this board?

Thanks,
Stefan

^ permalink raw reply	[flat|nested] 55+ messages in thread

* [U-Boot] [PATCH v2 02/18] net: phy: Support Marvell 88E1680
  2017-01-18 15:57   ` Stefan Roese
@ 2017-01-18 22:45     ` Joe Hershberger
  0 siblings, 0 replies; 55+ messages in thread
From: Joe Hershberger @ 2017-01-18 22:45 UTC (permalink / raw)
  To: u-boot

On Wed, Jan 18, 2017 at 9:57 AM, Stefan Roese <sr@denx.de> wrote:
> On 11.01.2017 16:00, Mario Six wrote:
>>
>> From: Dirk Eibach <dirk.eibach@gdsys.cc>
>>
>> Add support for Marvell 88E1680 Integrated Octal
>> 10/100/1000 Mbps Energy Efficient Ethernet Transceiver.
>>
>> Signed-off-by: Dirk Eibach <dirk.eibach@gdsys.cc>
>> Signed-off-by: Mario Six <mario.six@gdsys.cc>
>> ---
>> Changes in v2:
>>
>> * Switched to usage of pre-defined constant names where possible
>> * Added error handling for genphy_config_aneg call
>
>
> Reviewed-by: Stefan Roese <sr@denx.de>
>
> Joe, I would like to include this patch with the patch series once
> all is fine. Do you see any issues with it? Could I have your
> Acked-by and push it via the Marvell git repository?

Sounds good.

Cheers,
-Joe

^ permalink raw reply	[flat|nested] 55+ messages in thread

* [U-Boot] [PATCH v2 02/18] net: phy: Support Marvell 88E1680
  2017-01-11 15:00 ` [U-Boot] [PATCH v2 02/18] net: phy: Support Marvell 88E1680 Mario Six
  2017-01-18 15:57   ` Stefan Roese
@ 2017-01-18 22:48   ` Joe Hershberger
  2017-02-01 11:40   ` Stefan Roese
  2 siblings, 0 replies; 55+ messages in thread
From: Joe Hershberger @ 2017-01-18 22:48 UTC (permalink / raw)
  To: u-boot

On Wed, Jan 11, 2017 at 9:00 AM, Mario Six <mario.six@gdsys.cc> wrote:
> From: Dirk Eibach <dirk.eibach@gdsys.cc>
>
> Add support for Marvell 88E1680 Integrated Octal
> 10/100/1000 Mbps Energy Efficient Ethernet Transceiver.
>
> Signed-off-by: Dirk Eibach <dirk.eibach@gdsys.cc>
> Signed-off-by: Mario Six <mario.six@gdsys.cc>

Acked-by: Joe Hershberger <joe.hershberger@ni.com>

^ permalink raw reply	[flat|nested] 55+ messages in thread

* [U-Boot] [PATCH v2 06/18] lib: tpm: Add command to flush resources
  2017-01-11 15:00 ` [U-Boot] [PATCH v2 06/18] lib: tpm: Add command to flush resources Mario Six
  2017-01-18 16:07   ` Stefan Roese
@ 2017-01-19 13:57   ` Simon Glass
  2017-02-01 11:41   ` Stefan Roese
  2 siblings, 0 replies; 55+ messages in thread
From: Simon Glass @ 2017-01-19 13:57 UTC (permalink / raw)
  To: u-boot

On 11 January 2017 at 08:00, Mario Six <mario.six@gdsys.cc> wrote:
>
> This patch adds a function to the TPM library, which allows U-Boot to
> flush resources, e.g. keys, from the TPM.
>
> Signed-off-by: Mario Six <mario.six@gdsys.cc>
> ---
> Changes in v2:
>
> * Added U-Boot command for resource flushing ("tpm flush"), and made the
>   command and the library function deactivate-able via config
> ---
>  board/gdsys/p1022/controlcenterd-id.c |  9 -----
>  cmd/tpm.c                             | 70 +++++++++++++++++++++++++++++++++++
>  drivers/tpm/Kconfig                   |  6 +++
>  include/tpm.h                         | 45 ++++++++++++++++++++++
>  lib/tpm.c                             | 29 +++++++++++++++
>  5 files changed, 150 insertions(+), 9 deletions(-)

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

^ permalink raw reply	[flat|nested] 55+ messages in thread

* [U-Boot] [PATCH v2 07/18] core: device: Add dev_get_by_ofname function
  2017-01-18 16:23   ` Stefan Roese
@ 2017-01-19 13:57     ` Simon Glass
  0 siblings, 0 replies; 55+ messages in thread
From: Simon Glass @ 2017-01-19 13:57 UTC (permalink / raw)
  To: u-boot

Hi,

On 18 January 2017 at 09:23, Stefan Roese <sr@denx.de> wrote:
> On 11.01.2017 16:00, Mario Six wrote:
>>
>> On boards that use DM, it is sometimes convenient and quicker to get a
>> device
>> via its device tree path, since the devices used in the board
>> initialization
>> routines are usually known beforehand.
>>
>> This patch adds such a convenience function.
>>
>> Signed-off-by: Mario Six <mario.six@gdsys.cc>
>> ---
>> Changes in v2:
>>
>> New in v2
>> ---
>>  drivers/core/device.c | 7 +++++++
>>  include/dm/device.h   | 8 ++++++++
>>  2 files changed, 15 insertions(+)
>>
>> diff --git a/drivers/core/device.c b/drivers/core/device.c
>> index ed553d7..39d30b3 100644
>> --- a/drivers/core/device.c
>> +++ b/drivers/core/device.c
>> @@ -627,6 +627,13 @@ const char *dev_get_uclass_name(struct udevice *dev)
>>         return dev->uclass->uc_drv->name;
>>  }
>>
>> +void dev_get_by_ofname(char *ofname, struct udevice *dev)
>> +{
>> +       int offset = fdt_path_offset(gd->fdt_blob, ofname);
>> +
>> +       device_get_global_by_of_offset(offset, &dev);
>> +}
>> +
>>  fdt_addr_t dev_get_addr_index(struct udevice *dev, int index)
>>  {
>>  #if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)
>> diff --git a/include/dm/device.h b/include/dm/device.h
>> index 9948bd4..402482c 100644
>> --- a/include/dm/device.h
>> +++ b/include/dm/device.h
>> @@ -340,6 +340,14 @@ enum uclass_id device_get_uclass_id(struct udevice
>> *dev);
>>  const char *dev_get_uclass_name(struct udevice *dev);
>>
>>  /**
>> + * dev_get_by_ofname() - find a device via its device tree path
>> + *
>> + * @ofname: Device tree path to use ("/path1/path2/...")
>> + * @dev:    The found device or NULL
>> + */
>> +void dev_get_by_ofname(char *ofname, struct udevice *dev);
>
>
> I'm not 100% sure if the function naming is perfect here. Usually
> these dev_get_xxx function work on a "dev" provided by the caller
> and return something else (addr, size). The functions returning a
> "device" are called device_get_xxx. And perhaps its also better stick with
> using "struct udevice **devp" as parameter for
> consistency as the other device_ functions do.
>
> Simon, what do you think?

Agreed.

Also I'm not sure we should be hunting around a path in the DT.
Shouldn't we use compatible strings?

Regards,
Simon

^ permalink raw reply	[flat|nested] 55+ messages in thread

* [U-Boot] [PATCH v2 16/18] arm: mvebu: Implement secure boot
  2017-01-11 15:01 ` [U-Boot] [PATCH v2 16/18] arm: mvebu: Implement secure boot Mario Six
  2017-01-18 16:58   ` Stefan Roese
@ 2017-01-19 13:57   ` Simon Glass
  2017-02-01 11:42   ` Stefan Roese
  2 siblings, 0 replies; 55+ messages in thread
From: Simon Glass @ 2017-01-19 13:57 UTC (permalink / raw)
  To: u-boot

On 11 January 2017 at 08:01, Mario Six <mario.six@gdsys.cc> wrote:
> The patch implements secure booting for the mvebu architecture.
>
> This includes:
> - The addition of secure headers and all needed signatures and keys in
>   mkimage
> - Commands capable of writing the board's efuses to both write the
>   needed cryptographic data and enable the secure booting mechanism
> - The creation of convenience text files containing the necessary
>   commands to write the efuses
>
> The KAK and CSK keys are expected to reside in the files kwb_kak.key and
> kwb_csk.key (OpenSSL 2048 bit private keys) in the top-level directory.
>
> Signed-off-by: Reinhard Pfau <reinhard.pfau@gdsys.cc>
> Signed-off-by: Mario Six <mario.six@gdsys.cc>
> ---
> Changes in v2:
>
> * Added help text for MVEBU_EFUSE
> * Removed superfluous defined(CONFIG_MVEBU_EFUSE) from
>   arch/arm/mach-mvebu/Makefile
> * Rewrote disable_efuse_program to use clrbits_le32
> * Remove superfluous blank lines from arch/arm/mach-mvebu/include/mach/efuse.h
> ---
>  Makefile                                 |   3 +-
>  arch/arm/mach-mvebu/Kconfig              |  35 ++
>  arch/arm/mach-mvebu/Makefile             |   1 +
>  arch/arm/mach-mvebu/efuse.c              | 264 +++++++++++
>  arch/arm/mach-mvebu/include/mach/cpu.h   |   2 +
>  arch/arm/mach-mvebu/include/mach/efuse.h |  69 +++
>  doc/README.armada-secureboot             | 373 ++++++++++++++++
>  tools/Makefile                           |   6 +-
>  tools/kwbimage.c                         | 744 ++++++++++++++++++++++++++++++-
>  tools/kwbimage.h                         |  37 ++
>  10 files changed, 1526 insertions(+), 8 deletions(-)
>  create mode 100644 arch/arm/mach-mvebu/efuse.c
>  create mode 100644 arch/arm/mach-mvebu/include/mach/efuse.h
>  create mode 100644 doc/README.armada-secureboot
>

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

^ permalink raw reply	[flat|nested] 55+ messages in thread

* [U-Boot] [PATCH v2 01/18] pci: mvebu: Fix Armada 38x support
  2017-01-11 15:00 ` [U-Boot] [PATCH v2 01/18] pci: mvebu: Fix Armada 38x support Mario Six
  2017-01-18 15:56   ` Stefan Roese
@ 2017-02-01 11:40   ` Stefan Roese
  1 sibling, 0 replies; 55+ messages in thread
From: Stefan Roese @ 2017-02-01 11:40 UTC (permalink / raw)
  To: u-boot

On 11.01.2017 16:00, Mario Six wrote:
> From: Dirk Eibach <dirk.eibach@gdsys.cc>
>
> Armada 38x has four PCI ports, not three.
>
> The optimization in pci_init_board() seems to assume that every port has
> three lanes. This is obviously wrong, and breaks support for Armada 38x.
>
> Signed-off-by: Dirk Eibach <dirk.eibach@gdsys.cc>
> Signed-off-by: Mario Six <mario.six@gdsys.cc>

Applied to u-boot-marvell/master

Thanks,
Stefan

^ permalink raw reply	[flat|nested] 55+ messages in thread

* [U-Boot] [PATCH v2 02/18] net: phy: Support Marvell 88E1680
  2017-01-11 15:00 ` [U-Boot] [PATCH v2 02/18] net: phy: Support Marvell 88E1680 Mario Six
  2017-01-18 15:57   ` Stefan Roese
  2017-01-18 22:48   ` Joe Hershberger
@ 2017-02-01 11:40   ` Stefan Roese
  2 siblings, 0 replies; 55+ messages in thread
From: Stefan Roese @ 2017-02-01 11:40 UTC (permalink / raw)
  To: u-boot

On 11.01.2017 16:00, Mario Six wrote:
> From: Dirk Eibach <dirk.eibach@gdsys.cc>
>
> Add support for Marvell 88E1680 Integrated Octal
> 10/100/1000 Mbps Energy Efficient Ethernet Transceiver.
>
> Signed-off-by: Dirk Eibach <dirk.eibach@gdsys.cc>
> Signed-off-by: Mario Six <mario.six@gdsys.cc>
> ---
> Changes in v2:
>
> * Switched to usage of pre-defined constant names where possible
> * Added error handling for genphy_config_aneg call

Applied to u-boot-marvell/master

Thanks,
Stefan

^ permalink raw reply	[flat|nested] 55+ messages in thread

* [U-Boot] [PATCH v2 03/18] mvebu: Add board_pex_config()
  2017-01-11 15:00 ` [U-Boot] [PATCH v2 03/18] mvebu: Add board_pex_config() Mario Six
  2017-01-18 15:58   ` Stefan Roese
@ 2017-02-01 11:40   ` Stefan Roese
  1 sibling, 0 replies; 55+ messages in thread
From: Stefan Roese @ 2017-02-01 11:40 UTC (permalink / raw)
  To: u-boot

On 11.01.2017 16:00, Mario Six wrote:
> Allow boards to do some initialization when PCIe comes up.
>
> Signed-off-by: Dirk Eibach <dirk.eibach@gdsys.cc>
> Signed-off-by: Mario Six <mario.six@gdsys.cc>
> ---
> Changes in v2:
>
> * Switched usage of __attribute(...) to __weak to simplify weak function
>   declaration

Applied to u-boot-marvell/master

Thanks,
Stefan

^ permalink raw reply	[flat|nested] 55+ messages in thread

* [U-Boot] [PATCH v2 04/18] arm: mvebu: spl.c: Remove useless gd declaration
  2017-01-11 15:00 ` [U-Boot] [PATCH v2 04/18] arm: mvebu: spl.c: Remove useless gd declaration Mario Six
  2017-01-18 15:58   ` Stefan Roese
@ 2017-02-01 11:40   ` Stefan Roese
  1 sibling, 0 replies; 55+ messages in thread
From: Stefan Roese @ 2017-02-01 11:40 UTC (permalink / raw)
  To: u-boot

On 11.01.2017 16:00, Mario Six wrote:
> From: Reinhard Pfau <pfau@gdsys.de>
>
> ddaa905 ("arm: mvebu: Add DM (driver model) support") removed the
> assignment of the gd pointer, but kept the (now superfluous) declaration
> of the gd pointer.
>
> Remove this declaration.
>
> Signed-off-by: Reinhard Pfau <pfau@gdsys.de>
> ---
> Changes in v2:
>
> None

Applied to u-boot-marvell/master

Thanks,
Stefan

^ permalink raw reply	[flat|nested] 55+ messages in thread

* [U-Boot] [PATCH v2 06/18] lib: tpm: Add command to flush resources
  2017-01-11 15:00 ` [U-Boot] [PATCH v2 06/18] lib: tpm: Add command to flush resources Mario Six
  2017-01-18 16:07   ` Stefan Roese
  2017-01-19 13:57   ` Simon Glass
@ 2017-02-01 11:41   ` Stefan Roese
  2 siblings, 0 replies; 55+ messages in thread
From: Stefan Roese @ 2017-02-01 11:41 UTC (permalink / raw)
  To: u-boot

On 11.01.2017 16:00, Mario Six wrote:
> This patch adds a function to the TPM library, which allows U-Boot to
> flush resources, e.g. keys, from the TPM.
>
> Signed-off-by: Mario Six <mario.six@gdsys.cc>
> ---
> Changes in v2:
>
> * Added U-Boot command for resource flushing ("tpm flush"), and made the
>   command and the library function deactivate-able via config

Applied to u-boot-marvell/master

Thanks,
Stefan

^ permalink raw reply	[flat|nested] 55+ messages in thread

* [U-Boot] [PATCH v2 09/18] tools: kwbimage: Fix dest addr
  2017-01-11 15:00 ` [U-Boot] [PATCH v2 09/18] tools: kwbimage: Fix dest addr Mario Six
  2017-01-18 16:36   ` Stefan Roese
@ 2017-02-01 11:41   ` Stefan Roese
  1 sibling, 0 replies; 55+ messages in thread
From: Stefan Roese @ 2017-02-01 11:41 UTC (permalink / raw)
  To: u-boot

On 11.01.2017 16:00, Mario Six wrote:
> To enable secure boot, we need to jump back into the BootROM to continue
> the SoC's boot process instead of letting the SPL load and run the main
> U-Boot image.
>
> But, since the u-boot-spl.img (including the 64 byte header) is loaded
> by the SoC as the main image, we need to compensate for the header
> length to get a correct entry point.
>
> Thus, we subtract the header size from the destination address, so that
> the execution address points at the actual entry point of the image.
>
> The current boards ignore both parameters anyway, so this change shouldn't
> concern them.
>
> Signed-off-by: Mario Six <mario.six@gdsys.cc>
> ---
> Changes in v2:
>
> None

Applied to u-boot-marvell/master

Thanks,
Stefan

^ permalink raw reply	[flat|nested] 55+ messages in thread

* [U-Boot] [PATCH v2 10/18] tools: kwbimage: Fix style violations
  2017-01-11 15:00 ` [U-Boot] [PATCH v2 10/18] tools: kwbimage: Fix style violations Mario Six
  2017-01-18 16:37   ` Stefan Roese
@ 2017-02-01 11:41   ` Stefan Roese
  1 sibling, 0 replies; 55+ messages in thread
From: Stefan Roese @ 2017-02-01 11:41 UTC (permalink / raw)
  To: u-boot

On 11.01.2017 16:00, Mario Six wrote:
> Fix some style violations:
>
> - nine instances of missing blank lines after declarations
> - one overly long line
> - one split string (which also rewords an error message more concisely)
> - two superfluous else
>
> Signed-off-by: Mario Six <mario.six@gdsys.cc>
> ---
> Changes in v2:
>
> None

Applied to u-boot-marvell/master

Thanks,
Stefan

^ permalink raw reply	[flat|nested] 55+ messages in thread

* [U-Boot] [PATCH v2 11/18] tools: kwbimage: Fix arithmetic with void pointers
  2017-01-11 15:00 ` [U-Boot] [PATCH v2 11/18] tools: kwbimage: Fix arithmetic with void pointers Mario Six
  2017-01-18 16:38   ` Stefan Roese
@ 2017-02-01 11:41   ` Stefan Roese
  1 sibling, 0 replies; 55+ messages in thread
From: Stefan Roese @ 2017-02-01 11:41 UTC (permalink / raw)
  To: u-boot

On 11.01.2017 16:00, Mario Six wrote:
> Arithmetic with void pointers, e.g. a - b where both a and b are void
> pointers, is undefined in the C standard. Since we are operating with
> byte data here, we switch the void pointers to uint8_t pointers, and add
> the necessary casts.
>
> Signed-off-by: Mario Six <mario.six@gdsys.cc>
> ---
> Changes in v2:
>
> None

Applied to u-boot-marvell/master

Thanks,
Stefan

^ permalink raw reply	[flat|nested] 55+ messages in thread

* [U-Boot] [PATCH v2 12/18] tools: kwbimage: Reduce scope of variables
  2017-01-11 15:00 ` [U-Boot] [PATCH v2 12/18] tools: kwbimage: Reduce scope of variables Mario Six
  2017-01-18 16:39   ` Stefan Roese
@ 2017-02-01 11:41   ` Stefan Roese
  1 sibling, 0 replies; 55+ messages in thread
From: Stefan Roese @ 2017-02-01 11:41 UTC (permalink / raw)
  To: u-boot

On 11.01.2017 16:00, Mario Six wrote:
> This patch reduces the scope of some variables.
>
> Signed-off-by: Mario Six <mario.six@gdsys.cc>
> ---
> Changes in v2:
>
> None

Applied to u-boot-marvell/master

Thanks,
Stefan

^ permalink raw reply	[flat|nested] 55+ messages in thread

* [U-Boot] [PATCH v2 13/18] tools: kwbimage: Remove unused parameter
  2017-01-11 15:00 ` [U-Boot] [PATCH v2 13/18] tools: kwbimage: Remove unused parameter Mario Six
  2017-01-18 16:39   ` Stefan Roese
@ 2017-02-01 11:42   ` Stefan Roese
  1 sibling, 0 replies; 55+ messages in thread
From: Stefan Roese @ 2017-02-01 11:42 UTC (permalink / raw)
  To: u-boot

On 11.01.2017 16:00, Mario Six wrote:
> The parameter 'params' of the image_headersz_v1 function is never used
> by the function.
>
> Hence, remove it.
>
> Signed-off-by: Mario Six <mario.six@gdsys.cc>
> ---
> Changes in v2:
>
> None

Applied to u-boot-marvell/master

Thanks,
Stefan

^ permalink raw reply	[flat|nested] 55+ messages in thread

* [U-Boot] [PATCH v2 14/18] tools: kwbimage: Factor out add_binary_header_v1
  2017-01-11 15:00 ` [U-Boot] [PATCH v2 14/18] tools: kwbimage: Factor out add_binary_header_v1 Mario Six
  2017-01-18 16:40   ` Stefan Roese
@ 2017-02-01 11:42   ` Stefan Roese
  1 sibling, 0 replies; 55+ messages in thread
From: Stefan Roese @ 2017-02-01 11:42 UTC (permalink / raw)
  To: u-boot

On 11.01.2017 16:00, Mario Six wrote:
> In preparation of adding the creation of secure headers, we factor the
> add_binary_header_v1 function out of the image_create_v1 function.
>
> Signed-off-by: Mario Six <mario.six@gdsys.cc>
> ---
> Changes in v2:
>
> None

Applied to u-boot-marvell/master

Thanks,
Stefan

^ permalink raw reply	[flat|nested] 55+ messages in thread

* [U-Boot] [PATCH v2 15/18] tools: kwbimage: Refactor line parsing and fix error
  2017-01-11 15:00 ` [U-Boot] [PATCH v2 15/18] tools: kwbimage: Refactor line parsing and fix error Mario Six
  2017-01-18 16:47   ` Stefan Roese
@ 2017-02-01 11:42   ` Stefan Roese
  1 sibling, 0 replies; 55+ messages in thread
From: Stefan Roese @ 2017-02-01 11:42 UTC (permalink / raw)
  To: u-boot

On 11.01.2017 16:00, Mario Six wrote:
> The function image_create_config_parse_oneline is pretty complex, and
> since more parameters will be added to support secure booting, we
> refactor the function to make it more readable.
>
> Also, when a line contained just a keyword without any parameters,
> strtok_r returned NULL, which was then indiscriminately fed into atoi,
> causing a segfault. To correct this, we add a NULL check before feeding
> the extracted token to atoi, and print an error message in case the
> token is NULL.
>
> Signed-off-by: Mario Six <mario.six@gdsys.cc>
> ---
> Changes in v2:
>
> None

Applied to u-boot-marvell/master

Thanks,
Stefan

^ permalink raw reply	[flat|nested] 55+ messages in thread

* [U-Boot] [PATCH v2 16/18] arm: mvebu: Implement secure boot
  2017-01-11 15:01 ` [U-Boot] [PATCH v2 16/18] arm: mvebu: Implement secure boot Mario Six
  2017-01-18 16:58   ` Stefan Roese
  2017-01-19 13:57   ` Simon Glass
@ 2017-02-01 11:42   ` Stefan Roese
  2 siblings, 0 replies; 55+ messages in thread
From: Stefan Roese @ 2017-02-01 11:42 UTC (permalink / raw)
  To: u-boot

On 11.01.2017 16:01, Mario Six wrote:
> The patch implements secure booting for the mvebu architecture.
>
> This includes:
> - The addition of secure headers and all needed signatures and keys in
>   mkimage
> - Commands capable of writing the board's efuses to both write the
>   needed cryptographic data and enable the secure booting mechanism
> - The creation of convenience text files containing the necessary
>   commands to write the efuses
>
> The KAK and CSK keys are expected to reside in the files kwb_kak.key and
> kwb_csk.key (OpenSSL 2048 bit private keys) in the top-level directory.
>
> Signed-off-by: Reinhard Pfau <reinhard.pfau@gdsys.cc>
> Signed-off-by: Mario Six <mario.six@gdsys.cc>
> ---
> Changes in v2:
>
> * Added help text for MVEBU_EFUSE
> * Removed superfluous defined(CONFIG_MVEBU_EFUSE) from
>   arch/arm/mach-mvebu/Makefile
> * Rewrote disable_efuse_program to use clrbits_le32
> * Remove superfluous blank lines from arch/arm/mach-mvebu/include/mach/efuse.h

Applied to u-boot-marvell/master

Thanks,
Stefan

^ permalink raw reply	[flat|nested] 55+ messages in thread

end of thread, other threads:[~2017-02-01 11:42 UTC | newest]

Thread overview: 55+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-01-11 15:00 [U-Boot] [PATCH v2 00/18] arm: mvebu: Add gdsys ControlCenter-Compact board Mario Six
2017-01-11 15:00 ` [U-Boot] [PATCH v2 01/18] pci: mvebu: Fix Armada 38x support Mario Six
2017-01-18 15:56   ` Stefan Roese
2017-02-01 11:40   ` Stefan Roese
2017-01-11 15:00 ` [U-Boot] [PATCH v2 02/18] net: phy: Support Marvell 88E1680 Mario Six
2017-01-18 15:57   ` Stefan Roese
2017-01-18 22:45     ` Joe Hershberger
2017-01-18 22:48   ` Joe Hershberger
2017-02-01 11:40   ` Stefan Roese
2017-01-11 15:00 ` [U-Boot] [PATCH v2 03/18] mvebu: Add board_pex_config() Mario Six
2017-01-18 15:58   ` Stefan Roese
2017-02-01 11:40   ` Stefan Roese
2017-01-11 15:00 ` [U-Boot] [PATCH v2 04/18] arm: mvebu: spl.c: Remove useless gd declaration Mario Six
2017-01-18 15:58   ` Stefan Roese
2017-02-01 11:40   ` Stefan Roese
2017-01-11 15:00 ` [U-Boot] [PATCH v2 05/18] dm: Add callback to modify the device tree Mario Six
2017-01-18 16:03   ` Stefan Roese
2017-01-11 15:00 ` [U-Boot] [PATCH v2 06/18] lib: tpm: Add command to flush resources Mario Six
2017-01-18 16:07   ` Stefan Roese
2017-01-19 13:57   ` Simon Glass
2017-02-01 11:41   ` Stefan Roese
2017-01-11 15:00 ` [U-Boot] [PATCH v2 07/18] core: device: Add dev_get_by_ofname function Mario Six
2017-01-18 16:23   ` Stefan Roese
2017-01-19 13:57     ` Simon Glass
2017-01-11 15:00 ` [U-Boot] [PATCH v2 08/18] gpio: Add gpio_request_simple function Mario Six
2017-01-18 16:34   ` Stefan Roese
2017-01-11 15:00 ` [U-Boot] [PATCH v2 09/18] tools: kwbimage: Fix dest addr Mario Six
2017-01-18 16:36   ` Stefan Roese
2017-02-01 11:41   ` Stefan Roese
2017-01-11 15:00 ` [U-Boot] [PATCH v2 10/18] tools: kwbimage: Fix style violations Mario Six
2017-01-18 16:37   ` Stefan Roese
2017-02-01 11:41   ` Stefan Roese
2017-01-11 15:00 ` [U-Boot] [PATCH v2 11/18] tools: kwbimage: Fix arithmetic with void pointers Mario Six
2017-01-18 16:38   ` Stefan Roese
2017-02-01 11:41   ` Stefan Roese
2017-01-11 15:00 ` [U-Boot] [PATCH v2 12/18] tools: kwbimage: Reduce scope of variables Mario Six
2017-01-18 16:39   ` Stefan Roese
2017-02-01 11:41   ` Stefan Roese
2017-01-11 15:00 ` [U-Boot] [PATCH v2 13/18] tools: kwbimage: Remove unused parameter Mario Six
2017-01-18 16:39   ` Stefan Roese
2017-02-01 11:42   ` Stefan Roese
2017-01-11 15:00 ` [U-Boot] [PATCH v2 14/18] tools: kwbimage: Factor out add_binary_header_v1 Mario Six
2017-01-18 16:40   ` Stefan Roese
2017-02-01 11:42   ` Stefan Roese
2017-01-11 15:00 ` [U-Boot] [PATCH v2 15/18] tools: kwbimage: Refactor line parsing and fix error Mario Six
2017-01-18 16:47   ` Stefan Roese
2017-02-01 11:42   ` Stefan Roese
2017-01-11 15:01 ` [U-Boot] [PATCH v2 16/18] arm: mvebu: Implement secure boot Mario Six
2017-01-18 16:58   ` Stefan Roese
2017-01-19 13:57   ` Simon Glass
2017-02-01 11:42   ` Stefan Roese
2017-01-11 15:01 ` [U-Boot] [PATCH v2 17/18] arm: mvebu: Add gdsys ControlCenter-Compact board Mario Six
2017-01-18 17:09   ` Stefan Roese
2017-01-11 15:01 ` [U-Boot] [PATCH v2 18/18] controlcenterdc: Make secure boot available Mario Six
2017-01-18 17:10   ` Stefan Roese

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.