aboutsummaryrefslogtreecommitdiffstats
path: root/common
diff options
context:
space:
mode:
Diffstat (limited to 'common')
-rw-r--r--common/Makefile2
-rw-r--r--common/avb_verify.c741
-rw-r--r--common/board_r.c4
-rw-r--r--common/bootm.c19
-rw-r--r--common/console.c8
-rw-r--r--common/iotrace.c40
-rw-r--r--common/log.c10
7 files changed, 786 insertions, 38 deletions
diff --git a/common/Makefile b/common/Makefile
index b3da72ebb2..66584f8f48 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -120,3 +120,5 @@ obj-$(CONFIG_$(SPL_)LOG) += log.o
obj-$(CONFIG_$(SPL_)LOG_CONSOLE) += log_console.o
obj-y += s_record.o
obj-y += xyzModem.o
+
+obj-$(CONFIG_LIBAVB) += avb_verify.o
diff --git a/common/avb_verify.c b/common/avb_verify.c
new file mode 100644
index 0000000000..f9a00f8871
--- /dev/null
+++ b/common/avb_verify.c
@@ -0,0 +1,741 @@
+/*
+ * (C) Copyright 2018, Linaro Limited
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <avb_verify.h>
+#include <fastboot.h>
+#include <image.h>
+#include <malloc.h>
+#include <part.h>
+
+const unsigned char avb_root_pub[1032] = {
+ 0x0, 0x0, 0x10, 0x0, 0x55, 0xd9, 0x4, 0xad, 0xd8, 0x4,
+ 0xaf, 0xe3, 0xd3, 0x84, 0x6c, 0x7e, 0xd, 0x89, 0x3d, 0xc2,
+ 0x8c, 0xd3, 0x12, 0x55, 0xe9, 0x62, 0xc9, 0xf1, 0xf, 0x5e,
+ 0xcc, 0x16, 0x72, 0xab, 0x44, 0x7c, 0x2c, 0x65, 0x4a, 0x94,
+ 0xb5, 0x16, 0x2b, 0x0, 0xbb, 0x6, 0xef, 0x13, 0x7, 0x53,
+ 0x4c, 0xf9, 0x64, 0xb9, 0x28, 0x7a, 0x1b, 0x84, 0x98, 0x88,
+ 0xd8, 0x67, 0xa4, 0x23, 0xf9, 0xa7, 0x4b, 0xdc, 0x4a, 0xf,
+ 0xf7, 0x3a, 0x18, 0xae, 0x54, 0xa8, 0x15, 0xfe, 0xb0, 0xad,
+ 0xac, 0x35, 0xda, 0x3b, 0xad, 0x27, 0xbc, 0xaf, 0xe8, 0xd3,
+ 0x2f, 0x37, 0x34, 0xd6, 0x51, 0x2b, 0x6c, 0x5a, 0x27, 0xd7,
+ 0x96, 0x6, 0xaf, 0x6b, 0xb8, 0x80, 0xca, 0xfa, 0x30, 0xb4,
+ 0xb1, 0x85, 0xb3, 0x4d, 0xaa, 0xaa, 0xc3, 0x16, 0x34, 0x1a,
+ 0xb8, 0xe7, 0xc7, 0xfa, 0xf9, 0x9, 0x77, 0xab, 0x97, 0x93,
+ 0xeb, 0x44, 0xae, 0xcf, 0x20, 0xbc, 0xf0, 0x80, 0x11, 0xdb,
+ 0x23, 0xc, 0x47, 0x71, 0xb9, 0x6d, 0xd6, 0x7b, 0x60, 0x47,
+ 0x87, 0x16, 0x56, 0x93, 0xb7, 0xc2, 0x2a, 0x9a, 0xb0, 0x4c,
+ 0x1, 0xc, 0x30, 0xd8, 0x93, 0x87, 0xf0, 0xed, 0x6e, 0x8b,
+ 0xbe, 0x30, 0x5b, 0xf6, 0xa6, 0xaf, 0xdd, 0x80, 0x7c, 0x45,
+ 0x5e, 0x8f, 0x91, 0x93, 0x5e, 0x44, 0xfe, 0xb8, 0x82, 0x7,
+ 0xee, 0x79, 0xca, 0xbf, 0x31, 0x73, 0x62, 0x58, 0xe3, 0xcd,
+ 0xc4, 0xbc, 0xc2, 0x11, 0x1d, 0xa1, 0x4a, 0xbf, 0xfe, 0x27,
+ 0x7d, 0xa1, 0xf6, 0x35, 0xa3, 0x5e, 0xca, 0xdc, 0x57, 0x2f,
+ 0x3e, 0xf0, 0xc9, 0x5d, 0x86, 0x6a, 0xf8, 0xaf, 0x66, 0xa7,
+ 0xed, 0xcd, 0xb8, 0xed, 0xa1, 0x5f, 0xba, 0x9b, 0x85, 0x1a,
+ 0xd5, 0x9, 0xae, 0x94, 0x4e, 0x3b, 0xcf, 0xcb, 0x5c, 0xc9,
+ 0x79, 0x80, 0xf7, 0xcc, 0xa6, 0x4a, 0xa8, 0x6a, 0xd8, 0xd3,
+ 0x31, 0x11, 0xf9, 0xf6, 0x2, 0x63, 0x2a, 0x1a, 0x2d, 0xd1,
+ 0x1a, 0x66, 0x1b, 0x16, 0x41, 0xbd, 0xbd, 0xf7, 0x4d, 0xc0,
+ 0x4a, 0xe5, 0x27, 0x49, 0x5f, 0x7f, 0x58, 0xe3, 0x27, 0x2d,
+ 0xe5, 0xc9, 0x66, 0xe, 0x52, 0x38, 0x16, 0x38, 0xfb, 0x16,
+ 0xeb, 0x53, 0x3f, 0xe6, 0xfd, 0xe9, 0xa2, 0x5e, 0x25, 0x59,
+ 0xd8, 0x79, 0x45, 0xff, 0x3, 0x4c, 0x26, 0xa2, 0x0, 0x5a,
+ 0x8e, 0xc2, 0x51, 0xa1, 0x15, 0xf9, 0x7b, 0xf4, 0x5c, 0x81,
+ 0x9b, 0x18, 0x47, 0x35, 0xd8, 0x2d, 0x5, 0xe9, 0xad, 0xf,
+ 0x35, 0x74, 0x15, 0xa3, 0x8e, 0x8b, 0xcc, 0x27, 0xda, 0x7c,
+ 0x5d, 0xe4, 0xfa, 0x4, 0xd3, 0x5, 0xb, 0xba, 0x3a, 0xb2,
+ 0x49, 0x45, 0x2f, 0x47, 0xc7, 0xd, 0x41, 0x3f, 0x97, 0x80,
+ 0x4d, 0x3f, 0xc1, 0xb5, 0xbb, 0x70, 0x5f, 0xa7, 0x37, 0xaf,
+ 0x48, 0x22, 0x12, 0x45, 0x2e, 0xf5, 0xf, 0x87, 0x92, 0xe2,
+ 0x84, 0x1, 0xf9, 0x12, 0xf, 0x14, 0x15, 0x24, 0xce, 0x89,
+ 0x99, 0xee, 0xb9, 0xc4, 0x17, 0x70, 0x70, 0x15, 0xea, 0xbe,
+ 0xc6, 0x6c, 0x1f, 0x62, 0xb3, 0xf4, 0x2d, 0x16, 0x87, 0xfb,
+ 0x56, 0x1e, 0x45, 0xab, 0xae, 0x32, 0xe4, 0x5e, 0x91, 0xed,
+ 0x53, 0x66, 0x5e, 0xbd, 0xed, 0xad, 0xe6, 0x12, 0x39, 0xd,
+ 0x83, 0xc9, 0xe8, 0x6b, 0x6c, 0x2d, 0xa5, 0xee, 0xc4, 0x5a,
+ 0x66, 0xae, 0x8c, 0x97, 0xd7, 0xd, 0x6c, 0x49, 0xc7, 0xf5,
+ 0xc4, 0x92, 0x31, 0x8b, 0x9, 0xee, 0x33, 0xda, 0xa9, 0x37,
+ 0xb6, 0x49, 0x18, 0xf8, 0xe, 0x60, 0x45, 0xc8, 0x33, 0x91,
+ 0xef, 0x20, 0x57, 0x10, 0xbe, 0x78, 0x2d, 0x83, 0x26, 0xd6,
+ 0xca, 0x61, 0xf9, 0x2f, 0xe0, 0xbf, 0x5, 0x30, 0x52, 0x5a,
+ 0x12, 0x1c, 0x0, 0xa7, 0x5d, 0xcc, 0x7c, 0x2e, 0xc5, 0x95,
+ 0x8b, 0xa3, 0x3b, 0xf0, 0x43, 0x2e, 0x5e, 0xdd, 0x0, 0xdb,
+ 0xd, 0xb3, 0x37, 0x99, 0xa9, 0xcd, 0x9c, 0xb7, 0x43, 0xf7,
+ 0x35, 0x44, 0x21, 0xc2, 0x82, 0x71, 0xab, 0x8d, 0xaa, 0xb4,
+ 0x41, 0x11, 0xec, 0x1e, 0x8d, 0xfc, 0x14, 0x82, 0x92, 0x4e,
+ 0x83, 0x6a, 0xa, 0x6b, 0x35, 0x5e, 0x5d, 0xe9, 0x5c, 0xcc,
+ 0x8c, 0xde, 0x39, 0xd1, 0x4a, 0x5b, 0x5f, 0x63, 0xa9, 0x64,
+ 0xe0, 0xa, 0xcb, 0xb, 0xb8, 0x5a, 0x7c, 0xc3, 0xb, 0xe6,
+ 0xbe, 0xfe, 0x8b, 0xf, 0x7d, 0x34, 0x8e, 0x2, 0x66, 0x74,
+ 0x1, 0x6c, 0xca, 0x76, 0xac, 0x7c, 0x67, 0x8, 0x2f, 0x3f,
+ 0x1a, 0xa6, 0x2c, 0x60, 0xb3, 0xff, 0xda, 0x8d, 0xb8, 0x12,
+ 0xc, 0x0, 0x7f, 0xcc, 0x50, 0xa1, 0x5c, 0x64, 0xa1, 0xe2,
+ 0x5f, 0x32, 0x65, 0xc9, 0x9c, 0xbe, 0xd6, 0xa, 0x13, 0x87,
+ 0x3c, 0x2a, 0x45, 0x47, 0xc, 0xca, 0x42, 0x82, 0xfa, 0x89,
+ 0x65, 0xe7, 0x89, 0xb4, 0x8f, 0xf7, 0x1e, 0xe6, 0x23, 0xa5,
+ 0xd0, 0x59, 0x37, 0x79, 0x92, 0xd7, 0xce, 0x3d, 0xfd, 0xe3,
+ 0xa1, 0xb, 0xcf, 0x6c, 0x85, 0xa0, 0x65, 0xf3, 0x5c, 0xc6,
+ 0x4a, 0x63, 0x5f, 0x6e, 0x3a, 0x3a, 0x2a, 0x8b, 0x6a, 0xb6,
+ 0x2f, 0xbb, 0xf8, 0xb2, 0x4b, 0x62, 0xbc, 0x1a, 0x91, 0x25,
+ 0x66, 0xe3, 0x69, 0xca, 0x60, 0x49, 0xb, 0xf6, 0x8a, 0xbe,
+ 0x3e, 0x76, 0x53, 0xc2, 0x7a, 0xa8, 0x4, 0x17, 0x75, 0xf1,
+ 0xf3, 0x3, 0x62, 0x1b, 0x85, 0xb2, 0xb0, 0xef, 0x80, 0x15,
+ 0xb6, 0xd4, 0x4e, 0xdf, 0x71, 0xac, 0xdb, 0x2a, 0x4, 0xd4,
+ 0xb4, 0x21, 0xba, 0x65, 0x56, 0x57, 0xe8, 0xfa, 0x84, 0xa2,
+ 0x7d, 0x13, 0xe, 0xaf, 0xd7, 0x9a, 0x58, 0x2a, 0xa3, 0x81,
+ 0x84, 0x8d, 0x9, 0xa0, 0x6a, 0xc1, 0xbb, 0xd9, 0xf5, 0x86,
+ 0xac, 0xbd, 0x75, 0x61, 0x9, 0xe6, 0x8c, 0x3d, 0x77, 0xb2,
+ 0xed, 0x30, 0x20, 0xe4, 0x0, 0x1d, 0x97, 0xe8, 0xbf, 0xc7,
+ 0x0, 0x1b, 0x21, 0xb1, 0x16, 0xe7, 0x41, 0x67, 0x2e, 0xec,
+ 0x38, 0xbc, 0xe5, 0x1b, 0xb4, 0x6, 0x23, 0x31, 0x71, 0x1c,
+ 0x49, 0xcd, 0x76, 0x4a, 0x76, 0x36, 0x8d, 0xa3, 0x89, 0x8b,
+ 0x4a, 0x7a, 0xf4, 0x87, 0xc8, 0x15, 0xf, 0x37, 0x39, 0xf6,
+ 0x6d, 0x80, 0x19, 0xef, 0x5c, 0xa8, 0x66, 0xce, 0x1b, 0x16,
+ 0x79, 0x21, 0xdf, 0xd7, 0x31, 0x30, 0xc4, 0x21, 0xdd, 0x34,
+ 0x5b, 0xd2, 0x1a, 0x2b, 0x3e, 0x5d, 0xf7, 0xea, 0xca, 0x5,
+ 0x8e, 0xb7, 0xcb, 0x49, 0x2e, 0xa0, 0xe3, 0xf4, 0xa7, 0x48,
+ 0x19, 0x10, 0x9c, 0x4, 0xa7, 0xf4, 0x28, 0x74, 0xc8, 0x6f,
+ 0x63, 0x20, 0x2b, 0x46, 0x24, 0x26, 0x19, 0x1d, 0xd1, 0x2c,
+ 0x31, 0x6d, 0x5a, 0x29, 0xa2, 0x6, 0xa6, 0xb2, 0x41, 0xcc,
+ 0xa, 0x27, 0x96, 0x9, 0x96, 0xac, 0x47, 0x65, 0x78, 0x68,
+ 0x51, 0x98, 0xd6, 0xd8, 0xa6, 0x2d, 0xa0, 0xcf, 0xec, 0xe2,
+ 0x74, 0xf2, 0x82, 0xe3, 0x97, 0xd9, 0x7e, 0xd4, 0xf8, 0xb,
+ 0x70, 0x43, 0x3d, 0xb1, 0x7b, 0x97, 0x80, 0xd6, 0xcb, 0xd7,
+ 0x19, 0xbc, 0x63, 0xb, 0xfd, 0x4d, 0x88, 0xfe, 0x67, 0xac,
+ 0xb8, 0xcc, 0x50, 0xb7, 0x68, 0xb3, 0x5b, 0xd6, 0x1e, 0x25,
+ 0xfc, 0x5f, 0x3c, 0x8d, 0xb1, 0x33, 0x7c, 0xb3, 0x49, 0x1,
+ 0x3f, 0x71, 0x55, 0xe, 0x51, 0xba, 0x61, 0x26, 0xfa, 0xea,
+ 0xe5, 0xb5, 0xe8, 0xaa, 0xcf, 0xcd, 0x96, 0x9f, 0xd6, 0xc1,
+ 0x5f, 0x53, 0x91, 0xad, 0x5, 0xde, 0x20, 0xe7, 0x51, 0xda,
+ 0x5b, 0x95, 0x67, 0xed, 0xf4, 0xee, 0x42, 0x65, 0x70, 0x13,
+ 0xb, 0x70, 0x14, 0x1c, 0xc9, 0xe0, 0x19, 0xca, 0x5f, 0xf5,
+ 0x1d, 0x70, 0x4b, 0x6c, 0x6, 0x74, 0xec, 0xb5, 0x2e, 0x77,
+ 0xe1, 0x74, 0xa1, 0xa3, 0x99, 0xa0, 0x85, 0x9e, 0xf1, 0xac,
+ 0xd8, 0x7e,
+};
+
+/**
+ * ============================================================================
+ * Boot states support (GREEN, YELLOW, ORANGE, RED) and dm_verity
+ * ============================================================================
+ */
+char *avb_set_state(AvbOps *ops, enum avb_boot_state boot_state)
+{
+ struct AvbOpsData *data;
+ char *cmdline = NULL;
+
+ if (!ops)
+ return NULL;
+
+ data = (struct AvbOpsData *)ops->user_data;
+ if (!data)
+ return NULL;
+
+ data->boot_state = boot_state;
+ switch (boot_state) {
+ case AVB_GREEN:
+ cmdline = "androidboot.verifiedbootstate=green";
+ break;
+ case AVB_YELLOW:
+ cmdline = "androidboot.verifiedbootstate=yellow";
+ break;
+ case AVB_ORANGE:
+ cmdline = "androidboot.verifiedbootstate=orange";
+ case AVB_RED:
+ break;
+ }
+
+ return cmdline;
+}
+
+char *append_cmd_line(char *cmdline_orig, char *cmdline_new)
+{
+ char *cmd_line;
+
+ if (!cmdline_new)
+ return cmdline_orig;
+
+ if (cmdline_orig)
+ cmd_line = cmdline_orig;
+ else
+ cmd_line = " ";
+
+ cmd_line = avb_strdupv(cmd_line, " ", cmdline_new, NULL);
+
+ return cmd_line;
+}
+
+static int avb_find_dm_args(char **args, char *str)
+{
+ int i;
+
+ if (!str)
+ return -1;
+
+ for (i = 0; i < AVB_MAX_ARGS, args[i]; ++i) {
+ if (strstr(args[i], str))
+ return i;
+ }
+
+ return -1;
+}
+
+static char *avb_set_enforce_option(const char *cmdline, const char *option)
+{
+ char *cmdarg[AVB_MAX_ARGS];
+ char *newargs = NULL;
+ int i = 0;
+ int total_args;
+
+ memset(cmdarg, 0, sizeof(cmdarg));
+ cmdarg[i++] = strtok((char *)cmdline, " ");
+
+ do {
+ cmdarg[i] = strtok(NULL, " ");
+ if (!cmdarg[i])
+ break;
+
+ if (++i >= AVB_MAX_ARGS) {
+ printf("%s: Can't handle more then %d args\n",
+ __func__, i);
+ return NULL;
+ }
+ } while (true);
+
+ total_args = i;
+ i = avb_find_dm_args(&cmdarg[0], VERITY_TABLE_OPT_LOGGING);
+ if (i >= 0) {
+ cmdarg[i] = (char *)option;
+ } else {
+ i = avb_find_dm_args(&cmdarg[0], VERITY_TABLE_OPT_RESTART);
+ if (i < 0) {
+ printf("%s: No verity options found\n", __func__);
+ return NULL;
+ }
+
+ cmdarg[i] = (char *)option;
+ }
+
+ for (i = 0; i <= total_args; i++)
+ newargs = append_cmd_line(newargs, cmdarg[i]);
+
+ return newargs;
+}
+
+char *avb_set_ignore_corruption(const char *cmdline)
+{
+ char *newargs = NULL;
+
+ newargs = avb_set_enforce_option(cmdline, VERITY_TABLE_OPT_LOGGING);
+ if (newargs)
+ newargs = append_cmd_line(newargs,
+ "androidboot.veritymode=eio");
+
+ return newargs;
+}
+
+char *avb_set_enforce_verity(const char *cmdline)
+{
+ char *newargs;
+
+ newargs = avb_set_enforce_option(cmdline, VERITY_TABLE_OPT_RESTART);
+ if (newargs)
+ newargs = append_cmd_line(newargs,
+ "androidboot.veritymode=enforcing");
+ return newargs;
+}
+
+/**
+ * ============================================================================
+ * IO(mmc) auxiliary functions
+ * ============================================================================
+ */
+static unsigned long mmc_read_and_flush(struct mmc_part *part,
+ lbaint_t start,
+ lbaint_t sectors,
+ void *buffer)
+{
+ unsigned long blks;
+ void *tmp_buf;
+ size_t buf_size;
+ bool unaligned = is_buf_unaligned(buffer);
+
+ if (start < part->info.start) {
+ printf("%s: partition start out of bounds\n", __func__);
+ return 0;
+ }
+ if ((start + sectors) > (part->info.start + part->info.size)) {
+ sectors = part->info.start + part->info.size - start;
+ printf("%s: read sector aligned to partition bounds (%ld)\n",
+ __func__, sectors);
+ }
+
+ /*
+ * Reading fails on unaligned buffers, so we have to
+ * use aligned temporary buffer and then copy to destination
+ */
+
+ if (unaligned) {
+ printf("Handling unaligned read buffer..\n");
+ tmp_buf = get_sector_buf();
+ buf_size = get_sector_buf_size();
+ if (sectors > buf_size / part->info.blksz)
+ sectors = buf_size / part->info.blksz;
+ } else {
+ tmp_buf = buffer;
+ }
+
+ blks = part->mmc->block_dev.block_read(part->mmc_blk,
+ start, sectors, tmp_buf);
+ /* flush cache after read */
+ flush_cache((ulong)tmp_buf, sectors * part->info.blksz);
+
+ if (unaligned)
+ memcpy(buffer, tmp_buf, sectors * part->info.blksz);
+
+ return blks;
+}
+
+static unsigned long mmc_write(struct mmc_part *part, lbaint_t start,
+ lbaint_t sectors, void *buffer)
+{
+ void *tmp_buf;
+ size_t buf_size;
+ bool unaligned = is_buf_unaligned(buffer);
+
+ if (start < part->info.start) {
+ printf("%s: partition start out of bounds\n", __func__);
+ return 0;
+ }
+ if ((start + sectors) > (part->info.start + part->info.size)) {
+ sectors = part->info.start + part->info.size - start;
+ printf("%s: sector aligned to partition bounds (%ld)\n",
+ __func__, sectors);
+ }
+ if (unaligned) {
+ tmp_buf = get_sector_buf();
+ buf_size = get_sector_buf_size();
+ printf("Handling unaligned wrire buffer..\n");
+ if (sectors > buf_size / part->info.blksz)
+ sectors = buf_size / part->info.blksz;
+
+ memcpy(tmp_buf, buffer, sectors * part->info.blksz);
+ } else {
+ tmp_buf = buffer;
+ }
+
+ return part->mmc->block_dev.block_write(part->mmc_blk,
+ start, sectors, tmp_buf);
+}
+
+static struct mmc_part *get_partition(AvbOps *ops, const char *partition)
+{
+ int ret;
+ u8 dev_num;
+ int part_num = 0;
+ struct mmc_part *part;
+ struct blk_desc *mmc_blk;
+
+ part = malloc(sizeof(struct mmc_part));
+ if (!part)
+ return NULL;
+
+ dev_num = get_boot_device(ops);
+ part->mmc = find_mmc_device(dev_num);
+ if (!part->mmc) {
+ printf("No MMC device at slot %x\n", dev_num);
+ return NULL;
+ }
+
+ if (mmc_init(part->mmc)) {
+ printf("MMC initialization failed\n");
+ return NULL;
+ }
+
+ ret = mmc_switch_part(part->mmc, part_num);
+ if (ret)
+ return NULL;
+
+ mmc_blk = mmc_get_blk_desc(part->mmc);
+ if (!mmc_blk) {
+ printf("Error - failed to obtain block descriptor\n");
+ return NULL;
+ }
+
+ ret = part_get_info_by_name(mmc_blk, partition, &part->info);
+ if (!ret) {
+ printf("Can't find partition '%s'\n", partition);
+ return NULL;
+ }
+
+ part->dev_num = dev_num;
+ part->mmc_blk = mmc_blk;
+
+ return part;
+}
+
+static AvbIOResult mmc_byte_io(AvbOps *ops,
+ const char *partition,
+ s64 offset,
+ size_t num_bytes,
+ void *buffer,
+ size_t *out_num_read,
+ enum mmc_io_type io_type)
+{
+ ulong ret;
+ struct mmc_part *part;
+ u64 start_offset, start_sector, sectors, residue;
+ u8 *tmp_buf;
+ size_t io_cnt = 0;
+
+ if (!partition || !buffer || io_type > IO_WRITE)
+ return AVB_IO_RESULT_ERROR_IO;
+
+ part = get_partition(ops, partition);
+ if (!part)
+ return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
+
+ start_offset = calc_offset(part, offset);
+ while (num_bytes) {
+ start_sector = start_offset / part->info.blksz;
+ sectors = num_bytes / part->info.blksz;
+ /* handle non block-aligned reads */
+ if (start_offset % part->info.blksz ||
+ num_bytes < part->info.blksz) {
+ tmp_buf = get_sector_buf();
+ if (start_offset % part->info.blksz) {
+ residue = part->info.blksz -
+ (start_offset % part->info.blksz);
+ if (residue > num_bytes)
+ residue = num_bytes;
+ } else {
+ residue = num_bytes;
+ }
+
+ if (io_type == IO_READ) {
+ ret = mmc_read_and_flush(part,
+ part->info.start +
+ start_sector,
+ 1, tmp_buf);
+
+ if (ret != 1) {
+ printf("%s: read error (%ld, %lld)\n",
+ __func__, ret, start_sector);
+ return AVB_IO_RESULT_ERROR_IO;
+ }
+ /*
+ * if this is not aligned at sector start,
+ * we have to adjust the tmp buffer
+ */
+ tmp_buf += (start_offset % part->info.blksz);
+ memcpy(buffer, (void *)tmp_buf, residue);
+ } else {
+ ret = mmc_read_and_flush(part,
+ part->info.start +
+ start_sector,
+ 1, tmp_buf);
+
+ if (ret != 1) {
+ printf("%s: read error (%ld, %lld)\n",
+ __func__, ret, start_sector);
+ return AVB_IO_RESULT_ERROR_IO;
+ }
+ memcpy((void *)tmp_buf +
+ start_offset % part->info.blksz,
+ buffer, residue);
+
+ ret = mmc_write(part, part->info.start +
+ start_sector, 1, tmp_buf);
+ if (ret != 1) {
+ printf("%s: write error (%ld, %lld)\n",
+ __func__, ret, start_sector);
+ return AVB_IO_RESULT_ERROR_IO;
+ }
+ }
+
+ io_cnt += residue;
+ buffer += residue;
+ start_offset += residue;
+ num_bytes -= residue;
+ continue;
+ }
+
+ if (sectors) {
+ if (io_type == IO_READ) {
+ ret = mmc_read_and_flush(part,
+ part->info.start +
+ start_sector,
+ sectors, buffer);
+ } else {
+ ret = mmc_write(part,
+ part->info.start +
+ start_sector,
+ sectors, buffer);
+ }
+
+ if (!ret) {
+ printf("%s: sector read error\n", __func__);
+ return AVB_IO_RESULT_ERROR_IO;
+ }
+
+ io_cnt += ret * part->info.blksz;
+ buffer += ret * part->info.blksz;
+ start_offset += ret * part->info.blksz;
+ num_bytes -= ret * part->info.blksz;
+ }
+ }
+
+ /* Set counter for read operation */
+ if (io_type == IO_READ && out_num_read)
+ *out_num_read = io_cnt;
+
+ return AVB_IO_RESULT_OK;
+}
+
+/**
+ * ============================================================================
+ * AVB 2.0 operations
+ * ============================================================================
+ */
+
+/**
+ * read_from_partition() - reads @num_bytes from @offset from partition
+ * identified by a string name
+ *
+ * @ops: contains AVB ops handlers
+ * @partition_name: partition name, NUL-terminated UTF-8 string
+ * @offset: offset from the beginning of partition
+ * @num_bytes: amount of bytes to read
+ * @buffer: destination buffer to store data
+ * @out_num_read:
+ *
+ * @return:
+ * AVB_IO_RESULT_OK, if partition was found and read operation succeed
+ * AVB_IO_RESULT_ERROR_IO, if i/o error occurred from the underlying i/o
+ * subsystem
+ * AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION, if there is no partition with
+ * the given name
+ */
+static AvbIOResult read_from_partition(AvbOps *ops,
+ const char *partition_name,
+ s64 offset_from_partition,
+ size_t num_bytes,
+ void *buffer,
+ size_t *out_num_read)
+{
+ return mmc_byte_io(ops, partition_name, offset_from_partition,
+ num_bytes, buffer, out_num_read, IO_READ);
+}
+
+/**
+ * write_to_partition() - writes N bytes to a partition identified by a string
+ * name
+ *
+ * @ops: AvbOps, contains AVB ops handlers
+ * @partition_name: partition name
+ * @offset_from_partition: offset from the beginning of partition
+ * @num_bytes: amount of bytes to write
+ * @buf: data to write
+ * @out_num_read:
+ *
+ * @return:
+ * AVB_IO_RESULT_OK, if partition was found and read operation succeed
+ * AVB_IO_RESULT_ERROR_IO, if input/output error occurred
+ * AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION, if partition, specified in
+ * @partition_name was not found
+ */
+static AvbIOResult write_to_partition(AvbOps *ops,
+ const char *partition_name,
+ s64 offset_from_partition,
+ size_t num_bytes,
+ const void *buffer)
+{
+ return mmc_byte_io(ops, partition_name, offset_from_partition,
+ num_bytes, (void *)buffer, NULL, IO_WRITE);
+}
+
+/**
+ * validate_vmbeta_public_key() - checks if the given public key used to sign
+ * the vbmeta partition is trusted
+ *
+ * @ops: AvbOps, contains AVB ops handlers
+ * @public_key_data: public key for verifying vbmeta partition signature
+ * @public_key_length: length of public key
+ * @public_key_metadata:
+ * @public_key_metadata_length:
+ * @out_key_is_trusted:
+ *
+ * @return:
+ * AVB_IO_RESULT_OK, if partition was found and read operation succeed
+ */
+static AvbIOResult validate_vbmeta_public_key(AvbOps *ops,
+ const u8 *public_key_data,
+ size_t public_key_length,
+ const u8
+ *public_key_metadata,
+ size_t
+ public_key_metadata_length,
+ bool *out_key_is_trusted)
+{
+ if (!public_key_length || !public_key_data || !out_key_is_trusted)
+ return AVB_IO_RESULT_ERROR_IO;
+
+ *out_key_is_trusted = false;
+ if (public_key_length != sizeof(avb_root_pub))
+ return AVB_IO_RESULT_ERROR_IO;
+
+ if (memcmp(avb_root_pub, public_key_data, public_key_length) == 0)
+ *out_key_is_trusted = true;
+
+ return AVB_IO_RESULT_OK;
+}
+
+/**
+ * read_rollback_index() - gets the rollback index corresponding to the
+ * location of given by @out_rollback_index.
+ *
+ * @ops: contains AvbOps handlers
+ * @rollback_index_slot:
+ * @out_rollback_index: used to write a retrieved rollback index.
+ *
+ * @return
+ * AVB_IO_RESULT_OK, if the roolback index was retrieved
+ */
+static AvbIOResult read_rollback_index(AvbOps *ops,
+ size_t rollback_index_slot,
+ u64 *out_rollback_index)
+{
+ /* For now we always return 0 as the stored rollback index. */
+ printf("%s not supported yet\n", __func__);
+
+ if (out_rollback_index)
+ *out_rollback_index = 0;
+
+ return AVB_IO_RESULT_OK;
+}
+
+/**
+ * write_rollback_index() - sets the rollback index corresponding to the
+ * location of given by @out_rollback_index.
+ *
+ * @ops: contains AvbOps handlers
+ * @rollback_index_slot:
+ * @rollback_index: rollback index to write.
+ *
+ * @return
+ * AVB_IO_RESULT_OK, if the roolback index was retrieved
+ */
+static AvbIOResult write_rollback_index(AvbOps *ops,
+ size_t rollback_index_slot,
+ u64 rollback_index)
+{
+ /* For now this is a no-op. */
+ printf("%s not supported yet\n", __func__);
+
+ return AVB_IO_RESULT_OK;
+}
+
+/**
+ * read_is_device_unlocked() - gets whether the device is unlocked
+ *
+ * @ops: contains AVB ops handlers
+ * @out_is_unlocked: device unlock state is stored here, true if unlocked,
+ * false otherwise
+ *
+ * @return:
+ * AVB_IO_RESULT_OK: state is retrieved successfully
+ * AVB_IO_RESULT_ERROR_IO: an error occurred
+ */
+static AvbIOResult read_is_device_unlocked(AvbOps *ops, bool *out_is_unlocked)
+{
+ /* For now we always return that the device is unlocked. */
+
+ printf("%s not supported yet\n", __func__);
+
+ *out_is_unlocked = true;
+
+ return AVB_IO_RESULT_OK;
+}
+
+/**
+ * get_unique_guid_for_partition() - gets the GUID for a partition identified
+ * by a string name
+ *
+ * @ops: contains AVB ops handlers
+ * @partition: partition name (NUL-terminated UTF-8 string)
+ * @guid_buf: buf, used to copy in GUID string. Example of value:
+ * 527c1c6d-6361-4593-8842-3c78fcd39219
+ * @guid_buf_size: @guid_buf buffer size
+ *
+ * @return:
+ * AVB_IO_RESULT_OK, on success (GUID found)
+ * AVB_IO_RESULT_ERROR_IO, if incorrect buffer size (@guid_buf_size) was
+ * provided
+ * AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION, if partition was not found
+ */
+static AvbIOResult get_unique_guid_for_partition(AvbOps *ops,
+ const char *partition,
+ char *guid_buf,
+ size_t guid_buf_size)
+{
+ struct mmc_part *part;
+ size_t uuid_size;
+
+ part = get_partition(ops, partition);
+ if (!part)
+ return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
+
+ uuid_size = sizeof(part->info.uuid);
+ if (uuid_size > guid_buf_size)
+ return AVB_IO_RESULT_ERROR_IO;
+
+ memcpy(guid_buf, part->info.uuid, uuid_size);
+ guid_buf[uuid_size - 1] = 0;
+
+ return AVB_IO_RESULT_OK;
+}
+
+/**
+ * ============================================================================
+ * AVB2.0 AvbOps alloc/initialisation/free
+ * ============================================================================
+ */
+AvbOps *avb_ops_alloc(int boot_device)
+{
+ struct AvbOpsData *ops_data;
+
+ ops_data = avb_calloc(sizeof(struct AvbOpsData));
+ if (!ops_data)
+ return NULL;
+
+ ops_data->ops.user_data = ops_data;
+
+ ops_data->ops.read_from_partition = read_from_partition;
+ ops_data->ops.write_to_partition = write_to_partition;
+ ops_data->ops.validate_vbmeta_public_key = validate_vbmeta_public_key;
+ ops_data->ops.read_rollback_index = read_rollback_index;
+ ops_data->ops.write_rollback_index = write_rollback_index;
+ ops_data->ops.read_is_device_unlocked = read_is_device_unlocked;
+ ops_data->ops.get_unique_guid_for_partition =
+ get_unique_guid_for_partition;
+
+ ops_data->mmc_dev = boot_device;
+
+ return &ops_data->ops;
+}
+
+void avb_ops_free(AvbOps *ops)
+{
+ struct AvbOpsData *ops_data;
+
+ if (ops)
+ return;
+
+ ops_data = ops->user_data;
+
+ if (ops_data)
+ avb_free(ops_data);
+}
diff --git a/common/board_r.c b/common/board_r.c
index 6b297068bd..6949d4af0e 100644
--- a/common/board_r.c
+++ b/common/board_r.c
@@ -596,7 +596,7 @@ static int initr_pcmcia(void)
}
#endif
-#if defined(CONFIG_IDE)
+#if defined(CONFIG_IDE) && !defined(CONFIG_BLK)
static int initr_ide(void)
{
puts("IDE: ");
@@ -826,7 +826,7 @@ static init_fnc_t init_sequence_r[] = {
#if defined(CONFIG_CMD_PCMCIA) && !defined(CONFIG_IDE)
initr_pcmcia,
#endif
-#if defined(CONFIG_IDE)
+#if defined(CONFIG_IDE) && !defined(CONFIG_BLK)
initr_ide,
#endif
#ifdef CONFIG_LAST_STAGE_INIT
diff --git a/common/bootm.c b/common/bootm.c
index e789f6818a..e517d9f118 100644
--- a/common/bootm.c
+++ b/common/bootm.c
@@ -202,8 +202,23 @@ static int bootm_find_os(cmd_tbl_t *cmdtp, int flag, int argc,
}
if (images.os.type == IH_TYPE_KERNEL_NOLOAD) {
- images.os.load = images.os.image_start;
- images.ep += images.os.load;
+ if (CONFIG_IS_ENABLED(CMD_BOOTI) &&
+ images.os.arch == IH_ARCH_ARM64) {
+ ulong image_addr;
+ ulong image_size;
+
+ ret = booti_setup(images.os.image_start, &image_addr,
+ &image_size, true);
+ if (ret != 0)
+ return 1;
+
+ images.os.type = IH_TYPE_KERNEL;
+ images.os.load = image_addr;
+ images.ep = image_addr;
+ } else {
+ images.os.load = images.os.image_start;
+ images.ep += images.os.image_start;
+ }
}
images.os.start = map_to_sysmem(os_hdr);
diff --git a/common/console.c b/common/console.c
index 2688af56e1..2ba33dc574 100644
--- a/common/console.c
+++ b/common/console.c
@@ -502,8 +502,10 @@ void putc(const char c)
return;
}
#endif
+ if (!gd)
+ return;
#ifdef CONFIG_CONSOLE_RECORD
- if (gd && (gd->flags & GD_FLG_RECORD) && gd->console_out.start)
+ if ((gd->flags & GD_FLG_RECORD) && gd->console_out.start)
membuff_putbyte(&gd->console_out, c);
#endif
#ifdef CONFIG_SILENT_CONSOLE
@@ -541,8 +543,10 @@ void puts(const char *s)
return;
}
#endif
+ if (!gd)
+ return;
#ifdef CONFIG_CONSOLE_RECORD
- if (gd && (gd->flags & GD_FLG_RECORD) && gd->console_out.start)
+ if ((gd->flags & GD_FLG_RECORD) && gd->console_out.start)
membuff_put(&gd->console_out, s, strlen(s));
#endif
#ifdef CONFIG_SILENT_CONSOLE
diff --git a/common/iotrace.c b/common/iotrace.c
index 2f03a6082e..49bee3c92a 100644
--- a/common/iotrace.c
+++ b/common/iotrace.c
@@ -11,38 +11,12 @@
DECLARE_GLOBAL_DATA_PTR;
-/* Support up to the machine word length for now */
-typedef ulong iovalue_t;
-
-enum iotrace_flags {
- IOT_8 = 0,
- IOT_16,
- IOT_32,
-
- IOT_READ = 0 << 3,
- IOT_WRITE = 1 << 3,
-};
-
-/**
- * struct iotrace_record - Holds a single I/O trace record
- *
- * @flags: I/O access type
- * @timestamp: Timestamp of access
- * @addr: Address of access
- * @value: Value written or read
- */
-struct iotrace_record {
- enum iotrace_flags flags;
- u64 timestamp;
- phys_addr_t addr;
- iovalue_t value;
-};
-
/**
* struct iotrace - current trace status and checksum
*
* @start: Start address of iotrace buffer
- * @size: Size of iotrace buffer in bytes
+ * @size: Actual size of iotrace buffer in bytes
+ * @needed_size: Needed of iotrace buffer in bytes
* @offset: Current write offset into iotrace buffer
* @region_start: Address of IO region to trace
* @region_size: Size of region to trace. if 0 will trace all address space
@@ -52,6 +26,7 @@ struct iotrace_record {
static struct iotrace {
ulong start;
ulong size;
+ ulong needed_size;
ulong offset;
ulong region_start;
ulong region_size;
@@ -82,7 +57,12 @@ static void add_record(int flags, const void *ptr, ulong value)
rec = (struct iotrace_record *)map_sysmem(
iotrace.start + iotrace.offset,
sizeof(value));
+ } else {
+ WARN_ONCE(1, "WARNING: iotrace buffer exhausted, please check needed length using \"iotrace stats\"\n");
+ iotrace.needed_size += sizeof(struct iotrace_record);
+ return;
}
+
rec->timestamp = timer_get_us();
rec->flags = flags;
rec->addr = map_to_sysmem(ptr);
@@ -92,6 +72,7 @@ static void add_record(int flags, const void *ptr, ulong value)
iotrace.crc32 = crc32(iotrace.crc32, (unsigned char *)rec,
sizeof(*rec));
+ iotrace.needed_size += sizeof(struct iotrace_record);
iotrace.offset += sizeof(struct iotrace_record);
}
@@ -189,10 +170,11 @@ void iotrace_set_buffer(ulong start, ulong size)
iotrace.crc32 = 0;
}
-void iotrace_get_buffer(ulong *start, ulong *size, ulong *offset, ulong *count)
+void iotrace_get_buffer(ulong *start, ulong *size, ulong *needed_size, ulong *offset, ulong *count)
{
*start = iotrace.start;
*size = iotrace.size;
+ *needed_size = iotrace.needed_size;
*offset = iotrace.offset;
*count = iotrace.offset / sizeof(struct iotrace_record);
}
diff --git a/common/log.c b/common/log.c
index 3b5588ebe7..59869cd29d 100644
--- a/common/log.c
+++ b/common/log.c
@@ -38,12 +38,16 @@ static const char *log_level_name[LOGL_COUNT] = {
const char *log_get_cat_name(enum log_category_t cat)
{
- if (cat > LOGC_COUNT)
- return "invalid";
+ const char *name;
+
+ if (cat < 0 || cat >= LOGC_COUNT)
+ return "<invalid>";
if (cat >= LOGC_NONE)
return log_cat_name[cat - LOGC_NONE];
- return uclass_get_name((enum uclass_id)cat);
+ name = uclass_get_name((enum uclass_id)cat);
+
+ return name ? name : "<missing>";
}
enum log_category_t log_get_cat_by_name(const char *name)