summaryrefslogtreecommitdiff
path: root/chip/g/system.c
diff options
context:
space:
mode:
Diffstat (limited to 'chip/g/system.c')
-rw-r--r--chip/g/system.c90
1 files changed, 90 insertions, 0 deletions
diff --git a/chip/g/system.c b/chip/g/system.c
index bf1c39e805..2bbd5d0301 100644
--- a/chip/g/system.c
+++ b/chip/g/system.c
@@ -3,10 +3,14 @@
* found in the LICENSE file.
*/
+#include "config.h"
#include "cpu.h"
+#include "printf.h"
#include "registers.h"
+#include "signed_header.h"
#include "system.h"
#include "task.h"
+#include "version.h"
static void check_reset_cause(void)
{
@@ -145,3 +149,89 @@ int system_set_vbnvcontext(const uint8_t *block)
{
return 0;
}
+
+enum system_image_copy_t system_get_ro_image_copy(void)
+{
+ /*
+ * The bootrom protects the selected bootloader with REGION0,
+ * so we should be able to identify the active RO by seeing which one
+ * is protected.
+ */
+ switch (GREG32(GLOBALSEC, FLASH_REGION0_BASE_ADDR)) {
+ case CONFIG_PROGRAM_MEMORY_BASE + CONFIG_RO_MEM_OFF:
+ return SYSTEM_IMAGE_RO;
+ case CONFIG_PROGRAM_MEMORY_BASE + CHIP_RO_B_MEM_OFF:
+ return SYSTEM_IMAGE_RO_B;
+ }
+
+ return SYSTEM_IMAGE_UNKNOWN;
+}
+
+/*
+ * The RW images contain version strings. The RO images don't, so we'll make
+ * some here.
+ */
+#define MAX_RO_VER_LEN 48
+static char ro_str[2][MAX_RO_VER_LEN];
+
+const char *system_get_version(enum system_image_copy_t copy)
+{
+ const struct version_struct *v;
+ const struct SignedHeader *h;
+ enum system_image_copy_t this_copy;
+ uintptr_t vaddr, delta;
+ int i;
+
+ switch (copy) {
+ case SYSTEM_IMAGE_RO:
+ case SYSTEM_IMAGE_RO_B:
+ /* The RO header is the first thing in each flash half */
+ vaddr = get_program_memory_addr(copy);
+ if (vaddr == INVALID_ADDR)
+ break;
+ h = (const struct SignedHeader *)vaddr;
+ i = (copy == SYSTEM_IMAGE_RO) ? 0 : 1;
+ /* Use some fields from the header for the version string */
+ snprintf(ro_str[i], MAX_RO_VER_LEN, "%d.%d.%d/%08x",
+ h->epoch_, h->major_, h->minor_, h->img_chk_);
+ return ro_str[i];
+
+ case SYSTEM_IMAGE_RW:
+ case SYSTEM_IMAGE_RW_B:
+ /*
+ * This function isn't part of any RO image, so we must be in a
+ * RW image. If the current image is the one we're asked for,
+ * we can just return our version string.
+ */
+ this_copy = system_get_image_copy();
+ if (copy == this_copy)
+ return version_data.version;
+
+ /*
+ * We want the version of the other RW image. The linker script
+ * puts the version string right after the reset vectors, so
+ * it's at the same relative offset. Measure that offset here.
+ */
+ vaddr = get_program_memory_addr(this_copy);
+ delta = (uintptr_t)&version_data - vaddr;
+
+ /* Now look at that offset in the requested image */
+ vaddr = get_program_memory_addr(copy);
+ if (vaddr == INVALID_ADDR)
+ break;
+ vaddr += delta;
+ v = (const struct version_struct *)vaddr;
+
+ /*
+ * Make sure the version struct cookies match before returning
+ * the version string.
+ */
+ if (v->cookie1 == version_data.cookie1 &&
+ v->cookie2 == version_data.cookie2)
+ return v->version;
+ default:
+ break;
+ }
+
+ return "Error";
+}