aboot: Store unlock and rooted flag on NAND and eMMC.

-- Add 'fastboot oem unlock' command.
-- Add support to store ulock and rooted flags on disk.
-- Add support to reset rooted flag on request from recovery partition.

Change-Id: I9dc5c13f69a266ff6c81cc7157b43a975fbbf9e0
diff --git a/app/aboot/aboot.c b/app/aboot/aboot.c
index 312b278..f2d1169 100644
--- a/app/aboot/aboot.c
+++ b/app/aboot/aboot.c
@@ -55,8 +55,9 @@
 #include "fastboot.h"
 #include "sparse_format.h"
 #include "mmc.h"
+#include "devinfo.h"
 
-#include "scm_decrypt.h"
+#include "scm.h"
 
 #define EXPAND(NAME) #NAME
 #define TARGET(NAME) EXPAND(NAME)
@@ -84,6 +85,8 @@
 /* Assuming unauthorized kernel image by default */
 static int auth_kernel_img = 0;
 
+static device_info device = {DEVICE_MAGIC, 0, 0};
+
 static struct udc_device surf_udc_device = {
 	.vendor_id	= 0x18d1,
 	.product_id	= 0xD00D,
@@ -353,7 +356,7 @@
 	}
 
 	/* Authenticate Kernel */
-	if(target_use_signed_kernel())
+	if(target_use_signed_kernel() && (!device.is_unlocked) && (!device.is_rooted))
 	{
 		image_addr = (unsigned char *)target_get_scratch_address();
 		kernel_actual = ROUND_TO_PAGE(hdr->kernel_size, page_mask);
@@ -361,6 +364,10 @@
 		imagesize_actual = (page_size + kernel_actual + ramdisk_actual);
 
 		offset = 0;
+
+		/* Assuming device rooted at this time */
+		device.is_rooted = 1;
+
 		/* Read image without signature */
 		if (mmc_read(ptn + offset, (void *)image_addr, imagesize_actual))
 		{
@@ -380,11 +387,26 @@
 					(unsigned char *)(image_addr + imagesize_actual),
 					imagesize_actual,
 					CRYPTO_AUTH_ALG_SHA256);
+
+			if(auth_kernel_img)
+			{
+				/* Authorized kernel */
+				device.is_rooted = 0;
+			}
 		}
 
 		/* Move kernel and ramdisk to correct address */
 		memmove((void*) hdr->kernel_addr, (char *)(image_addr + page_size), hdr->kernel_size);
 		memmove((void*) hdr->ramdisk_addr, (char *)(image_addr + page_size + kernel_actual), hdr->ramdisk_size);
+
+		/* Make sure everything from scratch address is read before next step!*/
+		if(device.is_rooted)
+		{
+			write_device_info_mmc(&device);
+		#ifdef TZ_TAMPER_FUSE
+			set_tamper_fuse_cmd();
+		#endif
+		}
 	}
 	else
 	{
@@ -479,7 +501,6 @@
 		dprintf(CRITICAL, "ERROR: Cannot read boot image header\n");
 		return -1;
 	}
-	offset += page_size;
 
 	if (memcmp(hdr->magic, BOOT_MAGIC, BOOT_MAGIC_SIZE)) {
 		dprintf(CRITICAL, "ERROR: Invalid boot image header\n");
@@ -492,7 +513,7 @@
 	}
 
 	/* Authenticate Kernel */
-	if(target_use_signed_kernel())
+	if(target_use_signed_kernel() && (!device.is_unlocked) && (!device.is_rooted))
 	{
 		image_addr = (unsigned char *)target_get_scratch_address();
 		kernel_actual = ROUND_TO_PAGE(hdr->kernel_size, page_mask);
@@ -500,6 +521,10 @@
 		imagesize_actual = (page_size + kernel_actual + ramdisk_actual);
 
 		offset = 0;
+
+		/* Assuming device rooted at this time */
+		device.is_rooted = 1;
+
 		/* Read image without signature */
 		if (flash_read(ptn, offset, (void *)image_addr, imagesize_actual))
 		{
@@ -521,14 +546,28 @@
 						(unsigned char *)(image_addr + imagesize_actual),
 						imagesize_actual,
 						CRYPTO_AUTH_ALG_SHA256);
+
+			if(auth_kernel_img)
+			{
+				/* Authorized kernel */
+				device.is_rooted = 0;
+			}
 		}
 
 		/* Move kernel and ramdisk to correct address */
 		memmove((void*) hdr->kernel_addr, (char *)(image_addr + page_size), hdr->kernel_size);
 		memmove((void*) hdr->ramdisk_addr, (char *)(image_addr + page_size + kernel_actual), hdr->ramdisk_size);
