Re: [Openocd-development] [PATCH] kinetis auto mass erase on secured devices

2011-09-16 Thread Øyvind Harboe
Merged.

Thanks!




-- 
Øyvind Harboe - Can Zylin Consulting help on your project?
US toll free 1-866-980-3434
http://www.zylin.com/
___
Openocd-development mailing list
Openocd-development@lists.berlios.de
https://lists.berlios.de/mailman/listinfo/openocd-development


[Openocd-development] [PATCH] kinetis auto mass erase on secured devices

2011-09-12 Thread Mathias K.
Hello,

this patch add support for debug port access on a secured kinetis cpu with mass 
erase enabled.


Regards,

Mathias
From 63c322864f50d9c3489f498e2f29a508ac9156d8 Mon Sep 17 00:00:00 2001
From: Mathias K. kes...@freenet.de
Date: Mon, 12 Sep 2011 20:28:23 +0200
Subject: [PATCH] kinetis auto mass erase on secured devices

This is a proof of concept to get access to the debug port of a
secured kinetis cpu. On full flash erase the cpu is automatically
secured and the debug port is not accessible.
To get this to work the srst line is needed and the necessary
configuration should be added to the configuration file.
---
 src/target/arm_adi_v5.c |  182 +++
 1 files changed, 182 insertions(+), 0 deletions(-)

diff --git a/src/target/arm_adi_v5.c b/src/target/arm_adi_v5.c
index f8a2e22..cd68a20 100644
--- a/src/target/arm_adi_v5.c
+++ b/src/target/arm_adi_v5.c
@@ -955,6 +955,186 @@ int mem_ap_sel_write_buf_u32(struct adiv5_dap *swjdp, uint8_t ap,
 	return mem_ap_write_buf_u32(swjdp, buffer, count, address);
 }
 
