#   Zerocat Chipflasher --- Flash free firmware, kick the Management Engine.
#
#   Copyright (C) 2020, 2021, 2022, 2023  Kai Mertens <kmx@posteo.net>
#
#   This file is part of Zerocat Chipflasher.
#
#   Zerocat Chipflasher is free software: you can redistribute it and/or
#   modify it under the terms of the GNU General Public License as
#   published by the Free Software Foundation, either version 3 of the
#   License, or (at your option) any later version.
#
#   Zerocat Chipflasher is distributed in the hope that it will be useful,
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
#   General Public License for more details.
#
#   You should have received a copy of the GNU General Public License
#   along with Zerocat Chipflasher.
#   If not, see <http://www.gnu.org/licenses/>.


#   Usage
#   -----
#
#
#   To get an overview of targets, type:
#
#           make -C ../../firmware2/test help


#   Workaround for buggy GNU Make < 4.3
#   ===================================
#
#   Finalize commands within a $(shell) function with semicolon,
#   e.g.: $(shell echo;)


# Shell
SHELL                         := /bin/sh


# White Space
EMPTY                         :=
SPACE                         := $(EMPTY) $(EMPTY)
COMMA                         := ,
HASH                          := $(shell echo '#';)
M5                            := zzzzz
TAB1                          := \r\t\t
TAB2                          := \r\t\t\t


# Suffixes
.SUFFIXES :


# Root Paths
ROOT_ROOTDOC                  := ../../doc/
ROOT_HARDWARE                 := ../../hardware/
ROOT_HARDWAREARTWORK          := ../../hardware/artwork/
ROOT_GSCHEM                   := ../../hardware/gschem/
ROOT_DOC                      := ../../firmware2/doc/
ROOT_LOGO                     := ../../firmware2/artwork/logo/
ROOT_IMAGES                   := ../../firmware2/images/
ROOT_GUIX                     := ../../firmware2/guix/
ROOT_SRC                      := ../../firmware2/src/
ROOT_START                    := ../../firmware2/start/


# Standard Utilities
WHEREIS                       := $(shell command -v whereis;)
WHEREIS_FLAGS                 := -b
$(if $(strip $(WHEREIS)),,    $(error Cannot find whereis utility))

CD                            := $(shell command -v cd;)
CD_FLAGS                      :=
$(if $(strip $(CD)),,         $(error Cannot find cd utility))

RM                            := $(shell command -v rm;)
RM_FLAGS                      := -f
$(if $(strip $(RM)),,         $(error Cannot find rm utility))

CAT                           := $(shell command -v cat;)
CAT_FLAGS                     :=
$(if $(strip $(CAT)),,        $(error Cannot find cat utility))

CUT                           := $(shell command -v cut;)
CUT_FLAGS                     := -d' '
$(if $(strip $(CUT)),,        $(error Cannot find cut utility))

GIT                           := $(shell command -v git;)
GIT_FLAGS                     :=
$(if $(strip $(GIT)),,        $(error Cannot find git utility))

SED                           := $(shell command -v sed;)
SED_FLAGS                     := -r
$(if $(strip $(SED)),,        $(error Cannot find sed utility))

SET                           := $(shell command -v set;)
SET_FLAGS                     := -f
$(if $(strip $(SET)),,        $(error Cannot find set utility))

DATE                          := $(shell command -v date;)
DATE_FLAGS                    :=
$(if $(strip $(DATE)),,       $(error Cannot find date utility))

DIFF                          := $(shell command -v diff;)
DIFF_FLAGS                    :=
$(if $(strip $(DIFF)),,       $(error Cannot find diff utility))

ECHO                          := $(shell $(WHEREIS) $(WHEREIS_FLAGS) echo | $(CUT) $(CUT_FLAGS) -f2;)
ECHO_FLAGS                    := -e
$(if $(strip $(ECHO)),,       $(error Cannot find echo utility))

GREP                          := $(shell command -v grep;)
GREP_FLAGS                    :=
$(if $(strip $(GREP)),,       $(error Cannot find grep utility))

