All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH v6 0/5] Add gdsys ControlCenter Digital board
@ 2013-06-12  8:08 dirk.eibach at gdsys.cc
  2013-06-12  8:08 ` [U-Boot] [PATCH v6 1/5] tpm: add AUTH1 cmds for LoadKey2 and GetPubKey dirk.eibach at gdsys.cc
                   ` (4 more replies)
  0 siblings, 5 replies; 12+ messages in thread
From: dirk.eibach at gdsys.cc @ 2013-06-12  8:08 UTC (permalink / raw)
  To: u-boot

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



Changes in v6:
- Add CONFIG_PCI_INDIRECT_BRIDGE to controlcenterd.h
- Add MAINTAINERS entry
- drop "mpc85xx: Add CONFIG_RELEASE_CORE0_ONLY" and use mp_holdoff instead
- rename CONFIG_ATMEL_TWI_TPM to CONFIG_TPM_ATMEL_TWI
- rename drivers/tpm/atmel_twi_tpm.c to drivers/tpm/tpm_atmel_twi.c
- replace DEBUG_ATMEL_TWI_TPM, simply use DEBUG
- sort drivers/tpm/Makefile
- timeout on waiting for TPM reply

Changes in v5:
- avoid probing dp501 i2c bridge addresses
- fix i2c_probe

Changes in v4:
- consider CONFIG_CMD_BOOTM for all architectures

Changes in v3:
- fix email addresses

Changes in v2:
- configuration for SPI builds was missing
- replace some numeric constants with named constants
- style fixes (as shown by checkpatch.pl) in common/cmd_tpm.c and lib/tpm.c
- whitespace fixes

Dirk Eibach (3):
  Add Atmel I2C tpm
  Build arch/$ARCH/lib/bootm.o depending on CONFIG_CMD_BOOTM
  mpc85xx: Add gdsys ControlCenter Digital board

Reinhard Pfau (2):
  tpm: add AUTH1 cmds for LoadKey2 and GetPubKey
  i2c: fsl_i2c: i2c_read(): dont try to write address w/ alen=0

 .checkpatch.conf                      |    4 +-
 MAINTAINERS                           |    3 +-
 README                                |   17 +
 arch/arm/lib/Makefile                 |    2 +-
 arch/avr32/lib/Makefile               |    2 +-
 arch/m68k/lib/Makefile                |    2 +-
 arch/microblaze/lib/Makefile          |    2 +-
 arch/mips/lib/Makefile                |    4 +-
 arch/nds32/lib/Makefile               |    3 +-
 arch/nios2/lib/Makefile               |    2 +-
 arch/openrisc/lib/Makefile            |    2 +-
 arch/powerpc/lib/Makefile             |    2 +-
 arch/sh/lib/Makefile                  |    2 +-
 arch/sparc/lib/Makefile               |    3 +-
 arch/x86/lib/Makefile                 |    2 +-
 board/gdsys/common/Makefile           |    1 +
 board/gdsys/common/dp501.c            |  107 +++
 board/gdsys/common/dp501.h            |   30 +
 board/gdsys/p1022/Makefile            |   37 +
 board/gdsys/p1022/controlcenterd-id.c | 1205 +++++++++++++++++++++++++++++++++
 board/gdsys/p1022/controlcenterd-id.h |   29 +
 board/gdsys/p1022/controlcenterd.c    |  447 ++++++++++++
 board/gdsys/p1022/ddr.c               |   71 ++
 board/gdsys/p1022/diu.c               |   87 +++
 board/gdsys/p1022/law.c               |   20 +
 board/gdsys/p1022/sdhc_boot.c         |   63 ++
 board/gdsys/p1022/tlb.c               |   77 +++
 boards.cfg                            |    7 +
 common/cmd_tpm.c                      |  100 +++
 drivers/i2c/fsl_i2c.c                 |    9 +-
 drivers/tpm/Makefile                  |    1 +
 drivers/tpm/tpm_atmel_twi.c           |  121 ++++
 include/configs/controlcenterd.h      |  528 +++++++++++++++
 include/tpm.h                         |  174 +++++
 lib/tpm.c                             |  351 +++++++++-
 35 files changed, 3497 insertions(+), 20 deletions(-)
 create mode 100644 board/gdsys/common/dp501.c
 create mode 100644 board/gdsys/common/dp501.h
 create mode 100644 board/gdsys/p1022/Makefile
 create mode 100644 board/gdsys/p1022/controlcenterd-id.c
 create mode 100644 board/gdsys/p1022/controlcenterd-id.h
 create mode 100644 board/gdsys/p1022/controlcenterd.c
 create mode 100644 board/gdsys/p1022/ddr.c
 create mode 100644 board/gdsys/p1022/diu.c
 create mode 100644 board/gdsys/p1022/law.c
 create mode 100644 board/gdsys/p1022/sdhc_boot.c
 create mode 100644 board/gdsys/p1022/tlb.c
 create mode 100644 drivers/tpm/tpm_atmel_twi.c
 create mode 100644 include/configs/controlcenterd.h

-- 
1.8.3

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

* [U-Boot] [PATCH v6 1/5] tpm: add AUTH1 cmds for LoadKey2 and GetPubKey
  2013-06-12  8:08 [U-Boot] [PATCH v6 0/5] Add gdsys ControlCenter Digital board dirk.eibach at gdsys.cc
@ 2013-06-12  8:08 ` dirk.eibach at gdsys.cc
  2013-06-12 21:29   ` Che-liang Chiou
  2013-06-12  8:08 ` [U-Boot] [PATCH v6 2/5] i2c: fsl_i2c: i2c_read(): dont try to write address w/ alen=0 dirk.eibach at gdsys.cc
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 12+ messages in thread
From: dirk.eibach at gdsys.cc @ 2013-06-12  8:08 UTC (permalink / raw)
  To: u-boot

From: Reinhard Pfau <pfau@gdsys.de>

Extend the tpm library with support for single authorized (AUTH1) commands
as specified in the TCG Main Specification 1.2. (The internally used helper
functions are implemented in a way that they could also be used for double
authorized commands if someone needs it.)

Provide enums with the return codes from the TCG Main specification.

For now only a single OIAP session is supported.

OIAP authorized version of the commands TPM_LoadKey2 and TPM_GetPubKey are
provided. Both features are available using the 'tpm' command, too.

Authorized commands are enabled with CONFIG_TPM_AUTH_SESSIONS. (Note that
this also requires CONFIG_SHA1 to be enabled.)

Signed-off-by: Reinhard Pfau <reinhard.pfau@gdsys.cc>


Signed-off-by: Dirk Eibach <dirk.eibach@gdsys.cc>
---
Changes in v6: None
Changes in v5: None
Changes in v4: None
Changes in v3:
- fix email addresses

Changes in v2:
- replace some numeric constants with named constants
- style fixes (as shown by checkpatch.pl) in common/cmd_tpm.c and lib/tpm.c

 README           |  14 +++
 common/cmd_tpm.c | 100 ++++++++++++++++
 include/tpm.h    | 174 +++++++++++++++++++++++++++
 lib/tpm.c        | 351 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 4 files changed, 638 insertions(+), 1 deletion(-)

diff --git a/README b/README
index 33bda8c..3d1fa08 100644
--- a/README
+++ b/README
@@ -1234,6 +1234,20 @@ The following options need to be configured:
 			to. Contemporary x86 systems usually map it at
 			0xfed40000.
 
+		CONFIG_CMD_TPM
+		Add tpm monitor functions.
+		Requires CONFIG_TPM. If CONFIG_TPM_AUTH_SESSIONS is set, also
+		provides monitor access to authorized functions.
+
+		CONFIG_TPM
+		Define this to enable the TPM support library which provides
+		functional interfaces to some TPM commands.
+		Requires support for a TPM device.
+
+		CONFIG_TPM_AUTH_SESSIONS
+		Define this to enable authorized functions in the TPM library.
+		Requires CONFIG_TPM and CONFIG_SHA1.
+
 - USB Support:
 		At the moment only the UHCI host controller is
 		supported (PIP405, MIP405, MPC5200); define
diff --git a/common/cmd_tpm.c b/common/cmd_tpm.c
index 46fae18..c34000a 100644
--- a/common/cmd_tpm.c
+++ b/common/cmd_tpm.c
@@ -27,6 +27,13 @@
 #include <asm/unaligned.h>
 #include <linux/string.h>
 
+/* Useful constants */
+enum {
+	DIGEST_LENGTH		= 20,
+	/* max lengths, valid for RSA keys <= 2048 bits */
+	TPM_PUBKEY_MAX_LENGTH	= 288,
+};
+
 /**
  * Print a byte string in hexdecimal format, 16-bytes per line.
  *
@@ -546,6 +553,72 @@ static int do_tpm_nv_write(cmd_tbl_t *cmdtp, int flag,
 	return convert_return_code(err);
 }
 
+#ifdef CONFIG_TPM_AUTH_SESSIONS
+
+static int do_tpm_oiap(cmd_tbl_t *cmdtp, int flag,
+		int argc, char * const argv[])
+{
+	uint32_t auth_handle, err;
+
+	err = tpm_oiap(&auth_handle);
+
+	return convert_return_code(err);
+}
+
+static int do_tpm_load_key2_oiap(cmd_tbl_t *cmdtp, int flag,
+		int argc, char * const argv[])
+{
+	uint32_t parent_handle, key_len, key_handle, err;
+	uint8_t usage_auth[DIGEST_LENGTH];
+	void *key;
+
+	if (argc < 5)
+		return CMD_RET_USAGE;
+
+	parent_handle = simple_strtoul(argv[1], NULL, 0);
+	key = (void *)simple_strtoul(argv[2], NULL, 0);
+	key_len = simple_strtoul(argv[3], NULL, 0);
+	if (strlen(argv[4]) != 2 * DIGEST_LENGTH)
+		return CMD_RET_FAILURE;
+	parse_byte_string(argv[4], usage_auth, NULL);
+
+	err = tpm_load_key2_oiap(parent_handle, key, key_len, usage_auth,
+			&key_handle);
+	if (!err)
+		printf("Key handle is 0x%x\n", key_handle);
+
+	return convert_return_code(err);
+}
+
+static int do_tpm_get_pub_key_oiap(cmd_tbl_t *cmdtp, int flag,
+		int argc, char * const argv[])
+{
+	uint32_t key_handle, err;
+	uint8_t usage_auth[DIGEST_LENGTH];
+	uint8_t pub_key_buffer[TPM_PUBKEY_MAX_LENGTH];
+	size_t pub_key_len = sizeof(pub_key_buffer);
+
+	if (argc < 3)
+		return CMD_RET_USAGE;
+
+	key_handle = simple_strtoul(argv[1], NULL, 0);
+	if (strlen(argv[2]) != 2 * DIGEST_LENGTH)
+		return CMD_RET_FAILURE;
+	parse_byte_string(argv[2], usage_auth, NULL);
+
+	err = tpm_get_pub_key_oiap(key_handle, usage_auth,
+			pub_key_buffer, &pub_key_len);
+	if (!err) {
+		printf("dump of received pub key structure:\n");
+		print_byte_string(pub_key_buffer, pub_key_len);
+	}
+	return convert_return_code(err);
+}
+
+TPM_COMMAND_NO_ARG(tpm_end_oiap)
+
+#endif /* CONFIG_TPM_AUTH_SESSIONS */
+
 #define MAKE_TPM_CMD_ENTRY(cmd) \
 	U_BOOT_CMD_MKENT(cmd, 0, 1, do_tpm_ ## cmd, "", "")
 
@@ -590,6 +663,16 @@ static cmd_tbl_t tpm_commands[] = {
 			do_tpm_nv_read, "", ""),
 	U_BOOT_CMD_MKENT(nv_write, 0, 1,
 			do_tpm_nv_write, "", ""),
+#ifdef CONFIG_TPM_AUTH_SESSIONS
+	U_BOOT_CMD_MKENT(oiap, 0, 1,
+			 do_tpm_oiap, "", ""),
+	U_BOOT_CMD_MKENT(end_oiap, 0, 1,
+			 do_tpm_end_oiap, "", ""),
+	U_BOOT_CMD_MKENT(load_key2_oiap, 0, 1,
+			 do_tpm_load_key2_oiap, "", ""),
+	U_BOOT_CMD_MKENT(get_pub_key_oiap, 0, 1,
+			 do_tpm_get_pub_key_oiap, "", ""),
+#endif /* CONFIG_TPM_AUTH_SESSIONS */
 };
 
 static int do_tpm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
@@ -638,6 +721,16 @@ 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_AUTH_SESSIONS
+"Storage functions\n"
+"  loadkey2_oiap parent_handle key_addr key_len usage_auth\n"
+"    - loads a key data from memory address <key_addr>, <key_len> bytes\n"
+"      into TPM using the parent key <parent_handle> with authorization\n"
+"      <usage_auth> (20 bytes hex string).\n"
+"  get_pub_key_oiap key_handle usage_auth\n"
+"    - get the public key portion of a loaded key <key_handle> using\n"
+"      authorization <usage auth> (20 bytes hex string)\n"
+#endif /* CONFIG_TPM_AUTH_SESSIONS */
 "Endorsement Key Handling Commands:\n"
 "  read_pubek addr count\n"
 "    - Read <count> bytes of the public endorsement key to memory\n"
@@ -648,6 +741,13 @@ U_BOOT_CMD(tpm, CONFIG_SYS_MAXARGS, 1, do_tpm,
 "      <digest_hex_string>\n"
 "  pcr_read index addr count\n"
 "    - Read <count> bytes from PCR <index> to memory address <addr>.\n"
+#ifdef CONFIG_TPM_AUTH_SESSIONS
+"Authorization Sessions\n"
+"  oiap\n"
+"    - setup an OIAP session\n"
+"  end_oiap\n"
+"    - terminates an active OIAP session\n"
+#endif /* CONFIG_TPM_AUTH_SESSIONS */
 "Non-volatile Storage Commands:\n"
 "  nv_define_space index permission size\n"
 "    - Establish a space at index <index> with <permission> of <size> bytes.\n"
diff --git a/include/tpm.h b/include/tpm.h
index 7219b73..5e9f832 100644
--- a/include/tpm.h
+++ b/include/tpm.h
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2013 The Chromium OS Authors.
+ * Coypright (c) 2013 Guntermann & Drunck GmbH
  *
  * See file CREDITS for list of people who contributed to this
  * project.
@@ -54,6 +55,120 @@ enum tpm_nv_index {
 };
 
 /**
+ * TPM return codes as defined in the TCG Main specification
+ * (TPM Main Part 2 Structures; Specification version 1.2)
+ */
+enum tpm_return_code {
+	TPM_BASE	= 0x00000000,
+	TPM_NON_FATAL	= 0x00000800,
+	TPM_SUCCESS	= TPM_BASE,
+	/* TPM-defined fatal error codes */
+	TPM_AUTHFAIL			= TPM_BASE +  1,
+	TPM_BADINDEX			= TPM_BASE +  2,
+	TPM_BAD_PARAMETER		= TPM_BASE +  3,
+	TPM_AUDITFAILURE		= TPM_BASE +  4,
+	TPM_CLEAR_DISABLED		= TPM_BASE +  5,
+	TPM_DEACTIVATED			= TPM_BASE +  6,
+	TPM_DISABLED			= TPM_BASE +  7,
+	TPM_DISABLED_CMD		= TPM_BASE +  8,
+	TPM_FAIL			= TPM_BASE +  9,
+	TPM_BAD_ORDINAL			= TPM_BASE + 10,
+	TPM_INSTALL_DISABLED		= TPM_BASE + 11,
+	TPM_INVALID_KEYHANDLE		= TPM_BASE + 12,
+	TPM_KEYNOTFOUND			= TPM_BASE + 13,
+	TPM_INAPPROPRIATE_ENC		= TPM_BASE + 14,
+	TPM_MIGRATE_FAIL		= TPM_BASE + 15,
+	TPM_INVALID_PCR_INFO		= TPM_BASE + 16,
+	TPM_NOSPACE			= TPM_BASE + 17,
+	TPM_NOSRK			= TPM_BASE + 18,
+	TPM_NOTSEALED_BLOB		= TPM_BASE + 19,
+	TPM_OWNER_SET			= TPM_BASE + 20,
+	TPM_RESOURCES			= TPM_BASE + 21,
+	TPM_SHORTRANDOM			= TPM_BASE + 22,
+	TPM_SIZE			= TPM_BASE + 23,
+	TPM_WRONGPCRVAL			= TPM_BASE + 24,
+	TPM_BAD_PARAM_SIZE		= TPM_BASE + 25,
+	TPM_SHA_THREAD			= TPM_BASE + 26,
+	TPM_SHA_ERROR			= TPM_BASE + 27,
+	TPM_FAILEDSELFTEST		= TPM_BASE + 28,
+	TPM_AUTH2FAIL			= TPM_BASE + 29,
+	TPM_BADTAG			= TPM_BASE + 30,
+	TPM_IOERROR			= TPM_BASE + 31,
+	TPM_ENCRYPT_ERROR		= TPM_BASE + 32,
+	TPM_DECRYPT_ERROR		= TPM_BASE + 33,
+	TPM_INVALID_AUTHHANDLE		= TPM_BASE + 34,
+	TPM_NO_ENDORSEMENT		= TPM_BASE + 35,
+	TPM_INVALID_KEYUSAGE		= TPM_BASE + 36,
+	TPM_WRONG_ENTITYTYPE		= TPM_BASE + 37,
+	TPM_INVALID_POSTINIT		= TPM_BASE + 38,
+	TPM_INAPPROPRIATE_SIG		= TPM_BASE + 39,
+	TPM_BAD_KEY_PROPERTY		= TPM_BASE + 40,
+	TPM_BAD_MIGRATION		= TPM_BASE + 41,
+	TPM_BAD_SCHEME			= TPM_BASE + 42,
+	TPM_BAD_DATASIZE		= TPM_BASE + 43,
+	TPM_BAD_MODE			= TPM_BASE + 44,
+	TPM_BAD_PRESENCE		= TPM_BASE + 45,
+	TPM_BAD_VERSION			= TPM_BASE + 46,
+	TPM_NO_WRAP_TRANSPORT		= TPM_BASE + 47,
+	TPM_AUDITFAIL_UNSUCCESSFUL	= TPM_BASE + 48,
+	TPM_AUDITFAIL_SUCCESSFUL	= TPM_BASE + 49,
+	TPM_NOTRESETABLE		= TPM_BASE + 50,
+	TPM_NOTLOCAL			= TPM_BASE + 51,
+	TPM_BAD_TYPE			= TPM_BASE + 52,
+	TPM_INVALID_RESOURCE		= TPM_BASE + 53,
+	TPM_NOTFIPS			= TPM_BASE + 54,
+	TPM_INVALID_FAMILY		= TPM_BASE + 55,
+	TPM_NO_NV_PERMISSION		= TPM_BASE + 56,
+	TPM_REQUIRES_SIGN		= TPM_BASE + 57,
+	TPM_KEY_NOTSUPPORTED		= TPM_BASE + 58,
+	TPM_AUTH_CONFLICT		= TPM_BASE + 59,
+	TPM_AREA_LOCKED			= TPM_BASE + 60,
+	TPM_BAD_LOCALITY		= TPM_BASE + 61,
+	TPM_READ_ONLY			= TPM_BASE + 62,
+	TPM_PER_NOWRITE			= TPM_BASE + 63,
+	TPM_FAMILY_COUNT		= TPM_BASE + 64,
+	TPM_WRITE_LOCKED		= TPM_BASE + 65,
+	TPM_BAD_ATTRIBUTES		= TPM_BASE + 66,
+	TPM_INVALID_STRUCTURE		= TPM_BASE + 67,
+	TPM_KEY_OWNER_CONTROL		= TPM_BASE + 68,
+	TPM_BAD_COUNTER			= TPM_BASE + 69,
+	TPM_NOT_FULLWRITE		= TPM_BASE + 70,
+	TPM_CONTEXT_GAP			= TPM_BASE + 71,
+	TPM_MAXNVWRITES			= TPM_BASE + 72,
+	TPM_NOOPERATOR			= TPM_BASE + 73,
+	TPM_RESOURCEMISSING		= TPM_BASE + 74,
+	TPM_DELEGATE_LOCK		= TPM_BASE + 75,
+	TPM_DELEGATE_FAMILY		= TPM_BASE + 76,
+	TPM_DELEGATE_ADMIN		= TPM_BASE + 77,
+	TPM_TRANSPORT_NOTEXCLUSIVE	= TPM_BASE + 78,
+	TPM_OWNER_CONTROL		= TPM_BASE + 79,
+	TPM_DAA_RESOURCES		= TPM_BASE + 80,
+	TPM_DAA_INPUT_DATA0		= TPM_BASE + 81,
+	TPM_DAA_INPUT_DATA1		= TPM_BASE + 82,
+	TPM_DAA_ISSUER_SETTINGS		= TPM_BASE + 83,
+	TPM_DAA_TPM_SETTINGS		= TPM_BASE + 84,
+	TPM_DAA_STAGE			= TPM_BASE + 85,
+	TPM_DAA_ISSUER_VALIDITY		= TPM_BASE + 86,
+	TPM_DAA_WRONG_W			= TPM_BASE + 87,
+	TPM_BAD_HANDLE			= TPM_BASE + 88,
+	TPM_BAD_DELEGATE		= TPM_BASE + 89,
+	TPM_BADCONTEXT			= TPM_BASE + 90,
+	TPM_TOOMANYCONTEXTS		= TPM_BASE + 91,
+	TPM_MA_TICKET_SIGNATURE		= TPM_BASE + 92,
+	TPM_MA_DESTINATION		= TPM_BASE + 93,
+	TPM_MA_SOURCE			= TPM_BASE + 94,
+	TPM_MA_AUTHORITY		= TPM_BASE + 95,
+	TPM_PERMANENTEK			= TPM_BASE + 97,
+	TPM_BAD_SIGNATURE		= TPM_BASE + 98,
+	TPM_NOCONTEXTSPACE		= TPM_BASE + 99,
+	/* TPM-defined non-fatal errors */
+	TPM_RETRY		= TPM_BASE + TPM_NON_FATAL,
+	TPM_NEEDS_SELFTEST	= TPM_BASE + TPM_NON_FATAL + 1,
+	TPM_DOING_SELFTEST	= TPM_BASE + TPM_NON_FATAL + 2,
+	TPM_DEFEND_LOCK_RUNNING	= TPM_BASE + TPM_NON_FATAL + 3,
+};
+
+/**
  * Initialize TPM device.  It must be called before any TPM commands.
  *
  * @return 0 on success, non-0 on error.
@@ -201,4 +316,63 @@ uint32_t tpm_physical_set_deactivated(uint8_t state);
 uint32_t tpm_get_capability(uint32_t cap_area, uint32_t sub_cap,
 		void *cap, size_t count);
 
+/**
+ * Issue a TPM_FlushSpecific command for a AUTH ressource.
+ *
+ * @param auth_handle	handle of the auth session
+ * @return return code of the operation
+ */
+uint32_t tpm_terminate_auth_session(uint32_t auth_handle);
+
+/**
+ * Issue a TPM_OIAP command to setup an object independant authorization
+ * session.
+ * Information about the session is stored internally.
+ * If there was already an OIAP session active it is terminated and a new
+ * session is set up.
+ *
+ * @param auth_handle	pointer to the (new) auth handle or NULL.
+ * @return return code of the operation
+ */
+uint32_t tpm_oiap(uint32_t *auth_handle);
+
+/**
+ * Ends an active OIAP session.
+ *
+ * @return return code of the operation
+ */
+uint32_t tpm_end_oiap(void);
+
+/**
+ * Issue a TPM_LoadKey2 (Auth1) command using an OIAP session for authenticating
+ * the usage of the parent key.
+ *
+ * @param parent_handle	handle of the parent key.
+ * @param key		pointer to the key structure (TPM_KEY or TPM_KEY12).
+ * @param key_length	size of the key structure
+ * @param parent_key_usage_auth	usage auth for the parent key
+ * @param key_handle	pointer to the key handle
+ * @return return code of the operation
+ */
+uint32_t tpm_load_key2_oiap(uint32_t parent_handle,
+		const void *key, size_t key_length,
+		const void *parent_key_usage_auth,
+		uint32_t *key_handle);
+
+/**
+ * Issue a TPM_GetPubKey (Auth1) command using an OIAP session for
+ * authenticating the usage of the key.
+ *
+ * @param key_handle	handle of the key
+ * @param usage_auth	usage auth for the key
+ * @param pubkey	pointer to the pub key buffer; may be NULL if the pubkey
+ *			should not be stored.
+ * @param pubkey_len	pointer to the pub key buffer len. On entry: the size of
+ *			the provided pubkey buffer. On successful exit: the size
+ *			of the stored TPM_PUBKEY structure (iff pubkey != NULL).
+ * @return return code of the operation
+ */
+uint32_t tpm_get_pub_key_oiap(uint32_t key_handle, const void *usage_auth,
+		void *pubkey, size_t *pubkey_len);
+
 #endif /* __TPM_H */
diff --git a/lib/tpm.c b/lib/tpm.c
index 42c9bea..f0b4f59 100644
--- a/lib/tpm.c
+++ b/lib/tpm.c
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2013 The Chromium OS Authors.
+ * Coypright (c) 2013 Guntermann & Drunck GmbH
  *
  * See file CREDITS for list of people who contributed to this
  * project.
@@ -22,6 +23,7 @@
 
 #include <common.h>
 #include <stdarg.h>
+#include <sha1.h>
 #include <tpm.h>
 #include <asm/unaligned.h>
 
@@ -35,8 +37,31 @@ enum {
 	TPM_REQUEST_HEADER_LENGTH	= 10,
 	TPM_RESPONSE_HEADER_LENGTH	= 10,
 	PCR_DIGEST_LENGTH		= 20,
+	DIGEST_LENGTH			= 20,
+	TPM_REQUEST_AUTH_LENGTH		= 45,
+	TPM_RESPONSE_AUTH_LENGTH	= 41,
+	/* some max lengths, valid for RSA keys <= 2048 bits */
+	TPM_KEY12_MAX_LENGTH		= 618,
+	TPM_PUBKEY_MAX_LENGTH		= 288,
 };
 
+#ifdef CONFIG_TPM_AUTH_SESSIONS
+
+#ifndef CONFIG_SHA1
+#error "TPM_AUTH_SESSIONS require SHA1 to be configured, too"
+#endif /* !CONFIG_SHA1 */
+
+struct session_data {
+	int		valid;
+	uint32_t	handle;
+	uint8_t		nonce_even[DIGEST_LENGTH];
+	uint8_t		nonce_odd[DIGEST_LENGTH];
+};
+
+static struct session_data oiap_session = {0, };
+
+#endif /* CONFIG_TPM_AUTH_SESSIONS */
+
 /**
  * Pack data into a byte string.  The data types are specified in
  * the format string: 'b' means unsigned byte, 'w' unsigned word,
@@ -235,7 +260,7 @@ static uint32_t tpm_sendrecv_command(const void *command,
 			response, &response_length);
 	if (err)
 		return TPM_LIB_ERROR;
-	if (response)
+	if (size_ptr)
 		*size_ptr = response_length;
 
 	return tpm_return_code(response);
@@ -579,3 +604,327 @@ uint32_t tpm_get_capability(uint32_t cap_area, uint32_t sub_cap,
 
 	return 0;
 }
+
+#ifdef CONFIG_TPM_AUTH_SESSIONS
+
+/**
+ * Fill an authentication block in a request.
+ * This func can create the first as well as the second auth block (for
+ * double authorized commands).
+ *
+ * @param request	pointer to the request (w/ uninitialised auth data)
+ * @param request_len0	length of the request without auth data
+ * @param handles_len	length of the handles area in request
+ * @param auth_session	pointer to the (valid) auth session to be used
+ * @param request_auth	pointer to the auth block of the request to be filled
+ * @param auth		authentication data (HMAC key)
+ */
+static uint32_t create_request_auth(const void *request, size_t request_len0,
+	size_t handles_len,
+	struct session_data *auth_session,
+	void *request_auth, const void *auth)
+{
+	uint8_t hmac_data[DIGEST_LENGTH * 3 + 1];
+	sha1_context hash_ctx;
+	const size_t command_code_offset = 6;
+	const size_t auth_nonce_odd_offset = 4;
+	const size_t auth_continue_offset = 24;
+	const size_t auth_auth_offset = 25;
+
+	if (!auth_session || !auth_session->valid)
+		return TPM_LIB_ERROR;
+
+	sha1_starts(&hash_ctx);
+	sha1_update(&hash_ctx, request + command_code_offset, 4);
+	if (request_len0 > TPM_REQUEST_HEADER_LENGTH + handles_len)
+		sha1_update(&hash_ctx,
+			    request + TPM_REQUEST_HEADER_LENGTH + handles_len,
+			    request_len0 - TPM_REQUEST_HEADER_LENGTH
+			    - handles_len);
+	sha1_finish(&hash_ctx, hmac_data);
+
+	sha1_starts(&hash_ctx);
+	sha1_update(&hash_ctx, auth_session->nonce_odd, DIGEST_LENGTH);
+	sha1_update(&hash_ctx, hmac_data, sizeof(hmac_data));
+	sha1_finish(&hash_ctx, auth_session->nonce_odd);
+
+	if (pack_byte_string(request_auth, TPM_REQUEST_AUTH_LENGTH, "dsb",
+			     0, auth_session->handle,
+			     auth_nonce_odd_offset, auth_session->nonce_odd,
+			     DIGEST_LENGTH,
+			     auth_continue_offset, 1))
+		return TPM_LIB_ERROR;
+	if (pack_byte_string(hmac_data, sizeof(hmac_data), "ss",
+			     DIGEST_LENGTH,
+			     auth_session->nonce_even,
+			     DIGEST_LENGTH,
+			     2 * DIGEST_LENGTH,
+			     request_auth + auth_nonce_odd_offset,
+			     DIGEST_LENGTH + 1))
+		return TPM_LIB_ERROR;
+	sha1_hmac(auth, DIGEST_LENGTH, hmac_data, sizeof(hmac_data),
+		  request_auth + auth_auth_offset);
+
+	return TPM_SUCCESS;
+}
+
+/**
+ * Verify an authentication block in a response.
+ * Since this func updates the nonce_even in the session data it has to be
+ * called when receiving a succesfull AUTH response.
+ * This func can verify the first as well as the second auth block (for
+ * double authorized commands).
+ *
+ * @param command_code	command code of the request
+ * @param response	pointer to the request (w/ uninitialised auth data)
+ * @param handles_len	length of the handles area in response
+ * @param auth_session	pointer to the (valid) auth session to be used
+ * @param response_auth	pointer to the auth block of the response to be verified
+ * @param auth		authentication data (HMAC key)
+ */
+static uint32_t verify_response_auth(uint32_t command_code,
+	const void *response, size_t response_len0,
+	size_t handles_len,
+	struct session_data *auth_session,
+	const void *response_auth, const void *auth)
+{
+	uint8_t hmac_data[DIGEST_LENGTH * 3 + 1];
+	uint8_t computed_auth[DIGEST_LENGTH];
+	sha1_context hash_ctx;
+	const size_t return_code_offset = 6;
+	const size_t auth_continue_offset = 20;
+	const size_t auth_auth_offset = 21;
+	uint8_t auth_continue;
+
+	if (!auth_session || !auth_session->valid)
+		return TPM_AUTHFAIL;
+	if (pack_byte_string(hmac_data, sizeof(hmac_data), "d",
+			     0, command_code))
+		return TPM_LIB_ERROR;
+	if (response_len0 < TPM_RESPONSE_HEADER_LENGTH)
+		return TPM_LIB_ERROR;
+
+	sha1_starts(&hash_ctx);
+	sha1_update(&hash_ctx, response + return_code_offset, 4);
+	sha1_update(&hash_ctx, hmac_data, 4);
+	if (response_len0 > TPM_RESPONSE_HEADER_LENGTH + handles_len)
+		sha1_update(&hash_ctx,
+			    response + TPM_RESPONSE_HEADER_LENGTH + handles_len,
+			    response_len0 - TPM_RESPONSE_HEADER_LENGTH
+			    - handles_len);
+	sha1_finish(&hash_ctx, hmac_data);
+
+	memcpy(auth_session->nonce_even, response_auth, DIGEST_LENGTH);
+	auth_continue = ((uint8_t *)response_auth)[auth_continue_offset];
+	if (pack_byte_string(hmac_data, sizeof(hmac_data), "ssb",
+			     DIGEST_LENGTH,
+			     response_auth,
+			     DIGEST_LENGTH,
+			     2 * DIGEST_LENGTH,
+			     auth_session->nonce_odd,
+			     DIGEST_LENGTH,
+			     3 * DIGEST_LENGTH,
+			     auth_continue))
+		return TPM_LIB_ERROR;
+
+	sha1_hmac(auth, DIGEST_LENGTH, hmac_data, sizeof(hmac_data),
+		  computed_auth);
+
+	if (memcmp(computed_auth, response_auth + auth_auth_offset,
+		   DIGEST_LENGTH))
+		return TPM_AUTHFAIL;
+
+	return TPM_SUCCESS;
+}
+
+
+uint32_t tpm_terminate_auth_session(uint32_t auth_handle)
+{
+	const uint8_t command[18] = {
+		0x00, 0xc1,		/* TPM_TAG */
+		0x00, 0x00, 0x00, 0x00,	/* parameter size */
+		0x00, 0x00, 0x00, 0xba,	/* TPM_COMMAND_CODE */
+		0x00, 0x00, 0x00, 0x00,	/* TPM_HANDLE */
+		0x00, 0x00, 0x00, 0x02,	/* TPM_RESSOURCE_TYPE */
+	};
+	const size_t req_handle_offset = TPM_REQUEST_HEADER_LENGTH;
+	uint8_t request[COMMAND_BUFFER_SIZE];
+
+	if (pack_byte_string(request, sizeof(request), "sd",
+			     0, command, sizeof(command),
+			     req_handle_offset, auth_handle))
+		return TPM_LIB_ERROR;
+	if (oiap_session.valid && oiap_session.handle == auth_handle)
+		oiap_session.valid = 0;
+
+	return tpm_sendrecv_command(request, NULL, NULL);
+}
+
+uint32_t tpm_end_oiap(void)
+{
+	uint32_t err = TPM_SUCCESS;
+	if (oiap_session.valid)
+		err = tpm_terminate_auth_session(oiap_session.handle);
+	return err;
+}
+
+uint32_t tpm_oiap(uint32_t *auth_handle)
+{
+	const uint8_t command[10] = {
+		0x00, 0xc1,		/* TPM_TAG */
+		0x00, 0x00, 0x00, 0x0a,	/* parameter size */
+		0x00, 0x00, 0x00, 0x0a,	/* TPM_COMMAND_CODE */
+	};
+	const size_t res_auth_handle_offset = TPM_RESPONSE_HEADER_LENGTH;
+	const size_t res_nonce_even_offset = TPM_RESPONSE_HEADER_LENGTH + 4;
+	uint8_t response[COMMAND_BUFFER_SIZE];
+	size_t response_length = sizeof(response);
+	uint32_t err;
+
+	if (oiap_session.valid)
+		tpm_terminate_auth_session(oiap_session.handle);
+
+	err = tpm_sendrecv_command(command, response, &response_length);
+	if (err)
+		return err;
+	if (unpack_byte_string(response, response_length, "ds",
+			       res_auth_handle_offset, &oiap_session.handle,
+			       res_nonce_even_offset, &oiap_session.nonce_even,
+			       (uint32_t)DIGEST_LENGTH))
+		return TPM_LIB_ERROR;
+	oiap_session.valid = 1;
+	if (auth_handle)
+		*auth_handle = oiap_session.handle;
+	return 0;
+}
+
+uint32_t tpm_load_key2_oiap(uint32_t parent_handle,
+		const void *key, size_t key_length,
+		const void *parent_key_usage_auth,
+		uint32_t *key_handle)
+{
+	const uint8_t command[14] = {
+		0x00, 0xc2,		/* TPM_TAG */
+		0x00, 0x00, 0x00, 0x00,	/* parameter size */
+		0x00, 0x00, 0x00, 0x41,	/* TPM_COMMAND_CODE */
+		0x00, 0x00, 0x00, 0x00,	/* parent handle */
+	};
+	const size_t req_size_offset = 2;
+	const size_t req_parent_handle_offset = TPM_REQUEST_HEADER_LENGTH;
+	const size_t req_key_offset = TPM_REQUEST_HEADER_LENGTH + 4;
+	const size_t res_handle_offset = TPM_RESPONSE_HEADER_LENGTH;
+	uint8_t request[sizeof(command) + TPM_KEY12_MAX_LENGTH
+			+ TPM_REQUEST_AUTH_LENGTH];
+	uint8_t response[COMMAND_BUFFER_SIZE];
+	size_t response_length = sizeof(response);
+	uint32_t err;
+
+	if (!oiap_session.valid) {
+		err = tpm_oiap(NULL);
+		if (err)
+			return err;
+	}
+	if (pack_byte_string(request, sizeof(request), "sdds",
+			     0, command, sizeof(command),
+			     req_size_offset,
+			     sizeof(command) + key_length
+			     + TPM_REQUEST_AUTH_LENGTH,
+			     req_parent_handle_offset, parent_handle,
+			     req_key_offset, key, key_length
+		))
+		return TPM_LIB_ERROR;
+
+	err = create_request_auth(request, sizeof(command) + key_length, 4,
+				&oiap_session,
+				request + sizeof(command) + key_length,
+				parent_key_usage_auth);
+	if (err)
+		return err;
+	err = tpm_sendrecv_command(request, response, &response_length);
+	if (err) {
+		if (err == TPM_AUTHFAIL)
+			oiap_session.valid = 0;
+		return err;
+	}
+
+	err = verify_response_auth(0x00000041, response,
+			response_length - TPM_RESPONSE_AUTH_LENGTH,
+			4, &oiap_session,
+			response + response_length - TPM_RESPONSE_AUTH_LENGTH,
+			parent_key_usage_auth);
+	if (err)
+		return err;
+
+	if (key_handle) {
+		if (unpack_byte_string(response, response_length, "d",
+				       res_handle_offset, key_handle))
+			return TPM_LIB_ERROR;
+	}
+
+	return 0;
+}
+
+uint32_t tpm_get_pub_key_oiap(uint32_t key_handle, const void *usage_auth,
+			void *pubkey, size_t *pubkey_len)
+{
+	const uint8_t command[14] = {
+		0x00, 0xc2,		/* TPM_TAG */
+		0x00, 0x00, 0x00, 0x00,	/* parameter size */
+		0x00, 0x00, 0x00, 0x21,	/* TPM_COMMAND_CODE */
+		0x00, 0x00, 0x00, 0x00,	/* key handle */
+	};
+	const size_t req_size_offset = 2;
+	const size_t req_key_handle_offset = TPM_REQUEST_HEADER_LENGTH;
+	const size_t res_pubkey_offset = TPM_RESPONSE_HEADER_LENGTH;
+	uint8_t request[sizeof(command) + TPM_REQUEST_AUTH_LENGTH];
+	uint8_t response[TPM_RESPONSE_HEADER_LENGTH + TPM_PUBKEY_MAX_LENGTH
+			+ TPM_RESPONSE_AUTH_LENGTH];
+	size_t response_length = sizeof(response);
+	uint32_t err;
+
+	if (!oiap_session.valid) {
+		err = tpm_oiap(NULL);
+		if (err)
+			return err;
+	}
+	if (pack_byte_string(request, sizeof(request), "sdd",
+			     0, command, sizeof(command),
+			     req_size_offset,
+			     (uint32_t)(sizeof(command)
+			     + TPM_REQUEST_AUTH_LENGTH),
+			     req_key_handle_offset, key_handle
+		))
+		return TPM_LIB_ERROR;
+	err = create_request_auth(request, sizeof(command), 4, &oiap_session,
+			request + sizeof(command), usage_auth);
+	if (err)
+		return err;
+	err = tpm_sendrecv_command(request, response, &response_length);
+	if (err) {
+		if (err == TPM_AUTHFAIL)
+			oiap_session.valid = 0;
+		return err;
+	}
+	err = verify_response_auth(0x00000021, response,
+			response_length - TPM_RESPONSE_AUTH_LENGTH,
+			0, &oiap_session,
+			response + response_length - TPM_RESPONSE_AUTH_LENGTH,
+			usage_auth);
+	if (err)
+		return err;
+
+	if (pubkey) {
+		if ((response_length - TPM_RESPONSE_HEADER_LENGTH
+			- TPM_RESPONSE_AUTH_LENGTH) > *pubkey_len)
+			return TPM_LIB_ERROR;
+		*pubkey_len = response_length - TPM_RESPONSE_HEADER_LENGTH
+			- TPM_RESPONSE_AUTH_LENGTH;
+		memcpy(pubkey, response + res_pubkey_offset,
+		       response_length - TPM_RESPONSE_HEADER_LENGTH
+		       - TPM_RESPONSE_AUTH_LENGTH);
+	}
+
+	return 0;
+}
+
+#endif /* CONFIG_TPM_AUTH_SESSIONS */
-- 
1.8.3

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

* [U-Boot] [PATCH v6 2/5] i2c: fsl_i2c: i2c_read(): dont try to write address w/ alen=0
  2013-06-12  8:08 [U-Boot] [PATCH v6 0/5] Add gdsys ControlCenter Digital board dirk.eibach at gdsys.cc
  2013-06-12  8:08 ` [U-Boot] [PATCH v6 1/5] tpm: add AUTH1 cmds for LoadKey2 and GetPubKey dirk.eibach at gdsys.cc
