[Feature] add GA346 baseline version

Change-Id: Ic62933698569507dcf98240cdf5d9931ae34348f
diff --git a/meta/meta-mediatek-gpl/classes/hsm-sign-env.bbclass b/meta/meta-mediatek-gpl/classes/hsm-sign-env.bbclass
new file mode 100644
index 0000000..4259bc1
--- /dev/null
+++ b/meta/meta-mediatek-gpl/classes/hsm-sign-env.bbclass
@@ -0,0 +1,33 @@
+python __anonymous () {
+    hsm_env_str = ""
+
+    hsm_support = d.getVar('HSM_SUPPORT', True)
+    if hsm_support != 'yes':
+        d.setVar('HSM_SIGN_TOOL','')
+        d.setVar('HSM_SIGN_PARAM','')
+        d.setVar('HSM_ENV', '')
+        return
+    hsm_env_str += "HSM_SUPPORT=yes "
+
+    top_dir = d.getVar('TOPDIR',True)
+    hsm_sign_tool_dir = top_dir+"/../src/devtools/hsmsigntool/"
+
+    hsm_sign_tool = hsm_sign_tool_dir+"hsm_sign_tool"
+    hsm_env_str += "HSM_SIGN_TOOL=\""+hsm_sign_tool+"\" "
+
+    hsm_sign_tool_conf = d.getVar('HSM_SIGN_TOOL_CONF',True)
+    if hsm_sign_tool_conf is None:
+        hsm_sign_tool_conf = hsm_sign_tool_dir+"hsm_sign_tool.conf"
+    hsm_env_str += "HSM_SIGN_TOOL_CONF=\""+hsm_sign_tool_conf+"\" "
+
+    verified_key = d.getVar('VERIFIED_KEY')
+    hsm_env_str += "VERIFIED_KEY=\""+verified_key+"\" "
+
+    softhsm2_conf = d.getVar('SOFTHSM2_CONF',True)
+    if softhsm2_conf is not None:
+        hsm_env_str += "SOFTHSM2_CONF=\""+softhsm2_conf+"\" "
+
+    d.setVar('HSM_SIGN_TOOL',hsm_sign_tool)
+    d.setVar('HSM_SIGN_PARAM',' --signing_helper '+hsm_sign_tool)
+    d.setVar('HSM_ENV', hsm_env_str)
+}
diff --git a/meta/meta-mediatek-gpl/classes/kernel-fitimage-extension.bbclass b/meta/meta-mediatek-gpl/classes/kernel-fitimage-extension.bbclass
new file mode 100755
index 0000000..188b7d2
--- /dev/null
+++ b/meta/meta-mediatek-gpl/classes/kernel-fitimage-extension.bbclass
@@ -0,0 +1,263 @@
+inherit kernel-uboot-extension hsm-sign-env
+
+python __anonymous () {
+    kerneltype = d.getVar('KERNEL_IMAGETYPE', True)
+    if kerneltype == 'fitImage':
+        depends = d.getVar("DEPENDS", True)
+        depends = "%s u-boot-mkimage-native lz4-native dtc-native" % depends
+        d.setVar("DEPENDS", depends)
+
+        # Override KERNEL_IMAGETYPE_FOR_MAKE variable, which is internal
+        # to kernel.bbclass . We have to override it, since we pack zImage
+        # (at least for now) into the fitImage .
+        kernelarch = d.getVar('KERNEL_ARCH', True)
+        if kernelarch == 'arm':
+                d.setVar("KERNEL_IMAGETYPE_FOR_MAKE", "zImage")
+        elif kernelarch == 'arm64':
+                d.setVar("KERNEL_IMAGETYPE_FOR_MAKE", "Image")
+        else:
+                print("please set KERNEL_ARCH variable.")
+                sys.exit(1)
+        image = d.getVar('INITRAMFS_IMAGE', True)
+        if image:
+            d.appendVarFlag('do_assemble_fitimage', 'depends', ' ${INITRAMFS_IMAGE}:do_image_complete')
+}
+
+#
+# Emit the fitImage ITS header
+#
+fitimage_emit_fit_header() {
+        cat << EOF >> fit-image.its
+/dts-v1/;
+
+/ {
+        description = "U-Boot fitImage for ${DISTRO_NAME}/${PV}/${MACHINE}";
+        #address-cells = <1>;
+EOF
+}
+
+#
+# Emit the fitImage section bits
+#
+# $1 ... Section bit type: imagestart - image section start
+#                          confstart  - configuration section start
+#                          sectend    - section end
+#                          fitend     - fitimage end
+#
+fitimage_emit_section_maint() {
+        case $1 in
+        imagestart)
+                cat << EOF >> fit-image.its
+
+        images {
+EOF
+        ;;
+        confstart)
+                cat << EOF >> fit-image.its
+
+        configurations {
+EOF
+        ;;
+        sectend)
+                cat << EOF >> fit-image.its
+        };
+EOF
+        ;;
+        fitend)
+                cat << EOF >> fit-image.its
+};
+EOF
+        ;;
+        esac
+}
+
+#
+# Emit the fitImage ITS kernel section
+#
+# $1 ... Image counter
+# $2 ... Path to kernel image
+# $3 ... Compression type
+fitimage_emit_section_kernel() {
+
+        kernel_csum="sha256"
+
+        ENTRYPOINT=${UBOOT_ENTRYPOINT}
+        if test -n "${UBOOT_ENTRYSYMBOL}"; then
+                ENTRYPOINT=`${HOST_PREFIX}nm ${S}/vmlinux | \
+                        awk '$3=="${UBOOT_ENTRYSYMBOL}" {print $1}'`
+        fi
+
+        cat << EOF >> fit-image.its
+                kernel@${1} {
+                        description = "Linux kernel";
+                        data = /incbin/("${2}");
+                        type = "kernel";
+                        arch = "${UBOOT_ARCH}";
+                        os = "linux";
+                        compression = "${3}";
+                        load = <${UBOOT_LOADADDRESS}>;
+                        entry = <${ENTRYPOINT}>;
+                        hash@1 {
+                                algo = "${kernel_csum}";
+                        };
+                };
+EOF
+}
+
+#
+# Emit the fitImage ITS DTB section
+#
+# $1 ... Image counter
+# $2 ... Path to DTB image
+fitimage_emit_section_dtb() {
+
+        dtb_csum="sha256"
+
+        cat << EOF >> fit-image.its
+                fdt@${1} {
+                        description = "Flattened Device Tree blob";
+                        data = /incbin/("${2}");
+                        type = "flat_dt";
+                        arch = "${UBOOT_ARCH}";
+                        compression = "none";
+                        load = <${DTB_LOADADDRESS}>;
+                        hash@1 {
+                                algo = "${dtb_csum}";
+                        };
+                };
+EOF
+}
+
+#
+# Emit the fitImage ITS configuration section
+#
+# $1 ... Linux kernel ID
+# $2 ... DTB image ID
+fitimage_emit_section_config() {
+
+        conf_csum="sha256,rsa2048"
+        conf_key_name="dev"
+
+        # Test if we have any DTBs at all
+        if [ -z "${2}" ] ; then
+                conf_desc="Boot Linux kernel"
+                fdt_line=""
+        else
+                conf_desc="Boot Linux kernel with FDT blob"
+                fdt_line="fdt = \"fdt@${2}\";"
+        fi
+        kernel_line="kernel = \"kernel@${1}\";"
+
+        cat << EOF >> fit-image.its
+                default = "conf@1";
+                conf@1 {
+                        description = "${conf_desc}";
+                        ${kernel_line}
+                        ${fdt_line}
+                        signature@1 {
+                                algo = "${conf_csum}";
+                                key-name-hint="${conf_key_name}";
+                                sign-images="fdt","kernel";
+                        };
+                };
+EOF
+}
+
+do_assemble_fitimage() {
+        cd ${B}
+        if test "x${KERNEL_IMAGETYPE}" = "xfitImage" ; then
+                kernelcount=1
+                dtbcount=""
+                rm -f fit-image.its
+
+                fitimage_emit_fit_header
+
+                #
+                # Step 1: Prepare a kernel image section.
+                #
+                fitimage_emit_section_maint imagestart
+
+                uboot_prep_kimage
+                fitimage_emit_section_kernel "${kernelcount}" linux.bin "${linux_comp}"
+
+                #
+                # Step 2: Prepare a DTB image section
+                #
+                if test -n "${KERNEL_DEVICETREE}"; then
+                        dtbcount=1
+                        for DTB in ${KERNEL_DEVICETREE}; do
+                                if echo ${DTB} | grep -q '/dts/'; then
+                                        bbwarn "${DTB} contains the full path to the the dts file, but only the dtb name should be used."
+                                        DTB=`basename ${DTB} | sed 's,\.dts$,.dtb,g'`
+                                fi
+
+                                # go through device tree blob dir for 32/64 bits kernel
+                                DTB_PATH="arch/${ARCH}/boot/dts/mediatek/${DTB}"
+                                if [ ! -e "${DTB_PATH}" ]; then
+                                        DTB_PATH="arch/${ARCH}/boot/dts/${DTB}"
+                                        if [ ! -e "${DTB_PATH}" ]; then
+                                                DTB_PATH="arch/${ARCH}/boot/${DTB}"
+                                        fi
+                                fi
+
+                                fitimage_emit_section_dtb ${dtbcount} ${DTB_PATH}
+                                dtbcount=`expr ${dtbcount} + 1`
+                        done
+                fi
+
+                fitimage_emit_section_maint sectend
+
+                # Force the first Kernel and DTB in the default config
+                kernelcount=1
+                dtbcount=1
+
+                #
+                # Step 3: Prepare a configurations section
+                #
+                fitimage_emit_section_maint confstart
+
+                fitimage_emit_section_config ${kernelcount} ${dtbcount}
+
+                fitimage_emit_section_maint sectend
+
+                fitimage_emit_section_maint fitend
+
+                #
+                # Step 4: Assemble the image
+                #
+
+                ${HSM_ENV} HSM_KEY_NAME=${VERIFIED_KEY} uboot-mkimage -f fit-image.its arch/${ARCH}/boot/fitImage
+
+                if [ "${SECURE_BOOT_ENABLE}" = "yes" ]; then
+                        mkdir -p ./mykeys
+                        cp ${MTK_KEY_DIR}/${VERIFIED_KEY}.crt ./mykeys/dev.crt
+                        cp ${MTK_KEY_DIR}/${VERIFIED_KEY}.pem ./mykeys/dev.key
+                        ${HSM_ENV} HSM_KEY_NAME=${VERIFIED_KEY} uboot-mkimage -D "-I dts -O dtb -p 1024" -k ./mykeys -f fit-image.its -r arch/${ARCH}/boot/fitImage
+                fi
+        fi
+}
+
+addtask assemble_fitimage before do_install after do_compile
+
+kernel_do_deploy[vardepsexclude] = "DATETIME"
+kernel_do_deploy_append() {
+        # Update deploy directory
+        if test "x${KERNEL_IMAGETYPE}" = "xfitImage" ; then
+                cd ${B}
+                echo "Copying fit-image.its source file..."
+                its_base_name="${KERNEL_IMAGETYPE}-its-${PV}-${PR}-${MACHINE}-${DATETIME}"
+                its_symlink_name=${KERNEL_IMAGETYPE}-its-${MACHINE}
+                install -m 0644 fit-image.its ${DEPLOYDIR}/${its_base_name}.its
+                linux_bin_base_name="${KERNEL_IMAGETYPE}-linux.bin-${PV}-${PR}-${MACHINE}-${DATETIME}"
+                linux_bin_symlink_name=${KERNEL_IMAGETYPE}-linux.bin-${MACHINE}
+                install -m 0644 linux.bin ${DEPLOYDIR}/${linux_bin_base_name}.bin
+                if test -n "${RECOVERY_KERNEL_DEVICETREE}"; then
+                        find arch/${ARCH}/boot/dts -name "${RECOVERY_KERNEL_DEVICETREE}" -exec install -m 0644 {} ${DEPLOYDIR}/${RECOVERY_KERNEL_DEVICETREE} \;
+                fi
+
+                cd ${DEPLOYDIR}
+                ln -sf ${its_base_name}.its ${its_symlink_name}.its
+                ln -sf ${linux_bin_base_name}.bin ${linux_bin_symlink_name}.bin
+                ln -nfs ${KERNEL_IMAGETYPE}-${KERNEL_IMAGE_BASE_NAME}.bin boot.img
+        fi
+}
diff --git a/meta/meta-mediatek-gpl/classes/kernel-uboot-extension.bbclass b/meta/meta-mediatek-gpl/classes/kernel-uboot-extension.bbclass
new file mode 100644
index 0000000..f00e622
--- /dev/null
+++ b/meta/meta-mediatek-gpl/classes/kernel-uboot-extension.bbclass
@@ -0,0 +1,44 @@
+uboot_prep_kimage() {
+
+        linux_comp=${KERNEL_COMPRESS}
+
+        # uncompressed elf vmlinux
+        vmlinux_path="vmlinux"
+
+        if test "${linux_comp}" = "lz4"; then
+                linux_suffix=".lz4"
+        elif test "${linux_comp}" = "gzip"; then
+                linux_suffix=".gz"
+        else
+                linux_suffix=""
+        fi
+
+        ${OBJCOPY} -O binary -R .note -R .comment -S "${vmlinux_path}" linux.bin
+
+        if test "${linux_comp}" = "lz4"; then
+                lz4 -l -c1 linux.bin > linux.bin${linux_suffix}
+                # append uncompressed filesize info
+                dec_size=0
+                fsize=$(stat -c "%s" "linux.bin")
+                dec_size=$(expr $dec_size + $fsize)
+                printf "%08x\n" $dec_size |
+                        sed 's/\(..\)/\1 /g' | {
+                                read ch0 ch1 ch2 ch3;
+                                for ch in $ch3 $ch2 $ch1 $ch0; do
+                                        printf `printf '%s%03o' '\\' 0x$ch` >> linux.bin${linux_suffix};
+                                done;
+                        }
+        elif test "${linux_comp}" = "gzip"; then
+                gzip -9 linux.bin
+        else
+                echo "For none case or another compressing"
+        fi
+
+        if ! test "${linux_comp}" = "none"; then
+                mv -f "linux.bin${linux_suffix}" linux.bin
+        else
+                echo "No kerenl compression"
+        fi
+
+        echo "${linux_comp}"
+}
diff --git a/meta/meta-mediatek-gpl/classes/ramdisk-fitimage-extension.bbclass b/meta/meta-mediatek-gpl/classes/ramdisk-fitimage-extension.bbclass
new file mode 100755
index 0000000..4b864dc
--- /dev/null
+++ b/meta/meta-mediatek-gpl/classes/ramdisk-fitimage-extension.bbclass
@@ -0,0 +1,328 @@
+inherit kernel-uboot-extension
+
+python __anonymous () {
+    kerneltype = d.getVar('KERNEL_IMAGETYPE', True)
+    if kerneltype == 'fitImage':
+        depends = d.getVar("DEPENDS", True)
+        depends = "%s u-boot-mkimage-native lz4-native dtc-native" % depends
+        d.setVar("DEPENDS", depends)
+
+        # Override KERNEL_IMAGETYPE_FOR_MAKE variable, which is internal
+        # to kernel.bbclass . We have to override it, since we pack zImage
+        # (at least for now) into the fitImage .
+        kernelarch = d.getVar('KERNEL_ARCH', True)
+        if kernelarch == 'arm':
+                d.setVar("KERNEL_IMAGETYPE_FOR_MAKE", "zImage")
+        elif kernelarch == 'arm64':
+                d.setVar("KERNEL_IMAGETYPE_FOR_MAKE", "Image")
+        else:
+                print("please set KERNEL_ARCH variable.")
+                sys.exit(1)
+
+        image = d.getVar('INITRAMFS_IMAGE', True)
+        if image:
+            d.appendVarFlag('do_assemble_fitimage', 'depends', ' ${INITRAMFS_IMAGE}:do_image_complete')
+        d.appendVarFlag('do_assemble_fitimage_ramdisk', 'depends', ' ${INITRAMFS_IMAGE}:do_image_complete')
+}
+
+#
+# Emit the fitImage ITS header
+#
+fitimage_emit_fit_header() {
+        cat << EOF >> fit-image.its
+/dts-v1/;
+
+/ {
+        description = "U-Boot fitImage for ${DISTRO_NAME}/${PV}/${MACHINE}";
+        #address-cells = <1>;
+EOF
+}
+
+#
+# Emit the fitImage section bits
+#
+# $1 ... Section bit type: imagestart - image section start
+#                          confstart  - configuration section start
+#                          sectend    - section end
+#                          fitend     - fitimage end
+#
+fitimage_emit_section_maint() {
+        case $1 in
+        imagestart)
+                cat << EOF >> fit-image.its
+
+        images {
+EOF
+        ;;
+        confstart)
+                cat << EOF >> fit-image.its
+
+        configurations {
+EOF
+        ;;
+        sectend)
+                cat << EOF >> fit-image.its
+        };
+EOF
+        ;;
+        fitend)
+                cat << EOF >> fit-image.its
+};
+EOF
+        ;;
+        esac
+}
+
+#
+# Emit the fitImage ITS kernel section
+#
+# $1 ... Image counter
+# $2 ... Path to kernel image
+# $3 ... Compression type
+fitimage_emit_section_kernel() {
+
+        kernel_csum="sha256"
+
+        ENTRYPOINT=${UBOOT_ENTRYPOINT}
+        if test -n "${UBOOT_ENTRYSYMBOL}"; then
+                ENTRYPOINT=`${HOST_PREFIX}nm ${S}/vmlinux | \
+                        awk '$3=="${UBOOT_ENTRYSYMBOL}" {print $1}'`
+        fi
+
+        cat << EOF >> fit-image.its
+                kernel@${1} {
+                        description = "Linux kernel";
+                        data = /incbin/("${2}");
+                        type = "kernel";
+                        arch = "${UBOOT_ARCH}";
+                        os = "linux";
+                        compression = "${3}";
+                        load = <${UBOOT_LOADADDRESS}>;
+                        entry = <${ENTRYPOINT}>;
+                        hash@1 {
+                                algo = "${kernel_csum}";
+                        };
+                };
+EOF
+}
+
+#
+# Emit the fitImage ITS ramdisk section
+#
+# $1 ... Image counter
+# $2 ... Path to ramdifk image
+fitimage_emit_section_ramdisk() {
+
+        ramdisk_csum="sha256"
+
+        cat << EOF >> fit-image.its
+                ramdisk@${1} {
+                        description = "Ramdisk Image";
+                        data = /incbin/("${2}");
+                        type = "ramdisk";
+                        arch = "${UBOOT_ARCH}";
+                        os = "linux";
+                        compression = "none";
+                        load = <${RAMDISK_LOADADDRESS}>;
+                        entry = <${RAMDISK_LOADADDRESS}>;
+                        hash@1 {
+                                algo = "${ramdisk_csum}";
+                        };
+                };
+EOF
+}
+
+#
+# Emit the fitImage ITS DTB section
+#
+# $1 ... Image counter
+# $2 ... Path to DTB image
+fitimage_emit_section_dtb() {
+
+        dtb_csum="sha256"
+
+        cat << EOF >> fit-image.its
+                fdt@${1} {
+                        description = "Flattened Device Tree blob";
+                        data = /incbin/("${2}");
+                        type = "flat_dt";
+                        arch = "${UBOOT_ARCH}";
+                        compression = "none";
+                        load = <${DTB_LOADADDRESS}>;
+                        hash@1 {
+                                algo = "${dtb_csum}";
+                        };
+                };
+EOF
+}
+
+#
+# Emit the fitImage ITS configuration section
+#
+# $1 ... Linux kernel ID
+# $2 ... DTB image ID
+# $3 ... Ramdisk ID
+fitimage_emit_section_config() {
+
+        conf_csum="sha256,rsa2048"
+        conf_key_name="dev"
+
+        # Test if we have any DTBs at all
+        if [ -z "${2}" ] ; then
+                conf_desc="Boot Linux kernel"
+                fdt_line=""
+        else
+                conf_desc="Boot Linux kernel with FDT blob"
+                fdt_line="fdt = \"fdt@${2}\";"
+        fi
+        kernel_line="kernel = \"kernel@${1}\";"
+
+        # Test if we have ramdisk image
+        if [ -z "${3}" ] ; then
+                ramdisk_line=""
+        else
+                ramdisk_line="ramdisk = \"ramdisk@${3}\";"
+        fi
+
+        cat << EOF >> fit-image.its
+                default = "conf@1";
+                conf@1 {
+                        description = "${conf_desc}";
+                        ${kernel_line}
+                        ${ramdisk_line}
+                        ${fdt_line}
+                        signature@1 {
+                                algo = "${conf_csum}";
+                                key-name-hint="${conf_key_name}";
+                                sign-images="fdt","kernel";
+                        };
+                };
+EOF
+}
+
+#
+# Assemble the ITS format
+#
+# $1 ... Ramdisk ID
+do_assemble_fitimage() {
+        cd ${B}
+        if test "x${KERNEL_IMAGETYPE}" = "xfitImage" ; then
+                kernelcount=1
+                dtbcount=""
+                ramdiskcount="${1}"
+                rm -f fit-image.its
+
+                fitimage_emit_fit_header
+
+                #
+                # Step 1: Prepare a kernel image section.
+                #
+                fitimage_emit_section_maint imagestart
+
+                uboot_prep_kimage
+                fitimage_emit_section_kernel "${kernelcount}" linux.bin "${linux_comp}"
+
+                # Step 1.5: Prepare a ramdisk image section.
+                #
+                if [ "x${ramdiskcount}" = "x1" ] ; then
+                        fitimage_emit_section_ramdisk ${ramdiskcount} ${RAMDISK_PATH}
+                fi
+
+                #
+                # Step 2: Prepare a DTB image section
+                #
+                if test -n "${KERNEL_DEVICETREE}"; then
+                        dtbcount=1
+                        for DTB in ${KERNEL_DEVICETREE}; do
+                                if echo ${DTB} | grep -q '/dts/'; then
+                                        bbwarn "${DTB} contains the full path to the the dts file, but only the dtb name should be used."
+                                        DTB=`basename ${DTB} | sed 's,\.dts$,.dtb,g'`
+                                fi
+
+                                # go through device tree blob dir for 32/64 bits kernel
+                                DTB_PATH="arch/${ARCH}/boot/dts/mediatek/${DTB}"
+                                if [ ! -e "${DTB_PATH}" ]; then
+                                        DTB_PATH="arch/${ARCH}/boot/dts/${DTB}"
+                                        if [ ! -e "${DTB_PATH}" ]; then
+                                                DTB_PATH="arch/${ARCH}/boot/${DTB}"
+                                        fi
+                                fi
+
+                                fitimage_emit_section_dtb ${dtbcount} ${DTB_PATH}
+                                dtbcount=`expr ${dtbcount} + 1`
+                        done
+                fi
+
+                fitimage_emit_section_maint sectend
+
+                # Force the first Kernel and DTB in the default config
+                kernelcount=1
+                dtbcount=1
+
+                #
+                # Step 3: Prepare a configurations section
+                #
+                fitimage_emit_section_maint confstart
+
+                fitimage_emit_section_config ${kernelcount} ${dtbcount} ${ramdiskcount}
+
+                fitimage_emit_section_maint sectend
+
+                fitimage_emit_section_maint fitend
+
+                #
+                # Step 4: Assemble the image
+                #
+
+                uboot-mkimage -f fit-image.its arch/${ARCH}/boot/fitImage
+
+                if [ "${SECURE_BOOT_ENABLE}" = "yes" ]; then
+                        mkdir -p ./mykeys
+                        cp ${MTK_KEY_DIR}/${VERIFIED_KEY}.crt ./mykeys/dev.crt
+                        cp ${MTK_KEY_DIR}/${VERIFIED_KEY}.pem ./mykeys/dev.key
+                        uboot-mkimage -D "-I dts -O dtb -p 1024" -k ./mykeys -f fit-image.its -r arch/${ARCH}/boot/fitImage
+                fi
+        fi
+}
+
+do_assemble_fitimage_kernel() {
+        if test "x${KERNEL_IMAGETYPE}" = "xfitImage" ; then
+                do_assemble_fitimage
+        fi
+}
+
+do_assemble_fitimage_ramdisk() {
+        if test "x${KERNEL_IMAGETYPE}" = "xfitImage" -a -n "${INITRAMFS_IMAGE}" ; then
+                do_assemble_fitimage 1
+        fi
+}
+
+addtask assemble_fitimage_kernel before do_install after do_compile
+addtask assemble_fitimage_ramdisk before do_deploy after do_install
+
+kernel_do_deploy[vardepsexclude] = "DATETIME"
+kernel_do_deploy_append() {
+        # Update deploy directory
+        if test "x${KERNEL_IMAGETYPE}" = "xfitImage" ; then
+                cd ${B}
+                echo "Copying fit-image.its source file..."
+                its_base_name="${KERNEL_IMAGETYPE}-its-${PV}-${PR}-${MACHINE}-${DATETIME}"
+                its_symlink_name=${KERNEL_IMAGETYPE}-its-${MACHINE}
+                install -m 0644 fit-image.its ${DEPLOYDIR}/${its_base_name}.its
+                linux_bin_base_name="${KERNEL_IMAGETYPE}-linux.bin-${PV}-${PR}-${MACHINE}-${DATETIME}"
+                linux_bin_symlink_name=${KERNEL_IMAGETYPE}-linux.bin-${MACHINE}
+                install -m 0644 linux.bin ${DEPLOYDIR}/${linux_bin_base_name}.bin
+                if test -n "${RECOVERY_KERNEL_DEVICETREE}"; then
+                        find arch/${ARCH}/boot/dts -name "${RECOVERY_KERNEL_DEVICETREE}" -exec install -m 0644 {} ${DEPLOYDIR}/${RECOVERY_KERNEL_DEVICETREE} \;
+                fi
+
+                cd ${DEPLOYDIR}
+                ln -sf ${its_base_name}.its ${its_symlink_name}.its
+                ln -sf ${linux_bin_base_name}.bin ${linux_bin_symlink_name}.bin
+                ln -nfs ${KERNEL_IMAGETYPE}-${KERNEL_IMAGE_BASE_NAME}.bin boot.img
+        fi
+}
+
+do_bundle_initramfs() {
+        :
+}
diff --git a/meta/meta-mediatek-gpl/classes/recovery-kernel-fitimage.bbclass b/meta/meta-mediatek-gpl/classes/recovery-kernel-fitimage.bbclass
new file mode 100755
index 0000000..d92d7ab
--- /dev/null
+++ b/meta/meta-mediatek-gpl/classes/recovery-kernel-fitimage.bbclass
@@ -0,0 +1,243 @@
+inherit kernel-uboot-extension
+
+python __anonymous () {
+    kerneltype = d.getVar('KERNEL_IMAGETYPE', True)
+    recoverykerneldevicetree = d.getVar('RECOVERY_KERNEL_DEVICETREE', True)
+    if kerneltype == 'fitImage' and recoverykerneldevicetree != '' :
+        depends = d.getVar("DEPENDS", True)
+        depends = "%s u-boot-mkimage-native lz4-native dtc-native" % depends
+        d.setVar("DEPENDS", depends)
+
+        # Override KERNEL_IMAGETYPE_FOR_MAKE variable, which is internal
+        # to kernel.bbclass . We have to override it, since we pack zImage
+        # (at least for now) into the fitImage .
+        kernelarch = d.getVar('KERNEL_ARCH', True)
+        if kernelarch == 'arm':
+                d.setVar("KERNEL_IMAGETYPE_FOR_MAKE", "zImage")
+        elif kernelarch == 'arm64':
+                d.setVar("KERNEL_IMAGETYPE_FOR_MAKE", "Image")
+        else:
+                print("please set KERNEL_ARCH variable.")
+                sys.exit(1)
+}
+
+#
+# Emit the fitImage ITS header
+#
+fit_recovery_image_emit_fit_header() {
+        cat << EOF >> fit-recovery-image.its
+/dts-v1/;
+
+/ {
+        description = "U-Boot fitImage for ${DISTRO_NAME}/${PV}/${MACHINE}";
+        #address-cells = <1>;
+EOF
+}
+
+#
+# Emit the fitImage section bits
+#
+# $1 ... Section bit type: imagestart - image section start
+#                          confstart  - configuration section start
+#                          sectend    - section end
+#                          fitend     - fitimage end
+#
+fit_recovery_image_emit_section_maint() {
+        case $1 in
+        imagestart)
+                cat << EOF >> fit-recovery-image.its
+
+        images {
+EOF
+        ;;
+        confstart)
+                cat << EOF >> fit-recovery-image.its
+
+        configurations {
+EOF
+        ;;
+        sectend)
+                cat << EOF >> fit-recovery-image.its
+        };
+EOF
+        ;;
+        fitend)
+                cat << EOF >> fit-recovery-image.its
+};
+EOF
+        ;;
+        esac
+}
+
+#
+# Emit the fitImage ITS kernel section
+#
+# $1 ... Image counter
+# $2 ... Path to kernel image
+# $3 ... Compression type
+fit_recovery_image_emit_section_kernel() {
+
+        kernel_csum="sha256"
+
+        ENTRYPOINT=${UBOOT_ENTRYPOINT}
+        if test -n "${UBOOT_ENTRYSYMBOL}"; then
+                ENTRYPOINT=`${HOST_PREFIX}nm ${S}/vmlinux | \
+                        awk '$3=="${UBOOT_ENTRYSYMBOL}" {print $1}'`
+        fi
+
+        cat << EOF >> fit-recovery-image.its
+                kernel@${1} {
+                        description = "Linux kernel";
+                        data = /incbin/("${2}");
+                        type = "kernel";
+                        arch = "${UBOOT_ARCH}";
+                        os = "linux";
+                        compression = "${3}";
+                        load = <${UBOOT_LOADADDRESS}>;
+                        entry = <${ENTRYPOINT}>;
+                        hash@1 {
+                                algo = "${kernel_csum}";
+                        };
+                };
+EOF
+}
+
+#
+# Emit the fitImage ITS DTB section
+#
+# $1 ... Image counter
+# $2 ... Path to DTB image
+fit_recovery_image_emit_section_dtb() {
+
+        dtb_csum="sha256"
+
+        cat << EOF >> fit-recovery-image.its
+                fdt@${1} {
+                        description = "Flattened Device Tree blob";
+                        data = /incbin/("${2}");
+                        type = "flat_dt";
+                        arch = "${UBOOT_ARCH}";
+                        compression = "none";
+                        load = <${DTB_LOADADDRESS}>;
+                        hash@1 {
+                                algo = "${dtb_csum}";
+                        };
+                };
+EOF
+}
+
+#
+# Emit the fitImage ITS configuration section
+#
+# $1 ... Linux kernel ID
+# $2 ... DTB image ID
+fit_recovery_image_emit_section_config() {
+
+        conf_csum="sha256,rsa2048"
+        conf_key_name="dev"
+
+        # Test if we have any DTBs at all
+        if [ -z "${2}" ] ; then
+                conf_desc="Boot Linux kernel"
+                fdt_line=""
+        else
+                conf_desc="Boot Linux kernel with FDT blob"
+                fdt_line="fdt = \"fdt@${2}\";"
+        fi
+        kernel_line="kernel = \"kernel@${1}\";"
+
+        cat << EOF >> fit-recovery-image.its
+                default = "conf@1";
+                conf@1 {
+                        description = "${conf_desc}";
+                        ${kernel_line}
+                        ${fdt_line}
+                        signature@1 {
+                            algo = "${conf_csum}";
+                            key-name-hint="${conf_key_name}";
+                            sign-images="fdt","kernel";
+                        };
+                };
+EOF
+}
+
+do_assemble_recovery_fitimage() {
+        cd ${B}
+        if test "x${KERNEL_IMAGETYPE}" = "xfitImage" && test -n "${RECOVERY_KERNEL_DEVICETREE}"; then
+                kernelcount=1
+                dtbcount=""
+                rm -f fit-recovery-image.its
+
+                fit_recovery_image_emit_fit_header
+
+                #
+                # Step 1: Prepare a kernel image section.
+                #
+                fit_recovery_image_emit_section_maint imagestart
+
+                uboot_prep_kimage
+                fit_recovery_image_emit_section_kernel "${kernelcount}" linux.bin "${linux_comp}"
+
+                #
+                # Step 2: Prepare a DTB image section
+                #
+                dtbcount=1
+                for DTB in ${RECOVERY_KERNEL_DEVICETREE}; do
+                        if echo ${DTB} | grep -q '/dts/'; then
+                                bbwarn "${DTB} contains the full path to the the dts file, but only the dtb name should be used."
+                                DTB=`basename ${DTB} | sed 's,\.dts$,.dtb,g'`
+                        fi
+
+                        # go through device tree blob dir for 32/64 bits kernel
+                        DTB_PATH="arch/${ARCH}/boot/dts/mediatek/${DTB}"
+                        if [ ! -e "${DTB_PATH}" ]; then
+                                DTB_PATH="arch/${ARCH}/boot/dts/${DTB}"
+                                if [ ! -e "${DTB_PATH}" ]; then
+                                        DTB_PATH="arch/${ARCH}/boot/${DTB}"
+                                fi
+                        fi
+
+                        fit_recovery_image_emit_section_dtb ${dtbcount} ${DTB_PATH}
+                        dtbcount=`expr ${dtbcount} + 1`
+                done
+
+                fit_recovery_image_emit_section_maint sectend
+                # Force the first Kernel and DTB in the default config
+                kernelcount=1
+                dtbcount=1
+
+                #
+                # Step 3: Prepare a configurations section
+                #
+                fit_recovery_image_emit_section_maint confstart
+
+                fit_recovery_image_emit_section_config ${kernelcount} ${dtbcount}
+
+                fit_recovery_image_emit_section_maint sectend
+
+                fit_recovery_image_emit_section_maint fitend
+
+                #
+                # Step 4: Assemble the image
+                #
+                uboot-mkimage -f fit-recovery-image.its arch/${ARCH}/boot/fitRecoveryImage
+
+                if [ "${SECURE_BOOT_ENABLE}" = "yes" ]; then
+                        mkdir -p ./mykeys
+                        cp ${MTK_KEY_DIR}/${VERIFIED_KEY}.crt ./mykeys/dev.crt
+                        cp ${MTK_KEY_DIR}/${VERIFIED_KEY}.pem ./mykeys/dev.key
+                        uboot-mkimage -D "-I dts -O dtb -p 1024" -k ./mykeys -f fit-recovery-image.its -r arch/${ARCH}/boot/fitRecoveryImage
+                fi
+        fi
+}
+
+addtask assemble_recovery_fitimage before do_install after do_compile
+
+kernel_do_deploy_append() {
+        # Update deploy directory
+        if test "x${KERNEL_IMAGETYPE}" = "xfitImage" && test -n "${RECOVERY_KERNEL_DEVICETREE}"; then
+                cd ${B}
+                install -m 0644 fit-recovery-image.its ${DEPLOYDIR}/fit-recovery-image.its
+                install -m 0644 arch/${ARCH}/boot/fitRecoveryImage ${DEPLOYDIR}/recovery.img
+        fi
+}
diff --git a/meta/meta-mediatek-gpl/classes/u-boot-fitimage.bbclass b/meta/meta-mediatek-gpl/classes/u-boot-fitimage.bbclass
new file mode 100644
index 0000000..66fc82a
--- /dev/null
+++ b/meta/meta-mediatek-gpl/classes/u-boot-fitimage.bbclass
@@ -0,0 +1,185 @@
+
+python __anonymous () {
+        depends = d.getVar("DEPENDS", True)
+        depends = "%s u-boot-mkimage-native" % depends
+        d.setVar("DEPENDS", depends)
+}
+
+#
+# Emit the fitImage ITS header
+#
+fitimage_emit_fit_header() {
+        cat << EOF >> ${WORKDIR}/fit-image.its
+/dts-v1/;
+
+/ {
+        description = "U-Boot fitImage for ${DISTRO_NAME}/${PV}/${MACHINE}";
+        #address-cells = <1>;
+EOF
+}
+
+#
+# Emit the fitImage section bits
+#
+# $1 ... Section bit type: imagestart - image section start
+#                          confstart  - configuration section start
+#                          sectend    - section end
+#                          fitend     - fitimage end
+#
+fitimage_emit_section_maint() {
+        case $1 in
+        imagestart)
+                cat << EOF >> ${WORKDIR}/fit-image.its
+
+        images {
+EOF
+        ;;
+        confstart)
+                cat << EOF >> ${WORKDIR}/fit-image.its
+
+        configurations {
+EOF
+        ;;
+        sectend)
+                cat << EOF >> ${WORKDIR}/fit-image.its
+        };
+EOF
+        ;;
+        fitend)
+                cat << EOF >> ${WORKDIR}/fit-image.its
+};
+EOF
+        ;;
+        esac
+}
+
+#
+# Emit the fitImage ITS u-boot section
+#
+# $1 ... Path to u-boot image
+# $2 ... Compression type
+fitimage_emit_section_uboot() {
+
+        uboot_csum="sha256"
+        
+        cat << EOF >> ${WORKDIR}/fit-image.its
+                uboot@1 {
+                        description = "U-Boot";
+                        data = /incbin/("${1}");
+                        type = "uboot";
+                        arch = "arm";
+                        os = "linux";
+                        compression = "${2}";
+                        load = <${UBOOT_FIT_LOADADDRESS}>;
+                        entry = <${UBOOT_FIT_ENTRYPOINT}>;
+                        hash@1 {
+                                algo = "${uboot_csum}";
+                        };
+                };
+EOF
+}
+
+#
+# Emit the fitImage ITS DTB section
+#
+# $1 ... Image counter
+# $2 ... Path to DTB image
+fitimage_emit_section_dtb() {
+
+        dtb_csum="sha256"
+
+        cat << EOF >> ${WORKDIR}/fit-image.its
+		        fdt@1 {
+		                description = "sig blob for u-boot verified boot";
+		                data = /incbin/("${1}");
+		                type = "uboot";
+		                arch = "arm";
+		                os = "linux";
+		                compression = "${2}";
+		                load = <${UBOOT_DTB_LOADADDRESS}>;
+		                entry = <${UBOOT_DTB_LOADADDRESS}>;
+		                hash@1 {
+		                        algo = "${dtb_csum}";
+		                };
+		        };
+EOF
+}
+
+#
+# Emit the fitImage ITS configuration section
+#
+# $1 ... u-boot image ID
+fitimage_emit_section_config() {
+
+        conf_csum="sha256,rsa2048"
+        conf_key_name="dev"
+
+        conf_desc="${MTK_PROJECT} configuration"
+
+        uboot_line="uboot = \"uboot@1\";"
+        if [ "${SECURE_BOOT_ENABLE}" = "yes" ]; then
+            fdt_line="fdt = \"fdt@1\";"
+        else
+            fdt_line=""
+        fi
+
+        cat << EOF >> ${WORKDIR}/fit-image.its
+                default = "conf@1";
+                conf@1 {
+                        description = "${conf_desc}";
+                        ${uboot_line}
+                        ${fdt_line}
+                        signature@1 {
+                                algo = "${conf_csum}";
+                                key-name-hint="${conf_key_name}";
+                                sign-images="fdt","uboot";
+                        };
+                };
+EOF
+}
+
+do_assemble_fitimage() {
+
+                rm -f ${WORKDIR}/fit-image.its
+
+                fitimage_emit_fit_header
+
+                #
+                # Step 1: Prepare a u-boot image section.
+                #
+                fitimage_emit_section_maint imagestart
+
+                fitimage_emit_section_uboot ${UBOOT_OUT}/${UBOOT_BINARY} ${UBOOT_COMPRESS}
+                
+                if [ "${SECURE_BOOT_ENABLE}" = "yes" ]; then
+                    fitimage_emit_section_dtb ${UBOOT_OUT}/sig_blob.dtb none
+                fi
+
+                fitimage_emit_section_maint sectend
+
+                #
+                # Step 2: Prepare a configurations section
+                #
+                fitimage_emit_section_maint confstart
+
+                fitimage_emit_section_config
+
+                fitimage_emit_section_maint sectend
+
+                fitimage_emit_section_maint fitend
+
+                #
+                # Step 3: Assemble the image
+                #
+                uboot-mkimage -f ${WORKDIR}/fit-image.its ${UBOOT_OUT}/${UBOOT_FIT_IMAGE}
+
+                if [ "${SECURE_BOOT_ENABLE}" = "yes" ]; then
+                        mkdir -p ./mykeys
+                        cp ${MTK_KEY_DIR}/${VERIFIED_KEY}.crt ./mykeys/dev.crt
+                        cp ${MTK_KEY_DIR}/${VERIFIED_KEY}.pem ./mykeys/dev.key
+                        uboot-mkimage -D "-I dts -O dtb -p 1024" -k ./mykeys -f ${WORKDIR}/fit-image.its -r ${UBOOT_OUT}/${UBOOT_FIT_IMAGE}
+                fi
+}
+
+addtask assemble_fitimage before do_install after do_compile
+
diff --git a/meta/meta-mediatek-gpl/classes/workonsrc.bbclass b/meta/meta-mediatek-gpl/classes/workonsrc.bbclass
new file mode 100755
index 0000000..74a6b77
--- /dev/null
+++ b/meta/meta-mediatek-gpl/classes/workonsrc.bbclass
@@ -0,0 +1,281 @@
+# Copyright (C) 2017 Mediatek
+# Author: Richard Sun
+# Some code and influence taken from externalsrc.bbclass:
+# Copyright (C) 2012 Linux Foundation
+# Author: Richard Purdie
+# Some code and influence taken from srctree.bbclass:
+# Copyright (C) 2009 Chris Larson <clarson@kergoth.com>
+# Released under the MIT license (see COPYING.MIT for the terms)
+#
+# workonsrc.bbclass enables use of an existing source tree, usually workon to 
+# the build system to build a piece of software rather than the usual fetch/unpack/patch
+# process.
+#
+# To use, add workonsrc to the global inherit and set WORKONSRC to point at the
+# directory you want to use containing the sources e.g. from local.conf for a recipe
+# called "myrecipe" you would do:
+#
+# INHERIT += "workonsrc"
+# WORKONSRC_pn-myrecipe = "/path/to/my/source/tree"
+#
+# In order to make this class work for both target and native versions (or with
+# multilibs/cross or other BBCLASSEXTEND variants), B is set to point to a separate
+# directory under the work directory (split source and build directories). This is
+# the default, but the build directory can be set to the source directory if
+# circumstances dictate by setting WORKONSRC_BUILD to the same value, e.g.:
+#
+# WORKONSRC_BUILD_pn-myrecipe = "/path/to/my/source/tree"
+#
+
+SRCTREECOVEREDTASKS ?= "do_patch do_unpack do_fetch"
+EXTERNALSRC_SYMLINKS ?= "oe-workdir:${WORKDIR} oe-logs:${T}"
+
+python () {
+    import subprocess, os.path
+
+    depends = d.getVar("DEPENDS")
+    depends = "%s rsync-native" % depends
+    d.setVar("DEPENDS", depends)
+
+    pn = d.getVar('PN')
+    d.appendVarFlag('do_populate_lic', 'depends', ' %s:do_configure' % pn)
+    workonsrc = d.getVar('WORKONSRC')
+    workonprebuilt = workonsrc.replace("build/../src/", "build/../prebuilt/")
+    if not os.path.exists(workonsrc):
+        if os.path.exists(workonprebuilt):
+            workonsrc = workonprebuilt
+        else:
+            bb.warn("Both %s and %s aren't existed" % (workonsrc, workonprebuilt) )
+
+    # If this is the base recipe and WORKONSRC is set for it or any of its
+    # derivatives, then enable BB_DONT_CACHE to force the recipe to always be
+    # re-parsed so that the file-checksums function for do_compile is run every
+    # time.
+    bpn = d.getVar('BPN')
+    if bpn == d.getVar('PN'):
+        classextend = (d.getVar('BBCLASSEXTEND') or '').split()
+        if (workonsrc or
+                ('native' in classextend and
+                 d.getVar('WORKONSRC_pn-%s-native' % bpn)) or
+                ('nativesdk' in classextend and
+                 d.getVar('WORKONSRC_pn-nativesdk-%s' % bpn)) or
+                ('cross' in classextend and
+                 d.getVar('WORKONSRC_pn-%s-cross' % bpn))):
+            d.setVar('BB_DONT_CACHE', '1')
+
+    if workonsrc:
+        d.setVar('S', workonsrc)
+        workonsrcbuild = d.getVar('WORKONSRC_BUILD')
+        if workonsrcbuild:
+            d.setVar('B', workonsrcbuild)
+        else:
+            d.setVar('B', '${WORKDIR}/${BPN}-${PV}/')
+            workonsrcbuild = d.getVar('B')
+
+        if workonsrc != workonsrcbuild:
+            d.setVar('S', workonsrcbuild)
+
+        local_srcuri = []
+        fetch = bb.fetch2.Fetch((d.getVar('SRC_URI') or '').split(), d)
+        for url in fetch.urls:
+            url_data = fetch.ud[url]
+            parm = url_data.parm
+            if (url_data.type == 'file' or
+                    'type' in parm and parm['type'] == 'kmeta'):
+                local_srcuri.append(url)
+
+        d.setVar('SRC_URI', ' '.join(local_srcuri))
+
+        if '{SRCPV}' in d.getVar('PV', False):
+            # Dummy value because the default function can't be called with blank SRC_URI
+            d.setVar('SRCPV', '999')
+
+        tasks = filter(lambda k: d.getVarFlag(k, "task"), d.keys())
+
+        for task in tasks:
+            if task.endswith("_setscene"):
+                # sstate is never going to work for workon source trees, disable it
+                bb.build.deltask(task, d)
+            else:
+                # Since configure will likely touch ${S}, ensure only we lock so one task has access at a time
+                d.appendVarFlag(task, "lockfiles", " ${S}/singletask.lock")
+
+            # We do not want our source to be wiped out, ever (kernel.bbclass does this for do_clean)
+            cleandirs = (d.getVarFlag(task, 'cleandirs', False) or '').split()
+            setvalue = False
+            for cleandir in cleandirs[:]:
+                if d.expand(cleandir) == workonsrc:
+                    cleandirs.remove(cleandir)
+                    setvalue = True
+            if setvalue:
+                d.setVarFlag(task, 'cleandirs', ' '.join(cleandirs))
+
+        fetch_tasks = ['do_fetch', 'do_unpack']
+        # If we deltask do_patch, there's no dependency to ensure do_unpack gets run, so add one
+        # Note that we cannot use d.appendVarFlag() here because deps is expected to be a list object, not a string
+        d.setVarFlag('do_configure', 'deps', (d.getVarFlag('do_configure', 'deps', False) or []) + ['do_unpack'])
+
+        for task in d.getVar("SRCTREECOVEREDTASKS").split():
+            if local_srcuri and task in fetch_tasks:
+                continue
+            bb.build.deltask(task, d)
+
+        d.prependVarFlag('do_compile', 'prefuncs', "workonsrc_compile_prefunc ")
+        d.prependVarFlag('do_configure', 'prefuncs', "workonsrc_configure_prefunc ")
+
+        d.setVarFlag('do_compile', 'file-checksums', '${@srctree_hash_files(d)}')
+        d.setVarFlag('do_configure', 'file-checksums', '${@srctree_configure_hash_files(d)}')
+
+        # We don't want the workdir to go away
+        d.appendVar('RM_WORK_EXCLUDE', ' ' + d.getVar('PN'))
+
+        bb.build.addtask('do_buildclean',
+                         'do_clean' if d.getVar('S') == d.getVar('B') else None,
+                         None, d)
+
+
+        # If B=S the same builddir is used even for different architectures.
+        # Thus, use a shared CONFIGURESTAMPFILE and STAMP directory so that
+        # change of do_configure task hash is correctly detected and stamps are
+        # invalidated if e.g. MACHINE changes.
+        if d.getVar('S') == d.getVar('B'):
+            configstamp = '${TMPDIR}/work-shared/${PN}/${EXTENDPE}${PV}-${PR}/configure.sstate'
+            d.setVar('CONFIGURESTAMPFILE', configstamp)
+            d.setVar('STAMP', '${STAMPS_DIR}/work-shared/${PN}/${EXTENDPE}${PV}-${PR}')
+            d.setVar('STAMPCLEAN', '${STAMPS_DIR}/work-shared/${PN}/*-*')
+}
+
+python workonsrc_configure_prefunc() {
+    srctree_rsync_files(d)
+    s_dir = d.getVar('S')
+    # Create desired symlinks
+    symlinks = (d.getVar('EXTERNALSRC_SYMLINKS') or '').split()
+    newlinks = []
+    for symlink in symlinks:
+        symsplit = symlink.split(':', 1)
+        lnkfile = os.path.join(s_dir, symsplit[0])
+        target = d.expand(symsplit[1])
+        if len(symsplit) > 1:
+            if os.path.islink(lnkfile):
+                # Link already exists, leave it if it points to the right location already
+                if os.readlink(lnkfile) == target:
+                    continue
+                os.unlink(lnkfile)
+            elif os.path.exists(lnkfile):
+                # File/dir exists with same name as link, just leave it alone
+                continue
+            os.symlink(target, lnkfile)
+            newlinks.append(symsplit[0])
+    # Hide the symlinks from git
+    try:
+        git_exclude_file = os.path.join(s_dir, '.git/info/exclude')
+        if os.path.exists(git_exclude_file):
+            with open(git_exclude_file, 'r+') as efile:
+                elines = efile.readlines()
+                for link in newlinks:
+                    if link in elines or '/'+link in elines:
+                        continue
+                    efile.write('/' + link + '\n')
+    except IOError as ioe:
+        bb.note('Failed to hide EXTERNALSRC_SYMLINKS from git')
+}
+
+python workonsrc_compile_prefunc() {
+    srctree_rsync_files(d)
+    # Make it obvious that this is happening, since forgetting about it could lead to much confusion
+    bb.plain('NOTE: %s: compiling from workon source tree %s' % (d.getVar('PN'), d.getVar('WORKONSRC')))
+}
+
+do_buildclean[dirs] = "${S} ${B}"
+do_buildclean[nostamp] = "1"
+do_buildclean[doc] = "Call 'make clean' or equivalent in ${B}"
+workonsrc_do_buildclean() {
+	if [ -e Makefile -o -e makefile -o -e GNUmakefile ]; then
+		oe_runmake clean || die "make failed"
+	else
+		bbnote "nothing to do - no makefile found"
+	fi
+}
+
+def srctree_rsync_files(d):
+    import subprocess, os.path
+
+    workonsrc = d.getVar('WORKONSRC')
+    workonprebuilt = workonsrc.replace("build/../src/", "build/../prebuilt/")
+    if not os.path.exists(workonsrc):
+        if os.path.exists(workonprebuilt):
+            workonsrc = workonprebuilt
+        else:
+            bb.warn("Both %s and %s aren't existed" % (workonsrc, workonprebuilt) )
+
+    if workonsrc:
+        d.setVar('S', workonsrc)
+        workonsrcbuild = d.getVar('WORKONSRC_BUILD')
+        if workonsrcbuild:
+            d.setVar('B', workonsrcbuild)
+        else:
+            d.setVar('B', '${WORKDIR}/${BPN}-${PV}/')
+            workonsrcbuild = d.getVar('B')
+
+        if workonsrc != workonsrcbuild:
+            cmd = "mkdir -p %s" % (workonsrcbuild)
+            subprocess.call(cmd, shell=True)
+
+            if os.path.exists(workonsrc):
+                workonsrc_rsync_appended_flag = d.getVar('WORKONSRC_RSYNC_APPENDED_FLAG')
+                if workonsrc_rsync_appended_flag is None:
+                    workonsrc_rsync_appended_flag=""
+                cmd = "rsync -aL %s %s/* %s" % (workonsrc_rsync_appended_flag, workonsrc, workonsrcbuild)
+                ret = subprocess.call(cmd, shell=True)
+                if ret != 0:
+                    bb.fatal("rsync -aL %s %s/* %s failed." % (workonsrc_rsync_appended_flag, workonsrc, workonsrcbuild))
+            d.setVar('S', workonsrcbuild)
+
+def srctree_hash_files(d, srcdir=None):
+    import shutil
+    import subprocess
+    import tempfile
+
+    s_dir = srcdir or d.getVar('WORKONSRC')
+    git_dir = os.path.join(s_dir, '.git')
+    oe_hash_file = os.path.join(git_dir, 'oe-devtool-tree-sha1')
+
+    ret = " "
+    if os.path.exists(git_dir):
+        with tempfile.NamedTemporaryFile(dir=git_dir, prefix='oe-devtool-index') as tmp_index:
+            # Clone index
+            shutil.copy2(os.path.join(git_dir, 'index'), tmp_index.name)
+            # Update our custom index
+            env = os.environ.copy()
+            env['GIT_INDEX_FILE'] = tmp_index.name
+            subprocess.check_output(['git', 'add', '-A', '.'], cwd=s_dir, env=env)
+            sha1 = subprocess.check_output(['git', 'write-tree'], cwd=s_dir, env=env).decode("utf-8")
+        with open(oe_hash_file, 'w') as fobj:
+            fobj.write(sha1)
+        ret = oe_hash_file + ':True'
+    else:
+        ret = s_dir + '/*:True'
+    return ret
+
+def srctree_configure_hash_files(d):
+    """
+    Get the list of files that should trigger do_configure to re-execute,
+    based on the value of CONFIGURE_FILES
+    """
+    in_files = (d.getVar('CONFIGURE_FILES') or '').split()
+    out_items = []
+    search_files = []
+    for entry in in_files:
+        if entry.startswith('/'):
+            out_items.append('%s:%s' % (entry, os.path.exists(entry)))
+        else:
+            search_files.append(entry)
+    if search_files:
+        s_dir = d.getVar('WORKONSRC')
+        for root, _, files in os.walk(s_dir):
+            for f in files:
+                if f in search_files:
+                    out_items.append('%s:True' % os.path.join(root, f))
+    return ' '.join(out_items)
+
+EXPORT_FUNCTIONS do_buildclean