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);