@ 2013-06-12  8:08 ` dirk.eibach at gdsys.cc
  2013-06-20  4:59   ` Heiko Schocher
  2013-06-12  8:08 ` [U-Boot] [PATCH v6 3/5] Add Atmel I2C tpm dirk.eibach at gdsys.cc
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 12+ messages in thread
From: dirk.eibach at gdsys.cc @ 2013-06-12  8:08 UTC (permalink / raw)
  To: u-boot

From: Reinhard Pfau <pfau@gdsys.de>

if alen is 0: no longer start a write cycle before reading data.

Signed-off-by: Dirk Eibach <dirk.eibach@gdsys.cc>
Signed-off-by: Reinhard Pfau <reinhard.pfau@gdsys.cc>


Signed-off-by: Dirk Eibach <dirk.eibach@gdsys.cc>
---
Changes in v6: None
Changes in v5:
- fix i2c_probe

Changes in v4: None
Changes in v3: None
Changes in v2:
- whitespace fixes

 drivers/i2c/fsl_i2c.c | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/drivers/i2c/fsl_i2c.c b/drivers/i2c/fsl_i2c.c
index 1c7265d..5d7e010 100644
--- a/drivers/i2c/fsl_i2c.c
+++ b/drivers/i2c/fsl_i2c.c
@@ -383,13 +383,16 @@ i2c_read(u8 dev, uint addr, int alen, u8 *data, int length)
 	int i = -1; /* signal error */
 	u8 *a = (u8*)&addr;
 
-	if (i2c_wait4bus() >= 0
+	if (i2c_wait4bus() < 0)
+		return -1;
+
+	if ((!length || alen > 0)
 	    && i2c_write_addr(dev, I2C_WRITE_BIT, 0) != 0
 	    && __i2c_write(&a[4 - alen], alen) == alen)
 		i = 0; /* No error so far */
 
-	if (length
-	    && i2c_write_addr(dev, I2C_READ_BIT, 1) != 0)
+	if (length &&
+	    i2c_write_addr(dev, I2C_READ_BIT, alen ? 1 : 0) != 0)
 		i = __i2c_read(data, length);
 
 	writeb(I2C_CR_MEN, &i2c_dev[i2c_bus_num]->cr);
-- 
1.8.3

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

* [U-Boot] [PATCH v6 3/5] Add Atmel I2C tpm
  2013-06-12  8:08 [U-Boot] [PATCH v6 0/5] Add gdsys ControlCenter Digital board dirk.eibach at gdsys.cc
  2013-06-12  8:08 ` [U-Boot] [PATCH v6 1/5] tpm: add AUTH1 cmds for LoadKey2 and GetPubKey dirk.eibach at gdsys.cc
  2013-06-12  8:08 ` [U-Boot] [PATCH v6 2/5] i2c: fsl_i2c: i2c_read(): dont try to write address w/ alen=0 dirk.eibach at gdsys.cc
@ 2013-06-12  8:08 ` dirk.eibach at gdsys.cc
  2013-06-12  8:08 ` [U-Boot] [PATCH v6 4/5] Build arch/$ARCH/lib/bootm.o depending on CONFIG_CMD_BOOTM dirk.eibach at gdsys.cc
  2013-06-12  8:08 ` [U-Boot] [PATCH v6 5/5] mpc85xx: Add gdsys ControlCenter Digital board dirk.eibach at gdsys.cc
  4 siblings, 0 replies; 12+ messages in thread
From: dirk.eibach at gdsys.cc @ 2013-06-12  8:08 UTC (permalink / raw)
  To: u-boot

From: Dirk Eibach <eibach@gdsys.de>

Add support for Atmel TPM devices with two wire interface.

Signed-off-by: Dirk Eibach <dirk.eibach@gdsys.cc>
Signed-off-by: Reinhard Pfau <reinhard.pfau@gdsys.cc>


Signed-off-by: Dirk Eibach <dirk.eibach@gdsys.cc>
---
Changes in v6:
- rename CONFIG_ATMEL_TWI_TPM to CONFIG_TPM_ATMEL_TWI
- rename drivers/tpm/atmel_twi_tpm.c to drivers/tpm/tpm_atmel_twi.c
- replace DEBUG_ATMEL_TWI_TPM, simply use DEBUG
- sort drivers/tpm/Makefile
- timeout on waiting for TPM reply

Changes in v5: None
Changes in v4: None
Changes in v3: None
Changes in v2: None

 README                      |   3 ++
 drivers/tpm/Makefile        |   1 +
 drivers/tpm/tpm_atmel_twi.c | 121 ++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 125 insertions(+)
 create mode 100644 drivers/tpm/tpm_atmel_twi.c

diff --git a/README b/README
index 3d1fa08..44dd4b6 100644
--- a/README
+++ b/README
@@ -1225,6 +1225,9 @@ The following options need to be configured:
 			CONFIG_TPM_TIS_I2C_BURST_LIMITATION
 			Define the burst count bytes upper limit
 
+		CONFIG_TPM_ATMEL_TWI
+		Support for Atmel TWI TPM device. Requires I2C support.
+
 		CONFIG_TPM_TIS_LPC
 		Support for generic parallel port TPM devices. Only one device
 		per system is supported at this time.
diff --git a/drivers/tpm/Makefile b/drivers/tpm/Makefile
index 913dd9c..c3010ba 100644
--- a/drivers/tpm/Makefile
+++ b/drivers/tpm/Makefile
@@ -26,6 +26,7 @@ LIB := $(obj)libtpm.o
 $(shell mkdir -p $(obj)slb9635_i2c)
 
 # TODO: Merge tpm_tis_lpc.c with tpm.c
+COBJS-$(CONFIG_TPM_ATMEL_TWI) += tpm_atmel_twi.o
 COBJS-$(CONFIG_TPM_TIS_I2C) += tpm.o
 COBJS-$(CONFIG_TPM_TIS_I2C) += tpm_tis_i2c.o
 COBJS-$(CONFIG_TPM_TIS_LPC) += tpm_tis_lpc.o
diff --git a/drivers/tpm/tpm_atmel_twi.c b/drivers/tpm/tpm_atmel_twi.c
new file mode 100644
index 0000000..361a772
--- /dev/null
+++ b/drivers/tpm/tpm_atmel_twi.c
@@ -0,0 +1,121 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <tpm.h>
+#include <i2c.h>
+#include <asm/unaligned.h>
+
+#define ATMEL_TPM_TIMEOUT_MS 5000 /* sufficient for anything but
+				     generating/exporting keys */
+
+/*
+ * tis_init()
+ *
+ * Initialize the TPM device. Returns 0 on success or -1 on
+ * failure (in case device probing did not succeed).
+ */
+int tis_init(void)
+{
+	return 0;
+}
+
+/*
+ * tis_open()
+ *
+ * Requests access to locality 0 for the caller. After all commands have been
+ * completed the caller is supposed to call tis_close().
+ *
+ * Returns 0 on success, -1 on failure.
+ */
+int tis_open(void)
+{
+	return 0;
+}
+
+/*
+ * tis_close()
+ *
+ * terminate the currect session with the TPM by releasing the locked
+ * locality. Returns 0 on success of -1 on failure (in case lock
+ * removal did not succeed).
+ */
+int tis_close(void)
+{
+	return 0;
+}
+
+/*
+ * tis_sendrecv()
+ *
+ * Send the requested data to the TPM and then try to get its response
+ *
+ * @sendbuf - buffer of the data to send
+ * @send_size size of the data to send
+ * @recvbuf - memory to save the response to
+ * @recv_len - pointer to the size of the response buffer
+ *
+ * Returns 0 on success (and places the number of response bytes at recv_len)
+ * or -1 on failure.
+ */
+int tis_sendrecv(const uint8_t *sendbuf, size_t send_size, uint8_t *recvbuf,
+			size_t *recv_len)
+{
+	int res;
+	unsigned long start;
+
+#ifdef DEBUG
+	memset(recvbuf, 0xcc, *recv_len);
+	printf("send to TPM (%d bytes, recv_len=%d):\n", send_size, *recv_len);
+	print_buffer(0, (void *)sendbuf, 1, send_size, 0);
+#endif
+
+	res = i2c_write(0x29, 0, 0, (uchar *)sendbuf, send_size);
+	if (res) {
+		printf("i2c_write returned %d\n", res);
+		return -1;
+	}
+
+	start = get_timer(0);
+	while ((res = i2c_read(0x29, 0, 0, recvbuf, 10))) {
+		if (get_timer(start) > ATMEL_TPM_TIMEOUT_MS) {
+			puts("tpm timed out\n");
+			return -1;
+		}
+		udelay(100);
+	}
+	if (!res) {
+		*recv_len = get_unaligned_be32(recvbuf + 2);
+		if (*recv_len > 10)
+			res = i2c_read(0x29, 0, 0, recvbuf, *recv_len);
+	}
+	if (res) {
+		printf("i2c_read returned %d (rlen=%d)\n", res, *recv_len);
+#ifdef DEBUG
+		print_buffer(0, recvbuf, 1, *recv_len, 0);
+#endif
+	}
+
+#ifdef DEBUG
+	if (!res) {
+		printf("read from TPM (%d bytes):\n", *recv_len);
+		print_buffer(0, recvbuf, 1, *recv_len, 0);
+	}
+#endif
+
+	return res;
+}
-- 
1.8.3

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

