#
# Broadcom Proprietary and Confidential. (c) 2021 Broadcom.  All rights reserved.
#

TOP_DIR       	:= $(shell pwd)
EXT_TOP_DIR	= $(TOP_DIR)/external
EXT_BASE_DIR	= $(EXT_TOP_DIR)/base
EXT_DIRS	:= $(shell echo $(shell find $(EXT_TOP_DIR) -maxdepth 1 -mindepth 1 -type d -not -path '*/.git') | \
			sed 's/ /\n/g' | sort | tr '\n' ':' | rev | cut -c 2- | rev)
OUTPUT_DIR	?= $(TOP_DIR)/output
REPOS_DIR	= $(TOP_DIR)/repos
INTERNAL_DIR	?= $(TOP_DIR)/../rbb_internal_use_only
COMMON_DIR	?=$(TOP_DIR)/../rbb_common

# Don't use system LD_LIBRARY_PATH to avoid including build system libraries with common names
export LD_LIBRARY_PATH :=

DEFAULT_KERNEL  = 5.15

LINUX_DIR       := $(TOP_DIR)/linux
MERGEDLINUX_DIR	:= $(TOP_DIR)/../linux-$(DEFAULT_KERNEL)
BVGLINUX_DIR	:= $(TOP_DIR)/../BVG_CM_linux-$(DEFAULT_KERNEL)
CMLINUX_DIR     := $(TOP_DIR)/../cmlinux

ARCH		= $(shell cat $(TOP_DIR)/.arch 2>/dev/null || echo 'no-arch')
CONFIG_DIR  = $(OUTPUT_DIR)/configs

CONFIG_SUBDIRS  =. arch chip plat misc wifi

PATCHES_DIR	= $(TOP_DIR)/patches

SHELL           := /bin/bash
CFG             := perl -w bin/br_config.pl
RSYNC_FILE	:= $(OUTPUT_DIR)/$(ARCH)/build/pkg-rsync-list.txt
RSYNC_PKGS 	:= linux $(shell cat $(RSYNC_FILE) 2>/dev/null || echo "")
RSYNC_LIST	:= $(shell echo $(RSYNC_PKGS) | sed 's/\>/-rsync/g')
RECONFIGURE_LIST:= $(shell echo $(RSYNC_PKGS) | sed 's/\>/-reconfigure/g')
REBUILD_LIST	:= $(shell echo $(RSYNC_PKGS) | sed 's/\>/-rebuild/g')

BUILDROOT_NAME  = buildroot
BUILDROOT_DIR   = $(TOP_DIR)/$(BUILDROOT_NAME)

USE_THIS_TOOLCHAIN = $(shell cat $(TOP_DIR)/.toolchain || echo 'no-toolchain-set')

ifneq (,$(wildcard $(INTERNAL_DIR)/external/openbfc/sign_tool.mk))
	-include $(INTERNAL_DIR)/external/openbfc/sign_tool.mk
endif

.PHONY: all check-arch check-repos check-internal check-kernel check-common clean defaults-% default-kernel kernel-overlay-% menuconfig merge-% rsync setkernel-% merge-cont-% generic-config legal-info %-dirclean list-defconfigs repos_distclean
.PHONY: clean-external dtb

dtb: check-arch check-kernel generic-config linux-configure host-dt_select-rebuild dtb-rebuild

all: check-arch check-kernel check-common all_

all_: check-arch generic-config
	$(MAKE) -C $(OUTPUT_DIR)/$(ARCH) $(RECONFIGURE_LIST) all || exit 2
	$(MAKE) -C $(OUTPUT_DIR)/$(ARCH) images || exit 2
	$(eval build_opts:=$(shell cat $(OUTPUT_DIR)/.defaults_cmd | sed 's/bcm//'))
	$(eval images_dir=$(OUTPUT_DIR)/$(ARCH)/images)
	if [ "$(ARCH)" == "arm" ]; then \
		ln -sfT $(images_dir)/vmlinuz-$(ARCH) $(images_dir)/vmlinuz-$(build_opts); \
		ln -sfT $(images_dir)/vmlinuz-initrd-$(ARCH) $(images_dir)/vmlinuz-initrd-$(build_opts); \
		ln -sfT $(images_dir)/ubifs-128k-2048-$(ARCH).img $(images_dir)/rootfs-$(build_opts).ubifs-128K-2048; \
		ln -sfT $(images_dir)/ubi-squashfs-128k-2048-$(ARCH).img $(images_dir)/rootfs-$(build_opts).ubi-squashfs-128K-2048; \
	fi