+#define MDM_REG_STAT		0x00
+#define MDM_REG_CTRL		0x04
+#define MDM_REG_ID		0xfc
+
+#define MDM_STAT_FMEACK		(10)
+#define MDM_STAT_FREADY		(11)
+#define MDM_STAT_SYSSEC		(12)
+#define MDM_STAT_SYSRES		(13)
+#define MDM_STAT_FMEEN		(15)
+#define MDM_STAT_BACKDOOREN	(16)
+#define MDM_STAT_LPEN		(17)
+#define MDM_STAT_VLPEN		(18)
+#define MDM_STAT_LLSMODEXIT	(19)
+#define MDM_STAT_VLLSXMODEXIT	(110)
+#define MDM_STAT_CORE_HALTED	(116)
+#define MDM_STAT_CORE_SLEEPDEEP	(117)
+#define MDM_STAT_CORESLEEPING	(118)
+
+#define MEM_CTRL_FMEIP		(10)
+#define MEM_CTRL_DBG_DIS	(11)
+#define MEM_CTRL_DBG_REQ	(12)
+#define MEM_CTRL_SYS_RES_REQ	(13)
+#define MEM_CTRL_CORE_HOLD_RES	(14)
+#define MEM_CTRL_VLLSX_DBG_REQ	(15)
+#define MEM_CTRL_VLLSX_DBG_ACK	(16)
+#define MEM_CTRL_VLLSX_STAT_ACK	(17)
+
+/**
+ *
+ */
+int dap_syssec_kinetis_mdmap(struct adiv5_dap *dap)
+{
+	uint32_t val;
+	int retval;
+	enum reset_types jtag_reset_config = jtag_get_reset_config();
+
+	dap_ap_select(dap, 1);
+
+	/* first check mdm-ap id register */
+	retval = dap_queue_ap_read(dap, MDM_REG_ID, val);
+	if (retval != ERROR_OK)
+		return retval;
+	dap_run(dap);
+
+	if ( val != 0x001C )
+	{
+		LOG_DEBUG(id doesn't match %08X != 0x001C,val);
+		dap_ap_select(dap, 0);
+		return ERROR_FAIL;
+	}
+
+	/* read and parse status register
+	 * it's important that the device is out of
+	 * reset here
+	 */
+	retval = dap_queue_ap_read(dap, MDM_REG_STAT, val);
+	if (retval != ERROR_OK)
+		return retval;
+	dap_run(dap);
+
+	LOG_DEBUG(MDM_REG_STAT %08X,val);
+
+	if ( (val  (MDM_STAT_SYSSEC|MDM_STAT_FREADY)) != (MDM_STAT_FREADY) )
+	{
+		LOG_DEBUG(MDMAP: system is secured, masserase needed);
+
+		if ( !(val  MDM_STAT_FMEEN) )
+		{
+			LOG_DEBUG(MDMAP: masserase is disabled);
+		}
+		else
+		{
+			/* we need to assert reset */
+			if ( jtag_reset_config  RESET_HAS_SRST )
+			{
+/* default to asserting srst */
+if (jtag_reset_config  RESET_SRST_PULLS_TRST)
+{
+	jtag_add_reset(1, 1);
+}
+else
+{
+	jtag_add_reset(0, 1);
+}
+			}
+			else
+			{
+LOG_DEBUG(SRST not configured);
+dap_ap_select(dap, 0);
+return ERROR_FAIL;
+			}
+
+			while(1)
+			{
+retval = dap_queue_ap_write(dap, MDM_REG_CTRL, MEM_CTRL_FMEIP);
+if (retval != ERROR_OK)
+	return retval;
+dap_run(dap);
+/* read status register and wait for ready */
+retval = dap_queue_ap_read(dap, MDM_REG_STAT, val);
+if (retval != ERROR_OK)
+	return retval;
+dap_run(dap);
+LOG_DEBUG(MDM_REG_STAT %08X,val);
+
+if ( (val1))
+	break;
+			}
+
+			while(1)
+			{
+retval = dap_queue_ap_write(dap, MDM_REG_CTRL, 0);
+if (retval != ERROR_OK)
+	return retval;
+dap_run(dap);
+/* read status register */
+retval = dap_queue_ap_read(dap, MDM_REG_STAT, val);
+if (retval != ERROR_OK)
+	return retval;
+dap_run(dap);
+LOG_DEBUG(MDM_REG_STAT %08X,val);
+/* read control register and wait for ready */
+retval = dap_queue_ap_read(dap, MDM_REG_CTRL, val);
+if (retval != ERROR_OK)
+	return retval;
+dap_run(dap);
+LOG_DEBUG(MDM_REG_CTRL %08X,val);
+
+if ( val == 0x00 )
+	break;
+			}
+		}
+	}
+
+	dap_ap_select(dap, 0);
+
+	return ERROR_OK;
+}
+
+/** */
+typedef struct dap_syssec_filter_s {
+	/** */
+	uint32_t idcode;
+	/** */
+	int (*dap_init)(struct adiv5_dap *dap);
+} dap_syssec_filter_s;
+
+/** */
+static struct dap_syssec_filter_s dap_syssec_filter[] = {
+	{ 0x4BA00477, dap_syssec_kinetis_mdmap }
+};
+
+
+/**
+ *
+ */
+int dap_syssec(struct adiv5_dap *dap)
+{
+	unsigned int i;
+	struct jtag_tap *tap;
+
+	for(i=0;isizeof(dap_syssec_filter);i++)
+	{
+		tap = dap-jtag_info-tap;
+
+		while (tap != NULL)
+		{
+			if (!tap-hasidcode)
+continue;
+			if ( dap_syssec_filter[i].idcode == tap-idcode )
+			{
+LOG_DEBUG(DAP: mdmap_init for idcode: %08x,tap-idcode);
+dap_syssec_filter[i].dap_init(dap);
+			}
+			tap = 

Re: [Openocd-development] [PATCH] kinetis auto mass erase on secured devices

2011-09-12 Thread Eric Wetzel
On Mon, Sep 12, 2011 at 2:34 PM, Mathias K. kes...@freenet.de wrote:
 Hello,

 this patch add support for debug port access on a secured kinetis cpu with 
 mass erase enabled.


 Regards,

 Mathias


Hi,

This patch introduces an unused and unnecessary typedef and a tiny bit
of Hungarian-ish notation (the _s in dap_syssec_filter_s). Not sure if
we're going to be moving ahead on the Linux style, but automatic
formatters will not catch the Linux aversion to typedefs and
Hungarian.

Regards,
~Eric
___
Openocd-development mailing list
Openocd-development@lists.berlios.de
https://lists.berlios.de/mailman/listinfo/openocd-development


Re: [Openocd-development] [PATCH] kinetis auto mass erase on secured devices

2011-09-12 Thread Mathias K.
Hello,

yes you are right. Changes appended.


Regards,

Mathias

Am 12.09.2011 21:09, schrieb Eric Wetzel:
 On Mon, Sep 12, 2011 at 2:34 PM, Mathias K. kes...@freenet.de wrote:
 Hello,

 this patch add support for debug port access on a secured kinetis cpu with 
 mass erase enabled.


 Regards,

 Mathias

 
 Hi,
 
 This patch introduces an unused and unnecessary typedef and a tiny bit
 of Hungarian-ish notation (the _s in dap_syssec_filter_s). Not sure if
 we're going to be moving ahead on the Linux style, but automatic
 formatters will not catch the Linux aversion to typedefs and
 Hungarian.
 
 Regards,
 ~Eric


From becb405a8fb2253cbc99b114d2701ff81dc5bd6b Mon Sep 17 00:00:00 2001
From: Mathias K. kes...@freenet.de
Date: Mon, 12 Sep 2011 21:24:17 +0200
Subject: [PATCH] kinetis auto mass erase on secured devices

This is a proof of concept to get access to the debug port of a
secured kinetis cpu. On full flash erase the cpu is automatically
secured and the debug port is not accessible.
To get this to work the srst line is needed and the necessary
configuration should be added to the configuration file.
---
 src/target/arm_adi_v5.c |  182 +++
 1 files changed, 182 insertions(+), 0 deletions(-)

diff --git a/src/target/arm_adi_v5.c b/src/target/arm_adi_v5.c
index f8a2e22..21dc54c 100644
--- a/src/target/arm_adi_v5.c
+++ b/src/target/arm_adi_v5.c
@@ -955,6 +955,186 @@ int mem_ap_sel_write_buf_u32(struct adiv5_dap *swjdp, uint8_t ap,
 	return mem_ap_write_buf_u32(swjdp, buffer, count, address);
 }
 
+#define MDM_REG_STAT		0x00
+#define MDM_REG_CTRL		0x04
+#define MDM_REG_ID		0xfc
+
+#define MDM_STAT_FMEACK		(10)
+#define MDM_STAT_FREADY		(11)
+#define MDM_STAT_SYSSEC		(12)
+#define MDM_STAT_SYSRES		(13)
+#define MDM_STAT_FMEEN		(15)
+#define MDM_STAT_BACKDOOREN	(16)
+#define MDM_STAT_LPEN		(17)
+#define MDM_STAT_VLPEN		(18)
+#define MDM_STAT_LLSMODEXIT	(19)
+#define MDM_STAT_VLLSXMODEXIT	(110)
+#define MDM_STAT_CORE_HALTED	(116)
+#define MDM_STAT_CORE_SLEEPDEEP	(117)
+#define MDM_STAT_CORESLEEPING	(118)
+
+#define MEM_CTRL_FMEIP		(10)
+#define MEM_CTRL_DBG_DIS	(11)
+#define MEM_CTRL_DBG_REQ	(12)
+#define MEM_CTRL_SYS_RES_REQ	(13)
+#define MEM_CTRL_CORE_HOLD_RES	(14)
+#define MEM_CTRL_VLLSX_DBG_REQ	(15)
+#define MEM_CTRL_VLLSX_DBG_ACK	(16)
+#define MEM_CTRL_VLLSX_STAT_ACK	(17)
+
+/**
+ *
+ */
+int dap_syssec_kinetis_mdmap(struct adiv5_dap *dap)
+{
+	uint32_t val;
+	int retval;
+	enum reset_types jtag_reset_config = jtag_get_reset_config();
+
+	dap_ap_select(dap, 1);
+
+	/* first check mdm-ap id register */
+	retval = dap_queue_ap_read(dap, MDM_REG_ID, val);
+	if (retval != ERROR_OK)
+		return retval;
+	dap_run(dap);
+
+	if ( val != 0x001C )
+	{
+		LOG_DEBUG(id doesn't match %08X != 0x001C,val);
+		dap_ap_select(dap, 0);
+		return ERROR_FAIL;
+	}
+
+	/* read and parse status register
+	 * it's important that the device is out of
+	 * reset here
+	 */
+	retval = dap_queue_ap_read(dap, MDM_REG_STAT, val);
+	if (retval != ERROR_OK)
+		return retval;
+	dap_run(dap);
+
+	LOG_DEBUG(MDM_REG_STAT %08X,val);
+
+	if ( (val  (MDM_STAT_SYSSEC|MDM_STAT_FREADY)) != (MDM_STAT_FREADY) )
+	{
+		LOG_DEBUG(MDMAP: system is secured, masserase needed);
+
+		if ( !(val  MDM_STAT_FMEEN) )
+		{
+			LOG_DEBUG(MDMAP: masserase is disabled);
+		}
+		else
+		{
+			/* we need to assert reset */
+			if ( jtag_reset_config  RESET_HAS_SRST )
+			{
+/* default to asserting srst */
+if (jtag_reset_config  RESET_SRST_PULLS_TRST)
+{
+	jtag_add_reset(1, 1);
+}
+else
+{
+	jtag_add_reset(0, 1);
+}
+			}
+			else
+			{
+LOG_DEBUG(SRST not configured);
+dap_ap_select(dap, 0);
+return ERROR_FAIL;
+			}
+
+			while(1)
+			{
+retval = dap_queue_ap_write(dap, MDM_REG_CTRL, MEM_CTRL_FMEIP);
+if (retval != ERROR_OK)
+	return retval;
+dap_run(dap);
+/* read status register and wait for ready */
+retval = dap_queue_ap_read(dap, MDM_REG_STAT, val);
+if (retval != ERROR_OK)
+	return retval;
+dap_run(dap);
+LOG_DEBUG(MDM_REG_STAT %08X,val);
+
+if ( (val1))
+	break;
+			}
+
+			while(1)
+			{
+retval = dap_queue_ap_write(dap, MDM_REG_CTRL, 0);
+if (retval != ERROR_OK)
+	return retval;
+dap_run(dap);
+/* read status register */
+retval = dap_queue_ap_read(dap, MDM_REG_STAT, val);
+if (retval != ERROR_OK)
+	return retval;
+dap_run(dap);
+LOG_DEBUG(MDM_REG_STAT %08X,val);
+/* read control register and wait for ready */
+retval = dap_queue_ap_read(dap, MDM_REG_CTRL, val);
+if (retval != ERROR_OK)
+	return retval;
+dap_run(dap);
+LOG_DEBUG(MDM_REG_CTRL %08X,val);
+
+if ( val == 0x00 )
+	break;
+			}
+		}
+	}
+
+	dap_ap_select(dap, 0);
+
+	return ERROR_OK;
+}
+
+/** */
+struct dap_syssec_filter {
+	/** */
+	uint32_t idcode;
+	/** */
+	int (*dap_init)(struct adiv5_dap *dap);
+};
+
+/** */
+static struct dap_syssec_filter dap_syssec_filter_data[] = {
+