* [U-Boot] [PATCH v6 4/5] Build arch/$ARCH/lib/bootm.o depending on CONFIG_CMD_BOOTM
  2013-06-12  8:08 [U-Boot] [PATCH v6 0/5] Add gdsys ControlCenter Digital board dirk.eibach at gdsys.cc
                   ` (2 preceding siblings ...)
  2013-06-12  8:08 ` [U-Boot] [PATCH v6 3/5] Add Atmel I2C tpm dirk.eibach at gdsys.cc
@ 2013-06-12  8:08 ` dirk.eibach at gdsys.cc
  2013-06-19 21:49   ` Andy Fleming
  2013-06-12  8:08 ` [U-Boot] [PATCH v6 5/5] mpc85xx: Add gdsys ControlCenter Digital board dirk.eibach at gdsys.cc
  4 siblings, 1 reply; 12+ messages in thread
From: dirk.eibach at gdsys.cc @ 2013-06-12  8:08 UTC (permalink / raw)
  To: u-boot

From: Dirk Eibach <eibach@gdsys.de>

MAKEALL is fine for ppc4xx and mpc85xx.
Run checks were done on our controlcenterd hardware.

Signed-off-by: Dirk Eibach <dirk.eibach@gdsys.cc>


Signed-off-by: Dirk Eibach <dirk.eibach@gdsys.cc>
---
Changes in v6: None
Changes in v5: None
Changes in v4:
- consider CONFIG_CMD_BOOTM for all architectures

Changes in v3: None
Changes in v2: None

 arch/arm/lib/Makefile        | 2 +-
 arch/avr32/lib/Makefile      | 2 +-
 arch/m68k/lib/Makefile       | 2 +-
 arch/microblaze/lib/Makefile | 2 +-
 arch/mips/lib/Makefile       | 4 ++--
 arch/nds32/lib/Makefile      | 3 ++-
 arch/nios2/lib/Makefile      | 2 +-
 arch/openrisc/lib/Makefile   | 2 +-
 arch/powerpc/lib/Makefile    | 2 +-
 arch/sh/lib/Makefile         | 2 +-
 arch/sparc/lib/Makefile      | 3 ++-
 arch/x86/lib/Makefile        | 2 +-
 12 files changed, 15 insertions(+), 13 deletions(-)

diff --git a/arch/arm/lib/Makefile b/arch/arm/lib/Makefile
index 8ad9f66..6526fc8 100644
--- a/arch/arm/lib/Makefile
+++ b/arch/arm/lib/Makefile
@@ -45,8 +45,8 @@ COBJS-y	+= board.o
 endif
 COBJS-y += bss.o
 
-COBJS-y	+= bootm.o
 COBJS-$(CONFIG_OF_LIBFDT) += bootm-fdt.o
+COBJS-$(CONFIG_CMD_BOOTM) += bootm.o
 COBJS-$(CONFIG_SYS_L2_PL310) += cache-pl310.o
 SOBJS-$(CONFIG_USE_ARCH_MEMSET) += memset.o
 SOBJS-$(CONFIG_USE_ARCH_MEMCPY) += memcpy.o
diff --git a/arch/avr32/lib/Makefile b/arch/avr32/lib/Makefile
index ee6d067..fce8af3 100644
--- a/arch/avr32/lib/Makefile
+++ b/arch/avr32/lib/Makefile
@@ -30,7 +30,7 @@ LIB	= $(obj)lib$(ARCH).o
 SOBJS-y	+= memset.o
 
 COBJS-y	+= board.o
-COBJS-y	+= bootm.o
+COBJS-$(CONFIG_CMD_BOOTM) += bootm.o
 COBJS-y	+= interrupts.o
 
 SRCS	:= $(SOBJS-y:.o=.S) $(COBJS-y:.o=.c)
diff --git a/arch/m68k/lib/Makefile b/arch/m68k/lib/Makefile
index a8d6cd5..5722b67 100644
--- a/arch/m68k/lib/Makefile
+++ b/arch/m68k/lib/Makefile
@@ -28,7 +28,7 @@ LIB	= $(obj)lib$(ARCH).o
 SOBJS-y	+=
 
 COBJS-y	+= board.o
-COBJS-y	+= bootm.o
+COBJS-$(CONFIG_CMD_BOOTM) += bootm.o
 COBJS-y	+= cache.o
 COBJS-y	+= interrupts.o
 COBJS-y	+= time.o
diff --git a/arch/microblaze/lib/Makefile b/arch/microblaze/lib/Makefile
index 8d7febd..a40e8d4 100644
--- a/arch/microblaze/lib/Makefile
+++ b/arch/microblaze/lib/Makefile
@@ -28,7 +28,7 @@ LIB	= $(obj)lib$(ARCH).o
 SOBJS-y	+=
 
 COBJS-y	+= board.o
-COBJS-y	+= bootm.o
+COBJS-$(CONFIG_CMD_BOOTM) += bootm.o
 COBJS-y	+= muldi3.o
 
 SRCS	:= $(SOBJS-y:.o=.S) $(COBJS-y:.o=.c)
diff --git a/arch/mips/lib/Makefile b/arch/mips/lib/Makefile
index 967e98a..b6ded54 100644
--- a/arch/mips/lib/Makefile
+++ b/arch/mips/lib/Makefile
@@ -36,9 +36,9 @@ SOBJS-y	+=
 
 COBJS-y	+= board.o
 ifeq ($(CONFIG_QEMU_MIPS),y)
-COBJS-y	+= bootm_qemu_mips.o
+COBJS-$(CONFIG_CMD_BOOTM) += bootm_qemu_mips.o
 else
-COBJS-y	+= bootm.o
+COBJS-$(CONFIG_CMD_BOOTM) += bootm.o
 endif
 
 SRCS	:= $(SOBJS-y:.o=.S) $(COBJS-y:.o=.c)
diff --git a/arch/nds32/lib/Makefile b/arch/nds32/lib/Makefile
index 581a2e7..705e1ff 100644
--- a/arch/nds32/lib/Makefile
+++ b/arch/nds32/lib/Makefile
@@ -29,7 +29,8 @@ include $(TOPDIR)/config.mk
 
 LIB	= $(obj)lib$(ARCH).o
 
-OBJS	:= board.o bootm.o cache.o interrupts.o
+OBJS	:= board.o cache.o interrupts.o
+COBJS-$(CONFIG_CMD_BOOTM) += bootm.o
 
 all:	$(LIB)
 
diff --git a/arch/nios2/lib/Makefile b/arch/nios2/lib/Makefile
index 443f99e..f33f96a 100644
--- a/arch/nios2/lib/Makefile
+++ b/arch/nios2/lib/Makefile
@@ -28,7 +28,7 @@ LIB	= $(obj)lib$(ARCH).o
 SOBJS-y	+= cache.o
 
 COBJS-y	+= board.o
-COBJS-y	+= bootm.o
+COBJS-$(CONFIG_CMD_BOOTM) += bootm.o
 COBJS-y	+= libgcc.o
 COBJS-y	+= time.o
 
diff --git a/arch/openrisc/lib/Makefile b/arch/openrisc/lib/Makefile
index db3c657..ab822f4 100644
--- a/arch/openrisc/lib/Makefile
+++ b/arch/openrisc/lib/Makefile
@@ -28,7 +28,7 @@ LIB	= $(obj)lib$(ARCH).o
 SOBJS-y	+=
 
 COBJS-y	+= board.o
-COBJS-y	+= bootm.o
+COBJS-$(CONFIG_CMD_BOOTM) += bootm.o
 COBJS-y	+= timer.o
 
 SRCS	:= $(SOBJS-y:.o=.S) $(COBJS-y:.o=.c)
diff --git a/arch/powerpc/lib/Makefile b/arch/powerpc/lib/Makefile
index 59c723b..8c4920b 100644
--- a/arch/powerpc/lib/Makefile
+++ b/arch/powerpc/lib/Makefile
@@ -63,7 +63,7 @@ ifndef CONFIG_SYS_GENERIC_BOARD
 COBJS-y	+= board.o
 endif
 endif
-COBJS-y	+= bootm.o
+COBJS-$(CONFIG_CMD_BOOTM) += bootm.o
 COBJS-y	+= cache.o
 COBJS-y	+= extable.o
 COBJS-y	+= interrupts.o
diff --git a/arch/sh/lib/Makefile b/arch/sh/lib/Makefile
index 256811a..3d4eb53 100644
--- a/arch/sh/lib/Makefile
+++ b/arch/sh/lib/Makefile
@@ -33,7 +33,7 @@ GLSOBJS	+= lshrdi3.o
 GLSOBJS	+= movmem.o
 
 COBJS-y	+= board.o
-COBJS-y	+= bootm.o
+COBJS-$(CONFIG_CMD_BOOTM) += bootm.o
 ifeq ($(CONFIG_SH2),y)
 COBJS-y	+= time_sh2.o
 else
diff --git a/arch/sparc/lib/Makefile b/arch/sparc/lib/Makefile
index 7133ef1..aec29b3 100644
--- a/arch/sparc/lib/Makefile
+++ b/arch/sparc/lib/Makefile
@@ -27,7 +27,8 @@ LIB	= $(obj)lib$(ARCH).o
 
 SOBJS	=
 
-COBJS	= board.o cache.o interrupts.o time.o bootm.o
+COBJS	= board.o cache.o interrupts.o time.o
+COBJS-$(CONFIG_CMD_BOOTM) += bootm.o
 
 SRCS	:= $(SOBJS:.o=.S) $(COBJS:.o=.c)
 OBJS	:= $(addprefix $(obj),$(SOBJS) $(COBJS))
diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile
index f66ad30..ab3ccee 100644
--- a/arch/x86/lib/Makefile
+++ b/arch/x86/lib/Makefile
@@ -25,7 +25,7 @@ include $(TOPDIR)/config.mk
 
 LIB	= $(obj)lib$(ARCH).o
 
-COBJS-y	+= bootm.o
+COBJS-$(CONFIG_CMD_BOOTM) += bootm.o
 COBJS-y	+= cmd_boot.o
 COBJS-y	+= gcc.o
 COBJS-y	+= init_helpers.o
-- 
1.8.3

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

* [U-Boot] [PATCH v6 5/5] mpc85xx: Add gdsys ControlCenter Digital board
  2013-06-12  8:08 [U-Boot] [PATCH v6 0/5] Add gdsys ControlCenter Digital board dirk.eibach at gdsys.cc
                   ` (3 preceding siblings ...)
  2013-06-12  8:08 ` [U-Boot] [PATCH v6 4/5] Build arch/$ARCH/lib/bootm.o depending on CONFIG_CMD_BOOTM dirk.eibach at gdsys.cc
@ 2013-06-12  8:08 ` dirk.eibach at gdsys.cc
  2013-06-12 18:12   ` Wolfgang Denk
  4 siblings, 1 reply; 12+ messages in thread
From: dirk.eibach at gdsys.cc @ 2013-06-12  8:08 UTC (permalink / raw)
  To: u-boot

From: Dirk Eibach <eibach@gdsys.de>

The gdsys ControlCenter Digital board is based on a Freescale P1022 QorIQ SOC.
It boots from SPI-Flash but can be configured to boot from SD-card for
factory programming and testing.
On board peripherals include:
- 2x GbE
- Lattice ECP3 FPGA connected via PCIe
- mSATA RAID1
- USB host
- DisplayPort video output
- Atmel TPM

Signed-off-by: Dirk Eibach <dirk.eibach@gdsys.cc>
Signed-off-by: Reinhard Pfau <reinhard.pfau@gdsys.cc>

Signed-off-by: Dirk Eibach <dirk.eibach@gdsys.cc>
---
Changes in v6:
- Add CONFIG_PCI_INDIRECT_BRIDGE to controlcenterd.h
- Add MAINTAINERS entry
- drop "mpc85xx: Add CONFIG_RELEASE_CORE0_ONLY" and use mp_holdoff instead

Changes in v5:
- avoid probing dp501 i2c bridge addresses

Changes in v4: None
Changes in v3:
- fix email addresses

Changes in v2:
- configuration for SPI builds was missing
- whitespace fixes

 .checkpatch.conf                      |    4 +-
 MAINTAINERS                           |    3 +-
 board/gdsys/common/Makefile           |    1 +
 board/gdsys/common/dp501.c            |  107 +++
 board/gdsys/common/dp501.h            |   30 +
 board/gdsys/p1022/Makefile            |   37 +
 board/gdsys/p1022/controlcenterd-id.c | 1205 +++++++++++++++++++++++++++++++++
 board/gdsys/p1022/controlcenterd-id.h |   29 +
 board/gdsys/p1022/controlcenterd.c    |  447 ++++++++++++
 board/gdsys/p1022/ddr.c               |   71 ++
 board/gdsys/p1022/diu.c               |   87 +++
 board/gdsys/p1022/law.c               |   20 +
 board/gdsys/p1022/sdhc_boot.c         |   63 ++
 board/gdsys/p1022/tlb.c               |   77 +++
 boards.cfg                            |    7 +
 include/configs/controlcenterd.h      |  528 +++++++++++++++
 16 files changed, 2713 insertions(+), 3 deletions(-)
 create mode 100644 board/gdsys/common/dp501.c
 create mode 100644 board/gdsys/common/dp501.h
 create mode 100644 board/gdsys/p1022/Makefile
 create mode 100644 board/gdsys/p1022/controlcenterd-id.c
 create mode 100644 board/gdsys/p1022/controlcenterd-id.h
 create mode 100644 board/gdsys/p1022/controlcenterd.c
 create mode 100644 board/gdsys/p1022/ddr.c
 create mode 100644 board/gdsys/p1022/diu.c
 create mode 100644 board/gdsys/p1022/law.c
 create mode 100644 board/gdsys/p1022/sdhc_boot.c
 create mode 100644 board/gdsys/p1022/tlb.c
 create mode 100644 include/configs/controlcenterd.h

diff --git a/.checkpatch.conf b/.checkpatch.conf
index d88af57..ef9b595 100644
--- a/.checkpatch.conf
+++ b/.checkpatch.conf
@@ -2,10 +2,10 @@
 --no-tree
 
 # Temporary for false positive in checkpatch
---ignore COMPLEX_MACRO
+#--ignore COMPLEX_MACRO
 
 # For CONFIG_SYS_I2C_NOPROBES
---ignore MULTISTATEMENT_MACRO_USE_DO_WHILE
+#--ignore MULTISTATEMENT_MACRO_USE_DO_WHILE
 
 # For simple_strtoul
 --ignore CONSIDER_KSTRTO
diff --git a/MAINTAINERS b/MAINTAINERS
index 14075af..c5a9b08 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -160,8 +160,9 @@ egnite GmbH <info@egnite.de>
 
 Dirk Eibach <eibach@gdsys.de>
 
+	controlcenterd	P1022
 	devconcenter	PPC460EX
-	dlvision        PPC405EP
+	dlvision	PPC405EP
 	dlvision-10g	PPC405EP
 	gdppc440etx	PPC440EP/GR
 	intip		PPC460EX
diff --git a/board/gdsys/common/Makefile b/board/gdsys/common/Makefile
index 05dd65d..13a9c5d 100644
--- a/board/gdsys/common/Makefile
+++ b/board/gdsys/common/Makefile
@@ -33,6 +33,7 @@ COBJS-$(CONFIG_IO) += miiphybb.o
 COBJS-$(CONFIG_IO64) += miiphybb.o
 COBJS-$(CONFIG_IOCON) += osd.o
 COBJS-$(CONFIG_DLVISION_10G) += osd.o
+COBJS-$(CONFIG_CONTROLCENTERD) += dp501.o
 
 COBJS   := $(COBJS-y)
 SOBJS   =
diff --git a/board/gdsys/common/dp501.c b/board/gdsys/common/dp501.c
new file mode 100644
index 0000000..9aa4e3f
--- /dev/null
+++ b/board/gdsys/common/dp501.c
@@ -0,0 +1,107 @@
+/*
+ * (C) Copyright 2012
+ * Dirk Eibach,  Guntermann & Drunck GmbH, dirk.eibach at gdsys.cc
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/* Parade Technologies Inc. DP501 DisplayPort DVI/HDMI Transmitter */
+
+#include <common.h>
+#include <asm/io.h>
+#include <errno.h>
+#include <i2c.h>
+
+static void dp501_setbits(u8 addr, u8 reg, u8 mask)
+{
+	u8 val;
+
+	val = i2c_reg_read(addr, reg);
+	setbits_8(&val, mask);
+	i2c_reg_write(addr, reg, val);
+}
+
+static void dp501_clrbits(u8 addr, u8 reg, u8 mask)
+{
+	u8 val;
+
+	val = i2c_reg_read(addr, reg);
+	clrbits_8(&val, mask);
+	i2c_reg_write(addr, reg, val);
+}
+
+static int dp501_detect_cable_adapter(u8 addr)
+{
+	u8 val = i2c_reg_read(addr, 0x00);
+
+	return !(val & 0x04);
+}
+
+static void dp501_link_training(u8 addr)
+{
+	u8 val;
+
+	val = i2c_reg_read(addr, 0x51);
+	i2c_reg_write(addr, 0x5d, val); /* set link_bw */
+	val = i2c_reg_read(addr, 0x52);
+	i2c_reg_write(addr, 0x5e, val); /* set lane_cnt */
+	val = i2c_reg_read(addr, 0x53);
+	i2c_reg_write(addr, 0x5c, val); /* set downspread_ctl */
+
+	i2c_reg_write(addr, 0x5f, 0x0d); /* start training */
+}
+
+void dp501_powerup(u8 addr)
+{
+	dp501_clrbits(addr, 0x0a, 0x30); /* power on encoder */
+	i2c_reg_write(addr, 0x27, 0x30); /* Hardware auto detect DVO timing */
+	dp501_setbits(addr, 0x72, 0x80); /* DPCD read enable */
+	dp501_setbits(addr, 0x30, 0x20); /* RS polynomial select */
+	i2c_reg_write(addr, 0x71, 0x20); /* Enable Aux burst write */
+	dp501_setbits(addr, 0x78, 0x30); /* Disable HPD2 IRQ */
+	dp501_clrbits(addr, 0x2f, 0x40); /* Link FIFO reset selection */
+	i2c_reg_write(addr, 0x24, 0xc0); /* SDR mode 0, ext. H/VSYNC */
+	i2c_reg_write(addr + 2, 0x24, 0x02); /* clock input single ended */
+
+	if (dp501_detect_cable_adapter(addr)) {
+		printf("DVI/HDMI cable adapter detected\n");
+		i2c_reg_write(addr, 0x5e, 0x04); /* enable 4 channel */
+		dp501_clrbits(addr, 0x00, 0x08); /* DVI/HDMI HDCP operation */
+	} else {
+		printf("no DVI/HDMI cable adapter detected\n");
+		i2c_reg_write(addr + 2, 0x00, 0x18); /* driving strength */
+		i2c_reg_write(addr + 2, 0x03, 0x06); /* driving strength */
+		i2c_reg_write(addr, 0x2c, 0x00); /* configure N value */
+		i2c_reg_write(addr, 0x2d, 0x00); /* configure N value */
+		i2c_reg_write(addr, 0x2e, 0x0c); /* configure N value */
+		i2c_reg_write(addr, 0x76, 0xff); /* clear all interrupt */
+		dp501_setbits(addr, 0x78, 0x03); /* clear all interrupt */
+		i2c_reg_write(addr, 0x75, 0xf8); /* aux channel reset */
+		i2c_reg_write(addr, 0x75, 0x00); /* clear aux channel reset */
+		i2c_reg_write(addr, 0x87, 0x70); /* set retry counter as 7 */
+		dp501_setbits(addr, 0x00, 0x08); /* for DP HDCP operation */
+
+		dp501_link_training(addr);
+	}
+}
+
+void dp501_powerdown(u8 addr)
+{
+	dp501_setbits(addr, 0x0a, 0x30); /* power down encoder, standby mode */
+}
diff --git a/board/gdsys/common/dp501.h b/board/gdsys/common/dp501.h
new file mode 100644
index 0000000..8dc3215
--- /dev/null
+++ b/board/gdsys/common/dp501.h
@@ -0,0 +1,30 @@
+/*
+ * (C) Copyright 2012
+ * Dirk Eibach,  Guntermann & Drunck GmbH, dirk.eibach at gdsys.cc
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef _DP501_H_
+#define _DP501_H_
+
+void dp501_powerup(u8 addr);
+void dp501_powerdown(u8 addr);
+
+#endif
diff --git a/board/gdsys/p1022/Makefile b/board/gdsys/p1022/Makefile
new file mode 100644
index 0000000..17f602f
--- /dev/null
+++ b/board/gdsys/p1022/Makefile
@@ -0,0 +1,37 @@
+#
+# Copyright 2010 Freescale Semiconductor, Inc.
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the Free
+# Software Foundation; either version 2 of the License, or (at your option)
+# any later version.
+#
+
+include $(TOPDIR)/config.mk
+
+LIB	= $(obj)lib$(BOARD).o
+
+# COBJS-y	+= $(BOARD).o
+COBJS-y	+= law.o
+COBJS-y	+= ddr.o
+COBJS-y	+= tlb.o
+COBJS-y	+= sdhc_boot.o
+COBJS-$(CONFIG_CONTROLCENTERD) += controlcenterd.o controlcenterd-id.o
+
+COBJS-$(CONFIG_FSL_DIU_FB) += diu.o
+
+SRCS	:= $(SOBJS:.o=.S) $(COBJS-y:.o=.c)
+OBJS	:= $(addprefix $(obj),$(COBJS-y))
+SOBJS	:= $(addprefix $(obj),$(SOBJS))
+
+$(LIB):	$(OBJS) $(SOBJS)
+	$(call cmd_link_o_target, $(OBJS))
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/board/gdsys/p1022/controlcenterd-id.c b/board/gdsys/p1022/controlcenterd-id.c
new file mode 100644
index 0000000..0698b27
--- /dev/null
+++ b/board/gdsys/p1022/controlcenterd-id.c
@@ -0,0 +1,1205 @@
+/*
+ * (C) Copyright 2013
+ * Reinhard Pfau, Guntermann & Drunck GmbH, reinhard.pfau at gdsys.cc
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+/* TODO: some more #ifdef's to avoid unneeded code for stage 1 / stage 2 */
+
+#ifdef CCDM_ID_DEBUG
+#define DEBUG
+#endif
+
+#include <common.h>
+#include <malloc.h>
+#include <fs.h>
+#include <i2c.h>
+#include <mmc.h>
+#include <tpm.h>
+#include <sha1.h>
+#include <asm/byteorder.h>
+#include <asm/unaligned.h>
+#include <pca9698.h>
+
+#undef CCDM_FIRST_STAGE
+#undef CCDM_SECOND_STAGE
+#undef CCDM_AUTO_FIRST_STAGE
+
+#ifdef CONFIG_DEVELOP
+#define CCDM_DEVELOP
+#endif
+
+#ifdef CONFIG_TRAILBLAZER
+#define CCDM_FIRST_STAGE
+#undef CCDM_SECOND_STAGE
+#else
+#undef CCDM_FIRST_STAGE
+#define CCDM_SECOND_STAGE
+#endif
+
+#if defined(CCDM_DEVELOP) && defined(CCDM_SECOND_STAGE) && \
+	!defined(CCCM_FIRST_STAGE)
+#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 */
+	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),
+};
+
+/* 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,
+};
+
+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];
+};
+
+
+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_SELF_HASH	= 1,
+	FIX_HREG_STAGE2_HASH	= 2,
+	FIX_HREG_VENDOR		= 3,
+	COUNT_FIX_HREGS
+};
+
+
+/* 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 void(*bl2_entry)(void);
+
+static struct h_reg pcr_hregs[24];
+static struct h_reg fix_hregs[COUNT_FIX_HREGS];
+static struct h_reg var_hregs[8];
+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 prg_stage1_prepare[] = {
+	0x00, 0x20, 0x00, 0x00, /* opcode: SYNC f0 */
+	0x00, 0x24, 0x00, 0x00, /* opcode: SYNC f1 */
+	0x01, 0x80, 0x00, 0x00, /* opcode: CHECK0 PCR0 */
+	0x81, 0x22, 0x00, 0x00, /* opcode: LOAD PCR0, f0 */
+	0x01, 0x84, 0x00, 0x00, /* opcode: CHECK0 PCR1 */
+	0x81, 0x26, 0x10, 0x00, /* opcode: LOAD PCR1, f1 */
+	0x01, 0x88, 0x00, 0x00, /* opcode: CHECK0 PCR2 */
+	0x81, 0x2a, 0x20, 0x00, /* opcode: LOAD PCR2, f2 */
+	0x01, 0x8c, 0x00, 0x00, /* opcode: CHECK0 PCR3 */
+	0x81, 0x2e, 0x30, 0x00, /* opcode: LOAD PCR3, f3 */
+};
+
+static const uint8_t prg_stage2_prepare[] = {
+	0x00, 0x80, 0x00, 0x00, /* opcode: SYNC PCR0 */
+	0x00, 0x84, 0x00, 0x00, /* opcode: SYNC PCR1 */
+	0x00, 0x88, 0x00, 0x00, /* opcode: SYNC PCR2 */
+	0x00, 0x8c, 0x00, 0x00, /* opcode: SYNC PCR3 */
+	0x00, 0x90, 0x00, 0x00, /* opcode: SYNC PCR4 */
+};
+
+static const uint8_t prg_stage2_success[] = {
+	0x81, 0x02, 0x40, 0x14, /* opcode: LOAD PCR4, #<20B data> */
+	0x48, 0xfd, 0x95, 0x17, 0xe7, 0x54, 0x6b, 0x68, /* data */
+	0x92, 0x31, 0x18, 0x05, 0xf8, 0x58, 0x58, 0x3c, /* data */
+	0xe4, 0xd2, 0x81, 0xe0, /* data */
+};
+
+static const uint8_t prg_stage_fail[] = {
+	0x81, 0x01, 0x00, 0x14, /* opcode: LOAD v0, #<20B data> */
+	0xc0, 0x32, 0xad, 0xc1, 0xff, 0x62, 0x9c, 0x9b, /* data */
+	0x66, 0xf2, 0x27, 0x49, 0xad, 0x66, 0x7e, 0x6b, /* data */
+	0xea, 0xdf, 0x14, 0x4b, /* data */
+	0x81, 0x42, 0x30, 0x00, /* opcode: LOAD PCR3, v0 */
+	0x81, 0x42, 0x40, 0x00, /* opcode: LOAD PCR4, v0 */
+};
+
+static const uint8_t vendor[] = "Guntermann & Drunck";
+
+
+/**
+ * @brief read a bunch of data from MMC into memory.
+ *
+ * @param mmc	pointer to the mmc structure to use.
+ * @param src	offset where the data starts on MMC/SD device (in bytes).
+ * @param dst	pointer to the location where the read data should be stored.
+ * @param size	number of bytes to read from the MMC/SD device.
+ * @return number of bytes read or -1 on error.
+ */
+static int ccdm_mmc_read(struct mmc *mmc, u64 src, u8 *dst, int size)
+{
+	int result = 0;
+	u32 blk_len, ofs;
+	ulong block_no, n, cnt;
+	u8 *tmp_buf = NULL;
+
+	if (size <= 0)
+		goto end;
+
+	blk_len = mmc->read_bl_len;
+	tmp_buf = malloc(blk_len);
+	if (!tmp_buf)
+		goto failure;
+	block_no = src / blk_len;
+	ofs = src % blk_len;
+
+	if (ofs) {
+		n = mmc->block_dev.block_read(mmc->block_dev.dev, block_no++, 1,
+			tmp_buf);
+		if (!n)
+			goto failure;
+		result = min(size, blk_len - ofs);
+		memcpy(dst, tmp_buf + ofs, result);
+		dst += result;
+		size -= result;
+	}
+	cnt = size / blk_len;
+	if (cnt) {
+		n = mmc->block_dev.block_read(mmc->block_dev.dev, block_no, cnt,
+			dst);
+		if (n != cnt)
+			goto failure;
+		size -= cnt * blk_len;
+		result += cnt * blk_len;
+		dst += cnt * blk_len;
+		block_no += cnt;
+	}
+	if (size) {
+		n = mmc->block_dev.block_read(mmc->block_dev.dev, block_no++, 1,
+			tmp_buf);
+		if (!n)
+			goto failure;
+		memcpy(dst, tmp_buf, size);
+		result += size;
+	}
+	goto end;
+failure:
+	result = -1;
+end:
+	if (tmp_buf)
+		free(tmp_buf);
+	return result;
+}
+
+/**
+ * @brief returns a location where the 2nd stage bootloader can be(/ is) placed.
+ *
+ * @return pointer to the location for/of the 2nd stage bootloader
+ */
+static u8 *get_2nd_stage_bl_location(ulong target_addr)
+{
+	ulong addr;
+#ifdef CCDM_SECOND_STAGE
+	addr = getenv_ulong("loadaddr", 16, CONFIG_LOADADDR);
+#else
+	addr = target_addr;
+#endif
+	return (u8 *)(addr);
+}
+
+
+#ifdef CCDM_SECOND_STAGE
+/**
+ * @brief returns a location where the image can be(/ is) placed.
+ *
+ * @return pointer to the location for/of the image
+ */
+static u8 *get_image_location(void)
+{
+	ulong addr;
+	/* TODO use other area? */
+	addr = getenv_ulong("loadaddr", 16, CONFIG_LOADADDR);
+	return (u8 *)(addr);
+}
+#endif
+
+/**
+ * @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;
+	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 compute hash of bootloader itself.
+ * @param[out] dst	hash register where the hash should be stored
+ * @return 0 on success, != 0 on failure.
+ *
+ * @note MUST be called at a time where the boot loader is accessible@the
+ * configured location (; so take care when code is reallocated).
+ */
+static int compute_self_hash(struct h_reg *dst)
+{
+	sha1_csum((const uint8_t *)CONFIG_SYS_MONITOR_BASE,
+		  CONFIG_SYS_MONITOR_LEN, dst->digest);
+	dst->valid = true;
+	return 0;
+}
+
+int ccdm_compute_self_hash(void)
+{
+	if (!fix_hregs[FIX_HREG_SELF_HASH].valid)
+		compute_self_hash(&fix_hregs[FIX_HREG_SELF_HASH]);
+	return 0;
+}
+
+/**
+ * @brief compute the hash of the 2nd stage boot loader (on SD card)
+ * @param[out] dst	hash register to store the computed hash
+ * @return 0 on success, != 0 on failure
+ *
+ * Determines the size and location of the 2nd stage boot loader on SD card,
+ * loads the 2nd stage boot loader and computes the (SHA1) hash value.
+ * Within the 1st stage boot loader, the 2nd stage boot loader is loaded at
+ * the desired memory location and the variable @a bl2_entry is set.
+ *
+ * @note This sets the variable @a bl2_entry to the entry point when the
+ * 2nd stage boot loader is loaded at its configured memory location.
+ */
+static int compute_second_stage_hash(struct h_reg *dst)
+{
+	int result = 0;
+	u32 code_len, code_offset, target_addr, exec_entry;
+	struct mmc *mmc;
+	u8 *load_addr = NULL;
+	u8 buf[128];
+
+	mmc = find_mmc_device(0);
+	if (!mmc)
+		goto failure;
+	mmc_init(mmc);
+
+	if (ccdm_mmc_read(mmc, 0, buf, sizeof(buf)) < 0)
+		goto failure;
+
+	code_offset = *(u32 *)(buf + ESDHC_BOOT_IMAGE_ADDR_OFS);
+	code_len = *(u32 *)(buf + ESDHC_BOOT_IMAGE_SIZE_OFS);
+	target_addr = *(u32 *)(buf + ESDHC_BOOT_IMAGE_TARGET_OFS);
+	exec_entry =  *(u32 *)(buf + ESDHC_BOOT_IMAGE_ENTRY_OFS);
+
+	load_addr = get_2nd_stage_bl_location(target_addr);
+	if (load_addr == (u8 *)target_addr)
+		bl2_entry = (void(*)(void))exec_entry;
+
+	if (ccdm_mmc_read(mmc, code_offset, load_addr, code_len) < 0)
+		goto failure;
+
+	sha1_csum(load_addr, code_len, dst->digest);
+	dst->valid = true;
+
+	goto end;
+failure:
+	result = 1;
+	bl2_entry = NULL;
+end:
+	return result;
+}
+
+/**
+ * @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_SELF_HASH:
+					ccdm_compute_self_hash();
+					break;
+				case FIX_HREG_STAGE2_HASH:
+					compute_second_stage_hash(result);
+					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;
+	}
+	/* TODO remember key handle somehow? */
+	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(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.
+ */
+static 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;
+}
+
+static int check_hmac(struct key_program *hmac,
+	const uint8_t *data, size_t data_size)
+{
+	uint8_t key[20], computed_hmac[20];
+	uint32_t type;
+
+	type = get_unaligned_be32(hmac->code);
+	if (type != 0)
+		return 1;
+	memset(key, 0, sizeof(key));
+	compute_extend(key, pcr_hregs[1].digest, 20);
+	compute_extend(key, pcr_hregs[2].digest, 20);
+	compute_extend(key, pcr_hregs[3].digest, 20);
+	compute_extend(key, pcr_hregs[4].digest, 20);
+
+	sha1_hmac(key, sizeof(key), data, data_size, computed_hmac);
+
+	return memcmp(computed_hmac, hmac->code + 4, 20);
+}
+
+static int 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;
+}
+
+#if defined(CCDM_FIRST_STAGE) || (defined CCDM_AUTO_FIRST_STAGE)
+static struct key_program *load_sd_key_program(void)
+{
+	u32 code_len, code_offset;
+	struct mmc *mmc;
+	u8 buf[128];
+	struct key_program *result = NULL, *hmac = NULL;
+	struct key_program header;
+
+	mmc = find_mmc_device(0);
+	if (!mmc)
+		return NULL;
+	mmc_init(mmc);
+
+	if (ccdm_mmc_read(mmc, 0, buf, sizeof(buf)) <= 0)
+		goto failure;
+
+	code_offset = *(u32 *)(buf + ESDHC_BOOT_IMAGE_ADDR_OFS);
+	code_len = *(u32 *)(buf + ESDHC_BOOT_IMAGE_SIZE_OFS);
+
+	code_offset += code_len;
+	/* TODO: the following needs to be the size of the 2nd stage env */
+	code_offset += CONFIG_ENV_SIZE;
+
+	if (ccdm_mmc_read(mmc, code_offset, buf, 4*3) < 0)
+		goto failure;
+
+	header.magic = get_unaligned_be32(buf);
+	header.code_crc = get_unaligned_be32(buf + 4);
+	header.code_size = get_unaligned_be32(buf + 8);
+
+	if (header.magic != MAGIC_KEY_PROGRAM)
+		goto failure;
+
+	result = malloc(sizeof(struct key_program) + header.code_size);
+	if (!result)
+		goto failure;
+	*result = header;
+
+	printf("load key program chunk from SD card (%u bytes) ",
+	       header.code_size);
+	code_offset += 12;
+	if (ccdm_mmc_read(mmc, code_offset, result->code, header.code_size)
+		< 0)
+		goto failure;
+	code_offset += header.code_size;
+	puts("\n");
+
+	if (verify_program(result))
+		goto failure;
+
+	if (ccdm_mmc_read(mmc, code_offset, buf, 4*3) < 0)
+		goto failure;
+
+	header.magic = get_unaligned_be32(buf);
+	header.code_crc = get_unaligned_be32(buf + 4);
+	header.code_size = get_unaligned_be32(buf + 8);
+
+	if (header.magic == MAGIC_HMAC) {
+		puts("check integrity\n");
+		hmac = malloc(sizeof(struct key_program) + header.code_size);
+		if (!hmac)
+			goto failure;
+		*hmac = header;
+		code_offset += 12;
+		if (ccdm_mmc_read(mmc, code_offset, hmac->code,
+				  hmac->code_size) < 0)
+			goto failure;
+		if (verify_program(hmac))
+			goto failure;
+		if (check_hmac(hmac, result->code, result->code_size)) {
+			puts("key program integrity could not be verified\n");
+			goto failure;
+		}
+		puts("key program verified\n");
+	}
+
+	goto end;
+failure:
+	if (result)
+		free(result);
+	result = NULL;
+end:
+	if (hmac)
+		free(hmac);
+	return result;
+}
+#endif
+
+#ifdef CCDM_SECOND_STAGE
+/**
+ * @brief load a key program from file system.
+ * @param ifname	interface of the file system
+ * @param dev_part_str	device part of the file system
+ * @param fs_type	tyep of the file system
+ * @param path		path of the file to load.
+ * @return the loaded structure or NULL on failure.
+ */
+static struct key_program *load_key_chunk(const char *ifname,
+	const char *dev_part_str, int fs_type,
+	const char *path)
+{
+	struct key_program *result = NULL;
+	struct key_program header;
+	uint32_t crc;
+	uint8_t buf[12];
+	int i;
+
+	if (fs_set_blk_dev(ifname, dev_part_str, fs_type))
+		goto failure;
+	i = fs_read(path, (ulong)buf, 0, 12);
+	if (i < 12)
+		goto failure;
+	header.magic = get_unaligned_be32(buf);
+	header.code_crc = get_unaligned_be32(buf + 4);
+	header.code_size = get_unaligned_be32(buf + 8);
+
+	if (header.magic != MAGIC_HMAC && header.magic != MAGIC_KEY_PROGRAM)
+		goto failure;
+
+	result = malloc(sizeof(struct key_program) + header.code_size);
+	if (!result)
+		goto failure;
+	if (fs_set_blk_dev(ifname, dev_part_str, fs_type))
+		goto failure;
+	i = fs_read(path, (ulong)result, 0,
+		sizeof(struct key_program) + header.code_size);
+	if (i <= 0)
+		goto failure;
+	*result = header;
+
+	crc = crc32(0, result->code, result->code_size);
+
+	if (crc != result->code_crc) {
+		printf("%s: HRC crc mismatch: %08x != %08x\n",
+		       path, crc, result->code_crc);
+		goto failure;
+	}
+	goto end;
+failure:
+	if (result) {
+		free(result);
+		result = NULL;
+	}
+end:
+	return result;
+}
+#endif
+
+#if defined(CCDM_FIRST_STAGE) || (defined CCDM_AUTO_FIRST_STAGE)
+static int first_stage_actions(void)
+{
+	int result = 0;
+	struct key_program *sd_prg = NULL;
+
+	puts("CCDM S1: start actions\n");
+#ifndef CCDM_SECOND_STAGE
+	if (tpm_continue_self_test())
+		goto failure;
+#else
+	tpm_continue_self_test();
+#endif
+	mdelay(37);
+
+	if (hre_run_program(prg_stage1_prepare, sizeof(prg_stage1_prepare)))
+		goto failure;
+
+	sd_prg = load_sd_key_program();
+	if (sd_prg) {
+		if (hre_run_program(sd_prg->code, sd_prg->code_size))
+			goto failure;
+		puts("SD code run successfully\n");
+	} else {
+		puts("no key program found on SD\n");
+		goto failure;
+	}
+	goto end;
+failure:
+	result = 1;
+end:
+	if (sd_prg)
+		free(sd_prg);
+	printf("CCDM S1: actions done (%d)\n", result);
+	return result;
+}
+#endif
+
+#ifdef CCDM_FIRST_STAGE
+static int first_stage_init(void)
+{
+	int res = 0;
+	puts("CCDM S1\n");
+	if (tpm_init() || tpm_startup(TPM_ST_CLEAR))
+		return 1;
+	res = first_stage_actions();
+#ifndef CCDM_SECOND_STAGE
+	if (!res) {
+		if (bl2_entry)
+			(*bl2_entry)();
+		res = 1;
+	}
+#endif
+	return res;
+}
+#endif
+
+#ifdef CCDM_SECOND_STAGE
+static int second_stage_init(void)
+{
+	static const char mac_suffix[] = ".mac";
+	bool did_first_stage_run = true;
+	int result = 0;
+	char *cptr, *mmcdev = NULL;
+	struct key_program *hmac_blob = NULL;
+	const char *image_path = "/ccdm.itb";
+	char *mac_path = NULL;
+	ulong image_addr;
+	size_t image_size;
+	uint32_t err;
+
+	printf("CCDM S2\n");
+	if (tpm_init())
+		return 1;
+	err = tpm_startup(TPM_ST_CLEAR);
+	if (err != TPM_INVALID_POSTINIT)
+		did_first_stage_run = false;
+
+#ifdef CCDM_AUTO_FIRST_STAGE
+	if (!did_first_stage_run && first_stage_actions())
+		goto failure;
+#else
+	if (!did_first_stage_run)
+		goto failure;
+#endif
+
+	if (hre_run_program(prg_stage2_prepare, sizeof(prg_stage2_prepare)))
+		goto failure;
+
+	/* run "prepboot" from env to get "mmcdev" set */
+	cptr = getenv("prepboot");
+	if (cptr && !run_command(cptr, 0))
+		mmcdev = getenv("mmcdev");
+	if (!mmcdev)
+		goto failure;
+
+	cptr = getenv("ramdiskimage");
+	if (cptr)
+		image_path = cptr;
+
+	mac_path = malloc(strlen(image_path) + strlen(mac_suffix) + 1);
+	if (mac_path == NULL)
+		goto failure;
+	strcpy(mac_path, image_path);
+	strcat(mac_path, mac_suffix);
+
+	/* read image from mmcdev (ccdm.itb) */
+	image_addr = (ulong)get_image_location();
+	if (fs_set_blk_dev("mmc", mmcdev, FS_TYPE_EXT))
+		goto failure;
+	image_size = fs_read(image_path, image_addr, 0, 0);
+	if (image_size <= 0)
+		goto failure;
+	printf("CCDM image found on %s, %d bytes\n", mmcdev, image_size);
+
+	hmac_blob = load_key_chunk("mmc", mmcdev, FS_TYPE_EXT, mac_path);
+	if (!hmac_blob) {
+		puts("failed to load mac file\n");
+		goto failure;
+	}
+	if (verify_program(hmac_blob)) {
+		puts("corrupted mac file\n");
+		goto failure;
+	}
+	if (check_hmac(hmac_blob, (u8 *)image_addr, image_size)) {
+		puts("image integrity could not be verified\n");
+		goto failure;
+	}
+	puts("CCDM image OK\n");
+
+	hre_run_program(prg_stage2_success, sizeof(prg_stage2_success));
+
+	goto end;
+failure:
+	result = 1;
+	hre_run_program(prg_stage_fail, sizeof(prg_stage_fail));
+end:
+	if (hmac_blob)
+		free(hmac_blob);
+	if (mac_path)
+		free(mac_path);
+	return result;
+}
+#endif
+
+int show_self_hash(void)
+{
+	struct h_reg *hash_ptr;
+#ifdef CCDM_SECOND_STAGE
+	struct h_reg hash;
+	hash_ptr = &hash;
+	if (compute_self_hash(hash_ptr))
+		return 1;
+#else
+	hash_ptr = &fix_hregs[FIX_HREG_SELF_HASH];
+#endif
+	puts("self hash: ");
+	if (hash_ptr && hash_ptr->valid)
+		print_buffer(0, hash_ptr->digest, 1, 20, 20);
+	else
+		puts("INVALID\n");
+	return 0;
+}
+
+/**
+ * @brief let the system hang.
+ *
+ * Called on error.
+ * Will stop the boot process; display a message and signal the error condition
+ * by blinking the "status" and the "finder" LED of the controller board.
+ *
+ * @note the develop version runs the blink cycle 2 times and then returns.
+ * The release version never returns.
+ */
+static void ccdm_hang(void)
+{
+	static const u64 f0 = 0x0ba3bb8ba2e880; /* blink code "finder" LED */
+	static const u64 s0 = 0x00f0f0f0f0f0f0; /* blink code "status" LED */
+	u64 f, s;
+	int i;
+#ifdef CCDM_DEVELOP
+	int j;
+#endif
+	I2C_SET_BUS(0);
+	pca9698_direction_output(0x22, 0, 0); /* Finder */
+	pca9698_direction_output(0x22, 4, 0); /* Status */
+
+	puts("### ERROR ### Please RESET the board ###\n");
+	bootstage_error(BOOTSTAGE_ID_NEED_RESET);
+#ifdef CCDM_DEVELOP
+	puts("*** ERROR ******** THIS WOULD HANG ******** ERROR ***\n");
+	puts("** but we continue since this is a DEVELOP version **\n");
+	puts("*** ERROR ******** THIS WOULD HANG ******** ERROR ***\n");
+	for (j = 2; j-- > 0;) {
+		putc('#');
+#else
+	for (;;) {
+#endif
+		f = f0;
+		s = s0;
+		for (i = 54; i-- > 0;) {
+			pca9698_set_value(0x22, 0, !(f & 1));
+			pca9698_set_value(0x22, 4, (s & 1));
+			f >>= 1;
+			s >>= 1;
+			mdelay(120);
+		}
+	}
+	puts("\ncontinue...\n");
+}
+
+int startup_ccdm_id_module(void)
+{
+	int result = 0;
+	unsigned int orig_i2c_bus;
+
+	orig_i2c_bus = I2C_GET_BUS();
+	I2C_SET_BUS(1);
+
+	/* goto end; */
+
+#ifdef CCDM_DEVELOP
+	show_self_hash();
+#endif
+#ifdef CCDM_FIRST_STAGE
+	result = first_stage_init();
+	if (result) {
+		puts("1st stage init failed\n");
+		goto failure;
+	}
+#endif
+#ifdef CCDM_SECOND_STAGE
+	result = second_stage_init();
+	if (result) {
+		puts("2nd stage init failed\n");
+		goto failure;
+	}
+#endif
+
+	goto end;
+failure:
+	result = 1;
+end:
+	I2C_SET_BUS(orig_i2c_bus);
+	if (result)
+		ccdm_hang();
+	return result;
+}
diff --git a/board/gdsys/p1022/controlcenterd-id.h b/board/gdsys/p1022/controlcenterd-id.h
new file mode 100644
index 0000000..de4770a
--- /dev/null
+++ b/board/gdsys/p1022/controlcenterd-id.h
@@ -0,0 +1,29 @@
+/*
+ * (C) Copyright 2013
+ * Reinhard Pfau, Guntermann & Drunck GmbH, reinhard.pfau at gdsys.cc
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+#ifndef __CONTROLCENTER_ID_H
+#define __CONTROLCENTER_ID_H
+
+int ccdm_compute_self_hash(void);
+int startup_ccdm_id_module(void);
+
+int show_self_hash(void);
+
+#endif /* __CONTROLCENTER_ID_H */
diff --git a/board/gdsys/p1022/controlcenterd.c b/board/gdsys/p1022/controlcenterd.c
new file mode 100644
index 0000000..be1f638
--- /dev/null
+++ b/board/gdsys/p1022/controlcenterd.c
@@ -0,0 +1,447 @@
+/*
+ * (C) Copyright 2013
+ * Dirk Eibach,  Guntermann & Drunck GmbH, dirk.eibach at gdsys.cc
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <command.h>
+#include <pci.h>
+#include <asm/processor.h>
+#include <asm/mmu.h>
+#include <asm/cache.h>
+#include <asm/immap_85xx.h>
+#include <asm/fsl_pci.h>
+#include <asm/fsl_ddr_sdram.h>
+#include <asm/fsl_serdes.h>
+#include <asm/io.h>
+#include <libfdt.h>
+#include <fdt_support.h>
+#include <fsl_mdio.h>
+#include <tsec.h>
+#include <asm/fsl_law.h>
+#include <netdev.h>
+#include <i2c.h>
+#include <pca9698.h>
+#include <watchdog.h>
+#include "../common/dp501.h"
+#include "controlcenterd-id.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+enum {
+	REG_REFLECTION_LOW = 0x0000,
+	REG_VERSIONS = 0x0004,
+	REG_FPGA_VERSION = 0x0008,
+	REG_FEATURES = 0x000C,
+	REG_TOP_INTERRUPT = 0x0010,
+	REG_TOP_INTERRUPT_SET = 0x0014,
+	REG_TOP_INTERRUPT_CLEAR = 0x0018,
+	REG_STATUS = 0x001C,
+	REG_CONTROL = 0x0020,
+	REG_TESTMEM1 = 0x100,
+	REG_DMA_WRITE_CONTROL = 0x0200,
+	REG_DMA_WRITE_BASE_ADDRESS_LOW = 0x0204,
+	REG_DMA_WRITE_BASE_ADDRESS_HIGH = 0x0208,
+	REG_DMA_WRITE_LENGTH = 0x020C,
+	REG_DMA_WRITE_HEAD = 0x0210,
+	REG_DMA_WRITE_TAIL = 0x0214,
+	REG_DMA_WRITE_MIN_INT_INTERVAL = 0x0218,
+	REG_DMA_WRITE_MAX_PACKETS_INT_INTERVAL = 0x021C,
+	REG_DMA_READ_CONTROL = 0x0300,
+	REG_DMA_READ_BASE_ADDRESS_LOW = 0x0304,
+	REG_DMA_READ_BASE_ADDRESS_HIGH = 0x0308,
+	REG_DMA_READ_LENGTH = 0x030C,
+	REG_DMA_READ_HEAD = 0x0310,
+	REG_DMA_READ_TAIL = 0x0314,
+	REG_DMA_READ_MIN_INT_INTERVAL = 0x0318,
+	REG_DMA_READ_MAX_PACKETS_INT_INTERVAL = 0x031C,
+};
+
+enum {
+	HWVER_100 = 0,
+	HWVER_110 = 1,
+	HWVER_120 = 2,
+};
+
+#ifndef CONFIG_TRAILBLAZER
+static struct pci_device_id hydra_supported[] = {
+	{ 0x6d5e, 0xcdc0 },
+	{}
+};
+
+static void hydra_initialize(void);
+#endif
+
+int board_early_init_f(void)
+{
+	ccsr_gur_t *gur = (void *)CONFIG_SYS_MPC85xx_GUTS_ADDR;
+	ccsr_gpio_t *pgpio = (void *)(CONFIG_SYS_MPC85xx_GPIO3_ADDR);
+
+	/* Reset eLBC_DIU and SPI_eLBC in case we are booting from SD */
+	clrsetbits_be32(&gur->pmuxcr, 0x00600000, 0x80000000);
+
+	/* Set pmuxcr to allow both i2c1 and i2c2 */
+	setbits_be32(&gur->pmuxcr, 0x00001000);
+
+	/* Set pmuxcr to enable GPIO 3_11-3_13 */
+	setbits_be32(&gur->pmuxcr, 0x00000010);
+
+	/* Set pmuxcr to enable GPIO 2_31,3_9+10 */
+	setbits_be32(&gur->pmuxcr, 0x00000020);
+
+	/* Set pmuxcr to enable GPIO 2_28-2_30 */
+	setbits_be32(&gur->pmuxcr, 0x000000c0);
+
+	/* Set pmuxcr to enable GPIO 3_20-3_22 */
+	setbits_be32(&gur->pmuxcr2, 0x03000000);
+
+	/* Set pmuxcr to enable IRQ0-2 */
+	clrbits_be32(&gur->pmuxcr, 0x00000300);
+
+	/* Set pmuxcr to disable IRQ3-11 */
+	setbits_be32(&gur->pmuxcr, 0x000000F0);
+
+	/* Read back the register to synchronize the write. */
+	in_be32(&gur->pmuxcr);
+
+	/* Set the pin muxing to enable ETSEC2. */
+	clrbits_be32(&gur->pmuxcr2, 0x001F8000);
+
+#ifdef CONFIG_TRAILBLAZER
+	/*
+	 * GPIO3_10 SPERRTRIGGER
+	 */
+	setbits_be32(&pgpio->gpdir, 0x00200000);
+	clrbits_be32(&pgpio->gpdat, 0x00200000);
+	udelay(100);
+	setbits_be32(&pgpio->gpdat, 0x00200000);
+	udelay(100);
+	clrbits_be32(&pgpio->gpdat, 0x00200000);
+#endif
+
+	/*
+	 * GPIO3_11 CPU-TO-FPGA-RESET#
+	 */
+	setbits_be32(&pgpio->gpdir, 0x00100000);
+	clrbits_be32(&pgpio->gpdat, 0x00100000);
+
+	/*
+	 * GPIO3_21 CPU-STATUS-WATCHDOG-TRIGGER#
+	 */
+	setbits_be32(&pgpio->gpdir, 0x00000400);
+
+	return 0;
+}
+
+int checkboard(void)
+{
+	printf("Board: ControlCenter DIGITAL\n");
+
+	return 0;
+}
+
+int misc_init_r(void)
+{
+	return 0;
+}
+
+/*
+ * A list of PCI and SATA slots
+ */
+enum slot_id {
+	SLOT_PCIE1 = 1,
+	SLOT_PCIE2,
+	SLOT_PCIE3,
+	SLOT_PCIE4,
+	SLOT_PCIE5,
+	SLOT_SATA1,
+	SLOT_SATA2
+};
+
+/*
+ * This array maps the slot identifiers to their names on the P1022DS board.
+ */
+static const char * const slot_names[] = {
+	[SLOT_PCIE1] = "Slot 1",
+	[SLOT_PCIE2] = "Slot 2",
+	[SLOT_PCIE3] = "Slot 3",
+	[SLOT_PCIE4] = "Slot 4",
+	[SLOT_PCIE5] = "Mini-PCIe",
+	[SLOT_SATA1] = "SATA 1",
+	[SLOT_SATA2] = "SATA 2",
+};
+
+/*
+ * This array maps a given SERDES configuration and SERDES device to the PCI or
+ * SATA slot that it connects to.  This mapping is hard-coded in the FPGA.
+ */
+static u8 serdes_dev_slot[][SATA2 + 1] = {
+	[0x01] = { [PCIE3] = SLOT_PCIE4, [PCIE2] = SLOT_PCIE5 },
+	[0x02] = { [SATA1] = SLOT_SATA1, [SATA2] = SLOT_SATA2 },
+	[0x09] = { [PCIE1] = SLOT_PCIE1, [PCIE3] = SLOT_PCIE4,
+		   [PCIE2] = SLOT_PCIE5 },
+	[0x16] = { [PCIE1] = SLOT_PCIE1, [PCIE3] = SLOT_PCIE2,
+		   [PCIE2] = SLOT_PCIE3,
+		   [SATA1] = SLOT_SATA1, [SATA2] = SLOT_SATA2 },
+	[0x17] = { [PCIE1] = SLOT_PCIE1, [PCIE3] = SLOT_PCIE2,
+		   [PCIE2] = SLOT_PCIE3 },
+	[0x1a] = { [PCIE1] = SLOT_PCIE1, [PCIE2] = SLOT_PCIE3,
+		   [PCIE2] = SLOT_PCIE3,
+		   [SATA1] = SLOT_SATA1, [SATA2] = SLOT_SATA2 },
+	[0x1c] = { [PCIE1] = SLOT_PCIE1,
+		   [SATA1] = SLOT_SATA1, [SATA2] = SLOT_SATA2 },
+	[0x1e] = { [PCIE1] = SLOT_PCIE1, [PCIE3] = SLOT_PCIE3 },
+	[0x1f] = { [PCIE1] = SLOT_PCIE1 },
+};
+
+
+/*
+ * Returns the name of the slot to which the PCIe or SATA controller is
+ * connected
+ */
+const char *board_serdes_name(enum srds_prtcl device)
+{
+	ccsr_gur_t *gur = (void *)CONFIG_SYS_MPC85xx_GUTS_ADDR;
+	u32 pordevsr = in_be32(&gur->pordevsr);
+	unsigned int srds_cfg = (pordevsr & MPC85xx_PORDEVSR_IO_SEL) >>
+				MPC85xx_PORDEVSR_IO_SEL_SHIFT;
+	enum slot_id slot = serdes_dev_slot[srds_cfg][device];
+	const char *name = slot_names[slot];
+
+	if (name)
+		return name;
+	else
+		return "Nothing";
+}
+
+void hw_watchdog_reset(void)
+{
+	ccsr_gpio_t *pgpio = (void *)(CONFIG_SYS_MPC85xx_GPIO3_ADDR);
+
+	clrbits_be32(&pgpio->gpdat, 0x00000400);
+	setbits_be32(&pgpio->gpdat, 0x00000400);
+}
+
+#ifdef CONFIG_TRAILBLAZER
+int do_bootd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+	int rcode = 0;
+
+	if (run_command(getenv("bootcmd"), flag) < 0)
+		rcode = 1;
+	return rcode;
+}
+
+int board_early_init_r(void)
+{
+	ccsr_gpio_t *pgpio = (void *)(CONFIG_SYS_MPC85xx_GPIO3_ADDR);
+
+	/*
+	 * GPIO3_12 PPC_SYSTEMREADY#
+	 */
+	setbits_be32(&pgpio->gpdir, 0x00080000);
+	setbits_be32(&pgpio->gpodr, 0x00080000);
+	clrbits_be32(&pgpio->gpdat, 0x00080000);
+
+	return ccdm_compute_self_hash();
+}
+
+int last_stage_init(void)
+{
+	startup_ccdm_id_module();
+	return 0;
+}
+
+#else
+void pci_init_board(void)
+{
+	fsl_pcie_init_board(0);
+
+	hydra_initialize();
+}
+
+int board_early_init_r(void)
+{
+	unsigned int k = 0;
+	ccsr_gpio_t *pgpio = (void *)(CONFIG_SYS_MPC85xx_GPIO3_ADDR);
+
+	/* wait for FPGA configuration to finish */
+	while (!pca9698_get_value(0x22, 11) && (k++ < 30))
+		udelay(100000);
+
+	if (k > 30) {
+		puts("FPGA configuration timed out.\n");
+	} else {
+		/* clear FPGA reset */
+		udelay(1000);
+		setbits_be32(&pgpio->gpdat, 0x00100000);
+	}
+
+	/* give time for PCIe link training */
+	udelay(100000);
+
+	/*
+	 * GPIO3_12 PPC_SYSTEMREADY#
+	 */
+	setbits_be32(&pgpio->gpdir, 0x00080000);
+	setbits_be32(&pgpio->gpodr, 0x00080000);
+	clrbits_be32(&pgpio->gpdat, 0x00080000);
+
+	return 0;
+}
+
+int last_stage_init(void)
+{
+	/* Turn on Parade DP501 */
+	pca9698_direction_output(0x22, 7, 1);
+	udelay(500000);
+
+	dp501_powerup(0x08);
+
+	startup_ccdm_id_module();
+
+	return 0;
+}
+
+/*
+ * Initialize on-board and/or PCI Ethernet devices
+ *
+ * Returns:
+ *      <0, error
+ *       0, no ethernet devices found
+ *      >0, number of ethernet devices initialized
+ */
+int board_eth_init(bd_t *bis)
+{
+	struct fsl_pq_mdio_info mdio_info;
+	struct tsec_info_struct tsec_info[2];
+	unsigned int num = 0;
+
+#ifdef CONFIG_TSEC1
+	SET_STD_TSEC_INFO(tsec_info[num], 1);
+	num++;
+#endif
+#ifdef CONFIG_TSEC2
+	SET_STD_TSEC_INFO(tsec_info[num], 2);
+	num++;
+#endif
+
+	mdio_info.regs = (struct tsec_mii_mng *)CONFIG_SYS_MDIO_BASE_ADDR;
+	mdio_info.name = DEFAULT_MII_NAME;
+	fsl_pq_mdio_init(bis, &mdio_info);
+
+	return tsec_eth_init(bis, tsec_info, num) + pci_eth_init(bis);
+}
+
+#ifdef CONFIG_OF_BOARD_SETUP
+void ft_board_setup(void *blob, bd_t *bd)
+{
+	phys_addr_t base;
+	phys_size_t size;
+
+	ft_cpu_setup(blob, bd);
+
+	base = getenv_bootm_low();
+	size = getenv_bootm_size();
+
+	fdt_fixup_memory(blob, (u64)base, (u64)size);
+
+#ifdef CONFIG_HAS_FSL_DR_USB
+	fdt_fixup_dr_usb(blob, bd);
+#endif
+
+	FT_FSL_PCI_SETUP;
+}
+#endif
+
+static void hydra_initialize(void)
+{
+	unsigned int 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;
+		uint8_t *hw_addr;
+		u32 versions;
+		u32 fpga_version;
+		u32 fpga_features;
+
+		unsigned hardware_version;
+		unsigned feature_uart_channels;
+		unsigned feature_sb_channels;
+
+		/* 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 */
+		hw_addr = pci_map_bar(devno, PCI_BASE_ADDRESS_0,
+			PCI_REGION_MEM);
+
+		versions = readl(hw_addr + REG_VERSIONS);
+		fpga_version = readl(hw_addr + REG_FPGA_VERSION);
+		fpga_features = readl(hw_addr + REG_FEATURES);
+
+		hardware_version = versions & 0xf;
+		feature_uart_channels = (fpga_features >> 6) & 0x1f;
+		feature_sb_channels = fpga_features & 0x1f;
+
+		printf("FPGA%d: ", i);
+
+		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, features:",
+		       fpga_version / 100, fpga_version % 100);
+
+		printf(" %d uart channel(s)", feature_uart_channels);
+		printf(" %d sideband channel(s)\n", feature_sb_channels);
+	}
+}
+#endif
diff --git a/board/gdsys/p1022/ddr.c b/board/gdsys/p1022/ddr.c
new file mode 100644
index 0000000..4a652de
--- /dev/null
+++ b/board/gdsys/p1022/ddr.c
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2010 Freescale Semiconductor, Inc.
+ * Authors: Srikanth Srinivasan <srikanth.srinivasan@freescale.com>
+ *          Timur Tabi <timur@freescale.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ */
+
+#include <common.h>
+#include <i2c.h>
+
+#include <asm/fsl_ddr_sdram.h>
+#include <asm/fsl_ddr_dimm_params.h>
+
+void fsl_ddr_board_options(memctl_options_t *popts, dimm_params_t *pdimm,
+			   unsigned int ctrl_num)
+{
+	unsigned int i;
+
+	if (ctrl_num) {
+		printf("Wrong parameter for controller number %d", ctrl_num);
+		return;
+	}
+	if (!pdimm->n_ranks)
+		return;
+
+	/* set odt_rd_cfg and odt_wr_cfg. */
+	for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
+		popts->cs_local_opts[i].odt_rd_cfg = 0;
+		popts->cs_local_opts[i].odt_wr_cfg = 1;
+	}
+
+	popts->clk_adjust = 5;
+	popts->cpo_override = 0x1f;
+	popts->write_data_delay = 2;
+	popts->half_strength_driver_enable = 1;
+
+	/* Per AN4039, enable ZQ calibration. */
+	popts->zq_en = 1;
+}
+
+#ifdef CONFIG_SPD_EEPROM
+/*
+ * we only have a "fake" SPD-EEPROM here, which has 16 bit addresses
+ */
+void get_spd(generic_spd_eeprom_t *spd, u8 i2c_address)
+{
+	int ret = i2c_read(i2c_address, 0, 2, (uchar *)spd,
+				sizeof(generic_spd_eeprom_t));
+
+	if (ret) {
+		if (i2c_address ==
+#ifdef SPD_EEPROM_ADDRESS
+				SPD_EEPROM_ADDRESS
+#elif defined(SPD_EEPROM_ADDRESS1)
+				SPD_EEPROM_ADDRESS1
+#endif
+				) {
+			printf("DDR: failed to read SPD from address %u\n",
+			       i2c_address);
+		} else {
+			debug("DDR: failed to read SPD from address %u\n",
+			      i2c_address);
+		}
+		memset(spd, 0, sizeof(generic_spd_eeprom_t));
+	}
+}
+#endif
diff --git a/board/gdsys/p1022/diu.c b/board/gdsys/p1022/diu.c
new file mode 100644
index 0000000..52ac1e6
--- /dev/null
+++ b/board/gdsys/p1022/diu.c
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2010-2011 Freescale Semiconductor, Inc.
+ * Authors: Timur Tabi <timur@freescale.com>
+ *
+ * FSL DIU Framebuffer driver
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ */
+
+#include <common.h>
+#include <command.h>
+#include <linux/ctype.h>
+#include <asm/io.h>
+#include <stdio_dev.h>
+#include <video_fb.h>
+#include <fsl_diu_fb.h>
+
+#define PMUXCR_ELBCDIU_MASK	0xc0000000
+#define PMUXCR_ELBCDIU_NOR16	0x80000000
+#define PMUXCR_ELBCDIU_DIU	0x40000000
+
+/*
+ * DIU Area Descriptor
+ *
+ * Note that we need to byte-swap the value before it's written to the AD
+ * register.  So even though the registers don't look like they're in the same
+ * bit positions as they are on the MPC8610, the same value is written to the
+ * AD register on the MPC8610 and on the P1022.
+ */
+#define AD_BYTE_F		0x10000000
+#define AD_ALPHA_C_SHIFT	25
+#define AD_BLUE_C_SHIFT		23
+#define AD_GREEN_C_SHIFT	21
+#define AD_RED_C_SHIFT		19
+#define AD_PIXEL_S_SHIFT	16
+#define AD_COMP_3_SHIFT		12
+#define AD_COMP_2_SHIFT		8
+#define AD_COMP_1_SHIFT		4
+#define AD_COMP_0_SHIFT		0
+
+/*
+ * Variables used by the DIU/LBC switching code.  It's safe to makes these
+ * global, because the DIU requires DDR, so we'll only run this code after
+ * relocation.
+ */
+static u32 pmuxcr;
+
+void diu_set_pixel_clock(unsigned int pixclock)
+{
+	ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
+	unsigned long speed_ccb, temp;
+	u32 pixval;
+
+	speed_ccb = get_bus_freq(0);
+	temp = 1000000000 / pixclock;
+	temp *= 1000;
+	pixval = speed_ccb / temp;
+	debug("DIU pixval = %u\n", pixval);
+
+	/* Modify PXCLK in GUTS CLKDVDR */
+	temp = in_be32(&gur->clkdvdr) & 0x2000FFFF;
+	out_be32(&gur->clkdvdr, temp);			/* turn off clock */
+	out_be32(&gur->clkdvdr, temp | 0x80000000 | ((pixval & 0x1F) << 16));
+}
+
+int platform_diu_init(unsigned int xres, unsigned int yres, const char *port)
+{
+	ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
+	u32 pixel_format;
+
+	pixel_format = cpu_to_le32(AD_BYTE_F | (3 << AD_ALPHA_C_SHIFT) |
+		(0 << AD_BLUE_C_SHIFT) | (1 << AD_GREEN_C_SHIFT) |
+		(2 << AD_RED_C_SHIFT) | (8 << AD_COMP_3_SHIFT) |
+		(8 << AD_COMP_2_SHIFT) | (8 << AD_COMP_1_SHIFT) |
+		(8 << AD_COMP_0_SHIFT) | (3 << AD_PIXEL_S_SHIFT));
+
+	printf("DIU:   Switching to %ux%u\n", xres, yres);
+
+	/* Set PMUXCR to switch the muxed pins from the LBC to the DIU */
+	clrsetbits_be32(&gur->pmuxcr, PMUXCR_ELBCDIU_MASK, PMUXCR_ELBCDIU_DIU);
+	pmuxcr = in_be32(&gur->pmuxcr);
+
+	return fsl_diu_init(xres, yres, pixel_format, 0);
+}
diff --git a/board/gdsys/p1022/law.c b/board/gdsys/p1022/law.c
new file mode 100644
index 0000000..96f38f7
--- /dev/null
+++ b/board/gdsys/p1022/law.c
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2010 Freescale Semiconductor, Inc.
+ * Authors: Srikanth Srinivasan <srikanth.srinivasan@freescale.com>
+ *          Timur Tabi <timur@freescale.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ */
+
+#include <common.h>
+#include <asm/fsl_law.h>
+#include <asm/mmu.h>
+
+struct law_entry law_table[] = {
+	SET_LAW(CONFIG_SYS_ELBC_BASE_PHYS, LAW_SIZE_1M, LAW_TRGT_IF_LBC),
+};
+
+int num_law_entries = ARRAY_SIZE(law_table);
diff --git a/board/gdsys/p1022/sdhc_boot.c b/board/gdsys/p1022/sdhc_boot.c
new file mode 100644
index 0000000..e432318
--- /dev/null
+++ b/board/gdsys/p1022/sdhc_boot.c
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <mmc.h>
+#include <malloc.h>
+
+/*
+ * The environment variables are written to just after the u-boot image
+ * on SDCard, so we must read the MBR to get the start address and code
+ * length of the u-boot image, then calculate the address of the env.
+ */
+#define ESDHC_BOOT_IMAGE_SIZE	0x48
+#define ESDHC_BOOT_IMAGE_ADDR	0x50
+
+int mmc_get_env_addr(struct mmc *mmc, u32 *env_addr)
+{
+	u8 *tmp_buf;
+	u32 blklen, code_offset, code_len, n;
+
+	blklen = mmc->read_bl_len;
+	tmp_buf = malloc(blklen);
+	if (!tmp_buf)
+		return 1;
+
+	/* read out the first block, get the config data information */
+	n = mmc->block_dev.block_read(mmc->block_dev.dev, 0, 1, tmp_buf);
+	if (!n) {
+		free(tmp_buf);
+		return 1;
+	}
+
+	/* Get the Source Address, from offset 0x50 */
+	code_offset = *(u32 *)(tmp_buf + ESDHC_BOOT_IMAGE_ADDR);
+
+	/* Get the code size from offset 0x48 */
+	code_len = *(u32 *)(tmp_buf + ESDHC_BOOT_IMAGE_SIZE);
+
+	*env_addr = code_offset + code_len;
+
+	free(tmp_buf);
+
+	return 0;
+}
diff --git a/board/gdsys/p1022/tlb.c b/board/gdsys/p1022/tlb.c
new file mode 100644
index 0000000..9cad692
--- /dev/null
+++ b/board/gdsys/p1022/tlb.c
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2010 Freescale Semiconductor, Inc.
+ * Authors: Srikanth Srinivasan <srikanth.srinivasan@freescale.com>
+ *          Timur Tabi <timur@freescale.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ */
+
+#include <common.h>
+#include <asm/mmu.h>
+
+struct fsl_e_tlb_entry tlb_table[] = {
+	/* TLB 0 - for temp stack in cache */
+	SET_TLB_ENTRY(0, CONFIG_SYS_INIT_RAM_ADDR, CONFIG_SYS_INIT_RAM_ADDR,
+		      MAS3_SX|MAS3_SW|MAS3_SR, 0,
+		      0, 0, BOOKE_PAGESZ_4K, 0),
+	SET_TLB_ENTRY(0, CONFIG_SYS_INIT_RAM_ADDR + 4 * 1024,
+		      CONFIG_SYS_INIT_RAM_ADDR + 4 * 1024,
+		      MAS3_SX|MAS3_SW|MAS3_SR, 0,
+		      0, 0, BOOKE_PAGESZ_4K, 0),
+	SET_TLB_ENTRY(0, CONFIG_SYS_INIT_RAM_ADDR + 8 * 1024,
+		      CONFIG_SYS_INIT_RAM_ADDR + 8 * 1024,
+		      MAS3_SX|MAS3_SW|MAS3_SR, 0,
+		      0, 0, BOOKE_PAGESZ_4K, 0),
+	SET_TLB_ENTRY(0, CONFIG_SYS_INIT_RAM_ADDR + 12 * 1024,
+		      CONFIG_SYS_INIT_RAM_ADDR + 12 * 1024,
+		      MAS3_SX|MAS3_SW|MAS3_SR, 0,
+		      0, 0, BOOKE_PAGESZ_4K, 0),
+
+	/* TLB 1 */
+	/* *I*** - Covers boot page */
+	SET_TLB_ENTRY(1, 0xfffff000, 0xfffff000,
+		      MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I,
+		      0, 0, BOOKE_PAGESZ_4K, 1),
+
+	/* *I*G* - CCSRBAR */
+	SET_TLB_ENTRY(1, CONFIG_SYS_CCSRBAR, CONFIG_SYS_CCSRBAR_PHYS,
+		      MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
+		      0, 1, BOOKE_PAGESZ_1M, 1),
+
+	/* *I*G* - eLBC */
+	SET_TLB_ENTRY(1, CONFIG_SYS_ELBC_BASE, CONFIG_SYS_ELBC_BASE_PHYS,
+		      MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
+		      0, 2, BOOKE_PAGESZ_1M, 1),
+
+#if defined(CONFIG_TRAILBLAZER)
+	/* *I*G - L2SRAM */
+	SET_TLB_ENTRY(1, CONFIG_SYS_INIT_L2_ADDR, CONFIG_SYS_INIT_L2_ADDR_PHYS,
+		      MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
+		      0, 9, BOOKE_PAGESZ_256K, 1),
+#else
+	/* *I*G* - PCI */
+	SET_TLB_ENTRY(1, CONFIG_SYS_PCIE1_MEM_VIRT, CONFIG_SYS_PCIE1_MEM_PHYS,
+		      MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
+		      0, 3, BOOKE_PAGESZ_256M, 1),
+	SET_TLB_ENTRY(1, CONFIG_SYS_PCIE1_MEM_VIRT + 0x10000000,
+		      CONFIG_SYS_PCIE1_MEM_PHYS + 0x10000000,
+		      MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
+		      0, 4, BOOKE_PAGESZ_256M, 1),
+
+	/* *I*G* - PCI I/O */
+	SET_TLB_ENTRY(1, CONFIG_SYS_PCIE1_IO_VIRT, CONFIG_SYS_PCIE1_IO_PHYS,
+		      MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
+		      0, 5, BOOKE_PAGESZ_256K, 1),
+
+#ifdef CONFIG_SYS_RAMBOOT
+	SET_TLB_ENTRY(1, CONFIG_SYS_DDR_SDRAM_BASE, CONFIG_SYS_DDR_SDRAM_BASE,
+		      MAS3_SX|MAS3_SW|MAS3_SR, 0,
+		      0, 6, BOOKE_PAGESZ_1G, 1),
+#endif
+#endif
+};
+
+int num_tlb_entries = ARRAY_SIZE(tlb_table);
diff --git a/boards.cfg b/boards.cfg
index e2a8d42..7e80911 100644
--- a/boards.cfg
+++ b/boards.cfg
@@ -904,6 +904,13 @@ BSC9132QDS_SDCARD_DDRCLK100  powerpc     mpc85xx     bsc9132qds          freesca
 BSC9132QDS_SDCARD_DDRCLK133  powerpc     mpc85xx     bsc9132qds          freescale      -           BSC9132QDS:BSC9132QDS,SDCARD,SYS_CLK_100_DDR_133
 BSC9132QDS_SPIFLASH_DDRCLK100 powerpc    mpc85xx     bsc9132qds          freescale      -           BSC9132QDS:BSC9132QDS,SPIFLASH,SYS_CLK_100_DDR_100
 BSC9132QDS_SPIFLASH_DDRCLK133 powerpc    mpc85xx     bsc9132qds          freescale      -           BSC9132QDS:BSC9132QDS,SPIFLASH,SYS_CLK_100_DDR_133
+controlcenterd_36BIT_SDCARD         powerpc     mpc85xx     p1022             gdsys      -           controlcenterd:36BIT,SDCARD
+controlcenterd_36BIT_SDCARD_DEVELOP powerpc     mpc85xx     p1022             gdsys      -           controlcenterd:36BIT,SDCARD,DEVELOP
+controlcenterd_36BIT_SPIFLASH       powerpc     mpc85xx     p1022             gdsys      -           controlcenterd:36BIT,SPIFLASH
+controlcenterd_SDCARD               powerpc     mpc85xx     p1022             gdsys      -           controlcenterd:SDCARD
+controlcenterd_SPIFLASH             powerpc     mpc85xx     p1022             gdsys      -           controlcenterd:SPIFLASH
+controlcenterd_TRAILBLAZER          powerpc     mpc85xx     p1022             gdsys      -           controlcenterd:TRAILBLAZER,SPIFLASH
+controlcenterd_TRAILBLAZER_DEVELOP  powerpc     mpc85xx     p1022             gdsys      -           controlcenterd:TRAILBLAZER,SPIFLASH,DEVELOP
 stxgp3                       powerpc     mpc85xx     stxgp3              stx
 stxssa                       powerpc     mpc85xx     stxssa              stx            -           stxssa
 stxssa_4M                    powerpc     mpc85xx     stxssa              stx            -           stxssa:STXSSA_4M
diff --git a/include/configs/controlcenterd.h b/include/configs/controlcenterd.h
new file mode 100644
index 0000000..9236aa6
--- /dev/null
+++ b/include/configs/controlcenterd.h
@@ -0,0 +1,528 @@
+/*
+ * (C) Copyright 2013
+ * Dirk Eibach, Guntermann & Drunck GmbH, dirk.eibach at gdsys.cc
+ *
+ * based on P1022DS.h
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+#ifdef CONFIG_36BIT
+#define CONFIG_PHYS_64BIT
+#endif
+
+#ifdef CONFIG_SDCARD
+#define CONFIG_RAMBOOT_SDCARD
+#endif
+
+#ifdef CONFIG_SPIFLASH
+#define CONFIG_RAMBOOT_SPIFLASH
+#endif
+
+/* High Level Configuration Options */
+#define CONFIG_BOOKE			/* BOOKE */
+#define CONFIG_E500			/* BOOKE e500 family */
+#define CONFIG_MPC85xx			/* MPC8540/60/55/41/48 */
+#define CONFIG_P1022
+#define CONFIG_CONTROLCENTERD
+#define CONFIG_MP			/* support multiple processors */
+
+#define CONFIG_SYS_NO_FLASH
+#define CONFIG_ENABLE_36BIT_PHYS
+#define CONFIG_FSL_LAW			/* Use common FSL init code */
+
+#ifdef CONFIG_TRAILBLAZER
+#define CONFIG_IDENT_STRING	" controlcenterd trailblazer 0.01"
+#else
+#define CONFIG_IDENT_STRING	" controlcenterd 0.01"
+#endif
+
+#ifdef CONFIG_PHYS_64BIT
+#define CONFIG_ADDR_MAP
+#define CONFIG_SYS_NUM_ADDR_MAP		16	/* number of TLB1 entries */
+#endif
+
+#define CONFIG_L2_CACHE
+#define CONFIG_BTB
+
+#define CONFIG_SYS_CLK_FREQ	66666600
+#define CONFIG_DDR_CLK_FREQ	66666600
+
+#define CONFIG_SYS_RAMBOOT
+
+#ifdef CONFIG_TRAILBLAZER
+
+#define CONFIG_SYS_TEXT_BASE		0xf8fc0000
+#define CONFIG_RESET_VECTOR_ADDRESS	0xf8fffffc
+#define CONFIG_SYS_MONITOR_LEN		(256 * 1024)
+
+/*
+ * Config the L2 Cache
+ */
+#define CONFIG_SYS_INIT_L2_ADDR		0xf8fc0000
+#ifdef CONFIG_PHYS_64BIT
+#define CONFIG_SYS_INIT_L2_ADDR_PHYS	0xff8fc0000ull
+#else
+#define CONFIG_SYS_INIT_L2_ADDR_PHYS	CONFIG_SYS_INIT_L2_ADDR
+#endif
+#define CONFIG_SYS_L2_SIZE		(256 << 10)
+#define CONFIG_SYS_INIT_L2_END	(CONFIG_SYS_INIT_L2_ADDR + CONFIG_SYS_L2_SIZE)
+
+#else /* CONFIG_TRAILBLAZER */
+
+#define CONFIG_SYS_TEXT_BASE		0x11000000
+#define CONFIG_RESET_VECTOR_ADDRESS	0x1107fffc
+#define CONFIG_SYS_MONITOR_LEN		(512 * 1024)
+
+#endif /* CONFIG_TRAILBLAZER */
+
+#define CONFIG_SYS_MONITOR_BASE		CONFIG_SYS_TEXT_BASE
+#define CONFIG_SYS_MALLOC_LEN		(10 * 1024 * 1024)
+
+
+/*
+ * Memory map
+ *
+ * 0x0000_0000	0x3fff_ffff	DDR			1G Cacheable
+ * 0xc000_0000	0xdfff_ffff	PCI Express Mem		512M non-cacheable
+ * 0xffc0_0000	0xffc2_ffff	PCI IO range		192K non-cacheable
+ *
+ * Localbus non-cacheable
+ * 0xe000_0000	0xe00f_ffff	eLBC			1M non-cacheable
+ * 0xf8fc0000	0xf8ff_ffff	L2 SRAM			256k Cacheable
+ * 0xffd0_0000	0xffd0_3fff	L1 for stack		16K Cacheable TLB0
+ * 0xffe0_0000	0xffef_ffff	CCSR			1M non-cacheable
+ */
+
+#define CONFIG_SYS_INIT_RAM_LOCK
+#define CONFIG_SYS_INIT_RAM_ADDR	0xffd00000 /* Initial L1 address */
+#define CONFIG_SYS_INIT_RAM_SIZE	0x00004000 /* used area in RAM */
+#define CONFIG_SYS_GBL_DATA_OFFSET	\
+	(CONFIG_SYS_INIT_RAM_SIZE - GENERATED_GBL_DATA_SIZE)
+#define CONFIG_SYS_INIT_SP_OFFSET	CONFIG_SYS_GBL_DATA_OFFSET
+
+#ifdef CONFIG_TRAILBLAZER
+/* leave CCSRBAR@default, because u-boot expects it to be exactly there */
+#define CONFIG_SYS_CCSRBAR		CONFIG_SYS_CCSRBAR_DEFAULT
+#else
+#define CONFIG_SYS_CCSRBAR		0xffe00000
+#endif
+#define CONFIG_SYS_CCSRBAR_PHYS_LOW	CONFIG_SYS_CCSRBAR
+#define CONFIG_SYS_MPC85xx_GPIO3_ADDR	(CONFIG_SYS_CCSRBAR+0xf200)
+
+/*
+ * DDR Setup
+ */
+
+#define CONFIG_SYS_DDR_SDRAM_BASE	0x00000000
+#define CONFIG_SYS_SDRAM_BASE		CONFIG_SYS_DDR_SDRAM_BASE
+#define CONFIG_SYS_SDRAM_SIZE 1024
+#define CONFIG_VERY_BIG_RAM
+
+#define CONFIG_FSL_DDR3
+#define CONFIG_NUM_DDR_CONTROLLERS	1
+#define CONFIG_DIMM_SLOTS_PER_CTLR	1
+#define CONFIG_CHIP_SELECTS_PER_CTRL	(2 * CONFIG_DIMM_SLOTS_PER_CTLR)
+
+#define CONFIG_SYS_MEMTEST_START	0x00000000
+#define CONFIG_SYS_MEMTEST_END		0x3fffffff
+
+#ifdef CONFIG_TRAILBLAZER
+#define CONFIG_SPD_EEPROM
+#define SPD_EEPROM_ADDRESS 0x52
+/*#define CONFIG_FSL_DDR_INTERACTIVE*/
+#endif
+
+/*
+ * Local Bus Definitions
+ */
+#define CONFIG_FSL_ELBC			/* Has Enhanced localbus controller */
+
+#define CONFIG_SYS_ELBC_BASE		0xe0000000
+#ifdef CONFIG_PHYS_64BIT
+#define CONFIG_SYS_ELBC_BASE_PHYS	0xfe0000000ull
+#else
+#define CONFIG_SYS_ELBC_BASE_PHYS	CONFIG_SYS_ELBC_BASE
+#endif
+
+#define CONFIG_UART_BR_PRELIM  \
+	(BR_PHYS_ADDR((CONFIG_SYS_ELBC_BASE_PHYS)) | BR_PS_8 | BR_V)
+#define CONFIG_UART_OR_PRELIM	(OR_AM_32KB | 0xff7)
+
+#define CONFIG_SYS_BR0_PRELIM	0 /* CS0 was originally intended for FPGA */
+#define CONFIG_SYS_OR0_PRELIM	0 /* debugging, was never used */
+
+#define CONFIG_SYS_BR1_PRELIM	CONFIG_UART_BR_PRELIM
+#define CONFIG_SYS_OR1_PRELIM	CONFIG_UART_OR_PRELIM
+
+/*
+ * Serial Port
+ */
+#define CONFIG_CONS_INDEX		2
+#define CONFIG_SYS_NS16550
+#define CONFIG_SYS_NS16550_SERIAL
+#define CONFIG_SYS_NS16550_REG_SIZE	1
+#define CONFIG_SYS_NS16550_CLK		get_bus_freq(0)
+
+#define CONFIG_SYS_BAUDRATE_TABLE	\
+	{300, 600, 1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200}
+
+#define CONFIG_SYS_NS16550_COM1	(CONFIG_SYS_CCSRBAR+0x4500)
+#define CONFIG_SYS_NS16550_COM2	(CONFIG_SYS_CCSRBAR+0x4600)
+
+/*
+ * I2C
+ */
+#define CONFIG_HARD_I2C
+#define CONFIG_I2C_MULTI_BUS
+#define CONFIG_CMD_I2C
+
+#define CONFIG_FSL_I2C
+#define CONFIG_SYS_I2C_OFFSET		0x3000
+#define CONFIG_SYS_I2C2_OFFSET		0x3100
+#define CONFIG_SYS_I2C_SPEED		400000
+#define CONFIG_SYS_I2C_SLAVE		0x7F
+/* Probing DP501 I2C-Bridge will hang */
+#define CONFIG_SYS_I2C_NOPROBES		{ {0, 0x30}, {0, 0x37}, {0, 0x3a}, \
+					  {0, 0x3b}, {0, 0x50} }
+
+#define CONFIG_PCA9698			/* NXP PCA9698 */
+
+#define CONFIG_CMD_EEPROM
+#define CONFIG_SYS_I2C_EEPROM_ADDR 0x52
+#define CONFIG_SYS_I2C_EEPROM_ADDR_LEN 2
+
+#ifndef CONFIG_TRAILBLAZER
+/*
+ * eSPI - Enhanced SPI
+ */
+#define CONFIG_HARD_SPI
+#define CONFIG_FSL_ESPI
+
+#define CONFIG_SPI_FLASH
+#define CONFIG_SPI_FLASH_STMICRO
+
+#define CONFIG_CMD_SF
+#define CONFIG_SF_DEFAULT_SPEED		10000000
+#define CONFIG_SF_DEFAULT_MODE		0
+#endif
+
+/*
+ * TPM
+ */
+#define CONFIG_TPM_ATMEL_TWI
+#define CONFIG_TPM
+#define CONFIG_TPM_AUTH_SESSIONS
+#define CONFIG_SHA1
+#define CONFIG_CMD_TPM
+
+/*
+ * MMC
+ */
+#define CONFIG_MMC
+#define CONFIG_GENERIC_MMC
+#define CONFIG_CMD_MMC
+
+#define CONFIG_FSL_ESDHC
+#define CONFIG_SYS_FSL_ESDHC_ADDR	CONFIG_SYS_MPC85xx_ESDHC_ADDR
+
+
+#ifndef CONFIG_TRAILBLAZER
+
+/*
+ * Video
+ */
+#define CONFIG_FSL_DIU_FB
+#define CONFIG_SYS_DIU_ADDR	(CONFIG_SYS_CCSRBAR + 0x10000)
+#define CONFIG_VIDEO
+#define CONFIG_CFB_CONSOLE
+#define CONFIG_VGA_AS_SINGLE_DEVICE
+#define CONFIG_CMD_BMP
+
+/*
+ * General PCI
+ * Memory space is mapped 1-1, but I/O space must start from 0.
+ */
+#define CONFIG_PCI			/* Enable PCI/PCIE */
+#define CONFIG_PCIE1			/* PCIE controler 1 (slot 1) */
+#define CONFIG_PCI_INDIRECT_BRIDGE
+#define CONFIG_PCI_PNP			/* do pci plug-and-play */
+#define CONFIG_PCI_SCAN_SHOW		/* show pci devices on startup */
+#define CONFIG_SYS_PCI_64BIT		/* enable 64-bit PCI resources */
+#define CONFIG_CMD_PCI
+
+#define CONFIG_FSL_PCI_INIT		/* Use common FSL init code */
+#define CONFIG_FSL_PCIE_RESET		/* need PCIe reset errata */
+
+#define CONFIG_SYS_PCIE1_MEM_VIRT	0xc0000000
+#ifdef CONFIG_PHYS_64BIT
+#define CONFIG_SYS_PCIE1_MEM_BUS	0xe0000000
+#define CONFIG_SYS_PCIE1_MEM_PHYS	0xc40000000ull
+#else
+#define CONFIG_SYS_PCIE1_MEM_BUS	0xc0000000
+#define CONFIG_SYS_PCIE1_MEM_PHYS	0xc0000000
+#endif
+#define CONFIG_SYS_PCIE1_MEM_SIZE	0x20000000	/* 512M */
+#define CONFIG_SYS_PCIE1_IO_VIRT	0xffc20000
+#define CONFIG_SYS_PCIE1_IO_BUS		0x00000000
+#ifdef CONFIG_PHYS_64BIT
+#define CONFIG_SYS_PCIE1_IO_PHYS	0xfffc20000ull
+#else
+#define CONFIG_SYS_PCIE1_IO_PHYS	0xffc20000
+#endif
+#define CONFIG_SYS_PCIE1_IO_SIZE	0x00010000	/* 64k */
+
+/*
+ * SATA
+ */
+#define CONFIG_LIBATA
+#define CONFIG_LBA48
+#define CONFIG_CMD_SATA
+
+#define CONFIG_FSL_SATA
+#define CONFIG_SYS_SATA_MAX_DEVICE	2
+#define CONFIG_SATA1
+#define CONFIG_SYS_SATA1		CONFIG_SYS_MPC85xx_SATA1_ADDR
+#define CONFIG_SYS_SATA1_FLAGS		FLAGS_DMA
+#define CONFIG_SATA2
+#define CONFIG_SYS_SATA2		CONFIG_SYS_MPC85xx_SATA2_ADDR
+#define CONFIG_SYS_SATA2_FLAGS		FLAGS_DMA
+
+/*
+ * Ethernet
+ */
+#define CONFIG_TSEC_ENET
+
+#define CONFIG_TSECV2
+
+#define CONFIG_MII			/* MII PHY management */
+#define CONFIG_TSEC1		1
+#define CONFIG_TSEC1_NAME	"eTSEC1"
+#define CONFIG_TSEC2		1
+#define CONFIG_TSEC2_NAME	"eTSEC2"
+
+#define TSEC1_PHY_ADDR		0
+#define TSEC2_PHY_ADDR		1
+
+#define TSEC1_FLAGS		(TSEC_GIGABIT | TSEC_REDUCED)
+#define TSEC2_FLAGS		(TSEC_GIGABIT | TSEC_REDUCED)
+
+#define TSEC1_PHYIDX		0
+#define TSEC2_PHYIDX		0
+
+#define CONFIG_ETHPRIME		"eTSEC1"
+
+#define CONFIG_PHY_GIGE		/* Include GbE speed/duplex detection */
+
+/*
+ * USB
+ */
+#define CONFIG_USB_EHCI
+#define CONFIG_CMD_USB
+#define CONFIG_USB_STORAGE
+
+#define CONFIG_HAS_FSL_DR_USB
+#define CONFIG_USB_EHCI_FSL
+#define CONFIG_EHCI_HCD_INIT_AFTER_RESET
+
+#endif /* CONFIG_TRAILBLAZER */
+
+/*
+ * Environment
+ */
+#if defined(CONFIG_TRAILBLAZER)
+#define CONFIG_ENV_IS_NOWHERE
+#define CONFIG_ENV_SIZE		0x2000		/* 8KB */
+#undef CONFIG_CMD_SAVEENV
+#elif defined(CONFIG_RAMBOOT_SPIFLASH)
+#define CONFIG_ENV_IS_IN_SPI_FLASH
+#define CONFIG_ENV_SPI_BUS	0
+#define CONFIG_ENV_SPI_CS	0
+#define CONFIG_ENV_SPI_MAX_HZ	10000000
+#define CONFIG_ENV_SPI_MODE	0
+#define CONFIG_ENV_SIZE		0x2000		/* 8KB */
+#define CONFIG_ENV_OFFSET	0x100000	/* 1MB */
+#define CONFIG_ENV_SECT_SIZE	0x10000
+#elif defined(CONFIG_RAMBOOT_SDCARD)
+#define CONFIG_ENV_IS_IN_MMC
+#define CONFIG_FSL_FIXED_MMC_LOCATION
+#define CONFIG_ENV_SIZE		0x2000
+#define CONFIG_SYS_MMC_ENV_DEV	0
+#endif
+
+#define CONFIG_SYS_EXTRA_ENV_RELOC
+
+#define CONFIG_SYS_CONSOLE_IS_IN_ENV
+
+/*
+ * Command line configuration.
+ */
+#ifndef CONFIG_TRAILBLAZER
+#define CONFIG_SYS_HUSH_PARSER
+#define CONFIG_SYS_LONGHELP
+#define CONFIG_CMDLINE_EDITING			/* Command-line editing */
+#define CONFIG_AUTO_COMPLETE			/* add autocompletion support */
+#endif /* CONFIG_TRAILBLAZER */
+
+#define CONFIG_SYS_LOAD_ADDR	0x2000000	/* default load address */
+#define CONFIG_SYS_PROMPT	"=> "		/* Monitor Command Prompt */
+#ifdef CONFIG_CMD_KGDB
+#define CONFIG_SYS_CBSIZE	1024		/* Console I/O Buffer Size */
+#else
+#define CONFIG_SYS_CBSIZE	256		/* Console I/O Buffer Size */
+#endif
+/* Print Buffer Size */
+#define CONFIG_SYS_PBSIZE (CONFIG_SYS_CBSIZE + sizeof(CONFIG_SYS_PROMPT) + 16)
+#define CONFIG_SYS_MAXARGS	16
+#define CONFIG_SYS_BARGSIZE	CONFIG_SYS_CBSIZE
+
+#include <config_cmd_default.h>
+
+#ifndef CONFIG_TRAILBLAZER
+
+#define CONFIG_CMD_ELF
+#define CONFIG_CMD_ERRATA
+#define CONFIG_CMD_EXT2
+#define CONFIG_CMD_FAT
+#define CONFIG_CMD_IRQ
+#define CONFIG_CMD_MII
+#define CONFIG_CMD_NET
+#define CONFIG_CMD_PING
+#define CONFIG_CMD_SETEXPR
+#define CONFIG_CMD_REGINFO
+
+/*
+ * Board initialisation callbacks
+ */
+#define CONFIG_BOARD_EARLY_INIT_F
+#define CONFIG_BOARD_EARLY_INIT_R
+#define CONFIG_MISC_INIT_R
+#define CONFIG_LAST_STAGE_INIT
+
+/*
+ * Pass open firmware flat tree
+ */
+#define CONFIG_OF_LIBFDT
+#define CONFIG_OF_BOARD_SETUP
+#define CONFIG_OF_STDOUT_VIA_ALIAS
+
+/* new uImage format support */
+#define CONFIG_FIT
+#define CONFIG_FIT_VERBOSE
+
+#else /* CONFIG_TRAILBLAZER */
+
+#define CONFIG_BOARD_EARLY_INIT_F
+#define CONFIG_BOARD_EARLY_INIT_R
+#define CONFIG_LAST_STAGE_INIT
+#undef CONFIG_CMD_BOOTM
+
+#endif /* CONFIG_TRAILBLAZER */
+
+/*
+ * Miscellaneous configurable options
+ */
+#define CONFIG_SYS_HZ		1000
+#define CONFIG_HW_WATCHDOG
+#define CONFIG_LOADS_ECHO
+#define CONFIG_SYS_LOADS_BAUD_CHANGE
+#define CONFIG_DOS_PARTITION
+
+/*
+ * For booting Linux, the board info and command line data
+ * have to be in the first 64 MB of memory, since this is
+ * the maximum mapped by the Linux kernel during initialization.
+ */
+#define CONFIG_SYS_BOOTMAPSZ	(64 << 20)	/* Initial Linux Memory map */
+#define CONFIG_SYS_BOOTM_LEN	(64 << 20)	/* Increase max gunzip size */
+
+/*
+ * Environment Configuration
+ */
+
+#ifdef CONFIG_TRAILBLAZER
+
+#define CONFIG_BOOTDELAY	0	/* -1 disables auto-boot */
+#define CONFIG_BAUDRATE	115200
+
+#define	CONFIG_EXTRA_ENV_SETTINGS				\
+	"mp_holdoff=1\0"
+
+#else
+
+#define CONFIG_HOSTNAME		controlcenterd
+#define CONFIG_ROOTPATH		"/opt/nfsroot"
+#define CONFIG_BOOTFILE		"uImage"
+#define CONFIG_UBOOTPATH	u-boot.bin	/* U-Boot image on TFTP */
+
+#define CONFIG_LOADADDR		1000000
+
+#define CONFIG_BOOTDELAY	10	/* -1 disables auto-boot */
+
+#define CONFIG_BAUDRATE	115200
+
+#define	CONFIG_EXTRA_ENV_SETTINGS				\
+	"netdev=eth0\0"						\
+	"uboot=" __stringify(CONFIG_UBOOTPATH) "\0"		\
+	"ubootaddr=" __stringify(CONFIG_SYS_TEXT_BASE) "\0"	\
+	"tftpflash=tftpboot $loadaddr $uboot && "		\
+		"protect off $ubootaddr +$filesize && "		\
+		"erase $ubootaddr +$filesize && "		\
+		"cp.b $loadaddr $ubootaddr $filesize && "	\
+		"protect on $ubootaddr +$filesize && "		\
+		"cmp.b $loadaddr $ubootaddr $filesize\0"	\
+	"consoledev=ttyS1\0"					\
+	"ramdiskaddr=2000000\0"					\
+	"ramdiskfile=rootfs.ext2.gz.uboot\0"			\
+	"fdtaddr=c00000\0"					\
+	"fdtfile=controlcenterd.dtb\0"				\
+	"bdev=sda3\0"
+
+#define CONFIG_HDBOOT					\
+	"setenv bootargs root=/dev/$bdev rw "		\
+	"console=$consoledev,$baudrate $othbootargs $videobootargs;"	\
+	"tftp $loadaddr $bootfile;"			\
+	"tftp $fdtaddr $fdtfile;"			\
+	"bootm $loadaddr - $fdtaddr"
+
+#define CONFIG_NFSBOOTCOMMAND						\
+	"setenv bootargs root=/dev/nfs rw "				\
+	"nfsroot=$serverip:$rootpath "					\
+	"ip=$ipaddr:$serverip:$gatewayip:$netmask:$hostname:$netdev:off " \
+	"console=$consoledev,$baudrate $othbootargs $videobootargs;"	\
+	"tftp $loadaddr $bootfile;"					\
+	"tftp $fdtaddr $fdtfile;"					\
+	"bootm $loadaddr - $fdtaddr"
+
+#define CONFIG_RAMBOOTCOMMAND						\
+	"setenv bootargs root=/dev/ram rw "				\
+	"console=$consoledev,$baudrate $othbootargs $videobootargs;"	\
+	"tftp $ramdiskaddr $ramdiskfile;"				\
+	"tftp $loadaddr $bootfile;"					\
+	"tftp $fdtaddr $fdtfile;"					\
+	"bootm $loadaddr $ramdiskaddr $fdtaddr"
+
+#define CONFIG_BOOTCOMMAND		CONFIG_RAMBOOTCOMMAND
+
+#endif /* CONFIG_TRAILBLAZER */
+
+#endif
-- 
1.8.3

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

* [U-Boot] [PATCH v6 5/5] mpc85xx: Add gdsys ControlCenter Digital board
  2013-06-12  8:08 ` [U-Boot] [PATCH v6 5/5] mpc85xx: Add gdsys ControlCenter Digital board dirk.eibach at gdsys.cc
