summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile5
-rw-r--r--Makefile.rules9
-rw-r--r--Makefile.toolchain2
-rw-r--r--include/common.h52
-rw-r--r--test/build.mk6
-rw-r--r--test/is_enabled.c35
-rw-r--r--test/is_enabled.tasklist9
-rw-r--r--test/is_enabled_error.c27
-rw-r--r--test/is_enabled_error.sh40
-rw-r--r--test/is_enabled_error.tasklist9
10 files changed, 175 insertions, 19 deletions
diff --git a/Makefile b/Makefile
index b5e842a6d0..354c0bf14a 100644
--- a/Makefile
+++ b/Makefile
@@ -308,8 +308,9 @@ rw-objs := $(sort $(rw-common-objs) $(rw-only-objs))
ifeq ($(CONFIG_SHAREDLIB),y)
ro-objs := $(filter-out %_sharedlib.o, $(ro-objs))
endif
-ro-deps := $(ro-objs:%.o=%.o.d)
-rw-deps := $(rw-objs:%.o=%.o.d)
+ro-deps := $(addsuffix .d, $(ro-objs))
+rw-deps := $(addsuffix .d, $(rw-objs))
+
deps := $(ro-deps) $(rw-deps) $(deps-y)
.PHONY: ro rw
diff --git a/Makefile.rules b/Makefile.rules
index 419dd5a9ee..a86ac62869 100644
--- a/Makefile.rules
+++ b/Makefile.rules
@@ -94,7 +94,8 @@ cmd_cxx_to_host = $(HOSTCXX) -std=c++0x $(COMMON_WARN) $(HOST_CXXFLAGS)\
cmd_o_to_a = $(AR) rcs $@ $^
cmd_host_test = $(MAKE) --no-print-directory BOARD=host PROJECT=$* \
V=$(V) out=build/host/$* TEST_BUILD=y EMU_BUILD=y CROSS_COMPILE= \
- $(TEST_FLAG) build/host/$*/$*.exe
+ $(if $(TEST_SCRIPT),TEST_SCRIPT=$(TEST_SCRIPT)) $(TEST_FLAG) \
+ build/host/$*/$*.exe
cmd_run_host_test = ./util/run_host_test $* $(silent)
# generate new version.h, compare if it changed and replace if so
cmd_version = ./util/getversion.sh > $@.tmp && \
@@ -122,6 +123,7 @@ cmd_emmc_bootblock = $(out)/util/gen_emmc_transfer_data \
$(if $(BOOTBLOCK),-i $(BOOTBLOCK)) -o $@
cmd_ipi_table = $(out)/util/gen_ipi_table $@
+cmd_cp_script = cp "$<" "$@" && chmod +x "$@"
# 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.
@@ -471,11 +473,16 @@ $(out)/%.smap: $(out)/%.elf
ifeq ($(TEST_FUZZ),y)
$(out)/$(PROJECT).exe: $(rw-only-objs) $(out)/libec.a
$(call quiet,fuzz_exe,EXE )
+else ifneq ($(TEST_SCRIPT),)
+$(out)/$(PROJECT).exe: test/$(TEST_SCRIPT) | $(ro-objs)
+ $(call quiet,cp_script,CP )
else
$(out)/$(PROJECT).exe: $(ro-objs)
$(call quiet,exe,EXE )
endif
+$(out)/RO/%.o.cmd:%.c
+ $(file > $@,$(subst .o.cmd,.o,$(cmd_c_to_o)))
$(out)/RO/%.o:%.c
$(call quiet,c_to_o,CC )
$(out)/RW/%.o:%.c
diff --git a/Makefile.toolchain b/Makefile.toolchain
index 338caf0672..c7ab5ac106 100644
--- a/Makefile.toolchain
+++ b/Makefile.toolchain
@@ -92,6 +92,8 @@ HOST_CPPFLAGS=$(CFLAGS_DEFINE) $(CFLAGS_INCLUDE) $(CFLAGS_TEST) \
ifneq ($(BOARD),host)
CPPFLAGS+=-ffreestanding -fno-builtin -nostdinc -nostdlib
CPPFLAGS+=-Ibuiltin/
+else
+CPPFLAGS+=-Og
endif
CFLAGS=$(CPPFLAGS) $(CFLAGS_CPU) $(CFLAGS_DEBUG) $(COMMON_WARN) $(CFLAGS_y)
CFLAGS+= -ffunction-sections -fshort-wchar
diff --git a/include/common.h b/include/common.h
index da8b4b73e2..b275b27e1f 100644
--- a/include/common.h
+++ b/include/common.h
@@ -236,29 +236,49 @@ enum ec_error_list {
/*
* Getting something that works in C and CPP for an arg that may or may
- * not be defined is tricky. Here, if we have "#define CONFIG_BOOGER"
- * we match on the placeholder define, insert the "0," for arg1 and generate
- * the triplet (0, 1, 0). Then the last step cherry picks the 2nd arg (a one).
- * When CONFIG_BOOGER is not defined, we generate a (... 1, 0) pair, and when
- * the last step cherry picks the 2nd arg, we get a zero.
+ * not be defined is tricky. Here, if we have "#define CONFIG_FOO"
+ * we match on the placeholder define, insert the "_, 1," for arg1 and generate
+ * the triplet (_, 1, _, (...)). Then the last step cherry picks the 2nd arg
+ * (a one).
+ * When CONFIG_FOO is not defined, we generate a (_, (...)) pair, and when
+ * the last step cherry picks the 2nd arg, we get a code block that verifies
+ * the value of the option. Since the preprocessor won't replace an unknown
+ * token, we compare the option name with the value string. If they are
+ * identical we assume that the value was undefined and return 0. If the value
+ * happens to be anything else we call an undefined method that will raise
+ * a compiler error. This technique requires that the optimizer be enabled so it
+ * can remove the undefined function call.
+ *
*/
-#define __ARG_PLACEHOLDER_ 0,
-#define config_enabled(cfg) _config_enabled(cfg)
-#define _config_enabled(value) __config_enabled(__ARG_PLACEHOLDER_##value)
-#define __config_enabled(arg1_or_junk) ___config_enabled(arg1_or_junk 1, 0, 0)
+#define __ARG_PLACEHOLDER_ _, 1,
+#define _config_enabled(cfg, value) \
+ __config_enabled(__ARG_PLACEHOLDER_##value, cfg, value)
+#define __config_enabled(arg1_or_junk, cfg, value) ___config_enabled( \
+ arg1_or_junk _,\
+ ({ \
+ int __undefined = __builtin_strcmp(cfg, #value) == 0; \
+ extern int IS_ENABLED_BAD_ARGS(void) __attribute__(( \
+ error(cfg " must be <blank>, or not defined.")));\
+ if (!__undefined) \
+ IS_ENABLED_BAD_ARGS(); \
+ 0; \
+ }))
#define ___config_enabled(__ignored, val, ...) val
/**
- * Checks if a config option is defined to an empty value.
+ * Checks if a config option is enabled or disabled
+ *
+ * Enabled examples:
+ * #define CONFIG_FOO
*
- * IS_ENABLED(CONFIG_MY_OPTION) will return 1 in the following case:
- * #define CONFIG_MY_OPTION
+ * Disabled examples:
+ * #undef CONFIG_FOO
*
- * Otherwise if the option has not been defined or defined with a value, it will
- * return 0.
+ * If the option is defined to any value a compiler error will be thrown.
*
- * @param CONFIG_OPTION
+ * Note: This macro will only function inside a code block due to the way
+ * it checks for unknown values.
*/
-#define IS_ENABLED(option) config_enabled(option)
+#define IS_ENABLED(option) _config_enabled(#option, option)
#endif /* __CROS_EC_COMMON_H */
diff --git a/test/build.mk b/test/build.mk
index b5b6e8bbea..b668d1d06d 100644
--- a/test/build.mk
+++ b/test/build.mk
@@ -36,6 +36,8 @@ test-list-host += hooks
test-list-host += host_command
test-list-host += inductive_charging
test-list-host += interrupt
+test-list-host += is_enabled
+test-list-host += is_enabled_error
test-list-host += kb_8042
test-list-host += kb_mkbp
test-list-host += kb_scan
@@ -101,6 +103,7 @@ host_command-y=host_command.o
inductive_charging-y=inductive_charging.o
interrupt-scale=10
interrupt-y=interrupt.o
+is_enabled-y=is_enabled.o
kb_8042-y=kb_8042.o
kb_mkbp-y=kb_mkbp.o
kb_scan-y=kb_scan.o
@@ -152,3 +155,6 @@ TPM2_ROOT := $(CROS_WORKON_SRCROOT)/src/third_party/tpm2
$(out)/RO/common/new_nvmem.o: CFLAGS += -I$(TPM2_ROOT)
$(out)/RO/test/nvmem.o: CFLAGS += -I$(TPM2_ROOT)
$(out)/RO/test/nvmem_tpm2_mock.o: CFLAGS += -I$(TPM2_ROOT)
+
+host-is_enabled_error: TEST_SCRIPT=is_enabled_error.sh
+is_enabled_error-y=is_enabled_error.o.cmd
diff --git a/test/is_enabled.c b/test/is_enabled.c
new file mode 100644
index 0000000000..c994d84b45
--- /dev/null
+++ b/test/is_enabled.c
@@ -0,0 +1,35 @@
+/* Copyright 2019 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.
+ *
+ * Test the IS_ENABLED macro.
+ */
+#include "common.h"
+#include "test_util.h"
+
+#undef CONFIG_UNDEFINED
+#define CONFIG_BLANK
+
+static int test_undef(void)
+{
+ TEST_ASSERT(IS_ENABLED(CONFIG_UNDEFINED) == 0);
+
+ return EC_SUCCESS;
+}
+
+static int test_blank(void)
+{
+ TEST_ASSERT(IS_ENABLED(CONFIG_BLANK) == 1);
+
+ return EC_SUCCESS;
+}
+
+void run_test(void)
+{
+ test_reset();
+
+ RUN_TEST(test_undef);
+ RUN_TEST(test_blank);
+
+ test_print_result();
+}
diff --git a/test/is_enabled.tasklist b/test/is_enabled.tasklist
new file mode 100644
index 0000000000..b97ab17500
--- /dev/null
+++ b/test/is_enabled.tasklist
@@ -0,0 +1,9 @@
+/* Copyright (c) 2019 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.
+ */
+
+/**
+ * See CONFIG_TASK_LIST in config.h for details.
+ */
+#define CONFIG_TEST_TASK_LIST /* No test task */
diff --git a/test/is_enabled_error.c b/test/is_enabled_error.c
new file mode 100644
index 0000000000..2f17925337
--- /dev/null
+++ b/test/is_enabled_error.c
@@ -0,0 +1,27 @@
+/* Copyright 2019 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.
+ *
+ * Test the IS_ENABLED macro fails on unexpected input.
+ */
+#include "common.h"
+#include "test_util.h"
+
+#define CONFIG_VALUE TEST_VALUE
+
+static int test_invalid_value(void)
+{
+ /* This will cause a compilation error */
+ TEST_ASSERT(IS_ENABLED(CONFIG_VALUE) == 0);
+
+ return EC_ERROR_UNKNOWN;
+}
+
+void run_test(void)
+{
+ test_reset();
+
+ RUN_TEST(test_invalid_value);
+
+ test_print_result();
+}
diff --git a/test/is_enabled_error.sh b/test/is_enabled_error.sh
new file mode 100644
index 0000000000..1e5407f31f
--- /dev/null
+++ b/test/is_enabled_error.sh
@@ -0,0 +1,40 @@
+#!/bin/bash -e
+# Copyright 2019 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.
+
+TEST_DIR="$(dirname "${BASH_SOURCE[0]}")"
+
+TEST_CMD="$(cat "${TEST_DIR}/RO/test/is_enabled_error.o.cmd")"
+
+TEST_ERROR_COUNT=0
+
+for test_value in 0 1 2 A "5 + 5"; do
+ echo -n "Running TEST_VALUE=${test_value}..."
+ TEST_CMD_COMPLETE="${TEST_CMD} \"-DTEST_VALUE=${test_value}\""
+ if BUILD_OUTPUT="$(sh -c "$TEST_CMD_COMPLETE" 2>&1)"; then
+ echo "Fail"
+ echo "Compilation should not have succeeded for" \
+ "TEST_VALUE=${test_value}"
+ echo "$BUILD_OUTPUT"
+ TEST_ERROR_COUNT=$((TEST_ERROR_COUNT+1))
+ continue
+ fi
+
+ EXPECTED_ERROR="CONFIG_VALUE must be <blank>, or not defined"
+ if grep -q "$EXPECTED_ERROR" <<< "$BUILD_OUTPUT"; then
+ echo "OK"
+ else
+ echo "Fail"
+ echo "Expected to find: $EXPECTED_ERROR"
+ echo "Actual error:"
+ echo "$BUILD_OUTPUT"
+ TEST_ERROR_COUNT=$((TEST_ERROR_COUNT+1))
+ fi
+done
+
+if [[ $TEST_ERROR_COUNT -eq 0 ]]; then
+ echo "Pass!"
+else
+ echo "Fail! (${TEST_ERROR_COUNT} tests)"
+fi
diff --git a/test/is_enabled_error.tasklist b/test/is_enabled_error.tasklist
new file mode 100644
index 0000000000..b97ab17500
--- /dev/null
+++ b/test/is_enabled_error.tasklist
@@ -0,0 +1,9 @@
+/* Copyright (c) 2019 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.
+ */
+
+/**
+ * See CONFIG_TASK_LIST in config.h for details.
+ */
+#define CONFIG_TEST_TASK_LIST /* No test task */