ifdef SIGN_TOOL
	$(eval chip:=$(shell cat $(OUTPUT_DIR)/.defaults_cmd 2>/dev/null | sed 's/bcm//' | cut -d - -f 1 | tr -d "[:space:]"))
	$(eval PROFILES:=$(shell cat $(OUTPUT_DIR)/.profiles 2>/dev/null))
	@if [ -n "$(PROFILES)" ]; then \
		$(MAKE) sign_tool SIGN_NAME="$(chip)" SIGN_LIST="$(PROFILES)" SIGN_PATH="$(OUTPUT_DIR)/$(ARCH)/images"; \
	fi
endif
	@echo "--------------------------------------------------------------------------------"


legal-info:
	$(eval chip:=$(shell cat $(OUTPUT_DIR)/.defaults_cmd 2>/dev/null | sed 's/bcm//' | cut -d - -f 1 | tr -d "[:space:]"))
	$(eval images_dir=$(OUTPUT_DIR)/$(ARCH)/images)
	$(eval full_kernel_ver=$(shell make -C $(TOP_DIR)/linux -s --no-print-directory kernelversion))
	$(MAKE) -C $(OUTPUT_DIR)/$(ARCH) legal-info
	$(TOP_DIR)/scripts/legal-info-2-html.pl -i=$(OUTPUT_DIR)/$(ARCH)/legal-info/manifest.csv --kernel=$(full_kernel_ver)
	cp $(OUTPUT_DIR)/$(ARCH)/legal-info/manifest.html $(images_dir)/$(ARCH)-$(SETKERNEL)-lattice-opensource.html
	@echo "--------------------------------------------------------------------------------"

%:%-rebuild
	@echo ""

%-rebuild:
	$(MAKE) -C $(OUTPUT_DIR)/$(ARCH) $*-rebuild || exit 2
	@echo "--------------------------------------------------------------------------------"

%-configure:
	$(MAKE) -C $(OUTPUT_DIR)/$(ARCH) $*-configure || exit 2
	@echo "--------------------------------------------------------------------------------"

%-dirclean:
	$(MAKE) -C $(OUTPUT_DIR)/$(ARCH) $*-dirclean || exit 2
	@echo "--------------------------------------------------------------------------------"

rsync:
	$(MAKE) -C $(OUTPUT_DIR)/$(ARCH) $(RSYNC_LIST) 1>/dev/null
	@echo "--------------------------------------------------------------------------------"

list-defconfigs:
	$(MAKE) -C $(OUTPUT_DIR)/$(ARCH) list-defconfigs
	@echo "--------------------------------------------------------------------------------"

check-arch:
	@if [ ! -e .arch ]; then \
		echo "Architecture not set, run make defaults-<platform/board>"; \
		exit 2; \
	fi

check-kernel:
	@if [ ! -e linux ]; then \
		$(MAKE) default-kernel; \
	else \
		echo "Kernel build directory set to: `readlink linux`"; \
	fi

%-menuconfig:
	$(MAKE) -C $(OUTPUT_DIR)/$(ARCH) BR2_EXTERNAL=$(EXT_DIRS) $@

menuconfig:
	$(MAKE) -C $(OUTPUT_DIR)/$(ARCH) BR2_EXTERNAL=$(EXT_DIRS) menuconfig
	rm -f $(RSYNC_FILE)