READ                          := $(shell command -v read;)
READ_FLAGS                    :=
$(if $(strip $(READ)),,       $(error Cannot find read utility))

SLEEP                         := $(shell command -v sleep;)
SLEEP_FLAGS                   :=
$(if $(strip $(SLEEP)),,      $(error Cannot find sleep utility))

SORT                          := $(shell command -v sort;)
SORT_FLAGS                    :=
$(if $(strip $(SORT)),,       $(error Cannot find sort utility))

UNIQ                          := $(shell command -v uniq;)
UNIQ_FLAGS                    :=
$(if $(strip $(UNIQ)),,       $(error Cannot find uniq utility))

WGET                          := $(shell command -v wget;)
WGET_FLAGS                    := --page-requisites --convert-links
$(if $(strip $(WGET)),,       $(error Cannot find wget utility))

MKTEMP                        := $(shell command -v mktemp;)
MKTEMP_FLAGS                  :=
$(if $(strip $(MKTEMP)),,     $(error Cannot find mktemp utility))

MARKDOWN                      := $(shell command -v markdown;)
MARKDOWN_FLAGS                :=
$(if $(strip $(MARKDOWN)),,   $(error Cannot find markdown utility))


# Extra Utilities
CONNECT                       := $(ROOT_HOST_SRC)connect
CONNECT_FLAGS                 :=
$(if $(strip $(CONNECT)),,    $(error Cannot find connect utility))

SREC_CAT                      := $(shell command -v srec_cat;)
SREC_CAT_FLAGS               :=
$(if $(strip $(SREC_CAT)),,   $(error Cannot find srec_cat utility))

SREC_CMP                      := $(shell command -v srec_cmp;)
SREC_CMP_FLAGS               :=
$(if $(strip $(SREC_CMP)),,   $(error Cannot find srec_cmp utility))

SREC_INFO                     := $(shell command -v srec_info;)
SREC_INFO_FLAGS              :=
$(if $(strip $(SREC_INFO)),,  $(error Cannot find srec_info utility))

FLASHROM                     := $(shell command -v flashrom;)
FLASHROM_FLAGS               :=
$(if $(strip $(FLASHROM)),,  $(error Cannot find flashrom utility))


# Files


# Settings
PROJECT_TITLE                 := Zerocat Chipflasher: Kick2
PROJECT_BRIEF                 := The second firmware, and its interface to flashrom.
MAKEFILE_TITLE                := Test Device, Firmware and Target Chip
PROJECT_REPO                  := git://zerocat.org/zerocat/projects/chipflasher
PROJECT_NUMBER                := $(strip\
	$(shell\
		$(SET) $(SET_FLAGS);\
		$(GIT) $(GIT_FLAGS)\
			describe\
				--always\
				--match v* |\
		$(SED) $(SED_FLAGS)\
			-e 's/(.*)(-g)([0-9a-f]*)/\1-\3/;'\
				-;\
	)\
)
PROJECT_BRANCH                := $(strip\
	$(shell\
		$(GIT) $(GIT_FLAGS)\
			branch |\
		$(SED) $(SED_FLAGS)\
			-e '/^\*/!d; s/^\* //;'\
				-;\
	)\
)
CONFIG                        := settings.conf
FLASHROM_DEVICE               = $$($(SED) $(SED_FLAGS) -e '/^device=/!d; s/^.*=//;' $(CONFIG);)
FLASHROM_BAUDRATE             = $$($(SED) $(SED_FLAGS) -e '/^baudrate=/!d; s/^.*=//;' $(CONFIG);)
FLASHROM_SPISPEED             = $$($(SED) $(SED_FLAGS) -e '/^spispeed=/!d; s/^.*=//;' $(CONFIG);)

