diff --git a/tools/testing/selftests/cpu-hotplug/Makefile b/tools/testing/selftests/cpu-hotplug/Makefile
index c9e15ee..d2e540d 100644
--- a/tools/testing/selftests/cpu-hotplug/Makefile
+++ b/tools/testing/selftests/cpu-hotplug/Makefile
@@ -1,18 +1,11 @@
-TEST_STR=/bin/bash ./cpu-on-off-test.sh || echo cpu-hotplug selftests: [FAIL]
+TEST_TITLE = cpu-hotplug
+TEST_MAIN_PROG = cpu-on-off-test.sh
 
 all:
 
-install:
-ifdef INSTALL_KSFT_PATH
-	install ./cpu-on-off-test.sh $(INSTALL_KSFT_PATH)/cpu-on-off-test.sh
-	@echo "$(TEST_STR)" >> $(KSELFTEST)
-else
-	@echo Run make kselftest_install in top level source directory
-endif
-
-run_tests:
-	@$(TEST_STR)
+include ../kselftest.include
 
+# use -a to get all tests
 run_full_test:
 	@/bin/bash ./cpu-on-off-test.sh -a || echo "cpu-hotplug selftests: [FAIL]"
 
diff --git a/tools/testing/selftests/cpu-hotplug/cpu-on-off-test.sh b/tools/testing/selftests/cpu-hotplug/cpu-on-off-test.sh
old mode 100644
new mode 100755
diff --git a/tools/testing/selftests/efivarfs/Makefile b/tools/testing/selftests/efivarfs/Makefile
index aaf404b..8d48e9c 100644
--- a/tools/testing/selftests/efivarfs/Makefile
+++ b/tools/testing/selftests/efivarfs/Makefile
@@ -1,24 +1,15 @@
-CC = $(CROSS_COMPILE)gcc
-CFLAGS = -Wall
+TEST_TITLE = efivarfs
+TEST_MAIN_PROG = efivarfs.sh
 
-test_objs = open-unlink create-read
+CFLAGS = -Wall
 
-TEST_STR = /bin/bash ./efivarfs.sh || echo efivarfs selftests: [FAIL]
+TEST_PROGS = open-unlink create-read
 
 all:
 	gcc open-unlink.c -o open-unlink
 	gcc create-read.c -o create-read
 
-install:
-ifdef INSTALL_KSFT_PATH
-	install ./efivarfs.sh $(test_objs) $(INSTALL_KSFT_PATH)
-	@echo "$(TEST_STR)" >> $(KSELFTEST)
-else
-	@echo Run make kselftest_install in top level source directory
-endif
-
-run_tests: all
-	@$(TEST_STR)
+include ../kselftest.include
 
 clean:
-	rm -f $(test_objs)
+	rm -f $(TEST_PROGS)
diff --git a/tools/testing/selftests/efivarfs/efivarfs.sh b/tools/testing/selftests/efivarfs/efivarfs.sh
old mode 100644
new mode 100755
diff --git a/tools/testing/selftests/firmware/Makefile b/tools/testing/selftests/firmware/Makefile
index 7ac1cf3..b576308 100644
--- a/tools/testing/selftests/firmware/Makefile
+++ b/tools/testing/selftests/firmware/Makefile
@@ -1,36 +1,14 @@
 # Makefile for firmware loading selftests
+TEST_MAIN_PROG = fw_both.sh
+TEST_TITLE = firmware
+TEST_FILES = ./fw_filesystem.sh ./fw_userhelper.sh
 
 # No binaries, but make sure arg-less "make" doesn't trigger "run_tests"
-
-__fw_filesystem:
-fw_filesystem  = if /bin/sh ./fw_filesystem.sh ; then
-fw_filesystem += echo fw_filesystem: ok;
-fw_filesystem += else echo fw_filesystem: [FAIL];
-fw_filesystem += fi
-
-__fw_userhelper:
-fw_userhelper  = if /bin/sh ./fw_userhelper.sh ; then
-fw_userhelper += echo fw_userhelper: ok;
-fw_userhelper += else
-fw_userhelper += echo fw_userhelper: [FAIL];
-fw_userhelper += fi
-
 all:
 