clean:
	@# Note soft link temp workaround until fixed in linux repo done
	@if [ -d $(OUTPUT_DIR)/$(ARCH) ]; then \
		$(MAKE) -C $(OUTPUT_DIR)/$(ARCH) BR2_EXTERNAL= clean 2>/dev/null; \
		if [ -d $(LINUX_DIR) ]; then \
			$(MAKE) -C $(LINUX_DIR) distclean; \
		fi; \
	fi

# Clean and remove any files, generated by previous in-place compilation
clean-external: wl_clean
	$(MAKE) -C $(EXT_TOP_DIR) ARCH=$(ARCH) LINUX_DIR=$(LINUX_DIR) clean

distclean: clean wl_clean repos_distclean
	$(MAKE) -C $(BUILDROOT_DIR) distclean O=$(OUTPUT_DIR)/$(ARCH)
	rm -rf $(OUTPUT_DIR)/$(ARCH)

$(OUTPUT_DIR)/$(ARCH)/.config_: check-arch $(OUTPUT_DIR)/$(ARCH)/.config
	@echo "Create generic config file with CONFIG_ prefix"
	$(shell sed '/^\s*#/ d' $(OUTPUT_DIR)/$(ARCH)/.config > $(OUTPUT_DIR)/$(ARCH)/.config_)
	$(shell sed -i -e '/^$$/d' $(OUTPUT_DIR)/$(ARCH)/.config_)
	$(shell sed -i -e 's/BR2_PACKAGE_/CONFIG_BR2_PACKAGE_/g' $(OUTPUT_DIR)/$(ARCH)/.config_)

generic-config: $(OUTPUT_DIR)/$(ARCH)/.config_

define kernel-patch_
	@if [ ! -e $(LINUX_DIR)/drivers/bcm_media_gw/gfap ]; then \
		cd $(LINUX_DIR)/drivers/bcm_media_gw;  \
	fi
endef

default-kernel: setkernel-$(DEFAULT_KERNEL)

setkernel-%: check-repos
	@if [ ! -e linux ]; then \
	  ln -sfT linux-tbd linux; \
	fi
	@if [ -L linux ]; then \
	  if [ `readlink linux` != "../linux-$*" ]; then \
	    echo "Setting BR kernel build directory to: ../linux-$*"; \
	    ln -sfT ../linux-$* linux; \
	    echo $* > .kernel; \
	  else \
	    echo "Kernel BR build directory already set to linux-$*"; \
	  fi \
	else \
	  echo "Actual BR (not soft link) kernel directory detected, using this"; \
	fi

REBUILD_LIST_LATTICE := $(foreach var, $(REBUILD_LIST), $(if $(findstring lattice,$(var)),$(var)))
lattice_all-rebuild:
	@echo "------ Rebuild of all Lattice targets starting ------"
	$(foreach var, $(REBUILD_LIST_LATTICE), $(MAKE) -C $(OUTPUT_DIR)/$(ARCH) $(var) || exit 2;)
	@echo "------ Rebuild of all Lattice targets complete ------"

merge-cont-%:
	@echo "--------------------------------------------------------------------------------"
	@echo "Merge base/defaults and selected BR defconfig(s): "
	@echo "========================================"
	@for i in $(subst -, ,$*); do \
	    filename=br_$$i; filename+=_defconfig; \
	    for j in $(subst :, ,$(EXT_DIRS)); do \
	    for k in $(CONFIG_SUBDIRS); do \
		if [ -f $$j/configs/$$k/$$filename ]; then \
		    if [ ! -e .arch ]; then \
			ln -sfT $$j/board/broadcom/$$i/arch $(TOP_DIR)/.arch || exit 2; \
			ln -sfT $$j/board/broadcom/$$i/$$i/toolchain $(TOP_DIR)/.toolchain || exit 2; \
			rm -f $(BUILDROOT_DIR)/bin/build_rootfs_images.sh || exit 2; \
			ln -sfT $$j/board/broadcom/$$i/bin/build_rootfs_images.sh \
				$(BUILDROOT_DIR)/bin/build_rootfs_images.sh; \
		    fi; \
		    $(BUILDROOT_DIR)/support/kconfig/merge_config.sh -m -O $(CONFIG_DIR) \
			$(CONFIG_DIR)/ext_merged_defconfig \
			$$j/configs/$$k/$$filename; \
			cp $(CONFIG_DIR)/.config $(CONFIG_DIR)/ext_merged_defconfig; \
		fi; \
	    done; \
	    done; \
	done
	ln -sfT $(CONFIG_DIR)/ext_merged_defconfig $(EXT_TOP_DIR)/openbfc/configs/br_defconfig
	@echo "--------------------------------------------------------------------------------"