# Tinned Cans
define HEADER
$(strip\
	$(ECHO) $(ECHO_FLAGS)\
		"\n$(M5)$(M5)$(M5)$(M5)$(M5)$(M5)$(M5)$(M5)$(M5)$(M5)$(M5)$(M5)$(M5)$(M5)$(M5)$(M5)"\
		"\n$(M5) $(PROJECT_TITLE)"\
		"\n$(M5) – $(PROJECT_BRIEF)"\
		"\n$(M5) $(MAKEFILE_TITLE)"\
		"\n$(M5)$(M5)$(M5)$(M5)$(M5)$(M5)$(M5)$(M5)$(M5)$(M5)$(M5)$(M5)$(M5)$(M5)$(M5)$(M5)"\
)
endef
define HEADLINE
$(strip\
	$(ECHO) $(ECHO_FLAGS)\
		"$(M5) Process target “$@” $(M5)$(M5)"\
)
endef
define DONE
$(strip\
	$(ECHO) $(ECHO_FLAGS)\
		"... successfully processed: “$@”"\
		"\n"\
)
endef


# Built-in Special Targets
#~ .SECONDARY :                  # Uncomment for debugging
.PHONY :\
	all\
	\
	hello\
	help\
	\
	config\
	\
	probe\
	probe-chip\
	test-zeros-LF\
	test-zeros-HF\
	test-rand-LF\
	test-rand-HF\
	test-fakeROM\
	\
	clean-test-fakeROM\
	clean-config\
	clean


# Targets
#   Reset skin, generate all documents
all : hello
	@$(HEADLINE)\
	&& $(DONE);

#   display greeting
#     provided with all, clean and help
hello :
	@$(HEADER)\
	&& $(DONE);

#   display help information
help : hello
	@$(HEADLINE)\
	&& $(ECHO) $(ECHO_FLAGS)\
		"\nList of Targets"\
		"\n==============="\
		"\n"\
		"\nPrerequisite: The device is up and running."\
		"\n"\
		"\nDefault Goal"\
		"\n------------"\
		"\n"\
		"\nall$(TAB2)run all targets"\
		"\n"\
		"\nHelp"\
		"\n----"\
		"\n"\
		"\nhello$(TAB2)greeter, provided with targets all, clean and help"\
		"\nhelp$(TAB2)list available targets"\
		"\n"\
		"\nConfig"\
		"\n------"\
		"\n"\
		"\nconfig$(TAB2)set up configuration file"\
		"\n"\
		"\nActions"\
		"\n-------"\
		"\n"\
		"\ntest-zeros-LF$(TAB2)flash just zeros with lowest frequency"\
		"\ntest-zeros-HF$(TAB2)flash just zeros with highest frequency"\
		"\ntest-rand-LF$(TAB2)flash random bytes with lowest frequency"\
		"\ntest-rand-HF$(TAB2)flash random bytes with highest frequency"\
		"\ntest-fakeROM$(TAB2)test READ, VERIFY, ERASE, WRITE and ERASE-WRITE with a fake ROM"\
		"\n"\
		"\nClean"\
		"\n------"\
		"\n"\
		"\nclean-test-fakeROM$(TAB2)remove generated, fake ROM and test report"\
		"\nclean-config$(TAB2)remove configuration file"\
		"\nclean$(TAB2)remove all generated files"\
		"\n"\
	&& $(DONE);

#   store settings in a file
settings.conf :
	@$(HEADLINE)\
	&& $(ECHO) $(ECHO_FLAGS)\
		"# settings for flashrom"\
			> $@\
	&& $(ECHO) $(ECHO_FLAGS)\
		>> $@\
	&& $(ECHO) $(ECHO_FLAGS)\
		"device=$(ROOT_START)tty_port_pointer"\
			>> $@\
	&& $(READ) $(READ_FLAGS)\
		-p "baudrate: "\
		-r baudrate\
	&& $(ECHO) $(ECHO_FLAGS)\
		"baudrate=$${baudrate}"\
			>> $@\
	&& $(READ) $(READ_FLAGS)\
		-p "spispeed: "\
		-r spispeed\
	&& $(ECHO) $(ECHO_FLAGS)\
		"spispeed=$${spispeed}"\
			>> $@\
	&& $(DONE);