@ 2013-06-12 18:12   ` Wolfgang Denk
  0 siblings, 0 replies; 12+ messages in thread
From: Wolfgang Denk @ 2013-06-12 18:12 UTC (permalink / raw)
  To: u-boot

Dear dirk.eibach at gdsys.cc,

In message <1371024486-15629-6-git-send-email-dirk.eibach@gdsys.cc> you wrote:
> 
> The gdsys ControlCenter Digital board is based on a Freescale P1022 QorIQ SOC.
> It boots from SPI-Flash but can be configured to boot from SD-card for
> factory programming and testing.
> On board peripherals include:

> diff --git a/.checkpatch.conf b/.checkpatch.conf
> index d88af57..ef9b595 100644
> --- a/.checkpatch.conf
> +++ b/.checkpatch.conf
> @@ -2,10 +2,10 @@
>  --no-tree
>  
>  # Temporary for false positive in checkpatch
> ---ignore COMPLEX_MACRO
> +#--ignore COMPLEX_MACRO
>  
>  # For CONFIG_SYS_I2C_NOPROBES
> ---ignore MULTISTATEMENT_MACRO_USE_DO_WHILE
> +#--ignore MULTISTATEMENT_MACRO_USE_DO_WHILE

NAK.  Please do not mess with public settings.


> +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;
> +}

Here and everywhere else: please separate declarations and code by
inserting a blank line.

> +			for (i = 0; i < 20; ++i)
> +				if (src_reg->digest[i])
> +					return NULL;

This muti-line statement requires braces.

> +enum {
> +	REG_REFLECTION_LOW = 0x0000,
> +	REG_VERSIONS = 0x0004,
> +	REG_FPGA_VERSION = 0x0008,
> +	REG_FEATURES = 0x000C,
> +	REG_TOP_INTERRUPT = 0x0010,
> +	REG_TOP_INTERRUPT_SET = 0x0014,
> +	REG_TOP_INTERRUPT_CLEAR = 0x0018,
> +	REG_STATUS = 0x001C,
> +	REG_CONTROL = 0x0020,
> +	REG_TESTMEM1 = 0x100,
> +	REG_DMA_WRITE_CONTROL = 0x0200,
> +	REG_DMA_WRITE_BASE_ADDRESS_LOW = 0x0204,
> +	REG_DMA_WRITE_BASE_ADDRESS_HIGH = 0x0208,
> +	REG_DMA_WRITE_LENGTH = 0x020C,
> +	REG_DMA_WRITE_HEAD = 0x0210,
> +	REG_DMA_WRITE_TAIL = 0x0214,
> +	REG_DMA_WRITE_MIN_INT_INTERVAL = 0x0218,
> +	REG_DMA_WRITE_MAX_PACKETS_INT_INTERVAL = 0x021C,
> +	REG_DMA_READ_CONTROL = 0x0300,
> +	REG_DMA_READ_BASE_ADDRESS_LOW = 0x0304,
> +	REG_DMA_READ_BASE_ADDRESS_HIGH = 0x0308,
> +	REG_DMA_READ_LENGTH = 0x030C,
> +	REG_DMA_READ_HEAD = 0x0310,
> +	REG_DMA_READ_TAIL = 0x0314,
> +	REG_DMA_READ_MIN_INT_INTERVAL = 0x0318,
> +	REG_DMA_READ_MAX_PACKETS_INT_INTERVAL = 0x031C,
> +};

This looks very much like register offsets to me, that should rather
be represented by a C struct ?

> --- a/boards.cfg
> +++ b/boards.cfg
> @@ -904,6 +904,13 @@ BSC9132QDS_SDCARD_DDRCLK100  powerpc     mpc85xx     bsc9132qds          freesca
>  BSC9132QDS_SDCARD_DDRCLK133  powerpc     mpc85xx     bsc9132qds          freescale      -           BSC9132QDS:BSC9132QDS,SDCARD,SYS_CLK_100_DDR_133
>  BSC9132QDS_SPIFLASH_DDRCLK100 powerpc    mpc85xx     bsc9132qds          freescale      -           BSC9132QDS:BSC9132QDS,SPIFLASH,SYS_CLK_100_DDR_100
>  BSC9132QDS_SPIFLASH_DDRCLK133 powerpc    mpc85xx     bsc9132qds          freescale      -           BSC9132QDS:BSC9132QDS,SPIFLASH,SYS_CLK_100_DDR_133
> +controlcenterd_36BIT_SDCARD         powerpc     mpc85xx     p1022             gdsys      -           controlcenterd:36BIT,SDCARD
> +controlcenterd_36BIT_SDCARD_DEVELOP powerpc     mpc85xx     p1022             gdsys      -           controlcenterd:36BIT,SDCARD,DEVELOP
> +controlcenterd_36BIT_SPIFLASH       powerpc     mpc85xx     p1022             gdsys      -           controlcenterd:36BIT,SPIFLASH
> +controlcenterd_SDCARD               powerpc     mpc85xx     p1022             gdsys      -           controlcenterd:SDCARD
> +controlcenterd_SPIFLASH             powerpc     mpc85xx     p1022             gdsys      -           controlcenterd:SPIFLASH
> +controlcenterd_TRAILBLAZER          powerpc     mpc85xx     p1022             gdsys      -           controlcenterd:TRAILBLAZER,SPIFLASH
> +controlcenterd_TRAILBLAZER_DEVELOP  powerpc     mpc85xx     p1022             gdsys      -           controlcenterd:TRAILBLAZER,SPIFLASH,DEVELOP
>  stxgp3                       powerpc     mpc85xx     stxgp3              stx
>  stxssa                       powerpc     mpc85xx     stxssa              stx            -           stxssa
>  stxssa_4M                    powerpc     mpc85xx     stxssa              stx            -           stxssa:STXSSA_4M

Is it really, _really_ necessary to add 7 entries just for a single
board?   Please decide which configurations you really need, and omit
the rest.

...
> +#define CONFIG_HDBOOT					\
> +	"setenv bootargs root=/dev/$bdev rw "		\
> +	"console=$consoledev,$baudrate $othbootargs $videobootargs;"	\
> +	"tftp $loadaddr $bootfile;"			\
> +	"tftp $fdtaddr $fdtfile;"			\
> +	"bootm $loadaddr - $fdtaddr"

Should this definition (and the follwing ones) not rather be NUL
terminated?

Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
I think there's a world market for about five computers.
         -- attr. Thomas J. Watson (Chairman of the Board, IBM), 1943

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

* [U-Boot] [PATCH v6 1/5] tpm: add AUTH1 cmds for LoadKey2 and GetPubKey
  2013-06-12  8:08 ` [U-Boot] [PATCH v6 1/5] tpm: add AUTH1 cmds for LoadKey2 and GetPubKey dirk.eibach at gdsys.cc