check-internal:
	@if [ -d $(INTERNAL_DIR) ]; then \
	    if [ -f $(INTERNAL_DIR)/.only_dl ]; then \
		flock $(TOP_DIR) cp -rf $(INTERNAL_DIR)/dl $(TOP_DIR)/. ; \
	    else \
		flock $(TOP_DIR) cp -rf $(INTERNAL_DIR)/* $(TOP_DIR)/. ; \
	    fi; \
	fi

check-common:
ifeq (,$(wildcard $(COMMON_DIR)/*))
	$(error "The rbb_common directory is missing, compile halted! rbb_common must be installed at the top level of the code tree")
endif

check-dir:
	# Create output directory
	@mkdir -p $(OUTPUT_DIR) || exit 2
	@mkdir -p $(CONFIG_DIR) || exit 2

copy-defaults-defconfig: check-dir
	@rm -f $(CONFIG_DIR)/ext_merged_defconfig
	@cp $(EXT_TOP_DIR)/openbfc/configs/br_defaults_defconfig $(CONFIG_DIR)/ext_merged_defconfig
	@if [ -n "$(FOXCONN_INITRD_IMAGE)" ]; then \
		sed -i 's/BR2_PACKAGE_FXINIT=n/BR2_PACKAGE_FXINIT=y/g' $(CONFIG_DIR)/ext_merged_defconfig; \
		sed -i 's/BR2_PACKAGE_FXINITRD=n/BR2_PACKAGE_FXINITRD=y/g' $(CONFIG_DIR)/ext_merged_defconfig; \
	fi

defaults-%: clean-external check-repos check-internal check-kernel merge-%
	$(call configure)
	@echo "$* defaults set ($(ARCH))."
	@rm -f $(OUTPUT_DIR)/.defaults_cmd
	@echo "$*" | cut -d + -f 1 > $(OUTPUT_DIR)/.defaults_cmd
ifndef BUILD_FOR_RELEASE
ifneq (,$(findstring bcm,$(MAKECMDGOALS)))
	$(eval chip:=$(shell echo "$*" | rev | cut -d + -f 1 | rev))
else
	$(eval chip:=$(shell find $(TOP_DIR)/external/openbfc/configs -type l -name bcm*| xargs basename | cut -d- -f1 |sed 's/bcm//'))
	$(eval kern:=$(shell find $(TOP_DIR)/external/openbfc/configs -type l -name bcm*| xargs basename | rev | cut -f-1 -d- | rev))
	@rm -f $(TOP_DIR)/.defaults_cmd
	@echo "$(chip)-$*-$(kern)" > $(OUTPUT_DIR)/.defaults_cmd
	$(eval chip:=$(shell echo "$*" | cut -d - -f1))
endif
ifdef SIGN_TOOL
	$(call SIGN_LIST,$(OUTPUT_DIR)/.profiles,$(chip))
endif
endif
	$(MAKE) generic-config
#
# Broadcom Proprietary and Confidential. (c) 2021 Broadcom.  All rights reserved.
#
define configure
	@mkdir -p $(OUTPUT_DIR)/$(ARCH) || exit 2

	# Create soft link to misc directory in buildroot
	@ln -sfT $(BUILDROOT_DIR)/misc $(OUTPUT_DIR)/$(ARCH)/misc || exit 2

	# Create soft link to images directory
	@rm -rf images
	@ln -sfT $(OUTPUT_DIR)/$(ARCH)/images images || exit 2

	# Need to ensure a .gitignore before caling CFG
	@touch $(LINUX_DIR)/.gitignore

	@echo "--------------------------------------------------------------------------------"
	@echo "Merge brcmstb_defconfig with ext_merged_defconfig to create final config:"
	@echo "========================================================================="
	@echo "Linux source    : $(LINUX_DIR)"
	@echo "Architecture    : $(ARCH)"
	@echo "Toolchain       : $(USE_THIS_TOOLCHAIN)"
	@echo "Output directory: $(OUTPUT_DIR)/$(ARCH)"
	cd $(BUILDROOT_DIR) && \
	$(CFG)	-f $(CONFIG_DIR)/ext_merged_defconfig \
		-L $(LINUX_DIR) \
		-o $(OUTPUT_DIR) \
		-T $(USE_THIS_TOOLCHAIN) \
		-3 - \
		$(ARCH) 1>/dev/null

	@echo "--------------------------------------------------------------------------------"
	@echo "Set BR2_EXTERNAL and apply final defconfig again:"
	@echo "================================================="
	@echo "External directories: $(EXT_DIRS)"
	cd $(OUTPUT_DIR)/$(ARCH) && $(MAKE) BR2_EXTERNAL=$(EXT_DIRS) brcmstb_merged_defconfig


        @echo "--------------------------------------------------------------------------------"
        @echo "Create a softlink for the build_rootfs_images script:"
        @echo "================================================="
        flock $(BUILDROOT_DIR) ln -sfT  $(EXT_TOP_DIR)/openbfc/bin/build_rootfs_images.sh \
                $(BUILDROOT_DIR)/bin/build_rootfs_images.sh; \

	@echo "--------------------------------------------------------------------------------"
	@echo "List external packages with local source:"
	@echo "========================================="
	cd $(OUTPUT_DIR)/$(ARCH) && $(MAKE) external-deps | grep file:
	@echo "--------------------------------------------------------------------------------"
endef

defaults: distclean check-internal copy-defaults-defconfig
	if [ ! -d $(LINUX_DIR) ]; then \
		$(MAKE) default-kernel; \
	fi
	$(call configure)
	$(eval chip:=$(shell find $(TOP_DIR)/external/openbfc/configs -type l -name bcm*| xargs basename | cut -d- -f1 |sed 's/bcm//'))
	$(eval config:=$(shell find $(TOP_DIR)/external/openbfc/configs -type l -name bcm* | xargs basename | sed 's/-/\n-/g' | sed 's/-no.*//' | tr -d '\n' | grep bcm | sed 's/bcm//'))
	@echo "$(config)" > $(OUTPUT_DIR)/.defaults_cmd
