#   Zerocat Chipflasher --- Flash free firmware, kick the Management Engine.
#
#   Copyright (C) 2016  kai <kmx@posteo.net>
#   Copyright (C) 2016, 2017, 2018, 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/>.


#   Documentation
#   =============
#
#
#   Brief
#   -----
#
#
#   Upload, start ‘kick2’, the Chipflasher’s new firmware
#
#
#   Usage
#   -----
#
#
#   To get an overview of targets, type:
#
#           make help
#
#   To start ‘connect’, type:
#
#           make connect
#
#   To load ‘kick2’ into RAM and start ‘connect’, type:
#
#           make kick2-ram-connect
#
#   To load ‘kick2’ into EEPROM and start ‘connect’, type:
#
#           make kick2-eeprom-connect
#
#


#   Workaround for 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                         := ,
M5                            := xxxxx
TAB1                          := \r\t\t\t


# Suffixes
.SUFFIXES :


# Root Paths
ROOT_HOST_START               := ../../host/start/
ROOT_HOST_SRC                 := ../../host/src/
ROOT_FW2_START                := $(EMPTY)
ROOT_FW2_SRC                  := ../src/
ROOT_FW2_IO                   := $(ROOT_FW2_START)


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

CP                            := $(shell command -v cp;)
CP_FLAGS                      :=
$(if $(strip $(CP)),,         $(error Cannot find cp utility))

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

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

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

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

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


# Extra Utilities
CONNECT                       := $(ROOT_HOST_SRC)connect
CONNECT_FLAGS                 :=
#   No check for `connect`, it will be compiled.

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

PROPLOAD                      := $(shell command -v propeller-load;)
PROPLOAD_FLAGS                :=
$(if $(strip $(PROPLOAD)),,   $(error Cannot find propeller-load utility))


# Files
SPIN_PINS                     := $(ROOT_FW2_SRC)pins.spin
FLASHROM_LOG                  := $(ROOT_FW2_START)flashrom.log
KICK2                         := $(ROOT_FW2_SRC)kick2
BOARD_CONFIG                  := $(ROOT_FW2_START)board.cfg
TTY_PORT                      := $(ROOT_HOST_START)tty_port_pointer
CHIP2FILE                     := $(ROOT_FW2_IO)chip2file.txt
FILE2CHIP                     := $(ROOT_FW2_IO)file2chip.txt


# Settings
TTY_BAUDRATE                  = $(strip\
	$(shell\
		$(SED) $(SED_FLAGS)\
			-e '/^baudrate:/!d; s/^.*\: //;'\
				$(BOARD_CONFIG);\
	)\
)
TTY_BAUDRATE_SERPROG          = $(strip\
	$(shell\
		$(SED) $(SED_FLAGS)\
			-e '/^#.*define.*_CFG_BAUDRATE_/!d; s/^.*_CFG_BAUDRATE_//;'\
				$(SPIN_PINS);\
	)\
)
FLASHROM_FLAGS                += $(strip\
	-p serprog:dev=$(TTY_PORT):$(TTY_BAUDRATE_SERPROG)\
)
PROJECT_TITLE                 := Zerocat Chipflasher
PROJECT_BRIEF                 := Flash free firmware to BIOS chips, kick the Management Engine.
MAKEFILE_TITLE                := Load ‘kick2’ to chipflasher’s RAM or EEPROM.


# 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)\
		"... end of target “$@”."\
		"\n"\
)
endef


# Built-in Special Targets
#~ .SECONDARY :                  # Uncomment for debugging
.PHONY :\
	all\
	\
	hello\
	help\
	\
	config-baud115200\
	config-baud57600\
	config-baud38400\
	\
	reset\
	kick2-ram\
	kick2-eeprom\
	kick2-ram-terminal\
	connect\
	kick2-ram-connect\
	kick2-eeprom-connect\
	flashrom\
	\
	clean-config\
	clean


# Targets
#   all: same as kick2-ram, with greeter
all : hello kick2-ram
	@$(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"\
		"\nDefault Goal"\
		"\n------------"\
		"\n"\
		"\nall$(TAB1)same as kick2-ram, with hello greeter"\
		"\n"\
		"\nHelp"\
		"\n----"\
		"\n"\
		"\nhello$(TAB1)greeter"\
		"\nhelp$(TAB1)this short overview"\
		"\n"\
		"\nConfigure"\
		"\n---------"\
		"\n"\
		"\nThese goals help you to modify ‘$(BOARD_CONFIG)’ and to set an individual baudrate:"\
		"\n"\
		"\nconfig-baud115200$(TAB1)high speed (default)"\
		"\nconfig-baud57600$(TAB1)medium speed"\
		"\nconfig-baud38400$(TAB1)low speed"\
		"\n"\
		"\nThe rate set will be used by the ‘propeller-load’ utility"\
		"\na) to upload the firmware at the given speed,"\
		"\nb) to pass the baudrate as an argument to ‘connect’ or ‘flashrom’."\
		"\n"\
		"\nThe firmware itself will not be patched, it should have been compiled with the same rate."\
		"\n"\
		"\nActions"\
		"\n-------"\
		"\n"\
		"\nkick2-eeprom$(TAB1)reset device, send ‘kick2’ to EEPROM, don't run"\
		"\nkick2-ram$(TAB1)reset device, send ‘kick2’ to RAM and run"\
		"\nreset$(TAB1)reset chipflasher device"\
		"\n"\
		"\n### Get started with ‘connect’"\
		"\n"\
		"\nkick2-eeprom-connect$(TAB1)send ‘kick2’ to EEPROM and start ‘connect’"\
		"\nkick2-ram-connect$(TAB1)send ‘kick2’ to free-design RAM and start ‘connect’"\
		"\nconnect$(TAB1)start ‘connect’, the host utility, which will talk to ‘kick2’ stored in EEPROM or free-design RAM"\
		"\n"\
		"\n### Get started with ‘flashrom’"\
		"\n"\
		"\nflashrom$(TAB1)invoke ‘flashrom’ without options, just probe chip."\
		"\n"\
		"\n### Get started with ‘terminal’"\
		"\n"\
		"\nkick2-ram-terminal$(TAB1)reset device, send ‘kick2’ to RAM, run and start a propeller-terminal"\
		"\n"\
		"\nClean"\
		"\n-----"\
		"\n"\
		"\nclean-config$(TAB1)reset default baudrate"\
		"\nclean$(TAB1)make files and folders clean"\
		"\n"\
	&& $(DONE);