+
+		/* Make sure everything from scratch address is read before next step!*/
+		if(device.is_rooted)
+		{
+			write_device_info_flash(&device);
+		}
 	}
 	else
 	{
+		offset = page_size;
+
 		n = ROUND_TO_PAGE(hdr->kernel_size, page_mask);
 		if (flash_read(ptn, offset, (void *)hdr->kernel_addr, n)) {
 			dprintf(CRITICAL, "ERROR: Cannot read kernel image\n");
@@ -566,12 +605,176 @@
 	return 0;
 }
 
+unsigned char info_buf[4096];
+void write_device_info_mmc(device_info *dev)
+{
+	struct device_info *info = (void*) info_buf;
+	unsigned long long ptn = 0;
+	unsigned long long size;
+	int index = INVALID_PTN;
+
+	index = partition_get_index("aboot");
+	ptn = partition_get_offset(index);
+	if(ptn == 0)
+	{
+		return;
+	}
+
+	size = partition_get_size(index);
+
+	memcpy(info, dev, sizeof(device_info));
+
+	if(mmc_write((ptn + size - 512), 512, (void *)info_buf))
+	{
+		dprintf(CRITICAL, "ERROR: Cannot write device info\n");
+		return;
+	}
+}
+
+void read_device_info_mmc(device_info *dev)
+{
+	struct device_info *info = (void*) info_buf;
+	unsigned long long ptn = 0;
+	unsigned long long size;
+	int index = INVALID_PTN;
+
+	index = partition_get_index("aboot");
+	ptn = partition_get_offset(index);
+	if(ptn == 0)
+	{
+		return;
+	}
+
+	size = partition_get_size(index);
+
+	if(mmc_read((ptn + size - 512), (void *)info_buf, 512))
+	{
+		dprintf(CRITICAL, "ERROR: Cannot read device info\n");
+		return;
+	}
+
+	if (memcmp(info->magic, DEVICE_MAGIC, DEVICE_MAGIC_SIZE))
+	{
+		memcpy(info->magic, DEVICE_MAGIC, DEVICE_MAGIC_SIZE);
+		info->is_unlocked = 0;
+		info->is_rooted = 0;
+
+		write_device_info_mmc(info);
+	}
+	memcpy(dev, info, sizeof(device_info));
+}
+
+void write_device_info_flash(device_info *dev)
+{
+	struct device_info *info = (void *) info_buf;
+	struct ptentry *ptn;
+	struct ptable *ptable;
+
+	ptable = flash_get_ptable();
+	if (ptable == NULL)
+	{
+		dprintf(CRITICAL, "ERROR: Partition table not found\n");
+		return;
+	}
+
+	ptn = ptable_find(ptable, "devinfo");
+	if (ptn == NULL)
+	{
+		dprintf(CRITICAL, "ERROR: No boot partition found\n");
+			return;
+	}
+
+	memcpy(info, dev, sizeof(device_info));
+
+	if (flash_write(ptn, 0, (void *)info_buf, page_size))
+	{
+		dprintf(CRITICAL, "ERROR: Cannot write device info\n");
+			return;
+	}
+}
+
+void read_device_info_flash(device_info *dev)
+{
+	struct device_info *info = (void*) info_buf;
+	struct ptentry *ptn;
+	struct ptable *ptable;
+
+	ptable = flash_get_ptable();
+	if (ptable == NULL)
+	{
+		dprintf(CRITICAL, "ERROR: Partition table not found\n");
+		return;
+	}
+
+	ptn = ptable_find(ptable, "devinfo");
+	if (ptn == NULL)
+	{
+		dprintf(CRITICAL, "ERROR: No boot partition found\n");
+			return;
+	}
+
+	if (flash_read(ptn, 0, (void *)info_buf, page_size))
+	{
+		dprintf(CRITICAL, "ERROR: Cannot write device info\n");
+			return;
+	}
+
+	if (memcmp(info->magic, DEVICE_MAGIC, DEVICE_MAGIC_SIZE))
+	{
+		while(1);
+		memcpy(info->magic, DEVICE_MAGIC, DEVICE_MAGIC_SIZE);
+		info->is_unlocked = 0;
+		info->is_rooted = 0;
+		write_device_info_flash(info);
+	}
+	memcpy(dev, info, sizeof(device_info));
+}
+
+void write_device_info(device_info *dev)
+{
+	if(target_is_emmc_boot())
+	{
+		write_device_info_mmc(dev);
+	}
+	else
+	{
+		write_device_info_flash(dev);
+	}
+}
+
+void read_device_info(device_info *dev)
+{
+	if(target_is_emmc_boot())
+	{
+		read_device_info_mmc(dev);
+	}
+	else
+	{
+		read_device_info_flash(dev);
+	}
+}
+
+void reset_device_info()
+{
+	dprintf(ALWAYS, "reset_device_info called.");
+	device.is_rooted = 0;
+	write_device_info(&device);
+}
+
+void set_device_root()
+{
+	dprintf(ALWAYS, "set_device_root called.");
+	device.is_rooted = 1;
+	write_device_info(&device);
+}
+
 void cmd_boot(const char *arg, void *data, unsigned sz)
 {
 	unsigned kernel_actual;
 	unsigned ramdisk_actual;
 	static struct boot_img_hdr hdr;
 	char *ptr = ((char*) data);
+	unsigned image_actual;
 
 	if (sz < sizeof(hdr)) {
 		fastboot_fail("invalid bootimage header");
@@ -590,8 +793,12 @@
 
 	kernel_actual = ROUND_TO_PAGE(hdr.kernel_size, page_mask);
 	ramdisk_actual = ROUND_TO_PAGE(hdr.ramdisk_size, page_mask);
+	image_actual = page_size + kernel_actual + ramdisk_actual;
 
-	if (page_size + kernel_actual + ramdisk_actual < sz) {
+	if(target_use_signed_kernel())
+		image_actual += page_size;
+
+	if (image_actual > sz) {
 		fastboot_fail("incomplete bootimage");
 		return;
 	}
@@ -699,8 +906,6 @@
 	return;
 }
 
-
-
 void cmd_flash_mmc_sparse_img(const char *arg, void *data, unsigned sz)
 {
 	unsigned int chunk;
@@ -911,6 +1116,16 @@
 	reboot_device(FASTBOOT_MODE);
 }
 
+void cmd_oem_unlock(const char *arg, void *data, unsigned sz)
+{
+	if(!device.is_unlocked)
+	{
+		device.is_unlocked = 1;
+		write_device_info(&device);
+	}
+	fastboot_okay("");
+}
+
 void splash_screen ()
 {
 	struct ptentry *ptn;
@@ -959,6 +1174,18 @@
 		page_mask = page_size - 1;
 	}
 
+	if(target_use_signed_kernel())
+	{
+		read_device_info(&device);
+
+		if((device.is_unlocked) || (device.is_rooted))
+		{
+		#ifdef TZ_TAMPER_FUSE
+			set_tamper_fuse_cmd();
+		#endif
+		}
+	}
+
 	target_serialno((unsigned char *) sn_buf);
 	dprintf(SPEW,"serial number: %s\n",sn_buf);
 	surf_udc_device.serialno = sn_buf;
@@ -1008,7 +1235,7 @@
 
 fastboot:
 
-       target_fastboot_init();
+	target_fastboot_init();
 
 	if(!usb_init)
 		udc_init(&surf_udc_device);
@@ -1029,8 +1256,11 @@
 	fastboot_register("continue", cmd_continue);
 	fastboot_register("reboot", cmd_reboot);
 	fastboot_register("reboot-bootloader", cmd_reboot_bootloader);
+	fastboot_register("oem unlock", cmd_oem_unlock);
 	fastboot_publish("product", TARGET(BOARD));
 	fastboot_publish("kernel", "lk");
+	fastboot_publish("root-flag", device.is_rooted);
+	fastboot_publish("unlock-flag", device.is_unlocked);
 	partition_dump();
 	sz = target_get_max_flash_size();
 	fastboot_init(target_get_scratch_address(), sz);
diff --git a/app/aboot/devinfo.h b/app/aboot/devinfo.h
new file mode 100644
index 0000000..51cc9c7
--- /dev/null
+++ b/app/aboot/devinfo.h
@@ -0,0 +1,45 @@
+/*
+ * * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above
+ *    copyright notice, this list of conditions and the following
+ *    disclaimer in the documentation and/or other materials provided
+ *    with the distribution.
+ *  * Neither the name of Code Aurora Forum, Inc. nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _DEVINFO_H_
+#define _DEVINFO_H_
+
+typedef struct device_info device_info;
+
+#define DEVICE_MAGIC "ANDROID-BOOT!"
+#define DEVICE_MAGIC_SIZE 13
+
+struct device_info
+{
+	unsigned char magic[DEVICE_MAGIC_SIZE];
+	bool is_unlocked;
+	bool is_rooted;
+};
+
+#endif
diff --git a/app/aboot/recovery.c b/app/aboot/recovery.c
index 2ff6804..898ccb6 100644
--- a/app/aboot/recovery.c
+++ b/app/aboot/recovery.c
@@ -53,6 +53,8 @@
 static char buf[4096];
 unsigned boot_into_recovery = 0;
 
+extern void reset_device_info();
+extern void set_device_root();
 
 int get_recovery_message(struct recovery_message *out)
 {
@@ -447,12 +449,20 @@
 			dprintf(INFO,"radio update failed\n");
 			strcpy(msg.status, "failed-update");
 		}
+		boot_into_recovery = 1;		// Boot in recovery mode
+	}
+	if (!strcmp("reset-device-info",msg.command))
+	{
+		reset_device_info();
+	}
+	if (!strcmp("root-detect",msg.command))
+	{
+		set_device_root();
 	}
 	else
 		return 0;	// do nothing
 
 	strcpy(msg.command, "");	// clearing recovery command
 	emmc_set_recovery_msg(&msg);	// send recovery message
-	boot_into_recovery = 1;		// Boot in recovery mode
 	return 0;
 }
diff --git a/platform/msm8x60/rules.mk b/platform/msm8x60/rules.mk
index a5c7f64..42a12cc 100755
--- a/platform/msm8x60/rules.mk
+++ b/platform/msm8x60/rules.mk
@@ -10,7 +10,7 @@
 
 DEFINES += WITH_CPU_EARLY_INIT=0 WITH_CPU_WARM_BOOT=0 \
 	   MMC_SLOT=$(MMC_SLOT) MDP4=1 \
-	   SSD_ENABLE
+	   SSD_ENABLE TZ_TAMPER_FUSE
 
 
 DEFINES += QT_8660_KEYPAD_HW_BUG=1
diff --git a/platform/msm_shared/include/scm.h b/platform/msm_shared/include/scm.h
new file mode 100644
index 0000000..456cf46
--- /dev/null
+++ b/platform/msm_shared/include/scm.h
@@ -0,0 +1,125 @@
+/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above
+ *     copyright notice, this list of conditions and the following
+ *     disclaimer in the documentation and/or other materials provided
+ *     with the distribution.
+ *   * Neither the name of Code Aurora Forum, Inc. nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __SCM_H__
+#define __SCM_H__
+
+/* 8 Byte SSD magic number (LE) */
+#define SSD_HEADER_MAGIC_0     0x73737A74
+#define SSD_HEADER_MAGIC_1     0x676D6964
+#define SSD_HEADER_MAGIC_SIZE  8
+#define SSD_HEADER_XML_SIZE    2048
+
+typedef unsigned int uint32;
+
+typedef struct
+{
+	uint32  len;
+	uint32  buf_offset;
+	uint32  resp_hdr_offset;
+	uint32  id;
+} scm_command;
+
+typedef struct
+{
+	uint32  len;
+	uint32  buf_offset;
+	uint32  is_complete;
+} scm_response;
+
+typedef struct
+{
+	scm_command     common_req;
+	uint32*         img_ptr;
+	uint32*         img_len_ptr;
+} decrypt_img_req;
+
+#define SYSCALL_CREATE_CMD_ID(s, f) \
+	((uint32)(((s & 0x3ff) << 10) | (f & 0x3ff)))
+
+#define SCM_SVC_SSD                7
+#define SSD_DECRYPT_IMG_ID SYSCALL_CREATE_CMD_ID(SCM_SVC_SSD, 0x01)
+
+void setup_decrypt_cmd ( decrypt_img_req* dec_cmd,
+		uint32** img_ptr,
+		uint32* img_len_ptr);
+static uint32 smc(uint32 cmd_addr);
+int decrypt_img_scm(uint32** img_ptr, uint32* img_len_ptr);
+
+#define SCM_SVC_FUSE            0x08
+#define SCM_BLOW_SW_FUSE_ID     0x01
+#define SCM_IS_SW_FUSE_BLOWN_ID 0x02
+
+#define HLOS_IMG_TAMPER_FUSE    0
+void set_tamper_fuse_cmd();
+
+/**
+ * struct scm_command - one SCM command buffer
+ * @len: total available memory for command and response
+ * @buf_offset: start of command buffer
+ * @resp_hdr_offset: start of response buffer
+ * @id: command to be executed
+ * @buf: buffer returned from scm_get_command_buffer()
+ *
+ * An SCM command is layed out in memory as follows:
+ *
+ *	------------------- <--- struct scm_command
+ *	| command header  |
+ *	------------------- <--- scm_get_command_buffer()
+ *	| command buffer  |
+ *	------------------- <--- struct scm_response and
+ *	| response header |      scm_command_to_response()
+ *	------------------- <--- scm_get_response_buffer()
+ *	| response buffer |
+ *	-------------------
+ *
+ * There can be arbitrary padding between the headers and buffers so
+ * you should always use the appropriate scm_get_*_buffer() routines
+ * to access the buffers in a safe manner.
+ */
+struct scm_command {
+	uint32_t	len;
+	uint32_t	buf_offset;
+	uint32_t	resp_hdr_offset;
+	uint32_t	id;
+	uint32_t	buf[0];
+};
+
+/**
+ * struct scm_response - one SCM response buffer
+ * @len: total available memory for response
+ * @buf_offset: start of response data relative to start of scm_response
+ * @is_complete: indicates if the command has finished processing
+ */
+struct scm_response {
+	uint32_t	len;
+	uint32_t	buf_offset;
+	uint32_t	is_complete;
+};
+
+#endif
diff --git a/platform/msm_shared/include/scm_decrypt.h b/platform/msm_shared/include/scm_decrypt.h
deleted file mode 100644
index 4740759..0000000
--- a/platform/msm_shared/include/scm_decrypt.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
-
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *   * Redistributions of source code must retain the above copyright
- *     notice, this list of conditions and the following disclaimer.
- *   * Redistributions in binary form must reproduce the above
- *     copyright notice, this list of conditions and the following
- *     disclaimer in the documentation and/or other materials provided
- *     with the distribution.
- *   * Neither the name of Code Aurora Forum, Inc. nor the names of its
- *     contributors may be used to endorse or promote products derived
- *     from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
- * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
- * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <stdlib.h>
-
-/* 8 Byte SSD magic number (LE) */
-#define SSD_HEADER_MAGIC_0     0x73737A74
-#define SSD_HEADER_MAGIC_1     0x676D6964
-#define SSD_HEADER_MAGIC_SIZE  8
-#define SSD_HEADER_XML_SIZE    2048
-
-typedef unsigned int uint32;
-
-typedef struct
-{
-    uint32  len;
-    uint32  buf_offset;
-    uint32  resp_hdr_offset;
-    uint32  id;
-} scm_command;
-
-typedef struct
-{
-    uint32  len;
-    uint32  buf_offset;
-    uint32  is_complete;
-} scm_response;
-
-typedef struct
-{
-    scm_command     common_req;
-    uint32*         img_ptr;
-    uint32*         img_len_ptr;
-} decrypt_img_req;
-
-#define SYSCALL_CREATE_CMD_ID(s, f) \
-  ((uint32)(((s & 0x3ff) << 10) | (f & 0x3ff)))
-
-#define SCM_SVC_SSD                7
-#define SSD_DECRYPT_IMG_ID SYSCALL_CREATE_CMD_ID(SCM_SVC_SSD, 0x01)
-
-void setup_decrypt_cmd ( decrypt_img_req* dec_cmd,
-                         uint32** img_ptr,
-                         uint32* img_len_ptr);
-static uint32 smc(uint32 cmd_addr);
-int decrypt_img_scm(uint32** img_ptr, uint32* img_len_ptr);
diff --git a/platform/msm_shared/rules.mk b/platform/msm_shared/rules.mk
index 7887a8f..f2edb0e 100644
--- a/platform/msm_shared/rules.mk
+++ b/platform/msm_shared/rules.mk
@@ -24,7 +24,7 @@
 			$(LOCAL_DIR)/uart_dm.o \
 			$(LOCAL_DIR)/crypto_eng.o \
 			$(LOCAL_DIR)/crypto_hash.o \
-			$(LOCAL_DIR)/scm_decrypt.o \
+			$(LOCAL_DIR)/scm.o \
 			$(LOCAL_DIR)/lcdc.o \
 			$(LOCAL_DIR)/mddi.o \
 			$(LOCAL_DIR)/qgic.o \
diff --git a/platform/msm_shared/scm.c b/platform/msm_shared/scm.c
new file mode 100644
index 0000000..5838afd
--- /dev/null
+++ b/platform/msm_shared/scm.c
@@ -0,0 +1,251 @@
+/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above
+ *     copyright notice, this list of conditions and the following
+ *     disclaimer in the documentation and/or other materials provided
+ *     with the distribution.
+ *   * Neither the name of Code Aurora Forum, Inc. nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <err.h>
+#include "scm.h"
+
+#pragma GCC optimize ("O0")
+
+/* From Linux Kernel asm/system.h */
+#define __asmeq(x, y)  ".ifnc " x "," y " ; .err ; .endif\n\t"
+
+#ifndef offsetof
+#  define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
+#endif
+
+/**
+ * alloc_scm_command() - Allocate an SCM command
+ * @cmd_size: size of the command buffer
+ * @resp_size: size of the response buffer
+ *
+ * Allocate an SCM command, including enough room for the command
+ * and response headers as well as the command and response buffers.
+ *
+ * Returns a valid &scm_command on success or %NULL if the allocation fails.
+ */
+static struct scm_command *alloc_scm_command(size_t cmd_size, size_t resp_size)
+{
+	struct scm_command *cmd;
+	size_t len = sizeof(*cmd) + sizeof(struct scm_response) + cmd_size +
+		resp_size;
+
+	cmd = malloc(len);
+	if (cmd)
+	{
+		cmd->len = len;
+		cmd->buf_offset = offsetof(struct scm_command, buf);
+		cmd->resp_hdr_offset = cmd->buf_offset + cmd_size;
+	}
+	return cmd;
+}
+
+/**
+ * free_scm_command() - Free an SCM command
+ * @cmd: command to free
+ *
+ * Free an SCM command.
+ */
+static inline void free_scm_command(struct scm_command *cmd)
+{
+	free(cmd);
+}
+
+/**
+ * scm_command_to_response() - Get a pointer to a scm_response
+ * @cmd: command
+ *
+ * Returns a pointer to a response for a command.
+ */
+static inline struct scm_response *scm_command_to_response(
+		const struct scm_command *cmd)
+{
+	return (void *)cmd + cmd->resp_hdr_offset;
+}
+
+/**
+ * scm_get_command_buffer() - Get a pointer to a command buffer
+ * @cmd: command
+ *
+ * Returns a pointer to the command buffer of a command.
+ */
+static inline void *scm_get_command_buffer(const struct scm_command *cmd)
+{
+	return (void *)cmd->buf;
+}
+
+/**
+ * scm_get_response_buffer() - Get a pointer to a response buffer
+ * @rsp: response
+ *
+ * Returns a pointer to a response buffer of a response.
+ */
+static inline void *scm_get_response_buffer(const struct scm_response *rsp)
+{
+	return (void *)rsp + rsp->buf_offset;
+}
+
+static uint32_t smc(uint32_t cmd_addr)
+{
+	uint32_t context_id;
+	register uint32_t r0 __asm__("r0") = 1;
+	register uint32_t r1 __asm__("r1") = (uint32_t)&context_id;
+	register uint32_t r2 __asm__("r2") = cmd_addr;
+	__asm__(
+			"1:smc	#0	@ switch to secure world\n"
+			"cmp	r0, #1				\n"
+			"beq	1b				\n"
+			: "=r" (r0)
+			: "r" (r0), "r" (r1), "r" (r2)
+			: "r3", "cc");
+	return r0;
+}
+
+/**
+ * scm_call() - Send an SCM command
+ * @svc_id: service identifier
+ * @cmd_id: command identifier
+ * @cmd_buf: command buffer
+ * @cmd_len: length of the command buffer
+ * @resp_buf: response buffer
+ * @resp_len: length of the response buffer
+ *
+ * Sends a command to the SCM and waits for the command to finish processing.
+ */
+int scm_call(uint32_t svc_id, uint32_t cmd_id, const void *cmd_buf, size_t cmd_len,
+		void *resp_buf, size_t resp_len)
+{
+	int ret;
+	struct scm_command *cmd;
+	struct scm_response *rsp;
+
+	cmd = alloc_scm_command(cmd_len, resp_len);
+	if (!cmd)
+		return ERR_NO_MEMORY;
+
+	cmd->id = (svc_id << 10) | cmd_id;
+	if (cmd_buf)
+		memcpy(scm_get_command_buffer(cmd), cmd_buf, cmd_len);
+
+	ret = smc((uint32_t)cmd);
+	if (ret)
+		goto out;
+
+	if(resp_len)
+	{
+		rsp = scm_command_to_response(cmd);
+
+		while (!rsp->is_complete);
+
+		if (resp_buf)
+			memcpy(resp_buf, scm_get_response_buffer(rsp), resp_len);
+	}
+out:
+	free_scm_command(cmd);
+	return ret;
+}
+
+/* SCM Decrypt Command */
+void setup_decrypt_cmd ( decrypt_img_req* dec_cmd,
+		uint32_t** img_ptr,
+		uint32_t* img_len_ptr)
+{
+	dec_cmd->common_req.len = sizeof(decrypt_img_req);
+	dec_cmd->common_req.buf_offset = sizeof(scm_command);
+	dec_cmd->common_req.resp_hdr_offset = 0;
+	dec_cmd->common_req.id = SSD_DECRYPT_IMG_ID;
+
+	dec_cmd->img_ptr = img_ptr;
+	dec_cmd->img_len_ptr = img_len_ptr;
+}
+
+int decrypt_img_scm(uint32_t** img_ptr, uint32_t* img_len_ptr)
+{
+	int ret = 0;
+	decrypt_img_req *decrypt_cmd;
+
+	/* allocate memory for the command structure */
+	/* NEEDS TO BE CONTIGUOUS MEMORY */
+	decrypt_cmd = malloc(sizeof(decrypt_img_req));
+
+	/* setup the command for decryption */
+	setup_decrypt_cmd(decrypt_cmd, img_ptr, img_len_ptr);
+
+	ret = smc(decrypt_cmd);
+	free(decrypt_cmd);
+	return ret;
+}
+
+void set_tamper_fuse_cmd()
+{
+	uint32_t svc_id;
+	uint32_t cmd_id;
+	void *cmd_buf;
+	size_t cmd_len;
+	void *resp_buf = NULL;
+	size_t resp_len = 0;
+
+	uint32_t fuse_id = HLOS_IMG_TAMPER_FUSE;
+	cmd_buf = (void *)&fuse_id;
+	cmd_len = sizeof(fuse_id);
+
+	/*no response*/
+	resp_buf = NULL;
+	resp_len = 0;
+
+	svc_id = SCM_SVC_FUSE;
+	cmd_id = SCM_BLOW_SW_FUSE_ID;
+
+	scm_call(svc_id, cmd_id, cmd_buf, cmd_len, resp_buf, resp_len);
+	return;
+}
+
+uint8_t get_tamper_fuse_cmd()
+{
+	uint32_t svc_id;
+	uint32_t cmd_id;
+	void *cmd_buf;
+	size_t cmd_len;
+	size_t resp_len = 0;
+	uint8_t resp_buf;
+
+	uint32_t fuse_id = HLOS_IMG_TAMPER_FUSE;
+	cmd_buf = (void *)&fuse_id;
+	cmd_len = sizeof(fuse_id);
+
+	/*response*/
+	resp_len = sizeof(resp_buf);
+
+	svc_id = SCM_SVC_FUSE;
+	cmd_id = SCM_IS_SW_FUSE_BLOWN_ID;
+
+	scm_call(svc_id, cmd_id, cmd_buf, cmd_len, &resp_buf, resp_len);
+	return resp_buf;
+}
+
diff --git a/platform/msm_shared/scm_decrypt.c b/platform/msm_shared/scm_decrypt.c
deleted file mode 100644
index df1b399..0000000
--- a/platform/msm_shared/scm_decrypt.c
+++ /dev/null
@@ -1,82 +0,0 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
-
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *   * Redistributions of source code must retain the above copyright
- *     notice, this list of conditions and the following disclaimer.
- *   * Redistributions in binary form must reproduce the above
- *     copyright notice, this list of conditions and the following
- *     disclaimer in the documentation and/or other materials provided
- *     with the distribution.
- *   * Neither the name of Code Aurora Forum, Inc. nor the names of its
- *     contributors may be used to endorse or promote products derived
- *     from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
- * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
- * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "scm_decrypt.h"
-
-#pragma GCC optimize ("O0")
-
-/* From Linux Kernel asm/system.h */
-#define __asmeq(x, y)  ".ifnc " x "," y " ; .err ; .endif\n\t"
-
-void setup_decrypt_cmd ( decrypt_img_req* dec_cmd,
-                         uint32_t** img_ptr,
-                         uint32_t* img_len_ptr)
-{
-    dec_cmd->common_req.len = sizeof(decrypt_img_req);
-    dec_cmd->common_req.buf_offset = sizeof(scm_command);
-    dec_cmd->common_req.resp_hdr_offset = 0;
-    dec_cmd->common_req.id = SSD_DECRYPT_IMG_ID;
-
-    dec_cmd->img_ptr = img_ptr;
-    dec_cmd->img_len_ptr = img_len_ptr;
-}
-
-static uint32_t smc(uint32_t cmd_addr)
-{
-	uint32_t context_id;
-	register uint32_t r0 __asm__("r0") = 1;
-	register uint32_t r1 __asm__("r1") = (uint32_t)&context_id;
-	register uint32_t r2 __asm__("r2") = cmd_addr;
-	__asm__(
-		"1:smc	#0	@ switch to secure world\n"
-		"cmp	r0, #1				\n"
-		"beq	1b				\n"
-		: "=r" (r0)
-		: "r" (r0), "r" (r1), "r" (r2)
-		: "r3", "cc");
-	return r0;
-}
-
-
-int decrypt_img_scm(uint32_t** img_ptr, uint32_t* img_len_ptr)
-{
-   int ret = 0;
-   decrypt_img_req *decrypt_cmd;
-
-   /* allocate memory for the command structure */
-   /* NEEDS TO BE CONTIGUOUS MEMORY */
-   decrypt_cmd = malloc(sizeof(decrypt_img_req));
-
-   /* setup the command for decryption */
-   setup_decrypt_cmd(decrypt_cmd, img_ptr, img_len_ptr);
-
-   ret = smc(decrypt_cmd);
-   free(decrypt_cmd);
-   return ret;
-}
-
diff --git a/target/msm7630_surf/init.c b/target/msm7630_surf/init.c
index c89c252..675653b 100644
--- a/target/msm7630_surf/init.c
+++ b/target/msm7630_surf/init.c
@@ -87,6 +87,11 @@
 	},
 	{
 		.start = DIFF_START_ADDR,
+		.length = 1 /* In MB */,
+		.name = "devinfo",
+	},
+	{
+		.start = DIFF_START_ADDR,
 		.length = VARIABLE_LENGTH,
 		.name = "userdata",
 	},
diff --git a/target/msm8660_surf/init.c b/target/msm8660_surf/init.c
index 3629e7a..f0c49f6 100755
--- a/target/msm8660_surf/init.c
+++ b/target/msm8660_surf/init.c
@@ -447,3 +447,11 @@
 {
 	return uart_gsbi_id;
 }
+
+int emmc_recovery_init(void)
+{
+	int rc;
+	rc = _emmc_recovery_init();
+	return rc;
+}
+