@ 2013-06-12 21:29   ` Che-liang Chiou
  0 siblings, 0 replies; 12+ messages in thread
From: Che-liang Chiou @ 2013-06-12 21:29 UTC (permalink / raw)
  To: u-boot

Acked-by: Che-Liang Chiou <clchiou@chromium.org>

On Wed, Jun 12, 2013 at 1:08 AM,  <dirk.eibach@gdsys.cc> wrote:
> From: Reinhard Pfau <pfau@gdsys.de>
>
> Extend the tpm library with support for single authorized (AUTH1) commands
> as specified in the TCG Main Specification 1.2. (The internally used helper
> functions are implemented in a way that they could also be used for double
> authorized commands if someone needs it.)
>
> Provide enums with the return codes from the TCG Main specification.
>
> For now only a single OIAP session is supported.
>
> OIAP authorized version of the commands TPM_LoadKey2 and TPM_GetPubKey are
> provided. Both features are available using the 'tpm' command, too.
>
> Authorized commands are enabled with CONFIG_TPM_AUTH_SESSIONS. (Note that
> this also requires CONFIG_SHA1 to be enabled.)
>
> Signed-off-by: Reinhard Pfau <reinhard.pfau@gdsys.cc>
>
>
> Signed-off-by: Dirk Eibach <dirk.eibach@gdsys.cc>
> ---
> Changes in v6: None
> Changes in v5: None
> Changes in v4: None
> Changes in v3:
> - fix email addresses
>
> Changes in v2:
> - replace some numeric constants with named constants
> - style fixes (as shown by checkpatch.pl) in common/cmd_tpm.c and lib/tpm.c
>
>  README           |  14 +++
>  common/cmd_tpm.c | 100 ++++++++++++++++
>  include/tpm.h    | 174 +++++++++++++++++++++++++++
>  lib/tpm.c        | 351 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
>  4 files changed, 638 insertions(+), 1 deletion(-)
>
> diff --git a/README b/README
> index 33bda8c..3d1fa08 100644
> --- a/README
> +++ b/README
> @@ -1234,6 +1234,20 @@ The following options need to be configured:
>                         to. Contemporary x86 systems usually map it at
>                         0xfed40000.
>
> +               CONFIG_CMD_TPM
> +               Add tpm monitor functions.
> +               Requires CONFIG_TPM. If CONFIG_TPM_AUTH_SESSIONS is set, also
> +               provides monitor access to authorized functions.
> +
> +               CONFIG_TPM
> +               Define this to enable the TPM support library which provides
> +               functional interfaces to some TPM commands.
> +               Requires support for a TPM device.
> +
> +               CONFIG_TPM_AUTH_SESSIONS
> +               Define this to enable authorized functions in the TPM library.
> +               Requires CONFIG_TPM and CONFIG_SHA1.
> +
>  - USB Support:
>                 At the moment only the UHCI host controller is
>                 supported (PIP405, MIP405, MPC5200); define
> diff --git a/common/cmd_tpm.c b/common/cmd_tpm.c
> index 46fae18..c34000a 100644
> --- a/common/cmd_tpm.c
> +++ b/common/cmd_tpm.c
> @@ -27,6 +27,13 @@
>  #include <asm/unaligned.h>
>  #include <linux/string.h>
>
> +/* Useful constants */
> +enum {
> +       DIGEST_LENGTH           = 20,
> +       /* max lengths, valid for RSA keys <= 2048 bits */
> +       TPM_PUBKEY_MAX_LENGTH   = 288,
> +};
> +
>  /**
>   * Print a byte string in hexdecimal format, 16-bytes per line.
>   *
> @@ -546,6 +553,72 @@ static int do_tpm_nv_write(cmd_tbl_t *cmdtp, int flag,
>         return convert_return_code(err);
>  }
>
> +#ifdef CONFIG_TPM_AUTH_SESSIONS
> +
> +static int do_tpm_oiap(cmd_tbl_t *cmdtp, int flag,
> +               int argc, char * const argv[])
> +{
> +       uint32_t auth_handle, err;
> +
> +       err = tpm_oiap(&auth_handle);
> +
> +       return convert_return_code(err);
> +}
> +
> +static int do_tpm_load_key2_oiap(cmd_tbl_t *cmdtp, int flag,
> +               int argc, char * const argv[])
> +{
> +       uint32_t parent_handle, key_len, key_handle, err;
> +       uint8_t usage_auth[DIGEST_LENGTH];
> +       void *key;
> +
> +       if (argc < 5)
> +               return CMD_RET_USAGE;
> +
> +       parent_handle = simple_strtoul(argv[1], NULL, 0);
> +       key = (void *)simple_strtoul(argv[2], NULL, 0);
> +       key_len = simple_strtoul(argv[3], NULL, 0);
> +       if (strlen(argv[4]) != 2 * DIGEST_LENGTH)
> +               return CMD_RET_FAILURE;
> +       parse_byte_string(argv[4], usage_auth, NULL);
> +
> +       err = tpm_load_key2_oiap(parent_handle, key, key_len, usage_auth,
> +                       &key_handle);
> +       if (!err)
> +               printf("Key handle is 0x%x\n", key_handle);
> +
> +       return convert_return_code(err);
> +}
> +
> +static int do_tpm_get_pub_key_oiap(cmd_tbl_t *cmdtp, int flag,
> +               int argc, char * const argv[])
> +{
> +       uint32_t key_handle, err;
> +       uint8_t usage_auth[DIGEST_LENGTH];
> +       uint8_t pub_key_buffer[TPM_PUBKEY_MAX_LENGTH];
> +       size_t pub_key_len = sizeof(pub_key_buffer);
> +
> +       if (argc < 3)
> +               return CMD_RET_USAGE;
> +
> +       key_handle = simple_strtoul(argv[1], NULL, 0);
> +       if (strlen(argv[2]) != 2 * DIGEST_LENGTH)
> +               return CMD_RET_FAILURE;
> +       parse_byte_string(argv[2], usage_auth, NULL);
> +
> +       err = tpm_get_pub_key_oiap(key_handle, usage_auth,
> +                       pub_key_buffer, &pub_key_len);
> +       if (!err) {
> +               printf("dump of received pub key structure:\n");
> +               print_byte_string(pub_key_buffer, pub_key_len);
> +       }
> +       return convert_return_code(err);
> +}
> +
> +TPM_COMMAND_NO_ARG(tpm_end_oiap)
> +
> +#endif /* CONFIG_TPM_AUTH_SESSIONS */
> +
>  #define MAKE_TPM_CMD_ENTRY(cmd) \
>         U_BOOT_CMD_MKENT(cmd, 0, 1, do_tpm_ ## cmd, "", "")
>
> @@ -590,6 +663,16 @@ static cmd_tbl_t tpm_commands[] = {
>                         do_tpm_nv_read, "", ""),
>         U_BOOT_CMD_MKENT(nv_write, 0, 1,
>                         do_tpm_nv_write, "", ""),
> +#ifdef CONFIG_TPM_AUTH_SESSIONS
> +       U_BOOT_CMD_MKENT(oiap, 0, 1,
> +                        do_tpm_oiap, "", ""),
> +       U_BOOT_CMD_MKENT(end_oiap, 0, 1,
> +                        do_tpm_end_oiap, "", ""),
> +       U_BOOT_CMD_MKENT(load_key2_oiap, 0, 1,
> +                        do_tpm_load_key2_oiap, "", ""),
> +       U_BOOT_CMD_MKENT(get_pub_key_oiap, 0, 1,
> +                        do_tpm_get_pub_key_oiap, "", ""),
> +#endif /* CONFIG_TPM_AUTH_SESSIONS */
>  };
>
>  static int do_tpm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
> @@ -638,6 +721,16 @@ 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_AUTH_SESSIONS
> +"Storage functions\n"
> +"  loadkey2_oiap parent_handle key_addr key_len usage_auth\n"
> +"    - loads a key data from memory address <key_addr>, <key_len> bytes\n"
> +"      into TPM using the parent key <parent_handle> with authorization\n"
> +"      <usage_auth> (20 bytes hex string).\n"
> +"  get_pub_key_oiap key_handle usage_auth\n"
> +"    - get the public key portion of a loaded key <key_handle> using\n"
> +"      authorization <usage auth> (20 bytes hex string)\n"
> +#endif /* CONFIG_TPM_AUTH_SESSIONS */
>  "Endorsement Key Handling Commands:\n"
>  "  read_pubek addr count\n"
>  "    - Read <count> bytes of the public endorsement key to memory\n"
> @@ -648,6 +741,13 @@ U_BOOT_CMD(tpm, CONFIG_SYS_MAXARGS, 1, do_tpm,
>  "      <digest_hex_string>\n"
>  "  pcr_read index addr count\n"
>  "    - Read <count> bytes from PCR <index> to memory address <addr>.\n"
> +#ifdef CONFIG_TPM_AUTH_SESSIONS
> +"Authorization Sessions\n"
> +"  oiap\n"
> +"    - setup an OIAP session\n"
> +"  end_oiap\n"
> +"    - terminates an active OIAP session\n"
> +#endif /* CONFIG_TPM_AUTH_SESSIONS */
>  "Non-volatile Storage Commands:\n"
>  "  nv_define_space index permission size\n"
>  "    - Establish a space at index <index> with <permission> of <size> bytes.\n"
> diff --git a/include/tpm.h b/include/tpm.h
> index 7219b73..5e9f832 100644
> --- a/include/tpm.h
> +++ b/include/tpm.h
> @@ -1,5 +1,6 @@
>  /*
>   * Copyright (c) 2013 The Chromium OS Authors.
> + * Coypright (c) 2013 Guntermann & Drunck GmbH
>   *
>   * See file CREDITS for list of people who contributed to this
>   * project.
> @@ -54,6 +55,120 @@ enum tpm_nv_index {
>  };
>
>  /**
> + * TPM return codes as defined in the TCG Main specification
> + * (TPM Main Part 2 Structures; Specification version 1.2)
> + */
> +enum tpm_return_code {
> +       TPM_BASE        = 0x00000000,
> +       TPM_NON_FATAL   = 0x00000800,
> +       TPM_SUCCESS     = TPM_BASE,
> +       /* TPM-defined fatal error codes */
> +       TPM_AUTHFAIL                    = TPM_BASE +  1,
> +       TPM_BADINDEX                    = TPM_BASE +  2,
> +       TPM_BAD_PARAMETER               = TPM_BASE +  3,
> +       TPM_AUDITFAILURE                = TPM_BASE +  4,
> +       TPM_CLEAR_DISABLED              = TPM_BASE +  5,
> +       TPM_DEACTIVATED                 = TPM_BASE +  6,
> +       TPM_DISABLED                    = TPM_BASE +  7,
> +       TPM_DISABLED_CMD                = TPM_BASE +  8,
> +       TPM_FAIL                        = TPM_BASE +  9,
> +       TPM_BAD_ORDINAL                 = TPM_BASE + 10,
> +       TPM_INSTALL_DISABLED            = TPM_BASE + 11,
> +       TPM_INVALID_KEYHANDLE           = TPM_BASE + 12,
> +       TPM_KEYNOTFOUND                 = TPM_BASE + 13,
> +       TPM_INAPPROPRIATE_ENC           = TPM_BASE + 14,
> +       TPM_MIGRATE_FAIL                = TPM_BASE + 15,
> +       TPM_INVALID_PCR_INFO            = TPM_BASE + 16,
> +       TPM_NOSPACE                     = TPM_BASE + 17,
> +       TPM_NOSRK                       = TPM_BASE + 18,
> +       TPM_NOTSEALED_BLOB              = TPM_BASE + 19,
> +       TPM_OWNER_SET                   = TPM_BASE + 20,
> +       TPM_RESOURCES                   = TPM_BASE + 21,
> +       TPM_SHORTRANDOM                 = TPM_BASE + 22,
> +       TPM_SIZE                        = TPM_BASE + 23,
> +       TPM_WRONGPCRVAL                 = TPM_BASE + 24,
> +       TPM_BAD_PARAM_SIZE              = TPM_BASE + 25,
> +       TPM_SHA_THREAD                  = TPM_BASE + 26,
> +       TPM_SHA_ERROR                   = TPM_BASE + 27,
> +       TPM_FAILEDSELFTEST              = TPM_BASE + 28,
> +       TPM_AUTH2FAIL                   = TPM_BASE + 29,
> +       TPM_BADTAG                      = TPM_BASE + 30,
> +       TPM_IOERROR                     = TPM_BASE + 31,
> +       TPM_ENCRYPT_ERROR               = TPM_BASE + 32,
> +       TPM_DECRYPT_ERROR               = TPM_BASE + 33,
> +       TPM_INVALID_AUTHHANDLE          = TPM_BASE + 34,
> +       TPM_NO_ENDORSEMENT              = TPM_BASE + 35,
> +       TPM_INVALID_KEYUSAGE            = TPM_BASE + 36,
> +       TPM_WRONG_ENTITYTYPE            = TPM_BASE + 37,
> +       TPM_INVALID_POSTINIT            = TPM_BASE + 38,
> +       TPM_INAPPROPRIATE_SIG           = TPM_BASE + 39,
> +       TPM_BAD_KEY_PROPERTY            = TPM_BASE + 40,
> +       TPM_BAD_MIGRATION               = TPM_BASE + 41,
> +       TPM_BAD_SCHEME                  = TPM_BASE + 42,
> +       TPM_BAD_DATASIZE                = TPM_BASE + 43,
> +       TPM_BAD_MODE                    = TPM_BASE + 44,
> +       TPM_BAD_PRESENCE                = TPM_BASE + 45,
> +       TPM_BAD_VERSION                 = TPM_BASE + 46,
> +       TPM_NO_WRAP_TRANSPORT           = TPM_BASE + 47,
> +       TPM_AUDITFAIL_UNSUCCESSFUL      = TPM_BASE + 48,
> +       TPM_AUDITFAIL_SUCCESSFUL        = TPM_BASE + 49,
> +       TPM_NOTRESETABLE                = TPM_BASE + 50,
> +       TPM_NOTLOCAL                    = TPM_BASE + 51,
> +       TPM_BAD_TYPE                    = TPM_BASE + 52,
> +       TPM_INVALID_RESOURCE            = TPM_BASE + 53,
> +       TPM_NOTFIPS                     = TPM_BASE + 54,
> +       TPM_INVALID_FAMILY              = TPM_BASE + 55,
> +       TPM_NO_NV_PERMISSION            = TPM_BASE + 56,
> +       TPM_REQUIRES_SIGN               = TPM_BASE + 57,
> +       TPM_KEY_NOTSUPPORTED            = TPM_BASE + 58,
> +       TPM_AUTH_CONFLICT               = TPM_BASE + 59,
> +       TPM_AREA_LOCKED                 = TPM_BASE + 60,
> +       TPM_BAD_LOCALITY                = TPM_BASE + 61,
> +       TPM_READ_ONLY                   = TPM_BASE + 62,
> +       TPM_PER_NOWRITE                 = TPM_BASE + 63,
> +       TPM_FAMILY_COUNT                = TPM_BASE + 64,
> +       TPM_WRITE_LOCKED                = TPM_BASE + 65,
> +       TPM_BAD_ATTRIBUTES              = TPM_BASE + 66,
> +       TPM_INVALID_STRUCTURE           = TPM_BASE + 67,
> +       TPM_KEY_OWNER_CONTROL           = TPM_BASE + 68,
> +       TPM_BAD_COUNTER                 = TPM_BASE + 69,
> +       TPM_NOT_FULLWRITE               = TPM_BASE + 70,
> +       TPM_CONTEXT_GAP                 = TPM_BASE + 71,
> +       TPM_MAXNVWRITES                 = TPM_BASE + 72,
> +       TPM_NOOPERATOR                  = TPM_BASE + 73,
> +       TPM_RESOURCEMISSING             = TPM_BASE + 74,
> +       TPM_DELEGATE_LOCK               = TPM_BASE + 75,
> +       TPM_DELEGATE_FAMILY             = TPM_BASE + 76,
> +       TPM_DELEGATE_ADMIN              = TPM_BASE + 77,
> +       TPM_TRANSPORT_NOTEXCLUSIVE      = TPM_BASE + 78,
> +       TPM_OWNER_CONTROL               = TPM_BASE + 79,
> +       TPM_DAA_RESOURCES               = TPM_BASE + 80,
> +       TPM_DAA_INPUT_DATA0             = TPM_BASE + 81,
> +       TPM_DAA_INPUT_DATA1             = TPM_BASE + 82,
> +       TPM_DAA_ISSUER_SETTINGS         = TPM_BASE + 83,
> +       TPM_DAA_TPM_SETTINGS            = TPM_BASE + 84,
> +       TPM_DAA_STAGE                   = TPM_BASE + 85,
> +       TPM_DAA_ISSUER_VALIDITY         = TPM_BASE + 86,
> +       TPM_DAA_WRONG_W                 = TPM_BASE + 87,
> +       TPM_BAD_HANDLE                  = TPM_BASE + 88,
> +       TPM_BAD_DELEGATE                = TPM_BASE + 89,
> +       TPM_BADCONTEXT                  = TPM_BASE + 90,
> +       TPM_TOOMANYCONTEXTS             = TPM_BASE + 91,
> +       TPM_MA_TICKET_SIGNATURE         = TPM_BASE + 92,
> +       TPM_MA_DESTINATION              = TPM_BASE + 93,
> +       TPM_MA_SOURCE                   = TPM_BASE + 94,
> +       TPM_MA_AUTHORITY                = TPM_BASE + 95,
> +       TPM_PERMANENTEK                 = TPM_BASE + 97,
> +       TPM_BAD_SIGNATURE               = TPM_BASE + 98,
> +       TPM_NOCONTEXTSPACE              = TPM_BASE + 99,
> +       /* TPM-defined non-fatal errors */
> +       TPM_RETRY               = TPM_BASE + TPM_NON_FATAL,
> +       TPM_NEEDS_SELFTEST      = TPM_BASE + TPM_NON_FATAL + 1,
> +       TPM_DOING_SELFTEST      = TPM_BASE + TPM_NON_FATAL + 2,
> +       TPM_DEFEND_LOCK_RUNNING = TPM_BASE + TPM_NON_FATAL + 3,
> +};
> +
> +/**
>   * Initialize TPM device.  It must be called before any TPM commands.
>   *
>   * @return 0 on success, non-0 on error.
> @@ -201,4 +316,63 @@ uint32_t tpm_physical_set_deactivated(uint8_t state);
>  uint32_t tpm_get_capability(uint32_t cap_area, uint32_t sub_cap,
>                 void *cap, size_t count);
>
> +/**
> + * Issue a TPM_FlushSpecific command for a AUTH ressource.
> + *
> + * @param auth_handle  handle of the auth session
> + * @return return code of the operation
> + */
> +uint32_t tpm_terminate_auth_session(uint32_t auth_handle);
> +
> +/**
> + * Issue a TPM_OIAP command to setup an object independant authorization
> + * session.
> + * Information about the session is stored internally.
> + * If there was already an OIAP session active it is terminated and a new
> + * session is set up.
> + *
> + * @param auth_handle  pointer to the (new) auth handle or NULL.
> + * @return return code of the operation
> + */
> +uint32_t tpm_oiap(uint32_t *auth_handle);
> +
> +/**
> + * Ends an active OIAP session.
> + *
> + * @return return code of the operation
> + */
> +uint32_t tpm_end_oiap(void);
> +
> +/**
> + * Issue a TPM_LoadKey2 (Auth1) command using an OIAP session for authenticating
> + * the usage of the parent key.
> + *
> + * @param parent_handle        handle of the parent key.
> + * @param key          pointer to the key structure (TPM_KEY or TPM_KEY12).
> + * @param key_length   size of the key structure
> + * @param parent_key_usage_auth        usage auth for the parent key
> + * @param key_handle   pointer to the key handle
> + * @return return code of the operation
> + */
> +uint32_t tpm_load_key2_oiap(uint32_t parent_handle,
> +               const void *key, size_t key_length,
> +               const void *parent_key_usage_auth,
> +               uint32_t *key_handle);
> +
> +/**
> + * Issue a TPM_GetPubKey (Auth1) command using an OIAP session for
> + * authenticating the usage of the key.
> + *
> + * @param key_handle   handle of the key
> + * @param usage_auth   usage auth for the key
> + * @param pubkey       pointer to the pub key buffer; may be NULL if the pubkey
> + *                     should not be stored.
> + * @param pubkey_len   pointer to the pub key buffer len. On entry: the size of
> + *                     the provided pubkey buffer. On successful exit: the size
> + *                     of the stored TPM_PUBKEY structure (iff pubkey != NULL).
> + * @return return code of the operation
> + */
> +uint32_t tpm_get_pub_key_oiap(uint32_t key_handle, const void *usage_auth,
> +               void *pubkey, size_t *pubkey_len);
> +
>  #endif /* __TPM_H */
> diff --git a/lib/tpm.c b/lib/tpm.c
> index 42c9bea..f0b4f59 100644
> --- a/lib/tpm.c
> +++ b/lib/tpm.c
> @@ -1,5 +1,6 @@
>  /*
>   * Copyright (c) 2013 The Chromium OS Authors.
> + * Coypright (c) 2013 Guntermann & Drunck GmbH
>   *
>   * See file CREDITS for list of people who contributed to this
>   * project.
> @@ -22,6 +23,7 @@
>
>  #include <common.h>
>  #include <stdarg.h>
> +#include <sha1.h>
>  #include <tpm.h>
>  #include <asm/unaligned.h>
>
> @@ -35,8 +37,31 @@ enum {
>         TPM_REQUEST_HEADER_LENGTH       = 10,
>         TPM_RESPONSE_HEADER_LENGTH      = 10,
>         PCR_DIGEST_LENGTH               = 20,
> +       DIGEST_LENGTH                   = 20,
> +       TPM_REQUEST_AUTH_LENGTH         = 45,
> +       TPM_RESPONSE_AUTH_LENGTH        = 41,
> +       /* some max lengths, valid for RSA keys <= 2048 bits */
> +       TPM_KEY12_MAX_LENGTH            = 618,
> +       TPM_PUBKEY_MAX_LENGTH           = 288,
>  };
>
> +#ifdef CONFIG_TPM_AUTH_SESSIONS
> +
> +#ifndef CONFIG_SHA1
> +#error "TPM_AUTH_SESSIONS require SHA1 to be configured, too"
> +#endif /* !CONFIG_SHA1 */
> +
> +struct session_data {
> +       int             valid;
> +       uint32_t        handle;
> +       uint8_t         nonce_even[DIGEST_LENGTH];
> +       uint8_t         nonce_odd[DIGEST_LENGTH];
> +};
> +
> +static struct session_data oiap_session = {0, };
> +
> +#endif /* CONFIG_TPM_AUTH_SESSIONS */
> +
>  /**
>   * Pack data into a byte string.  The data types are specified in
>   * the format string: 'b' means unsigned byte, 'w' unsigned word,
> @@ -235,7 +260,7 @@ static uint32_t tpm_sendrecv_command(const void *command,
>                         response, &response_length);
>         if (err)
>                 return TPM_LIB_ERROR;
> -       if (response)
> +       if (size_ptr)
>                 *size_ptr = response_length;
>
>         return tpm_return_code(response);
> @@ -579,3 +604,327 @@ uint32_t tpm_get_capability(uint32_t cap_area, uint32_t sub_cap,
>
>         return 0;
>  }
> +
> +#ifdef CONFIG_TPM_AUTH_SESSIONS
> +
> +/**
> + * Fill an authentication block in a request.
> + * This func can create the first as well as the second auth block (for
> + * double authorized commands).
> + *
> + * @param request      pointer to the request (w/ uninitialised auth data)
> + * @param request_len0 length of the request without auth data
> + * @param handles_len  length of the handles area in request
> + * @param auth_session pointer to the (valid) auth session to be used
> + * @param request_auth pointer to the auth block of the request to be filled
> + * @param auth         authentication data (HMAC key)
> + */
> +static uint32_t create_request_auth(const void *request, size_t request_len0,
> +       size_t handles_len,
> +       struct session_data *auth_session,
> +       void *request_auth, const void *auth)
> +{
> +       uint8_t hmac_data[DIGEST_LENGTH * 3 + 1];
> +       sha1_context hash_ctx;
> +       const size_t command_code_offset = 6;
> +       const size_t auth_nonce_odd_offset = 4;
> +       const size_t auth_continue_offset = 24;
> +       const size_t auth_auth_offset = 25;
> +
> +       if (!auth_session || !auth_session->valid)
> +               return TPM_LIB_ERROR;
> +
> +       sha1_starts(&hash_ctx);
> +       sha1_update(&hash_ctx, request + command_code_offset, 4);
> +       if (request_len0 > TPM_REQUEST_HEADER_LENGTH + handles_len)
> +               sha1_update(&hash_ctx,
> +                           request + TPM_REQUEST_HEADER_LENGTH + handles_len,
> +                           request_len0 - TPM_REQUEST_HEADER_LENGTH
> +                           - handles_len);
> +       sha1_finish(&hash_ctx, hmac_data);
> +
> +       sha1_starts(&hash_ctx);
> +       sha1_update(&hash_ctx, auth_session->nonce_odd, DIGEST_LENGTH);
> +       sha1_update(&hash_ctx, hmac_data, sizeof(hmac_data));
> +       sha1_finish(&hash_ctx, auth_session->nonce_odd);
> +
> +       if (pack_byte_string(request_auth, TPM_REQUEST_AUTH_LENGTH, "dsb",
> +                            0, auth_session->handle,
> +                            auth_nonce_odd_offset, auth_session->nonce_odd,
> +                            DIGEST_LENGTH,
> +                            auth_continue_offset, 1))
> +               return TPM_LIB_ERROR;
> +       if (pack_byte_string(hmac_data, sizeof(hmac_data), "ss",
> +                            DIGEST_LENGTH,
> +                            auth_session->nonce_even,
> +                            DIGEST_LENGTH,
> +                            2 * DIGEST_LENGTH,
> +                            request_auth + auth_nonce_odd_offset,
> +                            DIGEST_LENGTH + 1))
> +               return TPM_LIB_ERROR;
> +       sha1_hmac(auth, DIGEST_LENGTH, hmac_data, sizeof(hmac_data),
> +                 request_auth + auth_auth_offset);
> +
> +       return TPM_SUCCESS;
> +}
> +
> +/**
> + * Verify an authentication block in a response.
> + * Since this func updates the nonce_even in the session data it has to be
> + * called when receiving a succesfull AUTH response.
> + * This func can verify the first as well as the second auth block (for
> + * double authorized commands).
> + *
> + * @param command_code command code of the request
> + * @param response     pointer to the request (w/ uninitialised auth data)
> + * @param handles_len  length of the handles area in response
> + * @param auth_session pointer to the (valid) auth session to be used
> + * @param response_auth        pointer to the auth block of the response to be verified
> + * @param auth         authentication data (HMAC key)
> + */
> +static uint32_t verify_response_auth(uint32_t command_code,
> +       const void *response, size_t response_len0,
> +       size_t handles_len,
> +       struct session_data *auth_session,
> +       const void *response_auth, const void *auth)
> +{
> +       uint8_t hmac_data[DIGEST_LENGTH * 3 + 1];
> +       uint8_t computed_auth[DIGEST_LENGTH];
> +       sha1_context hash_ctx;
> +       const size_t return_code_offset = 6;
> +       const size_t auth_continue_offset = 20;
> +       const size_t auth_auth_offset = 21;
> +       uint8_t auth_continue;
> +
> +       if (!auth_session || !auth_session->valid)
> +               return TPM_AUTHFAIL;
> +       if (pack_byte_string(hmac_data, sizeof(hmac_data), "d",
> +                            0, command_code))
> +               return TPM_LIB_ERROR;
> +       if (response_len0 < TPM_RESPONSE_HEADER_LENGTH)
> +               return TPM_LIB_ERROR;
> +
> +       sha1_starts(&hash_ctx);
> +       sha1_update(&hash_ctx, response + return_code_offset, 4);
> +       sha1_update(&hash_ctx, hmac_data, 4);
> +       if (response_len0 > TPM_RESPONSE_HEADER_LENGTH + handles_len)
> +               sha1_update(&hash_ctx,
> +                           response + TPM_RESPONSE_HEADER_LENGTH + handles_len,
> +                           response_len0 - TPM_RESPONSE_HEADER_LENGTH
> +                           - handles_len);
> +       sha1_finish(&hash_ctx, hmac_data);
> +
> +       memcpy(auth_session->nonce_even, response_auth, DIGEST_LENGTH);
> +       auth_continue = ((uint8_t *)response_auth)[auth_continue_offset];
> +       if (pack_byte_string(hmac_data, sizeof(hmac_data), "ssb",
> +                            DIGEST_LENGTH,
> +                            response_auth,
> +                            DIGEST_LENGTH,
> +                            2 * DIGEST_LENGTH,
> +                            auth_session->nonce_odd,
> +                            DIGEST_LENGTH,
> +                            3 * DIGEST_LENGTH,
> +                            auth_continue))
> +               return TPM_LIB_ERROR;
> +
> +       sha1_hmac(auth, DIGEST_LENGTH, hmac_data, sizeof(hmac_data),
> +                 computed_auth);
> +
> +       if (memcmp(computed_auth, response_auth + auth_auth_offset,
> +                  DIGEST_LENGTH))
> +               return TPM_AUTHFAIL;
> +
> +       return TPM_SUCCESS;
> +}
> +
> +
> +uint32_t tpm_terminate_auth_session(uint32_t auth_handle)
> +{
> +       const uint8_t command[18] = {
> +               0x00, 0xc1,             /* TPM_TAG */
> +               0x00, 0x00, 0x00, 0x00, /* parameter size */
> +               0x00, 0x00, 0x00, 0xba, /* TPM_COMMAND_CODE */
> +               0x00, 0x00, 0x00, 0x00, /* TPM_HANDLE */
> +               0x00, 0x00, 0x00, 0x02, /* TPM_RESSOURCE_TYPE */
> +       };
> +       const size_t req_handle_offset = TPM_REQUEST_HEADER_LENGTH;
> +       uint8_t request[COMMAND_BUFFER_SIZE];
> +
> +       if (pack_byte_string(request, sizeof(request), "sd",
> +                            0, command, sizeof(command),
> +                            req_handle_offset, auth_handle))
> +               return TPM_LIB_ERROR;
> +       if (oiap_session.valid && oiap_session.handle == auth_handle)
> +               oiap_session.valid = 0;
> +
> +       return tpm_sendrecv_command(request, NULL, NULL);
> +}
> +
> +uint32_t tpm_end_oiap(void)
> +{
> +       uint32_t err = TPM_SUCCESS;
> +       if (oiap_session.valid)
> +               err = tpm_terminate_auth_session(oiap_session.handle);
> +       return err;
> +}
> +
> +uint32_t tpm_oiap(uint32_t *auth_handle)
> +{
> +       const uint8_t command[10] = {
> +               0x00, 0xc1,             /* TPM_TAG */
> +               0x00, 0x00, 0x00, 0x0a, /* parameter size */
> +               0x00, 0x00, 0x00, 0x0a, /* TPM_COMMAND_CODE */
> +       };
> +       const size_t res_auth_handle_offset = TPM_RESPONSE_HEADER_LENGTH;
> +       const size_t res_nonce_even_offset = TPM_RESPONSE_HEADER_LENGTH + 4;
> +       uint8_t response[COMMAND_BUFFER_SIZE];
> +       size_t response_length = sizeof(response);
> +       uint32_t err;
> +
> +       if (oiap_session.valid)
> +               tpm_terminate_auth_session(oiap_session.handle);
> +
> +       err = tpm_sendrecv_command(command, response, &response_length);
> +       if (err)
> +               return err;
> +       if (unpack_byte_string(response, response_length, "ds",
> +                              res_auth_handle_offset, &oiap_session.handle,
> +                              res_nonce_even_offset, &oiap_session.nonce_even,
> +                              (uint32_t)DIGEST_LENGTH))
> +               return TPM_LIB_ERROR;
> +       oiap_session.valid = 1;
> +       if (auth_handle)
> +               *auth_handle = oiap_session.handle;
> +       return 0;
> +}
> +
> +uint32_t tpm_load_key2_oiap(uint32_t parent_handle,
> +               const void *key, size_t key_length,
> +               const void *parent_key_usage_auth,
> +               uint32_t *key_handle)
> +{
> +       const uint8_t command[14] = {
> +               0x00, 0xc2,             /* TPM_TAG */
> +               0x00, 0x00, 0x00, 0x00, /* parameter size */
> +               0x00, 0x00, 0x00, 0x41, /* TPM_COMMAND_CODE */
> +               0x00, 0x00, 0x00, 0x00, /* parent handle */
> +       };
> +       const size_t req_size_offset = 2;
> +       const size_t req_parent_handle_offset = TPM_REQUEST_HEADER_LENGTH;
> +       const size_t req_key_offset = TPM_REQUEST_HEADER_LENGTH + 4;
> +       const size_t res_handle_offset = TPM_RESPONSE_HEADER_LENGTH;
> +       uint8_t request[sizeof(command) + TPM_KEY12_MAX_LENGTH
> +                       + TPM_REQUEST_AUTH_LENGTH];
> +       uint8_t response[COMMAND_BUFFER_SIZE];
> +       size_t response_length = sizeof(response);
> +       uint32_t err;
> +
> +       if (!oiap_session.valid) {
> +               err = tpm_oiap(NULL);
> +               if (err)
> +                       return err;
> +       }
> +       if (pack_byte_string(request, sizeof(request), "sdds",
> +                            0, command, sizeof(command),
> +                            req_size_offset,
> +                            sizeof(command) + key_length
> +                            + TPM_REQUEST_AUTH_LENGTH,
> +                            req_parent_handle_offset, parent_handle,
> +                            req_key_offset, key, key_length
> +               ))
> +               return TPM_LIB_ERROR;
> +
> +       err = create_request_auth(request, sizeof(command) + key_length, 4,
> +                               &oiap_session,
> +                               request + sizeof(command) + key_length,
> +                               parent_key_usage_auth);
> +       if (err)
> +               return err;
> +       err = tpm_sendrecv_command(request, response, &response_length);
> +       if (err) {
> +               if (err == TPM_AUTHFAIL)
> +                       oiap_session.valid = 0;
> +               return err;
> +       }
> +
> +       err = verify_response_auth(0x00000041, response,
> +                       response_length - TPM_RESPONSE_AUTH_LENGTH,
> +                       4, &oiap_session,
> +                       response + response_length - TPM_RESPONSE_AUTH_LENGTH,
> +                       parent_key_usage_auth);
> +       if (err)
> +               return err;
> +
> +       if (key_handle) {
> +               if (unpack_byte_string(response, response_length, "d",
> +                                      res_handle_offset, key_handle))
> +                       return TPM_LIB_ERROR;
> +       }
> +
> +       return 0;
> +}
> +
> +uint32_t tpm_get_pub_key_oiap(uint32_t key_handle, const void *usage_auth,
> +                       void *pubkey, size_t *pubkey_len)
> +{
> +       const uint8_t command[14] = {
> +               0x00, 0xc2,             /* TPM_TAG */
> +               0x00, 0x00, 0x00, 0x00, /* parameter size */
> +               0x00, 0x00, 0x00, 0x21, /* TPM_COMMAND_CODE */
> +               0x00, 0x00, 0x00, 0x00, /* key handle */
> +       };
> +       const size_t req_size_offset = 2;
> +       const size_t req_key_handle_offset = TPM_REQUEST_HEADER_LENGTH;
> +       const size_t res_pubkey_offset = TPM_RESPONSE_HEADER_LENGTH;
> +       uint8_t request[sizeof(command) + TPM_REQUEST_AUTH_LENGTH];
> +       uint8_t response[TPM_RESPONSE_HEADER_LENGTH + TPM_PUBKEY_MAX_LENGTH
> +                       + TPM_RESPONSE_AUTH_LENGTH];
> +       size_t response_length = sizeof(response);
> +       uint32_t err;
> +
> +       if (!oiap_session.valid) {
> +               err = tpm_oiap(NULL);
> +               if (err)
> +                       return err;
> +       }
> +       if (pack_byte_string(request, sizeof(request), "sdd",
> +                            0, command, sizeof(command),
> +                            req_size_offset,
> +                            (uint32_t)(sizeof(command)
> +                            + TPM_REQUEST_AUTH_LENGTH),
> +                            req_key_handle_offset, key_handle
> +               ))
> +               return TPM_LIB_ERROR;
> +       err = create_request_auth(request, sizeof(command), 4, &oiap_session,
> +                       request + sizeof(command), usage_auth);
> +       if (err)
> +               return err;
> +       err = tpm_sendrecv_command(request, response, &response_length);
> +       if (err) {
> +               if (err == TPM_AUTHFAIL)
> +                       oiap_session.valid = 0;
> +               return err;
> +       }
> +       err = verify_response_auth(0x00000021, response,
> +                       response_length - TPM_RESPONSE_AUTH_LENGTH,
> +                       0, &oiap_session,
> +                       response + response_length - TPM_RESPONSE_AUTH_LENGTH,
> +                       usage_auth);
> +       if (err)
> +               return err;
> +
> +       if (pubkey) {
> +               if ((response_length - TPM_RESPONSE_HEADER_LENGTH
> +                       - TPM_RESPONSE_AUTH_LENGTH) > *pubkey_len)
> +                       return TPM_LIB_ERROR;
> +               *pubkey_len = response_length - TPM_RESPONSE_HEADER_LENGTH
> +                       - TPM_RESPONSE_AUTH_LENGTH;
> +               memcpy(pubkey, response + res_pubkey_offset,
> +                      response_length - TPM_RESPONSE_HEADER_LENGTH
> +                      - TPM_RESPONSE_AUTH_LENGTH);
> +       }
> +
> +       return 0;
> +}
> +
> +#endif /* CONFIG_TPM_AUTH_SESSIONS */
> --
> 1.8.3
>

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

* [U-Boot] [PATCH v6 4/5] Build arch/$ARCH/lib/bootm.o depending on CONFIG_CMD_BOOTM
  2013-06-12  8:08 ` [U-Boot] [PATCH v6 4/5] Build arch/$ARCH/lib/bootm.o depending on CONFIG_CMD_BOOTM dirk.eibach at gdsys.cc