#   retrieve chip info: probe
probe : settings.conf
	-@$(HEADLINE)\
	&& device=$(FLASHROM_DEVICE)\
	&& baudrate=$(FLASHROM_BAUDRATE)\
	&& spispeed=$(FLASHROM_SPISPEED)\
	&& $(ECHO) $(ECHO_FLAGS)\
		"device: $${device}"\
	&& $(ECHO) $(ECHO_FLAGS)\
		"baudrate: $${baudrate}"\
	&& $(ECHO) $(ECHO_FLAGS)\
		"spispeed: $${spispeed}"\
	&& $(FLASHROM) $(FLASHROM_FLAGS)\
		-p serprog:dev=$${device}:$${baudrate},spispeed=$${spispeed}\
	&& $(DONE);

#   dedicated probe
probe-chip : probe
	@$(HEADLINE)\
	&& device=$(FLASHROM_DEVICE)\
	&& baudrate=$(FLASHROM_BAUDRATE)\
	&& spispeed=$(FLASHROM_SPISPEED)\
	&& $(ECHO) $(ECHO_FLAGS)\
		"device: $${device}"\
	&& $(ECHO) $(ECHO_FLAGS)\
		"baudrate: $${baudrate}"\
	&& $(ECHO) $(ECHO_FLAGS)\
		"spispeed: $${spispeed}"\
	&& $(READ) $(READ_FLAGS)\
		-p "chipname: " -r chipname\
	&& $(FLASHROM) $(FLASHROM_FLAGS)\
		-p serprog:dev=$${device}:$${baudrate},spispeed=$${spispeed}\
		-c "$${chipname}"\
	&& $(DONE);

#   test random bytes with high frequency clock
test-rand-HF : probe
	@$(HEADLINE)\
	&& $(READ) $(READ_FLAGS)\
		-p "chipname: " -r chipname\
	&& $(READ) $(READ_FLAGS)\
		-p "chipsize: 0x" -r chipsize\
	&& spispeed=40M\
	&& $(SREC_CAT) $(SREC_CAT_FLAGS)\
		-gen 0x00000000 0x$${chipsize} -rand\
		-o rom-0x$${chipsize}.zero.bin -raw\
	&& $(FLASHROM) $(FLASHROM_FLAGS)\
		-p serprog:dev=$(FLASHROM_DEVICE):$(FLASHROM_BAUDRATE),spispeed=$${spispeed}\
		-V\
		-c "$${chipname}"\
		-w "rom-0x$${chipsize}.rand.bin"\
	&& $(DONE);

#   test random bytes with low frequency clock
test-rand-LF : probe
	@$(HEADLINE)\
	&& $(READ) $(READ_FLAGS)\
		-p "chipname: " -r chipname\
	&& $(READ) $(READ_FLAGS)\
		-p "chipsize: 0x" -r chipsize\
	&& spispeed=3M\
	&& $(SREC_CAT) $(SREC_CAT_FLAGS)\
		-gen 0x00000000 0x$${chipsize} -rand\
		-o rom-0x$${chipsize}.zero.bin -raw\
	&& $(FLASHROM) $(FLASHROM_FLAGS)\
		-p serprog:dev=$(FLASHROM_DEVICE):$(FLASHROM_BAUDRATE),spispeed=$${spispeed}\
		-V\
		-c "$${chipname}"\
		-w "rom-0x$${chipsize}.rand.bin"\
	&& $(DONE);

#   test zeros with high frequency clock
test-zeros-HF : probe
	@$(HEADLINE)\
	&& $(READ) $(READ_FLAGS)\
		-p "chipname: " -r chipname\
	&& $(READ) $(READ_FLAGS)\
		-p "chipsize: 0x" -r chipsize\
	&& spispeed=40M\
	&& $(SREC_CAT) $(SREC_CAT_FLAGS)\
		-gen 0x00000000 0x$${chipsize} -const 0x00\
		-o rom-0x$${chipsize}.zero.bin -raw\
	&& $(FLASHROM) $(FLASHROM_FLAGS)\
		-p serprog:dev=$(FLASHROM_DEVICE):$(FLASHROM_BAUDRATE),spispeed=$${spispeed}\
		-V\
		-c "$${chipname}"\
		-w "rom-0x$${chipsize}.zero.bin"\
	&& $(DONE);