-install:
-ifdef INSTALL_KSFT_PATH
-	install ./fw_filesystem.sh ./fw_userhelper.sh $(INSTALL_KSFT_PATH)
-	@echo "$(fw_filesystem)" >> $(KSELFTEST)
-	@echo "$(fw_userhelper)" >> $(KSELFTEST)
-else
-	@echo Run make kselftest_install in top level source directory
-endif
-
-run_tests:
-	@$(fw_filesystem)
-	@$(fw_userhelper)
+include ../kselftest.include
 
 # Nothing to clean up.
 clean:
 
-.PHONY: all clean run_tests fw_filesystem fw_userhelper
+.PHONY: all clean run_tests
diff --git a/tools/testing/selftests/firmware/fw_both.sh b/tools/testing/selftests/firmware/fw_both.sh
new file mode 100755
index 0000000..fb7fa8d
--- /dev/null
+++ b/tools/testing/selftests/firmware/fw_both.sh
@@ -0,0 +1,13 @@
+#!/bin/sh
+
+if /bin/sh ./fw_filesystem.sh ; then
+	echo "fw_filesystem: ok";
+else
+	echo "fw_filesystem: [FAIL]";
+fi
+
+if /bin/sh ./fw_userhelper.sh ; then
+	echo "fw_userhelper: ok";
+else
+	echo "fw_userhelper: [FAIL]";
+fi
diff --git a/tools/testing/selftests/kselftest.include b/tools/testing/selftests/kselftest.include
new file mode 100644
index 0000000..7020a82
--- /dev/null
+++ b/tools/testing/selftests/kselftest.include
@@ -0,0 +1,26 @@
+# this make include script expects the following variables to be set:
+#  TEST_MAIN_PROG - a single program to invoke to run the test
+#  TEST_TITLE - the title of the test
+#  TEST_FILES - other files that should be copied to the testing directory
+#  INSTALL_KSFT_PATH - where to put test programs
+#  KSELFTEST - the name of the generated script (which calls the sub-tests)
+#  the 'all' target, which makes sure everything is built
+
+# this file defines the 'install' and 'run_tests' targets
+
+CC = $(CROSS_COMPILE)gcc
+INSTALL = $(CROSS_INSTALL)install
+export INSTALL
+
+TEST_STR = ./$(TEST_MAIN_PROG) || echo $(TEST_TITLE) selftests: [FAIL]
+
+install:
+ifdef INSTALL_KSFT_PATH
+	$(INSTALL) ./$(TEST_MAIN_PROG) $(TEST_FILES) $(INSTALL_KSFT_PATH)
+	@echo "$(TEST_STR)" >> $(KSELFTEST)
+else
+	@echo Run make kselftest_install in the top level source directory
+endif
+
+run_tests: all
+	@$(TEST_STR)
diff --git a/tools/testing/selftests/size/Makefile b/tools/testing/selftests/size/Makefile
index bb7113b..c88819a 100644
--- a/tools/testing/selftests/size/Makefile
+++ b/tools/testing/selftests/size/Makefile
@@ -1,22 +1,11 @@
-CC = $(CROSS_COMPILE)gcc
+TEST_MAIN_PROG = get_size
 
-TEST_STR = ./get_size || echo get_size selftests: [FAIL]
+all: $(TEST_MAIN_PROG)
 
-all: get_size
+include ../kselftest.include
 
 get_size: get_size.c
 	$(CC) -static -ffreestanding -nostartfiles -s $< -o $@
 
-install:
-ifdef INSTALL_KSFT_PATH
-	install ./get_size $(INSTALL_KSFT_PATH)
-	@echo "$(TEST_STR)" >> $(KSELFTEST)
-else
-	@echo Run make kselftest_install in top level source directory
-endif
-
-run_tests: all
-	@$(TEST_STR)
-
 clean:
-	$(RM) get_size
+	$(RM) $(TEST_MAIN_PROG)