ifdef SIGN_TOOL
	$(call SIGN_LIST,$(OUTPUT_DIR)/.profiles,$(chip))
endif
#
# Broadcom Proprietary and Confidential. (c) 2021 Broadcom.  All rights reserved.
#

.PHONY: merge-%

merge-%: clean copy-defaults-defconfig
	make merge-cont-$*
#
# Broadcom Proprietary and Confidential. (c) 2023 Broadcom.  All rights reserved.
#

WIFI_WL     = "$(TOP_DIR)/../wl"
EXT_WIFI    = "$(EXT_TOP_DIR)/brcm_wifi"
EXT_WIFI_WL = "$(EXT_WIFI)/package/custom/wl"
SETKERNEL   = $(shell cat $(TOP_DIR)/.kernel)

.PHONY: wl-% wl_clean

wl-%: check-kernel
	@echo "Setting WiFi binary link to $*_linux$(SETKERNEL)"; \
	if [ -e $(WIFI_WL)/rbb_wifi_bin_$*_linux$(SETKERNEL) ]; then \
	    ln -snf "$(WIFI_WL)/rbb_wifi_bin_$*_linux$(SETKERNEL)" "$(EXT_WIFI_WL)/bin" || echo "failed to link"; \
	else \
	    echo "$(WIFI_WL)/rbb_wifi_bin_$*_linux$(SETKERNEL) does not exist"; \
	fi

wl_clean:
	rm -rf "$(EXT_WIFI_WL)/bin"
	rm -rf "$(EXT_WIFI_WL)/src"