#   test zeros with low frequency clock
test-zeros-LF : probe
	@$(HEADLINE)\
	&& $(READ) $(READ_FLAGS)\
		-p "chipname: " -r chipname\
	&& $(READ) $(READ_FLAGS)\
		-p "chipsize: 0x" -r chipsize\
	&& spispeed=3M\
	&& $(SREC_CAT) $(SREC_CAT_FLAGS)\
		-gen 0x00000000 0x$${chipsize} -const 0x00\
		-o rom-0x$${chipsize}.zero.bin -raw\
	&& $(FLASHROM) $(FLASHROM_FLAGS)\
		-p serprog:dev=$(FLASHROM_DEVICE):$(FLASHROM_BAUDRATE),spispeed=$${spispeed}\
		-V\
		-c "$${chipname}"\
		-w "rom-0x$${chipsize}.zero.bin"\
	&& $(DONE);

#   test flashrom READ, VERIFY, ERASE, WRITE, ERASE-WRITE with a fake ROM,
#   FIXME: How to redirect error status into log file??
test-fakeROM : probe
	@$(HEADLINE)\
	&& $(ECHO) $(ECHO_FLAGS)\
	&& $(ECHO) $(ECHO_FLAGS) "=== TEST SETUP ==="\
	&& $(READ) $(READ_FLAGS) -p "target: " -r target\
	&& $(READ) $(READ_FLAGS) -p "comment: " -r comment\
	&& $(READ) $(READ_FLAGS) -p "DIPSW 1-6 (e.g. xoooox, or ------): " -r dipsw\
	&& $(READ) $(READ_FLAGS) -p "baudrate: " -r baudrate\
	&& $(READ) $(READ_FLAGS) -p "spispeed: " -r spispeed\
	&& $(READ) $(READ_FLAGS) -p "chipname: " -r chipname\
	&& $(READ) $(READ_FLAGS) -p "chipsize: 0x" -r chipsize\
	&& $(ECHO) $(ECHO_FLAGS)\
	&& {\
		$(ECHO) $(ECHO_FLAGS) "=== TEST FAKE ROM ==="\
		&& $(ECHO) $(ECHO_FLAGS) "Project: $(PROJECT_TITLE)"\
		&& $(ECHO) $(ECHO_FLAGS) "Brief:   $(PROJECT_BRIEF)"\
		&& $(ECHO) $(ECHO_FLAGS) "Branch:  $(PROJECT_BRANCH)"\
		&& $(ECHO) $(ECHO_FLAGS) "Commit:  $(PROJECT_NUMBER)"\
		&& $(DATE) $(DATE_FLAGS);\
	} 2>&1 > $@.txt\
	&& {\
		$(ECHO) $(ECHO_FLAGS)\
		&& $(ECHO) $(ECHO_FLAGS) "=== SUMMARY ==="\
		&& $(ECHO) $(ECHO_FLAGS) "target:    $${target}"\
		&& $(ECHO) $(ECHO_FLAGS) "comment:   $${comment}"\
		&& $(ECHO) $(ECHO_FLAGS) "DIPSW 1-6: $${dipsw}"\
		&& $(ECHO) $(ECHO_FLAGS) "baudrate:  $${baudrate}"\
		&& $(ECHO) $(ECHO_FLAGS) "spispeed:  $${spispeed}"\
		&& $(ECHO) $(ECHO_FLAGS) "chipname:  $${chipname}"\
		&& $(ECHO) $(ECHO_FLAGS) "chipsize:  0x$${chipsize}"\
		&& $(ECHO) $(ECHO_FLAGS)\
		&& $(ECHO) $(ECHO_FLAGS) "=== FILES ==="\
		&& backup_target="$${target}.backup.bin"\
		&& rom_fake="rom-0x$${chipsize}.fake.bin"\
		&& chunk=$$((0x$${chipsize}/4))\
		&& $(SREC_CAT) $(SREC_CAT_FLAGS)\
			-gen $$((chunk*0)) $$((chunk*1)) -rand\
			-gen $$((chunk*1)) $$((chunk*2)) -const 0x00\
			-gen $$((chunk*2)) $$((chunk*3)) -const 0xff\
			-gen $$((chunk*3)) $$((chunk*4)) -rand\
			-o $${rom_fake} -raw\
		&& $(ECHO) $(ECHO_FLAGS) "$${backup_target}"\
		&& $(ECHO) $(ECHO_FLAGS) "$${rom_fake}"\
		&& $(ECHO) $(ECHO_FLAGS)\
		&& $(ECHO) $(ECHO_FLAGS) "=== START OF TEST ==="\
		&& $(DATE) $(DATE_FLAGS)\
		&& $(ECHO) $(ECHO_FLAGS)\
		&& $(ECHO) $(ECHO_FLAGS) "--- READ ---";\
	} 2>&1 >> $@.txt\
	&& $(FLASHROM) $(FLASHROM_FLAGS)\
		-p serprog:dev=/dev/ttyS0:$${baudrate},spispeed=$${spispeed}\
		-V\
		-c "$${chipname}"\
		-r "$${backup_target}"\
			2>&1 >> $@.txt\
	&& {\
		$(ECHO) $(ECHO_FLAGS) &&\
		$(ECHO) $(ECHO_FLAGS) "--- VERIFY ---";\
	} 2>&1 >> $@.txt\
	&& $(FLASHROM) $(FLASHROM_FLAGS)\
		-p serprog:dev=/dev/ttyS0:$${baudrate},spispeed=$${spispeed}\
		-V\
		-c "$${chipname}"\
		-v "$${backup_target}"\
			2>&1 >> $@.txt\
	&& {\
		$(ECHO) $(ECHO_FLAGS)\
		&& $(ECHO) $(ECHO_FLAGS) "--- ERASE ---";\
	} 2>&1 >> $@.txt\
	&& $(FLASHROM) $(FLASHROM_FLAGS)\
		-p serprog:dev=/dev/ttyS0:$${baudrate},spispeed=$${spispeed}\
		-V\
		-c "$${chipname}"\
		-E\
			2>&1 >> $@.txt\
	&& {\
		$(ECHO) $(ECHO_FLAGS)\
		&& $(ECHO) $(ECHO_FLAGS) "--- WRITE ---";\
	} 2>&1 >> $@.txt\
	&& $(FLASHROM) $(FLASHROM_FLAGS)\
		-p serprog:dev=/dev/ttyS0:$${baudrate},spispeed=$${spispeed}\
		-V\
		-c "$${chipname}"\
		-w "$${rom_fake}"\
			2>&1 >> $@.txt\
	&& {\
		$(ECHO) $(ECHO_FLAGS)\
		&& $(ECHO) $(ECHO_FLAGS) "--- ERASE/WRITE ---";\
	} 2>&1 >> $@.txt\
	&& $(FLASHROM) $(FLASHROM_FLAGS)\
		-p serprog:dev=/dev/ttyS0:$${baudrate},spispeed=$${spispeed}\
		-V\
		-c "$${chipname}"\
		-w "$${backup_target}"\
			2>&1 >> $@.txt\
	&& {\
		$(ECHO) $(ECHO_FLAGS)\
		&& $(ECHO) $(ECHO_FLAGS) "=== END OF TEST ==="\
		&& $(DATE) $(DATE_FLAGS)\
		&& $(ECHO) $(ECHO_FLAGS);\
	} 2>&1 >> $@.txt\
	&& $(DONE);

#   clean generated files
clean-test-fakeROM :
	@$(HEADLINE)\
	&& $(RM) $(RM_FLAGS)\
		-f\
		$(wildcard *.fake.bin)\
		test-fakeROM.txt\
	&& $(DONE);

#   config
config : $(CONFIG)
	@$(HEADLINE)\
	&& $(DONE);

#  clean settings
clean-config :
	@$(HEADLINE)\
	&& $(RM) $(RM_FLAGS)\
		-f\
		$(CONFIG)\
	&& $(DONE);

#   clean generated files
clean : hello clean-config clean-test-fakeROM
	@$(HEADLINE)\
	&& $(RM) $(RM_FLAGS)\
		-f\
		$(wildcard rom-*.rand.bin rom-*.zero.bin)\
	&& $(DONE);
