Merge "recovery: Add fast factory boot mode (FFBM) read"
diff --git a/app/aboot/recovery.c b/app/aboot/recovery.c
index 566d245..f99aa77 100644
--- a/app/aboot/recovery.c
+++ b/app/aboot/recovery.c
@@ -37,6 +37,7 @@
#include <lib/ptable.h>
#include <dev/keys.h>
#include <platform.h>
+#include <target.h>
#include <partition_parser.h>
#include <mmc.h>
@@ -51,6 +52,7 @@
static const int MISC_PAGES = 3; // number of pages to save
static const int MISC_COMMAND_PAGE = 1; // bootloader command is this page
static char buf[4096];
+
unsigned boot_into_recovery = 0;
extern void reset_device_info();
@@ -470,3 +472,110 @@
emmc_set_recovery_msg(&msg); // send recovery message
return 0;
}
+
+static int read_misc(unsigned page_offset, void *buf, unsigned size)
+{
+ const char *ptn_name = "misc";
+ void *scratch_addr = target_get_scratch_address();
+ unsigned offset;
+ unsigned aligned_size;
+
+ if (size == 0 || buf == NULL || scratch_addr == NULL)
+ return -1;
+
+ if (target_is_emmc_boot())
+ {
+ int index;
+ unsigned long long ptn;
+ unsigned long long ptn_size;
+
+ index = partition_get_index(ptn_name);
+ if (index == INVALID_PTN)
+ {
+ dprintf(CRITICAL, "No '%s' partition found\n", ptn_name);
+ return -1;
+ }
+
+ ptn = partition_get_offset(index);
+ ptn_size = partition_get_size(index);
+
+ offset = page_offset * BLOCK_SIZE;
+ aligned_size = ROUND_TO_PAGE(size, (unsigned)BLOCK_SIZE - 1);
+ if (ptn_size < offset + aligned_size)
+ {
+ dprintf(CRITICAL, "Read request out of '%s' boundaries\n",
+ ptn_name);
+ return -1;
+ }
+
+ if (mmc_read(ptn + offset, (unsigned int *)scratch_addr, aligned_size))
+ {
+ dprintf(CRITICAL, "Reading MMC failed\n");
+ return -1;
+ }
+ }
+ else
+ {
+ struct ptentry *ptn;
+ struct ptable *ptable;
+ unsigned pagesize = flash_page_size();
+
+ ptable = flash_get_ptable();
+ if (ptable == NULL)
+ {
+ dprintf(CRITICAL, "Partition table not found\n");
+ return -1;
+ }
+
+ ptn = ptable_find(ptable, ptn_name);
+ if (ptn == NULL)
+ {
+ dprintf(CRITICAL, "No '%s' partition found\n", ptn_name);
+ return -1;
+ }
+
+ offset = page_offset * pagesize;
+ aligned_size = ROUND_TO_PAGE(size, pagesize - 1);
+ if (ptn->length < offset + aligned_size)
+ {
+ dprintf(CRITICAL, "Read request out of '%s' boundaries\n",
+ ptn_name);
+ return -1;
+ }
+
+ if (flash_read(ptn, offset, scratch_addr, aligned_size)) {
+ dprintf(CRITICAL, "Reading flash failed\n");
+ return -1;
+ }
+ }
+
+ if (scratch_addr != buf)
+ memcpy(buf, scratch_addr, size);
+
+ return 0;
+}
+
+bool get_ffbm(char *ffbm, unsigned size)
+{
+ const char *ffbm_cmd = "ffbm-";
+ const unsigned ffbm_submode_size = 2;
+ unsigned ffbm_mode_size = strlen(ffbm_cmd) + ffbm_submode_size;
+
+ if (size < ffbm_mode_size + 1)
+ {
+ dprintf(CRITICAL, "Buffer too short to get FFBM string\n");
+ return false;
+ }
+
+ if (read_misc(0, ffbm, ffbm_mode_size))
+ {
+ dprintf(CRITICAL, "Error reading MISC partition\n");
+ return false;
+ }
+ ffbm[ffbm_mode_size] = 0;
+
+ if (!strncmp(ffbm, ffbm_cmd, strlen(ffbm_cmd)))
+ return true;
+
+ return false;
+}
diff --git a/app/aboot/recovery.h b/app/aboot/recovery.h
index 6037213..ac291fa 100644
--- a/app/aboot/recovery.h
+++ b/app/aboot/recovery.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -72,6 +72,8 @@
int recovery_init (void);
+bool get_ffbm(char *ffbm, unsigned size);
+
extern unsigned boot_into_recovery;
#endif