config-baud115200 : $(BOARD_CONFIG)
	@$(HEADLINE)\
	&& $(SED) $(SED_FLAGS)\
		-i\
		-e 's/^baudrate/#~ baudrate/;'\
		-e's/(\#~ )(baudrate: 115200)$$/\2/;'\
			$<\
	&& $(DONE);

config-baud57600 : $(BOARD_CONFIG)
	@$(HEADLINE)\
	&& $(SED) $(SED_FLAGS)\
		-i\
		-e 's/^baudrate/#~ baudrate/;'\
		-e's/(\#~ )(baudrate: 57600)$$/\2/;'\
			$<\
	&& $(DONE);

config-baud38400 : $(BOARD_CONFIG)
	@$(HEADLINE)\
	&& $(SED) $(SED_FLAGS)\
		-i\
		-e 's/^baudrate/#~ baudrate/;'\
		-e's/(\#~ )(baudrate: 38400)$$/\2/;'\
			$<\
	&& $(DONE);

#   send kick2 to RAM and run
kick2-ram : $(KICK2) $(TTY_PORT) $(BOARD_CONFIG) reset
	@$(HEADLINE)\
	&& $(PROPLOAD) $(PROPLOAD_FLAGS)\
		-p $(TTY_PORT)\
		-b $(basename $(BOARD_CONFIG))\
		$<\
		-r\
	&& $(DONE);

#   send kick2 to EEPROM, don't run
kick2-eeprom : $(KICK2).eeprom $(TTY_PORT) $(BOARD_CONFIG) reset
	@$(HEADLINE)\
	&& $(PROPLOAD) $(PROPLOAD_FLAGS)\
		-p $(TTY_PORT)\
		-b $(basename $(BOARD_CONFIG))\
		$<\
		-e\
	&& $(DONE);

#   send kick2 to RAM, run, and start a propeller-terminal
kick2-ram-terminal : $(KICK2) $(TTY_PORT) $(BOARD_CONFIG) reset
	@$(HEADLINE)\
	&& $(PROPLOAD) $(PROPLOAD_FLAGS)\
		-p $(TTY_PORT)\
		-b $(basename $(BOARD_CONFIG))\
		$<\
		-r\
		-t\
		-q\
	&& $(DONE);

#   connect utility
$(CONNECT) :
	@$(HEADLINE)\
	&& $(MAKE)\
		-C $(@D)\
			$(@F)\
	&& $(DONE);

#   start connect
connect : $(TTY_PORT) $(BOARD_CONFIG) $(CONNECT)
	@$(HEADLINE)\
	&& $(CONNECT) $(CONNECT_FLAGS)\
		$(ROOT_FW2_IO)$(CHIP2FILE)\
		$(ROOT_FW2_IO)$(FILE2CHIP)\
		$(TTY_PORT)\
		B$(TTY_BAUDRATE)\
	&& $(DONE);

#   send kick2 to RAM and start connect
kick2-ram-connect :
	@$(HEADLINE)\
	&& $(MAKE)\
		kick2-ram\
	&& $(SLEEP) $(SLEEP_FLAGS)\
		1\
	&& $(MAKE)\
		connect\
	&& $(DONE);

#   send kick2 to EEPROM and start connect
kick2-eeprom-connect :
	@$(HEADLINE)\
	&& $(MAKE)\
		kick2-eeprom\
	&& $(MAKE)\
		connect\
	&& $(DONE);

#   start flashrom with no operation, just probe chip
flashrom :
	@$(HEADLINE)\
	&& $(FLASHROM) $(FLASHROM_FLAGS)\
		-V\
		-o $(FLASHROM_LOG)\
	&& $(DONE);

#   reset chipflasher device, trigger two times
reset : $(TTY_PORT) $(BOARD_CONFIG)
	@$(HEADLINE)\
	&& $(PROPLOAD) $(PROPLOAD_FLAGS)\
		-p $(TTY_PORT)\
		-b $(basename $(BOARD_CONFIG))\
		-v\
		-r\
		|| (\
			$(SLEEP) $(SLEEP_FLAGS)\
				4s\
			&& $(PROPLOAD) $(PROPLOAD_FLAGS)\
				-p $(TTY_PORT)\
				-b $(basename $(BOARD_CONFIG))\
				-v\
				-r\
		)\
	&& $(DONE);

clean-config : config-baud115200
	@$(HEADLINE)\
	&& $(DONE);

clean : clean-config
	@$(HEADLINE)\
	&& $(DONE);