@ 2013-06-19 21:49   ` Andy Fleming
  2013-06-20  6:56     ` Dirk Eibach
  0 siblings, 1 reply; 12+ messages in thread
From: Andy Fleming @ 2013-06-19 21:49 UTC (permalink / raw)
  To: u-boot

On Wed, Jun 12, 2013 at 3:08 AM, <dirk.eibach@gdsys.cc> wrote:

> From: Dirk Eibach <eibach@gdsys.de>
>
> MAKEALL is fine for ppc4xx and mpc85xx.
> Run checks were done on our controlcenterd hardware.
>
> Signed-off-by: Dirk Eibach <dirk.eibach@gdsys.cc>
>
>
> Signed-off-by: Dirk Eibach <dirk.eibach@gdsys.cc>
>

You don't need two sign-offs.

Does anyone have comments on these patches? This one seems reasonable to
me, if a bit scary. Can others test this? Dirk has already tested this on
my systems. I'm not really sure these patches belong in my queue, but I can
apply them if other custodians give their sign-off.

Andy

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

* [U-Boot] [PATCH v6 2/5] i2c: fsl_i2c: i2c_read(): dont try to write address w/ alen=0
  2013-06-12  8:08 ` [U-Boot] [PATCH v6 2/5] i2c: fsl_i2c: i2c_read(): dont try to write address w/ alen=0 dirk.eibach at gdsys.cc
@ 2013-06-20  4:59   ` Heiko Schocher
  0 siblings, 0 replies; 12+ messages in thread
