summaryrefslogtreecommitdiff
path: root/arch/arm/mach-rockchip/rk_atags.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-rockchip/rk_atags.c')
-rw-r--r--arch/arm/mach-rockchip/rk_atags.c192
1 files changed, 139 insertions, 53 deletions
diff --git a/arch/arm/mach-rockchip/rk_atags.c b/arch/arm/mach-rockchip/rk_atags.c
index cde2f23a3e..be5dfecad7 100644
--- a/arch/arm/mach-rockchip/rk_atags.c
+++ b/arch/arm/mach-rockchip/rk_atags.c
@@ -10,6 +10,7 @@
#include <debug_uart.h>
#endif
+#define HASH_LEN sizeof(u32)
#define tag_next(t) ((struct tag *)((u32 *)(t) + (t)->hdr.size))
#define tag_size(type) ((sizeof(struct tag_header) + sizeof(struct type)) >> 2)
#define for_each_tag(t, base) \
@@ -72,11 +73,36 @@ void *memcpy(void *dest, const void *src, size_t count)
}
#endif
-static int inline bad_magic(u32 magic)
+static u32 js_hash(void *buf, u32 len)
{
- return ((magic != ATAG_CORE) &&
- (magic != ATAG_NONE) &&
- (magic < ATAG_SERIAL || magic > ATAG_MAX));
+ u32 i, hash = 0x47C6A7E6;
+ char *data = buf;
+
+ if (!buf || !len)
+ return hash;
+
+ for (i = 0; i < len; i++)
+ hash ^= ((hash << 5) + data[i] + (hash >> 2));
+
+ return hash;
+}
+
+static int bad_magic(u32 magic)
+{
+ bool bad;
+
+ bad = ((magic != ATAG_CORE) &&
+ (magic != ATAG_NONE) &&
+ (magic < ATAG_SERIAL || magic > ATAG_MAX));
+ if (bad) {
+#if !CONFIG_IS_ENABLED(TINY_FRAMEWORK)
+ printf("Magic(%x) is not support\n", magic);
+#else
+ printascii("Magic is not support\n");
+#endif
+ }
+
+ return bad;
}
static int inline atags_size_overflow(struct tag *t, u32 tag_size)
@@ -84,6 +110,23 @@ static int inline atags_size_overflow(struct tag *t, u32 tag_size)
return (unsigned long)t + (tag_size << 2) - ATAGS_PHYS_BASE > ATAGS_SIZE;
}
+static int atags_overflow(struct tag *t)
+{
+ bool overflow;
+
+ overflow = atags_size_overflow(t, 0) ||
+ atags_size_overflow(t, t->hdr.size);
+ if (overflow) {
+#if !CONFIG_IS_ENABLED(TINY_FRAMEWORK)
+ printf("Tag is overflow\n");
+#else
+ printascii("Tag is overflow\n");
+#endif
+ }
+
+ return overflow;
+}
+
int atags_is_available(void)
{
struct tag *t = (struct tag *)ATAGS_PHYS_BASE;
@@ -93,21 +136,14 @@ int atags_is_available(void)
int atags_set_tag(u32 magic, void *tagdata)
{
- u32 length, size = 0;
+ u32 length, size = 0, hash;
struct tag *t = (struct tag *)ATAGS_PHYS_BASE;
if (!tagdata)
return -ENODATA;
- if (bad_magic(magic)) {
-#if !CONFIG_IS_ENABLED(TINY_FRAMEWORK)
- printf("%s: magic(%x) is not support\n", __func__, magic);
-#else
- printascii("magic is not support\n");
-#endif
-
+ if (bad_magic(magic))
return -EINVAL;
- }
/* Not allowed to be set by user directly, so do nothing */
if ((magic == ATAG_CORE) || (magic == ATAG_NONE))
@@ -125,21 +161,15 @@ int atags_set_tag(u32 magic, void *tagdata)
} else {
/* Find the end, and use it as a new tag */
for_each_tag(t, (struct tag *)ATAGS_PHYS_BASE) {
- /*
- * We had better check magic to avoid traversing an
- * unknown tag, in case of atags has been damaged by
- * some unknown reason.
- */
- if (bad_magic(t->hdr.magic)) {
-#if !CONFIG_IS_ENABLED(TINY_FRAMEWORK)
- printf("%s: find unknown magic(%x)\n",
- __func__, t->hdr.magic);
-#else
- printascii("find unknown magic\n");
-#endif
+ if (atags_overflow(t))
+ return -EINVAL;
+ if (bad_magic(t->hdr.magic))
return -EINVAL;
- }
+
+ /* This is an old tag, override it */
+ if (t->hdr.magic == magic)
+ break;
if (t->hdr.magic == ATAG_NONE)
break;
@@ -166,24 +196,27 @@ int atags_set_tag(u32 magic, void *tagdata)
case ATAG_ATF_MEM:
size = tag_size(tag_atf_mem);
break;
+ case ATAG_PUB_KEY:
+ size = tag_size(tag_pub_key);
+ break;
+ case ATAG_SOC_INFO:
+ size = tag_size(tag_soc_info);
+ break;
};
- if (atags_size_overflow(t, size)) {
-#if !CONFIG_IS_ENABLED(TINY_FRAMEWORK)
- printf("%s: failed! no memory to setup magic(%x), max_mem=0x%x\n",
- __func__, magic, ATAGS_SIZE);
-#else
- printascii("no memory to setup magic\n");
-#endif
+ if (!size)
+ return -EINVAL;
+ if (atags_size_overflow(t, size))
return -ENOMEM;
- }
/* It's okay to setup a new tag */
t->hdr.magic = magic;
t->hdr.size = size;
- length = (t->hdr.size << 2) - sizeof(struct tag_header);
+ length = (t->hdr.size << 2) - sizeof(struct tag_header) - HASH_LEN;
memcpy(&t->u, (char *)tagdata, length);
+ hash = js_hash(t, (size << 2) - HASH_LEN);
+ memcpy((char *)&t->u + length, &hash, HASH_LEN);
/* Next tag */
t = tag_next(t);
@@ -197,24 +230,38 @@ int atags_set_tag(u32 magic, void *tagdata)
struct tag *atags_get_tag(u32 magic)
{
+ u32 *hash, calc_hash, size;
struct tag *t;
if (!atags_is_available())
return NULL;
for_each_tag(t, (struct tag *)ATAGS_PHYS_BASE) {
- if (bad_magic(t->hdr.magic)) {
-#if !CONFIG_IS_ENABLED(TINY_FRAMEWORK)
- printf("%s: find unknown magic(%x)\n",
- __func__, t->hdr.magic);
-#else
- printascii("find unknown magic\n");
-#endif
+ if (atags_overflow(t))
return NULL;
- }
- if (t->hdr.magic == magic)
+ if (bad_magic(t->hdr.magic))
+ return NULL;
+
+ if (t->hdr.magic != magic)
+ continue;
+
+ size = t->hdr.size;
+ hash = (u32 *)((ulong)t + (size << 2) - HASH_LEN);
+ if (!*hash) {
+ debug("No hash, magic(%x)\n", magic);
return t;
+ } else {
+ calc_hash = js_hash(t, (size << 2) - HASH_LEN);
+ if (calc_hash == *hash) {
+ debug("Hash okay, magic(%x)\n", magic);
+ return t;
+ } else {
+ debug("Hash bad, magic(%x), orgHash=%x, nowHash=%x\n",
+ magic, *hash, calc_hash);
+ return NULL;
+ }
+ }
}
return NULL;
@@ -234,12 +281,15 @@ void atags_stat(void)
u32 start = ATAGS_PHYS_BASE, end = ATAGS_PHYS_BASE + ATAGS_SIZE;
struct tag *t;
+ if (!atags_is_available())
+ return;
+
for_each_tag(t, (struct tag *)ATAGS_PHYS_BASE) {
- if (bad_magic(t->hdr.magic)) {
- printf("%s: find unknown magic(%x)\n",
- __func__, t->hdr.magic);
+ if (atags_overflow(t))
+ return;
+
+ if (bad_magic(t->hdr.magic))
return;
- }
in_use += (t->hdr.size << 2);
}
@@ -273,6 +323,7 @@ void atags_print_tag(struct tag *t)
printf(" id = 0x%x\n", t->u.serial.id);
for (i = 0; i < ARRAY_SIZE(t->u.serial.reserved); i++)
printf(" res[%d] = 0x%x\n", i, t->u.serial.reserved[i]);
+ printf(" hash = 0x%x\n", t->u.serial.hash);
break;
case ATAG_BOOTDEV:
printf("[bootdev]:\n");
@@ -285,6 +336,7 @@ void atags_print_tag(struct tag *t)
for (i = 0; i < ARRAY_SIZE(t->u.bootdev.reserved); i++)
printf(" res[%d] = 0x%x\n",
i, t->u.bootdev.reserved[i]);
+ printf(" hash = 0x%x\n", t->u.bootdev.hash);
break;
case ATAG_TOS_MEM:
printf("[tos_mem]:\n");
@@ -303,6 +355,8 @@ void atags_print_tag(struct tag *t)
printf(" flags = 0x%x\n", t->u.tos_mem.drm_mem.flags);
for (i = 0; i < ARRAY_SIZE(t->u.tos_mem.reserved); i++)
printf(" res[%d] = 0x%llx\n", i, t->u.tos_mem.reserved[i]);
+ printf(" res1 = 0x%x\n", t->u.tos_mem.reserved1);
+ printf(" hash = 0x%x\n", t->u.tos_mem.hash);
break;
case ATAG_DDR_MEM:
printf("[ddr_mem]:\n");
@@ -314,6 +368,7 @@ void atags_print_tag(struct tag *t)
printf(" bank[%d] = 0x%llx\n", i, t->u.ddr_mem.bank[i]);
for (i = 0; i < ARRAY_SIZE(t->u.ddr_mem.reserved); i++)
printf(" res[%d] = 0x%x\n", i, t->u.ddr_mem.reserved[i]);
+ printf(" hash = 0x%x\n", t->u.ddr_mem.hash);
break;
case ATAG_RAM_PARTITION:
printf("[ram_partition]:\n");
@@ -324,11 +379,14 @@ void atags_print_tag(struct tag *t)
printf(" res[%d] = 0x%x\n", i, t->u.ram_part.reserved[i]);
printf(" Part: Name Start Addr Size\t\n");
- for (i = 0; i < t->u.ram_part.count; i++)
+ for (i = 0; i < ARRAY_SIZE(t->u.ram_part.part); i++)
printf("%16s 0x%08llx 0x%08llx\n",
t->u.ram_part.part[i].name,
t->u.ram_part.part[i].start,
t->u.ram_part.part[i].size);
+ for (i = 0; i < ARRAY_SIZE(t->u.ram_part.reserved1); i++)
+ printf(" res1[%d] = 0x%x\n", i, t->u.ram_part.reserved1[i]);
+ printf(" hash = 0x%x\n", t->u.ram_part.hash);
break;
case ATAG_ATF_MEM:
printf("[atf_mem]:\n");
@@ -339,6 +397,25 @@ void atags_print_tag(struct tag *t)
printf(" size = 0x%x\n", t->u.atf_mem.size);
for (i = 0; i < ARRAY_SIZE(t->u.atf_mem.reserved); i++)
printf(" res[%d] = 0x%x\n", i, t->u.atf_mem.reserved[i]);
+ printf(" hash = 0x%x\n", t->u.atf_mem.hash);
+ break;
+ case ATAG_PUB_KEY:
+ printf("[pub_key_mem]:\n");
+ printf(" magic = 0x%x\n", t->hdr.magic);
+ printf(" size = 0x%x\n\n", t->hdr.size << 2);
+ printf(" version = 0x%x\n", t->u.pub_key.version);
+ printf(" hash = 0x%x\n", t->u.pub_key.hash);
+ break;
+ case ATAG_SOC_INFO:
+ printf("[soc_info]:\n");
+ printf(" magic = 0x%x\n", t->hdr.magic);
+ printf(" size = 0x%x\n\n", t->hdr.size << 2);
+ printf(" version = 0x%x\n", t->u.soc.version);
+ printf(" name = 0x%x\n", t->u.soc.name);
+ printf(" flags = 0x%x\n", t->u.soc.flags);
+ for (i = 0; i < ARRAY_SIZE(t->u.soc.reserved); i++)
+ printf(" res[%d] = 0x%x\n", i, t->u.soc.reserved[i]);
+ printf(" hash = 0x%x\n", t->u.soc.hash);
break;
case ATAG_CORE:
printf("[core]:\n");
@@ -359,12 +436,15 @@ void atags_print_all_tags(void)
{
struct tag *t;
+ if (!atags_is_available())
+ return;
+
for_each_tag(t, (struct tag *)ATAGS_PHYS_BASE) {
- if (bad_magic(t->hdr.magic)) {
- printf("%s: find unknown magic(%x)\n",
- __func__, t->hdr.magic);
+ if (atags_overflow(t))
+ return;
+
+ if (bad_magic(t->hdr.magic))
return;
- }
atags_print_tag(t);
}
@@ -378,6 +458,8 @@ void atags_test(void)
struct tag_tos_mem t_tos_mem;
struct tag_ram_partition t_ram_param;
struct tag_atf_mem t_atf_mem;
+ struct tag_pub_key t_pub_key;
+ struct tag_soc_info t_soc;
memset(&t_serial, 0x1, sizeof(t_serial));
memset(&t_bootdev, 0x2, sizeof(t_bootdev));
@@ -385,6 +467,8 @@ void atags_test(void)
memset(&t_tos_mem, 0x4, sizeof(t_tos_mem));
memset(&t_ram_param, 0x0, sizeof(t_ram_param));
memset(&t_atf_mem, 0x5, sizeof(t_atf_mem));
+ memset(&t_pub_key, 0x6, sizeof(t_pub_key));
+ memset(&t_soc, 0x7, sizeof(t_soc));
memcpy(&t_tos_mem.tee_mem.name, "tee_mem", 8);
memcpy(&t_tos_mem.drm_mem.name, "drm_mem", 8);
@@ -415,6 +499,8 @@ void atags_test(void)
atags_set_tag(ATAG_TOS_MEM, &t_tos_mem);
atags_set_tag(ATAG_RAM_PARTITION, &t_ram_param);
atags_set_tag(ATAG_ATF_MEM, &t_atf_mem);
+ atags_set_tag(ATAG_PUB_KEY, &t_pub_key);
+ atags_set_tag(ATAG_SOC_INFO, &t_soc);
atags_print_all_tags();
atags_stat();