summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile4
-rw-r--r--Makefile.rules3
-rw-r--r--common/build.mk24
-rw-r--r--include/config.h6
-rw-r--r--util/build.mk7
-rw-r--r--util/gen_emmc_transfer_data.c158
6 files changed, 202 insertions, 0 deletions
diff --git a/Makefile b/Makefile
index 53d49b0155..dcd8944a83 100644
--- a/Makefile
+++ b/Makefile
@@ -36,6 +36,10 @@ config=$(out)/.config
# If no key file is provided, use the default dev key
PEM ?= $(BDIR)/dev_key.pem
+# If CONFIG_BOOTBLOCK is set, includes AP-FW bootblock in the EC image.
+# If no bootblock is provided, just pack an empty file.
+BOOTBLOCK ?=
+
# If CONFIG_TOUCHPAD_HASH_FW is set, include hashes of a touchpad firmware in
# the EC image (if no touchpad firmware is provided, just output blank hashes).
TOUCHPAD_FW ?=
diff --git a/Makefile.rules b/Makefile.rules
index 9ca18284ea..29a1a27b85 100644
--- a/Makefile.rules
+++ b/Makefile.rules
@@ -103,6 +103,9 @@ cmd_link_taskinfo = $(BUILDCC) $(BUILD_CFLAGS) --shared -fPIC $^ \
cmd_tp_hash = $(out)/util/gen_touchpad_hash \
$(if $(TOUCHPAD_FW),-f $(TOUCHPAD_FW)) -o $@
+cmd_emmc_bootblock = $(out)/util/gen_emmc_transfer_data \
+ $(if $(BOOTBLOCK),-i $(BOOTBLOCK)) -o $@
+
# commands for RSA signature: rwsig does not need to sign the whole image
# (it signs the RW part separately). usbpd1 type needs to sign the final image.
ifeq ($(CONFIG_RWSIG_TYPE_RWSIG),)
diff --git a/common/build.mk b/common/build.mk
index 65665993b2..9530586e41 100644
--- a/common/build.mk
+++ b/common/build.mk
@@ -157,6 +157,30 @@ $(out)/RW/common/rsa.o: CFLAGS+=-O3
$(out)/RO/common/rsa.o: CFLAGS+=-O3
endif
+ifneq ($(CONFIG_BOOTBLOCK),)
+build-util-bin += gen_emmc_transfer_data
+
+# Bootblock is only packed in RO image.
+$(out)/util/gen_emmc_transfer_data: BUILD_LDFLAGS += -DSECTION_IS_RO
+$(out)/bootblock_data.h: $(out)/util/gen_emmc_transfer_data $(out)/.bootblock
+ $(call quiet,emmc_bootblock,BTBLK )
+
+# We only want to repack the bootblock if: $(BOOTBLOCK) variable value has
+# changed, or the file pointed at by $(BOOTBLOCK) has changed. We do this
+# by recording the latest $(BOOTBLOCK) file information in .bootblock
+# TODO: Need a better makefile tricks to do this.
+
+bootblock_ls := $(shell ls -l "$(BOOTBLOCK)" 2>&1)
+old_bootblock_ls := $(shell cat $(out)/.bootblock 2>/dev/null)
+
+$(out)/.bootblock: $(BOOTBLOCK)
+ @echo "$(bootblock_ls)" > $@
+
+ifneq ($(bootblock_ls),$(old_bootblock_ls))
+.PHONY: $(out)/.bootblock
+endif
+endif # CONFIG_BOOTBLOCK
+
ifneq ($(CONFIG_TOUCHPAD_HASH_FW),)
$(out)/RO/common/update_fw.o: $(out)/touchpad_fw_hash.h
$(out)/RW/common/update_fw.o: $(out)/touchpad_fw_hash.h
diff --git a/include/config.h b/include/config.h
index d9fbd06fb1..0701a981d3 100644
--- a/include/config.h
+++ b/include/config.h
@@ -420,6 +420,12 @@
#undef CONFIG_BOOT_HEADER_STORAGE_SIZE
/*****************************************************************************/
+/* Bootblock config */
+
+/* Pack AP-FW bootblock in EC image. */
+#undef CONFIG_BOOTBLOCK
+
+/*****************************************************************************/
/* EC has GPIOs to allow board to reset RTC */
#undef CONFIG_BOARD_HAS_RTC_RESET
diff --git a/util/build.mk b/util/build.mk
index 065528a681..ad9f5656c2 100644
--- a/util/build.mk
+++ b/util/build.mk
@@ -58,6 +58,13 @@ $(out)/util/%/usb_pd_policy.o: %/usb_pd_policy.c
$(call quiet,c_to_vif,BUILDCC)
endif # CONFIG_USB_POWER_DELIVERY
+ifneq ($(CONFIG_BOOTBLOCK),)
+build-util-bin += gen_emmc_transfer_data
+
+# Bootblock is only packed in RO image.
+$(out)/util/gen_emmc_transfer_data: BUILD_LDFLAGS += -DSECTION_IS_RO
+endif # CONFIG_BOOTBLOCK
+
ifneq ($(CONFIG_TOUCHPAD_HASH_FW),)
build-util-bin += gen_touchpad_hash
diff --git a/util/gen_emmc_transfer_data.c b/util/gen_emmc_transfer_data.c
new file mode 100644
index 0000000000..98417beb9b
--- /dev/null
+++ b/util/gen_emmc_transfer_data.c
@@ -0,0 +1,158 @@
+/* Copyright 2018 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ *
+ * Generate transferring data from a file. The transferring data emulates the
+ * eMMC protocol.
+ */
+
+#include <err.h>
+#include <errno.h>
+#include <getopt.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <compile_time_macros.h>
+
+/* eMMC transfer block size */
+#define BLOCK_SIZE 512
+#define BLOCK_RAW_DATA "bootblock_raw_data"
+
+uint16_t crc16_arg(uint8_t data, uint16_t previous_crc)
+{
+ unsigned int crc = previous_crc << 8;
+ int i;
+
+ crc ^= (data << 16);
+ for (i = 8; i; i--) {
+ if (crc & 0x800000)
+ crc ^= (0x11021 << 7);
+ crc <<= 1;
+ }
+
+ return (uint16_t)(crc >> 8);
+}
+
+void header_format(FILE *fin, FILE *fout)
+{
+ uint8_t data[BLOCK_SIZE];
+ int blk, j;
+ uint16_t crc16;
+ size_t cnt = 0;
+
+ fprintf(fout, "/* This file is auto-generated. Do not modify. */\n"
+ "#ifndef __CROS_EC_BOOTBLOCK_DATA_H\n"
+ "#define __CROS_EC_BOOTBLOCK_DATA_H\n"
+ "\n"
+ "#include <stdint.h>\n"
+ "\n"
+ );
+
+ fprintf(fout,
+ "static const uint8_t %s[] __attribute__((aligned(4))) =\n"
+ "{\n"
+ "\t0xff, 0x97, /* Acknowledge boot mode: 1 S=0 010 E=1 11 */\n"
+ "\t0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\n",
+ BLOCK_RAW_DATA);
+
+ for (blk = 0;; blk++) {
+ crc16 = 0;
+ if (fin)
+ cnt = fread(data, 1, BLOCK_SIZE, fin);
+
+ if (cnt == 0)
+ break;
+ else if (cnt < BLOCK_SIZE)
+ memset(&data[cnt], 0xff, BLOCK_SIZE-cnt);
+
+ fprintf(fout, "\t/* Block %d (%ld) */\n", blk, cnt);
+ fprintf(fout, "\t0xff, 0xfe, /* idle, start bit. */");
+ for (j = 0; j < sizeof(data); j++) {
+ fprintf(fout, "%s0x%02x,",
+ (j % 8) == 0 ? "\n\t" : " ", data[j]);
+ crc16 = crc16_arg(data[j], crc16);
+ }
+ fprintf(fout, "\n");
+
+ fprintf(fout, "\t0x%02x, 0x%02x, 0xff,"
+ " /* CRC, end bit, idle */\n",
+ crc16 >> 8, crc16 & 0xff);
+ }
+
+ fprintf(fout, "\t/* Last block: idle */\n");
+ fprintf(fout, "\t0xff, 0xff, 0xff, 0xff\n");
+ fprintf(fout, "};\n");
+ fprintf(fout, "#endif /* __CROS_EC_BOOTBLOCK_DATA_H */\n");
+}
+
+int main(int argc, char **argv)
+{
+ int nopt;
+ int ret = 0;
+ const char *output_name = NULL;
+ char *input_name = NULL;
+ FILE *fin = NULL;
+ FILE *fout = NULL;
+
+ const char short_opts[] = "i:ho:";
+ const struct option long_opts[] = {
+ { "input", 1, NULL, 'i' },
+ { "help", 0, NULL, 'h' },
+ { "out", 1, NULL, 'o' },
+ { NULL }
+ };
+ const char usage[] = "USAGE: %s [-i <input>] -o <output>\n";
+
+ while ((nopt = getopt_long(argc, argv, short_opts, long_opts,
+ NULL)) != -1) {
+ switch (nopt) {
+ case 'i': /* -i or --input*/
+ input_name = optarg;
+ break;
+ case 'h': /* -h or --help */
+ fprintf(stdout, usage, argv[0]);
+ return 0;
+ case 'o': /* -o or --out */
+ output_name = optarg;
+ break;
+ default: /* Invalid parameter. */
+ fprintf(stderr, usage, argv[0]);
+ return 1;
+ }
+ }
+
+ if (output_name == NULL) {
+ fprintf(stderr, usage, argv[0]);
+ return 1;
+ }
+
+ if (input_name == NULL) {
+ printf("No bootblock provided, outputting default file.\n");
+ } else {
+ fin = fopen(input_name, "r");
+ if (!fin) {
+ printf("Cannot open input file: %s\n", input_name);
+ ret = 1;
+ goto out;
+ }
+ }
+
+ fout = fopen(output_name, "w");
+
+ if (!fout) {
+ printf("Cannot open output file: %s\n", output_name);
+ ret = 1;
+ goto out;
+ }
+
+ header_format(fin, fout);
+
+ fclose(fout);
+
+out:
+ if (fin)
+ fclose(fin);
+
+ return ret;
+}