From: Heiko Schocher @ 2013-06-20  4:59 UTC (permalink / raw)
  To: u-boot

Hello Dirk,

Am 12.06.2013 10:08, schrieb dirk.eibach at gdsys.cc:
> From: Reinhard Pfau <pfau@gdsys.de>
> 
> if alen is 0: no longer start a write cycle before reading data.
> 
> Signed-off-by: Dirk Eibach <dirk.eibach@gdsys.cc>
> Signed-off-by: Reinhard Pfau <reinhard.pfau@gdsys.cc>
> 
> 
> Signed-off-by: Dirk Eibach <dirk.eibach@gdsys.cc>
> ---
> Changes in v6: None
> Changes in v5:
> - fix i2c_probe
> 
> Changes in v4: None
> Changes in v3: None
> Changes in v2:
> - whitespace fixes
> 
>  drivers/i2c/fsl_i2c.c | 9 ++++++---
>  1 file changed, 6 insertions(+), 3 deletions(-)

As it is in a patch serie:

Acked-by: Heiko Schocher <hs@denx.de>

bye,
Heiko
-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany

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

* [U-Boot] [PATCH v6 4/5] Build arch/$ARCH/lib/bootm.o depending on CONFIG_CMD_BOOTM
  2013-06-19 21:49   ` Andy Fleming
@ 2013-06-20  6:56     ` Dirk Eibach
  2013-06-20 13:06       ` Dirk Eibach
  0 siblings, 1 reply; 12+ messages in thread
From: Dirk Eibach @ 2013-06-20  6:56 UTC (permalink / raw)
  To: u-boot

Hi Andy,

>> From: Dirk Eibach <eibach@gdsys.de>
>>
>> MAKEALL is fine for ppc4xx and mpc85xx.
>> Run checks were done on our controlcenterd hardware.
>>
>> Signed-off-by: Dirk Eibach <dirk.eibach@gdsys.cc>
>>
>>
>> Signed-off-by: Dirk Eibach <dirk.eibach@gdsys.cc>
>
>
> You don't need two sign-offs.

patman puts and additional SOB to some of my patches. I'm not sure how
to fix this.

Cheers
Dirk

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

* [U-Boot] [PATCH v6 4/5] Build arch/$ARCH/lib/bootm.o depending on CONFIG_CMD_BOOTM
  2013-06-20  6:56     ` Dirk Eibach
@ 2013-06-20 13:06       ` Dirk Eibach
  0 siblings, 0 replies; 12+ messages in thread
From: Dirk Eibach @ 2013-06-20 13:06 UTC (permalink / raw)
  To: u-boot

2013/6/20 Dirk Eibach <dirk.eibach@gdsys.cc>:
> Hi Andy,
>
>>> From: Dirk Eibach <eibach@gdsys.de>
>>>
>>> MAKEALL is fine for ppc4xx and mpc85xx.
>>> Run checks were done on our controlcenterd hardware.
>>>
>>> Signed-off-by: Dirk Eibach <dirk.eibach@gdsys.cc>
>>>
>>>
>>> Signed-off-by: Dirk Eibach <dirk.eibach@gdsys.cc>
>>
>>
>> You don't need two sign-offs.
>
> patman puts and additional SOB to some of my patches. I'm not sure how
> to fix this.

Never mind. I just discovered that SOB line has to be located after
all the other patman stuff in the commit message, then it works as
expected. Will be fixed in v7.

Cheers
Dirk

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

end of thread, other threads:[~2013-06-20 13:06 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-06-12  8:08 [U-Boot] [PATCH v6 0/5] Add gdsys ControlCenter Digital board dirk.eibach at gdsys.cc
2013-06-12  8:08 ` [U-Boot] [PATCH v6 1/5] tpm: add AUTH1 cmds for LoadKey2 and GetPubKey dirk.eibach at gdsys.cc
2013-06-12 21:29   ` Che-liang Chiou
2013-06-12  8:08 ` [U-Boot] [PATCH v6 2/5] i2c: fsl_i2c: i2c_read(): dont try to write address w/ alen=0 dirk.eibach at gdsys.cc
2013-06-20  4:59   ` Heiko Schocher
2013-06-12  8:08 ` [U-Boot] [PATCH v6 3/5] Add Atmel I2C tpm dirk.eibach at gdsys.cc
2013-06-12  8:08 ` [U-Boot] [PATCH v6 4/5] Build arch/$ARCH/lib/bootm.o depending on CONFIG_CMD_BOOTM dirk.eibach at gdsys.cc
2013-06-19 21:49   ` Andy Fleming
2013-06-20  6:56     ` Dirk Eibach
2013-06-20 13:06       ` Dirk Eibach
2013-06-12  8:08 ` [U-Boot] [PATCH v6 5/5] mpc85xx: Add gdsys ControlCenter Digital board dirk.eibach at gdsys.cc
2013-06-12 18:12   ` Wolfgang Denk

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.