[Feature]add MT2731_MP2_MR2_SVN388 baseline version
Change-Id: Ief04314834b31e27effab435d3ca8ba33b499059
diff --git a/meta/meta-mediatek/LICENSE b/meta/meta-mediatek/LICENSE
new file mode 100644
index 0000000..7d4bcac
--- /dev/null
+++ b/meta/meta-mediatek/LICENSE
@@ -0,0 +1,3 @@
+All metadata is MediaTekProprietary licensed unless otherwise stated. Source code included
+in tree for individual recipes is under the LICENSE stated in the associated
+recipe (.bb file) unless otherwise stated.
diff --git a/meta/meta-mediatek/classes/add-pulseaudio-service.bbclass b/meta/meta-mediatek/classes/add-pulseaudio-service.bbclass
new file mode 100644
index 0000000..a61f0d2
--- /dev/null
+++ b/meta/meta-mediatek/classes/add-pulseaudio-service.bbclass
@@ -0,0 +1,6 @@
+install_pulseaudio_service_to_profile() {
+ echo "pulseaudio --start" > ${IMAGE_ROOTFS}${ROOT_HOME}/.profile
+}
+
+ROOTFS_POSTPROCESS_COMMAND += " install_pulseaudio_service_to_profile;"
+
diff --git a/meta/meta-mediatek/classes/add-recovery-rootfs-8167s.bbclass b/meta/meta-mediatek/classes/add-recovery-rootfs-8167s.bbclass
new file mode 100644
index 0000000..95ed301
--- /dev/null
+++ b/meta/meta-mediatek/classes/add-recovery-rootfs-8167s.bbclass
@@ -0,0 +1 @@
+do_rootfs[depends] += "mtk-image-aiv8167m3v4-emmc-recovery:do_mtdverity_for_rootfs"
\ No newline at end of file
diff --git a/meta/meta-mediatek/classes/add-recovery-rootfs.bbclass b/meta/meta-mediatek/classes/add-recovery-rootfs.bbclass
new file mode 100644
index 0000000..8bc0812
--- /dev/null
+++ b/meta/meta-mediatek/classes/add-recovery-rootfs.bbclass
@@ -0,0 +1 @@
+do_rootfs[depends] += "mtk-image-aud-8516-recovery:do_mtdverity_for_rootfs"
\ No newline at end of file
diff --git a/meta/meta-mediatek/classes/avb_sign_image.bbclass b/meta/meta-mediatek/classes/avb_sign_image.bbclass
new file mode 100644
index 0000000..def151c
--- /dev/null
+++ b/meta/meta-mediatek/classes/avb_sign_image.bbclass
@@ -0,0 +1,128 @@
+inherit hsm-sign-env
+
+AVBTOOL="python ${DEPLOY_DIR_IMAGE}/avbtool"
+SCATTER_FILE="${DEPLOY_DIR_IMAGE}/partition_${BOOTDEV_TYPE}.xml"
+
+IMAGE_FSTYPE="img"
+IMAGE_DIR_ROOTFS="${DEPLOY_DIR_IMAGE}"
+
+
+IMAGE_NAME_ROOTFS="system.${IMAGE_FSTYPE}"
+
+IMAGE_NAME_BOOTIMG="boot.img"
+IMAGE_DIR_BOOTIMG="${DEPLOY_DIR_IMAGE}"
+
+AVB_BLOCK_SIZE="1024"
+AVB_SYSTEM_KEY_NAME="verified_key"
+AVB_SYSTEM_KEY="${MTK_KEY_DIR}/${VERIFIED_KEY}.pem"
+
+DEPENDS += "python-pycrypto-native android-tools-avbtool scatter"
+
+exec_avbtool() {
+
+ echo "check config setting: enable=${SECURE_BOOT_ENABLE};SE_type=${SECURE_BOOT_TYPE}"
+ vb_hash_algo=`echo ${VB_HASH_ALGO}|tr 'a-z' 'A-Z'`
+ vb_rsa_algo=`echo ${VB_RSA_ALGO}|tr 'a-z' 'A-Z'`
+ if [ -n "${VB_HASH_ALGO}" ] && [ -n "${VB_RSA_ALGO}" ] ; then
+ AVB_ALGO="${vb_hash_algo}_${vb_rsa_algo}"
+ else
+ AVB_ALGO="SHA256_RSA2048"
+ fi
+ if [ "${SECURE_BOOT_ENABLE}" = "yes" ] && [ "${SECURE_BOOT_TYPE}" = "avb" ]; then
+ echo "start AVB sign ... "
+ echo "PARTITION_SIZE_BOOTIMG=${PARTITION_SIZE_BOOTIMG}; PARTITION_SIZE_ROOTFS=${PARTITION_SIZE_ROOTFS}"
+
+ PARTITION_NAME_ROOTFS="system"
+ PARTITION_NAME_BOOTIMG="boot"
+ if [ "${AVB_ANTIROLLBACK_VERSION}" = "" ]; then
+ AVB_ANTIROLLBACK_VERSION="0"
+ fi
+
+ echo "start to erase footer: ${IMAGE_NAME_BOOTIMG}"
+ ${AVBTOOL} erase_footer --image ${IMAGE_DIR_BOOTIMG}/${IMAGE_NAME_BOOTIMG} || true
+
+ echo "start to erase footer: system.${IMAGE_FSTYPE} "
+ ${AVBTOOL} erase_footer --image ${IMAGE_DIR_ROOTFS}/system.${IMAGE_FSTYPE} || true
+
+ if test -e ${IMAGE_DIR_BOOTIMG}/${IMAGE_NAME_BOOTIMG}; then
+ echo "start to sign image: ${IMAGE_NAME_BOOTIMG}"
+ ${HSM_ENV} ${AVBTOOL} add_hash_footer --image ${IMAGE_DIR_BOOTIMG}/${IMAGE_NAME_BOOTIMG} \
+ --partition_size ${PARTITION_SIZE_BOOTIMG} \
+ --partition_name ${PARTITION_NAME_BOOTIMG} \
+ --algorithm ${AVB_ALGO} \
+ --key ${AVB_SYSTEM_KEY} \
+ ${HSM_SIGN_PARAM}
+ fi
+
+ if test -e ${IMAGE_DIR_ROOTFS}/system.${IMAGE_FSTYPE}; then
+ echo "start to sign image: system.${IMAGE_FSTYPE} "
+ ${HSM_ENV} ${AVBTOOL} add_hashtree_footer --block_size ${AVB_BLOCK_SIZE} \
+ --partition_size ${PARTITION_SIZE_ROOTFS} \
+ --partition_name ${PARTITION_NAME_ROOTFS} \
+ --image ${IMAGE_DIR_ROOTFS}/system.${IMAGE_FSTYPE} \
+ --algorithm ${AVB_ALGO} \
+ --key ${AVB_SYSTEM_KEY} \
+ ${HSM_SIGN_PARAM}
+
+ if test -e ${IMAGE_DIR_BOOTIMG}/${IMAGE_NAME_BOOTIMG}; then
+ echo "start to make vbmeta image"
+ ${HSM_ENV} ${AVBTOOL} make_vbmeta_image --rollback_index ${AVB_ANTIROLLBACK_VERSION} \
+ --include_descriptors_from_image ${IMAGE_DIR_BOOTIMG}/${IMAGE_NAME_BOOTIMG} \
+ --include_descriptors_from_image ${IMAGE_DIR_ROOTFS}/system.${IMAGE_FSTYPE} \
+ --setup_rootfs_from_kernel ${IMAGE_DIR_ROOTFS}/system.${IMAGE_FSTYPE} \
+ --algorithm ${AVB_ALGO} \
+ --key ${AVB_SYSTEM_KEY} \
+ --output vbmeta.img \
+ ${HSM_SIGN_PARAM}
+
+ if [ ${BOOTDEV_TYPE} != "nand" ]; then
+ echo "start to append vbmeta image"
+ ${AVBTOOL} append_vbmeta_image --image ${IMAGE_DIR_BOOTIMG}/${IMAGE_NAME_BOOTIMG} \
+ --partition_size ${PARTITION_SIZE_BOOTIMG} \
+ --vbmeta_image vbmeta.img
+ else
+ cp vbmeta.img ${IMAGE_DIR_BOOTIMG}/
+ fi
+ fi
+ fi
+ else
+ exit 0
+ fi
+}
+
+python do_avb_sign_img() {
+ import xml.dom.minidom
+ import math
+ secure_boot_type = d.getVar('SECURE_BOOT_TYPE', True)
+ if secure_boot_type != "avb":
+ return
+ bootdev_type = d.getVar('BOOTDEV_TYPE', True)
+
+ deploy_path = d.getVar('DEPLOY_DIR_IMAGE',True)
+ for file in os.listdir(deploy_path):
+ if os.path.splitext(file)[1] == '.xml':
+ partition_path = os.path.join(deploy_path,file)
+ root = xml.dom.minidom.parse(partition_path)
+ for partition in root.childNodes:
+ if partition.nodeName == "partition":
+ break
+ lbs = partition.getAttribute("lbs")
+ lbs = lbs and eval(lbs) or 512
+ for node in partition.childNodes:
+ if node.nodeName != "entry":
+ continue
+ start = eval(node.getAttribute("start"))
+ end = eval(node.getAttribute("end"))
+ name = node.getAttribute("name")
+ size = (end-start+1)*lbs
+ #0.92=62/64 *0.95
+ if (bootdev_type == 'nand'):
+ size = math.ceil(size*0.92/4096)*4096
+ if name == "BOOTIMG" or name.startswith("boot"):
+ d.setVar('PARTITION_SIZE_BOOTIMG', str(size))
+ if name == "ROOTFS" or name.startswith("system"):
+ d.setVar('PARTITION_SIZE_ROOTFS', str(size))
+ bb.build.exec_func('exec_avbtool', d)
+}
+
+addtask avb_sign_img after do_image_complete before do_build
diff --git a/meta/meta-mediatek/classes/bl33-fitimage.bbclass b/meta/meta-mediatek/classes/bl33-fitimage.bbclass
new file mode 100644
index 0000000..b76f755
--- /dev/null
+++ b/meta/meta-mediatek/classes/bl33-fitimage.bbclass
@@ -0,0 +1,150 @@
+inherit hsm-sign-env
+
+python __anonymous () {
+ depends = d.getVar("DEPENDS", True)
+ depends = "%s u-boot-mkimage-native lz4-native" % depends
+ d.setVar("DEPENDS", depends)
+}
+
+#
+# Emit the fitImage ITS header
+#
+fitimage_emit_fit_header() {
+ cat << EOF >> ${WORKDIR}/fit-image.its
+/dts-v1/;
+
+/ {
+ description = "BL33 fitImage";
+ #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
+}
+
+fitimage_emit_section_bl33() {
+
+ if [ -n "${IMAGE_HASH_ALGO}" ] ; then
+ bl33_csum="${IMAGE_HASH_ALGO}"
+ else
+ bl33_csum="sha256"
+ fi
+
+ cat << EOF >> ${WORKDIR}/fit-image.its
+ bl33@1 {
+ description = "LK based BL33 Image";
+ data = /incbin/("${1}");
+ type = "kernel";
+ arch = "arm";
+ os = "linux";
+ compression = "${2}";
+ load = <${BL33_LOADADDRESS}>;
+ entry = <${BL33_ENTRYPOINT}>;
+ hash@1 {
+ algo = "${bl33_csum}";
+ };
+ };
+EOF
+}
+
+#
+# Emit the fitImage ITS configuration section
+#
+fitimage_emit_section_config() {
+
+ if [ -n "${VB_HASH_ALGO}" ] && [ -n "${VB_RSA_ALGO}" ] ; then
+ conf_csum="${VB_HASH_ALGO},${VB_RSA_ALGO}"
+ else
+ conf_csum="sha256,rsa2048"
+ fi
+ conf_key_name="dev"
+
+ conf_desc="${MTK_PROJECT} configuration"
+
+ cat << EOF >> ${WORKDIR}/fit-image.its
+ default = "conf@1";
+ conf@1 {
+ description = "${conf_desc}";
+ kernel = "bl33@1";
+ signature@1 {
+ algo = "${conf_csum}";
+ key-name-hint="${conf_key_name}";
+ sign-images = "kernel";
+ };
+ };
+EOF
+}
+
+do_assemble_fitimage() {
+
+ rm -f ${WORKDIR}/fit-image.its
+
+ fitimage_emit_fit_header
+
+ #
+ # Step 1: Prepare a bl33 image section.
+ #
+ fitimage_emit_section_maint imagestart
+
+
+ fitimage_emit_section_bl33 ${BL33_OUT}/build-${BL33_PROJECT}/${BL33_BINARY} ${BL33_COMPRESS}
+
+ 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
+ #
+ ${HSM_ENV} HSM_KEY_NAME=${VERIFIED_KEY} uboot-mkimage -f ${WORKDIR}/fit-image.its ${WORKDIR}/${BL33_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
+ ${HSM_ENV} HSM_KEY_NAME=${VERIFIED_KEY} uboot-mkimage -D "-I dts -O dtb -p 1024" -k ./mykeys -f ${WORKDIR}/fit-image.its -r ${WORKDIR}/${BL33_IMAGE}
+ fi
+}
+
+addtask assemble_fitimage before do_deploy after do_compile
diff --git a/meta/meta-mediatek/classes/boot-ubifs.bbclass b/meta/meta-mediatek/classes/boot-ubifs.bbclass
new file mode 100644
index 0000000..7508234
--- /dev/null
+++ b/meta/meta-mediatek/classes/boot-ubifs.bbclass
@@ -0,0 +1,4 @@
+add_boot_image() {
+ install -d ${IMAGE_ROOTFS}/boot/
+ install ${DEPLOY_DIR_IMAGE}/boot.img ${IMAGE_ROOTFS}/boot/
+}
diff --git a/meta/meta-mediatek/classes/core-image-tiny.bbclass b/meta/meta-mediatek/classes/core-image-tiny.bbclass
new file mode 100644
index 0000000..78f22d2
--- /dev/null
+++ b/meta/meta-mediatek/classes/core-image-tiny.bbclass
@@ -0,0 +1,67 @@
+# Common code for generating core reference images
+#
+# Copyright (C) 2007-2011 Linux Foundation
+
+LIC_FILES_CHKSUM = "file://${COREBASE}/LICENSE;md5=4d92cd373abda3937c2bc47fbc49d690 \
+ file://${COREBASE}/meta/COPYING.MIT;md5=3da9cfbcb788c80a0384361b4de20420"
+
+# IMAGE_FEATURES control content of the core reference images
+#
+# By default we install packagegroup-core-boot and packagegroup-base-extended packages;
+# this gives us working (console only) rootfs.
+#
+# Available IMAGE_FEATURES:
+#
+# - x11 - X server
+# - x11-base - X server with minimal environment
+# - x11-sato - OpenedHand Sato environment
+# - tools-debug - debugging tools
+# - eclipse-debug - Eclipse remote debugging support
+# - tools-profile - profiling tools
+# - tools-testapps - tools usable to make some device tests
+# - tools-sdk - SDK (C/C++ compiler, autotools, etc.)
+# - nfs-server - NFS server
+# - nfs-client - NFS client
+# - ssh-server-dropbear - SSH server (dropbear)
+# - ssh-server-openssh - SSH server (openssh)
+# - hwcodecs - Install hardware acceleration codecs
+# - package-management - installs package management tools and preserves the package manager database
+# - debug-tweaks - makes an image suitable for development, e.g. allowing passwordless root logins
+# - dev-pkgs - development packages (headers, etc.) for all installed packages in the rootfs
+# - dbg-pkgs - debug symbol packages for all installed packages in the rootfs
+# - doc-pkgs - documentation packages for all installed packages in the rootfs
+# - ptest-pkgs - ptest packages for all ptest-enabled recipes
+# - read-only-rootfs - tweaks an image to support read-only rootfs
+#
+FEATURE_PACKAGES_x11 = "packagegroup-core-x11"
+FEATURE_PACKAGES_x11-base = "packagegroup-core-x11-base"
+FEATURE_PACKAGES_x11-sato = "packagegroup-core-x11-sato"
+FEATURE_PACKAGES_tools-debug = "packagegroup-core-tools-debug"
+FEATURE_PACKAGES_eclipse-debug = "packagegroup-core-eclipse-debug"
+FEATURE_PACKAGES_tools-profile = "packagegroup-core-tools-profile"
+FEATURE_PACKAGES_tools-testapps = "packagegroup-core-tools-testapps"
+FEATURE_PACKAGES_tools-sdk = "packagegroup-core-sdk packagegroup-core-standalone-sdk-target"
+FEATURE_PACKAGES_nfs-server = "packagegroup-core-nfs-server"
+FEATURE_PACKAGES_nfs-client = "packagegroup-core-nfs-client"
+FEATURE_PACKAGES_ssh-server-dropbear = "packagegroup-core-ssh-dropbear"
+FEATURE_PACKAGES_ssh-server-openssh = "packagegroup-core-ssh-openssh"
+FEATURE_PACKAGES_hwcodecs = "${MACHINE_HWCODECS}"
+
+
+# IMAGE_FEATURES_REPLACES_foo = 'bar1 bar2'
+# Including image feature foo would replace the image features bar1 and bar2
+IMAGE_FEATURES_REPLACES_ssh-server-openssh = "ssh-server-dropbear"
+
+# IMAGE_FEATURES_CONFLICTS_foo = 'bar1 bar2'
+# An error exception would be raised if both image features foo and bar1(or bar2) are included
+
+MACHINE_HWCODECS ??= ""
+
+CORE_IMAGE_BASE_INSTALL = '\
+ '
+
+CORE_IMAGE_EXTRA_INSTALL ?= ""
+
+IMAGE_INSTALL ?= "${CORE_IMAGE_BASE_INSTALL}"
+
+inherit image
diff --git a/meta/meta-mediatek/classes/create-link.bbclass b/meta/meta-mediatek/classes/create-link.bbclass
new file mode 100644
index 0000000..42226f5
--- /dev/null
+++ b/meta/meta-mediatek/classes/create-link.bbclass
@@ -0,0 +1,5 @@
+soft_link_to_rootfs() {
+ ln -nfs ${IMAGE_NAME}.rootfs.${IMAGE_FSTYPES} ${DEPLOY_DIR_IMAGE}/system.${IMAGE_FSTYPES}
+}
+
+ROOTFS_POSTPROCESS_COMMAND += " soft_link_to_rootfs;"
diff --git a/meta/meta-mediatek/classes/create-mtdverity.bbclass b/meta/meta-mediatek/classes/create-mtdverity.bbclass
new file mode 100644
index 0000000..e4a3fdb
--- /dev/null
+++ b/meta/meta-mediatek/classes/create-mtdverity.bbclass
@@ -0,0 +1,28 @@
+MTDVERITY_TOOL_DIR="${TOPDIR}/../src/devtools/nfsb/mtd_verity"
+MTDVERITY_TOOL="${MTDVERITY_TOOL_DIR}/mtd_verity"
+MTDVERITY_WORKING_PATH="${DEPLOY_DIR_IMAGE}"
+OLD_ROOTFS_NAME="${IMAGE_NAME}.rootfs.${IMAGE_FSTYPES}"
+NEW_ROOTFS_NAME="mtdverity_system.${IMAGE_FSTYPES}"
+IMG_KEY_FILE = "${MTK_KEY_DIR}/${VERIFIED_KEY}.pem"
+
+do_mtdverity_for_rootfs() {
+
+ if [ "${SECURE_BOOT_ENABLE}" = "yes" ] && [ "${ENABLE_ROOTFS_CHECK}" = "yes" ]; then
+ if [ "${STANDALONE_SIGN_PREPARE}" = "yes" ];then
+ exit 0
+ fi
+ if [ ! -f ${MTDVERITY_WORKING_PATH}/${OLD_ROOTFS_NAME} ]; then
+ cp ${MTDVERITY_WORKING_PATH}/${IMAGE_BASENAME}-${MACHINE}.${IMAGE_FSTYPES} ${MTDVERITY_WORKING_PATH}/${OLD_ROOTFS_NAME}
+ fi
+ ${MTDVERITY_TOOL} ${MTDVERITY_WORKING_PATH}/${OLD_ROOTFS_NAME} 1048576 1048576 10 ${IMG_KEY_FILE} ${MTDVERITY_WORKING_PATH}/${NEW_ROOTFS_NAME}
+ rm -f ${MTDVERITY_WORKING_PATH}/${OLD_ROOTFS_NAME}
+ mv ${MTDVERITY_WORKING_PATH}/${NEW_ROOTFS_NAME} ${MTDVERITY_WORKING_PATH}/${OLD_ROOTFS_NAME}
+ else
+ exit 0
+ fi
+}
+
+addtask mtdverity_for_rootfs after do_image_complete before do_packing_images_post_funcs
+do_rootfs[nostamp] = "1"
+
+#IMAGE_POSTPROCESS_COMMAND += " add_mtdverity_for_rootfs;"
diff --git a/meta/meta-mediatek/classes/create-nfsb.bbclass b/meta/meta-mediatek/classes/create-nfsb.bbclass
new file mode 100644
index 0000000..5ac50d8
--- /dev/null
+++ b/meta/meta-mediatek/classes/create-nfsb.bbclass
@@ -0,0 +1,87 @@
+NFSBVERITY="/sbin/veritysetup"
+NFSB_TOOLS_DIR="${TOPDIR}/../src/devtools/nfsb"
+MKNFSBIMG="${NFSB_TOOLS_DIR}/mknfsbimg3"
+ZERO_PADDING_TOOL="${NFSB_TOOLS_DIR}/zero_padding.sh"
+NFSB_WORKING_PATH="${IMGDEPLOYDIR}"
+NFSB_BLOCK_SIZE="1024"
+OLD_ROOTFS_NAME="${IMAGE_NAME}.rootfs.${IMAGE_FSTYPES}"
+OLD_RECOVERY_ROOTFS_NAME="recovery.${IMAGE_FSTYPES}"
+NEW_ROOTFS_NAME="nfsb_rootfs.${IMAGE_FSTYPES}"
+NEW_RECOVERY_ROOTFS_NAME = "tmp_recovery.${IMAGE_FSTYPES}"
+ZERO_PADDING_SIZE="1048576"
+KEY_FILE_MOD="${NFSB_TOOLS_DIR}/rsa.key.pub_out"
+KEY_FILE_PRI="${NFSB_TOOLS_DIR}/rsa.key.pri_out"
+DST_IMG_KEY_FILE = "${TOPDIR}/../src/devtools/nfsb/rsa.key"
+
+add_nfsb_for_rootfs() {
+
+ mod_key=""
+ pri_key=""
+ SRC_IMG_KEY_FILE=""
+ DM_VERITY_ALG=""
+
+ if [ "${STANDALONE_SIGN_PREPARE}" = "yes" ]; then
+ exit 0
+ fi
+
+ if [ "${ROOTFS_VERITY_KEY}" = "" ]; then
+ SRC_IMG_KEY_FILE="${MTK_KEY_DIR}/${VERIFIED_KEY}.pem"
+ else
+ SRC_IMG_KEY_FILE="${MTK_KEY_DIR}/${ROOTFS_VERITY_KEY}.pem"
+ fi
+
+ if [ "${DM_NFSB_HASH_ALG}" = "" ]; then
+ DM_VERITY_ALG="md5"
+ else
+ DM_VERITY_ALG="${DM_NFSB_HASH_ALG}"
+ fi
+
+ #backwards compatible for FORCE_DISABLE_DM_VERITY which only for NFSB actually
+ if [ "${SECURE_BOOT_ENABLE}" = "yes" ] && [ "${SECURE_BOOT_TYPE}" = "" ]; then
+ ENABLE_DM_NFSB="yes"
+ fi
+ if [ "${FORCE_DISABLE_DM_VERITY}" = "yes" ]; then
+ ENABLE_DM_NFSB="no"
+ fi
+
+ if [ "${SECURE_BOOT_ENABLE}" = "yes" ] && [ "${ENABLE_DM_NFSB}" == "yes" ]; then
+ if [ -e ${KEY_FILE_MOD} ]; then
+ mod_key=${KEY_FILE_MOD}
+ pri_key=${KEY_FILE_PRI}
+ else
+ if [ -e ${SRC_IMG_KEY_FILE} ]; then
+ cp ${SRC_IMG_KEY_FILE} ${DST_IMG_KEY_FILE}
+ python ${TOPDIR}/../src/devtools/nfsb/pretreat-key.py ${TOPDIR} ${SRC_IMG_KEY_FILE}
+ mod_key=${KEY_FILE_MOD}
+ pri_key=${KEY_FILE_PRI}
+ else
+ bbfatal "${KEY_FILE_MOD} does not exist!"
+ fi
+ fi
+ else
+ exit 0
+ fi
+
+ ${NFSBVERITY} --hash=${DM_VERITY_ALG} --no-superblock --data-block-size=${NFSB_BLOCK_SIZE} --hash-block-size=${NFSB_BLOCK_SIZE} format ${NFSB_WORKING_PATH}/${OLD_ROOTFS_NAME} ${NFSB_WORKING_PATH}/rootfs_hashes | tee ${NFSB_WORKING_PATH}/rootfs_table
+ ${MKNFSBIMG} ${NFSB_WORKING_PATH}/${OLD_ROOTFS_NAME} ${NFSB_WORKING_PATH}/rootfs_hashes ${NFSB_WORKING_PATH}/${NEW_ROOTFS_NAME} ${NFSB_WORKING_PATH}/rootfs_table ${mod_key} ${pri_key};
+ rm -f ${NFSB_WORKING_PATH}/${OLD_ROOTFS_NAME}
+ mv ${NFSB_WORKING_PATH}/${NEW_ROOTFS_NAME} ${NFSB_WORKING_PATH}/${OLD_ROOTFS_NAME}
+ ${ZERO_PADDING_TOOL} ${NFSB_WORKING_PATH}/${OLD_ROOTFS_NAME} ${ZERO_PADDING_SIZE}
+ rm -f ${NFSB_WORKING_PATH}/rootfs_hashes
+ rm -f ${NFSB_WORKING_PATH}/rootfs_table
+
+ if [ -e ${NFSB_WORKING_PATH}/${OLD_RECOVERY_ROOTFS_NAME} ]; then
+ ${NFSBVERITY} --hash=md5 --no-superblock --data-block-size=${NFSB_BLOCK_SIZE} --hash-block-size=${NFSB_BLOCK_SIZE} format ${NFSB_WORKING_PATH}/${OLD_RECOVERY_ROOTFS_NAME} ${NFSB_WORKING_PATH}/recovery_rootfs_hashes | tee ${NFSB_WORKING_PATH}/recovery_rootfs_table
+ ${MKNFSBIMG} ${NFSB_WORKING_PATH}/${OLD_RECOVERY_ROOTFS_NAME} ${NFSB_WORKING_PATH}/recovery_rootfs_hashes ${NFSB_WORKING_PATH}/${NEW_RECOVERY_ROOTFS_NAME} ${NFSB_WORKING_PATH}/recovery_rootfs_table ${mod_key} ${pri_key};
+ rm -f ${NFSB_WORKING_PATH}/${OLD_RECOVERY_ROOTFS_NAME}
+ mv ${NFSB_WORKING_PATH}/${NEW_RECOVERY_ROOTFS_NAME} ${NFSB_WORKING_PATH}/${OLD_RECOVERY_ROOTFS_NAME}
+ ${ZERO_PADDING_TOOL} ${NFSB_WORKING_PATH}/${OLD_RECOVERY_ROOTFS_NAME} ${ZERO_PADDING_SIZE}
+ rm -f ${NFSB_WORKING_PATH}/recovery_rootfs_hashes
+ rm -f ${NFSB_WORKING_PATH}/recovery_rootfs_table
+ fi
+
+ rm -f ${mod_key}
+ rm -f ${pri_key}
+}
+
+IMAGE_POSTPROCESS_COMMAND += " add_nfsb_for_rootfs;"
diff --git a/meta/meta-mediatek/classes/create-sparse-image.bbclass b/meta/meta-mediatek/classes/create-sparse-image.bbclass
new file mode 100644
index 0000000..f19feb0
--- /dev/null
+++ b/meta/meta-mediatek/classes/create-sparse-image.bbclass
@@ -0,0 +1,13 @@
+DEPENDS += "android-tools-fsutils-native"
+
+do_sparse_image() {
+# Usage: img2simg <raw_image_file> <sparse_image_file> [<block_size>]
+if test -e ${IMGDEPLOYDIR}/${IMAGE_NAME}.rootfs.${IMAGE_FSTYPES} ; then
+ img2simg ${IMGDEPLOYDIR}/${IMAGE_NAME}.rootfs.${IMAGE_FSTYPES} ${DEPLOY_DIR_IMAGE}/system.img
+ if test -e ${DEPLOY_DIR_IMAGE}/sign_rootfs ; then
+ rm -rf ${DEPLOY_DIR_IMAGE}/sign_rootfs
+ fi
+fi
+}
+
+do_image_complete[postfuncs] += "do_sparse_image"
diff --git a/meta/meta-mediatek/classes/depends-systemd.bbclass b/meta/meta-mediatek/classes/depends-systemd.bbclass
new file mode 100644
index 0000000..8738279
--- /dev/null
+++ b/meta/meta-mediatek/classes/depends-systemd.bbclass
@@ -0,0 +1,5 @@
+
+python() {
+ d.appendVarFlag('do_cleansstate', 'depends', ' systemd:do_cleansstate')
+ d.appendVarFlag('do_compile', 'depends', ' systemd:do_compile')
+}
diff --git a/meta/meta-mediatek/classes/features_check.bbclass b/meta/meta-mediatek/classes/features_check.bbclass
new file mode 100644
index 0000000..876d32e
--- /dev/null
+++ b/meta/meta-mediatek/classes/features_check.bbclass
@@ -0,0 +1,88 @@
+# Allow checking of required and conflicting DISTRO_FEATURES
+#
+# ANY_OF_DISTRO_FEATURES: ensure at least one item on this list is included
+# in DISTRO_FEATURES.
+# REQUIRED_DISTRO_FEATURES: ensure every item on this list is included
+# in DISTRO_FEATURES.
+# CONFLICT_DISTRO_FEATURES: ensure no item in this list is included in
+# DISTRO_FEATURES.
+# ANY_OF_MACHINE_FEATURES: ensure at least one item on this list is included
+# in MACHINE_FEATURES.
+# REQUIRED_MACHINE_FEATURES: ensure every item on this list is included
+# in MACHINE_FEATURES.
+# CONFLICT_MACHINE_FEATURES: ensure no item in this list is included in
+# MACHINE_FEATURES.
+# ANY_OF_COMBINED_FEATURES: ensure at least one item on this list is included
+# in COMBINED_FEATURES.
+# REQUIRED_COMBINED_FEATURES: ensure every item on this list is included
+# in COMBINED_FEATURES.
+# CONFLICT_COMBINED_FEATURES: ensure no item in this list is included in
+# COMBINED_FEATURES.
+#
+# Copyright 2019 (C) Texas Instruments Inc.
+# Copyright 2013 (C) O.S. Systems Software LTDA.
+
+python () {
+ if d.getVar('PARSE_ALL_RECIPES', False):
+ return
+
+ # Assume at least one var is set.
+ distro_features = set((d.getVar('DISTRO_FEATURES') or '').split())
+
+ any_of_distro_features = set((d.getVar('ANY_OF_DISTRO_FEATURES') or '').split())
+ if any_of_distro_features:
+ if set.isdisjoint(any_of_distro_features, distro_features):
+ raise bb.parse.SkipRecipe("one of '%s' needs to be in DISTRO_FEATURES" % ' '.join(any_of_distro_features))
+
+ required_distro_features = set((d.getVar('REQUIRED_DISTRO_FEATURES') or '').split())
+ if required_distro_features:
+ missing = set.difference(required_distro_features, distro_features)
+ if missing:
+ raise bb.parse.SkipRecipe("missing required distro feature%s '%s' (not in DISTRO_FEATURES)" % ('s' if len(missing) > 1 else '', ' '.join(missing)))
+
+ conflict_distro_features = set((d.getVar('CONFLICT_DISTRO_FEATURES') or '').split())
+ if conflict_distro_features:
+ conflicts = set.intersection(conflict_distro_features, distro_features)
+ if conflicts:
+ raise bb.parse.SkipRecipe("conflicting distro feature%s '%s' (in DISTRO_FEATURES)" % ('s' if len(conflicts) > 1 else '', ' '.join(conflicts)))
+
+ # Assume at least one var is set.
+ machine_features = set((d.getVar('MACHINE_FEATURES') or '').split())
+
+ any_of_machine_features = set((d.getVar('ANY_OF_MACHINE_FEATURES') or '').split())
+ if any_of_machine_features:
+ if set.isdisjoint(any_of_machine_features, machine_features):
+ raise bb.parse.SkipRecipe("one of '%s' needs to be in MACHINE_FEATURES" % ' '.join(any_of_machine_features))
+
+ required_machine_features = set((d.getVar('REQUIRED_MACHINE_FEATURES') or '').split())
+ if required_machine_features:
+ missing = set.difference(required_machine_features, machine_features)
+ if missing:
+ raise bb.parse.SkipRecipe("missing required machine feature%s '%s' (not in MACHINE_FEATURES)" % ('s' if len(missing) > 1 else '', ' '.join(missing)))
+
+ conflict_machine_features = set((d.getVar('CONFLICT_MACHINE_FEATURES') or '').split())
+ if conflict_machine_features:
+ conflicts = set.intersection(conflict_machine_features, machine_features)
+ if conflicts:
+ raise bb.parse.SkipRecipe("conflicting machine feature%s '%s' (in MACHINE_FEATURES)" % ('s' if len(conflicts) > 1 else '', ' '.join(conflicts)))
+
+ # Assume at least one var is set.
+ combined_features = set((d.getVar('COMBINED_FEATURES') or '').split())
+
+ any_of_combined_features = set((d.getVar('ANY_OF_COMBINED_FEATURES') or '').split())
+ if any_of_combined_features:
+ if set.isdisjoint(any_of_combined_features, combined_features):
+ raise bb.parse.SkipRecipe("one of '%s' needs to be in COMBINED_FEATURES" % ' '.join(any_of_combined_features))
+
+ required_combined_features = set((d.getVar('REQUIRED_COMBINED_FEATURES') or '').split())
+ if required_combined_features:
+ missing = set.difference(required_combined_features, combined_features)
+ if missing:
+ raise bb.parse.SkipRecipe("missing required machine feature%s '%s' (not in COMBINED_FEATURES)" % ('s' if len(missing) > 1 else '', ' '.join(missing)))
+
+ conflict_combined_features = set((d.getVar('CONFLICT_COMBINED_FEATURES') or '').split())
+ if conflict_combined_features:
+ conflicts = set.intersection(conflict_combined_features, combined_features)
+ if conflicts:
+ raise bb.parse.SkipRecipe("conflicting machine feature%s '%s' (in COMBINED_FEATURES)" % ('s' if len(conflicts) > 1 else '', ' '.join(conflicts)))
+}
diff --git a/meta/meta-mediatek/classes/fsck-image.bbclass b/meta/meta-mediatek/classes/fsck-image.bbclass
new file mode 100644
index 0000000..79f0a60
--- /dev/null
+++ b/meta/meta-mediatek/classes/fsck-image.bbclass
@@ -0,0 +1,9 @@
+
+do_fsck_image_pre_funcs() {
+ cp ${IMGDEPLOYDIR}/${IMAGE_NAME}.rootfs.${IMAGE_FSTYPES} ${DEPLOY_DIR_IMAGE}/rootfs.${IMAGE_FSTYPES}
+ ${STAGING_DIR_NATIVE}${base_sbindir}/fsck.ext4 -f -y ${DEPLOY_DIR_IMAGE}/rootfs.${IMAGE_FSTYPES} || :
+ ${STAGING_DIR_NATIVE}${base_sbindir}/fsck.ext4 -f -y ${DEPLOY_DIR_IMAGE}/rootfs.${IMAGE_FSTYPES}
+}
+
+do_image_complete[prefuncs] += "do_fsck_image_pre_funcs"
+
diff --git a/meta/meta-mediatek/classes/get_toolchain_name.bbclass b/meta/meta-mediatek/classes/get_toolchain_name.bbclass
new file mode 100644
index 0000000..a31562d
--- /dev/null
+++ b/meta/meta-mediatek/classes/get_toolchain_name.bbclass
@@ -0,0 +1 @@
+TOOLCHAIN_NAME = "${@bb.utils.contains('TOOLCHAIN','clang','clang','gcc',d)}"
diff --git a/meta/meta-mediatek/classes/hsm-sign-env.bbclass b/meta/meta-mediatek/classes/hsm-sign-env.bbclass
new file mode 100644
index 0000000..4259bc1
--- /dev/null
+++ b/meta/meta-mediatek/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/classes/kernel-fitimage-extension.bbclass b/meta/meta-mediatek/classes/kernel-fitimage-extension.bbclass
new file mode 100644
index 0000000..95ea635
--- /dev/null
+++ b/meta/meta-mediatek/classes/kernel-fitimage-extension.bbclass
@@ -0,0 +1,275 @@
+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() {
+
+ if [ -n "${IMAGE_HASH_ALGO}" ] ; then
+ kernel_csum="${IMAGE_HASH_ALGO}"
+ else
+ kernel_csum="sha256"
+ fi
+
+ ENTRYPOINT=${UBOOT_ENTRYPOINT}
+ if [ -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() {
+
+ if [ -n "${IMAGE_HASH_ALGO}" ] ; then
+ dtb_csum="${IMAGE_HASH_ALGO}"
+ else
+ dtb_csum="sha256"
+ fi
+
+ 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() {
+
+ if [ -n "${VB_HASH_ALGO}" -a -n "${VB_RSA_ALGO}" ] ; then
+ conf_csum="${VB_HASH_ALGO},${VB_RSA_ALGO}"
+ else
+ conf_csum="sha256,rsa2048"
+ fi
+ 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 [ "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 [ -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" -a "${STANDALONE_SIGN_PREPARE}" != "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_kernelmodules
+
+kernel_do_deploy[vardepsexclude] = "DATETIME"
+kernel_do_deploy_append() {
+ # Update deploy directory
+ if [ "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 [ -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_NAME}.bin boot.img
+ fi
+}
diff --git a/meta/meta-mediatek/classes/kernel-uboot-extension.bbclass b/meta/meta-mediatek/classes/kernel-uboot-extension.bbclass
new file mode 100644
index 0000000..fc93a28
--- /dev/null
+++ b/meta/meta-mediatek/classes/kernel-uboot-extension.bbclass
@@ -0,0 +1,49 @@
+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
+ # Use 32-Bit kernel's compression method since
+ # it's is a kind of self-extracting executable.
+ if test -f "arch/arm/boot/compressed/vmlinux"; then
+ vmlinux_path="arch/arm/boot/compressed/vmlinux"
+ fi
+ 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/classes/lk-image.bbclass b/meta/meta-mediatek/classes/lk-image.bbclass
new file mode 100644
index 0000000..f7e0ec6
--- /dev/null
+++ b/meta/meta-mediatek/classes/lk-image.bbclass
@@ -0,0 +1,499 @@
+inherit hsm-sign-env
+
+python __anonymous () {
+ depends = d.getVar("DEPENDS", True)
+ depends = "%s u-boot-mkimage-native dtc-native openssl-native" % depends
+ d.setVar("DEPENDS", depends)
+}
+
+# split input string to multiple quadbyte word (with 0x prefix for each word)
+# input:
+# $1: input string, e.g., 0123456789ABCDEF...
+# $2: "swap", to do byte swap in each quadbyte; otherwise, no swap
+# output:
+# standard output: 0x67452301 0xEFCDAB89 ... if $2 = "swap"
+# 0x01234567 0x89ABCDEF ... otherwise
+split_str_to_quadbytes() {
+ quadbytes=""
+
+ if [ $2 = "swap" ]; then
+ sed_cmd="sed s,\(..\)\(..\)\(..\)\(..\),\4\3\2\1,g"
+ else
+ sed_cmd="sed s,\(..\)\(..\)\(..\)\(..\),\1\2\3\4,g"
+ fi
+
+ if [ ! -z "$1" ]; then
+ for i in $(seq 1 8 ${#1}); do
+ end_idx=`echo "${i} + 7" | bc`
+ qb=`echo ${1} | cut -c${i}-${end_idx} | ${sed_cmd}`
+ quadbytes="${quadbytes} 0x${qb}"
+ done
+ # trim leading space
+ awk '{$quadbytes=$quadbytes};1'
+ fi
+
+ echo $quadbytes
+}
+
+# Emit fit header
+# input param:
+# $1: fit its
+fitimage_emit_fit_header() {
+ cat << EOF >> $1
+/dts-v1/;
+
+/ {
+ description = "bl";
+ #address-cells = <1>;
+EOF
+}
+
+# Emit the fitimage image section
+# input param:
+# $1: fit its
+# $2: path to padding binary
+# $3: path to lk binary
+# $4: lk load address
+# $5: lk entry address
+# $6: hash algorithm
+fitimage_emit_fit_image_section() {
+ cat << EOF >> $1
+
+ images {
+ bl@1 {
+ description = "bl";
+ padding = /incbin/("${2}");
+ data = /incbin/("${3}");
+ type = "kernel";
+ compression = "none";
+ load = <${4}>;
+ entry = <${5}>;
+ hash@1 {
+ algo = "${6}";
+ };
+ };
+ };
+EOF
+}
+
+# Emit fitimage configuration section
+# input param:
+# $1: fit its
+# $2: hash algorithm
+# $3: rsa algorithm
+# $4: key name hint
+# $5: aes iv
+fitimage_emit_fit_conf_section() {
+ if [ "${ACK_EN}" = "yes" ]; then
+ # split aes iv to N 32-bit words
+ quadbytes=$(split_str_to_quadbytes ${5} noswap)
+ ack_iv_prop="ack_iv = <${quadbytes}>;"
+ else
+ ack_iv_prop=
+ fi
+
+ cat << EOF >> $1
+
+ configurations {
+ default = "conf@1";
+ conf@1 {
+ description = "bl";
+ kernel = "bl@1";
+ ${ack_iv_prop}
+ signature@1 {
+ algo = "${2},${3}";
+ key-name-hint = "${4}";
+ sign-images = "kernel";
+ };
+ };
+ };
+EOF
+}
+
+# Emit fitimage trusted-key-certificate oem section
+# input param:
+# $1: fit its
+fitimage_emit_fit_tkc_oem_section() {
+ cat << EOF >> $1
+
+ trusted-key-certificate {
+ sign-node {
+ device-check = "skip-device-id-check";
+ device-id = "N0cI//dxndWXnsh11WzSKG9tPPfs";
+ trusted-key {
+ key-name-hint = "TierPubKey";
+ };
+ };
+ };
+EOF
+}
+
+# Emit fitimage trusted-key-certificate tier section
+# input param:
+# $1: fit its
+# $2: TKC.dtsi
+fitimage_emit_fit_tkc_tier_section() {
+ cat << EOF >> $1
+
+ /include/ "$2"
+EOF
+}
+
+# Emit fitimage fit end
+# input param:
+# $1: fit its
+fitimage_emit_fit_end() {
+ cat << EOF >> $1
+};
+EOF
+}
+
+# get_fit_data_offset: get data offset from fit image
+# input param:
+# $1: fit image
+get_fit_data_offset() {
+ FIT_IMAGE=$1
+
+ TMPF=$(mktemp ${WORKDIR}/dump-fit-img.XXXXXX)
+
+ # dump fit image
+ fdtdump -d ${FIT_IMAGE} > ${TMPF}
+
+ # get props
+ LINE=$(grep -n '^ *data' ${TMPF} | grep -o '^[0-9]*')
+ LINE=`expr ${LINE} - 1`
+ ADDR=$(grep -n "^// [[:xdigit:]]*: value" ${TMPF} | grep "^${LINE}://" | \
+ grep -o " [[:xdigit:]]*" | grep -o "[[:xdigit:]]*")
+
+ # remove temp files
+ rm -f ${TMPF}
+
+ echo ${ADDR}
+}
+
+# check_fit_image: check fit image and also check load/entry address if 2nd
+# param was present
+# input param:
+# $1: fit image
+# $2: if present, will also check load and entry validity
+check_fit_image() {
+ FIT_IMAGE=$1
+ CHECK_OPT=$2
+
+ # check default cfg
+ CFG=$(fdtget ${FIT_IMAGE} /configurations default)
+ if [ "${CFG}" = "" ]; then
+ echo "ERROR: no default in /configurations"
+ exit 1
+ fi
+
+ # check image name
+ IMG_NAME=$(fdtget ${FIT_IMAGE} /configurations/${CFG} kernel)
+ if [ "${IMG_NAME}" = "" ]; then
+ echo "ERROR: no image name (kernel prop) in /configurations/${CFG}"
+ exit 1
+ fi
+
+ # check data
+ DATA=$(fdtget ${FIT_IMAGE} /images/${IMG_NAME} data)
+ if [ "${DATA}" = "" ]; then
+ echo "ERROR: no data in /images/${IMG_NAME}"
+ exit 1
+ fi
+
+ # check load
+ LOAD_D=$(fdtget ${FIT_IMAGE} /images/${IMG_NAME} load)
+ if [ "$LOAD_D" = "" ]; then
+ echo "ERROR: no load in /images/${IMG_NAME}"
+ exit 1
+ fi
+
+ # check entry
+ ENTRY_D=$(fdtget ${FIT_IMAGE} /images/${IMG_NAME} entry)
+ if [ "$ENTRY_D" = "" ]; then
+ echo "ERROR: no entry in /images/${IMG_NAME}"
+ exit 1
+ fi
+
+ if [ "${CHECK_OPT}" != "" ]; then
+ OFFSET=$(get_fit_data_offset ${FIT_IMAGE})
+ LOAD=$(printf "%x" ${LOAD_D})
+ if [ "`expr ${LOAD} : '.*\(....\)'`" != "${OFFSET}" ]; then
+ echo ERROR: load ${LOAD} is not align with data offset ${OFFSET}
+ exit 1
+ fi
+
+ LEN=$(echo ${DATA} | wc -w)
+ ENTRY=$(printf "%x" ${ENTRY_D})
+ END_D=`echo "${LOAD_D} + ${LEN} * 4" | bc`
+ END=$(printf "%x" ${END_D})
+ if [ ${ENTRY_D} -lt ${LOAD_D} -o ${END_D} -le ${ENTRY_D} ]; then
+ echo ERROR: entry ${ENTRY} is not in data ${LOAD} - ${END}
+ exit 1
+ fi
+ fi
+}
+
+# generate fit image: generate lk image in fit format
+# input param:
+# $1: fit image its file
+# $2: key dir
+# $3: output file
+gen_fit_image() {
+ FIT_ITS=$1
+ KEYDIR=$2
+ OUT=$3
+ DTB=$(mktemp ${WORKDIR}/dtb.XXXXXX)
+ KEYDTSI=$(mktemp ${WORKDIR}/key.XXXXXX.dtsi)
+ KEYITS=$(mktemp ${WORKDIR}/key-fit-image.XXXXXX.its)
+
+ if [ "${SBC_SIGN_ALGO}" = "ecc" ]; then
+ case "${SBC_ECC_ALGO}" in
+ nistp256)
+ HSM_SBC_KEY=${SBC_KEY_ECC256}
+ ;;
+ nistp384)
+ HSM_SBC_KEY=${SBC_KEY_ECC384}
+ ;;
+ nistp521)
+ HSM_SBC_KEY=${SBC_KEY_ECC521}
+ ;;
+ *)
+ echo ${SBC_ECC_ALGO} ": not supported."
+ exit 1
+ ;;
+ esac
+ else
+ case "${SBC_RSA_ALGO}" in
+ rsa2048 | rsassa-pss2048)
+ HSM_SBC_KEY=${SBC_KEY}
+ ;;
+ rsa3072 | rsassa-pss3072)
+ HSM_SBC_KEY=${SBC_KEY_RSA3072}
+ ;;
+ rsa4096 | rsassa-pss4096)
+ HSM_SBC_KEY=${SBC_KEY_RSA4096}
+ ;;
+ *)
+ echo ${SBC_RSA_ALGO} ": not supported."
+ exit 1
+ ;;
+ esac
+ fi
+ echo "HSM_SBC_KEY name is ${HSM_SBC_KEY}"
+
+ echo "/dts-v1/; / {};" | dtc -O dtb > ${DTB}
+ if [ "${TKC_SUPPORT}" = "oem" ]; then
+ ${HSM_ENV} HSM_KEY_NAME=${HSM_SBC_KEY} ${FIT_IMG_TOOL} -f ${FIT_ITS} -k ${KEYDIR} -K ${DTB} -g ${TKC_PUBLIC_KEY_TIER} ${OUT}
+ elif [ "${TKC_SUPPORT}" = "tier" ]; then
+ ${HSM_ENV} HSM_KEY_NAME=${HSM_SBC_KEY} ${FIT_IMG_TOOL} -f ${FIT_ITS} -k ${KEYDIR} -K ${DTB} -u ${TKC_PUBLIC_KEY_OEM} ${OUT}
+ else
+ ${HSM_ENV} HSM_KEY_NAME=${HSM_SBC_KEY} ${FIT_IMG_TOOL} -f ${FIT_ITS} -k ${KEYDIR} -K ${DTB} ${OUT}
+ fi
+
+ dtc -I dtb ${DTB} | tail -n+2 > ${KEYDTSI}
+
+ sed "s,\/dts-v1\/;,\0\n\/include\/ \"${KEYDTSI}\"," < ${FIT_ITS} > ${KEYITS}
+ ${HSM_ENV} HSM_KEY_NAME=${HSM_SBC_KEY} ${FIT_IMG_TOOL} -f ${KEYITS} -k ${KEYDIR} ${OUT}
+
+ # remove temporary files
+ rm -f ${DTB} ${KEYDTSI} ${KEYITS}
+}
+
+# gen_sbc_key_hash
+# input param:
+# $1: fit image
+gen_sbc_key_hash() {
+ FDT_IMG=$1
+ TMP_FILE=$(mktemp ${WORKDIR}/col_rgn.XXXXXX.bin)
+
+ DEF_CONF=`fdtget -t s ${FDT_IMG} /configurations default`
+ SIG_NODE=`fdtget -l ${FDT_IMG} /configurations/${DEF_CONF}`
+ KEY_HINT=`fdtget -t s ${FDT_IMG} /configurations/${DEF_CONF}/${SIG_NODE} key-name-hint`
+ SHAX=`fdtget -t s ${FDT_IMG} /configurations/${DEF_CONF}/${SIG_NODE} algo | cut -d, -f1`
+ ${WORKDIR}/fit-lk/extract_region ${FDT_IMG} ${TMP_FILE} /signature/key-${KEY_HINT}
+ KEY_HASH=`${SHAX}sum ${TMP_FILE} | cut -d " " -f 1`
+ echo "Hash algo: ${SHAX}"
+ echo "key_hash: ${KEY_HASH}"
+
+ key_hash_str=$(split_str_to_quadbytes ${KEY_HASH} swap)
+
+ idx=0
+ for qb in $key_hash_str; do
+ echo "keyhash_${idx}: ${qb}"
+ idx=`echo "${idx} + 1" | bc`
+ done
+
+ rm -f ${TMP_FILE}
+}
+
+# print_aes_key_iv
+# $1: aes key
+# $2: aes iv
+print_aes_key_iv() {
+ # print aes keys
+ echo "AES_KEY(AC_KEY)=${1}"
+ quadbytes=$(split_str_to_quadbytes ${1} swap)
+ idx=0
+ for qb in $quadbytes; do
+ echo "AC_KEY${idx}: ${qb}"
+ idx=`echo "${idx} + 1" | bc`
+ done
+
+ # print aes iv
+ echo "AES_IV=${2}"
+ quadbytes=$(split_str_to_quadbytes ${2} noswap)
+ echo "prop ack_iv=<${quadbytes}>"
+}
+
+gen_lk_fit_header() {
+ # generate temp files
+ BL_BIN=$(mktemp ${WORKDIR}/bl.XXXXXX.bin)
+ FIT_LK_IMG=${WORKDIR}/fit-lk.img
+ FIT_ITS=$(mktemp ${WORKDIR}/fit-bl-image.XXXXXX.its)
+ KEYDIR=${WORKDIR}/lk-key
+ PADDING=$(mktemp ${WORKDIR}/padding.XXXXXX.bin)
+
+ if [ "${ACK_EN}" = "yes" ]; then
+ # output AES encrypted BL image to working directory
+ openssl enc -e -aes-128-cbc -in ${LK_OUT}/build-${LK_PROJECT}/${LK_BINARY} \
+ -out ${BL_BIN} -K ${AES_KEY} -iv ${AES_IV}
+ else
+ # copy raw lk binary to working directory
+ cp ${LK_OUT}/build-${LK_PROJECT}/${LK_BINARY} ${BL_BIN}
+ fi
+
+ # generate a zero-size padding binary
+ touch ${PADDING}
+
+ # prepare rsa key
+ mkdir -p ${KEYDIR}
+
+ if [ "${SBC_SIGN_ALGO}" = "ecc" ]; then
+ case "${SBC_ECC_ALGO}" in
+ nistp256)
+ cp -f ${MTK_KEY_DIR}/${SBC_KEY_ECC256}_priv.pem ${KEYDIR}/dev_priv.key
+ cp -f ${MTK_KEY_DIR}/${SBC_KEY_ECC256}_public.pem ${KEYDIR}/dev_public.key
+ ;;
+ nistp384)
+ cp -f ${MTK_KEY_DIR}/${SBC_KEY_ECC384}_priv.pem ${KEYDIR}/dev_priv.key
+ cp -f ${MTK_KEY_DIR}/${SBC_KEY_ECC384}_public.pem ${KEYDIR}/dev_public.key
+ ;;
+ nistp521)
+ cp -f ${MTK_KEY_DIR}/${SBC_KEY_ECC521}_priv.pem ${KEYDIR}/dev_priv.key
+ cp -f ${MTK_KEY_DIR}/${SBC_KEY_ECC521}_public.pem ${KEYDIR}/dev_public.key
+ ;;
+ *)
+ echo ${SBC_ECC_ALGO} ": not supported."
+ exit 1
+ ;;
+ esac
+ else
+ case "${SBC_RSA_ALGO}" in
+ rsa2048 | rsassa-pss2048)
+ cp -f ${MTK_KEY_DIR}/${SBC_KEY}.crt ${KEYDIR}/dev.crt
+ cp -f ${MTK_KEY_DIR}/${SBC_KEY}.pem ${KEYDIR}/dev.key
+ ;;
+ rsa3072 | rsassa-pss3072)
+ cp -f ${MTK_KEY_DIR}/${SBC_KEY_RSA3072}.crt ${KEYDIR}/dev.crt
+ cp -f ${MTK_KEY_DIR}/${SBC_KEY_RSA3072}.pem ${KEYDIR}/dev.key
+ ;;
+ rsa4096 | rsassa-pss4096)
+ cp -f ${MTK_KEY_DIR}/${SBC_KEY_RSA4096}.crt ${KEYDIR}/dev.crt
+ cp -f ${MTK_KEY_DIR}/${SBC_KEY_RSA4096}.pem ${KEYDIR}/dev.key
+ ;;
+ *)
+ echo ${SBC_RSA_ALGO} ": not supported."
+ exit 1
+ ;;
+ esac
+ fi
+
+ # key for trusted-key-certificate
+ if [ "${TKC_SUPPORT}" = "oem" ]; then
+ if [ "${SBC_SIGN_ALGO}" = "ecc" ]; then
+ cp -f ${MTK_KEY_DIR}/${TKC_PUBLIC_KEY_TIER}.pem ${KEYDIR}/tier_public.key
+ elif [ "${SBC_SIGN_ALGO}" = "rsa" ]; then
+ cp -f ${MTK_KEY_DIR}/${TKC_PUBLIC_KEY_TIER}.crt ${KEYDIR}/tier_public.crt
+ fi
+ elif [ "${TKC_SUPPORT}" = "tier" ]; then
+ if [ "${SBC_SIGN_ALGO}" = "ecc" ]; then
+ cp -f ${MTK_KEY_DIR}/${TKC_PUBLIC_KEY_OEM}.pem ${KEYDIR}/oem_public.key
+ elif [ "${SBC_SIGN_ALGO}" = "rsa" ]; then
+ cp -f ${MTK_KEY_DIR}/${TKC_PUBLIC_KEY_OEM}.crt ${KEYDIR}/oem_public.crt
+ fi
+ fi
+
+ # generate base its file
+ fitimage_emit_fit_header ${FIT_ITS}
+
+ # if TKC is supportted, place it here
+ if [ "${TKC_SUPPORT}" = "oem" ]; then
+ fitimage_emit_fit_tkc_oem_section ${FIT_ITS} ${SBC_HASH_ALGO} ${SBC_ECC_ALGO} dev
+ elif [ "${TKC_SUPPORT}" = "tier" ]; then
+ fitimage_emit_fit_tkc_tier_section ${FIT_ITS} ${MTK_KEY_DIR}/TKC.dtsi
+ fi
+
+ fitimage_emit_fit_image_section ${FIT_ITS} ${PADDING} ${BL_BIN} \
+ ${LK_LOADADDRESS} ${LK_ENTRYPOINT} ${IMAGE_HASH_ALGO}
+
+ if [ "${SBC_SIGN_ALGO}" = "ecc" ]; then
+ fitimage_emit_fit_conf_section ${FIT_ITS} ${SBC_HASH_ALGO} ${SBC_ECC_ALGO} dev ${AES_IV}
+ else
+ fitimage_emit_fit_conf_section ${FIT_ITS} ${SBC_HASH_ALGO} ${SBC_RSA_ALGO} dev ${AES_IV}
+ fi
+
+ fitimage_emit_fit_end ${FIT_ITS}
+
+ # 1st pass: generate fit-lk image to get padding size
+ gen_fit_image ${FIT_ITS} ${KEYDIR} ${FIT_LK_IMG}
+ check_fit_image ${FIT_LK_IMG}
+
+ # get data offset and calculate padding size
+ # padding size = lk load offset - data offset
+ DATA_OFFSET=$(get_fit_data_offset ${FIT_LK_IMG})
+ DATA_OFFSET_HEX=0x${DATA_OFFSET}
+ DATA_OFFSET_D=$(printf "%d" ${DATA_OFFSET_HEX})
+ LK_LOAD_OFFSET_D=$(printf "%d" ${LK_LOAD_OFFSET})
+ PADDING_SIZE=`echo "${LK_LOAD_OFFSET_D} - ${DATA_OFFSET_D}" | bc`
+
+ rm -f ${PADDING}
+ dd if=/dev/zero of=${PADDING} bs=1 count=${PADDING_SIZE}
+
+ # 2nd pass: generate final fit-lk image
+ gen_fit_image ${FIT_ITS} ${KEYDIR} ${FIT_LK_IMG}
+ check_fit_image ${FIT_LK_IMG} all
+
+ cp ${FIT_LK_IMG} ${WORKDIR}/${LK_IMAGE}
+
+ # gen key hash for convenience
+ gen_sbc_key_hash ${FIT_LK_IMG}
+
+ # output aes key and iv for reference
+ if [ "${ACK_EN}" = "yes" ]; then
+ print_aes_key_iv ${AES_KEY} ${AES_IV}
+ fi
+
+ # remove temp files
+ rm -f ${BL_BIN} ${FIT_ITS} ${PADDING}
+ rm -rf ${KEYDIR}
+}
+
+gen_lk_gfh_header() {
+ cp ${LK_OUT}/build-${LK_PROJECT}/${LK_BINARY} ${WORKDIR}/temp_gfh
+
+ if [ "${SECURE_BOOT_ENABLE}" = "yes" ]; then
+ cp ${MTK_KEY_DIR}/${SBC_KEY}.pem ${KEY_DIR}/root_prvk.pem
+ fi
+
+ python ${PBP_DIR}/pbp.py -g ${GFH_DIR}/${TARGET_PLATFORM}/gfh_conf.ini \
+ -i ${KEY_DIR}/lk_key.ini -func sign \
+ -o ${WORKDIR}/temp_gfh ${WORKDIR}/temp_gfh
+
+ if [ "${BOOTDEV_TYPE}" != "nand" ]; then
+ python ${DEV_INFO_HDR_TOOL} \
+ ${BOOTDEV_TYPE} ${WORKDIR}/temp_gfh ${WORKDIR}/${LK_IMAGE}
+ else
+ cp ${WORKDIR}/temp_gfh ${WORKDIR}/${LK_IMAGE}
+ fi
+}
diff --git a/meta/meta-mediatek/classes/make_ota_full-package.bbclass b/meta/meta-mediatek/classes/make_ota_full-package.bbclass
new file mode 100644
index 0000000..d1e64e8
--- /dev/null
+++ b/meta/meta-mediatek/classes/make_ota_full-package.bbclass
@@ -0,0 +1,66 @@
+DEPENDS += "android-tools-fsutils-native abtools-native"
+HOSTTOOLS += "zip unzip"
+PATH_prepend = "/usr/local/jdk1.8.0_161/bin:${STAGING_DIR_NATIVE}${datadir}/abtools/scripts:"
+
+AFTER_CMD = "${@bb.utils.contains("BOARD_AVB_ENABLE","true", "do_avb_sign_img","do_image_complete",d)}"
+
+do_make_otafull_package() {
+ if [ "${AB_OTA_UPDATER}" = "yes" ]; then
+ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:${STAGING_DIR_NATIVE}/usr/lib
+ rm -rf ${DEPLOY_DIR_IMAGE}/target-files
+ mkdir ${DEPLOY_DIR_IMAGE}/target-files
+ mkdir ${DEPLOY_DIR_IMAGE}/target-files/IMAGES
+ mkdir ${DEPLOY_DIR_IMAGE}/target-files/SYSTEM
+ mkdir ${DEPLOY_DIR_IMAGE}/target-files/META
+ cp ${STAGING_DIR_NATIVE}/../rootfs/etc/update_engine/build.prop ${DEPLOY_DIR_IMAGE}/target-files/SYSTEM/
+ cp ${STAGING_DIR_NATIVE}/../rootfs/etc/update_engine/update_engine.conf ${DEPLOY_DIR_IMAGE}/target-files/META/update_engine_config.txt
+
+ if test -e ${DEPLOY_DIR_IMAGE}/target-files/META/misc_info.txt; then
+ rm ${DEPLOY_DIR_IMAGE}/target-files/META/misc_info.txt
+ fi
+ echo "recovery_api_version=3" >> ${DEPLOY_DIR_IMAGE}/target-files/META/misc_info.txt
+ echo "fstab_version=2" >> ${DEPLOY_DIR_IMAGE}/target-files/META/misc_info.txt
+ echo "ab_update=true" >> ${DEPLOY_DIR_IMAGE}/target-files/META/misc_info.txt
+
+ if [ ! -z "${AB_OTA_PARTITIONS}" ]; then
+ if test -e ${DEPLOY_DIR_IMAGE}/target-files/META/ab_partitions.txt; then
+ rm ${DEPLOY_DIR_IMAGE}/target-files/META/ab_partitions.txt
+ fi
+ tmp="${AB_OTA_PARTITIONS}"
+ for entry in $tmp ; do
+ echo $entry >> ${DEPLOY_DIR_IMAGE}/target-files/META/ab_partitions.txt
+ if [ ! -f ${DEPLOY_DIR_IMAGE}/$entry.img ]; then
+ if [ ! -n "${BUILD_ID}" ]; then
+ exit 0
+ fi
+ fi
+ cp ${DEPLOY_DIR_IMAGE}/$entry.img ${DEPLOY_DIR_IMAGE}/target-files/IMAGES/
+ done
+ fi
+ if test -e ${DEPLOY_DIR_IMAGE}/system.ext4 ; then
+ e2fsdroid ${DEPLOY_DIR_IMAGE}/system.ext4 -e -B ${DEPLOY_DIR_IMAGE}/target-files/IMAGES/system.map
+ fi
+
+ if test "x${BOARD_AVB_ENABLE}" = "xtrue" ; then
+ echo "avb_enable=true" >> ${DEPLOY_DIR_IMAGE}/target-files/META/misc_info.txt
+ echo "avb_system_hashtree_enable=true" >> ${DEPLOY_DIR_IMAGE}/target-files/META/misc_info.txt
+ add_care_map_to_target_files.py ${DEPLOY_DIR_IMAGE}/target-files
+ fi
+
+ cd ${DEPLOY_DIR_IMAGE}/target-files && zip -r -q ../target-files.zip IMAGES META SYSTEM && cd -
+ ota_from_target_files.py -p ${STAGING_DIR_NATIVE} --signapk_shared_library_path=usr/lib --signapk_path=usr/bin/signapk.jar -k ${STAGING_DATADIR_NATIVE}/abtools/security/testkey ${DEPLOY_DIR_IMAGE}/target-files.zip ${DEPLOY_DIR_IMAGE}/ota_full.zip
+ else
+ exit 0
+ fi
+}
+
+create_misc_folder() {
+ if [ "${AB_OTA_UPDATER}" = "yes" ]; then
+ install -d ${IMAGE_ROOTFS}/misc
+ fi
+}
+
+ROOTFS_PREPROCESS_COMMAND += " create_misc_folder;"
+
+
+addtask do_make_otafull_package after ${AFTER_CMD} before do_build
diff --git a/meta/meta-mediatek/classes/mkchrome.bbclass b/meta/meta-mediatek/classes/mkchrome.bbclass
new file mode 100644
index 0000000..bd18dde
--- /dev/null
+++ b/meta/meta-mediatek/classes/mkchrome.bbclass
@@ -0,0 +1,52 @@
+CHROME_DIR_IMAGE_SIZE ?= "${MKUBIFS_CHROME_IMAGE_SZ}"
+CHROME_EXT4_IMAGE_SIZE ?= "${CHROME_IMAGE_SZ}"
+CHROME_DIR_IMAGE_PATH = "${DEPLOY_DIR_IMAGE}/chrome"
+CHROME_DIR_CONTENT = "${IMAGE_ROOTFS}/../chrome"
+
+IMAGE_FSTYPES_NO_WHITESPACE="$(echo "${IMAGE_FSTYPES}" | tr -d '[:space:]')"
+CHROME_FS_PARTITION = "chrome_fs.ubi"
+CHROME_PARTITION = "chrome.ubi"
+CHROME_PARTITION_EXT4 = "chrome.ext4"
+
+mk_chrome_image() {
+
+ mkdir -p ${CHROME_DIR_CONTENT}/tmp
+ mkdir -p ${CHROME_DIR_CONTENT}/etc
+ mkdir -p ${CHROME_DIR_CONTENT}/var
+
+ install -d ${IMAGE_ROOTFS}/chrome
+ for i in ${CHROME_DIR_CONTENT}; do
+ CHROME_DIR_FILE_PATH=${CHROME_DIR_IMAGE_PATH}/${i##${CHROME_DIR_CONTENT}}
+ install -d ${CHROME_DIR_FILE_PATH}
+ if [ "$(ls -A ${i})" ]; then
+ cp -a ${i}/* ${CHROME_DIR_FILE_PATH}
+ else
+ echo "${i} is empty"
+ fi
+ done
+
+ if test "${IMAGE_FSTYPES_NO_WHITESPACE}" = "ubi"; then
+ echo \[ubifs\] > ubinize.cfg
+ echo mode=ubi >> ubinize.cfg
+ echo image=${CHROME_FS_PARTITION} >> ubinize.cfg
+ echo vol_id=0 >> ubinize.cfg
+ echo vol_size=${MKUBIFS_CHROME_VOL_SZ}
+ echo vol_type=dynamic >> ubinize.cfg
+ echo vol_name=chrome >> ubinize.cfg
+ echo vol_flags=autoresize >> ubinize.cfg
+ dd if=/dev/zero of=${DEPLOY_DIR_IMAGE}/${CHROME_FS_PARTITION} seek=${CHROME_DIR_IMAGE_SIZE} count=0 bs=1k
+ mkfs.ubifs -r ${CHROME_DIR_FILE_PATH} ${MKUBIFS_CHROME_ARGS} -o ${CHROME_FS_PARTITION}
+ #ubinize -o ${CHROME_PARTITION} -m 2048 -p 128KiB -s 2048 ubinize.cfg
+ ubinize -o ${CHROME_PARTITION} ${UBINIZE_ARGS} ubinize.cfg
+ cp ${CHROME_PARTITION} ${DEPLOY_DIR_IMAGE}/${CHROME_PARTITION}
+ elif test "${IMAGE_FSTYPES_NO_WHITESPACE}" = "ext4"; then
+ dd if=/dev/zero of=${DEPLOY_DIR_IMAGE}/${CHROME_PARTITION_EXT4} seek=${CHROME_EXT4_IMAGE_SIZE} count=${CHROME_IMAGE_CNT} bs=1k
+ mkfs.ext4 -F -i 4096 ${DEPLOY_DIR_IMAGE}/${CHROME_PARTITION_EXT4} -d ${CHROME_DIR_IMAGE_PATH}
+ else
+ echo "No method to make ${IMAGE_FSTYPES_NO_WHITESPACE} type state image"
+ fi
+}
+
+ROOTFS_POSTPROCESS_COMMAND += " mk_chrome_image;"
+
+
diff --git a/meta/meta-mediatek/classes/mkstateimage.bbclass b/meta/meta-mediatek/classes/mkstateimage.bbclass
new file mode 100644
index 0000000..56535a3
--- /dev/null
+++ b/meta/meta-mediatek/classes/mkstateimage.bbclass
@@ -0,0 +1,50 @@
+STATE_DIR_IMAGE_SIZE ?= "131072"
+STATE_DIR_IMAGE_PATH = "${DEPLOY_DIR_IMAGE}/state"
+STATE_DIR_CONTENT ?= "${IMAGE_ROOTFS}/home ${IMAGE_ROOTFS}/var ${IMAGE_ROOTFS}/usr/lib/tmpfiles.d ${STATE_DIR_IMAGE_PATH}/usr/local ${STATE_DIR_IMAGE_PATH}/srv"
+IMAGE_FSTYPES_NO_WHITESPACE="$(echo "${IMAGE_FSTYPES}" | tr -d '[:space:]')"
+DEPENDS += "mtd-utils-native"
+
+mk_state_image() {
+ rm -rf ${STATE_DIR_IMAGE_PATH}
+ install -d ${STATE_DIR_CONTENT}
+ for i in ${STATE_DIR_CONTENT}; do
+ STATE_DIR_FILE_PATH=${STATE_DIR_IMAGE_PATH}/${i##${IMAGE_ROOTFS}}
+ install -d ${STATE_DIR_FILE_PATH}
+ cp -a ${i}/. ${STATE_DIR_FILE_PATH}
+ done
+
+ if test "${IMAGE_FSTYPES_NO_WHITESPACE}" = "ubi"; then
+ STATE_PARTITION="userdata.ubifs"
+ STATE_UBI="userdata.ubi"
+ STATE_UBINIZE_CFG="ubinize-state.cfg"
+ dd if=/dev/zero of=${DEPLOY_DIR_IMAGE}/${STATE_PARTITION} seek=${STATE_DIR_IMAGE_SIZE} count=0 bs=1k
+ cat << EOF > ${STATE_UBINIZE_CFG}
+[ubifs]
+mode=ubi
+image=${DEPLOY_DIR_IMAGE}/${STATE_PARTITION}
+vol_id=0
+vol_type=dynamic
+vol_name=state
+vol_flags=autoresize
+EOF
+ mkfs.ubifs -r ${STATE_DIR_IMAGE_PATH} -o ${DEPLOY_DIR_IMAGE}/${STATE_PARTITION} ${MKUBIFS_ARGS}
+ ubinize -o ${DEPLOY_DIR_IMAGE}/${STATE_UBI} ${UBINIZE_ARGS} ${STATE_UBINIZE_CFG}
+ elif test "${IMAGE_FSTYPES_NO_WHITESPACE}" = "ext4"; then
+ STATE_PARTITION="userdata.ext4"
+ dd if=/dev/zero of=${DEPLOY_DIR_IMAGE}/${STATE_PARTITION} seek=${STATE_DIR_IMAGE_SIZE} count=0 bs=1k
+ mkfs.ext4 -F -i 4096 ${DEPLOY_DIR_IMAGE}/${STATE_PARTITION} -d ${STATE_DIR_IMAGE_PATH}
+ else
+ echo "No method to make ${IMAGE_FSTYPES_NO_WHITESPACE} type state image"
+ fi
+}
+
+ROOTFS_POSTPROCESS_COMMAND += " mk_state_image;"
+
+mk_rootfs_folder() {
+ install -d ${IMAGE_ROOTFS}/mnt/userdata ${IMAGE_ROOTFS}/srv
+ if test "${DISTRO}" != "poky-agl"; then
+ install -d ${IMAGE_ROOTFS}/usr/local
+ fi
+}
+
+ROOTFS_PREPROCESS_COMMAND += " mk_rootfs_folder;"
diff --git a/meta/meta-mediatek/classes/mktinyrootfs.bbclass b/meta/meta-mediatek/classes/mktinyrootfs.bbclass
new file mode 100644
index 0000000..f387eda
--- /dev/null
+++ b/meta/meta-mediatek/classes/mktinyrootfs.bbclass
@@ -0,0 +1,28 @@
+STATE_DIR_CONTENT = "${IMAGE_ROOTFS}/../usrdata"
+
+mk_tinyrootfs_image() {
+ mkdir -p ${STATE_DIR_CONTENT}/tmp
+ mkdir -p ${STATE_DIR_CONTENT}/etc
+ mkdir -p ${STATE_DIR_CONTENT}/var
+ mkdir -p ${STATE_DIR_CONTENT}/usr
+ mkdir -p ${STATE_DIR_CONTENT}/usr/bin
+ mkdir -p ${STATE_DIR_CONTENT}/usr/sbin
+ mkdir -p ${STATE_DIR_CONTENT}/config
+
+ install -d ${STATE_DIR_CONTENT}
+ rm -fr ${IMAGE_ROOTFS}/usr/share/X11/xkb/rules/evdev.xml
+ rm -fr ${IMAGE_ROOTFS}/usr/share/X11/xkb/rules/base.xml
+ rm -fr ${IMAGE_ROOTFS}/usr/share/X11/xkb/symbols/nokia_vndr/rx-51
+
+ rm -fr ${IMAGE_ROOTFS}/usr/lib/libQt5Test.so.5.8.0
+ rm -fr ${IMAGE_ROOTFS}/usr/lib/libQt5QuickTest.so.5.8.0
+
+ rm -fr ${IMAGE_ROOTFS}/usr/lib/libmdp_prot.mt2701.so
+ rm -fr ${IMAGE_ROOTFS}/usr/lib/libmdp_prot.mt2712.so
+ rm -fr ${IMAGE_ROOTFS}/usr/lib/libmdp_prot.mt8173.so
+ rm -fr ${IMAGE_ROOTFS}/usr/share/weston/rawdata.rgb565
+}
+
+ROOTFS_POSTPROCESS_COMMAND += " mk_tinyrootfs_image;"
+
+
diff --git a/meta/meta-mediatek/classes/mkusrdata.bbclass b/meta/meta-mediatek/classes/mkusrdata.bbclass
new file mode 100644
index 0000000..657bc92
--- /dev/null
+++ b/meta/meta-mediatek/classes/mkusrdata.bbclass
@@ -0,0 +1,70 @@
+STATE_DIR_IMAGE_SIZE ?= "${MKUBIFS_USRDATA_IMAGE_SZ}"
+STATE_DIR_IMAGE_PATH = "${DEPLOY_DIR_IMAGE}/userdata"
+STATE_DIR_CONTENT = "${IMAGE_ROOTFS}/../usrdata"
+IMAGE_FSTYPES_NO_WHITESPACE="$(echo "${IMAGE_FSTYPES}" | tr -d '[:space:]')"
+USERDATA_FS_PARTITION = "userdata_fs.ubi"
+USERDATA_PARTITION = "userdata.ubi"
+CRYPT_HOST_TOOL = "${TOPDIR}/../src/devtools/nfsb/crypt_tool/crypt_host_tool"
+DEPENDS += "mtd-utils-native"
+mk_userdata_image() {
+ mkdir -p ${STATE_DIR_CONTENT}/tmp
+ mkdir -p ${STATE_DIR_CONTENT}/etc
+ mkdir -p ${STATE_DIR_CONTENT}/var
+ mkdir -p ${STATE_DIR_CONTENT}/usr
+ mkdir -p ${STATE_DIR_CONTENT}/usr/bin
+ mkdir -p ${STATE_DIR_CONTENT}/usr/sbin
+ mkdir -p ${STATE_DIR_CONTENT}/config
+
+ if [ -d ${IMAGE_ROOTFS}/data ]; then
+ cp -a ${IMAGE_ROOTFS}/data/* ${STATE_DIR_CONTENT}
+ rm -rf ${IMAGE_ROOTFS}/data/*
+ fi
+ if test "${CONFIG_ICU_SUPPORT}" = "no"; then
+ rm -fr ${IMAGE_ROOTFS}/usr/lib/libicudata.so.59.1
+ rm -fr ${IMAGE_ROOTFS}/usr/lib/libicui18n.so.59.1
+ rm -fr ${IMAGE_ROOTFS}/usr/lib/libicuuc.so.59.1
+ fi
+
+ rm -rf ${STATE_DIR_IMAGE_PATH}
+
+ install -d ${STATE_DIR_CONTENT}
+
+ for i in ${STATE_DIR_CONTENT}; do
+ STATE_DIR_FILE_PATH=${STATE_DIR_IMAGE_PATH}/${i##${STATE_DIR_CONTENT}}
+ install -d ${STATE_DIR_FILE_PATH}
+ if [ "$(ls -A ${i})" ]; then
+ cp -a ${i}/* ${STATE_DIR_FILE_PATH}
+ else
+ echo "${i} is empty"
+ fi
+ done
+
+ if test "${IMAGE_FSTYPES_NO_WHITESPACE}" = "ubi"; then
+ echo \[ubifs\] > ubinize.cfg
+ echo mode=ubi >> ubinize.cfg
+ echo image=${USERDATA_FS_PARTITION} >> ubinize.cfg
+ echo vol_id=0 >> ubinize.cfg
+ echo vol_size=${MKUBIFS_USRDATA_VOL_SZ}
+ echo vol_type=dynamic >> ubinize.cfg
+ echo vol_name=useradata >> ubinize.cfg
+ echo vol_flags=autoresize >> ubinize.cfg
+ dd if=/dev/zero of=${DEPLOY_DIR_IMAGE}/${USERDATA_FS_PARTITION} seek=${STATE_DIR_IMAGE_SIZE} count=0 bs=1k
+ mkfs.ubifs -r ${STATE_DIR_FILE_PATH} ${MKUBIFS_USRDATA_ARGS} -o ${USERDATA_FS_PARTITION}
+ ubinize -o ${USERDATA_PARTITION} ${UBINIZE_ARGS} ubinize.cfg
+ cp ${USERDATA_PARTITION} ${DEPLOY_DIR_IMAGE}/${USERDATA_PARTITION}
+ elif test "${IMAGE_FSTYPES_NO_WHITESPACE}" = "ext4"; then
+ STATE_PARTITION="userdata.ext4"
+ dd if=/dev/zero of=${DEPLOY_DIR_IMAGE}/${STATE_PARTITION} seek=${STATE_DIR_IMAGE_SIZE} count=${MKEXT4_USRDATA_CNT} bs=1k
+ mkfs.ext4 -F -i 4096 ${DEPLOY_DIR_IMAGE}/${STATE_PARTITION} -d ${STATE_DIR_IMAGE_PATH}
+ if test "${ENABLE_USRDATA_DM_CRYPT}" = "yes"; then
+ mv ${DEPLOY_DIR_IMAGE}/${STATE_PARTITION} ${DEPLOY_DIR_IMAGE}/plain_${STATE_PARTITION}
+ ${CRYPT_HOST_TOOL} ${DM_CRYPT_ALG} `cat ${MTK_KEY_DIR}/${DM_CRYPT_KEY}` 0 0 ${DEPLOY_DIR_IMAGE}/plain_${STATE_PARTITION} ${DEPLOY_DIR_IMAGE}/${STATE_PARTITION} usrdata `cat ${MTK_KEY_DIR}/${DM_PROTECT_KEY}`
+ fi
+ else
+ echo "No method to make ${IMAGE_FSTYPES_NO_WHITESPACE} type state image"
+ fi
+}
+
+ROOTFS_POSTPROCESS_COMMAND += " mk_userdata_image;"
+
+
diff --git a/meta/meta-mediatek/classes/monitor-rootfs.bbclass b/meta/meta-mediatek/classes/monitor-rootfs.bbclass
new file mode 100644
index 0000000..a81daa2
--- /dev/null
+++ b/meta/meta-mediatek/classes/monitor-rootfs.bbclass
@@ -0,0 +1,16 @@
+inherit deploy
+
+rootfs_monitor() {
+ find ${IMAGE_ROOTFS} -type f -size +50k -print0 | xargs -0 du -h | sort -nr > ${IMAGE_ROOTFS}/rootfs_monitor.txt
+}
+
+do_deploy () {
+ install -d ${DEPLOYDIR}
+ cp ${IMAGE_ROOTFS}/rootfs_monitor.txt ${DEPLOYDIR}
+}
+
+addtask deploy before do_mtdverity_for_rootfs after do_image_complete
+
+ROOTFS_POSTPROCESS_COMMAND += " rootfs_monitor;"
+
+
diff --git a/meta/meta-mediatek/classes/optee-build.bbclass b/meta/meta-mediatek/classes/optee-build.bbclass
new file mode 100644
index 0000000..ee6d1a5
--- /dev/null
+++ b/meta/meta-mediatek/classes/optee-build.bbclass
@@ -0,0 +1,4 @@
+TA_DEV_KIT_DIR ?= "${WORKDIR}/lib64-recipe-sysroot${includedir}/optee/export-user_ta"
+OPTEE_LIB64 ?= "${BASE_WORKDIR}/x86_64-linux/lib64-gcc-cross-aarch64/8.2.0-r0/recipe-sysroot-native/usr/lib/"
+OPTEE_BULID_SA ?= "${BASE_WORKDIR}/aarch64-pokymllib64-linux/lib64-optee-os/3.2.0-r0/recipe-sysroot-native/usr/libexec/aarch64-pokymllib64-linux/gcc/aarch64-pokymllib64-linux/8.2.0/"
+TEE_TOOLCHAIN ?= "${OPTEE_BULID_SA}aarch64-pokymllib64-linux-"
\ No newline at end of file
diff --git a/meta/meta-mediatek/classes/pack-abupdate-zip.bbclass b/meta/meta-mediatek/classes/pack-abupdate-zip.bbclass
new file mode 100644
index 0000000..63ce430
--- /dev/null
+++ b/meta/meta-mediatek/classes/pack-abupdate-zip.bbclass
@@ -0,0 +1,11 @@
+IMAGE_PATH = "${DEPLOY_DIR_IMAGE}"
+IMAGE_LIST = "${IMAGE_PATH}/boot.img \
+ ${IMAGE_PATH}/system.img "
+DEPENDS += "zip-native"
+
+do_packing_images_post_funcs() {
+ zip -j ${IMAGE_PATH}/abupdate.zip ${IMAGE_LIST}
+}
+
+addtask packing_images_post_funcs after do_avb_sign_img before do_build
+
diff --git a/meta/meta-mediatek/classes/pack-update-zip-mt8183.bbclass b/meta/meta-mediatek/classes/pack-update-zip-mt8183.bbclass
new file mode 100644
index 0000000..e7f4880
--- /dev/null
+++ b/meta/meta-mediatek/classes/pack-update-zip-mt8183.bbclass
@@ -0,0 +1,15 @@
+IMAGE_PATH = "${DEPLOY_DIR_IMAGE}"
+IMAGE_LIST = "${IMAGE_PATH}/tee.img \
+ ${IMAGE_PATH}/boot.img \
+ ${IMAGE_PATH}/system.ext4 \
+ ${IMAGE_PATH}/system.ubi \
+ ${IMAGE_PATH}/recovery.ext4 \
+ ${IMAGE_PATH}/recovery.ubi "
+DEPENDS += "zip-native"
+
+do_packing_images_post_funcs() {
+ zip -j ${IMAGE_PATH}/update.zip ${IMAGE_LIST}
+}
+
+addtask packing_images_post_funcs after do_image_complete before do_build
+
diff --git a/meta/meta-mediatek/classes/pack-update-zip.bbclass b/meta/meta-mediatek/classes/pack-update-zip.bbclass
new file mode 100755
index 0000000..87beac9
--- /dev/null
+++ b/meta/meta-mediatek/classes/pack-update-zip.bbclass
@@ -0,0 +1,17 @@
+IMAGE_PATH = "${DEPLOY_DIR_IMAGE}"
+IMAGE_LIST = "${IMAGE_PATH}/tee.img \
+ ${IMAGE_PATH}/boot.img \
+ ${IMAGE_PATH}/system.ext4 \
+ ${IMAGE_PATH}/system.ubi \
+ ${IMAGE_PATH}/recovery.ext4 \
+ ${IMAGE_PATH}/recovery.ubi \
+ ${IMAGE_PATH}/chrome.ext4 \
+ ${IMAGE_PATH}/chrome.ubi "
+DEPENDS += "zip-native"
+
+do_packing_images_post_funcs() {
+ zip -j ${IMAGE_PATH}/update.zip ${IMAGE_LIST}
+}
+
+addtask packing_images_post_funcs after do_image_qa before do_build
+
diff --git a/meta/meta-mediatek/classes/packagebbclassappend.bbclass b/meta/meta-mediatek/classes/packagebbclassappend.bbclass
new file mode 100644
index 0000000..2d3bb85
--- /dev/null
+++ b/meta/meta-mediatek/classes/packagebbclassappend.bbclass
@@ -0,0 +1,577 @@
+inherit package
+
+def splitdebuginfo(file, dvar, debugdir, debuglibdir, debugappend, debugsrcdir, sourcefile, d):
+ # Function to split a single file into two components, one is the stripped
+ # target system binary, the other contains any debugging information. The
+ # two files are linked to reference each other.
+ #
+ # sourcefile is also generated containing a list of debugsources
+
+ import stat
+ import subprocess
+
+ src = file[len(dvar):]
+ dest = debuglibdir + os.path.dirname(src) + debugdir + "/" + os.path.basename(src) + debugappend
+ debugfile = dvar + dest
+ # Split the file...
+ bb.utils.mkdirhier(os.path.dirname(debugfile))
+ #bb.note("Split %s -> %s" % (file, debugfile))
+ # Only store off the hard link reference if we successfully split!
+
+ dvar = d.getVar('PKGD')
+ objcopy = d.getVar("OBJCOPY")
+
+ # We ignore kernel modules, we don't generate debug info files.
+ if file.find("/lib/modules/") != -1 and file.endswith(".ko"):
+ return 1
+
+ newmode = None
+ if os.path.exists(file):
+ if not os.access(file, os.W_OK) or os.access(file, os.R_OK):
+ origmode = os.stat(file)[stat.ST_MODE]
+ newmode = origmode | stat.S_IWRITE | stat.S_IREAD
+ os.chmod(file, newmode)
+
+ # We need to extract the debug src information here...
+ if debugsrcdir:
+ append_source_info(file, sourcefile, d)
+
+ bb.utils.mkdirhier(os.path.dirname(debugfile))
+
+ if os.path.basename(src) != "udevd" and os.path.basename(src) != "init":
+ subprocess.check_output([objcopy, file, debugfile], stderr=subprocess.STDOUT)
+
+ # Set the debuglink to have the view of the file path on the target
+ if not cpath.islink(file):
+ subprocess.check_output([objcopy, '--add-gnu-debuglink', debugfile, file], stderr=subprocess.STDOUT)
+
+ if newmode:
+ os.chmod(file, origmode)
+
+ return 0
+
+python split_and_strip_files () {
+ import stat, errno
+ import subprocess
+
+ dvar = d.getVar('PKGD')
+ pn = d.getVar('PN')
+ targetos = d.getVar('TARGET_OS')
+
+ oldcwd = os.getcwd()
+ os.chdir(dvar)
+
+ # We default to '.debug' style
+ if d.getVar('PACKAGE_DEBUG_SPLIT_STYLE') == 'debug-file-directory':
+ # Single debug-file-directory style debug info
+ debugappend = ".debug"
+ debugdir = ""
+ debuglibdir = "/usr/lib/debug"
+ debugsrcdir = "/usr/src/debug"
+ elif d.getVar('PACKAGE_DEBUG_SPLIT_STYLE') == 'debug-without-src':
+ # Original OE-core, a.k.a. ".debug", style debug info, but without sources in /usr/src/debug
+ debugappend = ""
+ debugdir = "/.debug"
+ debuglibdir = ""
+ debugsrcdir = ""
+ elif d.getVar('PACKAGE_DEBUG_SPLIT_STYLE') == 'debug-with-srcpkg':
+ debugappend = ""
+ debugdir = "/.debug"
+ debuglibdir = ""
+ debugsrcdir = "/usr/src/debug"
+ else:
+ # Original OE-core, a.k.a. ".debug", style debug info
+ debugappend = ""
+ debugdir = "/.debug"
+ debuglibdir = ""
+ debugsrcdir = "/usr/src/debug"
+
+ sourcefile = d.expand("${WORKDIR}/debugsources.list")
+ bb.utils.remove(sourcefile)
+
+ #
+ # First lets figure out all of the files we may have to process ... do this only once!
+ #
+ elffiles = {}
+ symlinks = {}
+ kernmods = []
+ staticlibs = []
+ inodes = {}
+ libdir = os.path.abspath(dvar + os.sep + d.getVar("libdir"))
+ baselibdir = os.path.abspath(dvar + os.sep + d.getVar("base_libdir"))
+ skipfiles = (d.getVar("INHIBIT_PACKAGE_STRIP_FILES") or "").split()
+ if (d.getVar('INHIBIT_PACKAGE_STRIP') != '1' or \
+ d.getVar('INHIBIT_PACKAGE_DEBUG_SPLIT') != '1'):
+ checkelf = {}
+ checkelflinks = {}
+ for root, dirs, files in cpath.walk(dvar):
+ for f in files:
+ file = os.path.join(root, f)
+ if file.endswith(".ko") and file.find("/lib/modules/") != -1:
+ kernmods.append(file)
+ continue
+ if oe.package.is_static_lib(file):
+ staticlibs.append(file)
+ continue
+
+ # Skip debug files
+ if debugappend and file.endswith(debugappend):
+ continue
+ if debugdir and debugdir in os.path.dirname(file[len(dvar):]):
+ continue
+
+ if file in skipfiles:
+ continue
+
+ try:
+ ltarget = cpath.realpath(file, dvar, False)
+ s = cpath.lstat(ltarget)
+ except OSError as e:
+ (err, strerror) = e.args
+ if err != errno.ENOENT:
+ raise
+ # Skip broken symlinks
+ continue
+ if not s:
+ continue
+ # Check its an executable
+ if (s[stat.ST_MODE] & stat.S_IXUSR) or (s[stat.ST_MODE] & stat.S_IXGRP) or (s[stat.ST_MODE] & stat.S_IXOTH) \
+ or ((file.startswith(libdir) or file.startswith(baselibdir)) and (".so" in f or ".node" in f)):
+
+ if cpath.islink(file):
+ checkelflinks[file] = ltarget
+ continue
+ # Use a reference of device ID and inode number to identify files
+ file_reference = "%d_%d" % (s.st_dev, s.st_ino)
+ checkelf[file] = (file, file_reference)
+
+ results = oe.utils.multiprocess_launch(oe.package.is_elf, checkelflinks.values(), d)
+ results_map = {}
+ for (ltarget, elf_file) in results:
+ results_map[ltarget] = elf_file
+ for file in checkelflinks:
+ ltarget = checkelflinks[file]
+ # If it's a symlink, and points to an ELF file, we capture the readlink target
+ if results_map[ltarget]:
+ target = os.readlink(file)
+ #bb.note("Sym: %s (%d)" % (ltarget, results_map[ltarget]))
+ symlinks[file] = target
+
+ results = oe.utils.multiprocess_launch(oe.package.is_elf, checkelf.keys(), d)
+ for (file, elf_file) in results:
+ # It's a file (or hardlink), not a link
+ # ...but is it ELF, and is it already stripped?
+ if elf_file & 1:
+ if elf_file & 2:
+ if 'already-stripped' in (d.getVar('INSANE_SKIP_' + pn) or "").split():
+ bb.note("Skipping file %s from %s for already-stripped QA test" % (file[len(dvar):], pn))
+ else:
+ msg = "File '%s' from %s was already stripped, this will prevent future debugging!" % (file[len(dvar):], pn)
+ package_qa_handle_error("already-stripped", msg, d)
+ continue
+
+ # At this point we have an unstripped elf file. We need to:
+ # a) Make sure any file we strip is not hardlinked to anything else outside this tree
+ # b) Only strip any hardlinked file once (no races)
+ # c) Track any hardlinks between files so that we can reconstruct matching debug file hardlinks
+
+ # Use a reference of device ID and inode number to identify files
+ file_reference = checkelf[file][1]
+ if file_reference in inodes:
+ os.unlink(file)
+ os.link(inodes[file_reference][0], file)
+ inodes[file_reference].append(file)
+ else:
+ inodes[file_reference] = [file]
+ # break hardlink
+ bb.utils.break_hardlinks(file)
+ elffiles[file] = elf_file
+ # Modified the file so clear the cache
+ cpath.updatecache(file)
+
+ #
+ # First lets process debug splitting
+ #
+ if (d.getVar('INHIBIT_PACKAGE_DEBUG_SPLIT') != '1'):
+ oe.utils.multiprocess_launch(splitdebuginfo, list(elffiles), d, extraargs=(dvar, debugdir, debuglibdir, debugappend, debugsrcdir, sourcefile, d))
+
+ # Add this line to keep link so(like libc.so.6) in dbg-rpm dir.
+ oe.utils.multiprocess_launch(splitdebuginfo, list(symlinks), d, extraargs=(dvar, debugdir, debuglibdir, debugappend, debugsrcdir, sourcefile, d))
+
+ if debugsrcdir and not targetos.startswith("mingw"):
+ for file in staticlibs:
+ append_source_info(file, sourcefile, d, fatal=False)
+
+ # Hardlink our debug symbols to the other hardlink copies
+ for ref in inodes:
+ if len(inodes[ref]) == 1:
+ continue
+
+ target = inodes[ref][0][len(dvar):]
+ for file in inodes[ref][1:]:
+ src = file[len(dvar):]
+ dest = debuglibdir + os.path.dirname(src) + debugdir + "/" + os.path.basename(target) + debugappend
+ fpath = dvar + dest
+ ftarget = dvar + debuglibdir + os.path.dirname(target) + debugdir + "/" + os.path.basename(target) + debugappend
+ bb.utils.mkdirhier(os.path.dirname(fpath))
+ # Only one hardlink of separated debug info file in each directory
+ if not os.access(fpath, os.R_OK):
+ #bb.note("Link %s -> %s" % (fpath, ftarget))
+ os.link(ftarget, fpath)
+
+ # Create symlinks for all cases we were able to split symbols
+ for file in symlinks:
+ src = file[len(dvar):]
+ dest = debuglibdir + os.path.dirname(src) + debugdir + "/" + os.path.basename(src) + debugappend
+ fpath = dvar + dest
+ # Skip it if the target doesn't exist
+ try:
+ s = os.stat(fpath)
+ except OSError as e:
+ (err, strerror) = e.args
+ if err != errno.ENOENT:
+ raise
+ continue
+
+ ltarget = symlinks[file]
+ lpath = os.path.dirname(ltarget)
+ lbase = os.path.basename(ltarget)
+ ftarget = ""
+ if lpath and lpath != ".":
+ ftarget += lpath + debugdir + "/"
+ ftarget += lbase + debugappend
+ if lpath.startswith(".."):
+ ftarget = os.path.join("..", ftarget)
+ bb.utils.mkdirhier(os.path.dirname(fpath))
+ #bb.note("Symlink %s -> %s" % (fpath, ftarget))
+ if not os.path.exists(fpath):
+ os.symlink(ftarget, fpath)
+
+ # Process the debugsrcdir if requested...
+ # This copies and places the referenced sources for later debugging...
+ copydebugsources(debugsrcdir, d)
+ #
+ # End of debug splitting
+ #
+
+ #
+ # Now lets go back over things and strip them
+ #
+ if (d.getVar('INHIBIT_PACKAGE_STRIP') != '1'):
+ strip = d.getVar("STRIP")
+ sfiles = []
+ for file in elffiles:
+ elf_file = int(elffiles[file])
+ #bb.note("Strip %s" % file)
+ sfiles.append((file, elf_file, strip))
+ for f in kernmods:
+ sfiles.append((f, 16, strip))
+
+ oe.utils.multiprocess_launch(oe.package.runstrip, sfiles, d)
+
+ #
+ # End of strip
+ #
+ os.chdir(oldcwd)
+}
+
+python package_do_shlibs() {
+ import re, pipes
+ import subprocess
+
+ exclude_shlibs = d.getVar('EXCLUDE_FROM_SHLIBS', False)
+ if exclude_shlibs:
+ bb.note("not generating shlibs")
+ return
+
+ lib_re = re.compile("^.*\.so")
+ libdir_re = re.compile(".*/%s$" % d.getVar('baselib'))
+
+ packages = d.getVar('PACKAGES')
+
+ shlib_pkgs = []
+ exclusion_list = d.getVar("EXCLUDE_PACKAGES_FROM_SHLIBS")
+ if exclusion_list:
+ for pkg in packages.split():
+ if pkg not in exclusion_list.split():
+ shlib_pkgs.append(pkg)
+ else:
+ bb.note("not generating shlibs for %s" % pkg)
+ else:
+ shlib_pkgs = packages.split()
+
+ targetos = d.getVar('TARGET_OS')
+
+ workdir = d.getVar('WORKDIR')
+
+ ver = d.getVar('PKGV')
+ if not ver:
+ msg = "PKGV not defined"
+ package_qa_handle_error("pkgv-undefined", msg, d)
+ return
+
+ pkgdest = d.getVar('PKGDEST')
+
+ shlibswork_dir = d.getVar('SHLIBSWORKDIR')
+
+ def linux_so(file, pkg, pkgver, d):
+ needs_ldconfig = False
+ needed = set()
+ sonames = set()
+ renames = []
+ if "-dbg" in pkg:
+ return (needs_ldconfig, needed, sonames, renames)
+
+ ldir = os.path.dirname(file).replace(pkgdest + "/" + pkg, '')
+ cmd = d.getVar('OBJDUMP') + " -p " + pipes.quote(file) + " 2>/dev/null"
+ fd = os.popen(cmd)
+ lines = fd.readlines()
+ fd.close()
+ rpath = tuple()
+ for l in lines:
+ m = re.match("\s+RPATH\s+([^\s]*)", l)
+ if m:
+ rpaths = m.group(1).replace("$ORIGIN", ldir).split(":")
+ rpath = tuple(map(os.path.normpath, rpaths))
+ for l in lines:
+ m = re.match("\s+NEEDED\s+([^\s]*)", l)
+ if m:
+ dep = m.group(1)
+ if dep not in needed:
+ needed.add((dep, file, rpath))
+ m = re.match("\s+SONAME\s+([^\s]*)", l)
+ if m:
+ this_soname = m.group(1)
+ prov = (this_soname, ldir, pkgver)
+ if not prov in sonames:
+ # if library is private (only used by package) then do not build shlib for it
+ if not private_libs or this_soname not in private_libs:
+ sonames.add(prov)
+ if libdir_re.match(os.path.dirname(file)):
+ needs_ldconfig = True
+ if snap_symlinks and (os.path.basename(file) != this_soname):
+ renames.append((file, os.path.join(os.path.dirname(file), this_soname)))
+ return (needs_ldconfig, needed, sonames, renames)
+
+ def darwin_so(file, needed, sonames, renames, pkgver):
+ if not os.path.exists(file):
+ return
+ ldir = os.path.dirname(file).replace(pkgdest + "/" + pkg, '')
+
+ def get_combinations(base):
+ #
+ # Given a base library name, find all combinations of this split by "." and "-"
+ #
+ combos = []
+ options = base.split(".")
+ for i in range(1, len(options) + 1):
+ combos.append(".".join(options[0:i]))
+ options = base.split("-")
+ for i in range(1, len(options) + 1):
+ combos.append("-".join(options[0:i]))
+ return combos
+
+ if (file.endswith('.dylib') or file.endswith('.so')) and not pkg.endswith('-dev') and not pkg.endswith('-dbg') and not pkg.endswith('-src'):
+ # Drop suffix
+ name = os.path.basename(file).rsplit(".",1)[0]
+ # Find all combinations
+ combos = get_combinations(name)
+ for combo in combos:
+ if not combo in sonames:
+ prov = (combo, ldir, pkgver)
+ sonames.add(prov)
+ if file.endswith('.dylib') or file.endswith('.so'):
+ rpath = []
+ p = subprocess.Popen([d.expand("${HOST_PREFIX}otool"), '-l', file], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ out, err = p.communicate()
+ # If returned successfully, process stdout for results
+ if p.returncode == 0:
+ for l in out.split("\n"):
+ l = l.strip()
+ if l.startswith('path '):
+ rpath.append(l.split()[1])
+
+ p = subprocess.Popen([d.expand("${HOST_PREFIX}otool"), '-L', file], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ out, err = p.communicate()
+ # If returned successfully, process stdout for results
+ if p.returncode == 0:
+ for l in out.split("\n"):
+ l = l.strip()
+ if not l or l.endswith(":"):
+ continue
+ if "is not an object file" in l:
+ continue
+ name = os.path.basename(l.split()[0]).rsplit(".", 1)[0]
+ if name and name not in needed[pkg]:
+ needed[pkg].add((name, file, tuple()))
+
+ def mingw_dll(file, needed, sonames, renames, pkgver):
+ if not os.path.exists(file):
+ return
+
+ if file.endswith(".dll"):
+ # assume all dlls are shared objects provided by the package
+ sonames.add((os.path.basename(file), os.path.dirname(file).replace(pkgdest + "/" + pkg, ''), pkgver))
+
+ if (file.endswith(".dll") or file.endswith(".exe")):
+ # use objdump to search for "DLL Name: .*\.dll"
+ p = subprocess.Popen([d.expand("${HOST_PREFIX}objdump"), "-p", file], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ out, err = p.communicate()
+ # process the output, grabbing all .dll names
+ if p.returncode == 0:
+ for m in re.finditer("DLL Name: (.*?\.dll)$", out.decode(), re.MULTILINE | re.IGNORECASE):
+ dllname = m.group(1)
+ if dllname:
+ needed[pkg].add((dllname, file, tuple()))
+
+ if d.getVar('PACKAGE_SNAP_LIB_SYMLINKS') == "1":
+ snap_symlinks = True
+ else:
+ snap_symlinks = False
+
+ use_ldconfig = bb.utils.contains('DISTRO_FEATURES', 'ldconfig', True, False, d)
+
+ needed = {}
+
+ # Take shared lock since we're only reading, not writing
+ lf = bb.utils.lockfile(d.expand("${PACKAGELOCK}"), True)
+ shlib_provider = oe.package.read_shlib_providers(d)
+ bb.utils.unlockfile(lf)
+
+ for pkg in shlib_pkgs:
+ private_libs = d.getVar('PRIVATE_LIBS_' + pkg) or d.getVar('PRIVATE_LIBS') or ""
+ private_libs = private_libs.split()
+ needs_ldconfig = False
+ bb.debug(2, "calculating shlib provides for %s" % pkg)
+
+ pkgver = d.getVar('PKGV_' + pkg)
+ if not pkgver:
+ pkgver = d.getVar('PV_' + pkg)
+ if not pkgver:
+ pkgver = ver
+
+ needed[pkg] = set()
+ sonames = set()
+ renames = []
+ linuxlist = []
+ for file in pkgfiles[pkg]:
+ soname = None
+ if cpath.islink(file):
+ continue
+ if targetos == "darwin" or targetos == "darwin8":
+ darwin_so(file, needed, sonames, renames, pkgver)
+ elif targetos.startswith("mingw"):
+ mingw_dll(file, needed, sonames, renames, pkgver)
+ elif os.access(file, os.X_OK) or lib_re.match(file):
+ linuxlist.append(file)
+
+ if linuxlist:
+ results = oe.utils.multiprocess_launch(linux_so, linuxlist, d, extraargs=(pkg, pkgver, d))
+ for r in results:
+ ldconfig = r[0]
+ needed[pkg] |= r[1]
+ sonames |= r[2]
+ renames.extend(r[3])
+ needs_ldconfig = needs_ldconfig or ldconfig
+
+ for (old, new) in renames:
+ bb.note("Renaming %s to %s" % (old, new))
+ os.rename(old, new)
+ pkgfiles[pkg].remove(old)
+
+ shlibs_file = os.path.join(shlibswork_dir, pkg + ".list")
+ if len(sonames):
+ fd = open(shlibs_file, 'w')
+ for s in sonames:
+ if s[0] in shlib_provider and s[1] in shlib_provider[s[0]]:
+ (old_pkg, old_pkgver) = shlib_provider[s[0]][s[1]]
+ if old_pkg != pkg:
+ bb.warn('%s-%s was registered as shlib provider for %s, changing it to %s-%s because it was built later' % (old_pkg, old_pkgver, s[0], pkg, pkgver))
+ bb.debug(1, 'registering %s-%s as shlib provider for %s' % (pkg, pkgver, s[0]))
+ fd.write(s[0] + ':' + s[1] + ':' + s[2] + '\n')
+ if s[0] not in shlib_provider:
+ shlib_provider[s[0]] = {}
+ shlib_provider[s[0]][s[1]] = (pkg, pkgver)
+ fd.close()
+ if needs_ldconfig and use_ldconfig:
+ bb.debug(1, 'adding ldconfig call to postinst for %s' % pkg)
+ postinst = d.getVar('pkg_postinst_%s' % pkg)
+ if not postinst:
+ postinst = '#!/bin/sh\n'
+ postinst += d.getVar('ldconfig_postinst_fragment')
+ d.setVar('pkg_postinst_%s' % pkg, postinst)
+ bb.debug(1, 'LIBNAMES: pkg %s sonames %s' % (pkg, sonames))
+
+ assumed_libs = d.getVar('ASSUME_SHLIBS')
+ if assumed_libs:
+ libdir = d.getVar("libdir")
+ for e in assumed_libs.split():
+ l, dep_pkg = e.split(":")
+ lib_ver = None
+ dep_pkg = dep_pkg.rsplit("_", 1)
+ if len(dep_pkg) == 2:
+ lib_ver = dep_pkg[1]
+ dep_pkg = dep_pkg[0]
+ if l not in shlib_provider:
+ shlib_provider[l] = {}
+ shlib_provider[l][libdir] = (dep_pkg, lib_ver)
+
+ libsearchpath = [d.getVar('libdir'), d.getVar('base_libdir')]
+
+ for pkg in shlib_pkgs:
+ bb.debug(2, "calculating shlib requirements for %s" % pkg)
+
+ private_libs = d.getVar('PRIVATE_LIBS_' + pkg) or d.getVar('PRIVATE_LIBS') or ""
+ private_libs = private_libs.split()
+
+ deps = list()
+ for n in needed[pkg]:
+ # if n is in private libraries, don't try to search provider for it
+ # this could cause problem in case some abc.bb provides private
+ # /opt/abc/lib/libfoo.so.1 and contains /usr/bin/abc depending on system library libfoo.so.1
+ # but skipping it is still better alternative than providing own
+ # version and then adding runtime dependency for the same system library
+ if private_libs and n[0] in private_libs:
+ bb.debug(2, '%s: Dependency %s covered by PRIVATE_LIBS' % (pkg, n[0]))
+ continue
+ if n[0] in shlib_provider.keys():
+ shlib_provider_path = []
+ for k in shlib_provider[n[0]].keys():
+ shlib_provider_path.append(k)
+ match = None
+ for p in list(n[2]) + shlib_provider_path + libsearchpath:
+ if p in shlib_provider[n[0]]:
+ match = p
+ break
+ if match:
+ (dep_pkg, ver_needed) = shlib_provider[n[0]][match]
+
+ bb.debug(2, '%s: Dependency %s requires package %s (used by files: %s)' % (pkg, n[0], dep_pkg, n[1]))
+
+ if dep_pkg == pkg:
+ continue
+
+ if ver_needed:
+ dep = "%s (>= %s)" % (dep_pkg, ver_needed)
+ else:
+ dep = dep_pkg
+ if not dep in deps:
+ deps.append(dep)
+ continue
+ bb.note("Couldn't find shared library provider for %s, used by files: %s" % (n[0], n[1]))
+
+ deps_file = os.path.join(pkgdest, pkg + ".shlibdeps")
+ if os.path.exists(deps_file):
+ os.remove(deps_file)
+ if len(deps):
+ fd = open(deps_file, 'w')
+ for dep in deps:
+ fd.write(dep + '\n')
+ fd.close()
+}
+PACKAGEBUILDPKGD := " \
+ perform_packagecopy \
+ ${PACKAGE_PREPROCESS_FUNCS} \
+ split_and_strip_files \
+ fixup_perms \
+ "
diff --git a/meta/meta-mediatek/classes/ramdisk-fitimage-extension.bbclass b/meta/meta-mediatek/classes/ramdisk-fitimage-extension.bbclass
new file mode 100644
index 0000000..ed7e413
--- /dev/null
+++ b/meta/meta-mediatek/classes/ramdisk-fitimage-extension.bbclass
@@ -0,0 +1,344 @@
+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() {
+
+ if [ -n "${IMAGE_HASH_ALGO}" ] ; then
+ kernel_csum="${IMAGE_HASH_ALGO}"
+ else
+ kernel_csum="sha256"
+ fi
+
+ ENTRYPOINT=${UBOOT_ENTRYPOINT}
+ if [ -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() {
+
+ if [ -n "${IMAGE_HASH_ALGO}" ] ; then
+ ramdisk_csum="${IMAGE_HASH_ALGO}"
+ else
+ ramdisk_csum="sha256"
+ fi
+
+ 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() {
+
+ if [ -n "${IMAGE_HASH_ALGO}" ] ; then
+ dtb_csum="${IMAGE_HASH_ALGO}"
+ else
+ dtb_csum="sha256"
+ fi
+
+ 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() {
+
+ if [ -n "${VB_HASH_ALGO}" -a -n "${VB_RSA_ALGO}" ] ; then
+ conf_csum="${VB_HASH_ALGO},${VB_RSA_ALGO}"
+ else
+ conf_csum="sha256,rsa2048"
+ fi
+ 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 [ "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 [ -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 [ "x${KERNEL_IMAGETYPE}" = "xfitImage" ] ; then
+ do_assemble_fitimage
+ fi
+}
+
+do_assemble_fitimage_ramdisk() {
+ if [ "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 [ "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 [ -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_NAME}.bin boot.img
+ fi
+}
+
+do_bundle_initramfs() {
+ :
+}
diff --git a/meta/meta-mediatek/classes/recovery-kernel-fitimage.bbclass b/meta/meta-mediatek/classes/recovery-kernel-fitimage.bbclass
new file mode 100644
index 0000000..d9992aa
--- /dev/null
+++ b/meta/meta-mediatek/classes/recovery-kernel-fitimage.bbclass
@@ -0,0 +1,255 @@
+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() {
+
+ if [ -n "${IMAGE_HASH_ALGO}" ] ; then
+ kernel_csum="${IMAGE_HASH_ALGO}"
+ else
+ kernel_csum="sha256"
+ fi
+
+ ENTRYPOINT=${UBOOT_ENTRYPOINT}
+ if [ -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() {
+
+ if [ -n "${IMAGE_HASH_ALGO}" ] ; then
+ dtb_csum="${IMAGE_HASH_ALGO}"
+ else
+ dtb_csum="sha256"
+ fi
+
+ 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() {
+
+ if [ -n "${VB_HASH_ALGO}" -a -n "${VB_RSA_ALGO}" ] ; then
+ conf_csum="${VB_HASH_ALGO},${VB_RSA_ALGO}"
+ else
+ conf_csum="sha256,rsa2048"
+ fi
+ 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 [ "x${KERNEL_IMAGETYPE}" = "xfitImage" -a -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_kernelmodules
+
+kernel_do_deploy_append() {
+ # Update deploy directory
+ if [ "x${KERNEL_IMAGETYPE}" = "xfitImage" -a -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/classes/recovery-ramdisk-kernel-fitimage.bbclass b/meta/meta-mediatek/classes/recovery-ramdisk-kernel-fitimage.bbclass
new file mode 100755
index 0000000..ff61d4c
--- /dev/null
+++ b/meta/meta-mediatek/classes/recovery-ramdisk-kernel-fitimage.bbclass
@@ -0,0 +1,260 @@
+inherit kernel-arch
+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)
+}
+
+do_image_complete[postfuncs] += "do_assemble_recovery_ramdisk_fitimage"
+
+#
+# Emit the fitImage ITS header
+#
+fit_recovery_ramdisk_image_emit_fit_header() {
+ cat << EOF >> fit-recovery-ramdisk-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_ramdisk_image_emit_section_maint() {
+ case $1 in
+ imagestart)
+ cat << EOF >> fit-recovery-ramdisk-image.its
+
+ images {
+EOF
+ ;;
+ confstart)
+ cat << EOF >> fit-recovery-ramdisk-image.its
+
+ configurations {
+EOF
+ ;;
+ sectend)
+ cat << EOF >> fit-recovery-ramdisk-image.its
+ };
+EOF
+ ;;
+ fitend)
+ cat << EOF >> fit-recovery-ramdisk-image.its
+};
+EOF
+ ;;
+ esac
+}
+
+#
+# Emit the fitImage ITS kernel section
+#
+# $1 ... Image counter
+# $2 ... Path to kernel image
+# $3 ... Compression type
+fit_recovery_ramdisk_image_emit_section_kernel() {
+
+ if [ -n "${IMAGE_HASH_ALGO}" ] ; then
+ kernel_csum="${IMAGE_HASH_ALGO}"
+ else
+ kernel_csum="sha256"
+ fi
+
+ cat << EOF >> fit-recovery-ramdisk-image.its
+ kernel@${1} {
+ description = "Linux kernel";
+ data = /incbin/("${2}");
+ type = "kernel";
+ arch = "${ARCH}";
+ os = "linux";
+ compression = "${3}";
+ load = <${UBOOT_LOADADDRESS}>;
+ entry = <${UBOOT_ENTRYPOINT}>;
+ hash@1 {
+ algo = "${kernel_csum}";
+ };
+ };
+EOF
+}
+
+#
+# Emit the fitImage ITS recovery ramdisk section
+#
+# $1 ... Image counter
+# $2 ... Path to ramdifk image
+fitimage_emit_section_recovery_ramdisk() {
+
+ if [ -n "${IMAGE_HASH_ALGO}" ] ; then
+ ramdisk_csum="${IMAGE_HASH_ALGO}"
+ else
+ ramdisk_csum="sha256"
+ fi
+
+ cat << EOF >> fit-recovery-ramdisk-image.its
+ ramdisk@${1} {
+ description = "Ramdisk Image";
+ data = /incbin/("${2}");
+ type = "ramdisk";
+ arch = "${ARCH}";
+ os = "linux";
+ compression = "none";
+ load = <${RECOVERY_RAMDISK_LOADADDRESS}>;
+ entry = <${RECOVERY_RAMDISK_LOADADDRESS}>;
+ hash@1 {
+ algo = "${ramdisk_csum}";
+ };
+ };
+EOF
+}
+
+#
+# Emit the fitImage ITS DTB section
+#
+# $1 ... Image counter
+# $2 ... Path to DTB image
+fit_recovery_ramdisk_image_emit_section_dtb() {
+
+ if [ -n "${IMAGE_HASH_ALGO}" ] ; then
+ dtb_csum="${IMAGE_HASH_ALGO}"
+ else
+ dtb_csum="sha256"
+ fi
+
+ cat << EOF >> fit-recovery-ramdisk-image.its
+ fdt@${1} {
+ description = "Flattened Device Tree blob";
+ data = /incbin/("${2}");
+ type = "flat_dt";
+ arch = "${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
+fit_recovery_ramdisk_image_emit_section_config() {
+
+ if [ -n "${VB_HASH_ALGO}" -a -n "${VB_RSA_ALGO}" ] ; then
+ conf_csum="${VB_HASH_ALGO},${VB_RSA_ALGO}"
+ else
+ conf_csum="sha256,rsa2048"
+ fi
+ 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-recovery-ramdisk-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
+}
+
+do_assemble_recovery_ramdisk_fitimage() {
+ cd ${B}
+ if [ "x${KERNEL_IMAGETYPE}" = "xfitImage" -a -n "${RECOVERY_KERNEL_DEVICETREE}" ] ; then
+ kernelcount=1
+ dtbcount=1
+ ramdiskcount=1
+ rm -f fit-recovery-ramdisk-image.its
+
+ fit_recovery_ramdisk_image_emit_fit_header
+
+ #
+ # Step 1: Prepare a kernel image section.
+ #
+ fit_recovery_ramdisk_image_emit_section_maint imagestart
+
+ fit_recovery_ramdisk_image_emit_section_kernel ${kernelcount} ${DEPLOY_DIR_IMAGE}/${KERNEL_IMAGETYPE}-linux.bin-${MACHINE}.bin ${KERNEL_COMPRESS}
+
+ # Step 1.5: Prepare a ramdisk image section.
+ #
+ fitimage_emit_section_recovery_ramdisk ${ramdiskcount} ${IMGDEPLOYDIR}/${IMAGE_BASENAME}-${MACHINE}.${IMAGE_FSTYPES}
+
+ #
+ # Step 2: Prepare a DTB image section
+ #
+ if [ -n "${RECOVERY_KERNEL_DEVICETREE}" ] ; then
+ fit_recovery_ramdisk_image_emit_section_dtb ${dtbcount} ${DEPLOY_DIR_IMAGE}/${RECOVERY_KERNEL_DEVICETREE}
+ fi
+
+ fit_recovery_ramdisk_image_emit_section_maint sectend
+
+ #
+ # Step 3: Prepare a configurations section
+ #
+ fit_recovery_ramdisk_image_emit_section_maint confstart
+
+ fit_recovery_ramdisk_image_emit_section_config ${kernelcount} ${dtbcount} ${ramdiskcount}
+
+ fit_recovery_ramdisk_image_emit_section_maint sectend
+
+ fit_recovery_ramdisk_image_emit_section_maint fitend
+
+ #
+ # Step 4: Assemble the image
+ #
+ uboot-mkimage -f fit-recovery-ramdisk-image.its recovery.ramdisk.img
+
+ 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-ramdisk-image.its -r recovery.ramdisk.img
+ fi
+
+ #
+ # Step 5: Install the recovery.ramdisk.img and recovery fit to DEPLOY_DIR_IMAGE folder
+ #
+ install -d ${DEPLOY_DIR_IMAGE}
+ install -m 0644 fit-recovery-ramdisk-image.its recovery.ramdisk.img -t ${DEPLOY_DIR_IMAGE}
+
+ fi
+}
diff --git a/meta/meta-mediatek/classes/scpsys-fitimage.bbclass b/meta/meta-mediatek/classes/scpsys-fitimage.bbclass
new file mode 100644
index 0000000..9b3c8b0
--- /dev/null
+++ b/meta/meta-mediatek/classes/scpsys-fitimage.bbclass
@@ -0,0 +1,277 @@
+inherit hsm-sign-env
+
+python __anonymous () {
+ depends = d.getVar("DEPENDS", True)
+ depends = "%s u-boot-mkimage-native lz4-native dtc-native" % depends
+ d.setVar("DEPENDS", depends)
+}
+
+# $1 ... Set compress bin name
+tinysys_prep_image() {
+
+ tinysys_comp=${TINYSYS_COMPRESS}
+
+ if test "${tinysys_comp}" = "lz4"; then
+ tinysys_suffix=".lz4"
+ elif test "${tinysys_comp}" = "gzip"; then
+ tinysys_suffix=".gz"
+ else
+ tinysys_suffix=""
+ fi
+
+ if test "${tinysys_comp}" = "lz4"; then
+ lz4 -l -c1 ${1} > ${1}${tinysys_suffix}
+ # append uncompressed filesize info
+ dec_size=0
+ fsize=$(stat -c "%s" "${1}")
+ 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` >> ${1}${tinysys_suffix};
+ done;
+ }
+ elif test "${tinysys_comp}" = "gzip"; then
+ gzip -9 ${1}
+ else
+ echo "For none case or another compressing"
+ fi
+
+ if ! test "${tinysys_comp}" = "none"; then
+ mv -f "${1}${tinysys_suffix}" ${1}
+ else
+ echo "No tinysys compression"
+ fi
+
+ echo "${tinysys_comp}"
+}
+
+
+#
+# Emit the fitImage ITS header
+#
+fitimage_emit_fit_header() {
+ cat << EOF >> ${WORKDIR}/fit-image.its
+/dts-v1/;
+
+/ {
+ description = "scpsys fitImage for fusa";
+ #address-cells = <2>;
+EOF
+}
+
+#
+fitimage_emit_scpdata_fit_header() {
+ cat << EOF >> ${WORKDIR}/fit-image.its
+/dts-v1/;
+
+/ {
+ description = "scpdata fitImage for fusa";
+ #address-cells = <2>;
+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
+}
+
+fitimage_emit_section_scpsys() {
+
+ if [ -n "${IMAGE_HASH_ALGO}" ] ; then
+ tinysys_csum="${IMAGE_HASH_ALGO}"
+ else
+ tinysys_csum="sha256"
+ fi
+
+ cat << EOF >> ${WORKDIR}/fit-image.its
+ ${3}@1 {
+ description = "${4}";
+ data = /incbin/("${1}");
+ type = "${7}";
+ compression = "${2}";
+ load = <${5} ${6}>;
+ hash@1 {
+ algo = "sha256";
+ };
+ };
+EOF
+}
+
+fitimage_emit_section_scpdata() {
+
+ if [ -n "${IMAGE_HASH_ALGO}" ] ; then
+ tinysys_csum="${IMAGE_HASH_ALGO}"
+ else
+ tinysys_csum="sha256"
+ fi
+
+ cat << EOF >> ${WORKDIR}/fit-image.its
+ ${3}@1 {
+ description = "${3}";
+ data = /incbin/("${1}");
+ type = "loadable";
+ compression = "${2}";
+ load = <${4} ${5}>;
+ hash@1 {
+ algo = "sha256";
+ };
+ };
+EOF
+}
+
+#
+# Emit the fitImage ITS configuration section
+#
+fitimage_emit_section_config() {
+
+ if [ -n "${VB_HASH_ALGO}" ] && [ -n "${VB_RSA_ALGO}" ] ; then
+ conf_csum="${VB_HASH_ALGO},${VB_RSA_ALGO}"
+ else
+ conf_csum="sha256,rsa2048"
+ fi
+ conf_key_name="dev"
+
+ conf_desc="${MTK_PROJECT} configuration"
+
+ if [ ! -n "${FUSA_EATURE_ENABLE}" ]; then
+ dram_node="firmware = \"scp_dram@1\";"
+ dram_img_type=",\"firmware\";"
+ else
+ dram_img_type=";"
+ fi
+
+ cat << EOF >> ${WORKDIR}/fit-image.its
+ default = "conf@1";
+ conf@1 {
+ description = "${conf_desc}";
+ kernel = "scpsys@1";
+ ${dram_node}
+ signature@1 {
+ algo = "${conf_csum}";
+ key-name-hint="${conf_key_name}";
+ sign-images = "kernel"${dram_img_type}
+ };
+ };
+EOF
+}
+
+do_assemble_fitimage() {
+
+ rm -f ${WORKDIR}/fit-image.its
+
+ fitimage_emit_fit_header
+
+ #
+ # Step 1: Prepare a tinysys image section.
+ #
+ fitimage_emit_section_maint imagestart
+
+ # compress scp dram image using lz4
+ ${S}build/lz4_compress.sh ${S}tinysys-scp_out/freertos/source/${TINYSYS_DRAM_BIN} ${TINYSYS_COMPRESS}
+
+ fitimage_emit_section_scpsys ${S}tinysys-scp_out/freertos/source/${TINYSYS_BIN} \
+ none scpsys ${SCP_SRAM_DESCRIPTION} 0 ${SCP_SRAM_LOAD_ADDR} ${SCP_SRAM_TYPE}
+
+ # to decide if dram image need to be load or not
+ if [ ! -n "${FUSA_EATURE_ENABLE}" ]; then
+ if [ -n "${4GB_DRAM_PROJECT}" ]; then
+ fitimage_emit_section_scpsys ${S}tinysys-scp_out/freertos/source/${TINYSYS_DRAM_BIN}.${TINYSYS_COMPRESS} \
+ lz4 scp_dram ${SCP_DRAM_DESCRIPTION} ${SCP_4GB_DRAM_LOAD_ADDR_UPPER_BITS} ${SCP_4GB_DRAM_LOAD_ADDR_LOWER_BITS} ${SCP_DRAM_TYPE}
+ else
+ fitimage_emit_section_scpsys ${S}tinysys-scp_out/freertos/source/${TINYSYS_DRAM_BIN}.${TINYSYS_COMPRESS} \
+ lz4 scp_dram ${SCP_DRAM_DESCRIPTION} ${SCP_NON_4GB_DRAM_LOAD_ADDR_UPPER_BITS} ${SCP_NON_4GB_DRAM_LOAD_ADDR_LOWER_BITS} ${SCP_DRAM_TYPE}
+ fi
+ 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
+ #
+ 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 -k ./mykeys -f ${WORKDIR}/fit-image.its -r ${WORKDIR}/${TINYSYS_IMAGE}
+ cp ${WORKDIR}/fit-image.its ${WORKDIR}/scpsys-fit-image.its
+
+ # scp_data image
+ if [ ! -n "${FUSA_EATURE_ENABLE}" ]; then
+ rm -f ${WORKDIR}/fit-image.its
+
+ fitimage_emit_scpdata_fit_header
+
+ #
+ # Step 1: Prepare a tinysys image section.
+ #
+ fitimage_emit_section_maint imagestart
+
+ cp -f ${SCP_LOGO_IMAGE} ${S}tinysys-scp_out/scp-logo
+ cp -f ${SCP_WARNING_IMAGE} ${S}tinysys-scp_out/scp-warning
+ cp -f ${SCP_CVBS_IMAGE} ${S}tinysys-scp_out/scp-cvbs
+ cp -f ${SCP_GUIDELING} ${S}tinysys-scp_out/scp-guideline
+ tinysys_prep_image ${S}tinysys-scp_out/scp-logo
+ tinysys_prep_image ${S}tinysys-scp_out/scp-warning
+ tinysys_prep_image ${S}tinysys-scp_out/scp-cvbs
+ tinysys_prep_image ${S}tinysys-scp_out/scp-guideline
+ fitimage_emit_section_scpdata ${S}tinysys-scp_out/scp-logo ${TINYSYS_COMPRESS} logo 0 ${SCP_LOGO_LOAD_ADDRESS}
+ fitimage_emit_section_scpdata ${S}tinysys-scp_out/scp-warning ${TINYSYS_COMPRESS} warnmsg 0 ${SCP_WARNMSG_LOAD_ADDRESS}
+ fitimage_emit_section_scpdata ${S}tinysys-scp_out/scp-cvbs ${TINYSYS_COMPRESS} cvbsimg 0 ${SCP_CVBSIMG_LOAD_ADDRESS}
+ fitimage_emit_section_scpdata ${S}tinysys-scp_out/scp-guideline ${TINYSYS_COMPRESS} guideline 0 ${SCP_GUILDLINE_LOAD_ADDRESS}
+
+ fitimage_emit_section_maint sectend
+
+ fitimage_emit_section_maint fitend
+
+ #
+ # Step 3: Assemble the image
+ #
+ uboot-mkimage -f ${WORKDIR}/fit-image.its -r ${WORKDIR}/${TINYDATA_IMAGE}
+ cp ${WORKDIR}/fit-image.its ${WORKDIR}/scpdata-fit-image.its
+ fi
+}
+
+addtask assemble_fitimage before do_package after do_install
diff --git a/meta/meta-mediatek/classes/showinfo.bbclass b/meta/meta-mediatek/classes/showinfo.bbclass
new file mode 100644
index 0000000..ee415f3
--- /dev/null
+++ b/meta/meta-mediatek/classes/showinfo.bbclass
@@ -0,0 +1,56 @@
+
+python() {
+ bb.warn("====Start")
+ bb.warn("B=%s" % d.getVar('B', True))
+ bb.warn("S=%s" % d.getVar('S', True))
+ bb.warn("D=%s" % d.getVar('D', True))
+ bb.warn("CC=%s" % d.getVar('CC', True))
+
+ bb.warn("bindir=%s" % d.getVar('bindir', True))
+ bb.warn("libdir=%s" % d.getVar('libdir', True))
+ bb.warn("sbindir=%s" % d.getVar('sbindir', True))
+ bb.warn("includedir=%s" % d.getVar('includedir', True))
+ bb.warn("sysconfdir=%s " % d.getVar('sysconfdir', True))
+ bb.warn("datadir=%s " % d.getVar('datadir', True))
+ bb.warn("base_bindir=%s" % d.getVar('base_bindir', True))
+ bb.warn("base_libdir=%s " % d.getVar('base_libdir', True))
+ bb.warn("base_sbindir=%s " % d.getVar('base_sbindir', True))
+ bb.warn("base_includedir=%s " % d.getVar('base_includedir', True))
+ bb.warn("systemd_unitdir=%s " % d.getVar('systemd_unitdir', True))
+
+
+ bb.warn("STAGING_INCDIR=%s" % d.getVar('STAGING_INCDIR', True))
+ bb.warn("STAGING_LIBDIR=%s" % d.getVar('STAGING_LIBDIR', True))
+ bb.warn("STAGING_DIR=%s " % d.getVar('STAGING_DIR', True))
+ bb.warn("STAGING_DIR_HOST=%s " % d.getVar('STAGING_DIR_HOST', True) )
+
+ bb.warn("WORKDIR=%s" % d.getVar('WORKDIR', True))
+ bb.warn("WORKSPACE=%s " % d.getVar('WORKSPACE', True))
+ bb.warn("TOPDIR=%s " % d.getVar('TOPDIR', True))
+ bb.warn("MTK_SRC=%s " % d.getVar('MTK_SRC', True))
+
+ bb.warn("COMMON_LICENSE_DIR=%s" % d.getVar('COMMON_LICENSE_DIR', True))
+ bb.warn("TARGET_PREFIX=%s " % d.getVar('TARGET_PREFIX', True))
+ bb.warn("DISTRO_FEATURES=%s " % d.getVar('DISTRO_FEATURES', True))
+ bb.warn("BPN=%s " % d.getVar('BPN', True))
+ bb.warn("PN=%s " % d.getVar('PN', True))
+ bb.warn("FILE=%s " % d.getVar('FILE', d))
+ bb.warn("PACKAGES=%s " % d.getVar('PACKAGES', d))
+ bb.warn("FILES_PN=%s " % d.getVar('FILES_${PN}', d))
+
+ bb.warn("ARMPKGARCH=%s" % d.getVar('ARMPKGARCH', True))
+ bb.warn("TUNE_FEATURES=%s" % d.getVar('TUNE_FEATURES', True))
+ bb.warn("PACKAGE_EXTRA_ARCHS =%s" % d.getVar('PACKAGE_EXTRA_ARCHS', True))
+ bb.warn("TUNE_PKGARCH=%s" % d.getVar('TUNE_PKGARCH', True))
+ bb.warn("PACKAGE_ARCHS=%s" % d.getVar('PACKAGE_ARCHS', True))
+ bb.warn("PACKAGE_ARCH=%s" % d.getVar('PACKAGE_ARCH', True))
+ bb.warn("TUNEABI=%s" % d.getVar('TUNEABI', True))
+ bb.warn("TARGET_FPU=%s" % d.getVar('TARGET_FPU', True))
+ bb.warn("TARGET_ARCH=%s" % d.getVar('TARGET_ARCH', True))
+ bb.warn("TARGET_CC_ARCH=%s" % d.getVar('TARGET_CC_ARCH', True))
+ bb.warn("TARGET_CC_KERNEL_ARCH=%s" % d.getVar('TARGET_CC_KERNEL_ARCH', True))
+ bb.warn("MACHINE=%s" % d.getVar('MACHINE', True))
+ bb.warn("MACHINE_ARCH=%s" % d.getVar('MACHINE_ARCH', True))
+
+ bb.warn("====End")
+}
diff --git a/meta/meta-mediatek/classes/slimko.bbclass b/meta/meta-mediatek/classes/slimko.bbclass
new file mode 100644
index 0000000..94502f9
--- /dev/null
+++ b/meta/meta-mediatek/classes/slimko.bbclass
@@ -0,0 +1,12 @@
+#./slimko -i input.ko -o output.ko -c cross-compile-prefix
+
+SLIMKOTOOL="${TOPDIR}/../prebuilt/devtools/slimko/slimko"
+slim_kernel_module() {
+ install -d ${IMAGE_ROOTFS}/lib/modules
+ KERNEL_MODULES=$(find ${IMAGE_ROOTFS}/lib/modules -name "*.ko")
+ for i in ${KERNEL_MODULES}; do
+ ${SLIMKOTOOL} -i ${i} -o ${i} -c ${TARGET_PREFIX}
+ done
+}
+
+ROOTFS_POSTPROCESS_COMMAND += " slim_kernel_module;"
diff --git a/meta/meta-mediatek/classes/spmfw-fitimage.bbclass b/meta/meta-mediatek/classes/spmfw-fitimage.bbclass
new file mode 100644
index 0000000..54df817
--- /dev/null
+++ b/meta/meta-mediatek/classes/spmfw-fitimage.bbclass
@@ -0,0 +1,161 @@
+inherit hsm-sign-env
+
+python __anonymous () {
+ spmfwtype = d.getVar('SPMFW_IMAGETYPE', True)
+ if spmfwtype == 'fitImage':
+ depends = d.getVar("DEPENDS", True)
+ depends = "%s u-boot-mkimage-native lz4-native dtc-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 spm section
+#
+# $1 ... Path to spmfw image
+# $2 ... Compression type
+fitimage_emit_section_spmfw() {
+
+ if [ -n "${IMAGE_HASH_ALGO}" ] ; then
+ spmfw_csum="${IMAGE_HASH_ALGO}"
+ else
+ spmfw_csum="sha256"
+ fi
+
+ cat << EOF >> ${WORKDIR}/fit-image.its
+ spmfw@1 {
+ description = "SPM firmware";
+ data = /incbin/("${1}");
+ type = "kernel";
+ arch = "arm";
+ os = "linux";
+ compression = "${2}";
+ load = <${SPMFW_LOADADDRESS}>;
+ entry = <${SPMFW_ENTRYPOINT}>;
+ hash@1 {
+ algo = "${spmfw_csum}";
+ };
+ };
+EOF
+}
+
+#
+# Emit the fitImage ITS configuration section
+#
+# $1 ... spmfw image ID
+fitimage_emit_section_config() {
+
+ if [ -n "${VB_HASH_ALGO}" -a -n "${VB_RSA_ALGO}" ] ; then
+ conf_csum="${VB_HASH_ALGO},${VB_RSA_ALGO}"
+ else
+ conf_csum="sha256,rsa2048"
+ fi
+ conf_key_name="dev"
+ conf_desc="spmfw configuration"
+
+ spmfw_line="kernel = \"spmfw@1\";"
+ sign_images_line="sign-images = \"kernel\";"
+
+ cat << EOF >> ${WORKDIR}/fit-image.its
+ default = "conf@1";
+ conf@1 {
+ description = "${conf_desc}";
+ ${spmfw_line}
+ signature@1 {
+ algo = "${conf_csum}";
+ key-name-hint="${conf_key_name}";
+ ${sign_images_line}
+ };
+ };
+EOF
+}
+
+do_assemble_fitimage() {
+ rm -f ${WORKDIR}/fit-image.its
+
+ fitimage_emit_fit_header
+
+ #
+ # Step 1: Prepare a spmfw image section.
+ #
+ fitimage_emit_section_maint imagestart
+
+ fitimage_emit_section_spmfw ${SPMFW_OUT}/${SPMFW_BINARY_SELECT} ${SPMFW_COMPRESS}
+
+ 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
+ #
+ ${HSM_ENV} HSM_KEY_NAME=${VERIFIED_KEY} uboot-mkimage -f ${WORKDIR}/fit-image.its ${SPMFW_OUT}/${SPMFW_BINARY}
+
+ if [ "${SECURE_BOOT_ENABLE}" = "yes" ]; then
+ if [ "${STANDALONE_SIGN_PREPARE}" = "yes" ];then
+ exit 0
+ fi
+ 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 ${WORKDIR}/fit-image.its -r ${SPMFW_OUT}/${SPMFW_BINARY}
+ fi
+}
+
+addtask assemble_fitimage before do_install after do_compile
diff --git a/meta/meta-mediatek/classes/srcprebuilt.bbclass b/meta/meta-mediatek/classes/srcprebuilt.bbclass
new file mode 100644
index 0000000..945179b
--- /dev/null
+++ b/meta/meta-mediatek/classes/srcprebuilt.bbclass
@@ -0,0 +1,20 @@
+python () {
+
+ import os.path
+
+ srcpath = d.getVar('MTK_SRC', True)
+ prebuiltpath = srcpath.replace("build/../src/", "build/../prebuilt/")
+ if os.path.exists(srcpath+'/.git'):
+ d.setVar('MTK_SRC', srcpath)
+ elif os.path.exists(prebuiltpath+'/.git'):
+ d.setVar('MTK_SRC', prebuiltpath)
+ else:
+ bb.warn("Both %s and %s aren't existed" % (srcpath, prebuiltpath) )
+
+ d.setVar('B', d.getVar('MTK_SRC', True) )
+ d.setVar('S', d.getVar('MTK_SRC', True) )
+# bb.warn("MTK_SRC = %s" % d.getVar('MTK_SRC', True) )
+# bb.warn("EXTERNALSRC = %s" % d.getVar('EXTERNALSRC', True))
+# bb.warn("EXTERNALSRC_BUILD = %s" % d.getVar('EXTERNALSRC_BUILD', True) )
+
+}
diff --git a/meta/meta-mediatek/classes/sspm-fitimage.bbclass b/meta/meta-mediatek/classes/sspm-fitimage.bbclass
new file mode 100644
index 0000000..75fca59
--- /dev/null
+++ b/meta/meta-mediatek/classes/sspm-fitimage.bbclass
@@ -0,0 +1,161 @@
+inherit hsm-sign-env
+
+python __anonymous () {
+ depends = d.getVar("DEPENDS", True)
+ depends = "%s u-boot-mkimage-native dtc-native" % depends
+ d.setVar("DEPENDS", depends)
+}
+
+#
+# Emit the fitImage ITS header
+#
+fitimage_emit_fit_header() {
+ cat << EOF >> ${WORKDIR}/fit-image.its
+/dts-v1/;
+
+/ {
+ description = "SSPM fitImage";
+ #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 sspm section
+#
+# $1 ... Path to sspm image
+# $2 ... Compression type
+fitimage_emit_section_sspm() {
+
+ if [ -n "${IMAGE_HASH_ALGO}" ] ; then
+ sspm_csum="${IMAGE_HASH_ALGO}"
+ else
+ sspm_csum="sha256"
+ fi
+
+ cat << EOF >> ${WORKDIR}/fit-image.its
+ sspm@1 {
+ description = "SSPM firmware";
+ data = /incbin/("${1}");
+ type = "kernel";
+ arch = "arm";
+ os = "linux";
+ compression = "${2}";
+ load = <${SSPM_LOADADDRESS}>;
+ entry = <${SSPM_ENTRYPOINT}>;
+ hash@1 {
+ algo = "${sspm_csum}";
+ };
+ };
+EOF
+}
+
+#
+# Emit the fitImage ITS configuration section
+#
+# $1 ... sspm image ID
+fitimage_emit_section_config() {
+
+ if [ -n "${VB_HASH_ALGO}" -a -n "${VB_RSA_ALGO}" ] ; then
+ conf_csum="${VB_HASH_ALGO},${VB_RSA_ALGO}"
+ else
+ conf_csum="sha256,rsa2048"
+ fi
+ conf_key_name="dev"
+ conf_desc="sspm configuration"
+
+ sspm_line="kernel = \"sspm@1\";"
+ sign_images_line="sign-images = \"kernel\";"
+
+ cat << EOF >> ${WORKDIR}/fit-image.its
+ default = "conf@1";
+ conf@1 {
+ description = "${conf_desc}";
+ ${sspm_line}
+ signature@1 {
+ algo = "${conf_csum}";
+ key-name-hint="${conf_key_name}";
+ ${sign_images_line}
+ };
+ };
+EOF
+}
+
+do_assemble_fitimage() {
+
+ rm -f ${WORKDIR}/fit-image.its
+
+ fitimage_emit_fit_header
+
+ #
+ # Step 1: Prepare a sspm image section.
+ #
+ fitimage_emit_section_maint imagestart
+
+ fitimage_emit_section_sspm ${SSPM_OUT}/${SSPM_BINARY} ${SSPM_COMPRESS}
+
+ 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
+ #
+ ${HSM_ENV} HSM_KEY_NAME=${VERIFIED_KEY} uboot-mkimage -f ${WORKDIR}/fit-image.its ${WORKDIR}/${SSPM_IMAGE}
+
+ if [ "${SECURE_BOOT_ENABLE}" = "yes" ]; then
+ if [ "${STANDALONE_SIGN_PREPARE}" = "yes" ];then
+ exit 0
+ fi
+ 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 ${WORKDIR}/fit-image.its -r ${WORKDIR}/${SSPM_IMAGE}
+ fi
+}
+
+addtask assemble_fitimage before do_deploy after do_install
+
diff --git a/meta/meta-mediatek/classes/staging-copyfile.bbclass b/meta/meta-mediatek/classes/staging-copyfile.bbclass
new file mode 100644
index 0000000..9e37983
--- /dev/null
+++ b/meta/meta-mediatek/classes/staging-copyfile.bbclass
@@ -0,0 +1,29 @@
+# need to inherit this bbclass after core-image
+def staging_copyfile(c, target, dest, postinsts, seendirs):
+ import errno
+
+ destdir = os.path.dirname(dest)
+ if destdir not in seendirs:
+ bb.utils.mkdirhier(destdir)
+ seendirs.add(destdir)
+ if "/usr/bin/postinst-" in c:
+ postinsts.append(dest)
+ if os.path.islink(c):
+ linkto = os.readlink(c)
+ if os.path.lexists(dest):
+ if not os.path.islink(dest):
+ raise OSError(errno.EEXIST, "Link %s already exists as a file" % dest, dest)
+ if os.readlink(dest) == linkto:
+ return dest
+ raise OSError(errno.EEXIST, "Link %s already exists to a different location? (%s vs %s)" % (dest, os.readlink(dest), linkto), dest)
+ os.symlink(linkto, dest)
+ #bb.warn(c)
+ else:
+ try:
+ os.link(c, dest)
+ except OSError as err:
+ if err.errno == errno.EXDEV or err.errno == errno.EEXIST:
+ bb.utils.copyfile(c, dest)
+ else:
+ raise
+ return dest
diff --git a/meta/meta-mediatek/classes/tinysys-fitimage.bbclass b/meta/meta-mediatek/classes/tinysys-fitimage.bbclass
new file mode 100644
index 0000000..f348265
--- /dev/null
+++ b/meta/meta-mediatek/classes/tinysys-fitimage.bbclass
@@ -0,0 +1,150 @@
+inherit hsm-sign-env
+
+python __anonymous () {
+ depends = d.getVar("DEPENDS", True)
+ depends = "%s u-boot-mkimage-native lz4-native dtc-native" % depends
+ d.setVar("DEPENDS", depends)
+}
+
+#
+# Emit the fitImage ITS header
+#
+fitimage_emit_fit_header() {
+ cat << EOF >> ${WORKDIR}/fit-image.its
+/dts-v1/;
+
+/ {
+ description = "TINYSYS fitImage";
+ #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
+}
+
+fitimage_emit_section_tinysys() {
+
+ if [ -n "${IMAGE_HASH_ALGO}" ] ; then
+ tinysys_csum="${IMAGE_HASH_ALGO}"
+ else
+ tinysys_csum="sha256"
+ fi
+
+ cat << EOF >> ${WORKDIR}/fit-image.its
+ tinysys@1 {
+ description = "TINYSYS Image";
+ data = /incbin/("${1}");
+ type = "kernel";
+ arch = "arm";
+ os = "FreeRTOS";
+ compression = "${2}";
+ load = <${TINYSYS_LOADADDRESS}>;
+ entry = <${TINYSYS_ENTRYPOINT}>;
+ hash@1 {
+ algo = "${tinysys_csum}";
+ };
+ };
+EOF
+}
+
+#
+# Emit the fitImage ITS configuration section
+#
+fitimage_emit_section_config() {
+
+ if [ -n "${VB_HASH_ALGO}" ] && [ -n "${VB_RSA_ALGO}" ] ; then
+ conf_csum="${VB_HASH_ALGO},${VB_RSA_ALGO}"
+ else
+ conf_csum="sha256,rsa2048"
+ fi
+ conf_key_name="dev"
+
+ conf_desc="${MTK_PROJECT} configuration"
+
+ cat << EOF >> ${WORKDIR}/fit-image.its
+ default = "conf@1";
+ conf@1 {
+ description = "${conf_desc}";
+ kernel = "tinysys@1";
+ signature@1 {
+ algo = "${conf_csum}";
+ key-name-hint="${conf_key_name}";
+ sign-images = "kernel";
+ };
+ };
+EOF
+}
+
+do_assemble_fitimage() {
+
+ rm -f ${WORKDIR}/fit-image.its
+
+ fitimage_emit_fit_header
+
+ #
+ # Step 1: Prepare a tinysys image section.
+ #
+ fitimage_emit_section_maint imagestart
+
+
+ fitimage_emit_section_tinysys ${TINYSYS_OUT}/${TINYSYS_BIN}.bin ${TINYSYS_COMPRESS}
+
+ 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
+ #
+ ${HSM_ENV} HSM_KEY_NAME=${VERIFIED_KEY} uboot-mkimage -f ${WORKDIR}/fit-image.its ${WORKDIR}/${TINYSYS_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
+ ${HSM_ENV} HSM_KEY_NAME=${VERIFIED_KEY} uboot-mkimage -D "-I dts -O dtb -p 1024" -k ./mykeys -f ${WORKDIR}/fit-image.its -r ${WORKDIR}/${TINYSYS_IMAGE}
+ fi
+}
+
+addtask assemble_fitimage before do_package after do_install
diff --git a/meta/meta-mediatek/classes/trustzone-build.bbclass b/meta/meta-mediatek/classes/trustzone-build.bbclass
new file mode 100644
index 0000000..5ef0c63
--- /dev/null
+++ b/meta/meta-mediatek/classes/trustzone-build.bbclass
@@ -0,0 +1,122 @@
+TZ_BINARY = "tee.img"
+ATF_RAW_BINARY="atf_raw.img"
+ATF_SIGNED_BINARY="atf_signed.img"
+
+TZ_RAW_BINARY= "tz.raw.img"
+TZ_SIGNED_BINARY = "tz_signed.img"
+
+TZ_TMP_SIGNED_BINARY = "tz_tmp_signed.img"
+TZ_TMP_RAW_BINARY = "tz_tmp_raw.img"
+TZ_TMP_BINARY = "tz_tmp.img"
+
+TRUSTEDOS_RAW_BINARY = "trusedos.img"
+TRUSTEDOS_SIGNED_BINARY = "trusedos_signed.img"
+
+TZ_ASSEMBLE_OUT = "${DEPLOY_DIR}/images/${MACHINE}/trustzone"
+TL_ALIGN_SIZE = "0xb000"
+
+TRUSTZONE_VERSION = "20200422"
+
+do_mkdir_assemble () {
+ mkdir -p ${TZ_ASSEMBLE_OUT}
+}
+addtask mkdir_assemble before do_compile after do_configure
+
+python __anonymous () {
+ tee_loadaddress = d.getVar('TRUSTZONE_LOADADDRESS', True)
+ tee_entrypoint = d.getVar('TRUSTZONE_ENTRYPOINT', True)
+ if tee_loadaddress is None or tee_entrypoint is None:
+ return
+ else:
+ tee_loadaddress = int(tee_loadaddress, 16)
+ tee_entrypoint = int(tee_entrypoint, 16)
+
+ tl_align_size = int(d.getVar('TL_ALIGN_SIZE', True), 16)
+ tee_loadaddress = tee_loadaddress - tl_align_size
+ tee_loadaddress_str = hex(tee_loadaddress).replace('L', '')
+ d.setVar('TEE_LOADADDRESS', tee_loadaddress_str)
+
+ tee_entrypoint = tee_entrypoint - tl_align_size
+ tee_entrypoint_str = hex(tee_entrypoint).replace('L', '')
+ d.setVar('TEE_ENTRYPOINT', tee_entrypoint_str)
+
+ image_desc = d.getVar('DESCRIPTION', True)
+ if image_desc == 'ARM trusted firmware':
+ atf_src = d.getVar('MTK_SRC', True)
+ mach_type = d.getVar('MTK_MACH_TYPE', True)
+ tee_support = d.getVar('TEE_SUPPORT', True)
+ atf_ver = d.getVar('ATF_VER', True)
+
+ if os.path.exists(atf_src+'/.git'):
+ bb.warn('please change your atf folder to new layout')
+ # backward to old atf layout
+ # change the mt8516 to v1.21 folder
+ # others remain the original path
+ if mach_type == "mt8516":
+ d.setVar('ATF_VER','1.21')
+ else:
+ # new atf layout, change to use folder atf_tbase
+ # if tee_support is tbase and atf version is 1.0
+ if tee_support == 'tbase' and atf_ver == '1.0':
+ d.setVar('B',atf_src+'_'+tee_support)
+ else:
+ # change folder to CHIP_TYPE {mt2xxx/mt8xxx}
+ tgtplt = d.getVar('TARGET_PLATFORM', True)
+ if tgtplt[0:3] == "mt2":
+ d.setVar('CHIP_TYPE', tgtplt[0:3]+'xxx')
+ else:
+ atf_path = os.path.join(atf_src,"v"+atf_ver,tgtplt)
+ if os.path.exists(atf_path+'/.git'):
+ d.setVar('CHIP_TYPE', tgtplt)
+ else:
+ d.setVar('CHIP_TYPE', 'mt8xxx')
+
+ if image_desc == 'TrustZone Image':
+ multilibs = d.getVar('MULTILIBS', True)
+ if multilibs == 'multilib:lib64':
+ d.appendVarFlag('do_cleansstate', 'depends', ' lib64-teeloader:do_cleansstate')
+ d.appendVarFlag('do_compile', 'depends', ' lib64-teeloader:do_deploy')
+ else:
+ d.appendVarFlag('do_cleansstate', 'depends', ' teeloader:do_cleansstate')
+ d.appendVarFlag('do_compile', 'depends', ' teeloader:do_deploy')
+
+ atfsupport = d.getVar('ATF_SUPPORT', True)
+ if atfsupport == 'yes':
+ if multilibs == 'multilib:lib64':
+ d.appendVarFlag('do_cleansstate', 'depends', ' lib64-atf:do_cleansstate')
+ d.appendVarFlag('do_compile', 'depends', ' lib64-atf:do_deploy')
+ else:
+ d.appendVarFlag('do_cleansstate', 'depends', ' atf:do_cleansstate')
+ d.appendVarFlag('do_compile', 'depends', ' atf:do_deploy')
+
+ tee_support = d.getVar('TEE_SUPPORT', True)
+ if tee_support is None:
+ tee_support = "mtee"
+ d.appendVarFlag('do_cleansstate', 'depends', ' tee-'+tee_support+':do_cleansstate')
+ d.appendVarFlag('do_compile', 'depends', ' tee-'+tee_support+':do_deploy')
+ if tee_support == 'optee':
+ if multilibs == 'multilib:lib64':
+ d.appendVarFlag('do_cleansstate', 'depends', ' lib64-optee-os:do_cleansstate')
+ d.appendVarFlag('do_compile', 'depends', ' lib64-optee-os:do_deploy')
+ else:
+ d.appendVarFlag('do_cleansstate', 'depends', ' optee-os:do_cleansstate')
+ d.appendVarFlag('do_compile', 'depends', ' optee-os:do_deploy')
+ elif tee_support != 'none':
+ if multilibs == 'multilib:lib64':
+ d.appendVarFlag('do_cleansstate', 'depends', ' lib64-tee-'+tee_support+':do_cleansstate')
+ d.appendVarFlag('do_compile', 'depends', ' lib64-tee-'+tee_support+':do_deploy')
+ else:
+ d.appendVarFlag('do_cleansstate', 'depends', ' tee-'+tee_support+':do_cleansstate')
+ d.appendVarFlag('do_compile', 'depends', ' tee-'+tee_support+':do_deploy')
+
+ secure_boot_enable = d.getVar('SECURE_BOOT_ENABLE', True)
+ force_disable_tee_encryption = d.getVar('FORCE_DISABLE_TEE_ENCRYPTION', True)
+ if secure_boot_enable == 'yes' and force_disable_tee_encryption != 'yes' :
+ d.setVar("ATF_BINARY_SELECT", '${ATF_SIGNED_BINARY}')
+ d.setVar("TZ_BINARY_SELECT", '${TZ_SIGNED_BINARY}')
+ d.setVar("TRUSTEDOS_BINARY_SELECT", '${TRUSTEDOS_SIGNED_BINARY}')
+ else:
+ d.setVar("ATF_BINARY_SELECT", '${ATF_RAW_BINARY}')
+ d.setVar("TZ_BINARY_SELECT", '${TZ_RAW_BINARY}')
+ d.setVar("TRUSTEDOS_BINARY_SELECT", '${TRUSTEDOS_RAW_BINARY}')
+}
diff --git a/meta/meta-mediatek/classes/trustzone-fitimage.bbclass b/meta/meta-mediatek/classes/trustzone-fitimage.bbclass
new file mode 100644
index 0000000..0572ee4
--- /dev/null
+++ b/meta/meta-mediatek/classes/trustzone-fitimage.bbclass
@@ -0,0 +1,223 @@
+inherit hsm-sign-env
+
+python __anonymous () {
+ depends = d.getVar("DEPENDS", True)
+ depends = "%s u-boot-mkimage-native lz4-native" % depends
+ d.setVar("DEPENDS", depends)
+}
+
+#
+# Emit the fitImage ITS header
+#
+fitimage_emit_fit_header() {
+ cat << EOF >> ${WORKDIR}/fit-image.its
+/dts-v1/;
+
+/ {
+ description = "Trustzone fitimage for ${DISTRO_NAME}/${PV}/${MACHINE} ver:${TRUSTZONE_VERSION}";
+ #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
+}
+
+fitimage_emit_section_trustedos() {
+
+ if [ -n "${IMAGE_HASH_ALGO}" ] ; then
+ trustedos_csum="${IMAGE_HASH_ALGO}"
+ else
+ trustedos_csum="sha256"
+ fi
+
+ cat << EOF >> ${WORKDIR}/fit-image.its
+ trustedos@1 {
+ description = "Trusted OS Image";
+ data = /incbin/("${1}");
+ type = "tee";
+ arch = "arm";
+ os = "linux";
+ compression = "${2}";
+ load = <${TRUSTEDOS_LOADADDRESS}>;
+ entry = <${TRUSTEDOS_ENTRYPOINT}>;
+ hash@1 {
+ algo = "${trustedos_csum}";
+ };
+ };
+EOF
+}
+
+#
+# Emit the fitImage ITS trustzone section
+#
+# $1 ... Path to trustzone image
+# $2 ... Compression type
+fitimage_emit_section_trustzone() {
+
+ if [ -n "${IMAGE_HASH_ALGO}" ] ; then
+ trustzone_csum="${IMAGE_HASH_ALGO}"
+ else
+ trustzone_csum="sha256"
+ fi
+
+if [ -d ${TL_SRC} ]; then
+ cat << EOF >> ${WORKDIR}/fit-image.its
+ tee@1 {
+ description = "Tee Image";
+ data = /incbin/("${1}");
+ type = "kernel";
+ arch = "arm";
+ os = "linux";
+ compression = "${2}";
+ load = <${TEE_LOADADDRESS}>;
+ entry = <${TEE_ENTRYPOINT}>;
+ hash@1 {
+ algo = "${trustzone_csum}";
+ };
+ };
+EOF
+else
+ cat << EOF >> ${WORKDIR}/fit-image.its
+ tee@1 {
+ description = "Tee Image";
+ data = /incbin/("${1}");
+ type = "kernel";
+ arch = "arm";
+ os = "linux";
+ compression = "${2}";
+ load = <${TRUSTZONE_LOADADDRESS}>;
+ entry = <${TRUSTZONE_ENTRYPOINT}>;
+ hash@1 {
+ algo = "${trustzone_csum}";
+ };
+ };
+EOF
+fi
+}
+
+#
+# Emit the fitImage ITS configuration section
+#
+# $1 ... trustzone image ID
+fitimage_emit_section_config() {
+
+ if [ -n "${VB_HASH_ALGO}" ] && [ -n "${VB_RSA_ALGO}" ] ; then
+ conf_csum="${VB_HASH_ALGO},${VB_RSA_ALGO}"
+ else
+ conf_csum="sha256,rsa2048"
+ fi
+ conf_key_name="dev"
+
+ conf_desc="${MTK_PROJECT} configuration"
+
+ trustzone_line="kernel = \"tee@1\";"
+ if [ -n "${TRUSTEDOS_ENTRYPOINT}" ] && [ -n "${TRUSTEDOS_LOADADDRESS}" ] ; then
+ trustedos_line="tee = \"trustedos@1\";"
+ sign_images_line="sign-images = \"kernel\", \"tee\";"
+ else
+ trustedos_line=""
+ sign_images_line="sign-images = \"kernel\";"
+ fi
+
+ cat << EOF >> ${WORKDIR}/fit-image.its
+ default = "conf@1";
+ conf@1 {
+ description = "${conf_desc}";
+ ${trustzone_line}
+ ${trustedos_line}
+ signature@1 {
+ algo = "${conf_csum}";
+ key-name-hint="${conf_key_name}";
+ ${sign_images_line}
+ };
+ };
+EOF
+}
+
+do_assemble_fitimage() {
+
+ rm -f ${WORKDIR}/fit-image.its
+
+ fitimage_emit_fit_header
+
+ #
+ # Step 1: Prepare a trustzone image section.
+ #
+ fitimage_emit_section_maint imagestart
+
+ #uboot_prep_kimage
+ if [ -d ${TL_SRC} ]; then
+ if [ "${SECURE_BOOT_ENABLE}" = "yes" ] && [ "${FORCE_DISABLE_TEE_ENCRYPTION}" != "yes" ]; then
+ fitimage_emit_section_trustzone ${TZ_ASSEMBLE_OUT}/${TZ_TMP_SIGNED_BINARY} ${TRUSTZONE_COMPRESS}
+ if [ -n "${TRUSTEDOS_ENTRYPOINT}" ] && [ -n "${TRUSTEDOS_LOADADDRESS}" ] ; then
+ fitimage_emit_section_trustedos ${TZ_ASSEMBLE_OUT}/${TRUSTEDOS_SIGNED_BINARY} ${TRUSTZONE_COMPRESS}
+ fi
+ else
+ fitimage_emit_section_trustzone ${TZ_ASSEMBLE_OUT}/${TZ_TMP_RAW_BINARY} ${TRUSTZONE_COMPRESS}
+ if [ -n "${TRUSTEDOS_ENTRYPOINT}" ] && [ -n "${TRUSTEDOS_LOADADDRESS}" ] ; then
+ fitimage_emit_section_trustedos ${TZ_ASSEMBLE_OUT}/${TRUSTEDOS_RAW_BINARY} ${TRUSTZONE_COMPRESS}
+ fi
+ fi
+ else
+ fitimage_emit_section_trustzone ${TZ_ASSEMBLE_OUT}/${TZ_RAW_BINARY} ${TRUSTZONE_COMPRESS}
+ 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
+ #
+ ${HSM_ENV} HSM_KEY_NAME=${VERIFIED_KEY} uboot-mkimage -f ${WORKDIR}/fit-image.its ${TZ_ASSEMBLE_OUT}/${TZ_BINARY}
+
+ if [ "${SECURE_BOOT_ENABLE}" = "yes" ] && [ "${STANDALONE_SIGN_PREPARE}" != "yes" ]; then
+ mkdir -p ./mykeys
+ cp -f ${MTK_KEY_DIR}/${VERIFIED_KEY}.crt ./mykeys/dev.crt
+ cp -f ${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 ${WORKDIR}/fit-image.its -r ${TZ_ASSEMBLE_OUT}/${TZ_BINARY}
+ fi
+}
+
+addtask assemble_fitimage before do_install after do_compile
diff --git a/meta/meta-mediatek/classes/u-boot-fitimage.bbclass b/meta/meta-mediatek/classes/u-boot-fitimage.bbclass
new file mode 100644
index 0000000..ffdc171
--- /dev/null
+++ b/meta/meta-mediatek/classes/u-boot-fitimage.bbclass
@@ -0,0 +1,202 @@
+
+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() {
+
+ if [ -n "${IMAGE_HASH_ALGO}" ] ; then
+ uboot_csum="${IMAGE_HASH_ALGO}"
+ else
+ uboot_csum="sha256"
+ fi
+
+ cat << EOF >> ${WORKDIR}/fit-image.its
+ kernel@1 {
+ description = "U-Boot";
+ data = /incbin/("${1}");
+ type = "kernel";
+ 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() {
+
+ if [ -n "${IMAGE_HASH_ALGO}" ] ; then
+ dtb_csum="${IMAGE_HASH_ALGO}"
+ else
+ dtb_csum="sha256"
+ fi
+
+ cat << EOF >> ${WORKDIR}/fit-image.its
+ fdt@1 {
+ description = "sig blob for u-boot verified boot";
+ data = /incbin/("${1}");
+ type = "kernel";
+ 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() {
+
+ if [ -n "${VB_HASH_ALGO}" -a -n "${VB_RSA_ALGO}" ] ; then
+ conf_csum="${VB_HASH_ALGO},${VB_RSA_ALGO}"
+ else
+ conf_csum="sha256,rsa2048"
+ fi
+ conf_key_name="dev"
+
+ conf_desc="${MTK_PROJECT} configuration"
+
+ uboot_line="kernel = \"kernel@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","kernel";
+ };
+ };
+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
+ #
+ dtc -p 0x3ff ${WORKDIR}/u-boot.dts -O dtb -o ${UBOOT_OUT}/sig_blob.dtb
+ uboot-mkimage -f ${WORKDIR}/fit-image.its ${UBOOT_OUT}/${UBOOT_FIT_IMAGE}
+
+ if [ "${SECURE_BOOT_ENABLE}" = "yes" ]; then
+ if [ "${STANDALONE_SIGN_PREPARE}" = "yes" ]; then
+ exit 0
+ fi
+ mkdir -p ./mykeys
+ cp ${MTK_KEY_DIR}/${VERIFIED_KEY}.crt ./mykeys/dev.crt
+ cp ${MTK_KEY_DIR}/${VERIFIED_KEY}.pem ./mykeys/dev.key
+ ${UBOOT_OUT}/tools/mkimage -D "-I dts -O dtb -p 1024" -k ./mykeys -f ${WORKDIR}/fit-image.its -K ${UBOOT_OUT}/sig_blob.dtb -r ${UBOOT_OUT}/${UBOOT_FIT_IMAGE}
+ 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/classes/workonsrc.bbclass b/meta/meta-mediatek/classes/workonsrc.bbclass
new file mode 100644
index 0000000..1137e98
--- /dev/null
+++ b/meta/meta-mediatek/classes/workonsrc.bbclass
@@ -0,0 +1,301 @@
+# 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')
+ workonsrcbuild = d.getVar('WORKONSRC_BUILD')
+ if workonsrc and not workonsrc.startswith("/"):
+ bb.error("WORKONSRC must be an absolute path")
+ if workonsrcbuild and not workonsrcbuild.startswith("/"):
+ bb.error("WORKONSRC_BUILD must be an absolute path")
+
+ 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')
+ classextend = (d.getVar('BBCLASSEXTEND') or '').split()
+ if bpn == d.getVar('PN') or not classextend:
+ 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:
+ import oe.recipeutils
+ import oe.path
+
+ d.setVar('S', workonsrc)
+ 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')
+
+ if d.getVar('CONFIGUREOPT_DEPTRACK') == '--disable-dependency-tracking':
+ d.setVar('CONFIGUREOPT_DEPTRACK', '')
+
+ 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 = oe.recipeutils.split_var_value(d.getVarFlag(task, 'cleandirs', False) or '')
+ setvalue = False
+ for cleandir in cleandirs[:]:
+ if oe.path.is_path_parent(workonsrc, d.expand(cleandir)):
+ 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
+ rm -f ${@' '.join([x.split(':')[0] for x in (d.getVar('EXTERNALSRC_SYMLINKS') or '').split()])}
+ if [ "${CLEANBROKEN}" != "1" ]; then
+ oe_runmake clean || die "make failed"
+ fi
+ 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 = None
+
+ try:
+ git_dir = os.path.join(s_dir,
+ subprocess.check_output(['git', '-C', s_dir, 'rev-parse', '--git-dir'], stderr=subprocess.DEVNULL).decode("utf-8").rstrip())
+ except subprocess.CalledProcessError:
+ pass
+
+ ret = " "
+ if git_dir is not None:
+ oe_hash_file = os.path.join(git_dir, 'oe-devtool-tree-sha1')
+ with tempfile.NamedTemporaryFile(prefix='oe-devtool-index') as tmp_index:
+ # Clone index
+ shutil.copyfile(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
diff --git a/meta/meta-mediatek/conf/layer.conf b/meta/meta-mediatek/conf/layer.conf
new file mode 100644
index 0000000..235a09c
--- /dev/null
+++ b/meta/meta-mediatek/conf/layer.conf
@@ -0,0 +1,11 @@
+# We have a conf and classes directory, add to BBPATH
+BBPATH .= ":${LAYERDIR}"
+
+# We have a recipes-* directories, add to BBFILES
+BBFILES += "${LAYERDIR}/recipes-*/*/*.bb \
+ ${LAYERDIR}/recipes-*/*/*.bbappend"
+
+BBFILE_COLLECTIONS += "mediatek"
+BBFILE_PATTERN_mediatek = "^${LAYERDIR}/"
+BBFILE_PRIORITY_mediatek = "8"
+LICENSE_PATH += "${LAYERDIR}/files/additional-licenses"
diff --git a/meta/meta-mediatek/conf/machine/arch-arm64-tune-cortexa7-multilib.inc b/meta/meta-mediatek/conf/machine/arch-arm64-tune-cortexa7-multilib.inc
new file mode 100644
index 0000000..eac89ac
--- /dev/null
+++ b/meta/meta-mediatek/conf/machine/arch-arm64-tune-cortexa7-multilib.inc
@@ -0,0 +1,36 @@
+DEFAULTTUNE ?= "aarch64"
+
+require conf/machine/include/tune-cortexa7.inc
+
+TUNEVALID[aarch64] = "Enable instructions for aarch64"
+
+MACHINEOVERRIDES .= "${@bb.utils.contains('TUNE_FEATURES', 'aarch64', ':aarch64', '' ,d)}"
+
+# Little Endian base configs
+AVAILTUNES += "aarch64 aarch64_be"
+ARMPKGARCH_tune-aarch64 ?= "aarch64"
+ARMPKGARCH_tune-aarch64_be ?= "aarch64_be"
+TUNE_FEATURES_tune-aarch64 = "aarch64"
+TUNE_FEATURES_tune-aarch64_be = "${TUNE_FEATURES_tune-aarch64} bigendian"
+BASE_LIB_tune-aarch64 = "lib64"
+BASE_LIB_tune-aarch64_be = "lib64"
+
+PACKAGE_EXTRA_ARCHS_tune-aarch64 = "aarch64"
+PACKAGE_EXTRA_ARCHS_tune-aarch64_be = "aarch64_be"
+
+ARMPKGSFX_ENDIAN_64 = "${@bb.utils.contains('TUNE_FEATURES', 'bigendian', '_be', '', d)}"
+TUNE_ARCH_64 = "aarch64${ARMPKGSFX_ENDIAN_64}"
+TUNE_PKGARCH_64 = "aarch64${ARMPKGSFX_ENDIAN_64}"
+ABIEXTENSION_64 = ""
+TARGET_FPU_64 = ""
+
+# Duplicated from arch-arm.inc
+TUNE_ARCH_32 = "${@bb.utils.contains('TUNE_FEATURES', 'bigendian', 'armeb', 'arm', d)}"
+TUNE_PKGARCH_32 = "${ARMPKGARCH}${ARMPKGSFX_THUMB}${ARMPKGSFX_DSP}${ARMPKGSFX_EABI}${ARMPKGSFX_ENDIAN}${ARMPKGSFX_FPU}"
+ABIEXTENSION_32 = "eabi"
+TARGET_FPU_32 = "${@d.getVar('TUNE_CCARGS_MFLOAT', True) or 'soft'}"
+
+TUNE_ARCH = "${@bb.utils.contains('TUNE_FEATURES', 'aarch64', '${TUNE_ARCH_64}', '${TUNE_ARCH_32}' ,d)}"
+TUNE_PKGARCH = "${@bb.utils.contains('TUNE_FEATURES', 'aarch64', '${TUNE_PKGARCH_64}', '${TUNE_PKGARCH_32}' ,d)}"
+ABIEXTENSION = "${@bb.utils.contains('TUNE_FEATURES', 'aarch64', '${ABIEXTENSION_64}', '${ABIEXTENSION_32}' ,d)}"
+TARGET_FPU = "${@bb.utils.contains('TUNE_FEATURES', 'aarch64', '${TARGET_FPU_64}', '${TARGET_FPU_32}' ,d)}"
\ No newline at end of file
diff --git a/meta/meta-mediatek/conf/machine/keys/dm_key b/meta/meta-mediatek/conf/machine/keys/dm_key
new file mode 100644
index 0000000..8994c46
--- /dev/null
+++ b/meta/meta-mediatek/conf/machine/keys/dm_key
@@ -0,0 +1 @@
+12121212121212121212121212121212
\ No newline at end of file
diff --git a/meta/meta-mediatek/conf/machine/keys/dm_protect_enc_key b/meta/meta-mediatek/conf/machine/keys/dm_protect_enc_key
new file mode 100644
index 0000000..8994c46
--- /dev/null
+++ b/meta/meta-mediatek/conf/machine/keys/dm_protect_enc_key
@@ -0,0 +1 @@
+12121212121212121212121212121212
\ No newline at end of file
diff --git a/meta/meta-mediatek/conf/machine/keys/dm_protect_key b/meta/meta-mediatek/conf/machine/keys/dm_protect_key
new file mode 100644
index 0000000..8994c46
--- /dev/null
+++ b/meta/meta-mediatek/conf/machine/keys/dm_protect_key
@@ -0,0 +1 @@
+12121212121212121212121212121212
\ No newline at end of file
diff --git a/meta/meta-mediatek/conf/machine/keys/p256_priv.pem b/meta/meta-mediatek/conf/machine/keys/p256_priv.pem
new file mode 100644
index 0000000..f5e8e4f
--- /dev/null
+++ b/meta/meta-mediatek/conf/machine/keys/p256_priv.pem
@@ -0,0 +1,5 @@
+-----BEGIN EC PRIVATE KEY-----
+MHcCAQEEIDYSK3F8hpjB9mGzFcdSdLXjlsF2Ewc24a5vuDyFrwJGoAoGCCqGSM49
+AwEHoUQDQgAEghPafeZCbrTiTRd6ruv9+OKBF76v+iF8V5UvVyj3CsjSrwsN7Wkc
+ovk8wiaZ9YFLoxDuAEAD0kQpre8JRuGrMg==
+-----END EC PRIVATE KEY-----
diff --git a/meta/meta-mediatek/conf/machine/keys/p256_public.pem b/meta/meta-mediatek/conf/machine/keys/p256_public.pem
new file mode 100644
index 0000000..baafd35
--- /dev/null
+++ b/meta/meta-mediatek/conf/machine/keys/p256_public.pem
@@ -0,0 +1,4 @@
+-----BEGIN PUBLIC KEY-----
+MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEghPafeZCbrTiTRd6ruv9+OKBF76v
++iF8V5UvVyj3CsjSrwsN7Wkcovk8wiaZ9YFLoxDuAEAD0kQpre8JRuGrMg==
+-----END PUBLIC KEY-----
diff --git a/meta/meta-mediatek/conf/machine/keys/p384_priv.pem b/meta/meta-mediatek/conf/machine/keys/p384_priv.pem
new file mode 100644
index 0000000..4eaf48f
--- /dev/null
+++ b/meta/meta-mediatek/conf/machine/keys/p384_priv.pem
@@ -0,0 +1,6 @@
+-----BEGIN EC PRIVATE KEY-----
+MIGkAgEBBDDcjiFU90/TDkdZYnRauT7pOKy/1iCsByv+ol9LhsqNFstWIPVwkEO+
+0c3/jbiDnOGgBwYFK4EEACKhZANiAARs1XcpFvklJJ4Citawj8HbjxTtAtnQt77S
+NEVMeX9HZfw4hZRw43e7l8Q6q3YKC/r+X0HDikibWwVPCdZ2mqnejKSh8cy4uoUz
+AMQuv6m9DXAlSmS9AIlkAM/LjEUmXDU=
+-----END EC PRIVATE KEY-----
diff --git a/meta/meta-mediatek/conf/machine/keys/p384_public.pem b/meta/meta-mediatek/conf/machine/keys/p384_public.pem
new file mode 100644
index 0000000..2c8400b
--- /dev/null
+++ b/meta/meta-mediatek/conf/machine/keys/p384_public.pem
@@ -0,0 +1,5 @@
+-----BEGIN PUBLIC KEY-----
+MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEbNV3KRb5JSSeAorWsI/B248U7QLZ0Le+
+0jRFTHl/R2X8OIWUcON3u5fEOqt2Cgv6/l9Bw4pIm1sFTwnWdpqp3oykofHMuLqF
+MwDELr+pvQ1wJUpkvQCJZADPy4xFJlw1
+-----END PUBLIC KEY-----
diff --git a/meta/meta-mediatek/conf/machine/keys/p521_priv.pem b/meta/meta-mediatek/conf/machine/keys/p521_priv.pem
new file mode 100644
index 0000000..1e37a5f
--- /dev/null
+++ b/meta/meta-mediatek/conf/machine/keys/p521_priv.pem
@@ -0,0 +1,7 @@
+-----BEGIN EC PRIVATE KEY-----
+MIHcAgEBBEIBlkhO++c7bWC5ax6eUq9eH8UyfjrT8Xv7tbgH44Z+Kmejr9srVqsN
+LpOnfegheWJwLDU8LsExJDyi7wWMkuJ6mkOgBwYFK4EEACOhgYkDgYYABAAH8JXj
+QOqfKJ8SbojneYn2wKgy62zPiA4A65xacs8tY0tQRdeag24mzBQD3uHUwwkLTJqF
+970Ifgl4bHDM655ATQBW87RCN1/UhR43J9Fh7gPegaz6z1VstaArfajMht7OEUQn
+ELLZnrucgpj1puZeX9Cjd8qpbhBAZDbLaZjyFafffg==
+-----END EC PRIVATE KEY-----
diff --git a/meta/meta-mediatek/conf/machine/keys/p521_public.pem b/meta/meta-mediatek/conf/machine/keys/p521_public.pem
new file mode 100644
index 0000000..9e67402
--- /dev/null
+++ b/meta/meta-mediatek/conf/machine/keys/p521_public.pem
@@ -0,0 +1,6 @@
+-----BEGIN PUBLIC KEY-----
+MIGbMBAGByqGSM49AgEGBSuBBAAjA4GGAAQAB/CV40DqnyifEm6I53mJ9sCoMuts
+z4gOAOucWnLPLWNLUEXXmoNuJswUA97h1MMJC0yahfe9CH4JeGxwzOueQE0AVvO0
+Qjdf1IUeNyfRYe4D3oGs+s9VbLWgK32ozIbezhFEJxCy2Z67nIKY9abmXl/Qo3fK
+qW4QQGQ2y2mY8hWn334=
+-----END PUBLIC KEY-----
diff --git a/meta/meta-mediatek/conf/machine/keys/plain_rootfs_enc_key b/meta/meta-mediatek/conf/machine/keys/plain_rootfs_enc_key
new file mode 100644
index 0000000..b201ccd
--- /dev/null
+++ b/meta/meta-mediatek/conf/machine/keys/plain_rootfs_enc_key
@@ -0,0 +1 @@
+Ödî0 (”hö \êO0ƒëҫ‰yÔʽÉ?±þÝ
\ No newline at end of file
diff --git a/meta/meta-mediatek/conf/machine/keys/rootfs_enc_iv b/meta/meta-mediatek/conf/machine/keys/rootfs_enc_iv
new file mode 100644
index 0000000..adebada
--- /dev/null
+++ b/meta/meta-mediatek/conf/machine/keys/rootfs_enc_iv
@@ -0,0 +1,2 @@
+u3Ën
+„=|1?yõG©£
\ No newline at end of file
diff --git a/meta/meta-mediatek/conf/machine/keys/sbc_key.crt b/meta/meta-mediatek/conf/machine/keys/sbc_key.crt
new file mode 100644
index 0000000..93969ef
--- /dev/null
+++ b/meta/meta-mediatek/conf/machine/keys/sbc_key.crt
@@ -0,0 +1,21 @@
+-----BEGIN CERTIFICATE-----
+MIIDXTCCAkWgAwIBAgIJALSj3Ybyqlo4MA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV
+BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX
+aWRnaXRzIFB0eSBMdGQwHhcNMTcwMjEwMDMwOTUyWhcNMTcwMzEyMDMwOTUyWjBF
+MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50
+ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
+CgKCAQEA0mlxI+3vrVlX8wH23CeTPDIH3c4DhEQNIGQltziYX7DOAHyft/5s9TXA
+OmqIY0cyrQsjw837aiN3QGXONeQorP4+G5wlzWESJeJyAGlZ11hSijVpQQFwCT++
++k4L8SEoMIgJUMNVd9pESqCYf08nhJXc/qgn++YiG8tMvHz9IA/Ef4OKXNj/+1+X
+yrtYRgYpfOwsoCgbe01NEpV3vM61fW0g3EtCQXW7MOD5VIWMkvTt+ob4qTF5/HpR
+lIJ5nth/8ZktkCx51Lu6yhQ1fw3KKPZ7A3ZmBtxSJ8I1xe1v/yWN+eD9Z9l7ZTkF
+Ve8Avej6NnudkH1f6uTNmEETXOXHWwIDAQABo1AwTjAdBgNVHQ4EFgQUa+EEC1KS
+J0Ge0uzUtIS7GSu4Hn8wHwYDVR0jBBgwFoAUa+EEC1KSJ0Ge0uzUtIS7GSu4Hn8w
+DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAw2rW8RtmfyaqTswj9Gpj
+eiBBvBDDlhTcQCKQGUEH3CQfnh+xNvTh3iZ2J0kRXC8Q+Y2q9ck3fzQf37PvsVgb
+5Yue2eLaEQ0I5qcIbCIHBUkHD6rcfU/608GhXPSA2bzyjYwbYIBjjXctSHc3lyLQ
+bQI41vX6nfTmlsHme/TIHF5cPGNZtb0HmEm7qbOLH0nHLOVWYHkUSL73JUDhVTRG
+dqIeaKKhIP/SfYs7jmK3G1kW0Vy47mEcZez5RvpYA7PJmTVUbsO1c8rp1RWbkeUp
+eQFGJMXZDNqp2pwefpuyKxfd75vcVSgtg810IYxIojckAtGSLoJjLnN3I5eWJspy
+4g==
+-----END CERTIFICATE-----
diff --git a/meta/meta-mediatek/conf/machine/keys/sbc_key.pem b/meta/meta-mediatek/conf/machine/keys/sbc_key.pem
new file mode 100644
index 0000000..fd987a3
--- /dev/null
+++ b/meta/meta-mediatek/conf/machine/keys/sbc_key.pem
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEowIBAAKCAQEA0mlxI+3vrVlX8wH23CeTPDIH3c4DhEQNIGQltziYX7DOAHyf
+t/5s9TXAOmqIY0cyrQsjw837aiN3QGXONeQorP4+G5wlzWESJeJyAGlZ11hSijVp
+QQFwCT+++k4L8SEoMIgJUMNVd9pESqCYf08nhJXc/qgn++YiG8tMvHz9IA/Ef4OK
+XNj/+1+XyrtYRgYpfOwsoCgbe01NEpV3vM61fW0g3EtCQXW7MOD5VIWMkvTt+ob4
+qTF5/HpRlIJ5nth/8ZktkCx51Lu6yhQ1fw3KKPZ7A3ZmBtxSJ8I1xe1v/yWN+eD9
+Z9l7ZTkFVe8Avej6NnudkH1f6uTNmEETXOXHWwIDAQABAoIBAAdKjhgfo6GPKgQK
+umIwoOKCHVGrVOXdcdMAhWoO9QDD4K+Vofc/QslQfoPHs0g1bGUgsLGVTrQD3JsH
+rBij+mDcQoy0YX73cSiM60RmYi2bKukNJsOQ6C/53IVR9Qn7Cyh7Xk9FJY4Mqzcm
+z4IB3S2z/793VkNdWys5ZURW1HKq6R7s5Z937wlinPdJhwi7kI148NFnHFO793+z
+MGRC4n45CP13dHG3jktc46UYksP3sQ4CFcjFhKS6BPKDsyjmbCx1HUYjjcaLTy2d
+CJhYDlEvvkjU6CmQfe+cFpKYXnW5zZTwwx1uUDFiWOgSZupaieWZtyPCX7hqQ4ea
+Q6u7RxkCgYEA6+WjIwTB+D3PKP1x82RY2BMpWQRxHuVJs7T0H4zA+IicfJYc/+Sh
+0Esqzfj9ak/sEuNR1fIj4XCKODEVL3/n+qjBz8lbsNDjUrjG8jv3TiGkeaOeOyFR
+8jv0cvedzFk+1lQElFwSHrWAOfeoZRMHOoxK1MNkELjo2wFa67o6rxcCgYEA5FfR
+PJRyu2OmCVwqzycMbSOz6gB/5O5bnI9DxZf0oMNE1n5ElsZWynEFE5L33E+bvB/8
+AdC4cPPL1pg46KiDDkJ/BQhw+mC4wwvBHwjZFlKdQMYtgGb9ErFL4WPnllXy+ETD
+8U9Az1zOvj6thy3RYA7JGyZus4t9ecM5M+xItF0CgYBm+u7G4NLUzhbbrBjMyifG
+3EaWp8vCUxJjs0FHbKjpVqoJ8XZjd6n0Rnw/Qs1OVemXLUmSfoyPZBPTCApZnBrn
+YDiLvzmZ7PbwK94d7XO+1gz5VSZEZf1iJC5I6jQm+2blJfSB19fJNC7wH1+SEEZ9
+lrUsQMg0TKTKxsKsWbY4rQKBgEjP//aTV6qNcgqWC0iXKQ08T0iU9DNqFmhr/q5p
+cCY7Xh4PkYuKn25ab8X4HXVxJTXt9QwXJFlQRHWfgLYf1fqcFajjMjOE2CXJ/8EH
+r0HBAkf/ac8CCD0HsCylENoNejbUpq6yGPaGn55mmir630MEM/imXrJ+DnrfV8RI
+2j45AoGBAN/fhfcjGu5ix88+T9sEmV1lfoHyETQIZD4r5c9NufMXPcztE33XTqjI
+DpBfOCVQ8ZNuHuScQdQC55K8XT7wR9sQRhNvRua1K0IsfcL73ghCJin9i0yxMEzp
+s00NbHgvb2kfhxCC8eyoiCmpRk9A9xg2V22hx7Hkcwv+A62e9tN4
+-----END RSA PRIVATE KEY-----
diff --git a/meta/meta-mediatek/conf/machine/keys/sbc_key_3072.crt b/meta/meta-mediatek/conf/machine/keys/sbc_key_3072.crt
new file mode 100644
index 0000000..73f0a14
--- /dev/null
+++ b/meta/meta-mediatek/conf/machine/keys/sbc_key_3072.crt
@@ -0,0 +1,26 @@
+-----BEGIN CERTIFICATE-----
+MIIEXTCCAsWgAwIBAgIJAN+2Z+fexh8PMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV
+BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX
+aWRnaXRzIFB0eSBMdGQwHhcNMTcwMTA1MDcwNDQ2WhcNMTcwMjA0MDcwNDQ2WjBF
+MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50
+ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIB
+igKCAYEA2N8R8TojgiJ6F5ykamhxRcSO5KXRIKqls5olzUIclfzVkav0ad4FRxyK
+3EuLPduPBYBv2azm3VKDjR536XmuPVb/K9bR481X080n7xRiHxJ3+VG4luTPfxm+
+/kKmJw4DSUe1i3JIVYIjsb7DqUKxQ2zUea0Kgj4SXi2HRvU0lqOzA6Bm9BVByNs6
+3/UXj8lXRrCLKRsqyVr0esGQD97u9SpcvRDp7046KyK7pbtViWOOuA7NYICMBVWD
+xmW/6lsvG6BKzl8bdRwpXzKYPqztdy7FIas/wcU1DFecEMuFD03kduMktmjGzglu
++ieEybqkvDD7BqTYDt38rPOTI4YDYg+zu8Tuwc7amu4AhAeFU+0B4E51HbUBeo6C
+HNkKoW0bImweRH0r5L4os1S9d8igfRjd5zzKRQ6AoZLBNd0P6Vhq5WvDI+4+2IuH
+IWE1eA8knKcJT+W4udaiH4e00h3ezPJB0eaUC9aLoypOU03q9IJuwgYFBmR4xqii
+j1gDHBuRAgMBAAGjUDBOMB0GA1UdDgQWBBQECqe8GcAiDDoKqVgJm5Ir5iC6TTAf
+BgNVHSMEGDAWgBQECqe8GcAiDDoKqVgJm5Ir5iC6TTAMBgNVHRMEBTADAQH/MA0G
+CSqGSIb3DQEBCwUAA4IBgQCmZv5LYENtO5tQxll69FR9nKGM52r6OpSP0GZbvTTX
+3i8k4PEqWplQFEwzy5t5CWqUqDTavU6D7Xjea6fQ8RuHUXFo7vfQHMBeBjYcsQC+
+CHa+BZa9byprTMAtGuKKaWL2+iWMdc0os+NIAX/BFOWfnUIPGLoFQDUJIQEQXJxS
+xAiYYTVwZjMOivVpYeQx1HFvHDQ7yvkB3OFmm7o6nP03Ave1NlMTUwg3DryWHvuW
+5ZyOio1SgRfx4FgwCDc6aHA0+JBLl9JsUEZWnlqPXCeF2eqr3cavxXOzc6crcFZr
+KSJ98BI5wqi96h5C+/dVT8d40Mgp1yQeDV7PRtVJQ2Vn5i8kAnQGNVAQ0nMRqpOL
+DncWfL7z0Jh0qER3WKoJFqYDmiGwbLZbfqv+7fXeC+dgGN8kwbVIDmFEfzg5tDAz
+0uf03AL3InO1xuhHLTDi4RKMyUY8KB4KmrdcxeUuQmynLECVNpj52IW+444dsvIU
+oxdF4JFXGTzUU4Zbkc4/92w=
+-----END CERTIFICATE-----
diff --git a/meta/meta-mediatek/conf/machine/keys/sbc_key_3072.pem b/meta/meta-mediatek/conf/machine/keys/sbc_key_3072.pem
new file mode 100644
index 0000000..b8ef4ee
--- /dev/null
+++ b/meta/meta-mediatek/conf/machine/keys/sbc_key_3072.pem
@@ -0,0 +1,39 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIG5AIBAAKCAYEA2N8R8TojgiJ6F5ykamhxRcSO5KXRIKqls5olzUIclfzVkav0
+ad4FRxyK3EuLPduPBYBv2azm3VKDjR536XmuPVb/K9bR481X080n7xRiHxJ3+VG4
+luTPfxm+/kKmJw4DSUe1i3JIVYIjsb7DqUKxQ2zUea0Kgj4SXi2HRvU0lqOzA6Bm
+9BVByNs63/UXj8lXRrCLKRsqyVr0esGQD97u9SpcvRDp7046KyK7pbtViWOOuA7N
+YICMBVWDxmW/6lsvG6BKzl8bdRwpXzKYPqztdy7FIas/wcU1DFecEMuFD03kduMk
+tmjGzglu+ieEybqkvDD7BqTYDt38rPOTI4YDYg+zu8Tuwc7amu4AhAeFU+0B4E51
+HbUBeo6CHNkKoW0bImweRH0r5L4os1S9d8igfRjd5zzKRQ6AoZLBNd0P6Vhq5WvD
+I+4+2IuHIWE1eA8knKcJT+W4udaiH4e00h3ezPJB0eaUC9aLoypOU03q9IJuwgYF
+BmR4xqiij1gDHBuRAgMBAAECggGAbbpX8qyO4L4e9ilsSuZzQXCVN/zp1dRhqIC6
+1aK4oe7eBClzrckG9Jbtb07NscuQDqGQdht0Z9Di/JjI5RmK3kBRNVYotlDkOibY
+KLAwgTYv+7asZbR5g/5701vXg3UkloQwx9BX5uPEuZ8iklZLKCk9TB8QbRuI4Zu5
+kV5pcDp9Tb1vudmzgjPiEwSIGlktznduwaqcOGrLvfyHrnAGiYcYixSuuETlS4P0
+W4NwYOY9hMUAhu4jamN9G/nJY4MkYSqG+gF/GREsfDl/zUod8V2EF67480U76Sdb
+HyUzUgC0X5h4wTQBFkiT79fmklNZGFJkhMHY0xArPD1vemoVHpJUxk54bQevUyA8
+LMKesqkqZ9i6ZG8v/uYjdmzHYG8K0xoacTCmj8RnuReWIRXfL/YM4ILEZUhQjwyM
+drrQsykXQTaN2XE6qNK8p63hFG3gQE/SiYO+bWfyj6r9I6fs5Z0Q9UPeoIPTDE83
+GnFpssMmZ3j9pwspWYBsGiXslRA9AoHBAO6SIS/RIbs2D5S7gW4OsmKfm58NytK6
+5fkqPj+CN26oYMDmZYstzx2Y/IIYrd57ICyVDSjPhGZgO3LPVPoUofoegUBMvcRl
+TX2PA8T/uL4CzdvCZDptOU3M0LD6F8LRP5dDsVcRjRP7jsl3owlcZPn7GZia40Dm
+Qw0urDZ08tXC19F5hChCxMfhNzgQuSppVvEhSi3/cjgRlFwOHKI9RblIFOBUe3hA
+UmMcQIRMwxNQGIPZIxX4LfXEAF/LGNBqtwKBwQDotxtDV6d0Fs3pdHTN7pkeVmAP
+lLham1uiCm3843fFgODe0FgatemNDTcmao3twgMZuwkqJXukh92+N3QLJsowjX5a
+bp7DF3saw9QbLrbL6YfwLAm+xiNWHReA6i7yqcKPMEHqOTNUQvjNBJlXaIhE+xiK
+NKL55ifES4j0onX8C+TRpShW2M1n+s0WHJNankVRqBx2Imb0Wkn2WxHRDCTzURAD
+SFYa3hSfq3Qs/Qgxouv/eZ9F/0MVMHdVT4RjA/cCgcEAyHfmhyW2sHem9BXzlqWm
+5BS2Uhrm2djPMmZ61Cb5qXS3iKCRpzghF//b/v357D+OM6gz3J0z5krq6XirMVFx
+IpnLhlp2A7gUO3OXeUxg0tnMXeOlESuCwYtfubcNjFkElHj/ZeiLocT6oPR0/YK0
+HxMO2Rsd5wUWRtd3QnNXMqR9cboogSRJ8qOfIO98iNTnh8uvZ6OFOPQctJXvHa1b
+D2wwjqiu78cs87djx0gxi+L8Fp65Sta22BORNO2WtltVAoHAHbFPTzZd7VgDiegM
+B0KMUuyecR5+r0DnXjOKeRvk6lRZXNSkiTPwysiG4uXxmgaJMr1EnBYQQpv7VQvq
+SIn4fl1vY8Z9h1L1qCKYa6d4N2hiqehUjfzmAVTQ7Of0eY3jfzWfE22c+QFakX4m
+upph2LtZFDlHGi+dn1Qr81rPRwuVdJJoJTygaMX9aPbYblWHbrXOe9xD2qWyjjZs
+fYnZJRqQunp+UgtIAl90AVF/vCWXiw9PnTTGsGtwrnfo4mFdAoHBAMtpV5gbcRkS
+ciEXsSpy7czzwOFUA+wYXB9yvTNvlo3EI/6Lxqc6w7kjrkUFgJl2JNP3/6VPGHvX
++BIDFdaWKISTFGXkUl29N+1eevgjtAy89B5+++CTbpaw9YXSUogQlRQr1eeNFdE8
+1KNdwsJn8COI10XueLFoip2rhwtFjp1hfwpqqCpXfhAc3MKvDDzwW1+FxZUu0Cmc
+VWpf1V0Rjh12PGOxJkqv1cSV/l8JcIBzbr6JZMOWBxZhArT1maRRlA==
+-----END RSA PRIVATE KEY-----
diff --git a/meta/meta-mediatek/conf/machine/keys/sbc_key_4096.crt b/meta/meta-mediatek/conf/machine/keys/sbc_key_4096.crt
new file mode 100644
index 0000000..5744080
--- /dev/null
+++ b/meta/meta-mediatek/conf/machine/keys/sbc_key_4096.crt
@@ -0,0 +1,31 @@
+-----BEGIN CERTIFICATE-----
+MIIFXTCCA0WgAwIBAgIJAI0qRHIKirVmMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV
+BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX
+aWRnaXRzIFB0eSBMdGQwHhcNMTcwMTA1MDcwNDI2WhcNMTcwMjA0MDcwNDI2WjBF
+MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50
+ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC
+CgKCAgEAuvJhDke0XcsTVBR8wHTR4WMUJSLvYn7KjZKXwKntTACQw8Fvr4t6+sOI
+86SPx6JoGL/kOtss/JCIHNr4kscSiPy+azIRxSQqdD4Cw6CK4LYswPUXEBO9WCKA
+1zuMCaj+OxsL4aEknwIUVhs2QGX3ZjtXB/7/FKhW1Y2j6wnDlgHHYhoDA4tcg0E8
+mLTtU53aknG1hd4uyUEZp3jrjNU7x97SAfy2AwYqgGuZe66Ko9f8Zv2NrskNfNv1
+GwI2UFIBhsUFbEXegwM94lIzk/fqFR1mAKB1LTizIL6iX6i4P77NYr0YMDX4uEL3
+w4hWTdPjli7i1Kupng8yfg64W1Qweum2dm0r3ssWBa9uDIpGbUT5NDoE7V4Q1pdX
+EySucs5+1WfLcDAosRpjU5FhKfP5uhVljJEGnDDyXlRE8dlcxbhMremx4/cB26HZ
+YnkxnPgCUv805i8dUCulIdn0aRJ+EF5QQWKQ0K0l0xSY/fFZAjRN+/fA2j/8E8cH
+1s2zoDuw3EZk1ScbZs9TgYAvJ+YWIkktxQ9w7Q/h+5LK4sWJTgAXKbx1pab9W3m9
+rrYgmzHgO4kHlLQKrL7CV1DGIp1jdpbYdDve33pU+1DyOgdKrVLuNEBvUtt82KIM
+ZPSZSLyOfCCeO6Cx/bHa1adC+09d/xcDr0Ankm2ARdjujSZaSdcCAwEAAaNQME4w
+HQYDVR0OBBYEFHl8sy1t7v8OzcgwHlMhL61EYbCRMB8GA1UdIwQYMBaAFHl8sy1t
+7v8OzcgwHlMhL61EYbCRMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggIB
+AJk9Bmaf6gKAF4KkFJiuagMmoHV9d+QucaMzVmGDblz3eoRZfhU/d4hg/QkKb+L/
+elu8LDeyD6UVDshLkeom1opDmhLchwwSeo86puLjCN71GQR6vpFS6jObIuc8gqpt
+324dtfRPM44djEhUKAqTIwdQ00UQhcK/bUifF7z9YwbiDmX+5G66OGkO3+h0ByBw
+nTPm8SprUmNNk4Y0C/8iZ0fhFOYDz5/+LH4KajNu3bTMHb1NcDMNKyTBKqRZTNDV
+Kcv66AWC28qvRSItBmFqLjNyPGqlug9C/twmHkTiqckbBqooFSq1gmo4cIsYTfA/
+fImLXSRDSUWHH9HBYP2ZsWedqSCOg5F53LRUvRq1o/Y/Adx3rBcNLPRMU3JkPtL5
+OooTbSNPjG6vYmPlE8/BqgJ4pLXGz7EpHde5yjX+2pHufX8ZT07agTVW5bwF9OEy
+EAnPyvxtuYu3McFRfXQYlkGaJUlEpoV4THN/3dBiaPl9lkQ4M5zey3Fjjl1W3/kz
+QW7Z+BqGuYCwP3Jm6pDGZgE2UP2wnSH0Lq7JPzMc3l6/H18+gTncEWxUVMGgZFZC
+3v1w8wLPEwpLEcOoefPEPFbOnb76zzUFPehs8JgCCau94FVBuMj8FB19BH/6su/h
+W4I6Db9CaWv1OhJvPRWEiu1N6q4q7+PE+DN4GJVGbSKq
+-----END CERTIFICATE-----
diff --git a/meta/meta-mediatek/conf/machine/keys/sbc_key_4096.pem b/meta/meta-mediatek/conf/machine/keys/sbc_key_4096.pem
new file mode 100644
index 0000000..f6f2dd9
--- /dev/null
+++ b/meta/meta-mediatek/conf/machine/keys/sbc_key_4096.pem
@@ -0,0 +1,51 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIJKgIBAAKCAgEAuvJhDke0XcsTVBR8wHTR4WMUJSLvYn7KjZKXwKntTACQw8Fv
+r4t6+sOI86SPx6JoGL/kOtss/JCIHNr4kscSiPy+azIRxSQqdD4Cw6CK4LYswPUX
+EBO9WCKA1zuMCaj+OxsL4aEknwIUVhs2QGX3ZjtXB/7/FKhW1Y2j6wnDlgHHYhoD
+A4tcg0E8mLTtU53aknG1hd4uyUEZp3jrjNU7x97SAfy2AwYqgGuZe66Ko9f8Zv2N
+rskNfNv1GwI2UFIBhsUFbEXegwM94lIzk/fqFR1mAKB1LTizIL6iX6i4P77NYr0Y
+MDX4uEL3w4hWTdPjli7i1Kupng8yfg64W1Qweum2dm0r3ssWBa9uDIpGbUT5NDoE
+7V4Q1pdXEySucs5+1WfLcDAosRpjU5FhKfP5uhVljJEGnDDyXlRE8dlcxbhMremx
+4/cB26HZYnkxnPgCUv805i8dUCulIdn0aRJ+EF5QQWKQ0K0l0xSY/fFZAjRN+/fA
+2j/8E8cH1s2zoDuw3EZk1ScbZs9TgYAvJ+YWIkktxQ9w7Q/h+5LK4sWJTgAXKbx1
+pab9W3m9rrYgmzHgO4kHlLQKrL7CV1DGIp1jdpbYdDve33pU+1DyOgdKrVLuNEBv
+Utt82KIMZPSZSLyOfCCeO6Cx/bHa1adC+09d/xcDr0Ankm2ARdjujSZaSdcCAwEA
+AQKCAgAGizFmhJAFsHQOv2DWg8BM+WDdI+npMrL4Xac+MTSDMonesEiuhl1ZpbqH
+fL0jqcWnCCB/Buj+NjjteaS1zo4RiXdI3UnN8sQhqYIDQv1ZfEb4wht6jpZUHXER
+F56BQA8WFo5F6ZQUlMgNc4pkmq0cQPt85iobmQDhHMIeGgtkls9Z2bs9RoWIeqIa
+XkroYGAkPCK0euB8XvD88bidB2G+T0helW/xjyexsxJ+R8/GiGrnV/y7n4H/Wtur
+hFpOWXCAPSlBbvio8VYbM/FmPolND+hgIT24xYFPphyc6JT6dj1ONXxBQ8JfAMkX
+aRBMTRxsR1vdQd0AEVwdGXrOh5XiyCXfGJ9/6JZ0dblSo9hdTQEis6I/dImQNZxk
+iQys09HMCejIUSsQiae8YiQRk4JFE+x9mSzW9FOjsZK58wjplshWX3wH2RtUOP6a
+ifkpldNHhElnmFvXlzI7Gx08JXsDqAeVmOH+6+v/O+F1M5Fol8CCX1+nfjjxhYsW
+g0q1lZkPnovTrnSVR2bMPcHRIp5GrD/q7xPxWivdddzu9dJdtSO08Sadbv6IfRLq
+J+/9B3pE0O+9xLjx7UJwdbqyfE8WDIyLlDAMSIBeOPr5HhEVZ1iuofX9ZFepfASQ
+EMt7k8mYtUELlErUVsBAhmnbYUJKqOqMduihR2afzwEp2Ba2IQKCAQEA8BIWXHG+
+N6pareFdDS3Gx9gmhuJhfFP2YxiFKr0Z5YND0UMNJIMIWZ352Hun40N6FVgxi7gU
+g+pL8g/tJTwWNK5WDqgf7X/Npzxf7GdLpNk9ttBgVuA8Z5vjIvD+9khMeyquJvHo
+PuvpVtitY/8DBS9vdV5P6EXkZYwyJChLMllB7xUralDqq1SBgI+pvIz7RbppVIWi
+A+yh3Ih9nfuAkLgedDsSL4jjo7C8bl0TgsrxmWux4G3Czppt/rFOd+MNKOrAwiZT
+DbX2GsjKBzncxEz0OE5GDPLYa1bMBz30OJeOS5q24Q4GPZSYJXG5xsw6n5goF+3b
+wTY+hck7X0gg6QKCAQEAx1np8TDONWqoh+9Ll4s+Gxl/cPbnFEnZYJeXaaBXvSrm
+qBK9cX29pxLLHfOZxUpiIHaIJIEuC9JH0GqjMiJmybVtFCFGehaNKWQl+RI8AvA+
+LNZdBvLCoa9D698d7BgtVxFOcB2zxEaBhlKbbgloLW8bXVUNXpT1S/0WcoC+kk81
+gKnOiE/Ccoz9QiCe7DlUQzeiXt3ai7YBW9K1Mh57lENb+0cCb6WguVNWZeDiIsY/
+FprqI+HOr5zlD6oelHmtGNOSzsxcJ1v7dsD5JYoRAucceP6HFA6YdzTOkI9Kxsp1
+b++PwkXuy+wm4/qRwfdUERBP3cfdgTlgpICChEZcvwKCAQEA65r0sxk182+OuuNX
+7R0l3u91MB9wSRIl1q8z0fPwPF0M64yAk3q9cSYnE5yX8eRBJj19sn+gMq54hkG3
+HTnRGTaXYp8BZpZtAFmyUlI13L0PYiEyy1AaOBy3V41oy8+8r4v9il8S7N2eDQtt
+b5vQHQCmxGsgxPYC5t4mP3IECo+qs7b0+swa4rZ2ufNEQ7WgzJfb04WqsWtElyil
+D6zKSj1INg3bFSelMPq8kxtpkI0XethEo9tUumq41KKyPdppCeUJ9ACkteoEc9jm
+3RyeW1Cixbeb7A1Q9FckuV7GFdw3XF+kZ07aNQlmIClyh3XbetFbV9CqQP65cZdC
+W4pwMQKCAQEArF+W5bLp205qg3/qwRLplM0rYSZdETH6AIeTqQW4WB2sbFAn9uZf
+AwRBFZj5sZpr1t4nQklg41/kMNbEXilY77kspGdRZWfyj4PFQeT+dxv85xBESCnJ
+Gb1O4bl/ShJtwgd454EHXAQLI3ZyZ2dC6WZVJxLQCKSMpjQlIMUqA6DyBlrN9xfg
+buRyaKeEQ4Ye0jBc+eKjgoLSEe/UNY4eFUlZU6FG/fsdSqJA5r7ZSnBZRNaW9ofe
+DAOCHVVgM8oyXnEzVBVo6a+jdD/QLyF/LB9ig0yyyCkGtKy4oE8GvXV6rlta1wVZ
+QoLj7eVP+4Q88LRGGuMjKQXQBu4H7RBaSQKCAQEA7KPNP6tuP1gq7aZpUPIN1MzC
+m7Ewr6L/0jrAf8cv1hxUC76klP8NVIUr8HucyGqOuq1kM2V8jxP8be5RyN1jQ+GY
+uET9mKxTO1jqzFhmPEGuXMVWLgUY5Qzsmu4n0Nu90TBkH5PlBc+1mm50FEsw4SQd
+gN+cb+POjtHfmYMgHLc5hB1NkeN5OWmCM/Z12fDFjsHIoCbrWV6G6MnjZ4C+eD/s
+y3+yavurJd1NS/vsueYoDpVCQG72a15hmn8v6BRR+FI8+dypBmwOu36SWuanS/0x
+d0tX7UH2zTJT0Meaa3SaE7AkJBm75+oNPBsFS6E8joOtbMi5Ush4R042WbMekw==
+-----END RSA PRIVATE KEY-----
diff --git a/meta/meta-mediatek/conf/machine/keys/verified_key.crt b/meta/meta-mediatek/conf/machine/keys/verified_key.crt
new file mode 100644
index 0000000..719a9c1
--- /dev/null
+++ b/meta/meta-mediatek/conf/machine/keys/verified_key.crt
@@ -0,0 +1,21 @@
+-----BEGIN CERTIFICATE-----
+MIIDXTCCAkWgAwIBAgIJAN1av87lFbQgMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV
+BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX
+aWRnaXRzIFB0eSBMdGQwHhcNMTYwODIyMDU0MTU4WhcNMTYwOTIxMDU0MTU4WjBF
+MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50
+ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
+CgKCAQEAvn55XgD1e5pR4+3kFDHnLQlVIJC1CtpS+1VaI68SuPLZIFf78QzGr3yp
+ScZ9BMdVwwdHMrg6CNLRjkoqFPHr82PPtb+0DVSCfTq2wA8MyiHc3Fp3Mv4mTwMY
+azrFTAhU62fug0WTVUF2ZqhrBuXXarhSEO0ZCtOYq/nEQ1AWaqIgjgR8rE98ECSr
+Rz0vAjdT5BChTsx/4cJ1z4jv6icFtAhHqMGWhzQjJP5LHWeass7DivNXC9JrY+Ca
+0okAmyXAKSwFhYJTPXNqi1qrIsCV9COLpnnId9qCuRca9cZhkf888Ygh/PJ1EbMD
+37sqH5HQ5jX0WuTYmusNU6iL4Hc7lwIDAQABo1AwTjAdBgNVHQ4EFgQUqwySHl4z
+Ogn30j58bk9PoEeyNOMwHwYDVR0jBBgwFoAUqwySHl4zOgn30j58bk9PoEeyNOMw
+DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAcJemU8MLZdBWqjiQDgyu
+ZGlU/COlDTohPOplVf05z/sIj3jbmN0NP0EeEjmBR0HqBJYlqhmjhvlJ3Z7ifOcX
+VQJKeFen46ym9iem/oUd8dKAI2EzH+G3Rzh4YQVdYA5r0pJBeoSQrsAgkwisF7ta
+B2CCLyxtLAd2o2CqERTCY/TBczP/5Y2WarjxYQHZgAfc8OCFCTswTMpqVZSALVrB
+t02uOP3BsknL0gd3JWV+/0L47s8aowXgw1/hoJiX4AXEcO3kVuY/EFchiL60e56X
+dA1olr6DmRkk3++u7ujSnCr461hLSRQN0rD/6W2ufycUV7n8kb1XbP5flwzEaFrG
+1w==
+-----END CERTIFICATE-----
diff --git a/meta/meta-mediatek/conf/machine/keys/verified_key.pem b/meta/meta-mediatek/conf/machine/keys/verified_key.pem
new file mode 100644
index 0000000..44a048c
--- /dev/null
+++ b/meta/meta-mediatek/conf/machine/keys/verified_key.pem
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEpgIBAAKCAQEAvn55XgD1e5pR4+3kFDHnLQlVIJC1CtpS+1VaI68SuPLZIFf7
+8QzGr3ypScZ9BMdVwwdHMrg6CNLRjkoqFPHr82PPtb+0DVSCfTq2wA8MyiHc3Fp3
+Mv4mTwMYazrFTAhU62fug0WTVUF2ZqhrBuXXarhSEO0ZCtOYq/nEQ1AWaqIgjgR8
+rE98ECSrRz0vAjdT5BChTsx/4cJ1z4jv6icFtAhHqMGWhzQjJP5LHWeass7DivNX
+C9JrY+Ca0okAmyXAKSwFhYJTPXNqi1qrIsCV9COLpnnId9qCuRca9cZhkf888Ygh
+/PJ1EbMD37sqH5HQ5jX0WuTYmusNU6iL4Hc7lwIDAQABAoIBAQCtgG40g3UTRiQu
+EJ97EVS4fVaOmZ57qwyHpF68P5oy3+WJAvoSvAs/DLD35BQ8RP5E6x0bAhbBsJpz
+GfOoLgw1G4S0yk1JEt7jBpYq6cpBVIRgIvmMdVUZA/26tMW8kZ4e5wOjhrxBm6Um
+rWEF4FPK/OSqS/lSFhVpFc1/bbNtHHi/eJDtqXyF4ySuDEKWn/LYUfU2Ff8G7O78
+7GIQr92xqmP4JNUhT/3Ppq7BqlBBH4AmRdMXByPLyvjvQnIbawf6Wd7qbqpaSbye
+z/2vyYZn5pNSsJoRkhJqpfhGyNbp9glm6wyrlTtR2c+Sk8PN44s2pnLzI2hrCVz8
+6BqWANCBAoGBAOqN1yIH3ZXjPsHp7brJtlBihdxfkAYfH0pOG/dVwY4X6dBU3z2a
+Rkr7WHzjn2bYNH80oyrqyO792EmiopCRdI/KSHqNb1cyQ/EtPbFeYnHwoNOzta53
+IP430YyGtE+avC+Dy/BlDojAICcepFOEM68dmKUvMceMsJcwoNu5utpBAoGBAM/p
+VGJh8RTReeWaOUqQhidlv1wn4ZZ+yzOYQv4kUqwaFoH8up18ImPBK+irLkD4qd0t
+K9hXHgRW6DRBEhh4fdM8BIN+ELDkXhfeeRQraae4MiYo2PenSVHPDh/jVGJZ0Dt9
+dK0dg/Q/ifYaeVYjhothaU9Re1uMoKDIdbFIeC/XAoGBAJw225FOq8WoE6QSqMI+
+la3z8DNVchaho7VZUEbqVn7MbmzSGdxtY2ONAuIqt39Hf68433M1651Ac0yXhK3E
+Ml2R27PDfuQUFiwKdYwr0GUSXgqhJd+Md+zYQDfXfz+FTtBWdv0kUQnC66ciQU9e
+PQ3kKEXbqMu+Z95KBNhSWqABAoGBALXk9KZ9+WS1P2fYXXcWqceeBKSjX4FCvJQP
+Cc0+CfX3fOmMKdfN2mhbgAa2fGjrI/EUq99BmElDnzLYGvS9tZcwUuKXUBLyOD+5
+q0QyFuVdCMLJycgg2sxv0XOkdxb0bHEfeQxbXi45yIE++BicTAF036U9LCcUCROh
+TRYkyMFRAoGBAOM1R/taaYeRcKLmAOSvGyRROXR970yPoqApib4QPlV2qPKEvpod
+unxDwDQcfKnb+n+181mXrWDoCiCe4vOYrTh7aSIH73fNOOW0oz3EVTZXNlnhGLGS
+6ImY+/va7cIBIWQmC+JmqlcPx91Jw0gS01aPlCooxBmWpdl1a7S9yr4J
+-----END RSA PRIVATE KEY-----
diff --git a/meta/meta-mediatek/conf/machine/keys/verified_rsa2048_key.crt b/meta/meta-mediatek/conf/machine/keys/verified_rsa2048_key.crt
new file mode 100644
index 0000000..719a9c1
--- /dev/null
+++ b/meta/meta-mediatek/conf/machine/keys/verified_rsa2048_key.crt
@@ -0,0 +1,21 @@
+-----BEGIN CERTIFICATE-----
+MIIDXTCCAkWgAwIBAgIJAN1av87lFbQgMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV
+BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX
+aWRnaXRzIFB0eSBMdGQwHhcNMTYwODIyMDU0MTU4WhcNMTYwOTIxMDU0MTU4WjBF
+MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50
+ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
+CgKCAQEAvn55XgD1e5pR4+3kFDHnLQlVIJC1CtpS+1VaI68SuPLZIFf78QzGr3yp
+ScZ9BMdVwwdHMrg6CNLRjkoqFPHr82PPtb+0DVSCfTq2wA8MyiHc3Fp3Mv4mTwMY
+azrFTAhU62fug0WTVUF2ZqhrBuXXarhSEO0ZCtOYq/nEQ1AWaqIgjgR8rE98ECSr
+Rz0vAjdT5BChTsx/4cJ1z4jv6icFtAhHqMGWhzQjJP5LHWeass7DivNXC9JrY+Ca
+0okAmyXAKSwFhYJTPXNqi1qrIsCV9COLpnnId9qCuRca9cZhkf888Ygh/PJ1EbMD
+37sqH5HQ5jX0WuTYmusNU6iL4Hc7lwIDAQABo1AwTjAdBgNVHQ4EFgQUqwySHl4z
+Ogn30j58bk9PoEeyNOMwHwYDVR0jBBgwFoAUqwySHl4zOgn30j58bk9PoEeyNOMw
+DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAcJemU8MLZdBWqjiQDgyu
+ZGlU/COlDTohPOplVf05z/sIj3jbmN0NP0EeEjmBR0HqBJYlqhmjhvlJ3Z7ifOcX
+VQJKeFen46ym9iem/oUd8dKAI2EzH+G3Rzh4YQVdYA5r0pJBeoSQrsAgkwisF7ta
+B2CCLyxtLAd2o2CqERTCY/TBczP/5Y2WarjxYQHZgAfc8OCFCTswTMpqVZSALVrB
+t02uOP3BsknL0gd3JWV+/0L47s8aowXgw1/hoJiX4AXEcO3kVuY/EFchiL60e56X
+dA1olr6DmRkk3++u7ujSnCr461hLSRQN0rD/6W2ufycUV7n8kb1XbP5flwzEaFrG
+1w==
+-----END CERTIFICATE-----
diff --git a/meta/meta-mediatek/conf/machine/keys/verified_rsa2048_key.pem b/meta/meta-mediatek/conf/machine/keys/verified_rsa2048_key.pem
new file mode 100644
index 0000000..44a048c
--- /dev/null
+++ b/meta/meta-mediatek/conf/machine/keys/verified_rsa2048_key.pem
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEpgIBAAKCAQEAvn55XgD1e5pR4+3kFDHnLQlVIJC1CtpS+1VaI68SuPLZIFf7
+8QzGr3ypScZ9BMdVwwdHMrg6CNLRjkoqFPHr82PPtb+0DVSCfTq2wA8MyiHc3Fp3
+Mv4mTwMYazrFTAhU62fug0WTVUF2ZqhrBuXXarhSEO0ZCtOYq/nEQ1AWaqIgjgR8
+rE98ECSrRz0vAjdT5BChTsx/4cJ1z4jv6icFtAhHqMGWhzQjJP5LHWeass7DivNX
+C9JrY+Ca0okAmyXAKSwFhYJTPXNqi1qrIsCV9COLpnnId9qCuRca9cZhkf888Ygh
+/PJ1EbMD37sqH5HQ5jX0WuTYmusNU6iL4Hc7lwIDAQABAoIBAQCtgG40g3UTRiQu
+EJ97EVS4fVaOmZ57qwyHpF68P5oy3+WJAvoSvAs/DLD35BQ8RP5E6x0bAhbBsJpz
+GfOoLgw1G4S0yk1JEt7jBpYq6cpBVIRgIvmMdVUZA/26tMW8kZ4e5wOjhrxBm6Um
+rWEF4FPK/OSqS/lSFhVpFc1/bbNtHHi/eJDtqXyF4ySuDEKWn/LYUfU2Ff8G7O78
+7GIQr92xqmP4JNUhT/3Ppq7BqlBBH4AmRdMXByPLyvjvQnIbawf6Wd7qbqpaSbye
+z/2vyYZn5pNSsJoRkhJqpfhGyNbp9glm6wyrlTtR2c+Sk8PN44s2pnLzI2hrCVz8
+6BqWANCBAoGBAOqN1yIH3ZXjPsHp7brJtlBihdxfkAYfH0pOG/dVwY4X6dBU3z2a
+Rkr7WHzjn2bYNH80oyrqyO792EmiopCRdI/KSHqNb1cyQ/EtPbFeYnHwoNOzta53
+IP430YyGtE+avC+Dy/BlDojAICcepFOEM68dmKUvMceMsJcwoNu5utpBAoGBAM/p
+VGJh8RTReeWaOUqQhidlv1wn4ZZ+yzOYQv4kUqwaFoH8up18ImPBK+irLkD4qd0t
+K9hXHgRW6DRBEhh4fdM8BIN+ELDkXhfeeRQraae4MiYo2PenSVHPDh/jVGJZ0Dt9
+dK0dg/Q/ifYaeVYjhothaU9Re1uMoKDIdbFIeC/XAoGBAJw225FOq8WoE6QSqMI+
+la3z8DNVchaho7VZUEbqVn7MbmzSGdxtY2ONAuIqt39Hf68433M1651Ac0yXhK3E
+Ml2R27PDfuQUFiwKdYwr0GUSXgqhJd+Md+zYQDfXfz+FTtBWdv0kUQnC66ciQU9e
+PQ3kKEXbqMu+Z95KBNhSWqABAoGBALXk9KZ9+WS1P2fYXXcWqceeBKSjX4FCvJQP
+Cc0+CfX3fOmMKdfN2mhbgAa2fGjrI/EUq99BmElDnzLYGvS9tZcwUuKXUBLyOD+5
+q0QyFuVdCMLJycgg2sxv0XOkdxb0bHEfeQxbXi45yIE++BicTAF036U9LCcUCROh
+TRYkyMFRAoGBAOM1R/taaYeRcKLmAOSvGyRROXR970yPoqApib4QPlV2qPKEvpod
+unxDwDQcfKnb+n+181mXrWDoCiCe4vOYrTh7aSIH73fNOOW0oz3EVTZXNlnhGLGS
+6ImY+/va7cIBIWQmC+JmqlcPx91Jw0gS01aPlCooxBmWpdl1a7S9yr4J
+-----END RSA PRIVATE KEY-----
diff --git a/meta/meta-mediatek/conf/machine/keys/verified_rsa4096_key.crt b/meta/meta-mediatek/conf/machine/keys/verified_rsa4096_key.crt
new file mode 100644
index 0000000..87520c5
--- /dev/null
+++ b/meta/meta-mediatek/conf/machine/keys/verified_rsa4096_key.crt
@@ -0,0 +1,31 @@
+-----BEGIN CERTIFICATE-----
+MIIFXTCCA0WgAwIBAgIJAMxL1sxOCMuBMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV
+BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX
+aWRnaXRzIFB0eSBMdGQwHhcNMTkwMTA0MDkyMjIwWhcNMTkwMjAzMDkyMjIwWjBF
+MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50
+ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC
+CgKCAgEAwhiEH+u0LnooUkddhD4wlbUFWrFUBc7ipQrEn6Xxnro896GMSDBRiYkL
+tO0Zl4IySY7hMsnhUTAoAe4rSVi5aSQWMm8z02cAIhKlpCokcrMiuTX0aN0nen4X
+lVPEyKNjcg26LyZoisD5MuMNtyirEs8+VrFzoPYBIg0Nt2wXvG9cemORvgtey6lH
+cTS7NNCZl9HT6fKoxCqvJJWy48a92GjJUXTC0ecq2v2d0YBSNVMGW2itTjyKT4Kl
+A61CyUsLS+HwQc4xUfz7qCwJaZKU3krQXtHwPNPbPd8NHG35qdAwFyjsT/3gdQ5n
+7JRpLRSGCuyJFk7oCzOG1ACR10r34uIkDljTDwK9g3f+A55i9xNS0kPPKYR60mbT
+SEcerOyZw2elbXx2hYfLdme9W7SsmlfDR7ZKwRTuOEa858LaRj92Q/46KckpV2U1
+EF86ZI5iGu3A2O4lUNBrWr1i68MF/0unL42EyLgS+i4EAScijkrphALfumev8USE
+awS6l92Sdm4+6gmcroGZpSaepd84tIghcQF4Ovi6UKR/MnLUrR4i5XJDCB4k4Cwb
+pJMUaEgODJRpUhR5nOXHEjjaWQ0APWzOVekg8OBKPXX2IOMP2yqqXGSwRF7cm24O
+DO2zFmVIaDUPIe6JVapRsaYA6yXD9W5avQf54l6fYQDFwLCpqP0CAwEAAaNQME4w
+HQYDVR0OBBYEFM4zyCLDdAsgl1LwYOIcI0p7UIY3MB8GA1UdIwQYMBaAFM4zyCLD
+dAsgl1LwYOIcI0p7UIY3MAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggIB
+AKHaRmeaH8H9LYNm8rSkCyT0pnlTENX69DS2t5RgyU3LMrMHtnnJBqagzSGMx7Ab
+TbuIfY5REBiZ1/1Ujis8dvK2/GqWhn9b5H4yYcwsRFLLqk1pEshBm7POgjiZFZlM
+Q5gOO0W+Ilfs5PJd4nPYPpEY2iV6cOscL0oRD7jHwsq01ngiECnCEFTJgfSR91C4
+P77DwzKswZO+jHZVhhgpT6lMUfOz1bC7Fmbm75HbXa7BRvdQF+4dXC+FKqTuUnbc
+CHae1AkYCfRM+/n6picNcOVyZjLuQH3w7ONmZz5kf/hywvFQFasEH9CG/EPfxT3Z
+6F2YO7vQyvfWT8ptJ3e3H9RRuoOmEBamCtK5vfxrEyP90pJyQxEc03Ykr0X0K90l
+pCT4ODDQhLGLAoFakcWH+JMg/lJDoF1TLO3caUE0n2juy8iEICEs1MIf2VKcYO7k
++5weSBoCcPnXmoMxUXbYonOYmBxRu/uxI2UINPN2oHSBgqZrqdWk2bQhOQqME5pf
+qp2s4x/GFHpX/Sj8yAksoV4S3VOm7xFazjm7EAdfnnOnfXIPoLg3e3LxkCgKzWjR
+PEDOo7ZQBGxJZavtS79GQbM+Y7scf9lb+0GNyEvkEW+I0jo2oHXA6CzMnr0dYRAc
+3Pi6LlWA36wk4ZtBjRw+tEFKBtTcNMitjBXIWMz+2mSt
+-----END CERTIFICATE-----
diff --git a/meta/meta-mediatek/conf/machine/keys/verified_rsa4096_key.pem b/meta/meta-mediatek/conf/machine/keys/verified_rsa4096_key.pem
new file mode 100644
index 0000000..d44454a
--- /dev/null
+++ b/meta/meta-mediatek/conf/machine/keys/verified_rsa4096_key.pem
@@ -0,0 +1,51 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIJKQIBAAKCAgEAwhiEH+u0LnooUkddhD4wlbUFWrFUBc7ipQrEn6Xxnro896GM
+SDBRiYkLtO0Zl4IySY7hMsnhUTAoAe4rSVi5aSQWMm8z02cAIhKlpCokcrMiuTX0
+aN0nen4XlVPEyKNjcg26LyZoisD5MuMNtyirEs8+VrFzoPYBIg0Nt2wXvG9cemOR
+vgtey6lHcTS7NNCZl9HT6fKoxCqvJJWy48a92GjJUXTC0ecq2v2d0YBSNVMGW2it
+TjyKT4KlA61CyUsLS+HwQc4xUfz7qCwJaZKU3krQXtHwPNPbPd8NHG35qdAwFyjs
+T/3gdQ5n7JRpLRSGCuyJFk7oCzOG1ACR10r34uIkDljTDwK9g3f+A55i9xNS0kPP
+KYR60mbTSEcerOyZw2elbXx2hYfLdme9W7SsmlfDR7ZKwRTuOEa858LaRj92Q/46
+KckpV2U1EF86ZI5iGu3A2O4lUNBrWr1i68MF/0unL42EyLgS+i4EAScijkrphALf
+umev8USEawS6l92Sdm4+6gmcroGZpSaepd84tIghcQF4Ovi6UKR/MnLUrR4i5XJD
+CB4k4CwbpJMUaEgODJRpUhR5nOXHEjjaWQ0APWzOVekg8OBKPXX2IOMP2yqqXGSw
+RF7cm24ODO2zFmVIaDUPIe6JVapRsaYA6yXD9W5avQf54l6fYQDFwLCpqP0CAwEA
+AQKCAgEAi/UTqNTUi0MIujO9qjMR45Gxd7EwrjN9WJcIKzqEnPkcJ0/1EMTOtsb8
+iw0BDDAUxNfjaTULZPi9kI7F5dC1eaxM2Tc4frLh9K/Pgy3kNFUZr8XJJKh75Cby
+KHpMBoVSmxZs77zZW1xFFT2GUVFg8mJASFES2LkrHfudrWqjPvxqCdKscAZQ57h7
+zJTCfRYB+uiRzztsGG/S9SWA5iAUGu2MZVE1fhgb3edNGplWLh9dESLM/QJIlYbW
+KG2SIAYd8izMixb8l2s9qAmBDABnmlcGI6lseuAlUlr5YEuo4Js/YiPfKtsdNCsc
+IwrtQFVxRoVDYLOrPRB9o3d5sm3bihkMNOeDGdr20K37sCzAjXOE9UrbMOExHoVg
+DkqRNZ+6l8oWKBcd/2Llq8/O6S+C6agKxKOrDbGUHHwCgbuqXNU4/v01GsTNQTpG
+s8YQH8bfOlXQzyxqCvr9yjHOGEo8mZfk6OaZTTmvFSpu9C/IGmwofl9xPEjoNzJO
+9cKa8hw+E3ZAP4EiSWSM9iCkGHeUjBJQmQNGIL+yPl4QtTmHECAGnNXRvLSk4H1a
+AFIncVwznf9v2yaN4U9YN2mSS67WehBTvBUfJ8pYD+9ZFMfzFa2G+3/Ao3kuYhej
+IwJCQG55LUngqLTMH+hfLpSZMCP0BS+rifnVeqTe4NU1RcfuFn0CggEBAP/1VmxK
+y7MCOjt7LnKd0xq/MGCMliekY0O9ZKYoWR8Qy0WzM2Xn/f3IFROCxUM9PeY5l7Xd
+7DR5nqJV3ueNgqtje1WAkJ93tIjipgCn/w6z4esJqkALr8dmh4BerhOfRzw34IVn
+eyPVr8E4YJX0kbDORVvvOD1uTSo/5J6S8FcipHMch7hCYJzu4b6rCpjSuJg3wuN+
+54Bg3vStzbwg1q2ks9tdhyBQF+8DYyRVjBA+2+wSVhz0P79PtSo3K1HoPclYVfvW
+W1YhMoyw38OxHnxY6bUt7AxiqWqSKs3tJuPAKGjhPRW3rb2VjNx4017S75LcpvA5
+ZwhrswscStip4FcCggEBAMIgmf13ZE6jnAdAsYM+LPUtioTc6wsMiB5SF5kOSr2B
+ILbohhWXjqLd8CwWyRdti6IDkg2XLmBJL72vPd5IwgrMIFXMViLzCad/09fj66vx
+wfT0gqf2FbG0tDX9KQGGwdSJUrqX6qaFUCMnTeheIM8dMozq3X+BBCFXd/Fjl3kW
+fKy+Z+ERAcLOxek0V2IV5fihf/ER8nGfDJbuVJileSC+FxYSnCVUhMsesWeuzQe3
+Nmeoy/1z3fmkQGrruAO/iVVpRGEX39QKbFTo8d/VJd5ZSVk1C8MVjXWtTmPOZLrg
+EYo4SrFo6/IXkHzNx+6z6SzRG0qQCIXhkUJG0wHm3MsCggEAQkf64EIiK7HY+Iw2
+g/HAt/1ofqgJPizAk8sYpDpwka3cpaj5F1uTF0PXyVykznuuas7hLXRRdWlFHg6U
+kWvAubciOgr36IOsGYJvsF3Qm7MTPrUbBEjCdSVk02YxN92YKczidElOxwHP6H47
+7LkPfTR9G4iADNBiZR10i2fLmxTadwCdWKa/tAPcK27JaLewm6Jc8mJreoAbXEsh
+qqTqUr8C4DyBAGodOIStCLyqb46HjsNUz1ykoVr3s/3jVuuIDHq2kWd58XzZRTuM
+RnW4SkUQCB3jMXXfHzzIntjZqEKbdEVXdydAc4almnYjbju7VFGVXUHQH4scKzVh
+YGflMwKCAQEAkZWbhrAMJMGkWPgWaEOvuauOr3dyOhYK2xpboihKuvXlD+cv7296
+w//Hh3kLFCvORRGCbfjMCd+5EvsiXdqY0zokodOdYZZ8zgYaXFUMwCWNfOQGPGpb
++Kp5X+fc4c0q/faCeXdGvd1KrSJj1fkJh+nwqCfXNzENZOfRBtHWnjPUCkS9aNe1
+R2CEohDj26Zqklyjs6nu9XD/Iw3Xmaa3QWvtqlsIiSJqeF4rU4OPNdMb1P+NBCXp
++bdJrCXdGcqB9vD8HAiojr/GYKNWCbQzMx4o2OLkUEiQjwkKueTmPBOgc9UlhwkV
+sbgkXsSAxS5dl4O2gOOl0KnKoza0Nj/powKCAQB1L9v9XS7W/pl3H6/SxpfuFEuV
+uaX6s42tERKmuBQmvdnw9lJ2dqTz1TBhVHj0rxJRfz4BrSulsLojYLI0X9fDc+yQ
+/7JXclafKM1Sj+szfJ/+eYiu4QugjTl34qkcLBUVgNieyNLLGHEQ8r2ivaJ0w1e1
+td2T67hr6eicffyRNr+r7rIxsSKqm9yVIFaO82bVlZN0IHqJ0EgrEaG/cm7dM7tE
+7HAYy0/pQGnN3Zm4coFSzQv6SxtAPoPRz0inVe/b6bDfvxs3v7Kf7atm/HFK+IG3
+pO2I0pcEijyXrN58wnKjN2siImlWLQZbBnGTNtEttb6puKVi8DIFjWWnEFu8
+-----END RSA PRIVATE KEY-----
diff --git a/meta/meta-mediatek/files/additional-licenses/ARM b/meta/meta-mediatek/files/additional-licenses/ARM
new file mode 100644
index 0000000..952249a
--- /dev/null
+++ b/meta/meta-mediatek/files/additional-licenses/ARM
@@ -0,0 +1,7 @@
+ This confidential and proprietary software may be used only as
+ authorised by a licensing agreement from ARM Limited
+ (C) COPYRIGHT 2008-2015 ARM Limited
+ ALL RIGHTS RESERVED
+ The entire notice above must be reproduced on all authorised
+ copies and copies may only be made to the extent permitted
+ by a licensing agreement from ARM Limited.
diff --git a/meta/meta-mediatek/files/additional-licenses/IMGTEC b/meta/meta-mediatek/files/additional-licenses/IMGTEC
new file mode 100644
index 0000000..cf2fa6b
--- /dev/null
+++ b/meta/meta-mediatek/files/additional-licenses/IMGTEC
@@ -0,0 +1,3 @@
+
+Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+
diff --git a/meta/meta-mediatek/files/additional-licenses/MediaTekProprietary b/meta/meta-mediatek/files/additional-licenses/MediaTekProprietary
new file mode 100644
index 0000000..8acc0e7
--- /dev/null
+++ b/meta/meta-mediatek/files/additional-licenses/MediaTekProprietary
@@ -0,0 +1,31 @@
+Copyright Statement:
+
+This software/firmware and related documentation ("MediaTek Software") are
+protected under relevant copyright laws. The information contained herein is
+confidential and proprietary to MediaTek Inc. and/or its licensors. Without
+the prior written permission of MediaTek inc. and/or its licensors, any
+reproduction, modification, use or disclosure of MediaTek Software, and
+information contained herein, in whole or in part, shall be strictly
+prohibited.
+
+MediaTek Inc. (C) <YEAR> All rights reserved.
+
+BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
+ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL
+WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
+WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
+NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH
+RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
+INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES
+TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
+RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
+OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
+SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
+RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S
+ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE
+RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE
+MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
+CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
diff --git a/meta/meta-mediatek/recipes-bsp/bl33/bl33_1.0.bb b/meta/meta-mediatek/recipes-bsp/bl33/bl33_1.0.bb
new file mode 100644
index 0000000..eaec221
--- /dev/null
+++ b/meta/meta-mediatek/recipes-bsp/bl33/bl33_1.0.bb
@@ -0,0 +1,116 @@
+inherit deploy srcprebuilt externalsrc bl33-fitimage hsm-sign-env
+
+LICENSE = "MIT"
+MTK_SRC = "${TOPDIR}/../src/bsp/lk"
+BL33_OUT = "${WORKDIR}/out"
+LIC_FILES_CHKSUM = "file://${MTK_SRC}/LICENSE;md5=25394d472e4c06f4d61140e88861fb5b"
+SRC_URI = "file://dev_info file://pbp file://key file://lk_dts file://dummy_img file://fit-lk"
+#S = "${WORKDIR}"
+DEPENDS += "u-boot-mkimage-native bc-native dtc-native"
+
+TOOLCHAIN_PREFIX = "${TARGET_PREFIX}"
+EXTERNALSRC = "${MTK_SRC}"
+EXTERNALSRC_BUILD = "${MTK_SRC}"
+BL33_BINARY = "lk.bin"
+BL33_DEPLOY_BINARY = "bl33.bin"
+BL33_IMAGE = "bl33.img"
+PACKAGE_ARCH = "${MACHINE_ARCH}"
+DEPENDS += "libgcc"
+PBP_DIR = "${WORKDIR}/pbp"
+KEY_DIR = "${WORKDIR}/key"
+DTS_DIR = "${WORKDIR}/lk_dts"
+DUMMY_IMG_DIR="${WORKDIR}/dummy_img"
+
+IC_NAME="$(echo ${TARGET_PLATFORM}|tr '[a-z]' '[A-Z]')"
+DEV_INFO_HDR_TOOL = "${TOPDIR}/../src/bsp/scatter/scripts/dev-info-hdr-tool.py"
+
+do_configure () {
+ :
+}
+
+do_genkey () {
+ mkdir -p ${BL33_OUT}/include
+ if [ "${SECURE_BOOT_ENABLE}" = "yes" ]; then
+ mkdir -p ${WORKDIR}/mykeys
+ dtc -p 0x3ff ${DTS_DIR}/lk.dts -O dtb -o ${DTS_DIR}/lk.dtb
+ cp ${MTK_KEY_DIR}/${VERIFIED_KEY}.crt ${WORKDIR}/mykeys/dev.crt
+ cp ${MTK_KEY_DIR}/${VERIFIED_KEY}.pem ${WORKDIR}/mykeys/dev.key
+ ${HSM_ENV} HSM_KEY_NAME=${VERIFIED_KEY} uboot-mkimage -D "-I dts -O dtb -p 1024" -F -k ${WORKDIR}/mykeys -K ${DTS_DIR}/lk.dtb -r ${DUMMY_IMG_DIR}/fitImage
+ OFF_DT_STRINGS="`fdtdump ${DTS_DIR}/lk.dtb | grep off_dt_strings | sed "s,^\/\/.*:\s*0x,,"`"
+ SIZE_DT_STRINGS="`fdtdump ${DTS_DIR}/lk.dtb | grep size_dt_strings | sed "s,^\/\/.*:\s*0x,,"`"
+ KEYNODE_LEN="`echo "obase=16;ibase=16;${OFF_DT_STRINGS} + ${SIZE_DT_STRINGS}" | bc`"
+ python ${WORKDIR}/dev_info/dtb-transfer-array.py ${DTS_DIR}/lk.dtb ${DTS_DIR}/blob.h ${KEYNODE_LEN}
+ cp ${DTS_DIR}/blob.h ${BL33_OUT}/include/blob.h
+ rm -rf ${WORKDIR}/mykeys
+ else
+ cp ${DTS_DIR}/tmp_blob.txt ${BL33_OUT}/include/blob.h
+ fi
+}
+
+do_compile () {
+ if [ "${DEFAULTTUNE}" = "aarch64" ]; then
+ oe_runmake ARCH_arm64_TOOLCHAIN_PREFIX=${TOOLCHAIN_PREFIX} \
+ NOECHO="" \
+ BUILDROOT=${BL33_OUT} \
+ LIBGCC="" \
+ CFLAGS="" \
+ DEBUG=0 \
+ SECURE_BOOT_ENABLE=${SECURE_BOOT_ENABLE} \
+ SECURE_BOOT_TYPE=${SECURE_BOOT_TYPE} \
+ AVB_ENABLE_ANTIROLLBACK=${AVB_ENABLE_ANTIROLLBACK} \
+ AB_OTA_UPDATER=${AB_OTA_UPDATER} \
+ ${BL33_PROJECT}
+ else
+ oe_runmake TOOLCHAIN_PREFIX=${TOOLCHAIN_PREFIX} \
+ NOECHO="" \
+ BUILDROOT=${BL33_OUT} \
+ LIBGCC="$(${CC} --sysroot ${STAGING_DIR_HOST} -print-libgcc-file-name)" \
+ CFLAGS="" \
+ DEBUG=0 \
+ SECURE_BOOT_ENABLE=${SECURE_BOOT_ENABLE} \
+ SECURE_BOOT_TYPE=${SECURE_BOOT_TYPE} \
+ AVB_ENABLE_ANTIROLLBACK=${AVB_ENABLE_ANTIROLLBACK} \
+ AB_OTA_UPDATER=${AB_OTA_UPDATER} \
+ ${BL33_PROJECT}
+ fi
+ # add filesize check
+ start=$(grep -w _start -n ${BL33_OUT}/build-${BL33_PROJECT}/lk.elf.sym.sorted | \
+ sed -E 's/(.*):([0-9a-fA-F]+)(.*)/\2/' | tr '[:lower:]' '[:upper:]')
+ end=$(grep -w _end -n ${BL33_OUT}/build-${BL33_PROJECT}/lk.elf.sym.sorted | \
+ sed -E 's/(.*):([0-9a-fA-F]+)(.*)/\2/' | tr '[:lower:]' '[:upper:]')
+ fs=`echo "obase=16;ibase=16; $end - $start" | bc`
+ maxsize=${BL33_MAX_SIZE}
+ if [ ${BL33_MAX_SIZE} != "" ] && [[ 0x$fs -gt $maxsize ]]; then
+ bberror "Little kernel image size overflow, please have a check."
+ fi
+}
+
+do_buildclean () {
+ if [ "${DEFAULTTUNE}" = "aarch64" ]; then
+ oe_runmake ARCH_arm64_TOOLCHAIN_PREFIX=${TOOLCHAIN_PREFIX} \
+ NOECHO="" \
+ BUILDROOT=${BL33_OUT} \
+ LIBGCC="" \
+ CFLAGS="" \
+ DEBUG=0 \
+ ${BL33_PROJECT} clean
+ else
+ oe_runmake TOOLCHAIN_PREFIX=${TOOLCHAIN_PREFIX} \
+ NOECHO="" \
+ BUILDROOT=${BL33_OUT} \
+ LIBGCC="$(${CC} --sysroot ${STAGING_DIR_HOST} -print-libgcc-file-name)" \
+ CFLAGS="" \
+ DEBUG=0 \
+ ${BL33_PROJECT} clean
+ fi
+}
+
+do_deploy () {
+ install -d ${DEPLOYDIR}
+ install ${BL33_OUT}/build-${BL33_PROJECT}/${BL33_BINARY} ${DEPLOYDIR}/${BL33_DEPLOY_BINARY}
+ install ${WORKDIR}/${BL33_IMAGE} ${DEPLOYDIR}/${BL33_IMAGE}
+}
+
+addtask genkey before do_compile after do_configure
+addtask deploy before do_build after do_compile
+
diff --git a/meta/meta-mediatek/recipes-bsp/bl33/files/dev_info/dtb-transfer-array.py b/meta/meta-mediatek/recipes-bsp/bl33/files/dev_info/dtb-transfer-array.py
new file mode 100644
index 0000000..c6b3583
--- /dev/null
+++ b/meta/meta-mediatek/recipes-bsp/bl33/files/dev_info/dtb-transfer-array.py
@@ -0,0 +1,41 @@
+import os
+import sys
+
+def read_dtb(filename, raw_data):
+ fin = open(filename, 'rb')
+ fin.seek(0, 0)
+ while True:
+ t_byte = fin.read(1)
+ if len(t_byte) == 0:
+ break
+ else :
+ raw_data.append("0x%.2X" % ord(t_byte))
+
+def write_blob_head_file(filename, raw_data, length):
+ fout = open(filename, 'w+')
+ fout.write('#define CHECK_RSA 1 \n')
+ fout.write('#define CHECK_HASH 1 \n')
+ fout.write('const unsigned char blob[] __attribute__((aligned(4))) = \n')
+ fout.write('{\n ')
+
+ i = 0
+ for data in raw_data:
+ i += 1
+ if i != length:
+ fout.write(data + ', ')
+ else:
+ fout.write(data)
+ if i % 16 == 0:
+ fout.write('\n ')
+ if i == length:
+ break;
+ fout.write('\n};')
+ fout.close()
+
+if __name__ == "__main__":
+ raw_data = []
+ in_path = str(sys.argv[1]);
+ out_path = str(sys.argv[2]);
+ length = int(sys.argv[3],16);
+ read_dtb(in_path, raw_data)
+ write_blob_head_file(out_path, raw_data, length)
diff --git a/meta/meta-mediatek/recipes-bsp/bl33/files/dummy_img/fitImage b/meta/meta-mediatek/recipes-bsp/bl33/files/dummy_img/fitImage
new file mode 100644
index 0000000..036ed1b
--- /dev/null
+++ b/meta/meta-mediatek/recipes-bsp/bl33/files/dummy_img/fitImage
Binary files differ
diff --git a/meta/meta-mediatek/recipes-bsp/bl33/files/fit-lk/extract_region b/meta/meta-mediatek/recipes-bsp/bl33/files/fit-lk/extract_region
new file mode 100755
index 0000000..261ba30
--- /dev/null
+++ b/meta/meta-mediatek/recipes-bsp/bl33/files/fit-lk/extract_region
Binary files differ
diff --git a/meta/meta-mediatek/recipes-bsp/bl33/files/key/lk_key.ini b/meta/meta-mediatek/recipes-bsp/bl33/files/key/lk_key.ini
new file mode 100755
index 0000000..d6d089a
--- /dev/null
+++ b/meta/meta-mediatek/recipes-bsp/bl33/files/key/lk_key.ini
@@ -0,0 +1,4 @@
+[KEY]
+sw_ver = "1"
+rootkey = "root_prvk.pem"
+ac_key = "0x112233445566778899aabbccddeeff"
diff --git a/meta/meta-mediatek/recipes-bsp/bl33/files/key/root_prvk.pem b/meta/meta-mediatek/recipes-bsp/bl33/files/key/root_prvk.pem
new file mode 100644
index 0000000..fd987a3
--- /dev/null
+++ b/meta/meta-mediatek/recipes-bsp/bl33/files/key/root_prvk.pem
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEowIBAAKCAQEA0mlxI+3vrVlX8wH23CeTPDIH3c4DhEQNIGQltziYX7DOAHyf
+t/5s9TXAOmqIY0cyrQsjw837aiN3QGXONeQorP4+G5wlzWESJeJyAGlZ11hSijVp
+QQFwCT+++k4L8SEoMIgJUMNVd9pESqCYf08nhJXc/qgn++YiG8tMvHz9IA/Ef4OK
+XNj/+1+XyrtYRgYpfOwsoCgbe01NEpV3vM61fW0g3EtCQXW7MOD5VIWMkvTt+ob4
+qTF5/HpRlIJ5nth/8ZktkCx51Lu6yhQ1fw3KKPZ7A3ZmBtxSJ8I1xe1v/yWN+eD9
+Z9l7ZTkFVe8Avej6NnudkH1f6uTNmEETXOXHWwIDAQABAoIBAAdKjhgfo6GPKgQK
+umIwoOKCHVGrVOXdcdMAhWoO9QDD4K+Vofc/QslQfoPHs0g1bGUgsLGVTrQD3JsH
+rBij+mDcQoy0YX73cSiM60RmYi2bKukNJsOQ6C/53IVR9Qn7Cyh7Xk9FJY4Mqzcm
+z4IB3S2z/793VkNdWys5ZURW1HKq6R7s5Z937wlinPdJhwi7kI148NFnHFO793+z
+MGRC4n45CP13dHG3jktc46UYksP3sQ4CFcjFhKS6BPKDsyjmbCx1HUYjjcaLTy2d
+CJhYDlEvvkjU6CmQfe+cFpKYXnW5zZTwwx1uUDFiWOgSZupaieWZtyPCX7hqQ4ea
+Q6u7RxkCgYEA6+WjIwTB+D3PKP1x82RY2BMpWQRxHuVJs7T0H4zA+IicfJYc/+Sh
+0Esqzfj9ak/sEuNR1fIj4XCKODEVL3/n+qjBz8lbsNDjUrjG8jv3TiGkeaOeOyFR
+8jv0cvedzFk+1lQElFwSHrWAOfeoZRMHOoxK1MNkELjo2wFa67o6rxcCgYEA5FfR
+PJRyu2OmCVwqzycMbSOz6gB/5O5bnI9DxZf0oMNE1n5ElsZWynEFE5L33E+bvB/8
+AdC4cPPL1pg46KiDDkJ/BQhw+mC4wwvBHwjZFlKdQMYtgGb9ErFL4WPnllXy+ETD
+8U9Az1zOvj6thy3RYA7JGyZus4t9ecM5M+xItF0CgYBm+u7G4NLUzhbbrBjMyifG
+3EaWp8vCUxJjs0FHbKjpVqoJ8XZjd6n0Rnw/Qs1OVemXLUmSfoyPZBPTCApZnBrn
+YDiLvzmZ7PbwK94d7XO+1gz5VSZEZf1iJC5I6jQm+2blJfSB19fJNC7wH1+SEEZ9
+lrUsQMg0TKTKxsKsWbY4rQKBgEjP//aTV6qNcgqWC0iXKQ08T0iU9DNqFmhr/q5p
+cCY7Xh4PkYuKn25ab8X4HXVxJTXt9QwXJFlQRHWfgLYf1fqcFajjMjOE2CXJ/8EH
+r0HBAkf/ac8CCD0HsCylENoNejbUpq6yGPaGn55mmir630MEM/imXrJ+DnrfV8RI
+2j45AoGBAN/fhfcjGu5ix88+T9sEmV1lfoHyETQIZD4r5c9NufMXPcztE33XTqjI
+DpBfOCVQ8ZNuHuScQdQC55K8XT7wR9sQRhNvRua1K0IsfcL73ghCJin9i0yxMEzp
+s00NbHgvb2kfhxCC8eyoiCmpRk9A9xg2V22hx7Hkcwv+A62e9tN4
+-----END RSA PRIVATE KEY-----
diff --git a/meta/meta-mediatek/recipes-bsp/bl33/files/lk_dts/lk.dts b/meta/meta-mediatek/recipes-bsp/bl33/files/lk_dts/lk.dts
new file mode 100644
index 0000000..7b1b06f
--- /dev/null
+++ b/meta/meta-mediatek/recipes-bsp/bl33/files/lk_dts/lk.dts
@@ -0,0 +1,12 @@
+/dts-v1/;
+/ {
+ model = "Keys";
+ compatible = "mediatek,auto2701evb2-ivi";
+ signature {
+ key-dev {
+ required = "conf";
+ algo = "sha256,rsa2048";
+ key-name-hint = "dev";
+ };
+ };
+};
diff --git a/meta/meta-mediatek/recipes-bsp/bl33/files/lk_dts/tmp_blob.txt b/meta/meta-mediatek/recipes-bsp/bl33/files/lk_dts/tmp_blob.txt
new file mode 100644
index 0000000..744dd90
--- /dev/null
+++ b/meta/meta-mediatek/recipes-bsp/bl33/files/lk_dts/tmp_blob.txt
@@ -0,0 +1,7 @@
+#define CHECK_RSA 0
+#define CHECK_HASH 0
+
+const unsigned char blob[] __attribute__((aligned(4))) =
+{
+0
+};
\ No newline at end of file
diff --git a/meta/meta-mediatek/recipes-bsp/bl33/files/pbp/hsm.py b/meta/meta-mediatek/recipes-bsp/bl33/files/pbp/hsm.py
new file mode 100755
index 0000000..be8d484
--- /dev/null
+++ b/meta/meta-mediatek/recipes-bsp/bl33/files/pbp/hsm.py
@@ -0,0 +1,78 @@
+import filecmp
+import os
+
+g_key_table = None
+
+class hsm_param:
+ def __init__(self):
+ #you can add parameter required by your HSM here
+ self.m_ref_key_path = ""
+ self.m_key_id = 0
+ self.m_attr1 = 0
+ self.m_attr2 = 0
+ self.m_padding_dict = {"raw": 0, "pss": 1}
+ self.m_padding = 0 #default: raw
+
+def create_key_table():
+ global g_key_table
+ if None == g_key_table:
+ #create key table
+ #here is reference design, please customize
+ #this part according to your HSM spec.
+ script_folder, script_name = os.path.split(os.path.realpath(__file__))
+ key_folder = os.path.join(script_folder, "keys")
+ key_folder = os.path.join(key_folder, "hsm")
+ g_key_table = list()
+ #key1 parameter
+ key1_param = hsm_param()
+ key1_param.m_ref_key_path = os.path.join(key_folder, 'pubk1.pem')
+ key1_param.m_key_id = 0
+ key1_param.m_attr1 = 1
+ key1_param.m_attr2 = 1
+ g_key_table.append(key1_param)
+ #key2 parameter
+ key2_param = hsm_param()
+ key2_param.m_ref_key_path = os.path.join(key_folder, 'pubk2.pem')
+ key2_param.m_key_id = 1
+ key2_param.m_attr1 = 2
+ key2_param.m_attr2 = 2
+ g_key_table.append(key2_param)
+ return
+
+def query_key_table(key):
+ global g_key_table
+ create_key_table()
+ for key_table_entry in g_key_table:
+ if filecmp.cmp(key, key_table_entry.m_ref_key_path):
+ print "key index: " + hex(key_table_entry.m_key_id)
+ return key_table_entry
+ print "no valid key entry found in table"
+ return None
+
+def hsm_rsa_sign(data, key, padding, sig):
+ hsm_param_obj = None
+
+ #note that key is pubk actually, use it as index for
+ #HSM parameters such as key selection
+ hsm_param_obj = query_key_table(key)
+ if None == hsm_param_obj:
+ return -1
+ hsm_param_obj.m_padding = hsm_param_obj.m_padding_dict[padding]
+
+ print "========================"
+ print "HSM parameter:"
+ print " m_key_id = " + hex(hsm_param_obj.m_key_id)
+ print " m_padding = " + hex(hsm_param_obj.m_padding)
+ print " m_attr1 = " + hex(hsm_param_obj.m_attr1)
+ print " m_attr2 = " + hex(hsm_param_obj.m_attr2)
+ print "========================"
+
+ #place hsm request here -- start
+ #create dummy sig for now
+ sig_file = open(sig, 'wb')
+ for i in range(0, 256):
+ sig_file.write(chr(0))
+ sig_file.close()
+ #place hsm request here -- end
+ return 0
+
diff --git a/meta/meta-mediatek/recipes-bsp/bl33/files/pbp/keys/sctrlcert/root_prvk.pem b/meta/meta-mediatek/recipes-bsp/bl33/files/pbp/keys/sctrlcert/root_prvk.pem
new file mode 100644
index 0000000..715ecca
--- /dev/null
+++ b/meta/meta-mediatek/recipes-bsp/bl33/files/pbp/keys/sctrlcert/root_prvk.pem
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEowIBAAKCAQEA0WQDRmxTDvm7U8HoqWphpOMy4X3A9Vu0bSB6wwW66TVOqsLL
+MHezN0DSdQNrgi2yaCAN4X2j23JmsnaGuJcLhXNwUPCE+NV2kE50zWxTsx8LsM1g
+aGv2fGDaDsIPVj7qcVzr2/dtHFwQ6YKrKVXYM95VPJza/X6iOIwCgjz+fdmsg/oq
+jrBoWr2rVqkt8aeAXorAvRDA89yxdwqea7w0GMX4Ski3yyMWssj2SXLzkbEWpYyT
+lanOnnQ1aaNnCG13cdOf7I67uj3StRl4Wnap9YnTbWN6+IRUP9ZbrHW+gjwMUKoW
+1YGHuXIjYlxUxmtaXk266re+iaTjQKLiQbCbLwIDAQABAoIBAAmXZTcCm0NiWRxb
+E4c/Ij3lUl1V31Ld4oPlKvpn9snb8UCNL7WGpiTvyTQm9fO+mB+A6GHd2XWh5eZi
+24T1FkgEo65xdgXX8Vhm357RSXw4/dYZckMWPvIvlY17gixXMXID6aHn0Y2tAfFQ
+VPrNvduSYaEnJjjaZh/k+fBxTs8A5lQcxDWvsf11on00sXrUAOlHS6hQ2vziZnmc
+r/MqBY/3Hkwtqsr4unCenKTch1hKf/6KqaChYO0GnDlwt9rjmH3tcb0LyCQ1aYe9
+dDY9RmgscZE8PtvbKpEfcB8jruP43ZgYC1oTj9WtdHQ2gtLS0bs9knhnECSPMW3Y
+ORF46oECgYEA8qz+H+tuqxCKAA1p6EXmegpEcqhkwapviqgMZMQAejfW//bf8LYd
+9CsyTtWER1uxJ+PjvhW/K0NYXn+tbWzrsW1UK/AaYwvaB9+JsjU07aZh9kmADZJi
+3KkPsKp4Unqlno59XkLm3XE9REoHursnIkiuzHZnqh/+50ck+GJGQQ8CgYEA3OMr
+xNfLkuTs5NyBDBCYSOf0s2wfLgpfu4eaUYuYMGoAAL4trvrLtW5tcW63ObMy51V5
+EJJAH3vk/EK9EgevMYGwbiVB7pkb11tcnLoxelorTAbpDCzSorbW71mruX11496w
+GBJw4yQcIUxET5GxU14qTEK4wLQQ7AZQIKVtw+ECgYEAv/YJuzQfwZ9+mhYCPaL1
+cnomtM/xi6SHQRY3X4oPmp4LK0Sc1ispPJji3atWTKACXbyNzTIkm1NVVsMGa7Wq
+JxqFZ5AxP0IDwRCZOmeOK6LegNSZP6MZItV0vNnL/epYkjjCgMrJFkfaH+ezf4lF
+pn/6DXBoBhHzL/1+CCCs1A8CgYBPk1+fSIbEYsidInszF39lNHtJcDhDY+VdL9r+
+aaXoOyfJHLpkgWGF+URgSxyjItXB1V8KA0YqkX3LC1gF+NK6qRggdjesd2g6S2Wv
+6LwOchGLECpBApzXlbsU+18MMhCYiQ8zfOFCUy33KPyrFbemaxQd6SOZ+MTn4tZX
+DIHgwQKBgFLvSmrc8eLKRDDDxdvZYiu8JMm/DS4TdbK3P2u67hhxd3Y4whdQboF5
+zHbkkTBIuKoFbbQj3bB91KmCIcxNkT66Xe3qmoAfDrUMp7cxBLcnpoDpJIXTlKnG
+bHThVsqvJvuwQByr2oUGUJd8eerqzUCAgx/mi+/9aTe+ztB/KmBF
+-----END RSA PRIVATE KEY-----
diff --git a/meta/meta-mediatek/recipes-bsp/bl33/files/pbp/keys/toolauth/da_prvk.pem b/meta/meta-mediatek/recipes-bsp/bl33/files/pbp/keys/toolauth/da_prvk.pem
new file mode 100644
index 0000000..715ecca
--- /dev/null
+++ b/meta/meta-mediatek/recipes-bsp/bl33/files/pbp/keys/toolauth/da_prvk.pem
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEowIBAAKCAQEA0WQDRmxTDvm7U8HoqWphpOMy4X3A9Vu0bSB6wwW66TVOqsLL
+MHezN0DSdQNrgi2yaCAN4X2j23JmsnaGuJcLhXNwUPCE+NV2kE50zWxTsx8LsM1g
+aGv2fGDaDsIPVj7qcVzr2/dtHFwQ6YKrKVXYM95VPJza/X6iOIwCgjz+fdmsg/oq
+jrBoWr2rVqkt8aeAXorAvRDA89yxdwqea7w0GMX4Ski3yyMWssj2SXLzkbEWpYyT
+lanOnnQ1aaNnCG13cdOf7I67uj3StRl4Wnap9YnTbWN6+IRUP9ZbrHW+gjwMUKoW
+1YGHuXIjYlxUxmtaXk266re+iaTjQKLiQbCbLwIDAQABAoIBAAmXZTcCm0NiWRxb
+E4c/Ij3lUl1V31Ld4oPlKvpn9snb8UCNL7WGpiTvyTQm9fO+mB+A6GHd2XWh5eZi
+24T1FkgEo65xdgXX8Vhm357RSXw4/dYZckMWPvIvlY17gixXMXID6aHn0Y2tAfFQ
+VPrNvduSYaEnJjjaZh/k+fBxTs8A5lQcxDWvsf11on00sXrUAOlHS6hQ2vziZnmc
+r/MqBY/3Hkwtqsr4unCenKTch1hKf/6KqaChYO0GnDlwt9rjmH3tcb0LyCQ1aYe9
+dDY9RmgscZE8PtvbKpEfcB8jruP43ZgYC1oTj9WtdHQ2gtLS0bs9knhnECSPMW3Y
+ORF46oECgYEA8qz+H+tuqxCKAA1p6EXmegpEcqhkwapviqgMZMQAejfW//bf8LYd
+9CsyTtWER1uxJ+PjvhW/K0NYXn+tbWzrsW1UK/AaYwvaB9+JsjU07aZh9kmADZJi
+3KkPsKp4Unqlno59XkLm3XE9REoHursnIkiuzHZnqh/+50ck+GJGQQ8CgYEA3OMr
+xNfLkuTs5NyBDBCYSOf0s2wfLgpfu4eaUYuYMGoAAL4trvrLtW5tcW63ObMy51V5
+EJJAH3vk/EK9EgevMYGwbiVB7pkb11tcnLoxelorTAbpDCzSorbW71mruX11496w
+GBJw4yQcIUxET5GxU14qTEK4wLQQ7AZQIKVtw+ECgYEAv/YJuzQfwZ9+mhYCPaL1
+cnomtM/xi6SHQRY3X4oPmp4LK0Sc1ispPJji3atWTKACXbyNzTIkm1NVVsMGa7Wq
+JxqFZ5AxP0IDwRCZOmeOK6LegNSZP6MZItV0vNnL/epYkjjCgMrJFkfaH+ezf4lF
+pn/6DXBoBhHzL/1+CCCs1A8CgYBPk1+fSIbEYsidInszF39lNHtJcDhDY+VdL9r+
+aaXoOyfJHLpkgWGF+URgSxyjItXB1V8KA0YqkX3LC1gF+NK6qRggdjesd2g6S2Wv
+6LwOchGLECpBApzXlbsU+18MMhCYiQ8zfOFCUy33KPyrFbemaxQd6SOZ+MTn4tZX
+DIHgwQKBgFLvSmrc8eLKRDDDxdvZYiu8JMm/DS4TdbK3P2u67hhxd3Y4whdQboF5
+zHbkkTBIuKoFbbQj3bB91KmCIcxNkT66Xe3qmoAfDrUMp7cxBLcnpoDpJIXTlKnG
+bHThVsqvJvuwQByr2oUGUJd8eerqzUCAgx/mi+/9aTe+ztB/KmBF
+-----END RSA PRIVATE KEY-----
diff --git a/meta/meta-mediatek/recipes-bsp/bl33/files/pbp/keys/toolauth/root_prvk.pem b/meta/meta-mediatek/recipes-bsp/bl33/files/pbp/keys/toolauth/root_prvk.pem
new file mode 100644
index 0000000..715ecca
--- /dev/null
+++ b/meta/meta-mediatek/recipes-bsp/bl33/files/pbp/keys/toolauth/root_prvk.pem
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEowIBAAKCAQEA0WQDRmxTDvm7U8HoqWphpOMy4X3A9Vu0bSB6wwW66TVOqsLL
+MHezN0DSdQNrgi2yaCAN4X2j23JmsnaGuJcLhXNwUPCE+NV2kE50zWxTsx8LsM1g
+aGv2fGDaDsIPVj7qcVzr2/dtHFwQ6YKrKVXYM95VPJza/X6iOIwCgjz+fdmsg/oq
+jrBoWr2rVqkt8aeAXorAvRDA89yxdwqea7w0GMX4Ski3yyMWssj2SXLzkbEWpYyT
+lanOnnQ1aaNnCG13cdOf7I67uj3StRl4Wnap9YnTbWN6+IRUP9ZbrHW+gjwMUKoW
+1YGHuXIjYlxUxmtaXk266re+iaTjQKLiQbCbLwIDAQABAoIBAAmXZTcCm0NiWRxb
+E4c/Ij3lUl1V31Ld4oPlKvpn9snb8UCNL7WGpiTvyTQm9fO+mB+A6GHd2XWh5eZi
+24T1FkgEo65xdgXX8Vhm357RSXw4/dYZckMWPvIvlY17gixXMXID6aHn0Y2tAfFQ
+VPrNvduSYaEnJjjaZh/k+fBxTs8A5lQcxDWvsf11on00sXrUAOlHS6hQ2vziZnmc
+r/MqBY/3Hkwtqsr4unCenKTch1hKf/6KqaChYO0GnDlwt9rjmH3tcb0LyCQ1aYe9
+dDY9RmgscZE8PtvbKpEfcB8jruP43ZgYC1oTj9WtdHQ2gtLS0bs9knhnECSPMW3Y
+ORF46oECgYEA8qz+H+tuqxCKAA1p6EXmegpEcqhkwapviqgMZMQAejfW//bf8LYd
+9CsyTtWER1uxJ+PjvhW/K0NYXn+tbWzrsW1UK/AaYwvaB9+JsjU07aZh9kmADZJi
+3KkPsKp4Unqlno59XkLm3XE9REoHursnIkiuzHZnqh/+50ck+GJGQQ8CgYEA3OMr
+xNfLkuTs5NyBDBCYSOf0s2wfLgpfu4eaUYuYMGoAAL4trvrLtW5tcW63ObMy51V5
+EJJAH3vk/EK9EgevMYGwbiVB7pkb11tcnLoxelorTAbpDCzSorbW71mruX11496w
+GBJw4yQcIUxET5GxU14qTEK4wLQQ7AZQIKVtw+ECgYEAv/YJuzQfwZ9+mhYCPaL1
+cnomtM/xi6SHQRY3X4oPmp4LK0Sc1ispPJji3atWTKACXbyNzTIkm1NVVsMGa7Wq
+JxqFZ5AxP0IDwRCZOmeOK6LegNSZP6MZItV0vNnL/epYkjjCgMrJFkfaH+ezf4lF
+pn/6DXBoBhHzL/1+CCCs1A8CgYBPk1+fSIbEYsidInszF39lNHtJcDhDY+VdL9r+
+aaXoOyfJHLpkgWGF+URgSxyjItXB1V8KA0YqkX3LC1gF+NK6qRggdjesd2g6S2Wv
+6LwOchGLECpBApzXlbsU+18MMhCYiQ8zfOFCUy33KPyrFbemaxQd6SOZ+MTn4tZX
+DIHgwQKBgFLvSmrc8eLKRDDDxdvZYiu8JMm/DS4TdbK3P2u67hhxd3Y4whdQboF5
+zHbkkTBIuKoFbbQj3bB91KmCIcxNkT66Xe3qmoAfDrUMp7cxBLcnpoDpJIXTlKnG
+bHThVsqvJvuwQByr2oUGUJd8eerqzUCAgx/mi+/9aTe+ztB/KmBF
+-----END RSA PRIVATE KEY-----
diff --git a/meta/meta-mediatek/recipes-bsp/bl33/files/pbp/keys/toolauth/sla_prvk.pem b/meta/meta-mediatek/recipes-bsp/bl33/files/pbp/keys/toolauth/sla_prvk.pem
new file mode 100644
index 0000000..715ecca
--- /dev/null
+++ b/meta/meta-mediatek/recipes-bsp/bl33/files/pbp/keys/toolauth/sla_prvk.pem
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEowIBAAKCAQEA0WQDRmxTDvm7U8HoqWphpOMy4X3A9Vu0bSB6wwW66TVOqsLL
+MHezN0DSdQNrgi2yaCAN4X2j23JmsnaGuJcLhXNwUPCE+NV2kE50zWxTsx8LsM1g
+aGv2fGDaDsIPVj7qcVzr2/dtHFwQ6YKrKVXYM95VPJza/X6iOIwCgjz+fdmsg/oq
+jrBoWr2rVqkt8aeAXorAvRDA89yxdwqea7w0GMX4Ski3yyMWssj2SXLzkbEWpYyT
+lanOnnQ1aaNnCG13cdOf7I67uj3StRl4Wnap9YnTbWN6+IRUP9ZbrHW+gjwMUKoW
+1YGHuXIjYlxUxmtaXk266re+iaTjQKLiQbCbLwIDAQABAoIBAAmXZTcCm0NiWRxb
+E4c/Ij3lUl1V31Ld4oPlKvpn9snb8UCNL7WGpiTvyTQm9fO+mB+A6GHd2XWh5eZi
+24T1FkgEo65xdgXX8Vhm357RSXw4/dYZckMWPvIvlY17gixXMXID6aHn0Y2tAfFQ
+VPrNvduSYaEnJjjaZh/k+fBxTs8A5lQcxDWvsf11on00sXrUAOlHS6hQ2vziZnmc
+r/MqBY/3Hkwtqsr4unCenKTch1hKf/6KqaChYO0GnDlwt9rjmH3tcb0LyCQ1aYe9
+dDY9RmgscZE8PtvbKpEfcB8jruP43ZgYC1oTj9WtdHQ2gtLS0bs9knhnECSPMW3Y
+ORF46oECgYEA8qz+H+tuqxCKAA1p6EXmegpEcqhkwapviqgMZMQAejfW//bf8LYd
+9CsyTtWER1uxJ+PjvhW/K0NYXn+tbWzrsW1UK/AaYwvaB9+JsjU07aZh9kmADZJi
+3KkPsKp4Unqlno59XkLm3XE9REoHursnIkiuzHZnqh/+50ck+GJGQQ8CgYEA3OMr
+xNfLkuTs5NyBDBCYSOf0s2wfLgpfu4eaUYuYMGoAAL4trvrLtW5tcW63ObMy51V5
+EJJAH3vk/EK9EgevMYGwbiVB7pkb11tcnLoxelorTAbpDCzSorbW71mruX11496w
+GBJw4yQcIUxET5GxU14qTEK4wLQQ7AZQIKVtw+ECgYEAv/YJuzQfwZ9+mhYCPaL1
+cnomtM/xi6SHQRY3X4oPmp4LK0Sc1ispPJji3atWTKACXbyNzTIkm1NVVsMGa7Wq
+JxqFZ5AxP0IDwRCZOmeOK6LegNSZP6MZItV0vNnL/epYkjjCgMrJFkfaH+ezf4lF
+pn/6DXBoBhHzL/1+CCCs1A8CgYBPk1+fSIbEYsidInszF39lNHtJcDhDY+VdL9r+
+aaXoOyfJHLpkgWGF+URgSxyjItXB1V8KA0YqkX3LC1gF+NK6qRggdjesd2g6S2Wv
+6LwOchGLECpBApzXlbsU+18MMhCYiQ8zfOFCUy33KPyrFbemaxQd6SOZ+MTn4tZX
+DIHgwQKBgFLvSmrc8eLKRDDDxdvZYiu8JMm/DS4TdbK3P2u67hhxd3Y4whdQboF5
+zHbkkTBIuKoFbbQj3bB91KmCIcxNkT66Xe3qmoAfDrUMp7cxBLcnpoDpJIXTlKnG
+bHThVsqvJvuwQByr2oUGUJd8eerqzUCAgx/mi+/9aTe+ztB/KmBF
+-----END RSA PRIVATE KEY-----
diff --git a/meta/meta-mediatek/recipes-bsp/bl33/files/pbp/lib/asn1_gen.pyc b/meta/meta-mediatek/recipes-bsp/bl33/files/pbp/lib/asn1_gen.pyc
new file mode 100644
index 0000000..554f44d
--- /dev/null
+++ b/meta/meta-mediatek/recipes-bsp/bl33/files/pbp/lib/asn1_gen.pyc
Binary files differ
diff --git a/meta/meta-mediatek/recipes-bsp/bl33/files/pbp/lib/cert.pyc b/meta/meta-mediatek/recipes-bsp/bl33/files/pbp/lib/cert.pyc
new file mode 100644
index 0000000..e9a251c
--- /dev/null
+++ b/meta/meta-mediatek/recipes-bsp/bl33/files/pbp/lib/cert.pyc
Binary files differ
diff --git a/meta/meta-mediatek/recipes-bsp/bl33/files/pbp/lib/dainfo.pyc b/meta/meta-mediatek/recipes-bsp/bl33/files/pbp/lib/dainfo.pyc
new file mode 100644
index 0000000..77a358f
--- /dev/null
+++ b/meta/meta-mediatek/recipes-bsp/bl33/files/pbp/lib/dainfo.pyc
Binary files differ
diff --git a/meta/meta-mediatek/recipes-bsp/bl33/files/pbp/lib/gfh.pyc b/meta/meta-mediatek/recipes-bsp/bl33/files/pbp/lib/gfh.pyc
new file mode 100644
index 0000000..3931c7d
--- /dev/null
+++ b/meta/meta-mediatek/recipes-bsp/bl33/files/pbp/lib/gfh.pyc
Binary files differ
diff --git a/meta/meta-mediatek/recipes-bsp/bl33/files/pbp/lib/hsm_hook.pyc b/meta/meta-mediatek/recipes-bsp/bl33/files/pbp/lib/hsm_hook.pyc
new file mode 100644
index 0000000..2e3d7bc
--- /dev/null
+++ b/meta/meta-mediatek/recipes-bsp/bl33/files/pbp/lib/hsm_hook.pyc
Binary files differ
diff --git a/meta/meta-mediatek/recipes-bsp/bl33/files/pbp/pbp.py b/meta/meta-mediatek/recipes-bsp/bl33/files/pbp/pbp.py
new file mode 100755
index 0000000..6420a8f
--- /dev/null
+++ b/meta/meta-mediatek/recipes-bsp/bl33/files/pbp/pbp.py
@@ -0,0 +1,272 @@
+import sys
+import os
+import struct
+import subprocess
+import shutil
+script_folder, script_name = os.path.split(os.path.realpath(__file__))
+sys.path.append(os.path.join(script_folder, "lib"))
+import gfh
+import cert
+
+def get_file_sizeb(file_path):
+ if not os.path.isfile(file_path):
+ return 0
+ file_handle = open(file_path, "rb")
+ file_handle.seek(0, 2)
+ file_size = file_handle.tell()
+ file_handle.close()
+ return file_size
+
+def concatb(file1_path, file2_path):
+ file1_size = get_file_sizeb(file1_path)
+ file2_size = get_file_sizeb(file2_path)
+ file1 = open(file1_path, "ab+")
+ file2 = open(file2_path, "rb")
+ file1.write(file2.read(file2_size))
+ file2.close()
+ file1.close()
+
+class bootloader:
+ def __init__(self, out_path, in_bootloader_file_path, out_bootloader_file_path):
+ self.m_gfh = gfh.image_gfh()
+ self.m_out_path = out_path
+ if not os.path.exists(self.m_out_path):
+ os.makedirs(self.m_out_path)
+ self.m_in_bootloader_file_path = in_bootloader_file_path
+ self.m_out_bootloader_file_path = out_bootloader_file_path
+ self.m_bootloader_is_signed = False
+ self.m_bootloader_content_offset = 0
+ #initialize content size to bootloader file size
+ self.m_bootloader_content_length = get_file_sizeb(self.m_in_bootloader_file_path)
+ self.m_bootloader_sig_size = 0
+ #generate file path for bootloader without gfh and signature
+ bootloader_path = in_bootloader_file_path.split('.')
+ self.m_bootloader_no_gfh_file_path = bootloader_path[0] + "_plain.bin"
+ self.m_sig_ver = 0
+ self.m_sw_ver = 0
+ self.m_root_prvk_path = ""
+ self.m_img_prvk_path = ""
+ self.m_ac_key = 0
+ self.m_sig_handler = None
+ def is_signed(self):
+ if self.m_in_bootloader_file_path:
+ bootloader_file = open(self.m_in_bootloader_file_path, "rb")
+ gfh_hdr_obj = gfh.gfh_header()
+ gfh_hdr_size = gfh_hdr_obj.get_size()
+ gfh_hdr_buf = bootloader_file.read(gfh_hdr_size)
+ self.m_bootloader_is_signed = gfh_hdr_obj.is_gfh(gfh_hdr_buf)
+ bootloader_file.close()
+ return self.m_bootloader_is_signed
+ def parse(self):
+ print "===parse bootloader==="
+ #image will be decomposed if it's signed
+ if self.is_signed():
+ gfh_total_size = self.m_gfh.parse(self.m_in_bootloader_file_path)
+ self.m_bootloader_content_offset = gfh_total_size
+ self.m_bootloader_content_length -= gfh_total_size
+ self.m_bootloader_content_length -= self.m_gfh.get_sig_size()
+ self.m_bootloader_sig_size = self.m_gfh.get_sig_size()
+ in_file = open(self.m_in_bootloader_file_path, "rb")
+ out_file = open(self.m_bootloader_no_gfh_file_path, "wb")
+ in_file.seek(self.m_bootloader_content_offset)
+ out_file.write(in_file.read(self.m_bootloader_content_length))
+ out_file.close()
+ in_file.close()
+ else:
+ shutil.copyfile(self.m_in_bootloader_file_path, self.m_bootloader_no_gfh_file_path)
+ print "bootloader content size = " + hex(self.m_bootloader_content_length)
+ def create_gfh(self, gfh_config):
+ self.parse()
+ if gfh_config:
+ if self.is_signed():
+ del self.m_gfh.gfhs[:]
+ self.m_gfh.load_ini(gfh_config)
+ elif not self.is_signed():
+ print "GFH_CONFIG.ini does not exist!!"
+ return -1
+ #self.m_gfh.dump()
+ return 0
+ def sign(self, key_ini_path, key_cert_path, content_config_file_path):
+ self.m_gfh.finalize(self.m_bootloader_content_length, key_ini_path)
+ #create tbs_bootloader.bin
+ tbs_bootloader_file_path = os.path.join(self.m_out_path, "tbs_preloader.bin")
+ tbs_bootloader_file = open(tbs_bootloader_file_path, "wb")
+ tbs_bootloader_file.write(self.m_gfh.pack())
+ bootloader_no_gfh_file = open(self.m_bootloader_no_gfh_file_path, "rb")
+ tbs_bootloader_file.write(bootloader_no_gfh_file.read(self.m_bootloader_content_length))
+ bootloader_no_gfh_file.close()
+ tbs_bootloader_file.close()
+ print "===sign==="
+ if self.m_gfh.get_sig_type() == "CERT_CHAIN":
+ self.m_sig_handler = cert.cert_chain_v2()
+ #create key cert if key cert does not exist
+ if key_cert_path == "":
+ key_cert_path = os.path.join(self.m_out_path, "key_cert.bin")
+ if not os.path.isfile(key_cert_path):
+ key_cert_folder_name, key_cert_file_name = os.path.split(os.path.abspath(key_cert_path))
+ self.m_sig_handler.create_key_cert(key_ini_path, self.m_out_path, key_cert_file_name)
+ key_cert_path = os.path.join(self.m_out_path, key_cert_file_name)
+ else:
+ self.m_sig_handler.set_key_cert(key_cert_path)
+ #create content cert
+ content_cert_name = "content_cert.bin"
+ self.m_sig_handler.create_content_cert(content_config_file_path, tbs_bootloader_file_path, self.m_out_path, content_cert_name)
+ #create final cert chain
+ sig_name = "preloader.sig"
+ sig_file_path = os.path.join(self.m_out_path, sig_name)
+ self.m_sig_handler.output(self.m_out_path, sig_name)
+ #output final cert chain size
+ sig_size_name = "sig_size.txt"
+ sig_size_file_path = os.path.join(self.m_out_path, sig_size_name)
+ sig_size_file = open(sig_size_file_path, 'w')
+ sig_size_file.write(hex(get_file_sizeb(sig_file_path)))
+ sig_size_file.close()
+ #create final preloader image
+ if os.path.isfile(self.m_out_bootloader_file_path):
+ os.remove(self.m_out_bootloader_file_path)
+ concatb(self.m_out_bootloader_file_path, tbs_bootloader_file_path)
+ concatb(self.m_out_bootloader_file_path, sig_file_path)
+ #clean up
+ os.remove(os.path.join(self.m_out_path, content_cert_name))
+ elif self.m_gfh.get_sig_type() == "SINGLE_AND_PHASH":
+ self.m_sig_handler = cert.sig_single_and_phash(self.m_gfh.get_pad_type())
+ self.m_sig_handler.set_out_path(self.m_out_path)
+ self.m_sig_handler.create(key_ini_path, tbs_bootloader_file_path)
+ #signature generation
+ self.m_sig_handler.sign()
+ sig_name = "preloader.sig"
+ sig_file_path = os.path.join(self.m_out_path, sig_name)
+ self.m_sig_handler.output(self.m_out_path, sig_name)
+ #output signature size
+ sig_size_name = "sig_size.txt"
+ sig_size_file_path = os.path.join(self.m_out_path, sig_size_name)
+ sig_size_file = open(sig_size_file_path, 'w')
+ sig_size_file.write(hex(get_file_sizeb(sig_file_path)))
+ sig_size_file.close()
+ #create final preloader image
+ if os.path.isfile(self.m_out_bootloader_file_path):
+ os.remove(self.m_out_bootloader_file_path)
+ concatb(self.m_out_bootloader_file_path, tbs_bootloader_file_path)
+ concatb(self.m_out_bootloader_file_path, sig_file_path)
+ else:
+ print "unknown signature type"
+ #clean up
+ os.remove(self.m_bootloader_no_gfh_file_path)
+ os.remove(tbs_bootloader_file_path)
+ os.remove(sig_file_path)
+ return
+
+def main():
+ #parameter parsing
+ idx = 1
+ key_ini_path = ""
+ key_path = ""
+ gfh_config_ini_path = ""
+ content_config_ini_path = ""
+ key_cert_path = ""
+ in_bootloader_path = ""
+ function = "sign"
+ function_out_path = ""
+ while idx < len(sys.argv):
+ if sys.argv[idx][0] == '-':
+ if sys.argv[idx][1] == 'i':
+ print "key ini: " + sys.argv[idx + 1]
+ key_ini_path = sys.argv[idx + 1]
+ idx += 2
+ if sys.argv[idx][1] == 'j':
+ print "key(pem): " + sys.argv[idx + 1]
+ key_path = sys.argv[idx + 1]
+ idx += 2
+ elif sys.argv[idx][1] == 'g':
+ print "gfh config: " + sys.argv[idx + 1]
+ gfh_config_ini_path = sys.argv[idx + 1]
+ idx += 2
+ elif sys.argv[idx][1] == 'c':
+ print "content config: " + sys.argv[idx + 1]
+ content_config_ini_path = sys.argv[idx + 1]
+ idx += 2
+ elif sys.argv[idx][1] == 'k':
+ print "key cert: " + sys.argv[idx + 1]
+ key_cert_path = sys.argv[idx + 1]
+ idx += 2
+ elif sys.argv[idx][1:] == 'func':
+ print "function: " + sys.argv[idx + 1]
+ function = sys.argv[idx + 1]
+ idx += 2
+ elif sys.argv[idx][1] == 'o':
+ print "function output: " + sys.argv[idx + 1]
+ function_out_path = sys.argv[idx + 1]
+ idx += 2
+ else:
+ print "unknown input"
+ idx += 2
+ else:
+ in_bootloader_path = sys.argv[idx]
+ print "bootloader: " + in_bootloader_path
+ idx += 1
+
+ if (function == "sign") and (not in_bootloader_path):
+ print "bootloader path is not given!"
+ return -1
+ if (not function_out_path):
+ print "function out path is not given!"
+ return -1
+ if function == "sign":
+ if (key_ini_path == "") and (key_cert_path == ""):
+ print "key path is not given!"
+ return -1
+ else:
+ if (key_path == "" and key_ini_path == ""):
+ print "key path is not given!"
+ return -1
+
+ out_path = os.path.dirname(os.path.abspath(function_out_path))
+ if not os.path.exists(out_path):
+ os.makedirs(out_path)
+
+ if function == "sign":
+ bootloader_obj = bootloader(out_path, in_bootloader_path, function_out_path)
+ bootloader_obj.create_gfh(gfh_config_ini_path)
+ bootloader_obj.sign(key_ini_path, key_cert_path, content_config_ini_path)
+ return 0
+ elif function == "keybin_pss":
+ key = cert.ct_key("pss")
+ key.create(key_path)
+ key_bin = key.pack()
+ out_file = open(function_out_path, "wb")
+ out_file.write(key_bin)
+ out_file.close()
+ return 0
+ elif function == "keybin_legacy":
+ key = cert.ct_key("legacy")
+ key.create(key_path)
+ key_bin = key.pack()
+ out_file = open(function_out_path, "wb")
+ out_file.write(key_bin)
+ out_file.close()
+ return 0
+ elif function == "keyhash_pss":
+ key = cert.ct_key("pss")
+ key.create(key_path)
+ key_bin = key.pack()
+ tmp_key_bin_path = os.path.join(out_path, "tmp_keybin.bin")
+ out_file = open(tmp_key_bin_path, "wb")
+ out_file.write(key_bin)
+ out_file.close()
+ cert.hash_gen(tmp_key_bin_path, function_out_path)
+ os.remove(tmp_key_bin_path)
+ return 0
+ elif function == "keyhash_legacy":
+ key = cert.ct_key("legacy")
+ key.create(key_path)
+ key_bin = key.pack()
+ tmp_key_bin_path = os.path.join(out_path, "tmp_keybin.bin")
+ out_file = open(tmp_key_bin_path, "wb")
+ out_file.write(key_bin)
+ out_file.close()
+ cert.hash_gen(tmp_key_bin_path, function_out_path)
+ os.remove(tmp_key_bin_path)
+ return 0
+
+if __name__ == '__main__':
+ main()
diff --git a/meta/meta-mediatek/recipes-bsp/bl33/files/pbp/prebuilt/toolauth/MTK_AllInOne_DA.bin b/meta/meta-mediatek/recipes-bsp/bl33/files/pbp/prebuilt/toolauth/MTK_AllInOne_DA.bin
new file mode 100644
index 0000000..3f5aea7
--- /dev/null
+++ b/meta/meta-mediatek/recipes-bsp/bl33/files/pbp/prebuilt/toolauth/MTK_AllInOne_DA.bin
Binary files differ
diff --git a/meta/meta-mediatek/recipes-bsp/bl33/files/pbp/sctrlcert.py b/meta/meta-mediatek/recipes-bsp/bl33/files/pbp/sctrlcert.py
new file mode 100755
index 0000000..214703f
--- /dev/null
+++ b/meta/meta-mediatek/recipes-bsp/bl33/files/pbp/sctrlcert.py
@@ -0,0 +1,170 @@
+import sys
+import os
+import struct
+script_folder, script_name = os.path.split(os.path.realpath(__file__))
+sys.path.append(os.path.join(script_folder, "lib"))
+import gfh
+import cert
+
+def get_file_sizeb(file_path):
+ if not os.path.isfile(file_path):
+ return 0
+ file_handle = open(file_path, "rb")
+ file_handle.seek(0, 2)
+ file_size = file_handle.tell()
+ file_handle.close()
+ return file_size
+
+def concatb(file1_path, file2_path):
+ file1_size = get_file_sizeb(file1_path)
+ file2_size = get_file_sizeb(file2_path)
+ file1 = open(file1_path, "ab+")
+ file2 = open(file2_path, "rb")
+ file1.write(file2.read(file2_size))
+ file2.close()
+ file1.close()
+
+class sctrl_cert:
+ def __init__(self, out_path, sctrl_cert_path):
+ self.m_out_path = out_path
+ if not os.path.exists(self.m_out_path):
+ os.makedirs(self.m_out_path)
+ self.m_sctrl_cert_path = sctrl_cert_path
+ self.m_gfh = gfh.image_gfh()
+ self.m_key_path = ""
+ self.m_out_path = out_path
+ self.m_sig_handler = None
+ def create_gfh(self, gfh_config):
+ self.m_gfh.load_ini(gfh_config)
+ self.m_gfh.dump()
+ return
+ def sign(self, key_ini_path, key_cert_path, primary_dbg_config_ini_path, primary_dbg_path, secondary_config_file_path):
+ #tool auth contains only gfh and signature, no extra content
+ self.m_gfh.finalize(0, key_ini_path)
+ #create tbs_sctrl_cert.bin
+ tbs_sctrl_cert_file_path = os.path.join(self.m_out_path, "tbs_sctrl_cert.bin")
+ tbs_sctrl_cert_file = open(tbs_sctrl_cert_file_path, "wb")
+ tbs_sctrl_cert_file.write(self.m_gfh.pack())
+ tbs_sctrl_cert_file.close()
+ print "===sctrl_cert sign==="
+ if self.m_gfh.get_sig_type() == "CERT_CHAIN":
+ self.m_sig_handler = cert.cert_chain_v5()
+ #create key cert
+ if key_cert_path == "":
+ key_cert_path = os.path.join(self.m_out_path, "key_cert.bin")
+ if os.path.isfile(key_ini_path):
+ key_cert_folder_name, key_cert_file_name = os.path.split(os.path.abspath(key_cert_path))
+ self.m_sig_handler.create_key_cert(key_ini_path, self.m_out_path, key_cert_file_name)
+ key_cert_path = os.path.join(self.m_out_path, key_cert_file_name)
+ else:
+ self.m_sig_handler.set_key_cert(key_cert_path)
+ #create primary debug cert
+ if primary_dbg_path == "":
+ primary_dbg_path = "primary_dbg_cert.bin"
+ if os.path.isfile(primary_dbg_config_ini_path):
+ primary_dbg_cert_folder_name, primary_dbg_cert_file_name = os.path.split(os.path.abspath(primary_dbg_path))
+ self.m_sig_handler.create_primary_dbg_cert(primary_dbg_config_ini_path, tbs_sctrl_cert_file_path, self.m_out_path, primary_dbg_cert_file_name)
+ primary_dbg_cert_path = os.path.join(self.m_out_path, primary_dbg_cert_file_name)
+ else:
+ self.m_sig_handler.set_primary_dbg_cert(primary_dbg_path)
+ #create secondary debug cert
+ secondary_dbg_cert_file_name = "secondary_dbg_cert.bin"
+ secondary_dbg_cert_file_path = os.path.join(self.m_out_path, secondary_dbg_cert_file_name)
+ self.m_sig_handler.create_secondary_dbg_cert(secondary_config_file_path, self.m_out_path, secondary_dbg_cert_file_name)
+ #create final cert chain
+ sig_name = "sctrl_cert.sig"
+ sig_file_path = os.path.join(self.m_out_path, sig_name)
+ self.m_sig_handler.output(self.m_out_path, sig_name)
+ #create final sctrl cert
+ if os.path.isfile(self.m_sctrl_cert_path):
+ os.remove(self.m_sctrl_cert_path)
+ concatb(self.m_sctrl_cert_path, tbs_sctrl_cert_file_path)
+ concatb(self.m_sctrl_cert_path, sig_file_path)
+ os.remove(secondary_dbg_cert_file_path)
+ elif self.m_gfh.get_sig_type() == "SINGLE":
+ self.m_sig_handler = cert.sig_single(self.m_gfh.get_pad_type())
+ self.m_sig_handler.set_out_path(self.m_out_path)
+ self.m_sig_handler.create(key_ini_path, tbs_sctrl_cert_file_path)
+ self.m_sig_handler.sign()
+ sig_name = "sctrl_cert.sig"
+ sig_file_path = os.path.join(self.m_out_path, sig_name)
+ self.m_sig_handler.output(self.m_out_path, sig_name)
+ #create final toolauth file
+ if os.path.isfile(self.m_sctrl_cert_path):
+ os.remove(self.m_sctrl_cert_path)
+ concatb(self.m_sctrl_cert_path, tbs_sctrl_cert_file_path)
+ concatb(self.m_sctrl_cert_path, sig_file_path)
+ else:
+ print "unknown signature type"
+
+ #clean up
+ os.remove(tbs_sctrl_cert_file_path)
+ os.remove(sig_file_path)
+ return
+
+def main():
+ #parameter parsing
+ idx = 1
+ key_ini_path = ""
+ key_cert_path = ""
+ gfh_config_ini_path = ""
+ primary_dbg_path = ""
+ primary_dbg_config_ini_path = ""
+ secondary_dbg_config_ini_path = ""
+ sctrl_cert_path = ""
+
+ while idx < len(sys.argv):
+ if sys.argv[idx][0] == '-':
+ if sys.argv[idx][1] == 'i':
+ print "key: " + sys.argv[idx + 1]
+ key_ini_path = sys.argv[idx + 1]
+ idx += 2
+ elif sys.argv[idx][1] == 'g':
+ print "gfh config: " + sys.argv[idx + 1]
+ gfh_config_ini_path = sys.argv[idx + 1]
+ idx += 2
+ elif sys.argv[idx][1] == 'p':
+ print "primary dbg cert: " + sys.argv[idx + 1]
+ primary_dbg_path = sys.argv[idx + 1]
+ idx += 2
+ elif sys.argv[idx][1] == 'q':
+ print "primary dbg cert config: " + sys.argv[idx + 1]
+ primary_dbg_config_ini_path = sys.argv[idx + 1]
+ idx += 2
+ elif sys.argv[idx][1] == 's':
+ print "secondary dbg cert config: " + sys.argv[idx + 1]
+ secondary_dbg_config_ini_path = sys.argv[idx + 1]
+ idx += 2
+ elif sys.argv[idx][1] == 'k':
+ print "key cert: " + sys.argv[idx + 1]
+ key_cert_path = sys.argv[idx + 1]
+ idx += 2
+ else:
+ print "unknown input"
+ idx += 2
+ else:
+ sctrl_cert_path = sys.argv[idx]
+ print "sctrl_cert_path: " + sctrl_cert_path
+ idx += 1
+
+ if not key_cert_path and not key_ini_path:
+ print "key path is not given!"
+ return -1
+ if not gfh_config_ini_path:
+ print "sctrl_cert_config_path is not given!"
+ return -1
+ if not sctrl_cert_path:
+ print "sctrl_cert is not given!"
+ return -1
+
+ out_path = os.path.dirname(os.path.abspath(sctrl_cert_path))
+
+ sctrl_cert_obj = sctrl_cert(out_path, sctrl_cert_path)
+ sctrl_cert_obj.create_gfh(gfh_config_ini_path)
+ sctrl_cert_obj.sign(key_ini_path, key_cert_path, primary_dbg_config_ini_path, primary_dbg_path, secondary_dbg_config_ini_path)
+
+ return 0
+
+if __name__ == '__main__':
+ main()
+
diff --git a/meta/meta-mediatek/recipes-bsp/bl33/files/pbp/sctrlcert/scc_gfh_config.ini b/meta/meta-mediatek/recipes-bsp/bl33/files/pbp/sctrlcert/scc_gfh_config.ini
new file mode 100644
index 0000000..3e002cb
--- /dev/null
+++ b/meta/meta-mediatek/recipes-bsp/bl33/files/pbp/sctrlcert/scc_gfh_config.ini
@@ -0,0 +1,14 @@
+[GFH_FILE_INFO]
+file_type = "4"
+start_addr = "0x00201000"
+flash_dev = "emmc"
+sig_type = "SINGLE"
+pad_type = "legacy"
+[GFH_SCTRL_CERT]
+version = "1"
+me_id = "9398c055df4d402b8be0ac030d609210"
+daa_dis = "1"
+sbc_dis = "1"
+jtag_enable = "1"
+secure_world_debug_enable = "1"
+
diff --git a/meta/meta-mediatek/recipes-bsp/bl33/files/pbp/sctrlcert/scc_key.ini b/meta/meta-mediatek/recipes-bsp/bl33/files/pbp/sctrlcert/scc_key.ini
new file mode 100644
index 0000000..2aac06f
--- /dev/null
+++ b/meta/meta-mediatek/recipes-bsp/bl33/files/pbp/sctrlcert/scc_key.ini
@@ -0,0 +1,3 @@
+[KEY]
+sw_ver = "1"
+rootkey = "keys/sctrlcert/root_prvk.pem"
\ No newline at end of file
diff --git a/meta/meta-mediatek/recipes-bsp/bl33/files/pbp/toolauth.py b/meta/meta-mediatek/recipes-bsp/bl33/files/pbp/toolauth.py
new file mode 100755
index 0000000..72188c2
--- /dev/null
+++ b/meta/meta-mediatek/recipes-bsp/bl33/files/pbp/toolauth.py
@@ -0,0 +1,110 @@
+import sys
+import os
+import struct
+script_folder, script_name = os.path.split(os.path.realpath(__file__))
+sys.path.append(os.path.join(script_folder, "lib"))
+import gfh
+import cert
+
+def get_file_sizeb(file_path):
+ if not os.path.isfile(file_path):
+ return 0
+ file_handle = open(file_path, "rb")
+ file_handle.seek(0, 2)
+ file_size = file_handle.tell()
+ file_handle.close()
+ return file_size
+
+def concatb(file1_path, file2_path):
+ file1_size = get_file_sizeb(file1_path)
+ file2_size = get_file_sizeb(file2_path)
+ file1 = open(file1_path, "ab+")
+ file2 = open(file2_path, "rb")
+ file1.write(file2.read(file2_size))
+ file2.close()
+ file1.close()
+
+class tool_auth:
+ def __init__(self, out_path, tool_auth_path):
+ self.m_out_path = out_path
+ if not os.path.exists(self.m_out_path):
+ os.makedirs(self.m_out_path)
+ self.m_tool_auth_path = tool_auth_path
+ self.m_gfh = gfh.image_gfh()
+ self.m_sig_handler = None
+ def create_gfh(self, gfh_config):
+ self.m_gfh.load_ini(gfh_config)
+ return
+ def sign(self, key_ini_path):
+ #tool auth contains only gfh and signature, no extra content
+ self.m_gfh.finalize(0, key_ini_path)
+ #write tbs_tool_auth
+ tbs_toolauth_file_path = os.path.join(self.m_out_path, "tbs_toolauth.bin")
+ tbs_tool_auth_file = open(tbs_toolauth_file_path, "wb")
+ tbs_tool_auth_file.write(self.m_gfh.pack())
+ tbs_tool_auth_file.close()
+ print "===tool_auth signing==="
+ if self.m_gfh.get_sig_type() == "SINGLE":
+ self.m_sig_handler = cert.sig_single(self.m_gfh.get_pad_type())
+ self.m_sig_handler.set_out_path(self.m_out_path)
+ self.m_sig_handler.create(key_ini_path, tbs_toolauth_file_path)
+ self.m_sig_handler.sign()
+ sig_name = "toolauth.sig"
+ sig_file_path = os.path.join(self.m_out_path, sig_name)
+ self.m_sig_handler.output(self.m_out_path, sig_name)
+ #create final toolauth file
+ if os.path.isfile(self.m_tool_auth_path):
+ os.remove(self.m_tool_auth_path)
+ concatb(self.m_tool_auth_path, tbs_toolauth_file_path)
+ concatb(self.m_tool_auth_path, sig_file_path)
+ else:
+ print "unknown signature type"
+ #clean up
+ os.remove(tbs_toolauth_file_path)
+ os.remove(sig_file_path)
+ return
+
+def main():
+ #parameter parsing
+ idx = 1
+ key_ini_path = ""
+ gfh_config_ini_path = ""
+ while idx < len(sys.argv):
+ if sys.argv[idx][0] == '-':
+ if sys.argv[idx][1] == 'i':
+ print "key: " + sys.argv[idx + 1]
+ key_ini_path = sys.argv[idx + 1]
+ idx += 2
+ elif sys.argv[idx][1] == 'g':
+ print "gfh: " + sys.argv[idx + 1]
+ gfh_config_ini_path = sys.argv[idx + 1]
+ idx += 2
+ else:
+ print "unknown input"
+ idx += 2
+ else:
+ tool_auth_path = sys.argv[idx]
+ print "tool_auth_path: " + tool_auth_path
+ idx += 1
+
+ if not key_ini_path:
+ print "key path is not given!"
+ return -1
+ if not gfh_config_ini_path:
+ print "gfh config path is not given!"
+ return -1
+ if not tool_auth_path:
+ print "tool_auth path is not given!"
+ return -1
+
+ out_path = os.path.dirname(os.path.abspath(tool_auth_path))
+
+ tool_auth_obj = tool_auth(out_path, tool_auth_path)
+ tool_auth_obj.create_gfh(gfh_config_ini_path)
+ tool_auth_obj.sign(key_ini_path)
+
+ return
+
+if __name__ == '__main__':
+ main()
+
diff --git a/meta/meta-mediatek/recipes-bsp/bl33/files/pbp/toolauth/bbchips.ini b/meta/meta-mediatek/recipes-bsp/bl33/files/pbp/toolauth/bbchips.ini
new file mode 100644
index 0000000..2a75c3d
--- /dev/null
+++ b/meta/meta-mediatek/recipes-bsp/bl33/files/pbp/toolauth/bbchips.ini
@@ -0,0 +1,11 @@
+[MT8521p]
+hw_code = 0x8521
+hw_sub_code = 0x0
+hw_ver = 0xca00
+sw_ver = 0x0
+load_region0_sigtype = epp
+load_region0_key = keys/resignda/epp_prvk.pem
+load_region1_sigtype = da
+load_region1_key = keys/resignda/da_prvk.pem
+load_region2_sigtype = da
+load_region2_key = keys/resignda/da_prvk.pem
diff --git a/meta/meta-mediatek/recipes-bsp/bl33/files/pbp/toolauth/toolauth_gfh_config.ini b/meta/meta-mediatek/recipes-bsp/bl33/files/pbp/toolauth/toolauth_gfh_config.ini
new file mode 100644
index 0000000..087063c
--- /dev/null
+++ b/meta/meta-mediatek/recipes-bsp/bl33/files/pbp/toolauth/toolauth_gfh_config.ini
@@ -0,0 +1,13 @@
+[GFH_FILE_INFO]
+file_type = "5"
+start_addr = "0x00201000"
+flash_dev = "emmc"
+sig_type = "SINGLE"
+pad_type = "legacy"
+[GFH_TOOL_AUTH]
+version = "1"
+da_path = "prebuilt/toolauth/MTK_AllInOne_DA.bin"
+bbchip = "MT8521p"
+bbchip_ini_path = "toolauth/bbchips.ini"
+sla_public_key = "keys/toolauth/sla_prvk.pem"
+daa_public_key = "keys/toolauth/da_prvk.pem"
diff --git a/meta/meta-mediatek/recipes-bsp/bl33/files/pbp/toolauth/toolauth_key.ini b/meta/meta-mediatek/recipes-bsp/bl33/files/pbp/toolauth/toolauth_key.ini
new file mode 100644
index 0000000..e760e20
--- /dev/null
+++ b/meta/meta-mediatek/recipes-bsp/bl33/files/pbp/toolauth/toolauth_key.ini
@@ -0,0 +1,3 @@
+[KEY]
+sw_ver = "1"
+rootkey = "keys/toolauth/root_prvk.pem"
\ No newline at end of file
diff --git a/meta/meta-mediatek/recipes-bsp/boost-service/boost-service/LICENSE b/meta/meta-mediatek/recipes-bsp/boost-service/boost-service/LICENSE
new file mode 100755
index 0000000..2270cd6
--- /dev/null
+++ b/meta/meta-mediatek/recipes-bsp/boost-service/boost-service/LICENSE
@@ -0,0 +1,31 @@
+Copyright Statement:
+
+This software/firmware and related documentation ("MediaTek Software") are
+protected under relevant copyright laws. The information contained herein is
+confidential and proprietary to MediaTek Inc. and/or its licensors. Without
+the prior written permission of MediaTek inc. and/or its licensors, any
+reproduction, modification, use or disclosure of MediaTek Software, and
+information contained herein, in whole or in part, shall be strictly
+prohibited.
+
+MediaTek Inc. (C) 2019. All rights reserved.
+
+BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
+ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL
+WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
+WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
+NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH
+RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
+INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES
+TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
+RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
+OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
+SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
+RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S
+ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE
+RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE
+MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
+CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
diff --git a/meta/meta-mediatek/recipes-bsp/boost-service/boost-service/boost_service_basic.service b/meta/meta-mediatek/recipes-bsp/boost-service/boost-service/boost_service_basic.service
new file mode 100644
index 0000000..e63e8b2
--- /dev/null
+++ b/meta/meta-mediatek/recipes-bsp/boost-service/boost-service/boost_service_basic.service
@@ -0,0 +1,10 @@
+[Unit]
+Description=BoostService_Basic Service
+Requires=sysinit.target
+
+[Service]
+Type=simple
+ExecStart=-/bin/sh /usr/share/boost-service/boostsc -p 1 -r 1
+
+[Install]
+WantedBy=sysinit.target
diff --git a/meta/meta-mediatek/recipes-bsp/boost-service/boost-service/boostsc b/meta/meta-mediatek/recipes-bsp/boost-service/boost-service/boostsc
new file mode 100755
index 0000000..03de5a0
--- /dev/null
+++ b/meta/meta-mediatek/recipes-bsp/boost-service/boost-service/boostsc
@@ -0,0 +1,41 @@
+#! /bin/bash
+
+readonly TEST_LOOP=100
+while getopts "h:p:b:r:" argv
+do
+ case $argv in
+ b)
+ BOOST=$OPTARG ;;
+ p)
+ PREFER_IDLE=$OPTARG ;;
+ r)
+ RCU_EXPEDITED=$OPTARG ;;
+ h)
+ echo Usage:
+ echo -b boost value
+ echo -p enable prefer idle
+ echo -r enable rcu expedited
+ ;;
+ *)
+ ;;
+ esac
+done
+
+if [ $BOOST ]; then
+ if [ -e "/sys/fs/cgroup/schedtune" ]; then
+ echo $BOOST > /sys/fs/cgroup/schedtune/schedtune.boost
+ fi
+fi
+
+if [ $PREFER_IDLE ]; then
+ if [ -e "/sys/fs/cgroup/schedtune" ]; then
+ echo $PREFER_IDLE > /sys/fs/cgroup/schedtune/schedtune.prefer_idle
+ fi
+fi
+
+if [ $RCU_EXPEDITED ]; then
+ if [ -e "/sys/kernel/rcu_expedited" ]; then
+ echo "common scheduler: To boost synchronize_rcu, set rcu_expedited as $RCU_EXPEDITED"
+ echo $RCU_EXPEDITED > /sys/kernel/rcu_expedited
+ fi
+fi
diff --git a/meta/meta-mediatek/recipes-bsp/boost-service/boost-service_1.0.0.bb b/meta/meta-mediatek/recipes-bsp/boost-service/boost-service_1.0.0.bb
new file mode 100755
index 0000000..75d4e12
--- /dev/null
+++ b/meta/meta-mediatek/recipes-bsp/boost-service/boost-service_1.0.0.bb
@@ -0,0 +1,23 @@
+DESCRIPTION = "Mediatek Boost Service"
+LICENSE = "MediaTekProprietary"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=35b74e6ee01be137c7e57a2cd6875f25"
+SRC_URI = "file://boost_service_basic.service \
+ file://boostsc \
+ file://LICENSE \
+"
+
+S = "${WORKDIR}"
+RDEPENDS_boost-service += "bash"
+inherit systemd
+
+SYSTEMD_PACKAGES = "${PN}"
+SYSTEMD_SERVICE_${PN} = "boost_service_basic.service"
+FILES_${PN} = "${systemd_unitdir} ${datadir}/boost-service"
+do_install_append() {
+ install -d ${D}${datadir}/boost-service
+ install -m 0755 ${S}/boostsc ${D}${datadir}/boost-service
+ if ${@bb.utils.contains('DISTRO_FEATURES','systemd','true','false',d)}; then
+ install -d ${D}${systemd_unitdir}/system/
+ install -m 0644 ${S}/boost_service_basic.service ${D}${systemd_unitdir}/system
+ fi
+}
diff --git a/meta/meta-mediatek/recipes-bsp/boot-assist/boot-assist/LICENSE b/meta/meta-mediatek/recipes-bsp/boot-assist/boot-assist/LICENSE
new file mode 100755
index 0000000..77f59ed
--- /dev/null
+++ b/meta/meta-mediatek/recipes-bsp/boot-assist/boot-assist/LICENSE
@@ -0,0 +1,31 @@
+Copyright Statement:
+
+This software/firmware and related documentation ("MediaTek Software") are
+protected under relevant copyright laws. The information contained herein is
+confidential and proprietary to MediaTek Inc. and/or its licensors. Without
+the prior written permission of MediaTek inc. and/or its licensors, any
+reproduction, modification, use or disclosure of MediaTek Software, and
+information contained herein, in whole or in part, shall be strictly
+prohibited.
+
+MediaTek Inc. (C) 2015. All rights reserved.
+
+BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
+ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL
+WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
+WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
+NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH
+RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
+INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES
+TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
+RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
+OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
+SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
+RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S
+ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE
+RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE
+MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
+CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
diff --git a/meta/meta-mediatek/recipes-bsp/boot-assist/boot-assist/boot_assist_basic.service b/meta/meta-mediatek/recipes-bsp/boot-assist/boot-assist/boot_assist_basic.service
new file mode 100644
index 0000000..9e016b0
--- /dev/null
+++ b/meta/meta-mediatek/recipes-bsp/boot-assist/boot-assist/boot_assist_basic.service
@@ -0,0 +1,10 @@
+[Unit]
+Description=BootAssist_Basic Service
+After=basic.target
+
+[Service]
+Type=simple
+ExecStart=-/bin/sh /usr/share/boot-assist/bootsc -t 60 -g schedutil -p Basic_target_done
+
+[Install]
+WantedBy=basic.target
diff --git a/meta/meta-mediatek/recipes-bsp/boot-assist/boot-assist/boot_assist_default.service b/meta/meta-mediatek/recipes-bsp/boot-assist/boot-assist/boot_assist_default.service
new file mode 100644
index 0000000..8fe5d33
--- /dev/null
+++ b/meta/meta-mediatek/recipes-bsp/boot-assist/boot-assist/boot_assist_default.service
@@ -0,0 +1,10 @@
+[Unit]
+Description=BootAssist_Default Service
+After=default.target
+
+[Service]
+Type=simple
+ExecStart=-/bin/sh /usr/share/boot-assist/bootsc -g schedutil -p Default_target_finish
+
+[Install]
+WantedBy=default.target
diff --git a/meta/meta-mediatek/recipes-bsp/boot-assist/boot-assist/bootsc b/meta/meta-mediatek/recipes-bsp/boot-assist/boot-assist/bootsc
new file mode 100755
index 0000000..e642058
--- /dev/null
+++ b/meta/meta-mediatek/recipes-bsp/boot-assist/boot-assist/bootsc
@@ -0,0 +1,95 @@
+#! /bin/bash
+
+readonly TEST_LOOP=100
+while getopts "hs:p:t:g:r:l:" argv
+do
+ case $argv in
+ t)
+ TIMEOUT=$OPTARG
+ echo TIMEOUT is $TIMEOUT ;;
+ g)
+ GOV=$OPTARG
+ echo GOV is $GOV ;;
+ p)
+ MARK=$OPTARG
+ echo MARK is $MARK ;;
+ s)
+ echo $OPTARG > /sys/kernel/debug/tracing/tracing_on ;;
+ r)
+ TARGET=$OPTARG ;;
+ l)
+ LIMITED=$OPTARG ;;
+ h)
+ echo Usage:
+ echo -t timeout, recover governor, need assign -g together
+ echo -p string, print string to bootprof
+ echo -g gov, change governor
+ echo -s echo control bit to tracing_on
+ echo -r reliability test, -r target, ex: -r Rndis_active -l 3800
+ echo -l reliability test, -l limited time [ms] ex: -r Rndis_active -l 3800
+ ;;
+ *)
+ ;;
+ esac
+done
+
+if [ $MARK ]; then
+ if [ -e "/proc/bootprof" ]; then
+ echo $MARK > /proc/bootprof
+ fi
+fi
+
+LITTLECORE=$(cat /sys/devices/system/cpu/online | cut -c1)
+BIGCORE=$(cat /sys/devices/system/cpu/online | cut -c3)
+if [ -z $TIMEOUT ] && [ $GOV ]; then
+ if grep -q "performance" /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor ; then
+ echo $GOV > /sys/devices/system/cpu/cpu$LITTLECORE/cpufreq/scaling_governor
+ echo $GOV > /sys/devices/system/cpu/cpu$BIGCORE/cpufreq/scaling_governor
+ fi
+ if [ -e "/tmp" ]; then
+ cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor > /tmp/gov.log
+ fi
+fi
+
+if [ $TIMEOUT ] && [ $GOV ]; then
+ sleep $TIMEOUT
+ if grep -q "performance" /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor ; then
+ echo $GOV > /sys/devices/system/cpu/cpu$LITTLECORE/cpufreq/scaling_governor
+ echo $GOV > /sys/devices/system/cpu/cpu$BIGCORE/cpufreq/scaling_governor
+ if [ -e "/proc/bootprof" ]; then
+ echo Recover_gov > /proc/bootprof
+ fi
+ fi
+fi
+
+if [ $TARGET ] && [ $LIMITED ]; then
+ if [ ! -f /bootinfo ]; then
+ mkdir -p /bootinfo
+ touch /bootinfo/history.txt
+ fi
+ COUNT=$(cat /bootinfo/history.txt | wc -l)
+ if [ $COUNT -lt $TEST_LOOP ]; then
+ VAL=$(grep $TARGET /proc/bootprof | grep -ho "[[:digit:]]\+\.[[:digit:]]\+")
+ printf -v INT %.0f "$VAL"
+ echo $TARGET is $VAL >> /bootinfo/history.txt
+ if [ $INT -gt $LIMITED ]; then
+ echo "Rndis long active"
+ # cat /sys/kernel/debug/tracing/trace > /tmp/bootinfo/trace.log
+ # echo 0 > /sys/kernel/debug/tracing/tracing_on
+ dmesg > /bootinfo/boot.log
+ journalctl > /bootinfo/journal.log
+ systemctl --failed > /bootinfo/fail.log
+ systemd-analyze plot > /bootinfo/analyze.svg
+ else
+ echo boot time test: $COUNT
+ let COUNT++
+ if [ $COUNT -lt $TEST_LOOP ]; then
+ echo "Reboot"
+ reboot
+ else
+ echo "boot time test pass"
+ echo "boot time test pass" >> /bootinfo/history.txt
+ fi
+ fi
+ fi
+fi
diff --git a/meta/meta-mediatek/recipes-bsp/boot-assist/boot-assist_1.0.0.bb b/meta/meta-mediatek/recipes-bsp/boot-assist/boot-assist_1.0.0.bb
new file mode 100755
index 0000000..43b5d85
--- /dev/null
+++ b/meta/meta-mediatek/recipes-bsp/boot-assist/boot-assist_1.0.0.bb
@@ -0,0 +1,25 @@
+DESCRIPTION = "MTK Boot Assist"
+LICENSE = "MediaTekProprietary"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=e1696b147d49d491bcb4da1a57173fff"
+SRC_URI = "file://boot_assist_basic.service \
+ file://boot_assist_default.service \
+ file://bootsc \
+ file://LICENSE \
+"
+
+S = "${WORKDIR}"
+RDEPENDS_boot-assist += "bash"
+inherit systemd
+
+SYSTEMD_PACKAGES = "${PN}"
+SYSTEMD_SERVICE_${PN} = "boot_assist_basic.service boot_assist_default.service"
+FILES_${PN} = "${systemd_unitdir} ${datadir}/boot-assist"
+do_install_append() {
+ install -d ${D}${datadir}/boot-assist
+ install -m 0755 ${S}/bootsc ${D}${datadir}/boot-assist
+ if ${@bb.utils.contains('DISTRO_FEATURES','systemd','true','false',d)}; then
+ install -d ${D}${systemd_unitdir}/system/
+ install -m 0644 ${S}/boot_assist_basic.service ${D}${systemd_unitdir}/system
+ install -m 0644 ${S}/boot_assist_default.service ${D}${systemd_unitdir}/system
+ fi
+}
diff --git a/meta/meta-mediatek/recipes-bsp/energy-aware/energy-aware.bb b/meta/meta-mediatek/recipes-bsp/energy-aware/energy-aware.bb
new file mode 100644
index 0000000..814477e
--- /dev/null
+++ b/meta/meta-mediatek/recipes-bsp/energy-aware/energy-aware.bb
@@ -0,0 +1,41 @@
+DESCRIPTION = "Energy Aware assist"
+LICENSE = "MediaTekProprietary"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=e1696b147d49d491bcb4da1a57173fff"
+
+S = "${WORKDIR}"
+SRC_URI = "file://energy-aware-control.service \
+ file://ea-init \
+ file://LICENSE \
+"
+
+inherit systemd
+RDEPENDS_energy-aware += "bash"
+FILES_${PN} += " \
+ ${systemd_unitdir}/system/energy-aware-control.service \
+ "
+
+SYSTEMD_SERVICE_${PN} = "energy-aware-control.service"
+
+do_install_append() {
+ if ${@bb.utils.contains('DISTRO_FEATURES','systemd','true','false',d)}; then
+ install -d ${D}${systemd_unitdir}/system ${D}${datadir}/energy-aware
+ install -m 0755 ${S}/ea-init ${D}${datadir}/energy-aware
+ install -m 644 ${WORKDIR}/energy-aware-control.service ${D}${systemd_unitdir}/system/energy-aware-control.service
+ fi
+}
+
+
+# Install Sysvinit Scripts #
+DEPENDS_append = " update-rc.d-native"
+SRC_URI += "file://energy-aware-control-service"
+INITSCRIPT_NAME_energy-aware-control-service = "energy-aware-control-service"
+INITSCRIPT_PARAMS_energy-aware-control-service = "defaults"
+FILES_${PN} += "${sysconfdir}/init.d/energy-aware-control-service"
+
+do_install_append() {
+ if ${@bb.utils.contains('DISTRO_FEATURES','sysvinit','true','false',d)}; then
+ install -d ${D}${sysconfdir}/init.d
+ install -m 0755 ${TOPDIR}/../meta/meta-mediatek/recipes-bsp/energy-aware/energy-aware/energy-aware-control-service ${D}${sysconfdir}/init.d/energy-aware-control-service
+ update-rc.d -r ${D} ${INITSCRIPT_NAME_energy-aware-control-service} ${INITSCRIPT_PARAMS_energy-aware-control-service}
+ fi
+}
diff --git a/meta/meta-mediatek/recipes-bsp/energy-aware/energy-aware/LICENSE b/meta/meta-mediatek/recipes-bsp/energy-aware/energy-aware/LICENSE
new file mode 100644
index 0000000..77f59ed
--- /dev/null
+++ b/meta/meta-mediatek/recipes-bsp/energy-aware/energy-aware/LICENSE
@@ -0,0 +1,31 @@
+Copyright Statement:
+
+This software/firmware and related documentation ("MediaTek Software") are
+protected under relevant copyright laws. The information contained herein is
+confidential and proprietary to MediaTek Inc. and/or its licensors. Without
+the prior written permission of MediaTek inc. and/or its licensors, any
+reproduction, modification, use or disclosure of MediaTek Software, and
+information contained herein, in whole or in part, shall be strictly
+prohibited.
+
+MediaTek Inc. (C) 2015. All rights reserved.
+
+BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
+ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL
+WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
+WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
+NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH
+RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
+INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES
+TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
+RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
+OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
+SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
+RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S
+ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE
+RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE
+MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
+CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
diff --git a/meta/meta-mediatek/recipes-bsp/energy-aware/energy-aware/ea-init b/meta/meta-mediatek/recipes-bsp/energy-aware/energy-aware/ea-init
new file mode 100644
index 0000000..30380a5
--- /dev/null
+++ b/meta/meta-mediatek/recipes-bsp/energy-aware/energy-aware/ea-init
@@ -0,0 +1,33 @@
+#! /bin/bash
+if [ -e "/sys/kernel/rcu_expedited" ]; then
+ echo "common scheduler: To boost synchronize_rcu, set rcu_expedited as 1"
+ echo 1 > /sys/kernel/rcu_expedited
+fi
+
+if [ -e "/proc/sys/kernel/sched_is_big_little" ]; then
+ echo "energy-aware: set sched_is_big_little"
+ echo 1 > /proc/sys/kernel/sched_is_big_little
+fi
+
+if [ -e "/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor" ]; then
+ nr_cpu=$(cat /proc/cpuinfo | grep processor | wc -l)
+ nr_cpu=$(($nr_cpu-1))
+
+ sg=$(cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_available_governors | grep -oh "\w*schedplus\w*")
+
+ if [-z "$sg"]; then
+ echo "energy-aware: set schedutil as dvfs policy"
+
+ for i in `seq $nr_cpu`;
+ do
+ echo schedutil > /sys/devices/system/cpu/cpu${i}/cpufreq/scaling_governor
+ done
+ else
+ echo "energy-aware: set schedplus as dvfs policy"
+
+ for i in `seq $nr_cpu`;
+ do
+ echo schedplus > /sys/devices/system/cpu/cpu${i}/cpufreq/scaling_governor
+ done
+ fi
+fi
\ No newline at end of file
diff --git a/meta/meta-mediatek/recipes-bsp/energy-aware/energy-aware/energy-aware-control-service b/meta/meta-mediatek/recipes-bsp/energy-aware/energy-aware/energy-aware-control-service
new file mode 100644
index 0000000..c98a6e6
--- /dev/null
+++ b/meta/meta-mediatek/recipes-bsp/energy-aware/energy-aware/energy-aware-control-service
@@ -0,0 +1,62 @@
+#!/bin/sh
+### BEGIN INIT INFO
+# Provides: energy-aware-control
+# Required-Start:
+# Required-Stop:
+# Short-Description: Energy Aware Control Service
+### END INIT INFO
+
+. /etc/init.d/init-functions
+prog=energy-aware-control
+PIDFILE=/var/run/$prog.pid
+DESC="Energy Aware Control Service"
+start() {
+ log_daemon_msg "Starting $DESC" "$prog"
+ start_daemon_background -p $PIDFILE /bin/sh /usr/share/energy-aware/ea-init
+ if [ $? -ne 0 ]; then
+ log_end_msg 1
+ exit 1
+ fi
+ if [ $? -eq 0 ]; then
+ log_end_msg 0
+ fi
+ exit 0
+}
+
+stop() {
+ log_daemon_msg "Stopping $DESC" "$prog"
+ killproc -p $PIDFILE /bin/sh
+ if [ $? -ne 0 ]; then
+ log_end_msg 1
+ exit 1
+ fi
+ if [ $? -eq 0 ]; then
+ log_end_msg 0
+ fi
+}
+
+force_reload() {
+ stop
+ start
+
+}
+
+case "$1" in
+ start)
+ start
+ ;;
+ stop)
+ stop
+ ;;
+ force-reload)
+ force_reload
+ ;;
+ restart)
+ stop
+ start
+ ;;
+
+ *)
+ echo "$Usage: $prog {start|stop|force-reload|restart}"
+ exit 2
+esac
diff --git a/meta/meta-mediatek/recipes-bsp/energy-aware/energy-aware/energy-aware-control.service b/meta/meta-mediatek/recipes-bsp/energy-aware/energy-aware/energy-aware-control.service
new file mode 100644
index 0000000..4a60814
--- /dev/null
+++ b/meta/meta-mediatek/recipes-bsp/energy-aware/energy-aware/energy-aware-control.service
@@ -0,0 +1,14 @@
+# This file is used to enable sched_is_big_little sysctl
+# from user space
+[Unit]
+Description=Energy Aware Control Service
+DefaultDependencies=no
+Before=sysinit.target
+
+[Service]
+Type=oneshot
+ExecStart=-/bin/sh /usr/share/energy-aware/ea-init
+TimeoutSec=10
+
+[Install]
+WantedBy=sysinit.target
diff --git a/meta/meta-mediatek/recipes-bsp/lk/files/dev_info/dtb-transfer-array.py b/meta/meta-mediatek/recipes-bsp/lk/files/dev_info/dtb-transfer-array.py
new file mode 100644
index 0000000..c6b3583
--- /dev/null
+++ b/meta/meta-mediatek/recipes-bsp/lk/files/dev_info/dtb-transfer-array.py
@@ -0,0 +1,41 @@
+import os
+import sys
+
+def read_dtb(filename, raw_data):
+ fin = open(filename, 'rb')
+ fin.seek(0, 0)
+ while True:
+ t_byte = fin.read(1)
+ if len(t_byte) == 0:
+ break
+ else :
+ raw_data.append("0x%.2X" % ord(t_byte))
+
+def write_blob_head_file(filename, raw_data, length):
+ fout = open(filename, 'w+')
+ fout.write('#define CHECK_RSA 1 \n')
+ fout.write('#define CHECK_HASH 1 \n')
+ fout.write('const unsigned char blob[] __attribute__((aligned(4))) = \n')
+ fout.write('{\n ')
+
+ i = 0
+ for data in raw_data:
+ i += 1
+ if i != length:
+ fout.write(data + ', ')
+ else:
+ fout.write(data)
+ if i % 16 == 0:
+ fout.write('\n ')
+ if i == length:
+ break;
+ fout.write('\n};')
+ fout.close()
+
+if __name__ == "__main__":
+ raw_data = []
+ in_path = str(sys.argv[1]);
+ out_path = str(sys.argv[2]);
+ length = int(sys.argv[3],16);
+ read_dtb(in_path, raw_data)
+ write_blob_head_file(out_path, raw_data, length)
diff --git a/meta/meta-mediatek/recipes-bsp/lk/files/dummy_img/fitImage b/meta/meta-mediatek/recipes-bsp/lk/files/dummy_img/fitImage
new file mode 100644
index 0000000..036ed1b
--- /dev/null
+++ b/meta/meta-mediatek/recipes-bsp/lk/files/dummy_img/fitImage
Binary files differ
diff --git a/meta/meta-mediatek/recipes-bsp/lk/files/fit-lk/extract_region b/meta/meta-mediatek/recipes-bsp/lk/files/fit-lk/extract_region
new file mode 100755
index 0000000..261ba30
--- /dev/null
+++ b/meta/meta-mediatek/recipes-bsp/lk/files/fit-lk/extract_region
Binary files differ
diff --git a/meta/meta-mediatek/recipes-bsp/lk/files/key/lk_key.ini b/meta/meta-mediatek/recipes-bsp/lk/files/key/lk_key.ini
new file mode 100755
index 0000000..d6d089a
--- /dev/null
+++ b/meta/meta-mediatek/recipes-bsp/lk/files/key/lk_key.ini
@@ -0,0 +1,4 @@
+[KEY]
+sw_ver = "1"
+rootkey = "root_prvk.pem"
+ac_key = "0x112233445566778899aabbccddeeff"
diff --git a/meta/meta-mediatek/recipes-bsp/lk/files/key/root_prvk.pem b/meta/meta-mediatek/recipes-bsp/lk/files/key/root_prvk.pem
new file mode 100644
index 0000000..fd987a3
--- /dev/null
+++ b/meta/meta-mediatek/recipes-bsp/lk/files/key/root_prvk.pem
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEowIBAAKCAQEA0mlxI+3vrVlX8wH23CeTPDIH3c4DhEQNIGQltziYX7DOAHyf
+t/5s9TXAOmqIY0cyrQsjw837aiN3QGXONeQorP4+G5wlzWESJeJyAGlZ11hSijVp
+QQFwCT+++k4L8SEoMIgJUMNVd9pESqCYf08nhJXc/qgn++YiG8tMvHz9IA/Ef4OK
+XNj/+1+XyrtYRgYpfOwsoCgbe01NEpV3vM61fW0g3EtCQXW7MOD5VIWMkvTt+ob4
+qTF5/HpRlIJ5nth/8ZktkCx51Lu6yhQ1fw3KKPZ7A3ZmBtxSJ8I1xe1v/yWN+eD9
+Z9l7ZTkFVe8Avej6NnudkH1f6uTNmEETXOXHWwIDAQABAoIBAAdKjhgfo6GPKgQK
+umIwoOKCHVGrVOXdcdMAhWoO9QDD4K+Vofc/QslQfoPHs0g1bGUgsLGVTrQD3JsH
+rBij+mDcQoy0YX73cSiM60RmYi2bKukNJsOQ6C/53IVR9Qn7Cyh7Xk9FJY4Mqzcm
+z4IB3S2z/793VkNdWys5ZURW1HKq6R7s5Z937wlinPdJhwi7kI148NFnHFO793+z
+MGRC4n45CP13dHG3jktc46UYksP3sQ4CFcjFhKS6BPKDsyjmbCx1HUYjjcaLTy2d
+CJhYDlEvvkjU6CmQfe+cFpKYXnW5zZTwwx1uUDFiWOgSZupaieWZtyPCX7hqQ4ea
+Q6u7RxkCgYEA6+WjIwTB+D3PKP1x82RY2BMpWQRxHuVJs7T0H4zA+IicfJYc/+Sh
+0Esqzfj9ak/sEuNR1fIj4XCKODEVL3/n+qjBz8lbsNDjUrjG8jv3TiGkeaOeOyFR
+8jv0cvedzFk+1lQElFwSHrWAOfeoZRMHOoxK1MNkELjo2wFa67o6rxcCgYEA5FfR
+PJRyu2OmCVwqzycMbSOz6gB/5O5bnI9DxZf0oMNE1n5ElsZWynEFE5L33E+bvB/8
+AdC4cPPL1pg46KiDDkJ/BQhw+mC4wwvBHwjZFlKdQMYtgGb9ErFL4WPnllXy+ETD
+8U9Az1zOvj6thy3RYA7JGyZus4t9ecM5M+xItF0CgYBm+u7G4NLUzhbbrBjMyifG
+3EaWp8vCUxJjs0FHbKjpVqoJ8XZjd6n0Rnw/Qs1OVemXLUmSfoyPZBPTCApZnBrn
+YDiLvzmZ7PbwK94d7XO+1gz5VSZEZf1iJC5I6jQm+2blJfSB19fJNC7wH1+SEEZ9
+lrUsQMg0TKTKxsKsWbY4rQKBgEjP//aTV6qNcgqWC0iXKQ08T0iU9DNqFmhr/q5p
+cCY7Xh4PkYuKn25ab8X4HXVxJTXt9QwXJFlQRHWfgLYf1fqcFajjMjOE2CXJ/8EH
+r0HBAkf/ac8CCD0HsCylENoNejbUpq6yGPaGn55mmir630MEM/imXrJ+DnrfV8RI
+2j45AoGBAN/fhfcjGu5ix88+T9sEmV1lfoHyETQIZD4r5c9NufMXPcztE33XTqjI
+DpBfOCVQ8ZNuHuScQdQC55K8XT7wR9sQRhNvRua1K0IsfcL73ghCJin9i0yxMEzp
+s00NbHgvb2kfhxCC8eyoiCmpRk9A9xg2V22hx7Hkcwv+A62e9tN4
+-----END RSA PRIVATE KEY-----
diff --git a/meta/meta-mediatek/recipes-bsp/lk/files/lk_dts/lk.dts b/meta/meta-mediatek/recipes-bsp/lk/files/lk_dts/lk.dts
new file mode 100644
index 0000000..7b1b06f
--- /dev/null
+++ b/meta/meta-mediatek/recipes-bsp/lk/files/lk_dts/lk.dts
@@ -0,0 +1,12 @@
+/dts-v1/;
+/ {
+ model = "Keys";
+ compatible = "mediatek,auto2701evb2-ivi";
+ signature {
+ key-dev {
+ required = "conf";
+ algo = "sha256,rsa2048";
+ key-name-hint = "dev";
+ };
+ };
+};
diff --git a/meta/meta-mediatek/recipes-bsp/lk/files/lk_dts/tmp_blob.txt b/meta/meta-mediatek/recipes-bsp/lk/files/lk_dts/tmp_blob.txt
new file mode 100644
index 0000000..23a0ee1
--- /dev/null
+++ b/meta/meta-mediatek/recipes-bsp/lk/files/lk_dts/tmp_blob.txt
@@ -0,0 +1,7 @@
+#define CHECK_RSA 0
+#define CHECK_HASH 0
+
+const unsigned char blob[] __attribute__((aligned(4))) =
+{
+0
+};
\ No newline at end of file
diff --git a/meta/meta-mediatek/recipes-bsp/lk/files/pbp/hsm.py b/meta/meta-mediatek/recipes-bsp/lk/files/pbp/hsm.py
new file mode 100755
index 0000000..afad840
--- /dev/null
+++ b/meta/meta-mediatek/recipes-bsp/lk/files/pbp/hsm.py
@@ -0,0 +1,89 @@
+"""
+This module is used to delegate signature generation to HSM(Hardware Security Module)
+If public key is given for signing instead of private key, we'll know that
+we're trying to delegate signature to HSM. Then we look up key table created
+here to find HSM parameters. Here public key is used only as id for HSM
+parameters and won't act as a public key.
+"""
+import filecmp
+import os
+import lib.cert
+
+class HsmParam(object):
+ """
+ Parameter for HSM
+ """
+ def __init__(self):
+ # you can add parameter required by your HSM here
+ self.m_prvk = None
+
+def create_key_table():
+ """
+ create key table for public key to private key mapping
+ """
+ prvk_list = []
+ pubk_list = []
+ key_database_path = os.path.join(os.path.dirname(__file__), 'hsm_test_keys')
+ keys = os.listdir(key_database_path)
+ key_table = {}
+
+ for key in keys:
+ key_path = os.path.join(key_database_path, key)
+ if lib.cert.is_prvk(key_path):
+ prvk_list.append(key_path)
+ elif lib.cert.is_pubk(key_path):
+ pubk_list.append(key_path)
+
+ for pubk in pubk_list:
+ for prvk in prvk_list:
+ tmp_pubk = os.path.join(os.path.dirname(__file__), 'tmp_pubk.pem')
+ lib.cert.prvk_to_pubk(prvk, tmp_pubk)
+ if filecmp.cmp(pubk, tmp_pubk, False) is True:
+ key_table[pubk] = os.path.join(key_database_path, prvk)
+ os.remove(tmp_pubk)
+ break
+ os.remove(tmp_pubk)
+
+ return key_table
+
+def query_key_table(key_table, key):
+ """
+ get private key from public key.
+ In your implementation, you should convert input public
+ key to parameter passed to HSM, so HSM knows how to sign
+ message. Here as an example, we search public keys in a folder
+ as public key data base, and use corresponding private key
+ to sign message.
+ """
+ for pubk in key_table.keys():
+ if filecmp.cmp(key, pubk, False) is True:
+ return key_table[pubk]
+
+ return None
+
+
+def hsm_rsa_sign(data, key, padding, sig):
+ """
+ sign data with HSM
+ """
+ # note that key is pubk actually, use it as index for
+ # HSM parameters such as key selection
+ hsm_param_obj = HsmParam()
+ key_table = create_key_table()
+ hsm_param_obj.m_prvk = query_key_table(key_table, key)
+ if hsm_param_obj.m_prvk is None:
+ print 'not valid HSM parameter'
+ return -1
+
+ print "========================"
+ print "HSM parameter:"
+ print " m_prvk = " + hsm_param_obj.m_prvk
+ print "========================"
+
+ # place hsm request here -- start
+ # we re-direct it to signing with private key to mimic HSM
+ # data is not hashed here, you can hash data here to reduce
+ # network usage
+ lib.cert.sig_gen(data, hsm_param_obj.m_prvk, padding, sig)
+ # place hsm request here -- end
+ return 0
diff --git a/meta/meta-mediatek/recipes-bsp/lk/files/pbp/keys/sctrlcert/root_prvk.pem b/meta/meta-mediatek/recipes-bsp/lk/files/pbp/keys/sctrlcert/root_prvk.pem
new file mode 100644
index 0000000..715ecca
--- /dev/null
+++ b/meta/meta-mediatek/recipes-bsp/lk/files/pbp/keys/sctrlcert/root_prvk.pem
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEowIBAAKCAQEA0WQDRmxTDvm7U8HoqWphpOMy4X3A9Vu0bSB6wwW66TVOqsLL
+MHezN0DSdQNrgi2yaCAN4X2j23JmsnaGuJcLhXNwUPCE+NV2kE50zWxTsx8LsM1g
+aGv2fGDaDsIPVj7qcVzr2/dtHFwQ6YKrKVXYM95VPJza/X6iOIwCgjz+fdmsg/oq
+jrBoWr2rVqkt8aeAXorAvRDA89yxdwqea7w0GMX4Ski3yyMWssj2SXLzkbEWpYyT
+lanOnnQ1aaNnCG13cdOf7I67uj3StRl4Wnap9YnTbWN6+IRUP9ZbrHW+gjwMUKoW
+1YGHuXIjYlxUxmtaXk266re+iaTjQKLiQbCbLwIDAQABAoIBAAmXZTcCm0NiWRxb
+E4c/Ij3lUl1V31Ld4oPlKvpn9snb8UCNL7WGpiTvyTQm9fO+mB+A6GHd2XWh5eZi
+24T1FkgEo65xdgXX8Vhm357RSXw4/dYZckMWPvIvlY17gixXMXID6aHn0Y2tAfFQ
+VPrNvduSYaEnJjjaZh/k+fBxTs8A5lQcxDWvsf11on00sXrUAOlHS6hQ2vziZnmc
+r/MqBY/3Hkwtqsr4unCenKTch1hKf/6KqaChYO0GnDlwt9rjmH3tcb0LyCQ1aYe9
+dDY9RmgscZE8PtvbKpEfcB8jruP43ZgYC1oTj9WtdHQ2gtLS0bs9knhnECSPMW3Y
+ORF46oECgYEA8qz+H+tuqxCKAA1p6EXmegpEcqhkwapviqgMZMQAejfW//bf8LYd
+9CsyTtWER1uxJ+PjvhW/K0NYXn+tbWzrsW1UK/AaYwvaB9+JsjU07aZh9kmADZJi
+3KkPsKp4Unqlno59XkLm3XE9REoHursnIkiuzHZnqh/+50ck+GJGQQ8CgYEA3OMr
+xNfLkuTs5NyBDBCYSOf0s2wfLgpfu4eaUYuYMGoAAL4trvrLtW5tcW63ObMy51V5
+EJJAH3vk/EK9EgevMYGwbiVB7pkb11tcnLoxelorTAbpDCzSorbW71mruX11496w
+GBJw4yQcIUxET5GxU14qTEK4wLQQ7AZQIKVtw+ECgYEAv/YJuzQfwZ9+mhYCPaL1
+cnomtM/xi6SHQRY3X4oPmp4LK0Sc1ispPJji3atWTKACXbyNzTIkm1NVVsMGa7Wq
+JxqFZ5AxP0IDwRCZOmeOK6LegNSZP6MZItV0vNnL/epYkjjCgMrJFkfaH+ezf4lF
+pn/6DXBoBhHzL/1+CCCs1A8CgYBPk1+fSIbEYsidInszF39lNHtJcDhDY+VdL9r+
+aaXoOyfJHLpkgWGF+URgSxyjItXB1V8KA0YqkX3LC1gF+NK6qRggdjesd2g6S2Wv
+6LwOchGLECpBApzXlbsU+18MMhCYiQ8zfOFCUy33KPyrFbemaxQd6SOZ+MTn4tZX
+DIHgwQKBgFLvSmrc8eLKRDDDxdvZYiu8JMm/DS4TdbK3P2u67hhxd3Y4whdQboF5
+zHbkkTBIuKoFbbQj3bB91KmCIcxNkT66Xe3qmoAfDrUMp7cxBLcnpoDpJIXTlKnG
+bHThVsqvJvuwQByr2oUGUJd8eerqzUCAgx/mi+/9aTe+ztB/KmBF
+-----END RSA PRIVATE KEY-----
diff --git a/meta/meta-mediatek/recipes-bsp/lk/files/pbp/keys/toolauth/da_prvk.pem b/meta/meta-mediatek/recipes-bsp/lk/files/pbp/keys/toolauth/da_prvk.pem
new file mode 100644
index 0000000..715ecca
--- /dev/null
+++ b/meta/meta-mediatek/recipes-bsp/lk/files/pbp/keys/toolauth/da_prvk.pem
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEowIBAAKCAQEA0WQDRmxTDvm7U8HoqWphpOMy4X3A9Vu0bSB6wwW66TVOqsLL
+MHezN0DSdQNrgi2yaCAN4X2j23JmsnaGuJcLhXNwUPCE+NV2kE50zWxTsx8LsM1g
+aGv2fGDaDsIPVj7qcVzr2/dtHFwQ6YKrKVXYM95VPJza/X6iOIwCgjz+fdmsg/oq
+jrBoWr2rVqkt8aeAXorAvRDA89yxdwqea7w0GMX4Ski3yyMWssj2SXLzkbEWpYyT
+lanOnnQ1aaNnCG13cdOf7I67uj3StRl4Wnap9YnTbWN6+IRUP9ZbrHW+gjwMUKoW
+1YGHuXIjYlxUxmtaXk266re+iaTjQKLiQbCbLwIDAQABAoIBAAmXZTcCm0NiWRxb
+E4c/Ij3lUl1V31Ld4oPlKvpn9snb8UCNL7WGpiTvyTQm9fO+mB+A6GHd2XWh5eZi
+24T1FkgEo65xdgXX8Vhm357RSXw4/dYZckMWPvIvlY17gixXMXID6aHn0Y2tAfFQ
+VPrNvduSYaEnJjjaZh/k+fBxTs8A5lQcxDWvsf11on00sXrUAOlHS6hQ2vziZnmc
+r/MqBY/3Hkwtqsr4unCenKTch1hKf/6KqaChYO0GnDlwt9rjmH3tcb0LyCQ1aYe9
+dDY9RmgscZE8PtvbKpEfcB8jruP43ZgYC1oTj9WtdHQ2gtLS0bs9knhnECSPMW3Y
+ORF46oECgYEA8qz+H+tuqxCKAA1p6EXmegpEcqhkwapviqgMZMQAejfW//bf8LYd
+9CsyTtWER1uxJ+PjvhW/K0NYXn+tbWzrsW1UK/AaYwvaB9+JsjU07aZh9kmADZJi
+3KkPsKp4Unqlno59XkLm3XE9REoHursnIkiuzHZnqh/+50ck+GJGQQ8CgYEA3OMr
+xNfLkuTs5NyBDBCYSOf0s2wfLgpfu4eaUYuYMGoAAL4trvrLtW5tcW63ObMy51V5
+EJJAH3vk/EK9EgevMYGwbiVB7pkb11tcnLoxelorTAbpDCzSorbW71mruX11496w
+GBJw4yQcIUxET5GxU14qTEK4wLQQ7AZQIKVtw+ECgYEAv/YJuzQfwZ9+mhYCPaL1
+cnomtM/xi6SHQRY3X4oPmp4LK0Sc1ispPJji3atWTKACXbyNzTIkm1NVVsMGa7Wq
+JxqFZ5AxP0IDwRCZOmeOK6LegNSZP6MZItV0vNnL/epYkjjCgMrJFkfaH+ezf4lF
+pn/6DXBoBhHzL/1+CCCs1A8CgYBPk1+fSIbEYsidInszF39lNHtJcDhDY+VdL9r+
+aaXoOyfJHLpkgWGF+URgSxyjItXB1V8KA0YqkX3LC1gF+NK6qRggdjesd2g6S2Wv
+6LwOchGLECpBApzXlbsU+18MMhCYiQ8zfOFCUy33KPyrFbemaxQd6SOZ+MTn4tZX
+DIHgwQKBgFLvSmrc8eLKRDDDxdvZYiu8JMm/DS4TdbK3P2u67hhxd3Y4whdQboF5
+zHbkkTBIuKoFbbQj3bB91KmCIcxNkT66Xe3qmoAfDrUMp7cxBLcnpoDpJIXTlKnG
+bHThVsqvJvuwQByr2oUGUJd8eerqzUCAgx/mi+/9aTe+ztB/KmBF
+-----END RSA PRIVATE KEY-----
diff --git a/meta/meta-mediatek/recipes-bsp/lk/files/pbp/keys/toolauth/root_prvk.pem b/meta/meta-mediatek/recipes-bsp/lk/files/pbp/keys/toolauth/root_prvk.pem
new file mode 100644
index 0000000..715ecca
--- /dev/null
+++ b/meta/meta-mediatek/recipes-bsp/lk/files/pbp/keys/toolauth/root_prvk.pem
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEowIBAAKCAQEA0WQDRmxTDvm7U8HoqWphpOMy4X3A9Vu0bSB6wwW66TVOqsLL
+MHezN0DSdQNrgi2yaCAN4X2j23JmsnaGuJcLhXNwUPCE+NV2kE50zWxTsx8LsM1g
+aGv2fGDaDsIPVj7qcVzr2/dtHFwQ6YKrKVXYM95VPJza/X6iOIwCgjz+fdmsg/oq
+jrBoWr2rVqkt8aeAXorAvRDA89yxdwqea7w0GMX4Ski3yyMWssj2SXLzkbEWpYyT
+lanOnnQ1aaNnCG13cdOf7I67uj3StRl4Wnap9YnTbWN6+IRUP9ZbrHW+gjwMUKoW
+1YGHuXIjYlxUxmtaXk266re+iaTjQKLiQbCbLwIDAQABAoIBAAmXZTcCm0NiWRxb
+E4c/Ij3lUl1V31Ld4oPlKvpn9snb8UCNL7WGpiTvyTQm9fO+mB+A6GHd2XWh5eZi
+24T1FkgEo65xdgXX8Vhm357RSXw4/dYZckMWPvIvlY17gixXMXID6aHn0Y2tAfFQ
+VPrNvduSYaEnJjjaZh/k+fBxTs8A5lQcxDWvsf11on00sXrUAOlHS6hQ2vziZnmc
+r/MqBY/3Hkwtqsr4unCenKTch1hKf/6KqaChYO0GnDlwt9rjmH3tcb0LyCQ1aYe9
+dDY9RmgscZE8PtvbKpEfcB8jruP43ZgYC1oTj9WtdHQ2gtLS0bs9knhnECSPMW3Y
+ORF46oECgYEA8qz+H+tuqxCKAA1p6EXmegpEcqhkwapviqgMZMQAejfW//bf8LYd
+9CsyTtWER1uxJ+PjvhW/K0NYXn+tbWzrsW1UK/AaYwvaB9+JsjU07aZh9kmADZJi
+3KkPsKp4Unqlno59XkLm3XE9REoHursnIkiuzHZnqh/+50ck+GJGQQ8CgYEA3OMr
+xNfLkuTs5NyBDBCYSOf0s2wfLgpfu4eaUYuYMGoAAL4trvrLtW5tcW63ObMy51V5
+EJJAH3vk/EK9EgevMYGwbiVB7pkb11tcnLoxelorTAbpDCzSorbW71mruX11496w
+GBJw4yQcIUxET5GxU14qTEK4wLQQ7AZQIKVtw+ECgYEAv/YJuzQfwZ9+mhYCPaL1
+cnomtM/xi6SHQRY3X4oPmp4LK0Sc1ispPJji3atWTKACXbyNzTIkm1NVVsMGa7Wq
+JxqFZ5AxP0IDwRCZOmeOK6LegNSZP6MZItV0vNnL/epYkjjCgMrJFkfaH+ezf4lF
+pn/6DXBoBhHzL/1+CCCs1A8CgYBPk1+fSIbEYsidInszF39lNHtJcDhDY+VdL9r+
+aaXoOyfJHLpkgWGF+URgSxyjItXB1V8KA0YqkX3LC1gF+NK6qRggdjesd2g6S2Wv
+6LwOchGLECpBApzXlbsU+18MMhCYiQ8zfOFCUy33KPyrFbemaxQd6SOZ+MTn4tZX
+DIHgwQKBgFLvSmrc8eLKRDDDxdvZYiu8JMm/DS4TdbK3P2u67hhxd3Y4whdQboF5
+zHbkkTBIuKoFbbQj3bB91KmCIcxNkT66Xe3qmoAfDrUMp7cxBLcnpoDpJIXTlKnG
+bHThVsqvJvuwQByr2oUGUJd8eerqzUCAgx/mi+/9aTe+ztB/KmBF
+-----END RSA PRIVATE KEY-----
diff --git a/meta/meta-mediatek/recipes-bsp/lk/files/pbp/keys/toolauth/sla_prvk.pem b/meta/meta-mediatek/recipes-bsp/lk/files/pbp/keys/toolauth/sla_prvk.pem
new file mode 100644
index 0000000..715ecca
--- /dev/null
+++ b/meta/meta-mediatek/recipes-bsp/lk/files/pbp/keys/toolauth/sla_prvk.pem
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEowIBAAKCAQEA0WQDRmxTDvm7U8HoqWphpOMy4X3A9Vu0bSB6wwW66TVOqsLL
+MHezN0DSdQNrgi2yaCAN4X2j23JmsnaGuJcLhXNwUPCE+NV2kE50zWxTsx8LsM1g
+aGv2fGDaDsIPVj7qcVzr2/dtHFwQ6YKrKVXYM95VPJza/X6iOIwCgjz+fdmsg/oq
+jrBoWr2rVqkt8aeAXorAvRDA89yxdwqea7w0GMX4Ski3yyMWssj2SXLzkbEWpYyT
+lanOnnQ1aaNnCG13cdOf7I67uj3StRl4Wnap9YnTbWN6+IRUP9ZbrHW+gjwMUKoW
+1YGHuXIjYlxUxmtaXk266re+iaTjQKLiQbCbLwIDAQABAoIBAAmXZTcCm0NiWRxb
+E4c/Ij3lUl1V31Ld4oPlKvpn9snb8UCNL7WGpiTvyTQm9fO+mB+A6GHd2XWh5eZi
+24T1FkgEo65xdgXX8Vhm357RSXw4/dYZckMWPvIvlY17gixXMXID6aHn0Y2tAfFQ
+VPrNvduSYaEnJjjaZh/k+fBxTs8A5lQcxDWvsf11on00sXrUAOlHS6hQ2vziZnmc
+r/MqBY/3Hkwtqsr4unCenKTch1hKf/6KqaChYO0GnDlwt9rjmH3tcb0LyCQ1aYe9
+dDY9RmgscZE8PtvbKpEfcB8jruP43ZgYC1oTj9WtdHQ2gtLS0bs9knhnECSPMW3Y
+ORF46oECgYEA8qz+H+tuqxCKAA1p6EXmegpEcqhkwapviqgMZMQAejfW//bf8LYd
+9CsyTtWER1uxJ+PjvhW/K0NYXn+tbWzrsW1UK/AaYwvaB9+JsjU07aZh9kmADZJi
+3KkPsKp4Unqlno59XkLm3XE9REoHursnIkiuzHZnqh/+50ck+GJGQQ8CgYEA3OMr
+xNfLkuTs5NyBDBCYSOf0s2wfLgpfu4eaUYuYMGoAAL4trvrLtW5tcW63ObMy51V5
+EJJAH3vk/EK9EgevMYGwbiVB7pkb11tcnLoxelorTAbpDCzSorbW71mruX11496w
+GBJw4yQcIUxET5GxU14qTEK4wLQQ7AZQIKVtw+ECgYEAv/YJuzQfwZ9+mhYCPaL1
+cnomtM/xi6SHQRY3X4oPmp4LK0Sc1ispPJji3atWTKACXbyNzTIkm1NVVsMGa7Wq
+JxqFZ5AxP0IDwRCZOmeOK6LegNSZP6MZItV0vNnL/epYkjjCgMrJFkfaH+ezf4lF
+pn/6DXBoBhHzL/1+CCCs1A8CgYBPk1+fSIbEYsidInszF39lNHtJcDhDY+VdL9r+
+aaXoOyfJHLpkgWGF+URgSxyjItXB1V8KA0YqkX3LC1gF+NK6qRggdjesd2g6S2Wv
+6LwOchGLECpBApzXlbsU+18MMhCYiQ8zfOFCUy33KPyrFbemaxQd6SOZ+MTn4tZX
+DIHgwQKBgFLvSmrc8eLKRDDDxdvZYiu8JMm/DS4TdbK3P2u67hhxd3Y4whdQboF5
+zHbkkTBIuKoFbbQj3bB91KmCIcxNkT66Xe3qmoAfDrUMp7cxBLcnpoDpJIXTlKnG
+bHThVsqvJvuwQByr2oUGUJd8eerqzUCAgx/mi+/9aTe+ztB/KmBF
+-----END RSA PRIVATE KEY-----
diff --git a/meta/meta-mediatek/recipes-bsp/lk/files/pbp/lib/__init__.pyc b/meta/meta-mediatek/recipes-bsp/lk/files/pbp/lib/__init__.pyc
new file mode 100644
index 0000000..efe7800
--- /dev/null
+++ b/meta/meta-mediatek/recipes-bsp/lk/files/pbp/lib/__init__.pyc
Binary files differ
diff --git a/meta/meta-mediatek/recipes-bsp/lk/files/pbp/lib/asn1_gen.pyc b/meta/meta-mediatek/recipes-bsp/lk/files/pbp/lib/asn1_gen.pyc
new file mode 100755
index 0000000..9a44921
--- /dev/null
+++ b/meta/meta-mediatek/recipes-bsp/lk/files/pbp/lib/asn1_gen.pyc
Binary files differ
diff --git a/meta/meta-mediatek/recipes-bsp/lk/files/pbp/lib/cert.pyc b/meta/meta-mediatek/recipes-bsp/lk/files/pbp/lib/cert.pyc
new file mode 100644
index 0000000..d7941ef
--- /dev/null
+++ b/meta/meta-mediatek/recipes-bsp/lk/files/pbp/lib/cert.pyc
Binary files differ
diff --git a/meta/meta-mediatek/recipes-bsp/lk/files/pbp/lib/dainfo.pyc b/meta/meta-mediatek/recipes-bsp/lk/files/pbp/lib/dainfo.pyc
new file mode 100644
index 0000000..292f62e
--- /dev/null
+++ b/meta/meta-mediatek/recipes-bsp/lk/files/pbp/lib/dainfo.pyc
Binary files differ
diff --git a/meta/meta-mediatek/recipes-bsp/lk/files/pbp/lib/gfh.pyc b/meta/meta-mediatek/recipes-bsp/lk/files/pbp/lib/gfh.pyc
new file mode 100644
index 0000000..a653ad6
--- /dev/null
+++ b/meta/meta-mediatek/recipes-bsp/lk/files/pbp/lib/gfh.pyc
Binary files differ
diff --git a/meta/meta-mediatek/recipes-bsp/lk/files/pbp/lib/hsm_hook.pyc b/meta/meta-mediatek/recipes-bsp/lk/files/pbp/lib/hsm_hook.pyc
new file mode 100644
index 0000000..93a084f
--- /dev/null
+++ b/meta/meta-mediatek/recipes-bsp/lk/files/pbp/lib/hsm_hook.pyc
Binary files differ
diff --git a/meta/meta-mediatek/recipes-bsp/lk/files/pbp/pbp.py b/meta/meta-mediatek/recipes-bsp/lk/files/pbp/pbp.py
new file mode 100755
index 0000000..6ca7326
--- /dev/null
+++ b/meta/meta-mediatek/recipes-bsp/lk/files/pbp/pbp.py
@@ -0,0 +1,367 @@
+"""
+pbp is a tool that signs/re-signs bootloader and generate data for root public key authentication.
+"""
+import os
+import shutil
+import argparse
+from lib import gfh
+from lib import cert
+
+
+def get_file_sizeb(file_path):
+ """
+ Get size of binary file
+ """
+ if not os.path.isfile(file_path):
+ return 0
+ file_handle = open(file_path, "rb")
+ file_handle.seek(0, 2)
+ file_size = file_handle.tell()
+ file_handle.close()
+ return file_size
+
+
+def concatb(file1_path, file2_path):
+ """
+ Concatenate binary files
+ """
+ file2_size = get_file_sizeb(file2_path)
+ file1 = open(file1_path, "ab+")
+ file2 = open(file2_path, "rb")
+ file1.write(file2.read(file2_size))
+ file2.close()
+ file1.close()
+
+
+class Bl(object):
+ """
+ Bl, which stands for preloader in Mediatek solution.
+ Mediatek preloader is loaded/verified by BootROM and its format is determined by BootROM
+ and is different from other images due to several reasons.
+ It has basic format as follows:
+ =======================
+ GFH
+ =======================
+ Preloader_NO_GFH.bin
+ =======================
+ Sig
+ =======================
+ Where Preloader_NO_GFH.bin is converted from preloader.elf.
+ """
+ def __init__(self, out_path, in_bootloader_file_path, out_bootloader_file_path):
+ self.m_gfh = gfh.ImageGFH()
+ self.m_out_path = out_path
+ if not os.path.exists(self.m_out_path):
+ os.makedirs(self.m_out_path)
+ self.m_in_bl_file_path = in_bootloader_file_path
+ self.m_out_bl_file_path = out_bootloader_file_path
+ self.m_bl_is_signed = False
+ self.m_bl_content_offset = 0
+ # initialize content size to bl file size
+ self.m_bl_content_length = get_file_sizeb(self.m_in_bl_file_path)
+ self.m_bl_sig_size = 0
+ # generate file path for bl without gfh and signature
+ bl_path = os.path.splitext(in_bootloader_file_path)
+ self.m_bl_no_gfh_file_path = bl_path[0] + "_plain.bin"
+ self.m_sig_ver = 0
+ self.m_sw_ver = 0
+ self.m_root_prvk_path = ""
+ self.m_img_prvk_path = ""
+ self.m_ac_key = 0
+ self.m_sig_handler = None
+
+ def is_signed(self):
+ """
+ GFH and signature are added after bootloader image has been processed by pbp.
+ We use this fact to determine whether bootloader image is signed.
+ """
+ if self.m_in_bl_file_path:
+ bl_file = open(self.m_in_bl_file_path, "rb")
+ gfh_hdr_obj = gfh.GFHHeader()
+ gfh_hdr_size = gfh_hdr_obj.get_size()
+ gfh_hdr_buf = bl_file.read(gfh_hdr_size)
+ self.m_bl_is_signed = gfh_hdr_obj.is_gfh(gfh_hdr_buf)
+ bl_file.close()
+ return self.m_bl_is_signed
+
+ def parse(self):
+ """
+ If image is signed, we remove GFH and signature. Removed GFH is parsed and
+ stored. Stored GFH will be used later if GFH ini file is not given.
+ """
+ print "===parse bootloader==="
+ # image will be decomposed if it's signed
+ if self.is_signed():
+ gfh_total_size = self.m_gfh.parse(self.m_in_bl_file_path)
+ self.m_bl_content_offset = gfh_total_size
+ self.m_bl_content_length -= gfh_total_size
+ self.m_bl_content_length -= self.m_gfh.get_sig_size()
+ self.m_bl_sig_size = self.m_gfh.get_sig_size()
+ in_file = open(self.m_in_bl_file_path, "rb")
+ out_file = open(self.m_bl_no_gfh_file_path, "wb")
+ in_file.seek(self.m_bl_content_offset)
+ out_file.write(in_file.read(self.m_bl_content_length))
+ out_file.close()
+ in_file.close()
+ else:
+ shutil.copyfile(self.m_in_bl_file_path, self.m_bl_no_gfh_file_path)
+ print "bootloader content size = " + hex(self.m_bl_content_length)
+
+ def create_gfh(self, gfh_config):
+ """
+ GFH creation. GFH may be created from parsed/stored GFH config or from GFH config file
+ provided by user.
+ """
+ self.parse()
+ if gfh_config:
+ if self.is_signed():
+ del self.m_gfh.gfhs[:]
+ self.m_gfh.load_ini(gfh_config)
+ elif not self.is_signed():
+ print "GFH_CONFIG.ini does not exist!!"
+ return -1
+ # self.m_gfh.dump()
+ return 0
+
+ def sign(self, key_ini_path, key_cert_path, content_config_file_path):
+ """
+ Sign bootloader according to its signature type, which is stored in GFH.
+ """
+ self.m_gfh.finalize(self.m_bl_content_length, key_ini_path)
+ # create tbs_bootloader.bin
+ tbs_bl_file_path = os.path.join(self.m_out_path, "tbs_preloader.bin")
+ tbs_bl_file = open(tbs_bl_file_path, "wb")
+ tbs_bl_file.write(self.m_gfh.pack())
+ bl_no_gfh_file = open(self.m_bl_no_gfh_file_path, "rb")
+ tbs_bl_file.write(bl_no_gfh_file.read(self.m_bl_content_length))
+ bl_no_gfh_file.close()
+ tbs_bl_file.close()
+ print "===sign==="
+ if self.m_gfh.get_sig_type() == "CERT_CHAIN":
+ self.m_sig_handler = cert.CertChainV2()
+ # create key cert if key cert does not exist
+ if key_cert_path == "":
+ key_cert_path = os.path.join(self.m_out_path, "key_cert.bin")
+ if not os.path.isfile(key_cert_path):
+ key_cert_file_name = os.path.basename(os.path.abspath(key_cert_path))
+ self.m_sig_handler.create_key_cert(key_ini_path,
+ self.m_out_path,
+ key_cert_file_name)
+ key_cert_path = os.path.join(self.m_out_path, key_cert_file_name)
+ else:
+ self.m_sig_handler.set_key_cert(key_cert_path)
+ # create content cert
+ content_cert_name = "content_cert.bin"
+ self.m_sig_handler.create_content_cert(content_config_file_path,
+ tbs_bl_file_path,
+ self.m_out_path,
+ content_cert_name)
+ # create final cert chain
+ sig_name = "preloader.sig"
+ sig_file_path = os.path.join(self.m_out_path, sig_name)
+ self.m_sig_handler.output(self.m_out_path, sig_name)
+ # output final cert chain size
+ sig_size_name = "sig_size.txt"
+ sig_size_file_path = os.path.join(self.m_out_path, sig_size_name)
+ sig_size_file = open(sig_size_file_path, 'w')
+ sig_size_file.write(hex(get_file_sizeb(sig_file_path)))
+ sig_size_file.close()
+ # create final preloader image
+ if os.path.isfile(self.m_out_bl_file_path):
+ os.remove(self.m_out_bl_file_path)
+ concatb(self.m_out_bl_file_path, tbs_bl_file_path)
+ concatb(self.m_out_bl_file_path, sig_file_path)
+ # clean up
+ os.remove(os.path.join(self.m_out_path, content_cert_name))
+ elif self.m_gfh.get_sig_type() == "SINGLE_AND_PHASH":
+ self.m_sig_handler = cert.SigSingleAndPhash(self.m_gfh.get_pad_type())
+ self.m_sig_handler.set_out_path(self.m_out_path)
+ self.m_sig_handler.create(key_ini_path, tbs_bl_file_path)
+ # signature generation
+ self.m_sig_handler.sign()
+ sig_name = "preloader.sig"
+ sig_file_path = os.path.join(self.m_out_path, sig_name)
+ self.m_sig_handler.output(self.m_out_path, sig_name)
+ # output signature size
+ sig_size_name = "sig_size.txt"
+ sig_size_file_path = os.path.join(self.m_out_path, sig_size_name)
+ sig_size_file = open(sig_size_file_path, 'w')
+ sig_size_file.write(hex(get_file_sizeb(sig_file_path)))
+ sig_size_file.close()
+ # create final preloader image
+ if os.path.isfile(self.m_out_bl_file_path):
+ os.remove(self.m_out_bl_file_path)
+ concatb(self.m_out_bl_file_path, tbs_bl_file_path)
+ concatb(self.m_out_bl_file_path, sig_file_path)
+ else:
+ print "unknown signature type"
+ # clean up
+ os.remove(self.m_bl_no_gfh_file_path)
+ os.remove(tbs_bl_file_path)
+ os.remove(sig_file_path)
+ return
+
+class PbpArgs(object):
+ """
+ PbpArgs is used to pass parameter to pbp.
+ This structure is both used when user executes this python script directly or imports
+ this module and use exported method.
+ """
+ def __init__(self):
+ self.op = None
+ self.padding = None
+ self.key_ini_path = None
+ self.key_path = None
+ self.gfh_cfg_ini_path = None
+ self.cnt_cfg_ini_path = None
+ self.key_cert_path = None
+ self.input_bl_path = None
+ self.tmp_output_path = None
+ self.output_path = None
+ def reset(self):
+ self.__init__()
+ def dump(self):
+ """
+ dump parameters.
+ """
+ f = lambda arg: 'Not Set' if arg is None else arg
+ print "op = " + f(self.op)
+ print "padding = " + f(self.padding)
+ print "key_ini_path = " + f(self.key_ini_path)
+ print "key_path = " + f(self.key_path)
+ print "gfh_cfg_ini_path = " + f(self.gfh_cfg_ini_path)
+ print "cnt_cfg_ini_path = " + f(self.cnt_cfg_ini_path)
+ print "key_cert_path = " + f(self.key_cert_path)
+ print "input_bl_path = " + f(self.input_bl_path)
+ print "tmp_output_path = " + f(self.tmp_output_path)
+ print "output_path = " + f(self.output_path)
+
+def _op_sign(args):
+ """
+ Sign/re-sign operation
+ """
+ bl_obj = Bl(args.tmp_output_path, args.input_bl_path, args.output_path)
+ bl_obj.create_gfh(args.gfh_cfg_ini_path)
+ bl_obj.sign(args.key_ini_path, args.key_cert_path, args.cnt_cfg_ini_path)
+ return 0
+
+def _op_keybin(args):
+ """
+ Generate root key data structure for root public key authentication.
+ """
+ key = cert.CtKey(args.padding)
+ key.create(args.key_path)
+ key_bin = key.pack()
+ out_file = open(args.output_path, "wb")
+ out_file.write(key_bin)
+ out_file.close()
+ return 0
+
+def _op_keybin_pss(args):
+ """
+ Root key data structures are different for different padding. Here we handles pss padding.
+ """
+ args.padding = 'pss'
+ return _op_keybin(args)
+
+def _op_keybin_legacy(args):
+ """
+ Root key data structures are different for different padding. Here we handles legacy padding.
+ """
+ args.padding = 'legacy'
+ return _op_keybin(args)
+
+def _op_keyhash(args):
+ """
+ Generate hash of root key data structure, which is dependent on padding used.
+ """
+ key = cert.CtKey(args.padding)
+ key.create(args.key_path)
+ key_bin = key.pack()
+ tmp_key_bin_path = os.path.join(args.tmp_output_path, "tmp_keybin.bin")
+ out_file = open(tmp_key_bin_path, "wb")
+ out_file.write(key_bin)
+ out_file.close()
+ cert.hash_gen(tmp_key_bin_path, args.output_path)
+ os.remove(tmp_key_bin_path)
+ return 0
+
+def _op_keyhash_pss(args):
+ """
+ Root key data struture hash for pss padding.
+ """
+ args.padding = 'pss'
+ return _op_keyhash(args)
+
+def _op_keyhash_legacy(args):
+ """
+ Root key data struture hash for legacy padding.
+ """
+ args.padding = 'legacy'
+ return _op_keyhash(args)
+
+def pbp_op(args):
+ """
+ Handles and dispatches all operations supported by pbp.
+ """
+ supported_ops = {
+ 'sign': _op_sign,
+ 'keybin_pss': _op_keybin_pss,
+ 'keybin_legacy': _op_keybin_legacy,
+ 'keyhash_pss': _op_keyhash_pss,
+ 'keyhash_legacy': _op_keyhash_legacy
+ }
+
+ if args.output_path is None:
+ print "output path is not given!"
+ return -1
+
+ if args.op is None:
+ print "op is not given!"
+ return -1
+
+ if args.op == 'sign':
+ if not args.input_bl_path:
+ print "bootloader path is not given!"
+ return -1
+ if (args.key_ini_path is None) and (args.key_cert_path is None):
+ print "key path is not given!"
+ return -1
+ else:
+ if (args.key_ini_path is None) and (args.key_path is None):
+ print "key path is not given!"
+ return -1
+
+ args.tmp_output_path = os.path.dirname(os.path.abspath(args.output_path))
+ if not os.path.exists(args.tmp_output_path):
+ os.makedirs(args.tmp_output_path)
+
+ op_f = supported_ops.get(args.op)
+ return op_f(args)
+
+
+def main():
+ """
+ Main function for pbp, which is used when pbp.py is executed directly.
+ Note that we changed input bootloader parameter to -in_bl $BL_PATH.
+ Please remember to add -in_bl if you're migrating from previous version.
+ """
+ parser = argparse.ArgumentParser(description='pbp tool for preloader gfh \
+creation/replacement and signing/re-signing')
+ parser.add_argument('-i', dest='key_ini_path', help='key configuartion path')
+ parser.add_argument('-j', dest='key_path', help='key path (with pem format)')
+ parser.add_argument('-g', dest='gfh_cfg_ini_path', help='gfh(generaic file header) \
+configuration path')
+ parser.add_argument('-c', dest='cnt_cfg_ini_path', help='content certificate \
+configuration path')
+ parser.add_argument('-k', dest='key_cert_path', help='key certificate path')
+ parser.add_argument('-func', dest='op', help='operation to be performed', required=True)
+ parser.add_argument('-o', dest='output_path', help='output file path')
+ parser.add_argument('input_bl_path', nargs='?', help='input file path')
+
+ pbp_args = parser.parse_args()
+ return pbp_op(pbp_args)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/meta/meta-mediatek/recipes-bsp/lk/files/pbp/prebuilt/toolauth/MTK_AllInOne_DA.bin b/meta/meta-mediatek/recipes-bsp/lk/files/pbp/prebuilt/toolauth/MTK_AllInOne_DA.bin
new file mode 100644
index 0000000..3f5aea7
--- /dev/null
+++ b/meta/meta-mediatek/recipes-bsp/lk/files/pbp/prebuilt/toolauth/MTK_AllInOne_DA.bin
Binary files differ
diff --git a/meta/meta-mediatek/recipes-bsp/lk/files/pbp/sctrlcert.py b/meta/meta-mediatek/recipes-bsp/lk/files/pbp/sctrlcert.py
new file mode 100755
index 0000000..e8cfff4
--- /dev/null
+++ b/meta/meta-mediatek/recipes-bsp/lk/files/pbp/sctrlcert.py
@@ -0,0 +1,202 @@
+"""
+This module is for debug control certificate generation
+"""
+import os
+import sys
+from lib import gfh
+from lib import cert
+
+
+def get_file_sizeb(file_path):
+ """
+ get binary file size
+ """
+ if not os.path.isfile(file_path):
+ return 0
+ file_handle = open(file_path, "rb")
+ file_handle.seek(0, 2)
+ file_size = file_handle.tell()
+ file_handle.close()
+ return file_size
+
+
+def concatb(file1_path, file2_path):
+ """
+ concatenate two binary files
+ """
+ file2_size = get_file_sizeb(file2_path)
+ file1 = open(file1_path, "ab+")
+ file2 = open(file2_path, "rb")
+ file1.write(file2.read(file2_size))
+ file2.close()
+ file1.close()
+
+
+class SctrlCert(object):
+ """
+ class for debug control certificate
+ """
+ def __init__(self, out_path, sctrl_cert_path):
+ self.m_out_path = out_path
+ if not os.path.exists(self.m_out_path):
+ os.makedirs(self.m_out_path)
+ self.m_sctrl_cert_path = sctrl_cert_path
+ self.m_gfh = gfh.ImageGFH()
+ self.m_key_path = ""
+ self.m_out_path = out_path
+ self.m_sig_handler = None
+
+ def create_gfh(self, gfh_config):
+ """
+ create GFH(generic file header) for debug control certificate
+ """
+ self.m_gfh.load_ini(gfh_config)
+ self.m_gfh.dump()
+ return
+
+ def sign(self, key_ini_path, key_cert_path, primary_dbg_config_ini_path, primary_dbg_path,
+ secondary_config_file_path):
+ """
+ generate signature for debug control certificate
+ """
+ # tool auth contains only gfh and signature, no extra content
+ self.m_gfh.finalize(0, key_ini_path)
+ # create tbs_sctrl_cert.bin
+ tbs_sctrl_cert_file_path = os.path.join(self.m_out_path, "tbs_sctrl_cert.bin")
+ tbs_sctrl_cert_file = open(tbs_sctrl_cert_file_path, "wb")
+ tbs_sctrl_cert_file.write(self.m_gfh.pack())
+ tbs_sctrl_cert_file.close()
+ print "===sctrl_cert sign==="
+ if self.m_gfh.get_sig_type() == "CERT_CHAIN":
+ self.m_sig_handler = cert.CertChainV5()
+ # create key cert
+ if key_cert_path == "":
+ key_cert_path = os.path.join(self.m_out_path, "key_cert.bin")
+ if os.path.isfile(key_ini_path):
+ key_cert_file_name = os.path.basename(os.path.abspath(key_cert_path))
+ self.m_sig_handler.create_key_cert(key_ini_path,
+ self.m_out_path,
+ key_cert_file_name)
+ key_cert_path = os.path.join(self.m_out_path, key_cert_file_name)
+ else:
+ self.m_sig_handler.set_key_cert(key_cert_path)
+ # create primary debug cert
+ if primary_dbg_path == "":
+ primary_dbg_path = "primary_dbg_cert.bin"
+ if os.path.isfile(primary_dbg_config_ini_path):
+ primary_dbg_cert_file_name = os.path.basename(os.path.abspath(primary_dbg_path))
+ self.m_sig_handler.create_primary_dbg_cert(primary_dbg_config_ini_path,
+ tbs_sctrl_cert_file_path,
+ self.m_out_path,
+ primary_dbg_cert_file_name)
+ else:
+ self.m_sig_handler.set_primary_dbg_cert(primary_dbg_path)
+ # create secondary debug cert
+ secondary_dbg_cert_file_name = "secondary_dbg_cert.bin"
+ secondary_dbg_cert_file_path = os.path.join(self.m_out_path,
+ secondary_dbg_cert_file_name)
+ self.m_sig_handler.create_secondary_dbg_cert(secondary_config_file_path,
+ self.m_out_path,
+ secondary_dbg_cert_file_name)
+ # create final cert chain
+ sig_name = "sctrl_cert.sig"
+ sig_file_path = os.path.join(self.m_out_path, sig_name)
+ self.m_sig_handler.output(self.m_out_path, sig_name)
+ # create final sctrl cert
+ if os.path.isfile(self.m_sctrl_cert_path):
+ os.remove(self.m_sctrl_cert_path)
+ concatb(self.m_sctrl_cert_path, tbs_sctrl_cert_file_path)
+ concatb(self.m_sctrl_cert_path, sig_file_path)
+ os.remove(secondary_dbg_cert_file_path)
+ elif self.m_gfh.get_sig_type() == "SINGLE":
+ self.m_sig_handler = cert.SigSingle(self.m_gfh.get_pad_type())
+ self.m_sig_handler.set_out_path(self.m_out_path)
+ self.m_sig_handler.create(key_ini_path, tbs_sctrl_cert_file_path)
+ self.m_sig_handler.sign()
+ sig_name = "sctrl_cert.sig"
+ sig_file_path = os.path.join(self.m_out_path, sig_name)
+ self.m_sig_handler.output(self.m_out_path, sig_name)
+ # create final toolauth file
+ if os.path.isfile(self.m_sctrl_cert_path):
+ os.remove(self.m_sctrl_cert_path)
+ concatb(self.m_sctrl_cert_path, tbs_sctrl_cert_file_path)
+ concatb(self.m_sctrl_cert_path, sig_file_path)
+ else:
+ print "unknown signature type"
+
+ # clean up
+ os.remove(tbs_sctrl_cert_file_path)
+ os.remove(sig_file_path)
+ return
+
+
+def main():
+ """
+ entry point if this module is executed from cmdline.
+ """
+ # parameter parsing
+ idx = 1
+ key_ini_path = ""
+ key_cert_path = ""
+ gfh_config_ini_path = ""
+ primary_dbg_path = ""
+ primary_dbg_config_ini_path = ""
+ secondary_dbg_config_ini_path = ""
+ sctrl_cert_path = ""
+
+ while idx < len(sys.argv):
+ if sys.argv[idx][0] == '-':
+ if sys.argv[idx][1] == 'i':
+ print "key: " + sys.argv[idx + 1]
+ key_ini_path = sys.argv[idx + 1]
+ idx += 2
+ elif sys.argv[idx][1] == 'g':
+ print "gfh config: " + sys.argv[idx + 1]
+ gfh_config_ini_path = sys.argv[idx + 1]
+ idx += 2
+ elif sys.argv[idx][1] == 'p':
+ print "primary dbg cert: " + sys.argv[idx + 1]
+ primary_dbg_path = sys.argv[idx + 1]
+ idx += 2
+ elif sys.argv[idx][1] == 'q':
+ print "primary dbg cert config: " + sys.argv[idx + 1]
+ primary_dbg_config_ini_path = sys.argv[idx + 1]
+ idx += 2
+ elif sys.argv[idx][1] == 's':
+ print "secondary dbg cert config: " + sys.argv[idx + 1]
+ secondary_dbg_config_ini_path = sys.argv[idx + 1]
+ idx += 2
+ elif sys.argv[idx][1] == 'k':
+ print "key cert: " + sys.argv[idx + 1]
+ key_cert_path = sys.argv[idx + 1]
+ idx += 2
+ else:
+ print "unknown input"
+ idx += 2
+ else:
+ sctrl_cert_path = sys.argv[idx]
+ print "sctrl_cert_path: " + sctrl_cert_path
+ idx += 1
+
+ if not key_cert_path and not key_ini_path:
+ print "key path is not given!"
+ return -1
+ if not gfh_config_ini_path:
+ print "sctrl_cert_config_path is not given!"
+ return -1
+ if not sctrl_cert_path:
+ print "sctrl_cert is not given!"
+ return -1
+
+ out_path = os.path.dirname(os.path.abspath(sctrl_cert_path))
+
+ sctrl_cert_obj = SctrlCert(out_path, sctrl_cert_path)
+ sctrl_cert_obj.create_gfh(gfh_config_ini_path)
+ sctrl_cert_obj.sign(key_ini_path, key_cert_path, primary_dbg_config_ini_path, primary_dbg_path,
+ secondary_dbg_config_ini_path)
+
+ return 0
+
+
+if __name__ == '__main__':
+ main()
diff --git a/meta/meta-mediatek/recipes-bsp/lk/files/pbp/sctrlcert/scc_gfh_config.ini b/meta/meta-mediatek/recipes-bsp/lk/files/pbp/sctrlcert/scc_gfh_config.ini
new file mode 100644
index 0000000..394d1bd
--- /dev/null
+++ b/meta/meta-mediatek/recipes-bsp/lk/files/pbp/sctrlcert/scc_gfh_config.ini
@@ -0,0 +1,43 @@
+[CHIP]
+version = "mt8167"
+[GFH_FILE_INFO]
+version = "1"
+file_type = "4"
+start_addr = "0x00201000"
+flash_dev = "emmc"
+sig_type = "SINGLE"
+pad_type = "pss"
+max_size = "0x00040000"
+sig_ver = "1"
+attr = "0"
+[GFH_SCTRL_CERT]
+version = "1"
+cust_name = "MTK"
+me_id = "9398c055df4d402b8be0ac030d609210"
+sla_dis = "1"
+daa_dis = "1"
+sbc_dis = "1"
+jtag_enable = "1"
+secure_world_debug_enable = "1"
+
+[CHIP]
+version = "mt8518"
+[GFH_FILE_INFO]
+version = "1"
+file_type = "4"
+start_addr = "0x00201000"
+flash_dev = "nand"
+sig_type = "SINGLE"
+pad_type = "pss"
+max_size = "0x00040000"
+sig_ver = "1"
+attr = "0"
+[GFH_SCTRL_CERT]
+version = "1"
+cust_name = "MTK"
+me_id = "9398c055df4d402b8be0ac030d609210"
+sla_dis = "1"
+daa_dis = "1"
+sbc_dis = "1"
+jtag_enable = "1"
+secure_world_debug_enable = "1"
diff --git a/meta/meta-mediatek/recipes-bsp/lk/files/pbp/sctrlcert/scc_key.ini b/meta/meta-mediatek/recipes-bsp/lk/files/pbp/sctrlcert/scc_key.ini
new file mode 100644
index 0000000..2aac06f
--- /dev/null
+++ b/meta/meta-mediatek/recipes-bsp/lk/files/pbp/sctrlcert/scc_key.ini
@@ -0,0 +1,3 @@
+[KEY]
+sw_ver = "1"
+rootkey = "keys/sctrlcert/root_prvk.pem"
\ No newline at end of file
diff --git a/meta/meta-mediatek/recipes-bsp/lk/files/pbp/toolauth.py b/meta/meta-mediatek/recipes-bsp/lk/files/pbp/toolauth.py
new file mode 100755
index 0000000..5319605
--- /dev/null
+++ b/meta/meta-mediatek/recipes-bsp/lk/files/pbp/toolauth.py
@@ -0,0 +1,135 @@
+"""
+This module generates tool auth, which combines public certificate and other functions
+such as DA binding.
+"""
+import os
+import sys
+from lib import gfh
+from lib import cert
+
+
+def get_file_sizeb(file_path):
+ """
+ get binary file size
+ """
+ if not os.path.isfile(file_path):
+ return 0
+ file_handle = open(file_path, "rb")
+ file_handle.seek(0, 2)
+ file_size = file_handle.tell()
+ file_handle.close()
+ return file_size
+
+
+def concatb(file1_path, file2_path):
+ """
+ concatenate two binary files
+ """
+ file2_size = get_file_sizeb(file2_path)
+ file1 = open(file1_path, "ab+")
+ file2 = open(file2_path, "rb")
+ file1.write(file2.read(file2_size))
+ file2.close()
+ file1.close()
+
+
+class ToolAuth(object):
+ """
+ class for tool auth, which is a public key certificate for DAA/SLA.
+ """
+ def __init__(self, out_path, tool_auth_path):
+ self.m_out_path = out_path
+ if not os.path.exists(self.m_out_path):
+ os.makedirs(self.m_out_path)
+ self.m_tool_auth_path = tool_auth_path
+ self.m_gfh = gfh.ImageGFH()
+ self.m_sig_handler = None
+
+ def create_gfh(self, gfh_config):
+ """
+ create GFH(generic file header) for tool auth.
+ """
+ self.m_gfh.load_ini(gfh_config)
+ return
+
+ def sign(self, key_ini_path):
+ """
+ generate signature for tool auth.
+ """
+ # tool auth contains only gfh and signature, no extra content
+ self.m_gfh.finalize(0, key_ini_path)
+ # write tbs_tool_auth
+ tbs_toolauth_file_path = os.path.join(self.m_out_path,
+ "tbs_toolauth.bin")
+ tbs_tool_auth_file = open(tbs_toolauth_file_path, "wb")
+ tbs_tool_auth_file.write(self.m_gfh.pack())
+ tbs_tool_auth_file.close()
+ print "===tool_auth signing==="
+ if self.m_gfh.get_sig_type() == "SINGLE":
+ self.m_sig_handler = cert.SigSingle(self.m_gfh.get_pad_type())
+ self.m_sig_handler.set_out_path(self.m_out_path)
+ self.m_sig_handler.create(key_ini_path, tbs_toolauth_file_path)
+ self.m_sig_handler.sign()
+ sig_name = "toolauth.sig"
+ sig_file_path = os.path.join(self.m_out_path, sig_name)
+ self.m_sig_handler.output(self.m_out_path, sig_name)
+ # create final toolauth file
+ if os.path.isfile(self.m_tool_auth_path):
+ os.remove(self.m_tool_auth_path)
+ concatb(self.m_tool_auth_path, tbs_toolauth_file_path)
+ concatb(self.m_tool_auth_path, sig_file_path)
+ else:
+ print "unknown signature type"
+ # clean up
+ os.remove(tbs_toolauth_file_path)
+ os.remove(sig_file_path)
+ return
+
+
+def main():
+ """
+ entry point if this module is executed from cmdline.
+ """
+ # parameter parsing
+ idx = 1
+ key_ini_path = ""
+ gfh_config_ini_path = ""
+ while idx < len(sys.argv):
+ if sys.argv[idx][0] == '-':
+ if sys.argv[idx][1] == 'i':
+ print "key: " + sys.argv[idx + 1]
+ key_ini_path = sys.argv[idx + 1]
+ idx += 2
+ elif sys.argv[idx][1] == 'g':
+ print "gfh: " + sys.argv[idx + 1]
+ gfh_config_ini_path = sys.argv[idx + 1]
+ idx += 2
+ else:
+ print "unknown input"
+ idx += 2
+ else:
+ tool_auth_path = sys.argv[idx]
+ print "tool_auth_path: " + tool_auth_path
+ idx += 1
+
+ if not key_ini_path:
+ print "key path is not given!"
+ return -1
+ if not gfh_config_ini_path:
+ print "gfh config path is not given!"
+ return -1
+ if not tool_auth_path:
+ print "tool_auth path is not given!"
+ return -1
+
+ out_path = os.path.dirname(os.path.abspath(tool_auth_path))
+
+ tool_auth_obj = ToolAuth(out_path, tool_auth_path)
+ tool_auth_obj.create_gfh(gfh_config_ini_path)
+ tool_auth_obj.sign(key_ini_path)
+
+ return 0
+
+
+if __name__ == '__main__':
+ main()
diff --git a/meta/meta-mediatek/recipes-bsp/lk/files/pbp/toolauth/bbchips.ini b/meta/meta-mediatek/recipes-bsp/lk/files/pbp/toolauth/bbchips.ini
new file mode 100644
index 0000000..9cba1be
--- /dev/null
+++ b/meta/meta-mediatek/recipes-bsp/lk/files/pbp/toolauth/bbchips.ini
@@ -0,0 +1,25 @@
+[MT8521p]
+hw_code = 0x8521
+hw_sub_code = 0x0
+hw_ver = 0xca00
+sw_ver = 0x0
+load_region0_sigtype = epp
+load_region0_key = keys/resignda/epp_prvk.pem
+load_region1_sigtype = da
+load_region1_key = keys/resignda/da_prvk.pem
+load_region2_sigtype = da
+load_region2_key = keys/resignda/da_prvk.pem
+[MT8518]
+hw_code = 0x8518
+hw_sub_code = 0x8a00
+hw_ver = 0xcb00
+sw_ver = 0x0
+load_region0_sigtype = epp
+load_region0_sigpad = pss
+load_region0_key = keys/resignda/epp_prvk.pem
+load_region1_sigtype = da
+load_region1_sigpad = pss
+load_region1_key = keys/resignda/da_prvk.pem
+load_region2_sigtype = da
+load_region2_sigpad = pss
+load_region2_key = keys/resignda/da_prvk.pem
diff --git a/meta/meta-mediatek/recipes-bsp/lk/files/pbp/toolauth/toolauth_gfh_config.ini b/meta/meta-mediatek/recipes-bsp/lk/files/pbp/toolauth/toolauth_gfh_config.ini
new file mode 100644
index 0000000..6948f1b
--- /dev/null
+++ b/meta/meta-mediatek/recipes-bsp/lk/files/pbp/toolauth/toolauth_gfh_config.ini
@@ -0,0 +1,19 @@
+[CHIP]
+version = "mt8518"
+[GFH_FILE_INFO]
+version = "1"
+file_type = "5"
+start_addr = "0x00201000"
+flash_dev = "nand"
+sig_type = "SINGLE"
+pad_type = "pss"
+max_size = "0x00040000"
+[GFH_TOOL_AUTH]
+version = "1"
+cust_name = "MTK"
+attr = "0x0"
+sla_public_key = "keys/toolauth/sla_prvk.pem"
+sla_pad_type = "pss"
+daa_public_key = "keys/toolauth/da_prvk.pem"
+daa_pad_type = "pss"
+ar_version_v2 = "0"
diff --git a/meta/meta-mediatek/recipes-bsp/lk/files/pbp/toolauth/toolauth_key.ini b/meta/meta-mediatek/recipes-bsp/lk/files/pbp/toolauth/toolauth_key.ini
new file mode 100644
index 0000000..e760e20
--- /dev/null
+++ b/meta/meta-mediatek/recipes-bsp/lk/files/pbp/toolauth/toolauth_key.ini
@@ -0,0 +1,3 @@
+[KEY]
+sw_ver = "1"
+rootkey = "keys/toolauth/root_prvk.pem"
\ No newline at end of file
diff --git a/meta/meta-mediatek/recipes-bsp/lk/lk_1.0.0.bb b/meta/meta-mediatek/recipes-bsp/lk/lk_1.0.0.bb
new file mode 100644
index 0000000..0674e76
--- /dev/null
+++ b/meta/meta-mediatek/recipes-bsp/lk/lk_1.0.0.bb
@@ -0,0 +1,44 @@
+inherit deploy srcprebuilt externalsrc
+
+LICENSE = "MediaTekProprietary"
+MTK_SRC = "${TOPDIR}/../src/bsp/lk"
+LK_OUT = "${WORKDIR}/out"
+LIC_FILES_CHKSUM = "file://${MTK_SRC}/LICENSE;md5=5a1abdab641eec675725c843f43f03af"
+TOOLCHAIN_PREFIX = "${TARGET_PREFIX}"
+EXTERNALSRC = "${MTK_SRC}"
+EXTERNALSRC_BUILD = "${MTK_SRC}"
+LK_BINARY = "lk.bin"
+PACKAGE_ARCH = "${MACHINE_ARCH}"
+DEPENDS += "libgcc"
+
+python __anonymous () {
+ defaulttune = d.getVar('DEFAULTTUNE', True)
+ if defaulttune == 'cortexa7hf-neon-vfpv4':
+ d.setVar("LIBGCC", '${TOPDIR}/../prebuilt/bsp/lk/${LK_PROJECT}/libgcc.a')
+ else:
+ d.setVar("LIBGCC", '$(${CC} -print-libgcc-file-name)')
+}
+
+do_configure () {
+ :
+}
+
+do_compile () {
+ oe_runmake TOOLCHAIN_PREFIX=${TOOLCHAIN_PREFIX} \
+ NOECHO="" \
+ BOOTLOADER_OUT=${LK_OUT} \
+ FULL_PROJECT=${FULL_PROJECT} \
+ USE_ITS_BOOTIMG=yes \
+ LIBGCC=${LIBGCC} \
+ LK_PROJECT=${LK_PROJECT} \
+ LK_BINARY=${LK_BINARY} \
+ ${LK_PROJECT}
+}
+
+do_deploy () {
+ install -d ${DEPLOYDIR}
+ install ${LK_OUT}/build-${LK_PROJECT}/${LK_BINARY} ${DEPLOYDIR}/${LK_BINARY}
+
+}
+
+addtask deploy before do_build after do_compile
diff --git a/meta/meta-mediatek/recipes-bsp/lk/lk_2.0.0.bb b/meta/meta-mediatek/recipes-bsp/lk/lk_2.0.0.bb
new file mode 100644
index 0000000..fd3f1ca
--- /dev/null
+++ b/meta/meta-mediatek/recipes-bsp/lk/lk_2.0.0.bb
@@ -0,0 +1,131 @@
+inherit deploy srcprebuilt externalsrc lk-image hsm-sign-env
+
+LICENSE = "MIT"
+MTK_SRC = "${TOPDIR}/../src/bsp/lk"
+LK_OUT = "${WORKDIR}/out"
+LIC_FILES_CHKSUM = "file://${MTK_SRC}/LICENSE;md5=25394d472e4c06f4d61140e88861fb5b"
+SRC_URI = "file://gfh file://dev_info file://pbp file://key file://lk_dts file://dummy_img file://fit-lk"
+#S = "${WORKDIR}"
+DEPENDS += "u-boot-mkimage-native bc-native dtc-native"
+
+TOOLCHAIN_PREFIX = "${TARGET_PREFIX}"
+EXTERNALSRC = "${MTK_SRC}"
+EXTERNALSRC_BUILD = "${MTK_SRC}"
+LK_BINARY = "lk.bin"
+LK_IMAGE = "bl2.img"
+PACKAGE_ARCH = "${MACHINE_ARCH}"
+DEPENDS += "libgcc"
+GFH_DIR = "${WORKDIR}/gfh"
+PBP_DIR = "${WORKDIR}/pbp"
+KEY_DIR = "${WORKDIR}/key"
+DTS_DIR = "${WORKDIR}/lk_dts"
+DUMMY_IMG_DIR="${WORKDIR}/dummy_img"
+FIT_IMG_TOOL ?= "uboot-mkimage"
+
+IC_NAME="$(echo ${TARGET_PLATFORM}|tr '[a-z]' '[A-Z]')"
+DEV_INFO_HDR_TOOL = "${TOPDIR}/../src/bsp/scatter/scripts/dev-info-hdr-tool.py"
+
+
+do_configure () {
+ :
+}
+
+do_genkey () {
+ mkdir -p ${LK_OUT}/include
+ if [ "${SECURE_BOOT_ENABLE}" = "yes" ]; then
+ mkdir -p ${WORKDIR}/mykeys
+ dtc -p 0x3ff ${DTS_DIR}/lk.dts -O dtb -o ${DTS_DIR}/lk.dtb
+ cp ${MTK_KEY_DIR}/${VERIFIED_KEY}.crt ${WORKDIR}/mykeys/dev.crt
+ cp ${MTK_KEY_DIR}/${VERIFIED_KEY}.pem ${WORKDIR}/mykeys/dev.key
+ ${HSM_ENV} HSM_KEY_NAME=${VERIFIED_KEY} uboot-mkimage -D "-I dts -O dtb -p 1024" -F -k ${WORKDIR}/mykeys -K ${DTS_DIR}/lk.dtb -r ${DUMMY_IMG_DIR}/fitImage
+ OFF_DT_STRINGS="`fdtdump ${DTS_DIR}/lk.dtb | grep off_dt_strings | sed "s,^\/\/.*:\s*0x,,"`"
+ SIZE_DT_STRINGS="`fdtdump ${DTS_DIR}/lk.dtb | grep size_dt_strings | sed "s,^\/\/.*:\s*0x,,"`"
+ KEYNODE_LEN="`echo "obase=16;ibase=16;${OFF_DT_STRINGS} + ${SIZE_DT_STRINGS}" | bc`"
+ python ${WORKDIR}/dev_info/dtb-transfer-array.py ${DTS_DIR}/lk.dtb ${DTS_DIR}/blob.h ${KEYNODE_LEN}
+ cp ${DTS_DIR}/blob.h ${LK_OUT}/include/blob.h
+ cp ${DTS_DIR}/lk.dtb ${TOPDIR}/lk.dtb
+ rm -rf ${WORKDIR}/mykeys
+ else
+ cp ${DTS_DIR}/tmp_blob.txt ${LK_OUT}/include/blob.h
+ fi
+}
+
+do_compile () {
+ if [ "${DEFAULTTUNE}" = "aarch64" ]; then
+ oe_runmake ARCH_arm64_TOOLCHAIN_PREFIX=${TOOLCHAIN_PREFIX} \
+ NOECHO="" \
+ BUILDROOT=${LK_OUT} \
+ LIBGCC="" \
+ CFLAGS="" \
+ DEBUG=0 \
+ SECURE_BOOT_ENABLE=${SECURE_BOOT_ENABLE} \
+ SECURE_BOOT_TYPE=${SECURE_BOOT_TYPE} \
+ AVB_ENABLE_ANTIROLLBACK=${AVB_ENABLE_ANTIROLLBACK} \
+ AB_OTA_UPDATER=${AB_OTA_UPDATER} \
+ MTK_CLK32K_EXT_REMOVAL_SUPPORT=${MTK_CLK32K_EXT_REMOVAL_SUPPORT} \
+ ${LK_PROJECT}
+ else
+ oe_runmake TOOLCHAIN_PREFIX=${TOOLCHAIN_PREFIX} \
+ NOECHO="" \
+ BUILDROOT=${LK_OUT} \
+ LIBGCC="$(${CC} --sysroot ${STAGING_DIR_HOST} -print-libgcc-file-name)" \
+ CFLAGS="" \
+ DEBUG=0 \
+ SECURE_BOOT_ENABLE=${SECURE_BOOT_ENABLE} \
+ SECURE_BOOT_TYPE=${SECURE_BOOT_TYPE} \
+ AVB_ENABLE_ANTIROLLBACK=${AVB_ENABLE_ANTIROLLBACK} \
+ AB_OTA_UPDATER=${AB_OTA_UPDATER} \
+ MTK_CLK32K_EXT_REMOVAL_SUPPORT=${MTK_CLK32K_EXT_REMOVAL_SUPPORT} \
+ ${LK_PROJECT}
+ fi
+ # add filesize check
+ start=$(grep -w _start -n ${LK_OUT}/build-${LK_PROJECT}/lk.elf.sym.sorted | \
+ sed -E 's/(.*):([0-9a-fA-F]+)(.*)/\2/' | tr '[:lower:]' '[:upper:]')
+ end=$(grep -w _end -n ${LK_OUT}/build-${LK_PROJECT}/lk.elf.sym.sorted | \
+ sed -E 's/(.*):([0-9a-fA-F]+)(.*)/\2/' | tr '[:lower:]' '[:upper:]')
+ fs=`echo "obase=10;ibase=16; $end - $start" | bc`
+ maxsize=$(printf '%d' ${LK_MAX_SIZE})
+
+ if [ ${LK_MAX_SIZE} != "" ] && [ $fs -gt $maxsize ]; then
+ bberror "Little kernel image size overflow, please have a check. $fs > $maxsize"
+ fi
+}
+
+do_buildclean () {
+ if [ "${DEFAULTTUNE}" = "aarch64" ]; then
+ oe_runmake ARCH_arm64_TOOLCHAIN_PREFIX=${TOOLCHAIN_PREFIX} \
+ NOECHO="" \
+ BUILDROOT=${LK_OUT} \
+ LIBGCC="" \
+ CFLAGS="" \
+ DEBUG=0 \
+ ${LK_PROJECT} clean
+ else
+ oe_runmake TOOLCHAIN_PREFIX=${TOOLCHAIN_PREFIX} \
+ NOECHO="" \
+ BUILDROOT=${LK_OUT} \
+ LIBGCC="$(${CC} --sysroot ${STAGING_DIR_HOST} -print-libgcc-file-name)" \
+ CFLAGS="" \
+ DEBUG=0 \
+ ${LK_PROJECT} clean
+ fi
+}
+
+do_genheader () {
+ if [ "${FIT_LK_IMAGE}" = "yes" ]; then
+ gen_lk_fit_header
+ else
+ gen_lk_gfh_header
+ fi
+}
+
+do_deploy () {
+ install -d ${DEPLOYDIR}
+ install ${LK_OUT}/build-${LK_PROJECT}/${LK_BINARY} ${DEPLOYDIR}/${LK_BINARY}
+ install ${WORKDIR}/${LK_IMAGE} ${DEPLOYDIR}/${LK_IMAGE}
+}
+
+addtask genkey before do_compile after do_configure
+addtask genheader before do_deploy after do_compile
+addtask deploy before do_build after do_compile
+
diff --git a/meta/meta-mediatek/recipes-bsp/preloader/preloader.bb b/meta/meta-mediatek/recipes-bsp/preloader/preloader.bb
new file mode 100644
index 0000000..e1e387a
--- /dev/null
+++ b/meta/meta-mediatek/recipes-bsp/preloader/preloader.bb
@@ -0,0 +1,46 @@
+inherit deploy externalsrc
+
+LICENSE = "MediaTekProprietary"
+MTK_SRC = "${TOPDIR}/../src/bsp/preloader"
+LIC_FILES_CHKSUM = "file://${MTK_SRC}/README;md5=661d538ca8a7b4b17d03d6e90e384ffa"
+PRELOADER_OUT = "${WORKDIR}/out"
+CROSS_COMPILE = "${TARGET_PREFIX}"
+EXTERNALSRC = "${MTK_SRC}"
+EXTERNALSRC_BUILD = "${MTK_SRC}"
+PACKAGE_ARCH = "${MACHINE_ARCH}"
+PRELOADER_BINARY = "preloader_${PRELOADER_PROJECT}.bin"
+PRELOADER_IMAGE = "preloader.img"
+PRELOADER_NOR_IMAGE = "preloader_nor.img"
+
+do_compile () {
+ oe_runmake MTK_PROJECT=${PRELOADER_PROJECT} \
+ PRELOADER_OUT=${PRELOADER_OUT} \
+ CROSS_COMPILE=${CROSS_COMPILE} \
+ PRELOADER_BINARY=${PRELOADER_BINARY} \
+ PRELOADER_PROJECT=${PRELOADER_PROJECT}
+ python ${MTK_SRC}/tools/gen-preloader-img.py \
+ ${PRELOADER_OUT}/bin/${PRELOADER_BINARY} \
+ ${PRELOADER_OUT}/bin/${PRELOADER_IMAGE}
+ python ${MTK_SRC}/tools/gen-sf-preloader-img.py \
+ ${PRELOADER_OUT}/bin/${PRELOADER_BINARY} \
+ ${PRELOADER_OUT}/bin/${PRELOADER_NOR_IMAGE}
+}
+
+
+do_buildclean () {
+ oe_runmake MTK_PROJECT=${PRELOADER_PROJECT} \
+ PRELOADER_OUT=${PRELOADER_OUT} \
+ CROSS_COMPILE=${CROSS_COMPILE} \
+ PRELOADER_BINARY=${PRELOADER_BINARY} \
+ PRELOADER_PROJECT=${PRELOADER_PROJECT} clean
+}
+
+do_deploy () {
+ install -d ${DEPLOYDIR}
+ install ${PRELOADER_OUT}/bin/${PRELOADER_BINARY} ${DEPLOYDIR}/${PRELOADER_BINARY}
+ ln -nfs ${PRELOADER_BINARY} ${DEPLOYDIR}/preloader.bin
+ install ${PRELOADER_OUT}/bin/${PRELOADER_IMAGE} ${DEPLOYDIR}/${PRELOADER_IMAGE}
+ install ${PRELOADER_OUT}/bin/${PRELOADER_NOR_IMAGE} ${DEPLOYDIR}/${PRELOADER_NOR_IMAGE}
+}
+
+addtask deploy before do_build after do_compile
diff --git a/meta/meta-mediatek/recipes-bsp/scatter/scatter.bb b/meta/meta-mediatek/recipes-bsp/scatter/scatter.bb
new file mode 100644
index 0000000..e0f5761
--- /dev/null
+++ b/meta/meta-mediatek/recipes-bsp/scatter/scatter.bb
@@ -0,0 +1,26 @@
+inherit deploy srcprebuilt externalsrc
+
+DESCRIPTION = "Scatter File for FlashTool"
+LICENSE = "MediaTekProprietary"
+MTK_SRC = "${TOPDIR}/../src/bsp/scatter"
+SCATTER_SCRIPTS_DIR = "${MTK_SRC}/scripts"
+LIC_FILES_CHKSUM = "file://${MTK_SRC}/README;md5=ee4e5f73850b12ab5da2fa41dc560729"
+EXTERNALSRC = "${MTK_SRC}"
+EXTERNALSRC_BUILD = "${MTK_SRC}"
+SCATTER_OUT = "${WORKDIR}/out"
+NAND_HEADER_VERSION ?= "1.0"
+HEADER_LK_MERGE ?= "no"
+
+do_compile () {
+ ${SCATTER_SCRIPTS_DIR}/gen-partitions.sh ${WORKDIR}/${SCATTER_PROJECT} \
+ ${SCATTER_OUT} ${BOOTDEV_TYPE} ${SCATTER_SCRIPTS_DIR} ${NAND_CHIP_NAME} \
+ ${NAND_HEADER_VERSION} ${HEADER_LK_MERGE}
+}
+
+do_deploy () {
+ install -d ${DEPLOYDIR}
+ install ${SCATTER_OUT}/* -t ${DEPLOYDIR}
+ install ${WORKDIR}/${SCATTER_PROJECT}/*.xml -t ${DEPLOYDIR}
+}
+
+addtask deploy before do_build after do_compile
diff --git a/meta/meta-mediatek/recipes-bsp/spmfw-fit/spmfw-fit.bb b/meta/meta-mediatek/recipes-bsp/spmfw-fit/spmfw-fit.bb
new file mode 100644
index 0000000..c678031
--- /dev/null
+++ b/meta/meta-mediatek/recipes-bsp/spmfw-fit/spmfw-fit.bb
@@ -0,0 +1,62 @@
+inherit deploy spmfw-fitimage
+inherit staging-copyfile
+
+SUMMARY = "SPM Firmware"
+DESCRIPTION = "SPM Firmware"
+LICENSE = "MediaTekProprietary"
+LIC_FILES_CHKSUM = "file://${SPMFW_PREBUILT}/LICENSE;md5=31605e32b2213851d3687355e1ef06f9"
+SPMFW_PREBUILT = "${TOPDIR}/../prebuilt/firmware/spmfw/${TARGET_PLATFORM}"
+SPMFW_OUT = "${WORKDIR}/out"
+SPMFW_IMAGETYPE = "fitImage"
+DEPENDS += "u-boot-mkimage-native"
+
+SPMFW_PREBUILT_BINARY = "spmfw.img"
+SPMFW_BINARY = "spmfw.img"
+SPMFW_RAW_BINARY = "spmfw_raw.img"
+SPMFW_SIGNED_BINARY = "spmfw_signed.img"
+SPMFW_COMPRESS = "none"
+do_compile[nostamp] = "1"
+
+# LOADER ENTRYPOINT, LOADADDRESS
+SPMFW_ENTRYPOINT = "0x44600000"
+SPMFW_LOADADDRESS = "0x44600000"
+
+run_lz4_compression() {
+ dec_size=0
+ fsize=$(stat -c "%s" "${SPMFW_OUT}/${1}")
+ dec_size=$(expr $dec_size + $fsize)
+ lz4 -l -c1 ${SPMFW_OUT}/${1} > ${SPMFW_OUT}/${1}.lz4
+ mv -f ${SPMFW_OUT}/${1}.lz4 ${SPMFW_OUT}/${1}
+ 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` >> ${SPMFW_OUT}/${1};
+ done;
+ }
+}
+
+python __anonymous () {
+ secure_boot_enable = d.getVar('SECURE_BOOT_ENABLE', True)
+ if secure_boot_enable == 'yes':
+ d.setVar("SPMFW_BINARY_SELECT", '${SPMFW_SIGNED_BINARY}')
+ else:
+ d.setVar("SPMFW_BINARY_SELECT", '${SPMFW_RAW_BINARY}')
+}
+
+do_compile () {
+ mkdir -p ${SPMFW_OUT}
+ cp ${SPMFW_PREBUILT}/${SPMFW_PREBUILT_BINARY} ${SPMFW_OUT}/${SPMFW_BINARY_SELECT}
+
+ # compression method LZ4 support
+ if [ "${SPMFW_COMPRESS}" = "lz4" ]; then
+ run_lz4_compression ${SPMFW_BINARY_SELECT}
+ fi
+}
+
+do_deploy () {
+ install -d ${DEPLOYDIR}
+ install ${SPMFW_OUT}/${SPMFW_BINARY} ${DEPLOYDIR}/${SPMFW_BINARY}
+}
+
+addtask deploy before do_build after do_install
\ No newline at end of file
diff --git a/meta/meta-mediatek/recipes-bsp/spmfw/spmfw.bb b/meta/meta-mediatek/recipes-bsp/spmfw/spmfw.bb
new file mode 100644
index 0000000..b23d674
--- /dev/null
+++ b/meta/meta-mediatek/recipes-bsp/spmfw/spmfw.bb
@@ -0,0 +1,55 @@
+inherit deploy spmfw-fitimage
+inherit staging-copyfile
+
+SUMMARY = "SPM Firmware"
+DESCRIPTION = "SPM Firmware"
+LICENSE = "MediaTekProprietary"
+LIC_FILES_CHKSUM = "file://${SPMFW_PREBUILT}/LICENSE;md5=31605e32b2213851d3687355e1ef06f9"
+SPMFW_PREBUILT = "${TOPDIR}/../prebuilt/firmware/spmfw/${TARGET_PLATFORM}"
+SPMFW_OUT = "${WORKDIR}/out"
+
+SPMFW_PREBUILT_BINARY = "spm_firmware.bin"
+SPMFW_BINARY = "spmfw.img"
+SPMFW_RAW_BINARY = "spmfw_raw.img"
+SPMFW_SIGNED_BINARY = "spmfw_signed.img"
+do_compile[nostamp] = "1"
+
+run_lz4_compression() {
+ dec_size=0
+ fsize=$(stat -c "%s" "${SPMFW_OUT}/${1}")
+ dec_size=$(expr $dec_size + $fsize)
+ lz4 -l -c1 ${SPMFW_OUT}/${1} > ${SPMFW_OUT}/${1}.lz4
+ mv -f ${SPMFW_OUT}/${1}.lz4 ${SPMFW_OUT}/${1}
+ 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` >> ${SPMFW_OUT}/${1};
+ done;
+ }
+}
+
+python __anonymous () {
+ secure_boot_enable = d.getVar('SECURE_BOOT_ENABLE', True)
+ if secure_boot_enable == 'yes':
+ d.setVar("SPMFW_BINARY_SELECT", '${SPMFW_SIGNED_BINARY}')
+ else:
+ d.setVar("SPMFW_BINARY_SELECT", '${SPMFW_RAW_BINARY}')
+}
+
+do_compile () {
+ mkdir -p ${SPMFW_OUT}
+ cp ${SPMFW_PREBUILT}/${SPMFW_PREBUILT_BINARY} ${SPMFW_OUT}/${SPMFW_BINARY_SELECT}
+
+ # compression method LZ4 support
+ if [ "${SPMFW_COMPRESS}" = "lz4" ]; then
+ run_lz4_compression ${SPMFW_BINARY_SELECT}
+ fi
+}
+
+do_deploy () {
+ install -d ${DEPLOYDIR}
+ install ${SPMFW_OUT}/${SPMFW_BINARY} ${DEPLOYDIR}/${SPMFW_BINARY}
+}
+
+addtask deploy before do_build after do_install
diff --git a/meta/meta-mediatek/recipes-bsp/sspm/sspm.bb b/meta/meta-mediatek/recipes-bsp/sspm/sspm.bb
new file mode 100644
index 0000000..df9ba15
--- /dev/null
+++ b/meta/meta-mediatek/recipes-bsp/sspm/sspm.bb
@@ -0,0 +1,29 @@
+inherit deploy sspm-fitimage
+inherit staging-copyfile
+
+LICENSE = "MIT"
+SSPM_PREBUILT = "${TOPDIR}/../prebuilt/bsp/collect/aiv8183m1v2-64b"
+SSPM_OUT = "${WORKDIR}/out"
+LIC_FILES_CHKSUM = "file://${SSPM_PREBUILT}/LICENSE;md5=25394d472e4c06f4d61140e88861fb5b"
+DEPENDS += "u-boot-mkimage-native"
+
+SSPM_BINARY = "sspm.img"
+SSPM_IMAGE = "sspm-fit.img"
+SSPM_COMPRESS = "none"
+
+# LOADER ENTRYPOINT, LOADADDRESS
+SSPM_ENTRYPOINT = "0x44000000"
+SSPM_LOADADDRESS = "0x44000000"
+
+do_compile () {
+ mkdir -p ${SSPM_OUT}
+ cp ${SSPM_PREBUILT}/${SSPM_BINARY} ${SSPM_OUT}/${SSPM_BINARY}
+}
+
+do_deploy () {
+ install -d ${DEPLOYDIR}
+ install ${SSPM_OUT}/${SSPM_BINARY} ${DEPLOYDIR}/${SSPM_BINARY}
+ install ${WORKDIR}/${SSPM_IMAGE} ${DEPLOYDIR}/${SSPM_IMAGE}
+}
+
+addtask deploy before do_build after do_compile
\ No newline at end of file
diff --git a/meta/meta-mediatek/recipes-bsp/trustzone/atf_1.0.bb b/meta/meta-mediatek/recipes-bsp/trustzone/atf_1.0.bb
new file mode 100644
index 0000000..cb1be3b
--- /dev/null
+++ b/meta/meta-mediatek/recipes-bsp/trustzone/atf_1.0.bb
@@ -0,0 +1,40 @@
+inherit externalsrc
+inherit deploy trustzone-build
+
+DESCRIPTION = "ARM trusted firmware"
+LICENSE = "BSD"
+# code src may be change in trustzone-build.bb to adapt license
+MTK_SRC = "${TOPDIR}/../src/bsp/trustzone/atf"
+ATF_VER = '1.0'
+CHIP_TYPE = ''
+EXTERNALSRC = "${MTK_SRC}"
+EXTERNALSRC_BUILD = "${MTK_SRC}"
+LIC_FILES_CHKSUM = "file://${B}/v${ATF_VER}/${CHIP_TYPE}/license.md;md5=829bdeb34c1d9044f393d5a16c068371"
+PACKAGE_ARCH = "${MACHINE_ARCH}"
+ATF_OUT = "${WORKDIR}/out"
+ATF_OUT_BINARY = "${ATF_OUT}/${ATF_INSTALL_MODE}/bl31.bin"
+DEPLOY_DIR_IMAGE = "${DEPLOY_DIR}/images/${MACHINE}/trustzone"
+
+EXTRA_OEMAKE = "'CROSS_COMPILE=${TARGET_PREFIX}' \
+ 'PLAT=${MTK_MACH_TYPE}' \
+ 'MACH_TYPE=${MTK_MACH_TYPE}' \
+ 'SECURE_OS=${TEE_SUPPORT}' \
+ 'BUILD_BASE=${ATF_OUT}'"
+
+CFLAGS[unexport] = "1"
+LDFLAGS[unexport] = "1"
+AS[unexport] = "1"
+LD[unexport] = "1"
+do_compile[nostamp] = "1"
+
+do_compile () {
+ oe_runmake -C ${B}/v${ATF_VER}/${CHIP_TYPE} -f ${B}/v${ATF_VER}/${CHIP_TYPE}/Makefile
+}
+
+do_deploy () {
+ install -d ${DEPLOYDIR}
+ install ${ATF_OUT_BINARY} ${DEPLOYDIR}/${ATF_RAW_BINARY}
+ install ${ATF_OUT_BINARY} ${DEPLOYDIR}/${ATF_SIGNED_BINARY}
+}
+
+addtask deploy before do_build after do_install
diff --git a/meta/meta-mediatek/recipes-bsp/trustzone/atf_1.2.bb b/meta/meta-mediatek/recipes-bsp/trustzone/atf_1.2.bb
new file mode 100644
index 0000000..36b1c5f
--- /dev/null
+++ b/meta/meta-mediatek/recipes-bsp/trustzone/atf_1.2.bb
@@ -0,0 +1,47 @@
+inherit externalsrc
+inherit deploy trustzone-build
+
+DESCRIPTION = "ARM trusted firmware"
+LICENSE = "BSD"
+# code src may be change in trustzone-build.bb to adapt license
+MTK_SRC = "${TOPDIR}/../src/bsp/trustzone/atf"
+ATF_VER = '1.2'
+CHIP_TYPE = ''
+LIC_FILES_CHKSUM = "file://${B}/v${ATF_VER}/${CHIP_TYPE}/license.md;md5=829bdeb34c1d9044f393d5a16c068371"
+EXTERNALSRC = "${MTK_SRC}"
+EXTERNALSRC_BUILD = "${MTK_SRC}"
+PACKAGE_ARCH = "${MACHINE_ARCH}"
+ATF_OUT = "${WORKDIR}/out"
+ATF_OUT_BINARY = "${ATF_OUT}/${ATF_INSTALL_MODE}/bl31.bin"
+DEPLOY_DIR_IMAGE = "${DEPLOY_DIR}/images/${MACHINE}/trustzone"
+TBASE_VER ?= "none"
+UBOOT_ARCH ?= "arm64"
+
+EXTRA_OEMAKE = "'CROSS_COMPILE=${TARGET_PREFIX}' \
+ 'KERNEL_ARCH=${KERNEL_ARCH}' \
+ 'ATF_UBOOT_ARCH=${UBOOT_ARCH}' \
+ 'PLAT=${MTK_MACH_TYPE}' \
+ 'MACH_TYPE=${MTK_MACH_TYPE}' \
+ 'SECURE_OS=${TEE_SUPPORT}' \
+ 'BUILD_BASE=${ATF_OUT}' \
+ 'TBASE_VER=${@oe.utils.conditional('TEE_SUPPORT', 'tbase', '${TBASE_VER}', '', d)}' \
+ "
+
+CFLAGS[unexport] = "1"
+LDFLAGS[unexport] = "1"
+AS[unexport] = "1"
+LD[unexport] = "1"
+do_compile[nostamp] = "1"
+
+do_compile () {
+ oe_runmake -C ${B}/v${ATF_VER}/${CHIP_TYPE} -f ${B}/v${ATF_VER}/${CHIP_TYPE}/Makefile
+}
+
+do_deploy () {
+ install -d ${DEPLOYDIR}
+ install ${ATF_OUT_BINARY} ${DEPLOYDIR}/${ATF_RAW_BINARY}
+ install ${ATF_OUT_BINARY} ${DEPLOYDIR}/${ATF_SIGNED_BINARY}
+}
+
+addtask populate_lic before do_install after do_compile
+addtask deploy before do_build after do_install
diff --git a/meta/meta-mediatek/recipes-bsp/trustzone/atf_1.21.bb b/meta/meta-mediatek/recipes-bsp/trustzone/atf_1.21.bb
new file mode 100644
index 0000000..b3edda9
--- /dev/null
+++ b/meta/meta-mediatek/recipes-bsp/trustzone/atf_1.21.bb
@@ -0,0 +1,41 @@
+inherit externalsrc
+inherit deploy trustzone-build
+
+DESCRIPTION = "ARM trusted firmware"
+LICENSE = "BSD"
+# code src may be change in trustzone-build.bb to adapt license
+MTK_SRC = "${TOPDIR}/../src/bsp/trustzone/atf"
+ATF_VER = '1.2'
+CHIP_TYPE = ''
+LIC_FILES_CHKSUM = "file://${B}/v${ATF_VER}/${CHIP_TYPE}/license.md;md5=829bdeb34c1d9044f393d5a16c068371"
+EXTERNALSRC = "${MTK_SRC}"
+EXTERNALSRC_BUILD = "${MTK_SRC}"
+PACKAGE_ARCH = "${MACHINE_ARCH}"
+ATF_OUT = "${WORKDIR}/out"
+ATF_OUT_BINARY = "${ATF_OUT}/${ATF_INSTALL_MODE}/bl31.bin"
+DEPLOY_DIR_IMAGE = "${DEPLOY_DIR}/images/${MACHINE}/trustzone"
+
+EXTRA_OEMAKE = "'CROSS_COMPILE=${TARGET_PREFIX}' \
+ 'KERNEL_ARCH=${KERNEL_ARCH}' \
+ 'PLAT=${MTK_MACH_TYPE}' \
+ 'MACH_TYPE=${MTK_MACH_TYPE}' \
+ 'SECURE_OS=${TEE_SUPPORT}' \
+ 'BUILD_BASE=${ATF_OUT}'"
+
+CFLAGS[unexport] = "1"
+LDFLAGS[unexport] = "1"
+AS[unexport] = "1"
+LD[unexport] = "1"
+do_compile[nostamp] = "1"
+
+do_compile () {
+ oe_runmake -C ${B}/v${ATF_VER}/${CHIP_TYPE} -f ${B}/v${ATF_VER}/${CHIP_TYPE}/Makefile
+}
+
+do_deploy () {
+ install -d ${DEPLOYDIR}
+ install ${ATF_OUT_BINARY} ${DEPLOYDIR}/${ATF_RAW_BINARY}
+ install ${ATF_OUT_BINARY} ${DEPLOYDIR}/${ATF_SIGNED_BINARY}
+}
+
+addtask deploy before do_build after do_install
diff --git a/meta/meta-mediatek/recipes-bsp/trustzone/atf_1.3.bb b/meta/meta-mediatek/recipes-bsp/trustzone/atf_1.3.bb
new file mode 100644
index 0000000..3992f3d
--- /dev/null
+++ b/meta/meta-mediatek/recipes-bsp/trustzone/atf_1.3.bb
@@ -0,0 +1,45 @@
+inherit externalsrc
+inherit deploy trustzone-build
+
+DESCRIPTION = "ARM trusted firmware"
+LICENSE = "BSD"
+# code src may be change in trustzone-build.bb to adapt license
+MTK_SRC = "${TOPDIR}/../src/bsp/trustzone/atf"
+ATF_VER = '1.3'
+CHIP_TYPE = ''
+LIC_FILES_CHKSUM = "file://${B}/v${ATF_VER}/${CHIP_TYPE}/license.md;md5=829bdeb34c1d9044f393d5a16c068371"
+EXTERNALSRC = "${MTK_SRC}"
+EXTERNALSRC_BUILD = "${MTK_SRC}"
+PACKAGE_ARCH = "${MACHINE_ARCH}"
+ATF_OUT = "${WORKDIR}/out"
+ATF_OUT_BINARY = "${ATF_OUT}/${ATF_INSTALL_MODE}/bl31.bin"
+DEPLOY_DIR_IMAGE = "${DEPLOY_DIR}/images/${MACHINE}/trustzone"
+TOOLCHAIN = "gcc"
+
+EXTRA_OEMAKE = "'CROSS_COMPILE=${TARGET_PREFIX}' \
+ 'KERNEL_ARCH=${KERNEL_ARCH}' \
+ 'KERNEL_VERSION = ${PREFERRED_VERSION_linux-mtk-extension}' \
+ 'PLAT=${TZ_PLATFORM}' \
+ 'MACH_TYPE=${MTK_MACH_TYPE}' \
+ 'SECURE_OS=${TEE_SUPPORT}' \
+ 'BUILD_BASE=${ATF_OUT}' \
+ 'V=1' \
+ ${ATF_FEATURE_OPTIONS}"
+
+CFLAGS[unexport] = "1"
+LDFLAGS[unexport] = "1"
+AS[unexport] = "1"
+LD[unexport] = "1"
+do_compile[nostamp] = "1"
+
+do_compile () {
+ oe_runmake -C ${B}/v${ATF_VER}/${CHIP_TYPE} -f ${B}/v${ATF_VER}/${CHIP_TYPE}/Makefile
+}
+
+do_deploy () {
+ install -d ${DEPLOYDIR}
+ install ${ATF_OUT_BINARY} ${DEPLOYDIR}/${ATF_RAW_BINARY}
+ install ${ATF_OUT_BINARY} ${DEPLOYDIR}/${ATF_SIGNED_BINARY}
+}
+
+addtask deploy before do_build after do_install
diff --git a/meta/meta-mediatek/recipes-bsp/trustzone/atf_1.4.bb b/meta/meta-mediatek/recipes-bsp/trustzone/atf_1.4.bb
new file mode 100644
index 0000000..8a86b7d
--- /dev/null
+++ b/meta/meta-mediatek/recipes-bsp/trustzone/atf_1.4.bb
@@ -0,0 +1,44 @@
+inherit externalsrc
+inherit deploy trustzone-build
+
+DESCRIPTION = "ARM trusted firmware"
+LICENSE = "BSD"
+# code src may be change in trustzone-build.bb to adapt license
+MTK_SRC = "${TOPDIR}/../src/bsp/trustzone/atf"
+ATF_VER = '1.4'
+CHIP_TYPE = ''
+LIC_FILES_CHKSUM = "file://${B}/v${ATF_VER}/${CHIP_TYPE}/license.rst;md5=e927e02bca647e14efd87e9e914b2443"
+EXTERNALSRC = "${MTK_SRC}"
+EXTERNALSRC_BUILD = "${MTK_SRC}"
+PACKAGE_ARCH = "${MACHINE_ARCH}"
+ATF_OUT = "${WORKDIR}/out"
+ATF_OUT_BINARY = "${ATF_OUT}/${ATF_INSTALL_MODE}/bl31.bin"
+DEPLOY_DIR_IMAGE = "${DEPLOY_DIR}/images/${MACHINE}/trustzone"
+
+EXTRA_OEMAKE = "'CROSS_COMPILE=${TARGET_PREFIX}' \
+ 'MTK_BL33_PROJECT=${BL33_PROJECT}' \
+ 'KERNEL_ARCH=${KERNEL_ARCH}' \
+ 'PLAT=${MTK_MACH_TYPE}' \
+ 'MACH_TYPE=${MTK_MACH_TYPE}' \
+ 'SECURE_OS=${TEE_SUPPORT}' \
+ 'DEBUG=${@bb.utils.contains("ATF_INSTALL_MODE", "debug", "1", "0", d)}' \
+ 'BUILD_BASE=${ATF_OUT}'"
+
+CFLAGS[unexport] = "1"
+LDFLAGS[unexport] = "1"
+AS[unexport] = "1"
+LD[unexport] = "1"
+do_compile[nostamp] = "1"
+
+do_compile () {
+ oe_runmake -C ${B}/v${ATF_VER}/${CHIP_TYPE} -f ${B}/v${ATF_VER}/${CHIP_TYPE}/Makefile
+}
+
+do_deploy () {
+ install -d ${DEPLOYDIR}
+ install ${ATF_OUT_BINARY} ${DEPLOYDIR}/${ATF_RAW_BINARY}
+ install ${ATF_OUT_BINARY} ${DEPLOYDIR}/${ATF_SIGNED_BINARY}
+}
+
+addtask populate_lic before do_install after do_compile
+addtask deploy before do_build after do_install
diff --git a/meta/meta-mediatek/recipes-bsp/trustzone/atf_1.6.bb b/meta/meta-mediatek/recipes-bsp/trustzone/atf_1.6.bb
new file mode 100644
index 0000000..581685e
--- /dev/null
+++ b/meta/meta-mediatek/recipes-bsp/trustzone/atf_1.6.bb
@@ -0,0 +1,49 @@
+inherit externalsrc
+inherit deploy trustzone-build
+
+DESCRIPTION = "ARM trusted firmware"
+LICENSE = "BSD-3-Clause & MediaTekProprietary"
+# code src may be change in trustzone-build.bb to adapt license
+MTK_SRC = "${TOPDIR}/../src/bsp/trustzone/atf"
+ATF_VER = '1.6'
+CHIP_TYPE = ''
+LIC_FILES_CHKSUM = "file://${B}/v${ATF_VER}/${CHIP_TYPE}/license.rst;md5=e927e02bca647e14efd87e9e914b2443"
+EXTERNALSRC = "${MTK_SRC}"
+EXTERNALSRC_BUILD = "${MTK_SRC}"
+PACKAGE_ARCH = "${MACHINE_ARCH}"
+ATF_OUT = "${WORKDIR}/out"
+ATF_OUT_BINARY = "${ATF_OUT}/${ATF_INSTALL_MODE}/bl31.bin"
+DEPLOY_DIR_IMAGE = "${DEPLOY_DIR}/images/${MACHINE}/trustzone"
+TBASE_VER ?= "none"
+BL33_ARCH ?= "${KERNEL_ARCH}"
+
+EXTRA_OEMAKE = "'CROSS_COMPILE=${TARGET_PREFIX}' \
+ 'MTK_BL33_PROJECT=${BL33_PROJECT}' \
+ 'MTK_BL33_ARCH=${BL33_ARCH}' \
+ 'KERNEL_ARCH=${KERNEL_ARCH}' \
+ 'PLAT=${MTK_MACH_TYPE}' \
+ 'MACH_TYPE=${MTK_MACH_TYPE}' \
+ 'SECURE_OS=${TEE_SUPPORT}' \
+ 'SECURE_OS_ARCH=${TEE_ARCH}' \
+ 'DEBUG=${@bb.utils.contains("ATF_INSTALL_MODE", "debug", "1", "0", d)}' \
+ 'BUILD_BASE=${ATF_OUT}' \
+ ${@oe.utils.conditional('TEE_SUPPORT', 'tbase', 'TBASE_VER=${TBASE_VER}', '', d)}"
+
+CFLAGS[unexport] = "1"
+LDFLAGS[unexport] = "1"
+AS[unexport] = "1"
+LD[unexport] = "1"
+do_compile[nostamp] = "1"
+
+do_compile () {
+ oe_runmake -C ${B}/v${ATF_VER}/${CHIP_TYPE} -f ${B}/v${ATF_VER}/${CHIP_TYPE}/Makefile
+}
+
+do_deploy () {
+ install -d ${DEPLOYDIR}
+ install ${ATF_OUT_BINARY} ${DEPLOYDIR}/${ATF_RAW_BINARY}
+ install ${ATF_OUT_BINARY} ${DEPLOYDIR}/${ATF_SIGNED_BINARY}
+}
+
+addtask populate_lic before do_install after do_compile
+addtask deploy before do_build after do_install
diff --git a/meta/meta-mediatek/recipes-bsp/trustzone/optee-client_3.2.0.bb b/meta/meta-mediatek/recipes-bsp/trustzone/optee-client_3.2.0.bb
new file mode 100644
index 0000000..2699644
--- /dev/null
+++ b/meta/meta-mediatek/recipes-bsp/trustzone/optee-client_3.2.0.bb
@@ -0,0 +1,54 @@
+inherit workonsrc
+inherit trustzone-build
+inherit systemd
+
+DESCRIPTION = "OPTEE CLIENT"
+LICENSE = "BSD-2-Clause & MediaTekProprietary"
+PLATFORM_TYPE = "${@d.getVar('TARGET_PLATFORM', True)[0:3]+'xxx'}"
+OVERRIDES_append = ":${PLATFORM_TYPE}"
+
+TZ_SRC = "${TOPDIR}/../src/bsp/trustzone"
+WORKONSRC = "${TZ_SRC}/optee/3.2.0/source/optee_client"
+WORKONSRC_mt2xxx = "${TZ_SRC}/optee/optee_client/mt2xxx/3.2.0"
+WORKONSRC_BUILD = "${TZ_SRC}/optee/3.2.0/source/optee_client"
+WORKONSRC_BUILD_mt2xxx = "${TZ_SRC}/optee/optee_client/mt2xxx/3.2.0"
+LIC_FILES_CHKSUM = "file://${S}/LICENSE;md5=69663ab153298557a59c67a60a743e5b"
+
+EXTRA_OEMAKE_append = "O=${WORKDIR}/out"
+
+SYSTEMD_PACKAGS = "${PN}"
+SYSTEMD_SERVICE_${PN} = "tee-supplicant.service"
+
+FILES_${PN}_append_mt8xxx = " ${D}${systemd_unitdir}/system/tee-supplicant.service"
+FILES_${PN}_append_mt2xxx = " ${systemd_unitdir}/system/tee-supplicant.service"
+
+do_install() {
+ oe_runmake install
+
+ install -D -p -m0755 ${WORKDIR}/out/export/bin/tee-supplicant ${D}${bindir}/tee-supplicant
+
+ install -D -p -m0644 ${WORKDIR}/out/export/lib/libteec.so.1.0 ${D}${libdir}/libteec.so.1.0
+ ln -sf libteec.so.1.0 ${D}${libdir}/libteec.so
+ ln -sf libteec.so.1.0 ${D}${libdir}/libteec.so.1
+
+ cp -a ${WORKDIR}/out/export/include ${D}/usr/
+
+ if ${@bb.utils.contains('DISTRO_FEATURES','systemd','true','false',d)}; then
+ cp -a ${S}/tee-supplicant.service ${WORKDIR}
+ sed -i -e s:/etc:${sysconfdir}:g \
+ -e s:/usr/bin:${bindir}:g \
+ ${WORKDIR}/tee-supplicant.service
+
+ install -d ${D}${systemd_unitdir}/system
+ install -D -p -m0644 ${WORKDIR}/tee-supplicant.service ${D}${systemd_unitdir}/system/tee-supplicant.service
+ fi
+
+ if ${@bb.utils.contains('DISTRO_FEATURES','sysvinit','true','false',d)}; then
+ install -d ${D}${sysconfdir}/init.d
+ install -m 0755 ${S}/tee-supplicant.init ${D}${sysconfdir}/init.d/tee-supplicant.init
+ update-rc.d -r ${D} tee-supplicant.init start 4 S .
+ fi
+}
+
+# Install Sysvinit Scripts #
+DEPENDS_append = " update-rc.d-native"
diff --git a/meta/meta-mediatek/recipes-bsp/trustzone/optee-example_3.2.0.bb b/meta/meta-mediatek/recipes-bsp/trustzone/optee-example_3.2.0.bb
new file mode 100644
index 0000000..e7f10f4
--- /dev/null
+++ b/meta/meta-mediatek/recipes-bsp/trustzone/optee-example_3.2.0.bb
@@ -0,0 +1,44 @@
+inherit workonsrc
+inherit trustzone-build
+
+DESCRIPTION = "OPTEE example"
+LICENSE = "BSD-2-Clause & MediaTekProprietary"
+TZ_SRC = "${TOPDIR}/../src/bsp/trustzone"
+WORKONSRC = "${TZ_SRC}/optee/source/mt2xxx/optee_examples"
+WORKONSRC_BUILD = "${TZ_SRC}/optee/source/mt2xxx/optee_examples"
+LIC_FILES_CHKSUM = "file://${S}/LICENSE;md5=cd95ab417e23b94f381dafc453d70c30"
+
+DEPENDS = "optee-client optee-os"
+
+OPTEE_CLIENT_EXPORT = "${STAGING_DIR_HOST}${prefix}"
+TEEC_EXPORT = "${STAGING_DIR_HOST}${prefix}"
+TA_DEV_KIT_DIR = "${STAGING_INCDIR}/optee/export-user_ta"
+
+OPTEE_ARCH = "${TEE_ARCH}"
+TEE_TOOLCHAIN ?= "${HOST_PREFIX}"
+
+EXTRA_OEMAKE = " TA_DEV_KIT_DIR=${TA_DEV_KIT_DIR} \
+ OPTEE_CLIENT_EXPORT=${OPTEE_CLIENT_EXPORT} \
+ TEEC_EXPORT=${TEEC_EXPORT} \
+ HOST_CROSS_COMPILE=${TEE_TOOLCHAIN} \
+ CROSS_COMPILE_TA=${TEE_TOOLCHAIN} \
+ V=1 \
+ OUTPUT_DIR=${WORKDIR}/out \
+ "
+
+do_compile() {
+ # Top level makefile doesn't seem to handle parallel make gracefully
+ oe_runmake all
+}
+
+do_install () {
+ install -d ${D}${bindir}/
+ install -D -p -m0755 ${WORKDIR}/out/ca/optee_example_* ${D}${bindir}/
+
+ # install path should match the value set in optee-client/tee-supplicant
+ # default TEEC_LOAD_PATH is /lib
+ mkdir -p ${D}${nonarch_base_libdir}/optee_armtz/
+ install -D -p -m0444 ${WORKDIR}/out/ta/*.ta ${D}${nonarch_base_libdir}/optee_armtz/
+}
+
+FILES_${PN} += "${nonarch_base_libdir}/optee_armtz/"
\ No newline at end of file
diff --git a/meta/meta-mediatek/recipes-bsp/trustzone/optee-os_3.2.0.bb b/meta/meta-mediatek/recipes-bsp/trustzone/optee-os_3.2.0.bb
new file mode 100644
index 0000000..d9dc459
--- /dev/null
+++ b/meta/meta-mediatek/recipes-bsp/trustzone/optee-os_3.2.0.bb
@@ -0,0 +1,80 @@
+inherit workonsrc
+inherit deploy trustzone-build
+DEPENDS = "python-pycrypto-native"
+
+inherit pythonnative
+
+DESCRIPTION = "OPTEE OS"
+LICENSE = "BSD-2-Clause"
+PLATFORM_TYPE = "${@d.getVar('TARGET_PLATFORM', True)[0:3]+'xxx'}"
+OVERRIDES += ":${PLATFORM_TYPE}"
+TZ_SRC = "${TOPDIR}/../src/bsp/trustzone"
+WORKONSRC = "${TZ_SRC}/optee/3.2.0/optee_os"
+WORKONSRC_mt2xxx = "${TZ_SRC}/optee/optee_os/mt2xxx/3.2.0"
+WORKONSRC_BUILD = "${TZ_SRC}/optee/3.2.0/optee_os"
+WORKONSRC_BUILD_mt2xxx = "${TZ_SRC}/optee/optee_os/mt2xxx/3.2.0"
+LIC_FILES_CHKSUM = "file://${S}/LICENSE;md5=69663ab153298557a59c67a60a743e5b"
+OPTEEMACHINE = "mediatek"
+OPTEEOUTPUTMACHINE = "mediatek"
+
+OPTEE_ARCH = "${TEE_ARCH}"
+TEE_TOOLCHAIN ?= "${TARGET_PREFIX}"
+DEPENDS += "virtual/${TARGET_PREFIX}gcc"
+TEE_OS_RAM_SIZE = "0x1d0000"
+
+do_compile[nostamp] = "1"
+
+EXTRA_OEMAKE = "PLATFORM=${OPTEEMACHINE} \
+ CFG_ARM64_core=y \
+ CROSS_COMPILE64=${TEE_TOOLCHAIN} \
+ NOWERROR=1 \
+ ta-targets=ta_${OPTEE_ARCH} \
+ LDFLAGS= \
+ LIBGCC_LOCATE_CFLAGS=--sysroot=${STAGING_DIR_HOST} \
+ CFLAGS='${CFLAGS} --sysroot=${STAGING_DIR_HOST}' \
+ O=${WORKDIR}/out/${OPTEE_ARCH}-plat-${OPTEEOUTPUTMACHINE} \
+ "
+
+EXTRA_OEMAKE_append="PLATFORM_FLAVOR=${TZ_PLATFORM} \
+ CFG_TZDRAM_START=${TRUSTEDOS_ENTRYPOINT} \
+ CFG_TZDRAM_SIZE=${TRUSTEDOS_SIZE} \
+ CFG_SHMEM_START=${TRUSTEDOS_ENTRYPOINT}+CFG_TZDRAM_SIZE \
+ CFG_SHMEM_SIZE=${TRUSTEDOS_SHMEM_SIZE} \
+ MTK_PROJECT=${MTK_PROJECT} \
+ "
+
+EXTRA_OEMAKE_append_mt8xxx = " CFG_TEE_RAM_VA_SIZE=${TEE_OS_RAM_SIZE}"
+
+do_compile () {
+ oe_runmake all
+}
+
+do_install() {
+ #install core on boot directory
+ install -d ${D}${nonarch_base_libdir}/firmware/
+
+ install -m 644 ${WORKDIR}/out/${OPTEE_ARCH}-plat-${OPTEEOUTPUTMACHINE}/core/*.bin ${D}${nonarch_base_libdir}/firmware/
+ #install TA devkit
+ install -d ${D}/usr/include/optee/export-user_ta/
+
+ for f in ${WORKDIR}/out/${OPTEE_ARCH}-plat-${OPTEEOUTPUTMACHINE}/export-ta_${OPTEE_ARCH}/* ; do
+ cp -aR $f ${D}/usr/include/optee/export-user_ta/
+ done
+}
+
+do_deploy() {
+ install -d ${DEPLOYDIR}/optee
+ for f in ${D}${nonarch_base_libdir}/firmware/*; do
+ install -m 644 $f ${DEPLOYDIR}/optee/
+ done
+ install ${DEPLOYDIR}/optee/tee-pager.bin ${TZ_ASSEMBLE_OUT}/${TZ_RAW_BINARY}
+ install ${DEPLOYDIR}/optee/tee-pager.bin ${TZ_ASSEMBLE_OUT}/${TRUSTEDOS_RAW_BINARY}
+ install ${DEPLOYDIR}/optee/tee-pager.bin ${TZ_ASSEMBLE_OUT}/${TRUSTEDOS_SIGNED_BINARY}
+}
+
+addtask deploy before do_build after do_install
+
+FILES_${PN} = "${nonarch_base_libdir}/firmware/"
+FILES_${PN}-dev = "/usr/include/optee"
+
+INSANE_SKIP_${PN}-dev = "staticdev"
diff --git a/meta/meta-mediatek/recipes-bsp/trustzone/optee-services.bb b/meta/meta-mediatek/recipes-bsp/trustzone/optee-services.bb
new file mode 100644
index 0000000..c1db561
--- /dev/null
+++ b/meta/meta-mediatek/recipes-bsp/trustzone/optee-services.bb
@@ -0,0 +1,58 @@
+inherit workonsrc
+inherit trustzone-build
+inherit optee-build
+DEPENDS = "python3-pycrypto-native"
+
+#inherit pythonnative
+
+SUMMARY = "OP-TEE services"
+LICENSE = "BSD-2-Clause & MediaTekProprietary"
+LIC_FILES_CHKSUM = "file://${S}/LICENSE;md5=cd95ab417e23b94f381dafc453d70c30"
+
+DEPENDS += "optee-client"
+
+DEPENDS += "${@bb.utils.contains('MULTILIBS', 'multilib:lib64', 'lib64-optee-os', 'optee-os' ,d)}"
+
+PLATFORM_TYPE = "${@d.getVar('TARGET_PLATFORM', True)[0:3]+'xxx'}"
+OVERRIDES_append = ":${PLATFORM_TYPE}"
+
+TZ_SRC = "${TOPDIR}/../src/bsp/trustzone"
+WORKONSRC = "${TZ_SRC}/optee/3.2.0/source/optee_services"
+WORKONSRC_mt2xxx = "${TZ_SRC}/optee/source/mt2xxx/optee_services"
+
+OPTEE_CLIENT_EXPORT = "${STAGING_DIR_HOST}${prefix}"
+TEEC_EXPORT = "${STAGING_DIR_HOST}${prefix}"
+TA_DEV_KIT_DIR_mt2xxx = "${STAGING_INCDIR}/optee/export-user_ta"
+
+INSANE_SKIP_${PN} = "installed-vs-shipped"
+SOLIBS = ".so"
+FILES_SOLIBSDEV = ""
+FILES_${PN} += "${nonarch_base_libdir}/optee_armtz/"
+
+OPTEE_ARCH = "${TEE_ARCH}"
+DEPENDS += "virtual/${TARGET_PREFIX}gcc"
+
+EXTRA_OEMAKE = " TA_DEV_KIT_DIR=${TA_DEV_KIT_DIR} \
+ OPTEE_CLIENT_EXPORT=${OPTEE_CLIENT_EXPORT} \
+ TEEC_EXPORT=${TEEC_EXPORT} \
+ HOST_CROSS_COMPILE=${TARGET_PREFIX} \
+ TA_CROSS_COMPILE=${TEE_TOOLCHAIN} \
+ V=1 \
+ "
+
+do_compile() {
+ export LD_LIBRARY_PATH=${OPTEE_LIB64}:${LD_LIBRARY_PATH}
+ export PATH=${OPTEE_BULID_SA}:${PATH}
+ oe_runmake
+}
+
+do_install () {
+ install -d ${D}${libdir}
+ install -d ${D}${bindir}
+ install -d ${D}${includedir}
+ install -d ${S}/out/ta
+ oe_runmake install LIBDIR="${D}${libdir}" BINDIR="${D}${bindir}" INCDIR="${D}${includedir}" TADIR="${S}out/ta"
+
+ mkdir -p ${D}${nonarch_base_libdir}/optee_armtz
+ install -D -p -m0444 ${S}/out/ta/* ${D}${nonarch_base_libdir}/optee_armtz
+}
\ No newline at end of file
diff --git a/meta/meta-mediatek/recipes-bsp/trustzone/optee-test_3.2.0.bb b/meta/meta-mediatek/recipes-bsp/trustzone/optee-test_3.2.0.bb
new file mode 100644
index 0000000..89d3f96
--- /dev/null
+++ b/meta/meta-mediatek/recipes-bsp/trustzone/optee-test_3.2.0.bb
@@ -0,0 +1,63 @@
+inherit workonsrc
+inherit deploy
+inherit optee-build
+DEPENDS = "python-pycrypto-native"
+
+inherit pythonnative
+
+DESCRIPTION = "OPTEE TESTSUITE"
+LICENSE = "BSD-2-Clause & GPL-2.0"
+PLATFORM_TYPE = "${@d.getVar('TARGET_PLATFORM', True)[0:3]+'xxx'}"
+OVERRIDES_append = ":${PLATFORM_TYPE}"
+TZ_SRC = "${TOPDIR}/../src/bsp/trustzone"
+WORKONSRC = "${TZ_SRC}/optee/3.2.0/source/optee_test"
+WORKONSRC_mt2xxx = "${TZ_SRC}/optee/optee_test/mt2xxx"
+WORKONSRC_BUILD = "${TZ_SRC}/optee/3.2.0/source/optee_test"
+WORKONSRC_BUILD_mt2xxx = "${TZ_SRC}/optee/optee_test/mt2xxx"
+LIC_FILES_CHKSUM = "file://${S}/LICENSE.md;md5=daa2bcccc666345ab8940aab1315a4fa"
+DEPENDS += "optee-client openssl"
+DEPENDS_append_mt2xxx = " optee-os "
+DEPENDS_append_mt8xxx = " lib64-optee-os "
+OPTEE_CLIENT_EXPORT = "${STAGING_DIR_HOST}${prefix}"
+OPTEE_OPENSSL_EXPORT = "${STAGING_INCDIR}"
+TEEC_EXPORT = "${STAGING_DIR_HOST}${prefix}"
+TA_DEV_KIT_DIR_mt2xxx = "${STAGING_INCDIR}/optee/export-user_ta"
+
+OPTEE_ARCH = "${TEE_ARCH}"
+TEE_TOOLCHAIN_mt2xxx = "${TARGET_PREFIX}"
+DEPENDS += "virtual/${TARGET_PREFIX}gcc"
+
+EXTRA_OEMAKE = " TA_DEV_KIT_DIR=${TA_DEV_KIT_DIR} \
+ OPTEE_CLIENT_EXPORT=${OPTEE_CLIENT_EXPORT} \
+ OPTEE_OPENSSL_EXPORT=${OPTEE_OPENSSL_EXPORT} \
+ TEEC_EXPORT=${TEEC_EXPORT} \
+ CROSS_COMPILE_HOST=${TARGET_PREFIX} \
+ CROSS_COMPILE_TA=${TEE_TOOLCHAIN} \
+ V=1 \
+ O=${WORKDIR}/out \
+ COMPILE_NS_USER=32 \
+ "
+
+do_compile() {
+ # Top level makefile doesn't seem to handle parallel make gracefully
+if ${@bb.utils.contains('PLATFORM_TYPE','mt2xxx','false','true',d)}; then
+ export LD_LIBRARY_PATH=${OPTEE_LIB64}:${LD_LIBRARY_PATH}
+ export PATH=${OPTEE_BULID_SA}:${PATH}
+fi
+ oe_runmake xtest
+ oe_runmake ta
+}
+
+do_install () {
+ install -D -p -m0755 ${WORKDIR}/out/xtest/xtest ${D}${bindir}/xtest
+
+ # install path should match the value set in optee-client/tee-supplicant
+ # default TEEC_LOAD_PATH is /lib
+ mkdir -p ${D}${nonarch_base_libdir}/optee_armtz/
+ install -D -p -m0444 ${WORKDIR}/out/ta/*/*.ta ${D}${nonarch_base_libdir}/optee_armtz/
+}
+
+FILES_${PN} += "${nonarch_base_libdir}/optee_armtz/"
+
+# Imports machine specific configs from staging to build
+PACKAGE_ARCH = "${MACHINE_ARCH}"
diff --git a/meta/meta-mediatek/recipes-bsp/trustzone/tee-mtee.bb b/meta/meta-mediatek/recipes-bsp/trustzone/tee-mtee.bb
new file mode 100644
index 0000000..ba62693
--- /dev/null
+++ b/meta/meta-mediatek/recipes-bsp/trustzone/tee-mtee.bb
@@ -0,0 +1,64 @@
+inherit workonsrc
+inherit deploy trustzone-build
+
+DESCRIPTION = "MTEE Image"
+LICENSE = "MediaTekProprietary"
+TZ_SRC = "${TOPDIR}/../src/bsp/trustzone"
+TZ_PREBUILT = "${TOPDIR}/../prebuilt/bsp/trustzone"
+WORKONSRC = "${TZ_SRC}/mtee/build"
+WORKONSRC_BUILD = "${TZ_SRC}/mtee/build"
+LIC_FILES_CHKSUM = "file://${TZ_PREBUILT}/mtee/build/yocto_build/README;md5=5a126b0ba82af703f1c30cf8d0bb4e13"
+TZ_OUT = "${WORKDIR}/out"
+TZ_BINARY_OUT = "${TZ_OUT}/bin"
+TZ_RAW_OUT = "${TZ_OUT}/archive"
+TZ_BINARY = "tz.img"
+PACKAGE_ARCH = "${MACHINE_ARCH}"
+do_compile[nostamp] = "1"
+
+do_compile () {
+if [ "${TEE_ARCH}" = "" ]; then
+ TEE_ARCH=${KERNEL_ARCH}
+fi
+if [ -e ${TZ_SRC}/mtee/build/yocto_build/makefile ] && [ -d ${TZ_SRC}/mtee/source/${TZ_PLATFORM} ]; then
+ python ${TZ_SRC}/mtee/build/yocto_build/android_makefile_parser.py \
+ ${TZ_SRC}/mtee \
+ ${TZ_PLATFORM} \
+ ${TZ_PROJECT} \
+ ${TEE_ARCH} \
+ ${TZ_SRC}/mtee/trustzone.mk \
+ ${TZ_PREBUILT}/${TZ_PROJECT}/prebuilts
+
+ TZ_SRC=${TZ_SRC} \
+ TZ_OUT=${TZ_OUT} \
+ TZ_VERSION=${TRUSTZONE_VERSION} \
+ ARCH=${TEE_ARCH} \
+ MTK_PLATFORM=${TZ_PLATFORM} \
+ MTK_PROJECT=${TZ_PROJECT} \
+ CROSS_COMPILE=${TARGET_PREFIX} \
+ make -C ${TZ_SRC}/mtee -f ${TZ_SRC}/mtee/build/yocto_build/makefile
+fi
+}
+
+do_deploy () {
+ install -d ${DEPLOYDIR}
+ if [ -e ${TZ_SRC}/mtee/build/yocto_build/makefile ] && [ -d ${TZ_SRC}/mtee/source/${TZ_PLATFORM} ]; then
+ install ${TZ_RAW_OUT}/${TZ_BINARY} ${TZ_ASSEMBLE_OUT}/${TZ_RAW_BINARY}
+ install ${TZ_BINARY_OUT}/${TZ_SIGNED_BINARY} ${TZ_ASSEMBLE_OUT}/${TZ_SIGNED_BINARY}
+ install ${TZ_RAW_OUT}/${TZ_BINARY} ${TZ_ASSEMBLE_OUT}/${TRUSTEDOS_RAW_BINARY}
+ install ${TZ_BINARY_OUT}/${TZ_SIGNED_BINARY} ${TZ_ASSEMBLE_OUT}/${TRUSTEDOS_SIGNED_BINARY}
+ else
+ if [ "${TRUSTZONE_HEADER}" = "fit" ]; then
+ echo "fit image case"
+ echo ${TZ_PREBUILT}/${TZ_PROJECT}/${TZ_RAW_BINARY} ${TZ_ASSEMBLE_OUT}/${TZ_RAW_BINARY}
+ install ${TZ_PREBUILT}/${TZ_PROJECT}/${TZ_RAW_BINARY} ${TZ_ASSEMBLE_OUT}/${TZ_RAW_BINARY}
+ install ${TZ_PREBUILT}/${TZ_PROJECT}/${TZ_SIGNED_BINARY} ${TZ_ASSEMBLE_OUT}/${TZ_SIGNED_BINARY}
+ install ${TZ_PREBUILT}/${TZ_PROJECT}/${TZ_RAW_BINARY} ${TZ_ASSEMBLE_OUT}/${TRUSTEDOS_RAW_BINARY}
+ install ${TZ_PREBUILT}/${TZ_PROJECT}/${TZ_SIGNED_BINARY} ${TZ_ASSEMBLE_OUT}/${TRUSTEDOS_SIGNED_BINARY}
+ else
+ echo "no fit image case"
+ install ${TZ_PREBUILT}/${TZ_PROJECT}/${TZ_BINARY} ${TZ_ASSEMBLE_OUT}/${TZ_BINARY}
+ fi
+ fi
+}
+
+addtask deploy before do_build after do_install
diff --git a/meta/meta-mediatek/recipes-bsp/trustzone/teeloader.bb b/meta/meta-mediatek/recipes-bsp/trustzone/teeloader.bb
new file mode 100644
index 0000000..39eae85
--- /dev/null
+++ b/meta/meta-mediatek/recipes-bsp/trustzone/teeloader.bb
@@ -0,0 +1,64 @@
+inherit deploy trustzone-build
+
+DESCRIPTION = "TEELOADER Image"
+LICENSE = "MediaTekProprietary"
+TZ_SRC = "${TOPDIR}/../src/bsp/trustzone"
+TL_SRC = "${TOPDIR}/../src/bsp/trustzone/teeloader"
+TZ_PREBUILT = "${TOPDIR}/../prebuilt/bsp/trustzone"
+LIC_FILES_CHKSUM = "file://${TL_SRC}/README;md5=5a126b0ba82af703f1c30cf8d0bb4e13"
+TL_OUT = "${WORKDIR}/out"
+TL_RAW_OUT = "${TL_OUT}/archive_tl"
+TZ_ORIG_KEY = "${MTK_KEY_DIR}/${MTEE_KEY}.pem"
+PACKAGE_ARCH = "${MACHINE_ARCH}"
+DEPLOY_DIR_IMAGE = "${DEPLOY_DIR}/images/${MACHINE}/trustzone"
+do_compile[nostamp] = "1"
+
+do_compile () {
+if [ ${SECURE_BOOT_ENABLE} = "yes" ]; then
+ if [ -d ${TL_SRC} ]; then
+ if [ ${FORCE_DISABLE_TEE_ENCRYPTION} = "yes" ]; then
+ TL_VERIFY_ENABLE="0x0"
+ else
+ TL_VERIFY_ENABLE="0x1"
+ fi
+ if [ -e ${TZ_ORIG_KEY} ] && [ ${FORCE_DISABLE_TEE_ENCRYPTION} != "yes" ]; then
+ cp -rf ${TZ_ORIG_KEY} ${TL_SRC}/${TZ_PLATFORM}/include/mtee_key.pem
+ python ${TL_SRC}/${TZ_PLATFORM}/cus_tzimg_dec_key.py
+ python ${TL_SRC}/${TZ_PLATFORM}/cus_tzimg_enc_key.py ${TZ_PLATFORM}
+ rm -rf ${TL_SRC}/${TZ_PLATFORM}/include/mtee_key.pem
+ fi
+ else
+ TL_VERIFY_ENABLE="0x0"
+ TL_ALIGN_SIZE="0x0"
+ fi
+else
+ TL_VERIFY_ENABLE="0x0"
+fi
+
+if [ ${TEE_SUPPORT} = "none" ]; then
+ TRUSTEDOS_EP=0x0
+else
+ TRUSTEDOS_EP=${TRUSTEDOS_ENTRYPOINT}
+fi
+
+if [ -d ${TL_SRC} ]; then
+ TL_RAW_OUT=${TL_RAW_OUT} \
+ BASE_ADDR=${TEE_LOADADDRESS} \
+ TL_ALIGN_SIZE=${TL_ALIGN_SIZE} \
+ CROSS_COMPILE=${TARGET_PREFIX} \
+ TL_VERIFY_ENABLE=${TL_VERIFY_ENABLE} \
+ TRUSTEDOS_ENTRYPOINT=${TRUSTEDOS_EP} \
+ TZ_PROJECT=${TZ_PROJECT} \
+ make -C ${TL_SRC}/${TZ_PLATFORM} -f ${TL_SRC}/${TZ_PLATFORM}/Makefile
+fi
+}
+
+do_deploy () {
+if [ -d ${TL_SRC} ]; then
+ install -d ${DEPLOYDIR}
+ install ${TL_RAW_OUT}/bin/teeloader.bin ${DEPLOYDIR}/teeloader.bin
+fi
+}
+
+addtask populate_lic before do_install after do_compile
+addtask deploy before do_build after do_install
diff --git a/meta/meta-mediatek/recipes-bsp/trustzone/trustzone.bb b/meta/meta-mediatek/recipes-bsp/trustzone/trustzone.bb
new file mode 100644
index 0000000..f3702cd
--- /dev/null
+++ b/meta/meta-mediatek/recipes-bsp/trustzone/trustzone.bb
@@ -0,0 +1,86 @@
+inherit deploy trustzone-build trustzone-fitimage
+inherit staging-copyfile
+DESCRIPTION = "TrustZone Image"
+LICENSE = "MediaTekProprietary"
+TL_SRC = "${TOPDIR}/../src/bsp/trustzone/teeloader"
+LIC_FILES_CHKSUM = "file://${TL_SRC}/LICENSE;md5=e75e69d55c2eacd5692b77cb4ba4d00e"
+PACKAGE_ARCH = "${MACHINE_ARCH}"
+DEPENDS += "u-boot-mkimage-native dtc-native lz4-native"
+
+TZ_OUT = "${WORKDIR}/out"
+
+#please make sure all output file under ${TZ_ASSEMBLE_OUT}
+#TEELOADER: teeloader.bin
+#ATF: ${ATF_RAW_BINARY} ${ATF_SIGNED_BINARY}
+#TEE: ${TZ_RAW_BINARY} ${TZ_SIGNED_BINARY}
+#final layout:
+#raw tz.img (not has extra tee verification):
+#[teeloader.bin][${ATF_RAW_BINARY}][[${TZ_RAW_BINARY}](if has tee)]
+#signed tz.img (has extra tee verification handled in tee loader):
+#[teeloader.bin][${ATF_SIGNED_BINARY}][[${TZ_SIGNED_BINARY}](if has tee)]
+#
+#trustzone.bb only assemble the final tz.img with the files under ${TZ_ASSEMBLE_OUT}
+#
+
+run_lz4_compression() {
+ dec_size=0
+ fsize=$(stat -c "%s" "${TZ_ASSEMBLE_OUT}/${1}")
+ dec_size=$(expr $dec_size + $fsize)
+ lz4 -l -c1 ${TZ_ASSEMBLE_OUT}/${1} > ${TZ_ASSEMBLE_OUT}/${1}.lz4
+ mv -f ${TZ_ASSEMBLE_OUT}/${1}.lz4 ${TZ_ASSEMBLE_OUT}/${1}
+ 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` >> ${TZ_ASSEMBLE_OUT}/${1};
+ done;
+ }
+}
+
+do_compile () {
+if ${@bb.utils.contains('TRUSTZONE_HEADER','fit','true','false',d)}; then
+ # integrate tz image
+ if [ -d ${TL_SRC} ]; then
+ cp ${TZ_ASSEMBLE_OUT}/teeloader.bin ${TZ_ASSEMBLE_OUT}/${TZ_TMP_BINARY}
+ fi
+ if [ "${ATF_SUPPORT}" = "yes" ]; then
+ cat ${TZ_ASSEMBLE_OUT}/${ATF_BINARY_SELECT} >> ${TZ_ASSEMBLE_OUT}/${TZ_TMP_BINARY}
+ fi
+ if [ "${TEE_SUPPORT}" != "none" ]; then
+ if [ -z "${TRUSTEDOS_ENTRYPOINT}" ] && [ -z "${TRUSTEDOS_LOADADDRESS}" ] ; then
+ cat ${TZ_ASSEMBLE_OUT}/${TZ_BINARY_SELECT} >> ${TZ_ASSEMBLE_OUT}/${TZ_TMP_BINARY}
+ fi
+ fi
+
+ # compression method LZ4 support
+ if [ "${TRUSTZONE_COMPRESS}" = "lz4" ]; then
+ run_lz4_compression ${TZ_TMP_BINARY}
+
+ if [ "${TEE_SUPPORT}" != "none" ]; then
+ if [ -n "${TRUSTEDOS_ENTRYPOINT}" ] && [ -n "${TRUSTEDOS_LOADADDRESS}" ]; then
+ run_lz4_compression ${TRUSTEDOS_BINARY_SELECT}
+ fi
+ fi
+ fi
+
+ # raw and signed tz image flow
+ if [ "${SECURE_BOOT_ENABLE}" = "yes" ] && [ "${FORCE_DISABLE_TEE_ENCRYPTION}" != "yes" ]; then
+ mv ${TZ_ASSEMBLE_OUT}/${TZ_TMP_BINARY} ${TZ_ASSEMBLE_OUT}/${TZ_TMP_SIGNED_BINARY}
+ else
+ mv ${TZ_ASSEMBLE_OUT}/${TZ_TMP_BINARY} ${TZ_ASSEMBLE_OUT}/${TZ_TMP_RAW_BINARY}
+ fi
+fi
+}
+
+do_deploy () {
+ install -d ${DEPLOYDIR}
+ install ${TZ_ASSEMBLE_OUT}/${TZ_BINARY} ${DEPLOYDIR}/${TZ_BINARY}
+ if [ -e ${TZ_ASSEMBLE_OUT}/${TZ_RAW_BINARY} ]; then
+ install ${TZ_ASSEMBLE_OUT}/${TZ_RAW_BINARY} ${DEPLOYDIR}/${TZ_RAW_BINARY}
+ fi
+ if [ -e ${TZ_ASSEMBLE_OUT}/${TZ_SIGNED_BINARY} ]; then
+ install ${TZ_ASSEMBLE_OUT}/${TZ_SIGNED_BINARY} ${DEPLOYDIR}/${TZ_SIGNED_BINARY}
+ fi
+}
+
+addtask deploy before do_build after do_install
diff --git a/meta/meta-mediatek/recipes-bsp/tzapp/hal-dha-headers.bb b/meta/meta-mediatek/recipes-bsp/tzapp/hal-dha-headers.bb
new file mode 100644
index 0000000..05678bd
--- /dev/null
+++ b/meta/meta-mediatek/recipes-bsp/tzapp/hal-dha-headers.bb
@@ -0,0 +1,32 @@
+DESCRIPTION = "ACE headers recipe"
+SECTION = "ACE"
+LICENSE = "CLOSED"
+
+inherit workonsrc
+
+#The location in the Build Directory where unpacked recipe source code resides.
+WORKONSRC = "${TOPDIR}/../src/support/assistant-sdk/alexa/ace/sdk/include/ace"
+
+#The version of the recipe
+PV = "1.0"
+
+#The revision of the recipe
+PR = "r0"
+
+do_compile() {
+}
+
+# This will copy the header files and place it in ${includedir}
+do_install () {
+ if [ -e ${B}/ace_config.h -a \
+ -e ${B}/ace_status.h -a \
+ -e ${B}/hal_dha.h -a \
+ -e ${B}/hal_device_info.h ]; then
+ install -d ${D}${includedir}/ace
+ install -m 0644 ${B}/ace_config.h ${D}${includedir}/ace
+ install -m 0644 ${B}/ace_status.h ${D}${includedir}/ace
+ install -m 0644 ${B}/hal_dha.h ${D}${includedir}/ace
+ install -m 0644 ${B}/hal_device_info.h ${D}${includedir}/ace
+ fi
+}
+
diff --git a/meta/meta-mediatek/recipes-bsp/tzapp/tzapp-common.bb b/meta/meta-mediatek/recipes-bsp/tzapp/tzapp-common.bb
new file mode 100644
index 0000000..96da0e1
--- /dev/null
+++ b/meta/meta-mediatek/recipes-bsp/tzapp/tzapp-common.bb
@@ -0,0 +1,54 @@
+inherit deploy workonsrc
+
+DESCRIPTION = "MTK In-house TEE Userspace Library/Application"
+LICENSE = "MediaTekProprietary"
+WORKONSRC = "${TOPDIR}/../src/bsp/tzapp/common"
+LIC_FILES_CHKSUM = "file://uree/README;md5=5a126b0ba82af703f1c30cf8d0bb4e13"
+TZ_UREE_OUT = "${WORKDIR}/out"
+TZ_EFUSE_OUT = "${WORKDIR}/out"
+TZ_UREE_BINRARY_OUT = "${TZ_UREE_OUT}/binraies"
+TZ_EFUSE_BINRARY_OUT = "${TZ_EFUSE_OUT}/binraies"
+TZ_UREE_LIBRARY = "libtz_uree.so"
+TZ_EFUSE_LIBRARY = "libtz_efuse.so"
+
+# Avoid QA Issue: No GNU_HASH in the elf binary
+INSANE_SKIP_${PN} = "ldflags"
+INSANE_SKIP_${PN}-dev = "ldflags"
+FILES_${PN} = "${libdir}/${TZ_UREE_LIBRARY}"
+FILES_${PN} += "${libdir}/${TZ_EFUSE_LIBRARY}"
+FILES_${PN}-dev = "${includedir} \
+ ${includedir}/uree/system.h \
+ ${includedir}/uree/mem.h \
+ ${includedir}/uree/dbg.h \
+ ${includedir}/tz_cross/trustzone.h \
+ ${includedir}/tz_cross/tz_gcpu.h \
+ ${includedir}/efuse/efuse.h \
+ ${includedir}/tz_cross/ta_mem.h \
+ ${includedir}/tz_cross/ta_sbcv.h \
+ ${includedir}/image_verifier/img_vfy.h \
+ ${includedir}/secure_api/mtk_crypto_api_user.h "
+
+# Avoid QA Issue: 'Files/directories were installed but not shipped'
+INSANE_SKIP_${PN} += "installed-vs-shipped"
+DEPENDS += " openssl rpm-native "
+
+do_compile() {
+if [ -e uree/makefile ]; then
+ oe_runmake CFLAGS+=' -O2' -C uree CROSS_COMPILE=${TARGET_PREFIX} MTK_PROJECT=${MTK_PROJECT} TZ_UREE_OUT=${TZ_UREE_OUT} TZ_UREE_BINRARY_OUT=${TZ_UREE_BINRARY_OUT}
+fi
+if [ -e efuse/makefile ]; then
+ oe_runmake CFLAGS+=' -O2' -C efuse CROSS_COMPILE=${TARGET_PREFIX} TZ_EFUSE_OUT=${TZ_EFUSE_OUT} TZ_EFUSE_BINRARY_OUT=${TZ_EFUSE_BINRARY_OUT}
+fi
+}
+
+do_install() {
+ oe_runmake -C uree PREFIX="${prefix}" DESTDIR="${D}" PACKAGE_ARCH="${PACKAGE_ARCH}" TZ_UREE_BINRARY_OUT="${TZ_UREE_BINRARY_OUT}" install
+if ${@bb.utils.contains('TEE_SUPPORT','mtee','true','false',d)}; then
+ oe_runmake -C efuse PREFIX="${prefix}" DESTDIR="${D}" TZ_PROJECT=${TZ_PROJECT} TZ_PLATFORM=${TZ_PLATFORM} PACKAGE_ARCH="${PACKAGE_ARCH}" TZ_EFUSE_BINRARY_OUT="${TZ_EFUSE_BINRARY_OUT}" install
+fi
+}
+
+
+
+INSANE_SKIP_${PN} += "already-stripped"
+
diff --git a/meta/meta-mediatek/recipes-bsp/tzapp/tzapp.bb b/meta/meta-mediatek/recipes-bsp/tzapp/tzapp.bb
new file mode 100644
index 0000000..7eacc87
--- /dev/null
+++ b/meta/meta-mediatek/recipes-bsp/tzapp/tzapp.bb
@@ -0,0 +1,73 @@
+inherit deploy workonsrc
+
+DESCRIPTION = "MTK In-house TEE Userspace Library/Application"
+LICENSE = "MediaTekProprietary"
+WORKONSRC = "${TOPDIR}/../src/bsp/tzapp/external"
+LIC_FILES_CHKSUM = "file://uree/README;md5=5a126b0ba82af703f1c30cf8d0bb4e13"
+TZ_DRMKEY_OUT = "${WORKDIR}/out"
+TZ_IMGVFY_OUT = "${WORKDIR}/out"
+TZ_SECURE_API_OUT = "${WORKDIR}/out"
+TZ_SOFTHSM_OUT = "${WORKDIR}/out"
+TZ_DHAV2_OUT = "${WORKDIR}/out"
+TZ_DRMKEY_BINRARY_OUT = "${TZ_DRMKEY_OUT}/binraies"
+TZ_IMGVFY_BINRARY_OUT = "${TZ_IMGVFY_OUT}/binraies"
+TZ_SECURE_API_BINRARY_OUT = "${TZ_SECURE_API_OUT}/binraies"
+TZ_SOFTHSM_BINRARY_OUT = "${TZ_SOFTHSM_OUT}/binraies"
+TZ_DRMKEY_LIBRARY = "liburee_drmkey.so"
+TZ_DHAV2_BINARY_OUT = "${TZ_DHAV2_OUT}/binraies"
+TZ_IMGVFY_LIBRARY = "libimg_vfy.so"
+TZ_SECURE_API_LIBRARY = "libsecure_api.so"
+TZ_DHAV2_LIBRARY = "libacehal_dha.so"
+TZ_SECURE_PROGRAM = "secure_program"
+TZ_SOFTHSM_LIBRARY = "libsofthsm2.so"
+TZ_SOFTHSM_UTIL_BINARY = "softhsm2-util"
+
+# Avoid QA Issue: No GNU_HASH in the elf binary
+INSANE_SKIP_${PN} = "ldflags"
+INSANE_SKIP_${PN}-dev = "ldflags"
+FILES_${PN} = "${libdir}/${TZ_IMGVFY_LIBRARY}"
+FILES_${PN} += "${libdir}/${TZ_DRMKEY_LIBRARY}"
+FILES_${PN} += "${libdir}/${TZ_SECURE_API_LIBRARY}"
+FILES_${PN} += "${bindir}/${TZ_SECURE_PROGRAM}"
+FILES_${PN} += "${libdir}/${TZ_SOFTHSM_LIBRARY}"
+FILES_${PN} += "${bindir}/${TZ_SOFTHSM_UTIL_BINARY}"
+FILES_${PN} += "${libdir}/${TZ_DHAV2_LIBRARY}"
+FILES_${PN}-dev = "${includedir}/image_verifier/img_vfy.h \
+ ${includedir}/secure_api/mtk_crypto_api_user.h \
+ ${includedir}/softhsmv2/pkcs11/ "
+
+# Avoid QA Issue: 'Files/directories were installed but not shipped'
+INSANE_SKIP_${PN} += "installed-vs-shipped"
+DEPENDS += " openssl rpm-native tzapp-common"
+DEPENDS += " hal-dha-headers"
+
+do_compile() {
+if [ -e drmkey/makefile ]; then
+ oe_runmake CFLAGS+=' -O2' -C drmkey CROSS_COMPILE=${TARGET_PREFIX} MTK_PROJECT=${MTK_PROJECT} TZ_DRMKEY_OUT=${TZ_DRMKEY_OUT} TZ_DRMKEY_BINRARY_OUT=${TZ_DRMKEY_BINRARY_OUT}
+fi
+if [ -e image_verifier/makefile ]; then
+ oe_runmake CFLAGS+=' -O2 -I${TOPDIR}/../src/bsp/tzapp/common/include' -C image_verifier CROSS_COMPILE=${TARGET_PREFIX} MTK_PROJECT=${MTK_PROJECT} TZ_IMGVFY_OUT=${TZ_IMGVFY_OUT} TZ_IMGVFY_BINRARY_OUT=${TZ_IMGVFY_BINRARY_OUT}
+fi
+if [ -e secure_api/makefile ]; then
+ oe_runmake CFLAGS+=' -O2 -I${TOPDIR}/../src/bsp/tzapp/common/include' -C secure_api CROSS_COMPILE=${TARGET_PREFIX} MTK_PROJECT=${MTK_PROJECT} TZ_SECURE_API_OUT=${TZ_SECURE_API_OUT} TZ_PLATFORM=${TZ_PLATFORM} TZ_SECURE_API_BINRARY_OUT=${TZ_SECURE_API_BINRARY_OUT}
+fi
+if [ -e softhsmv2/makefile ]; then
+ oe_runmake CFLAGS+=' -O2 -I${TOPDIR}/../src/bsp/tzapp/common/include' -C softhsmv2 CROSS_COMPILE=${TARGET_PREFIX} MTK_PROJECT=${MTK_PROJECT} TZ_SOFTHSM_OUT=${TZ_SOFTHSM_OUT} TZ_PLATFORM=${TZ_PLATFORM} TZ_SOFTHSM_BINRARY_OUT=${TZ_SOFTHSM_BINRARY_OUT} all
+fi
+if [ -e dhav2/makefile -a -e ${WORKDIR}/recipe-sysroot/${includedir}/ace ]; then
+ oe_runmake CFLAGS+=' -O2' -C dhav2 CROSS_COMPILE=${TARGET_PREFIX} MTK_PROJECT=${MTK_PROJECT} TZ_DHAV2_OUT=${TZ_DHAV2_OUT} TZ_PLATFORM=${TZ_PLATFORM} TZ_DHAV2_BINARY_OUT=${TZ_DHAV2_BINARY_OUT} VA_SUPPORT_ALEXA_FFS="${VA_SUPPORT_ALEXA_FFS}" all
+fi
+}
+
+do_install() {
+ oe_runmake -C drmkey PREFIX="${prefix}" DESTDIR="${D}" PACKAGE_ARCH="${PACKAGE_ARCH}" TZ_DRMKEY_BINRARY_OUT="${TZ_DRMKEY_BINRARY_OUT}" install
+ oe_runmake -C image_verifier PREFIX="${prefix}" DESTDIR="${D}" PACKAGE_ARCH="${PACKAGE_ARCH}" TZ_IMGVFY_BINRARY_OUT="${TZ_IMGVFY_BINRARY_OUT}" install
+ oe_runmake -C secure_api PREFIX="${prefix}" DESTDIR="${D}" PACKAGE_ARCH="${PACKAGE_ARCH}" TZ_SECURE_API_BINRARY_OUT="${TZ_SECURE_API_BINRARY_OUT}" install
+ oe_runmake -C softhsmv2 PREFIX="${prefix}" DESTDIR="${D}" PACKAGE_ARCH="${PACKAGE_ARCH}" TZ_SOFTHSM_BINRARY_OUT="${TZ_SOFTHSM_BINRARY_OUT}" install
+ oe_runmake -C dhav2 PREFIX="${prefix}" DESTDIR="${D}" PACKAGE_ARCH="${PACKAGE_ARCH}" TZ_DHAV2_BINARY_OUT="${TZ_DHAV2_BINARY_OUT}" VA_SUPPORT_ALEXA_FFS="${VA_SUPPORT_ALEXA_FFS}" install
+}
+
+
+
+INSANE_SKIP_${PN} += "already-stripped"
+
diff --git a/meta/meta-mediatek/recipes-bsp/u-boot/files/u-boot.dts b/meta/meta-mediatek/recipes-bsp/u-boot/files/u-boot.dts
new file mode 100644
index 0000000..7b1b06f
--- /dev/null
+++ b/meta/meta-mediatek/recipes-bsp/u-boot/files/u-boot.dts
@@ -0,0 +1,12 @@
+/dts-v1/;
+/ {
+ model = "Keys";
+ compatible = "mediatek,auto2701evb2-ivi";
+ signature {
+ key-dev {
+ required = "conf";
+ algo = "sha256,rsa2048";
+ key-name-hint = "dev";
+ };
+ };
+};
diff --git a/meta/meta-mediatek/recipes-bsp/u-boot/u-boot-201711.bb b/meta/meta-mediatek/recipes-bsp/u-boot/u-boot-201711.bb
new file mode 100644
index 0000000..e762ee1
--- /dev/null
+++ b/meta/meta-mediatek/recipes-bsp/u-boot/u-boot-201711.bb
@@ -0,0 +1,50 @@
+inherit deploy u-boot-fitimage
+
+UBOOT_SRC = "${TOPDIR}/../src/bsp/u-boot"
+UBOOT_OUT = "${WORKDIR}/out"
+LIC_FILES_CHKSUM = "file://${UBOOT_SRC}/Licenses/README;md5=025bf9f768cbcb1a165dbe1a110babfb"
+SRC_URI = "file://u-boot.dts "
+TOOLCHAIN = "gcc"
+SECTION = "bootloaders"
+PROVIDES = "virtual/bootloader"
+DEPENDS += "bc-native dtc-native"
+
+LICENSE = "GPLv2+"
+
+PACKAGE_ARCH = "${MACHINE_ARCH}"
+
+PROJECT = "mtk"
+
+# Some versions of u-boot use .bin and others use .img. By default use .bin
+# but enable individual recipes to change this value.
+UBOOT_SUFFIX ??= "bin"
+UBOOT_IMAGE ?= "u-boot-${PROJECT}.${UBOOT_SUFFIX}"
+UBOOT_BINARY ?= "u-boot.${UBOOT_SUFFIX}"
+UBOOT_FIT_IMAGE ?= "u-boot-mtk-fit.${UBOOT_SUFFIX}"
+UBOOT_MAKE_TARGET ?= "all"
+UBOOT_FIT_LOADADDRESS ?="0x44e00000"
+CONFIG_UBOOT_ARCH ?="arm"
+EXTRA_OEMAKE = "${@bb.utils.contains('CONFIG_UBOOT_ARCH', 'arm64', 'CROSS_COMPILE="${TARGET_PREFIX}" CC="${CC}" KBUILD_OUTPUT="${UBOOT_OUT}" STRIP=true V=1', 'CROSS_COMPILE="${TARGET_PREFIX}" KBUILD_OUTPUT="${UBOOT_OUT}" STRIP=true V=1', d)}"
+
+python __anonymous () {
+ tee_loadaddress = int(d.getVar('UBOOT_FIT_LOADADDRESS', True), 16)
+ dtb_loadaddress = tee_loadaddress - 0x10000
+ dtb_loadaddress_str = hex(dtb_loadaddress).replace('L', '')
+ d.setVar('UBOOT_DTB_LOADADDRESS', dtb_loadaddress_str)
+}
+
+do_compile () {
+ cd ${UBOOT_SRC}
+ oe_runmake mrproper
+ oe_runmake ${UBOOT_BUILD_DEFCONFIG}
+ oe_runmake -f Makefile
+}
+
+do_deploy () {
+ install -d ${DEPLOYDIR}
+ install -m 755 ${UBOOT_OUT}/${UBOOT_BINARY} -t ${DEPLOYDIR}
+ install -m 755 ${UBOOT_OUT}/${UBOOT_FIT_IMAGE} -t ${DEPLOYDIR}
+}
+
+addtask deploy before do_build after do_assemble_fitimage
+
diff --git a/meta/meta-mediatek/recipes-bsp/u-boot/u-boot-upstream.bb b/meta/meta-mediatek/recipes-bsp/u-boot/u-boot-upstream.bb
new file mode 100644
index 0000000..a721828
--- /dev/null
+++ b/meta/meta-mediatek/recipes-bsp/u-boot/u-boot-upstream.bb
@@ -0,0 +1,50 @@
+inherit deploy u-boot-fitimage
+
+UBOOT_SRC = "${TOPDIR}/../src/bsp/u-boot"
+UBOOT_OUT = "${WORKDIR}/out"
+LIC_FILES_CHKSUM = "file://${UBOOT_SRC}/Licenses/README;md5=025bf9f768cbcb1a165dbe1a110babfb"
+SRC_URI = "file://u-boot.dts "
+
+SECTION = "bootloaders"
+PROVIDES = "virtual/bootloader"
+DEPENDS += "bc-native dtc-native"
+
+LICENSE = "GPLv2+"
+
+PACKAGE_ARCH = "${MACHINE_ARCH}"
+
+PROJECT = "mtk"
+
+# Some versions of u-boot use .bin and others use .img. By default use .bin
+# but enable individual recipes to change this value.
+UBOOT_SUFFIX ??= "bin"
+UBOOT_IMAGE ?= "u-boot-${PROJECT}.${UBOOT_SUFFIX}"
+UBOOT_BINARY ?= "u-boot.${UBOOT_SUFFIX}"
+UBOOT_FIT_IMAGE ?= "u-boot-mtk-fit.${UBOOT_SUFFIX}"
+UBOOT_MAKE_TARGET ?= "all"
+UBOOT_FIT_LOADADDRESS ?="0x44e00000"
+
+EXTRA_OEMAKE = 'CROSS_COMPILE="${TARGET_PREFIX}" KBUILD_OUTPUT="${UBOOT_OUT}" STRIP=true V=1'
+
+python __anonymous () {
+ tee_loadaddress = int(d.getVar('UBOOT_FIT_LOADADDRESS', True), 16)
+ dtb_loadaddress = tee_loadaddress - 0x10000
+ dtb_loadaddress_str = hex(dtb_loadaddress).replace('L', '')
+ d.setVar('UBOOT_DTB_LOADADDRESS', dtb_loadaddress_str)
+}
+
+do_compile () {
+ cd ${UBOOT_SRC}
+ oe_runmake mrproper
+ oe_runmake ${UBOOT_BUILD_DEFCONFIG}
+ oe_runmake -f Makefile
+}
+
+do_deploy () {
+ install -d ${DEPLOYDIR}
+ install -m 755 ${UBOOT_OUT}/${UBOOT_BINARY} -t ${DEPLOYDIR}
+ install -m 755 ${UBOOT_OUT}/${UBOOT_FIT_IMAGE} -t ${DEPLOYDIR}
+}
+
+addtask deploy before do_build after do_assemble_fitimage
+
diff --git a/meta/meta-mediatek/recipes-bsp/upgrade_app/upgrade_app.bb b/meta/meta-mediatek/recipes-bsp/upgrade_app/upgrade_app.bb
new file mode 100644
index 0000000..0c03d58
--- /dev/null
+++ b/meta/meta-mediatek/recipes-bsp/upgrade_app/upgrade_app.bb
@@ -0,0 +1,39 @@
+inherit externalsrc
+
+DESCRIPTION = "mediatek update image demo"
+LICENSE = "MediaTekProprietary"
+DEPENDS += "libdrm curl android-tools-fsutils zlib"
+MTK_SRC = "${TOPDIR}/../src/multimedia/mtk-demo-app/upgrade_app"
+#LIC_FILES_CHKSUM = "file://LICENSE;md5=e1696b147d49d491bcb4da1a57173fff"
+PN='upgrade_app'
+
+INSANE_SKIP_${PN} +="installed-vs-shipped"
+
+S="${WORKDIR}"
+
+inherit workonsrc
+WORKONSRC = "${TOPDIR}/../src/multimedia/mtk-demo-app/upgrade_app"
+
+inherit pkgconfig
+inherit systemd
+
+SYSTEMD_PACKAGES = "${PN}"
+SYSTEMD_SERVICE_${PN} = "upgrade_app.service"
+FILES_${PN} += "${systemd_unitdir}/system/upgrade_app.service"
+
+do_compile() {
+ oe_runmake \
+ CFLAGS=" -lpthread ${CFLAGS}" \
+ LDFLAGS="-Wl,--whole-archive -lsparse -Wl,--no-whole-archive -lz -ldrm -lstdc++ -lpthread -lm -lcurl ${LDFLAGS}" \
+ BOOTDEV_TYPE=${BOOTDEV_TYPE}
+}
+
+do_install(){
+ oe_runmake \
+ PREFIX="${PREFIX}" DESTDIR="${D}" install
+}
+
+do_install_append() {
+ install -d ${D}${systemd_unitdir}/system
+ install -m 0755 ${TOPDIR}/../meta/meta-mediatek/recipes-bsp/upgrade_app/upgrade_app.service ${D}${systemd_unitdir}/system
+}
diff --git a/meta/meta-mediatek/recipes-bsp/upgrade_app/upgrade_app.service b/meta/meta-mediatek/recipes-bsp/upgrade_app/upgrade_app.service
new file mode 100644
index 0000000..05c2405
--- /dev/null
+++ b/meta/meta-mediatek/recipes-bsp/upgrade_app/upgrade_app.service
@@ -0,0 +1,10 @@
+[Unit]
+Description=upgrade_app
+
+[Service]
+ExecStart=/bin/upgrade_app
+Type=simple
+
+[Install]
+Alias=upgrade
+WantedBy=multi-user.target
\ No newline at end of file
diff --git a/meta/meta-mediatek/recipes-connectivity/agps/agps.bb b/meta/meta-mediatek/recipes-connectivity/agps/agps.bb
new file mode 100755
index 0000000..b0cf250
--- /dev/null
+++ b/meta/meta-mediatek/recipes-connectivity/agps/agps.bb
@@ -0,0 +1,43 @@
+DESCRIPTION = "MTK AGPS Daemon"
+LICENSE = "MediaTekProprietary"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=e1696b147d49d491bcb4da1a57173fff"
+FILESEXTRAPATHS_append := ":${THISDIR}/files"
+
+inherit workonsrc
+WORKONSRC = "${TOPDIR}/../src/connectivity/agps"
+SRC_URI = "file://agps_profiles_conf2.xml"
+
+DEPENDS += "openssl platform-libs libsncfg"
+TARGET_CC_ARCH += "${LDFLAGS}"
+EXTRA_OEMAKE = "'BB_SYSROOT_ADD=${STAGING_DIR_HOST}'"
+LDFLAGS += "-lsncfg"
+
+INSANE_SKIP_${PN} += "already-stripped"
+
+FILES_${PN} += "${bindir}/mtk_agpsd"
+FILES_${PN} += "${bindir}/mtk_lbs_em_tool"
+FILES_${PN} += "${datadir}/agps/agps_profiles_conf2.xml"
+FILES_${PN} += "/data/agps_supl/"
+
+do_install() {
+ oe_runmake PREFIX="${prefix}" DESTDIR="${D}" install
+}
+
+inherit systemd
+
+SYSTEMD_PACKAGES = "${PN}"
+SYSTEMD_SERVICE_${PN} = "agps.service"
+FILES_${PN} += "${systemd_unitdir}/system/agps.service /system/etc/security/"
+
+do_install_append() {
+ install -d ${D}${datadir}/agps
+ install -m 0664 ${WORKDIR}/agps_profiles_conf2.xml ${D}${datadir}/agps
+ if ${@bb.utils.contains('DISTRO_FEATURES','systemd','true','false',d)}; then
+ install -d ${D}${systemd_unitdir}/system/
+ install -m 0644 ${B}/lib/systemd/system/agps.service ${D}${systemd_unitdir}/system
+ fi
+ install -d ${D}/system
+ install -d ${D}/system/etc
+ install -d ${D}/system/etc/security
+ cp -rf ${TOPDIR}/../meta/meta-mediatek/recipes-connectivity/agps/files/cacerts ${D}/system/etc/security
+}
diff --git a/meta/meta-mediatek/recipes-connectivity/agps/files/agps_profiles_conf2.xml b/meta/meta-mediatek/recipes-connectivity/agps/files/agps_profiles_conf2.xml
new file mode 100644
index 0000000..10ad791
--- /dev/null
+++ b/meta/meta-mediatek/recipes-connectivity/agps/files/agps_profiles_conf2.xml
@@ -0,0 +1,861 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<mtk_agps_profiles maj_ver="1" min_ver="2">
+
+ <!-- cur_supl_profile and supl_profile
+
+ name:
+ SLP name will be displayed on LocatioEM2 - SLP Template list
+
+ addr:
+ SLP address
+
+ port:
+ SLP port
+
+ tls:
+ enable/disable TLS connection
+ available value: true (default), false
+
+ ===== load SLP profile automatically based on PLMN =====
+ mcc (optional):
+ auto configure the supl_profile if the current MCC on DUT are the same as mcc parameter you specified and auto_profile_enable is enabled
+
+ mcc_mnc (optional):
+ auto configure the supl_profile if the current MCC and MNC on DUT are the same as mcc_mnc paramter you specified and auto_profile_enable is enabled
+
+ supl_version (optional):
+ auto configure supl_version if above mcc_mnc condition is met
+ available value: 1 -> SUPL1.0 (default)
+ available value: 2 -> SUPL2.0
+
+ tls_version (optional):
+ auto configure tls_version if above mcc_mnc condition is met
+ available value: 0 -> TLS1.0 (default)
+ available value: 1 -> TLS1.1
+ available value: 2 -> TLS1.2
+
+ sha_version (optional):
+ auto configure sha_version if above mcc_mnc condition is met
+ available value: 0 -> SHA1 for SUPL1.0 and SHA256 for SUPL2.0 (default)
+ available value: 1 -> SHA1 for SUPL1.0 and SUPL2.0
+ available value: 2 -> SHA256 for SUPL1.0 and SUPL2.0
+
+ supl_ver_minor (optional):
+ auto configure the minor of supl_version if above mcc_mnc condition is met
+ available value: 0~255, default value is 0
+
+ supl_ver_ser_ind (optional):
+ auto configure the service indicator of supl_version if above mcc_mnc condition is met
+ available value: 0~255, default value is 0
+
+ esupl_apn_mode:
+ how to choose APN for eSUPL
+ available value: 0 to use Emergency / IMS APN if they are available as GSMA IR92 (default)
+ 1 to use Emergency APN if it is available
+ 2 to use IMS APN if it is available
+ 3 not to use Emergency / IMS APN, just as a normal supl
+
+ ===== other parameters are used for DM =====
+ app_id (optional):
+ "ap0004"
+
+ provider_id (optional):
+ "221.176.0.55"
+
+ default_apn (optional):
+ "XXX WAP"
+
+ optional_apn (optional):
+ "internet"
+
+ optional_apn_2 (optional):
+ ""
+
+ address_type (optional):
+ "IPv4address:port"
+ -->
+
+ <cur_supl_profile name="GOOGLE"
+ addr="supl.google.com"
+ port="7275"
+ tls="true"
+ />
+
+ <!-- GOOGLE-->
+ <supl_profile name="GOOGLE"
+ addr="supl.google.com"
+ port="7275"
+ tls="true"
+ />
+
+ <!-- GOOGLE-->
+ <supl_profile name="GOOGLE nonTLS"
+ addr="supl.google.com"
+ port="7276"
+ tls="false"
+ />
+
+ <!-- GOOGLE-->
+ <supl_profile name="GOOGLE IP"
+ addr="74.125.204.192"
+ port="7276"
+ tls="false"
+ />
+
+ <!-- Spirent Lab -->
+ <supl_profile name="SpirentLcs"
+ addr="www.spirent-lcs.com"
+ port="7275"
+ tls="true"
+ />
+
+ <!-- Spirent Lab Operator Test Cases -->
+ <supl_profile name="Spirent"
+ addr="www.spirent.com"
+ port="7275"
+ tls="true"
+ />
+
+ <!-- R&S Lab -->
+ <supl_profile name="RnS"
+ addr="slp.rs.de"
+ port="7275"
+ tls="true"
+ />
+
+ <!-- CMCC Lab -->
+ <supl_profile name="CMCC Lab"
+ addr="218.206.176.50"
+ port="7275"
+ tls="true"
+ />
+
+ <!-- Andrew Lab -->
+ <supl_profile name="Andrew"
+ addr="slp1acva.andrew.com"
+ port="7275"
+ tls="true"
+ />
+
+ <!-- Ericsson Lab -->
+ <supl_profile name="Ericsson"
+ addr="172.22.1.100"
+ port="7275"
+ tls="true"
+ />
+
+ <!-- Ericsson Lab FQDN -->
+ <supl_profile name="Ericsson FQDN"
+ addr="mvtvltegmpc.naladmz.ericsson.ca"
+ port="7275"
+ tls="true"
+ />
+
+ <!-- Ericsson Lab FQDN 2 -->
+ <supl_profile name="Ericsson FQDN 2"
+ addr="mvtv-broadcom.naladmz.ericsson.ca"
+ port="7275"
+ tls="true"
+ />
+
+ <!-- Ericsson Lab FQDN 3 -->
+ <supl_profile name="Ericsson FQDN TW"
+ addr="gmpc01.ert.ericsson.se"
+ port="7275"
+ tls="true"
+ />
+
+ <!-- Ericsson Lab FQDN 4 -->
+ <supl_profile name="Ericsson FQDN TW 2"
+ addr="gmpc03GIC.ericsson.ca"
+ port="7275"
+ tls="true"
+ />
+
+ <!-- ORANGE -->
+ <supl_profile name="ORANGE"
+ addr="agpss.orange.fr"
+ port="7275"
+ tls="true"
+ />
+
+ <!-- CMCC-->
+ <supl_profile name="CMCC"
+ addr="221.176.0.55"
+ port="7275"
+ tls="true"
+ app_id="ap0004"
+ provider_id="221.176.0.55"
+ default_apn="CMCC WAP"
+ optional_apn="CMNET"
+ optional_apn_2=""
+ address_type="IPv4address:port"
+ />
+
+ <!-- qxwz: China Public Server on Internet -->
+ <supl_profile name="qxwz"
+ addr="supl.qxwz.com"
+ port="7275"
+ tls="true"
+ />
+
+ <!-- Telstra -->
+ <supl_profile name="Telstra"
+ addr="agps.supl.telstra.com"
+ port="7275"
+ tls="true"
+ />
+
+ <!-- CHUAN HWA -->
+ <supl_profile name="Chunghwa"
+ addr="10.1.101.137"
+ port="8025"
+ tls="false"
+ />
+
+ <!-- T-Mobile -->
+ <supl_profile name="T-Mobile LBS"
+ addr="lbs.geo.t-mobile.com"
+ port="7275"
+ tls="true"
+ />
+
+ <!-- T-Mobile for UE with SHA2 -->
+ <supl_profile name="T-Mobile SUPL"
+ addr="supl.geo.t-mobile.com"
+ port="7275"
+ tls="true"
+ />
+
+ <!-- T-Mobile for LPP Test -->
+ <supl_profile name="T-Mobile LAB"
+ addr="supl.geo.msg.lab.t-mobile.com"
+ port="7275"
+ tls="true"
+ />
+
+ <!-- KDDI for Enterprise Device: Live Network -->
+ <supl_profile name="KDDI"
+ addr="lcs-iot.kddi.ne.jp"
+ port="7275"
+ tls="true"
+ />
+
+ <!-- KDDI for Enterprise Device: Lab Test -->
+ <supl_profile name="KDDI Lab Test"
+ addr="lcs-iot-test.kddi.ne.jp"
+ port="7275"
+ tls="true"
+ />
+
+ <!-- KDDI for Consumer Device: Live Network and Lab Test -->
+ <supl_profile name="KDDI Consumer"
+ addr="location2.kddi.ne.jp"
+ port="7275"
+ tls="true"
+ />
+
+ <!-- Vodafone -->
+ <supl_profile name="Vodafone"
+ addr="supl.vodafone.com"
+ port="7275"
+ tls="true"
+ mcc_mnc="22010"
+ supl_version="2"
+ tls_version="1"
+ sha_version="0"
+ />
+
+ <!-- Iusacell (ATT Mexico) -->
+ <supl_profile name="Iusacell (ATT Mexico)"
+ addr="supl.iusacell.com"
+ port="7275"
+ tls="true"
+ mcc_mnc="334050"
+ supl_version="2"
+ tls_version="1"
+ sha_version="0"
+ />
+
+ <!-- NEXTEL (ATT Mexico) -->
+ <supl_profile name="NEXTEL (ATT Mexico)"
+ addr="supl.iusacell.com"
+ port="7275"
+ tls="true"
+ mcc_mnc="334090"
+ supl_version="2"
+ tls_version="1"
+ sha_version="0"
+ />
+
+ <!-- Sprint Lab Test -->
+ <supl_profile name="Sprint Lab Test"
+ addr="supl1.lbs.pcslab.com"
+ port="7275"
+ tls="true"
+ />
+
+ <!-- Sprint for Production -->
+ <supl_profile name="Sprint"
+ addr="supl.lbs.sprint.com"
+ port="7275"
+ tls="true"
+ />
+
+ <!-- Sprint for Production 2019 -->
+ <supl_profile name="Sprint2019"
+ addr="supl2019.lbs.sprint.com"
+ port="7275"
+ tls="true"
+ />
+
+ <!-- Test 1 -->
+ <supl_profile name="Test 1"
+ addr="127.0.0.1"
+ port="7276"
+ tls="false"
+ mcc_mnc="999998"
+ supl_version="1"
+ tls_version="0"
+ sha_version="2"
+ supl_ver_minor="4"
+ supl_ver_ser_ind="2"
+ />
+
+ <!-- Test 2 -->
+ <supl_profile name="Test 2"
+ addr="127.0.0.1"
+ port="7276"
+ tls="false"
+ mcc_mnc="999999"
+ supl_version="2"
+ tls_version="1"
+ sha_version="0"
+ />
+
+ <!-- Test 3 -->
+ <supl_profile name="Test 3"
+ addr="127.0.0.1"
+ port="7276"
+ tls="false"
+ mcc="998"
+ supl_version="1"
+ tls_version="2"
+ sha_version="1"
+ />
+
+ <!-- nlp_profile
+
+ name:
+ NLP vendor name
+
+ package_name:
+ NLP apk package name
+ -->
+ <nlp_profile name="Baidu"
+ package_name="com.baidu.map.location"
+ />
+
+ <!-- cdma_profile
+
+ name:
+ SLP name
+
+ mcp_enable:
+ enable/disable MCP parameters
+ available value: true, false (default)
+
+ mcp_addr:
+ MCP address
+
+ mcp_port:
+ MCP port
+
+ pde_addr_valid:
+ PDE address is valid or invalid
+ available value: true, false (default)
+
+ pde_ip_type:
+ PDE's address type
+ available value: 0 -> IPv4 (default)
+ available value: 1 -> IPv6
+
+ pde_addr:
+ PDE IP address
+
+ pde_port:
+ PDE port
+
+ pde_url_valid:
+ PDE URL is valid or invalid
+ available value: true, false (default)
+
+ pde_url_addr:
+ PDE URL
+ -->
+
+ <!-- CDMA profile template -->
+ <cdma_profile name="CDMA1"
+ mcp_enable="true"
+ mcp_addr="10.199.22.165"
+ mcp_port="6066"
+ pde_addr_valid="false"
+ pde_ip_type="0"
+ pde_addr="11.11.11.11"
+ pde_port="1111"
+ pde_url_valid="false"
+ pde_url_addr="www.mediatek.com"
+ />
+
+
+ <!-- agps_setting
+
+ agps_enable:
+ enable/disable A-GPS
+ available value: true (default), false
+
+ agps_protocol:
+ choose which A-GPS you want to use for SET Initiated
+ available value: 0 -> User Plane (default)
+ available value: 1 -> Control Plane
+
+ gpevt:
+ enable/disable GPEVT report
+ available value: true, false (default)
+
+ e911_gps_icon_enable:
+ enable/disable showing GPS icon during E911 location
+ available value: true (default), false
+
+ e911_open_gps:
+ enable/disable opening GPS earlier when E911 call is dialed
+
+ tc10_ignore_fw_config:
+ enable/disable TC10's configuration from FWK
+ available value: true, false (default)
+
+ lppe_network_location_disable:
+ enable/disable LPPe's crowd source location (ex: network location)
+ available value: true, false (default)
+
+ agps_nvram_enable
+ enable/disable AGPS NVRAM functionality
+ available value: true (default), false
+
+ lbs_log_enable
+ enable/disable tc10 lbs log to the debugging port
+ available value: true (default), false
+
+ lppe_crowd_source_confident
+ determine how confident you would like to fill in LPPe HA3D Position for crowd source location
+ available value: 0~99, 90 is default
+
+ ignore_si_for_e911:
+ ignore MOLR / SI for Emergency Call (For northern america operators)
+ available value: true, false (default)
+
+ -->
+ <agps_setting
+ agps_enable="true"
+ agps_protocol="0"
+ gpevt="false"
+ e911_gps_icon_enable="false"
+ e911_open_gps="false"
+ tc10_ignore_fw_config="false"
+ lppe_network_location_disable="false"
+ agps_nvram_enable="true"
+ lbs_log_enable="false"
+ lppe_crowd_source_confident="90"
+ ignore_si_for_e911="false"
+ />
+
+
+ <!-- gnss_setting
+
+ sib8_16_enable:
+ enable/disable SIB8/SIB16
+ available value: true (default), false
+
+ a_glonass_satellite_enable:
+ enable/disable Glonass aiding if hardware can support A-Glonass
+ available value: true (default), false
+
+ a_beidou_satellite_enable:
+ enable/disable Beidou aiding if hardware can support A-Beidou
+ available value: true, false (default)
+
+ a_galileo__satellite_enable:
+ enable/disable Galileo aiding if hardware can support A-Galileo
+ available value: true, false (default)
+
+ -->
+ <gnss_setting
+ sib8_16_enable="true"
+ a_glonass_satellite_enable="true"
+ a_beidou_satellite_enable="false"
+ a_galileo_satellite_enable="false"
+ />
+
+ <!-- cp_setting
+
+ molr_pos_method:
+ available value: 0 (Location Estimate) (default)
+ available value: 1 (Assistance Data)
+
+ external_addr_enable:
+ enable/disable the external address
+ available value: true, false (default)
+
+ external_addr:
+ external_address
+
+ mlc_number_enable:
+ enable/disable the mlc number
+ available value: true, false (default)
+
+ mlc_number:
+ MLC number
+
+ cp_auto_reset:
+ enable/disable to send PMTK997_5
+ available value: true, false (default)
+
+ epc_molr_lpp_payload_enable:
+ enable/disable to send LPP payload in the EPC-MOLR message
+ available value: true, false (default)
+
+ epc_molr_lpp_payload:
+ specify the LPP payload in the EPC-MOLR message in hexString format (ex: "010203ff" = { 0x01, 0x02, 0x03, 0xff }
+ the purpose of this parameter is used for LAB testing only, please do not change it.
+
+ reject_non911_nilr_enable:
+ enable/disable to reject non911 NILR request
+ available value: true, false (default)
+
+ cp_2g_disable:
+ enable/disable CP GSM functionality (tc10 requirement)
+ available value: true, false (default)
+
+ cp_3g_disable:
+ enable/disable CP UMTS functionality (tc10 requirement)
+ available value: true, false (default)
+
+ cp_4g_disable:
+ enable/disable CP LTE functionality (tc10 requirement)
+ available value: true, false (default)
+
+ cp_lppe_enable:
+ enable/disable CP LPPe functionality
+ available value: true (default), false
+
+ cp_lppe_wlan_enable:
+ enable/disable CP LPPe Wireless LAN part functionality (tc1 requirement)
+ available value: true (default), false
+
+ cp_lppe_srn_enable:
+ enable/disable CP LPPe srn (e.g., Bluetooth or BluetoothLE) part functionality (tc1 requirement)
+ available value: true (default), false
+
+ cp_lppe_sensor_enable:
+ enable/disable CP LPPe sensor (e.g., Barometers) part functionality (tc1 requirement)
+ available value: true (default), false
+
+ cp_lppe_dbh_enable:
+ enable/disable CP LPPe Device Based Hybrid functionality (tc1 requirement)
+ available value: true (default), false
+ -->
+ <cp_setting
+ molr_pos_method="0"
+ external_addr_enable="false"
+ external_addr="0123456789*#+"
+ mlc_number_enable="false"
+ mlc_number="0123456789*#+"
+ cp_auto_reset="false"
+ epc_molr_lpp_payload_enable="false"
+ epc_molr_lpp_payload="D2000010237B2026404FB8007202BFFFFFFFF80000000020C0000100940FB9001202B7FFFFF8000000000061800002018A00"
+ reject_non911_nilr_enable="false"
+ cp_2g_disable="false"
+ cp_3g_disable="false"
+ cp_4g_disable="false"
+ cp_lppe_enable="true"
+ cp_lppe_wlan_enable="true"
+ cp_lppe_srn_enable="true"
+ cp_lppe_sensor_enable="true"
+ cp_lppe_dbh_enable="true"
+ />
+
+ <!-- up_setting
+
+ ca_enable:
+ enable/disable the certificate verification
+ available value: true, false (default)
+
+ ni_request:
+ enable/disable Network Initiated (NI) functionality
+ available value: true (default), false
+
+ roaming:
+ enable/disable to use A-GPS when device is under roaming state
+ available value: true (default), false
+
+ cdma_preferred:
+ when CDMA network and WCDMA network are available, which AGPS protocol you prefer?
+ available value: 0 (WCDMA AGPS protocol is preferred) (default)
+ available value: 2 (FORCE CDMA AGPS protocol)
+
+ pref_method:
+ the preferred method in SUPL_START and SUPL_POS_INIT
+ available value: 0 -> SET assisted Preferred
+ available value: 1 -> SET Based Preferred (default)
+ available value: 2 -> no Preference
+
+ supl_version:
+ Major of SUPL version for ULP
+ available value: 1 -> SUPL1.0 (default)
+ available value: 2 -> SUPL2.0
+
+ tls_version:
+ TLS version for TLS connection
+ available value: 0 -> TLS1.0 (default)
+ available value: 1 -> TLS1.1
+ available value: 2 -> TLS1.2
+
+ sha_version:
+ SHA version for calculating VER
+ available value: 0 -> SHA1 for SUPL1.0 and SHA256 for SUPL2.0 (default)
+ available value: 1 -> SHA1 for SUPL1.0 and SUPL2.0
+ available value: 2 -> SHA256 for SUPL1.0 and SUPL2.0
+
+ supl_log:
+ enable or disable the AGPS log
+ available value: true, false (default)
+
+ msa_enable:
+ enable/disable the MSA capability
+ available value: true (default), false
+
+ msb_enable:
+ enable/disable the MSB capability
+ available value: true (default), false
+
+ ecid_enable:
+ enable/disable the eCID capability
+ available value: true (default), false
+
+ autonomous_enable:
+ enable/disable the Autonomous capability
+ available value: true (default), false
+
+ aflt_enable:
+ enable/disable the AFLT capability
+ available value: true, false (default)
+
+ udp_port_enable:
+ enable/disable the UDP 7275 port by default, if you enable it, you may cause Android/CTS failure for checking netstat
+ available value: true, false (default)
+
+ dedicated_apn_enable:
+ enable/disable the dedicated SUPL APN flow
+ available value: true, false (default)
+
+ preferred_2g3g_cell_age:
+ max age of 2G / 3G cell info in history is OK to send to SLP server instead if the latest cell is of 3G or 4G.
+ available value: non-negative integer, from 0 ~ 1800, unit in second
+ 0 (always use the latest cell info)
+ 300 (prefer to use 2G / 3G cell if its age is less than 5 mins)
+
+ lpp_enable:
+ enable/disable the LPP capability
+ available value: true (default), false
+
+ cert_from_sdcard:
+ enable/disable the AGPS certification installation from the internal SDCard (~ Android 8)
+ or from "/vendor/etc/security/cacerts_supl/lab" (Android 9 does not allow vendor modules accessing the internal SDCard).
+ Please use "false" for Android 9 and laters because the lab root certs are not secure (they may be issued by a
+ non-trusted CA or their related private keys may be public).
+ And enable this option for lab test by using Engineering Mode Utility
+ available value: true (default), false
+
+ auto_profile_enable:
+ enable/disable the auto profile configuration based on current mcc or mcc_mnc specified in cur_supl_profile or supl_profile
+ available value: true (default), false
+
+ ut1:
+ customize the SUPL UT1 timer
+ available value: 1~60, default value is 11 (OMA spec)
+
+ ut2:
+ customize the SUPL UT2 timer
+ available value: 1~60, default value is 11 (OMA spec)
+
+ ut3:
+ customize the SUPL UT3 timer
+ available value: 1~60, default value is 10 (OMA spec)
+
+ sync_to_slp:
+ sync the AGPS setting (ex: SUPL profile, SUPL version, TLS version) from AGPSD to SLPD in runtime
+ available value: true, false (default)
+
+ imsi_enable:
+ enable/disable the valid IMSI in SUPL messages
+ available value: true (default), false
+
+ no_sensitive_log:
+ remove/allow agps daemon's log with sensitive info (e.g., the current location)
+ available value: true, false (default)
+
+ supl_ver_minor:
+ Minor of SUPL version for ULP
+ available value: 0~255, default value is 0
+ choosable value in LocationEM: 0~5
+
+ supl_ver_ser_ind:
+ Service Indicator of SUPL version for ULP
+ available value: 0~255, default value is 0
+ choosable value in LocationEM: 0~5
+
+ tls_reuse_enable:
+ enable/disable tls session reuse mode
+ available value: true, false (default)
+
+ imsi_cache_enable:
+ enable/disable the IMSI cache mechanism
+ available value: true, false (default)
+ supl_raw_data_enable:
+
+ enable/disable SUPL raw data dump to main log (logcat)
+ available value: true, false (default)
+
+ allow_ni_for_gps_off:
+ allow NI request when GPS is off in location setting
+ available value: true, false (default)
+
+ force_otdoa_assist_req:
+ force to fill otdoa assistance request when posMethod=agpsSETassisted,agpsSETassistedpref,ver2-agnssSETassisted or agnssSETassistedpref
+ Notice that some servers may not allow to get otdoa assistance request when posMethod is not OTDOA
+ available value: true, false (default)
+
+ up_lppe_enable
+ enable/disable UP LPPe functionality
+ available value: true (default), false
+
+ esupl_apn_mode:
+ how to choose APN for eSUPL
+ available value: 0 to use Emergency / IMS APN if they are available as GSMA IR92 (default)
+ 1 to use Emergency APN if it is available
+ 2 to use IMS APN if it is available
+ 3 not to use Emergency / IMS APN, just as a normal supl
+
+ tcp_keepalive:
+ enable/disable TCP Keepalive functionality for SUPL
+ available value: 0 disable (default)
+ > 0 enable to send TCP keepalive packetets and interval value is tcp_keepalive in second
+
+ aosp_profile_enable:
+ enable/disable the supl profile configuration from GnssLocationProvider via native_set_agps_server (tc3 requirement)
+ auto_profile_enable will be ignored when aosp_profile_enable is true because AOSP Location Framework
+ can load SUPL_HOST and SUPL_PORT from framework resource for different MCC/MNC
+ available value: true, false (default)
+
+ bind_nlp_setting_to_supl
+ enable/disable to bind nlp setting to SUPL SI flow
+ If it is enabled, the SUPL SI is enabled only if NLP setting is enabled by user
+ If it is disabled, agps_enable will be used and it's same as previous design
+ available value: true, false (default)
+
+ up_lppe_wlan_enable:
+ enable/disable UP LPPe Wireless LAN part functionality (tc1 requirement)
+ available value: true (default), false
+
+ up_lppe_srn_enable:
+ enable/disable UP LPPe srn (e.g., Bluetooth or BluetoothLE) part functionality (tc1 requirement)
+ available value: true (default), false
+
+ up_lppe_sensor_enable:
+ enable/disable UP LPPe sensor (e.g., Barometers) part functionality (tc1 requirement)
+ available value: true (default), false
+
+ up_lppe_dbh_enable:
+ enable/disable UP LPPe Device Based Hybrid functionality (tc1 requirement)
+ available value: true (default), false
+
+ ip_version_prefer
+ select the preferred mode for IP version when connnecting to the SUPL server (Softbank requirement)
+ available value: 0 IPv6 if we have both (default)
+ 1 IPv4 if we have both
+
+ up_lpp_in_2g3g_disable
+ decide if we need to turn off lpp in 2G / 3G network (ATT requirement)
+ US ATT SUPL server may not provide assistance data if we have the lpp capability in 2G / 3G network
+ available value: true, false (default)
+
+ up_rrlp_in_4g_disable
+ decide if we need to turn off RRLP in 4G network when we have SUPL 2.0 and LPP (ATT requirement)
+ US ATT SUPL server may not provide assistance data if we have the rrlp capability in 4G network
+ available value: true, false (default)
+
+ up_si_disable
+ decide if we need to reject SUPL SI request (Sprint requirement)
+ Sprint_2019Feb_GTR-LBS-00219 asks us not to trigger SUPL SI.
+ Sprint_2019Feb_GTR-LBS-00222 asks us to support NI including normal and emergency
+ Sprint_2019Feb_GTR-LBS-00223 asks us to use Sprint SLP in our configuration
+ If we turn off agps_enable, we will allow Emergency NI only (reject SI and normal NI)
+ If we turn on up_si_disable, we will allow both normal NI and Emergency NI (reject SI only)
+ So this option is more suitable for Sprint requirements.
+ available value: true, false (default)
+
+ -->
+ <up_setting
+ ca_enable="false"
+ ni_request="true"
+ roaming="true"
+ cdma_preferred="0"
+ pref_method="1"
+ supl_version="2"
+ tls_version="1"
+ sha_version="0"
+ supl_log="false"
+ msa_enable="true"
+ msb_enable="true"
+ ecid_enable="true"
+ autonomous_enable="true"
+ aflt_enable="false"
+ qop_hacc="22"
+ qop_vacc="0"
+ qop_loc_age="0"
+ qop_delay="0"
+ udp_port_enable="false"
+ dedicated_apn_enable="false"
+ preferred_2g3g_cell_age="300"
+ lpp_enable="true"
+ cert_from_sdcard="true"
+ auto_profile_enable="true"
+ ut1="11"
+ ut2="11"
+ ut3="10"
+ sync_to_slp="false"
+ imsi_enable="true"
+ no_sensitive_log="true"
+ supl_ver_minor="0"
+ supl_ver_ser_ind="0"
+ tls_reuse_enable="false"
+ imsi_cache_enable="false"
+ supl_raw_data_enable="false"
+ allow_ni_for_gps_off="false"
+ force_otdoa_assist_req="false"
+ up_lppe_enable="true"
+ esupl_apn_mode="0"
+ tcp_keepalive="0"
+ aosp_profile_enable="false"
+ bind_nlp_setting_to_supl="false"
+ up_lppe_wlan_enable="true"
+ up_lppe_srn_enable="true"
+ up_lppe_sensor_enable="true"
+ up_lppe_dbh_enable="true"
+ ip_version_prefer="0"
+ up_lpp_in_2g3g_disable="false"
+ up_rrlp_in_4g_disable="false"
+ up_si_disable="false"
+ />
+
+</mtk_agps_profiles>
diff --git a/meta/meta-mediatek/recipes-connectivity/agps/files/cacerts/0f0d3382.0 b/meta/meta-mediatek/recipes-connectivity/agps/files/cacerts/0f0d3382.0
new file mode 100644
index 0000000..5ac1e4b
--- /dev/null
+++ b/meta/meta-mediatek/recipes-connectivity/agps/files/cacerts/0f0d3382.0
@@ -0,0 +1,41 @@
+-----BEGIN CERTIFICATE-----
+MIICNDCCAd4CCQDNZBw4CvIZ/TANBgkqhkiG9w0BAQsFADCBnzEfMB0GA1UEChMW
+U3BpcmVudCBDb21tdW5pY2F0aW9uczEMMAoGA1UECxMDUEFXMSIwIAYJKoZIhvcN
+AQkBFhNzdXBwb3J0QHNwaXJlbnQuY29tMRIwEAYDVQQHEwlFYXRvbnRvd24xCzAJ
+BgNVBAgTAk5KMQswCQYDVQQGEwJVUzEcMBoGA1UEAxMTd3d3LnNwaXJlbnQtbGNz
+LmNvbTAgFw0xNzAzMDMwOTM1NTRaGA8yMTE3MDIwNzA5MzU1NFowgZ8xHzAdBgNV
+BAoTFlNwaXJlbnQgQ29tbXVuaWNhdGlvbnMxDDAKBgNVBAsTA1BBVzEiMCAGCSqG
+SIb3DQEJARYTc3VwcG9ydEBzcGlyZW50LmNvbTESMBAGA1UEBxMJRWF0b250b3du
+MQswCQYDVQQIEwJOSjELMAkGA1UEBhMCVVMxHDAaBgNVBAMTE3d3dy5zcGlyZW50
+LWxjcy5jb20wXDANBgkqhkiG9w0BAQEFAANLADBIAkEAy+6I3kxd5NJA5r0n76br
+XTP1n8gsFU9ygKW8oGbLbqRGKmc9tGg8JwE9hxmCy+TvHEKRGCJpFouA6PIaH48M
+JwIDAQABMA0GCSqGSIb3DQEBCwUAA0EAVdeZ9Baf+NS9WFqwp1XBXjJzBsTv/yoK
+IfaYpn+XTD8J49AYcu1J+X/bGGBfu3/WEcF0MkR0+1n0fdsecImpNA==
+-----END CERTIFICATE-----
+Certificate:
+ Data:
+ Version: 1 (0x0)
+ Serial Number:
+ cd:64:1c:38:0a:f2:19:fd
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: O=Spirent Communications, OU=PAW/emailAddress=support@spirent.com, L=Eatontown, ST=NJ, C=US, CN=www.spirent-lcs.com
+ Validity
+ Not Before: Mar 3 09:35:54 2017 GMT
+ Not After : Feb 7 09:35:54 2117 GMT
+ Subject: O=Spirent Communications, OU=PAW/emailAddress=support@spirent.com, L=Eatontown, ST=NJ, C=US, CN=www.spirent-lcs.com
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (512 bit)
+ Modulus:
+ 00:cb:ee:88:de:4c:5d:e4:d2:40:e6:bd:27:ef:a6:
+ eb:5d:33:f5:9f:c8:2c:15:4f:72:80:a5:bc:a0:66:
+ cb:6e:a4:46:2a:67:3d:b4:68:3c:27:01:3d:87:19:
+ 82:cb:e4:ef:1c:42:91:18:22:69:16:8b:80:e8:f2:
+ 1a:1f:8f:0c:27
+ Exponent: 65537 (0x10001)
+ Signature Algorithm: sha256WithRSAEncryption
+ 55:d7:99:f4:16:9f:f8:d4:bd:58:5a:b0:a7:55:c1:5e:32:73:
+ 06:c4:ef:ff:2a:0a:21:f6:98:a6:7f:97:4c:3f:09:e3:d0:18:
+ 72:ed:49:f9:7f:db:18:60:5f:bb:7f:d6:11:c1:74:32:44:74:
+ fb:59:f4:7d:db:1e:70:89:a9:34
+SHA1 Fingerprint=B1:DE:C8:55:35:3C:F8:6C:1E:32:12:85:3C:3E:A6:E3:F9:64:CC:45
diff --git a/meta/meta-mediatek/recipes-connectivity/agps/files/cacerts/0f0d3382.1 b/meta/meta-mediatek/recipes-connectivity/agps/files/cacerts/0f0d3382.1
new file mode 100644
index 0000000..7f06cea
--- /dev/null
+++ b/meta/meta-mediatek/recipes-connectivity/agps/files/cacerts/0f0d3382.1
@@ -0,0 +1,73 @@
+-----BEGIN CERTIFICATE-----
+MIIDvDCCAqQCCQCTs5QCfs4x9jANBgkqhkiG9w0BAQUFADCBnzEfMB0GA1UEChMW
+U3BpcmVudCBDb21tdW5pY2F0aW9uczEMMAoGA1UECxMDUEFXMSIwIAYJKoZIhvcN
+AQkBFhNzdXBwb3J0QHNwaXJlbnQuY29tMRIwEAYDVQQHEwlFYXRvbnRvd24xCzAJ
+BgNVBAgTAk5KMQswCQYDVQQGEwJVUzEcMBoGA1UEAxMTd3d3LnNwaXJlbnQtbGNz
+LmNvbTAeFw0xNjA1MzExMDM0MDhaFw0yNjA1MjkxMDM0MDhaMIGfMR8wHQYDVQQK
+ExZTcGlyZW50IENvbW11bmljYXRpb25zMQwwCgYDVQQLEwNQQVcxIjAgBgkqhkiG
+9w0BCQEWE3N1cHBvcnRAc3BpcmVudC5jb20xEjAQBgNVBAcTCUVhdG9udG93bjEL
+MAkGA1UECBMCTkoxCzAJBgNVBAYTAlVTMRwwGgYDVQQDExN3d3cuc3BpcmVudC1s
+Y3MuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAu3BPjQxwbGMG
+DAZ50XDvT4VnfDxMJfp7F1u6j/cGi0yoZ9KG6k9KLhLRcdkc/xocCX1EO7AJFCr6
+YLijbhfsUZYIPgIKXZShwdFoCdTJdeMXwv9T7GybKSNokhz9wTiTIpeq/qAvH0yR
+8h+ifLnoPnijKOOas4s7au25P15yEreR0FZ39hsCCJ2RFvhIcgudk8Nrb9ChgEpI
+hAoIN1LRq6z212QW/yL4FV9TouCqNJQjqGaEl25kTPKR+IieJ6z4J6+kgA2D6xVB
+zHlXga4aDHu/KWVMiLkoLNyCpa7/fxSxAqsPyPLzVBtQqDdvtHC7LIKbu+eytluI
+B2j95X/i4QIDAQABMA0GCSqGSIb3DQEBBQUAA4IBAQBek1pdhqRA0vYGwL89NXL9
+/T2jmN3vUtwjlacsjkEUH2n2YjxiG+S8dmfrUMaYpVS3yUxNN/Pd6rhn71oA10Os
+ML180FmSYwtBuTJBfwfyK1gem2k13Se/h+mzf/ZOlr69hBrDH2fxhdCtwi9iHPO1
+zj5Yl8/7vesrIyjmhwlT82BpG/ej/5Gh+cEKh1yllg5WhEraCiiDwYupxW21AWWQ
+5YWL34qBkIE11HZs1BgwI8IK/xMcC9Pqoime34s5eosqx6Ojx7StO4EVHHSo0zVl
+713G0D08kzdHDGNEZ53dbni4D+MzCt31F2Q0dGrIGdhxEZ2bncBRdI0OzC8T1bP5
+-----END CERTIFICATE-----
+Certificate:
+ Data:
+ Version: 1 (0x0)
+ Serial Number:
+ 93:b3:94:02:7e:ce:31:f6
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: O=Spirent Communications, OU=PAW/emailAddress=support@spirent.com, L=Eatontown, ST=NJ, C=US, CN=www.spirent-lcs.com
+ Validity
+ Not Before: May 31 10:34:08 2016 GMT
+ Not After : May 29 10:34:08 2026 GMT
+ Subject: O=Spirent Communications, OU=PAW/emailAddress=support@spirent.com, L=Eatontown, ST=NJ, C=US, CN=www.spirent-lcs.com
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:bb:70:4f:8d:0c:70:6c:63:06:0c:06:79:d1:70:
+ ef:4f:85:67:7c:3c:4c:25:fa:7b:17:5b:ba:8f:f7:
+ 06:8b:4c:a8:67:d2:86:ea:4f:4a:2e:12:d1:71:d9:
+ 1c:ff:1a:1c:09:7d:44:3b:b0:09:14:2a:fa:60:b8:
+ a3:6e:17:ec:51:96:08:3e:02:0a:5d:94:a1:c1:d1:
+ 68:09:d4:c9:75:e3:17:c2:ff:53:ec:6c:9b:29:23:
+ 68:92:1c:fd:c1:38:93:22:97:aa:fe:a0:2f:1f:4c:
+ 91:f2:1f:a2:7c:b9:e8:3e:78:a3:28:e3:9a:b3:8b:
+ 3b:6a:ed:b9:3f:5e:72:12:b7:91:d0:56:77:f6:1b:
+ 02:08:9d:91:16:f8:48:72:0b:9d:93:c3:6b:6f:d0:
+ a1:80:4a:48:84:0a:08:37:52:d1:ab:ac:f6:d7:64:
+ 16:ff:22:f8:15:5f:53:a2:e0:aa:34:94:23:a8:66:
+ 84:97:6e:64:4c:f2:91:f8:88:9e:27:ac:f8:27:af:
+ a4:80:0d:83:eb:15:41:cc:79:57:81:ae:1a:0c:7b:
+ bf:29:65:4c:88:b9:28:2c:dc:82:a5:ae:ff:7f:14:
+ b1:02:ab:0f:c8:f2:f3:54:1b:50:a8:37:6f:b4:70:
+ bb:2c:82:9b:bb:e7:b2:b6:5b:88:07:68:fd:e5:7f:
+ e2:e1
+ Exponent: 65537 (0x10001)
+ Signature Algorithm: sha1WithRSAEncryption
+ 5e:93:5a:5d:86:a4:40:d2:f6:06:c0:bf:3d:35:72:fd:fd:3d:
+ a3:98:dd:ef:52:dc:23:95:a7:2c:8e:41:14:1f:69:f6:62:3c:
+ 62:1b:e4:bc:76:67:eb:50:c6:98:a5:54:b7:c9:4c:4d:37:f3:
+ dd:ea:b8:67:ef:5a:00:d7:43:ac:30:bd:7c:d0:59:92:63:0b:
+ 41:b9:32:41:7f:07:f2:2b:58:1e:9b:69:35:dd:27:bf:87:e9:
+ b3:7f:f6:4e:96:be:bd:84:1a:c3:1f:67:f1:85:d0:ad:c2:2f:
+ 62:1c:f3:b5:ce:3e:58:97:cf:fb:bd:eb:2b:23:28:e6:87:09:
+ 53:f3:60:69:1b:f7:a3:ff:91:a1:f9:c1:0a:87:5c:a5:96:0e:
+ 56:84:4a:da:0a:28:83:c1:8b:a9:c5:6d:b5:01:65:90:e5:85:
+ 8b:df:8a:81:90:81:35:d4:76:6c:d4:18:30:23:c2:0a:ff:13:
+ 1c:0b:d3:ea:a2:29:9e:df:8b:39:7a:8b:2a:c7:a3:a3:c7:b4:
+ ad:3b:81:15:1c:74:a8:d3:35:65:ef:5d:c6:d0:3d:3c:93:37:
+ 47:0c:63:44:67:9d:dd:6e:78:b8:0f:e3:33:0a:dd:f5:17:64:
+ 34:74:6a:c8:19:d8:71:11:9d:9b:9d:c0:51:74:8d:0e:cc:2f:
+ 13:d5:b3:f9
+SHA1 Fingerprint=7A:6D:8A:73:FF:90:5C:F2:CE:52:2D:C6:9B:6C:2A:C3:62:A7:66:B8
diff --git a/meta/meta-mediatek/recipes-connectivity/agps/files/cacerts/0f0d3382.2 b/meta/meta-mediatek/recipes-connectivity/agps/files/cacerts/0f0d3382.2
new file mode 100644
index 0000000..3696076
--- /dev/null
+++ b/meta/meta-mediatek/recipes-connectivity/agps/files/cacerts/0f0d3382.2
@@ -0,0 +1,52 @@
+-----BEGIN CERTIFICATE-----
+MIICtzCCAiACCQCDLHF0XTXDZDANBgkqhkiG9w0BAQUFADCBnzEfMB0GA1UEChMW
+U3BpcmVudCBDb21tdW5pY2F0aW9uczEMMAoGA1UECxMDUEFXMSIwIAYJKoZIhvcN
+AQkBFhNzdXBwb3J0QHNwaXJlbnQuY29tMRIwEAYDVQQHEwlFYXRvbnRvd24xCzAJ
+BgNVBAgTAk5KMQswCQYDVQQGEwJVUzEcMBoGA1UEAxMTd3d3LnNwaXJlbnQtbGNz
+LmNvbTAeFw0xNTA1MjAwODM3MDZaFw0yNTA1MTcwODM3MDZaMIGfMR8wHQYDVQQK
+ExZTcGlyZW50IENvbW11bmljYXRpb25zMQwwCgYDVQQLEwNQQVcxIjAgBgkqhkiG
+9w0BCQEWE3N1cHBvcnRAc3BpcmVudC5jb20xEjAQBgNVBAcTCUVhdG9udG93bjEL
+MAkGA1UECBMCTkoxCzAJBgNVBAYTAlVTMRwwGgYDVQQDExN3d3cuc3BpcmVudC1s
+Y3MuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC/9xvPjrwx4iw+JE11
+scEEP+MlE7yvZHrPO1aiNAMB8Q6WCgz9ZN0+5pjvT2EOnXYAJ6WsaAWwgD8yXxyi
+9SjmtOg7OcnXbHCaq6xgIM/elXrUge+TnkrBoUxNO0kgUY1BE1tBmBBFgQmVKvjf
+Gbrx/HZJEbukq+148jSkWeTrswIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAEI1ilmt
+DZkI8QxaqX5NzDijPcqRRCO57ULUiq50V0tXS6DfIiBugeGw/gAJrxo6LDrszuCo
+EWTjNJZhCTZz4075B1IQ7VF1fYL1J3XLQsJR8ydFxDisan2tfdbFpUi5W/CnOO4U
+BN7o06HM4J4ysC1GB4a+WU7MpngJl7YXblRp
+-----END CERTIFICATE-----
+Certificate:
+ Data:
+ Version: 1 (0x0)
+ Serial Number:
+ 83:2c:71:74:5d:35:c3:64
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: O=Spirent Communications, OU=PAW/emailAddress=support@spirent.com, L=Eatontown, ST=NJ, C=US, CN=www.spirent-lcs.com
+ Validity
+ Not Before: May 20 08:37:06 2015 GMT
+ Not After : May 17 08:37:06 2025 GMT
+ Subject: O=Spirent Communications, OU=PAW/emailAddress=support@spirent.com, L=Eatontown, ST=NJ, C=US, CN=www.spirent-lcs.com
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (1024 bit)
+ Modulus:
+ 00:bf:f7:1b:cf:8e:bc:31:e2:2c:3e:24:4d:75:b1:
+ c1:04:3f:e3:25:13:bc:af:64:7a:cf:3b:56:a2:34:
+ 03:01:f1:0e:96:0a:0c:fd:64:dd:3e:e6:98:ef:4f:
+ 61:0e:9d:76:00:27:a5:ac:68:05:b0:80:3f:32:5f:
+ 1c:a2:f5:28:e6:b4:e8:3b:39:c9:d7:6c:70:9a:ab:
+ ac:60:20:cf:de:95:7a:d4:81:ef:93:9e:4a:c1:a1:
+ 4c:4d:3b:49:20:51:8d:41:13:5b:41:98:10:45:81:
+ 09:95:2a:f8:df:19:ba:f1:fc:76:49:11:bb:a4:ab:
+ ed:78:f2:34:a4:59:e4:eb:b3
+ Exponent: 65537 (0x10001)
+ Signature Algorithm: sha1WithRSAEncryption
+ 42:35:8a:59:ad:0d:99:08:f1:0c:5a:a9:7e:4d:cc:38:a3:3d:
+ ca:91:44:23:b9:ed:42:d4:8a:ae:74:57:4b:57:4b:a0:df:22:
+ 20:6e:81:e1:b0:fe:00:09:af:1a:3a:2c:3a:ec:ce:e0:a8:11:
+ 64:e3:34:96:61:09:36:73:e3:4e:f9:07:52:10:ed:51:75:7d:
+ 82:f5:27:75:cb:42:c2:51:f3:27:45:c4:38:ac:6a:7d:ad:7d:
+ d6:c5:a5:48:b9:5b:f0:a7:38:ee:14:04:de:e8:d3:a1:cc:e0:
+ 9e:32:b0:2d:46:07:86:be:59:4e:cc:a6:78:09:97:b6:17:6e:
+ 54:69
+SHA1 Fingerprint=19:A3:30:2D:04:6A:1C:0A:E0:79:8D:BF:E1:C8:BE:F7:07:2E:11:D5
diff --git a/meta/meta-mediatek/recipes-connectivity/agps/files/cacerts/0f0d3382.3 b/meta/meta-mediatek/recipes-connectivity/agps/files/cacerts/0f0d3382.3
new file mode 100644
index 0000000..dc346fb
--- /dev/null
+++ b/meta/meta-mediatek/recipes-connectivity/agps/files/cacerts/0f0d3382.3
@@ -0,0 +1,73 @@
+-----BEGIN CERTIFICATE-----
+MIIDvDCCAqQCCQDDkVHHKI3WVzANBgkqhkiG9w0BAQUFADCBnzEfMB0GA1UEChMW
+U3BpcmVudCBDb21tdW5pY2F0aW9uczEMMAoGA1UECxMDUEFXMSIwIAYJKoZIhvcN
+AQkBFhNzdXBwb3J0QHNwaXJlbnQuY29tMRIwEAYDVQQHEwlFYXRvbnRvd24xCzAJ
+BgNVBAgTAk5KMQswCQYDVQQGEwJVUzEcMBoGA1UEAxMTd3d3LnNwaXJlbnQtbGNz
+LmNvbTAeFw0xMzA1MjIwNTEzMjRaFw0yMzA1MjAwNTEzMjRaMIGfMR8wHQYDVQQK
+ExZTcGlyZW50IENvbW11bmljYXRpb25zMQwwCgYDVQQLEwNQQVcxIjAgBgkqhkiG
+9w0BCQEWE3N1cHBvcnRAc3BpcmVudC5jb20xEjAQBgNVBAcTCUVhdG9udG93bjEL
+MAkGA1UECBMCTkoxCzAJBgNVBAYTAlVTMRwwGgYDVQQDExN3d3cuc3BpcmVudC1s
+Y3MuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmiQewaITek2/
+tv8rRGhuMwlC3wM6O8C9POYdwWD98OwzasaxwjDyljV2Cdj/77YOkwXgFoyQRXoA
+KtsnOWNG3PjJ+tA/0weMyWXWGDNEii4YhUrVKgSswMzgf6H4bEYy3XJrfwc3DUCb
+WrcrG1Vlk2s9DDTY56A5HuevYP6BOxZK6XOHR7aYFiDXn9QXFTiIK8W4nRkTtAKl
+SNBfwbNIbwkUygTjcqjVwZ4ZkjUNR+BVBJbu6KWumfxfCjN0HcKWiGACu3Zag3gZ
+VIYuQsXkln5Nr61H9H4ZuSiOp7wl/P8ihv3r8ohfSHmPKSJjWwAOIkmPSg7+R5nv
+wMd5r4a2NQIDAQABMA0GCSqGSIb3DQEBBQUAA4IBAQB2F8+oXZnxCT4SjPxGu1+/
+ptsHFdQnjANq50o6D1DYKnXufbkq/4DfMMTM62ViJ0WBxnsO1fPyhoiWmQ4vQJjI
+0Vr+4fDNo3eZhqSWtyeEp5SUopRIZy3kYeXqOQAeav8RqTs6/WNRSOuyKpCL3s0T
+uilBgNDSMKuUA8zAOCU/H/xyHGgBou5F9dklzMStfQ7kx6G5vvpprdS+kZfov400
+XH8UAvH/E9UxS8Kexavb0YFN1Vj4e81zmpZu4k14TR97cLtZHXyaDl2T7GetgEgU
+OaCbMeBGRy8fa14GOmdMmxJ7Ufps/SvyLop9Fv3HrIAES7w5cKEyLw5fY0ZxKU5C
+-----END CERTIFICATE-----
+Certificate:
+ Data:
+ Version: 1 (0x0)
+ Serial Number:
+ c3:91:51:c7:28:8d:d6:57
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: O=Spirent Communications, OU=PAW/emailAddress=support@spirent.com, L=Eatontown, ST=NJ, C=US, CN=www.spirent-lcs.com
+ Validity
+ Not Before: May 22 05:13:24 2013 GMT
+ Not After : May 20 05:13:24 2023 GMT
+ Subject: O=Spirent Communications, OU=PAW/emailAddress=support@spirent.com, L=Eatontown, ST=NJ, C=US, CN=www.spirent-lcs.com
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:9a:24:1e:c1:a2:13:7a:4d:bf:b6:ff:2b:44:68:
+ 6e:33:09:42:df:03:3a:3b:c0:bd:3c:e6:1d:c1:60:
+ fd:f0:ec:33:6a:c6:b1:c2:30:f2:96:35:76:09:d8:
+ ff:ef:b6:0e:93:05:e0:16:8c:90:45:7a:00:2a:db:
+ 27:39:63:46:dc:f8:c9:fa:d0:3f:d3:07:8c:c9:65:
+ d6:18:33:44:8a:2e:18:85:4a:d5:2a:04:ac:c0:cc:
+ e0:7f:a1:f8:6c:46:32:dd:72:6b:7f:07:37:0d:40:
+ 9b:5a:b7:2b:1b:55:65:93:6b:3d:0c:34:d8:e7:a0:
+ 39:1e:e7:af:60:fe:81:3b:16:4a:e9:73:87:47:b6:
+ 98:16:20:d7:9f:d4:17:15:38:88:2b:c5:b8:9d:19:
+ 13:b4:02:a5:48:d0:5f:c1:b3:48:6f:09:14:ca:04:
+ e3:72:a8:d5:c1:9e:19:92:35:0d:47:e0:55:04:96:
+ ee:e8:a5:ae:99:fc:5f:0a:33:74:1d:c2:96:88:60:
+ 02:bb:76:5a:83:78:19:54:86:2e:42:c5:e4:96:7e:
+ 4d:af:ad:47:f4:7e:19:b9:28:8e:a7:bc:25:fc:ff:
+ 22:86:fd:eb:f2:88:5f:48:79:8f:29:22:63:5b:00:
+ 0e:22:49:8f:4a:0e:fe:47:99:ef:c0:c7:79:af:86:
+ b6:35
+ Exponent: 65537 (0x10001)
+ Signature Algorithm: sha1WithRSAEncryption
+ 76:17:cf:a8:5d:99:f1:09:3e:12:8c:fc:46:bb:5f:bf:a6:db:
+ 07:15:d4:27:8c:03:6a:e7:4a:3a:0f:50:d8:2a:75:ee:7d:b9:
+ 2a:ff:80:df:30:c4:cc:eb:65:62:27:45:81:c6:7b:0e:d5:f3:
+ f2:86:88:96:99:0e:2f:40:98:c8:d1:5a:fe:e1:f0:cd:a3:77:
+ 99:86:a4:96:b7:27:84:a7:94:94:a2:94:48:67:2d:e4:61:e5:
+ ea:39:00:1e:6a:ff:11:a9:3b:3a:fd:63:51:48:eb:b2:2a:90:
+ 8b:de:cd:13:ba:29:41:80:d0:d2:30:ab:94:03:cc:c0:38:25:
+ 3f:1f:fc:72:1c:68:01:a2:ee:45:f5:d9:25:cc:c4:ad:7d:0e:
+ e4:c7:a1:b9:be:fa:69:ad:d4:be:91:97:e8:bf:8d:34:5c:7f:
+ 14:02:f1:ff:13:d5:31:4b:c2:9e:c5:ab:db:d1:81:4d:d5:58:
+ f8:7b:cd:73:9a:96:6e:e2:4d:78:4d:1f:7b:70:bb:59:1d:7c:
+ 9a:0e:5d:93:ec:67:ad:80:48:14:39:a0:9b:31:e0:46:47:2f:
+ 1f:6b:5e:06:3a:67:4c:9b:12:7b:51:fa:6c:fd:2b:f2:2e:8a:
+ 7d:16:fd:c7:ac:80:04:4b:bc:39:70:a1:32:2f:0e:5f:63:46:
+ 71:29:4e:42
+SHA1 Fingerprint=FB:10:C1:6C:00:2B:6D:49:AB:58:86:80:AE:81:A1:27:50:E5:90:AE
diff --git a/meta/meta-mediatek/recipes-connectivity/agps/files/cacerts/0f0d3382.4 b/meta/meta-mediatek/recipes-connectivity/agps/files/cacerts/0f0d3382.4
new file mode 100644
index 0000000..82ea6a4
--- /dev/null
+++ b/meta/meta-mediatek/recipes-connectivity/agps/files/cacerts/0f0d3382.4
@@ -0,0 +1,115 @@
+-----BEGIN CERTIFICATE-----
+MIIFvDCCA6QCCQCg0UECrM07ljANBgkqhkiG9w0BAQUFADCBnzEfMB0GA1UEChMW
+U3BpcmVudCBDb21tdW5pY2F0aW9uczEMMAoGA1UECxMDUEFXMSIwIAYJKoZIhvcN
+AQkBFhNzdXBwb3J0QHNwaXJlbnQuY29tMRIwEAYDVQQHEwlFYXRvbnRvd24xCzAJ
+BgNVBAgTAk5KMQswCQYDVQQGEwJVUzEcMBoGA1UEAxMTd3d3LnNwaXJlbnQtbGNz
+LmNvbTAeFw0xMjAyMjAwNjQwMzRaFw0yMjAyMTcwNjQwMzRaMIGfMR8wHQYDVQQK
+ExZTcGlyZW50IENvbW11bmljYXRpb25zMQwwCgYDVQQLEwNQQVcxIjAgBgkqhkiG
+9w0BCQEWE3N1cHBvcnRAc3BpcmVudC5jb20xEjAQBgNVBAcTCUVhdG9udG93bjEL
+MAkGA1UECBMCTkoxCzAJBgNVBAYTAlVTMRwwGgYDVQQDExN3d3cuc3BpcmVudC1s
+Y3MuY29tMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA0hJNgKoFeGXC
+JkGbeNpLRhOmFSOkfiO7Y+FYuUliNF4pwTrHizO1LgzoEoi2wdDfDSIY3HtBFqXk
+3QXZbxG239/PSFw9ONGoODSesQasUb2PJuRP6pOiLjAo810vyj31nDM5R7UgVnni
+xNtZX+WlQUNaXSkClaVU/a5Rh1GgBmk0Faf80c0d1EMJzDy731J4eipPGn1fmh0S
+tq68dWCWV+391MWy0LWL0UEvl+uyzAvp7H2IAaohO34VtFDxGYRuvw8qfbIJHB8p
+xZBGirnlYdfkPcyv031MYScPFzmuv+qxYWOGy/KB3WTRXsSzTdQQHBzn4M8/OtRf
+LRsffWEBsWnnDBB4+N+FSqh/gkkU9iL0vrjo1SYzBZF89tfASbxxIs045naMPD/i
+uZ1s62267ushTGaPmSpLFWX+KylyAkzXWDiI7Or86DOIo9LGIVOlMciK2rdUkZs7
+fNvvSUxhcdCslzbw456WNHXPT8sPtwLiD689lx60JIsk3D7dcWX9buvjld7zFoTw
+jz/elNTAocwg3JoujSKV2E1ztHAjpXR9s4QEJshwfa9bkT6iLxcjy3ujbB23u00/
+YOplqOu0ZSpqoO7anzseE3vcL8bhCFxz23k+vvGrbzciP62SgLKKf8E97pq+VuhV
+6YE/MTajJ7tzDz3O482zurL1NV2I+2kCAwEAATANBgkqhkiG9w0BAQUFAAOCAgEA
+XNGBXp3glf6K5l78QNLEyCHWuoUJY1/gLiGCPBKv3lBIPTdqY/mxJMc3dM+SErAI
+utsMQQOJZ6jircrzyVYn88P7Y5QzB9m+h6p9wxFix4aqISvOXfQhmf2fWS1bc64o
+2ZxkBJRTvO1epz/rD06HVgJ3HLW016EMYN2cDrrUEZMM8kKdDv/Fxu6vZ+Yt/CUx
++isJ+Ute4+t1o2p0c4lMOH4IRGq6/Pe/8wKSGPXwgGdnVIzvbjGv9Lfy3mbhyulk
+yb5DhYebFbRS6rGLHv/McpYy8d+ualEkAIxVa2T6sDG9eskih5qCIjEBSnTvWJsS
+kuTMtHmc6ZnHuoGuR1GkwaZ9EH6TtcNvt1XfgT1dulbGaDTnBI7lqLGfiUTDue8f
+VivVLtZDcBl9GxfQXig6CpD7Yvr10GaJ2IbaRZkbtkMUTbBJi32GF/FihHv1V/ZE
+DGODfp8J2GPh/KdOihksV3WfpS6EIS5zKxNKNJdJUUtFJ5ERxTCrz+QgBwchJnhQ
+WCIAzz/9//lvVPzaz22t/iWzx5iW3B6pxI8PmbZeC1NYSvbG3aP9e25TFlD4/i00
+b1Nu4Xz+RltgUmj69i+eFeA9VwtqOoez/tLLCXT+w0qEz9faIRwc0qfskCamqw9O
+6VPtyMKSYy5++0U0xZBpqjbSSs4FRWNnC4iXXjZ6MgI=
+-----END CERTIFICATE-----
+Certificate:
+ Data:
+ Version: 1 (0x0)
+ Serial Number:
+ a0:d1:41:02:ac:cd:3b:96
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: O=Spirent Communications, OU=PAW/emailAddress=support@spirent.com, L=Eatontown, ST=NJ, C=US, CN=www.spirent-lcs.com
+ Validity
+ Not Before: Feb 20 06:40:34 2012 GMT
+ Not After : Feb 17 06:40:34 2022 GMT
+ Subject: O=Spirent Communications, OU=PAW/emailAddress=support@spirent.com, L=Eatontown, ST=NJ, C=US, CN=www.spirent-lcs.com
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (4096 bit)
+ Modulus:
+ 00:d2:12:4d:80:aa:05:78:65:c2:26:41:9b:78:da:
+ 4b:46:13:a6:15:23:a4:7e:23:bb:63:e1:58:b9:49:
+ 62:34:5e:29:c1:3a:c7:8b:33:b5:2e:0c:e8:12:88:
+ b6:c1:d0:df:0d:22:18:dc:7b:41:16:a5:e4:dd:05:
+ d9:6f:11:b6:df:df:cf:48:5c:3d:38:d1:a8:38:34:
+ 9e:b1:06:ac:51:bd:8f:26:e4:4f:ea:93:a2:2e:30:
+ 28:f3:5d:2f:ca:3d:f5:9c:33:39:47:b5:20:56:79:
+ e2:c4:db:59:5f:e5:a5:41:43:5a:5d:29:02:95:a5:
+ 54:fd:ae:51:87:51:a0:06:69:34:15:a7:fc:d1:cd:
+ 1d:d4:43:09:cc:3c:bb:df:52:78:7a:2a:4f:1a:7d:
+ 5f:9a:1d:12:b6:ae:bc:75:60:96:57:ed:fd:d4:c5:
+ b2:d0:b5:8b:d1:41:2f:97:eb:b2:cc:0b:e9:ec:7d:
+ 88:01:aa:21:3b:7e:15:b4:50:f1:19:84:6e:bf:0f:
+ 2a:7d:b2:09:1c:1f:29:c5:90:46:8a:b9:e5:61:d7:
+ e4:3d:cc:af:d3:7d:4c:61:27:0f:17:39:ae:bf:ea:
+ b1:61:63:86:cb:f2:81:dd:64:d1:5e:c4:b3:4d:d4:
+ 10:1c:1c:e7:e0:cf:3f:3a:d4:5f:2d:1b:1f:7d:61:
+ 01:b1:69:e7:0c:10:78:f8:df:85:4a:a8:7f:82:49:
+ 14:f6:22:f4:be:b8:e8:d5:26:33:05:91:7c:f6:d7:
+ c0:49:bc:71:22:cd:38:e6:76:8c:3c:3f:e2:b9:9d:
+ 6c:eb:6d:ba:ee:eb:21:4c:66:8f:99:2a:4b:15:65:
+ fe:2b:29:72:02:4c:d7:58:38:88:ec:ea:fc:e8:33:
+ 88:a3:d2:c6:21:53:a5:31:c8:8a:da:b7:54:91:9b:
+ 3b:7c:db:ef:49:4c:61:71:d0:ac:97:36:f0:e3:9e:
+ 96:34:75:cf:4f:cb:0f:b7:02:e2:0f:af:3d:97:1e:
+ b4:24:8b:24:dc:3e:dd:71:65:fd:6e:eb:e3:95:de:
+ f3:16:84:f0:8f:3f:de:94:d4:c0:a1:cc:20:dc:9a:
+ 2e:8d:22:95:d8:4d:73:b4:70:23:a5:74:7d:b3:84:
+ 04:26:c8:70:7d:af:5b:91:3e:a2:2f:17:23:cb:7b:
+ a3:6c:1d:b7:bb:4d:3f:60:ea:65:a8:eb:b4:65:2a:
+ 6a:a0:ee:da:9f:3b:1e:13:7b:dc:2f:c6:e1:08:5c:
+ 73:db:79:3e:be:f1:ab:6f:37:22:3f:ad:92:80:b2:
+ 8a:7f:c1:3d:ee:9a:be:56:e8:55:e9:81:3f:31:36:
+ a3:27:bb:73:0f:3d:ce:e3:cd:b3:ba:b2:f5:35:5d:
+ 88:fb:69
+ Exponent: 65537 (0x10001)
+ Signature Algorithm: sha1WithRSAEncryption
+ 5c:d1:81:5e:9d:e0:95:fe:8a:e6:5e:fc:40:d2:c4:c8:21:d6:
+ ba:85:09:63:5f:e0:2e:21:82:3c:12:af:de:50:48:3d:37:6a:
+ 63:f9:b1:24:c7:37:74:cf:92:12:b0:08:ba:db:0c:41:03:89:
+ 67:a8:e2:ad:ca:f3:c9:56:27:f3:c3:fb:63:94:33:07:d9:be:
+ 87:aa:7d:c3:11:62:c7:86:aa:21:2b:ce:5d:f4:21:99:fd:9f:
+ 59:2d:5b:73:ae:28:d9:9c:64:04:94:53:bc:ed:5e:a7:3f:eb:
+ 0f:4e:87:56:02:77:1c:b5:b4:d7:a1:0c:60:dd:9c:0e:ba:d4:
+ 11:93:0c:f2:42:9d:0e:ff:c5:c6:ee:af:67:e6:2d:fc:25:31:
+ fa:2b:09:f9:4b:5e:e3:eb:75:a3:6a:74:73:89:4c:38:7e:08:
+ 44:6a:ba:fc:f7:bf:f3:02:92:18:f5:f0:80:67:67:54:8c:ef:
+ 6e:31:af:f4:b7:f2:de:66:e1:ca:e9:64:c9:be:43:85:87:9b:
+ 15:b4:52:ea:b1:8b:1e:ff:cc:72:96:32:f1:df:ae:6a:51:24:
+ 00:8c:55:6b:64:fa:b0:31:bd:7a:c9:22:87:9a:82:22:31:01:
+ 4a:74:ef:58:9b:12:92:e4:cc:b4:79:9c:e9:99:c7:ba:81:ae:
+ 47:51:a4:c1:a6:7d:10:7e:93:b5:c3:6f:b7:55:df:81:3d:5d:
+ ba:56:c6:68:34:e7:04:8e:e5:a8:b1:9f:89:44:c3:b9:ef:1f:
+ 56:2b:d5:2e:d6:43:70:19:7d:1b:17:d0:5e:28:3a:0a:90:fb:
+ 62:fa:f5:d0:66:89:d8:86:da:45:99:1b:b6:43:14:4d:b0:49:
+ 8b:7d:86:17:f1:62:84:7b:f5:57:f6:44:0c:63:83:7e:9f:09:
+ d8:63:e1:fc:a7:4e:8a:19:2c:57:75:9f:a5:2e:84:21:2e:73:
+ 2b:13:4a:34:97:49:51:4b:45:27:91:11:c5:30:ab:cf:e4:20:
+ 07:07:21:26:78:50:58:22:00:cf:3f:fd:ff:f9:6f:54:fc:da:
+ cf:6d:ad:fe:25:b3:c7:98:96:dc:1e:a9:c4:8f:0f:99:b6:5e:
+ 0b:53:58:4a:f6:c6:dd:a3:fd:7b:6e:53:16:50:f8:fe:2d:34:
+ 6f:53:6e:e1:7c:fe:46:5b:60:52:68:fa:f6:2f:9e:15:e0:3d:
+ 57:0b:6a:3a:87:b3:fe:d2:cb:09:74:fe:c3:4a:84:cf:d7:da:
+ 21:1c:1c:d2:a7:ec:90:26:a6:ab:0f:4e:e9:53:ed:c8:c2:92:
+ 63:2e:7e:fb:45:34:c5:90:69:aa:36:d2:4a:ce:05:45:63:67:
+ 0b:88:97:5e:36:7a:32:02
+SHA1 Fingerprint=F0:A5:EA:4F:BD:9E:22:38:FD:A2:08:F1:2E:5F:65:48:A9:1C:EF:95
diff --git a/meta/meta-mediatek/recipes-connectivity/agps/files/cacerts/107bf039.0 b/meta/meta-mediatek/recipes-connectivity/agps/files/cacerts/107bf039.0
new file mode 100644
index 0000000..bf1aa33
--- /dev/null
+++ b/meta/meta-mediatek/recipes-connectivity/agps/files/cacerts/107bf039.0
@@ -0,0 +1,40 @@
+-----BEGIN CERTIFICATE-----
+MIICDDCCAbYCCQDTsReF396KmzANBgkqhkiG9w0BAQUFADCBjDEQMA4GA1UEChMH
+U3BpcmVudDEMMAoGA1UECxMDUEFXMSIwIAYJKoZIhvcNAQkBFhNzdXBwb3J0QHNw
+aXJlbnQuY29tMRIwEAYDVQQHEwlFYXRvbnRvd24xCzAJBgNVBAgTAk5KMQswCQYD
+VQQGEwJVUzEYMBYGA1UEAxMPd3d3LnNwaXJlbnQuY29tMB4XDTExMDkwMjAyMjc0
+OFoXDTIxMDgzMDAyMjc0OFowgYwxEDAOBgNVBAoTB1NwaXJlbnQxDDAKBgNVBAsT
+A1BBVzEiMCAGCSqGSIb3DQEJARYTc3VwcG9ydEBzcGlyZW50LmNvbTESMBAGA1UE
+BxMJRWF0b250b3duMQswCQYDVQQIEwJOSjELMAkGA1UEBhMCVVMxGDAWBgNVBAMT
+D3d3dy5zcGlyZW50LmNvbTBcMA0GCSqGSIb3DQEBAQUAA0sAMEgCQQDrVQ0g3cgC
+0GZ7CVBwlBWf3ogxpi82rvxY7o3NGNoNWJKD/aju650HDph+/hriAxbAva9zIaKA
+YJEmN9oNPDxRAgMBAAEwDQYJKoZIhvcNAQEFBQADQQAJpKZ/i+KHVdndyfdYI5lM
+oNe6EkRXrrFSNPiKH6UoKdq+bbMlLljzBhd76Bgn18rMdAfx0yp2Z+aoK68/bbGJ
+-----END CERTIFICATE-----
+Certificate:
+ Data:
+ Version: 1 (0x0)
+ Serial Number:
+ d3:b1:17:85:df:de:8a:9b
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: O=Spirent, OU=PAW/emailAddress=support@spirent.com, L=Eatontown, ST=NJ, C=US, CN=www.spirent.com
+ Validity
+ Not Before: Sep 2 02:27:48 2011 GMT
+ Not After : Aug 30 02:27:48 2021 GMT
+ Subject: O=Spirent, OU=PAW/emailAddress=support@spirent.com, L=Eatontown, ST=NJ, C=US, CN=www.spirent.com
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (512 bit)
+ Modulus:
+ 00:eb:55:0d:20:dd:c8:02:d0:66:7b:09:50:70:94:
+ 15:9f:de:88:31:a6:2f:36:ae:fc:58:ee:8d:cd:18:
+ da:0d:58:92:83:fd:a8:ee:eb:9d:07:0e:98:7e:fe:
+ 1a:e2:03:16:c0:bd:af:73:21:a2:80:60:91:26:37:
+ da:0d:3c:3c:51
+ Exponent: 65537 (0x10001)
+ Signature Algorithm: sha1WithRSAEncryption
+ 09:a4:a6:7f:8b:e2:87:55:d9:dd:c9:f7:58:23:99:4c:a0:d7:
+ ba:12:44:57:ae:b1:52:34:f8:8a:1f:a5:28:29:da:be:6d:b3:
+ 25:2e:58:f3:06:17:7b:e8:18:27:d7:ca:cc:74:07:f1:d3:2a:
+ 76:67:e6:a8:2b:af:3f:6d:b1:89
+SHA1 Fingerprint=56:B8:57:24:68:A8:88:BC:B9:B6:8E:2F:0A:18:A3:41:98:EF:C2:B0
diff --git a/meta/meta-mediatek/recipes-connectivity/agps/files/cacerts/1a6fed5c.0 b/meta/meta-mediatek/recipes-connectivity/agps/files/cacerts/1a6fed5c.0
new file mode 100644
index 0000000..b57322a
--- /dev/null
+++ b/meta/meta-mediatek/recipes-connectivity/agps/files/cacerts/1a6fed5c.0
@@ -0,0 +1,41 @@
+-----BEGIN CERTIFICATE-----
+MIICOjCCAeQCCQClcmEx/0u9TzANBgkqhkiG9w0BAQsFADCBojEfMB0GA1UEChMW
+U3BpcmVudCBDb21tdW5pY2F0aW9uczEMMAoGA1UECxMDUEFXMSIwIAYJKoZIhvcN
+AQkBFhNzdXBwb3J0QHNwaXJlbnQuY29tMRIwEAYDVQQHEwlFYXRvbnRvd24xCzAJ
+BgNVBAgTAk5KMQswCQYDVQQGEwJVUzEfMB0GA1UEAxMWU3BpcmVudCBDb21tdW5p
+Y2F0aW9uczAgFw0xNzAxMjMwOTA3NDNaGA8yMTE2MTIzMDA5MDc0M1owgaIxHzAd
+BgNVBAoTFlNwaXJlbnQgQ29tbXVuaWNhdGlvbnMxDDAKBgNVBAsTA1BBVzEiMCAG
+CSqGSIb3DQEJARYTc3VwcG9ydEBzcGlyZW50LmNvbTESMBAGA1UEBxMJRWF0b250
+b3duMQswCQYDVQQIEwJOSjELMAkGA1UEBhMCVVMxHzAdBgNVBAMTFlNwaXJlbnQg
+Q29tbXVuaWNhdGlvbnMwXDANBgkqhkiG9w0BAQEFAANLADBIAkEAwd1d4rRb9Z73
+v+UXFGzkiKXHMdFdiqL/r7hmyNt3j2yfslXwRGQA0QV6uBXfnUWkKTXPeUQNEpz+
+qXc20L0suQIDAQABMA0GCSqGSIb3DQEBCwUAA0EAhUEbXeKl0D4kny2DMc+xiByx
+cy8rn68mOpkp/mmRYFgeT/Ez4bViUz3PV3kptwTF/NOaDL2BTCIiDzzMs9dCxA==
+-----END CERTIFICATE-----
+Certificate:
+ Data:
+ Version: 1 (0x0)
+ Serial Number:
+ a5:72:61:31:ff:4b:bd:4f
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: O=Spirent Communications, OU=PAW/emailAddress=support@spirent.com, L=Eatontown, ST=NJ, C=US, CN=Spirent Communications
+ Validity
+ Not Before: Jan 23 09:07:43 2017 GMT
+ Not After : Dec 30 09:07:43 2116 GMT
+ Subject: O=Spirent Communications, OU=PAW/emailAddress=support@spirent.com, L=Eatontown, ST=NJ, C=US, CN=Spirent Communications
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (512 bit)
+ Modulus:
+ 00:c1:dd:5d:e2:b4:5b:f5:9e:f7:bf:e5:17:14:6c:
+ e4:88:a5:c7:31:d1:5d:8a:a2:ff:af:b8:66:c8:db:
+ 77:8f:6c:9f:b2:55:f0:44:64:00:d1:05:7a:b8:15:
+ df:9d:45:a4:29:35:cf:79:44:0d:12:9c:fe:a9:77:
+ 36:d0:bd:2c:b9
+ Exponent: 65537 (0x10001)
+ Signature Algorithm: sha256WithRSAEncryption
+ 85:41:1b:5d:e2:a5:d0:3e:24:9f:2d:83:31:cf:b1:88:1c:b1:
+ 73:2f:2b:9f:af:26:3a:99:29:fe:69:91:60:58:1e:4f:f1:33:
+ e1:b5:62:53:3d:cf:57:79:29:b7:04:c5:fc:d3:9a:0c:bd:81:
+ 4c:22:22:0f:3c:cc:b3:d7:42:c4
+SHA1 Fingerprint=CC:1E:10:F1:11:85:A9:FC:E6:6C:16:5E:42:9D:C1:1F:B3:25:32:A9
diff --git a/meta/meta-mediatek/recipes-connectivity/agps/files/cacerts/20a318fa.0 b/meta/meta-mediatek/recipes-connectivity/agps/files/cacerts/20a318fa.0
new file mode 100644
index 0000000..61f3bc3
--- /dev/null
+++ b/meta/meta-mediatek/recipes-connectivity/agps/files/cacerts/20a318fa.0
@@ -0,0 +1,81 @@
+-----BEGIN CERTIFICATE-----
+MIIDrTCCApWgAwIBAgIJAOmdJ+pU1nQ1MA0GCSqGSIb3DQEBBQUAMG0xCzAJBgNV
+BAYTAkpQMQ4wDAYDVQQIDAVUb2t5bzEwMC4GA1UECgwnQ29yZSBBcHBsb2NhdGlv
+biBEZXZlbG9wbWVudCBEZXBhcnRtZW50MRwwGgYDVQQDDBNsb2NhdGlvbi5rZGRp
+Lm5lLmpwMB4XDTEzMTIwODAyNTk0MVoXDTM3MTIwMjAyNTk0MVowbTELMAkGA1UE
+BhMCSlAxDjAMBgNVBAgMBVRva3lvMTAwLgYDVQQKDCdDb3JlIEFwcGxvY2F0aW9u
+IERldmVsb3BtZW50IERlcGFydG1lbnQxHDAaBgNVBAMME2xvY2F0aW9uLmtkZGku
+bmUuanAwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDHssBcgaPRdjRq
+0mjfyUNNi47BT1jtF8/wyYuW0Muz2kyF3kl7fA2HP9BJTMpFVykeH5c33l6XDYWM
+8jT9c/SDVcUcZS2FFFkpDq9MiVtRdJJib/QsMzKqanf4iw53jjoTmqZFwDtmlubs
+7tEkeDjRnwnVybeCZ5tWoIVCep7d/pWK2KtSstzg5klYHsZS2ussp9lFcGQfD8oH
+flObsVu091+zKo+ON97R5igxUJ9eQzhPjj8tWUfJT3rLy6HCNJXMtQUMxXtDarrR
+6Rz18vq6FbDvxoID1vRMCyOI9u95LFdlImow0QN/fTxerwQOCzGNyAMWpVox6b91
+ai5YjHfhAgMBAAGjUDBOMB0GA1UdDgQWBBRwysV2Wo52jU7b4AHyMaoL5+7w7TAf
+BgNVHSMEGDAWgBRwysV2Wo52jU7b4AHyMaoL5+7w7TAMBgNVHRMEBTADAQH/MA0G
+CSqGSIb3DQEBBQUAA4IBAQBoKmI3FcTIArCKyW2uBsrtXQHgsuXe7KYyEvIFYjNN
+s5U13L+Kod2qX1/w0gAd6r9HxQ6OjMQ73NMq9oPOAuoNl+F6UFgUomix/vTD4oei
+h+xLiUn0FZ2tV28tCTU9Ff9j8wLPcjeH6NBmTx31goPRtsHS+jUQ5bLXmhGOSz0a
+3eFe4fci6vtlpxCJ8ys6Wxij1sJoM93PFLDJzQRzrdVsV9IvZioszT/KaFEjc8s9
+78mw8vQxHihcTp9dTkkC6ykuqPL00jLks3ckkw8fdSM/WdT3QAOYMj9bbVvBZKKL
+/4oGmn0g6PpT9LtHY3jS4+de33hMcatsYe9KwwgJb0jL
+-----END CERTIFICATE-----
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ e9:9d:27:ea:54:d6:74:35
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=JP, ST=Tokyo, O=Core Applocation Development Department, CN=location.kddi.ne.jp
+ Validity
+ Not Before: Dec 8 02:59:41 2013 GMT
+ Not After : Dec 2 02:59:41 2037 GMT
+ Subject: C=JP, ST=Tokyo, O=Core Applocation Development Department, CN=location.kddi.ne.jp
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:c7:b2:c0:5c:81:a3:d1:76:34:6a:d2:68:df:c9:
+ 43:4d:8b:8e:c1:4f:58:ed:17:cf:f0:c9:8b:96:d0:
+ cb:b3:da:4c:85:de:49:7b:7c:0d:87:3f:d0:49:4c:
+ ca:45:57:29:1e:1f:97:37:de:5e:97:0d:85:8c:f2:
+ 34:fd:73:f4:83:55:c5:1c:65:2d:85:14:59:29:0e:
+ af:4c:89:5b:51:74:92:62:6f:f4:2c:33:32:aa:6a:
+ 77:f8:8b:0e:77:8e:3a:13:9a:a6:45:c0:3b:66:96:
+ e6:ec:ee:d1:24:78:38:d1:9f:09:d5:c9:b7:82:67:
+ 9b:56:a0:85:42:7a:9e:dd:fe:95:8a:d8:ab:52:b2:
+ dc:e0:e6:49:58:1e:c6:52:da:eb:2c:a7:d9:45:70:
+ 64:1f:0f:ca:07:7e:53:9b:b1:5b:b4:f7:5f:b3:2a:
+ 8f:8e:37:de:d1:e6:28:31:50:9f:5e:43:38:4f:8e:
+ 3f:2d:59:47:c9:4f:7a:cb:cb:a1:c2:34:95:cc:b5:
+ 05:0c:c5:7b:43:6a:ba:d1:e9:1c:f5:f2:fa:ba:15:
+ b0:ef:c6:82:03:d6:f4:4c:0b:23:88:f6:ef:79:2c:
+ 57:65:22:6a:30:d1:03:7f:7d:3c:5e:af:04:0e:0b:
+ 31:8d:c8:03:16:a5:5a:31:e9:bf:75:6a:2e:58:8c:
+ 77:e1
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ 70:CA:C5:76:5A:8E:76:8D:4E:DB:E0:01:F2:31:AA:0B:E7:EE:F0:ED
+ X509v3 Authority Key Identifier:
+ keyid:70:CA:C5:76:5A:8E:76:8D:4E:DB:E0:01:F2:31:AA:0B:E7:EE:F0:ED
+
+ X509v3 Basic Constraints:
+ CA:TRUE
+ Signature Algorithm: sha1WithRSAEncryption
+ 68:2a:62:37:15:c4:c8:02:b0:8a:c9:6d:ae:06:ca:ed:5d:01:
+ e0:b2:e5:de:ec:a6:32:12:f2:05:62:33:4d:b3:95:35:dc:bf:
+ 8a:a1:dd:aa:5f:5f:f0:d2:00:1d:ea:bf:47:c5:0e:8e:8c:c4:
+ 3b:dc:d3:2a:f6:83:ce:02:ea:0d:97:e1:7a:50:58:14:a2:68:
+ b1:fe:f4:c3:e2:87:a2:87:ec:4b:89:49:f4:15:9d:ad:57:6f:
+ 2d:09:35:3d:15:ff:63:f3:02:cf:72:37:87:e8:d0:66:4f:1d:
+ f5:82:83:d1:b6:c1:d2:fa:35:10:e5:b2:d7:9a:11:8e:4b:3d:
+ 1a:dd:e1:5e:e1:f7:22:ea:fb:65:a7:10:89:f3:2b:3a:5b:18:
+ a3:d6:c2:68:33:dd:cf:14:b0:c9:cd:04:73:ad:d5:6c:57:d2:
+ 2f:66:2a:2c:cd:3f:ca:68:51:23:73:cb:3d:ef:c9:b0:f2:f4:
+ 31:1e:28:5c:4e:9f:5d:4e:49:02:eb:29:2e:a8:f2:f4:d2:32:
+ e4:b3:77:24:93:0f:1f:75:23:3f:59:d4:f7:40:03:98:32:3f:
+ 5b:6d:5b:c1:64:a2:8b:ff:8a:06:9a:7d:20:e8:fa:53:f4:bb:
+ 47:63:78:d2:e3:e7:5e:df:78:4c:71:ab:6c:61:ef:4a:c3:08:
+ 09:6f:48:cb
+SHA1 Fingerprint=F7:30:B2:A2:8B:4B:15:57:53:81:55:E4:81:9D:C6:5F:1B:9C:48:22
diff --git a/meta/meta-mediatek/recipes-connectivity/agps/files/cacerts/37ee4e18.0 b/meta/meta-mediatek/recipes-connectivity/agps/files/cacerts/37ee4e18.0
new file mode 100644
index 0000000..6780435
--- /dev/null
+++ b/meta/meta-mediatek/recipes-connectivity/agps/files/cacerts/37ee4e18.0
@@ -0,0 +1,55 @@
+-----BEGIN CERTIFICATE-----
+MIIC5zCCAlCgAwIBAgIEPhLkEjANBgkqhkiG9w0BAQQFADCBrTEoMCYGCSqGSIb3
+DQEJARYZc3VwcG9ydEByb2hkZS1zY2h3YXJ6LmNvbTELMAkGA1UEBhMCREUxETAP
+BgNVBAgMCEJhdmFyaWFuMQ8wDQYDVQQHDAZNdW5pY2gxDDAKBgNVBAoMA1ImUzEQ
+MA4GA1UECwwHUiZTIEFURTEwMC4GA1UEAwwnaC1zbHAubW5jMDAxLm1jYzAwMS5w
+dWIuM2dwcG5ldHdvcmsub3JnMB4XDTAzMDEwMTEyNTAyNloXDTI3MTIyNjEyNTAy
+Nlowga0xKDAmBgkqhkiG9w0BCQEWGXN1cHBvcnRAcm9oZGUtc2Nod2Fyei5jb20x
+CzAJBgNVBAYTAkRFMREwDwYDVQQIDAhCYXZhcmlhbjEPMA0GA1UEBwwGTXVuaWNo
+MQwwCgYDVQQKDANSJlMxEDAOBgNVBAsMB1ImUyBBVEUxMDAuBgNVBAMMJ2gtc2xw
+Lm1uYzAwMS5tY2MwMDEucHViLjNncHBuZXR3b3JrLm9yZzCBnzANBgkqhkiG9w0B
+AQEFAAOBjQAwgYkCgYEA5NH4/aSXbcFsKOlPcvBtswB0flDOYZItOrn+mdreNWFS
+crg3O7JJYiI/TrdeJiXR5VPwGxJ4GBUjZj3fA2mng7gJYD3Ox4AkkmzAB7HCwvUo
+WggUBhMjNmDDbMnEDelz8NiAZubNfNu28pTcB3SZOhWX3geZ0hipmkvVwerEF5UC
+AwEAAaMSMBAwDgYDVR0PAQH/BAQDAgSwMA0GCSqGSIb3DQEBBAUAA4GBAHfRtirz
+R66aOgpyu8RJkyKyZg4TzOZtlKBxIkkO30Q92iZf/pocfvKW2lSWhWo9jgMbhVAe
+KI4tuFf5JQMI6G01gJt4+66tYPnUBXHWg+MnBNNqmoMJUHDT4+kxRY7hM7bpvXD9
+tyV79vCitUjjqHwoINcK1WPOt13efou5YiZn
+-----END CERTIFICATE-----
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 1041425426 (0x3e12e412)
+ Signature Algorithm: md5WithRSAEncryption
+ Issuer: emailAddress=support@rohde-schwarz.com, C=DE, ST=Bavarian, L=Munich, O=R&S, OU=R&S ATE, CN=h-slp.mnc001.mcc001.pub.3gppnetwork.org
+ Validity
+ Not Before: Jan 1 12:50:26 2003 GMT
+ Not After : Dec 26 12:50:26 2027 GMT
+ Subject: emailAddress=support@rohde-schwarz.com, C=DE, ST=Bavarian, L=Munich, O=R&S, OU=R&S ATE, CN=h-slp.mnc001.mcc001.pub.3gppnetwork.org
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (1024 bit)
+ Modulus:
+ 00:e4:d1:f8:fd:a4:97:6d:c1:6c:28:e9:4f:72:f0:
+ 6d:b3:00:74:7e:50:ce:61:92:2d:3a:b9:fe:99:da:
+ de:35:61:52:72:b8:37:3b:b2:49:62:22:3f:4e:b7:
+ 5e:26:25:d1:e5:53:f0:1b:12:78:18:15:23:66:3d:
+ df:03:69:a7:83:b8:09:60:3d:ce:c7:80:24:92:6c:
+ c0:07:b1:c2:c2:f5:28:5a:08:14:06:13:23:36:60:
+ c3:6c:c9:c4:0d:e9:73:f0:d8:80:66:e6:cd:7c:db:
+ b6:f2:94:dc:07:74:99:3a:15:97:de:07:99:d2:18:
+ a9:9a:4b:d5:c1:ea:c4:17:95
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Key Usage: critical
+ Digital Signature, Key Encipherment, Data Encipherment
+ Signature Algorithm: md5WithRSAEncryption
+ 77:d1:b6:2a:f3:47:ae:9a:3a:0a:72:bb:c4:49:93:22:b2:66:
+ 0e:13:cc:e6:6d:94:a0:71:22:49:0e:df:44:3d:da:26:5f:fe:
+ 9a:1c:7e:f2:96:da:54:96:85:6a:3d:8e:03:1b:85:50:1e:28:
+ 8e:2d:b8:57:f9:25:03:08:e8:6d:35:80:9b:78:fb:ae:ad:60:
+ f9:d4:05:71:d6:83:e3:27:04:d3:6a:9a:83:09:50:70:d3:e3:
+ e9:31:45:8e:e1:33:b6:e9:bd:70:fd:b7:25:7b:f6:f0:a2:b5:
+ 48:e3:a8:7c:28:20:d7:0a:d5:63:ce:b7:5d:de:7e:8b:b9:62:
+ 26:67
+SHA1 Fingerprint=70:44:DD:F3:0C:74:4F:1B:1E:B8:53:00:46:F4:BE:51:97:91:EC:DF
diff --git a/meta/meta-mediatek/recipes-connectivity/agps/files/cacerts/42d25a61.0 b/meta/meta-mediatek/recipes-connectivity/agps/files/cacerts/42d25a61.0
new file mode 100644
index 0000000..32f31a9
--- /dev/null
+++ b/meta/meta-mediatek/recipes-connectivity/agps/files/cacerts/42d25a61.0
@@ -0,0 +1,39 @@
+-----BEGIN CERTIFICATE-----
+MIIB9TCCAZ8CAxAALDANBgkqhkiG9w0BAQsFADCBnzEfMB0GA1UEChMWU3BpcmVu
+dCBDb21tdW5pY2F0aW9uczEMMAoGA1UECxMDUEFXMSIwIAYJKoZIhvcNAQkBFhNz
+dXBwb3J0QHNwaXJlbnQuY29tMRIwEAYDVQQHEwlFYXRvbnRvd24xCzAJBgNVBAgT
+Ak5KMQswCQYDVQQGEwJVUzEcMBoGA1UEAxMTd3d3LnNwaXJlbnQtbGNzLmNvbTAg
+Fw0xNzAzMDMwOTM2MTdaGA8yMTE3MDIwNzA5MzYxN1owZzELMAkGA1UEBhMCVVMx
+CzAJBgNVBAgTAk5KMR8wHQYDVQQKExZTcGlyZW50IENvbW11bmljYXRpb25zMQww
+CgYDVQQLEwNQQVcxHDAaBgNVBAMTE3d3dy5zcGlyZW50LWxjcy5jb20wXDANBgkq
+hkiG9w0BAQEFAANLADBIAkEA7hDzb8s3NbG10ZcnRGtkbYn1kg0XEozAx28AzWcB
+qc+PAF3m0uViHwu8LE+mk9Lr8OISojo2U3LFM1LHY9x5lwIDAQABMA0GCSqGSIb3
+DQEBCwUAA0EAjjLDCHHn4g31B1WmWptRwuBDZnbYf0Tr97bqWqQ2IaHn9lrJKAnr
+CWcxKSyNRkeWJ8Wi9RGSpjUabD2UGQ0+Dg==
+-----END CERTIFICATE-----
+Certificate:
+ Data:
+ Version: 1 (0x0)
+ Serial Number: 1048620 (0x10002c)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: O=Spirent Communications, OU=PAW/emailAddress=support@spirent.com, L=Eatontown, ST=NJ, C=US, CN=www.spirent-lcs.com
+ Validity
+ Not Before: Mar 3 09:36:17 2017 GMT
+ Not After : Feb 7 09:36:17 2117 GMT
+ Subject: C=US, ST=NJ, O=Spirent Communications, OU=PAW, CN=www.spirent-lcs.com
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (512 bit)
+ Modulus:
+ 00:ee:10:f3:6f:cb:37:35:b1:b5:d1:97:27:44:6b:
+ 64:6d:89:f5:92:0d:17:12:8c:c0:c7:6f:00:cd:67:
+ 01:a9:cf:8f:00:5d:e6:d2:e5:62:1f:0b:bc:2c:4f:
+ a6:93:d2:eb:f0:e2:12:a2:3a:36:53:72:c5:33:52:
+ c7:63:dc:79:97
+ Exponent: 65537 (0x10001)
+ Signature Algorithm: sha256WithRSAEncryption
+ 8e:32:c3:08:71:e7:e2:0d:f5:07:55:a6:5a:9b:51:c2:e0:43:
+ 66:76:d8:7f:44:eb:f7:b6:ea:5a:a4:36:21:a1:e7:f6:5a:c9:
+ 28:09:eb:09:67:31:29:2c:8d:46:47:96:27:c5:a2:f5:11:92:
+ a6:35:1a:6c:3d:94:19:0d:3e:0e
+SHA1 Fingerprint=BD:8C:4D:9D:A5:85:0D:D6:3F:FC:69:1D:56:E0:0D:64:F2:1B:CF:B8
diff --git a/meta/meta-mediatek/recipes-connectivity/agps/files/cacerts/42d25a61.1 b/meta/meta-mediatek/recipes-connectivity/agps/files/cacerts/42d25a61.1
new file mode 100644
index 0000000..425d8e5
--- /dev/null
+++ b/meta/meta-mediatek/recipes-connectivity/agps/files/cacerts/42d25a61.1
@@ -0,0 +1,113 @@
+-----BEGIN CERTIFICATE-----
+MIIFfTCCA2UCAxAALjANBgkqhkiG9w0BAQUFADCBnzEfMB0GA1UEChMWU3BpcmVu
+dCBDb21tdW5pY2F0aW9uczEMMAoGA1UECxMDUEFXMSIwIAYJKoZIhvcNAQkBFhNz
+dXBwb3J0QHNwaXJlbnQuY29tMRIwEAYDVQQHEwlFYXRvbnRvd24xCzAJBgNVBAgT
+Ak5KMQswCQYDVQQGEwJVUzEcMBoGA1UEAxMTd3d3LnNwaXJlbnQtbGNzLmNvbTAe
+Fw0xMjAyMjAwNjQyNTNaFw0yMjAyMTcwNjQyNTNaMGcxCzAJBgNVBAYTAlVTMQsw
+CQYDVQQIEwJOSjEfMB0GA1UEChMWU3BpcmVudCBDb21tdW5pY2F0aW9uczEMMAoG
+A1UECxMDUEFXMRwwGgYDVQQDExN3d3cuc3BpcmVudC1sY3MuY29tMIICIjANBgkq
+hkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA3nTp+T2Vt6QtidOib1Xy6OhBDQHeWEsw
+Bm3GUa3Lyaz3uYX0b/C2RHPdOHXWQBF+6mwtZqfyeXvWZ1+gZ/dWxTiWZWojxgAt
+zS4a9sjVjvEbyOsg/XXlLsf9TYJdr+i7EVx1rThOX40aGjrC+Xautj3Urb2ZzDoS
+Hy6weGwwGHRvWKvEdf8jv++cqy6UF+zpVHXhEcZqSiBLv7KTUNnKsx8nAKzMLlrz
+q56XI4dJrc2nVaPIOw72UfkPsK2sAYLCwE0T2i3fT2ORPy+r0DmLeU22sbEx9HRZ
+E6UyWTjiuGCDnHf6qvfj0MxXCmYyBFsLHKt2//sYQ+7yczhcEPZHf9sIvs4n+ZZl
+qQY6IUUTJTStFDEXJDy++Tocu6aZ4RgXs5oWdIKmVxWx/t8+WpGBJpkkEjF76a/x
+SNGVIhNNpL//TV6V4pnrklPhN2ealSwaa9BHkNQmlMzKOOeNhcbRspP2l01hn63d
+HIFFmGbxlD94QKJvDoDHM6lJY9ZfkvfBpSzuFGa0zfkmneiQ8wMVdUsx7P0EPT1I
+dJpko/mjYplRfTL9bP+CQfw6I2vBWBHkmBxFaF4LBoxodMvnrN+fKKZRIz8b0Z1K
+uxxPi7yZkaby6UCZjfB1GVmg0n++1/SfkuU9YGF3viNm8UL9UmmthXix4+9k3Vby
+huKppEMOfG0CAwEAATANBgkqhkiG9w0BAQUFAAOCAgEAmBmYoMCQP7J9SWbkJnDA
+mI6+UyAgjEiChAIL98tNsJztHV/RT7/bFy5V8E42gbtxQc+rHciebbbAK7rtIk8M
+gYQ8nrBmyeCzgBNfvctGprt/r7WhL+sF6tFVqaxZkLtsuqCwnFP1st/8Wj8D2l6a
+3X3l4vlH8p92JBU1NXNiSNSK7a2bgXsuyT7g1c1+Wj3nRVqzjgGtoT54ULjqrpep
+Vg+YRmnrxMoVH0VsKh6cA5srHr1D5fIfquGY1yUdYiGZIoB9NsUMs7d9K+RFxfol
+BsOJo+eo0ZIgUZJ3vxtyFWIfXdGg0mTNgGnTYGuzxFMeEvUZqfOhZv7C31HpSGs3
+WQ95873Nr5xP2lfMfTP34HNW6pk5EF4KetaT9i1YHeBJBUcHFEj2PYCKJdorwlF6
+A2znIOyRZMkeCE/yy58jAztvHniKFDAvimEBFlVXEBbjGztmpHnRHcmdWu2+DsCL
+f5JZKe2S20AUQWmX/LIWSp//RbtQe9VTTXqFK9Sqedn+FQjbQKV6SVwvGX/rR5E6
++yfkeAWrsWywn/VHN9G32dg1VzHwCOAzfjz5rYbrsu9wN5fPAX4xAMLiXo5ACnG7
+XyToIyX2findzewkarLDCcNdg6dDFVBE3oH3A80djBDGlGFW9ldxlB0NpriJOjhY
+AaUIEEzciSMFez2QaTJSqv8=
+-----END CERTIFICATE-----
+Certificate:
+ Data:
+ Version: 1 (0x0)
+ Serial Number: 1048622 (0x10002e)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: O=Spirent Communications, OU=PAW/emailAddress=support@spirent.com, L=Eatontown, ST=NJ, C=US, CN=www.spirent-lcs.com
+ Validity
+ Not Before: Feb 20 06:42:53 2012 GMT
+ Not After : Feb 17 06:42:53 2022 GMT
+ Subject: C=US, ST=NJ, O=Spirent Communications, OU=PAW, CN=www.spirent-lcs.com
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (4096 bit)
+ Modulus:
+ 00:de:74:e9:f9:3d:95:b7:a4:2d:89:d3:a2:6f:55:
+ f2:e8:e8:41:0d:01:de:58:4b:30:06:6d:c6:51:ad:
+ cb:c9:ac:f7:b9:85:f4:6f:f0:b6:44:73:dd:38:75:
+ d6:40:11:7e:ea:6c:2d:66:a7:f2:79:7b:d6:67:5f:
+ a0:67:f7:56:c5:38:96:65:6a:23:c6:00:2d:cd:2e:
+ 1a:f6:c8:d5:8e:f1:1b:c8:eb:20:fd:75:e5:2e:c7:
+ fd:4d:82:5d:af:e8:bb:11:5c:75:ad:38:4e:5f:8d:
+ 1a:1a:3a:c2:f9:76:ae:b6:3d:d4:ad:bd:99:cc:3a:
+ 12:1f:2e:b0:78:6c:30:18:74:6f:58:ab:c4:75:ff:
+ 23:bf:ef:9c:ab:2e:94:17:ec:e9:54:75:e1:11:c6:
+ 6a:4a:20:4b:bf:b2:93:50:d9:ca:b3:1f:27:00:ac:
+ cc:2e:5a:f3:ab:9e:97:23:87:49:ad:cd:a7:55:a3:
+ c8:3b:0e:f6:51:f9:0f:b0:ad:ac:01:82:c2:c0:4d:
+ 13:da:2d:df:4f:63:91:3f:2f:ab:d0:39:8b:79:4d:
+ b6:b1:b1:31:f4:74:59:13:a5:32:59:38:e2:b8:60:
+ 83:9c:77:fa:aa:f7:e3:d0:cc:57:0a:66:32:04:5b:
+ 0b:1c:ab:76:ff:fb:18:43:ee:f2:73:38:5c:10:f6:
+ 47:7f:db:08:be:ce:27:f9:96:65:a9:06:3a:21:45:
+ 13:25:34:ad:14:31:17:24:3c:be:f9:3a:1c:bb:a6:
+ 99:e1:18:17:b3:9a:16:74:82:a6:57:15:b1:fe:df:
+ 3e:5a:91:81:26:99:24:12:31:7b:e9:af:f1:48:d1:
+ 95:22:13:4d:a4:bf:ff:4d:5e:95:e2:99:eb:92:53:
+ e1:37:67:9a:95:2c:1a:6b:d0:47:90:d4:26:94:cc:
+ ca:38:e7:8d:85:c6:d1:b2:93:f6:97:4d:61:9f:ad:
+ dd:1c:81:45:98:66:f1:94:3f:78:40:a2:6f:0e:80:
+ c7:33:a9:49:63:d6:5f:92:f7:c1:a5:2c:ee:14:66:
+ b4:cd:f9:26:9d:e8:90:f3:03:15:75:4b:31:ec:fd:
+ 04:3d:3d:48:74:9a:64:a3:f9:a3:62:99:51:7d:32:
+ fd:6c:ff:82:41:fc:3a:23:6b:c1:58:11:e4:98:1c:
+ 45:68:5e:0b:06:8c:68:74:cb:e7:ac:df:9f:28:a6:
+ 51:23:3f:1b:d1:9d:4a:bb:1c:4f:8b:bc:99:91:a6:
+ f2:e9:40:99:8d:f0:75:19:59:a0:d2:7f:be:d7:f4:
+ 9f:92:e5:3d:60:61:77:be:23:66:f1:42:fd:52:69:
+ ad:85:78:b1:e3:ef:64:dd:56:f2:86:e2:a9:a4:43:
+ 0e:7c:6d
+ Exponent: 65537 (0x10001)
+ Signature Algorithm: sha1WithRSAEncryption
+ 98:19:98:a0:c0:90:3f:b2:7d:49:66:e4:26:70:c0:98:8e:be:
+ 53:20:20:8c:48:82:84:02:0b:f7:cb:4d:b0:9c:ed:1d:5f:d1:
+ 4f:bf:db:17:2e:55:f0:4e:36:81:bb:71:41:cf:ab:1d:c8:9e:
+ 6d:b6:c0:2b:ba:ed:22:4f:0c:81:84:3c:9e:b0:66:c9:e0:b3:
+ 80:13:5f:bd:cb:46:a6:bb:7f:af:b5:a1:2f:eb:05:ea:d1:55:
+ a9:ac:59:90:bb:6c:ba:a0:b0:9c:53:f5:b2:df:fc:5a:3f:03:
+ da:5e:9a:dd:7d:e5:e2:f9:47:f2:9f:76:24:15:35:35:73:62:
+ 48:d4:8a:ed:ad:9b:81:7b:2e:c9:3e:e0:d5:cd:7e:5a:3d:e7:
+ 45:5a:b3:8e:01:ad:a1:3e:78:50:b8:ea:ae:97:a9:56:0f:98:
+ 46:69:eb:c4:ca:15:1f:45:6c:2a:1e:9c:03:9b:2b:1e:bd:43:
+ e5:f2:1f:aa:e1:98:d7:25:1d:62:21:99:22:80:7d:36:c5:0c:
+ b3:b7:7d:2b:e4:45:c5:fa:25:06:c3:89:a3:e7:a8:d1:92:20:
+ 51:92:77:bf:1b:72:15:62:1f:5d:d1:a0:d2:64:cd:80:69:d3:
+ 60:6b:b3:c4:53:1e:12:f5:19:a9:f3:a1:66:fe:c2:df:51:e9:
+ 48:6b:37:59:0f:79:f3:bd:cd:af:9c:4f:da:57:cc:7d:33:f7:
+ e0:73:56:ea:99:39:10:5e:0a:7a:d6:93:f6:2d:58:1d:e0:49:
+ 05:47:07:14:48:f6:3d:80:8a:25:da:2b:c2:51:7a:03:6c:e7:
+ 20:ec:91:64:c9:1e:08:4f:f2:cb:9f:23:03:3b:6f:1e:78:8a:
+ 14:30:2f:8a:61:01:16:55:57:10:16:e3:1b:3b:66:a4:79:d1:
+ 1d:c9:9d:5a:ed:be:0e:c0:8b:7f:92:59:29:ed:92:db:40:14:
+ 41:69:97:fc:b2:16:4a:9f:ff:45:bb:50:7b:d5:53:4d:7a:85:
+ 2b:d4:aa:79:d9:fe:15:08:db:40:a5:7a:49:5c:2f:19:7f:eb:
+ 47:91:3a:fb:27:e4:78:05:ab:b1:6c:b0:9f:f5:47:37:d1:b7:
+ d9:d8:35:57:31:f0:08:e0:33:7e:3c:f9:ad:86:eb:b2:ef:70:
+ 37:97:cf:01:7e:31:00:c2:e2:5e:8e:40:0a:71:bb:5f:24:e8:
+ 23:25:f6:7e:29:dd:cd:ec:24:6a:b2:c3:09:c3:5d:83:a7:43:
+ 15:50:44:de:81:f7:03:cd:1d:8c:10:c6:94:61:56:f6:57:71:
+ 94:1d:0d:a6:b8:89:3a:38:58:01:a5:08:10:4c:dc:89:23:05:
+ 7b:3d:90:69:32:52:aa:ff
+SHA1 Fingerprint=D9:4E:75:24:AE:F4:3E:BC:70:19:82:B8:85:CE:F9:E4:30:BC:AF:5D
diff --git a/meta/meta-mediatek/recipes-connectivity/agps/files/cacerts/47d59e14.0 b/meta/meta-mediatek/recipes-connectivity/agps/files/cacerts/47d59e14.0
new file mode 100644
index 0000000..9e07619
--- /dev/null
+++ b/meta/meta-mediatek/recipes-connectivity/agps/files/cacerts/47d59e14.0
@@ -0,0 +1,61 @@
+-----BEGIN CERTIFICATE-----
+MIIC2jCCAkOgAwIBAgIJALifyeI1CpzLMA0GCSqGSIb3DQEBCwUAMIGFMQswCQYD
+VQQGEwJUVzESMBAGA1UECAwJTmV3VGFpcGVpMQwwCgYDVQQKDANFUlQxDDAKBgNV
+BAsMA0lPVDEfMB0GA1UEAwwWZ21wYzAyLmVydC5lcmljc3Nvbi5zZTElMCMGCSqG
+SIb3DQEJARYWYXBwbGUueWluQGVyaWNzc29uLmNvbTAeFw0xODA1MjMwMzU4NTZa
+Fw0yMTA1MjIwMzU4NTZaMIGFMQswCQYDVQQGEwJUVzESMBAGA1UECAwJTmV3VGFp
+cGVpMQwwCgYDVQQKDANFUlQxDDAKBgNVBAsMA0lPVDEfMB0GA1UEAwwWZ21wYzAy
+LmVydC5lcmljc3Nvbi5zZTElMCMGCSqGSIb3DQEJARYWYXBwbGUueWluQGVyaWNz
+c29uLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAzMh7iP+lhdC/l104
+I1wDMPNzsEhcN21rRLaanvEx2ERwpGSqiNoj7G2PHf4ASCUgXoRZAWWdTjvoYYdt
+QE6/ZmxdbJac8Mj5oRnPdl436AF/tSqlxHwNphyNiYBl8y1x2App3s1htZ+vcKRX
+XGiRS/sSwYhWXioq4hV1EmCNXUsCAwEAAaNQME4wHQYDVR0OBBYEFHIwSo9Np1t0
+wKtHOdlXA+to96J5MB8GA1UdIwQYMBaAFHIwSo9Np1t0wKtHOdlXA+to96J5MAwG
+A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADgYEAZo/yvpw9tzDf0laiUtGPCKap
++oDyKAh3o5vkt6/SSdCkw/zI+w76jq/LPLqKpGHPG9kON1n9LRHlyKvAeQKfJfKJ
++0zdaL5bhoSgAyCHgcwKvyLSonEqLXyRpLbNGIw6Ah4EQvQhS5UdP/2mv3REPE3e
+XgL2E3EZrJs1PosJTXA=
+-----END CERTIFICATE-----
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ b8:9f:c9:e2:35:0a:9c:cb
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C=TW, ST=NewTaipei, O=ERT, OU=IOT, CN=gmpc02.ert.ericsson.se/emailAddress=apple.yin@ericsson.com
+ Validity
+ Not Before: May 23 03:58:56 2018 GMT
+ Not After : May 22 03:58:56 2021 GMT
+ Subject: C=TW, ST=NewTaipei, O=ERT, OU=IOT, CN=gmpc02.ert.ericsson.se/emailAddress=apple.yin@ericsson.com
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (1024 bit)
+ Modulus:
+ 00:cc:c8:7b:88:ff:a5:85:d0:bf:97:5d:38:23:5c:
+ 03:30:f3:73:b0:48:5c:37:6d:6b:44:b6:9a:9e:f1:
+ 31:d8:44:70:a4:64:aa:88:da:23:ec:6d:8f:1d:fe:
+ 00:48:25:20:5e:84:59:01:65:9d:4e:3b:e8:61:87:
+ 6d:40:4e:bf:66:6c:5d:6c:96:9c:f0:c8:f9:a1:19:
+ cf:76:5e:37:e8:01:7f:b5:2a:a5:c4:7c:0d:a6:1c:
+ 8d:89:80:65:f3:2d:71:d8:0a:69:de:cd:61:b5:9f:
+ af:70:a4:57:5c:68:91:4b:fb:12:c1:88:56:5e:2a:
+ 2a:e2:15:75:12:60:8d:5d:4b
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ 72:30:4A:8F:4D:A7:5B:74:C0:AB:47:39:D9:57:03:EB:68:F7:A2:79
+ X509v3 Authority Key Identifier:
+ keyid:72:30:4A:8F:4D:A7:5B:74:C0:AB:47:39:D9:57:03:EB:68:F7:A2:79
+
+ X509v3 Basic Constraints:
+ CA:TRUE
+ Signature Algorithm: sha256WithRSAEncryption
+ 66:8f:f2:be:9c:3d:b7:30:df:d2:56:a2:52:d1:8f:08:a6:a9:
+ fa:80:f2:28:08:77:a3:9b:e4:b7:af:d2:49:d0:a4:c3:fc:c8:
+ fb:0e:fa:8e:af:cb:3c:ba:8a:a4:61:cf:1b:d9:0e:37:59:fd:
+ 2d:11:e5:c8:ab:c0:79:02:9f:25:f2:89:fb:4c:dd:68:be:5b:
+ 86:84:a0:03:20:87:81:cc:0a:bf:22:d2:a2:71:2a:2d:7c:91:
+ a4:b6:cd:18:8c:3a:02:1e:04:42:f4:21:4b:95:1d:3f:fd:a6:
+ bf:74:44:3c:4d:de:5e:02:f6:13:71:19:ac:9b:35:3e:8b:09:
+ 4d:70
+SHA1 Fingerprint=F3:EE:B7:21:95:D5:E8:FD:B8:4E:A4:4A:27:94:97:A5:FA:EB:F9:59
diff --git a/meta/meta-mediatek/recipes-connectivity/agps/files/cacerts/5238210a.0 b/meta/meta-mediatek/recipes-connectivity/agps/files/cacerts/5238210a.0
new file mode 100644
index 0000000..ad4338d
--- /dev/null
+++ b/meta/meta-mediatek/recipes-connectivity/agps/files/cacerts/5238210a.0
@@ -0,0 +1,60 @@
+-----BEGIN CERTIFICATE-----
+MIICojCCAgugAwIBAgIJAOKRTsbHFjRqMA0GCSqGSIb3DQEBBQUAMGkxCzAJBgNV
+BAYTAkRFMRAwDgYDVQQIEwdCYXZhcmlhMQ8wDQYDVQQHEwZNdW5pY2gxFjAUBgNV
+BAoMDVJvaGRlJlNjaHdhcnoxDDAKBgNVBAsTA0FURTERMA8GA1UEAxMIQVRFLVRF
+U1QwIBcNNzkxMjMxMjMwMDIxWhgPMjA2OTEyMDgyMzAwMjFaMGkxCzAJBgNVBAYT
+AkRFMRAwDgYDVQQIEwdCYXZhcmlhMQ8wDQYDVQQHEwZNdW5pY2gxFjAUBgNVBAoM
+DVJvaGRlJlNjaHdhcnoxDDAKBgNVBAsTA0FURTERMA8GA1UEAxMIQVRFLVRFU1Qw
+gZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAK9TFF6860g96uSnV5kKPHzN06JS
+jI0EmxcbyKhYeOu4LB4pyGVeyxUTZhQ1f8huDix/sWZonQ69p79X/zd/gN5bxS88
+uCqrgFZPwrmYDlGDR7rHZqCOwgx+qI9nxeDSmoLlsonrg6MG2rqOa4LqEHa1xrl1
+lGWXLCuHHZrV+KffAgMBAAGjUDBOMB0GA1UdDgQWBBT9fQc68TXzRbksHo0DJov1
+ZWx0vjAfBgNVHSMEGDAWgBT9fQc68TXzRbksHo0DJov1ZWx0vjAMBgNVHRMEBTAD
+AQH/MA0GCSqGSIb3DQEBBQUAA4GBAHbN7hCWrOCJbZv3sNm9Zt6pgq1DKVDjfBky
+x9wi7YuM1EaL7Tnn/2m/+nRincBr9IKCQigIrR5m43ZMJMyZMKYIG1OV1ad2b5Fa
+iQTNeyzo/hekFy1XSEon9McrScls4sGn+2WPO4EShyLxTD6/lqmBBQjl7288g+Hr
+UCq43huD
+-----END CERTIFICATE-----
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ e2:91:4e:c6:c7:16:34:6a
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=DE, ST=Bavaria, L=Munich, O=Rohde&Schwarz, OU=ATE, CN=ATE-TEST
+ Validity
+ Not Before: Dec 31 23:00:21 1979 GMT
+ Not After : Dec 8 23:00:21 2069 GMT
+ Subject: C=DE, ST=Bavaria, L=Munich, O=Rohde&Schwarz, OU=ATE, CN=ATE-TEST
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (1024 bit)
+ Modulus:
+ 00:af:53:14:5e:bc:eb:48:3d:ea:e4:a7:57:99:0a:
+ 3c:7c:cd:d3:a2:52:8c:8d:04:9b:17:1b:c8:a8:58:
+ 78:eb:b8:2c:1e:29:c8:65:5e:cb:15:13:66:14:35:
+ 7f:c8:6e:0e:2c:7f:b1:66:68:9d:0e:bd:a7:bf:57:
+ ff:37:7f:80:de:5b:c5:2f:3c:b8:2a:ab:80:56:4f:
+ c2:b9:98:0e:51:83:47:ba:c7:66:a0:8e:c2:0c:7e:
+ a8:8f:67:c5:e0:d2:9a:82:e5:b2:89:eb:83:a3:06:
+ da:ba:8e:6b:82:ea:10:76:b5:c6:b9:75:94:65:97:
+ 2c:2b:87:1d:9a:d5:f8:a7:df
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ FD:7D:07:3A:F1:35:F3:45:B9:2C:1E:8D:03:26:8B:F5:65:6C:74:BE
+ X509v3 Authority Key Identifier:
+ keyid:FD:7D:07:3A:F1:35:F3:45:B9:2C:1E:8D:03:26:8B:F5:65:6C:74:BE
+
+ X509v3 Basic Constraints:
+ CA:TRUE
+ Signature Algorithm: sha1WithRSAEncryption
+ 76:cd:ee:10:96:ac:e0:89:6d:9b:f7:b0:d9:bd:66:de:a9:82:
+ ad:43:29:50:e3:7c:19:32:c7:dc:22:ed:8b:8c:d4:46:8b:ed:
+ 39:e7:ff:69:bf:fa:74:62:9d:c0:6b:f4:82:82:42:28:08:ad:
+ 1e:66:e3:76:4c:24:cc:99:30:a6:08:1b:53:95:d5:a7:76:6f:
+ 91:5a:89:04:cd:7b:2c:e8:fe:17:a4:17:2d:57:48:4a:27:f4:
+ c7:2b:49:c9:6c:e2:c1:a7:fb:65:8f:3b:81:12:87:22:f1:4c:
+ 3e:bf:96:a9:81:05:08:e5:ef:6f:3c:83:e1:eb:50:2a:b8:de:
+ 1b:83
+SHA1 Fingerprint=97:02:38:19:2F:A2:89:D7:83:64:B1:EA:65:5D:05:52:68:25:DD:B4
diff --git a/meta/meta-mediatek/recipes-connectivity/agps/files/cacerts/5238210a.1 b/meta/meta-mediatek/recipes-connectivity/agps/files/cacerts/5238210a.1
new file mode 100644
index 0000000..acb0970
--- /dev/null
+++ b/meta/meta-mediatek/recipes-connectivity/agps/files/cacerts/5238210a.1
@@ -0,0 +1,50 @@
+-----BEGIN CERTIFICATE-----
+MIICSzCCAbQCCQCCNadq6ShcgjANBgkqhkiG9w0BAQUFADBpMQswCQYDVQQGEwJE
+RTEQMA4GA1UECBMHQmF2YXJpYTEPMA0GA1UEBxMGTXVuaWNoMRYwFAYDVQQKDA1S
+b2hkZSZTY2h3YXJ6MQwwCgYDVQQLEwNBVEUxETAPBgNVBAMTCEFURS1URVNUMCAX
+DTc5MTIzMTIzMDAxNVoYDzIwNjkxMjA4MjMwMDE1WjBpMQswCQYDVQQGEwJERTEQ
+MA4GA1UECBMHQmF2YXJpYTEPMA0GA1UEBxMGTXVuaWNoMRYwFAYDVQQKDA1Sb2hk
+ZSZTY2h3YXJ6MQwwCgYDVQQLEwNBVEUxETAPBgNVBAMTCEFURS1URVNUMIGfMA0G
+CSqGSIb3DQEBAQUAA4GNADCBiQKBgQCvUxRevOtIPerkp1eZCjx8zdOiUoyNBJsX
+G8ioWHjruCweKchlXssVE2YUNX/Ibg4sf7FmaJ0Ovae/V/83f4DeW8UvPLgqq4BW
+T8K5mA5Rg0e6x2agjsIMfqiPZ8Xg0pqC5bKJ64OjBtq6jmuC6hB2tca5dZRllywr
+hx2a1fin3wIDAQABMA0GCSqGSIb3DQEBBQUAA4GBABiI4c2AXO2eZHxrQnqY22ph
+0YgkilqJbrv5lyM4St7XdXmqJomN0KkquT0l4OcajjCWi1TFthYaRep35rfaSHv+
+PX/5Uwp+mvjQXApIvcVgRtty2Wlpzyy9lGmPf4N503Gq355mKcMcqbhma2pTG6p+
+1bHGxbU8T+1MdPkoiMBB
+-----END CERTIFICATE-----
+Certificate:
+ Data:
+ Version: 1 (0x0)
+ Serial Number:
+ 82:35:a7:6a:e9:28:5c:82
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=DE, ST=Bavaria, L=Munich, O=Rohde&Schwarz, OU=ATE, CN=ATE-TEST
+ Validity
+ Not Before: Dec 31 23:00:15 1979 GMT
+ Not After : Dec 8 23:00:15 2069 GMT
+ Subject: C=DE, ST=Bavaria, L=Munich, O=Rohde&Schwarz, OU=ATE, CN=ATE-TEST
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (1024 bit)
+ Modulus:
+ 00:af:53:14:5e:bc:eb:48:3d:ea:e4:a7:57:99:0a:
+ 3c:7c:cd:d3:a2:52:8c:8d:04:9b:17:1b:c8:a8:58:
+ 78:eb:b8:2c:1e:29:c8:65:5e:cb:15:13:66:14:35:
+ 7f:c8:6e:0e:2c:7f:b1:66:68:9d:0e:bd:a7:bf:57:
+ ff:37:7f:80:de:5b:c5:2f:3c:b8:2a:ab:80:56:4f:
+ c2:b9:98:0e:51:83:47:ba:c7:66:a0:8e:c2:0c:7e:
+ a8:8f:67:c5:e0:d2:9a:82:e5:b2:89:eb:83:a3:06:
+ da:ba:8e:6b:82:ea:10:76:b5:c6:b9:75:94:65:97:
+ 2c:2b:87:1d:9a:d5:f8:a7:df
+ Exponent: 65537 (0x10001)
+ Signature Algorithm: sha1WithRSAEncryption
+ 18:88:e1:cd:80:5c:ed:9e:64:7c:6b:42:7a:98:db:6a:61:d1:
+ 88:24:8a:5a:89:6e:bb:f9:97:23:38:4a:de:d7:75:79:aa:26:
+ 89:8d:d0:a9:2a:b9:3d:25:e0:e7:1a:8e:30:96:8b:54:c5:b6:
+ 16:1a:45:ea:77:e6:b7:da:48:7b:fe:3d:7f:f9:53:0a:7e:9a:
+ f8:d0:5c:0a:48:bd:c5:60:46:db:72:d9:69:69:cf:2c:bd:94:
+ 69:8f:7f:83:79:d3:71:aa:df:9e:66:29:c3:1c:a9:b8:66:6b:
+ 6a:53:1b:aa:7e:d5:b1:c6:c5:b5:3c:4f:ed:4c:74:f9:28:88:
+ c0:41
+SHA1 Fingerprint=18:B8:97:CB:27:F4:F7:1A:31:04:B4:BA:A2:81:FE:28:3E:48:0D:F3
diff --git a/meta/meta-mediatek/recipes-connectivity/agps/files/cacerts/7b637099.0 b/meta/meta-mediatek/recipes-connectivity/agps/files/cacerts/7b637099.0
new file mode 100644
index 0000000..6f41d24
--- /dev/null
+++ b/meta/meta-mediatek/recipes-connectivity/agps/files/cacerts/7b637099.0
@@ -0,0 +1,50 @@
+-----BEGIN CERTIFICATE-----
+MIICkjCCAfsCBD4S3EQwDQYJKoZIhvcNAQEEBQAwgY8xKDAmBgkqhkiG9w0BCQEW
+GXN1cHBvcnRAcm9oZGUtc2Nod2Fyei5jb20xCzAJBgNVBAYTAkRFMREwDwYDVQQI
+DAhCYXZhcmlhbjEPMA0GA1UEBwwGTXVuaWNoMQwwCgYDVQQKDANSJlMxEDAOBgNV
+BAsMB1ImUyBBVEUxEjAQBgNVBAMMCXNscC5ycy5kZTAeFw0wMzAxMDExMjE3MDha
+Fw0yNzEyMjYxMjE3MDhaMIGPMSgwJgYJKoZIhvcNAQkBFhlzdXBwb3J0QHJvaGRl
+LXNjaHdhcnouY29tMQswCQYDVQQGEwJERTERMA8GA1UECAwIQmF2YXJpYW4xDzAN
+BgNVBAcMBk11bmljaDEMMAoGA1UECgwDUiZTMRAwDgYDVQQLDAdSJlMgQVRFMRIw
+EAYDVQQDDAlzbHAucnMuZGUwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAJyn
+kTj84x8KPxnX3vJQ7/g/AMTPX4OnoRUFt6feusB9tlzD6jt4q3Fd7Exjmm45KwLe
+PGIz91JbghwN9XG520+E+8yA8a7QPDU4w9TQFA4m9adwJFAPRW+uoAn+Uw89Xzzz
+8usgkcZFtFNPJ2dzijDQUdv7EWPogBVRPRBvWfuVAgMBAAEwDQYJKoZIhvcNAQEE
+BQADgYEAaQEoxHPEFMQYunxCvORyxaUDJMjzWF+U8aRZvRGZ3t0NeosCGliOG3GG
+0Uk4MnpmkInLFr/UXn+2q772+L5iIfmwhkprFLS7np09fueEsNMpvZlz3ze/sNfV
+qYztfwkrbgXowvSoSAvWvZiZ7rFy+0AJ0MisUGB4M3JKw6tgOKY=
+-----END CERTIFICATE-----
+Certificate:
+ Data:
+ Version: 1 (0x0)
+ Serial Number: 1041423428 (0x3e12dc44)
+ Signature Algorithm: md5WithRSAEncryption
+ Issuer: emailAddress=support@rohde-schwarz.com, C=DE, ST=Bavarian, L=Munich, O=R&S, OU=R&S ATE, CN=slp.rs.de
+ Validity
+ Not Before: Jan 1 12:17:08 2003 GMT
+ Not After : Dec 26 12:17:08 2027 GMT
+ Subject: emailAddress=support@rohde-schwarz.com, C=DE, ST=Bavarian, L=Munich, O=R&S, OU=R&S ATE, CN=slp.rs.de
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (1024 bit)
+ Modulus:
+ 00:9c:a7:91:38:fc:e3:1f:0a:3f:19:d7:de:f2:50:
+ ef:f8:3f:00:c4:cf:5f:83:a7:a1:15:05:b7:a7:de:
+ ba:c0:7d:b6:5c:c3:ea:3b:78:ab:71:5d:ec:4c:63:
+ 9a:6e:39:2b:02:de:3c:62:33:f7:52:5b:82:1c:0d:
+ f5:71:b9:db:4f:84:fb:cc:80:f1:ae:d0:3c:35:38:
+ c3:d4:d0:14:0e:26:f5:a7:70:24:50:0f:45:6f:ae:
+ a0:09:fe:53:0f:3d:5f:3c:f3:f2:eb:20:91:c6:45:
+ b4:53:4f:27:67:73:8a:30:d0:51:db:fb:11:63:e8:
+ 80:15:51:3d:10:6f:59:fb:95
+ Exponent: 65537 (0x10001)
+ Signature Algorithm: md5WithRSAEncryption
+ 69:01:28:c4:73:c4:14:c4:18:ba:7c:42:bc:e4:72:c5:a5:03:
+ 24:c8:f3:58:5f:94:f1:a4:59:bd:11:99:de:dd:0d:7a:8b:02:
+ 1a:58:8e:1b:71:86:d1:49:38:32:7a:66:90:89:cb:16:bf:d4:
+ 5e:7f:b6:ab:be:f6:f8:be:62:21:f9:b0:86:4a:6b:14:b4:bb:
+ 9e:9d:3d:7e:e7:84:b0:d3:29:bd:99:73:df:37:bf:b0:d7:d5:
+ a9:8c:ed:7f:09:2b:6e:05:e8:c2:f4:a8:48:0b:d6:bd:98:99:
+ ee:b1:72:fb:40:09:d0:c8:ac:50:60:78:33:72:4a:c3:ab:60:
+ 38:a6
+SHA1 Fingerprint=81:6C:C2:FE:CA:68:FB:C4:33:65:2A:B9:6B:51:1D:61:47:92:FB:EE
diff --git a/meta/meta-mediatek/recipes-connectivity/agps/files/cacerts/9ba3db56.0 b/meta/meta-mediatek/recipes-connectivity/agps/files/cacerts/9ba3db56.0
new file mode 100644
index 0000000..ed44e27
--- /dev/null
+++ b/meta/meta-mediatek/recipes-connectivity/agps/files/cacerts/9ba3db56.0
@@ -0,0 +1,63 @@
+-----BEGIN CERTIFICATE-----
+MIICzjCCAjegAwIBAgIJAJSPXrpHroFUMA0GCSqGSIb3DQEBBQUAME8xEDAOBgNV
+BAoTB1NwaXJlbnQxDTALBgNVBAsTBFBBV1AxEjAQBgNVBAcTCUVhdG9udG93bjEL
+MAkGA1UECBMCTkoxCzAJBgNVBAYTAlVTMB4XDTExMDIwNDIzNDcyMFoXDTIxMDIw
+MTIzNDcyMFowTzEQMA4GA1UEChMHU3BpcmVudDENMAsGA1UECxMEUEFXUDESMBAG
+A1UEBxMJRWF0b250b3duMQswCQYDVQQIEwJOSjELMAkGA1UEBhMCVVMwgZ8wDQYJ
+KoZIhvcNAQEBBQADgY0AMIGJAoGBANFIX5YtfzevR7jxitqQVVvdjkkN28vQzFKx
+N2rp6Cuqg6c2YQP6VqN51ZC+7R6eTO9KAuvlYcfhE2ux6hDyI01wkkO3erMZARuQ
+ZQ1sRWvM3xKI0l9Ti8W330U29DDw93mmpduRkclnggIpR/Txo3F07up2t4VHbC1k
+ibmcmhN1AgMBAAGjgbEwga4wDAYDVR0TBAUwAwEB/zAdBgNVHQ4EFgQUbviGjBjo
+DXOC6hcaqWKKfOpX8Z4wfwYDVR0jBHgwdoAUbviGjBjoDXOC6hcaqWKKfOpX8Z6h
+U6RRME8xEDAOBgNVBAoTB1NwaXJlbnQxDTALBgNVBAsTBFBBV1AxEjAQBgNVBAcT
+CUVhdG9udG93bjELMAkGA1UECBMCTkoxCzAJBgNVBAYTAlVTggkAlI9eukeugVQw
+DQYJKoZIhvcNAQEFBQADgYEASPCO8YOKV34K5lpccUGa9P8i1uaqJ2FMjhNtcC+7
+djn3gP0IfdWhrRCoxfQPuT7/MEtLshAMvzjp0ljbPR0816iU68dTsgYDgyelRV5G
+SjSkumTq7e70p55HoBLzWhFAazzs/h/nyJFqJLnlLnyFlEGHXLAezfofM0sx5CaW
+5OY=
+-----END CERTIFICATE-----
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ 94:8f:5e:ba:47:ae:81:54
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: O=Spirent, OU=PAWP, L=Eatontown, ST=NJ, C=US
+ Validity
+ Not Before: Feb 4 23:47:20 2011 GMT
+ Not After : Feb 1 23:47:20 2021 GMT
+ Subject: O=Spirent, OU=PAWP, L=Eatontown, ST=NJ, C=US
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (1024 bit)
+ Modulus:
+ 00:d1:48:5f:96:2d:7f:37:af:47:b8:f1:8a:da:90:
+ 55:5b:dd:8e:49:0d:db:cb:d0:cc:52:b1:37:6a:e9:
+ e8:2b:aa:83:a7:36:61:03:fa:56:a3:79:d5:90:be:
+ ed:1e:9e:4c:ef:4a:02:eb:e5:61:c7:e1:13:6b:b1:
+ ea:10:f2:23:4d:70:92:43:b7:7a:b3:19:01:1b:90:
+ 65:0d:6c:45:6b:cc:df:12:88:d2:5f:53:8b:c5:b7:
+ df:45:36:f4:30:f0:f7:79:a6:a5:db:91:91:c9:67:
+ 82:02:29:47:f4:f1:a3:71:74:ee:ea:76:b7:85:47:
+ 6c:2d:64:89:b9:9c:9a:13:75
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints:
+ CA:TRUE
+ X509v3 Subject Key Identifier:
+ 6E:F8:86:8C:18:E8:0D:73:82:EA:17:1A:A9:62:8A:7C:EA:57:F1:9E
+ X509v3 Authority Key Identifier:
+ keyid:6E:F8:86:8C:18:E8:0D:73:82:EA:17:1A:A9:62:8A:7C:EA:57:F1:9E
+ DirName:/O=Spirent/OU=PAWP/L=Eatontown/ST=NJ/C=US
+ serial:94:8F:5E:BA:47:AE:81:54
+
+ Signature Algorithm: sha1WithRSAEncryption
+ 48:f0:8e:f1:83:8a:57:7e:0a:e6:5a:5c:71:41:9a:f4:ff:22:
+ d6:e6:aa:27:61:4c:8e:13:6d:70:2f:bb:76:39:f7:80:fd:08:
+ 7d:d5:a1:ad:10:a8:c5:f4:0f:b9:3e:ff:30:4b:4b:b2:10:0c:
+ bf:38:e9:d2:58:db:3d:1d:3c:d7:a8:94:eb:c7:53:b2:06:03:
+ 83:27:a5:45:5e:46:4a:34:a4:ba:64:ea:ed:ee:f4:a7:9e:47:
+ a0:12:f3:5a:11:40:6b:3c:ec:fe:1f:e7:c8:91:6a:24:b9:e5:
+ 2e:7c:85:94:41:87:5c:b0:1e:cd:fa:1f:33:4b:31:e4:26:96:
+ e4:e6
+SHA1 Fingerprint=A5:7F:0C:80:31:10:AC:67:AE:CF:5A:DA:E4:E4:E3:A7:66:8A:A5:9E
diff --git a/meta/meta-mediatek/recipes-connectivity/agps/files/cacerts/e2220fb6.0 b/meta/meta-mediatek/recipes-connectivity/agps/files/cacerts/e2220fb6.0
new file mode 100644
index 0000000..59a7ca6
--- /dev/null
+++ b/meta/meta-mediatek/recipes-connectivity/agps/files/cacerts/e2220fb6.0
@@ -0,0 +1,42 @@
+-----BEGIN CERTIFICATE-----
+MIICQjCCAewCCQDZ9j78P4VYLDANBgkqhkiG9w0BAQUFADCBpzEfMB0GA1UEChMW
+U3BpcmVudCBDb21tdW5pY2F0aW9uczEOMAwGA1UECxMFUEEtV1AxJTAjBgkqhkiG
+9w0BCQEWFnN1cHBvcnRAc3BpcmVudGNvbS5jb20xEjAQBgNVBAcTCUVhdG9udG93
+bjELMAkGA1UECBMCTkoxCzAJBgNVBAYTAlVTMR8wHQYDVQQDExZzcGlyZW50IENv
+bW11bmljYXRpb25zMB4XDTk4MDEwMjE1MjUyOVoXDTE3MTIyODE1MjUyOVowgacx
+HzAdBgNVBAoTFlNwaXJlbnQgQ29tbXVuaWNhdGlvbnMxDjAMBgNVBAsTBVBBLVdQ
+MSUwIwYJKoZIhvcNAQkBFhZzdXBwb3J0QHNwaXJlbnRjb20uY29tMRIwEAYDVQQH
+EwlFYXRvbnRvd24xCzAJBgNVBAgTAk5KMQswCQYDVQQGEwJVUzEfMB0GA1UEAxMW
+c3BpcmVudCBDb21tdW5pY2F0aW9uczBcMA0GCSqGSIb3DQEBAQUAA0sAMEgCQQC9
+DEVw4fIKnNB/BgqKRh8G5Fb/8CW0BshBAofAUmkzmFr2pZj46HO8phJ0NfstSRMH
+0euv9yU0DIL4PFCl+JGpAgMBAAEwDQYJKoZIhvcNAQEFBQADQQAKB00iTL0LDLy4
+DdRkZ+1O8f2l8/2lNhwpjerhNYLaVvnjAff948+3LrSHgsCmycFQC0DwoelJZTjZ
+NSy3yOOM
+-----END CERTIFICATE-----
+Certificate:
+ Data:
+ Version: 1 (0x0)
+ Serial Number:
+ d9:f6:3e:fc:3f:85:58:2c
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: O=Spirent Communications, OU=PA-WP/emailAddress=support@spirentcom.com, L=Eatontown, ST=NJ, C=US, CN=spirent Communications
+ Validity
+ Not Before: Jan 2 15:25:29 1998 GMT
+ Not After : Dec 28 15:25:29 2017 GMT
+ Subject: O=Spirent Communications, OU=PA-WP/emailAddress=support@spirentcom.com, L=Eatontown, ST=NJ, C=US, CN=spirent Communications
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (512 bit)
+ Modulus:
+ 00:bd:0c:45:70:e1:f2:0a:9c:d0:7f:06:0a:8a:46:
+ 1f:06:e4:56:ff:f0:25:b4:06:c8:41:02:87:c0:52:
+ 69:33:98:5a:f6:a5:98:f8:e8:73:bc:a6:12:74:35:
+ fb:2d:49:13:07:d1:eb:af:f7:25:34:0c:82:f8:3c:
+ 50:a5:f8:91:a9
+ Exponent: 65537 (0x10001)
+ Signature Algorithm: sha1WithRSAEncryption
+ 0a:07:4d:22:4c:bd:0b:0c:bc:b8:0d:d4:64:67:ed:4e:f1:fd:
+ a5:f3:fd:a5:36:1c:29:8d:ea:e1:35:82:da:56:f9:e3:01:f7:
+ fd:e3:cf:b7:2e:b4:87:82:c0:a6:c9:c1:50:0b:40:f0:a1:e9:
+ 49:65:38:d9:35:2c:b7:c8:e3:8c
+SHA1 Fingerprint=42:87:0C:3D:A5:0E:86:8B:DE:7B:57:C8:FD:9D:BA:EA:62:60:69:24
diff --git a/meta/meta-mediatek/recipes-connectivity/ate_tool/mtkatetool-7668.bb b/meta/meta-mediatek/recipes-connectivity/ate_tool/mtkatetool-7668.bb
new file mode 100644
index 0000000..d4c9578
--- /dev/null
+++ b/meta/meta-mediatek/recipes-connectivity/ate_tool/mtkatetool-7668.bb
@@ -0,0 +1,38 @@
+DESCRIPTION = "Mediatek MT7668 ATE Tool"
+LICENSE = "MediaTekProprietary"
+LIC_FILES_CHKSUM = "file://${COREBASE}/bitbake/COPYING;md5=751419260aa954499f7abaabaa882bbe"
+
+inherit workonsrc
+WORKONSRC = "${TOPDIR}/../src/connectivity/wlan_daemon/ated_ext"
+MODULE_NAME = "ated"
+
+#CFLAGS += "-I ${STAGING_DIR_HOST}/usr/include/"
+#CFLAGS += "-I ${STAGING_DIR_HOST}/usr/lib64/"
+#CFLAGS += "-I ${TOPDIR}/tmp/sysroots/${MTK_PROJECT}/usr/include/"
+#CFLAGS += "-I ${TOPDIR}/tmp/sysroots/${MTK_PROJECT}/usr/lib64/"
+#LDFLAGS += "-L ${TOPDIR}/tmp/sysroots/${MTK_PROJECT}/usr/lib64/"
+#LDFLAGS += "-L ${TOPDIR}/tmp/sysroots/${MTK_PROJECT}/lib64/"
+do_compile() {
+
+ if test "${COMBO_CHIP_ID}" = "mt7668"; then
+ echo mt7668 ate tool start compile
+ echo ${WORKONSRC}
+ echo ${S}
+
+ #cd ${S} && make PLATFORM=MT8516 CROSS_COMPILE=aarch64-agl-linux- MODULE_NAME=${MODULE_NAME} v=2 m=3 p=2
+ oe_runmake DESTDIR="${D}" CROSS_COMPILE=aarch64-agl-linux- PLATFORM=MT8516 MODULE_NAME=${MODULE_NAME} v=2 m=3 p=2
+ echo mt7668 ate tool end compile
+ fi
+}
+
+do_install() {
+ echo ${D}
+
+ if test "${COMBO_CHIP_ID}" = "mt7668"; then
+ install -d ${D}/usr/sbin/
+ install -m 0755 ${S}/${MODULE_NAME} ${D}/usr/sbin
+ fi
+}
+
+FILES_${PN} += "/usr/sbin"
+FILES_${PN}-dev = ""
diff --git a/meta/meta-mediatek/recipes-connectivity/boots/boots.bb b/meta/meta-mediatek/recipes-connectivity/boots/boots.bb
new file mode 100644
index 0000000..d0e0eca
--- /dev/null
+++ b/meta/meta-mediatek/recipes-connectivity/boots/boots.bb
@@ -0,0 +1,22 @@
+DESCRIPTION = "MTK boots"
+LICENSE = "MediaTekProprietary"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=23ecd380102e45504ca038dc56f6bdf5"
+
+inherit workonsrc
+WORKONSRC = "${TOPDIR}/../src/connectivity/bt_others/boots"
+
+INSANE_SKIP_${PN} += "already-stripped ldflags"
+name = "${@bb.utils.contains("TARGET_PLATFORM","mt2731", "-DSPECIAL_USB_RELAY","-DSPECIAL_USB_RELAY",d)}"
+btchip = "${@bb.utils.contains("MTK_COMBO_CHIP","MT6630", "MTK_MT6630","",d)}"
+FILES_${PN} += "${bindir}/boots"
+FILES_${PN} += "${bindir}/boots_srv"
+
+do_compile() {
+ oe_runmake PREFIX="${prefix}" DESTDIR="${D}" BT_VCOM_RELAYER="-DVCOM_OPENED" MTK_BT_CHIP="${btchip}" SPECIAL_USB_RELAY="${name}" BOOTS_SOCKET_PATH="-DBOOTS_SOCKET_PATH=\"\\\"/tmp/\\\"\""
+}
+
+do_install() {
+ install -d ${D}${bindir}
+ install -m 0755 boots ${D}${bindir}
+ install -m 0755 boots_srv ${D}${bindir}
+}
diff --git a/meta/meta-mediatek/recipes-connectivity/bt-vendor-lib/bt-vendor-lib.bb b/meta/meta-mediatek/recipes-connectivity/bt-vendor-lib/bt-vendor-lib.bb
new file mode 100644
index 0000000..b9810e0
--- /dev/null
+++ b/meta/meta-mediatek/recipes-connectivity/bt-vendor-lib/bt-vendor-lib.bb
@@ -0,0 +1,33 @@
+DESCRIPTION = "MTK bt_vendor_lib"
+LICENSE = "Apache-2.0 & MediaTekProprietary"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=e1696b147d49d491bcb4da1a57173fff"
+
+inherit workonsrc
+WORKONSRC = "${TOPDIR}/../src/connectivity/bt_others/vendor_lib/mt66xx/mtk/pure"
+
+LDFLAGS += "-Wl,--hash-style=gnu"
+
+INSANE_SKIP_${PN} += "already-stripped"
+
+DEPENDS += "${@bb.utils.contains("TARGET_PLATFORM", "mt2731", "nvram", "nvram4", d)}"
+FILES_${PN}-dev = ""
+FILES_${PN} += "${libdir}/libbluetooth_mtk_pure.so"
+#FILES_${PN} += "${libdir}/libbluetoothem_mtk.so"
+
+BB_INCLUDE_ADD = "-ISTAGING_INCDIR \
+ -I${STAGING_INCDIR}/nvram \
+ -I${STAGING_INCDIR}/custom/${LINUX_KERNEL}/common/cgen/cfgfileinc \
+ -I${STAGING_INCDIR}/custom/${LINUX_KERNEL}/common/cgen/cfgdefault \
+ -I${STAGING_INCDIR}/custom/${LINUX_KERNEL}/common/cgen/inc \
+ -I${STAGING_INCDIR}/custom/${LINUX_KERNEL}/common/cgen \
+ "
+
+do_compile() {
+ oe_runmake PREFIX="${prefix}" DESTDIR="${D}" CFLAGS+="${BB_INCLUDE_ADD}"
+}
+
+do_install() {
+ install -d ${D}${libdir}
+ install -m 0755 libbluetooth_mtk_pure.so ${D}${libdir}
+# install -m 0755 libbluetoothem_mtk.so ${D}${libdir}
+}
diff --git a/meta/meta-mediatek/recipes-connectivity/combo_tool/mtkcombotool.bb b/meta/meta-mediatek/recipes-connectivity/combo_tool/mtkcombotool.bb
new file mode 100644
index 0000000..6254765
--- /dev/null
+++ b/meta/meta-mediatek/recipes-connectivity/combo_tool/mtkcombotool.bb
@@ -0,0 +1,40 @@
+DESCRIPTION = "This module serves the common part driver of connectivity"
+LICENSE = "MediaTekProprietary"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=e1696b147d49d491bcb4da1a57173fff"
+
+inherit workonsrc
+WORKONSRC = "${TOPDIR}/../src/connectivity/combo_tool"
+
+inherit autotools
+
+inherit systemd
+
+SYSTEMD_PACKAGES = "${PN}"
+SYSTEMD_SERVICE_${PN} = "wmtd.service launcher.service poweronwifi.service stp_dump.service"
+FILES_${PN} += "${systemd_unitdir}/system/wmtd.service"
+FILES_${PN} += "${systemd_unitdir}/system/launcher.service"
+FILES_${PN} += "${systemd_unitdir}/system/poweronwifi.service"
+FILES_${PN} += "${systemd_unitdir}/system/stp_dump.service"
+FILES_${PN} += "/lib/firmware/mt6630_ant_m1.cfg"
+
+do_compile () {
+ if test "${TARGET_PLATFORM}" = "mt2712"; then
+ oe_runmake all CFLAGS="-DMTK_COMBO_USING_PATCH_NAME=1"
+ fi
+ if test "${TARGET_PLATFORM}" = "mt2731"; then
+ oe_runmake all CFLAGS="-DMTK_COMBO_USING_PATCH_NAME=1"
+ fi
+}
+
+do_install_append() {
+ install -d ${D}/lib/firmware
+ install -m 0755 ${S}/cfg_folder/mt6630_ant_m1.cfg ${D}/lib/firmware
+ if ${@bb.utils.contains('DISTRO_FEATURES','systemd','true','false',d)}; then
+ install -d ${D}${systemd_unitdir}/system/
+ install -m 0644 ${B}/wmtd.service ${D}${systemd_unitdir}/system
+ install -m 0644 ${B}/launcher.service ${D}${systemd_unitdir}/system
+ install -m 0644 ${B}/poweronwifi.service ${D}${systemd_unitdir}/system
+ install -m 0644 ${B}/stp_dump.service ${D}${systemd_unitdir}/system
+ fi
+}
+
diff --git a/meta/meta-mediatek/recipes-connectivity/hostapd/hostapd/CVE-2019-16275.patch b/meta/meta-mediatek/recipes-connectivity/hostapd/hostapd/CVE-2019-16275.patch
new file mode 100755
index 0000000..9cefd4f
--- /dev/null
+++ b/meta/meta-mediatek/recipes-connectivity/hostapd/hostapd/CVE-2019-16275.patch
@@ -0,0 +1,79 @@
+From d86d66dc073bc21d3b12faf4112062ae00c1773f Mon Sep 17 00:00:00 2001
+From: Jouni Malinen <j@w1.fi>
+Date: Thu, 29 Aug 2019 11:52:04 +0300
+Subject: AP: Silently ignore management frame from unexpected source
+address
+
+Do not process any received Management frames with unexpected/invalid SA
+so that we do not add any state for unexpected STA addresses or end up
+sending out frames to unexpected destination. This prevents unexpected
+sequences where an unprotected frame might end up causing the AP to send
+out a response to another device and that other device processing the
+unexpected response.
+
+In particular, this prevents some potential denial of service cases
+where the unexpected response frame from the AP might result in a
+connected station dropping its association.
+
+Upstream-Status: Accepted
+CVE: CVE-2019-16275
+
+Reference to upstream patch:
+https://w1.fi/cgit/hostap/commit/?id=d86d66dc073bc21d3b12faf4112062ae00c1773f
+
+Signed-off-by: Jouni Malinen <j@w1.fi>
+---
+ src/ap/drv_callbacks.c | 13 +++++++++++++
+ src/ap/ieee802_11.c | 12 ++++++++++++
+ 2 files changed, 25 insertions(+)
+
+diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c
+index 3158768..34ca379 100644
+--- a/src/ap/drv_callbacks.c
++++ b/src/ap/drv_callbacks.c
+@@ -131,6 +131,19 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
+ "hostapd_notif_assoc: Skip event with no address");
+ return -1;
+ }
++
++ if (is_multicast_ether_addr(addr) ||
++ is_zero_ether_addr(addr) ||
++ os_memcmp(addr, hapd->own_addr, ETH_ALEN) == 0) {
++ /* Do not process any frames with unexpected/invalid SA so that
++ * we do not add any state for unexpected STA addresses or end
++ * up sending out frames to unexpected destination. */
++ wpa_printf(MSG_DEBUG, "%s: Invalid SA=" MACSTR
++ " in received indication - ignore this indication silently",
++ __func__, MAC2STR(addr));
++ return 0;
++ }
++
+ random_add_randomness(addr, ETH_ALEN);
+
+ hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211,
+diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c
+index c85a28d..2816812 100644
+--- a/src/ap/ieee802_11.c
++++ b/src/ap/ieee802_11.c
+@@ -4626,6 +4626,18 @@ int ieee802_11_mgmt(struct hostapd_data *hapd, const u8 *buf, size_t len,
+ fc = le_to_host16(mgmt->frame_control);
+ stype = WLAN_FC_GET_STYPE(fc);
+
++ if (is_multicast_ether_addr(mgmt->sa) ||
++ is_zero_ether_addr(mgmt->sa) ||
++ os_memcmp(mgmt->sa, hapd->own_addr, ETH_ALEN) == 0) {
++ /* Do not process any frames with unexpected/invalid SA so that
++ * we do not add any state for unexpected STA addresses or end
++ * up sending out frames to unexpected destination. */
++ wpa_printf(MSG_DEBUG, "MGMT: Invalid SA=" MACSTR
++ " in received frame - ignore this frame silently",
++ MAC2STR(mgmt->sa));
++ return 0;
++ }
++
+ if (stype == WLAN_FC_STYPE_BEACON) {
+ handle_beacon(hapd, mgmt, len, fi);
+ return 1;
+--
+2.17.1
+
diff --git a/meta/meta-mediatek/recipes-connectivity/hostapd/hostapd/defconfig b/meta/meta-mediatek/recipes-connectivity/hostapd/hostapd/defconfig
new file mode 100755
index 0000000..a62bec4
--- /dev/null
+++ b/meta/meta-mediatek/recipes-connectivity/hostapd/hostapd/defconfig
@@ -0,0 +1,148 @@
+# Example hostapd build time configuration
+#
+# This file lists the configuration options that are used when building the
+# hostapd binary. All lines starting with # are ignored. Configuration option
+# lines must be commented out complete, if they are not to be included, i.e.,
+# just setting VARIABLE=n is not disabling that variable.
+#
+# This file is included in Makefile, so variables like CFLAGS and LIBS can also
+# be modified from here. In most cass, these lines should use += in order not
+# to override previous values of the variables.
+
+# Driver interface for Host AP driver
+CONFIG_DRIVER_HOSTAP=y
+
+# Driver interface for wired authenticator
+CONFIG_DRIVER_WIRED=y
+
+# Driver interface for madwifi driver
+#CONFIG_DRIVER_MADWIFI=y
+#CFLAGS += -I../../madwifi # change to the madwifi source directory
+
+# Driver interface for Prism54 driver
+CONFIG_DRIVER_PRISM54=y
+
+# Driver interface for drivers using the nl80211 kernel interface
+CONFIG_DRIVER_NL80211=y
+CONFIG_LIBNL32=y
+# driver_nl80211.c requires a rather new libnl (version 1.1) which may not be
+# shipped with your distribution yet. If that is the case, you need to build
+# newer libnl version and point the hostapd build to use it.
+#LIBNL=/usr/src/libnl
+#CFLAGS += -I$(LIBNL)/include
+#LIBS += -L$(LIBNL)/lib
+
+# Driver interface for FreeBSD net80211 layer (e.g., Atheros driver)
+#CONFIG_DRIVER_BSD=y
+#CFLAGS += -I/usr/local/include
+#LIBS += -L/usr/local/lib
+
+# Driver interface for no driver (e.g., RADIUS server only)
+#CONFIG_DRIVER_NONE=y
+
+# IEEE 802.11F/IAPP
+CONFIG_IAPP=y
+
+# WPA2/IEEE 802.11i RSN pre-authentication
+CONFIG_RSN_PREAUTH=y
+
+# PeerKey handshake for Station to Station Link (IEEE 802.11e DLS)
+CONFIG_PEERKEY=y
+
+# IEEE 802.11w (management frame protection)
+# This version is an experimental implementation based on IEEE 802.11w/D1.0
+# draft and is subject to change since the standard has not yet been finalized.
+# Driver support is also needed for IEEE 802.11w.
+#CONFIG_IEEE80211W=y
+
+# Integrated EAP server
+CONFIG_EAP=y
+
+# EAP-MD5 for the integrated EAP server
+CONFIG_EAP_MD5=y
+
+# EAP-TLS for the integrated EAP server
+CONFIG_EAP_TLS=y
+
+# EAP-MSCHAPv2 for the integrated EAP server
+CONFIG_EAP_MSCHAPV2=y
+
+# EAP-PEAP for the integrated EAP server
+CONFIG_EAP_PEAP=y
+
+# EAP-GTC for the integrated EAP server
+CONFIG_EAP_GTC=y
+
+# EAP-TTLS for the integrated EAP server
+CONFIG_EAP_TTLS=y
+
+# EAP-SIM for the integrated EAP server
+#CONFIG_EAP_SIM=y
+
+# EAP-AKA for the integrated EAP server
+#CONFIG_EAP_AKA=y
+
+# EAP-AKA' for the integrated EAP server
+# This requires CONFIG_EAP_AKA to be enabled, too.
+#CONFIG_EAP_AKA_PRIME=y
+
+# EAP-PAX for the integrated EAP server
+#CONFIG_EAP_PAX=y
+
+# EAP-PSK for the integrated EAP server (this is _not_ needed for WPA-PSK)
+#CONFIG_EAP_PSK=y
+
+# EAP-SAKE for the integrated EAP server
+#CONFIG_EAP_SAKE=y
+
+# EAP-GPSK for the integrated EAP server
+#CONFIG_EAP_GPSK=y
+# Include support for optional SHA256 cipher suite in EAP-GPSK
+#CONFIG_EAP_GPSK_SHA256=y
+
+# EAP-FAST for the integrated EAP server
+# Note: Default OpenSSL package does not include support for all the
+# functionality needed for EAP-FAST. If EAP-FAST is enabled with OpenSSL,
+# the OpenSSL library must be patched (openssl-0.9.9-session-ticket.patch)
+# to add the needed functions.
+#CONFIG_EAP_FAST=y
+
+# Wi-Fi Protected Setup (WPS)
+CONFIG_WPS=y
+# Enable UPnP support for external WPS Registrars
+#CONFIG_WPS_UPNP=y
+
+# EAP-IKEv2
+#CONFIG_EAP_IKEV2=y
+
+# Trusted Network Connect (EAP-TNC)
+#CONFIG_EAP_TNC=y
+
+# PKCS#12 (PFX) support (used to read private key and certificate file from
+# a file that usually has extension .p12 or .pfx)
+CONFIG_PKCS12=y
+
+# RADIUS authentication server. This provides access to the integrated EAP
+# server from external hosts using RADIUS.
+CONFIG_RADIUS_SERVER=y
+
+# Build IPv6 support for RADIUS operations
+CONFIG_IPV6=y
+
+# IEEE Std 802.11r-2008 (Fast BSS Transition)
+#CONFIG_IEEE80211R=y
+
+# Use the hostapd's IEEE 802.11 authentication (ACL), but without
+# the IEEE 802.11 Management capability (e.g., madwifi or FreeBSD/net80211)
+CONFIG_DRIVER_RADIUS_ACL=y
+
+# IEEE 802.11n (High Throughput) support
+CONFIG_IEEE80211N=y
+
+# IEEE 802.11ac (Very High Throughput) support
+CONFIG_IEEE80211AC=y
+
+# Remove debugging code that is printing out debug messages to stdout.
+# This can be used to reduce the size of the hostapd considerably if debugging
+# code is not needed.
+#CONFIG_NO_STDOUT_DEBUG=y
diff --git a/meta/meta-mediatek/recipes-connectivity/hostapd/hostapd/hostapd.service b/meta/meta-mediatek/recipes-connectivity/hostapd/hostapd/hostapd.service
new file mode 100755
index 0000000..151c050
--- /dev/null
+++ b/meta/meta-mediatek/recipes-connectivity/hostapd/hostapd/hostapd.service
@@ -0,0 +1,11 @@
+[Unit]
+Description=Hostapd IEEE 802.11 AP, IEEE 802.1X/WPA/WPA2/EAP/RADIUS Authenticator
+After=network.target
+
+[Service]
+Type=forking
+PIDFile=/run/hostapd.pid
+ExecStart=@SBINDIR@/hostapd @SYSCONFDIR@/hostapd.conf -P /run/hostapd.pid -B
+
+[Install]
+WantedBy=multi-user.target
diff --git a/meta/meta-mediatek/recipes-connectivity/hostapd/hostapd/init b/meta/meta-mediatek/recipes-connectivity/hostapd/hostapd/init
new file mode 100755
index 0000000..8ba4e07
--- /dev/null
+++ b/meta/meta-mediatek/recipes-connectivity/hostapd/hostapd/init
@@ -0,0 +1,58 @@
+#!/bin/sh
+DAEMON=/usr/sbin/hostapd
+NAME=hostapd
+DESC="HOSTAP Daemon"
+ARGS="/etc/hostapd.conf -B"
+
+test -f $DAEMON || exit 0
+
+set -e
+
+# source function library
+. /etc/init.d/functions
+
+delay_stop() {
+ count=0
+ while [ $count -lt 9 ] ; do
+ if pidof $DAEMON >/dev/null; then
+ sleep 1
+ else
+ return 0
+ fi
+ count=`expr $count + 1`
+ done
+ echo "Failed to stop $DESC."
+ return 1
+}
+
+case "$1" in
+ start)
+ echo -n "Starting $DESC: "
+ start-stop-daemon -S -x $DAEMON -- $ARGS
+ echo "$NAME."
+ ;;
+ stop)
+ echo -n "Stopping $DESC: "
+ start-stop-daemon -K --oknodo -x $DAEMON
+ echo "$NAME."
+ ;;
+ restart)
+ $0 stop
+ delay_stop && $0 start
+ ;;
+ reload)
+ echo -n "Reloading $DESC: "
+ killall -HUP $(basename ${DAEMON})
+ echo "$NAME."
+ ;;
+ status)
+ status $DAEMON
+ exit $?
+ ;;
+ *)
+ echo "Usage: $0 {start|stop|restart|reload|status}"
+ exit 1
+ ;;
+esac
+
+exit 0
diff --git a/meta/meta-mediatek/recipes-connectivity/hostapd/hostapd_2.9.bb b/meta/meta-mediatek/recipes-connectivity/hostapd/hostapd_2.9.bb
new file mode 100755
index 0000000..68dc123
--- /dev/null
+++ b/meta/meta-mediatek/recipes-connectivity/hostapd/hostapd_2.9.bb
@@ -0,0 +1,52 @@
+SUMMARY = "User space daemon for extended IEEE 802.11 management"
+HOMEPAGE = "http://w1.fi/hostapd/"
+SECTION = "kernel/userland"
+LICENSE = "BSD-3-Clause"
+LIC_FILES_CHKSUM = "file://hostapd/README;md5=1ec986bec88070e2a59c68c95d763f89"
+
+DEPENDS = "libnl openssl"
+
+SRC_URI = " \
+ http://w1.fi/releases/hostapd-${PV}.tar.gz \
+ file://defconfig \
+ file://init \
+ file://hostapd.service \
+ file://CVE-2019-16275.patch \
+"
+
+SRC_URI[md5sum] = "f188fc53a495fe7af3b6d77d3c31dee8"
+SRC_URI[sha256sum] = "881d7d6a90b2428479288d64233151448f8990ab4958e0ecaca7eeb3c9db2bd7"
+
+S = "${WORKDIR}/hostapd-${PV}"
+B = "${WORKDIR}/hostapd-${PV}/hostapd"
+
+inherit update-rc.d systemd pkgconfig features_check
+
+CONFLICT_DISTRO_FEATURES = "openssl-no-weak-ciphers"
+
+INITSCRIPT_NAME = "hostapd"
+
+SYSTEMD_SERVICE_${PN} = "hostapd.service"
+SYSTEMD_AUTO_ENABLE_${PN} = "disable"
+
+do_configure_append() {
+ install -m 0644 ${WORKDIR}/defconfig ${B}/.config
+}
+
+do_compile() {
+ export CFLAGS="-MMD -O2 -Wall -g"
+ export EXTRA_CFLAGS="${CFLAGS}"
+ make V=1
+}
+
+do_install() {
+ install -d ${D}${sbindir} ${D}${sysconfdir}/init.d ${D}${systemd_unitdir}/system/
+ install -m 0644 ${B}/hostapd.conf ${D}${sysconfdir}
+ install -m 0755 ${B}/hostapd ${D}${sbindir}
+ install -m 0755 ${B}/hostapd_cli ${D}${sbindir}
+ install -m 755 ${WORKDIR}/init ${D}${sysconfdir}/init.d/hostapd
+ install -m 0644 ${WORKDIR}/hostapd.service ${D}${systemd_unitdir}/system/
+ sed -i -e 's,@SBINDIR@,${sbindir},g' -e 's,@SYSCONFDIR@,${sysconfdir},g' ${D}${systemd_unitdir}/system/hostapd.service
+}
+
+CONFFILES_${PN} += "${sysconfdir}/hostapd.conf"
diff --git a/meta/meta-mediatek/recipes-connectivity/libnftnl/libnftnl/0001-Move-exports-before-symbol-definition.patch b/meta/meta-mediatek/recipes-connectivity/libnftnl/libnftnl/0001-Move-exports-before-symbol-definition.patch
new file mode 100644
index 0000000..c59a2c2
--- /dev/null
+++ b/meta/meta-mediatek/recipes-connectivity/libnftnl/libnftnl/0001-Move-exports-before-symbol-definition.patch
@@ -0,0 +1,290 @@
+From 21eb59fbd071ebffb8495232766824944fb521a0 Mon Sep 17 00:00:00 2001
+From: Alex Kiernan <alex.kiernan@gmail.com>
+Date: Wed, 7 Nov 2018 21:19:53 +0000
+Subject: [PATCH] Move exports before symbol definition
+
+Based on 7966020 ("src: Fix exporting symbols with clang"), when
+EXPORT_SYMBOL is located after function definition, clang won't properly
+export the function, resulting in a library with no symbols when built with
+clang.
+
+Signed-off-by: Alex Kiernan <alex.kiernan@gmail.com>
+---
+ src/flowtable.c | 54 +++++++++++++++++++++++++++---------------------------
+ 1 file changed, 27 insertions(+), 27 deletions(-)
+
+diff --git a/src/flowtable.c b/src/flowtable.c
+index c1ddae4..d7434e3 100644
+--- a/src/flowtable.c
++++ b/src/flowtable.c
+@@ -34,12 +34,13 @@ struct nftnl_flowtable {
+ uint32_t flags;
+ };
+
++EXPORT_SYMBOL(nftnl_flowtable_alloc);
+ struct nftnl_flowtable *nftnl_flowtable_alloc(void)
+ {
+ return calloc(1, sizeof(struct nftnl_flowtable));
+ }
+-EXPORT_SYMBOL(nftnl_flowtable_alloc);
+
++EXPORT_SYMBOL(nftnl_flowtable_free);
+ void nftnl_flowtable_free(const struct nftnl_flowtable *c)
+ {
+ int i;
+@@ -56,14 +57,14 @@ void nftnl_flowtable_free(const struct nftnl_flowtable *c)
+ }
+ xfree(c);
+ }
+-EXPORT_SYMBOL(nftnl_flowtable_free);
+
++EXPORT_SYMBOL(nftnl_flowtable_is_set);
+ bool nftnl_flowtable_is_set(const struct nftnl_flowtable *c, uint16_t attr)
+ {
+ return c->flags & (1 << attr);
+ }
+-EXPORT_SYMBOL(nftnl_flowtable_is_set);
+
++EXPORT_SYMBOL(nftnl_flowtable_unset);
+ void nftnl_flowtable_unset(struct nftnl_flowtable *c, uint16_t attr)
+ {
+ int i;
+@@ -96,7 +97,6 @@ void nftnl_flowtable_unset(struct nftnl_flowtable *c, uint16_t attr)
+
+ c->flags &= ~(1 << attr);
+ }
+-EXPORT_SYMBOL(nftnl_flowtable_unset);
+
+ static uint32_t nftnl_flowtable_validate[NFTNL_FLOWTABLE_MAX + 1] = {
+ [NFTNL_FLOWTABLE_HOOKNUM] = sizeof(uint32_t),
+@@ -105,6 +105,7 @@ static uint32_t nftnl_flowtable_validate[NFTNL_FLOWTABLE_MAX + 1] = {
+ [NFTNL_FLOWTABLE_FLAGS] = sizeof(uint32_t),
+ };
+
++EXPORT_SYMBOL(nftnl_flowtable_set_data);
+ int nftnl_flowtable_set_data(struct nftnl_flowtable *c, uint16_t attr,
+ const void *data, uint32_t data_len)
+ {
+@@ -170,32 +171,32 @@ int nftnl_flowtable_set_data(struct nftnl_flowtable *c, uint16_t attr,
+ c->flags |= (1 << attr);
+ return 0;
+ }
+-EXPORT_SYMBOL(nftnl_flowtable_set_data);
+
++EXPORT_SYMBOL(nftnl_flowtable_set);
+ void nftnl_flowtable_set(struct nftnl_flowtable *c, uint16_t attr, const void *data)
+ {
+ nftnl_flowtable_set_data(c, attr, data, nftnl_flowtable_validate[attr]);
+ }
+-EXPORT_SYMBOL(nftnl_flowtable_set);
+
++EXPORT_SYMBOL(nftnl_flowtable_set_u32);
+ void nftnl_flowtable_set_u32(struct nftnl_flowtable *c, uint16_t attr, uint32_t data)
+ {
+ nftnl_flowtable_set_data(c, attr, &data, sizeof(uint32_t));
+ }
+-EXPORT_SYMBOL(nftnl_flowtable_set_u32);
+
++EXPORT_SYMBOL(nftnl_flowtable_set_s32);
+ void nftnl_flowtable_set_s32(struct nftnl_flowtable *c, uint16_t attr, int32_t data)
+ {
+ nftnl_flowtable_set_data(c, attr, &data, sizeof(int32_t));
+ }
+-EXPORT_SYMBOL(nftnl_flowtable_set_s32);
+
++EXPORT_SYMBOL(nftnl_flowtable_set_str);
+ int nftnl_flowtable_set_str(struct nftnl_flowtable *c, uint16_t attr, const char *str)
+ {
+ return nftnl_flowtable_set_data(c, attr, str, strlen(str) + 1);
+ }
+-EXPORT_SYMBOL(nftnl_flowtable_set_str);
+
++EXPORT_SYMBOL(nftnl_flowtable_get_data);
+ const void *nftnl_flowtable_get_data(const struct nftnl_flowtable *c,
+ uint16_t attr, uint32_t *data_len)
+ {
+@@ -229,21 +230,21 @@ const void *nftnl_flowtable_get_data(const struct nftnl_flowtable *c,
+ }
+ return NULL;
+ }
+-EXPORT_SYMBOL(nftnl_flowtable_get_data);
+
++EXPORT_SYMBOL(nftnl_flowtable_get);
+ const void *nftnl_flowtable_get(const struct nftnl_flowtable *c, uint16_t attr)
+ {
+ uint32_t data_len;
+ return nftnl_flowtable_get_data(c, attr, &data_len);
+ }
+-EXPORT_SYMBOL(nftnl_flowtable_get);
+
++EXPORT_SYMBOL(nftnl_flowtable_get_str);
+ const char *nftnl_flowtable_get_str(const struct nftnl_flowtable *c, uint16_t attr)
+ {
+ return nftnl_flowtable_get(c, attr);
+ }
+-EXPORT_SYMBOL(nftnl_flowtable_get_str);
+
++EXPORT_SYMBOL(nftnl_flowtable_get_u32);
+ uint32_t nftnl_flowtable_get_u32(const struct nftnl_flowtable *c, uint16_t attr)
+ {
+ uint32_t data_len;
+@@ -253,8 +254,8 @@ uint32_t nftnl_flowtable_get_u32(const struct nftnl_flowtable *c, uint16_t attr)
+
+ return val ? *val : 0;
+ }
+-EXPORT_SYMBOL(nftnl_flowtable_get_u32);
+
++EXPORT_SYMBOL(nftnl_flowtable_get_s32);
+ int32_t nftnl_flowtable_get_s32(const struct nftnl_flowtable *c, uint16_t attr)
+ {
+ uint32_t data_len;
+@@ -264,8 +265,8 @@ int32_t nftnl_flowtable_get_s32(const struct nftnl_flowtable *c, uint16_t attr)
+
+ return val ? *val : 0;
+ }
+-EXPORT_SYMBOL(nftnl_flowtable_get_s32);
+
++EXPORT_SYMBOL(nftnl_flowtable_nlmsg_build_payload);
+ void nftnl_flowtable_nlmsg_build_payload(struct nlmsghdr *nlh,
+ const struct nftnl_flowtable *c)
+ {
+@@ -301,7 +302,6 @@ void nftnl_flowtable_nlmsg_build_payload(struct nlmsghdr *nlh,
+ if (c->flags & (1 << NFTNL_FLOWTABLE_SIZE))
+ mnl_attr_put_u32(nlh, NFTA_FLOWTABLE_SIZE, htonl(c->size));
+ }
+-EXPORT_SYMBOL(nftnl_flowtable_nlmsg_build_payload);
+
+ static int nftnl_flowtable_parse_attr_cb(const struct nlattr *attr, void *data)
+ {
+@@ -412,6 +412,7 @@ static int nftnl_flowtable_parse_hook(struct nlattr *attr, struct nftnl_flowtabl
+ return 0;
+ }
+
++EXPORT_SYMBOL(nftnl_flowtable_nlmsg_parse);
+ int nftnl_flowtable_nlmsg_parse(const struct nlmsghdr *nlh, struct nftnl_flowtable *c)
+ {
+ struct nlattr *tb[NFTA_FLOWTABLE_MAX + 1] = {};
+@@ -460,7 +461,6 @@ int nftnl_flowtable_nlmsg_parse(const struct nlmsghdr *nlh, struct nftnl_flowtab
+
+ return ret;
+ }
+-EXPORT_SYMBOL(nftnl_flowtable_nlmsg_parse);
+
+ static const char *nftnl_hooknum2str(int family, int hooknum)
+ {
+@@ -612,20 +612,20 @@ static int nftnl_flowtable_do_parse(struct nftnl_flowtable *c,
+ return ret;
+ }
+
++EXPORT_SYMBOL(nftnl_flowtable_parse);
+ int nftnl_flowtable_parse(struct nftnl_flowtable *c, enum nftnl_parse_type type,
+ const char *data, struct nftnl_parse_err *err)
+ {
+ return nftnl_flowtable_do_parse(c, type, data, err, NFTNL_PARSE_BUFFER);
+ }
+-EXPORT_SYMBOL(nftnl_flowtable_parse);
+
++EXPORT_SYMBOL(nftnl_flowtable_parse_file);
+ int nftnl_flowtable_parse_file(struct nftnl_flowtable *c,
+ enum nftnl_parse_type type,
+ FILE *fp, struct nftnl_parse_err *err)
+ {
+ return nftnl_flowtable_do_parse(c, type, fp, err, NFTNL_PARSE_FILE);
+ }
+-EXPORT_SYMBOL(nftnl_flowtable_parse_file);
+
+ static int nftnl_flowtable_export(char *buf, size_t size,
+ const struct nftnl_flowtable *c, int type)
+@@ -720,6 +720,7 @@ static int nftnl_flowtable_cmd_snprintf(char *buf, size_t size,
+ return offset;
+ }
+
++EXPORT_SYMBOL(nftnl_flowtable_snprintf);
+ int nftnl_flowtable_snprintf(char *buf, size_t size, const struct nftnl_flowtable *c,
+ uint32_t type, uint32_t flags)
+ {
+@@ -729,7 +730,6 @@ int nftnl_flowtable_snprintf(char *buf, size_t size, const struct nftnl_flowtabl
+ return nftnl_flowtable_cmd_snprintf(buf, size, c, nftnl_flag2cmd(flags),
+ type, flags);
+ }
+-EXPORT_SYMBOL(nftnl_flowtable_snprintf);
+
+ static int nftnl_flowtable_do_snprintf(char *buf, size_t size, const void *c,
+ uint32_t cmd, uint32_t type, uint32_t flags)
+@@ -737,18 +737,19 @@ static int nftnl_flowtable_do_snprintf(char *buf, size_t size, const void *c,
+ return nftnl_flowtable_snprintf(buf, size, c, type, flags);
+ }
+
++EXPORT_SYMBOL(nftnl_flowtable_fprintf);
+ int nftnl_flowtable_fprintf(FILE *fp, const struct nftnl_flowtable *c,
+ uint32_t type, uint32_t flags)
+ {
+ return nftnl_fprintf(fp, c, NFTNL_CMD_UNSPEC, type, flags,
+ nftnl_flowtable_do_snprintf);
+ }
+-EXPORT_SYMBOL(nftnl_flowtable_fprintf);
+
+ struct nftnl_flowtable_list {
+ struct list_head list;
+ };
+
++EXPORT_SYMBOL(nftnl_flowtable_list_alloc);
+ struct nftnl_flowtable_list *nftnl_flowtable_list_alloc(void)
+ {
+ struct nftnl_flowtable_list *list;
+@@ -761,8 +762,8 @@ struct nftnl_flowtable_list *nftnl_flowtable_list_alloc(void)
+
+ return list;
+ }
+-EXPORT_SYMBOL(nftnl_flowtable_list_alloc);
+
++EXPORT_SYMBOL(nftnl_flowtable_list_free);
+ void nftnl_flowtable_list_free(struct nftnl_flowtable_list *list)
+ {
+ struct nftnl_flowtable *s, *tmp;
+@@ -773,34 +774,34 @@ void nftnl_flowtable_list_free(struct nftnl_flowtable_list *list)
+ }
+ xfree(list);
+ }
+-EXPORT_SYMBOL(nftnl_flowtable_list_free);
+
++EXPORT_SYMBOL(nftnl_flowtable_list_is_empty);
+ int nftnl_flowtable_list_is_empty(const struct nftnl_flowtable_list *list)
+ {
+ return list_empty(&list->list);
+ }
+-EXPORT_SYMBOL(nftnl_flowtable_list_is_empty);
+
++EXPORT_SYMBOL(nftnl_flowtable_list_add);
+ void nftnl_flowtable_list_add(struct nftnl_flowtable *s,
+ struct nftnl_flowtable_list *list)
+ {
+ list_add(&s->head, &list->list);
+ }
+-EXPORT_SYMBOL(nftnl_flowtable_list_add);
+
++EXPORT_SYMBOL(nftnl_flowtable_list_add_tail);
+ void nftnl_flowtable_list_add_tail(struct nftnl_flowtable *s,
+ struct nftnl_flowtable_list *list)
+ {
+ list_add_tail(&s->head, &list->list);
+ }
+-EXPORT_SYMBOL(nftnl_flowtable_list_add_tail);
+
++EXPORT_SYMBOL(nftnl_flowtable_list_del);
+ void nftnl_flowtable_list_del(struct nftnl_flowtable *s)
+ {
+ list_del(&s->head);
+ }
+-EXPORT_SYMBOL(nftnl_flowtable_list_del);
+
++EXPORT_SYMBOL(nftnl_flowtable_list_foreach);
+ int nftnl_flowtable_list_foreach(struct nftnl_flowtable_list *flowtable_list,
+ int (*cb)(struct nftnl_flowtable *t, void *data), void *data)
+ {
+@@ -814,4 +815,3 @@ int nftnl_flowtable_list_foreach(struct nftnl_flowtable_list *flowtable_list,
+ }
+ return 0;
+ }
+-EXPORT_SYMBOL(nftnl_flowtable_list_foreach);
+
diff --git a/meta/meta-mediatek/recipes-connectivity/libnftnl/libnftnl/0002-avoid-naming-local-function-as-one-of-printf-family.patch b/meta/meta-mediatek/recipes-connectivity/libnftnl/libnftnl/0002-avoid-naming-local-function-as-one-of-printf-family.patch
new file mode 100644
index 0000000..1023f59
--- /dev/null
+++ b/meta/meta-mediatek/recipes-connectivity/libnftnl/libnftnl/0002-avoid-naming-local-function-as-one-of-printf-family.patch
@@ -0,0 +1,549 @@
+From 5ea9fa9d345005f2f53b1b598edb85f5f24ca9da Mon Sep 17 00:00:00 2001
+From: Alex Kiernan <alex.kiernan@gmail.com>
+Date: Wed, 7 Nov 2018 19:41:54 +0000
+Subject: [PATCH] avoid naming local function as one of printf family
+
+Fixes build issues with clang
+error: no member named '__builtin___snprintf_chk' in 'struct expr_ops'
+
+Signed-off-by: Khem Raj <raj.khem@gmail.com>
+Signed-off-by: Alex Kiernan <alex.kiernan@gmail.com>
+---
+ include/expr_ops.h | 2 +-
+ include/obj.h | 2 +-
+ src/expr.c | 4 ++--
+ src/expr/bitwise.c | 2 +-
+ src/expr/byteorder.c | 2 +-
+ src/expr/cmp.c | 2 +-
+ src/expr/connlimit.c | 2 +-
+ src/expr/counter.c | 2 +-
+ src/expr/ct.c | 2 +-
+ src/expr/dup.c | 2 +-
+ src/expr/dynset.c | 2 +-
+ src/expr/exthdr.c | 2 +-
+ src/expr/fib.c | 2 +-
+ src/expr/flow_offload.c | 2 +-
+ src/expr/fwd.c | 2 +-
+ src/expr/hash.c | 2 +-
+ src/expr/immediate.c | 2 +-
+ src/expr/limit.c | 2 +-
+ src/expr/log.c | 2 +-
+ src/expr/lookup.c | 2 +-
+ src/expr/masq.c | 2 +-
+ src/expr/match.c | 2 +-
+ src/expr/meta.c | 2 +-
+ src/expr/nat.c | 2 +-
+ src/expr/numgen.c | 2 +-
+ src/expr/objref.c | 2 +-
+ src/expr/payload.c | 2 +-
+ src/expr/queue.c | 2 +-
+ src/expr/quota.c | 2 +-
+ src/expr/range.c | 2 +-
+ src/expr/redir.c | 2 +-
+ src/expr/reject.c | 2 +-
+ src/expr/rt.c | 2 +-
+ src/expr/socket.c | 2 +-
+ src/expr/target.c | 2 +-
+ src/obj/counter.c | 2 +-
+ src/obj/ct_helper.c | 2 +-
+ src/obj/limit.c | 2 +-
+ src/obj/quota.c | 2 +-
+ src/object.c | 4 ++--
+ 40 files changed, 42 insertions(+), 42 deletions(-)
+
+diff --git a/include/expr_ops.h b/include/expr_ops.h
+index e639390..c4fe050 100644
+--- a/include/expr_ops.h
++++ b/include/expr_ops.h
+@@ -18,7 +18,7 @@ struct expr_ops {
+ const void *(*get)(const struct nftnl_expr *e, uint16_t type, uint32_t *data_len);
+ int (*parse)(struct nftnl_expr *e, struct nlattr *attr);
+ void (*build)(struct nlmsghdr *nlh, const struct nftnl_expr *e);
+- int (*snprintf)(char *buf, size_t len, uint32_t type, uint32_t flags, const struct nftnl_expr *e);
++ int (*snprintf_)(char *buf, size_t len, uint32_t type, uint32_t flags, const struct nftnl_expr *e);
+ int (*json_parse)(struct nftnl_expr *e, json_t *data,
+ struct nftnl_parse_err *err);
+ };
+diff --git a/include/obj.h b/include/obj.h
+index 4a728c8..4c20bd1 100644
+--- a/include/obj.h
++++ b/include/obj.h
+@@ -55,7 +55,7 @@ struct obj_ops {
+ const void *(*get)(const struct nftnl_obj *e, uint16_t type, uint32_t *data_len);
+ int (*parse)(struct nftnl_obj *e, struct nlattr *attr);
+ void (*build)(struct nlmsghdr *nlh, const struct nftnl_obj *e);
+- int (*snprintf)(char *buf, size_t len, uint32_t type, uint32_t flags, const struct nftnl_obj *e);
++ int (*snprintf_)(char *buf, size_t len, uint32_t type, uint32_t flags, const struct nftnl_obj *e);
+ int (*json_parse)(struct nftnl_obj *e, json_t *data,
+ struct nftnl_parse_err *err);
+ };
+diff --git a/src/expr.c b/src/expr.c
+index 62565e0..2489c30 100644
+--- a/src/expr.c
++++ b/src/expr.c
+@@ -285,10 +285,10 @@ int nftnl_expr_snprintf(char *buf, size_t size, const struct nftnl_expr *expr,
+ if (size)
+ buf[0] = '\0';
+
+- if (!expr->ops->snprintf)
++ if (!expr->ops->snprintf_)
+ return 0;
+
+- ret = expr->ops->snprintf(buf + offset, remain, type, flags, expr);
++ ret = expr->ops->snprintf_(buf + offset, remain, type, flags, expr);
+ SNPRINTF_BUFFER_SIZE(ret, remain, offset);
+
+ return offset;
+diff --git a/src/expr/bitwise.c b/src/expr/bitwise.c
+index a89734b..f8360b1 100644
+--- a/src/expr/bitwise.c
++++ b/src/expr/bitwise.c
+@@ -299,6 +299,6 @@ struct expr_ops expr_ops_bitwise = {
+ .get = nftnl_expr_bitwise_get,
+ .parse = nftnl_expr_bitwise_parse,
+ .build = nftnl_expr_bitwise_build,
+- .snprintf = nftnl_expr_bitwise_snprintf,
++ .snprintf_ = nftnl_expr_bitwise_snprintf,
+ .json_parse = nftnl_expr_bitwise_json_parse,
+ };
+diff --git a/src/expr/byteorder.c b/src/expr/byteorder.c
+index 47c04cf..61f733f 100644
+--- a/src/expr/byteorder.c
++++ b/src/expr/byteorder.c
+@@ -314,6 +314,6 @@ struct expr_ops expr_ops_byteorder = {
+ .get = nftnl_expr_byteorder_get,
+ .parse = nftnl_expr_byteorder_parse,
+ .build = nftnl_expr_byteorder_build,
+- .snprintf = nftnl_expr_byteorder_snprintf,
++ .snprintf_ = nftnl_expr_byteorder_snprintf,
+ .json_parse = nftnl_expr_byteorder_json_parse,
+ };
+diff --git a/src/expr/cmp.c b/src/expr/cmp.c
+index b26d0eb..522c7be 100644
+--- a/src/expr/cmp.c
++++ b/src/expr/cmp.c
+@@ -284,6 +284,6 @@ struct expr_ops expr_ops_cmp = {
+ .get = nftnl_expr_cmp_get,
+ .parse = nftnl_expr_cmp_parse,
+ .build = nftnl_expr_cmp_build,
+- .snprintf = nftnl_expr_cmp_snprintf,
++ .snprintf_ = nftnl_expr_cmp_snprintf,
+ .json_parse = nftnl_expr_cmp_json_parse,
+ };
+diff --git a/src/expr/connlimit.c b/src/expr/connlimit.c
+index 60965b5..4e41866 100644
+--- a/src/expr/connlimit.c
++++ b/src/expr/connlimit.c
+@@ -202,6 +202,6 @@ struct expr_ops expr_ops_connlimit = {
+ .get = nftnl_expr_connlimit_get,
+ .parse = nftnl_expr_connlimit_parse,
+ .build = nftnl_expr_connlimit_build,
+- .snprintf = nftnl_expr_connlimit_snprintf,
++ .snprintf_ = nftnl_expr_connlimit_snprintf,
+ .json_parse = nftnl_expr_connlimit_json_parse,
+ };
+diff --git a/src/expr/counter.c b/src/expr/counter.c
+index 21901e8..9fd7655 100644
+--- a/src/expr/counter.c
++++ b/src/expr/counter.c
+@@ -200,6 +200,6 @@ struct expr_ops expr_ops_counter = {
+ .get = nftnl_expr_counter_get,
+ .parse = nftnl_expr_counter_parse,
+ .build = nftnl_expr_counter_build,
+- .snprintf = nftnl_expr_counter_snprintf,
++ .snprintf_ = nftnl_expr_counter_snprintf,
+ .json_parse = nftnl_expr_counter_json_parse,
+ };
+diff --git a/src/expr/ct.c b/src/expr/ct.c
+index 39e9be6..b363f7c 100644
+--- a/src/expr/ct.c
++++ b/src/expr/ct.c
+@@ -357,6 +357,6 @@ struct expr_ops expr_ops_ct = {
+ .get = nftnl_expr_ct_get,
+ .parse = nftnl_expr_ct_parse,
+ .build = nftnl_expr_ct_build,
+- .snprintf = nftnl_expr_ct_snprintf,
++ .snprintf_ = nftnl_expr_ct_snprintf,
+ .json_parse = nftnl_expr_ct_json_parse,
+ };
+diff --git a/src/expr/dup.c b/src/expr/dup.c
+index ed8e620..8d603e3 100644
+--- a/src/expr/dup.c
++++ b/src/expr/dup.c
+@@ -206,6 +206,6 @@ struct expr_ops expr_ops_dup = {
+ .get = nftnl_expr_dup_get,
+ .parse = nftnl_expr_dup_parse,
+ .build = nftnl_expr_dup_build,
+- .snprintf = nftnl_expr_dup_snprintf,
++ .snprintf_ = nftnl_expr_dup_snprintf,
+ .json_parse = nftnl_expr_dup_json_parse,
+ };
+diff --git a/src/expr/dynset.c b/src/expr/dynset.c
+index 160d0e1..a43f4da 100644
+--- a/src/expr/dynset.c
++++ b/src/expr/dynset.c
+@@ -368,6 +368,6 @@ struct expr_ops expr_ops_dynset = {
+ .get = nftnl_expr_dynset_get,
+ .parse = nftnl_expr_dynset_parse,
+ .build = nftnl_expr_dynset_build,
+- .snprintf = nftnl_expr_dynset_snprintf,
++ .snprintf_ = nftnl_expr_dynset_snprintf,
+ .json_parse = nftnl_expr_dynset_json_parse,
+ };
+diff --git a/src/expr/exthdr.c b/src/expr/exthdr.c
+index 75cafbc..89ea7f5 100644
+--- a/src/expr/exthdr.c
++++ b/src/expr/exthdr.c
+@@ -385,6 +385,6 @@ struct expr_ops expr_ops_exthdr = {
+ .get = nftnl_expr_exthdr_get,
+ .parse = nftnl_expr_exthdr_parse,
+ .build = nftnl_expr_exthdr_build,
+- .snprintf = nftnl_expr_exthdr_snprintf,
++ .snprintf_ = nftnl_expr_exthdr_snprintf,
+ .json_parse = nftnl_expr_exthdr_json_parse,
+ };
+diff --git a/src/expr/fib.c b/src/expr/fib.c
+index b922b26..ece4645 100644
+--- a/src/expr/fib.c
++++ b/src/expr/fib.c
+@@ -274,6 +274,6 @@ struct expr_ops expr_ops_fib = {
+ .get = nftnl_expr_fib_get,
+ .parse = nftnl_expr_fib_parse,
+ .build = nftnl_expr_fib_build,
+- .snprintf = nftnl_expr_fib_snprintf,
++ .snprintf_ = nftnl_expr_fib_snprintf,
+ .json_parse = nftnl_expr_fib_json_parse,
+ };
+diff --git a/src/expr/flow_offload.c b/src/expr/flow_offload.c
+index a2001c9..9cdbc21 100644
+--- a/src/expr/flow_offload.c
++++ b/src/expr/flow_offload.c
+@@ -179,6 +179,6 @@ struct expr_ops expr_ops_flow = {
+ .get = nftnl_expr_flow_get,
+ .parse = nftnl_expr_flow_parse,
+ .build = nftnl_expr_flow_build,
+- .snprintf = nftnl_expr_flow_snprintf,
++ .snprintf_ = nftnl_expr_flow_snprintf,
+ .json_parse = nftnl_expr_flow_json_parse,
+ };
+diff --git a/src/expr/fwd.c b/src/expr/fwd.c
+index 9021606..7178f43 100644
+--- a/src/expr/fwd.c
++++ b/src/expr/fwd.c
+@@ -233,6 +233,6 @@ struct expr_ops expr_ops_fwd = {
+ .get = nftnl_expr_fwd_get,
+ .parse = nftnl_expr_fwd_parse,
+ .build = nftnl_expr_fwd_build,
+- .snprintf = nftnl_expr_fwd_snprintf,
++ .snprintf_ = nftnl_expr_fwd_snprintf,
+ .json_parse = nftnl_expr_fwd_json_parse,
+ };
+diff --git a/src/expr/hash.c b/src/expr/hash.c
+index 415537e..186c5b0 100644
+--- a/src/expr/hash.c
++++ b/src/expr/hash.c
+@@ -383,6 +383,6 @@ struct expr_ops expr_ops_hash = {
+ .get = nftnl_expr_hash_get,
+ .parse = nftnl_expr_hash_parse,
+ .build = nftnl_expr_hash_build,
+- .snprintf = nftnl_expr_hash_snprintf,
++ .snprintf_ = nftnl_expr_hash_snprintf,
+ .json_parse = nftnl_expr_hash_json_parse,
+ };
+diff --git a/src/expr/immediate.c b/src/expr/immediate.c
+index b0570bd..91ccbdc 100644
+--- a/src/expr/immediate.c
++++ b/src/expr/immediate.c
+@@ -316,6 +316,6 @@ struct expr_ops expr_ops_immediate = {
+ .get = nftnl_expr_immediate_get,
+ .parse = nftnl_expr_immediate_parse,
+ .build = nftnl_expr_immediate_build,
+- .snprintf = nftnl_expr_immediate_snprintf,
++ .snprintf_ = nftnl_expr_immediate_snprintf,
+ .json_parse = nftnl_expr_immediate_json_parse,
+ };
+diff --git a/src/expr/limit.c b/src/expr/limit.c
+index 856ab18..e71fc2f 100644
+--- a/src/expr/limit.c
++++ b/src/expr/limit.c
+@@ -285,6 +285,6 @@ struct expr_ops expr_ops_limit = {
+ .get = nftnl_expr_limit_get,
+ .parse = nftnl_expr_limit_parse,
+ .build = nftnl_expr_limit_build,
+- .snprintf = nftnl_expr_limit_snprintf,
++ .snprintf_ = nftnl_expr_limit_snprintf,
+ .json_parse = nftnl_expr_limit_json_parse,
+ };
+diff --git a/src/expr/log.c b/src/expr/log.c
+index 86d9651..5769c1c 100644
+--- a/src/expr/log.c
++++ b/src/expr/log.c
+@@ -353,6 +353,6 @@ struct expr_ops expr_ops_log = {
+ .get = nftnl_expr_log_get,
+ .parse = nftnl_expr_log_parse,
+ .build = nftnl_expr_log_build,
+- .snprintf = nftnl_expr_log_snprintf,
++ .snprintf_ = nftnl_expr_log_snprintf,
+ .json_parse = nftnl_expr_log_json_parse,
+ };
+diff --git a/src/expr/lookup.c b/src/expr/lookup.c
+index 5fcb81f..b2f0dd6 100644
+--- a/src/expr/lookup.c
++++ b/src/expr/lookup.c
+@@ -292,6 +292,6 @@ struct expr_ops expr_ops_lookup = {
+ .get = nftnl_expr_lookup_get,
+ .parse = nftnl_expr_lookup_parse,
+ .build = nftnl_expr_lookup_build,
+- .snprintf = nftnl_expr_lookup_snprintf,
++ .snprintf_ = nftnl_expr_lookup_snprintf,
+ .json_parse = nftnl_expr_lookup_json_parse,
+ };
+diff --git a/src/expr/masq.c b/src/expr/masq.c
+index 7c235d3..adec325 100644
+--- a/src/expr/masq.c
++++ b/src/expr/masq.c
+@@ -228,6 +228,6 @@ struct expr_ops expr_ops_masq = {
+ .get = nftnl_expr_masq_get,
+ .parse = nftnl_expr_masq_parse,
+ .build = nftnl_expr_masq_build,
+- .snprintf = nftnl_expr_masq_snprintf,
++ .snprintf_ = nftnl_expr_masq_snprintf,
+ .json_parse = nftnl_expr_masq_json_parse,
+ };
+diff --git a/src/expr/match.c b/src/expr/match.c
+index dd09e1e..f0d8868 100644
+--- a/src/expr/match.c
++++ b/src/expr/match.c
+@@ -249,6 +249,6 @@ struct expr_ops expr_ops_match = {
+ .get = nftnl_expr_match_get,
+ .parse = nftnl_expr_match_parse,
+ .build = nftnl_expr_match_build,
+- .snprintf = nftnl_expr_match_snprintf,
++ .snprintf_ = nftnl_expr_match_snprintf,
+ .json_parse = nftnl_expr_match_json_parse,
+ };
+diff --git a/src/expr/meta.c b/src/expr/meta.c
+index de82105..91f1ebb 100644
+--- a/src/expr/meta.c
++++ b/src/expr/meta.c
+@@ -291,6 +291,6 @@ struct expr_ops expr_ops_meta = {
+ .get = nftnl_expr_meta_get,
+ .parse = nftnl_expr_meta_parse,
+ .build = nftnl_expr_meta_build,
+- .snprintf = nftnl_expr_meta_snprintf,
++ .snprintf_ = nftnl_expr_meta_snprintf,
+ .json_parse = nftnl_expr_meta_json_parse,
+ };
+diff --git a/src/expr/nat.c b/src/expr/nat.c
+index 9271303..427c282 100644
+--- a/src/expr/nat.c
++++ b/src/expr/nat.c
+@@ -384,6 +384,6 @@ struct expr_ops expr_ops_nat = {
+ .get = nftnl_expr_nat_get,
+ .parse = nftnl_expr_nat_parse,
+ .build = nftnl_expr_nat_build,
+- .snprintf = nftnl_expr_nat_snprintf,
++ .snprintf_ = nftnl_expr_nat_snprintf,
+ .json_parse = nftnl_expr_nat_json_parse,
+ };
+diff --git a/src/expr/numgen.c b/src/expr/numgen.c
+index 5336fde..8e0479a 100644
+--- a/src/expr/numgen.c
++++ b/src/expr/numgen.c
+@@ -313,6 +313,6 @@ struct expr_ops expr_ops_ng = {
+ .get = nftnl_expr_ng_get,
+ .parse = nftnl_expr_ng_parse,
+ .build = nftnl_expr_ng_build,
+- .snprintf = nftnl_expr_ng_snprintf,
++ .snprintf_ = nftnl_expr_ng_snprintf,
+ .json_parse = nftnl_expr_ng_json_parse,
+ };
+diff --git a/src/expr/objref.c b/src/expr/objref.c
+index 64ee863..4504488 100644
+--- a/src/expr/objref.c
++++ b/src/expr/objref.c
+@@ -278,6 +278,6 @@ struct expr_ops expr_ops_objref = {
+ .get = nftnl_expr_objref_get,
+ .parse = nftnl_expr_objref_parse,
+ .build = nftnl_expr_objref_build,
+- .snprintf = nftnl_expr_objref_snprintf,
++ .snprintf_ = nftnl_expr_objref_snprintf,
+ .json_parse = nftnl_expr_objref_json_parse,
+ };
+diff --git a/src/expr/payload.c b/src/expr/payload.c
+index 91e1587..894ac08 100644
+--- a/src/expr/payload.c
++++ b/src/expr/payload.c
+@@ -348,6 +348,6 @@ struct expr_ops expr_ops_payload = {
+ .get = nftnl_expr_payload_get,
+ .parse = nftnl_expr_payload_parse,
+ .build = nftnl_expr_payload_build,
+- .snprintf = nftnl_expr_payload_snprintf,
++ .snprintf_ = nftnl_expr_payload_snprintf,
+ .json_parse = nftnl_expr_payload_json_parse,
+ };
+diff --git a/src/expr/queue.c b/src/expr/queue.c
+index a392a27..ee26c10 100644
+--- a/src/expr/queue.c
++++ b/src/expr/queue.c
+@@ -275,6 +275,6 @@ struct expr_ops expr_ops_queue = {
+ .get = nftnl_expr_queue_get,
+ .parse = nftnl_expr_queue_parse,
+ .build = nftnl_expr_queue_build,
+- .snprintf = nftnl_expr_queue_snprintf,
++ .snprintf_ = nftnl_expr_queue_snprintf,
+ .json_parse = nftnl_expr_queue_json_parse,
+ };
+diff --git a/src/expr/quota.c b/src/expr/quota.c
+index 667e6e1..ff5d182 100644
+--- a/src/expr/quota.c
++++ b/src/expr/quota.c
+@@ -203,6 +203,6 @@ struct expr_ops expr_ops_quota = {
+ .get = nftnl_expr_quota_get,
+ .parse = nftnl_expr_quota_parse,
+ .build = nftnl_expr_quota_build,
+- .snprintf = nftnl_expr_quota_snprintf,
++ .snprintf_ = nftnl_expr_quota_snprintf,
+ .json_parse = nftnl_expr_quota_json_parse,
+ };
+diff --git a/src/expr/range.c b/src/expr/range.c
+index b2789ff..8910f8a 100644
+--- a/src/expr/range.c
++++ b/src/expr/range.c
+@@ -283,6 +283,6 @@ struct expr_ops expr_ops_range = {
+ .get = nftnl_expr_range_get,
+ .parse = nftnl_expr_range_parse,
+ .build = nftnl_expr_range_build,
+- .snprintf = nftnl_expr_range_snprintf,
++ .snprintf_ = nftnl_expr_range_snprintf,
+ .json_parse = nftnl_expr_range_json_parse,
+ };
+diff --git a/src/expr/redir.c b/src/expr/redir.c
+index b2aa345..41b77ab 100644
+--- a/src/expr/redir.c
++++ b/src/expr/redir.c
+@@ -242,6 +242,6 @@ struct expr_ops expr_ops_redir = {
+ .get = nftnl_expr_redir_get,
+ .parse = nftnl_expr_redir_parse,
+ .build = nftnl_expr_redir_build,
+- .snprintf = nftnl_expr_redir_snprintf,
++ .snprintf_ = nftnl_expr_redir_snprintf,
+ .json_parse = nftnl_expr_redir_json_parse,
+ };
+diff --git a/src/expr/reject.c b/src/expr/reject.c
+index 11d8b20..b10e729 100644
+--- a/src/expr/reject.c
++++ b/src/expr/reject.c
+@@ -200,6 +200,6 @@ struct expr_ops expr_ops_reject = {
+ .get = nftnl_expr_reject_get,
+ .parse = nftnl_expr_reject_parse,
+ .build = nftnl_expr_reject_build,
+- .snprintf = nftnl_expr_reject_snprintf,
++ .snprintf_ = nftnl_expr_reject_snprintf,
+ .json_parse = nftnl_expr_reject_json_parse,
+ };
+diff --git a/src/expr/rt.c b/src/expr/rt.c
+index c3c92c7..688a042 100644
+--- a/src/expr/rt.c
++++ b/src/expr/rt.c
+@@ -235,6 +235,6 @@ struct expr_ops expr_ops_rt = {
+ .get = nftnl_expr_rt_get,
+ .parse = nftnl_expr_rt_parse,
+ .build = nftnl_expr_rt_build,
+- .snprintf = nftnl_expr_rt_snprintf,
++ .snprintf_ = nftnl_expr_rt_snprintf,
+ .json_parse = nftnl_expr_rt_json_parse,
+ };
+diff --git a/src/expr/socket.c b/src/expr/socket.c
+index db160a1..4c50011 100644
+--- a/src/expr/socket.c
++++ b/src/expr/socket.c
+@@ -204,5 +204,5 @@ struct expr_ops expr_ops_socket = {
+ .get = nftnl_expr_socket_get,
+ .parse = nftnl_expr_socket_parse,
+ .build = nftnl_expr_socket_build,
+- .snprintf = nftnl_expr_socket_snprintf,
++ .snprintf_ = nftnl_expr_socket_snprintf,
+ };
+diff --git a/src/expr/target.c b/src/expr/target.c
+index ed4bf7d..2ef4078 100644
+--- a/src/expr/target.c
++++ b/src/expr/target.c
+@@ -249,6 +249,6 @@ struct expr_ops expr_ops_target = {
+ .get = nftnl_expr_target_get,
+ .parse = nftnl_expr_target_parse,
+ .build = nftnl_expr_target_build,
+- .snprintf = nftnl_expr_target_snprintf,
++ .snprintf_ = nftnl_expr_target_snprintf,
+ .json_parse = nftnl_expr_target_json_parse,
+ };
+diff --git a/src/obj/counter.c b/src/obj/counter.c
+index 332bb2b..edeb7be 100644
+--- a/src/obj/counter.c
++++ b/src/obj/counter.c
+@@ -182,6 +182,6 @@ struct obj_ops obj_ops_counter = {
+ .get = nftnl_obj_counter_get,
+ .parse = nftnl_obj_counter_parse,
+ .build = nftnl_obj_counter_build,
+- .snprintf = nftnl_obj_counter_snprintf,
++ .snprintf_ = nftnl_obj_counter_snprintf,
+ .json_parse = nftnl_obj_counter_json_parse,
+ };
+diff --git a/src/obj/ct_helper.c b/src/obj/ct_helper.c
+index 62569fe..69757ff 100644
+--- a/src/obj/ct_helper.c
++++ b/src/obj/ct_helper.c
+@@ -208,6 +208,6 @@ struct obj_ops obj_ops_ct_helper = {
+ .get = nftnl_obj_ct_helper_get,
+ .parse = nftnl_obj_ct_helper_parse,
+ .build = nftnl_obj_ct_helper_build,
+- .snprintf = nftnl_obj_ct_helper_snprintf,
++ .snprintf_ = nftnl_obj_ct_helper_snprintf,
+ .json_parse = nftnl_obj_quota_json_parse,
+ };
+diff --git a/src/obj/limit.c b/src/obj/limit.c
+index 7f8bcf7..25018b6 100644
+--- a/src/obj/limit.c
++++ b/src/obj/limit.c
+@@ -236,6 +236,6 @@ struct obj_ops obj_ops_limit = {
+ .get = nftnl_obj_limit_get,
+ .parse = nftnl_obj_limit_parse,
+ .build = nftnl_obj_limit_build,
+- .snprintf = nftnl_obj_limit_snprintf,
++ .snprintf_ = nftnl_obj_limit_snprintf,
+ .json_parse = nftnl_obj_limit_json_parse,
+ };
+diff --git a/src/obj/quota.c b/src/obj/quota.c
+index 6d36784..ecaa8b1 100644
+--- a/src/obj/quota.c
++++ b/src/obj/quota.c
+@@ -203,6 +203,6 @@ struct obj_ops obj_ops_quota = {
+ .get = nftnl_obj_quota_get,
+ .parse = nftnl_obj_quota_parse,
+ .build = nftnl_obj_quota_build,
+- .snprintf = nftnl_obj_quota_snprintf,
++ .snprintf_ = nftnl_obj_quota_snprintf,
+ .json_parse = nftnl_obj_quota_json_parse,
+ };
+diff --git a/src/object.c b/src/object.c
+index d8278f3..9654b7b 100644
+--- a/src/object.c
++++ b/src/object.c
+@@ -429,7 +429,7 @@ static int nftnl_obj_export(char *buf, size_t size,
+ nftnl_buf_u64(&b, type, obj->handle, HANDLE);
+
+ if (obj->ops)
+- ret = obj->ops->snprintf(buf + b.len, size - b.len, type,
++ ret = obj->ops->snprintf_(buf + b.len, size - b.len, type,
+ flags, obj);
+
+ b.len += ret;
+@@ -450,7 +450,7 @@ static int nftnl_obj_snprintf_dflt(char *buf, size_t size,
+ SNPRINTF_BUFFER_SIZE(ret, remain, offset);
+
+ if (obj->ops) {
+- ret = obj->ops->snprintf(buf + offset, offset, type, flags,
++ ret = obj->ops->snprintf_(buf + offset, offset, type, flags,
+ obj);
+ SNPRINTF_BUFFER_SIZE(ret, remain, offset);
+ }
\ No newline at end of file
diff --git a/meta/meta-mediatek/recipes-connectivity/libnftnl/libnftnl_%.bbappend b/meta/meta-mediatek/recipes-connectivity/libnftnl/libnftnl_%.bbappend
new file mode 100644
index 0000000..c5fb9ce
--- /dev/null
+++ b/meta/meta-mediatek/recipes-connectivity/libnftnl/libnftnl_%.bbappend
@@ -0,0 +1,16 @@
+SUMMARY = "Library for low-level interaction with nftables Netlink's API over libmnl"
+LICENSE = "GPLv2"
+LIC_FILES_CHKSUM = "file://COPYING;md5=79808397c3355f163c012616125c9e26"
+SECTION = "libs"
+DEPENDS = "libmnl"
+PV .= "+git${SRCPV}"
+FILESEXTRAPATHS_append := ":${THISDIR}/${PN}"
+SRCREV = "d379dfcb6c94dcb93a8f16896572d6e162138e0f"
+SRC_URI = "git://git.netfilter.org/libnftnl \
+ file://0001-Move-exports-before-symbol-definition.patch \
+ file://0002-avoid-naming-local-function-as-one-of-printf-family.patch \
+ "
+
+S = "${WORKDIR}/git"
+
+inherit autotools pkgconfig
diff --git a/meta/meta-mediatek/recipes-connectivity/mnld/gnsstest.bb b/meta/meta-mediatek/recipes-connectivity/mnld/gnsstest.bb
new file mode 100644
index 0000000..466ff8e
--- /dev/null
+++ b/meta/meta-mediatek/recipes-connectivity/mnld/gnsstest.bb
@@ -0,0 +1,35 @@
+DESCRIPTION = "MTK GNSS Test"
+LICENSE = "MediaTekProprietary"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=e1696b147d49d491bcb4da1a57173fff"
+
+DEPENDS += "gpshal"
+
+inherit workonsrc
+WORKONSRC = "${TOPDIR}/../src/connectivity/gps/gnss_test/"
+inherit systemd
+SYSTEMD_PACKAGES = "${PN}"
+
+DEPENDS += "openssl curl gpshal"
+
+# Avoid QA Issue: No GNU_HASH in the elf binary
+INSANE_SKIP_${PN} = "ldflags"
+INSANE_SKIP_${PN}-dev = "ldflags"
+FILES_${PN}-dev = "${includedir}"
+
+# Avoid QA Issue: 'Files/directories were installed but not shipped'
+INSANE_SKIP_${PN} += "installed-vs-shipped"
+FLAGS = "${@bb.utils.contains("ADR_SUPPORT","YES", "-DMTK_ADR_SUPPORT","",d)}"
+
+EXTRA_OEMAKE = "\
+ 'PACKAGE_ARCH=${PACKAGE_ARCH}' \
+ 'DNS_FLAGS=${FLAGS}' \
+ "
+
+do_install_append() {
+ install -d ${D}${bindir}
+}
+
+INSANE_SKIP_${PN} += "already-stripped"
+
+inherit autotools
+
diff --git a/meta/meta-mediatek/recipes-connectivity/mnld/gnsstest3303.bb b/meta/meta-mediatek/recipes-connectivity/mnld/gnsstest3303.bb
new file mode 100644
index 0000000..98daa06
--- /dev/null
+++ b/meta/meta-mediatek/recipes-connectivity/mnld/gnsstest3303.bb
@@ -0,0 +1,35 @@
+DESCRIPTION = "MTK GNSS Test"
+LICENSE = "MediaTekProprietary"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=e1696b147d49d491bcb4da1a57173fff"
+
+DEPENDS += "gpshal"
+
+inherit workonsrc
+WORKONSRC = "${TOPDIR}/../src/connectivity/gps/gnss_test/"
+inherit systemd
+SYSTEMD_PACKAGES = "${PN}"
+
+DEPENDS += "openssl curl gpshal"
+
+# Avoid QA Issue: No GNU_HASH in the elf binary
+INSANE_SKIP_${PN} = "ldflags"
+INSANE_SKIP_${PN}-dev = "ldflags"
+FILES_${PN}-dev = "${includedir}"
+
+# Avoid QA Issue: 'Files/directories were installed but not shipped'
+INSANE_SKIP_${PN} += "installed-vs-shipped"
+FLAGS = "-DCONFIG_GPS_MT3303 ${@bb.utils.contains("ADR_SUPPORT","YES", "-DMTK_ADR_SUPPORT","",d)}"
+
+EXTRA_OEMAKE = "\
+ 'PACKAGE_ARCH=${PACKAGE_ARCH}' \
+ 'DNS_FLAGS=${FLAGS}' \
+ "
+
+do_install_append() {
+ install -d ${D}${bindir}
+}
+
+INSANE_SKIP_${PN} += "already-stripped"
+
+inherit autotools
+
diff --git a/meta/meta-mediatek/recipes-connectivity/mnld/gpshal.bb b/meta/meta-mediatek/recipes-connectivity/mnld/gpshal.bb
new file mode 100644
index 0000000..be0e9c4
--- /dev/null
+++ b/meta/meta-mediatek/recipes-connectivity/mnld/gpshal.bb
@@ -0,0 +1,27 @@
+DESCRIPTION = "MTK GNSS HAL"
+LICENSE = "MediaTekProprietary"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=e1696b147d49d491bcb4da1a57173fff"
+
+inherit workonsrc
+WORKONSRC = "${TOPDIR}/../src/connectivity/gps/gps_hal/"
+inherit systemd
+SYSTEMD_PACKAGES = "${PN}"
+
+# Avoid QA Issue: No GNU_HASH in the elf binary
+INSANE_SKIP_${PN} = "ldflags"
+INSANE_SKIP_${PN}-dev = "ldflags"
+FILES_${PN}-dev = "${includedir}"
+
+# Avoid QA Issue: 'Files/directories were installed but not shipped'
+INSANE_SKIP_${PN} += "installed-vs-shipped"
+
+EXTRA_OEMAKE = "PACKAGE_ARCH=${PACKAGE_ARCH}"
+
+do_install_append() {
+ install -d ${D}${libdir}
+}
+
+INSANE_SKIP_${PN} += "already-stripped"
+
+inherit autotools
+
diff --git a/meta/meta-mediatek/recipes-connectivity/mnld/mnld.bb b/meta/meta-mediatek/recipes-connectivity/mnld/mnld.bb
new file mode 100755
index 0000000..ef3b61e
--- /dev/null
+++ b/meta/meta-mediatek/recipes-connectivity/mnld/mnld.bb
@@ -0,0 +1,65 @@
+DESCRIPTION = "MTK GNSS driver"
+LICENSE = "MediaTekProprietary"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=e1696b147d49d491bcb4da1a57173fff"
+
+inherit workonsrc
+WORKONSRC = "${TOPDIR}/../src/connectivity/gps/mtk_mnld/"
+inherit systemd
+SYSTEMD_PACKAGES = "${PN}"
+SYSTEMD_SERVICE_${PN} = "mnld.service"
+
+FILES_${PN} += "${systemd_unitdir}/system/mnld.service"
+FILES_${PN} += "${libdir}/libmnl_gnss.so*"
+FILES_${PN} += "${bindir}/mnld0"
+FILES_${PN} += "/data/misc"
+FILES_${PN} += "/data/misc/gps"
+FILES_${PN} += "/data/gps_mnl"
+FILES_${PN} += "/data/mpe_mnl"
+FILES_${PN} += "/data/agps_supl"
+FILES_${PN} += "/usr/share/gps"
+FILES_${PN} += "/usr/share/gps/mpe_mnl"
+
+DEPENDS += "openssl curl"
+
+# Avoid QA Issue: No GNU_HASH in the elf binary
+INSANE_SKIP_${PN} = "ldflags"
+INSANE_SKIP_${PN}-dev = "ldflags"
+#FILES_${PN} = "${libdir}/*.so"
+FILES_${PN}-dev = "${includedir}"
+
+# Avoid QA Issue: 'Files/directories were installed but not shipped'
+INSANE_SKIP_${PN} += "installed-vs-shipped"
+FLAGS = "-Os -flto ${@bb.utils.contains("ADR_SUPPORT","YES", "-DMTK_ADR_SUPPORT","",d)}"
+
+EXTRA_OEMAKE = "\
+ 'PACKAGE_ARCH=${PACKAGE_ARCH}' \
+ 'DNS_FLAGS=${FLAGS}' \
+ "
+
+do_compile_append() {
+ cp mnl/libs/linux/${PACKAGE_ARCH}/lib* mnl/libs/
+}
+
+do_install_append() {
+ install -d ${D}${libdir}
+ install -d ${D}${bindir}
+ install -d ${D}/data/misc
+ install -d ${D}/data/misc/gps
+ install -d ${D}/data/gps_mnl
+ install -d ${D}/data/mpe_mnl
+ install -d ${D}/data/agps_supl
+ install -d ${D}/usr/share/gps
+ install -d ${D}/usr/share/gps/mpe_mnl
+ install -m 0755 mnld0 ${D}${bindir}
+ install -m 0755 ${TOPDIR}/../src/connectivity/gps/mtk_mnld/mnl/libs/linux/${PACKAGE_ARCH}/libmnl_gnss.so ${D}${libdir}
+ if ${@bb.utils.contains('DISTRO_FEATURES','systemd','true','false',d)}; then
+ install -d ${D}${systemd_unitdir}/system/
+ install -m 0644 ${B}/mnld.service ${D}${systemd_unitdir}/system
+ fi
+}
+
+
+INSANE_SKIP_${PN} += "already-stripped"
+
+inherit autotools
+
diff --git a/meta/meta-mediatek/recipes-connectivity/mnld/mnld3303.bb b/meta/meta-mediatek/recipes-connectivity/mnld/mnld3303.bb
new file mode 100644
index 0000000..289c675
--- /dev/null
+++ b/meta/meta-mediatek/recipes-connectivity/mnld/mnld3303.bb
@@ -0,0 +1,63 @@
+DESCRIPTION = "MTK GNSS driver"
+LICENSE = "MediaTekProprietary"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=e1696b147d49d491bcb4da1a57173fff"
+
+inherit workonsrc
+WORKONSRC = "${TOPDIR}/../src/connectivity/gps/mtk_mnld/"
+inherit systemd
+SYSTEMD_PACKAGES = "${PN}"
+SYSTEMD_SERVICE_${PN} = "mnld.service"
+
+FILES_${PN} += "${systemd_unitdir}/system/mnld.service"
+FILES_${PN} += "${libdir}/libmnl_gnss.so*"
+FILES_${PN} += "${bindir}/mnld0"
+FILES_${PN} += "/usr/share/gps"
+
+DEPENDS += "openssl curl"
+
+# Avoid QA Issue: No GNU_HASH in the elf binary
+INSANE_SKIP_${PN} = "ldflags"
+INSANE_SKIP_${PN}-dev = "ldflags"
+#FILES_${PN} = "${libdir}/*.so"
+FILES_${PN}-dev = "${includedir}"
+
+# Avoid QA Issue: 'Files/directories were installed but not shipped'
+INSANE_SKIP_${PN} += "installed-vs-shipped"
+FLAGS = "-Os -flto -DCONFIG_GPS_MT3303 ${@bb.utils.contains("ADR_SUPPORT","YES", "-DMTK_ADR_SUPPORT","",d)}"
+FLAGS += "${@bb.utils.contains('TARGET_PLATFORM','mt2712', '-DCONFIG_GPS_MT3303_TTYS1','',d)}"
+FLAGS += "${@bb.utils.contains('TARGET_PLATFORM','mt2712', '-DCONFIG_GPS_MT3303_WITHOUT_POWER_CONTROL','',d)}"
+
+EXTRA_OEMAKE = "\
+ 'PACKAGE_ARCH=${PACKAGE_ARCH}' \
+ 'TARGET_PLATFORM=${TARGET_PLATFORM}' \
+ 'DNS_FLAGS=${FLAGS}' \
+ "
+
+do_compile_append() {
+ cp mnl/libs/linux/${PACKAGE_ARCH}/lib* mnl/libs/
+}
+
+do_install_append() {
+ install -d ${D}${libdir}
+ install -d ${D}/usr/share/gps
+ install -m 0755 mnld0 ${D}${bindir}
+ install -m 0755 ${TOPDIR}/../src/connectivity/gps/mtk_mnld/flashdownload/bin/* ${D}/usr/share/gps
+ install -m 0755 ${TOPDIR}/../src/connectivity/gps/mtk_mnld/mnl/libs/linux/${PACKAGE_ARCH}/libmnl_gnss.so ${D}${libdir}
+ if ${@bb.utils.contains('DISTRO_FEATURES','systemd','true','false',d)}; then
+ install -d ${D}${systemd_unitdir}/system/
+ fi
+
+ if ${@bb.utils.contains('TARGET_PLATFORM','mt2731','true','false',d)}; then
+ install -m 0644 ${B}/mnld_mt33xx.service ${D}${systemd_unitdir}/system/mnld.service
+ fi
+
+ if ${@bb.utils.contains('TARGET_PLATFORM','mt2712','true','false',d)}; then
+ install -m 0644 ${B}/mnld.service ${D}${systemd_unitdir}/system/mnld.service
+ fi
+}
+
+
+INSANE_SKIP_${PN} += "already-stripped"
+
+inherit autotools
+
diff --git a/meta/meta-mediatek/recipes-connectivity/network_cfg/mtknetworkcfg.bb b/meta/meta-mediatek/recipes-connectivity/network_cfg/mtknetworkcfg.bb
new file mode 100644
index 0000000..b2d8a8e
--- /dev/null
+++ b/meta/meta-mediatek/recipes-connectivity/network_cfg/mtknetworkcfg.bb
@@ -0,0 +1,22 @@
+DESCRIPTION = "Network Config"
+LICENSE = "MediaTekProprietary"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=e1696b147d49d491bcb4da1a57173fff"
+INSANE_SKIP_${PN} += "installed-vs-shipped"
+FILES_${PN} += "/etc/hostapd_mtk.conf"
+FILES_${PN} += "/etc/dhcpd.conf"
+FILES_${PN} += "/etc/udhcpd.conf"
+FILES_${PN} += "/bin/runap.sh"
+FILES_${PN} += "/etc/dnsmasq_mtk.conf"
+
+inherit workonsrc
+WORKONSRC = "${TOPDIR}/../src/connectivity/network_cfg"
+
+do_install_append () {
+ install -d ${D}/etc/
+ install -m 0644 ${S}/hostapd_conf/hostapd.conf.in ${D}/etc/hostapd_mtk.conf
+ install -m 0644 ${S}/dhcpd_conf/dhcpd.sample.conf ${D}/etc/dhcpd.conf
+ install -m 0644 ${S}/udhcpd_conf/udhcpd.conf ${D}/etc/udhcpd.conf
+ install -m 0644 ${S}/dnsmasq_conf/dnsmasq_mtk.conf ${D}/etc/dnsmasq_mtk.conf
+ install -d ${D}/bin/
+ install -m 0755 ${S}/hostapd_conf/runap.sh ${D}/bin/runap.sh
+}
diff --git a/meta/meta-mediatek/recipes-connectivity/nftables/nftables_%.bbappend b/meta/meta-mediatek/recipes-connectivity/nftables/nftables_%.bbappend
new file mode 100644
index 0000000..1e670ec
--- /dev/null
+++ b/meta/meta-mediatek/recipes-connectivity/nftables/nftables_%.bbappend
@@ -0,0 +1,22 @@
+SUMMARY = "Netfilter Tables userspace utillites"
+SECTION = "net"
+LICENSE = "GPLv2"
+LIC_FILES_CHKSUM = "file://COPYING;md5=d1a78fdd879a263a5e0b42d1fc565e79"
+PN = "nftables"
+PV = "0.9.0"
+BP = "nftables-0.9.0"
+DEPENDS = "libmnl libnftnl readline gmp bison-native"
+
+SRC_URI = "http://www.netfilter.org/projects/nftables/files/nftables-0.9.0.tar.bz2 \
+ "
+SRC_URI[md5sum] = "d4dcb61df80aa544b2e142e91d937635"
+SRC_URI[sha256sum] = "ad8181b5fcb9ca572f444bed54018749588522ee97e4c21922648bb78d7e7e91"
+
+inherit autotools manpages pkgconfig
+
+PACKAGECONFIG ?= ""
+PACKAGECONFIG[man] = "--enable--man-doc, --disable-man-doc"
+
+ASNEEDED = ""
+
+RRECOMMENDS_${PN} += "kernel-module-nf-tables"
diff --git a/meta/meta-mediatek/recipes-connectivity/packagegroups/packagegroup-mtk-3303.bb b/meta/meta-mediatek/recipes-connectivity/packagegroups/packagegroup-mtk-3303.bb
new file mode 100644
index 0000000..64938f8
--- /dev/null
+++ b/meta/meta-mediatek/recipes-connectivity/packagegroups/packagegroup-mtk-3303.bb
@@ -0,0 +1,10 @@
+SUMMARY = "Mediatek 3303 firmware"
+LICENSE = "MediaTekProprietary"
+
+inherit packagegroup
+
+RDEPENDS_packagegroup-mtk-3303 = "\
+ gpshal \
+ ${@bb.utils.contains("KERNEL_ARCH", "arm64", "lib32-mnld3303", "mnld3303", d)} \
+ gnsstest3303 \
+"
\ No newline at end of file
diff --git a/meta/meta-mediatek/recipes-connectivity/packagegroups/packagegroup-mtk-6630-without-gps.bb b/meta/meta-mediatek/recipes-connectivity/packagegroups/packagegroup-mtk-6630-without-gps.bb
new file mode 100755
index 0000000..bdf8f61
--- /dev/null
+++ b/meta/meta-mediatek/recipes-connectivity/packagegroups/packagegroup-mtk-6630-without-gps.bb
@@ -0,0 +1,16 @@
+SUMMARY = "Mediatek 6630 firmware"
+LICENSE = "MediaTekProprietary"
+
+inherit packagegroup
+
+
+RDEPENDS_packagegroup-mtk-6630-without-gps = "\
+ mtkcombotool\
+ mtknetworkcfg \
+ mtkcombo \
+ mtkwifitesttool \
+ hostapd \
+ ${@bb.utils.contains("TEST_LOAD_ENABLE", "YES", "dhcp-server", "", d)} \
+ ${@bb.utils.contains("TEST_LOAD_ENABLE", "YES", "dhcp-client", "", d)} \
+ ${@bb.utils.contains("TEST_LOAD_ENABLE", "YES", "dhcp-relay", "", d)} \
+"
diff --git a/meta/meta-mediatek/recipes-connectivity/packagegroups/packagegroup-mtk-6630.bb b/meta/meta-mediatek/recipes-connectivity/packagegroups/packagegroup-mtk-6630.bb
new file mode 100644
index 0000000..a439b58
--- /dev/null
+++ b/meta/meta-mediatek/recipes-connectivity/packagegroups/packagegroup-mtk-6630.bb
@@ -0,0 +1,18 @@
+SUMMARY = "Mediatek 6630 firmware"
+LICENSE = "MediaTekProprietary"
+
+inherit packagegroup
+
+RDEPENDS_packagegroup-mtk-6630 = "\
+ mtkcombotool\
+ mtknetworkcfg \
+ mtkcombo \
+ mtkwifitesttool \
+ gpshal \
+ ${@bb.utils.contains("TARGET_PLATFORM", "mt2712", "lib32-mnld", "mnld", d)} \
+ gnsstest \
+ hostapd \
+ ${@bb.utils.contains("TEST_LOAD_ENABLE", "YES", "dhcp-server", "", d)} \
+ ${@bb.utils.contains("TEST_LOAD_ENABLE", "YES", "dhcp-client", "", d)} \
+ ${@bb.utils.contains("TEST_LOAD_ENABLE", "YES", "dhcp-relay", "", d)} \
+"
diff --git a/meta/meta-mediatek/recipes-connectivity/packagegroups/packagegroup-wifi-common.bb b/meta/meta-mediatek/recipes-connectivity/packagegroups/packagegroup-wifi-common.bb
new file mode 100644
index 0000000..61f9cd4
--- /dev/null
+++ b/meta/meta-mediatek/recipes-connectivity/packagegroups/packagegroup-wifi-common.bb
@@ -0,0 +1,15 @@
+SUMMARY = "wifi common"
+#all bbs in this packagegroup have nothing to do with driver chip.
+LICENSE = "MediaTekProprietary"
+
+inherit packagegroup
+
+
+RDEPENDS_packagegroup-wifi-common = "\
+ mtknetworkcfg \
+ connman-client \
+ hostapd \
+ ${@bb.utils.contains("TEST_LOAD_ENABLE", "YES", "dhcp-server", "", d)} \
+ ${@bb.utils.contains("TEST_LOAD_ENABLE", "YES", "dhcp-client", "", d)} \
+ ${@bb.utils.contains("TEST_LOAD_ENABLE", "YES", "dhcp-relay", "", d)} \
+"
diff --git a/meta/meta-mediatek/recipes-connectivity/patch_folder/mtkcombo.bb b/meta/meta-mediatek/recipes-connectivity/patch_folder/mtkcombo.bb
new file mode 100755
index 0000000..f0781c5
--- /dev/null
+++ b/meta/meta-mediatek/recipes-connectivity/patch_folder/mtkcombo.bb
@@ -0,0 +1,37 @@
+DESCRIPTION = "Combo FW"
+LICENSE = "MediaTekProprietary"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=e1696b147d49d491bcb4da1a57173fff"
+INSANE_SKIP_${PN} += "installed-vs-shipped"
+FILES_${PN} += "/lib/firmware/mt6630_patch_e3_0_hdr.bin /lib/firmware/mt6630_patch_e3_1_hdr.bin"
+FILES_${PN} += "/lib/firmware/ROMv2_lm_patch_1_0_hdr.bin /lib/firmware/ROMv2_lm_patch_1_1_hdr.bin"
+FILES_${PN} += "/lib/firmware/WIFI_RAM_CODE_MT6630"
+FILES_${PN} += "/vendor/firmware/WIFI_RAM_CODE_8167"
+
+inherit workonsrc
+WORKONSRC = "${TOPDIR}/../src/connectivity/combo_tool/patch_folder"
+
+do_install () {
+ if test "${COMBO_CHIP_ID}" = "mt6630"; then
+ install -d ${D}/lib/firmware
+ if test "${TARGET_PLATFORM}" = "mt2731"; then
+ install -m 0755 ${S}/mt2731/mt6630_patch_e3_0_hdr.bin ${D}/lib/firmware
+ install -m 0755 ${S}/mt2731/mt6630_patch_e3_1_hdr.bin ${D}/lib/firmware
+ else
+ install -m 0755 ${S}/mt6630_patch_e3_0_hdr.bin ${D}/lib/firmware
+ install -m 0755 ${S}/mt6630_patch_e3_1_hdr.bin ${D}/lib/firmware
+ fi
+ if test "${TARGET_PLATFORM}" = "mt8516"; then
+ install -m 0755 ${S}/audio/WIFI_RAM_CODE_MT6630 ${D}/lib/firmware
+ else
+ install -m 0755 ${S}/WIFI_RAM_CODE_MT6630 ${D}/lib/firmware
+ fi
+ fi
+
+ if test "${COMBO_CHIP_ID}" = "mt8167"; then
+ install -d ${D}/lib/firmware
+ install -m 0755 ${S}/ROMv2_lm_patch_1_0_hdr.bin ${D}/lib/firmware
+ install -m 0755 ${S}/ROMv2_lm_patch_1_1_hdr.bin ${D}/lib/firmware
+ install -d ${D}/vendor/firmware
+ install -m 0755 ${S}/WIFI_RAM_CODE_8167 ${D}/vendor/firmware
+ fi
+}
diff --git a/meta/meta-mediatek/recipes-connectivity/wifitesttool/mtkwifitesttool-7668.bb b/meta/meta-mediatek/recipes-connectivity/wifitesttool/mtkwifitesttool-7668.bb
new file mode 100644
index 0000000..256e877
--- /dev/null
+++ b/meta/meta-mediatek/recipes-connectivity/wifitesttool/mtkwifitesttool-7668.bb
@@ -0,0 +1,31 @@
+DESCRIPTION = "Wi-Fi test tool fro HW test"
+LICENSE = "MediaTekProprietary"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=269275cbb6a31791d8edd8137e3612f6"
+
+inherit workonsrc
+WORKONSRC = "${TOPDIR}/../src/connectivity/wlan_tool/wifi_test_tool/wifitesttool"
+MODULE_NAME = "wifitest"
+
+do_compile() {
+ if test "${COMBO_CHIP_ID}" = "mt7668"; then
+ echo mt7668 wifi tool start compile
+ echo ${WORKONSRC}
+ echo ${S}
+
+ cd ${S} && oe_runmake CFLAGS="-DCONFIG_YOCTO_EEPROM_PATH=1"
+ echo mt7668 wifi tool end compile
+ fi
+}
+
+do_install() {
+ echo ${D}
+
+ if test "${COMBO_CHIP_ID}" = "mt7668"; then
+ install -d ${D}/usr/sbin/
+ install -m 0755 ${S}/${MODULE_NAME} ${D}/usr/sbin
+ fi
+}
+
+FILES_${PN} += "/usr/sbin"
+FILES_${PN}-dev = ""
+INSANE_SKIP_${PN} += "ldflags"
\ No newline at end of file
diff --git a/meta/meta-mediatek/recipes-connectivity/wifitesttool/mtkwifitesttool.bb b/meta/meta-mediatek/recipes-connectivity/wifitesttool/mtkwifitesttool.bb
new file mode 100755
index 0000000..850fb6f
--- /dev/null
+++ b/meta/meta-mediatek/recipes-connectivity/wifitesttool/mtkwifitesttool.bb
@@ -0,0 +1,8 @@
+DESCRIPTION = "Wi-Fi test tool fro HW test"
+LICENSE = "MediaTekProprietary"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=e1696b147d49d491bcb4da1a57173fff"
+
+inherit workonsrc
+WORKONSRC = "${TOPDIR}/../src/connectivity/wifitesttool"
+
+inherit autotools
diff --git a/meta/meta-mediatek/recipes-connectivity/wireless-tools/wireless-tools/avoid_strip.patch b/meta/meta-mediatek/recipes-connectivity/wireless-tools/wireless-tools/avoid_strip.patch
new file mode 100644
index 0000000..f34e243
--- /dev/null
+++ b/meta/meta-mediatek/recipes-connectivity/wireless-tools/wireless-tools/avoid_strip.patch
@@ -0,0 +1,21 @@
+wireless_tools: Avoid stripping iwmulticall
+
+Upstream-Status: Inappropriate [other]
+ The removed code was from upstream.
+
+Signed-off-by: Mark Hatle <mark.hatle@windriver.com>
+
+diff -ur wireless_tools.29.orig/Makefile wireless_tools.29/Makefile
+--- wireless_tools.29.orig/Makefile 2011-06-18 11:35:12.183907453 -0500
++++ wireless_tools.29/Makefile 2011-06-18 11:38:09.995907985 -0500
+@@ -135,9 +135,8 @@
+
+ macaddr: macaddr.o $(IWLIB)
+
+-# Always do symbol stripping here
+ iwmulticall: iwmulticall.o
+- $(CC) $(LDFLAGS) -Wl,-s $(XCFLAGS) -o $@ $^ $(LIBS)
++ $(CC) $(LDFLAGS) $(STRIPFLAGS) $(XCFLAGS) -o $@ $^ $(LIBS)
+
+ # It's a kind of magic...
+ wireless.h:
diff --git a/meta/meta-mediatek/recipes-connectivity/wireless-tools/wireless-tools/ldflags.patch b/meta/meta-mediatek/recipes-connectivity/wireless-tools/wireless-tools/ldflags.patch
new file mode 100644
index 0000000..6c0d8cb
--- /dev/null
+++ b/meta/meta-mediatek/recipes-connectivity/wireless-tools/wireless-tools/ldflags.patch
@@ -0,0 +1,22 @@
+wireless-tools: Remove QA warning: No GNU_HASH in the elf binary
+
+Upstream-Status: Inappropriate [other]
+ Useful within bitbake environment only.
+
+Signed-off-by: Muhammad Shakeel <muhammad_shakeel@mentor.com>
+
+---
+ Makefile | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- wireless_tools.29.orig/Makefile
++++ wireless_tools.29/Makefile
+@@ -144,7 +144,7 @@ wireless.h:
+
+ # Compilation of the dynamic library
+ $(DYNAMIC): $(OBJS:.o=.so)
+- $(CC) -shared -o $@ -Wl,-soname,$@ $(STRIPFLAGS) $(LIBS) -lc $^
++ $(CC) -shared -o $@ -Wl,-soname,$@ $(LDFLAGS) $(STRIPFLAGS) $(LIBS) -lc $^
+
+ # Compilation of the static library
+ $(STATIC): $(OBJS:.o=.so)
diff --git a/meta/meta-mediatek/recipes-connectivity/wireless-tools/wireless-tools/man.patch b/meta/meta-mediatek/recipes-connectivity/wireless-tools/wireless-tools/man.patch
new file mode 100644
index 0000000..6a757da
--- /dev/null
+++ b/meta/meta-mediatek/recipes-connectivity/wireless-tools/wireless-tools/man.patch
@@ -0,0 +1,15 @@
+Upstream-Status: Inappropriate [configuration]
+
+Index: wireless_tools.30/Makefile
+===================================================================
+--- wireless_tools.30.orig/Makefile 2014-02-01 00:21:04.148463382 -0800
++++ wireless_tools.30/Makefile 2014-02-01 00:23:35.448072279 -0800
+@@ -76,7 +76,7 @@
+ INSTALL_DIR= $(PREFIX)/sbin
+ INSTALL_LIB= $(PREFIX)/lib
+ INSTALL_INC= $(PREFIX)/include
+-INSTALL_MAN= $(PREFIX)/man
++INSTALL_MAN= $(PREFIX)/share/man
+
+ # Various commands
+ RM = rm -f
diff --git a/meta/meta-mediatek/recipes-connectivity/wireless-tools/wireless-tools/remove.ldconfig.call.patch b/meta/meta-mediatek/recipes-connectivity/wireless-tools/wireless-tools/remove.ldconfig.call.patch
new file mode 100644
index 0000000..3a22c3f
--- /dev/null
+++ b/meta/meta-mediatek/recipes-connectivity/wireless-tools/wireless-tools/remove.ldconfig.call.patch
@@ -0,0 +1,19 @@
+When /etc/ld.so.cache is writeable by user running bitbake then it creates invalid cache
+(in my case libstdc++.so cannot be found after building zlib(-native) and I have to call
+touch */libstdc++.so && /sbin/ldconfig to fix it.
+
+So remove ldconfig call from make install-libs
+
+Upstream-Status: Inappropriate [disable feature]
+
+diff -uNr wireless_tools.29.orig/Makefile wireless_tools.29/Makefile
+--- wireless_tools.29.orig/Makefile 2007-09-18 01:56:46.000000000 +0200
++++ wireless_tools.29/Makefile 2012-02-15 20:46:41.780763514 +0100
+@@ -163,7 +163,6 @@
+ install -m 755 $(DYNAMIC) $(INSTALL_LIB)
+ ln -sfn $(DYNAMIC) $(INSTALL_LIB)/$(DYNAMIC_LINK)
+ @echo "*** Don't forget to add $(INSTALL_LIB) to /etc/ld.so.conf, and run ldconfig as root. ***"
+- @$(LDCONFIG) || echo "*** Could not run ldconfig ! ***"
+
+ # Install the static library
+ install-static:: $(STATIC)
diff --git a/meta/meta-mediatek/recipes-connectivity/wireless-tools/wireless-tools_30.pre9.bb b/meta/meta-mediatek/recipes-connectivity/wireless-tools/wireless-tools_30.pre9.bb
new file mode 100644
index 0000000..0a34207
--- /dev/null
+++ b/meta/meta-mediatek/recipes-connectivity/wireless-tools/wireless-tools_30.pre9.bb
@@ -0,0 +1,50 @@
+SUMMARY = "Tools for the Linux Standard Wireless Extension Subsystem"
+HOMEPAGE = "https://hewlettpackard.github.io/wireless-tools/Tools.html"
+LICENSE = "GPLv2 & (LGPLv2.1 | MPL-1.1 | BSD)"
+LIC_FILES_CHKSUM = "file://COPYING;md5=94d55d512a9ba36caa9b7df079bae19f \
+ file://iwconfig.c;beginline=1;endline=12;md5=cf710eb1795c376eb10ea4ff04649caf \
+ file://iwevent.c;beginline=59;endline=72;md5=d66a10026d4394f0a5b1c5587bce4537 \
+ file://sample_enc.c;beginline=1;endline=4;md5=838372be07874260b566bae2f6ed33b6"
+SECTION = "base"
+PE = "1"
+
+SRC_URI = "https://hewlettpackard.github.io/wireless-tools/wireless_tools.${PV}.tar.gz \
+ file://remove.ldconfig.call.patch \
+ file://man.patch \
+ file://avoid_strip.patch \
+ file://ldflags.patch \
+ "
+SRC_URI[md5sum] = "ca91ba7c7eff9bfff6926b1a34a4697d"
+SRC_URI[sha256sum] = "abd9c5c98abf1fdd11892ac2f8a56737544fe101e1be27c6241a564948f34c63"
+
+UPSTREAM_CHECK_URI = "https://hewlettpackard.github.io/wireless-tools/Tools.html"
+UPSTREAM_CHECK_REGEX = "wireless_tools\.(?P<pver>(\d+)(\..*|))\.tar\.gz"
+
+S = "${WORKDIR}/wireless_tools.30"
+
+CFLAGS =+ "-I${S}"
+EXTRA_OEMAKE = "-e 'BUILD_SHARED=y' \
+ 'INSTALL_DIR=${D}${base_sbindir}' \
+ 'INSTALL_LIB=${D}${libdir}' \
+ 'INSTALL_INC=${D}${includedir}' \
+ 'INSTALL_MAN=${D}${mandir}'"
+
+do_compile() {
+ oe_runmake all libiw.a
+}
+
+do_install() {
+ oe_runmake PREFIX=${D} install-iwmulticall install-dynamic install-man install-hdr
+ install -d ${D}${sbindir}
+ install -m 0755 ifrename ${D}${sbindir}/ifrename
+}
+
+PACKAGES = "libiw libiw-dev libiw-doc ifrename-doc ifrename ${PN} ${PN}-doc ${PN}-dbg"
+
+FILES_libiw = "${libdir}/*.so.*"
+FILES_libiw-dev = "${libdir}/*.a ${libdir}/*.so ${includedir}"
+FILES_libiw-doc = "${mandir}/man7"
+FILES_ifrename = "${sbindir}/ifrename"
+FILES_ifrename-doc = "${mandir}/man8/ifrename.8 ${mandir}/man5/iftab.5"
+FILES_${PN} = "${bindir} ${sbindir}/iw* ${base_sbindir} ${base_bindir} ${sysconfdir}/network"
+FILES_${PN}-doc = "${mandir}"
diff --git a/meta/meta-mediatek/recipes-connectivity/wpa-supplicant/wpa-supplicant_%.bbappend b/meta/meta-mediatek/recipes-connectivity/wpa-supplicant/wpa-supplicant_%.bbappend
new file mode 100644
index 0000000..c3dc1cf
--- /dev/null
+++ b/meta/meta-mediatek/recipes-connectivity/wpa-supplicant/wpa-supplicant_%.bbappend
@@ -0,0 +1,14 @@
+FILES_${PN} += "/data/wifi"
+
+do_configure_append () {
+ # Activate config options needed by connman and tethering
+ echo "CONFIG_P2P=y" >> wpa_supplicant/.config
+ echo "p2p_no_group_iface=1" >> ../wpa_supplicant.conf-sane
+ echo "config_methods=display push_button keypad" >> ../wpa_supplicant.conf-sane
+ echo "driver_param=use_p2p_group_interface=1" >> ../wpa_supplicant.conf-sane
+}
+
+do_install_append () {
+ install -d ${D}/data/wifi
+ install -m 755 ${WORKDIR}/wpa_supplicant.conf-sane ${D}/data/wifi/wpa_supplicant.conf
+}
diff --git a/meta/meta-mediatek/recipes-core/coreutils/coreutils/fix-absolute-include.patch b/meta/meta-mediatek/recipes-core/coreutils/coreutils/fix-absolute-include.patch
new file mode 100755
index 0000000..32c130b
--- /dev/null
+++ b/meta/meta-mediatek/recipes-core/coreutils/coreutils/fix-absolute-include.patch
@@ -0,0 +1,216 @@
+diff --git a/lib/dirent_.h b/lib/dirent_.h
+index 3fa8480..0bd2fed 100644
+--- a/lib/dirent_.h
++++ b/lib/dirent_.h
+@@ -18,7 +18,7 @@
+ #ifndef _GL_DIRENT_H
+ #define _GL_DIRENT_H
+
+-#include @ABSOLUTE_DIRENT_H@
++#include_next <dirent.h>
+
+
+ /* Declare overridden functions. */
+diff --git a/lib/fcntl_.h b/lib/fcntl_.h
+index e16ad54..b99d945 100644
+--- a/lib/fcntl_.h
++++ b/lib/fcntl_.h
+@@ -24,7 +24,7 @@
+ #include <sys/types.h>
+ #include <sys/stat.h>
+ #include <unistd.h>
+-#include @ABSOLUTE_FCNTL_H@
++#include_next <fcntl.h>
+
+
+ /* Declare overridden functions. */
+diff --git a/lib/inttypes_.h b/lib/inttypes_.h
+index 3d3ead6..ed47fd8 100644
+--- a/lib/inttypes_.h
++++ b/lib/inttypes_.h
+@@ -21,7 +21,7 @@
+ which in turn includes this file. */
+ #if ! defined INTTYPES_H || defined _GL_JUST_INCLUDE_ABSOLUTE_INTTYPES_H
+ # if @HAVE_INTTYPES_H@
+-# include @ABSOLUTE_INTTYPES_H@
++# include_next <inttypes.h>
+ # endif
+ #endif
+
+diff --git a/lib/netinet_in_.h b/lib/netinet_in_.h
+index 4a53605..ce9a979 100644
+--- a/lib/netinet_in_.h
++++ b/lib/netinet_in_.h
+@@ -24,7 +24,7 @@
+ <sys/types.h>. */
+
+ # include <sys/types.h>
+-# include @ABSOLUTE_NETINET_IN_H@
++# include_next <netinet/in.h>
+
+ #else
+
+diff --git a/lib/socket_.h b/lib/socket_.h
+index 623c98c..a45436d 100644
+--- a/lib/socket_.h
++++ b/lib/socket_.h
+@@ -30,7 +30,7 @@
+ <sys/types.h>. */
+
+ # include <sys/types.h>
+-# include @ABSOLUTE_SYS_SOCKET_H@
++# include_next <sys/socket.h>
+
+ #else
+
+diff --git a/lib/stat_.h b/lib/stat_.h
+index cbf5ac0..243b4c0 100644
+--- a/lib/stat_.h
++++ b/lib/stat_.h
+@@ -23,7 +23,7 @@
+ /* This file is supposed to be used on platforms where <sys/stat.h> is
+ incomplete. It is intended to provide definitions and prototypes
+ needed by an application. Start with what the system provides. */
+-#include @ABSOLUTE_SYS_STAT_H@
++#include_next <sys/stat.h>
+
+ #ifndef S_IFMT
+ # define S_IFMT 0170000
+diff --git a/lib/stdint_.h b/lib/stdint_.h
+index 4fa5251..788a980 100644
+--- a/lib/stdint_.h
++++ b/lib/stdint_.h
+@@ -43,7 +43,7 @@
+ Include it before <inttypes.h>, since any "#include <stdint.h>"
+ in <inttypes.h> would reinclude us, skipping our contents because
+ _GL_STDINT_H is defined. */
+-# include @ABSOLUTE_STDINT_H@
++# include_next <stdint.h>
+ #endif
+
+ /* <sys/types.h> defines some of the stdint.h types as well, on glibc,
+diff --git a/lib/stdio_.h b/lib/stdio_.h
+index 441c0d5..cd1d18c 100644
+--- a/lib/stdio_.h
++++ b/lib/stdio_.h
+@@ -19,14 +19,14 @@
+ #if defined __need_FILE || defined __need___FILE
+ /* Special invocation convention inside glibc header files. */
+
+-#include @ABSOLUTE_STDIO_H@
++#include_next <stdio.h>
+
+ #else
+ /* Normal invocation convention. */
+ #ifndef _GL_STDIO_H
+ #define _GL_STDIO_H
+
+-#include @ABSOLUTE_STDIO_H@
++#include_next <stdio.h>
+
+ #include <stdarg.h>
+ #include <stddef.h>
+diff --git a/lib/stdlib_.h b/lib/stdlib_.h
+index a920408..dc33b29 100644
+--- a/lib/stdlib_.h
++++ b/lib/stdlib_.h
+@@ -26,7 +26,7 @@
+ # pragma GCC system_header
+ #endif
+
+-#include @ABSOLUTE_STDLIB_H@
++#include_next <stdlib.h>
+
+ #else
+ /* Normal invocation convention. */
+@@ -40,7 +40,7 @@
+ # pragma GCC system_header
+ #endif
+
+-#include @ABSOLUTE_STDLIB_H@
++#include_next <stdlib.h>
+
+
+ /* The definition of GL_LINK_WARNING is copied here. */
+diff --git a/lib/string_.h b/lib/string_.h
+index b50523c..4316660 100644
+--- a/lib/string_.h
++++ b/lib/string_.h
+@@ -25,7 +25,7 @@
+ # pragma GCC system_header
+ #endif
+
+-#include @ABSOLUTE_STRING_H@
++#include_next <string.h>
+
+
+ /* The definition of GL_LINK_WARNING is copied here. */
+diff --git a/lib/sys_time_.h b/lib/sys_time_.h
+index 46cdb70..f98de57 100644
+--- a/lib/sys_time_.h
++++ b/lib/sys_time_.h
+@@ -22,7 +22,7 @@
+ #define _gl_SYS_TIME_H
+
+ #if @HAVE_SYS_TIME_H@
+-# include @ABSOLUTE_SYS_TIME_H@
++# include_next <sys/time.h>
+ #else
+ # include <time.h>
+ #endif
+diff --git a/lib/time_.h b/lib/time_.h
+index 5467d3d..fe97130 100644
+--- a/lib/time_.h
++++ b/lib/time_.h
+@@ -20,11 +20,11 @@
+ declare a few standard symbols, rather than to declare all the
+ symbols. */
+ #if defined __need_time_t || defined __need_clock_t || defined __need_timespec
+-# include @ABSOLUTE_TIME_H@
++# include_next <time.h>
+
+ #elif ! defined _GL_TIME_H
+ # define _GL_TIME_H
+-# include @ABSOLUTE_TIME_H@
++# include_next <time.h>
+
+ # ifdef __cplusplus
+ extern "C" {
+diff --git a/lib/unistd_.h b/lib/unistd_.h
+index 77df861..9241475 100644
+--- a/lib/unistd_.h
++++ b/lib/unistd_.h
+@@ -19,7 +19,7 @@
+ #define _GL_UNISTD_H
+
+ #if @HAVE_UNISTD_H@
+-# include @ABSOLUTE_UNISTD_H@
++# include_next <unistd.h>
+ #endif
+
+
+diff --git a/lib/wchar_.h b/lib/wchar_.h
+index 6813a21..bd86ce4 100644
+--- a/lib/wchar_.h
++++ b/lib/wchar_.h
+@@ -37,6 +37,6 @@
+ #include <time.h>
+
+ /* Include the original <wchar.h>. */
+-#include @ABSOLUTE_WCHAR_H@
++#include_next <wchar.h>
+
+ #endif /* _GL_WCHAR_H */
+diff --git a/lib/wctype_.h b/lib/wctype_.h
+index 1297c61..fca78cd 100644
+--- a/lib/wctype_.h
++++ b/lib/wctype_.h
+@@ -47,7 +47,7 @@ typedef int __wctype_wint_t;
+ /* Include the original <wctype.h> if it exists.
+ BeOS 5 has the functions but no <wctype.h>. */
+ #if @HAVE_WCTYPE_H@
+-# include @ABSOLUTE_WCTYPE_H@
++# include_next <wctype.h>
+ #endif
+
+ /* FreeBSD 4.4 to 4.11 has <wctype.h> but lacks the functions.
diff --git a/meta/meta-mediatek/recipes-core/coreutils/coreutils_6.9.bbappend b/meta/meta-mediatek/recipes-core/coreutils/coreutils_6.9.bbappend
new file mode 100644
index 0000000..302450f
--- /dev/null
+++ b/meta/meta-mediatek/recipes-core/coreutils/coreutils_6.9.bbappend
@@ -0,0 +1,3 @@
+FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
+
+SRC_URI_append_toolchain-clang = " file://fix-absolute-include.patch"
diff --git a/meta/meta-mediatek/recipes-core/images/mtk-core-image-initubifs.bb b/meta/meta-mediatek/recipes-core/images/mtk-core-image-initubifs.bb
new file mode 100644
index 0000000..110d626
--- /dev/null
+++ b/meta/meta-mediatek/recipes-core/images/mtk-core-image-initubifs.bb
@@ -0,0 +1,22 @@
+# Simple ubifs image. Only add bootimage in the rootfs
+DESCRIPTION = "Small image capable of booting a device. The kernel includes \
+the Minimal RAM-based Initial Root Filesystem (initramfs), which finds the \
+first 'init' program more efficiently."
+
+PACKAGE_INSTALL = ""
+
+# Do not pollute the initrd image with rootfs features
+IMAGE_FEATURES = ""
+
+IMAGE_LINGUAS = ""
+
+LICENSE = "MIT"
+
+IMAGE_FSTYPES = "ubi"
+inherit core-image
+
+inherit boot-ubifs
+do_rootfs[depends] += "virtual/kernel:do_deploy"
+do_rootfs[postfuncs] += "add_boot_image"
+
+IMAGE_ROOTFS_SIZE = "8192"
diff --git a/meta/meta-mediatek/recipes-core/images/mtk-core-image-minimal-initramfs.bb b/meta/meta-mediatek/recipes-core/images/mtk-core-image-minimal-initramfs.bb
new file mode 100644
index 0000000..439fdd8
--- /dev/null
+++ b/meta/meta-mediatek/recipes-core/images/mtk-core-image-minimal-initramfs.bb
@@ -0,0 +1,31 @@
+# Simple initramfs image. Mostly used for live images.
+DESCRIPTION = "Small image capable of booting a device. The kernel includes \
+the Minimal RAM-based Initial Root Filesystem (initramfs), which finds the \
+first 'init' program more efficiently."
+
+PACKAGE_INSTALL = " \
+ ${@bb.utils.contains('MTK_LDVT_SUPPORT','yes','uvvf','',d)} \
+ ${@bb.utils.contains('MTK_LDVT_SUPPORT','yes','ldvt-scripts','',d)} \
+ initramfs-live-boot \
+ busybox \
+ udev \
+ base-passwd \
+ ${@bb.utils.contains('MTK_UBIFS_SUPPORT','yes','mtd-utils-ubifs','',d)} \
+ ${ROOTFS_BOOTSTRAP_INSTALL} \
+"
+
+
+# Do not pollute the initrd image with rootfs features
+IMAGE_FEATURES = ""
+
+export IMAGE_BASENAME = "mtk-core-image-minimal-initramfs"
+IMAGE_LINGUAS = ""
+
+LICENSE = "MIT"
+
+IMAGE_FSTYPES = "${INITRAMFS_FSTYPES}"
+inherit core-image
+
+IMAGE_ROOTFS_SIZE = "8192"
+
+BAD_RECOMMENDATIONS += "busybox-syslog"
diff --git a/meta/meta-mediatek/recipes-core/images/mtk-core-image-minimal.bb b/meta/meta-mediatek/recipes-core/images/mtk-core-image-minimal.bb
new file mode 100644
index 0000000..2f6c970
--- /dev/null
+++ b/meta/meta-mediatek/recipes-core/images/mtk-core-image-minimal.bb
@@ -0,0 +1,19 @@
+SUMMARY = "A small image just capable of allowing a device to boot."
+
+IMAGE_INSTALL = "packagegroup-core-boot ${CORE_IMAGE_EXTRA_INSTALL}"
+
+IMAGE_LINGUAS = " "
+
+LICENSE = "MIT"
+
+inherit core-image
+inherit create-link
+inherit create-nfsb
+
+
+IMAGE_FEATURES_append = " \
+ ssh-server-openssh \
+"
+
+IMAGE_ROOTFS_SIZE ?= "8192"
+IMAGE_ROOTFS_EXTRA_SPACE_append = "${@bb.utils.contains("DISTRO_FEATURES", "systemd", " + 4096", "" ,d)}"
diff --git a/meta/meta-mediatek/recipes-core/images/mtk-core-image-recovery-initramfs.bb b/meta/meta-mediatek/recipes-core/images/mtk-core-image-recovery-initramfs.bb
new file mode 100644
index 0000000..1af6db5
--- /dev/null
+++ b/meta/meta-mediatek/recipes-core/images/mtk-core-image-recovery-initramfs.bb
@@ -0,0 +1,32 @@
+# Simple initramfs image. Mostly used for live images.
+DESCRIPTION = "Small image capable of booting a device. The kernel includes \
+the Minimal RAM-based Initial Root Filesystem (initramfs), which finds the \
+first 'init' program more efficiently."
+
+PACKAGE_INSTALL = " \
+ initramfs-live-boot \
+ busybox \
+ udev \
+ base-passwd \
+ recovery-scripts \
+ ${ROOTFS_BOOTSTRAP_INSTALL} \
+"
+
+
+# Do not pollute the initrd image with rootfs features
+IMAGE_FEATURES = ""
+
+export IMAGE_BASENAME = "mtk-core-image-recovery-initramfs"
+IMAGE_LINGUAS = ""
+
+LICENSE = "MIT"
+
+IMAGE_FSTYPES = "${INITRAMFS_FSTYPES}"
+inherit core-image
+
+IMAGE_ROOTFS_SIZE = "8192"
+
+
+do_rootfs[depends] += "virtual/kernel:do_deploy"
+
+inherit recovery-ramdisk-kernel-fitimage
diff --git a/meta/meta-mediatek/recipes-core/images/mtk-core-image-recovery.bb b/meta/meta-mediatek/recipes-core/images/mtk-core-image-recovery.bb
new file mode 100644
index 0000000..ea95703
--- /dev/null
+++ b/meta/meta-mediatek/recipes-core/images/mtk-core-image-recovery.bb
@@ -0,0 +1,40 @@
+SUMMARY = "A small image just capable of allowing a device to boot."
+
+IMAGE_INSTALL = "packagegroup-core-boot ${ROOTFS_PKGMANAGE_BOOTSTRAP} ${CORE_IMAGE_EXTRA_INSTALL}"
+
+IMAGE_LINGUAS = " "
+
+LICENSE = "MIT"
+
+inherit core-image
+
+DEPENDS += "virtual/kernel"
+
+IMAGE_ROOTFS_SIZE ?= "8192"
+
+IMAGE_INSTALL_append = " \
+ util-linux \
+ udev-extraconf \
+ recovery-scripts \
+"
+BAD_RECOMMENDATIONS += "busybox-syslog"
+
+install_recovery_fstab() {
+ cat > ${IMAGE_ROOTFS}${sysconfdir}/fstab <<EOF
+/dev/root / auto ro 0 0
+proc /proc proc defaults 0 0
+devpts /dev/pts devpts mode=0620,gid=5 0 0
+tmpfs /run tmpfs mode=0755,nodev,nosuid,strictatime 0 0
+tmpfs /var/volatile tmpfs defaults 0 0
+EOF
+}
+
+soft_link_to_recovery_image() {
+ ln -nfs ${IMAGE_NAME}.rootfs.${IMAGE_FSTYPES} ${DEPLOY_DIR_IMAGE}/recovery.${IMAGE_FSTYPES}
+}
+
+ROOTFS_POSTPROCESS_COMMAND += " install_recovery_fstab; soft_link_to_recovery_image;"
+
+do_rootfs[depends] += "virtual/kernel:do_deploy"
+
+inherit recovery-kernel-fitimage
diff --git a/meta/meta-mediatek/recipes-core/initscripts/initscripts/init-functions b/meta/meta-mediatek/recipes-core/initscripts/initscripts/init-functions
new file mode 100644
index 0000000..a798c82
--- /dev/null
+++ b/meta/meta-mediatek/recipes-core/initscripts/initscripts/init-functions
@@ -0,0 +1,406 @@
+# /lib/lsb/init-functions for Debian -*- shell-script -*-
+#
+#Copyright (c) 2002-08 Chris Lawrence
+#All rights reserved.
+#
+#Redistribution and use in source and binary forms, with or without
+#modification, are permitted provided that the following conditions
+#are met:
+#1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#3. Neither the name of the author nor the names of other contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+#THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+#IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+#WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+#ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
+#LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+#CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+#SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+#BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+#WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+#OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+#EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+start_daemon_background () {
+ local force nice pidfile exec i args
+ force=0
+ nice=0
+ pidfile=/dev/null
+
+ OPTIND=1
+ while getopts fn:p: opt ; do
+ case "$opt" in
+ f) force=1;;
+ n) nice="$OPTARG";;
+ p) pidfile="$OPTARG";;
+ esac
+ done
+
+ shift $(($OPTIND - 1))
+ if [ "$1" = '--' ]; then
+ shift
+ fi
+
+ exec="$1"; shift
+
+ args="--start --nicelevel $nice --quiet --oknodo --background"
+ if [ $force = 1 ]; then
+ /sbin/start-stop-daemon $args --chdir "$PWD" --startas $exec --pidfile /dev/null -- "$@"
+ elif [ $pidfile ]; then
+ /sbin/start-stop-daemon $args --chdir "$PWD" --exec $exec --oknodo --pidfile "$pidfile" -- "$@"
+ else
+ /sbin/start-stop-daemon $args --chdir "$PWD" --exec $exec -- "$@"
+ fi
+}
+
+
+start_daemon () {
+ local force nice pidfile exec i args
+ force=0
+ nice=0
+ pidfile=/dev/null
+
+ OPTIND=1
+ while getopts fn:p: opt ; do
+ case "$opt" in
+ f) force=1;;
+ n) nice="$OPTARG";;
+ p) pidfile="$OPTARG";;
+ esac
+ done
+
+ shift $(($OPTIND - 1))
+ if [ "$1" = '--' ]; then
+ shift
+ fi
+
+ exec="$1"; shift
+
+ args="--start --nicelevel $nice --quiet --oknodo"
+ if [ $force = 1 ]; then
+ /sbin/start-stop-daemon $args --chdir "$PWD" --startas $exec --pidfile /dev/null -- "$@"
+ elif [ $pidfile ]; then
+ /sbin/start-stop-daemon $args --chdir "$PWD" --exec $exec --oknodo --pidfile "$pidfile" -- "$@"
+ else
+ /sbin/start-stop-daemon $args --chdir "$PWD" --exec $exec -- "$@"
+ fi
+}
+
+pidofproc () {
+ local pidfile line i pids= status specified pid
+ pidfile=
+ specified=
+
+ OPTIND=1
+ while getopts p: opt ; do
+ case "$opt" in
+ p) pidfile="$OPTARG"; specified=1;;
+ esac
+ done
+ shift $(($OPTIND - 1))
+
+ base=${1##*/}
+ if [ ! "$specified" ]; then
+ pidfile="/var/run/$base.pid"
+ fi
+
+ if [ -n "${pidfile:-}" -a -r "$pidfile" ]; then
+ read pid < "$pidfile"
+ if [ -n "${pid:-}" ]; then
+ if $(kill -0 "${pid:-}" 2> /dev/null); then
+ echo "$pid"
+ return 0
+ elif ps "${pid:-}" >/dev/null 2>&1; then
+ echo "$pid"
+ return 0 # program is running, but not owned by this user
+ else
+ return 1 # program is dead and /var/run pid file exists
+ fi
+ fi
+ fi
+ if [ -x /bin/pidof -a ! "$specified" ]; then
+ status="0"
+ /bin/pidof -o %PPID -x $1 || status="$?"
+ if [ "$status" = 1 ]; then
+ return 3 # program is not running
+ fi
+ return 0
+ fi
+ return 4 # Unable to determine status
+}
+
+# start-stop-daemon uses the same algorithm as "pidofproc" above.
+killproc () {
+ local pidfile sig status base i name_param is_term_sig
+ pidfile=
+ name_param=
+ is_term_sig=no
+
+ OPTIND=1
+ while getopts p: opt ; do
+ case "$opt" in
+ p) pidfile="$OPTARG";;
+ esac
+ done
+ shift $(($OPTIND - 1))
+
+ base=${1##*/}
+ if [ ! $pidfile ]; then
+ name_param="--name $base --pidfile /var/run/$base.pid"
+ else
+ name_param="--pidfile $pidfile"
+ fi
+
+ sig=$(echo ${2:-} | sed -e 's/^-\(.*\)/\1/')
+ sig=$(echo $sig | sed -e 's/^SIG\(.*\)/\1/')
+ if [ -z "$sig" -o "$sig" = 15 -o "$sig" = TERM ]; then
+ is_term_sig=yes
+ fi
+ status=0
+ if [ ! "$is_term_sig" = yes ]; then
+ if [ -n "$sig" ]; then
+ /sbin/start-stop-daemon --stop --signal "$sig" --quiet $name_param || status="$?"
+ else
+ /sbin/start-stop-daemon --stop --quiet $name_param || status="$?"
+ fi
+ else
+ /sbin/start-stop-daemon --stop --quiet --oknodo $name_param || status="$?"
+ fi
+ if [ "$status" = 1 ]; then
+ if [ -n "$sig" ]; then
+ return 0
+ fi
+ return 3 # program is not running
+ fi
+
+ if [ "$status" = 0 -a "$is_term_sig" = yes -a "$pidfile" ]; then
+ pidofproc -p "$pidfile" "$1" >/dev/null || rm -f "$pidfile"
+ fi
+ return 0
+}
+
+# Return LSB status
+status_of_proc () {
+ local pidfile daemon name status
+
+ pidfile=
+ OPTIND=1
+ while getopts p: opt ; do
+ case "$opt" in
+ p) pidfile="$OPTARG";;
+ esac
+ done
+ shift $(($OPTIND - 1))
+
+ if [ -n "$pidfile" ]; then
+ pidfile="-p $pidfile"
+ fi
+ daemon="$1"
+ name="$2"
+
+ status="0"
+ pidofproc $pidfile $daemon >/dev/null || status="$?"
+ if [ "$status" = 0 ]; then
+ log_success_msg "$name is running"
+ return 0
+ elif [ "$status" = 4 ]; then
+ log_failure_msg "could not access PID file for $name"
+ return $status
+ else
+ log_failure_msg "$name is not running"
+ return $status
+ fi
+}
+
+log_use_fancy_output () {
+ TPUT=/usr/bin/tput
+ EXPR=/usr/bin/expr
+ if [ -t 1 ] && [ "x${TERM:-}" != "x" ] && [ "x${TERM:-}" != "xdumb" ] && [ -x $TPUT ] && [ -x $EXPR ] && $TPUT hpa 60 >/dev/null 2>&1 && $TPUT setaf 1 >/dev/null 2>&1; then
+ [ -z $FANCYTTY ] && FANCYTTY=1 || true
+ else
+ FANCYTTY=0
+ fi
+ case "$FANCYTTY" in
+ 1|Y|yes|true) true;;
+ *) false;;
+ esac
+}
+
+log_success_msg () {
+ if [ -n "${1:-}" ]; then
+ log_begin_msg $@
+ fi
+ log_end_msg 0
+}
+
+log_failure_msg () {
+ if [ -n "${1:-}" ]; then
+ log_begin_msg $@ "..."
+ fi
+ log_end_msg 1 || true
+}
+
+log_warning_msg () {
+ if [ -n "${1:-}" ]; then
+ log_begin_msg $@ "..."
+ fi
+ log_end_msg 255 || true
+}
+
+#
+# NON-LSB HELPER FUNCTIONS
+#
+# int get_lsb_header_val (char *scriptpathname, char *key)
+get_lsb_header_val () {
+ if [ ! -f "$1" ] || [ -z "${2:-}" ]; then
+ return 1
+ fi
+ LSB_S="### BEGIN INIT INFO"
+ LSB_E="### END INIT INFO"
+ sed -n "/$LSB_S/,/$LSB_E/ s/# $2: \(.*\)/\1/p" $1
+}
+
+# int log_begin_message (char *message)
+log_begin_msg () {
+ if [ -z "${1:-}" ]; then
+ return 1
+ fi
+ echo -n "$@"
+}
+
+# Sample usage:
+# log_daemon_msg "Starting GNOME Login Manager" "gdm"
+#
+# On Debian, would output "Starting GNOME Login Manager: gdm"
+# On Ubuntu, would output " * Starting GNOME Login Manager..."
+#
+# If the second argument is omitted, logging suitable for use with
+# log_progress_msg() is used:
+#
+# log_daemon_msg "Starting remote filesystem services"
+#
+# On Debian, would output "Starting remote filesystem services:"
+# On Ubuntu, would output " * Starting remote filesystem services..."
+
+log_daemon_msg () {
+ if [ -z "${1:-}" ]; then
+ return 1
+ fi
+ log_daemon_msg_pre "$@"
+
+ if [ -z "${2:-}" ]; then
+ echo -n "$1:"
+ return
+ fi
+
+ echo -n "$1: $2"
+ log_daemon_msg_post "$@"
+}
+
+# #319739
+#
+# Per policy docs:
+#
+# log_daemon_msg "Starting remote file system services"
+# log_progress_msg "nfsd"; start-stop-daemon --start --quiet nfsd
+# log_progress_msg "mountd"; start-stop-daemon --start --quiet mountd
+# log_progress_msg "ugidd"; start-stop-daemon --start --quiet ugidd
+# log_end_msg 0
+#
+# You could also do something fancy with log_end_msg here based on the
+# return values of start-stop-daemon; this is left as an exercise for
+# the reader...
+#
+# On Ubuntu, one would expect log_progress_msg to be a no-op.
+log_progress_msg () {
+ if [ -z "${1:-}" ]; then
+ return 1
+ fi
+ echo -n " $@"
+}
+
+
+# int log_end_message (int exitstatus)
+log_end_msg () {
+ # If no arguments were passed, return
+ if [ -z "${1:-}" ]; then
+ return 1
+ fi
+
+ retval=$1
+
+ log_end_msg_pre "$@"
+
+ # Only do the fancy stuff if we have an appropriate terminal
+ # and if /usr is already mounted
+ if log_use_fancy_output; then
+ RED=`$TPUT setaf 1`
+ YELLOW=`$TPUT setaf 3`
+ NORMAL=`$TPUT op`
+ else
+ RED=''
+ YELLOW=''
+ NORMAL=''
+ fi
+
+ if [ $1 -eq 0 ]; then
+ echo "."
+ elif [ $1 -eq 255 ]; then
+ /bin/echo -e " ${YELLOW}(warning).${NORMAL}"
+ else
+ /bin/echo -e " ${RED}failed!${NORMAL}"
+ fi
+ log_end_msg_post "$@"
+ return $retval
+}
+
+log_action_msg () {
+ echo "$@."
+}
+
+log_action_begin_msg () {
+ echo -n "$@..."
+}
+
+log_action_cont_msg () {
+ echo -n "$@..."
+}
+
+log_action_end_msg () {
+ log_action_end_msg_pre "$@"
+ if [ -z "${2:-}" ]; then
+ end="."
+ else
+ end=" ($2)."
+ fi
+
+ if [ $1 -eq 0 ]; then
+ echo "done${end}"
+ else
+ if log_use_fancy_output; then
+ RED=`$TPUT setaf 1`
+ NORMAL=`$TPUT op`
+ /bin/echo -e "${RED}failed${end}${NORMAL}"
+ else
+ echo "failed${end}"
+ fi
+ fi
+ log_action_end_msg_post "$@"
+}
+
+# Hooks for /etc/lsb-base-logging.sh
+log_daemon_msg_pre () { :; }
+log_daemon_msg_post () { :; }
+log_end_msg_pre () { :; }
+log_end_msg_post () { :; }
+log_action_end_msg_pre () { :; }
+log_action_end_msg_post () { :; }
+
+FANCYTTY=
+[ -e /etc/lsb-base-logging.sh ] && . /etc/lsb-base-logging.sh || true
\ No newline at end of file
diff --git a/meta/meta-mediatek/recipes-core/initscripts/initscripts_1.0.bbappend b/meta/meta-mediatek/recipes-core/initscripts/initscripts_1.0.bbappend
new file mode 100644
index 0000000..9b81261
--- /dev/null
+++ b/meta/meta-mediatek/recipes-core/initscripts/initscripts_1.0.bbappend
@@ -0,0 +1,11 @@
+FILESEXTRAPATHS_append := ":${THISDIR}/${PN}"
+
+SRC_URI_append = " file://init-functions "
+
+DEPENDS += " start-stop-daemon "
+
+do_install_append() {
+ install -d ${D}${sysconfdir}/init.d
+ install -m 0755 ${WORKDIR}/init-functions ${D}${sysconfdir}/init.d
+}
+
diff --git a/meta/meta-mediatek/recipes-core/ldvt-scripts/files/init-ldvt.sh b/meta/meta-mediatek/recipes-core/ldvt-scripts/files/init-ldvt.sh
new file mode 100644
index 0000000..cb41ef7
--- /dev/null
+++ b/meta/meta-mediatek/recipes-core/ldvt-scripts/files/init-ldvt.sh
@@ -0,0 +1,65 @@
+#!/bin/sh
+
+PATH=/sbin:/bin:/usr/sbin:/usr/bin
+
+ROOT_MOUNT="/rootfs/"
+ROOT_IMAGE="rootfs.img"
+MOUNT="/bin/mount"
+UMOUNT="/bin/umount"
+ISOLINUX=""
+
+ROOT_DISK=""
+
+# Copied from initramfs-framework. The core of this script probably should be
+# turned into initramfs-framework modules to reduce duplication.
+udev_daemon() {
+ OPTIONS="/sbin/udev/udevd /sbin/udevd /lib/udev/udevd /lib/systemd/systemd-udevd"
+
+ for o in $OPTIONS; do
+ if [ -x "$o" ]; then
+ echo $o
+ return 0
+ fi
+ done
+
+ return 1
+}
+
+_UDEV_DAEMON=`udev_daemon`
+
+early_setup() {
+ mkdir -p /proc
+ mkdir -p /sys
+ mount -t proc proc /proc
+ mount -t sysfs sysfs /sys
+ mount -t devtmpfs none /dev
+
+ # support modular kernel
+ # modprobe isofs 2> /dev/null
+
+ mkdir -p /run
+ mkdir -p /var/run
+
+ $_UDEV_DAEMON --daemon
+ udevadm trigger --action=add
+}
+
+
+boot_live_root() {
+ # Watches the udev event queue, and exits if all current events are handled
+ udevadm settle --timeout=3 --quiet
+ killall "${_UDEV_DAEMON##*/}" 2>/dev/null
+}
+
+fatal() {
+ echo $1 >$CONSOLE
+ echo >$CONSOLE
+ exec sh
+}
+
+early_setup
+
+sleep 5
+
+boot_live_root
+
diff --git a/meta/meta-mediatek/recipes-core/ldvt-scripts/ldvt-scripts.bb b/meta/meta-mediatek/recipes-core/ldvt-scripts/ldvt-scripts.bb
new file mode 100644
index 0000000..d03a8b3
--- /dev/null
+++ b/meta/meta-mediatek/recipes-core/ldvt-scripts/ldvt-scripts.bb
@@ -0,0 +1,17 @@
+SUMMARY = "Ldvt init script"
+LICENSE = "MIT"
+LIC_FILES_CHKSUM = "file://${COREBASE}/meta/COPYING.MIT;md5=3da9cfbcb788c80a0384361b4de20420"
+DEPENDS = "virtual/kernel"
+RDEPENDS_${PN} = "udev udev-extraconf"
+SRC_URI = "file://init-ldvt.sh"
+
+S = "${WORKDIR}"
+
+do_install() {
+ install -m 0755 ${WORKDIR}/init-ldvt.sh ${D}/ldvt_init
+}
+
+FILES_${PN} += " /ldvt_init "
+
+# Due to kernel dependency
+PACKAGE_ARCH = "${MACHINE_ARCH}"
diff --git a/meta/meta-mediatek/recipes-core/packagegroups/packagegroup-mtk-upgrade-kit-native.bb b/meta/meta-mediatek/recipes-core/packagegroups/packagegroup-mtk-upgrade-kit-native.bb
new file mode 100644
index 0000000..3c7bdf1
--- /dev/null
+++ b/meta/meta-mediatek/recipes-core/packagegroups/packagegroup-mtk-upgrade-kit-native.bb
@@ -0,0 +1,10 @@
+SUMMARY = "Mediatek Upgrade Kit"
+LICENSE = "MediaTekProprietary"
+
+inherit packagegroup
+
+DEPENDS += "\
+ platform-tools-native \
+ fbtool-native \
+ flashtool-native \
+ "
diff --git a/meta/meta-mediatek/recipes-core/packagegroups/packagegroup-mtk-upgrade-kit.bb b/meta/meta-mediatek/recipes-core/packagegroups/packagegroup-mtk-upgrade-kit.bb
new file mode 100644
index 0000000..c703c4c
--- /dev/null
+++ b/meta/meta-mediatek/recipes-core/packagegroups/packagegroup-mtk-upgrade-kit.bb
@@ -0,0 +1,9 @@
+SUMMARY = "Mediatek Upgrade Kit"
+LICENSE = "MediaTekProprietary"
+
+inherit packagegroup
+
+DEPENDS += "\
+ platform-tools \
+ fbtool \
+ "
diff --git a/meta/meta-mediatek/recipes-core/packagegroups/packagegroup-self-hosted-without-x11.bb b/meta/meta-mediatek/recipes-core/packagegroups/packagegroup-self-hosted-without-x11.bb
new file mode 100644
index 0000000..79e56bd
--- /dev/null
+++ b/meta/meta-mediatek/recipes-core/packagegroups/packagegroup-self-hosted-without-x11.bb
@@ -0,0 +1,155 @@
+#
+# Copyright (C) 2010 Intel Corporation
+#
+
+SUMMARY = "Essential build dependencies"
+LICENSE = "MIT"
+
+inherit packagegroup
+
+
+RDEPENDS_packagegroup-self-hosted-without-x11 = "\
+ autoconf \
+ automake \
+ binutils \
+ binutils-symlinks \
+ cpp \
+ cpp-symlinks \
+ gcc \
+ gcc-symlinks \
+ g++ \
+ g++-symlinks \
+ gettext \
+ make \
+ libstdc++ \
+ libstdc++-dev \
+ libtool \
+ pkgconfig \
+ connman \
+ connman-plugin-ethernet \
+ dhcp-client \
+ e2fsprogs \
+ e2fsprogs-e2fsck \
+ e2fsprogs-mke2fs \
+ e2fsprogs-tune2fs \
+ hdparm \
+ iptables \
+ lsb \
+ mc \
+ mc-fish \
+ mc-helpers \
+ mc-helpers-perl \
+ mc-helpers-python \
+ parted \
+ pseudo \
+ screen \
+ autoconf \
+ automake \
+ binutils \
+ binutils-symlinks \
+ ccache \
+ coreutils \
+ cpp \
+ cpp-symlinks \
+ glibc-utils \
+ glibc-gconv-ibm850 \
+ file \
+ findutils \
+ g++ \
+ g++-symlinks \
+ gcc \
+ gcc-symlinks \
+ intltool \
+ ldd \
+ less \
+ libssp \
+ libssp-dev \
+ libssp-staticdev \
+ libstdc++ \
+ libstdc++-dev \
+ libtool \
+ make \
+ mktemp \
+ perl-module-re \
+ perl-module-text-wrap \
+ pkgconfig \
+ quilt \
+ sed \
+ gdb \
+ gdbserver \
+ rsync \
+ strace \
+ tcf-agent \
+ bzip2 \
+ chkconfig \
+ chrpath \
+ cpio \
+ curl \
+ diffstat \
+ diffutils \
+ elfutils \
+ expat \
+ gamin \
+ gawk \
+ gdbm \
+ gettext \
+ gettext-runtime \
+ git \
+ git-perltools \
+ grep \
+ groff \
+ gzip \
+ hicolor-icon-theme \
+ sato-icon-theme \
+ libaio \
+ libusb1 \
+ libxml2 \
+ lrzsz \
+ lsof \
+ lzo \
+ man \
+ man-pages \
+ mdadm \
+ minicom \
+ mtools \
+ ncurses \
+ ncurses-terminfo-base \
+ neon \
+ nfs-utils \
+ nfs-utils-client \
+ openssl \
+ openssh-sftp-server \
+ opkg \
+ opkg-utils \
+ patch \
+ perl \
+ perl-dev \
+ perl-modules \
+ perl-pod \
+ python \
+ python-compiler \
+ python-git \
+ python-misc \
+ python-modules \
+ python-rpm \
+ quota \
+ readline \
+ rpm \
+ setserial \
+ socat \
+ subversion \
+ sudo \
+ sysstat \
+ tar \
+ tcl \
+ texi2html \
+ texinfo \
+ unzip \
+ usbutils \
+ wget \
+ which \
+ xinetd \
+ zip \
+ zlib \
+ xz \
+ "
diff --git a/meta/meta-mediatek/recipes-core/recovery-scripts/recovery-scripts.bb b/meta/meta-mediatek/recipes-core/recovery-scripts/recovery-scripts.bb
new file mode 100644
index 0000000..0618106
--- /dev/null
+++ b/meta/meta-mediatek/recipes-core/recovery-scripts/recovery-scripts.bb
@@ -0,0 +1,14 @@
+DESCRIPTION = "An Example for Recovery Mode"
+LICENSE = "MediaTekProprietary"
+LIC_FILES_CHKSUM = "file://README;md5=6b2da25093d94b7c2bd0b5ce697f27b9"
+SRC_URI = "file://README \
+ file://recovery.sh \
+"
+S = "${WORKDIR}"
+FILES_${PN} = "${bindir}/recovery.sh"
+
+do_install () {
+ install -d ${D}${bindir}
+ install -m 755 ${S}/recovery.sh ${D}${bindir}/recovery.sh
+}
+
diff --git a/meta/meta-mediatek/recipes-core/recovery-scripts/recovery-scripts/README b/meta/meta-mediatek/recipes-core/recovery-scripts/recovery-scripts/README
new file mode 100644
index 0000000..70ec215
--- /dev/null
+++ b/meta/meta-mediatek/recipes-core/recovery-scripts/recovery-scripts/README
@@ -0,0 +1 @@
+An example for recovery mode
diff --git a/meta/meta-mediatek/recipes-core/recovery-scripts/recovery-scripts/recovery.sh b/meta/meta-mediatek/recipes-core/recovery-scripts/recovery-scripts/recovery.sh
new file mode 100644
index 0000000..6af4a51
--- /dev/null
+++ b/meta/meta-mediatek/recipes-core/recovery-scripts/recovery-scripts/recovery.sh
@@ -0,0 +1,35 @@
+MOUNTFOLDER="/run/media/sda1"
+MOUNTDEV="/dev/sda1"
+BOOTIMAGE="${MOUNTFOLDER}/boot.img"
+BOOT_PARTITION="/dev/mmcblk0p2"
+ROOTFS="${MOUNTFOLDER}/system.ext4"
+ROOTFS_PARTITION="/dev/mmcblk0p3"
+
+# mount USB device
+if ! test -d ${MOUNTFOLDER} ; then
+ mkdir -p ${MOUNTFOLDER}
+ /bin/mount ${MOUNTDEV} ${MOUNTFOLDER}
+fi
+
+#Flashing boot.img (kernel image)
+while ! test -f ${BOOTIMAGE} ; do
+ echo "Please insert usb disk and place boot.img in usb disk"
+ echo "Press ENTER key to Continue"
+ read
+done
+echo "Flashing boot.img ..."
+/bin/dd if=${BOOTIMAGE} of=${BOOT_PARTITION} bs=1048576
+
+#Flashing rootfs.ext4
+while ! test -f ${ROOTFS} ; do
+ echo "Please insert usb disk and place rootfs.ext4 in usb disk"
+ echo "Press ENTER key to Continue"
+ read
+done
+echo "Flashing rootfs.ext4 ..."
+/bin/dd if=${ROOTFS} of=${ROOTFS_PARTITION} bs=1048576
+
+echo "Finish ... Press ENTER key to Reboot"
+read
+echo "Rebooting ..."
+/sbin/reboot -f
diff --git a/meta/meta-mediatek/recipes-core/sysvinit/sysvinit-inittab_2.88dsf.bbappend b/meta/meta-mediatek/recipes-core/sysvinit/sysvinit-inittab_2.88dsf.bbappend
new file mode 100644
index 0000000..5fced55
--- /dev/null
+++ b/meta/meta-mediatek/recipes-core/sysvinit/sysvinit-inittab_2.88dsf.bbappend
@@ -0,0 +1,7 @@
+USE_VT := "0"
+
+DEFAULT_RUNLEVEL ?= "3"
+
+do_install_append() {
+ sed -i -e 's/id:5:initdefault/id:${DEFAULT_RUNLEVEL}:initdefault/' ${D}${sysconfdir}/inittab
+}
diff --git a/meta/meta-mediatek/recipes-core/udev/udev-only-hdmi/hdmi_hotplug.rules b/meta/meta-mediatek/recipes-core/udev/udev-only-hdmi/hdmi_hotplug.rules
new file mode 100644
index 0000000..db05df8
--- /dev/null
+++ b/meta/meta-mediatek/recipes-core/udev/udev-only-hdmi/hdmi_hotplug.rules
@@ -0,0 +1 @@
+ACTION=="change", KERNEL=="card0", SUBSYSTEM=="drm", RUN+="/etc/udev/scripts/hdmi_hotplug.sh"
diff --git a/meta/meta-mediatek/recipes-core/udev/udev-only-hdmi/hdmi_hotplug.sh b/meta/meta-mediatek/recipes-core/udev/udev-only-hdmi/hdmi_hotplug.sh
new file mode 100644
index 0000000..37afef7
--- /dev/null
+++ b/meta/meta-mediatek/recipes-core/udev/udev-only-hdmi/hdmi_hotplug.sh
@@ -0,0 +1,9 @@
+#!/bin/bash
+
+HDMIStatus=$(cat /sys/class/drm/card0-HDMI-A-1/status)
+
+if [ $HDMIStatus = 'connected' ]; then
+ systemctl restart weston
+else
+ systemctl stop weston
+fi
diff --git a/meta/meta-mediatek/recipes-core/udev/udev-only-hdmi_1.0.bb b/meta/meta-mediatek/recipes-core/udev/udev-only-hdmi_1.0.bb
new file mode 100644
index 0000000..52978df
--- /dev/null
+++ b/meta/meta-mediatek/recipes-core/udev/udev-only-hdmi_1.0.bb
@@ -0,0 +1,20 @@
+SUMMARY = "Extra machine specific configuration files"
+DESCRIPTION = "Extra machine specific configuration files for udev, specifically blacklist information."
+LICENSE = "MediaTekProprietary"
+
+SRC_URI = " \
+ file://hdmi_hotplug.rules \
+ file://hdmi_hotplug.sh \
+"
+
+S = "${WORKDIR}"
+
+do_install() {
+ install -d ${D}${sysconfdir}/udev/rules.d
+ install -m 0644 ${WORKDIR}/hdmi_hotplug.rules ${D}${sysconfdir}/udev/rules.d/hdmi_hotplug.rules
+ install -d ${D}${sysconfdir}/udev/scripts/
+ install -m 0755 ${WORKDIR}/hdmi_hotplug.sh ${D}${sysconfdir}/udev/scripts/hdmi_hotplug.sh
+}
+
+FILES_${PN} = "${sysconfdir}/udev"
+RDEPENDS_${PN} = "udev"
diff --git a/meta/meta-mediatek/recipes-core/uvvf/uvvf.bb b/meta/meta-mediatek/recipes-core/uvvf/uvvf.bb
new file mode 100644
index 0000000..835f2a7
--- /dev/null
+++ b/meta/meta-mediatek/recipes-core/uvvf/uvvf.bb
@@ -0,0 +1,24 @@
+inherit package
+
+INHIBIT_PACKAGE_STRIP = "1"
+
+DESCRIPTION = "Mediatek ldvt uvvf library"
+LICENSE = "MediaTekProprietary"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=cfae02679eba352c5d667a0cda7ef56e"
+
+TESTCASE_SRC = "${TOPDIR}/../src/ldvt/ldvt_tc/"
+TESTCASE_BIN_DIR = "${D}/usr/local/ldvt/bin"
+TESTCASE_BIN_INSTALL = "/usr/local/ldvt/bin"
+SRC_URI = "file://${TESTCASE_SRC}"
+S = "${TESTCASE_SRC}"
+
+do_compile () {
+ oe_runmake
+}
+
+do_install () {
+ oe_runmake \
+ DESTDIR="${D}" install
+}
+
+FILES_${PN} += "${TESTCASE_BIN_INSTALL}"
diff --git a/meta/meta-mediatek/recipes-devtools/11acsigma/mtk11acsigma.bb b/meta/meta-mediatek/recipes-devtools/11acsigma/mtk11acsigma.bb
new file mode 100644
index 0000000..093e68e
--- /dev/null
+++ b/meta/meta-mediatek/recipes-devtools/11acsigma/mtk11acsigma.bb
@@ -0,0 +1,8 @@
+DESCRIPTION = "Wi-Fi sigma tool for certification"
+LICENSE = "MediaTekProprietary"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=d7810fab7487fb0aad327b76f1be7cd7"
+
+inherit workonsrc
+WORKONSRC = "${TOPDIR}/../src/devtools/wifi-sigma/TGac-pmf-sigma"
+
+INSANE_SKIP_${PN} += "ldflags"
diff --git a/meta/meta-mediatek/recipes-devtools/11apsigma/mtk11apsigma.bb b/meta/meta-mediatek/recipes-devtools/11apsigma/mtk11apsigma.bb
new file mode 100644
index 0000000..022a5f9
--- /dev/null
+++ b/meta/meta-mediatek/recipes-devtools/11apsigma/mtk11apsigma.bb
@@ -0,0 +1,8 @@
+DESCRIPTION = "Wi-Fi sigma tool for certification"
+LICENSE = "MediaTekProprietary"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=e1696b147d49d491bcb4da1a57173fff"
+
+inherit workonsrc
+WORKONSRC = "${TOPDIR}/../src/devtools/wifi-sigma/AP-TGn-sigma"
+
+INSANE_SKIP_${PN} += "ldflags"
diff --git a/meta/meta-mediatek/recipes-devtools/11nsigma/mtk11nsigma.bb b/meta/meta-mediatek/recipes-devtools/11nsigma/mtk11nsigma.bb
new file mode 100644
index 0000000..d4a1122
--- /dev/null
+++ b/meta/meta-mediatek/recipes-devtools/11nsigma/mtk11nsigma.bb
@@ -0,0 +1,8 @@
+DESCRIPTION = "Wi-Fi sigma tool for certification"
+LICENSE = "MediaTekProprietary"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=e1696b147d49d491bcb4da1a57173fff"
+
+inherit workonsrc
+WORKONSRC = "${TOPDIR}/../src/devtools/wifi-sigma/TGn-sigma"
+
+INSANE_SKIP_${PN} += "ldflags"
diff --git a/meta/meta-mediatek/recipes-devtools/aee/aee.bb b/meta/meta-mediatek/recipes-devtools/aee/aee.bb
new file mode 100644
index 0000000..98a881a
--- /dev/null
+++ b/meta/meta-mediatek/recipes-devtools/aee/aee.bb
@@ -0,0 +1,68 @@
+DESCRIPTION = "Mediatek debug tool"
+SECTION = "base"
+LICENSE = "MediaTekProprietary"
+
+AEE_SRC = "${TOPDIR}/../src/devtools/aee"
+
+WORKONSRC = "${AEE_SRC}"
+
+DEPENDS = "zlib libunwind libsncfg platform-libs-header"
+TARGET_CC_ARCH = "-pthread"
+BB_CFLAGS_ADD = "--sysroot=${STAGING_DIR_HOST} -g"
+BB_LDFLAGS_ADD = "--sysroot=${STAGING_DIR_HOST}"
+BB_INCLUDE_ADD = "-I${MTK_SRC}/inc \
+ -I${STAGING_DIR_HOST} \
+ -I${STAGING_INCDIR} \
+ "
+
+inherit deploy workonsrc
+
+#Parameters passed to do_compile
+EXTRA_OEMAKE = "BB_INCLUDE_ADD=${BB_INCLUDE_ADD} \
+ BB_LDFLAGS_ADD=${BB_LDFLAGS_ADD}"
+
+FILES_${PN} = "${libdir}/*.so ${bindir}"
+FILES_${PN}-dev = "${includedir}"
+
+# Avoid QA Issue: No GNU_HASH in the elf binary
+INSANE_SKIP_${PN} = "ldflags"
+
+# Avoid QA Issue: Files/directories were installed but not shipped in any package
+INSANE_SKIP_${PN} += "installed-vs-shipped"
+
+#Skip strip check in QA test.
+INSANE_SKIP_${PN} += "already-stripped"
+
+do_compile () {
+ oe_runmake CFLAGS="${BB_CFLAGS_ADD}" TUNE_FEATURES="${TUNE_FEATURES}"
+}
+
+do_install () {
+ oe_runmake PREFIX="${prefix}" DESTDIR="${D}" PACKAGE_ARCH="${PACKAGE_ARCH}" install
+}
+
+inherit systemd
+SYSTEMD_PACKAGES = "${PN}"
+SYSTEMD_SERVICE_${PN} = "aed.service"
+FILES_${PN} += "${systemd_unitdir}/system/aed.service"
+do_install_append() {
+ if ${@bb.utils.contains('DISTRO_FEATURES','systemd','true','false',d)}; then
+ install -d ${D}${systemd_unitdir}/system
+ if [ -s ${B}/aed.service ] && [ -f ${B}/aed.service ]; then
+ install -m 0644 ${B}/aed.service ${D}${systemd_unitdir}/system
+ fi
+ if [ -s ${B}/lib/systemd/system/aed.service ] && [ -f ${B}/lib/systemd/system/aed.service ]; then
+ install -m 0644 ${B}/lib/systemd/system/aed.service ${D}${systemd_unitdir}/system
+ fi
+ fi
+}
+
+create_misc_mount_point() {
+ install -d ${IMAGE_ROOTFS}/misc
+}
+ROOTFS_PREPROCESS_COMMAND += "create_misc_mount_point;"
+
+addtask bachclean
+do_bachclean () {
+ oe_runmake clean
+}
diff --git a/meta/meta-mediatek/recipes-devtools/clang/clang-cross_git.bbappend b/meta/meta-mediatek/recipes-devtools/clang/clang-cross_git.bbappend
new file mode 100644
index 0000000..4985a5c
--- /dev/null
+++ b/meta/meta-mediatek/recipes-devtools/clang/clang-cross_git.bbappend
@@ -0,0 +1,12 @@
+do_install_append() {
+
+ rm -f ${D}${bindir}/${TARGET_PREFIX}llvm-ar
+ cat > ${D}${bindir}/${TARGET_PREFIX}llvm-ar << 'EOF'
+#!/bin/sh
+basedir=$(dirname "$0")
+"${basedir}/../llvm-ar" "$@"
+exit "$?"
+EOF
+ chmod +x ${D}${bindir}/${TARGET_PREFIX}llvm-ar
+
+}
diff --git a/meta/meta-mediatek/recipes-devtools/clang/compiler-rt_git.bbappend b/meta/meta-mediatek/recipes-devtools/clang/compiler-rt_git.bbappend
new file mode 100644
index 0000000..2733168
--- /dev/null
+++ b/meta/meta-mediatek/recipes-devtools/clang/compiler-rt_git.bbappend
@@ -0,0 +1 @@
+baselib = "lib"
diff --git a/meta/meta-mediatek/recipes-devtools/clang/files/0002-use-gcc_s-instead-unwind.patch b/meta/meta-mediatek/recipes-devtools/clang/files/0002-use-gcc_s-instead-unwind.patch
new file mode 100644
index 0000000..c885d9e
--- /dev/null
+++ b/meta/meta-mediatek/recipes-devtools/clang/files/0002-use-gcc_s-instead-unwind.patch
@@ -0,0 +1,27 @@
+From 10085819b632fecf6b4cd16dbb26f65ac56fa86e Mon Sep 17 00:00:00 2001
+From: Jizhou Deng <jizhou.deng@mediatek.com>
+Date: Fri, 26 Jul 2019 11:33:54 +0800
+Subject: [PATCH] use gcc_s instead unwind
+
+---
+ clang/lib/Driver/ToolChains/CommonArgs.cpp | 4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp
+index 5f6b24e33eb..cb4854710cb 100644
+--- a/clang/lib/Driver/ToolChains/CommonArgs.cpp
++++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp
+@@ -1192,9 +1192,7 @@ void tools::AddRunTimeLibs(const ToolChain &TC, const Driver &D,
+ case ToolChain::RLT_CompilerRT:
+ CmdArgs.push_back(TC.getCompilerRTArgString(Args, "builtins"));
+ CmdArgs.push_back("--as-needed");
+- CmdArgs.push_back("-l:libunwind.a");
+- CmdArgs.push_back("-lpthread");
+- CmdArgs.push_back("-ldl");
++ CmdArgs.push_back("-lgcc_s");
+ CmdArgs.push_back("--no-as-needed");
+
+ break;
+--
+2.18.0
+
diff --git a/meta/meta-mediatek/recipes-devtools/clang/libcxx_%.bbappend b/meta/meta-mediatek/recipes-devtools/clang/libcxx_%.bbappend
new file mode 100644
index 0000000..2733168
--- /dev/null
+++ b/meta/meta-mediatek/recipes-devtools/clang/libcxx_%.bbappend
@@ -0,0 +1 @@
+baselib = "lib"
diff --git a/meta/meta-mediatek/recipes-devtools/clang/libcxx_git.bbappend b/meta/meta-mediatek/recipes-devtools/clang/libcxx_git.bbappend
new file mode 100644
index 0000000..2975a45
--- /dev/null
+++ b/meta/meta-mediatek/recipes-devtools/clang/libcxx_git.bbappend
@@ -0,0 +1,5 @@
+TARGET_CXXFLAGS_remove_toolchain-clang = "--stdlib=libc++ "
+TUNE_CCARGS_append_toolchain-clang = " -Wl,-lgcc_s "
+PACKAGECONFIG_arm = ""
+PACKAGECONFIG_aarch64 = ""
+
diff --git a/meta/meta-mediatek/recipes-devtools/clang/llvm-project-source.bbappend b/meta/meta-mediatek/recipes-devtools/clang/llvm-project-source.bbappend
new file mode 100644
index 0000000..5bf7379
--- /dev/null
+++ b/meta/meta-mediatek/recipes-devtools/clang/llvm-project-source.bbappend
@@ -0,0 +1,6 @@
+FILESEXTRAPATHS_append := ":${THISDIR}/files"
+
+SRC_URI_append = " \
+ file://0002-use-gcc_s-instead-unwind.patch \
+"
+
diff --git a/meta/meta-mediatek/recipes-devtools/cpumem-debug-tool/cpumem-debug-tool.bb b/meta/meta-mediatek/recipes-devtools/cpumem-debug-tool/cpumem-debug-tool.bb
new file mode 100644
index 0000000..705253c
--- /dev/null
+++ b/meta/meta-mediatek/recipes-devtools/cpumem-debug-tool/cpumem-debug-tool.bb
@@ -0,0 +1,18 @@
+DESCRIPTION = "Mediatek cpumem-debug-tool"
+LICENSE = "MediaTekProprietary"
+LIC_FILES_CHKSUM = "file://${WORKDIR}/README;md5=ecf62296074513b19f1c6e1ae1bd704a"
+BBCLASSEXTEND += "native"
+APPS_SRC = "${TOPDIR}/../src/devtools/debug-utils"
+
+WORKONSRC = "${APPS_SRC}"
+
+inherit deploy workonsrc
+
+do_deploy () {
+ install -d ${DEPLOYDIR}
+ if [ -f "${S}/Collect_CPU_Mem_info.py" ]; then
+ install -m 755 ${S}/Collect_CPU_Mem_info.py -t ${DEPLOYDIR}
+ fi
+}
+
+addtask deploy before do_build after do_compile
diff --git a/meta/meta-mediatek/recipes-devtools/crypttool/crypttool.bb b/meta/meta-mediatek/recipes-devtools/crypttool/crypttool.bb
new file mode 100644
index 0000000..1cc2b2c
--- /dev/null
+++ b/meta/meta-mediatek/recipes-devtools/crypttool/crypttool.bb
@@ -0,0 +1,31 @@
+inherit deploy workonsrc
+
+DESCRIPTION = "crypt_tool"
+LICENSE = "MediaTekProprietary"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=e1696b147d49d491bcb4da1a57173fff"
+MTK_SRC = "${TOPDIR}/../src/devtools/nfsb/crypt_tool"
+
+WORKONSRC = "${MTK_SRC}"
+
+INSANE_SKIP_${PN} += "installed-vs-shipped"
+INSANE_SKIP_${PN} += "already-stripped"
+
+EXTRA_OEMAKE = "CROSS=${TARGET_PREFIX} OUT=${WORKDIR} ARCH=${KERNEL_ARCH} DM_PROTECT_KEY=${MTK_KEY_DIR}/${DM_PROTECT_ENC_KEY}"
+
+INSANE_SKIP_${PN} = "ldflags"
+INSANE_SKIP_${PN}-dev = "ldflags already-stripped"
+FILES_${PN} = "${bindir}/crypt_target_tool"
+FILES_${PN} += "${bindir}/dmsetup"
+FILES_${PN} += "${libdir}/libdevmapper.so.1.02"
+
+DEPENDS += " tzapp "
+
+do_compile () {
+ oe_runmake all
+}
+
+do_install () {
+ oe_runmake install DESTDIR="${D}"
+}
+
+
diff --git a/meta/meta-mediatek/recipes-devtools/factory/factory.bb b/meta/meta-mediatek/recipes-devtools/factory/factory.bb
new file mode 100644
index 0000000..e11b2e7
--- /dev/null
+++ b/meta/meta-mediatek/recipes-devtools/factory/factory.bb
@@ -0,0 +1,24 @@
+DESCRIPTION = "factory is a tool to test driver function"
+inherit workonsrc
+WORKONSRC = "${TOPDIR}/../src/devtools/factory/factory"
+LICENSE = "MediaTekProprietary"
+#LIC_FILES_CHKSUM = "file://LICENSE;md5=e1696b147d49d491bcb4da1a57173fff"
+
+do_compile() {
+ if [ -d "${TOPDIR}/../src/devtools/factory/${TARGET_PLATFORM}/${MTK_PROJECT}" ]; then
+ oe_runmake FACTORY_CUSTOM="${TOPDIR}/../src/devtools/factory/${TARGET_PLATFORM}/${MTK_PROJECT}"
+ else
+ oe_runmake FACTORY_CUSTOM="${TOPDIR}/../src/devtools/factory/factory/common"
+ fi
+}
+
+do_install() {
+ install -d ${D}${bindir}
+ install -m 0755 ${S}/factory ${D}${bindir}
+ install -d ${D}/etc
+ if [ -d "${TOPDIR}/../src/devtools/factory/${TARGET_PLATFORM}/${MTK_PROJECT}" ]; then
+ install -m 0755 "${TOPDIR}/../src/devtools/factory/${TARGET_PLATFORM}/${MTK_PROJECT}"/factory.ini ${D}/etc/
+ else
+ install -m 0755 "${TOPDIR}/../src/devtools/factory/factory/common"/factory.ini ${D}/etc/
+ fi
+}
diff --git a/meta/meta-mediatek/recipes-devtools/flashtool/flashtool.bb b/meta/meta-mediatek/recipes-devtools/flashtool/flashtool.bb
new file mode 100644
index 0000000..8e20452
--- /dev/null
+++ b/meta/meta-mediatek/recipes-devtools/flashtool/flashtool.bb
@@ -0,0 +1,15 @@
+DESCRIPTION = "Mediatek FlashScript"
+LICENSE = "MediaTekProprietary"
+LIC_FILES_CHKSUM = "file://${WORKDIR}/README;md5=ecf62296074513b19f1c6e1ae1bd704a"
+SRC_URI = "file://README file://flashimage.py file://flashimage_NoEnforce.py"
+BBCLASSEXTEND += "native"
+
+inherit deploy
+
+do_deploy () {
+ install -d ${DEPLOYDIR}
+ install -m 755 ${WORKDIR}/flashimage.py -t ${DEPLOYDIR}
+ install -m 755 ${WORKDIR}/flashimage_NoEnforce.py -t ${DEPLOYDIR}
+}
+
+addtask deploy before do_build after do_compile
diff --git a/meta/meta-mediatek/recipes-devtools/flashtool/flashtool/README b/meta/meta-mediatek/recipes-devtools/flashtool/flashtool/README
new file mode 100644
index 0000000..cf13d27
--- /dev/null
+++ b/meta/meta-mediatek/recipes-devtools/flashtool/flashtool/README
@@ -0,0 +1 @@
+flashimage.py -h to get information
diff --git a/meta/meta-mediatek/recipes-devtools/flashtool/flashtool/flashimage.py b/meta/meta-mediatek/recipes-devtools/flashtool/flashtool/flashimage.py
new file mode 100644
index 0000000..6e0d6f3
--- /dev/null
+++ b/meta/meta-mediatek/recipes-devtools/flashtool/flashtool/flashimage.py
@@ -0,0 +1,428 @@
+from __future__ import print_function
+
+
+import sys
+import platform
+import os
+import os.path
+import time
+import re
+import argparse
+import subprocess
+
+try:
+ input = raw_input
+except NameError:
+ pass
+
+arguments = None
+fastboot_name = "fastboot"
+fbtool_name = "fbtool.py"
+prod_out_path = os.path.abspath(".")
+
+
+def initialize_env():
+ global fastboot_name
+
+ # check python version
+ if sys.version_info[:2] == (2, 7) or sys.version_info[:2][0] == 3:
+ pass
+ else:
+ print("Python 2.7.x / Python 3.x.x required")
+ exit(1)
+
+ # set fastboot
+ if "Windows" in platform.system():
+ fastboot_name += ".exe"
+ elif "CYGWIN" in platform.system():
+ fastboot_name += ".exe"
+ elif "Linux" in platform.system():
+ if "arm" in platform.machine():
+ fastboot_name += "-linux-arm"
+ elif "aarch64" in platform.machine():
+ fastboot_name += "-linux-arm"
+ elif "x86_64" in platform.machine():
+ fastboot_name += "-linux-x86_64"
+ elif "Darwin" in platform.system():
+ fastboot_name += "-darwin"
+
+
+def set_arguments():
+ global arguments
+
+ parser = argparse.ArgumentParser(
+ description='''
+Auto device flasher, Python 2.7.x / Python 3.x.x required
+''',
+ formatter_class=argparse.RawTextHelpFormatter)
+
+ parser.add_argument("--productdir", default=None,
+ help='''
+The product out dir is where to find images.
+The Following is the path priority order:
+ 1. --productdir specified
+ 2. current directory
+''')
+
+ parser.add_argument("--toolsdir", default=None,
+ help='''
+The tools dir is where to find fbtool and fastboot.
+The Following is the path priority order:
+ 1. --toolsdir specified
+ 2. current directory
+ 3. $PATH
+''')
+
+ parser.add_argument("partition", nargs="?", default="all",
+ help="partition to flash (default: all) \
+ , not include the test partition")
+
+ parser.add_argument("-b", "--boot", action="store_true", default=False,
+ help="Flash boot partition")
+
+ parser.add_argument("-d", "--dryrun", action="store_true", default=False,
+ help="No image would be flashed, for debug")
+
+ parser.add_argument("-s", "--userdefined",
+ action="store_true", default=False,
+ help="Flash user-defined partitions \
+ and run user-defined actions")
+
+ parser.add_argument("-t", "--test", action="store_true", default=False,
+ help="Flash test partition")
+
+ parser.add_argument("-u", "--user", action="store_true", default=False,
+ help="Flash user data partition")
+
+ parser.add_argument("-v", "--verbose", action="store_true", default=False,
+ help="print more information")
+
+ arguments = parser.parse_args()
+
+
+def show_info(case):
+ def print_platform():
+ print("".center(60, "="))
+ print("")
+ print(("Running flasher on " + platform.platform()).center(60))
+ print("")
+ print("".center(60, "="))
+
+ def print_imagepath():
+ global prod_out_path
+ print("".center(60, "="))
+ print("= flash images under:".ljust(58), "=")
+ print("= ", prod_out_path.ljust(52), "=")
+ print("".center(60, "="))
+
+ def print_success():
+ if platform.system() == "Windows":
+ input("Success! press enter to exit: ")
+ else:
+ print("Success!")
+
+ def print_default():
+ print("No information about %s." % case)
+
+ information = {
+ "platform": print_platform,
+ "imagepath": print_imagepath,
+ "success": print_success
+ }
+
+ information.get(case, print_default)()
+
+
+def check_flash_tools():
+ global arguments, fbtool_name, fastboot_name
+ toolsdir = ""
+ if arguments.toolsdir:
+ try:
+ toolsdir = os.path.abspath(arguments.toolsdir)
+ fastboot_name = os.path.join(toolsdir, fastboot_name)
+ fbtool_name = os.path.join(toolsdir, fbtool_name)
+ if not os.path.exists(fbtool_name):
+ raise Exception("Cannot find " + str(fbtool_name) + " in \
+ " + str(toolsdir))
+ if not os.path.exists(fastboot_name):
+ raise Exception("Cannot find " + str(fastboot_name) + " in \
+ " + str(toolsdir))
+ except Exception as err:
+ print(str(err))
+ exit(1)
+ else:
+ toolsdir = os.path.abspath(".")
+ if os.path.exists(os.path.join(toolsdir, fbtool_name)):
+ if os.path.exists(os.path.join(toolsdir, fastboot_name)):
+ fastboot_name = os.path.join(toolsdir, fastboot_name)
+ fbtool_name = os.path.join(toolsdir, fbtool_name)
+
+
+def get_flashprocs():
+ global arguments
+ devProduct = "DEFAULT"
+
+ try:
+ from flashproc import getFlashProc
+ except ImportError as err:
+ print("ImportError: ", err)
+ exit(1)
+
+ flashprocs = getFlashProc(devProduct)
+
+ if arguments.userdefined:
+ try:
+ from flashproc import getFlashUserdefinedProc
+ flashprocs = getFlashUserdefinedProc(devProduct)
+ except:
+ flashprocs = getFlashProc(devProduct)
+
+ if arguments.user:
+ try:
+ from flashproc import getFlashUserProc
+ flashprocs = getFlashUserProc(devProduct)
+ except:
+ flashprocs = getFlashProc(devProduct)
+
+ if arguments.boot:
+ try:
+ from flashproc import getFlashBootProc
+ flashprocs = getFlashBootProc(devProduct)
+ except:
+ flashprocs = getFlashProc(devProduct)
+
+ if arguments.test:
+ try:
+ from flashproc import getFlashTestProc
+ flashprocs = getFlashTestProc(devProduct)
+ except:
+ flashprocs = getFlashProc(devProduct)
+
+ if flashprocs is None:
+ print("Cannot retrieve flash procedure according \
+ to product type of", devProduct)
+ print("Terminate program !")
+ exit(1)
+
+ if arguments.verbose:
+ print("Flash procedure".center(60))
+ print("".center(60, "-"))
+ for p in flashprocs:
+ print("fastboot", " ".join(p))
+
+ return flashprocs
+
+
+def get_img_list():
+ flashprocs = get_flashprocs()
+ imgs = []
+ try:
+ for proc in flashprocs:
+ if proc[0] == "fastboot":
+ if proc[1] == "flash":
+ if proc[3] not in imgs:
+ imgs.append(proc[3])
+ except Exception as err:
+ print(err)
+ return imgs
+
+
+def check_img(filename, _needreboot=True, _showdetail=False):
+ global fastboot_name, prod_out_path
+ if _showdetail:
+ print((filename).rjust(28), ": ", end="")
+ path = os.path.join(prod_out_path, filename)
+ if os.path.exists(path):
+ if _showdetail:
+ print("PASS!")
+ return path
+ if _needreboot:
+ print("FAIL!\n Rebooting...")
+ call([fastboot_name, "reboot"])
+ exit(1)
+ return None
+
+
+def call(cmd):
+ global arguments
+ if arguments.verbose:
+ print("call:", " ".join(cmd))
+ return subprocess.call(cmd)
+
+
+def check_output(cmd):
+ global arguments
+ if arguments.verbose:
+ print("check_output:", " ".join(cmd))
+ return subprocess.check_output(cmd, stderr=subprocess.STDOUT, shell=True)
+
+
+def check_img_path():
+ global arguments, prod_out_path
+ if arguments.productdir:
+ prod_out_path = os.path.abspath(arguments.productdir)
+ else:
+ prod_out_path = os.path.abspath(".")
+ for img in get_img_list():
+ if check_img(img, _needreboot=False, _showdetail=False) is None:
+ prod_out_path = None
+ break
+ if prod_out_path is None:
+ prod_out_path = os.getenv("PRODUCT_OUT", ".")
+ prod_out_path = os.path.abspath(prod_out_path)
+
+
+def da_mode_wait(wait_secs=30):
+ global fbtool_name
+ print("\nWaiting for DA mode:")
+ ret_code = None
+ for i in range(wait_secs):
+ time.sleep(1)
+ print("# ", end="")
+ sys.stdout.flush()
+ ret_code = check_output("python %s " % fbtool_name)
+ if ret_code is not None and len(ret_code) != 0:
+ print("datool - device detected: ")
+ break
+ if ret_code is None:
+ print("No device detected.")
+ print("Please ensure that datool is running.\n")
+ exit(1)
+
+
+def fastboot_wait(wait_secs=30):
+ global fastboot_name
+ print("\nWaiting for fastboot mode:")
+ ret_code = None
+ for i in range(wait_secs):
+ time.sleep(1)
+ print("# ", end="")
+ sys.stdout.flush()
+ ret_code = check_output("%s devices" % fastboot_name).decode()
+ if ret_code is not None and len(ret_code) != 0:
+ print("Fastboot - device detected: ", (ret_code.split())[0])
+ break
+ if ret_code is None:
+ print("No device detected. ")
+ exit(1)
+
+
+def command_reboot(_tobootloader=True):
+ global fastboot_name
+ if _tobootloader:
+ call([fastboot_name, "reboot-bootloader"])
+ fastboot_wait()
+ else:
+ call([fastboot_name, "reboot"])
+
+
+def reboot_device():
+ time.sleep(3)
+ command_reboot(_tobootloader=False)
+
+
+def check_all_imgs():
+ images = get_img_list()
+ print("".center(60, "-"))
+ print("Checking image".center(60))
+ print("".center(60, "-"))
+ try:
+ for img in images:
+ check_img(img, _needreboot=True, _showdetail=True)
+ except Exception as err:
+ print(err)
+ time.sleep(3)
+ command_reboot(_tobootloader=False)
+ input("Fail, press enter to exit: ")
+ exit(1)
+
+
+def reboot_bootloader(tries=3):
+ check_output("adb devices")
+
+ for i in range(tries):
+ print(". ", end="")
+ time.sleep(2)
+ sys.stdout.flush()
+ try:
+ device_id = check_output("adb get-serialno")
+ except subprocess.CalledProcessError as err:
+ print("command '{}' return with error (code {}): {}".format(
+ err.cmd, err.returncode, err.output))
+ continue
+ print("\nAdb - device detected: ", (device_id.split())[0])
+ check_output("adb -s %s reboot bootloader" % (device_id.split())[0])
+ return
+
+ print("adb is not ready!")
+ print("Please check whether the usb cable is plugged or adb is supported.")
+ exit(1)
+
+
+def command_run(cmd, dryrun=False):
+ ret_code = 1
+ raw_cmd = []
+ if cmd[0] == "fastboot":
+ cmd[0] = fastboot_name
+ if cmd[1] == "flash":
+ path = check_img(cmd[3], _needreboot=False, _showdetail=False)
+ if path is not None:
+ if "CYGWIN" in platform.system():
+ p = subprocess.check_output(
+ "cygpath --absolute --mixed %s" % path, shell=True)
+ if p:
+ path = p.strip()
+ raw_cmd += [cmd[0], cmd[1], cmd[2], path]
+ else:
+ raw_cmd += cmd
+ elif cmd[0] == "fbWait":
+ fastboot_wait()
+ return 0
+ elif cmd[0] == "daWait":
+ da_mode_wait()
+ return 0
+ elif cmd[0] == "reboottobl":
+ reboot_bootloader()
+ return 0
+ else:
+ print("FAIL: Unknown command!\n")
+ return -1
+
+ if dryrun:
+ print(" ".join(raw_cmd))
+ ret_code = 0
+ else:
+ ret_code = call(raw_cmd)
+ if ret_code == 0:
+ if cmd[0] == "fastboot":
+ if cmd[1] == "reboot-bootloader":
+ fastboot_wait()
+ return ret_code
+
+
+def flash_imgs():
+ print("\nStart flashing".center(60))
+ print("".center(60, "-"))
+ try:
+ for p in get_flashprocs():
+ if command_run(p, arguments.dryrun) != 0:
+ raise Exception("<FAILED> %s" % " ".join(proc))
+ except Exception as err:
+ print(err)
+ time.sleep(3)
+ command_reboot(_tobootloader=False)
+ exit(1)
+
+
+if __name__ == "__main__":
+ initialize_env()
+ set_arguments()
+ show_info("platform")
+ check_flash_tools()
+ check_img_path()
+ show_info("imagepath")
+ check_all_imgs()
+ flash_imgs()
+ reboot_device()
+ show_info("success")
+ exit(0)
diff --git a/meta/meta-mediatek/recipes-devtools/flashtool/flashtool/flashimage_NoEnforce.py b/meta/meta-mediatek/recipes-devtools/flashtool/flashtool/flashimage_NoEnforce.py
new file mode 100644
index 0000000..980228b
--- /dev/null
+++ b/meta/meta-mediatek/recipes-devtools/flashtool/flashtool/flashimage_NoEnforce.py
@@ -0,0 +1,333 @@
+#!/usr/bin/python
+
+import os
+import os.path
+import sys
+import platform
+import argparse
+import subprocess
+import time
+import re
+import string
+
+################################################################################
+# check python version
+if sys.version_info[:2] == (2,7):
+ pass
+else:
+ print 'Please install Python 2.7.x to run this script'
+ exit(1)
+################################################################################
+
+verbose = False
+skipFlash = False
+
+fbtool = 'fbtool.py'
+fastboot = 'fastboot'
+adb = 'adb'
+
+system = platform.system()
+machine = platform.machine()
+product_out = os.path.abspath('.')
+
+if 'Windows' in system or 'CYGWIN' in system:
+ adb += '.exe'
+ fastboot += '.exe'
+elif 'Linux' in system:
+ if 'x86_64' in machine:
+ adb += '-linux-x86_64'
+ fastboot += '-linux-x86_64'
+ elif 'arm' in machine or 'aarch64' in machine:
+ adb += '-linux-arm'
+ fastboot += '-linux-arm'
+elif 'Darwin' in system:
+ adb += '-darwin'
+ fastboot += '-darwin'
+
+# Generate image list from procedure list
+def getImageList(procs):
+ imgs = []
+ try:
+ for p in procs:
+ if p[0] == 'fastboot' and p[1] == 'flash' and p[3] not in imgs:
+ imgs.append(p[3])
+ except Exception, e:
+ print e
+ return imgs
+
+def call(cmd):
+ '''cmd: the command list for subprocess.call'''
+ if verbose:
+ print 'call:', ' '.join(cmd)
+ return subprocess.call(cmd)
+
+def check_output(cmd):
+ '''cmd: the command list for subprocess.check_output'''
+ if verbose:
+ print 'check_output:', ' '.join(cmd)
+ return subprocess.check_output(cmd, stderr = subprocess.STDOUT, shell=True)
+
+def checkImage(filename, needreboot = True, _verbose = False):
+ if _verbose:
+ print (filename).rjust(38),':',
+ filepath = os.path.join(product_out, filename)
+ if os.path.exists(filepath):
+ if _verbose:
+ print 'PASS'
+ return filepath
+ if needreboot:
+ print 'FAIL'
+ call([fastboot, 'reboot'])
+ exit(1)
+ return None
+
+# return 0 if success
+def cmdRun(cmd, dryrun = False):
+ ret = 1
+ raw_cmd = []
+ if cmd[0] == 'daWait':
+ daWait()
+ print ''
+ return 0
+ elif cmd[0] == 'fbWait':
+ fbWait()
+ print ''
+ return 0
+ elif cmd[0] == 'fastboot': # processing fastboot commands
+ cmd[0] = fastboot
+ if cmd[1] == 'flash':
+ # check if image path exits and valid
+ filepath = checkImage(cmd[3], False, False)
+ if filepath != None:
+ if 'CYGWIN' in system:
+ p = subprocess.check_output('cygpath --absolute --mixed %s' % filepath, shell=True)
+ if p:
+ filepath = p.strip()
+ raw_cmd += [cmd[0], cmd[1], cmd[2], filepath]
+ else:
+ raw_cmd += cmd
+ else:
+ print 'FAIL: Unknown command!'
+ return -1
+ if dryrun:
+ print ' '.join(raw_cmd)
+ ret = 0
+ else:
+ ret = call(raw_cmd)
+ if ret == 0 and cmd[0] == 'fastboot' and cmd[1] == 'reboot-bootloader' and not dryrun:
+ fbWait()
+ return ret
+
+def daWait(secs = 60):
+ print 'adb devices'
+ ret = None
+ adb_found = 0
+ for i in range(secs):
+ print '.',
+ sys.stdout.flush()
+ time.sleep(1)
+ ret = check_output('%s devices' % adb)
+ if ret != None and len(ret) > 29 :
+ print ''
+ print 'Adb - device detected: ', (ret.split())[4]
+ print ret
+ adb_found = 1
+ break
+ if adb_found:
+ print 'rebooting to bootloader'
+ check_output('%s reboot bootloader' % adb)
+ else:
+ print 'adb is not ready, please make sure your device is cable-in, and check your device status!'
+ exit(1)
+
+
+def fbWait(secs = 60):
+ print 'Waiting for fastboot mode'
+ ret = None
+ for i in range(secs):
+ print '.',
+ sys.stdout.flush()
+ time.sleep(1)
+ ret = check_output('%s devices' % fastboot)
+ if ret != None and len(ret) != 0:
+ print ''
+ print 'Fastboot - device detected: ', (ret.split())[0]
+ break
+ if ret == None:
+ print 'No device detected. Please ensure that fastboot is running on the target device'
+ exit(1)
+
+def cmdReboot(toBootloader = True):
+ if toBootloader:
+ call([fastboot, 'reboot-bootloader'])
+ fbWait()
+ else:
+ call([fastboot, 'reboot'])
+
+if __name__ == '__main__':
+ # parse args
+ parser = argparse.ArgumentParser( \
+ description = '''
+Auto device flasher, Python 2.7.x required
+''',
+ formatter_class = argparse.RawTextHelpFormatter)
+ parser.add_argument('partition', nargs='?', default = 'all', \
+ help = 'partition to flash [default: all] , not include test partition')
+ parser.add_argument('-d', '--dryrun', action = 'store_true', default = False, \
+ help = 'dryrun for debug, no image would be flashed')
+ parser.add_argument('-u', '--user', action = 'store_true', default = False, \
+ help = 'Flash user data partition')
+ parser.add_argument('-b', '--boot', action = 'store_true', default = False, \
+ help = 'Flash boot partition')
+ parser.add_argument('-t', '--test', action = 'store_true', default = False, \
+ help = 'Flash test partition')
+ parser.add_argument('-v', '--verbose', action = 'store_true', default = False, \
+ help = 'print more information while flashing')
+ parser.add_argument('--toolsdir', default = None, \
+ help = '''\
+The tools dir where to find fbtool and fastboot.
+Path priority order:
+ 1. --toolsdir specified
+ 2. current directory
+ 3. $PATH
+''')
+ parser.add_argument('--productdir', default = None, \
+ help = '''\
+The product out directory where to find images.
+Path priority order:
+ 1. --productdir specified
+ 2. current directory
+''')
+
+ args = parser.parse_args()
+ verbose = args.verbose
+ if args.dryrun:
+ verbose = True
+
+ print ''
+ parser.print_usage()
+ print ''
+ print ''.center(80, '*')
+ print ('Running flasher on ' + platform.platform()).center(80)
+ print ''.center(80, '*')
+ print ''
+
+ try:
+ from flashproc import getFlashProc
+ except ImportError, e:
+ print 'ImportError:',e
+ print ''
+ exit(1)
+ try:
+ from flashproc import getFlashUserProc
+ except:
+ getFlashUserProc = getFlashProc
+ try:
+ from flashproc import getFlashBootProc
+ except:
+ getFlashBootProc = getFlashProc
+ try:
+ from flashproc import getFlashTestProc
+ except:
+ getFlashTestProc = getFlashProc
+
+ # check flash tools
+ toolsdir = ''
+ try:
+ if args.toolsdir:
+ toolsdir = os.path.abspath(args.toolsdir);
+ fbtool = os.path.join(toolsdir, fbtool)
+ fastboot = os.path.join(toolsdir, fastboot)
+ if not os.path.exists(fbtool) or not os.path.exists(fastboot):
+ raise Exception(str(toolsdir))
+ else:
+ toolsdir = os.path.abspath('.')
+ if os.path.exists(os.path.join(toolsdir, fbtool)) and os.path.exists(os.path.join(toolsdir, fastboot)):
+ fbtool = os.path.join(toolsdir, fbtool)
+ fastboot = os.path.join(toolsdir, fastboot)
+ except Exception, e:
+ print 'Can not find fbtool or fastboot in %s' % str(e)
+ print ''
+ exit(1)
+
+ devProduct='DEFAULT'
+
+ procs = getFlashProc(devProduct)
+ if args.user:
+ procs = getFlashUserProc(devProduct)
+ if args.boot:
+ procs = getFlashBootProc(devProduct)
+ if args.test:
+ procs = getFlashTestProc(devProduct)
+ if procs:
+ if verbose:
+ print 'Flash procedure'.center(80)
+ print ''.center(80, '-')
+ for p in procs:
+ print 'fastboot',' '.join(p)
+ print ''
+ else:
+ print 'Can not retrieve flash procedure according to product type of', devProduct
+ print 'Exit !'
+ exit(1)
+
+ # check image path
+ if args.productdir:
+ # take user specific product directory
+ product_out = os.path.abspath(args.productdir)
+ else:
+ # check current directory
+ product_out = os.path.abspath('.')
+ for img in getImageList(procs):
+ if checkImage(img, False, False) is None:
+ product_out = None
+ break
+ if product_out is None:
+ product_out = os.getenv('PRODUCT_OUT', '.')
+ product_out = os.path.abspath(product_out)
+
+ print ''.center(80, '*')
+ print '* flash images under:'.ljust(78), '*'
+ print '* ', product_out.ljust(72), '*'
+ print ''.center(80, '*')
+ print ''
+
+ # check images
+ print 'Checking image'.center(80)
+ print ''.center(80, '-')
+ images = getImageList(procs)
+ try:
+ for img in images:
+ checkImage(img, _verbose = True)
+ except Exception, e:
+ print e
+ time.sleep(2)
+ cmdReboot(False)
+ raw_input('Fail, press enter to exit: ')
+ exit(1)
+
+ # flash images
+ print ''
+ print 'Start flashing'.center(80)
+ print ''.center(80, '-')
+ try:
+ for proc in procs:
+ if skipFlash == False:
+ if 0 != cmdRun(proc, args.dryrun):
+ raise Exception('<<FAILED>> %s' % ' '.join(proc))
+ else:
+ if proc[0] == 'fastboot' and proc[1] == 'flash':
+ print 'Skip flashing', proc[3]
+ except Exception, e:
+ print e
+ time.sleep(2)
+ cmdReboot(False)
+ exit(1)
+
+ time.sleep(2)
+ cmdReboot(False)
+ print ''
+ if system == "Windows":
+ raw_input('Success, press enter to exit: ')
+ else:
+ print 'Success'
diff --git a/meta/meta-mediatek/recipes-devtools/iputilssigma/mtkiputilssigma.bb b/meta/meta-mediatek/recipes-devtools/iputilssigma/mtkiputilssigma.bb
new file mode 100644
index 0000000..9683a6d
--- /dev/null
+++ b/meta/meta-mediatek/recipes-devtools/iputilssigma/mtkiputilssigma.bb
@@ -0,0 +1,8 @@
+DESCRIPTION = "Utilities for the IP protocol, including traceroute6, \
+tracepath, tracepath6, ping, ping6 and arping."
+LICENSE = "BSD & GPLv2+"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=e1696b147d49d491bcb4da1a57173fff"
+
+inherit workonsrc
+WORKONSRC = "${TOPDIR}/../src/devtools/wifi-sigma/iputils-sigma"
+
diff --git a/meta/meta-mediatek/recipes-devtools/m4/m4/fix-absolute-include.patch b/meta/meta-mediatek/recipes-devtools/m4/m4/fix-absolute-include.patch
new file mode 100755
index 0000000..9301378
--- /dev/null
+++ b/meta/meta-mediatek/recipes-devtools/m4/m4/fix-absolute-include.patch
@@ -0,0 +1,99 @@
+diff --git a/lib/stat_.h b/lib/stat_.h
+index cbf5ac0..243b4c0 100644
+--- a/lib/stat_.h
++++ b/lib/stat_.h
+@@ -23,7 +23,7 @@
+ /* This file is supposed to be used on platforms where <sys/stat.h> is
+ incomplete. It is intended to provide definitions and prototypes
+ needed by an application. Start with what the system provides. */
+-#include @ABSOLUTE_SYS_STAT_H@
++#include_next <sys/stat.h>
+
+ #ifndef S_IFMT
+ # define S_IFMT 0170000
+diff --git a/lib/stdint_.h b/lib/stdint_.h
+index 4fa5251..788a980 100644
+--- a/lib/stdint_.h
++++ b/lib/stdint_.h
+@@ -43,7 +43,7 @@
+ Include it before <inttypes.h>, since any "#include <stdint.h>"
+ in <inttypes.h> would reinclude us, skipping our contents because
+ _GL_STDINT_H is defined. */
+-# include @ABSOLUTE_STDINT_H@
++# include_next <stdint.h>
+ #endif
+
+ /* <sys/types.h> defines some of the stdint.h types as well, on glibc,
+diff --git a/lib/stdlib_.h b/lib/stdlib_.h
+index a920408..dc33b29 100644
+--- a/lib/stdlib_.h
++++ b/lib/stdlib_.h
+@@ -26,7 +26,7 @@
+ # pragma GCC system_header
+ #endif
+
+-#include @ABSOLUTE_STDLIB_H@
++#include_next <stdlib.h>
+
+ #else
+ /* Normal invocation convention. */
+@@ -40,7 +40,7 @@
+ # pragma GCC system_header
+ #endif
+
+-#include @ABSOLUTE_STDLIB_H@
++#include_next <stdlib.h>
+
+
+ /* The definition of GL_LINK_WARNING is copied here. */
+diff --git a/lib/sys_time_.h b/lib/sys_time_.h
+index 46cdb70..f98de57 100644
+--- a/lib/sys_time_.h
++++ b/lib/sys_time_.h
+@@ -22,7 +22,7 @@
+ #define _gl_SYS_TIME_H
+
+ #if @HAVE_SYS_TIME_H@
+-# include @ABSOLUTE_SYS_TIME_H@
++# include_next <sys/time.h>
+ #else
+ # include <time.h>
+ #endif
+diff --git a/lib/unistd_.h b/lib/unistd_.h
+index 77df861..9241475 100644
+--- a/lib/unistd_.h
++++ b/lib/unistd_.h
+@@ -19,7 +19,7 @@
+ #define _GL_UNISTD_H
+
+ #if @HAVE_UNISTD_H@
+-# include @ABSOLUTE_UNISTD_H@
++# include_next <unistd.h>
+ #endif
+
+
+diff --git a/lib/wchar_.h b/lib/wchar_.h
+index 6813a21..bd86ce4 100644
+--- a/lib/wchar_.h
++++ b/lib/wchar_.h
+@@ -37,6 +37,6 @@
+ #include <time.h>
+
+ /* Include the original <wchar.h>. */
+-#include @ABSOLUTE_WCHAR_H@
++#include_next <wchar.h>
+
+ #endif /* _GL_WCHAR_H */
+diff --git a/lib/wctype_.h b/lib/wctype_.h
+index 1297c61..fca78cd 100644
+--- a/lib/wctype_.h
++++ b/lib/wctype_.h
+@@ -47,7 +47,7 @@ typedef int __wctype_wint_t;
+ /* Include the original <wctype.h> if it exists.
+ BeOS 5 has the functions but no <wctype.h>. */
+ #if @HAVE_WCTYPE_H@
+-# include @ABSOLUTE_WCTYPE_H@
++# include_next <wctype.h>
+ #endif
+
+ /* FreeBSD 4.4 to 4.11 has <wctype.h> but lacks the functions.
diff --git a/meta/meta-mediatek/recipes-devtools/m4/m4_1.4.9.bbappend b/meta/meta-mediatek/recipes-devtools/m4/m4_1.4.9.bbappend
new file mode 100644
index 0000000..870f92d
--- /dev/null
+++ b/meta/meta-mediatek/recipes-devtools/m4/m4_1.4.9.bbappend
@@ -0,0 +1,4 @@
+FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
+
+SRC_URI_append_toolchain-clang = " file://fix-absolute-include.patch"
+SRC_URI_remove_toolchain-clang = " file://disable_builtin_mul_overflow.patch"
diff --git a/meta/meta-mediatek/recipes-devtools/met/met-driver-internal.bb b/meta/meta-mediatek/recipes-devtools/met/met-driver-internal.bb
new file mode 100644
index 0000000..91763bd
--- /dev/null
+++ b/meta/meta-mediatek/recipes-devtools/met/met-driver-internal.bb
@@ -0,0 +1,49 @@
+DESCRIPTION = "MET-DRIVER-INTERNAL"
+LICENSE = "MediaTekProprietary"
+DEPENDS = "linux-mtk-extension"
+DEPENDS += "met-driver"
+
+inherit workonsrc
+WORKONSRC = "${TOPDIR}/../src/devtools/met-driver-internal"
+export LINUX_VERSION = "${@[d.getVar('TUNE_PKGARCH'), d.getVar('PREFERRED_VERSION_linux-mtk-extension')][bool(d.getVar('PREFERRED_VERSION_linux-mtk-extension'))].replace('%', '')}"
+LDFLAGS = "-L ${RECIPE_SYSROOT}"
+PRJ_DISTRO = "${@bb.utils.contains("DISTRO", "poky-agl", "agl", "poky", d)}"
+
+export KERNEL_SRC = "${TOPDIR}/../src/kernel/linux/v${LINUX_VERSION}"
+export KERNEL_OUT = "${TOPDIR}/tmp/work/${MACHINE_ARCH}-${PRJ_DISTRO}-${TARGET_OS}/${PREFERRED_PROVIDER_virtual/kernel}/${LINUX_VERSION}-${PR}/${PREFERRED_PROVIDER_virtual/kernel}-${LINUX_VERSION}/"
+export MET_DRIVER_INTERNAL_DIR = "${S}/${LINUX_VERSION}"
+#export KBUILD_EXTRA_SYMBOLS= "${TOPDIR}/../src/devtools/met-driver/${LINUX_VERSION}/Module.symvers"
+export CONFIG_MTK_PLATFORM = "${TARGET_PLATFORM}"
+export CONFIG_MET = "m"
+export CONFIG_MET_PLF = "m"
+export CONFIG_BUILD_YOCTO = "y"
+TOOLCHAIN = "gcc"
+
+do_compile() {
+ if [ -d "${MET_DRIVER_INTERNAL_DIR}" ]; then
+ if test "${TARGET_PLATFORM}" != ""; then
+ echo ${TARGET_PLATFORM} met driver internal start compile
+
+ if test "${KERNEL_ARCH}" = "arm64"; then
+ oe_runmake -f ${LINUX_VERSION}/Makefile.yocto TOPDIR=${TOPDIR} ARCH=arm64 CROSS_COMPILE=aarch64-${PRJ_DISTRO}-linux-
+ else
+ oe_runmake -f ${LINUX_VERSION}/Makefile.yocto TOPDIR=${TOPDIR} ARCH=arm CROSS_COMPILE=arm-${PRJ_DISTRO}-linux-gnueabi-
+ fi
+
+ echo ${TARGET_PLATFORM} met driver internal end compile
+ fi
+ fi
+}
+
+do_install() {
+ install -d ${D}/vendor/lib/modules
+ if [ -d "${MET_DRIVER_INTERNAL_DIR}" ]; then
+ install -m 0644 ${MET_DRIVER_INTERNAL_DIR}/met_plf.ko ${D}/vendor/lib/modules
+ fi
+}
+
+# Avoid QA Issue: No GNU_HASH in the elf binary
+PN='met-driver-internal'
+INSANE_SKIP_${PN} = "ldflags"
+INSANE_SKIP_${PN} += "already-stripped"
+FILES_${PN} += "/vendor/lib/modules"
diff --git a/meta/meta-mediatek/recipes-devtools/met/met-driver.bb b/meta/meta-mediatek/recipes-devtools/met/met-driver.bb
new file mode 100644
index 0000000..30addcc
--- /dev/null
+++ b/meta/meta-mediatek/recipes-devtools/met/met-driver.bb
@@ -0,0 +1,54 @@
+DESCRIPTION = "MET-DRIVER"
+LICENSE = "GPL-2.0"
+DEPENDS = "linux-mtk-extension"
+
+inherit workonsrc
+WORKONSRC = "${TOPDIR}/../src/devtools/met-driver"
+LINUX_VERSION = "${@[d.getVar('TUNE_PKGARCH'), d.getVar('PREFERRED_VERSION_linux-mtk-extension')][bool(d.getVar('PREFERRED_VERSION_linux-mtk-extension'))].replace('%', '')}"
+LDFLAGS = "-L ${RECIPE_SYSROOT}"
+PRJ_DISTRO = "${@bb.utils.contains("DISTRO", "poky-agl", "agl", "poky", d)}"
+
+export KERNEL_SRC = "${TOPDIR}/../src/kernel/linux/v${LINUX_VERSION}"
+export KERNEL_OUT = "${TOPDIR}/tmp/work/${MACHINE_ARCH}-${PRJ_DISTRO}-${TARGET_OS}/${PREFERRED_PROVIDER_virtual/kernel}/${LINUX_VERSION}-${PR}/${PREFERRED_PROVIDER_virtual/kernel}-${LINUX_VERSION}/"
+export MET_DRIVER_DIR = "${S}/${LINUX_VERSION}"
+export CONFIG_MTK_PLATFORM = "${TARGET_PLATFORM}"
+export CONFIG_MTK_MET = "m"
+export CONFIG_BUILD_YOCTO = "y"
+TOOLCHAIN = "gcc"
+
+do_compile() {
+ if [ -d "${MET_DRIVER_DIR}" ]; then
+ if test "${TARGET_PLATFORM}" != ""; then
+ echo ${TARGET_PLATFORM} met driver start compile
+
+ # for different kerenl src path naming
+ if test "${KERNELDIR}" != ""; then
+ if test "${TARGET_PLATFORM}" = "mt8183"; then
+ export KERNEL_SRC="${TOPDIR}/../src/kernel/linux/${KERNELDIR}"
+ fi
+ fi
+
+ if test "${KERNEL_ARCH}" = "arm64"; then
+ oe_runmake -f ${LINUX_VERSION}/Makefile.yocto TOPDIR=${TOPDIR} ARCH=arm64 CROSS_COMPILE=aarch64-${PRJ_DISTRO}-linux-
+ else
+ oe_runmake -f ${LINUX_VERSION}/Makefile.yocto TOPDIR=${TOPDIR} ARCH=arm CROSS_COMPILE=arm-${PRJ_DISTRO}-linux-gnueabi-
+ fi
+
+ echo ${TARGET_PLATFORM} met driver end compile
+ fi
+ fi
+}
+
+do_install() {
+ install -d ${D}/vendor/lib/modules
+ if [ -d "${MET_DRIVER_DIR}" ]; then
+ install -m 0644 ${MET_DRIVER_DIR}/met.ko ${D}/vendor/lib/modules
+ fi
+}
+
+# Avoid QA Issue: No GNU_HASH in the elf binary
+PN='met-driver'
+INSANE_SKIP_${PN} = "ldflags"
+INSANE_SKIP_${PN} += "already-stripped"
+FILES_${PN} += "/vendor/lib/modules"
+
diff --git a/meta/meta-mediatek/recipes-devtools/met/met-utils.bb b/meta/meta-mediatek/recipes-devtools/met/met-utils.bb
new file mode 100644
index 0000000..6ceacb1
--- /dev/null
+++ b/meta/meta-mediatek/recipes-devtools/met/met-utils.bb
@@ -0,0 +1,35 @@
+DESCRIPTION = "MET-UTILS"
+LICENSE = "MediaTekProprietary"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=b415b1f2e589c23040ce1f39702002e6"
+
+inherit get_toolchain_name
+inherit workonsrc
+WORKONSRC = "${TOPDIR}/../src/devtools/met-utils"
+export CONFIG_MTK_PLATFORM = "${TARGET_PLATFORM}"
+#TOOLCHAIN = "gcc"
+
+export EXTRA_CFLAGS += "-Wl,--hash-style=gnu"
+
+do_compile() {
+ if [ -d "${WORKONSRC}" ]; then
+ echo ${TARGET_PLATFORM} met-utils start compile
+
+ if test "${KERNEL_ARCH}" = "arm64"; then
+ oe_runmake -f ${WORKONSRC}/Makefile TOPDIR=${TOPDIR} ARCH=arm64 CROSS_COMPILE=aarch64-poky-linux- TOOLCHAIN_NAME=${TOOLCHAIN_NAME}
+ else
+ oe_runmake -f ${WORKONSRC}/Makefile TOPDIR=${TOPDIR} ARCH=arm CROSS_COMPILE=arm-poky-linux-gnueabi- TOOLCHAIN_NAME=${TOOLCHAIN_NAME}
+ fi
+
+ echo ${TARGET_PLATFORM} met-utils end compile
+ fi
+}
+
+do_install() {
+ oe_runmake \
+ PREFIX="${prefix}" DESTDIR="${D}" PACKAGE_ARCH="${PACKAGE_ARCH}" install
+}
+
+# Avoid QA Issue: No GNU_HASH in the elf binary
+PN='met-utils'
+INSANE_SKIP_${PN} += "already-stripped"
+
diff --git a/meta/meta-mediatek/recipes-devtools/mrdump/mrdump.bb b/meta/meta-mediatek/recipes-devtools/mrdump/mrdump.bb
new file mode 100644
index 0000000..0d4aaa2
--- /dev/null
+++ b/meta/meta-mediatek/recipes-devtools/mrdump/mrdump.bb
@@ -0,0 +1,36 @@
+DESCRIPTION = "Mediatek MRDUMP application"
+SECTION = "base"
+LICENSE = "MediaTekProprietary"
+
+MRDUMP_SRC = "${TOPDIR}/../src/devtools/mrdump"
+
+WORKONSRC = "${MRDUMP_SRC}"
+
+DEPENDS = "zlib"
+LDFLAGS = "-lz"
+TARGET_CC_ARCH += "${LDFLAGS}"
+# BB_CFLAGS_ADD
+BB_LDFLAGS_ADD = "-lz"
+BB_INCLUDE_ADD = "-I${MRDUMP_SRC}"
+
+inherit deploy workonsrc
+
+FILES_${PN} = "${libdir}/*.so ${bindir}"
+FILES_${PN}-dev = "${includedir}"
+
+# Avoid QA Issue: No GNU_HASH in the elf binary
+INSANE_SKIP_${PN} = "ldflags"
+
+# Avoid QA Issue: Files/directories were installed but not shipped in any package
+INSANE_SKIP_${PN} += "installed-vs-shipped"
+
+do_compile() {
+ oe_runmake \
+ PACKAGE_ARCH="${PACKAGE_ARCH}" \
+ CFLAGS="${CFLAGS}" \
+ LDFLAGS="${LDFLAGS}"
+}
+
+do_install() {
+ oe_runmake install PREFIX="${prefix}" DESTDIR="${D}"
+}
diff --git a/meta/meta-mediatek/recipes-devtools/nfsbmount/nfsbmount.bb b/meta/meta-mediatek/recipes-devtools/nfsbmount/nfsbmount.bb
new file mode 100644
index 0000000..8227821
--- /dev/null
+++ b/meta/meta-mediatek/recipes-devtools/nfsbmount/nfsbmount.bb
@@ -0,0 +1,36 @@
+inherit deploy workonsrc
+
+DESCRIPTION = "nfsb_mount"
+LICENSE = "MediaTekProprietary"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=e1696b147d49d491bcb4da1a57173fff"
+MTK_SRC = "${TOPDIR}/../src/devtools/nfsb/nfsb_mount"
+
+WORKONSRC = "${MTK_SRC}"
+
+INSANE_SKIP_${PN} += "installed-vs-shipped"
+INSANE_SKIP_${PN} += "already-stripped"
+
+EXTRA_OEMAKE = "CROSS=${TARGET_PREFIX} OUT=${WORKDIR} ARCH=${KERNEL_ARCH}"
+
+INSANE_SKIP_${PN} = "ldflags"
+INSANE_SKIP_${PN}-dev = "ldflags already-stripped"
+FILES_${PN} = "${bindir}/nfsb_mount"
+
+DEPENDS += " openssl openssl-native"
+
+do_compile () {
+ IMG_KEY_FILE=""
+ if [ "${ROOTFS_VERITY_KEY}" = "" ]; then
+ IMG_KEY_FILE="${MTK_KEY_DIR}/${VERIFIED_KEY}.pem"
+ else
+ IMG_KEY_FILE="${MTK_KEY_DIR}/${ROOTFS_VERITY_KEY}.pem"
+ fi
+ python ${MTK_SRC}/pretreat-key.py ${IMG_KEY_FILE} ${WORKDIR}/nfsbmount-${PV}/
+ oe_runmake all
+}
+
+do_install () {
+ oe_runmake install DESTDIR="${D}"
+}
+
+
diff --git a/meta/meta-mediatek/recipes-devtools/sp_meta/sp-meta_1.0.0.bb b/meta/meta-mediatek/recipes-devtools/sp_meta/sp-meta_1.0.0.bb
new file mode 100644
index 0000000..78eb4d2
--- /dev/null
+++ b/meta/meta-mediatek/recipes-devtools/sp_meta/sp-meta_1.0.0.bb
@@ -0,0 +1,85 @@
+#Basic Configuration
+DESCRIPTION = "spmeta"
+SECTION = "base"
+LICENSE = "MediaTekProprietary"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=e1696b147d49d491bcb4da1a57173fff"
+MTK_SRC = "${TOPDIR}/../src/devtools/sp_meta"
+SP_PREFIX = "${STAGING_INCDIR}/install"
+LINUX_KERNEL = "linux-4.4"
+
+WORKONSRC = "${MTK_SRC}"
+BB_CFLAGS_ADD = "--sysroot=${STAGING_DIR_HOST} -g"
+BB_LDFLAGS_ADD = "--sysroot=${STAGING_DIR_HOST}"
+
+BB_INCLUDE_ADD = "-I${MTK_SRC}/common/inc \
+ -I${STAGING_DIR_HOST} \
+ -I${STAGING_INCDIR} \
+ "
+
+inherit deploy workonsrc
+
+#Parameters passed to do_compile()
+
+
+EXTRA_OEMAKE = "CROSS=${TARGET_PREFIX} \
+ PREFIX=${SP_PREFIX} \
+ PACKAGE_ARCH=${PACKAGE_ARCH} \
+ BB_INCLUDE_ADD=${BB_INCLUDE_ADD} \
+ BB_LDFLAGS_ADD=${BB_LDFLAGS_ADD} \
+ LINUX_KERNEL=${LINUX_KERNEL}"
+
+FILES_${PN} = "${base_libdir}/*.so\
+ ${base_bindir}\
+ ${base_sbindir}\
+ /mnt\
+ /tmp\
+ /etc\
+ /test"
+
+FILES_${PN}-dev = "${includedir}"
+
+FILES_${PN}-staticdev = "${base_libdir}/*.a"
+
+FILES_${PN}-doc = "/doc"
+
+FILES_${PN}-dbg = "/usr/src/debug \
+ ${base_bindir}/.debug \
+ ${base_libdir}/.debug \
+ ${base_sbindir}/.debug"
+
+#Skip strip check in QA test.
+INSANE_SKIP_${PN} += "already-stripped"
+
+
+do_compile () {
+ unset LDFLAGS
+ if test "${PACKAGE_ARCH}" = "cortexa7hf-vfp-vfpv4-neon" || test "${PACKAGE_ARCH}" = "cortexa7hf-neon-vfpv4"; then
+ oe_runmake all ROOT=${STAGING_DIR_HOST} CFLAGS="${BB_CFLAGS_ADD} -mhard-float"
+ else
+ oe_runmake all ROOT=${STAGING_DIR_HOST} CFLAGS="${BB_CFLAGS_ADD}"
+ fi
+}
+
+do_install () {
+ oe_runmake install ROOT=${D}
+
+ if [ -d "${D}/include" ]; then
+ install -d ${D}${includedir}
+ cp -af ${D}/include/* ${D}${includedir}
+ rm -rf ${D}/include
+ fi
+}
+inherit systemd
+SYSTEMD_PACKAGES = "${PN}"
+SYSTEMD_SERVICE_${PN} = "keymonitor.service"
+FILES_${PN} += "${systemd_unitdir}/system/keymonitor.service"
+do_install_append(){
+ if ${@bb.utils.contains('DISTRO_FEATURES','systemd','true','false',d)}; then
+ install -d ${D}${systemd_unitdir}/system/
+ install -m 0644 ${B}/lib/systemd/system/keymonitor.service ${D}${systemd_unitdir}/system
+ fi
+}
+addtask bachclean
+do_bachclean () {
+ oe_runmake clean
+}
diff --git a/meta/meta-mediatek/recipes-devtools/wpa2improvementsigma/mtkwpa2improvementsigma.bb b/meta/meta-mediatek/recipes-devtools/wpa2improvementsigma/mtkwpa2improvementsigma.bb
new file mode 100644
index 0000000..8e474e0
--- /dev/null
+++ b/meta/meta-mediatek/recipes-devtools/wpa2improvementsigma/mtkwpa2improvementsigma.bb
@@ -0,0 +1,8 @@
+DESCRIPTION = "Wi-Fi sigma tool for certification"
+LICENSE = "MediaTekProprietary"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=d7810fab7487fb0aad327b76f1be7cd7"
+
+inherit workonsrc
+WORKONSRC = "${TOPDIR}/../src/devtools/wifi-sigma/wpa2-improvement-sigma"
+
+INSANE_SKIP_${PN} += "ldflags"
diff --git a/meta/meta-mediatek/recipes-extended/mtklogger/mtklogger.bb b/meta/meta-mediatek/recipes-extended/mtklogger/mtklogger.bb
new file mode 100644
index 0000000..e7c4cf8
--- /dev/null
+++ b/meta/meta-mediatek/recipes-extended/mtklogger/mtklogger.bb
@@ -0,0 +1,33 @@
+DESCRIPTION = "mtklogger is a tool to collect logs when exception"
+LICENSE = "MediaTekProprietary"
+WORKONSRC = "${TOPDIR}/../src/extended/mtklogger"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=e1696b147d49d491bcb4da1a57173fff"
+
+inherit workonsrc
+inherit pkgconfig
+
+do_compile() {
+ oe_runmake \
+ CFLAGS="${CFLAGS}" \
+ LDFLAGS="${LDFLAGS}"
+}
+
+do_install() {
+ oe_runmake \
+ PREFIX="${prefix}" DESTDIR="${D}" PACKAGE_ARCH="${PACKAGE_ARCH}" install
+}
+
+
+inherit systemd
+SYSTEMD_PACKAGES = "${PN}"
+SYSTEMD_SERVICE_${PN} = "mtklogger.service"
+FILES_${PN} += "${systemd_unitdir}/system/mtklogger.service"
+
+do_install_append() {
+ if ${@bb.utils.contains('DISTRO_FEATURES','systemd','true','false',d)}; then
+ install -d ${D}${systemd_unitdir}/system/
+ install -m 0644 ${B}/lib/systemd/system/mtklogger.service ${D}${systemd_unitdir}/system
+ fi
+}
+
+INSANE_SKIP_${PN} += "already-stripped"
diff --git a/meta/meta-mediatek/recipes-extended/thermal-manager/thermal-manager.bb b/meta/meta-mediatek/recipes-extended/thermal-manager/thermal-manager.bb
new file mode 100644
index 0000000..9d3829c
--- /dev/null
+++ b/meta/meta-mediatek/recipes-extended/thermal-manager/thermal-manager.bb
@@ -0,0 +1,50 @@
+DESCRIPTION = "thermal manager"
+LICENSE = "MediaTekProprietary"
+
+SRC = "${TOPDIR}/../src/apps/aiv-base/thermal-manager"
+
+S = "${WORKDIR}"
+
+inherit workonsrc
+
+WORKONSRC = "${SRC}"
+
+LD_PATH = "${S}/${base_libdir}"
+
+do_compile() {
+ oe_runmake LD_PATH=${LD_PATH}
+}
+
+do_install_append() {
+if ${@bb.utils.contains('DISTRO_FEATURES','systemd','true','false',d)}; then
+ install -d ${D}${systemd_unitdir}/system
+ install -m 755 ${S}/thermal-manager.service ${D}${systemd_unitdir}/system
+fi
+}
+
+do_install() {
+ install -d ${D}${bindir}/
+ install -m 0755 ${S}/thermal_manager ${D}${bindir}/
+ install -d ${D}${libdir}/
+ install -m 0755 ${S}/${base_libdir}/libmtcloader.so ${D}${libdir}/
+ install -d ${D}/etc/.tp
+if [ -f "${TARGET_PLATFORM}/thermal.conf" ]; then
+ install -m 0777 ${S}/${TARGET_PLATFORM}/thermal.conf ${D}/etc/.tp
+else
+ install -m 0777 ${S}/thermal.conf ${D}/etc/.tp
+fi
+}
+
+
+# if systemd service include.
+inherit systemd
+SYSTEMD_PACKAGES = "${PN}"
+SYSTEMD_SERVICE_${PN} = "thermal-manager.service"
+FILES_${PN} += "${systemd_unitdir}/system/thermal-manager.service"
+
+FILES_${PN} += "${libdir} /etc/.tp/thermal.conf"
+FILES_${PN}-dev = ""
+INSANE_SKIP_${PN} += "ldflags"
+
+#DEBUG_BUILD = "1"
+#INHIBIT_PACKAGE_STRIP = "1"
diff --git a/meta/meta-mediatek/recipes-graphics/disppq/disppq.bb b/meta/meta-mediatek/recipes-graphics/disppq/disppq.bb
new file mode 100644
index 0000000..87c4b6e
--- /dev/null
+++ b/meta/meta-mediatek/recipes-graphics/disppq/disppq.bb
@@ -0,0 +1,29 @@
+DESCRIPTION = "MediaTek PQ daemon"
+LICENSE = "MediaTekProprietary"
+
+inherit workonsrc
+WORKONSRC = "${TOPDIR}/../src/graphics/disppq"
+
+DEPENDS = "drm"
+
+inherit pkgconfig
+
+do_configure() {
+ :
+}
+
+do_compile() {
+ oe_runmake \
+ TARGET_PLATFORM="${TARGET_PLATFORM}" \
+ CFLAGS+="${CFLAGS} -I${STAGING_INCDIR}/drm"
+}
+
+do_install() {
+ oe_runmake \
+ PREFIX="${prefix}" PACKAGE_ARCH="${PACKAGE_ARCH}" TARGET_PLATFORM="${TARGET_PLATFORM}" DESTDIR="${D}" LIBDIR="${libdir}" INCDIR="${includedir}" install
+}
+
+FILES_${PN}-dev = ""
+FILES_${PN} += "${includedir} ${libdir} ${bindir} ${sysconfdir}/pq"
+
+
diff --git a/meta/meta-mediatek/recipes-graphics/libaal/libaal.bb b/meta/meta-mediatek/recipes-graphics/libaal/libaal.bb
new file mode 100644
index 0000000..4dcf80e
--- /dev/null
+++ b/meta/meta-mediatek/recipes-graphics/libaal/libaal.bb
@@ -0,0 +1,28 @@
+DESCRIPTION = "MediaTek AAL daemon"
+LICENSE = "MediaTekProprietary"
+
+inherit workonsrc
+WORKONSRC = "${TOPDIR}/../prebuilt/graphics/libaal"
+
+inherit pkgconfig
+
+do_configure() {
+ :
+}
+
+do_compile() {
+ oe_runmake \
+ TARGET_PLATFORM="${TARGET_PLATFORM}" \
+ CFLAGS+="${CFLAGS}"
+}
+
+do_install() {
+ kernel_version=v`echo "${PREFERRED_VERSION_linux-mtk-extension}" | cut -d "%" -f 1`
+ oe_runmake \
+ PREFIX="${prefix}" PACKAGE_ARCH="${PACKAGE_ARCH}" TARGET_PLATFORM="${TARGET_PLATFORM}" kernel_version="${kernel_version}" DESTDIR="${D}" LIBDIR="${libdir}" INCDIR="${includedir}" install
+}
+
+INSANE_SKIP_${PN} += "already-stripped"
+FILES_${PN}-dev = ""
+FILES_${PN} += "${includedir} ${libdir} ${bindir}"
+
diff --git a/meta/meta-mediatek/recipes-graphics/libdrm/files/0001-Sync-drm-headfile-with-the-kernel.patch b/meta/meta-mediatek/recipes-graphics/libdrm/files/0001-Sync-drm-headfile-with-the-kernel.patch
new file mode 100644
index 0000000..b5f22e9
--- /dev/null
+++ b/meta/meta-mediatek/recipes-graphics/libdrm/files/0001-Sync-drm-headfile-with-the-kernel.patch
@@ -0,0 +1,131 @@
+From e379c6a137bba5c40d9a126b71a667b4d7f5697a Mon Sep 17 00:00:00 2001
+From: Daniel Stone <daniels@collabora.com>
+Date: Tue, 4 Apr 2017 21:38:56 +0100
+Subject: [PATCH] Headers: Sync drm{,_mode}.h with the kernel
+
+Generated using make headers_install, based on drm-misc-next commit
+5db06a8a98f515f67446a69c57577c4c363ec65d.
+
+This clarifies the comments around modifiers such that they are
+per-framebuffer rather than per-plane, adds the beginnings of aspect
+ratio mode flags, link status properties, and updates the 'reserved'
+field from vblank events to include the CRTC ID.
+
+v2: Split into separate patch, pull in full kernel changes.
+v3: Undo revert of connector-type enums, since it is not actually
+ harmful.
+
+Signed-off-by: Daniel Stone <daniels@collabora.com>
+Reviewed-by: Emil Velikov <emil.velikov@collabora.com>
+---
+ include/drm/drm.h | 3 ++-
+ include/drm/drm_mode.h | 45 +++++++++++++++++++++++++++++++--------------
+ 2 files changed, 33 insertions(+), 15 deletions(-)
+
+diff --git a/include/drm/drm.h b/include/drm/drm.h
+index f6fd5c2..1e7a4bc 100644
+--- a/include/drm/drm.h
++++ b/include/drm/drm.h
+@@ -641,6 +641,7 @@ struct drm_gem_open {
+ #define DRM_CAP_CURSOR_HEIGHT 0x9
+ #define DRM_CAP_ADDFB2_MODIFIERS 0x10
+ #define DRM_CAP_PAGE_FLIP_TARGET 0x11
++#define DRM_CAP_CRTC_IN_VBLANK_EVENT 0x12
+
+ /** DRM_IOCTL_GET_CAP ioctl argument type */
+ struct drm_get_cap {
+@@ -845,7 +846,7 @@ struct drm_event_vblank {
+ __u32 tv_sec;
+ __u32 tv_usec;
+ __u32 sequence;
+- __u32 reserved;
++ __u32 crtc_id; /* 0 on older kernels that do not support this */
+ };
+
+ /* typedef area */
+diff --git a/include/drm/drm_mode.h b/include/drm/drm_mode.h
+index df0e350..70571af 100644
+--- a/include/drm/drm_mode.h
++++ b/include/drm/drm_mode.h
+@@ -47,7 +47,15 @@ extern "C" {
+ #define DRM_MODE_TYPE_DRIVER (1<<6)
+
+ /* Video mode flags */
+-/* bit compatible with the xorg definitions. */
++/* bit compatible with the xrandr RR_ definitions (bits 0-13)
++ *
++ * ABI warning: Existing userspace really expects
++ * the mode flags to match the xrandr definitions. Any
++ * changes that don't match the xrandr definitions will
++ * likely need a new client cap or some other mechanism
++ * to avoid breaking existing userspace. This includes
++ * allocating new flags in the previously unused bits!
++ */
+ #define DRM_MODE_FLAG_PHSYNC (1<<0)
+ #define DRM_MODE_FLAG_NHSYNC (1<<1)
+ #define DRM_MODE_FLAG_PVSYNC (1<<2)
+@@ -107,6 +115,10 @@ extern "C" {
+ #define DRM_MODE_DIRTY_ON 1
+ #define DRM_MODE_DIRTY_ANNOTATE 2
+
++/* Link Status options */
++#define DRM_MODE_LINK_STATUS_GOOD 0
++#define DRM_MODE_LINK_STATUS_BAD 1
++
+ struct drm_mode_modeinfo {
+ __u32 clock;
+ __u16 hdisplay;
+@@ -220,14 +232,16 @@ struct drm_mode_get_encoder {
+
+ /* This is for connectors with multiple signal types. */
+ /* Try to match DRM_MODE_CONNECTOR_X as closely as possible. */
+-#define DRM_MODE_SUBCONNECTOR_Automatic 0
+-#define DRM_MODE_SUBCONNECTOR_Unknown 0
+-#define DRM_MODE_SUBCONNECTOR_DVID 3
+-#define DRM_MODE_SUBCONNECTOR_DVIA 4
+-#define DRM_MODE_SUBCONNECTOR_Composite 5
+-#define DRM_MODE_SUBCONNECTOR_SVIDEO 6
+-#define DRM_MODE_SUBCONNECTOR_Component 8
+-#define DRM_MODE_SUBCONNECTOR_SCART 9
++enum drm_mode_subconnector {
++ DRM_MODE_SUBCONNECTOR_Automatic = 0,
++ DRM_MODE_SUBCONNECTOR_Unknown = 0,
++ DRM_MODE_SUBCONNECTOR_DVID = 3,
++ DRM_MODE_SUBCONNECTOR_DVIA = 4,
++ DRM_MODE_SUBCONNECTOR_Composite = 5,
++ DRM_MODE_SUBCONNECTOR_SVIDEO = 6,
++ DRM_MODE_SUBCONNECTOR_Component = 8,
++ DRM_MODE_SUBCONNECTOR_SCART = 9,
++};
+
+ #define DRM_MODE_CONNECTOR_Unknown 0
+ #define DRM_MODE_CONNECTOR_VGA 1
+@@ -392,17 +406,20 @@ struct drm_mode_fb_cmd2 {
+ * offsets[1]. Note that offsets[0] will generally
+ * be 0 (but this is not required).
+ *
+- * To accommodate tiled, compressed, etc formats, a per-plane
++ * To accommodate tiled, compressed, etc formats, a
+ * modifier can be specified. The default value of zero
+ * indicates "native" format as specified by the fourcc.
+- * Vendor specific modifier token. This allows, for example,
+- * different tiling/swizzling pattern on different planes.
+- * See discussion above of DRM_FORMAT_MOD_xxx.
++ * Vendor specific modifier token. Note that even though
++ * it looks like we have a modifier per-plane, we in fact
++ * do not. The modifier for each plane must be identical.
++ * Thus all combinations of different data layouts for
++ * multi plane formats must be enumerated as separate
++ * modifiers.
+ */
+ __u32 handles[4];
+ __u32 pitches[4]; /* pitch for each plane */
+ __u32 offsets[4]; /* offset of each plane */
+- __u64 modifier[4]; /* ie, tiling, compressed (per plane) */
++ __u64 modifier[4]; /* ie, tiling, compress */
+ };
+
+ #define DRM_MODE_FB_DIRTY_ANNOTATE_COPY 0x01
+--
+libgit2 0.26.0
+
diff --git a/meta/meta-mediatek/recipes-graphics/libdrm/files/0002-Add-CRTC-ID-to-vblank-event.patch b/meta/meta-mediatek/recipes-graphics/libdrm/files/0002-Add-CRTC-ID-to-vblank-event.patch
new file mode 100644
index 0000000..1519dc2
--- /dev/null
+++ b/meta/meta-mediatek/recipes-graphics/libdrm/files/0002-Add-CRTC-ID-to-vblank-event.patch
@@ -0,0 +1,100 @@
+From 890d43a6a8d091211b82dd432af5e0a38472ffa6 Mon Sep 17 00:00:00 2001
+From: Ander Conselvan de Oliveira <ander.conselvan.de.oliveira@intel.com>
+Date: Mon, 17 Aug 2015 16:21:24 +0300
+Subject: [PATCH] Add CRTC ID to vblank event
+
+When using the atomic API, one request can span multiple CRTCs, however
+one event is generated per CRTC. As we cannot disambiguate the CRTC with
+user data (since we only have one piece of user data to pass in), newer
+kernels can include the CRTC ID in the page flip event.
+
+Add a new vfunc to dispatch vblank events carrying a CRTC ID to clients
+who negotiate a higher interface version.
+
+[daniels: Rebased, include new cap, call page_flip_handler if it is set
+ but page_flip_handler2 isn't even on newer contexts, write a
+ commit message.]
+
+v2: Split into separate commit.
+
+Signed-off-by: Ander Conselvan de Oliveira <ander.conselvan.de.oliveira@intel.com>
+Signed-off-by: Daniel Stone <daniels@collabora.com>
+Reviewed-by: Maarten Lankhorst <maarten.lankhorst@intel.com>
+---
+ xf86drm.h | 9 ++++++++-
+ xf86drmMode.c | 24 ++++++++++++++++--------
+ 2 files changed, 24 insertions(+), 9 deletions(-)
+
+diff --git a/xf86drm.h b/xf86drm.h
+index 0d92701..d75ca8c 100644
+--- a/xf86drm.h
++++ b/xf86drm.h
+@@ -728,7 +728,7 @@ extern void drmMsg(const char *format, ...) DRM_PRINTFLIKE(1, 2);
+ extern int drmSetMaster(int fd);
+ extern int drmDropMaster(int fd);
+
+-#define DRM_EVENT_CONTEXT_VERSION 2
++#define DRM_EVENT_CONTEXT_VERSION 3
+
+ typedef struct _drmEventContext {
+
+@@ -748,6 +748,13 @@ typedef struct _drmEventContext {
+ unsigned int tv_usec,
+ void *user_data);
+
++ void (*page_flip_handler2)(int fd,
++ unsigned int sequence,
++ unsigned int tv_sec,
++ unsigned int tv_usec,
++ unsigned int crtc_id,
++ void *user_data);
++
+ } drmEventContext, *drmEventContextPtr;
+
+ extern int drmHandleEvent(int fd, drmEventContextPtr evctx);
+diff --git a/xf86drmMode.c b/xf86drmMode.c
+index 0266bc1..d3bc20e 100644
+--- a/xf86drmMode.c
++++ b/xf86drmMode.c
+@@ -889,6 +889,7 @@ int drmHandleEvent(int fd, drmEventContextPtr evctx)
+ int len, i;
+ struct drm_event *e;
+ struct drm_event_vblank *vblank;
++ void *user_data;
+
+ /* The DRM read semantics guarantees that we always get only
+ * complete events. */
+@@ -915,15 +916,22 @@ int drmHandleEvent(int fd, drmEventContextPtr evctx)
+ U642VOID (vblank->user_data));
+ break;
+ case DRM_EVENT_FLIP_COMPLETE:
+- if (evctx->version < 2 ||
+- evctx->page_flip_handler == NULL)
+- break;
+ vblank = (struct drm_event_vblank *) e;
+- evctx->page_flip_handler(fd,
+- vblank->sequence,
+- vblank->tv_sec,
+- vblank->tv_usec,
+- U642VOID (vblank->user_data));
++ user_data = U642VOID (vblank->user_data);
++
++ if (evctx->version >= 3 && evctx->page_flip_handler2)
++ evctx->page_flip_handler2(fd,
++ vblank->sequence,
++ vblank->tv_sec,
++ vblank->tv_usec,
++ vblank->crtc_id,
++ user_data);
++ else if (evctx->version >= 2 && evctx->page_flip_handler)
++ evctx->page_flip_handler(fd,
++ vblank->sequence,
++ vblank->tv_sec,
++ vblank->tv_usec,
++ user_data);
+ break;
+ default:
+ break;
+--
+libgit2 0.26.0
+
diff --git a/meta/meta-mediatek/recipes-graphics/mali/mali_bifrost-r15p0.bb b/meta/meta-mediatek/recipes-graphics/mali/mali_bifrost-r15p0.bb
new file mode 100644
index 0000000..1cef0ad
--- /dev/null
+++ b/meta/meta-mediatek/recipes-graphics/mali/mali_bifrost-r15p0.bb
@@ -0,0 +1,131 @@
+DESCRIPTION = "Mali-Bifrost GPU"
+LICENSE = "ARM"
+LIC_FILES_CHKSUM = "file://${TOPDIR}/../prebuilt/graphics/mali/bifrost/NOTICE;md5=ccf6b0dfe7f9ae14e0d41187f7b05ef9"
+inherit workonsrc
+WORKONSRC = "${TOPDIR}/../src/graphics/mali/bifrost/r15p0"
+
+DEPENDS = "libdrm wayland python-scons-native"
+PROVIDES = "virtual/egl virtual/libgles1 virtual/libgles2 virtual/libgl virtual/mesa"
+inherit pkgconfig
+
+do_compile() {
+ oe_runmake LIB_ROOT=${STAGING_LIBDIR} SYSROOT=${STAGING_DIR_TARGET} REC_SYSROOT=${WORKDIR}/recipe-sysroot STAGING_BINDIR=${STAGING_BINDIR_NATIVE} CROSS=${TARGET_PREFIX}
+}
+
+do_install() {
+ oe_runmake mali_ver="${mali_ver}" \
+ PREFIX="${prefix}" DESTDIR="${D}" SRCDIR="${B}" PACKAGE_ARCH="${PACKAGE_ARCH}" LIB=${libdir} install
+}
+
+do_install_append() {
+ ln -nfs libmali.so ${D}${libdir}/libmali.so.0
+
+ ln -nfs libmali.so ${D}${libdir}/libEGL.so
+ ln -nfs libmali.so ${D}${libdir}/libEGL.so.1
+ ln -nfs libmali.so ${D}${libdir}/libEGL.so.1.0.0
+ ln -nfs libmali.so ${D}${libdir}/libEGL.so.1.4.0
+
+ ln -nfs libmali.so ${D}${libdir}/libgbm.so
+ ln -nfs libmali.so ${D}${libdir}/libgbm.so.1
+ ln -nfs libmali.so ${D}${libdir}/libgbm.so.1.0.0
+
+ ln -nfs libmali.so ${D}${libdir}/libGLESv1_CM.so
+ ln -nfs libmali.so ${D}${libdir}/libGLESv1_CM.so.1
+ ln -nfs libmali.so ${D}${libdir}/libGLESv1_CM.so.1.1
+ ln -nfs libmali.so ${D}${libdir}/libGLESv1_CM.so.1.1.0
+
+ ln -nfs libmali.so ${D}${libdir}/libGLESv2.so
+ ln -nfs libmali.so ${D}${libdir}/libGLESv2.so.2
+ ln -nfs libmali.so ${D}${libdir}/libGLESv2.so.2.0.0
+
+ ln -nfs libmali.so ${D}${libdir}/libwayland-egl.so
+ ln -nfs libmali.so ${D}${libdir}/libwayland-egl.so.1
+ ln -nfs libmali.so ${D}${libdir}/libwayland-egl.so.1.0.0
+
+ ln -nfs libOpenCL.so ${D}${libdir}/libOpenCL.so.1
+ ln -nfs libOpenCL.so ${D}${libdir}/libOpenCL.so.1.1
+ ln -nfs libOpenCL.so ${D}${libdir}/libOpenCL.so.1.1.0
+}
+
+RDEPENDS_${PN}-dev = ""
+
+FILES_${PN} = "${libdir}/libmali.so* \
+ ${libdir}/libGLESv2.so* \
+ ${libdir}/libEGL.so* \
+ ${libdir}/libgbm.so* \
+ ${libdir}/libGLESv1_CM.so* \
+ ${libdir}/libwayland-egl.so* \
+ ${libdir}/libOpenCL.so* \
+ ${bindir}/mali_base_jd_test \
+ ${bindir}/mali_gles_integration_suite \
+ ${bindir}/mali_egl_integration_tests \
+ ${bindir}/mali_cl_unit \
+ ${bindir}/mali_cl_simple_example_cpp \
+ ${bindir}/mali_cl_simple_example \
+ ${bindir}/mali_cl_svm_opencl_example \
+ ${bindir}/mali_cl_peak_flops_example \
+ ${bindir}/mali_cl_import_memory_example "
+
+FILES_${PN}-dev = "${libdir}/libMali.la \
+ ${libdir}/libEGL.la \
+ ${libdir}/libOpenCL.la \
+ ${libdir}/pkgconfig/egl.pc \
+ ${includedir}/EGL/eglextchromium.h \
+ ${includedir}/EGL/eglext.h \
+ ${includedir}/EGL/egl.h \
+ ${includedir}/EGL/eglmesaext.h \
+ ${includedir}/EGL/eglplatform.h \
+ ${libdir}/libgbm.la \
+ ${libdir}/pkgconfig/gbm.pc \
+ ${includedir}/gbm.h \
+ ${libdir}/libGLESv2.la \
+ ${libdir}/pkgconfig/glesv2.pc \
+ ${includedir}/GLES2/gl2ext.h \
+ ${includedir}/GLES2/gl2.h \
+ ${includedir}/GLES2/gl2platform.h \
+ ${includedir}/GLES3/gl3.h \
+ ${includedir}/GLES3/gl3platform.h \
+ ${includedir}/GLES3/gl31.h \
+ ${includedir}/GLES3/gl32.h \
+ ${includedir}/GLES3/gl3ext.h \
+ ${libdir}/libGLESv1_CM.la \
+ ${libdir}/pkgconfig/glesv1_cm.pc \
+ ${includedir}/GLES/egl.h \
+ ${includedir}/GLES/glext.h \
+ ${includedir}/GLES/gl.h \
+ ${includedir}/GLES/glplatform.h \
+ ${libdir}/libwayland-egl.la \
+ ${libdir}/pkgconfig/wayland-egl.pc \
+ ${includedir}/KHR/khrplatform.h \
+ ${includedir}/CL/cl.h \
+ ${includedir}/CL/cl.hpp \
+ ${includedir}/CL/cl_d3d10.h \
+ ${includedir}/CL/cl_d3d11.h \
+ ${includedir}/CL/cl_dx9_media_sharing.h \
+ ${includedir}/CL/cl_egl.h \
+ ${includedir}/CL/cl_ext.h \
+ ${includedir}/CL/cl_gl.h \
+ ${includedir}/CL/cl_gl_ext.h \
+ ${includedir}/CL/cl_platform.h \
+ ${includedir}/CL/opencl.h \
+ ${includedir}/CL_2_0/cl.h \
+ ${includedir}/CL_2_0/cl.hpp \
+ ${includedir}/CL_2_0/cl_d3d10.h \
+ ${includedir}/CL_2_0/cl_d3d11.h \
+ ${includedir}/CL_2_0/cl_dx9_media_sharing.h \
+ ${includedir}/CL_2_0/cl_egl.h \
+ ${includedir}/CL_2_0/cl_ext.h \
+ ${includedir}/CL_2_0/cl_gl.h \
+ ${includedir}/CL_2_0/cl_gl_ext.h \
+ ${includedir}/CL_2_0/cl_platform.h \
+ ${includedir}/CL_2_0/opencl.h \
+ ${includedir}/CL_HPP/cl.hpp \
+ ${includedir}/CL_HPP/cl2.hpp"
+
+INHIBIT_PACKAGE_DEBUG_SPLIT = "1"
+INSANE_SKIP_${PN} += "dev-so"
+INSANE_SKIP_${PN} += "dev-deps"
+INSANE_SKIP_${PN} += "already-stripped"
+INSANE_SKIP_${PN} += "ldflags"
+INSANE_SKIP_${PN}-dev += "ldflags"
+
diff --git a/meta/meta-mediatek/recipes-graphics/mali/mali_bifrost-r16p0.bb b/meta/meta-mediatek/recipes-graphics/mali/mali_bifrost-r16p0.bb
new file mode 100644
index 0000000..8bb9757
--- /dev/null
+++ b/meta/meta-mediatek/recipes-graphics/mali/mali_bifrost-r16p0.bb
@@ -0,0 +1,131 @@
+DESCRIPTION = "Mali-Bifrost GPU"
+LICENSE = "ARM"
+LIC_FILES_CHKSUM = "file://${TOPDIR}/../prebuilt/graphics/mali/bifrost/NOTICE;md5=ccf6b0dfe7f9ae14e0d41187f7b05ef9"
+inherit workonsrc
+WORKONSRC = "${TOPDIR}/../src/graphics/mali/bifrost/r16p0"
+
+DEPENDS = "libdrm wayland python-scons-native"
+PROVIDES = "virtual/egl virtual/libgles1 virtual/libgles2 virtual/libgl virtual/mesa"
+inherit pkgconfig
+
+do_compile() {
+ oe_runmake LIB_ROOT=${STAGING_LIBDIR} SYSROOT=${STAGING_DIR_TARGET} REC_SYSROOT=${WORKDIR}/recipe-sysroot STAGING_BINDIR=${STAGING_BINDIR_NATIVE} CROSS=${TARGET_PREFIX}
+}
+
+do_install() {
+ oe_runmake mali_ver="${mali_ver}" \
+ PREFIX="${prefix}" DESTDIR="${D}" SRCDIR="${B}" PACKAGE_ARCH="${PACKAGE_ARCH}" LIB=${libdir} install
+}
+
+do_install_append() {
+ ln -nfs libmali.so ${D}${libdir}/libmali.so.0
+
+ ln -nfs libmali.so ${D}${libdir}/libEGL.so
+ ln -nfs libmali.so ${D}${libdir}/libEGL.so.1
+ ln -nfs libmali.so ${D}${libdir}/libEGL.so.1.0.0
+ ln -nfs libmali.so ${D}${libdir}/libEGL.so.1.4.0
+
+ ln -nfs libmali.so ${D}${libdir}/libgbm.so
+ ln -nfs libmali.so ${D}${libdir}/libgbm.so.1
+ ln -nfs libmali.so ${D}${libdir}/libgbm.so.1.0.0
+
+ ln -nfs libmali.so ${D}${libdir}/libGLESv1_CM.so
+ ln -nfs libmali.so ${D}${libdir}/libGLESv1_CM.so.1
+ ln -nfs libmali.so ${D}${libdir}/libGLESv1_CM.so.1.1
+ ln -nfs libmali.so ${D}${libdir}/libGLESv1_CM.so.1.1.0
+
+ ln -nfs libmali.so ${D}${libdir}/libGLESv2.so
+ ln -nfs libmali.so ${D}${libdir}/libGLESv2.so.2
+ ln -nfs libmali.so ${D}${libdir}/libGLESv2.so.2.0.0
+
+ ln -nfs libmali.so ${D}${libdir}/libwayland-egl.so
+ ln -nfs libmali.so ${D}${libdir}/libwayland-egl.so.1
+ ln -nfs libmali.so ${D}${libdir}/libwayland-egl.so.1.0.0
+
+ ln -nfs libOpenCL.so ${D}${libdir}/libOpenCL.so.1
+ ln -nfs libOpenCL.so ${D}${libdir}/libOpenCL.so.1.1
+ ln -nfs libOpenCL.so ${D}${libdir}/libOpenCL.so.1.1.0
+}
+
+RDEPENDS_${PN}-dev = ""
+
+FILES_${PN} = "${libdir}/libmali.so* \
+ ${libdir}/libGLESv2.so* \
+ ${libdir}/libEGL.so* \
+ ${libdir}/libgbm.so* \
+ ${libdir}/libGLESv1_CM.so* \
+ ${libdir}/libwayland-egl.so* \
+ ${libdir}/libOpenCL.so* \
+ ${bindir}/mali_base_jd_test \
+ ${bindir}/mali_gles_integration_suite \
+ ${bindir}/mali_egl_integration_tests \
+ ${bindir}/mali_cl_unit \
+ ${bindir}/mali_cl_simple_example_cpp \
+ ${bindir}/mali_cl_simple_example \
+ ${bindir}/mali_cl_svm_opencl_example \
+ ${bindir}/mali_cl_peak_flops_example \
+ ${bindir}/mali_cl_import_memory_example "
+
+FILES_${PN}-dev = "${libdir}/libMali.la \
+ ${libdir}/libEGL.la \
+ ${libdir}/libOpenCL.la \
+ ${libdir}/pkgconfig/egl.pc \
+ ${includedir}/EGL/eglextchromium.h \
+ ${includedir}/EGL/eglext.h \
+ ${includedir}/EGL/egl.h \
+ ${includedir}/EGL/eglmesaext.h \
+ ${includedir}/EGL/eglplatform.h \
+ ${libdir}/libgbm.la \
+ ${libdir}/pkgconfig/gbm.pc \
+ ${includedir}/gbm.h \
+ ${libdir}/libGLESv2.la \
+ ${libdir}/pkgconfig/glesv2.pc \
+ ${includedir}/GLES2/gl2ext.h \
+ ${includedir}/GLES2/gl2.h \
+ ${includedir}/GLES2/gl2platform.h \
+ ${includedir}/GLES3/gl3.h \
+ ${includedir}/GLES3/gl3platform.h \
+ ${includedir}/GLES3/gl31.h \
+ ${includedir}/GLES3/gl32.h \
+ ${includedir}/GLES3/gl3ext.h \
+ ${libdir}/libGLESv1_CM.la \
+ ${libdir}/pkgconfig/glesv1_cm.pc \
+ ${includedir}/GLES/egl.h \
+ ${includedir}/GLES/glext.h \
+ ${includedir}/GLES/gl.h \
+ ${includedir}/GLES/glplatform.h \
+ ${libdir}/libwayland-egl.la \
+ ${libdir}/pkgconfig/wayland-egl.pc \
+ ${includedir}/KHR/khrplatform.h \
+ ${includedir}/CL/cl.h \
+ ${includedir}/CL/cl.hpp \
+ ${includedir}/CL/cl_d3d10.h \
+ ${includedir}/CL/cl_d3d11.h \
+ ${includedir}/CL/cl_dx9_media_sharing.h \
+ ${includedir}/CL/cl_egl.h \
+ ${includedir}/CL/cl_ext.h \
+ ${includedir}/CL/cl_gl.h \
+ ${includedir}/CL/cl_gl_ext.h \
+ ${includedir}/CL/cl_platform.h \
+ ${includedir}/CL/opencl.h \
+ ${includedir}/CL_2_0/cl.h \
+ ${includedir}/CL_2_0/cl.hpp \
+ ${includedir}/CL_2_0/cl_d3d10.h \
+ ${includedir}/CL_2_0/cl_d3d11.h \
+ ${includedir}/CL_2_0/cl_dx9_media_sharing.h \
+ ${includedir}/CL_2_0/cl_egl.h \
+ ${includedir}/CL_2_0/cl_ext.h \
+ ${includedir}/CL_2_0/cl_gl.h \
+ ${includedir}/CL_2_0/cl_gl_ext.h \
+ ${includedir}/CL_2_0/cl_platform.h \
+ ${includedir}/CL_2_0/opencl.h \
+ ${includedir}/CL_HPP/cl.hpp \
+ ${includedir}/CL_HPP/cl2.hpp"
+
+INHIBIT_PACKAGE_DEBUG_SPLIT = "1"
+INSANE_SKIP_${PN} += "dev-so"
+INSANE_SKIP_${PN} += "dev-deps"
+INSANE_SKIP_${PN} += "already-stripped"
+INSANE_SKIP_${PN} += "ldflags"
+INSANE_SKIP_${PN}-dev += "ldflags"
+
diff --git a/meta/meta-mediatek/recipes-graphics/mali/mali_bifrost-r19p0.bb b/meta/meta-mediatek/recipes-graphics/mali/mali_bifrost-r19p0.bb
new file mode 100644
index 0000000..91475eb
--- /dev/null
+++ b/meta/meta-mediatek/recipes-graphics/mali/mali_bifrost-r19p0.bb
@@ -0,0 +1,138 @@
+DESCRIPTION = "Mali-Bifrost GPU"
+LICENSE = "ARM"
+LIC_FILES_CHKSUM = "file://${TOPDIR}/../prebuilt/graphics/mali/bifrost/NOTICE;md5=ccf6b0dfe7f9ae14e0d41187f7b05ef9"
+inherit workonsrc
+WORKONSRC = "${TOPDIR}/../src/graphics/mali/bifrost/r19p0"
+
+DEPENDS = "libdrm wayland python-scons-native"
+PROVIDES = "virtual/libgbm virtual/egl virtual/libgles1 virtual/libgles2 virtual/libgl virtual/mesa"
+inherit pkgconfig
+
+do_compile() {
+ oe_runmake LIB_ROOT=${STAGING_LIBDIR} SYSROOT=${STAGING_DIR_TARGET} REC_SYSROOT=${WORKDIR}/recipe-sysroot STAGING_BINDIR=${STAGING_BINDIR_NATIVE} CROSS=${TARGET_PREFIX}
+}
+
+do_install() {
+ oe_runmake mali_ver="${mali_ver}" \
+ PREFIX="${prefix}" DESTDIR="${D}" SRCDIR="${B}" PACKAGE_ARCH="${PACKAGE_ARCH}" LIB=${libdir} install
+}
+
+do_install_append() {
+ ln -nfs libmali.so ${D}${libdir}/libmali.so.0
+ ln -nfs libmali.so ${D}${libdir}/libmali.so.1
+ ln -nfs libmali.so ${D}${libdir}/libmali.so.1.0.0
+
+ ln -nfs libmali.so ${D}${libdir}/libEGL.so
+ ln -nfs libmali.so ${D}${libdir}/libEGL.so.1
+ ln -nfs libmali.so ${D}${libdir}/libEGL.so.1.0.0
+ ln -nfs libmali.so ${D}${libdir}/libEGL.so.1.4.0
+
+ ln -nfs libmali.so ${D}${libdir}/libgbm.so
+ ln -nfs libmali.so ${D}${libdir}/libgbm.so.1
+ ln -nfs libmali.so ${D}${libdir}/libgbm.so.1.0.0
+
+ ln -nfs libmali.so ${D}${libdir}/libGLESv1_CM.so
+ ln -nfs libmali.so ${D}${libdir}/libGLESv1_CM.so.1
+ ln -nfs libmali.so ${D}${libdir}/libGLESv1_CM.so.1.1
+ ln -nfs libmali.so ${D}${libdir}/libGLESv1_CM.so.1.1.0
+
+ ln -nfs libmali.so ${D}${libdir}/libGLESv2.so
+ ln -nfs libmali.so ${D}${libdir}/libGLESv2.so.2
+ ln -nfs libmali.so ${D}${libdir}/libGLESv2.so.2.0.0
+
+ ln -nfs libmali.so ${D}${libdir}/libwayland-egl.so
+ ln -nfs libmali.so ${D}${libdir}/libwayland-egl.so.1
+ ln -nfs libmali.so ${D}${libdir}/libwayland-egl.so.1.0.0
+
+ ln -nfs libmali.so ${D}${libdir}/libOpenCL.so
+ ln -nfs libmali.so ${D}${libdir}/libOpenCL.so.1
+ ln -nfs libmali.so ${D}${libdir}/libOpenCL.so.1.1
+ ln -nfs libmali.so ${D}${libdir}/libOpenCL.so.1.1.0
+}
+
+RDEPENDS_${PN}-dev = ""
+
+FILES_${PN} = "${libdir}/libmali.so* \
+ ${libdir}/libGLESv2.so* \
+ ${libdir}/libEGL.so* \
+ ${libdir}/libgbm.so* \
+ ${libdir}/libGLESv1_CM.so* \
+ ${libdir}/libOpenCL.so* \
+ ${libdir}/libwayland-egl.so* \
+ ${bindir}/mali_base_jd_test \
+ ${bindir}/mali_gles_integration_suite \
+ ${bindir}/mali_egl_integration_tests \
+ ${bindir}/mali_cl_unit \
+ ${bindir}/mali_cl_simple_example_cpp \
+ ${bindir}/mali_cl_simple_example \
+ ${bindir}/mali_cl_svm_opencl_example \
+ ${bindir}/mali_cl_peak_flops_example \
+ ${bindir}/mali_cl_import_memory_example "
+
+FILES_${PN}-dev = "${libdir}/libMali.la \
+ ${libdir}/libEGL.la \
+ ${libdir}/libOpenCL.la \
+ ${libdir}/pkgconfig/egl.pc \
+ ${includedir}/EGL/eglextchromium.h \
+ ${includedir}/EGL/eglext.h \
+ ${includedir}/EGL/egl.h \
+ ${includedir}/EGL/eglmesaext.h \
+ ${includedir}/EGL/eglplatform.h \
+ ${libdir}/libgbm.la \
+ ${libdir}/pkgconfig/gbm.pc \
+ ${includedir}/gbm.h \
+ ${libdir}/libGLESv2.la \
+ ${libdir}/pkgconfig/glesv2.pc \
+ ${includedir}/GLES2/gl2ext.h \
+ ${includedir}/GLES2/gl2.h \
+ ${includedir}/GLES2/gl2platform.h \
+ ${includedir}/GLES3/gl3.h \
+ ${includedir}/GLES3/gl3platform.h \
+ ${includedir}/GLES3/gl31.h \
+ ${includedir}/GLES3/gl32.h \
+ ${includedir}/GLES3/gl3ext.h \
+ ${libdir}/libGLESv1_CM.la \
+ ${libdir}/pkgconfig/glesv1_cm.pc \
+ ${includedir}/GLES/egl.h \
+ ${includedir}/GLES/glext.h \
+ ${includedir}/GLES/gl.h \
+ ${includedir}/GLES/glplatform.h \
+ ${libdir}/libwayland-egl.la \
+ ${libdir}/pkgconfig/wayland-egl.pc \
+ ${includedir}/KHR/khrplatform.h \
+ ${includedir}/CL/cl.h \
+ ${includedir}/CL/cl.hpp \
+ ${includedir}/CL/cl_d3d10.h \
+ ${includedir}/CL/cl_d3d11.h \
+ ${includedir}/CL/cl_dx9_media_sharing.h \
+ ${includedir}/CL/cl_egl.h \
+ ${includedir}/CL/cl_ext.h \
+ ${includedir}/CL/cl_gl.h \
+ ${includedir}/CL/cl_gl_ext.h \
+ ${includedir}/CL/cl_platform.h \
+ ${includedir}/CL/cl_va_api_media_sharing_intel.h \
+ ${includedir}/CL/cl_ext_intel.h \
+ ${includedir}/CL/cl_version.h \
+ ${includedir}/CL/cl_dx9_media_sharing_intel.h \
+ ${includedir}/CL/opencl.h \
+ ${includedir}/CL_2_0/cl.h \
+ ${includedir}/CL_2_0/cl.hpp \
+ ${includedir}/CL_2_0/cl_d3d10.h \
+ ${includedir}/CL_2_0/cl_d3d11.h \
+ ${includedir}/CL_2_0/cl_dx9_media_sharing.h \
+ ${includedir}/CL_2_0/cl_egl.h \
+ ${includedir}/CL_2_0/cl_ext.h \
+ ${includedir}/CL_2_0/cl_gl.h \
+ ${includedir}/CL_2_0/cl_gl_ext.h \
+ ${includedir}/CL_2_0/cl_platform.h \
+ ${includedir}/CL_2_0/opencl.h \
+ ${includedir}/CL_HPP/cl.hpp \
+ ${includedir}/CL_HPP/cl2.hpp"
+
+INHIBIT_PACKAGE_DEBUG_SPLIT = "1"
+INSANE_SKIP_${PN} += "dev-so"
+INSANE_SKIP_${PN} += "dev-deps"
+INSANE_SKIP_${PN} += "already-stripped"
+INSANE_SKIP_${PN} += "ldflags"
+INSANE_SKIP_${PN}-dev += "ldflags"
+
diff --git a/meta/meta-mediatek/recipes-graphics/mali/mali_bifrost-r20p0.bb b/meta/meta-mediatek/recipes-graphics/mali/mali_bifrost-r20p0.bb
new file mode 100644
index 0000000..a9c56e3
--- /dev/null
+++ b/meta/meta-mediatek/recipes-graphics/mali/mali_bifrost-r20p0.bb
@@ -0,0 +1,138 @@
+DESCRIPTION = "Mali-Bifrost GPU"
+LICENSE = "ARM"
+LIC_FILES_CHKSUM = "file://${TOPDIR}/../prebuilt/graphics/mali/bifrost/NOTICE;md5=ccf6b0dfe7f9ae14e0d41187f7b05ef9"
+inherit workonsrc
+WORKONSRC = "${TOPDIR}/../src/graphics/mali/bifrost/r20p0"
+
+DEPENDS = "libdrm wayland python-native python-scons-native"
+PROVIDES = "virtual/libgbm virtual/egl virtual/libgles1 virtual/libgles2 virtual/libgl virtual/mesa"
+inherit pkgconfig
+
+do_compile() {
+ oe_runmake LIB_ROOT=${STAGING_LIBDIR} SYSROOT=${STAGING_DIR_TARGET} REC_SYSROOT=${WORKDIR}/recipe-sysroot STAGING_BINDIR=${STAGING_BINDIR_NATIVE} CROSS=${TARGET_PREFIX} TOPDIR=${TOPDIR}
+}
+
+do_install() {
+ oe_runmake mali_ver="${mali_ver}" \
+ PREFIX="${prefix}" DESTDIR="${D}" SRCDIR="${B}" PACKAGE_ARCH="${PACKAGE_ARCH}" LIB=${libdir} install
+}
+
+do_install_append() {
+ ln -nfs libmali.so ${D}${libdir}/libmali.so.0
+ ln -nfs libmali.so ${D}${libdir}/libmali.so.1
+ ln -nfs libmali.so ${D}${libdir}/libmali.so.1.0.0
+
+ ln -nfs libmali.so ${D}${libdir}/libEGL.so
+ ln -nfs libmali.so ${D}${libdir}/libEGL.so.1
+ ln -nfs libmali.so ${D}${libdir}/libEGL.so.1.0.0
+ ln -nfs libmali.so ${D}${libdir}/libEGL.so.1.4.0
+
+ ln -nfs libmali.so ${D}${libdir}/libgbm.so
+ ln -nfs libmali.so ${D}${libdir}/libgbm.so.1
+ ln -nfs libmali.so ${D}${libdir}/libgbm.so.1.0.0
+
+ ln -nfs libmali.so ${D}${libdir}/libGLESv1_CM.so
+ ln -nfs libmali.so ${D}${libdir}/libGLESv1_CM.so.1
+ ln -nfs libmali.so ${D}${libdir}/libGLESv1_CM.so.1.1
+ ln -nfs libmali.so ${D}${libdir}/libGLESv1_CM.so.1.1.0
+
+ ln -nfs libmali.so ${D}${libdir}/libGLESv2.so
+ ln -nfs libmali.so ${D}${libdir}/libGLESv2.so.2
+ ln -nfs libmali.so ${D}${libdir}/libGLESv2.so.2.0.0
+
+ ln -nfs libmali.so ${D}${libdir}/libwayland-egl.so
+ ln -nfs libmali.so ${D}${libdir}/libwayland-egl.so.1
+ ln -nfs libmali.so ${D}${libdir}/libwayland-egl.so.1.0.0
+
+ ln -nfs libmali.so ${D}${libdir}/libOpenCL.so
+ ln -nfs libmali.so ${D}${libdir}/libOpenCL.so.1
+ ln -nfs libmali.so ${D}${libdir}/libOpenCL.so.1.1
+ ln -nfs libmali.so ${D}${libdir}/libOpenCL.so.1.1.0
+}
+
+RDEPENDS_${PN}-dev = ""
+
+FILES_${PN} = "${libdir}/libmali.so* \
+ ${libdir}/libGLESv2.so* \
+ ${libdir}/libEGL.so* \
+ ${libdir}/libgbm.so* \
+ ${libdir}/libGLESv1_CM.so* \
+ ${libdir}/libOpenCL.so* \
+ ${libdir}/libwayland-egl.so* \
+ ${bindir}/mali_base_jd_test \
+ ${bindir}/mali_gles_integration_suite \
+ ${bindir}/mali_egl_integration_tests \
+ ${bindir}/mali_cl_unit \
+ ${bindir}/mali_cl_simple_example_cpp \
+ ${bindir}/mali_cl_simple_example \
+ ${bindir}/mali_cl_svm_opencl_example \
+ ${bindir}/mali_cl_peak_flops_example \
+ ${bindir}/mali_cl_import_memory_example "
+
+FILES_${PN}-dev = "${libdir}/libMali.la \
+ ${libdir}/libEGL.la \
+ ${libdir}/libOpenCL.la \
+ ${libdir}/pkgconfig/egl.pc \
+ ${includedir}/EGL/eglextchromium.h \
+ ${includedir}/EGL/eglext.h \
+ ${includedir}/EGL/egl.h \
+ ${includedir}/EGL/eglmesaext.h \
+ ${includedir}/EGL/eglplatform.h \
+ ${libdir}/libgbm.la \
+ ${libdir}/pkgconfig/gbm.pc \
+ ${includedir}/gbm.h \
+ ${libdir}/libGLESv2.la \
+ ${libdir}/pkgconfig/glesv2.pc \
+ ${includedir}/GLES2/gl2ext.h \
+ ${includedir}/GLES2/gl2.h \
+ ${includedir}/GLES2/gl2platform.h \
+ ${includedir}/GLES3/gl3.h \
+ ${includedir}/GLES3/gl3platform.h \
+ ${includedir}/GLES3/gl31.h \
+ ${includedir}/GLES3/gl32.h \
+ ${includedir}/GLES3/gl3ext.h \
+ ${libdir}/libGLESv1_CM.la \
+ ${libdir}/pkgconfig/glesv1_cm.pc \
+ ${includedir}/GLES/egl.h \
+ ${includedir}/GLES/glext.h \
+ ${includedir}/GLES/gl.h \
+ ${includedir}/GLES/glplatform.h \
+ ${libdir}/libwayland-egl.la \
+ ${libdir}/pkgconfig/wayland-egl.pc \
+ ${includedir}/KHR/khrplatform.h \
+ ${includedir}/CL/cl.h \
+ ${includedir}/CL/cl.hpp \
+ ${includedir}/CL/cl_d3d10.h \
+ ${includedir}/CL/cl_d3d11.h \
+ ${includedir}/CL/cl_dx9_media_sharing.h \
+ ${includedir}/CL/cl_egl.h \
+ ${includedir}/CL/cl_ext.h \
+ ${includedir}/CL/cl_gl.h \
+ ${includedir}/CL/cl_gl_ext.h \
+ ${includedir}/CL/cl_platform.h \
+ ${includedir}/CL/cl_va_api_media_sharing_intel.h \
+ ${includedir}/CL/cl_ext_intel.h \
+ ${includedir}/CL/cl_version.h \
+ ${includedir}/CL/cl_dx9_media_sharing_intel.h \
+ ${includedir}/CL/opencl.h \
+ ${includedir}/CL_2_0/cl.h \
+ ${includedir}/CL_2_0/cl.hpp \
+ ${includedir}/CL_2_0/cl_d3d10.h \
+ ${includedir}/CL_2_0/cl_d3d11.h \
+ ${includedir}/CL_2_0/cl_dx9_media_sharing.h \
+ ${includedir}/CL_2_0/cl_egl.h \
+ ${includedir}/CL_2_0/cl_ext.h \
+ ${includedir}/CL_2_0/cl_gl.h \
+ ${includedir}/CL_2_0/cl_gl_ext.h \
+ ${includedir}/CL_2_0/cl_platform.h \
+ ${includedir}/CL_2_0/opencl.h \
+ ${includedir}/CL_HPP/cl.hpp \
+ ${includedir}/CL_HPP/cl2.hpp"
+
+INHIBIT_PACKAGE_DEBUG_SPLIT = "1"
+INSANE_SKIP_${PN} += "dev-so"
+INSANE_SKIP_${PN} += "dev-deps"
+INSANE_SKIP_${PN} += "already-stripped"
+INSANE_SKIP_${PN} += "ldflags"
+INSANE_SKIP_${PN}-dev += "ldflags"
+
diff --git a/meta/meta-mediatek/recipes-graphics/mali/mali_midgard-r13p0.bb b/meta/meta-mediatek/recipes-graphics/mali/mali_midgard-r13p0.bb
new file mode 100644
index 0000000..ee6ce42
--- /dev/null
+++ b/meta/meta-mediatek/recipes-graphics/mali/mali_midgard-r13p0.bb
@@ -0,0 +1,125 @@
+DESCRIPTION = "Mali-880 GPU"
+LICENSE = "ARM"
+LIC_FILES_CHKSUM = "file://${TOPDIR}/../prebuilt/graphics/mali/midgard/NOTICE;md5=4610adf2da9e96774ed48a3e3e0fb18f"
+#inherit externalsrc
+#EXTERNALSRC = "${TOPDIR}/../prebuilt/graphics/mali/midgard"
+#EXTERNALSRC_BUILD = "${TOPDIR}/../prebuilt/graphics/mali/midgard"
+inherit workonsrc
+WORKONSRC = "${TOPDIR}/../src/graphics/mali/midgard/r13p0"
+
+DEPENDS = "libdrm wayland python-scons-native"
+PROVIDES = "virtual/egl virtual/libgles1 virtual/libgles2 virtual/libgl virtual/mesa"
+inherit pkgconfig
+
+do_compile() {
+ oe_runmake LIB_ROOT=${STAGING_LIBDIR} SYSROOT=${STAGING_DIR_TARGET} REC_SYSROOT=${WORKDIR}/recipe-sysroot STAGING_BINDIR=${STAGING_BINDIR_NATIVE} DONWLOADS=${TOPDIR}/../downloads CROSSCOMPILER_PREFIX=${TARGET_PREFIX}
+}
+
+do_install() {
+ oe_runmake mali_ver="${mali_ver}" \
+ PREFIX="${prefix}" DESTDIR="${D}" SRCDIR="${B}" PACKAGE_ARCH="${PACKAGE_ARCH}" LIB=${libdir} install
+}
+
+do_install_append() {
+ ln -nfs libmali.so ${D}${libdir}/libmali.so.0
+
+ ln -nfs libmali.so ${D}${libdir}/libEGL.so
+ ln -nfs libmali.so ${D}${libdir}/libEGL.so.1
+ ln -nfs libmali.so ${D}${libdir}/libEGL.so.1.0.0
+ ln -nfs libmali.so ${D}${libdir}/libEGL.so.1.4
+
+ ln -nfs libmali.so ${D}${libdir}/libgbm.so
+ ln -nfs libmali.so ${D}${libdir}/libgbm.so.1
+ ln -nfs libmali.so ${D}${libdir}/libgbm.so.1.0.0
+
+ ln -nfs libmali.so ${D}${libdir}/libGLESv1_CM.so
+ ln -nfs libmali.so ${D}${libdir}/libGLESv1_CM.so.1
+ ln -nfs libmali.so ${D}${libdir}/libGLESv1_CM.so.1.1
+ ln -nfs libmali.so ${D}${libdir}/libGLESv1_CM.so.1.1.0
+
+ ln -nfs libmali.so ${D}${libdir}/libGLESv2.so
+ ln -nfs libmali.so ${D}${libdir}/libGLESv2.so.2
+ ln -nfs libmali.so ${D}${libdir}/libGLESv2.so.2.0.0
+
+ ln -nfs libmali.so ${D}${libdir}/libwayland-egl.so
+ ln -nfs libmali.so ${D}${libdir}/libwayland-egl.so.1
+ ln -nfs libmali.so ${D}${libdir}/libwayland-egl.so.1.0.0
+
+ ln -nfs libOpenCL.so ${D}${libdir}/libOpenCL.so.1
+ ln -nfs libOpenCL.so ${D}${libdir}/libOpenCL.so.1.1
+ ln -nfs libOpenCL.so ${D}${libdir}/libOpenCL.so.1.1.0
+}
+
+RDEPENDS_${PN}-dev = ""
+
+FILES_${PN} = "${libdir}/libmali.so* \
+ ${libdir}/libGLESv2.so* \
+ ${libdir}/libEGL.so* \
+ ${libdir}/libgbm.so* \
+ ${libdir}/libGLESv1_CM.so* \
+ ${libdir}/libwayland-egl.so* \
+ ${libdir}/libOpenCL.so* \
+ ${bindir}/mali_cl_unit \
+ ${bindir}/mali_cl_simple_opencl_example "
+
+FILES_${PN}-dev = "${libdir}/libMali.la \
+ ${libdir}/libEGL.la \
+ ${libdir}/libOpenCL.la \
+ ${libdir}/pkgconfig/egl.pc \
+ ${includedir}/EGL/eglextchromium.h \
+ ${includedir}/EGL/eglext.h \
+ ${includedir}/EGL/egl.h \
+ ${includedir}/EGL/eglmesaext.h \
+ ${includedir}/EGL/eglplatform.h \
+ ${libdir}/libgbm.la \
+ ${libdir}/pkgconfig/gbm.pc \
+ ${includedir}/gbm.h \
+ ${libdir}/libGLESv2.la \
+ ${libdir}/pkgconfig/glesv2.pc \
+ ${includedir}/GLES2/gl2ext.h \
+ ${includedir}/GLES2/gl2.h \
+ ${includedir}/GLES2/gl2platform.h \
+ ${includedir}/GLES3/gl3.h \
+ ${includedir}/GLES3/gl3platform.h \
+ ${includedir}/GLES3/gl31.h \
+ ${includedir}/GLES3/gl32.h \
+ ${includedir}/GLES3/gl3ext.h \
+ ${libdir}/libGLESv1_CM.la \
+ ${libdir}/pkgconfig/glesv1_cm.pc \
+ ${includedir}/GLES/egl.h \
+ ${includedir}/GLES/glext.h \
+ ${includedir}/GLES/gl.h \
+ ${includedir}/GLES/glplatform.h \
+ ${libdir}/libwayland-egl.la \
+ ${libdir}/pkgconfig/wayland-egl.pc \
+ ${includedir}/KHR/khrplatform.h \
+ ${includedir}/CL/cl.h \
+ ${includedir}/CL/cl.hpp \
+ ${includedir}/CL/cl_d3d10.h \
+ ${includedir}/CL/cl_d3d11.h \
+ ${includedir}/CL/cl_dx9_media_sharing.h \
+ ${includedir}/CL/cl_egl.h \
+ ${includedir}/CL/cl_ext.h \
+ ${includedir}/CL/cl_gl.h \
+ ${includedir}/CL/cl_gl_ext.h \
+ ${includedir}/CL/cl_platform.h \
+ ${includedir}/CL/opencl.h \
+ ${includedir}/CL_2_0/cl.h \
+ ${includedir}/CL_2_0/cl.hpp \
+ ${includedir}/CL_2_0/cl_d3d10.h \
+ ${includedir}/CL_2_0/cl_d3d11.h \
+ ${includedir}/CL_2_0/cl_dx9_media_sharing.h \
+ ${includedir}/CL_2_0/cl_egl.h \
+ ${includedir}/CL_2_0/cl_ext.h \
+ ${includedir}/CL_2_0/cl_gl.h \
+ ${includedir}/CL_2_0/cl_gl_ext.h \
+ ${includedir}/CL_2_0/cl_platform.h \
+ ${includedir}/CL_2_0/opencl.h \
+ ${includedir}/CL_HPP/cl.hpp \
+ ${includedir}/CL_HPP/cl2.hpp"
+
+INHIBIT_PACKAGE_DEBUG_SPLIT = "1"
+INSANE_SKIP_${PN} += "dev-so"
+INSANE_SKIP_${PN} += "dev-deps"
+INSANE_SKIP_${PN} += "already-stripped"
+
diff --git a/meta/meta-mediatek/recipes-graphics/mali/mali_midgard-r20p0.bb b/meta/meta-mediatek/recipes-graphics/mali/mali_midgard-r20p0.bb
new file mode 100644
index 0000000..9b4afa1
--- /dev/null
+++ b/meta/meta-mediatek/recipes-graphics/mali/mali_midgard-r20p0.bb
@@ -0,0 +1,127 @@
+DESCRIPTION = "Mali-880 GPU"
+LICENSE = "ARM"
+LIC_FILES_CHKSUM = "file://${TOPDIR}/../prebuilt/graphics/mali/midgard/NOTICE;md5=4610adf2da9e96774ed48a3e3e0fb18f"
+#inherit externalsrc
+#EXTERNALSRC = "${TOPDIR}/../prebuilt/graphics/mali/midgard"
+#EXTERNALSRC_BUILD = "${TOPDIR}/../prebuilt/graphics/mali/midgard"
+inherit workonsrc
+WORKONSRC = "${TOPDIR}/../src/graphics/mali/midgard/r20p0"
+
+DEPENDS = "libdrm wayland python-scons-native"
+PROVIDES = "virtual/egl virtual/libgles1 virtual/libgles2 virtual/libgl virtual/mesa"
+inherit pkgconfig
+
+do_compile() {
+ oe_runmake LIB_ROOT=${STAGING_LIBDIR} SYSROOT=${STAGING_DIR_TARGET} REC_SYSROOT=${WORKDIR}/recipe-sysroot STAGING_BINDIR=${STAGING_BINDIR_NATIVE} DONWLOADS=${TOPDIR}/../downloads CROSS=${TARGET_PREFIX}
+}
+
+do_install() {
+ oe_runmake mali_ver="${mali_ver}" \
+ PREFIX="${prefix}" DESTDIR="${D}" SRCDIR="${B}" PACKAGE_ARCH="${PACKAGE_ARCH}" LIB=${libdir} install
+}
+
+do_install_append() {
+ ln -nfs libmali.so ${D}${libdir}/libmali.so.0
+
+ ln -nfs libmali.so ${D}${libdir}/libEGL.so
+ ln -nfs libmali.so ${D}${libdir}/libEGL.so.1
+ ln -nfs libmali.so ${D}${libdir}/libEGL.so.1.0.0
+ ln -nfs libmali.so ${D}${libdir}/libEGL.so.1.4
+
+ ln -nfs libmali.so ${D}${libdir}/libgbm.so
+ ln -nfs libmali.so ${D}${libdir}/libgbm.so.1
+ ln -nfs libmali.so ${D}${libdir}/libgbm.so.1.0.0
+
+ ln -nfs libmali.so ${D}${libdir}/libGLESv1_CM.so
+ ln -nfs libmali.so ${D}${libdir}/libGLESv1_CM.so.1
+ ln -nfs libmali.so ${D}${libdir}/libGLESv1_CM.so.1.1
+ ln -nfs libmali.so ${D}${libdir}/libGLESv1_CM.so.1.1.0
+
+ ln -nfs libmali.so ${D}${libdir}/libGLESv2.so
+ ln -nfs libmali.so ${D}${libdir}/libGLESv2.so.2
+ ln -nfs libmali.so ${D}${libdir}/libGLESv2.so.2.0.0
+
+ ln -nfs libmali.so ${D}${libdir}/libwayland-egl.so
+ ln -nfs libmali.so ${D}${libdir}/libwayland-egl.so.1
+ ln -nfs libmali.so ${D}${libdir}/libwayland-egl.so.1.0.0
+
+ ln -nfs libOpenCL.so ${D}${libdir}/libOpenCL.so.1
+ ln -nfs libOpenCL.so ${D}${libdir}/libOpenCL.so.1.1
+ ln -nfs libOpenCL.so ${D}${libdir}/libOpenCL.so.1.1.0
+}
+
+RDEPENDS_${PN}-dev = ""
+
+FILES_${PN} = "${libdir}/libmali.so* \
+ ${libdir}/libGLESv2.so* \
+ ${libdir}/libEGL.so* \
+ ${libdir}/libgbm.so* \
+ ${libdir}/libGLESv1_CM.so* \
+ ${libdir}/libwayland-egl.so* \
+ ${libdir}/libOpenCL.so* \
+ ${bindir}/mali_cl_unit \
+ ${bindir}/mali_cl_simple_opencl_example "
+
+FILES_${PN}-dev = "${libdir}/libMali.la \
+ ${libdir}/libEGL.la \
+ ${libdir}/libOpenCL.la \
+ ${libdir}/pkgconfig/egl.pc \
+ ${includedir}/EGL/eglextchromium.h \
+ ${includedir}/EGL/eglext.h \
+ ${includedir}/EGL/egl.h \
+ ${includedir}/EGL/eglmesaext.h \
+ ${includedir}/EGL/eglplatform.h \
+ ${libdir}/libgbm.la \
+ ${libdir}/pkgconfig/gbm.pc \
+ ${includedir}/gbm.h \
+ ${libdir}/libGLESv2.la \
+ ${libdir}/pkgconfig/glesv2.pc \
+ ${includedir}/GLES2/gl2ext.h \
+ ${includedir}/GLES2/gl2.h \
+ ${includedir}/GLES2/gl2platform.h \
+ ${includedir}/GLES3/gl3.h \
+ ${includedir}/GLES3/gl3platform.h \
+ ${includedir}/GLES3/gl31.h \
+ ${includedir}/GLES3/gl32.h \
+ ${includedir}/GLES3/gl3ext.h \
+ ${libdir}/libGLESv1_CM.la \
+ ${libdir}/pkgconfig/glesv1_cm.pc \
+ ${includedir}/GLES/egl.h \
+ ${includedir}/GLES/glext.h \
+ ${includedir}/GLES/gl.h \
+ ${includedir}/GLES/glplatform.h \
+ ${libdir}/libwayland-egl.la \
+ ${libdir}/pkgconfig/wayland-egl.pc \
+ ${includedir}/KHR/khrplatform.h \
+ ${includedir}/CL/cl.h \
+ ${includedir}/CL/cl.hpp \
+ ${includedir}/CL/cl_d3d10.h \
+ ${includedir}/CL/cl_d3d11.h \
+ ${includedir}/CL/cl_dx9_media_sharing.h \
+ ${includedir}/CL/cl_egl.h \
+ ${includedir}/CL/cl_ext.h \
+ ${includedir}/CL/cl_gl.h \
+ ${includedir}/CL/cl_gl_ext.h \
+ ${includedir}/CL/cl_platform.h \
+ ${includedir}/CL/opencl.h \
+ ${includedir}/CL_2_0/cl.h \
+ ${includedir}/CL_2_0/cl.hpp \
+ ${includedir}/CL_2_0/cl_d3d10.h \
+ ${includedir}/CL_2_0/cl_d3d11.h \
+ ${includedir}/CL_2_0/cl_dx9_media_sharing.h \
+ ${includedir}/CL_2_0/cl_egl.h \
+ ${includedir}/CL_2_0/cl_ext.h \
+ ${includedir}/CL_2_0/cl_gl.h \
+ ${includedir}/CL_2_0/cl_gl_ext.h \
+ ${includedir}/CL_2_0/cl_platform.h \
+ ${includedir}/CL_2_0/opencl.h \
+ ${includedir}/CL_HPP/cl.hpp \
+ ${includedir}/CL_HPP/cl2.hpp"
+
+INHIBIT_PACKAGE_DEBUG_SPLIT = "1"
+INSANE_SKIP_${PN} += "dev-so"
+INSANE_SKIP_${PN} += "dev-deps"
+INSANE_SKIP_${PN} += "already-stripped"
+INSANE_SKIP_${PN} += "ldflags"
+INSANE_SKIP_${PN}-dev += "ldflags"
+
diff --git a/meta/meta-mediatek/recipes-graphics/mali/mali_midgard-r26p0.bb b/meta/meta-mediatek/recipes-graphics/mali/mali_midgard-r26p0.bb
new file mode 100644
index 0000000..95218c8
--- /dev/null
+++ b/meta/meta-mediatek/recipes-graphics/mali/mali_midgard-r26p0.bb
@@ -0,0 +1,127 @@
+DESCRIPTION = "Mali-880 GPU"
+LICENSE = "ARM"
+LIC_FILES_CHKSUM = "file://${TOPDIR}/../prebuilt/graphics/mali/midgard/NOTICE;md5=4610adf2da9e96774ed48a3e3e0fb18f"
+#inherit externalsrc
+#EXTERNALSRC = "${TOPDIR}/../prebuilt/graphics/mali/midgard"
+#EXTERNALSRC_BUILD = "${TOPDIR}/../prebuilt/graphics/mali/midgard"
+inherit workonsrc
+WORKONSRC = "${TOPDIR}/../src/graphics/mali/midgard/r26p0"
+
+DEPENDS = "libdrm wayland python-scons-native"
+PROVIDES = "virtual/libgbm virtual/egl virtual/libgles1 virtual/libgles2 virtual/libgl virtual/mesa"
+inherit pkgconfig
+
+do_compile() {
+ oe_runmake LIB_ROOT=${STAGING_LIBDIR} SYSROOT=${STAGING_DIR_TARGET} REC_SYSROOT=${WORKDIR}/recipe-sysroot STAGING_BINDIR=${STAGING_BINDIR_NATIVE} DONWLOADS=${TOPDIR}/../downloads CROSS=${TARGET_PREFIX}
+}
+
+do_install() {
+ oe_runmake mali_ver="${mali_ver}" \
+ PREFIX="${prefix}" DESTDIR="${D}" SRCDIR="${B}" PACKAGE_ARCH="${PACKAGE_ARCH}" LIB=${libdir} install
+}
+
+do_install_append() {
+ ln -nfs libmali.so ${D}${libdir}/libmali.so.0
+
+ ln -nfs libmali.so ${D}${libdir}/libEGL.so
+ ln -nfs libmali.so ${D}${libdir}/libEGL.so.1
+ ln -nfs libmali.so ${D}${libdir}/libEGL.so.1.0.0
+ ln -nfs libmali.so ${D}${libdir}/libEGL.so.1.4
+
+ ln -nfs libmali.so ${D}${libdir}/libgbm.so
+ ln -nfs libmali.so ${D}${libdir}/libgbm.so.1
+ ln -nfs libmali.so ${D}${libdir}/libgbm.so.1.0.0
+
+ ln -nfs libmali.so ${D}${libdir}/libGLESv1_CM.so
+ ln -nfs libmali.so ${D}${libdir}/libGLESv1_CM.so.1
+ ln -nfs libmali.so ${D}${libdir}/libGLESv1_CM.so.1.1
+ ln -nfs libmali.so ${D}${libdir}/libGLESv1_CM.so.1.1.0
+
+ ln -nfs libmali.so ${D}${libdir}/libGLESv2.so
+ ln -nfs libmali.so ${D}${libdir}/libGLESv2.so.2
+ ln -nfs libmali.so ${D}${libdir}/libGLESv2.so.2.0.0
+
+ ln -nfs libmali.so ${D}${libdir}/libwayland-egl.so
+ ln -nfs libmali.so ${D}${libdir}/libwayland-egl.so.1
+ ln -nfs libmali.so ${D}${libdir}/libwayland-egl.so.1.0.0
+
+ ln -nfs libOpenCL.so ${D}${libdir}/libOpenCL.so.1
+ ln -nfs libOpenCL.so ${D}${libdir}/libOpenCL.so.1.1
+ ln -nfs libOpenCL.so ${D}${libdir}/libOpenCL.so.1.1.0
+}
+
+RDEPENDS_${PN}-dev = ""
+
+FILES_${PN} = "${libdir}/libmali.so* \
+ ${libdir}/libGLESv2.so* \
+ ${libdir}/libEGL.so* \
+ ${libdir}/libgbm.so* \
+ ${libdir}/libGLESv1_CM.so* \
+ ${libdir}/libwayland-egl.so* \
+ ${libdir}/libOpenCL.so* \
+ ${bindir}/mali_cl_unit \
+ ${bindir}/mali_cl_simple_example "
+
+FILES_${PN}-dev = "${libdir}/libMali.la \
+ ${libdir}/libEGL.la \
+ ${libdir}/libOpenCL.la \
+ ${libdir}/pkgconfig/egl.pc \
+ ${includedir}/EGL/eglextchromium.h \
+ ${includedir}/EGL/eglext.h \
+ ${includedir}/EGL/egl.h \
+ ${includedir}/EGL/eglmesaext.h \
+ ${includedir}/EGL/eglplatform.h \
+ ${libdir}/libgbm.la \
+ ${libdir}/pkgconfig/gbm.pc \
+ ${includedir}/gbm.h \
+ ${libdir}/libGLESv2.la \
+ ${libdir}/pkgconfig/glesv2.pc \
+ ${includedir}/GLES2/gl2ext.h \
+ ${includedir}/GLES2/gl2.h \
+ ${includedir}/GLES2/gl2platform.h \
+ ${includedir}/GLES3/gl3.h \
+ ${includedir}/GLES3/gl3platform.h \
+ ${includedir}/GLES3/gl31.h \
+ ${includedir}/GLES3/gl32.h \
+ ${includedir}/GLES3/gl3ext.h \
+ ${libdir}/libGLESv1_CM.la \
+ ${libdir}/pkgconfig/glesv1_cm.pc \
+ ${includedir}/GLES/egl.h \
+ ${includedir}/GLES/glext.h \
+ ${includedir}/GLES/gl.h \
+ ${includedir}/GLES/glplatform.h \
+ ${libdir}/libwayland-egl.la \
+ ${libdir}/pkgconfig/wayland-egl.pc \
+ ${includedir}/KHR/khrplatform.h \
+ ${includedir}/CL/cl.h \
+ ${includedir}/CL/cl.hpp \
+ ${includedir}/CL/cl_d3d10.h \
+ ${includedir}/CL/cl_d3d11.h \
+ ${includedir}/CL/cl_dx9_media_sharing.h \
+ ${includedir}/CL/cl_egl.h \
+ ${includedir}/CL/cl_ext.h \
+ ${includedir}/CL/cl_gl.h \
+ ${includedir}/CL/cl_gl_ext.h \
+ ${includedir}/CL/cl_platform.h \
+ ${includedir}/CL/opencl.h \
+ ${includedir}/CL_2_0/cl.h \
+ ${includedir}/CL_2_0/cl.hpp \
+ ${includedir}/CL_2_0/cl_d3d10.h \
+ ${includedir}/CL_2_0/cl_d3d11.h \
+ ${includedir}/CL_2_0/cl_dx9_media_sharing.h \
+ ${includedir}/CL_2_0/cl_egl.h \
+ ${includedir}/CL_2_0/cl_ext.h \
+ ${includedir}/CL_2_0/cl_gl.h \
+ ${includedir}/CL_2_0/cl_gl_ext.h \
+ ${includedir}/CL_2_0/cl_platform.h \
+ ${includedir}/CL_2_0/opencl.h \
+ ${includedir}/CL_HPP/cl.hpp \
+ ${includedir}/CL_HPP/cl2.hpp"
+
+INHIBIT_PACKAGE_DEBUG_SPLIT = "1"
+INSANE_SKIP_${PN} += "dev-so"
+INSANE_SKIP_${PN} += "dev-deps"
+INSANE_SKIP_${PN} += "already-stripped"
+INSANE_SKIP_${PN} += "ldflags"
+INSANE_SKIP_${PN}-dev += "ldflags"
+
diff --git a/meta/meta-mediatek/recipes-graphics/mali/mali_midgard-r6p0.bb b/meta/meta-mediatek/recipes-graphics/mali/mali_midgard-r6p0.bb
new file mode 100644
index 0000000..79d655d
--- /dev/null
+++ b/meta/meta-mediatek/recipes-graphics/mali/mali_midgard-r6p0.bb
@@ -0,0 +1,88 @@
+DESCRIPTION = "Mali-450 GPU"
+LICENSE = "ARM"
+LIC_FILES_CHKSUM = "file://NOTICE;md5=4610adf2da9e96774ed48a3e3e0fb18f"
+#inherit externalsrc
+#EXTERNALSRC = "${TOPDIR}/../prebuilt/graphics/mali/midgard"
+#EXTERNALSRC_BUILD = "${TOPDIR}/../prebuilt/graphics/mali/midgard"
+inherit workonsrc
+WORKONSRC = "${TOPDIR}/../src/graphics/mali/midgard"
+
+DEPENDS = "libdrm wayland"
+PROVIDES = "virtual/egl virtual/libgles1 virtual/libgles2 virtual/libgl virtual/mesa"
+inherit pkgconfig
+
+do_compile() {
+ oe_runmake -f Makefile.mediatek
+}
+
+do_install() {
+ oe_runmake -f Makefile.mediatek \
+ PREFIX="${prefix}" DESTDIR="${D}" SRCDIR="${B}" PACKAGE_ARCH="${PACKAGE_ARCH}" install
+}
+
+do_install_append() {
+ ln -nfs libMali.so ${D}${libdir}/libMali.so.1
+
+ ln -nfs libMali.so ${D}${libdir}/libEGL.so
+ ln -nfs libMali.so ${D}${libdir}/libEGL.so.1
+ ln -nfs libMali.so ${D}${libdir}/libEGL.so.1.0.0
+ ln -nfs libMali.so ${D}${libdir}/libEGL.so.1.4
+
+ ln -nfs libMali.so ${D}${libdir}/libgbm.so
+ ln -nfs libMali.so ${D}${libdir}/libgbm.so.1
+ ln -nfs libMali.so ${D}${libdir}/libgbm.so.1.0.0
+
+ ln -nfs libMali.so ${D}${libdir}/libGLESv1_CM.so
+ ln -nfs libMali.so ${D}${libdir}/libGLESv1_CM.so.1
+ ln -nfs libMali.so ${D}${libdir}/libGLESv1_CM.so.1.1
+ ln -nfs libMali.so ${D}${libdir}/libGLESv1_CM.so.1.1.0
+
+ ln -nfs libMali.so ${D}${libdir}/libGLESv2.so
+ ln -nfs libMali.so ${D}${libdir}/libGLESv2.so.2
+ ln -nfs libMali.so ${D}${libdir}/libGLESv2.so.2.0.0
+
+ ln -nfs libMali.so ${D}${libdir}/libwayland-egl.so
+ ln -nfs libMali.so ${D}${libdir}/libwayland-egl.so.1
+ ln -nfs libMali.so ${D}${libdir}/libwayland-egl.so.1.0.0
+}
+
+RDEPENDS_${PN}-dev = ""
+
+FILES_${PN} = "${libdir}/libMali.so* \
+ ${libdir}/libGLESv2.so* \
+ ${libdir}/libEGL.so* \
+ ${libdir}/libgbm.so* \
+ ${libdir}/libGLESv1_CM.so* \
+ ${libdir}/libwayland-egl.so* "
+
+FILES_${PN}-dev = "${libdir}/libMali.la \
+ ${libdir}/libEGL.la \
+ ${libdir}/pkgconfig/egl.pc \
+ ${includedir}/EGL/eglextchromium.h \
+ ${includedir}/EGL/eglext.h \
+ ${includedir}/EGL/egl.h \
+ ${includedir}/EGL/eglmesaext.h \
+ ${includedir}/EGL/eglplatform.h \
+ ${libdir}/libgbm.la \
+ ${libdir}/pkgconfig/gbm.pc \
+ ${includedir}/gbm.h \
+ ${libdir}/libGLESv2.la \
+ ${libdir}/pkgconfig/glesv2.pc \
+ ${includedir}/GLES2/gl2ext.h \
+ ${includedir}/GLES2/gl2.h \
+ ${includedir}/GLES2/gl2platform.h \
+ ${libdir}/libGLESv1_CM.la \
+ ${libdir}/pkgconfig/glesv1_cm.pc \
+ ${includedir}/GLES/egl.h \
+ ${includedir}/GLES/glext.h \
+ ${includedir}/GLES/gl.h \
+ ${includedir}/GLES/glplatform.h \
+ ${libdir}/libwayland-egl.la \
+ ${libdir}/pkgconfig/wayland-egl.pc \
+ ${includedir}/KHR/khrplatform.h"
+
+INHIBIT_PACKAGE_DEBUG_SPLIT = "1"
+INSANE_SKIP_${PN} += "dev-so"
+INSANE_SKIP_${PN} += "dev-deps"
+INSANE_SKIP_${PN} += "already-stripped"
+
diff --git a/meta/meta-mediatek/recipes-graphics/mali/mali_utgard-r6p0.bb b/meta/meta-mediatek/recipes-graphics/mali/mali_utgard-r6p0.bb
new file mode 100644
index 0000000..570f2ef
--- /dev/null
+++ b/meta/meta-mediatek/recipes-graphics/mali/mali_utgard-r6p0.bb
@@ -0,0 +1,2 @@
+mali_ver="r6p0"
+require mali_utgard.inc
\ No newline at end of file
diff --git a/meta/meta-mediatek/recipes-graphics/mali/mali_utgard-r6p2.bb b/meta/meta-mediatek/recipes-graphics/mali/mali_utgard-r6p2.bb
new file mode 100644
index 0000000..234388d
--- /dev/null
+++ b/meta/meta-mediatek/recipes-graphics/mali/mali_utgard-r6p2.bb
@@ -0,0 +1,2 @@
+mali_ver="r6p2"
+require mali_utgard.inc
\ No newline at end of file
diff --git a/meta/meta-mediatek/recipes-graphics/mali/mali_utgard.inc b/meta/meta-mediatek/recipes-graphics/mali/mali_utgard.inc
new file mode 100644
index 0000000..4290471
--- /dev/null
+++ b/meta/meta-mediatek/recipes-graphics/mali/mali_utgard.inc
@@ -0,0 +1,91 @@
+DESCRIPTION = "Mali-450 GPU"
+LICENSE = "ARM"
+LIC_FILES_CHKSUM = "file://NOTICE;md5=4c46d84528c2908a46ac79d54284016d"
+#inherit externalsrc
+#EXTERNALSRC = "${TOPDIR}/../prebuilt/graphics/mali/utgard"
+#EXTERNALSRC_BUILD = "${TOPDIR}/../prebuilt/graphics/mali/utgard"
+inherit workonsrc
+WORKONSRC = "${TOPDIR}/../src/graphics/mali/utgard"
+
+DEPENDS = "libdrm wayland"
+PROVIDES = "virtual/egl virtual/libgles1 virtual/libgles2 virtual/libgl virtual/mesa"
+RPROVIDES_${PN} = "libgles2"
+
+inherit pkgconfig
+
+do_compile() {
+ oe_runmake mali_ver="${mali_ver}" -f Makefile.mediatek
+}
+
+do_install() {
+ oe_runmake mali_ver="${mali_ver}" -f Makefile.mediatek \
+ PREFIX="${prefix}" DESTDIR="${D}" SRCDIR="${B}" PACKAGE_ARCH="${PACKAGE_ARCH}" install
+}
+
+do_install_append() {
+ ln -nfs libMali.so ${D}${libdir}/libMali.so.1
+
+ ln -nfs libMali.so ${D}${libdir}/libEGL.so
+ ln -nfs libMali.so ${D}${libdir}/libEGL.so.1
+ ln -nfs libMali.so ${D}${libdir}/libEGL.so.1.0.0
+ ln -nfs libMali.so ${D}${libdir}/libEGL.so.1.4
+
+ ln -nfs libMali.so ${D}${libdir}/libgbm.so
+ ln -nfs libMali.so ${D}${libdir}/libgbm.so.1
+ ln -nfs libMali.so ${D}${libdir}/libgbm.so.1.0.0
+
+ ln -nfs libMali.so ${D}${libdir}/libGLESv1_CM.so
+ ln -nfs libMali.so ${D}${libdir}/libGLESv1_CM.so.1
+ ln -nfs libMali.so ${D}${libdir}/libGLESv1_CM.so.1.1
+ ln -nfs libMali.so ${D}${libdir}/libGLESv1_CM.so.1.1.0
+
+ ln -nfs libMali.so ${D}${libdir}/libGLESv2.so
+ ln -nfs libMali.so ${D}${libdir}/libGLESv2.so.2
+ ln -nfs libMali.so ${D}${libdir}/libGLESv2.so.2.0.0
+
+ ln -nfs libMali.so ${D}${libdir}/libwayland-egl.so
+ ln -nfs libMali.so ${D}${libdir}/libwayland-egl.so.1
+ ln -nfs libMali.so ${D}${libdir}/libwayland-egl.so.1.0.0
+}
+
+RDEPENDS_${PN}-dev = ""
+
+FILES_${PN} = "${libdir}/libMali.so* \
+ ${libdir}/libGLESv2.so* \
+ ${libdir}/libEGL.so* \
+ ${libdir}/libgbm.so* \
+ ${libdir}/libGLESv1_CM.so* \
+ ${libdir}/libwayland-egl.so* "
+
+FILES_${PN}-dev = "${libdir}/libMali.la \
+ ${libdir}/libEGL.la \
+ ${libdir}/pkgconfig/egl.pc \
+ ${includedir}/EGL/eglextchromium.h \
+ ${includedir}/EGL/eglext.h \
+ ${includedir}/EGL/egl.h \
+ ${includedir}/EGL/eglmesaext.h \
+ ${includedir}/EGL/eglplatform.h \
+ ${libdir}/libgbm.la \
+ ${libdir}/pkgconfig/gbm.pc \
+ ${includedir}/gbm.h \
+ ${libdir}/libGLESv2.la \
+ ${libdir}/pkgconfig/glesv2.pc \
+ ${includedir}/GLES2/gl2ext.h \
+ ${includedir}/GLES2/gl2.h \
+ ${includedir}/GLES2/gl2platform.h \
+ ${includedir}/GLES3/gl3ext.h \
+ ${libdir}/libGLESv1_CM.la \
+ ${libdir}/pkgconfig/glesv1_cm.pc \
+ ${includedir}/GLES/egl.h \
+ ${includedir}/GLES/glext.h \
+ ${includedir}/GLES/gl.h \
+ ${includedir}/GLES/glplatform.h \
+ ${libdir}/libwayland-egl.la \
+ ${libdir}/pkgconfig/wayland-egl.pc \
+ ${includedir}/KHR/khrplatform.h"
+
+INHIBIT_PACKAGE_DEBUG_SPLIT = "1"
+INSANE_SKIP_${PN} += "dev-so"
+INSANE_SKIP_${PN} += "dev-deps"
+INSANE_SKIP_${PN} += "already-stripped"
+
diff --git a/meta/meta-mediatek/recipes-graphics/mesa/mesa_%.bbappend b/meta/meta-mediatek/recipes-graphics/mesa/mesa_%.bbappend
new file mode 100644
index 0000000..8bf893a
--- /dev/null
+++ b/meta/meta-mediatek/recipes-graphics/mesa/mesa_%.bbappend
@@ -0,0 +1,4 @@
+PACKAGECONFIG_remove_mt2701 = "egl gles"
+PROVIDES_remove_mt2701 = "virtual/libgles1 virtual/libgles2 virtual/egl virtual/libgl virtual/mesa"
+PACKAGECONFIG_remove_mt8173p1v2 = "egl gles"
+PROVIDES_remove_mt8173p1v2 = "virtual/libgles1 virtual/libgles2 virtual/egl virtual/libgl virtual/mesa"
diff --git a/meta/meta-mediatek/recipes-graphics/wayland/weston-init.bbappend b/meta/meta-mediatek/recipes-graphics/wayland/weston-init.bbappend
new file mode 100644
index 0000000..f38d928
--- /dev/null
+++ b/meta/meta-mediatek/recipes-graphics/wayland/weston-init.bbappend
@@ -0,0 +1,12 @@
+FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
+
+WESTONSTART ??= "/usr/bin/weston-launch -u root -- --idle-time=4294967 --tty=1"
+WESTONSTOP ??= "/usr/bin/killall -s KILL weston"
+
+do_install_append() {
+ sed -e 's,ExecStart=.*,ExecStart=${WESTONSTART},g' \
+ -e '/ExecStart/a\ExecStop=${WESTONSTOP}' \
+ -e '/EnvironmentFile/d' \
+ -i ${D}${systemd_system_unitdir}/weston.service
+}
+
diff --git a/meta/meta-mediatek/recipes-graphics/wayland/weston/0001-PATCH-1-9-hmi-controller-use-output_w-h-instead-of-c.patch b/meta/meta-mediatek/recipes-graphics/wayland/weston/0001-PATCH-1-9-hmi-controller-use-output_w-h-instead-of-c.patch
new file mode 100644
index 0000000..1a241ee
--- /dev/null
+++ b/meta/meta-mediatek/recipes-graphics/wayland/weston/0001-PATCH-1-9-hmi-controller-use-output_w-h-instead-of-c.patch
@@ -0,0 +1,55 @@
+From c9120f0c15f901f507c0c626b7225f4e93fca700 Mon Sep 17 00:00:00 2001
+From: Qian Hu <Qian.Hu@mediatek.com>
+Date: Tue, 24 Sep 2019 11:21:23 +0800
+Subject: [PATCH 1/8] [[PATCH 1/9] hmi-controller: use output_w/h instead of
+ current_mode_w/h
+
+make use of output->w/h instead of output->current_mode->w/h,
+ output->w/h have involve factor of transform and scale
+
+Signed-off-by: Qian Hu <Qian.Hu@mediatek.com>
+---
+ ivi-shell/hmi-controller.c | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+diff --git a/ivi-shell/hmi-controller.c b/ivi-shell/hmi-controller.c
+index a0e49ba..c4f106d 100644
+--- a/ivi-shell/hmi-controller.c
++++ b/ivi-shell/hmi-controller.c
+@@ -804,8 +804,8 @@ hmi_controller_create(struct weston_compositor *ec)
+ base_layer = MEM_ALLOC(1 * sizeof(struct hmi_controller_layer));
+ base_layer->x = 0;
+ base_layer->y = 0;
+- base_layer->width = output->current_mode->width;
+- base_layer->height = output->current_mode->height;
++ base_layer->width = output->width;
++ base_layer->height = output->height;
+ base_layer->id_layer =
+ hmi_ctrl->hmi_setting->base_layer_id +
+ (i * hmi_ctrl->hmi_setting->base_layer_id_offset);
+@@ -824,8 +824,8 @@ hmi_controller_create(struct weston_compositor *ec)
+ application_layer = MEM_ALLOC(1 * sizeof(struct hmi_controller_layer));
+ application_layer->x = 0;
+ application_layer->y = 0;
+- application_layer->width = output->current_mode->width;
+- application_layer->height = output->current_mode->height - panel_height;
++ application_layer->width = output->width;
++ application_layer->height = output->height - panel_height;
+ application_layer->id_layer =
+ hmi_ctrl->hmi_setting->application_layer_id +
+ (i * hmi_ctrl->hmi_setting->base_layer_id_offset);
+@@ -841,9 +841,9 @@ hmi_controller_create(struct weston_compositor *ec)
+ hmi_ctrl->workspace_background_layer.x = 0;
+ hmi_ctrl->workspace_background_layer.y = 0;
+ hmi_ctrl->workspace_background_layer.width =
+- output->current_mode->width;
++ output->width;
+ hmi_ctrl->workspace_background_layer.height =
+- output->current_mode->height - panel_height;
++ output->height - panel_height;
+
+ hmi_ctrl->workspace_background_layer.id_layer =
+ hmi_ctrl->hmi_setting->workspace_background_layer_id;
+--
+2.6.4
+
diff --git a/meta/meta-mediatek/recipes-graphics/wayland/weston/0001-add-switch_config.patch b/meta/meta-mediatek/recipes-graphics/wayland/weston/0001-add-switch_config.patch
new file mode 100644
index 0000000..3d011d6
--- /dev/null
+++ b/meta/meta-mediatek/recipes-graphics/wayland/weston/0001-add-switch_config.patch
@@ -0,0 +1,31 @@
+From 08f1aa62f0a5faa0dc8aaf082264b77d37f0610d Mon Sep 17 00:00:00 2001
+From: Qian Hu <Qian.Hu@mediatek.com>
+Date: Wed, 25 Sep 2019 19:14:50 +0800
+Subject: [PATCH] add switch_config
+
+Signed-off-by: Qian Hu <Qian.Hu@mediatek.com>
+---
+ compositor/main.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/compositor/main.c b/compositor/main.c
+index 21c501c..64e4e30 100644
+--- a/compositor/main.c
++++ b/compositor/main.c
+@@ -2499,6 +2499,13 @@ int main(int argc, char *argv[])
+ goto out;
+ }
+
++
++ if (config_switch_global_create(wet.compositor) < 0) {
++ weston_log("fatal: failed to config_switch_global_create\n");
++ goto out;
++ }
++
++
+ weston_compositor_flush_heads_changed(wet.compositor);
+ if (wet.init_failed)
+ goto out;
+--
+2.6.4
+
diff --git a/meta/meta-mediatek/recipes-graphics/wayland/weston/0001-hmi-controller-use-output_w-h-instead-of-current_mod.patch b/meta/meta-mediatek/recipes-graphics/wayland/weston/0001-hmi-controller-use-output_w-h-instead-of-current_mod.patch
new file mode 100644
index 0000000..d7f23a3
--- /dev/null
+++ b/meta/meta-mediatek/recipes-graphics/wayland/weston/0001-hmi-controller-use-output_w-h-instead-of-current_mod.patch
@@ -0,0 +1,58 @@
+From 05da7cf21de58425828099100358cddab67d2f6f Mon Sep 17 00:00:00 2001
+From: Jia Rong <jia.rong@mediatek.com>
+Date: Fri, 20 Apr 2018 10:49:48 +0800
+Subject: [PATCH 1/9] hmi-controller: use output_w/h instead of
+ current_mode_w/h
+
+make use of output->w/h instead of output->current_mode->w/h,
+output->w/h have involve factor of transform and scale
+Test: tesk ok
+
+Change-Id: Icd902acef813c1674020cf2af2352388539f9e37
+Signed-off-by: Jia Rong <jia.rong@mediatek.com>
+CR-Id: AUTO00016576
+---
+ ivi-shell/hmi-controller.c | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+diff --git a/ivi-shell/hmi-controller.c b/ivi-shell/hmi-controller.c
+index 7b2f270..e47b499 100644
+--- a/ivi-shell/hmi-controller.c
++++ b/ivi-shell/hmi-controller.c
+@@ -802,8 +802,8 @@ hmi_controller_create(struct weston_compositor *ec)
+ base_layer = MEM_ALLOC(1 * sizeof(struct hmi_controller_layer));
+ base_layer->x = 0;
+ base_layer->y = 0;
+- base_layer->width = output->current_mode->width;
+- base_layer->height = output->current_mode->height;
++ base_layer->width = output->width;
++ base_layer->height = output->height;
+ base_layer->id_layer =
+ hmi_ctrl->hmi_setting->base_layer_id +
+ (i * hmi_ctrl->hmi_setting->base_layer_id_offset);
+@@ -822,8 +822,8 @@ hmi_controller_create(struct weston_compositor *ec)
+ application_layer = MEM_ALLOC(1 * sizeof(struct hmi_controller_layer));
+ application_layer->x = 0;
+ application_layer->y = 0;
+- application_layer->width = output->current_mode->width;
+- application_layer->height = output->current_mode->height - panel_height;
++ application_layer->width = output->width;
++ application_layer->height = output->height - panel_height;
+ application_layer->id_layer =
+ hmi_ctrl->hmi_setting->application_layer_id +
+ (i * hmi_ctrl->hmi_setting->base_layer_id_offset);
+@@ -839,9 +839,9 @@ hmi_controller_create(struct weston_compositor *ec)
+ hmi_ctrl->workspace_background_layer.x = 0;
+ hmi_ctrl->workspace_background_layer.y = 0;
+ hmi_ctrl->workspace_background_layer.width =
+- output->current_mode->width;
++ output->width;
+ hmi_ctrl->workspace_background_layer.height =
+- output->current_mode->height - panel_height;
++ output->height - panel_height;
+
+ hmi_ctrl->workspace_background_layer.id_layer =
+ hmi_ctrl->hmi_setting->workspace_background_layer_id;
+--
+1.9.1
+
diff --git a/meta/meta-mediatek/recipes-graphics/wayland/weston/0002-PATCH-2-9-libinput-fix-issue-for-touch_event-cause-w.patch b/meta/meta-mediatek/recipes-graphics/wayland/weston/0002-PATCH-2-9-libinput-fix-issue-for-touch_event-cause-w.patch
new file mode 100644
index 0000000..cf86044
--- /dev/null
+++ b/meta/meta-mediatek/recipes-graphics/wayland/weston/0002-PATCH-2-9-libinput-fix-issue-for-touch_event-cause-w.patch
@@ -0,0 +1,40 @@
+From 4ba125216b900fc57c63a915fb194c48f4b516c4 Mon Sep 17 00:00:00 2001
+From: Qian Hu <Qian.Hu@mediatek.com>
+Date: Tue, 24 Sep 2019 11:26:20 +0800
+Subject: [PATCH 2/8] [PATCH 2/9] libinput: fix issue for touch_event cause
+ weston crash
+
+1.fix touch_event cause weston crash
+
+Signed-off-by: Qian Hu <Qian.Hu@mediatek.com>
+---
+ libweston/libinput-device.c | 13 +++++++++++++
+ 1 file changed, 13 insertions(+)
+
+diff --git a/libweston/libinput-device.c b/libweston/libinput-device.c
+index e25df14..18a3032 100644
+--- a/libweston/libinput-device.c
++++ b/libweston/libinput-device.c
+@@ -436,6 +436,19 @@ handle_touch_with_coords(struct libinput_device *libinput_device,
+ x = libinput_event_touch_get_x_transformed(touch_event, width);
+ y = libinput_event_touch_get_y_transformed(touch_event, height);
+
++ if (x == 0)
++ x = x + 1;
++
++ if (y == 0)
++ y = y + 1;
++
++ if (x == wl_fixed_from_int(width))
++ x = x - 1;
++
++ if (y == wl_fixed_from_int(height))
++ y = y - 1;
++
++
+ weston_output_transform_coordinate(device->output,
+ x, y, &x, &y);
+
+--
+2.6.4
+
diff --git a/meta/meta-mediatek/recipes-graphics/wayland/weston/0002-libinput-fix-issue-for-touch_event-cause-weston-cras.patch b/meta/meta-mediatek/recipes-graphics/wayland/weston/0002-libinput-fix-issue-for-touch_event-cause-weston-cras.patch
new file mode 100644
index 0000000..85df381
--- /dev/null
+++ b/meta/meta-mediatek/recipes-graphics/wayland/weston/0002-libinput-fix-issue-for-touch_event-cause-weston-cras.patch
@@ -0,0 +1,41 @@
+From 411e213e6e87acf027a18cc4db38a27838352c0f Mon Sep 17 00:00:00 2001
+From: Jia Rong <jia.rong@mediatek.com>
+Date: Fri, 20 Apr 2018 10:51:51 +0800
+Subject: [PATCH 2/9] libinput: fix issue for touch_event cause weston crash
+
+1.fix touch_event cause weston crash
+Test: test ok
+
+Change-Id: I69bd82ef9c46e97392212b32d599c7fbb3fbb3f5
+Signed-off-by: Jia Rong <jia.rong@mediatek.com>
+CR-Id: AUTO00016576
+---
+ libweston/libinput-device.c | 12 ++++++++++++
+ 1 file changed, 12 insertions(+)
+
+diff --git a/libweston/libinput-device.c b/libweston/libinput-device.c
+index f97afcf..031148c 100644
+--- a/libweston/libinput-device.c
++++ b/libweston/libinput-device.c
+@@ -312,6 +312,18 @@ handle_touch_with_coords(struct libinput_device *libinput_device,
+ x = libinput_event_touch_get_x_transformed(touch_event, width);
+ y = libinput_event_touch_get_y_transformed(touch_event, height);
+
++ if (x == 0)
++ x = x + 1;
++
++ if (y == 0)
++ y = y + 1;
++
++ if (x == wl_fixed_from_int(width))
++ x = x - 1;
++
++ if (y == wl_fixed_from_int(height))
++ y = y - 1;
++
+ weston_output_transform_coordinate(device->output,
+ x, y, &x, &y);
+
+--
+1.9.1
+
diff --git a/meta/meta-mediatek/recipes-graphics/wayland/weston/0003-PATCH-3-9-compose-engine-turn-to-pixman-if-gl-init-f.patch b/meta/meta-mediatek/recipes-graphics/wayland/weston/0003-PATCH-3-9-compose-engine-turn-to-pixman-if-gl-init-f.patch
new file mode 100644
index 0000000..13d3edb
--- /dev/null
+++ b/meta/meta-mediatek/recipes-graphics/wayland/weston/0003-PATCH-3-9-compose-engine-turn-to-pixman-if-gl-init-f.patch
@@ -0,0 +1,43 @@
+From 621569253b34788e096adda8132010d0a17d0844 Mon Sep 17 00:00:00 2001
+From: Qian Hu <Qian.Hu@mediatek.com>
+Date: Tue, 24 Sep 2019 11:31:09 +0800
+Subject: [PATCH 3/8] [PATCH 3/9] compose-engine: turn to pixman if gl init
+ fail
+
+if init_gl fail then turn to pixman to compose buffer
+
+Signed-off-by: Qian Hu <Qian.Hu@mediatek.com>
+---
+ libweston/compositor-drm.c | 9 +++++++--
+ 1 file changed, 7 insertions(+), 2 deletions(-)
+
+diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c
+index 3891176..ef38a64 100644
+--- a/libweston/compositor-drm.c
++++ b/libweston/compositor-drm.c
+@@ -3921,6 +3921,7 @@ init_egl(struct drm_backend *b)
+
+ if (drm_backend_create_gl_renderer(b) < 0) {
+ gbm_device_destroy(b->gbm);
++ b->gbm = NULL;
+ return -1;
+ }
+
+@@ -6766,8 +6767,12 @@ drm_backend_create(struct weston_compositor *compositor,
+ }
+ } else {
+ if (init_egl(b) < 0) {
+- weston_log("failed to initialize egl\n");
+- goto err_udev_dev;
++ weston_log("failed to initialize egl, use pixman\n");
++ if (init_pixman(b) < 0) {
++ weston_log("failed to initialize pixman renderer\n");
++ goto err_udev_dev;
++ }
++ b->use_pixman = 1;
+ }
+ }
+
+--
+2.6.4
+
diff --git a/meta/meta-mediatek/recipes-graphics/wayland/weston/0003-compose-engine-turn-to-pixman-if-gl-init-fail.patch b/meta/meta-mediatek/recipes-graphics/wayland/weston/0003-compose-engine-turn-to-pixman-if-gl-init-fail.patch
new file mode 100644
index 0000000..a4bf921
--- /dev/null
+++ b/meta/meta-mediatek/recipes-graphics/wayland/weston/0003-compose-engine-turn-to-pixman-if-gl-init-fail.patch
@@ -0,0 +1,45 @@
+From 46cee2c18276062d45817fd38fedfa737f16f776 Mon Sep 17 00:00:00 2001
+From: Jia Rong <jia.rong@mediatek.com>
+Date: Fri, 20 Apr 2018 11:23:00 +0800
+Subject: [PATCH 3/9] compose-engine: turn to pixman if gl init fail
+
+if init_gl fail then turn to pixman to compose buffer
+Test: test ok
+
+Change-Id: I18979e4d6cc2d12e51bc12e7be581e919b3166e8
+Signed-off-by: Jia Rong <jia.rong@mediatek.com>
+CR-Id: AUTO00016576
+---
+ libweston/compositor-drm.c | 9 +++++++--
+ 1 file changed, 7 insertions(+), 2 deletions(-)
+
+diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c
+index 1d38f05..4a5cd67 100644
+--- a/libweston/compositor-drm.c
++++ b/libweston/compositor-drm.c
+@@ -1642,6 +1642,7 @@ init_egl(struct drm_backend *b)
+
+ if (drm_backend_create_gl_renderer(b) < 0) {
+ gbm_device_destroy(b->gbm);
++ b->gbm = NULL;
+ return -1;
+ }
+
+@@ -3261,8 +3262,12 @@ drm_backend_create(struct weston_compositor *compositor,
+ }
+ } else {
+ if (init_egl(b) < 0) {
+- weston_log("failed to initialize egl\n");
+- goto err_udev_dev;
++ weston_log("failed to initialize egl, use pixman\n");
++ if (init_pixman(b) < 0) {
++ weston_log("failed to initialize pixman renderer\n");
++ goto err_udev_dev;
++ }
++ b->use_pixman = 1;
+ }
+ }
+
+--
+1.9.1
+
diff --git a/meta/meta-mediatek/recipes-graphics/wayland/weston/0004-PATCH-4-9-weston-do-not-check-master-fd-for-DRM-driv.patch b/meta/meta-mediatek/recipes-graphics/wayland/weston/0004-PATCH-4-9-weston-do-not-check-master-fd-for-DRM-driv.patch
new file mode 100644
index 0000000..22093bb
--- /dev/null
+++ b/meta/meta-mediatek/recipes-graphics/wayland/weston/0004-PATCH-4-9-weston-do-not-check-master-fd-for-DRM-driv.patch
@@ -0,0 +1,31 @@
+From 264cd761cc03e2dd85e57a1162db73c4beec0d07 Mon Sep 17 00:00:00 2001
+From: Qian Hu <Qian.Hu@mediatek.com>
+Date: Tue, 24 Sep 2019 11:33:56 +0800
+Subject: [PATCH 4/8] [PATCH 4/9] weston: do not check master fd for DRM driver
+
+give access to other module to use drm.
+
+Signed-off-by: Qian Hu <Qian.Hu@mediatek.com>
+---
+ libweston/launcher-direct.c | 5 -----
+ 1 file changed, 5 deletions(-)
+
+diff --git a/libweston/launcher-direct.c b/libweston/launcher-direct.c
+index e0ce6d6..fe76f51 100644
+--- a/libweston/launcher-direct.c
++++ b/libweston/launcher-direct.c
+@@ -231,11 +231,6 @@ launcher_direct_open(struct weston_launcher *launcher_base, const char *path, in
+
+ if (major(s.st_rdev) == DRM_MAJOR) {
+ launcher->drm_fd = fd;
+- if (!is_drm_master(fd)) {
+- weston_log("drm fd not master\n");
+- close(fd);
+- return -1;
+- }
+ }
+
+ return fd;
+--
+2.6.4
+
diff --git a/meta/meta-mediatek/recipes-graphics/wayland/weston/0004-weston-do-not-check-master-fd-for-DRM-driver.patch b/meta/meta-mediatek/recipes-graphics/wayland/weston/0004-weston-do-not-check-master-fd-for-DRM-driver.patch
new file mode 100644
index 0000000..cf319d6
--- /dev/null
+++ b/meta/meta-mediatek/recipes-graphics/wayland/weston/0004-weston-do-not-check-master-fd-for-DRM-driver.patch
@@ -0,0 +1,34 @@
+From af63d3bb90fac87b823112c5a7aac58848620ab0 Mon Sep 17 00:00:00 2001
+From: Jia Rong <jia.rong@mediatek.com>
+Date: Fri, 20 Apr 2018 13:29:58 +0800
+Subject: [PATCH 4/9] weston: do not check master fd for DRM driver
+
+give access to other module to use drm.
+Test: test ok
+
+Change-Id: I8dff3a2b9d7e21cb8a78fb6c0066a7befea05242
+Signed-off-by: Jia Rong <jia.rong@mediatek.com>
+CR-Id: AUTO00016576
+---
+ libweston/launcher-direct.c | 5 -----
+ 1 file changed, 5 deletions(-)
+
+diff --git a/libweston/launcher-direct.c b/libweston/launcher-direct.c
+index 8f16a69..2cf6c60 100644
+--- a/libweston/launcher-direct.c
++++ b/libweston/launcher-direct.c
+@@ -223,11 +223,6 @@ launcher_direct_open(struct weston_launcher *launcher_base, const char *path, in
+
+ if (major(s.st_rdev) == DRM_MAJOR) {
+ launcher->drm_fd = fd;
+- if (!is_drm_master(fd)) {
+- weston_log("drm fd not master\n");
+- close(fd);
+- return -1;
+- }
+ }
+
+ return fd;
+--
+1.9.1
+
diff --git a/meta/meta-mediatek/recipes-graphics/wayland/weston/0005-PATCH-5-9-weston-install-client-protocol-to-sysroot-.patch b/meta/meta-mediatek/recipes-graphics/wayland/weston/0005-PATCH-5-9-weston-install-client-protocol-to-sysroot-.patch
new file mode 100644
index 0000000..4fd683d
--- /dev/null
+++ b/meta/meta-mediatek/recipes-graphics/wayland/weston/0005-PATCH-5-9-weston-install-client-protocol-to-sysroot-.patch
@@ -0,0 +1,31 @@
+From 21f5f1844e02a50a8b1c2f9ddb39d01b34c92b0a Mon Sep 17 00:00:00 2001
+From: Qian Hu <Qian.Hu@mediatek.com>
+Date: Tue, 24 Sep 2019 11:37:19 +0800
+Subject: [PATCH 5/8] [PATCH 5/9] weston: install client-protocol to sysroot
+ for other
+
+install *-protocol.c and *-client-protocol.h to sysroot.
+
+Signed-off-by: Qian Hu <Qian.Hu@mediatek.com>
+---
+ Makefile.am | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/Makefile.am b/Makefile.am
+index 83bb253..769e103 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -292,7 +292,9 @@ libwestoninclude_HEADERS = \
+ libweston/timeline-object.h \
+ shared/matrix.h \
+ shared/config-parser.h \
+- shared/zalloc.h
++ shared/zalloc.h \
++ protocol/*-protocol.c \
++ protocol/*-client-protocol.h
+
+ libwestoninclude_HEADERS += \
+ libweston-desktop/libweston-desktop.h
+--
+2.6.4
+
diff --git a/meta/meta-mediatek/recipes-graphics/wayland/weston/0005-weston-install-client-protocol-to-sysroot-for-other-.patch b/meta/meta-mediatek/recipes-graphics/wayland/weston/0005-weston-install-client-protocol-to-sysroot-for-other-.patch
new file mode 100644
index 0000000..2503173
--- /dev/null
+++ b/meta/meta-mediatek/recipes-graphics/wayland/weston/0005-weston-install-client-protocol-to-sysroot-for-other-.patch
@@ -0,0 +1,34 @@
+From 5f18c3a9f28fe46b03135c10d389ca0f60fba218 Mon Sep 17 00:00:00 2001
+From: Jia Rong <jia.rong@mediatek.com>
+Date: Fri, 20 Apr 2018 13:34:51 +0800
+Subject: [PATCH 5/9] weston: install client-protocol to sysroot for other
+ modules access
+
+install *-protocol.c and *-client-protocol.h to sysroot.
+Test: test ok
+
+Change-Id: I621931a6eaa66689415dd5c3fa035326a8ee25a0
+Signed-off-by: Jia Rong <jia.rong@mediatek.com>
+CR-Id: AUTO00016576
+---
+ Makefile.am | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/Makefile.am b/Makefile.am
+index 89790d6..e23b03b 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -293,7 +293,9 @@ libwestoninclude_HEADERS = \
+ libweston/timeline-object.h \
+ shared/matrix.h \
+ shared/config-parser.h \
+- shared/zalloc.h
++ shared/zalloc.h \
++ protocol/*-protocol.c \
++ protocol/*-client-protocol.h
+
+ libwestoninclude_HEADERS += \
+ libweston-desktop/libweston-desktop.h
+--
+1.9.1
+
diff --git a/meta/meta-mediatek/recipes-graphics/wayland/weston/0006-PATCH-7-9-weston-screen-shot-add-screen-shot.patch b/meta/meta-mediatek/recipes-graphics/wayland/weston/0006-PATCH-7-9-weston-screen-shot-add-screen-shot.patch
new file mode 100644
index 0000000..19cb8e2
--- /dev/null
+++ b/meta/meta-mediatek/recipes-graphics/wayland/weston/0006-PATCH-7-9-weston-screen-shot-add-screen-shot.patch
@@ -0,0 +1,603 @@
+From 79d48c68d79e7436a045bb875e18f7e8c6829392 Mon Sep 17 00:00:00 2001
+From: Qian Hu <Qian.Hu@mediatek.com>
+Date: Tue, 24 Sep 2019 14:25:47 +0800
+Subject: [PATCH 6/8] [PATCH 7/9] weston-screen-shot: add screen shot
+
+add screen shot
+
+Signed-off-by: Qian Hu <Qian.Hu@mediatek.com>
+---
+ Makefile.am | 26 +++-
+ clients/simple-screenshooter-mtk.c | 259 +++++++++++++++++++++++++++++++++++
+ libweston/compositor.c | 3 +
+ libweston/compositor.h | 3 +
+ libweston/pixel-formats.c | 2 +
+ libweston/weston-screenshooter-mtk.c | 129 +++++++++++++++++
+ protocol/weston-configure-mtk.xml | 67 +++++++++
+ 7 files changed, 486 insertions(+), 3 deletions(-)
+ create mode 100644 clients/simple-screenshooter-mtk.c
+ create mode 100644 libweston/weston-screenshooter-mtk.c
+ create mode 100644 protocol/weston-configure-mtk.xml
+
+diff --git a/Makefile.am b/Makefile.am
+index 769e103..a9e48f8 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -96,6 +96,7 @@ libweston_@LIBWESTON_MAJOR@_la_SOURCES = \
+ libweston/linux-dmabuf.h \
+ libweston/pixel-formats.c \
+ libweston/pixel-formats.h \
++ libweston/weston-screenshooter-mtk.c \
+ shared/helpers.h \
+ shared/matrix.c \
+ shared/matrix.h \
+@@ -169,7 +170,10 @@ nodist_libweston_@LIBWESTON_MAJOR@_la_SOURCES = \
+ protocol/input-timestamps-unstable-v1-protocol.c \
+ protocol/input-timestamps-unstable-v1-server-protocol.h \
+ protocol/weston-touch-calibration-protocol.c \
+- protocol/weston-touch-calibration-server-protocol.h
++ protocol/weston-touch-calibration-server-protocol.h \
++ protocol/pointer-constraints-unstable-v1-server-protocol.h \
++ protocol/weston-configure-mtk-protocol.c \
++ protocol/weston-configure-mtk-server-protocol.h
+
+ BUILT_SOURCES += $(nodist_libweston_@LIBWESTON_MAJOR@_la_SOURCES)
+
+@@ -652,6 +656,19 @@ weston_simple_dmabuf_v4l_CFLAGS = $(AM_CFLAGS) $(SIMPLE_DMABUF_V4L_CLIENT_CFLAGS
+ weston_simple_dmabuf_v4l_LDADD = $(SIMPLE_DMABUF_V4L_CLIENT_LIBS) libshared.la
+ endif
+
++demo_clients += weston-simple-screenshooter-mtk
++weston_simple_screenshooter_mtk_SOURCES = clients/simple-screenshooter-mtk.c
++nodist_weston_simple_screenshooter_mtk_SOURCES = \
++ protocol/xdg-shell-unstable-v6-protocol.c \
++ protocol/xdg-shell-unstable-v6-client-protocol.h \
++ protocol/fullscreen-shell-unstable-v1-protocol.c \
++ protocol/fullscreen-shell-unstable-v1-client-protocol.h \
++ protocol/weston-configure-mtk-protocol.c \
++ protocol/weston-configure-mtk-client-protocol.h
++weston_simple_screenshooter_mtk_CFLAGS = $(AM_CFLAGS) $(CLIENT_CFLAGS)
++weston_simple_screenshooter_mtk_LDADD = $(EGL_LIBS) $(LIBDRM_LIBS) libtoytoolkit.la
++
++
+ noinst_LTLIBRARIES += libtoytoolkit.la
+
+ libtoytoolkit_la_SOURCES = \
+@@ -911,7 +928,9 @@ BUILT_SOURCES += \
+ protocol/tablet-unstable-v2-protocol.c \
+ protocol/tablet-unstable-v2-client-protocol.h \
+ protocol/input-timestamps-unstable-v1-protocol.c \
+- protocol/input-timestamps-unstable-v1-client-protocol.h
++ protocol/input-timestamps-unstable-v1-client-protocol.h \
++ protocol/weston-configure-mtk-protocol.c \
++ protocol/weston-configure-mtk-client-protocol.h
+
+ westondatadir = $(datadir)/weston
+ dist_westondata_DATA = \
+@@ -1564,7 +1583,8 @@ EXTRA_DIST += \
+ protocol/weston-test.xml \
+ protocol/weston-touch-calibration.xml \
+ protocol/ivi-application.xml \
+- protocol/ivi-hmi-controller.xml
++ protocol/ivi-hmi-controller.xml \
++ protocol/weston-configure-mtk.xml
+
+ #
+ # manual test modules in tests subdirectory
+diff --git a/clients/simple-screenshooter-mtk.c b/clients/simple-screenshooter-mtk.c
+new file mode 100644
+index 0000000..cbca18b
+--- /dev/null
++++ b/clients/simple-screenshooter-mtk.c
+@@ -0,0 +1,259 @@
++/*
++ * Copyright © 2008 Kristian Høgsberg
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software"),
++ * to deal in the Software without restriction, including without limitation
++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ * and/or sell copies of the Software, and to permit persons to whom the
++ * Software is furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the next
++ * paragraph) shall be included in all copies or substantial portions of the
++ * Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
++ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++ * DEALINGS IN THE SOFTWARE.
++ */
++
++#include "config.h"
++
++#include <stdint.h>
++#include <errno.h>
++#include <stdlib.h>
++#include <stdio.h>
++#include <string.h>
++#include <fcntl.h>
++#include <unistd.h>
++#include <limits.h>
++#include <sys/param.h>
++#include <sys/mman.h>
++#include <cairo.h>
++
++#include <wayland-client.h>
++#include "weston-configure-mtk-client-protocol.h"
++#include "shared/os-compatibility.h"
++#include "shared/xalloc.h"
++
++/* The screenshooter is a good example of a custom object exposed by
++ * the compositor and serves as a test bed for implementing client
++ * side marshalling outside libwayland.so */
++
++static struct wl_shm *shm;
++static struct weston_screenshooter_mtk *mtk_screenshooter;
++static struct wl_list output_list;
++int min_x, min_y, max_x, max_y;
++int buffer_copy_done;
++
++struct screenshooter_output {
++ struct wl_output *output;
++ struct wl_buffer *buffer;
++ int width, height, offset_x, offset_y;
++ void *data;
++ struct wl_list link;
++};
++
++static void
++display_handle_geometry(void *data,
++ struct wl_output *wl_output,
++ int x,
++ int y,
++ int physical_width,
++ int physical_height,
++ int subpixel,
++ const char *make,
++ const char *model,
++ int transform)
++{
++ struct screenshooter_output *output;
++
++ output = wl_output_get_user_data(wl_output);
++
++ if (wl_output == output->output) {
++ output->offset_x = x;
++ output->offset_y = y;
++ }
++}
++
++static void
++display_handle_mode(void *data,
++ struct wl_output *wl_output,
++ uint32_t flags,
++ int width,
++ int height,
++ int refresh)
++{
++ struct screenshooter_output *output;
++
++ output = wl_output_get_user_data(wl_output);
++
++ if (wl_output == output->output && (flags & WL_OUTPUT_MODE_CURRENT)) {
++ output->width = width;
++ output->height = height;
++ }
++}
++
++static const struct wl_output_listener output_listener = {
++ display_handle_geometry,
++ display_handle_mode
++};
++
++static void
++screenshooter_done(void *data, struct weston_screenshooter_mtk *mtk_screenshooter)
++{
++ fprintf(stderr, "screenshooter_done\n");
++ buffer_copy_done = 1;
++}
++
++static const struct weston_screenshooter_mtk_listener screenshooter_mtk_listener =
++{
++ screenshooter_done
++};
++
++static void
++handle_global(void *data, struct wl_registry *registry,
++ uint32_t name, const char *interface, uint32_t version)
++{
++ static struct screenshooter_output *output;
++
++ if (strcmp(interface, "wl_output") == 0) {
++ output = xmalloc(sizeof *output);
++ output->output = wl_registry_bind(registry, name,
++ &wl_output_interface, 1);
++ wl_list_insert(&output_list, &output->link);
++ wl_output_add_listener(output->output, &output_listener, output);
++ } else if (strcmp(interface, "wl_shm") == 0) {
++ shm = wl_registry_bind(registry, name, &wl_shm_interface, 1);
++ } else if (strcmp(interface, "weston_screenshooter_mtk") == 0) {
++ mtk_screenshooter = wl_registry_bind(registry, name,
++ &weston_screenshooter_mtk_interface,
++ 1);
++ }
++}
++
++static void
++handle_global_remove(void *data, struct wl_registry *registry, uint32_t name)
++{
++ /* XXX: unimplemented */
++}
++
++static const struct wl_registry_listener registry_listener = {
++ handle_global,
++ handle_global_remove
++};
++
++static struct wl_buffer *
++create_shm_buffer(int width, int height, void **data_out)
++{
++ struct wl_shm_pool *pool;
++ struct wl_buffer *buffer;
++ int fd, size, stride;
++ void *data;
++
++ stride = width * 4;
++ size = stride * height;
++
++ fd = os_create_anonymous_file(size);
++ if (fd < 0) {
++ fprintf(stderr, "creating a buffer file for %d B failed: %m\n",
++ size);
++ return NULL;
++ }
++
++ data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
++ if (data == MAP_FAILED) {
++ fprintf(stderr, "mmap failed: %m\n");
++ close(fd);
++ return NULL;
++ }
++
++ pool = wl_shm_create_pool(shm, fd, size);
++ close(fd);
++ buffer = wl_shm_pool_create_buffer(pool, 0, width, height, stride,
++ WL_SHM_FORMAT_XRGB8888);
++ wl_shm_pool_destroy(pool);
++
++ *data_out = data;
++ fprintf(stderr,"create_shm_buffer\n");
++ return buffer;
++}
++
++static void
++usage(int error_code)
++{
++ fprintf(stderr, "Usage: simple-screenshooter-mtk [OPTIONS]\n\n"
++ " -m dump mainscreen\n"
++ " -s dump subscreen\n"
++ " -h This help text! default dump all screens\n\n");
++
++ exit(error_code);
++}
++
++int main(int argc, char *argv[])
++{
++ struct wl_display *display;
++ struct wl_registry *registry;
++ struct screenshooter_output *output;
++ int i, width, height;
++ int mainscreen=0;
++ int subscreen=0;
++ for (i = 1; i < argc; i++) {
++ if (strcmp("-m", argv[i]) == 0)
++ mainscreen = 1;
++ else if (strcmp("-s", argv[i]) == 0)
++ subscreen = 1;
++ else if (strcmp("-h", argv[i]) == 0)
++ usage(EXIT_SUCCESS);
++ else
++ usage(EXIT_SUCCESS);
++ }
++
++ display = wl_display_connect(NULL);
++ if (display == NULL) {
++ fprintf(stderr, "failed to create display: %m\n");
++ return -1;
++ }
++
++ wl_list_init(&output_list);
++ registry = wl_display_get_registry(display);
++ wl_registry_add_listener(registry, ®istry_listener, NULL);
++ wl_display_dispatch(display);
++ wl_display_roundtrip(display);
++ if (mtk_screenshooter == NULL) {
++ fprintf(stderr, "display doesn't support screenshooter\n");
++ return -1;
++ }
++
++ weston_screenshooter_mtk_add_listener(mtk_screenshooter,
++ &screenshooter_mtk_listener,
++ NULL);
++
++ wl_list_for_each_reverse(output, &output_list, link) {
++ if(mainscreen == 1) {
++ output->buffer = create_shm_buffer(1920, 1080, &output->data);
++ weston_screenshooter_mtk_shoot(mtk_screenshooter,output->output,output->buffer);
++ buffer_copy_done = 0;
++ while (!buffer_copy_done)
++ wl_display_roundtrip(display);
++
++ break;
++ }
++ else if(subscreen == 1) {
++ subscreen = 0;
++ }
++ else {
++ output->buffer = create_shm_buffer(1920, 1080, &output->data);
++ weston_screenshooter_mtk_shoot(mtk_screenshooter,output->output,output->buffer);
++ buffer_copy_done = 0;
++ while (!buffer_copy_done)
++ wl_display_roundtrip(display);
++ }
++ }
++ fprintf(stderr,"end!!!!!\n");
++ return 0;
++}
+diff --git a/libweston/compositor.c b/libweston/compositor.c
+index 9deb781..fdf5d25 100644
+--- a/libweston/compositor.c
++++ b/libweston/compositor.c
+@@ -2756,6 +2756,9 @@ weston_output_schedule_repaint(struct weston_output *output)
+ compositor->state == WESTON_COMPOSITOR_OFFSCREEN)
+ return;
+
++ if(output->screenshoot_needed)
++ output->screenshoot_dump = 1;
++
+ if (!output->repaint_needed)
+ TL_POINT("core_repaint_req", TLP_OUTPUT(output), TLP_END);
+
+diff --git a/libweston/compositor.h b/libweston/compositor.h
+index 8b7a102..8736691 100644
+--- a/libweston/compositor.h
++++ b/libweston/compositor.h
+@@ -238,6 +238,9 @@ struct weston_output {
+ REPAINT_AWAITING_COMPLETION, /**< last repaint not yet finished */
+ } repaint_status;
+
++ int screenshoot_needed;
++ int screenshoot_dump;
++
+ /** If repaint_status is REPAINT_SCHEDULED, contains the time the
+ * next repaint should be run */
+ struct timespec next_repaint;
+diff --git a/libweston/pixel-formats.c b/libweston/pixel-formats.c
+index df84a9f..b45db93 100644
+--- a/libweston/pixel-formats.c
++++ b/libweston/pixel-formats.c
+@@ -145,6 +145,8 @@ static const struct pixel_format_info pixel_format_table[] = {
+ },
+ {
+ .format = DRM_FORMAT_RGB888,
++ .depth = 24,
++ .bpp = 24,
+ },
+ {
+ .format = DRM_FORMAT_BGR888,
+diff --git a/libweston/weston-screenshooter-mtk.c b/libweston/weston-screenshooter-mtk.c
+new file mode 100644
+index 0000000..7ad8f97
+--- /dev/null
++++ b/libweston/weston-screenshooter-mtk.c
+@@ -0,0 +1,129 @@
++/*
++ * Copyright © 2008-2011 Kristian Høgsberg
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#include "config.h"
++
++#include <stdlib.h>
++#include <stdio.h>
++#include <string.h>
++#include <linux/input.h>
++#include <fcntl.h>
++#include <unistd.h>
++#include <sys/uio.h>
++
++#include "compositor.h"
++#include "weston-configure-mtk-server-protocol.h"
++#include "shared/helpers.h"
++
++#include "wcap/wcap-decode.h"
++
++struct screenshooter {
++ struct weston_compositor *ec;
++ struct wl_global *global;
++ struct wl_client *client;
++ //struct weston_process process;
++ struct wl_listener destroy_listener;
++};
++
++struct screenshooter_frame_listener {
++ struct wl_listener listener;
++ struct weston_buffer *buffer;
++ weston_screenshooter_done_func_t done;
++ void *data;
++};
++
++static void
++weston_screenshooter_mtk_shoot(struct wl_client *client,
++ struct wl_resource *resource,
++ struct wl_resource *output_resource,
++ struct wl_resource *buffer_resource)
++{
++ struct weston_output *output =
++ wl_resource_get_user_data(output_resource);
++ struct weston_buffer *buffer =
++ weston_buffer_from_resource(buffer_resource);
++ weston_log("weston_screenshooter_mtk_shoot.\n");
++ output->screenshoot_needed = 1;
++ weston_output_schedule_repaint(output);
++ if (buffer == NULL) {
++ wl_resource_post_no_memory(resource);
++ return;
++ }
++
++ weston_screenshooter_mtk_send_done(resource);
++}
++
++static const struct weston_screenshooter_mtk_interface screenshooter_mtk_implementation = {
++ weston_screenshooter_mtk_shoot
++};
++
++static void
++bind_screenshooter_mtk(struct wl_client *client,
++ void *data, uint32_t version, uint32_t id)
++{
++ struct screenshooter *shooter = data;
++ struct wl_resource *resource;
++
++ resource = wl_resource_create(client,
++ &weston_screenshooter_mtk_interface, 1, id);
++
++ if (resource == NULL) {
++ wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
++ "screenshooter failed: permission denied");
++ wl_client_post_no_memory(client);
++ return;
++ }
++
++ wl_resource_set_implementation(resource, &screenshooter_mtk_implementation,
++ data, NULL);
++}
++
++static void
++screenshooter_destroy(struct wl_listener *listener, void *data)
++{
++ struct screenshooter *shooter =
++ container_of(listener, struct screenshooter, destroy_listener);
++
++ wl_global_destroy(shooter->global);
++ free(shooter);
++}
++
++WL_EXPORT void
++screenshooter_mtk_create(struct weston_compositor *ec)
++{
++ struct screenshooter *shooter;
++
++ shooter = malloc(sizeof *shooter);
++ if (shooter == NULL)
++ return;
++
++ shooter->ec = ec;
++ shooter->global = wl_global_create(ec->wl_display,
++ &weston_screenshooter_mtk_interface, 1,
++ shooter, bind_screenshooter_mtk);
++
++ shooter->destroy_listener.notify = screenshooter_destroy;
++ wl_signal_add(&ec->destroy_signal, &shooter->destroy_listener);
++}
+diff --git a/protocol/weston-configure-mtk.xml b/protocol/weston-configure-mtk.xml
+new file mode 100644
+index 0000000..120e904
+--- /dev/null
++++ b/protocol/weston-configure-mtk.xml
+@@ -0,0 +1,67 @@
++<?xml version="1.0" encoding="UTF-8"?>
++<protocol name="weston_configure_mtk">
++
++ <copyright>
++ Copyright (C) 2016 MediaTek
++
++ Permission is hereby granted, free of charge, to any person obtaining a
++ copy of this software and associated documentation files (the "Software"),
++ to deal in the Software without restriction, including without limitation
++ the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ and/or sell copies of the Software, and to permit persons to whom the
++ Software is furnished to do so, subject to the following conditions:
++
++ The above copyright notice and this permission notice (including the next
++ paragraph) shall be included in all copies or substantial portions of the
++ Software.
++
++ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
++ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++ DEALINGS IN THE SOFTWARE.
++ </copyright>
++
++ <interface name="weston_screenshooter_mtk" version="1">
++ <request name="shoot">
++ <arg name="output" type="object" interface="wl_output"/>
++ <arg name="buffer" type="object" interface="wl_buffer"/>
++ </request>
++ <event name="done">
++ </event>
++ </interface>
++
++ <interface name="config_switch_set" version="1">
++ <description summary="app interface for setting configure for the surface"/>
++
++ <request name="sprite_switch">
++ <description summary="setting the surface configure">
++ This set view matched with the surface to show in overlay plane if
++ overlay planes are available.Otherwise, it walk primary plane to
++ render, and then send to drm to show.
++ </description>
++ <arg name="sprite_switch" type="int"/>
++ </request>
++ </interface>
++
++ <interface name="config_switch" version="1">
++ <description summary="create app configure path for setting parameter">
++ This interface is exposed as a global singleton.
++ This interface is implemented by server, it mainly provide channel to allow
++ client to control some properties.
++ </description>
++
++ <request name="connect">
++ <description summary="connect to server for setting parameter">
++ This request gives client way to connect server.In fact, parameters set by
++ app all through wl_surface because this is only way can be transmit by app.
++ </description>
++ <arg name="surface" type="object" interface="wl_surface" allow-null="true"/>
++ <arg name="id" type="new_id" interface="config_switch_set"/>
++ </request>
++ </interface>
++
++</protocol>
++
+--
+2.6.4
+
diff --git a/meta/meta-mediatek/recipes-graphics/wayland/weston/0006-weston-porting-atomic-drm-from-weston4.0.patch b/meta/meta-mediatek/recipes-graphics/wayland/weston/0006-weston-porting-atomic-drm-from-weston4.0.patch
new file mode 100644
index 0000000..e7c0f05
--- /dev/null
+++ b/meta/meta-mediatek/recipes-graphics/wayland/weston/0006-weston-porting-atomic-drm-from-weston4.0.patch
@@ -0,0 +1,6546 @@
+From 6ff0106dc3fc3e9e442d634cb8e5dc0ef792416b Mon Sep 17 00:00:00 2001
+From: Jia Rong <jia.rong@mediatek.com>
+Date: Fri, 20 Apr 2018 20:43:48 +0800
+Subject: [PATCH 6/9] weston: porting atomic drm from weston4.0
+
+porting atomic drm from weston4.0
+Test: build pass
+
+Change-Id: I37829d8a4815117d4b8bac8d2f8d21f666f83104
+Signed-off-by: Jia Rong <jia.rong@mediatek.com>
+CR-Id: AUTO00016576
+---
+ Makefile.am | 2 +
+ libweston/compositor-drm.c | 3922 +++++++++++++++++++++++++++++++--------
+ libweston/compositor-drm.h | 16 +-
+ libweston/compositor-fbdev.c | 5 +-
+ libweston/compositor-headless.c | 3 +-
+ libweston/compositor-rdp.c | 3 +-
+ libweston/compositor-wayland.c | 6 +-
+ libweston/compositor-x11.c | 6 +-
+ libweston/compositor.c | 177 +-
+ libweston/compositor.h | 59 +-
+ libweston/pixel-formats.c | 430 +++++
+ libweston/pixel-formats.h | 194 ++
+ shared/timespec-util.h | 184 ++
+ 13 files changed, 4221 insertions(+), 786 deletions(-)
+ create mode 100644 libweston/pixel-formats.c
+ create mode 100644 libweston/pixel-formats.h
+
+diff --git a/Makefile.am b/Makefile.am
+index e23b03b..238cd2f 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -105,6 +105,8 @@ libweston_@LIBWESTON_MAJOR@_la_SOURCES = \
+ libweston/timeline-object.h \
+ libweston/linux-dmabuf.c \
+ libweston/linux-dmabuf.h \
++ libweston/pixel-formats.c \
++ libweston/pixel-formats.h \
+ shared/helpers.h \
+ shared/matrix.c \
+ shared/matrix.h \
+diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c
+index 4a5cd67..bba22b3 100644
+--- a/libweston/compositor-drm.c
++++ b/libweston/compositor-drm.c
+@@ -54,6 +54,7 @@
+ #include "gl-renderer.h"
+ #include "weston-egl-ext.h"
+ #include "pixman-renderer.h"
++#include "pixel-formats.h"
+ #include "libbacklight.h"
+ #include "libinput-seat.h"
+ #include "launcher-util.h"
+@@ -62,10 +63,16 @@
+ #include "linux-dmabuf.h"
+ #include "linux-dmabuf-unstable-v1-server-protocol.h"
+
++#define HAVE_DRM_ATOMIC
++
+ #ifndef DRM_CAP_TIMESTAMP_MONOTONIC
+ #define DRM_CAP_TIMESTAMP_MONOTONIC 0x6
+ #endif
+
++#ifndef DRM_CLIENT_CAP_UNIVERSAL_PLANES
++#define DRM_CLIENT_CAP_UNIVERSAL_PLANES 2
++#endif
++
+ #ifndef DRM_CAP_CURSOR_WIDTH
+ #define DRM_CAP_CURSOR_WIDTH 0x8
+ #endif
+@@ -78,6 +85,139 @@
+ #define GBM_BO_USE_CURSOR GBM_BO_USE_CURSOR_64X64
+ #endif
+
++/**
++ * Represents the values of an enum-type KMS property
++ */
++struct drm_property_enum_info {
++ const char *name; /**< name as string (static, not freed) */
++ bool valid; /**< true if value is supported; ignore if false */
++ uint64_t value; /**< raw value */
++};
++
++/**
++ * Holds information on a DRM property, including its ID and the enum
++ * values it holds.
++ *
++ * DRM properties are allocated dynamically, and maintained as DRM objects
++ * within the normal object ID space; they thus do not have a stable ID
++ * to refer to. This includes enum values, which must be referred to by
++ * integer values, but these are not stable.
++ *
++ * drm_property_info allows a cache to be maintained where Weston can use
++ * enum values internally to refer to properties, with the mapping to DRM
++ * ID values being maintained internally.
++ */
++struct drm_property_info {
++ const char *name; /**< name as string (static, not freed) */
++ uint32_t prop_id; /**< KMS property object ID */
++ unsigned int num_enum_values; /**< number of enum values */
++ struct drm_property_enum_info *enum_values; /**< array of enum values */
++};
++
++/**
++ * List of properties attached to DRM planes
++ */
++enum wdrm_plane_property {
++ WDRM_PLANE_TYPE = 0,
++ WDRM_PLANE_SRC_X,
++ WDRM_PLANE_SRC_Y,
++ WDRM_PLANE_SRC_W,
++ WDRM_PLANE_SRC_H,
++ WDRM_PLANE_CRTC_X,
++ WDRM_PLANE_CRTC_Y,
++ WDRM_PLANE_CRTC_W,
++ WDRM_PLANE_CRTC_H,
++ WDRM_PLANE_FB_ID,
++ WDRM_PLANE_CRTC_ID,
++ WDRM_PLANE__COUNT
++};
++
++/**
++ * Possible values for the WDRM_PLANE_TYPE property.
++ */
++enum wdrm_plane_type {
++ WDRM_PLANE_TYPE_PRIMARY = 0,
++ WDRM_PLANE_TYPE_CURSOR,
++ WDRM_PLANE_TYPE_OVERLAY,
++ WDRM_PLANE_TYPE__COUNT
++};
++
++static struct drm_property_enum_info plane_type_enums[] = {
++ [WDRM_PLANE_TYPE_PRIMARY] = {
++ .name = "Primary",
++ },
++ [WDRM_PLANE_TYPE_OVERLAY] = {
++ .name = "Overlay",
++ },
++ [WDRM_PLANE_TYPE_CURSOR] = {
++ .name = "Cursor",
++ },
++};
++
++static const struct drm_property_info plane_props[] = {
++ [WDRM_PLANE_TYPE] = {
++ .name = "type",
++ .enum_values = plane_type_enums,
++ .num_enum_values = WDRM_PLANE_TYPE__COUNT,
++ },
++ [WDRM_PLANE_SRC_X] = { .name = "SRC_X", },
++ [WDRM_PLANE_SRC_Y] = { .name = "SRC_Y", },
++ [WDRM_PLANE_SRC_W] = { .name = "SRC_W", },
++ [WDRM_PLANE_SRC_H] = { .name = "SRC_H", },
++ [WDRM_PLANE_CRTC_X] = { .name = "CRTC_X", },
++ [WDRM_PLANE_CRTC_Y] = { .name = "CRTC_Y", },
++ [WDRM_PLANE_CRTC_W] = { .name = "CRTC_W", },
++ [WDRM_PLANE_CRTC_H] = { .name = "CRTC_H", },
++ [WDRM_PLANE_FB_ID] = { .name = "FB_ID", },
++ [WDRM_PLANE_CRTC_ID] = { .name = "CRTC_ID", },
++};
++
++/**
++ * List of properties attached to a DRM connector
++ */
++enum wdrm_connector_property {
++ WDRM_CONNECTOR_EDID = 0,
++ WDRM_CONNECTOR_DPMS,
++ WDRM_CONNECTOR_CRTC_ID,
++ WDRM_CONNECTOR__COUNT
++};
++
++static const struct drm_property_info connector_props[] = {
++ [WDRM_CONNECTOR_EDID] = { .name = "EDID" },
++ [WDRM_CONNECTOR_DPMS] = { .name = "DPMS" },
++ [WDRM_CONNECTOR_CRTC_ID] = { .name = "CRTC_ID", },
++};
++
++/**
++ * List of properties attached to DRM CRTCs
++ */
++enum wdrm_crtc_property {
++ WDRM_CRTC_MODE_ID = 0,
++ WDRM_CRTC_ACTIVE,
++ WDRM_CRTC__COUNT
++};
++
++static const struct drm_property_info crtc_props[] = {
++ [WDRM_CRTC_MODE_ID] = { .name = "MODE_ID", },
++ [WDRM_CRTC_ACTIVE] = { .name = "ACTIVE", },
++};
++
++/**
++ * Mode for drm_output_state_duplicate.
++ */
++enum drm_output_state_duplicate_mode {
++ DRM_OUTPUT_STATE_CLEAR_PLANES, /**< reset all planes to off */
++ DRM_OUTPUT_STATE_PRESERVE_PLANES, /**< preserve plane state */
++};
++
++/**
++ * Mode for drm_pending_state_apply and co.
++ */
++enum drm_state_apply_mode {
++ DRM_STATE_APPLY_SYNC, /**< state fully processed */
++ DRM_STATE_APPLY_ASYNC, /**< state pending event delivery */
++};
++
+ struct drm_backend {
+ struct weston_backend base;
+ struct weston_compositor *compositor;
+@@ -103,14 +243,24 @@ struct drm_backend {
+ */
+ int min_width, max_width;
+ int min_height, max_height;
+- int no_addfb2;
+
+- struct wl_list sprite_list;
++ struct wl_list plane_list;
+ int sprites_are_broken;
+ int sprites_hidden;
+
++ void *repaint_data;
++
++ bool state_invalid;
++
++ /* Connector and CRTC IDs not used by any enabled output. */
++ struct wl_array unused_connectors;
++ struct wl_array unused_crtcs;
++
+ int cursors_are_broken;
+
++ bool universal_planes;
++ bool atomic_modeset;
++
+ int use_pixman;
+
+ struct udev_input input;
+@@ -118,23 +268,39 @@ struct drm_backend {
+ int32_t cursor_width;
+ int32_t cursor_height;
+
+- uint32_t connector;
++ uint32_t pageflip_timeout;
++
++ bool shutting_down;
+ };
+
+ struct drm_mode {
+ struct weston_mode base;
+ drmModeModeInfo mode_info;
++ uint32_t blob_id;
++};
++
++enum drm_fb_type {
++ BUFFER_INVALID = 0, /**< never used */
++ BUFFER_CLIENT, /**< directly sourced from client */
++ BUFFER_PIXMAN_DUMB, /**< internal Pixman rendering */
++ BUFFER_GBM_SURFACE, /**< internal EGL rendering */
++ BUFFER_CURSOR, /**< internal cursor buffer */
+ };
+
+ struct drm_fb {
++ enum drm_fb_type type;
++
++ int refcnt;
++
+ uint32_t fb_id, stride, handle, size;
++ const struct pixel_format_info *format;
+ int width, height;
+ int fd;
+- int is_client_buffer;
+ struct weston_buffer_reference buffer_ref;
+
+ /* Used by gbm fbs */
+ struct gbm_bo *bo;
++ struct gbm_surface *gbm_surface;
+
+ /* Used by dumb fbs */
+ void *map;
+@@ -147,6 +313,95 @@ struct drm_edid {
+ char serial_number[13];
+ };
+
++/**
++ * Pending state holds one or more drm_output_state structures, collected from
++ * performing repaint. This pending state is transient, and only lives between
++ * beginning a repaint group and flushing the results: after flush, each
++ * output state will complete and be retired separately.
++ */
++struct drm_pending_state {
++ struct drm_backend *backend;
++ struct wl_list output_list;
++};
++
++/*
++ * Output state holds the dynamic state for one Weston output, i.e. a KMS CRTC,
++ * plus >= 1 each of encoder/connector/plane. Since everything but the planes
++ * is currently statically assigned per-output, we mainly use this to track
++ * plane state.
++ *
++ * pending_state is set when the output state is owned by a pending_state,
++ * i.e. when it is being constructed and has not yet been applied. When the
++ * output state has been applied, the owning pending_state is freed.
++ */
++struct drm_output_state {
++ struct drm_pending_state *pending_state;
++ struct drm_output *output;
++ struct wl_list link;
++ enum dpms_enum dpms;
++ struct wl_list plane_list;
++};
++
++/**
++ * Plane state holds the dynamic state for a plane: where it is positioned,
++ * and which buffer it is currently displaying.
++ *
++ * The plane state is owned by an output state, except when setting an initial
++ * state. See drm_output_state for notes on state object lifetime.
++ */
++struct drm_plane_state {
++ struct drm_plane *plane;
++ struct drm_output *output;
++ struct drm_output_state *output_state;
++
++ struct drm_fb *fb;
++
++ int32_t src_x, src_y;
++ uint32_t src_w, src_h;
++ int32_t dest_x, dest_y;
++ uint32_t dest_w, dest_h;
++
++ bool complete;
++
++ struct wl_list link; /* drm_output_state::plane_list */
++};
++
++/**
++ * A plane represents one buffer, positioned within a CRTC, and stacked
++ * relative to other planes on the same CRTC.
++ *
++ * Each CRTC has a 'primary plane', which use used to display the classic
++ * framebuffer contents, as accessed through the legacy drmModeSetCrtc
++ * call (which combines setting the CRTC's actual physical mode, and the
++ * properties of the primary plane).
++ *
++ * The cursor plane also has its own alternate legacy API.
++ *
++ * Other planes are used opportunistically to display content we do not
++ * wish to blit into the primary plane. These non-primary/cursor planes
++ * are referred to as 'sprites'.
++ */
++struct drm_plane {
++ struct weston_plane base;
++
++ struct drm_backend *backend;
++
++ enum wdrm_plane_type type;
++
++ uint32_t possible_crtcs;
++ uint32_t plane_id;
++ uint32_t count_formats;
++
++ struct drm_property_info props[WDRM_PLANE__COUNT];
++
++ /* The last state submitted to the kernel for this plane. */
++ struct drm_plane_state *state_cur;
++
++ struct wl_list link;
++
++ uint32_t formats[];
++};
++
+ struct drm_output {
+ struct weston_output base;
+ drmModeConnector *connector;
+@@ -154,26 +409,38 @@ struct drm_output {
+ uint32_t crtc_id; /* object ID to pass to DRM functions */
+ int pipe; /* index of CRTC in resource array / bitmasks */
+ uint32_t connector_id;
+- drmModeCrtcPtr original_crtc;
+ struct drm_edid edid;
+- drmModePropertyPtr dpms_prop;
+- uint32_t gbm_format;
+
+- enum dpms_enum dpms;
++ /* Holds the properties for the connector */
++ struct drm_property_info props_conn[WDRM_CONNECTOR__COUNT];
++ /* Holds the properties for the CRTC */
++ struct drm_property_info props_crtc[WDRM_CRTC__COUNT];
++
++ struct backlight *backlight;
+
+ int vblank_pending;
+ int page_flip_pending;
++ int atomic_complete_pending;
+ int destroy_pending;
+ int disable_pending;
++ int dpms_off_pending;
+
+- struct gbm_surface *gbm_surface;
+- struct gbm_bo *gbm_cursor_bo[2];
+- struct weston_plane cursor_plane;
+- struct weston_plane fb_plane;
++ struct drm_fb *gbm_cursor_fb[2];
++ struct drm_plane *cursor_plane;
+ struct weston_view *cursor_view;
+ int current_cursor;
+- struct drm_fb *current, *next;
+- struct backlight *backlight;
++
++ struct gbm_surface *gbm_surface;
++ uint32_t gbm_format;
++
++ /* Plane being displayed directly on the CRTC */
++ struct drm_plane *scanout_plane;
++
++ /* The last state submitted to the kernel for this CRTC. */
++ struct drm_output_state *state_cur;
++ /* The previously-submitted state, where the hardware has not
++ * yet acknowledged completion of state_cur. */
++ struct drm_output_state *state_last;
+
+ struct drm_fb *dumb[2];
+ pixman_image_t *image[2];
+@@ -182,36 +449,33 @@ struct drm_output {
+
+ struct vaapi_recorder *recorder;
+ struct wl_listener recorder_frame_listener;
+-};
+
+-/*
+- * An output has a primary display plane plus zero or more sprites for
+- * blending display contents.
+- */
+-struct drm_sprite {
+- struct wl_list link;
++ struct wl_event_source *pageflip_timer;
++};
+
+- struct weston_plane plane;
++static struct gl_renderer_interface *gl_renderer;
+
+- struct drm_fb *current, *next;
+- struct drm_output *output;
+- struct drm_backend *backend;
++static const char default_seat[] = "seat0";
+
+- uint32_t possible_crtcs;
+- uint32_t plane_id;
+- uint32_t count_formats;
++static void
++wl_array_remove_uint32(struct wl_array *array, uint32_t elm)
++{
++ uint32_t *pos, *end;
+
+- int32_t src_x, src_y;
+- uint32_t src_w, src_h;
+- uint32_t dest_x, dest_y;
+- uint32_t dest_w, dest_h;
++ end = (uint32_t *) ((char *) array->data + array->size);
+
+- uint32_t formats[];
+-};
++ wl_array_for_each(pos, array) {
++ if (*pos != elm)
++ continue;
+
+-static struct gl_renderer_interface *gl_renderer;
++ array->size -= sizeof(*pos);
++ if (pos + 1 == end)
++ break;
+
+-static const char default_seat[] = "seat0";
++ memmove(pos, pos + 1, (char *) end - (char *) (pos + 1));
++ break;
++ }
++}
+
+ static inline struct drm_output *
+ to_drm_output(struct weston_output *base)
+@@ -225,16 +489,286 @@ to_drm_backend(struct weston_compositor *base)
+ return container_of(base->backend, struct drm_backend, base);
+ }
+
++static int
++pageflip_timeout(void *data) {
++ /*
++ * Our timer just went off, that means we're not receiving drm
++ * page flip events anymore for that output. Let's gracefully exit
++ * weston with a return value so devs can debug what's going on.
++ */
++ struct drm_output *output = data;
++ struct weston_compositor *compositor = output->base.compositor;
++
++ weston_log("Pageflip timeout reached on output %s, your "
++ "driver is probably buggy! Exiting.\n",
++ output->base.name);
++ weston_compositor_exit_with_code(compositor, EXIT_FAILURE);
++
++ return 0;
++}
++
++/* Creates the pageflip timer. Note that it isn't armed by default */
++static int
++drm_output_pageflip_timer_create(struct drm_output *output)
++{
++ struct wl_event_loop *loop = NULL;
++ struct weston_compositor *ec = output->base.compositor;
++
++ loop = wl_display_get_event_loop(ec->wl_display);
++ assert(loop);
++ output->pageflip_timer = wl_event_loop_add_timer(loop,
++ pageflip_timeout,
++ output);
++
++ if (output->pageflip_timer == NULL) {
++ weston_log("creating drm pageflip timer failed: %m\n");
++ return -1;
++ }
++
++ return 0;
++}
++
++static inline struct drm_mode *
++to_drm_mode(struct weston_mode *base)
++{
++ return container_of(base, struct drm_mode, base);
++}
++
++/**
++ * Get the current value of a KMS property
++ *
++ * Given a drmModeObjectGetProperties return, as well as the drm_property_info
++ * for the target property, return the current value of that property,
++ * with an optional default. If the property is a KMS enum type, the return
++ * value will be translated into the appropriate internal enum.
++ *
++ * If the property is not present, the default value will be returned.
++ *
++ * @param info Internal structure for property to look up
++ * @param props Raw KMS properties for the target object
++ * @param def Value to return if property is not found
++ */
++static uint64_t
++drm_property_get_value(struct drm_property_info *info,
++ drmModeObjectPropertiesPtr props,
++ uint64_t def)
++{
++ unsigned int i;
++
++ if (info->prop_id == 0)
++ return def;
++
++ for (i = 0; i < props->count_props; i++) {
++ unsigned int j;
++
++ if (props->props[i] != info->prop_id)
++ continue;
++
++ /* Simple (non-enum) types can return the value directly */
++ if (info->num_enum_values == 0)
++ return props->prop_values[i];
++
++ /* Map from raw value to enum value */
++ for (j = 0; j < info->num_enum_values; j++) {
++ if (!info->enum_values[j].valid)
++ continue;
++ if (info->enum_values[j].value != props->prop_values[i])
++ continue;
++
++ return j;
++ }
++
++ /* We don't have a mapping for this enum; return default. */
++ break;
++ }
++
++ return def;
++}
++
++/**
++ * Cache DRM property values
++ *
++ * Update a per-object array of drm_property_info structures, given the
++ * DRM properties of the object.
++ *
++ * Call this every time an object newly appears (note that only connectors
++ * can be hotplugged), the first time it is seen, or when its status changes
++ * in a way which invalidates the potential property values (currently, the
++ * only case for this is connector hotplug).
++ *
++ * This updates the property IDs and enum values within the drm_property_info
++ * array.
++ *
++ * DRM property enum values are dynamic at runtime; the user must query the
++ * property to find out the desired runtime value for a requested string
++ * name. Using the 'type' field on planes as an example, there is no single
++ * hardcoded constant for primary plane types; instead, the property must be
++ * queried at runtime to find the value associated with the string "Primary".
++ *
++ * This helper queries and caches the enum values, to allow us to use a set
++ * of compile-time-constant enums portably across various implementations.
++ * The values given in enum_names are searched for, and stored in the
++ * same-indexed field of the map array.
++ *
++ * @param b DRM backend object
++ * @param src DRM property info array to source from
++ * @param info DRM property info array to copy into
++ * @param num_infos Number of entries in the source array
++ * @param props DRM object properties for the object
++ */
++static void
++drm_property_info_populate(struct drm_backend *b,
++ const struct drm_property_info *src,
++ struct drm_property_info *info,
++ unsigned int num_infos,
++ drmModeObjectProperties *props)
++{
++ drmModePropertyRes *prop;
++ unsigned i, j;
++
++ for (i = 0; i < num_infos; i++) {
++ unsigned int j;
++
++ info[i].name = src[i].name;
++ info[i].prop_id = 0;
++ info[i].num_enum_values = src[i].num_enum_values;
++
++ if (src[i].num_enum_values == 0)
++ continue;
++
++ info[i].enum_values =
++ malloc(src[i].num_enum_values *
++ sizeof(*info[i].enum_values));
++ assert(info[i].enum_values);
++ for (j = 0; j < info[i].num_enum_values; j++) {
++ info[i].enum_values[j].name = src[i].enum_values[j].name;
++ info[i].enum_values[j].valid = false;
++ }
++ }
++
++ for (i = 0; i < props->count_props; i++) {
++ unsigned int k;
++
++ prop = drmModeGetProperty(b->drm.fd, props->props[i]);
++ if (!prop)
++ continue;
++
++ for (j = 0; j < num_infos; j++) {
++ if (!strcmp(prop->name, info[j].name))
++ break;
++ }
++
++ /* We don't know/care about this property. */
++ if (j == num_infos) {
++#ifdef DEBUG
++ weston_log("DRM debug: unrecognized property %u '%s'\n",
++ prop->prop_id, prop->name);
++#endif
++ drmModeFreeProperty(prop);
++ continue;
++ }
++
++ if (info[j].num_enum_values == 0 &&
++ (prop->flags & DRM_MODE_PROP_ENUM)) {
++ weston_log("DRM: expected property %s to not be an"
++ " enum, but it is; ignoring\n", prop->name);
++ drmModeFreeProperty(prop);
++ continue;
++ }
++
++ info[j].prop_id = props->props[i];
++
++ if (info[j].num_enum_values == 0) {
++ drmModeFreeProperty(prop);
++ continue;
++ }
++
++ if (!(prop->flags & DRM_MODE_PROP_ENUM)) {
++ weston_log("DRM: expected property %s to be an enum,"
++ " but it is not; ignoring\n", prop->name);
++ drmModeFreeProperty(prop);
++ info[j].prop_id = 0;
++ continue;
++ }
++
++ for (k = 0; k < info[j].num_enum_values; k++) {
++ int l;
++
++ for (l = 0; l < prop->count_enums; l++) {
++ if (!strcmp(prop->enums[l].name,
++ info[j].enum_values[k].name))
++ break;
++ }
++
++ if (l == prop->count_enums)
++ continue;
++
++ info[j].enum_values[k].valid = true;
++ info[j].enum_values[k].value = prop->enums[l].value;
++ }
++
++ drmModeFreeProperty(prop);
++ }
++
++#ifdef DEBUG
++ for (i = 0; i < num_infos; i++) {
++ if (info[i].prop_id == 0)
++ weston_log("DRM warning: property '%s' missing\n",
++ info[i].name);
++ }
++#endif
++}
++
++/**
++ * Free DRM property information
++ *
++ * Frees all memory associated with a DRM property info array and zeroes
++ * it out, leaving it usable for a further drm_property_info_update() or
++ * drm_property_info_free().
++ *
++ * @param info DRM property info array
++ * @param num_props Number of entries in array to free
++ */
++static void
++drm_property_info_free(struct drm_property_info *info, int num_props)
++{
++ int i;
++
++ for (i = 0; i < num_props; i++)
++ free(info[i].enum_values);
++
++ memset(info, 0, sizeof(*info) * num_props);
++}
++
+ static void
+-drm_output_set_cursor(struct drm_output *output);
++drm_output_set_cursor(struct drm_output_state *output_state);
+
+ static void
+ drm_output_update_msc(struct drm_output *output, unsigned int seq);
+
+-static int
+-drm_sprite_crtc_supported(struct drm_output *output, struct drm_sprite *sprite)
++static void
++drm_output_destroy(struct weston_output *output_base);
++
++/**
++ * Returns true if the plane can be used on the given output for its current
++ * repaint cycle.
++ */
++static bool
++drm_plane_is_available(struct drm_plane *plane, struct drm_output *output)
+ {
+- return !!(sprite->possible_crtcs & (1 << output->pipe));
++ assert(plane->state_cur);
++
++ /* The plane still has a request not yet completed by the kernel. */
++ if (!plane->state_cur->complete)
++ return false;
++
++ /* The plane is still active on another output. */
++ if (plane->state_cur->output && plane->state_cur->output != output)
++ return false;
++
++ /* Check whether the plane can be used with this CRTC; possible_crtcs
++ * is a bitmask of CRTC indices (pipe), rather than CRTC object ID. */
++ return !!(plane->possible_crtcs & (1 << output->pipe));
+ }
+
+ static struct drm_output *
+@@ -276,16 +810,39 @@ drm_output_find_by_connector(struct drm_backend *b, uint32_t connector_id)
+ }
+
+ static void
+-drm_fb_destroy_callback(struct gbm_bo *bo, void *data)
++drm_fb_destroy(struct drm_fb *fb)
+ {
+- struct drm_fb *fb = data;
+-
+- if (fb->fb_id)
++ if (fb->fb_id != 0)
+ drmModeRmFB(fb->fd, fb->fb_id);
+-
+ weston_buffer_reference(&fb->buffer_ref, NULL);
++ free(fb);
++}
++
++static void
++drm_fb_destroy_dumb(struct drm_fb *fb)
++{
++ struct drm_mode_destroy_dumb destroy_arg;
+
+- free(data);
++ assert(fb->type == BUFFER_PIXMAN_DUMB);
++
++ if (fb->map && fb->size > 0)
++ munmap(fb->map, fb->size);
++
++ memset(&destroy_arg, 0, sizeof(destroy_arg));
++ destroy_arg.handle = fb->handle;
++ drmIoctl(fb->fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy_arg);
++
++ drm_fb_destroy(fb);
++}
++
++static void
++drm_fb_destroy_gbm(struct gbm_bo *bo, void *data)
++{
++ struct drm_fb *fb = data;
++
++ assert(fb->type == BUFFER_GBM_SURFACE || fb->type == BUFFER_CLIENT ||
++ fb->type == BUFFER_CURSOR);
++ drm_fb_destroy(fb);
+ }
+
+ static struct drm_fb *
+@@ -294,30 +851,33 @@ drm_fb_create_dumb(struct drm_backend *b, int width, int height,
+ {
+ struct drm_fb *fb;
+ int ret;
+- uint32_t bpp, depth;
+
+ struct drm_mode_create_dumb create_arg;
+ struct drm_mode_destroy_dumb destroy_arg;
+ struct drm_mode_map_dumb map_arg;
++ uint32_t handles[4] = { 0 }, pitches[4] = { 0 }, offsets[4] = { 0 };
+
+ fb = zalloc(sizeof *fb);
+ if (!fb)
+ return NULL;
+
+- switch (format) {
+- case GBM_FORMAT_XRGB8888:
+- bpp = 32;
+- depth = 24;
+- break;
+- case GBM_FORMAT_RGB565:
+- bpp = depth = 16;
+- break;
+- default:
+- return NULL;
++ fb->refcnt = 1;
++
++ fb->format = pixel_format_get_info(format);
++ if (!fb->format) {
++ weston_log("failed to look up format 0x%lx\n",
++ (unsigned long) format);
++ goto err_fb;
++ }
++
++ if (!fb->format->depth || !fb->format->bpp) {
++ weston_log("format 0x%lx is not compatible with dumb buffers\n",
++ (unsigned long) format);
++ goto err_fb;
+ }
+
+ memset(&create_arg, 0, sizeof create_arg);
+- create_arg.bpp = bpp;
++ create_arg.bpp = fb->format->bpp;
+ create_arg.width = width;
+ create_arg.height = height;
+
+@@ -325,6 +885,7 @@ drm_fb_create_dumb(struct drm_backend *b, int width, int height,
+ if (ret)
+ goto err_fb;
+
++ fb->type = BUFFER_PIXMAN_DUMB;
+ fb->handle = create_arg.handle;
+ fb->stride = create_arg.pitch;
+ fb->size = create_arg.size;
+@@ -332,26 +893,15 @@ drm_fb_create_dumb(struct drm_backend *b, int width, int height,
+ fb->height = height;
+ fb->fd = b->drm.fd;
+
+- ret = -1;
+-
+- if (!b->no_addfb2) {
+- uint32_t handles[4] = { 0 }, pitches[4] = { 0 }, offsets[4] = { 0 };
+-
+- handles[0] = fb->handle;
+- pitches[0] = fb->stride;
+- offsets[0] = 0;
+-
+- ret = drmModeAddFB2(b->drm.fd, width, height,
+- format, handles, pitches, offsets,
+- &fb->fb_id, 0);
+- if (ret) {
+- weston_log("addfb2 failed: %m\n");
+- b->no_addfb2 = 1;
+- }
+- }
++ handles[0] = fb->handle;
++ pitches[0] = fb->stride;
++ offsets[0] = 0;
+
++ ret = drmModeAddFB2(b->drm.fd, width, height, fb->format->format,
++ handles, pitches, offsets, &fb->fb_id, 0);
+ if (ret) {
+- ret = drmModeAddFB(b->drm.fd, width, height, depth, bpp,
++ ret = drmModeAddFB(b->drm.fd, width, height,
++ fb->format->depth, fb->format->bpp,
+ fb->stride, fb->handle, &fb->fb_id);
+ }
+
+@@ -382,52 +932,50 @@ err_fb:
+ return NULL;
+ }
+
+-static void
+-drm_fb_destroy_dumb(struct drm_fb *fb)
++static struct drm_fb *
++drm_fb_ref(struct drm_fb *fb)
+ {
+- struct drm_mode_destroy_dumb destroy_arg;
+-
+- if (!fb->map)
+- return;
+-
+- if (fb->fb_id)
+- drmModeRmFB(fb->fd, fb->fb_id);
+-
+- weston_buffer_reference(&fb->buffer_ref, NULL);
+-
+- munmap(fb->map, fb->size);
+-
+- memset(&destroy_arg, 0, sizeof(destroy_arg));
+- destroy_arg.handle = fb->handle;
+- drmIoctl(fb->fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy_arg);
+-
+- free(fb);
++ fb->refcnt++;
++ return fb;
+ }
+
+ static struct drm_fb *
+-drm_fb_get_from_bo(struct gbm_bo *bo,
+- struct drm_backend *backend, uint32_t format)
++drm_fb_get_from_bo(struct gbm_bo *bo, struct drm_backend *backend,
++ uint32_t format, enum drm_fb_type type)
+ {
+ struct drm_fb *fb = gbm_bo_get_user_data(bo);
+ uint32_t handles[4] = { 0 }, pitches[4] = { 0 }, offsets[4] = { 0 };
+ int ret;
+
+- if (fb)
+- return fb;
++ if (fb) {
++ assert(fb->type == type);
++ return drm_fb_ref(fb);
++ }
++
++ assert(format != 0);
+
+ fb = zalloc(sizeof *fb);
+ if (fb == NULL)
+ return NULL;
+
++ fb->type = type;
++ fb->refcnt = 1;
+ fb->bo = bo;
+
+ fb->width = gbm_bo_get_width(bo);
+ fb->height = gbm_bo_get_height(bo);
+ fb->stride = gbm_bo_get_stride(bo);
+ fb->handle = gbm_bo_get_handle(bo).u32;
++ fb->format = pixel_format_get_info(format);
+ fb->size = fb->stride * fb->height;
+ fb->fd = backend->drm.fd;
+
++ if (!fb->format) {
++ weston_log("couldn't look up format 0x%lx\n",
++ (unsigned long) format);
++ goto err_free;
++ }
++
+ if (backend->min_width > fb->width ||
+ fb->width > backend->max_width ||
+ backend->min_height > fb->height ||
+@@ -436,33 +984,24 @@ drm_fb_get_from_bo(struct gbm_bo *bo,
+ goto err_free;
+ }
+
+- ret = -1;
+-
+- if (format && !backend->no_addfb2) {
+- handles[0] = fb->handle;
+- pitches[0] = fb->stride;
+- offsets[0] = 0;
++ handles[0] = fb->handle;
++ pitches[0] = fb->stride;
++ offsets[0] = 0;
+
+- ret = drmModeAddFB2(backend->drm.fd, fb->width, fb->height,
+- format, handles, pitches, offsets,
+- &fb->fb_id, 0);
+- if (ret) {
+- weston_log("addfb2 failed: %m\n");
+- backend->no_addfb2 = 1;
+- backend->sprites_are_broken = 1;
+- }
+- }
+-
+- if (ret)
++ ret = drmModeAddFB2(backend->drm.fd, fb->width, fb->height,
++ fb->format->format, handles, pitches, offsets,
++ &fb->fb_id, 0);
++ if (ret && fb->format->depth && fb->format->bpp)
+ ret = drmModeAddFB(backend->drm.fd, fb->width, fb->height,
+- 24, 32, fb->stride, fb->handle, &fb->fb_id);
++ fb->format->depth, fb->format->bpp,
++ fb->stride, fb->handle, &fb->fb_id);
+
+ if (ret) {
+ weston_log("failed to create kms fb: %m\n");
+ goto err_free;
+ }
+
+- gbm_bo_set_user_data(bo, fb, drm_fb_destroy_callback);
++ gbm_bo_set_user_data(bo, fb, drm_fb_destroy_gbm);
+
+ return fb;
+
+@@ -475,28 +1014,496 @@ static void
+ drm_fb_set_buffer(struct drm_fb *fb, struct weston_buffer *buffer)
+ {
+ assert(fb->buffer_ref.buffer == NULL);
++ assert(fb->type == BUFFER_CLIENT);
++ weston_buffer_reference(&fb->buffer_ref, buffer);
++}
++
++static void
++drm_fb_unref(struct drm_fb *fb)
++{
++ if (!fb)
++ return;
++
++ assert(fb->refcnt > 0);
++ if (--fb->refcnt > 0)
++ return;
++
++ switch (fb->type) {
++ case BUFFER_PIXMAN_DUMB:
++ drm_fb_destroy_dumb(fb);
++ break;
++ case BUFFER_CURSOR:
++ case BUFFER_CLIENT:
++ gbm_bo_destroy(fb->bo);
++ break;
++ case BUFFER_GBM_SURFACE:
++ gbm_surface_release_buffer(fb->gbm_surface, fb->bo);
++ break;
++ default:
++ assert(NULL);
++ break;
++ }
++}
++
++/**
++ * Allocate a new, empty, plane state.
++ */
++static struct drm_plane_state *
++drm_plane_state_alloc(struct drm_output_state *state_output,
++ struct drm_plane *plane)
++{
++ struct drm_plane_state *state = zalloc(sizeof(*state));
++
++ assert(state);
++ state->output_state = state_output;
++ state->plane = plane;
++
++ /* Here we only add the plane state to the desired link, and not
++ * set the member. Having an output pointer set means that the
++ * plane will be displayed on the output; this won't be the case
++ * when we go to disable a plane. In this case, it must be part of
++ * the commit (and thus the output state), but the member must be
++ * NULL, as it will not be on any output when the state takes
++ * effect.
++ */
++ if (state_output)
++ wl_list_insert(&state_output->plane_list, &state->link);
++ else
++ wl_list_init(&state->link);
++
++ return state;
++}
++
++/**
++ * Free an existing plane state. As a special case, the state will not
++ * normally be freed if it is the current state; see drm_plane_set_state.
++ */
++static void
++drm_plane_state_free(struct drm_plane_state *state, bool force)
++{
++ if (!state)
++ return;
++
++ wl_list_remove(&state->link);
++ wl_list_init(&state->link);
++ state->output_state = NULL;
++
++ if (force || state != state->plane->state_cur) {
++ drm_fb_unref(state->fb);
++ free(state);
++ }
++}
++
++/**
++ * Duplicate an existing plane state into a new plane state, storing it within
++ * the given output state. If the output state already contains a plane state
++ * for the drm_plane referenced by 'src', that plane state is freed first.
++ */
++static struct drm_plane_state *
++drm_plane_state_duplicate(struct drm_output_state *state_output,
++ struct drm_plane_state *src)
++{
++ struct drm_plane_state *dst = malloc(sizeof(*dst));
++ struct drm_plane_state *old, *tmp;
++
++ assert(src);
++ assert(dst);
++ *dst = *src;
++ wl_list_init(&dst->link);
++
++ wl_list_for_each_safe(old, tmp, &state_output->plane_list, link) {
++ /* Duplicating a plane state into the same output state, so
++ * it can replace itself with an identical copy of itself,
++ * makes no sense. */
++ assert(old != src);
++ if (old->plane == dst->plane)
++ drm_plane_state_free(old, false);
++ }
++
++ wl_list_insert(&state_output->plane_list, &dst->link);
++ if (src->fb)
++ dst->fb = drm_fb_ref(src->fb);
++ dst->output_state = state_output;
++ dst->complete = false;
++
++ return dst;
++}
++
++/**
++ * Remove a plane state from an output state; if the plane was previously
++ * enabled, then replace it with a disabling state. This ensures that the
++ * output state was untouched from it was before the plane state was
++ * modified by the caller of this function.
++ *
++ * This is required as drm_output_state_get_plane may either allocate a
++ * new plane state, in which case this function will just perform a matching
++ * drm_plane_state_free, or it may instead repurpose an existing disabling
++ * state (if the plane was previously active), in which case this function
++ * will reset it.
++ */
++static void
++drm_plane_state_put_back(struct drm_plane_state *state)
++{
++ struct drm_output_state *state_output;
++ struct drm_plane *plane;
++
++ if (!state)
++ return;
++
++ state_output = state->output_state;
++ plane = state->plane;
++ drm_plane_state_free(state, false);
++
++ /* Plane was previously disabled; no need to keep this temporary
++ * state around. */
++ if (!plane->state_cur->fb)
++ return;
++
++ (void) drm_plane_state_alloc(state_output, plane);
++}
++
++/**
++ * Return a plane state from a drm_output_state.
++ */
++static struct drm_plane_state *
++drm_output_state_get_existing_plane(struct drm_output_state *state_output,
++ struct drm_plane *plane)
++{
++ struct drm_plane_state *ps;
++
++ wl_list_for_each(ps, &state_output->plane_list, link) {
++ if (ps->plane == plane)
++ return ps;
++ }
++
++ return NULL;
++}
++
++/**
++ * Return a plane state from a drm_output_state, either existing or
++ * freshly allocated.
++ */
++static struct drm_plane_state *
++drm_output_state_get_plane(struct drm_output_state *state_output,
++ struct drm_plane *plane)
++{
++ struct drm_plane_state *ps;
++
++ ps = drm_output_state_get_existing_plane(state_output, plane);
++ if (ps)
++ return ps;
++
++ return drm_plane_state_alloc(state_output, plane);
++}
++
++/**
++ * Allocate a new, empty drm_output_state. This should not generally be used
++ * in the repaint cycle; see drm_output_state_duplicate.
++ */
++static struct drm_output_state *
++drm_output_state_alloc(struct drm_output *output,
++ struct drm_pending_state *pending_state)
++{
++ struct drm_output_state *state = zalloc(sizeof(*state));
++
++ assert(state);
++ state->output = output;
++ state->dpms = WESTON_DPMS_OFF;
++ state->pending_state = pending_state;
++ if (pending_state)
++ wl_list_insert(&pending_state->output_list, &state->link);
++ else
++ wl_list_init(&state->link);
++
++ wl_list_init(&state->plane_list);
++
++ return state;
++}
++
++/**
++ * Duplicate an existing drm_output_state into a new one. This is generally
++ * used during the repaint cycle, to capture the existing state of an output
++ * and modify it to create a new state to be used.
++ *
++ * The mode determines whether the output will be reset to an a blank state,
++ * or an exact mirror of the current state.
++ */
++static struct drm_output_state *
++drm_output_state_duplicate(struct drm_output_state *src,
++ struct drm_pending_state *pending_state,
++ enum drm_output_state_duplicate_mode plane_mode)
++{
++ struct drm_output_state *dst = malloc(sizeof(*dst));
++ struct drm_plane_state *ps;
++
++ assert(dst);
++
++ /* Copy the whole structure, then individually modify the
++ * pending_state, as well as the list link into our pending
++ * state. */
++ *dst = *src;
++
++ dst->pending_state = pending_state;
++ if (pending_state)
++ wl_list_insert(&pending_state->output_list, &dst->link);
++ else
++ wl_list_init(&dst->link);
++
++ wl_list_init(&dst->plane_list);
++
++ wl_list_for_each(ps, &src->plane_list, link) {
++ /* Don't carry planes which are now disabled; these should be
++ * free for other outputs to reuse. */
++ if (!ps->output)
++ continue;
++
++ if (plane_mode == DRM_OUTPUT_STATE_CLEAR_PLANES)
++ (void) drm_plane_state_alloc(dst, ps->plane);
++ else
++ (void) drm_plane_state_duplicate(dst, ps);
++ }
++
++ return dst;
++}
++
++/**
++ * Free an unused drm_output_state.
++ */
++static void
++drm_output_state_free(struct drm_output_state *state)
++{
++ struct drm_plane_state *ps, *next;
++
++ if (!state)
++ return;
++
++ wl_list_for_each_safe(ps, next, &state->plane_list, link)
++ drm_plane_state_free(ps, false);
++
++ wl_list_remove(&state->link);
++
++ free(state);
++}
++
++/**
++ * Get output state to disable output
++ *
++ * Returns a pointer to an output_state object which can be used to disable
++ * an output (e.g. DPMS off).
++ *
++ * @param pending_state The pending state object owning this update
++ * @param output The output to disable
++ * @returns A drm_output_state to disable the output
++ */
++static struct drm_output_state *
++drm_output_get_disable_state(struct drm_pending_state *pending_state,
++ struct drm_output *output)
++{
++ struct drm_output_state *output_state;
++
++ output_state = drm_output_state_duplicate(output->state_cur,
++ pending_state,
++ DRM_OUTPUT_STATE_CLEAR_PLANES);
++ output_state->dpms = WESTON_DPMS_OFF;
++
++ return output_state;
++}
++
++/**
++ * Allocate a new drm_pending_state
++ *
++ * Allocate a new, empty, 'pending state' structure to be used across a
++ * repaint cycle or similar.
++ *
++ * @param backend DRM backend
++ * @returns Newly-allocated pending state structure
++ */
++static struct drm_pending_state *
++drm_pending_state_alloc(struct drm_backend *backend)
++{
++ struct drm_pending_state *ret;
++
++ ret = calloc(1, sizeof(*ret));
++ if (!ret)
++ return NULL;
++
++ ret->backend = backend;
++ wl_list_init(&ret->output_list);
++
++ return ret;
++}
++
++/**
++ * Free a drm_pending_state structure
++ *
++ * Frees a pending_state structure, as well as any output_states connected
++ * to this pending state.
++ *
++ * @param pending_state Pending state structure to free
++ */
++static void
++drm_pending_state_free(struct drm_pending_state *pending_state)
++{
++ struct drm_output_state *output_state, *tmp;
++
++ if (!pending_state)
++ return;
++
++ wl_list_for_each_safe(output_state, tmp, &pending_state->output_list,
++ link) {
++ drm_output_state_free(output_state);
++ }
++
++ free(pending_state);
++}
++
++/**
++ * Find an output state in a pending state
++ *
++ * Given a pending_state structure, find the output_state for a particular
++ * output.
++ *
++ * @param pending_state Pending state structure to search
++ * @param output Output to find state for
++ * @returns Output state if present, or NULL if not
++ */
++static struct drm_output_state *
++drm_pending_state_get_output(struct drm_pending_state *pending_state,
++ struct drm_output *output)
++{
++ struct drm_output_state *output_state;
++
++ wl_list_for_each(output_state, &pending_state->output_list, link) {
++ if (output_state->output == output)
++ return output_state;
++ }
++
++ return NULL;
++}
++
++static int drm_pending_state_apply_sync(struct drm_pending_state *state);
++
++/**
++ * Mark a drm_output_state (the output's last state) as complete. This handles
++ * any post-completion actions such as updating the repaint timer, disabling the
++ * output, and finally freeing the state.
++ */
++static void
++drm_output_update_complete(struct drm_output *output, uint32_t flags,
++ unsigned int sec, unsigned int usec)
++{
++ struct drm_backend *b = to_drm_backend(output->base.compositor);
++ struct drm_plane_state *ps;
++ struct timespec ts;
++
++ /* Stop the pageflip timer instead of rearming it here */
++ if (output->pageflip_timer)
++ wl_event_source_timer_update(output->pageflip_timer, 0);
++
++ wl_list_for_each(ps, &output->state_cur->plane_list, link)
++ ps->complete = true;
++
++ drm_output_state_free(output->state_last);
++ output->state_last = NULL;
++
++ if (output->destroy_pending) {
++ output->destroy_pending = 0;
++ output->disable_pending = 0;
++ output->dpms_off_pending = 0;
++ drm_output_destroy(&output->base);
++ return;
++ } else if (output->disable_pending) {
++ output->disable_pending = 0;
++ output->dpms_off_pending = 0;
++ weston_output_disable(&output->base);
++ return;
++ } else if (output->dpms_off_pending) {
++ struct drm_pending_state *pending = drm_pending_state_alloc(b);
++ output->dpms_off_pending = 0;
++ drm_output_get_disable_state(pending, output);
++ drm_pending_state_apply_sync(pending);
++ return;
++ } else if (output->state_cur->dpms == WESTON_DPMS_OFF &&
++ output->base.repaint_status != REPAINT_AWAITING_COMPLETION) {
++ /* DPMS can happen to us either in the middle of a repaint
++ * cycle (when we have painted fresh content, only to throw it
++ * away for DPMS off), or at any other random point. If the
++ * latter is true, then we cannot go through finish_frame,
++ * because the repaint machinery does not expect this. */
++ return;
++ }
++
++ ts.tv_sec = sec;
++ ts.tv_nsec = usec * 1000;
++ weston_output_finish_frame(&output->base, &ts, flags);
++
++ /* We can't call this from frame_notify, because the output's
++ * repaint needed flag is cleared just after that */
++ if (output->recorder)
++ weston_output_schedule_repaint(&output->base);
++}
++
++/**
++ * Mark an output state as current on the output, i.e. it has been
++ * submitted to the kernel. The mode argument determines whether this
++ * update will be applied synchronously (e.g. when calling drmModeSetCrtc),
++ * or asynchronously (in which case we wait for events to complete).
++ */
++static void
++drm_output_assign_state(struct drm_output_state *state,
++ enum drm_state_apply_mode mode)
++{
++ struct drm_output *output = state->output;
++ struct drm_backend *b = to_drm_backend(output->base.compositor);
++ struct drm_plane_state *plane_state;
++
++ assert(!output->state_last);
++
++ if (mode == DRM_STATE_APPLY_ASYNC)
++ output->state_last = output->state_cur;
++ else
++ drm_output_state_free(output->state_cur);
++
++ wl_list_remove(&state->link);
++ wl_list_init(&state->link);
++ state->pending_state = NULL;
++
++ output->state_cur = state;
++
++ if (b->atomic_modeset && mode == DRM_STATE_APPLY_ASYNC)
++ output->atomic_complete_pending = 1;
++
++ /* Replace state_cur on each affected plane with the new state, being
++ * careful to dispose of orphaned (but only orphaned) previous state.
++ * If the previous state is not orphaned (still has an output_state
++ * attached), it will be disposed of by freeing the output_state. */
++ wl_list_for_each(plane_state, &state->plane_list, link) {
++ struct drm_plane *plane = plane_state->plane;
++
++ if (plane->state_cur && !plane->state_cur->output_state)
++ drm_plane_state_free(plane->state_cur, true);
++ plane->state_cur = plane_state;
+
+- fb->is_client_buffer = 1;
++ if (mode != DRM_STATE_APPLY_ASYNC) {
++ plane_state->complete = true;
++ continue;
++ }
+
+- weston_buffer_reference(&fb->buffer_ref, buffer);
++ if (b->atomic_modeset)
++ continue;
++
++ if (plane->type == WDRM_PLANE_TYPE_OVERLAY)
++ output->vblank_pending++;
++ else if (plane->type == WDRM_PLANE_TYPE_PRIMARY)
++ output->page_flip_pending = 1;
++ }
+ }
+
+-static void
+-drm_output_release_fb(struct drm_output *output, struct drm_fb *fb)
++static int
++drm_view_transform_supported(struct weston_view *ev)
+ {
+- if (!fb)
+- return;
+-
+- if (fb->map &&
+- (fb != output->dumb[0] && fb != output->dumb[1])) {
+- drm_fb_destroy_dumb(fb);
+- } else if (fb->bo) {
+- if (fb->is_client_buffer)
+- gbm_bo_destroy(fb->bo);
+- else
+- gbm_surface_release_buffer(output->gbm_surface,
+- fb->bo);
+- }
++ return !ev->transform.enabled ||
++ (ev->transform.matrix.type < WESTON_MATRIX_TRANSFORM_ROTATE);
+ }
+
+ static uint32_t
+@@ -530,36 +1537,61 @@ drm_output_check_scanout_format(struct drm_output *output,
+ }
+
+ static struct weston_plane *
+-drm_output_prepare_scanout_view(struct drm_output *output,
++drm_output_prepare_scanout_view(struct drm_output_state *output_state,
+ struct weston_view *ev)
+ {
++ struct drm_output *output = output_state->output;
+ struct drm_backend *b = to_drm_backend(output->base.compositor);
++ struct drm_plane *scanout_plane = output->scanout_plane;
++ struct drm_plane_state *state;
+ struct weston_buffer *buffer = ev->surface->buffer_ref.buffer;
+ struct weston_buffer_viewport *viewport = &ev->surface->buffer_viewport;
+ struct gbm_bo *bo;
+ uint32_t format;
+
++ /* Don't import buffers which span multiple outputs. */
++ if (ev->output_mask != (1u << output->base.id))
++ return NULL;
++
+ /* We use GBM to import buffers. */
+ if (b->gbm == NULL)
+ return NULL;
+
+ if (buffer == NULL)
+ return NULL;
++ if (wl_shm_buffer_get(buffer->resource))
++ return NULL;
+
+ /* Make sure our view is exactly compatible with the output. */
+ if (ev->geometry.x != output->base.x ||
+ ev->geometry.y != output->base.y)
+ return NULL;
++ if (buffer->width != output->base.current_mode->width ||
++ buffer->height != output->base.current_mode->height)
++ return NULL;
++
+ if (ev->transform.enabled)
+ return NULL;
+ if (ev->geometry.scissor_enabled)
+ return NULL;
++ if (viewport->buffer.transform != output->base.transform)
++ return NULL;
++ if (viewport->buffer.scale != output->base.current_scale)
++ return NULL;
++ if (!drm_view_transform_supported(ev))
++ return NULL;
+
+- if (buffer->width != output->base.current_mode->width ||
+- buffer->height != output->base.current_mode->height)
++ if (ev->alpha != 1.0f)
+ return NULL;
+- if (viewport->buffer.transform != output->base.transform)
++
++ state = drm_output_state_get_plane(output_state, scanout_plane);
++ if (state->fb) {
++ /* If there is already a framebuffer on the scanout plane,
++ * a client view has already been placed on the scanout
++ * view. In that case, do not free or put back the state,
++ * but just leave it in place and quietly exit. */
+ return NULL;
++ }
+
+ bo = gbm_bo_import(b->gbm, GBM_BO_IMPORT_WL_BUFFER,
+ buffer->resource, GBM_BO_USE_SCANOUT);
+@@ -570,26 +1602,42 @@ drm_output_prepare_scanout_view(struct drm_output *output,
+
+ format = drm_output_check_scanout_format(output, ev->surface, bo);
+ if (format == 0) {
++ drm_plane_state_put_back(state);
+ gbm_bo_destroy(bo);
+ return NULL;
+ }
+
+- output->next = drm_fb_get_from_bo(bo, b, format);
+- if (!output->next) {
++ state->fb = drm_fb_get_from_bo(bo, b, format, BUFFER_CLIENT);
++ if (!state->fb) {
++ drm_plane_state_put_back(state);
+ gbm_bo_destroy(bo);
+ return NULL;
+ }
+
+- drm_fb_set_buffer(output->next, buffer);
++ drm_fb_set_buffer(state->fb, buffer);
++
++ state->output = output;
++
++ state->src_x = 0;
++ state->src_y = 0;
++ state->src_w = state->fb->width << 16;
++ state->src_h = state->fb->height << 16;
+
+- return &output->fb_plane;
++ state->dest_x = 0;
++ state->dest_y = 0;
++ state->dest_w = output->base.current_mode->width;
++ state->dest_h = output->base.current_mode->height;
++
++ return &scanout_plane->base;
+ }
+
+-static void
+-drm_output_render_gl(struct drm_output *output, pixman_region32_t *damage)
++static struct drm_fb *
++drm_output_render_gl(struct drm_output_state *state, pixman_region32_t *damage)
+ {
++ struct drm_output *output = state->output;
+ struct drm_backend *b = to_drm_backend(output->base.compositor);
+ struct gbm_bo *bo;
++ struct drm_fb *ret;
+
+ output->base.compositor->renderer->repaint_output(&output->base,
+ damage);
+@@ -597,20 +1645,25 @@ drm_output_render_gl(struct drm_output *output, pixman_region32_t *damage)
+ bo = gbm_surface_lock_front_buffer(output->gbm_surface);
+ if (!bo) {
+ weston_log("failed to lock front buffer: %m\n");
+- return;
++ return NULL;
+ }
+
+- output->next = drm_fb_get_from_bo(bo, b, output->gbm_format);
+- if (!output->next) {
++ ret = drm_fb_get_from_bo(bo, b, output->gbm_format, BUFFER_GBM_SURFACE);
++ if (!ret) {
+ weston_log("failed to get drm_fb for bo\n");
+ gbm_surface_release_buffer(output->gbm_surface, bo);
+- return;
++ return NULL;
+ }
++ ret->gbm_surface = output->gbm_surface;
++
++ return ret;
+ }
+
+-static void
+-drm_output_render_pixman(struct drm_output *output, pixman_region32_t *damage)
++static struct drm_fb *
++drm_output_render_pixman(struct drm_output_state *state,
++ pixman_region32_t *damage)
+ {
++ struct drm_output *output = state->output;
+ struct weston_compositor *ec = output->base.compositor;
+ pixman_region32_t total_damage, previous_damage;
+
+@@ -624,7 +1677,6 @@ drm_output_render_pixman(struct drm_output *output, pixman_region32_t *damage)
+
+ output->current_image ^= 1;
+
+- output->next = output->dumb[output->current_image];
+ pixman_renderer_output_set_buffer(&output->base,
+ output->image[output->current_image]);
+
+@@ -632,18 +1684,60 @@ drm_output_render_pixman(struct drm_output *output, pixman_region32_t *damage)
+
+ pixman_region32_fini(&total_damage);
+ pixman_region32_fini(&previous_damage);
++
++ return drm_fb_ref(output->dumb[output->current_image]);
+ }
+
+ static void
+-drm_output_render(struct drm_output *output, pixman_region32_t *damage)
++drm_output_render(struct drm_output_state *state, pixman_region32_t *damage)
+ {
++ struct drm_output *output = state->output;
+ struct weston_compositor *c = output->base.compositor;
++ struct drm_plane_state *scanout_state;
++ struct drm_plane *scanout_plane = output->scanout_plane;
+ struct drm_backend *b = to_drm_backend(c);
++ struct drm_fb *fb;
++
++ /* If we already have a client buffer promoted to scanout, then we don't
++ * want to render. */
++ scanout_state = drm_output_state_get_plane(state,
++ output->scanout_plane);
++ if (scanout_state->fb)
++ return;
++
++ if (!pixman_region32_not_empty(damage) &&
++ scanout_plane->state_cur->fb &&
++ (scanout_plane->state_cur->fb->type == BUFFER_GBM_SURFACE ||
++ scanout_plane->state_cur->fb->type == BUFFER_PIXMAN_DUMB) &&
++ scanout_plane->state_cur->fb->width ==
++ output->base.current_mode->width &&
++ scanout_plane->state_cur->fb->height ==
++ output->base.current_mode->height) {
++ fb = drm_fb_ref(scanout_plane->state_cur->fb);
++ } else if (b->use_pixman) {
++ fb = drm_output_render_pixman(state, damage);
++ } else {
++ fb = drm_output_render_gl(state, damage);
++ }
++
++ if (!fb) {
++ drm_plane_state_put_back(scanout_state);
++ return;
++ }
++
++ scanout_state->fb = fb;
++ scanout_state->output = output;
++
++ scanout_state->src_x = 0;
++ scanout_state->src_y = 0;
++ scanout_state->src_w = output->base.current_mode->width << 16;
++ scanout_state->src_h = output->base.current_mode->height << 16;
++
++ scanout_state->dest_x = 0;
++ scanout_state->dest_y = 0;
++ scanout_state->dest_w = scanout_state->src_w >> 16;
++ scanout_state->dest_h = scanout_state->src_h >> 16;
+
+- if (b->use_pixman)
+- drm_output_render_pixman(output, damage);
+- else
+- drm_output_render_gl(output, damage);
+
+ pixman_region32_subtract(&c->primary_plane.damage,
+ &c->primary_plane.damage, damage);
+@@ -661,8 +1755,6 @@ drm_output_set_gamma(struct weston_output *output_base,
+ /* check */
+ if (output_base->gamma_size != size)
+ return;
+- if (!output->original_crtc)
+- return;
+
+ rc = drmModeCrtcSetGamma(backend->drm.fd,
+ output->crtc_id,
+@@ -697,102 +1789,612 @@ drm_waitvblank_pipe(struct drm_output *output)
+ }
+
+ static int
+-drm_output_repaint(struct weston_output *output_base,
+- pixman_region32_t *damage)
++drm_output_apply_state_legacy(struct drm_output_state *state)
+ {
+- struct drm_output *output = to_drm_output(output_base);
+- struct drm_backend *backend =
+- to_drm_backend(output->base.compositor);
+- struct drm_sprite *s;
++ struct drm_output *output = state->output;
++ struct drm_backend *backend = to_drm_backend(output->base.compositor);
++ struct drm_plane *scanout_plane = output->scanout_plane;
++ struct drm_property_info *dpms_prop =
++ &output->props_conn[WDRM_CONNECTOR_DPMS];
++ struct drm_plane_state *scanout_state;
++ struct drm_plane_state *ps;
++ struct drm_plane *p;
+ struct drm_mode *mode;
++ struct timespec now;
+ int ret = 0;
+
+- if (output->disable_pending || output->destroy_pending)
+- return -1;
++ /* If disable_planes is set then assign_planes() wasn't
++ * called for this render, so we could still have a stale
++ * cursor plane set up.
++ */
++ if (output->base.disable_planes) {
++ output->cursor_view = NULL;
++ if (output->cursor_plane) {
++ output->cursor_plane->base.x = INT32_MIN;
++ output->cursor_plane->base.y = INT32_MIN;
++ }
++ }
+
+- if (!output->next)
+- drm_output_render(output, damage);
+- if (!output->next)
+- return -1;
++ if (state->dpms != WESTON_DPMS_ON) {
++ wl_list_for_each(ps, &state->plane_list, link) {
++ p = ps->plane;
++ assert(ps->fb == NULL);
++ assert(ps->output == NULL);
++
++ if (p->type != WDRM_PLANE_TYPE_OVERLAY)
++ continue;
++
++ ret = drmModeSetPlane(backend->drm.fd, p->plane_id,
++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
++ if (ret)
++ weston_log("drmModeSetPlane failed disable: %m\n");
++ }
++
++ if (output->cursor_plane) {
++ ret = drmModeSetCursor(backend->drm.fd, output->crtc_id,
++ 0, 0, 0);
++ if (ret)
++ weston_log("drmModeSetCursor failed disable: %m\n");
++ }
++
++ ret = drmModeSetCrtc(backend->drm.fd, output->crtc_id, 0, 0, 0,
++ &output->connector_id, 0, NULL);
++ if (ret)
++ weston_log("drmModeSetCrtc failed disabling: %m\n");
++
++ drm_output_assign_state(state, DRM_STATE_APPLY_SYNC);
++ weston_compositor_read_presentation_clock(output->base.compositor, &now);
++ drm_output_update_complete(output,
++ WP_PRESENTATION_FEEDBACK_KIND_HW_COMPLETION,
++ now.tv_sec, now.tv_nsec / 1000);
++
++ return 0;
++ }
+
+- mode = container_of(output->base.current_mode, struct drm_mode, base);
+- if (!output->current ||
+- output->current->stride != output->next->stride) {
++ scanout_state =
++ drm_output_state_get_existing_plane(state, scanout_plane);
++
++ /* The legacy SetCrtc API doesn't allow us to do scaling, and the
++ * legacy PageFlip API doesn't allow us to do clipping either. */
++ assert(scanout_state->src_x == 0);
++ assert(scanout_state->src_y == 0);
++ assert(scanout_state->src_w ==
++ (unsigned) (output->base.current_mode->width << 16));
++ assert(scanout_state->src_h ==
++ (unsigned) (output->base.current_mode->height << 16));
++ assert(scanout_state->dest_x == 0);
++ assert(scanout_state->dest_y == 0);
++ assert(scanout_state->dest_w == scanout_state->src_w >> 16);
++ assert(scanout_state->dest_h == scanout_state->src_h >> 16);
++
++ mode = to_drm_mode(output->base.current_mode);
++ if (backend->state_invalid || !scanout_plane->state_cur->fb ||
++ scanout_plane->state_cur->fb->stride != scanout_state->fb->stride) {
+ ret = drmModeSetCrtc(backend->drm.fd, output->crtc_id,
+- output->next->fb_id, 0, 0,
++ scanout_state->fb->fb_id,
++ 0, 0,
+ &output->connector_id, 1,
+ &mode->mode_info);
+ if (ret) {
+ weston_log("set mode failed: %m\n");
+- goto err_pageflip;
++ goto err;
+ }
+- output_base->set_dpms(output_base, WESTON_DPMS_ON);
+ }
+
+ if (drmModePageFlip(backend->drm.fd, output->crtc_id,
+- output->next->fb_id,
++ scanout_state->fb->fb_id,
+ DRM_MODE_PAGE_FLIP_EVENT, output) < 0) {
+ weston_log("queueing pageflip failed: %m\n");
+- goto err_pageflip;
++ goto err;
+ }
+
+- output->page_flip_pending = 1;
++ assert(!output->page_flip_pending);
++
++ if (output->pageflip_timer)
++ wl_event_source_timer_update(output->pageflip_timer,
++ backend->pageflip_timeout);
+
+- drm_output_set_cursor(output);
++ drm_output_set_cursor(state);
+
+ /*
+ * Now, update all the sprite surfaces
+ */
+- wl_list_for_each(s, &backend->sprite_list, link) {
++ wl_list_for_each(ps, &state->plane_list, link) {
+ uint32_t flags = 0, fb_id = 0;
+ drmVBlank vbl = {
+ .request.type = DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT,
+ .request.sequence = 1,
+ };
+
+- if ((!s->current && !s->next) ||
+- !drm_sprite_crtc_supported(output, s))
+- continue;
++ p = ps->plane;
++ if (p->type != WDRM_PLANE_TYPE_OVERLAY)
++ continue;
++
++ assert(p->state_cur->complete);
++ assert(!!p->state_cur->output == !!p->state_cur->fb);
++ assert(!p->state_cur->output || p->state_cur->output == output);
++ assert(!ps->complete);
++ assert(!ps->output || ps->output == output);
++ assert(!!ps->output == !!ps->fb);
++
++ if (ps->fb && !backend->sprites_hidden)
++ fb_id = ps->fb->fb_id;
++
++ ret = drmModeSetPlane(backend->drm.fd, p->plane_id,
++ output->crtc_id, fb_id, flags,
++ ps->dest_x, ps->dest_y,
++ ps->dest_w, ps->dest_h,
++ ps->src_x, ps->src_y,
++ ps->src_w, ps->src_h);
++ if (ret)
++ weston_log("setplane failed: %d: %s\n",
++ ret, strerror(errno));
++
++ vbl.request.type |= drm_waitvblank_pipe(output);
++
++ /*
++ * Queue a vblank signal so we know when the surface
++ * becomes active on the display or has been replaced.
++ */
++ vbl.request.signal = (unsigned long) ps;
++ ret = drmWaitVBlank(backend->drm.fd, &vbl);
++ if (ret) {
++ weston_log("vblank event request failed: %d: %s\n",
++ ret, strerror(errno));
++ }
++ }
++
++ if (dpms_prop->prop_id && state->dpms != output->state_cur->dpms) {
++ ret = drmModeConnectorSetProperty(backend->drm.fd,
++ output->connector_id,
++ dpms_prop->prop_id,
++ state->dpms);
++ if (ret) {
++ weston_log("DRM: DPMS: failed property set for %s\n",
++ output->base.name);
++ }
++ }
++
++ drm_output_assign_state(state, DRM_STATE_APPLY_ASYNC);
++
++ return 0;
++
++err:
++ output->cursor_view = NULL;
++ drm_output_state_free(state);
++ return -1;
++}
++
++#ifdef HAVE_DRM_ATOMIC
++static int
++crtc_add_prop(drmModeAtomicReq *req, struct drm_output *output,
++ enum wdrm_crtc_property prop, uint64_t val)
++{
++ struct drm_property_info *info = &output->props_crtc[prop];
++ int ret;
++
++ if (info->prop_id == 0)
++ return -1;
++
++ ret = drmModeAtomicAddProperty(req, output->crtc_id, info->prop_id,
++ val);
++ return (ret <= 0) ? -1 : 0;
++}
++
++static int
++connector_add_prop(drmModeAtomicReq *req, struct drm_output *output,
++ enum wdrm_connector_property prop, uint64_t val)
++{
++ struct drm_property_info *info = &output->props_conn[prop];
++ int ret;
++
++ if (info->prop_id == 0)
++ return -1;
++
++ ret = drmModeAtomicAddProperty(req, output->connector_id,
++ info->prop_id, val);
++ return (ret <= 0) ? -1 : 0;
++}
++
++static int
++plane_add_prop(drmModeAtomicReq *req, struct drm_plane *plane,
++ enum wdrm_plane_property prop, uint64_t val)
++{
++ struct drm_property_info *info = &plane->props[prop];
++ int ret;
++
++ if (info->prop_id == 0)
++ return -1;
++
++ ret = drmModeAtomicAddProperty(req, plane->plane_id, info->prop_id,
++ val);
++ return (ret <= 0) ? -1 : 0;
++}
++
++static int
++drm_mode_ensure_blob(struct drm_backend *backend, struct drm_mode *mode)
++{
++ int ret;
++
++ if (mode->blob_id)
++ return 0;
++
++ ret = drmModeCreatePropertyBlob(backend->drm.fd,
++ &mode->mode_info,
++ sizeof(mode->mode_info),
++ &mode->blob_id);
++ if (ret != 0)
++ weston_log("failed to create mode property blob: %m\n");
++
++ return ret;
++}
++
++static int
++drm_output_apply_state_atomic(struct drm_output_state *state,
++ drmModeAtomicReq *req,
++ uint32_t *flags)
++{
++ struct drm_output *output = state->output;
++ struct drm_backend *backend = to_drm_backend(output->base.compositor);
++ struct drm_plane_state *plane_state;
++ struct drm_mode *current_mode = to_drm_mode(output->base.current_mode);
++ int ret = 0;
++
++ if (state->dpms != output->state_cur->dpms)
++ *flags |= DRM_MODE_ATOMIC_ALLOW_MODESET;
++
++ if (state->dpms == WESTON_DPMS_ON) {
++ ret = drm_mode_ensure_blob(backend, current_mode);
++ if (ret != 0)
++ return ret;
++
++ ret |= crtc_add_prop(req, output, WDRM_CRTC_MODE_ID,
++ current_mode->blob_id);
++ ret |= crtc_add_prop(req, output, WDRM_CRTC_ACTIVE, 1);
++ ret |= connector_add_prop(req, output, WDRM_CONNECTOR_CRTC_ID,
++ output->crtc_id);
++ } else {
++ ret |= crtc_add_prop(req, output, WDRM_CRTC_MODE_ID, 0);
++ ret |= crtc_add_prop(req, output, WDRM_CRTC_ACTIVE, 0);
++ ret |= connector_add_prop(req, output, WDRM_CONNECTOR_CRTC_ID,
++ 0);
++ }
++
++ if (ret != 0) {
++ weston_log("couldn't set atomic CRTC/connector state\n");
++ return ret;
++ }
++
++ wl_list_for_each(plane_state, &state->plane_list, link) {
++ struct drm_plane *plane = plane_state->plane;
++
++ ret |= plane_add_prop(req, plane, WDRM_PLANE_FB_ID,
++ plane_state->fb ? plane_state->fb->fb_id : 0);
++ ret |= plane_add_prop(req, plane, WDRM_PLANE_CRTC_ID,
++ plane_state->fb ? output->crtc_id : 0);
++ ret |= plane_add_prop(req, plane, WDRM_PLANE_SRC_X,
++ plane_state->src_x);
++ ret |= plane_add_prop(req, plane, WDRM_PLANE_SRC_Y,
++ plane_state->src_y);
++ ret |= plane_add_prop(req, plane, WDRM_PLANE_SRC_W,
++ plane_state->src_w);
++ ret |= plane_add_prop(req, plane, WDRM_PLANE_SRC_H,
++ plane_state->src_h);
++ ret |= plane_add_prop(req, plane, WDRM_PLANE_CRTC_X,
++ plane_state->dest_x);
++ ret |= plane_add_prop(req, plane, WDRM_PLANE_CRTC_Y,
++ plane_state->dest_y);
++ ret |= plane_add_prop(req, plane, WDRM_PLANE_CRTC_W,
++ plane_state->dest_w);
++ ret |= plane_add_prop(req, plane, WDRM_PLANE_CRTC_H,
++ plane_state->dest_h);
++
++ if (ret != 0) {
++ weston_log("couldn't set plane state\n");
++ return ret;
++ }
++ }
++
++ return 0;
++}
++
++/**
++ * Helper function used only by drm_pending_state_apply, with the same
++ * guarantees and constraints as that function.
++ */
++static int
++drm_pending_state_apply_atomic(struct drm_pending_state *pending_state,
++ enum drm_state_apply_mode mode)
++{
++ struct drm_backend *b = pending_state->backend;
++ struct drm_output_state *output_state, *tmp;
++ struct drm_plane *plane;
++ drmModeAtomicReq *req = drmModeAtomicAlloc();
++ uint32_t flags = 0;
++ int ret = 0;
++
++ if (!req)
++ return -1;
++
++ if (b->state_invalid) {
++ uint32_t *unused;
++ int err;
++
++ /* If we need to reset all our state (e.g. because we've
++ * just started, or just been VT-switched in), explicitly
++ * disable all the CRTCs and connectors we aren't using. */
++ wl_array_for_each(unused, &b->unused_connectors) {
++ struct drm_property_info infos[WDRM_CONNECTOR__COUNT];
++ struct drm_property_info *info;
++ drmModeObjectProperties *props;
++
++ memset(infos, 0, sizeof(infos));
++
++ props = drmModeObjectGetProperties(b->drm.fd,
++ *unused,
++ DRM_MODE_OBJECT_CONNECTOR);
++ if (!props) {
++ ret = -1;
++ continue;
++ }
++
++ drm_property_info_populate(b, connector_props, infos,
++ WDRM_CONNECTOR__COUNT,
++ props);
++ drmModeFreeObjectProperties(props);
++
++ info = &infos[WDRM_CONNECTOR_CRTC_ID];
++ err = drmModeAtomicAddProperty(req, *unused,
++ info->prop_id, 0);
++ if (err <= 0)
++ ret = -1;
++
++ info = &infos[WDRM_CONNECTOR_DPMS];
++ if (info->prop_id > 0)
++ err = drmModeAtomicAddProperty(req, *unused,
++ info->prop_id,
++ DRM_MODE_DPMS_OFF);
++ if (err <= 0)
++ ret = -1;
++
++ drm_property_info_free(infos, WDRM_CONNECTOR__COUNT);
++ }
++
++ wl_array_for_each(unused, &b->unused_crtcs) {
++ struct drm_property_info infos[WDRM_CRTC__COUNT];
++ struct drm_property_info *info;
++ drmModeObjectProperties *props;
++ uint64_t active;
++
++ memset(infos, 0, sizeof(infos));
++
++ /* We can't emit a disable on a CRTC that's already
++ * off, as the kernel will refuse to generate an event
++ * for an off->off state and fail the commit.
++ */
++ props = drmModeObjectGetProperties(b->drm.fd,
++ *unused,
++ DRM_MODE_OBJECT_CRTC);
++ if (!props) {
++ ret = -1;
++ continue;
++ }
++
++ drm_property_info_populate(b, crtc_props, infos,
++ WDRM_CRTC__COUNT,
++ props);
++
++ info = &infos[WDRM_CRTC_ACTIVE];
++ active = drm_property_get_value(info, props, 0);
++ drmModeFreeObjectProperties(props);
++ if (active == 0) {
++ drm_property_info_free(infos, WDRM_CRTC__COUNT);
++ continue;
++ }
++
++ err = drmModeAtomicAddProperty(req, *unused,
++ info->prop_id, 0);
++ if (err <= 0)
++ ret = -1;
++
++ info = &infos[WDRM_CRTC_MODE_ID];
++ err = drmModeAtomicAddProperty(req, *unused,
++ info->prop_id, 0);
++ if (err <= 0)
++ ret = -1;
++
++ drm_property_info_free(infos, WDRM_CRTC__COUNT);
++ }
++
++ /* Disable all the planes; planes which are being used will
++ * override this state in the output-state application. */
++ wl_list_for_each(plane, &b->plane_list, link) {
++ plane_add_prop(req, plane, WDRM_PLANE_CRTC_ID, 0);
++ plane_add_prop(req, plane, WDRM_PLANE_FB_ID, 0);
++ }
++
++ flags |= DRM_MODE_ATOMIC_ALLOW_MODESET;
++ }
++
++ wl_list_for_each(output_state, &pending_state->output_list, link) {
++ if (mode == DRM_STATE_APPLY_SYNC)
++ assert(output_state->dpms == WESTON_DPMS_OFF);
++ ret |= drm_output_apply_state_atomic(output_state, req, &flags);
++ }
++
++ if (ret != 0) {
++ weston_log("atomic: couldn't compile atomic state\n");
++ goto out;
++ }
++
++ switch (mode) {
++ case DRM_STATE_APPLY_SYNC:
++ break;
++ case DRM_STATE_APPLY_ASYNC:
++ flags |= DRM_MODE_PAGE_FLIP_EVENT | DRM_MODE_ATOMIC_NONBLOCK;
++ break;
++ }
++
++ ret = drmModeAtomicCommit(b->drm.fd, req, flags, b);
++ if (ret != 0) {
++ weston_log("atomic: couldn't commit new state: %m\n");
++ goto out;
++ }
++
++ wl_list_for_each_safe(output_state, tmp, &pending_state->output_list,
++ link)
++ drm_output_assign_state(output_state, mode);
++
++ b->state_invalid = false;
++
++ assert(wl_list_empty(&pending_state->output_list));
++
++out:
++ drmModeAtomicFree(req);
++ drm_pending_state_free(pending_state);
++ return ret;
++}
++#endif
++
++/**
++ * Applies all of a pending_state asynchronously: the primary entry point for
++ * applying KMS state to a device. Updates the state for all outputs in the
++ * pending_state, as well as disabling any unclaimed outputs.
++ *
++ * Unconditionally takes ownership of pending_state, and clears state_invalid.
++ */
++static int
++drm_pending_state_apply(struct drm_pending_state *pending_state)
++{
++ struct drm_backend *b = pending_state->backend;
++ struct drm_output_state *output_state, *tmp;
++ uint32_t *unused;
++
++#ifdef HAVE_DRM_ATOMIC
++ if (b->atomic_modeset)
++ return drm_pending_state_apply_atomic(pending_state,
++ DRM_STATE_APPLY_ASYNC);
++#endif
++
++ if (b->state_invalid) {
++ /* If we need to reset all our state (e.g. because we've
++ * just started, or just been VT-switched in), explicitly
++ * disable all the CRTCs we aren't using. This also disables
++ * all connectors on these CRTCs, so we don't need to do that
++ * separately with the pre-atomic API. */
++ wl_array_for_each(unused, &b->unused_crtcs)
++ drmModeSetCrtc(b->drm.fd, *unused, 0, 0, 0, NULL, 0,
++ NULL);
++ }
++
++ wl_list_for_each_safe(output_state, tmp, &pending_state->output_list,
++ link) {
++ struct drm_output *output = output_state->output;
++ int ret;
++
++ ret = drm_output_apply_state_legacy(output_state);
++ if (ret != 0) {
++ weston_log("Couldn't apply state for output %s\n",
++ output->base.name);
++ }
++ }
++
++ b->state_invalid = false;
++
++ assert(wl_list_empty(&pending_state->output_list));
++
++ drm_pending_state_free(pending_state);
++
++ return 0;
++}
++
++/**
++ * The synchronous version of drm_pending_state_apply. May only be used to
++ * disable outputs. Does so synchronously: the request is guaranteed to have
++ * completed on return, and the output will not be touched afterwards.
++ *
++ * Unconditionally takes ownership of pending_state, and clears state_invalid.
++ */
++static int
++drm_pending_state_apply_sync(struct drm_pending_state *pending_state)
++{
++ struct drm_backend *b = pending_state->backend;
++ struct drm_output_state *output_state, *tmp;
++ uint32_t *unused;
++
++#ifdef HAVE_DRM_ATOMIC
++ if (b->atomic_modeset)
++ return drm_pending_state_apply_atomic(pending_state,
++ DRM_STATE_APPLY_SYNC);
++#endif
++
++ if (b->state_invalid) {
++ /* If we need to reset all our state (e.g. because we've
++ * just started, or just been VT-switched in), explicitly
++ * disable all the CRTCs we aren't using. This also disables
++ * all connectors on these CRTCs, so we don't need to do that
++ * separately with the pre-atomic API. */
++ wl_array_for_each(unused, &b->unused_crtcs)
++ drmModeSetCrtc(b->drm.fd, *unused, 0, 0, 0, NULL, 0,
++ NULL);
++ }
++
++ wl_list_for_each_safe(output_state, tmp, &pending_state->output_list,
++ link) {
++ int ret;
++
++ assert(output_state->dpms == WESTON_DPMS_OFF);
++ ret = drm_output_apply_state_legacy(output_state);
++ if (ret != 0) {
++ weston_log("Couldn't apply state for output %s\n",
++ output_state->output->base.name);
++ }
++ }
++
++ b->state_invalid = false;
+
+- if (s->next && !backend->sprites_hidden)
+- fb_id = s->next->fb_id;
++ assert(wl_list_empty(&pending_state->output_list));
+
+- ret = drmModeSetPlane(backend->drm.fd, s->plane_id,
+- output->crtc_id, fb_id, flags,
+- s->dest_x, s->dest_y,
+- s->dest_w, s->dest_h,
+- s->src_x, s->src_y,
+- s->src_w, s->src_h);
+- if (ret)
+- weston_log("setplane failed: %d: %s\n",
+- ret, strerror(errno));
++ drm_pending_state_free(pending_state);
+
+- vbl.request.type |= drm_waitvblank_pipe(output);
++ return 0;
++}
+
+- /*
+- * Queue a vblank signal so we know when the surface
+- * becomes active on the display or has been replaced.
+- */
+- vbl.request.signal = (unsigned long)s;
+- ret = drmWaitVBlank(backend->drm.fd, &vbl);
+- if (ret) {
+- weston_log("vblank event request failed: %d: %s\n",
+- ret, strerror(errno));
+- }
++static int
++drm_output_repaint(struct weston_output *output_base,
++ pixman_region32_t *damage,
++ void *repaint_data)
++{
++ struct drm_pending_state *pending_state = repaint_data;
++ struct drm_output *output = to_drm_output(output_base);
++ struct drm_output_state *state = NULL;
++ struct drm_plane_state *scanout_state;
+
+- s->output = output;
+- output->vblank_pending = 1;
+- }
++ if (output->disable_pending || output->destroy_pending)
++ goto err;
+
+- return 0;
++ assert(!output->state_last);
++
++ /* If planes have been disabled in the core, we might not have
++ * hit assign_planes at all, so might not have valid output state
++ * here. */
++ state = drm_pending_state_get_output(pending_state, output);
++ if (!state)
++ state = drm_output_state_duplicate(output->state_cur,
++ pending_state,
++ DRM_OUTPUT_STATE_CLEAR_PLANES);
++ state->dpms = WESTON_DPMS_ON;
++
++ drm_output_render(state, damage);
++ scanout_state = drm_output_state_get_plane(state,
++ output->scanout_plane);
++ if (!scanout_state || !scanout_state->fb)
++ goto err;
+
+-err_pageflip:
+- output->cursor_view = NULL;
+- if (output->next) {
+- drm_output_release_fb(output, output->next);
+- output->next = NULL;
+- }
++ return 0;
+
++err:
++ drm_output_state_free(state);
+ return -1;
+ }
+
+@@ -800,9 +2402,10 @@ static void
+ drm_output_start_repaint_loop(struct weston_output *output_base)
+ {
+ struct drm_output *output = to_drm_output(output_base);
++ struct drm_pending_state *pending_state;
++ struct drm_plane *scanout_plane = output->scanout_plane;
+ struct drm_backend *backend =
+ to_drm_backend(output_base->compositor);
+- uint32_t fb_id;
+ struct timespec ts, tnow;
+ struct timespec vbl2now;
+ int64_t refresh_nsec;
+@@ -816,11 +2419,19 @@ drm_output_start_repaint_loop(struct weston_output *output_base)
+ if (output->disable_pending || output->destroy_pending)
+ return;
+
+- if (!output->current) {
++ if (!output->scanout_plane->state_cur->fb) {
+ /* We can't page flip if there's no mode set */
+ goto finish_frame;
+ }
+
++ /* Need to smash all state in from scratch; current timings might not
++ * be what we want, page flip might not work, etc.
++ */
++ if (backend->state_invalid)
++ goto finish_frame;
++
++ assert(scanout_plane->state_cur->output == output);
++
+ /* Try to get current msc and timestamp via instant query */
+ vbl.request.type |= drm_waitvblank_pipe(output);
+ ret = drmWaitVBlank(backend->drm.fd, &vbl);
+@@ -850,11 +2461,17 @@ drm_output_start_repaint_loop(struct weston_output *output_base)
+ /* Immediate query didn't provide valid timestamp.
+ * Use pageflip fallback.
+ */
+- fb_id = output->current->fb_id;
+
+- if (drmModePageFlip(backend->drm.fd, output->crtc_id, fb_id,
+- DRM_MODE_PAGE_FLIP_EVENT, output) < 0) {
+- weston_log("queueing pageflip failed: %m\n");
++ assert(!output->page_flip_pending);
++ assert(!output->state_last);
++
++ pending_state = drm_pending_state_alloc(backend);
++ drm_output_state_duplicate(output->state_cur, pending_state,
++ DRM_OUTPUT_STATE_PRESERVE_PLANES);
++
++ ret = drm_pending_state_apply(pending_state);
++ if (ret != 0) {
++ weston_log("applying repaint-start state failed: %m\n");
+ goto finish_frame;
+ }
+
+@@ -862,8 +2479,7 @@ drm_output_start_repaint_loop(struct weston_output *output_base)
+
+ finish_frame:
+ /* if we cannot page-flip, immediately finish frame */
+- weston_compositor_read_presentation_clock(output_base->compositor, &ts);
+- weston_output_finish_frame(output_base, &ts,
++ weston_output_finish_frame(output_base, NULL,
+ WP_PRESENTATION_FEEDBACK_INVALID);
+ }
+
+@@ -882,70 +2498,132 @@ static void
+ vblank_handler(int fd, unsigned int frame, unsigned int sec, unsigned int usec,
+ void *data)
+ {
+- struct drm_sprite *s = (struct drm_sprite *)data;
+- struct drm_output *output = s->output;
+- struct timespec ts;
++ struct drm_plane_state *ps = (struct drm_plane_state *) data;
++ struct drm_output_state *os = ps->output_state;
++ struct drm_output *output = os->output;
++ struct drm_backend *b = to_drm_backend(output->base.compositor);
+ uint32_t flags = WP_PRESENTATION_FEEDBACK_KIND_HW_COMPLETION |
+ WP_PRESENTATION_FEEDBACK_KIND_HW_CLOCK;
+
++ assert(!b->atomic_modeset);
++
+ drm_output_update_msc(output, frame);
+- output->vblank_pending = 0;
++ output->vblank_pending--;
++ assert(output->vblank_pending >= 0);
+
+- drm_output_release_fb(output, s->current);
+- s->current = s->next;
+- s->next = NULL;
++ assert(ps->fb);
+
+- if (!output->page_flip_pending) {
+- ts.tv_sec = sec;
+- ts.tv_nsec = usec * 1000;
+- weston_output_finish_frame(&output->base, &ts, flags);
+- }
+-}
++ if (output->page_flip_pending || output->vblank_pending)
++ return;
+
+-static void
+-drm_output_destroy(struct weston_output *base);
++ drm_output_update_complete(output, flags, sec, usec);
++}
+
+ static void
+ page_flip_handler(int fd, unsigned int frame,
+ unsigned int sec, unsigned int usec, void *data)
+ {
+ struct drm_output *output = data;
+- struct timespec ts;
++ struct drm_backend *b = to_drm_backend(output->base.compositor);
+ uint32_t flags = WP_PRESENTATION_FEEDBACK_KIND_VSYNC |
+ WP_PRESENTATION_FEEDBACK_KIND_HW_COMPLETION |
+ WP_PRESENTATION_FEEDBACK_KIND_HW_CLOCK;
+
+ drm_output_update_msc(output, frame);
+
+- /* We don't set page_flip_pending on start_repaint_loop, in that case
+- * we just want to page flip to the current buffer to get an accurate
+- * timestamp */
+- if (output->page_flip_pending) {
+- drm_output_release_fb(output, output->current);
+- output->current = output->next;
+- output->next = NULL;
+- }
+-
++ assert(!b->atomic_modeset);
++ assert(output->page_flip_pending);
+ output->page_flip_pending = 0;
+
+- if (output->destroy_pending)
+- drm_output_destroy(&output->base);
+- else if (output->disable_pending)
+- weston_output_disable(&output->base);
+- else if (!output->vblank_pending) {
+- ts.tv_sec = sec;
+- ts.tv_nsec = usec * 1000;
+- weston_output_finish_frame(&output->base, &ts, flags);
++ if (output->vblank_pending)
++ return;
+
+- /* We can't call this from frame_notify, because the output's
+- * repaint needed flag is cleared just after that */
+- if (output->recorder)
+- weston_output_schedule_repaint(&output->base);
+- }
++ drm_output_update_complete(output, flags, sec, usec);
++}
++
++/**
++ * Begin a new repaint cycle
++ *
++ * Called by the core compositor at the beginning of a repaint cycle. Creates
++ * a new pending_state structure to own any output state created by individual
++ * output repaint functions until the repaint is flushed or cancelled.
++ */
++static void *
++drm_repaint_begin(struct weston_compositor *compositor)
++{
++ struct drm_backend *b = to_drm_backend(compositor);
++ struct drm_pending_state *ret;
++
++ ret = drm_pending_state_alloc(b);
++ b->repaint_data = ret;
++
++ return ret;
++}
++
++/**
++ * Flush a repaint set
++ *
++ * Called by the core compositor when a repaint cycle has been completed
++ * and should be flushed. Frees the pending state, transitioning ownership
++ * of the output state from the pending state, to the update itself. When
++ * the update completes (see drm_output_update_complete), the output
++ * state will be freed.
++ */
++static void
++drm_repaint_flush(struct weston_compositor *compositor, void *repaint_data)
++{
++ struct drm_backend *b = to_drm_backend(compositor);
++ struct drm_pending_state *pending_state = repaint_data;
++
++ drm_pending_state_apply(pending_state);
++ b->repaint_data = NULL;
++}
++
++/**
++ * Cancel a repaint set
++ *
++ * Called by the core compositor when a repaint has finished, so the data
++ * held across the repaint cycle should be discarded.
++ */
++static void
++drm_repaint_cancel(struct weston_compositor *compositor, void *repaint_data)
++{
++ struct drm_backend *b = to_drm_backend(compositor);
++ struct drm_pending_state *pending_state = repaint_data;
++
++ drm_pending_state_free(pending_state);
++ b->repaint_data = NULL;
++}
++
++#ifdef HAVE_DRM_ATOMIC
++static void
++atomic_flip_handler(int fd, unsigned int frame, unsigned int sec,
++ unsigned int usec, unsigned int crtc_id, void *data)
++{
++ struct drm_backend *b = data;
++ struct drm_output *output = drm_output_find_by_crtc(b, crtc_id);
++ uint32_t flags = WP_PRESENTATION_FEEDBACK_KIND_VSYNC |
++ WP_PRESENTATION_FEEDBACK_KIND_HW_COMPLETION |
++ WP_PRESENTATION_FEEDBACK_KIND_HW_CLOCK;
++
++ /* During the initial modeset, we can disable CRTCs which we don't
++ * actually handle during normal operation; this will give us events
++ * for unknown outputs. Ignore them. */
++ if (!output || !output->base.enabled)
++ return;
++
++ drm_output_update_msc(output, frame);
++
++ assert(b->atomic_modeset);
++ assert(output->atomic_complete_pending);
++ output->atomic_complete_pending = 0;
++
++ drm_output_update_complete(output, flags, sec, usec);
+ }
++#endif
+
+ static uint32_t
+-drm_output_check_sprite_format(struct drm_sprite *s,
++drm_output_check_plane_format(struct drm_plane *p,
+ struct weston_view *ev, struct gbm_bo *bo)
+ {
+ uint32_t i, format;
+@@ -966,31 +2644,25 @@ drm_output_check_sprite_format(struct drm_sprite *s,
+ pixman_region32_fini(&r);
+ }
+
+- for (i = 0; i < s->count_formats; i++)
+- if (s->formats[i] == format)
++ for (i = 0; i < p->count_formats; i++)
++ if (p->formats[i] == format)
+ return format;
+
+ return 0;
+ }
+
+-static int
+-drm_view_transform_supported(struct weston_view *ev)
+-{
+- return !ev->transform.enabled ||
+- (ev->transform.matrix.type < WESTON_MATRIX_TRANSFORM_ROTATE);
+-}
+-
+ static struct weston_plane *
+-drm_output_prepare_overlay_view(struct drm_output *output,
++drm_output_prepare_overlay_view(struct drm_output_state *output_state,
+ struct weston_view *ev)
+ {
++ struct drm_output *output = output_state->output;
+ struct weston_compositor *ec = output->base.compositor;
+ struct drm_backend *b = to_drm_backend(ec);
+ struct weston_buffer_viewport *viewport = &ev->surface->buffer_viewport;
+ struct wl_resource *buffer_resource;
+- struct drm_sprite *s;
++ struct drm_plane *p;
++ struct drm_plane_state *state = NULL;
+ struct linux_dmabuf_buffer *dmabuf;
+- int found = 0;
+ struct gbm_bo *bo;
+ pixman_region32_t dest_rect, src_rect;
+ pixman_box32_t *box, tbox;
+@@ -1024,18 +2696,24 @@ drm_output_prepare_overlay_view(struct drm_output *output,
+ if (ev->alpha != 1.0f)
+ return NULL;
+
+- wl_list_for_each(s, &b->sprite_list, link) {
+- if (!drm_sprite_crtc_supported(output, s))
++ wl_list_for_each(p, &b->plane_list, link) {
++ if (p->type != WDRM_PLANE_TYPE_OVERLAY)
+ continue;
+
+- if (!s->next) {
+- found = 1;
+- break;
++ if (!drm_plane_is_available(p, output))
++ continue;
++
++ state = drm_output_state_get_plane(output_state, p);
++ if (state->fb) {
++ state = NULL;
++ continue;
+ }
++
++ break;
+ }
+
+ /* No sprites available */
+- if (!found)
++ if (!state)
+ return NULL;
+
+ if ((dmabuf = linux_dmabuf_buffer_get(buffer_resource))) {
+@@ -1072,32 +2750,30 @@ drm_output_prepare_overlay_view(struct drm_output *output,
+ bo = gbm_bo_import(b->gbm, GBM_BO_IMPORT_FD, &gbm_dmabuf,
+ GBM_BO_USE_SCANOUT);
+ #else
+- return NULL;
++ goto err;
+ #endif
+ } else {
+ bo = gbm_bo_import(b->gbm, GBM_BO_IMPORT_WL_BUFFER,
+ buffer_resource, GBM_BO_USE_SCANOUT);
+ }
+ if (!bo)
+- return NULL;
++ goto err;
+
+- format = drm_output_check_sprite_format(s, ev, bo);
+- if (format == 0) {
+- gbm_bo_destroy(bo);
+- return NULL;
+- }
++ format = drm_output_check_plane_format(p, ev, bo);
++ if (format == 0)
++ goto err;
+
+- s->next = drm_fb_get_from_bo(bo, b, format);
+- if (!s->next) {
+- gbm_bo_destroy(bo);
+- return NULL;
+- }
++ state->fb = drm_fb_get_from_bo(bo, b, format, BUFFER_CLIENT);
++ if (!state->fb)
++ goto err;
++
++ drm_fb_set_buffer(state->fb, ev->surface->buffer_ref.buffer);
+
+- drm_fb_set_buffer(s->next, ev->surface->buffer_ref.buffer);
++ state->output = output;
+
+ box = pixman_region32_extents(&ev->transform.boundingbox);
+- s->plane.x = box->x1;
+- s->plane.y = box->y1;
++ p->base.x = box->x1;
++ p->base.y = box->y1;
+
+ /*
+ * Calculate the source & dest rects properly based on actual
+@@ -1114,10 +2790,10 @@ drm_output_prepare_overlay_view(struct drm_output *output,
+ output->base.transform,
+ output->base.current_scale,
+ *box);
+- s->dest_x = tbox.x1;
+- s->dest_y = tbox.y1;
+- s->dest_w = tbox.x2 - tbox.x1;
+- s->dest_h = tbox.y2 - tbox.y1;
++ state->dest_x = tbox.x1;
++ state->dest_y = tbox.y1;
++ state->dest_w = tbox.x2 - tbox.x1;
++ state->dest_h = tbox.y2 - tbox.y1;
+ pixman_region32_fini(&dest_rect);
+
+ pixman_region32_init(&src_rect);
+@@ -1154,27 +2830,83 @@ drm_output_prepare_overlay_view(struct drm_output *output,
+ viewport->buffer.scale,
+ tbox);
+
+- s->src_x = tbox.x1 << 8;
+- s->src_y = tbox.y1 << 8;
+- s->src_w = (tbox.x2 - tbox.x1) << 8;
+- s->src_h = (tbox.y2 - tbox.y1) << 8;
++ state->src_x = tbox.x1 << 8;
++ state->src_y = tbox.y1 << 8;
++ state->src_w = (tbox.x2 - tbox.x1) << 8;
++ state->src_h = (tbox.y2 - tbox.y1) << 8;
+ pixman_region32_fini(&src_rect);
+
+- return &s->plane;
++ return &p->base;
++
++err:
++ drm_plane_state_put_back(state);
++ if (bo)
++ gbm_bo_destroy(bo);
++ return NULL;
++}
++
++/**
++ * Update the image for the current cursor surface
++ *
++ * @param b DRM backend structure
++ * @param bo GBM buffer object to write into
++ * @param ev View to use for cursor image
++ */
++static void
++cursor_bo_update(struct drm_backend *b, struct gbm_bo *bo,
++ struct weston_view *ev)
++{
++ struct weston_buffer *buffer = ev->surface->buffer_ref.buffer;
++ uint32_t buf[b->cursor_width * b->cursor_height];
++ int32_t stride;
++ uint8_t *s;
++ int i;
++
++ assert(buffer && buffer->shm_buffer);
++ assert(buffer->shm_buffer == wl_shm_buffer_get(buffer->resource));
++ assert(ev->surface->width <= b->cursor_width);
++ assert(ev->surface->height <= b->cursor_height);
++
++ memset(buf, 0, sizeof buf);
++ stride = wl_shm_buffer_get_stride(buffer->shm_buffer);
++ s = wl_shm_buffer_get_data(buffer->shm_buffer);
++
++ wl_shm_buffer_begin_access(buffer->shm_buffer);
++ for (i = 0; i < ev->surface->height; i++)
++ memcpy(buf + i * b->cursor_width,
++ s + i * stride,
++ ev->surface->width * 4);
++ wl_shm_buffer_end_access(buffer->shm_buffer);
++
++ if (gbm_bo_write(bo, buf, sizeof buf) < 0)
++ weston_log("failed update cursor: %m\n");
+ }
+
+ static struct weston_plane *
+-drm_output_prepare_cursor_view(struct drm_output *output,
++drm_output_prepare_cursor_view(struct drm_output_state *output_state,
+ struct weston_view *ev)
+ {
++ struct drm_output *output = output_state->output;
+ struct drm_backend *b = to_drm_backend(output->base.compositor);
++ struct drm_plane *plane = output->cursor_plane;
++ struct drm_plane_state *plane_state;
+ struct weston_buffer_viewport *viewport = &ev->surface->buffer_viewport;
+ struct wl_shm_buffer *shmbuf;
++ bool needs_update = false;
++ float x, y;
+
++ if (!plane)
++ return NULL;
++
++#if 0
+ if (b->cursors_are_broken)
+ return NULL;
++#endif
++
++ if (!plane->state_cur->complete)
++ return NULL;
+
+- if (output->cursor_view)
++ if (plane->state_cur->output && plane->state_cur->output != output)
+ return NULL;
+
+ /* Don't import buffers which span multiple outputs. */
+@@ -1207,111 +2939,120 @@ drm_output_prepare_cursor_view(struct drm_output *output,
+ ev->surface->height > b->cursor_height)
+ return NULL;
+
+- output->cursor_view = ev;
+-
+- return &output->cursor_plane;
+-}
+-
+-/**
+- * Update the image for the current cursor surface
+- *
+- * @param b DRM backend structure
+- * @param bo GBM buffer object to write into
+- * @param ev View to use for cursor image
+- */
+-static void
+-cursor_bo_update(struct drm_backend *b, struct gbm_bo *bo,
+- struct weston_view *ev)
+-{
+- struct weston_buffer *buffer = ev->surface->buffer_ref.buffer;
+- uint32_t buf[b->cursor_width * b->cursor_height];
+- int32_t stride;
+- uint8_t *s;
+- int i;
+-
+- assert(buffer && buffer->shm_buffer);
+- assert(buffer->shm_buffer == wl_shm_buffer_get(buffer->resource));
+- assert(ev->surface->width <= b->cursor_width);
+- assert(ev->surface->height <= b->cursor_height);
++ plane_state =
++ drm_output_state_get_plane(output_state, output->cursor_plane);
+
+- memset(buf, 0, sizeof buf);
+- stride = wl_shm_buffer_get_stride(buffer->shm_buffer);
+- s = wl_shm_buffer_get_data(buffer->shm_buffer);
++ if (plane_state && plane_state->fb)
++ return NULL;
+
+- wl_shm_buffer_begin_access(buffer->shm_buffer);
+- for (i = 0; i < ev->surface->height; i++)
+- memcpy(buf + i * b->cursor_width,
+- s + i * stride,
+- ev->surface->width * 4);
+- wl_shm_buffer_end_access(buffer->shm_buffer);
++ /* Since we're setting plane state up front, we need to work out
++ * whether or not we need to upload a new cursor. We can't use the
++ * plane damage, since the planes haven't actually been calculated
++ * yet: instead try to figure it out directly. KMS cursor planes are
++ * pretty unique here, in that they lie partway between a Weston plane
++ * (direct scanout) and a renderer. */
++ if (ev != output->cursor_view ||
++ pixman_region32_not_empty(&ev->surface->damage)) {
++ output->current_cursor++;
++ output->current_cursor =
++ output->current_cursor %
++ ARRAY_LENGTH(output->gbm_cursor_fb);
++ needs_update = true;
++ }
+
+- if (gbm_bo_write(bo, buf, sizeof buf) < 0)
+- weston_log("failed update cursor: %m\n");
++ output->cursor_view = ev;
++ weston_view_to_global_float(ev, 0, 0, &x, &y);
++ plane->base.x = x;
++ plane->base.y = y;
++
++ plane_state->fb =
++ drm_fb_ref(output->gbm_cursor_fb[output->current_cursor]);
++ plane_state->output = output;
++ plane_state->src_x = 0;
++ plane_state->src_y = 0;
++ plane_state->src_w = b->cursor_width << 16;
++ plane_state->src_h = b->cursor_height << 16;
++ plane_state->dest_x = (x - output->base.x) * output->base.current_scale;
++ plane_state->dest_y = (y - output->base.y) * output->base.current_scale;
++ plane_state->dest_w = b->cursor_width;
++ plane_state->dest_h = b->cursor_height;
++
++ if (needs_update)
++ cursor_bo_update(b, plane_state->fb->bo, ev);
++
++ return &plane->base;
+ }
+
+ static void
+-drm_output_set_cursor(struct drm_output *output)
++drm_output_set_cursor(struct drm_output_state *output_state)
+ {
+- struct weston_view *ev = output->cursor_view;
+- struct weston_buffer *buffer;
++ struct drm_output *output = output_state->output;
+ struct drm_backend *b = to_drm_backend(output->base.compositor);
++ struct drm_plane *plane = output->cursor_plane;
++ struct drm_plane_state *state;
+ EGLint handle;
+ struct gbm_bo *bo;
+- float x, y;
+
+- output->cursor_view = NULL;
+- if (ev == NULL) {
++ if (!plane)
++ return;
++
++ state = drm_output_state_get_existing_plane(output_state, plane);
++ if (!state)
++ return;
++
++ if (!state->fb) {
++ pixman_region32_fini(&plane->base.damage);
++ pixman_region32_init(&plane->base.damage);
+ drmModeSetCursor(b->drm.fd, output->crtc_id, 0, 0, 0);
+- output->cursor_plane.x = INT32_MIN;
+- output->cursor_plane.y = INT32_MIN;
+ return;
+ }
+
+- buffer = ev->surface->buffer_ref.buffer;
+-
+- if (buffer &&
+- pixman_region32_not_empty(&output->cursor_plane.damage)) {
+- pixman_region32_fini(&output->cursor_plane.damage);
+- pixman_region32_init(&output->cursor_plane.damage);
+- output->current_cursor ^= 1;
+- bo = output->gbm_cursor_bo[output->current_cursor];
++ assert(state->fb == output->gbm_cursor_fb[output->current_cursor]);
++ assert(!plane->state_cur->output || plane->state_cur->output == output);
+
+- cursor_bo_update(b, bo, ev);
++ if (plane->state_cur->fb != state->fb) {
++ bo = state->fb->bo;
+ handle = gbm_bo_get_handle(bo).s32;
+ if (drmModeSetCursor(b->drm.fd, output->crtc_id, handle,
+- b->cursor_width, b->cursor_height)) {
++ b->cursor_width, b->cursor_height)) {
+ weston_log("failed to set cursor: %m\n");
+- b->cursors_are_broken = 1;
++ goto err;
+ }
+ }
+
+- weston_view_to_global_float(ev, 0, 0, &x, &y);
++ pixman_region32_fini(&plane->base.damage);
++ pixman_region32_init(&plane->base.damage);
+
+- /* From global to output space, output transform is guaranteed to be
+- * NORMAL by drm_output_prepare_cursor_view().
+- */
+- x = (x - output->base.x) * output->base.current_scale;
+- y = (y - output->base.y) * output->base.current_scale;
++ if (drmModeMoveCursor(b->drm.fd, output->crtc_id,
++ state->dest_x, state->dest_y)) {
++ weston_log("failed to move cursor: %m\n");
++ goto err;
++ }
+
+- if (output->cursor_plane.x != x || output->cursor_plane.y != y) {
+- if (drmModeMoveCursor(b->drm.fd, output->crtc_id, x, y)) {
+- weston_log("failed to move cursor: %m\n");
+- b->cursors_are_broken = 1;
+- }
++ return;
+
+- output->cursor_plane.x = x;
+- output->cursor_plane.y = y;
+- }
++err:
++ b->cursors_are_broken = 1;
++ drmModeSetCursor(b->drm.fd, output->crtc_id, 0, 0, 0);
+ }
+
+ static void
+-drm_assign_planes(struct weston_output *output_base)
++drm_assign_planes(struct weston_output *output_base, void *repaint_data)
+ {
+ struct drm_backend *b = to_drm_backend(output_base->compositor);
++ struct drm_pending_state *pending_state = repaint_data;
+ struct drm_output *output = to_drm_output(output_base);
+- struct weston_view *ev, *next;
+- pixman_region32_t overlap, surface_overlap;
++ struct drm_output_state *state;
++ struct drm_plane_state *plane_state;
++ struct weston_view *ev;
++ pixman_region32_t surface_overlap, renderer_region;
+ struct weston_plane *primary, *next_plane;
++ bool picked_scanout = false;
++
++ assert(!output->state_last);
++ state = drm_output_state_duplicate(output->state_cur,
++ pending_state,
++ DRM_OUTPUT_STATE_CLEAR_PLANES);
+
+ /*
+ * Find a surface for each sprite in the output using some heuristics:
+@@ -1326,10 +3067,10 @@ drm_assign_planes(struct weston_output *output_base)
+ * the client buffer can be used directly for the sprite surface
+ * as we do for flipping full screen surfaces.
+ */
+- pixman_region32_init(&overlap);
++ pixman_region32_init(&renderer_region);
+ primary = &output_base->compositor->primary_plane;
+
+- wl_list_for_each_safe(ev, next, &output_base->compositor->view_list, link) {
++ wl_list_for_each(ev, &output_base->compositor->view_list, link) {
+ struct weston_surface *es = ev->surface;
+
+ /* Test whether this buffer can ever go into a plane:
+@@ -1350,29 +3091,40 @@ drm_assign_planes(struct weston_output *output_base)
+ es->keep_buffer = false;
+
+ pixman_region32_init(&surface_overlap);
+- pixman_region32_intersect(&surface_overlap, &overlap,
++ pixman_region32_intersect(&surface_overlap, &renderer_region,
+ &ev->transform.boundingbox);
+
+ next_plane = NULL;
+- if (pixman_region32_not_empty(&surface_overlap))
++ if (pixman_region32_not_empty(&surface_overlap) || picked_scanout)
+ next_plane = primary;
+ if (next_plane == NULL)
+- next_plane = drm_output_prepare_cursor_view(output, ev);
+- if (next_plane == NULL)
+- next_plane = drm_output_prepare_scanout_view(output, ev);
++ next_plane = drm_output_prepare_cursor_view(state, ev);
++
++ /* If a higher-stacked view already got assigned to scanout, it's incorrect to
++ * assign a subsequent (lower-stacked) view to scanout.
++ */
++ if (next_plane == NULL) {
++ next_plane = drm_output_prepare_scanout_view(state, ev);
++ if (next_plane)
++ picked_scanout = true;
++ }
++
+ if (next_plane == NULL)
+- next_plane = drm_output_prepare_overlay_view(output, ev);
++ next_plane = drm_output_prepare_overlay_view(state, ev);
++
+ if (next_plane == NULL)
+ next_plane = primary;
+
+ weston_view_move_to_plane(ev, next_plane);
+
+ if (next_plane == primary)
+- pixman_region32_union(&overlap, &overlap,
++ pixman_region32_union(&renderer_region,
++ &renderer_region,
+ &ev->transform.boundingbox);
+
+ if (next_plane == primary ||
+- next_plane == &output->cursor_plane) {
++ (output->cursor_plane &&
++ next_plane == &output->cursor_plane->base)) {
+ /* cursor plane involves a copy */
+ ev->psf_flags = 0;
+ } else {
+@@ -1384,7 +3136,20 @@ drm_assign_planes(struct weston_output *output_base)
+
+ pixman_region32_fini(&surface_overlap);
+ }
+- pixman_region32_fini(&overlap);
++ pixman_region32_fini(&renderer_region);
++
++ /* We rely on output->cursor_view being both an accurate reflection of
++ * the cursor plane's state, but also being maintained across repaints
++ * to avoid unnecessary damage uploads, per the comment in
++ * drm_output_prepare_cursor_view. In the event that we go from having
++ * a cursor view to not having a cursor view, we need to clear it. */
++ if (output->cursor_view) {
++ plane_state =
++ drm_output_state_get_existing_plane(state,
++ output->cursor_plane);
++ if (!plane_state || !plane_state->fb)
++ output->cursor_view = NULL;
++ }
+ }
+
+ /**
+@@ -1407,7 +3172,7 @@ choose_mode (struct drm_output *output, struct weston_mode *target_mode)
+ output->base.current_mode->height == target_mode->height &&
+ (output->base.current_mode->refresh == target_mode->refresh ||
+ target_mode->refresh == 0))
+- return (struct drm_mode *)output->base.current_mode;
++ return to_drm_mode(output->base.current_mode);
+
+ wl_list_for_each(mode, &output->base.mode_list, base.link) {
+ if (mode->mode_info.hdisplay == target_mode->width &&
+@@ -1435,26 +3200,13 @@ drm_output_fini_pixman(struct drm_output *output);
+ static int
+ drm_output_switch_mode(struct weston_output *output_base, struct weston_mode *mode)
+ {
+- struct drm_output *output;
+- struct drm_mode *drm_mode;
+- struct drm_backend *b;
+-
+- if (output_base == NULL) {
+- weston_log("output is NULL.\n");
+- return -1;
+- }
+-
+- if (mode == NULL) {
+- weston_log("mode is NULL.\n");
+- return -1;
+- }
+-
+- b = to_drm_backend(output_base->compositor);
+- output = to_drm_output(output_base);
+- drm_mode = choose_mode (output, mode);
++ struct drm_output *output = to_drm_output(output_base);
++ struct drm_backend *b = to_drm_backend(output_base->compositor);
++ struct drm_mode *drm_mode = choose_mode(output, mode);
+
+ if (!drm_mode) {
+- weston_log("%s, invalid resolution:%dx%d\n", __func__, mode->width, mode->height);
++ weston_log("%s: invalid resolution %dx%d\n",
++ output_base->name, mode->width, mode->height);
+ return -1;
+ }
+
+@@ -1467,10 +3219,13 @@ drm_output_switch_mode(struct weston_output *output_base, struct weston_mode *mo
+ output->base.current_mode->flags =
+ WL_OUTPUT_MODE_CURRENT | WL_OUTPUT_MODE_PREFERRED;
+
+- /* reset rendering stuff. */
+- drm_output_release_fb(output, output->current);
+- drm_output_release_fb(output, output->next);
+- output->current = output->next = NULL;
++ /* XXX: This drops our current buffer too early, before we've started
++ * displaying it. Ideally this should be much more atomic and
++ * integrated with a full repaint cycle, rather than doing a
++ * sledgehammer modeswitch first, and only later showing new
++ * content.
++ */
++ b->state_invalid = true;
+
+ if (b->use_pixman) {
+ drm_output_fini_pixman(output);
+@@ -1494,11 +3249,21 @@ drm_output_switch_mode(struct weston_output *output_base, struct weston_mode *mo
+ static int
+ on_drm_input(int fd, uint32_t mask, void *data)
+ {
++#ifdef HAVE_DRM_ATOMIC
++ struct drm_backend *b = data;
++#endif
+ drmEventContext evctx;
+
+ memset(&evctx, 0, sizeof evctx);
+- evctx.version = DRM_EVENT_CONTEXT_VERSION;
+- evctx.page_flip_handler = page_flip_handler;
++#ifndef HAVE_DRM_ATOMIC
++ evctx.version = 2;
++#else
++ evctx.version = 3;
++ if (b->atomic_modeset)
++ evctx.page_flip_handler2 = atomic_flip_handler;
++ else
++#endif
++ evctx.page_flip_handler = page_flip_handler;
+ evctx.vblank_handler = vblank_handler;
+ drmHandleEvent(fd, &evctx);
+
+@@ -1506,36 +3271,15 @@ on_drm_input(int fd, uint32_t mask, void *data)
+ }
+
+ static int
+-init_drm(struct drm_backend *b, struct udev_device *device)
++init_kms_caps(struct drm_backend *b)
+ {
+- const char *filename, *sysnum;
+ uint64_t cap;
+- int fd, ret;
++ int ret;
+ clockid_t clk_id;
+
+- sysnum = udev_device_get_sysnum(device);
+- if (sysnum)
+- b->drm.id = atoi(sysnum);
+- if (!sysnum || b->drm.id < 0) {
+- weston_log("cannot get device sysnum\n");
+- return -1;
+- }
+-
+- filename = udev_device_get_devnode(device);
+- fd = weston_launcher_open(b->compositor->launcher, filename, O_RDWR);
+- if (fd < 0) {
+- /* Probably permissions error */
+- weston_log("couldn't open %s, skipping\n",
+- udev_device_get_devnode(device));
+- return -1;
+- }
+-
+- weston_log("using %s\n", filename);
+-
+- b->drm.fd = fd;
+- b->drm.filename = strdup(filename);
++ weston_log("using %s\n", b->drm.filename);
+
+- ret = drmGetCap(fd, DRM_CAP_TIMESTAMP_MONOTONIC, &cap);
++ ret = drmGetCap(b->drm.fd, DRM_CAP_TIMESTAMP_MONOTONIC, &cap);
+ if (ret == 0 && cap == 1)
+ clk_id = CLOCK_MONOTONIC;
+ else
+@@ -1547,18 +3291,40 @@ init_drm(struct drm_backend *b, struct udev_device *device)
+ return -1;
+ }
+
+- ret = drmGetCap(fd, DRM_CAP_CURSOR_WIDTH, &cap);
++ ret = drmGetCap(b->drm.fd, DRM_CAP_CURSOR_WIDTH, &cap);
+ if (ret == 0)
+ b->cursor_width = cap;
+ else
+ b->cursor_width = 64;
+
+- ret = drmGetCap(fd, DRM_CAP_CURSOR_HEIGHT, &cap);
++ ret = drmGetCap(b->drm.fd, DRM_CAP_CURSOR_HEIGHT, &cap);
+ if (ret == 0)
+ b->cursor_height = cap;
+ else
+ b->cursor_height = 64;
+
++ if (!getenv("WESTON_DISABLE_UNIVERSAL_PLANES")) {
++ ret = drmSetClientCap(b->drm.fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1);
++ b->universal_planes = (ret == 0);
++ }
++ weston_log("DRM: %s universal planes\n",
++ b->universal_planes ? "supports" : "does not support");
++
++#ifdef HAVE_DRM_ATOMIC
++ if (b->universal_planes && !getenv("WESTON_DISABLE_ATOMIC")) {
++ #if 0
++ ret = drmGetCap(b->drm.fd, DRM_CAP_CRTC_IN_VBLANK_EVENT, &cap);
++ if (ret != 0)
++ cap = 0;
++ #endif
++ cap = 1 ;
++ ret = drmSetClientCap(b->drm.fd, DRM_CLIENT_CAP_ATOMIC, 1);
++ b->atomic_modeset = ((ret == 0) && (cap == 1));
++ }
++#endif
++ weston_log("DRM: %s atomic modesetting\n",
++ b->atomic_modeset ? "supports" : "does not support");
++
+ return 0;
+ }
+
+@@ -1642,7 +3408,6 @@ init_egl(struct drm_backend *b)
+
+ if (drm_backend_create_gl_renderer(b) < 0) {
+ gbm_device_destroy(b->gbm);
+- b->gbm = NULL;
+ return -1;
+ }
+
+@@ -1656,6 +3421,293 @@ init_pixman(struct drm_backend *b)
+ }
+
+ /**
++ * Create a drm_plane for a hardware plane
++ *
++ * Creates one drm_plane structure for a hardware plane, and initialises its
++ * properties and formats.
++ *
++ * In the absence of universal plane support, where KMS does not explicitly
++ * expose the primary and cursor planes to userspace, this may also create
++ * an 'internal' plane for internal management.
++ *
++ * This function does not add the plane to the list of usable planes in Weston
++ * itself; the caller is responsible for this.
++ *
++ * Call drm_plane_destroy to clean up the plane.
++ *
++ * @sa drm_output_find_special_plane
++ * @param b DRM compositor backend
++ * @param kplane DRM plane to create, or NULL if creating internal plane
++ * @param output Output to create internal plane for, or NULL
++ * @param type Type to use when creating internal plane, or invalid
++ * @param format Format to use for internal planes, or 0
++ */
++static struct drm_plane *
++drm_plane_create(struct drm_backend *b, const drmModePlane *kplane,
++ struct drm_output *output, enum wdrm_plane_type type,
++ uint32_t format)
++{
++ struct drm_plane *plane;
++ drmModeObjectProperties *props;
++ int num_formats = (kplane) ? kplane->count_formats : 1;
++
++ plane = zalloc(sizeof(*plane) +
++ (sizeof(uint32_t) * num_formats));
++ if (!plane) {
++ weston_log("%s: out of memory\n", __func__);
++ return NULL;
++ }
++
++ plane->backend = b;
++ plane->state_cur = drm_plane_state_alloc(NULL, plane);
++ plane->state_cur->complete = true;
++
++ if (kplane) {
++ plane->possible_crtcs = kplane->possible_crtcs;
++ plane->plane_id = kplane->plane_id;
++ plane->count_formats = kplane->count_formats;
++ memcpy(plane->formats, kplane->formats,
++ kplane->count_formats * sizeof(kplane->formats[0]));
++
++ props = drmModeObjectGetProperties(b->drm.fd, kplane->plane_id,
++ DRM_MODE_OBJECT_PLANE);
++ if (!props) {
++ weston_log("couldn't get plane properties\n");
++ goto err;
++ }
++ drm_property_info_populate(b, plane_props, plane->props,
++ WDRM_PLANE__COUNT, props);
++ plane->type =
++ drm_property_get_value(&plane->props[WDRM_PLANE_TYPE],
++ props,
++ WDRM_PLANE_TYPE__COUNT);
++ drmModeFreeObjectProperties(props);
++ }
++ else {
++ plane->possible_crtcs = (1 << output->pipe);
++ plane->plane_id = 0;
++ plane->count_formats = 1;
++ plane->formats[0] = format;
++ plane->type = type;
++ }
++
++ if (plane->type == WDRM_PLANE_TYPE__COUNT)
++ goto err_props;
++
++ /* With universal planes, everything is a DRM plane; without
++ * universal planes, the only DRM planes are overlay planes.
++ * Everything else is a fake plane. */
++ if (b->universal_planes) {
++ assert(kplane);
++ } else {
++ if (kplane)
++ assert(plane->type == WDRM_PLANE_TYPE_OVERLAY);
++ else
++ assert(plane->type != WDRM_PLANE_TYPE_OVERLAY &&
++ output);
++ }
++
++ weston_plane_init(&plane->base, b->compositor, 0, 0);
++ wl_list_insert(&b->plane_list, &plane->link);
++
++ return plane;
++
++err_props:
++ drm_property_info_free(plane->props, WDRM_PLANE__COUNT);
++err:
++ drm_plane_state_free(plane->state_cur, true);
++ free(plane);
++ return NULL;
++}
++
++/**
++ * Find, or create, a special-purpose plane
++ *
++ * Primary and cursor planes are a special case, in that before universal
++ * planes, they are driven by non-plane API calls. Without universal plane
++ * support, the only way to configure a primary plane is via drmModeSetCrtc,
++ * and the only way to configure a cursor plane is drmModeSetCursor2.
++ *
++ * Although they may actually be regular planes in the hardware, without
++ * universal plane support, these planes are not actually exposed to
++ * userspace in the regular plane list.
++ *
++ * However, for ease of internal tracking, we want to manage all planes
++ * through the same drm_plane structures. Therefore, when we are running
++ * without universal plane support, we create fake drm_plane structures
++ * to track these planes.
++ *
++ * @param b DRM backend
++ * @param output Output to use for plane
++ * @param type Type of plane
++ */
++static struct drm_plane *
++drm_output_find_special_plane(struct drm_backend *b, struct drm_output *output,
++ enum wdrm_plane_type type)
++{
++ struct drm_plane *plane;
++
++ if (!b->universal_planes) {
++ uint32_t format;
++
++ switch (type) {
++ case WDRM_PLANE_TYPE_CURSOR:
++ format = GBM_FORMAT_ARGB8888;
++ break;
++ case WDRM_PLANE_TYPE_PRIMARY:
++ /* We don't know what formats the primary plane supports
++ * before universal planes, so we just assume that the
++ * GBM format works; however, this isn't set until after
++ * the output is created. */
++ format = 0;
++ break;
++ default:
++ assert(!"invalid type in drm_output_find_special_plane");
++ break;
++ }
++
++ return drm_plane_create(b, NULL, output, type, format);
++ }
++
++ wl_list_for_each(plane, &b->plane_list, link) {
++ struct drm_output *tmp;
++ bool found_elsewhere = false;
++
++ if (plane->type != type)
++ continue;
++ if (!drm_plane_is_available(plane, output))
++ continue;
++
++ /* On some platforms, primary/cursor planes can roam
++ * between different CRTCs, so make sure we don't claim the
++ * same plane for two outputs. */
++ wl_list_for_each(tmp, &b->compositor->pending_output_list,
++ base.link) {
++ if (tmp->cursor_plane == plane ||
++ tmp->scanout_plane == plane) {
++ found_elsewhere = true;
++ break;
++ }
++ }
++ wl_list_for_each(tmp, &b->compositor->output_list,
++ base.link) {
++ if (tmp->cursor_plane == plane ||
++ tmp->scanout_plane == plane) {
++ found_elsewhere = true;
++ break;
++ }
++ }
++
++ if (found_elsewhere)
++ continue;
++
++ plane->possible_crtcs = (1 << output->pipe);
++ return plane;
++ }
++
++ return NULL;
++}
++
++/**
++ * Destroy one DRM plane
++ *
++ * Destroy a DRM plane, removing it from screen and releasing its retained
++ * buffers in the process. The counterpart to drm_plane_create.
++ *
++ * @param plane Plane to deallocate (will be freed)
++ */
++static void
++drm_plane_destroy(struct drm_plane *plane)
++{
++ if (plane->type == WDRM_PLANE_TYPE_OVERLAY)
++ drmModeSetPlane(plane->backend->drm.fd, plane->plane_id,
++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
++ drm_plane_state_free(plane->state_cur, true);
++ drm_property_info_free(plane->props, WDRM_PLANE__COUNT);
++ weston_plane_release(&plane->base);
++ wl_list_remove(&plane->link);
++ free(plane);
++}
++
++/**
++ * Initialise sprites (overlay planes)
++ *
++ * Walk the list of provided DRM planes, and add overlay planes.
++ *
++ * Call destroy_sprites to free these planes.
++ *
++ * @param b DRM compositor backend
++ */
++static void
++create_sprites(struct drm_backend *b)
++{
++ drmModePlaneRes *kplane_res;
++ drmModePlane *kplane;
++ struct drm_plane *drm_plane;
++ uint32_t i;
++ kplane_res = drmModeGetPlaneResources(b->drm.fd);
++ if (!kplane_res) {
++ weston_log("failed to get plane resources: %s\n",
++ strerror(errno));
++ return;
++ }
++
++ for (i = 0; i < kplane_res->count_planes; i++) {
++ kplane = drmModeGetPlane(b->drm.fd, kplane_res->planes[i]);
++ if (!kplane)
++ continue;
++
++ drm_plane = drm_plane_create(b, kplane, NULL,
++ WDRM_PLANE_TYPE__COUNT, 0);
++ drmModeFreePlane(kplane);
++ if (!drm_plane)
++ continue;
++
++ if (drm_plane->type == WDRM_PLANE_TYPE_OVERLAY)
++ weston_compositor_stack_plane(b->compositor,
++ &drm_plane->base,
++ &b->compositor->primary_plane);
++ }
++
++ drmModeFreePlaneResources(kplane_res);
++}
++
++/**
++ * Clean up sprites (overlay planes)
++ *
++ * The counterpart to create_sprites.
++ *
++ * @param b DRM compositor backend
++ */
++static void
++destroy_sprites(struct drm_backend *b)
++{
++ struct drm_plane *plane, *next;
++
++ wl_list_for_each_safe(plane, next, &b->plane_list, link)
++ drm_plane_destroy(plane);
++}
++
++static uint32_t
++drm_refresh_rate_mHz(const drmModeModeInfo *info)
++{
++ uint64_t refresh;
++
++ /* Calculate higher precision (mHz) refresh rate */
++ refresh = (info->clock * 1000000LL / info->htotal +
++ info->vtotal / 2) / info->vtotal;
++
++ if (info->flags & DRM_MODE_FLAG_INTERLACE)
++ refresh *= 2;
++ if (info->flags & DRM_MODE_FLAG_DBLSCAN)
++ refresh /= 2;
++ if (info->vscan > 1)
++ refresh /= info->vscan;
++
++ return refresh;
++}
++
++/**
+ * Add a mode to output's mode list
+ *
+ * Copy the supplied DRM mode into a Weston mode structure, and add it to the
+@@ -1669,7 +3721,6 @@ static struct drm_mode *
+ drm_output_add_mode(struct drm_output *output, const drmModeModeInfo *info)
+ {
+ struct drm_mode *mode;
+- uint64_t refresh;
+
+ mode = malloc(sizeof *mode);
+ if (mode == NULL)
+@@ -1679,19 +3730,9 @@ drm_output_add_mode(struct drm_output *output, const drmModeModeInfo *info)
+ mode->base.width = info->hdisplay;
+ mode->base.height = info->vdisplay;
+
+- /* Calculate higher precision (mHz) refresh rate */
+- refresh = (info->clock * 1000000LL / info->htotal +
+- info->vtotal / 2) / info->vtotal;
+-
+- if (info->flags & DRM_MODE_FLAG_INTERLACE)
+- refresh *= 2;
+- if (info->flags & DRM_MODE_FLAG_DBLSCAN)
+- refresh /= 2;
+- if (info->vscan > 1)
+- refresh /= info->vscan;
+-
+- mode->base.refresh = refresh;
++ mode->base.refresh = drm_refresh_rate_mHz(info);
+ mode->mode_info = *info;
++ mode->blob_id = 0;
+
+ if (info->type & DRM_MODE_TYPE_PREFERRED)
+ mode->base.flags |= WL_OUTPUT_MODE_PREFERRED;
+@@ -1701,6 +3742,32 @@ drm_output_add_mode(struct drm_output *output, const drmModeModeInfo *info)
+ return mode;
+ }
+
++/**
++ * Destroys a mode, and removes it from the list.
++ */
++static void
++drm_output_destroy_mode(struct drm_backend *backend, struct drm_mode *mode)
++{
++ if (mode->blob_id)
++ drmModeDestroyPropertyBlob(backend->drm.fd, mode->blob_id);
++ wl_list_remove(&mode->base.link);
++ free(mode);
++}
++
++/** Destroy a list of drm_modes
++ *
++ * @param backend The backend for releasing mode property blobs.
++ * @param mode_list The list linked by drm_mode::base.link.
++ */
++static void
++drm_mode_list_destroy(struct drm_backend *backend, struct wl_list *mode_list)
++{
++ struct drm_mode *mode, *next;
++
++ wl_list_for_each_safe(mode, next, mode_list, base.link)
++ drm_output_destroy_mode(backend, mode);
++}
++
+ static int
+ drm_subpixel_to_wayland(int drm_value)
+ {
+@@ -1757,46 +3824,72 @@ drm_set_backlight(struct weston_output *output_base, uint32_t value)
+ backlight_set_brightness(output->backlight, new_brightness);
+ }
+
+-static drmModePropertyPtr
+-drm_get_prop(int fd, drmModeConnectorPtr connector, const char *name)
+-{
+- drmModePropertyPtr props;
+- int i;
+-
+- for (i = 0; i < connector->count_props; i++) {
+- props = drmModeGetProperty(fd, connector->props[i]);
+- if (!props)
+- continue;
+-
+- if (!strcmp(props->name, name))
+- return props;
+-
+- drmModeFreeProperty(props);
+- }
+-
+- return NULL;
+-}
+-
++/**
++ * Power output on or off
++ *
++ * The DPMS/power level of an output is used to switch it on or off. This
++ * is DRM's hook for doing so, which can called either as part of repaint,
++ * or independently of the repaint loop.
++ *
++ * If we are called as part of repaint, we simply set the relevant bit in
++ * state and return.
++ */
+ static void
+ drm_set_dpms(struct weston_output *output_base, enum dpms_enum level)
+ {
+ struct drm_output *output = to_drm_output(output_base);
+- struct weston_compositor *ec = output_base->compositor;
+- struct drm_backend *b = to_drm_backend(ec);
++ struct drm_backend *b = to_drm_backend(output_base->compositor);
++ struct drm_pending_state *pending_state = b->repaint_data;
++ struct drm_output_state *state;
+ int ret;
+
+- if (!output->dpms_prop)
++ if (output->state_cur->dpms == level)
+ return;
+
+- ret = drmModeConnectorSetProperty(b->drm.fd, output->connector_id,
+- output->dpms_prop->prop_id, level);
+- if (ret) {
+- weston_log("DRM: DPMS: failed property set for %s\n",
+- output->base.name);
++ /* If we're being called during the repaint loop, then this is
++ * simple: discard any previously-generated state, and create a new
++ * state where we disable everything. When we come to flush, this
++ * will be applied.
++ *
++ * However, we need to be careful: we can be called whilst another
++ * output is in its repaint cycle (pending_state exists), but our
++ * output still has an incomplete state application outstanding.
++ * In that case, we need to wait until that completes. */
++ if (pending_state && !output->state_last) {
++ /* The repaint loop already sets DPMS on; we don't need to
++ * explicitly set it on here, as it will already happen
++ * whilst applying the repaint state. */
++ if (level == WESTON_DPMS_ON)
++ return;
++
++ state = drm_pending_state_get_output(pending_state, output);
++ if (state)
++ drm_output_state_free(state);
++ state = drm_output_get_disable_state(pending_state, output);
+ return;
+ }
+
+- output->dpms = level;
++ /* As we throw everything away when disabling, just send us back through
++ * a repaint cycle. */
++ if (level == WESTON_DPMS_ON) {
++ if (output->dpms_off_pending)
++ output->dpms_off_pending = 0;
++ weston_output_schedule_repaint(output_base);
++ return;
++ }
++
++ /* If we've already got a request in the pipeline, then we need to
++ * park our DPMS request until that request has quiesced. */
++ if (output->state_last) {
++ output->dpms_off_pending = 1;
++ return;
++ }
++
++ pending_state = drm_pending_state_alloc(b);
++ drm_output_get_disable_state(pending_state, output);
++ ret = drm_pending_state_apply_sync(pending_state);
++ if (ret != 0)
++ weston_log("drm_set_dpms: couldn't disable output?\n");
+ }
+
+ static const char * const connector_type_names[] = {
+@@ -1821,11 +3914,20 @@ static const char * const connector_type_names[] = {
+ #endif
+ };
+
++/** Create a name given a DRM connector
++ *
++ * \param con The DRM connector whose type and id form the name.
++ * \return A newly allocate string, or NULL on error. Must be free()'d
++ * after use.
++ *
++ * The name does not identify the DRM display device.
++ */
+ static char *
+ make_connector_name(const drmModeConnector *con)
+ {
+- char name[32];
++ char *name;
+ const char *type_name = NULL;
++ int ret;
+
+ if (con->connector_type < ARRAY_LENGTH(connector_type_names))
+ type_name = connector_type_names[con->connector_type];
+@@ -1833,9 +3935,11 @@ make_connector_name(const drmModeConnector *con)
+ if (!type_name)
+ type_name = "UNNAMED";
+
+- snprintf(name, sizeof name, "%s-%d", type_name, con->connector_type_id);
++ ret = asprintf(&name, "%s-%d", type_name, con->connector_type_id);
++ if (ret < 0)
++ return NULL;
+
+- return strdup(name);
++ return name;
+ }
+
+ static int
+@@ -1843,16 +3947,20 @@ find_crtc_for_connector(struct drm_backend *b,
+ drmModeRes *resources, drmModeConnector *connector)
+ {
+ drmModeEncoder *encoder;
+- uint32_t possible_crtcs;
+ int i, j;
++ int ret = -1;
+
+ for (j = 0; j < connector->count_encoders; j++) {
++ uint32_t possible_crtcs, encoder_id, crtc_id;
++
+ encoder = drmModeGetEncoder(b->drm.fd, connector->encoders[j]);
+ if (encoder == NULL) {
+ weston_log("Failed to get encoder.\n");
+- return -1;
++ continue;
+ }
++ encoder_id = encoder->encoder_id;
+ possible_crtcs = encoder->possible_crtcs;
++ crtc_id = encoder->crtc_id;
+ drmModeFreeEncoder(encoder);
+
+ for (i = 0; i < resources->count_crtcs; i++) {
+@@ -1862,10 +3970,66 @@ find_crtc_for_connector(struct drm_backend *b,
+ if (drm_output_find_by_crtc(b, resources->crtcs[i]))
+ continue;
+
+- return i;
++ /* Try to preserve the existing
++ * CRTC -> encoder -> connector routing; it makes
++ * initialisation faster, and also since we have a
++ * very dumb picking algorithm, may preserve a better
++ * choice. */
++ if (!connector->encoder_id ||
++ (encoder_id == connector->encoder_id &&
++ crtc_id == resources->crtcs[i]))
++ return i;
++
++ ret = i;
++ }
++ }
++
++ return ret;
++}
++
++static void drm_output_fini_cursor_egl(struct drm_output *output)
++{
++ unsigned int i;
++
++ for (i = 0; i < ARRAY_LENGTH(output->gbm_cursor_fb); i++) {
++ drm_fb_unref(output->gbm_cursor_fb[i]);
++ output->gbm_cursor_fb[i] = NULL;
++ }
++}
++
++static int
++drm_output_init_cursor_egl(struct drm_output *output, struct drm_backend *b)
++{
++ unsigned int i;
++
++ /* No point creating cursors if we don't have a plane for them. */
++ if (!output->cursor_plane)
++ return 0;
++
++ for (i = 0; i < ARRAY_LENGTH(output->gbm_cursor_fb); i++) {
++ struct gbm_bo *bo;
++
++ bo = gbm_bo_create(b->gbm, b->cursor_width, b->cursor_height,
++ GBM_FORMAT_ARGB8888,
++ GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE);
++ if (!bo)
++ goto err;
++
++ output->gbm_cursor_fb[i] =
++ drm_fb_get_from_bo(bo, b, GBM_FORMAT_ARGB8888,
++ BUFFER_CURSOR);
++ if (!output->gbm_cursor_fb[i]) {
++ gbm_bo_destroy(bo);
++ goto err;
+ }
+ }
+
++ return 0;
++
++err:
++ weston_log("cursor buffers unavailable, using gl cursors\n");
++ b->cursors_are_broken = 1;
++ drm_output_fini_cursor_egl(output);
+ return -1;
+ }
+
+@@ -1877,7 +4041,7 @@ drm_output_init_egl(struct drm_output *output, struct drm_backend *b)
+ output->gbm_format,
+ fallback_format_for(output->gbm_format),
+ };
+- int i, flags, n_formats = 1;
++ int n_formats = 1;
+
+ output->gbm_surface = gbm_surface_create(b->gbm,
+ output->base.current_mode->width,
+@@ -1903,21 +4067,7 @@ drm_output_init_egl(struct drm_output *output, struct drm_backend *b)
+ return -1;
+ }
+
+- flags = GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE;
+-
+- for (i = 0; i < 2; i++) {
+- if (output->gbm_cursor_bo[i])
+- continue;
+-
+- output->gbm_cursor_bo[i] =
+- gbm_bo_create(b->gbm, b->cursor_width, b->cursor_height,
+- GBM_FORMAT_ARGB8888, flags);
+- }
+-
+- if (output->gbm_cursor_bo[0] == NULL || output->gbm_cursor_bo[1] == NULL) {
+- weston_log("cursor buffers unavailable, using gl cursors\n");
+- b->cursors_are_broken = 1;
+- }
++ drm_output_init_cursor_egl(output, b);
+
+ return 0;
+ }
+@@ -1925,8 +4075,22 @@ drm_output_init_egl(struct drm_output *output, struct drm_backend *b)
+ static void
+ drm_output_fini_egl(struct drm_output *output)
+ {
++ struct drm_backend *b = to_drm_backend(output->base.compositor);
++
++ /* Destroying the GBM surface will destroy all our GBM buffers,
++ * regardless of refcount. Ensure we destroy them here. */
++ if (!b->shutting_down &&
++ output->scanout_plane->state_cur->fb &&
++ output->scanout_plane->state_cur->fb->type == BUFFER_GBM_SURFACE) {
++ drm_plane_state_free(output->scanout_plane->state_cur, true);
++ output->scanout_plane->state_cur =
++ drm_plane_state_alloc(NULL, output->scanout_plane);
++ output->scanout_plane->state_cur->complete = true;
++ }
++
+ gl_renderer->output_destroy(&output->base);
+ gbm_surface_destroy(output->gbm_surface);
++ drm_output_fini_cursor_egl(output);
+ }
+
+ static int
+@@ -1975,7 +4139,7 @@ drm_output_init_pixman(struct drm_output *output, struct drm_backend *b)
+ err:
+ for (i = 0; i < ARRAY_LENGTH(output->dumb); i++) {
+ if (output->dumb[i])
+- drm_fb_destroy_dumb(output->dumb[i]);
++ drm_fb_unref(output->dumb[i]);
+ if (output->image[i])
+ pixman_image_unref(output->image[i]);
+
+@@ -1989,14 +4153,26 @@ err:
+ static void
+ drm_output_fini_pixman(struct drm_output *output)
+ {
++ struct drm_backend *b = to_drm_backend(output->base.compositor);
+ unsigned int i;
+
++ /* Destroying the Pixman surface will destroy all our buffers,
++ * regardless of refcount. Ensure we destroy them here. */
++ if (!b->shutting_down &&
++ output->scanout_plane->state_cur->fb &&
++ output->scanout_plane->state_cur->fb->type == BUFFER_PIXMAN_DUMB) {
++ drm_plane_state_free(output->scanout_plane->state_cur, true);
++ output->scanout_plane->state_cur =
++ drm_plane_state_alloc(NULL, output->scanout_plane);
++ output->scanout_plane->state_cur->complete = true;
++ }
++
+ pixman_renderer_output_destroy(&output->base);
+ pixman_region32_fini(&output->previous_damage);
+
+ for (i = 0; i < ARRAY_LENGTH(output->dumb); i++) {
+- drm_fb_destroy_dumb(output->dumb[i]);
+ pixman_image_unref(output->image[i]);
++ drm_fb_unref(output->dumb[i]);
+ output->dumb[i] = NULL;
+ output->image[i] = NULL;
+ }
+@@ -2100,27 +4276,38 @@ edid_parse(struct drm_edid *edid, const uint8_t *data, size_t length)
+ return 0;
+ }
+
++/** Parse monitor make, model and serial from EDID
++ *
++ * \param b The backend instance.
++ * \param output The output whose \c drm_edid to fill in.
++ * \param props The DRM connector properties to get the EDID from.
++ * \param make[out] The monitor make (PNP ID).
++ * \param model[out] The monitor model (name).
++ * \param serial_number[out] The monitor serial number.
++ *
++ * Each of \c *make, \c *model and \c *serial_number are set only if the
++ * information is found in the EDID. The pointers they are set to must not
++ * be free()'d explicitly, instead they get implicitly freed when the
++ * \c drm_output is destroyed.
++ */
+ static void
+-find_and_parse_output_edid(struct drm_backend *b,
+- struct drm_output *output,
+- drmModeConnector *connector)
++find_and_parse_output_edid(struct drm_backend *b, struct drm_output *output,
++ drmModeObjectPropertiesPtr props,
++ const char **make,
++ const char **model,
++ const char **serial_number)
+ {
+ drmModePropertyBlobPtr edid_blob = NULL;
+- drmModePropertyPtr property;
+- int i;
++ uint32_t blob_id;
+ int rc;
+
+- for (i = 0; i < connector->count_props && !edid_blob; i++) {
+- property = drmModeGetProperty(b->drm.fd, connector->props[i]);
+- if (!property)
+- continue;
+- if ((property->flags & DRM_MODE_PROP_BLOB) &&
+- !strcmp(property->name, "EDID")) {
+- edid_blob = drmModeGetPropertyBlob(b->drm.fd,
+- connector->prop_values[i]);
+- }
+- drmModeFreeProperty(property);
+- }
++ blob_id =
++ drm_property_get_value(&output->props_conn[WDRM_CONNECTOR_EDID],
++ props, 0);
++ if (!blob_id)
++ return;
++
++ edid_blob = drmModeGetPropertyBlob(b->drm.fd, blob_id);
+ if (!edid_blob)
+ return;
+
+@@ -2133,17 +4320,15 @@ find_and_parse_output_edid(struct drm_backend *b,
+ output->edid.monitor_name,
+ output->edid.serial_number);
+ if (output->edid.pnp_id[0] != '\0')
+- output->base.make = output->edid.pnp_id;
++ *make = output->edid.pnp_id;
+ if (output->edid.monitor_name[0] != '\0')
+- output->base.model = output->edid.monitor_name;
++ *model = output->edid.monitor_name;
+ if (output->edid.serial_number[0] != '\0')
+- output->base.serial_number = output->edid.serial_number;
++ *serial_number = output->edid.serial_number;
+ }
+ drmModeFreePropertyBlob(edid_blob);
+ }
+
+-
+-
+ static int
+ parse_modeline(const char *s, drmModeModeInfo *mode)
+ {
+@@ -2151,6 +4336,8 @@ parse_modeline(const char *s, drmModeModeInfo *mode)
+ char vsync[16];
+ float fclock;
+
++ memset(mode, 0, sizeof *mode);
++
+ mode->type = DRM_MODE_TYPE_USERDEF;
+ mode->hskew = 0;
+ mode->vscan = 0;
+@@ -2355,29 +4542,15 @@ drm_output_set_mode(struct weston_output *base,
+ struct drm_output *output = to_drm_output(base);
+ struct drm_backend *b = to_drm_backend(base->compositor);
+
+- struct drm_mode *drm_mode, *next, *current;
+- drmModeModeInfo crtc_mode;
+- int i;
+-
+- output->base.make = "unknown";
+- output->base.model = "unknown";
+- output->base.serial_number = "unknown";
+- wl_list_init(&output->base.mode_list);
+-
+- output->original_crtc = drmModeGetCrtc(b->drm.fd, output->crtc_id);
++ struct drm_mode *current;
++ drmModeModeInfo crtc_mode;
+
+ if (connector_get_current_mode(output->connector, b->drm.fd, &crtc_mode) < 0)
+- goto err_free;
+-
+- for (i = 0; i < output->connector->count_modes; i++) {
+- drm_mode = drm_output_add_mode(output, &output->connector->modes[i]);
+- if (!drm_mode)
+- goto err_free;
+- }
++ return -1;
+
+ current = drm_output_choose_initial_mode(b, output, mode, modeline, &crtc_mode);
+ if (!current)
+- goto err_free;
++ return -1;
+
+ output->base.current_mode = ¤t->base;
+ output->base.current_mode->flags |= WL_OUTPUT_MODE_CURRENT;
+@@ -2386,22 +4559,7 @@ drm_output_set_mode(struct weston_output *base,
+ output->base.native_mode = output->base.current_mode;
+ output->base.native_scale = output->base.current_scale;
+
+- output->base.mm_width = output->connector->mmWidth;
+- output->base.mm_height = output->connector->mmHeight;
+-
+ return 0;
+-
+-err_free:
+- drmModeFreeCrtc(output->original_crtc);
+- output->original_crtc = NULL;
+-
+- wl_list_for_each_safe(drm_mode, next, &output->base.mode_list,
+- base.link) {
+- wl_list_remove(&drm_mode->base.link);
+- free(drm_mode);
+- }
+-
+- return -1;
+ }
+
+ static void
+@@ -2413,6 +4571,12 @@ drm_output_set_gbm_format(struct weston_output *base,
+
+ if (parse_gbm_format(gbm_format, b->gbm_format, &output->gbm_format) == -1)
+ output->gbm_format = b->gbm_format;
++
++ /* Without universal planes, we can't discover which formats are
++ * supported by the primary plane; we just hope that the GBM format
++ * works. */
++ if (!b->universal_planes)
++ output->scanout_plane->formats[0] = output->gbm_format;
+ }
+
+ static void
+@@ -2427,22 +4591,145 @@ drm_output_set_seat(struct weston_output *base,
+ }
+
+ static int
++drm_output_init_gamma_size(struct drm_output *output)
++{
++ struct drm_backend *backend = to_drm_backend(output->base.compositor);
++ drmModeCrtc *crtc;
++
++ assert(output->base.compositor);
++ assert(output->crtc_id != 0);
++ crtc = drmModeGetCrtc(backend->drm.fd, output->crtc_id);
++ if (!crtc)
++ return -1;
++
++ output->base.gamma_size = crtc->gamma_size;
++
++ drmModeFreeCrtc(crtc);
++
++ return 0;
++}
++
++/** Allocate a CRTC for the output
++ *
++ * @param output The output with no allocated CRTC.
++ * @param resources DRM KMS resources.
++ * @param connector The DRM KMS connector data.
++ * @return 0 on success, -1 on failure.
++ *
++ * Finds a free CRTC that can drive the given connector, reserves the CRTC
++ * for the output, and loads the CRTC properties.
++ *
++ * Populates the cursor and scanout planes.
++ *
++ * On failure, the output remains without a CRTC.
++ */
++static int
++drm_output_init_crtc(struct drm_output *output,
++ drmModeRes *resources, drmModeConnector *connector)
++{
++ struct drm_backend *b = to_drm_backend(output->base.compositor);
++ drmModeObjectPropertiesPtr props;
++ int i;
++
++ assert(output->crtc_id == 0);
++
++ i = find_crtc_for_connector(b, resources, connector);
++ if (i < 0) {
++ weston_log("No usable crtc/encoder pair for connector.\n");
++ return -1;
++ }
++
++ output->crtc_id = resources->crtcs[i];
++ output->pipe = i;
++
++ props = drmModeObjectGetProperties(b->drm.fd, output->crtc_id,
++ DRM_MODE_OBJECT_CRTC);
++ if (!props) {
++ weston_log("failed to get CRTC properties\n");
++ goto err_crtc;
++ }
++ drm_property_info_populate(b, crtc_props, output->props_crtc,
++ WDRM_CRTC__COUNT, props);
++ drmModeFreeObjectProperties(props);
++
++ output->scanout_plane =
++ drm_output_find_special_plane(b, output,
++ WDRM_PLANE_TYPE_PRIMARY);
++ if (!output->scanout_plane) {
++ weston_log("Failed to find primary plane for output %s\n",
++ output->base.name);
++ goto err_crtc;
++ }
++
++ /* Failing to find a cursor plane is not fatal, as we'll fall back
++ * to software cursor. */
++ output->cursor_plane =
++ drm_output_find_special_plane(b, output,
++ WDRM_PLANE_TYPE_CURSOR);
++
++ return 0;
++
++err_crtc:
++ output->crtc_id = 0;
++ output->pipe = 0;
++
++ return -1;
++}
++
++/** Free the CRTC from the output
++ *
++ * @param output The output whose CRTC to deallocate.
++ *
++ * The CRTC reserved for the given output becomes free to use again.
++ */
++static void
++drm_output_fini_crtc(struct drm_output *output)
++{
++ struct drm_backend *b = to_drm_backend(output->base.compositor);
++
++ if (!b->universal_planes && !b->shutting_down) {
++ /* With universal planes, the 'special' planes are allocated at
++ * startup, freed at shutdown, and live on the plane list in
++ * between. We want the planes to continue to exist and be freed
++ * up for other outputs.
++ *
++ * Without universal planes, our special planes are
++ * pseudo-planes allocated at output creation, freed at output
++ * destruction, and not usable by other outputs.
++ *
++ * On the other hand, if the compositor is already shutting down,
++ * the plane has already been destroyed.
++ */
++ if (output->cursor_plane)
++ drm_plane_destroy(output->cursor_plane);
++ if (output->scanout_plane)
++ drm_plane_destroy(output->scanout_plane);
++ }
++
++ drm_property_info_free(output->props_crtc, WDRM_CRTC__COUNT);
++ output->crtc_id = 0;
++ output->cursor_plane = NULL;
++ output->scanout_plane = NULL;
++}
++
++static int
+ drm_output_enable(struct weston_output *base)
+ {
+ struct drm_output *output = to_drm_output(base);
+ struct drm_backend *b = to_drm_backend(base->compositor);
+ struct weston_mode *m;
+
+- output->dpms_prop = drm_get_prop(b->drm.fd, output->connector, "DPMS");
++ if (b->pageflip_timeout)
++ drm_output_pageflip_timer_create(output);
+
+ if (b->use_pixman) {
+ if (drm_output_init_pixman(output, b) < 0) {
+ weston_log("Failed to init output pixman state\n");
+- goto err_free;
++ goto err;
+ }
+ } else if (drm_output_init_egl(output, b) < 0) {
+ weston_log("Failed to init output gl state\n");
+- goto err_free;
++ goto err;
+ }
+
+ if (output->backlight) {
+@@ -2459,25 +4746,22 @@ drm_output_enable(struct weston_output *base)
+ output->base.assign_planes = drm_assign_planes;
+ output->base.set_dpms = drm_set_dpms;
+ output->base.switch_mode = drm_output_switch_mode;
+-
+- output->base.gamma_size = output->original_crtc->gamma_size;
+ output->base.set_gamma = drm_output_set_gamma;
+
+- output->base.subpixel = drm_subpixel_to_wayland(output->connector->subpixel);
+-
+- find_and_parse_output_edid(b, output, output->connector);
+- if (output->connector->connector_type == DRM_MODE_CONNECTOR_LVDS ||
+- output->connector->connector_type == DRM_MODE_CONNECTOR_eDP)
+- output->base.connection_internal = 1;
+-
+- weston_plane_init(&output->cursor_plane, b->compositor,
+- INT32_MIN, INT32_MIN);
+- weston_plane_init(&output->fb_plane, b->compositor, 0, 0);
++ if (output->cursor_plane)
++ weston_compositor_stack_plane(b->compositor,
++ &output->cursor_plane->base,
++ NULL);
++ else
++ b->cursors_are_broken = 1;
+
+- weston_compositor_stack_plane(b->compositor, &output->cursor_plane, NULL);
+- weston_compositor_stack_plane(b->compositor, &output->fb_plane,
++ weston_compositor_stack_plane(b->compositor,
++ &output->scanout_plane->base,
+ &b->compositor->primary_plane);
+
++ wl_array_remove_uint32(&b->unused_connectors, output->connector_id);
++ wl_array_remove_uint32(&b->unused_crtcs, output->crtc_id);
++
+ weston_log("Output %s, (connector %d, crtc %d)\n",
+ output->base.name, output->connector_id, output->crtc_id);
+ wl_list_for_each(m, &output->base.mode_list, link)
+@@ -2492,9 +4776,7 @@ drm_output_enable(struct weston_output *base)
+
+ return 0;
+
+-err_free:
+- drmModeFreeProperty(output->dpms_prop);
+-
++err:
+ return -1;
+ }
+
+@@ -2503,19 +4785,36 @@ drm_output_deinit(struct weston_output *base)
+ {
+ struct drm_output *output = to_drm_output(base);
+ struct drm_backend *b = to_drm_backend(base->compositor);
++ uint32_t *unused;
+
+ if (b->use_pixman)
+ drm_output_fini_pixman(output);
+ else
+ drm_output_fini_egl(output);
+
+- weston_plane_release(&output->fb_plane);
+- weston_plane_release(&output->cursor_plane);
++ /* Since our planes are no longer in use anywhere, remove their base
++ * weston_plane's link from the plane stacking list, unless we're
++ * shutting down, in which case the plane has already been
++ * destroyed. */
++ if (!b->shutting_down) {
++ wl_list_remove(&output->scanout_plane->base.link);
++ wl_list_init(&output->scanout_plane->base.link);
++
++ if (output->cursor_plane) {
++ wl_list_remove(&output->cursor_plane->base.link);
++ wl_list_init(&output->cursor_plane->base.link);
++ /* Turn off hardware cursor */
++ drmModeSetCursor(b->drm.fd, output->crtc_id, 0, 0, 0);
++ }
++ }
+
+- drmModeFreeProperty(output->dpms_prop);
++ unused = wl_array_add(&b->unused_connectors, sizeof(*unused));
++ *unused = output->connector_id;
++ unused = wl_array_add(&b->unused_crtcs, sizeof(*unused));
++ *unused = output->crtc_id;
+
+- /* Turn off hardware cursor */
+- drmModeSetCursor(b->drm.fd, output->crtc_id, 0, 0, 0);
++ /* Force programming unused connectors and crtcs. */
++ b->state_invalid = true;
+ }
+
+ static void
+@@ -2523,9 +4822,9 @@ drm_output_destroy(struct weston_output *base)
+ {
+ struct drm_output *output = to_drm_output(base);
+ struct drm_backend *b = to_drm_backend(base->compositor);
+- drmModeCrtcPtr origcrtc = output->original_crtc;
+
+- if (output->page_flip_pending) {
++ if (output->page_flip_pending || output->vblank_pending ||
++ output->atomic_complete_pending) {
+ output->destroy_pending = 1;
+ weston_log("destroy output while page flip pending\n");
+ return;
+@@ -2534,21 +4833,24 @@ drm_output_destroy(struct weston_output *base)
+ if (output->base.enabled)
+ drm_output_deinit(&output->base);
+
+- if (origcrtc) {
+- /* Restore original CRTC state */
+- drmModeSetCrtc(b->drm.fd, origcrtc->crtc_id, origcrtc->buffer_id,
+- origcrtc->x, origcrtc->y,
+- &output->connector_id, 1, &origcrtc->mode);
+- drmModeFreeCrtc(origcrtc);
+- }
++ drm_mode_list_destroy(b, &output->base.mode_list);
++
++ if (output->pageflip_timer)
++ wl_event_source_remove(output->pageflip_timer);
+
+ weston_output_destroy(&output->base);
+
++ drm_output_fini_crtc(output);
++
++ drm_property_info_free(output->props_conn, WDRM_CONNECTOR__COUNT);
+ drmModeFreeConnector(output->connector);
+
+ if (output->backlight)
+ backlight_destroy(output->backlight);
+
++ assert(!output->state_last);
++ drm_output_state_free(output->state_cur);
++
+ free(output);
+ }
+
+@@ -2556,26 +4858,69 @@ static int
+ drm_output_disable(struct weston_output *base)
+ {
+ struct drm_output *output = to_drm_output(base);
+- struct drm_backend *b = to_drm_backend(base->compositor);
+
+- if (output->page_flip_pending) {
++ if (output->page_flip_pending || output->vblank_pending ||
++ output->atomic_complete_pending) {
+ output->disable_pending = 1;
+ return -1;
+ }
+
++ weston_log("Disabling output %s\n", output->base.name);
++
+ if (output->base.enabled)
+ drm_output_deinit(&output->base);
+
+ output->disable_pending = 0;
+
+- weston_log("Disabling output %s\n", output->base.name);
+- drmModeSetCrtc(b->drm.fd, output->crtc_id,
+- 0, 0, 0, 0, 0, NULL);
+-
+ return 0;
+ }
+
+ /**
++ * Update the list of unused connectors and CRTCs
++ *
++ * This keeps the unused_connectors and unused_crtcs arrays up to date.
++ *
++ * @param b Weston backend structure
++ * @param resources DRM resources for this device
++ */
++static void
++drm_backend_update_unused_outputs(struct drm_backend *b, drmModeRes *resources)
++{
++ int i;
++
++ wl_array_release(&b->unused_connectors);
++ wl_array_init(&b->unused_connectors);
++
++ for (i = 0; i < resources->count_connectors; i++) {
++ struct drm_output *output;
++ uint32_t *connector_id;
++
++ output = drm_output_find_by_connector(b, resources->connectors[i]);
++ if (output && output->base.enabled)
++ continue;
++
++ connector_id = wl_array_add(&b->unused_connectors,
++ sizeof(*connector_id));
++ *connector_id = resources->connectors[i];
++ }
++
++ wl_array_release(&b->unused_crtcs);
++ wl_array_init(&b->unused_crtcs);
++
++ for (i = 0; i < resources->count_crtcs; i++) {
++ struct drm_output *output;
++ uint32_t *crtc_id;
++
++ output = drm_output_find_by_crtc(b, resources->crtcs[i]);
++ if (output && output->base.enabled)
++ continue;
++
++ crtc_id = wl_array_add(&b->unused_crtcs, sizeof(*crtc_id));
++ *crtc_id = resources->crtcs[i];
++ }
++}
++
++/**
+ * Create a Weston output structure
+ *
+ * Given a DRM connector, create a matching drm_output structure and add it
+@@ -2595,108 +4940,87 @@ create_output_for_connector(struct drm_backend *b,
+ struct udev_device *drm_device)
+ {
+ struct drm_output *output;
++ drmModeObjectPropertiesPtr props;
++ struct drm_mode *drm_mode;
++ char *name;
++ const char *make = "unknown";
++ const char *model = "unknown";
++ const char *serial_number = "unknown";
+ int i;
+
+- i = find_crtc_for_connector(b, resources, connector);
+- if (i < 0) {
+- weston_log("No usable crtc/encoder pair for connector.\n");
+- return -1;
+- }
+-
+ output = zalloc(sizeof *output);
+ if (output == NULL)
+- return -1;
++ goto err_init;
+
+ output->connector = connector;
+- output->crtc_id = resources->crtcs[i];
+- output->pipe = i;
+ output->connector_id = connector->connector_id;
+
+ output->backlight = backlight_init(drm_device,
+ connector->connector_type);
+
++ output->base.name = make_connector_name(connector);
++ weston_output_init(&output->base, b->compositor);
++ wl_list_init(&output->base.mode_list);
++
+ output->base.enable = drm_output_enable;
+ output->base.destroy = drm_output_destroy;
+ output->base.disable = drm_output_disable;
+- output->base.name = make_connector_name(connector);
+
+ output->destroy_pending = 0;
+ output->disable_pending = 0;
+- output->original_crtc = NULL;
+
+- weston_output_init(&output->base, b->compositor);
+- weston_compositor_add_pending_output(&output->base, b->compositor);
++ if (drm_output_init_crtc(output, resources, connector) < 0)
++ goto err_output;
+
+- return 0;
+-}
++ props = drmModeObjectGetProperties(b->drm.fd, connector->connector_id,
++ DRM_MODE_OBJECT_CONNECTOR);
++ if (!props) {
++ weston_log("failed to get connector properties\n");
++ goto err_output;
++ }
++ drm_property_info_populate(b, connector_props, output->props_conn,
++ WDRM_CONNECTOR__COUNT, props);
++ find_and_parse_output_edid(b, output, props,
++ &make, &model, &serial_number);
++ output->base.make = (char *)make;
++ output->base.model = (char *)model;
++ output->base.serial_number = (char *)serial_number;
++ output->base.subpixel = drm_subpixel_to_wayland(output->connector->subpixel);
+
+-static void
+-create_sprites(struct drm_backend *b)
+-{
+- struct drm_sprite *sprite;
+- drmModePlaneRes *plane_res;
+- drmModePlane *plane;
+- uint32_t i;
++ drmModeFreeObjectProperties(props);
+
+- plane_res = drmModeGetPlaneResources(b->drm.fd);
+- if (!plane_res) {
+- weston_log("failed to get plane resources: %s\n",
+- strerror(errno));
+- return;
+- }
++ if (output->connector->connector_type == DRM_MODE_CONNECTOR_LVDS ||
++ output->connector->connector_type == DRM_MODE_CONNECTOR_eDP)
++ output->base.connection_internal = true;
+
+- for (i = 0; i < plane_res->count_planes; i++) {
+- plane = drmModeGetPlane(b->drm.fd, plane_res->planes[i]);
+- if (!plane)
+- continue;
++ if (drm_output_init_gamma_size(output) < 0)
++ goto err_output;
+
+- sprite = zalloc(sizeof(*sprite) + ((sizeof(uint32_t)) *
+- plane->count_formats));
+- if (!sprite) {
+- weston_log("%s: out of memory\n",
+- __func__);
+- drmModeFreePlane(plane);
+- continue;
+- }
++ output->state_cur = drm_output_state_alloc(output, NULL);
+
+- sprite->possible_crtcs = plane->possible_crtcs;
+- sprite->plane_id = plane->plane_id;
+- sprite->current = NULL;
+- sprite->next = NULL;
+- sprite->backend = b;
+- sprite->count_formats = plane->count_formats;
+- memcpy(sprite->formats, plane->formats,
+- plane->count_formats * sizeof(plane->formats[0]));
+- drmModeFreePlane(plane);
+- weston_plane_init(&sprite->plane, b->compositor, 0, 0);
+- weston_compositor_stack_plane(b->compositor, &sprite->plane,
+- &b->compositor->primary_plane);
++ output->base.mm_width = output->connector->mmWidth;
++ output->base.mm_height = output->connector->mmHeight;
+
+- wl_list_insert(&b->sprite_list, &sprite->link);
++ for (i = 0; i < output->connector->count_modes; i++) {
++ drm_mode = drm_output_add_mode(output, &output->connector->modes[i]);
++ if (!drm_mode) {
++ weston_log("failed to add mode\n");
++ goto err_output;
++ }
+ }
+
+- drmModeFreePlaneResources(plane_res);
+-}
++ weston_compositor_add_pending_output(&output->base, b->compositor);
+
+-static void
+-destroy_sprites(struct drm_backend *backend)
+-{
+- struct drm_sprite *sprite, *next;
+- struct drm_output *output;
++ return 0;
+
+- output = container_of(backend->compositor->output_list.next,
+- struct drm_output, base.link);
++err_output:
++ drm_output_destroy(&output->base);
++ return -1;
++ /* no fallthrough! */
+
+- wl_list_for_each_safe(sprite, next, &backend->sprite_list, link) {
+- drmModeSetPlane(backend->drm.fd,
+- sprite->plane_id,
+- output->crtc_id, 0, 0,
+- 0, 0, 0, 0, 0, 0, 0, 0);
+- drm_output_release_fb(output, sprite->current);
+- drm_output_release_fb(output, sprite->next);
+- weston_plane_release(&sprite->plane);
+- free(sprite);
+- }
++err_init:
++ drmModeFreeConnector(connector);
++ return -1;
+ }
+
+ static int
+@@ -2718,24 +5042,25 @@ create_outputs(struct drm_backend *b, struct udev_device *drm_device)
+ b->max_height = resources->max_height;
+
+ for (i = 0; i < resources->count_connectors; i++) {
++ int ret;
++
+ connector = drmModeGetConnector(b->drm.fd,
+ resources->connectors[i]);
+ if (connector == NULL)
+ continue;
+
+- if (connector->connection == DRM_MODE_CONNECTED &&
+- (b->connector == 0 ||
+- connector->connector_id == b->connector)) {
+- if (create_output_for_connector(b, resources,
+- connector, drm_device) < 0) {
+- drmModeFreeConnector(connector);
+- continue;
+- }
++ if (connector->connection == DRM_MODE_CONNECTED) {
++ ret = create_output_for_connector(b, resources,
++ connector, drm_device);
++ if (ret < 0)
++ weston_log("failed to create new connector\n");
+ } else {
+ drmModeFreeConnector(connector);
+ }
+ }
+
++ drm_backend_update_unused_outputs(b, resources);
++
+ if (wl_list_empty(&b->compositor->output_list) &&
+ wl_list_empty(&b->compositor->pending_output_list))
+ weston_log("No currently active connector found.\n");
+@@ -2779,11 +5104,6 @@ update_outputs(struct drm_backend *b, struct udev_device *drm_device)
+ continue;
+ }
+
+- if (b->connector && (b->connector != connector_id)) {
+- drmModeFreeConnector(connector);
+- continue;
+- }
+-
+ connected[i] = connector_id;
+
+ if (drm_output_find_by_connector(b, connector_id)) {
+@@ -2832,6 +5152,8 @@ update_outputs(struct drm_backend *b, struct udev_device *drm_device)
+ drm_output_destroy(&output->base);
+ }
+
++ drm_backend_update_unused_outputs(b, resources);
++
+ free(connected);
+ drmModeFreeResources(resources);
+ }
+@@ -2885,6 +5207,8 @@ drm_destroy(struct weston_compositor *ec)
+ wl_event_source_remove(b->udev_drm_source);
+ wl_event_source_remove(b->drm_source);
+
++ b->shutting_down = true;
++
+ destroy_sprites(b);
+
+ weston_compositor_shutdown(ec);
+@@ -2892,9 +5216,16 @@ drm_destroy(struct weston_compositor *ec)
+ if (b->gbm)
+ gbm_device_destroy(b->gbm);
+
++ udev_monitor_unref(b->udev_monitor);
++ udev_unref(b->udev);
++
+ weston_launcher_destroy(ec->launcher);
+
++ wl_array_release(&b->unused_crtcs);
++ wl_array_release(&b->unused_connectors);
++
+ close(b->drm.fd);
++ free(b->drm.filename);
+ free(b);
+ }
+
+@@ -2903,13 +5234,14 @@ session_notify(struct wl_listener *listener, void *data)
+ {
+ struct weston_compositor *compositor = data;
+ struct drm_backend *b = to_drm_backend(compositor);
+- struct drm_sprite *sprite;
++ struct drm_plane *plane;
+ struct drm_output *output;
+
+ if (compositor->session_active) {
+ weston_log("activating session\n");
+ weston_compositor_wake(compositor);
+ weston_compositor_damage_all(compositor);
++ b->state_invalid = true;
+ udev_input_enable(&b->input);
+ } else {
+ weston_log("deactivating session\n");
+@@ -2926,19 +5258,80 @@ session_notify(struct wl_listener *listener, void *data)
+ * pending frame callbacks. */
+
+ wl_list_for_each(output, &compositor->output_list, base.link) {
+- output->base.repaint_needed = 0;
+- drmModeSetCursor(b->drm.fd, output->crtc_id, 0, 0, 0);
++ output->base.repaint_needed = false;
++ if (output->cursor_plane)
++ drmModeSetCursor(b->drm.fd, output->crtc_id,
++ 0, 0, 0);
+ }
+
+ output = container_of(compositor->output_list.next,
+ struct drm_output, base.link);
+
+- wl_list_for_each(sprite, &b->sprite_list, link)
++ wl_list_for_each(plane, &b->plane_list, link) {
++ if (plane->type != WDRM_PLANE_TYPE_OVERLAY)
++ continue;
++
+ drmModeSetPlane(b->drm.fd,
+- sprite->plane_id,
++ plane->plane_id,
+ output->crtc_id, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0);
+- };
++ }
++ }
++}
++
++/**
++ * Determines whether or not a device is capable of modesetting. If successful,
++ * sets b->drm.fd and b->drm.filename to the opened device.
++ */
++static bool
++drm_device_is_kms(struct drm_backend *b, struct udev_device *device)
++{
++ const char *filename = udev_device_get_devnode(device);
++ const char *sysnum = udev_device_get_sysnum(device);
++ drmModeRes *res;
++ int id, fd;
++
++ if (!filename)
++ return false;
++
++ fd = weston_launcher_open(b->compositor->launcher, filename, O_RDWR);
++ if (fd < 0)
++ return false;
++
++ res = drmModeGetResources(fd);
++ if (!res)
++ goto out_fd;
++
++ if (res->count_crtcs <= 0 || res->count_connectors <= 0 ||
++ res->count_encoders <= 0)
++ goto out_res;
++
++ if (sysnum)
++ id = atoi(sysnum);
++ if (!sysnum || id < 0) {
++ weston_log("couldn't get sysnum for device %s\n", filename);
++ goto out_res;
++ }
++
++ /* We can be called successfully on multiple devices; if we have,
++ * clean up old entries. */
++ if (b->drm.fd >= 0)
++ weston_launcher_close(b->compositor->launcher, b->drm.fd);
++ free(b->drm.filename);
++
++ b->drm.fd = fd;
++ b->drm.id = id;
++ b->drm.filename = strdup(filename);
++
++ drmModeFreeResources(res);
++
++ return true;
++
++out_res:
++ drmModeFreeResources(res);
++out_fd:
++ weston_launcher_close(b->compositor->launcher, fd);
++ return false;
+ }
+
+ /*
+@@ -2947,6 +5340,9 @@ session_notify(struct wl_listener *listener, void *data)
+ * function loops over all devices and tries to find a PCI device with the
+ * boot_vga sysfs attribute set to 1.
+ * If no such device is found, the first DRM device reported by udev is used.
++ * Devices are also vetted to make sure they are are capable of modesetting,
++ * rather than pure render nodes (GPU with no display), or pure
++ * memory-allocation devices (VGEM).
+ */
+ static struct udev_device*
+ find_primary_gpu(struct drm_backend *b, const char *seat)
+@@ -2963,6 +5359,8 @@ find_primary_gpu(struct drm_backend *b, const char *seat)
+ udev_enumerate_scan_devices(e);
+ drm_device = NULL;
+ udev_list_entry_foreach(entry, udev_enumerate_get_list_entry(e)) {
++ bool is_boot_vga = false;
++
+ path = udev_list_entry_get_name(entry);
+ device = udev_device_new_from_syspath(b->udev, path);
+ if (!device)
+@@ -2979,27 +5377,77 @@ find_primary_gpu(struct drm_backend *b, const char *seat)
+ "pci", NULL);
+ if (pci) {
+ id = udev_device_get_sysattr_value(pci, "boot_vga");
+- if (id && !strcmp(id, "1")) {
+- if (drm_device)
+- udev_device_unref(drm_device);
+- drm_device = device;
+- break;
+- }
++ if (id && !strcmp(id, "1"))
++ is_boot_vga = true;
+ }
+
+- if (!drm_device)
+- drm_device = device;
+- else
++ /* If we already have a modesetting-capable device, and this
++ * device isn't our boot-VGA device, we aren't going to use
++ * it. */
++ if (!is_boot_vga && drm_device) {
++ udev_device_unref(device);
++ continue;
++ }
++
++ /* Make sure this device is actually capable of modesetting;
++ * if this call succeeds, b->drm.{fd,filename} will be set,
++ * and any old values freed. */
++ if (!drm_device_is_kms(b, device)) {
+ udev_device_unref(device);
++ continue;
++ }
++
++ /* There can only be one boot_vga device, and we try to use it
++ * at all costs. */
++ if (is_boot_vga) {
++ if (drm_device)
++ udev_device_unref(drm_device);
++ drm_device = device;
++ break;
++ }
++
++ /* Per the (!is_boot_vga && drm_device) test above, we only
++ * trump existing saved devices with boot-VGA devices, so if
++ * we end up here, this must be the first device we've seen. */
++ assert(!drm_device);
++ drm_device = device;
+ }
+
++ /* If we're returning a device to use, we must have an open FD for
++ * it. */
++ assert(!!drm_device == (b->drm.fd >= 0));
++
+ udev_enumerate_unref(e);
+ return drm_device;
+ }
+
++static struct udev_device *
++open_specific_drm_device(struct drm_backend *b, const char *name)
++{
++ struct udev_device *device;
++
++ device = udev_device_new_from_subsystem_sysname(b->udev, "drm", name);
++ if (!device) {
++ weston_log("ERROR: could not open DRM device '%s'\n", name);
++ return NULL;
++ }
++
++ if (!drm_device_is_kms(b, device)) {
++ udev_device_unref(device);
++ weston_log("ERROR: DRM device '%s' is not a KMS device.\n", name);
++ return NULL;
++ }
++
++ /* If we're returning a device to use, we must have an open FD for
++ * it. */
++ assert(b->drm.fd >= 0);
++
++ return device;
++}
++
+ static void
+-planes_binding(struct weston_keyboard *keyboard, uint32_t time, uint32_t key,
+- void *data)
++planes_binding(struct weston_keyboard *keyboard, uint32_t time,
++ uint32_t key, void *data)
+ {
+ struct drm_backend *b = data;
+
+@@ -3045,7 +5493,8 @@ recorder_frame_notify(struct wl_listener *listener, void *data)
+ if (!output->recorder)
+ return;
+
+- ret = drmPrimeHandleToFD(b->drm.fd, output->current->handle,
++ ret = drmPrimeHandleToFD(b->drm.fd,
++ output->scanout_plane->state_cur->fb->handle,
+ DRM_CLOEXEC, &fd);
+ if (ret) {
+ weston_log("[libva recorder] "
+@@ -3054,7 +5503,7 @@ recorder_frame_notify(struct wl_listener *listener, void *data)
+ }
+
+ ret = vaapi_recorder_frame(output->recorder, fd,
+- output->current->stride);
++ output->scanout_plane->state_cur->fb->stride);
+ if (ret < 0) {
+ weston_log("[libva recorder] aborted: %m\n");
+ recorder_destroy(output);
+@@ -3079,8 +5528,8 @@ create_recorder(struct drm_backend *b, int width, int height,
+ }
+
+ static void
+-recorder_binding(struct weston_keyboard *keyboard, uint32_t time, uint32_t key,
+- void *data)
++recorder_binding(struct weston_keyboard *keyboard, uint32_t time,
++ uint32_t key, void *data)
+ {
+ struct drm_backend *b = data;
+ struct drm_output *output;
+@@ -3121,8 +5570,8 @@ recorder_binding(struct weston_keyboard *keyboard, uint32_t time, uint32_t key,
+ }
+ #else
+ static void
+-recorder_binding(struct weston_keyboard *keyboard, uint32_t time, uint32_t key,
+- void *data)
++recorder_binding(struct weston_keyboard *keyboard, uint32_t time,
++ uint32_t key, void *data)
+ {
+ weston_log("Compiled without libva support\n");
+ }
+@@ -3173,8 +5622,8 @@ switch_to_gl_renderer(struct drm_backend *b)
+ }
+
+ static void
+-renderer_switch_binding(struct weston_keyboard *keyboard, uint32_t time,
+- uint32_t key, void *data)
++renderer_switch_binding(struct weston_keyboard *keyboard,
++ uint32_t time, uint32_t key, void *data)
+ {
+ struct drm_backend *b =
+ to_drm_backend(keyboard->seat->compositor);
+@@ -3195,7 +5644,6 @@ drm_backend_create(struct weston_compositor *compositor,
+ struct drm_backend *b;
+ struct udev_device *drm_device;
+ struct wl_event_loop *loop;
+- const char *path;
+ const char *seat_id = default_seat;
+ int ret;
+
+@@ -3205,6 +5653,11 @@ drm_backend_create(struct weston_compositor *compositor,
+ if (b == NULL)
+ return NULL;
+
++ b->state_invalid = true;
++ b->drm.fd = -1;
++ wl_array_init(&b->unused_crtcs);
++ wl_array_init(&b->unused_connectors);
++
+ /*
+ * KMS support for hardware planes cannot properly synchronize
+ * without nuclear page flip. Without nuclear/atomic, hw plane
+@@ -3218,6 +5671,9 @@ drm_backend_create(struct weston_compositor *compositor,
+ b->sprites_are_broken = 1;
+ b->compositor = compositor;
+ b->use_pixman = config->use_pixman;
++ b->pageflip_timeout = config->pageflip_timeout;
++
++ compositor->backend = &b->base;
+
+ if (parse_gbm_format(config->gbm_format, GBM_FORMAT_XRGB8888, &b->gbm_format) < 0)
+ goto err_compositor;
+@@ -3229,8 +5685,9 @@ drm_backend_create(struct weston_compositor *compositor,
+ compositor->launcher = weston_launcher_connect(compositor, config->tty,
+ seat_id, true);
+ if (compositor->launcher == NULL) {
+- weston_log("fatal: drm backend should be run "
+- "using weston-launch binary or as root\n");
++ weston_log("fatal: drm backend should be run using "
++ "weston-launch binary, or your system should "
++ "provide the logind D-Bus API.\n");
+ goto err_compositor;
+ }
+
+@@ -3243,14 +5700,16 @@ drm_backend_create(struct weston_compositor *compositor,
+ b->session_listener.notify = session_notify;
+ wl_signal_add(&compositor->session_signal, &b->session_listener);
+
+- drm_device = find_primary_gpu(b, seat_id);
++ if (config->specific_device)
++ drm_device = open_specific_drm_device(b, config->specific_device);
++ else
++ drm_device = find_primary_gpu(b, seat_id);
+ if (drm_device == NULL) {
+ weston_log("no drm device found\n");
+ goto err_udev;
+ }
+- path = udev_device_get_syspath(drm_device);
+
+- if (init_drm(b, drm_device) < 0) {
++ if (init_kms_caps(b) < 0) {
+ weston_log("failed to initialize kms\n");
+ goto err_udev_dev;
+ }
+@@ -3262,21 +5721,20 @@ drm_backend_create(struct weston_compositor *compositor,
+ }
+ } else {
+ if (init_egl(b) < 0) {
+- weston_log("failed to initialize egl, use pixman\n");
+- if (init_pixman(b) < 0) {
+- weston_log("failed to initialize pixman renderer\n");
+- goto err_udev_dev;
+- }
+- b->use_pixman = 1;
++ weston_log("failed to initialize egl\n");
++ goto err_udev_dev;
+ }
+ }
+
+ b->base.destroy = drm_destroy;
+ b->base.restore = drm_restore;
++ b->base.repaint_begin = drm_repaint_begin;
++ b->base.repaint_flush = drm_repaint_flush;
++ b->base.repaint_cancel = drm_repaint_cancel;
+
+ weston_setup_vt_switch_bindings(compositor);
+
+- wl_list_init(&b->sprite_list);
++ wl_list_init(&b->plane_list);
+ create_sprites(b);
+
+ if (udev_input_init(&b->input,
+@@ -3286,10 +5744,8 @@ drm_backend_create(struct weston_compositor *compositor,
+ goto err_sprite;
+ }
+
+- b->connector = config->connector;
+-
+ if (create_outputs(b, drm_device) < 0) {
+- weston_log("failed to create output for %s\n", path);
++ weston_log("failed to create output for %s\n", b->drm.filename);
+ goto err_udev_input;
+ }
+
+@@ -3298,8 +5754,6 @@ drm_backend_create(struct weston_compositor *compositor,
+ if (!b->cursors_are_broken)
+ compositor->capabilities |= WESTON_CAP_CURSOR_PLANE;
+
+- path = NULL;
+-
+ loop = wl_display_get_event_loop(compositor->wl_display);
+ b->drm_source =
+ wl_event_loop_add_fd(loop, b->drm.fd,
+@@ -3341,8 +5795,6 @@ drm_backend_create(struct weston_compositor *compositor,
+ "support failed.\n");
+ }
+
+- compositor->backend = &b->base;
+-
+ ret = weston_plugin_api_register(compositor, WESTON_DRM_OUTPUT_API_NAME,
+ &api, sizeof(api));
+
+diff --git a/libweston/compositor-drm.h b/libweston/compositor-drm.h
+index 2e2995a..838e937 100644
+--- a/libweston/compositor-drm.h
++++ b/libweston/compositor-drm.h
+@@ -35,7 +35,7 @@
+ extern "C" {
+ #endif
+
+-#define WESTON_DRM_BACKEND_CONFIG_VERSION 2
++#define WESTON_DRM_BACKEND_CONFIG_VERSION 3
+
+ struct libinput_device;
+
+@@ -138,6 +138,20 @@ struct weston_drm_backend_config {
+ */
+ void (*configure_device)(struct weston_compositor *compositor,
+ struct libinput_device *device);
++
++ /** Maximum duration for a pageflip event to arrive, after which the
++ * compositor will consider the DRM driver crashed and will try to exit
++ * cleanly.
++ *
++ * It is exprimed in milliseconds, 0 means disabled. */
++ uint32_t pageflip_timeout;
++
++ /** Specific DRM device to open
++ *
++ * A DRM device name, like "card0", to open. If NULL, use heuristics
++ * based on seat names and boot_vga to find the right device.
++ */
++ char *specific_device;
+ };
+
+ #ifdef __cplusplus
+diff --git a/libweston/compositor-fbdev.c b/libweston/compositor-fbdev.c
+index 44f0cf5..32d71e0 100644
+--- a/libweston/compositor-fbdev.c
++++ b/libweston/compositor-fbdev.c
+@@ -118,7 +118,8 @@ fbdev_output_start_repaint_loop(struct weston_output *output)
+ }
+
+ static int
+-fbdev_output_repaint(struct weston_output *base, pixman_region32_t *damage)
++fbdev_output_repaint(struct weston_output *base, pixman_region32_t *damage,
++ void *repaint_data)
+ {
+ struct fbdev_output *output = to_fbdev_output(base);
+ struct weston_compositor *ec = output->base.compositor;
+@@ -693,7 +694,7 @@ session_notify(struct wl_listener *listener, void *data)
+
+ wl_list_for_each(output,
+ &compositor->output_list, link) {
+- output->repaint_needed = 0;
++ output->repaint_needed = false;
+ }
+ }
+ }
+diff --git a/libweston/compositor-headless.c b/libweston/compositor-headless.c
+index a1aec6d..9e42e7f 100644
+--- a/libweston/compositor-headless.c
++++ b/libweston/compositor-headless.c
+@@ -92,7 +92,8 @@ finish_frame_handler(void *data)
+
+ static int
+ headless_output_repaint(struct weston_output *output_base,
+- pixman_region32_t *damage)
++ pixman_region32_t *damage,
++ void *repaint_data)
+ {
+ struct headless_output *output = to_headless_output(output_base);
+ struct weston_compositor *ec = output->base.compositor;
+diff --git a/libweston/compositor-rdp.c b/libweston/compositor-rdp.c
+index d9668e8..091472b 100644
+--- a/libweston/compositor-rdp.c
++++ b/libweston/compositor-rdp.c
+@@ -355,7 +355,8 @@ rdp_output_start_repaint_loop(struct weston_output *output)
+ }
+
+ static int
+-rdp_output_repaint(struct weston_output *output_base, pixman_region32_t *damage)
++rdp_output_repaint(struct weston_output *output_base, pixman_region32_t *damage,
++ void *repaint_data)
+ {
+ struct rdp_output *output = container_of(output_base, struct rdp_output, base);
+ struct weston_compositor *ec = output->base.compositor;
+diff --git a/libweston/compositor-wayland.c b/libweston/compositor-wayland.c
+index 9d35ef7..ebdbd13 100644
+--- a/libweston/compositor-wayland.c
++++ b/libweston/compositor-wayland.c
+@@ -488,7 +488,8 @@ wayland_output_start_repaint_loop(struct weston_output *output_base)
+ #ifdef ENABLE_EGL
+ static int
+ wayland_output_repaint_gl(struct weston_output *output_base,
+- pixman_region32_t *damage)
++ pixman_region32_t *damage,
++ void *repaint_data)
+ {
+ struct wayland_output *output = to_wayland_output(output_base);
+ struct weston_compositor *ec = output->base.compositor;
+@@ -595,7 +596,8 @@ wayland_shm_buffer_attach(struct wayland_shm_buffer *sb)
+
+ static int
+ wayland_output_repaint_pixman(struct weston_output *output_base,
+- pixman_region32_t *damage)
++ pixman_region32_t *damage,
++ void *repaint_data)
+ {
+ struct wayland_output *output = to_wayland_output(output_base);
+ struct wayland_backend *b =
+diff --git a/libweston/compositor-x11.c b/libweston/compositor-x11.c
+index f9cb461..02cdf3e 100644
+--- a/libweston/compositor-x11.c
++++ b/libweston/compositor-x11.c
+@@ -389,7 +389,8 @@ x11_output_start_repaint_loop(struct weston_output *output)
+
+ static int
+ x11_output_repaint_gl(struct weston_output *output_base,
+- pixman_region32_t *damage)
++ pixman_region32_t *damage,
++ void *repaint_data)
+ {
+ struct x11_output *output = to_x11_output(output_base);
+ struct weston_compositor *ec = output->base.compositor;
+@@ -457,7 +458,8 @@ set_clip_for_output(struct weston_output *output_base, pixman_region32_t *region
+
+ static int
+ x11_output_repaint_shm(struct weston_output *output_base,
+- pixman_region32_t *damage)
++ pixman_region32_t *damage,
++ void *repaint_data)
+ {
+ struct x11_output *output = to_x11_output(output_base);
+ struct weston_compositor *ec = output->base.compositor;
+diff --git a/libweston/compositor.c b/libweston/compositor.c
+index 9ded23f..fb647da 100644
+--- a/libweston/compositor.c
++++ b/libweston/compositor.c
+@@ -2254,7 +2254,7 @@ weston_output_take_feedback_list(struct weston_output *output,
+ }
+
+ static int
+-weston_output_repaint(struct weston_output *output)
++weston_output_repaint(struct weston_output *output, void *repaint_data)
+ {
+ struct weston_compositor *ec = output->compositor;
+ struct weston_view *ev;
+@@ -2273,7 +2273,7 @@ weston_output_repaint(struct weston_output *output)
+ weston_compositor_build_view_list(ec);
+
+ if (output->assign_planes && !output->disable_planes) {
+- output->assign_planes(output);
++ output->assign_planes(output, repaint_data);
+ } else {
+ wl_list_for_each(ev, &ec->view_list, link) {
+ weston_view_move_to_plane(ev, &ec->primary_plane);
+@@ -2306,11 +2306,13 @@ weston_output_repaint(struct weston_output *output)
+ if (output->dirty)
+ weston_output_update_matrix(output);
+
+- r = output->repaint(output, &output_damage);
++ r = output->repaint(output, &output_damage, repaint_data);
+
+ pixman_region32_fini(&output_damage);
+
+- output->repaint_needed = 0;
++ output->repaint_needed = false;
++ if (r == 0)
++ output->repaint_status = REPAINT_AWAITING_COMPLETION;
+
+ weston_compositor_repick(ec);
+
+@@ -2332,16 +2334,25 @@ weston_output_repaint(struct weston_output *output)
+ static void
+ weston_output_schedule_repaint_reset(struct weston_output *output)
+ {
+- output->repaint_scheduled = 0;
++ output->repaint_status = REPAINT_NOT_SCHEDULED;
+ TL_POINT("core_repaint_exit_loop", TLP_OUTPUT(output), TLP_END);
+ }
+
+ static int
+-output_repaint_timer_handler(void *data)
++weston_output_maybe_repaint(struct weston_output *output, struct timespec *now,
++ void *repaint_data)
+ {
+- struct weston_output *output = data;
+ struct weston_compositor *compositor = output->compositor;
+- int ret;
++ int ret = 0;
++ int64_t msec_to_repaint;
++
++ /* We're not ready yet; come back to make a decision later. */
++ if (output->repaint_status != REPAINT_SCHEDULED)
++ return ret;
++
++ msec_to_repaint = timespec_sub_to_msec(&output->next_repaint, now);
++ if (msec_to_repaint > 1)
++ return ret;
+
+ /* If we're sleeping, drop the repaint machinery entirely; we will
+ * explicitly repaint all outputs when we come back. */
+@@ -2356,15 +2367,92 @@ output_repaint_timer_handler(void *data)
+
+ /* If repaint fails, we aren't going to get weston_output_finish_frame
+ * to trigger a new repaint, so drop it from repaint and hope
+- * something schedules a successful repaint later. */
+- ret = weston_output_repaint(output);
++ * something schedules a successful repaint later. As repainting may
++ * take some time, re-read our clock as a courtesy to the next
++ * output. */
++ ret = weston_output_repaint(output, repaint_data);
++ weston_compositor_read_presentation_clock(compositor, now);
+ if (ret != 0)
+ goto err;
+
+- return 0;
++ return ret;
+
+ err:
+ weston_output_schedule_repaint_reset(output);
++ return ret;
++}
++
++static void
++output_repaint_timer_arm(struct weston_compositor *compositor)
++{
++ struct weston_output *output;
++ bool any_should_repaint = false;
++ struct timespec now;
++ int64_t msec_to_next;
++
++ weston_compositor_read_presentation_clock(compositor, &now);
++
++ wl_list_for_each(output, &compositor->output_list, link) {
++ int64_t msec_to_this;
++
++ if (output->repaint_status != REPAINT_SCHEDULED)
++ continue;
++
++ msec_to_this = timespec_sub_to_msec(&output->next_repaint,
++ &now);
++ if (!any_should_repaint || msec_to_this < msec_to_next)
++ msec_to_next = msec_to_this;
++
++ any_should_repaint = true;
++ }
++
++ if (!any_should_repaint)
++ return;
++
++ /* Even if we should repaint immediately, add the minimum 1 ms delay.
++ * This is a workaround to allow coalescing multiple output repaints
++ * particularly from weston_output_finish_frame()
++ * into the same call, which would not happen if we called
++ * output_repaint_timer_handler() directly.
++ */
++ if (msec_to_next < 1)
++ msec_to_next = 1;
++
++ wl_event_source_timer_update(compositor->repaint_timer, msec_to_next);
++}
++
++static int
++output_repaint_timer_handler(void *data)
++{
++ struct weston_compositor *compositor = data;
++ struct weston_output *output;
++ struct timespec now;
++ void *repaint_data = NULL;
++ int ret;
++
++ weston_compositor_read_presentation_clock(compositor, &now);
++
++ if (compositor->backend->repaint_begin)
++ repaint_data = compositor->backend->repaint_begin(compositor);
++
++ wl_list_for_each(output, &compositor->output_list, link) {
++ ret = weston_output_maybe_repaint(output, &now, repaint_data);
++ if (ret)
++ break;
++ }
++
++ if (ret == 0) {
++ if (compositor->backend->repaint_flush)
++ compositor->backend->repaint_flush(compositor,
++ repaint_data);
++ } else {
++ if (compositor->backend->repaint_cancel)
++ compositor->backend->repaint_cancel(compositor,
++ repaint_data);
++ }
++
++ output_repaint_timer_arm(compositor);
++
+ return 0;
+ }
+
+@@ -2376,47 +2464,59 @@ weston_output_finish_frame(struct weston_output *output,
+ struct weston_compositor *compositor = output->compositor;
+ int32_t refresh_nsec;
+ struct timespec now;
+- struct timespec gone;
+- int msec;
++ int64_t msec_rel;
+
+ TL_POINT("core_repaint_finished", TLP_OUTPUT(output),
+ TLP_VBLANK(stamp), TLP_END);
+
++ assert(output->repaint_status == REPAINT_AWAITING_COMPLETION);
++ assert(stamp || (presented_flags & WP_PRESENTATION_FEEDBACK_INVALID));
++
++ weston_compositor_read_presentation_clock(compositor, &now);
++
++ /* If we haven't been supplied any timestamp at all, we don't have a
++ * timebase to work against, so any delay just wastes time. Push a
++ * repaint as soon as possible so we can get on with it. */
++ if (!stamp) {
++ output->next_repaint = now;
++ goto out;
++ }
++
+ refresh_nsec = millihz_to_nsec(output->current_mode->refresh);
+ weston_presentation_feedback_present_list(&output->feedback_list,
+ output, refresh_nsec, stamp,
+ output->msc,
+ presented_flags);
+
+- output->frame_time = stamp->tv_sec * 1000 + stamp->tv_nsec / 1000000;
++ output->frame_time = timespec_to_msec(stamp);
+
+- weston_compositor_read_presentation_clock(compositor, &now);
+- timespec_sub(&gone, &now, stamp);
+- msec = (refresh_nsec - timespec_to_nsec(&gone)) / 1000000; /* floor */
+- msec -= compositor->repaint_msec;
++ timespec_add_nsec(&output->next_repaint, stamp, refresh_nsec);
++ timespec_add_msec(&output->next_repaint, &output->next_repaint,
++ -compositor->repaint_msec);
++ msec_rel = timespec_sub_to_msec(&output->next_repaint, &now);
+
+- if (msec < -1000 || msec > 1000) {
++ if (msec_rel < -1000 || msec_rel > 1000) {
+ static bool warned;
+
+ if (!warned)
+ weston_log("Warning: computed repaint delay is "
+- "insane: %d msec\n", msec);
++ "insane: %lld msec\n", (long long) msec_rel);
+ warned = true;
+
+- msec = 0;
++ output->next_repaint = now;
+ }
+
+ /* Called from restart_repaint_loop and restart happens already after
+ * the deadline given by repaint_msec? In that case we delay until
+ * the deadline of the next frame, to give clients a more predictable
+ * timing of the repaint cycle to lock on. */
+- if (presented_flags == WP_PRESENTATION_FEEDBACK_INVALID && msec < 0)
+- msec += refresh_nsec / 1000000;
++ if (presented_flags == WP_PRESENTATION_FEEDBACK_INVALID && msec_rel < 0)
++ timespec_add_nsec(&output->next_repaint, &output->next_repaint,
++ refresh_nsec);
+
+- if (msec < 1)
+- output_repaint_timer_handler(output);
+- else
+- wl_event_source_timer_update(output->repaint_timer, msec);
++out:
++ output->repaint_status = REPAINT_SCHEDULED;
++ output_repaint_timer_arm(compositor);
+ }
+
+ static void
+@@ -2424,6 +2524,8 @@ idle_repaint(void *data)
+ {
+ struct weston_output *output = data;
+
++ assert(output->repaint_status == REPAINT_BEGIN_FROM_IDLE);
++ output->repaint_status = REPAINT_AWAITING_COMPLETION;
+ output->start_repaint_loop(output);
+ }
+
+@@ -2538,12 +2640,17 @@ weston_output_schedule_repaint(struct weston_output *output)
+ TL_POINT("core_repaint_req", TLP_OUTPUT(output), TLP_END);
+
+ loop = wl_display_get_event_loop(compositor->wl_display);
+- output->repaint_needed = 1;
+- if (output->repaint_scheduled)
++ output->repaint_needed = true;
++
++ /* If we already have a repaint scheduled for our idle handler,
++ * no need to set it again. If the repaint has been called but
++ * not finished, then weston_output_finish_frame() will notice
++ * that a repaint is needed and schedule one. */
++ if (output->repaint_status != REPAINT_NOT_SCHEDULED)
+ return;
+
++ output->repaint_status = REPAINT_BEGIN_FROM_IDLE;
+ wl_event_loop_add_idle(loop, idle_repaint, output);
+- output->repaint_scheduled = 1;
+ TL_POINT("core_repaint_enter_loop", TLP_OUTPUT(output), TLP_END);
+ }
+
+@@ -4400,8 +4507,6 @@ weston_output_transform_coordinate(struct weston_output *output,
+ static void
+ weston_output_enable_undo(struct weston_output *output)
+ {
+- wl_event_source_remove(output->repaint_timer);
+-
+ wl_global_destroy(output->global);
+
+ pixman_region32_fini(&output->region);
+@@ -4583,7 +4688,6 @@ weston_output_enable(struct weston_output *output)
+ {
+ struct weston_compositor *c = output->compositor;
+ struct weston_output *iterator;
+- struct wl_event_loop *loop;
+ int x = 0, y = 0;
+
+ assert(output->enable);
+@@ -4624,10 +4728,6 @@ weston_output_enable(struct weston_output *output)
+ wl_list_init(&output->feedback_list);
+ wl_list_init(&output->link);
+
+- loop = wl_display_get_event_loop(c->wl_display);
+- output->repaint_timer = wl_event_loop_add_timer(loop,
+- output_repaint_timer_handler, output);
+-
+ /* Invert the output id pool and look for the lowest numbered
+ * switch (the least significant bit). Take that bit's position
+ * as our ID, and mark it used in the compositor's output_id_pool.
+@@ -5129,6 +5229,9 @@ weston_compositor_create(struct wl_display *display, void *user_data)
+
+ loop = wl_display_get_event_loop(ec->wl_display);
+ ec->idle_source = wl_event_loop_add_timer(loop, idle_handler, ec);
++ ec->repaint_timer =
++ wl_event_loop_add_timer(loop, output_repaint_timer_handler,
++ ec);
+
+ weston_layer_init(&ec->fade_layer, ec);
+ weston_layer_init(&ec->cursor_layer, ec);
+diff --git a/libweston/compositor.h b/libweston/compositor.h
+index 08e728a..6070c77 100644
+--- a/libweston/compositor.h
++++ b/libweston/compositor.h
+@@ -170,9 +170,23 @@ struct weston_output {
+ pixman_region32_t region;
+
+ pixman_region32_t previous_damage;
+- int repaint_needed;
+- int repaint_scheduled;
+- struct wl_event_source *repaint_timer;
++
++ /** True if damage has occurred since the last repaint for this output;
++ * if set, a repaint will eventually occur. */
++ bool repaint_needed;
++
++ /** State of the repaint loop */
++ enum {
++ REPAINT_NOT_SCHEDULED = 0, /**< idle; no repaint will occur */
++ REPAINT_BEGIN_FROM_IDLE, /**< start_repaint_loop scheduled */
++ REPAINT_SCHEDULED, /**< repaint is scheduled to occur */
++ REPAINT_AWAITING_COMPLETION, /**< last repaint not yet finished */
++ } repaint_status;
++
++ /** If repaint_status is REPAINT_SCHEDULED, contains the time the
++ * next repaint should be run */
++ struct timespec next_repaint;
++
+ struct weston_output_zoom zoom;
+ int dirty;
+ struct wl_signal frame_signal;
+@@ -198,9 +212,10 @@ struct weston_output {
+
+ void (*start_repaint_loop)(struct weston_output *output);
+ int (*repaint)(struct weston_output *output,
+- pixman_region32_t *damage);
++ pixman_region32_t *damage,
++ void *repaint_data);
+ void (*destroy)(struct weston_output *output);
+- void (*assign_planes)(struct weston_output *output);
++ void (*assign_planes)(struct weston_output *output, void *repaint_data);
+ int (*switch_mode)(struct weston_output *output, struct weston_mode *mode);
+
+ /* backlight values are on 0-255 range, where higher is brighter */
+@@ -790,6 +805,39 @@ struct weston_backend_config {
+ struct weston_backend {
+ void (*destroy)(struct weston_compositor *compositor);
+ void (*restore)(struct weston_compositor *compositor);
++
++ /** Begin a repaint sequence
++ *
++ * Provides the backend with explicit markers around repaint
++ * sequences, which may allow the backend to aggregate state
++ * application. This call will be bracketed by the repaint_flush (on
++ * success), or repaint_cancel (when any output in the grouping fails
++ * repaint).
++ *
++ * Returns an opaque pointer, which the backend may use as private
++ * data referring to the repaint cycle.
++ */
++ void * (*repaint_begin)(struct weston_compositor *compositor);
++
++ /** Cancel a repaint sequence
++ *
++ * Cancels a repaint sequence, when an error has occurred during
++ * one output's repaint; see repaint_begin.
++ *
++ * @param repaint_data Data returned by repaint_begin
++ */
++ void (*repaint_cancel)(struct weston_compositor *compositor,
++ void *repaint_data);
++
++ /** Conclude a repaint sequence
++ *
++ * Called on successful completion of a repaint sequence; see
++ * repaint_begin.
++ *
++ * @param repaint_data Data returned by repaint_begin
++ */
++ void (*repaint_flush)(struct weston_compositor *compositor,
++ void *repaint_data);
+ };
+
+ struct weston_desktop_xwayland;
+@@ -845,6 +893,7 @@ struct weston_compositor {
+ struct wl_event_source *idle_source;
+ uint32_t idle_inhibit;
+ int idle_time; /* timeout, s */
++ struct wl_event_source *repaint_timer;
+
+ const struct weston_pointer_grab_interface *default_pointer_grab;
+
+diff --git a/libweston/pixel-formats.c b/libweston/pixel-formats.c
+new file mode 100644
+index 0000000..df84a9f
+--- /dev/null
++++ b/libweston/pixel-formats.c
+@@ -0,0 +1,430 @@
++/*
++ * Copyright © 2016 Collabora, Ltd.
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software"),
++ * to deal in the Software without restriction, including without limitation
++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ * and/or sell copies of the Software, and to permit persons to whom the
++ * Software is furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the next
++ * paragraph) shall be included in all copies or substantial portions of the
++ * Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
++ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++ * DEALINGS IN THE SOFTWARE.
++ *
++ * Author: Daniel Stone <daniels@collabora.com>
++ */
++
++#include "config.h"
++
++#include <endian.h>
++#include <inttypes.h>
++#include <stdbool.h>
++#include <unistd.h>
++#include <drm_fourcc.h>
++
++#include "helpers.h"
++#include "wayland-util.h"
++#include "pixel-formats.h"
++
++#if ENABLE_EGL
++#include <EGL/egl.h>
++#include <EGL/eglext.h>
++#include <GLES2/gl2.h>
++#include <GLES2/gl2ext.h>
++#define GL_FORMAT(fmt) .gl_format = (fmt)
++#define GL_TYPE(type) .gl_type = (type)
++#define SAMPLER_TYPE(type) .sampler_type = (type)
++#else
++#define GL_FORMAT(fmt) .gl_format = 0
++#define GL_TYPE(type) .gl_type = 0
++#define SAMPLER_TYPE(type) .sampler_type = 0
++#endif
++
++#include "weston-egl-ext.h"
++
++/**
++ * Table of DRM formats supported by Weston; RGB, ARGB and YUV formats are
++ * supported. Indexed/greyscale formats, and formats not containing complete
++ * colour channels, are not supported.
++ */
++static const struct pixel_format_info pixel_format_table[] = {
++ {
++ .format = DRM_FORMAT_XRGB4444,
++ },
++ {
++ .format = DRM_FORMAT_ARGB4444,
++ .opaque_substitute = DRM_FORMAT_XRGB4444,
++ },
++ {
++ .format = DRM_FORMAT_XBGR4444,
++ },
++ {
++ .format = DRM_FORMAT_ABGR4444,
++ .opaque_substitute = DRM_FORMAT_XBGR4444,
++ },
++ {
++ .format = DRM_FORMAT_RGBX4444,
++# if __BYTE_ORDER == __LITTLE_ENDIAN
++ GL_FORMAT(GL_RGBA),
++ GL_TYPE(GL_UNSIGNED_SHORT_4_4_4_4),
++#endif
++ },
++ {
++ .format = DRM_FORMAT_RGBA4444,
++ .opaque_substitute = DRM_FORMAT_RGBX4444,
++# if __BYTE_ORDER == __LITTLE_ENDIAN
++ GL_FORMAT(GL_RGBA),
++ GL_TYPE(GL_UNSIGNED_SHORT_4_4_4_4),
++#endif
++ },
++ {
++ .format = DRM_FORMAT_BGRX4444,
++ },
++ {
++ .format = DRM_FORMAT_BGRA4444,
++ .opaque_substitute = DRM_FORMAT_BGRX4444,
++ },
++ {
++ .format = DRM_FORMAT_XRGB1555,
++ .depth = 15,
++ .bpp = 16,
++ },
++ {
++ .format = DRM_FORMAT_ARGB1555,
++ .opaque_substitute = DRM_FORMAT_XRGB1555,
++ },
++ {
++ .format = DRM_FORMAT_XBGR1555,
++ },
++ {
++ .format = DRM_FORMAT_ABGR1555,
++ .opaque_substitute = DRM_FORMAT_XBGR1555,
++ },
++ {
++ .format = DRM_FORMAT_RGBX5551,
++# if __BYTE_ORDER == __LITTLE_ENDIAN
++ GL_FORMAT(GL_RGBA),
++ GL_TYPE(GL_UNSIGNED_SHORT_5_5_5_1),
++#endif
++ },
++ {
++ .format = DRM_FORMAT_RGBA5551,
++ .opaque_substitute = DRM_FORMAT_RGBX5551,
++# if __BYTE_ORDER == __LITTLE_ENDIAN
++ GL_FORMAT(GL_RGBA),
++ GL_TYPE(GL_UNSIGNED_SHORT_5_5_5_1),
++#endif
++ },
++ {
++ .format = DRM_FORMAT_BGRX5551,
++ },
++ {
++ .format = DRM_FORMAT_BGRA5551,
++ .opaque_substitute = DRM_FORMAT_BGRX5551,
++ },
++ {
++ .format = DRM_FORMAT_RGB565,
++ .depth = 16,
++ .bpp = 16,
++# if __BYTE_ORDER == __LITTLE_ENDIAN
++ GL_FORMAT(GL_RGB),
++ GL_TYPE(GL_UNSIGNED_SHORT_5_6_5),
++#endif
++ },
++ {
++ .format = DRM_FORMAT_BGR565,
++ },
++ {
++ .format = DRM_FORMAT_RGB888,
++ },
++ {
++ .format = DRM_FORMAT_BGR888,
++ GL_FORMAT(GL_RGB),
++ GL_TYPE(GL_UNSIGNED_BYTE),
++ },
++ {
++ .format = DRM_FORMAT_XRGB8888,
++ .depth = 24,
++ .bpp = 32,
++ GL_FORMAT(GL_BGRA_EXT),
++ GL_TYPE(GL_UNSIGNED_BYTE),
++ },
++ {
++ .format = DRM_FORMAT_ARGB8888,
++ .opaque_substitute = DRM_FORMAT_XRGB8888,
++ .depth = 32,
++ .bpp = 32,
++ GL_FORMAT(GL_BGRA_EXT),
++ GL_TYPE(GL_UNSIGNED_BYTE),
++ },
++ {
++ .format = DRM_FORMAT_XBGR8888,
++ GL_FORMAT(GL_RGBA),
++ GL_TYPE(GL_UNSIGNED_BYTE),
++ },
++ {
++ .format = DRM_FORMAT_ABGR8888,
++ .opaque_substitute = DRM_FORMAT_XBGR8888,
++ GL_FORMAT(GL_RGBA),
++ GL_TYPE(GL_UNSIGNED_BYTE),
++ },
++ {
++ .format = DRM_FORMAT_RGBX8888,
++ },
++ {
++ .format = DRM_FORMAT_RGBA8888,
++ .opaque_substitute = DRM_FORMAT_RGBX8888,
++ },
++ {
++ .format = DRM_FORMAT_BGRX8888,
++ },
++ {
++ .format = DRM_FORMAT_BGRA8888,
++ .opaque_substitute = DRM_FORMAT_BGRX8888,
++ },
++ {
++ .format = DRM_FORMAT_XRGB2101010,
++ .depth = 30,
++ .bpp = 32,
++ },
++ {
++ .format = DRM_FORMAT_ARGB2101010,
++ .opaque_substitute = DRM_FORMAT_XRGB2101010,
++ },
++ {
++ .format = DRM_FORMAT_XBGR2101010,
++# if __BYTE_ORDER == __LITTLE_ENDIAN
++ GL_FORMAT(GL_RGBA),
++ GL_TYPE(GL_UNSIGNED_INT_2_10_10_10_REV_EXT),
++#endif
++ },
++ {
++ .format = DRM_FORMAT_ABGR2101010,
++ .opaque_substitute = DRM_FORMAT_XBGR2101010,
++# if __BYTE_ORDER == __LITTLE_ENDIAN
++ GL_FORMAT(GL_RGBA),
++ GL_TYPE(GL_UNSIGNED_INT_2_10_10_10_REV_EXT),
++#endif
++ },
++ {
++ .format = DRM_FORMAT_RGBX1010102,
++ },
++ {
++ .format = DRM_FORMAT_RGBA1010102,
++ .opaque_substitute = DRM_FORMAT_RGBX1010102,
++ },
++ {
++ .format = DRM_FORMAT_BGRX1010102,
++ },
++ {
++ .format = DRM_FORMAT_BGRA1010102,
++ .opaque_substitute = DRM_FORMAT_BGRX1010102,
++ },
++ {
++ .format = DRM_FORMAT_YUYV,
++ SAMPLER_TYPE(EGL_TEXTURE_Y_XUXV_WL),
++ .num_planes = 1,
++ .hsub = 2,
++ },
++ {
++ .format = DRM_FORMAT_YVYU,
++ SAMPLER_TYPE(EGL_TEXTURE_Y_XUXV_WL),
++ .num_planes = 1,
++ .chroma_order = ORDER_VU,
++ .hsub = 2,
++ },
++ {
++ .format = DRM_FORMAT_UYVY,
++ SAMPLER_TYPE(EGL_TEXTURE_Y_XUXV_WL),
++ .num_planes = 1,
++ .luma_chroma_order = ORDER_CHROMA_LUMA,
++ .hsub = 2,
++ },
++ {
++ .format = DRM_FORMAT_VYUY,
++ SAMPLER_TYPE(EGL_TEXTURE_Y_XUXV_WL),
++ .num_planes = 1,
++ .luma_chroma_order = ORDER_CHROMA_LUMA,
++ .chroma_order = ORDER_VU,
++ .hsub = 2,
++ },
++ {
++ .format = DRM_FORMAT_NV12,
++ SAMPLER_TYPE(EGL_TEXTURE_Y_UV_WL),
++ .num_planes = 2,
++ .hsub = 2,
++ .vsub = 2,
++ },
++ {
++ .format = DRM_FORMAT_NV21,
++ SAMPLER_TYPE(EGL_TEXTURE_Y_UV_WL),
++ .num_planes = 2,
++ .chroma_order = ORDER_VU,
++ .hsub = 2,
++ .vsub = 2,
++ },
++ {
++ .format = DRM_FORMAT_NV16,
++ SAMPLER_TYPE(EGL_TEXTURE_Y_UV_WL),
++ .num_planes = 2,
++ .hsub = 2,
++ .vsub = 1,
++ },
++ {
++ .format = DRM_FORMAT_NV61,
++ SAMPLER_TYPE(EGL_TEXTURE_Y_UV_WL),
++ .num_planes = 2,
++ .chroma_order = ORDER_VU,
++ .hsub = 2,
++ .vsub = 1,
++ },
++ {
++ .format = DRM_FORMAT_NV24,
++ SAMPLER_TYPE(EGL_TEXTURE_Y_UV_WL),
++ .num_planes = 2,
++ },
++ {
++ .format = DRM_FORMAT_NV42,
++ SAMPLER_TYPE(EGL_TEXTURE_Y_UV_WL),
++ .num_planes = 2,
++ .chroma_order = ORDER_VU,
++ },
++ {
++ .format = DRM_FORMAT_YUV410,
++ SAMPLER_TYPE(EGL_TEXTURE_Y_U_V_WL),
++ .num_planes = 3,
++ .hsub = 4,
++ .vsub = 4,
++ },
++ {
++ .format = DRM_FORMAT_YVU410,
++ SAMPLER_TYPE(EGL_TEXTURE_Y_U_V_WL),
++ .num_planes = 3,
++ .chroma_order = ORDER_VU,
++ .hsub = 4,
++ .vsub = 4,
++ },
++ {
++ .format = DRM_FORMAT_YUV411,
++ SAMPLER_TYPE(EGL_TEXTURE_Y_U_V_WL),
++ .num_planes = 3,
++ .hsub = 4,
++ .vsub = 1,
++ },
++ {
++ .format = DRM_FORMAT_YVU411,
++ SAMPLER_TYPE(EGL_TEXTURE_Y_U_V_WL),
++ .num_planes = 3,
++ .chroma_order = ORDER_VU,
++ .hsub = 4,
++ .vsub = 1,
++ },
++ {
++ .format = DRM_FORMAT_YUV420,
++ SAMPLER_TYPE(EGL_TEXTURE_Y_U_V_WL),
++ .num_planes = 3,
++ .hsub = 2,
++ .vsub = 2,
++ },
++ {
++ .format = DRM_FORMAT_YVU420,
++ SAMPLER_TYPE(EGL_TEXTURE_Y_U_V_WL),
++ .num_planes = 3,
++ .chroma_order = ORDER_VU,
++ .hsub = 2,
++ .vsub = 2,
++ },
++ {
++ .format = DRM_FORMAT_YUV422,
++ SAMPLER_TYPE(EGL_TEXTURE_Y_U_V_WL),
++ .num_planes = 3,
++ .hsub = 2,
++ .vsub = 1,
++ },
++ {
++ .format = DRM_FORMAT_YVU422,
++ SAMPLER_TYPE(EGL_TEXTURE_Y_U_V_WL),
++ .num_planes = 3,
++ .chroma_order = ORDER_VU,
++ .hsub = 2,
++ .vsub = 1,
++ },
++ {
++ .format = DRM_FORMAT_YUV444,
++ SAMPLER_TYPE(EGL_TEXTURE_Y_U_V_WL),
++ .num_planes = 3,
++ },
++ {
++ .format = DRM_FORMAT_YVU444,
++ SAMPLER_TYPE(EGL_TEXTURE_Y_U_V_WL),
++ .num_planes = 3,
++ .chroma_order = ORDER_VU,
++ },
++};
++
++WL_EXPORT const struct pixel_format_info *
++pixel_format_get_info(uint32_t format)
++{
++ unsigned int i;
++
++ for (i = 0; i < ARRAY_LENGTH(pixel_format_table); i++) {
++ if (pixel_format_table[i].format == format)
++ return &pixel_format_table[i];
++ }
++
++ return NULL;
++}
++
++WL_EXPORT unsigned int
++pixel_format_get_plane_count(const struct pixel_format_info *info)
++{
++ return info->num_planes ? info->num_planes : 1;
++}
++
++WL_EXPORT bool
++pixel_format_is_opaque(const struct pixel_format_info *info)
++{
++ return !info->opaque_substitute;
++}
++
++WL_EXPORT const struct pixel_format_info *
++pixel_format_get_opaque_substitute(const struct pixel_format_info *info)
++{
++ if (!info->opaque_substitute)
++ return info;
++ else
++ return pixel_format_get_info(info->opaque_substitute);
++}
++
++WL_EXPORT unsigned int
++pixel_format_width_for_plane(const struct pixel_format_info *info,
++ unsigned int plane,
++ unsigned int width)
++{
++ /* We don't support any formats where the first plane is subsampled. */
++ if (plane == 0 || !info->hsub)
++ return width;
++
++ return width / info->hsub;
++}
++
++WL_EXPORT unsigned int
++pixel_format_height_for_plane(const struct pixel_format_info *info,
++ unsigned int plane,
++ unsigned int height)
++{
++ /* We don't support any formats where the first plane is subsampled. */
++ if (plane == 0 || !info->vsub)
++ return height;
++
++ return height / info->vsub;
++}
+diff --git a/libweston/pixel-formats.h b/libweston/pixel-formats.h
+new file mode 100644
+index 0000000..b16aae3
+--- /dev/null
++++ b/libweston/pixel-formats.h
+@@ -0,0 +1,194 @@
++/*
++ * Copyright © 2016 Collabora, Ltd.
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software"),
++ * to deal in the Software without restriction, including without limitation
++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ * and/or sell copies of the Software, and to permit persons to whom the
++ * Software is furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the next
++ * paragraph) shall be included in all copies or substantial portions of the
++ * Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
++ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++ * DEALINGS IN THE SOFTWARE.
++ *
++ * Author: Daniel Stone <daniels@collabora.com>
++ */
++
++#include <inttypes.h>
++#include <stdbool.h>
++
++/**
++ * Contains information about pixel formats, mapping format codes from
++ * wl_shm and drm_fourcc.h (which are deliberately identical, but for the
++ * special cases of WL_SHM_ARGB8888 and WL_SHM_XRGB8888) into various
++ * sets of information. Helper functions are provided for dealing with these
++ * raw structures.
++ */
++struct pixel_format_info {
++ /** DRM/wl_shm format code */
++ uint32_t format;
++
++ /** If non-zero, number of planes in base (non-modified) format. */
++ int num_planes;
++
++ /** If format contains alpha channel, opaque equivalent of format,
++ * i.e. alpha channel replaced with X. */
++ uint32_t opaque_substitute;
++
++ /** How the format should be sampled, expressed in terms of tokens
++ * from the EGL_WL_bind_wayland_display extension. If not set,
++ * assumed to be either RGB or RGBA, depending on whether or not
++ * the format contains an alpha channel. The samplers may still
++ * return alpha even for opaque formats; users must manually set
++ * the alpha channel to 1.0 (or ignore it) if the format is
++ * opaque. */
++ uint32_t sampler_type;
++
++ /** GL format, if data can be natively/directly uploaded. Note that
++ * whilst DRM formats are little-endian unless explicitly specified,
++ * (i.e. DRM_FORMAT_ARGB8888 is stored BGRA as sequential bytes in
++ * memory), GL uses the sequential byte order, so that format maps to
++ * GL_BGRA_EXT plus GL_UNSIGNED_BYTE. To add to the confusion, the
++ * explicitly-sized types (e.g. GL_UNSIGNED_SHORT_5_5_5_1) read in
++ * machine-endian order, so for these types, the correspondence
++ * depends on endianness. */
++ int gl_format;
++
++ /** GL data type, if data can be natively/directly uploaded. */
++ int gl_type;
++
++ /** If set, this format can be used with the legacy drmModeAddFB()
++ * function (not AddFB2), using this and the bpp member. */
++ int depth;
++
++ /** See 'depth' member above. */
++ int bpp;
++
++ /** Horizontal subsampling; if non-zero, divide the width by this
++ * member to obtain the number of columns in the source buffer for
++ * secondary planes only. Stride is not affected by horizontal
++ * subsampling. */
++ int hsub;
++
++ /** Vertical subsampling; if non-zero, divide the height by this
++ * member to obtain the number of rows in the source buffer for
++ * secondary planes only. */
++ int vsub;
++
++ /* Ordering of chroma components. */
++ enum {
++ ORDER_UV = 0,
++ ORDER_VU,
++ } chroma_order;
++
++ /* If packed YUV (num_planes == 1), ordering of luma/chroma
++ * components. */
++ enum {
++ ORDER_LUMA_CHROMA = 0,
++ ORDER_CHROMA_LUMA,
++ } luma_chroma_order;
++};
++
++/**
++ * Get pixel format information for a DRM format code
++ *
++ * Given a DRM format code, return a pixel format info structure describing
++ * the properties of that format.
++ *
++ * @param format DRM format code to get info for
++ * @returns A pixel format structure (must not be freed), or NULL if the
++ * format could not be found
++ */
++const struct pixel_format_info *pixel_format_get_info(uint32_t format);
++
++/**
++ * Get number of planes used by a pixel format
++ *
++ * Given a pixel format info structure, return the number of planes
++ * required for a buffer. Note that this is not necessarily identical to
++ * the number of samplers required to be bound, as two views into a single
++ * plane are sometimes required.
++ *
++ * @param format Pixel format info structure
++ * @returns Number of planes required for the format
++ */
++unsigned int
++pixel_format_get_plane_count(const struct pixel_format_info *format);
++
++/**
++ * Determine if a pixel format is opaque or contains alpha
++ *
++ * Returns whether or not the pixel format is opaque, or contains a
++ * significant alpha channel. Note that the suggested EGL sampler type may
++ * still sample undefined data into the alpha channel; users must consider
++ * alpha as 1.0 if the format is opaque, and not rely on the sampler to
++ * return this when sampling from the alpha channel.
++ *
++ * @param format Pixel format info structure
++ * @returns True if the format is opaque, or false if it has significant alpha
++ */
++bool pixel_format_is_opaque(const struct pixel_format_info *format);
++
++/**
++ * Get compatible opaque equivalent for a format
++ *
++ * Given a pixel format info structure, return a format which is wholly
++ * compatible with the input format, but opaque, ignoring the alpha channel.
++ * If an alpha format is provided, but the content is known to all be opaque,
++ * then this can be used as a substitute to avoid blending.
++ *
++ * If the input format is opaque, this function will return the input format.
++ *
++ * @param format Pixel format info structure
++ * @returns A pixel format info structure for the compatible opaque substitute
++ */
++const struct pixel_format_info *
++pixel_format_get_opaque_substitute(const struct pixel_format_info *format);
++
++/**
++ * Return the effective sampling width for a given plane
++ *
++ * When horizontal subsampling is effective, a sampler bound to a secondary
++ * plane must bind the sampler with a smaller effective width. This function
++ * returns the effective width to use for the sampler, i.e. dividing by hsub.
++ *
++ * If horizontal subsampling is not in effect, this will be equal to the
++ * width.
++ *
++ * @param format Pixel format info structure
++ * @param plane Zero-indexed plane number
++ * @param width Width of the buffer
++ * @returns Effective width for sampling
++ */
++unsigned int
++pixel_format_width_for_plane(const struct pixel_format_info *format,
++ unsigned int plane,
++ unsigned int width);
++
++/**
++ * Return the effective sampling height for a given plane
++ *
++ * When vertical subsampling is in effect, a sampler bound to a secondary
++ * plane must bind the sampler with a smaller effective height. This function
++ * returns the effective height to use for the sampler, i.e. dividing by vsub.
++ *
++ * If vertical subsampling is not in effect, this will be equal to the height.
++ *
++ * @param format Pixel format info structure
++ * @param plane Zero-indexed plane number
++ * @param height Height of the buffer
++ * @returns Effective width for sampling
++ */
++unsigned int
++pixel_format_height_for_plane(const struct pixel_format_info *format,
++ unsigned int plane,
++ unsigned int height);
+diff --git a/shared/timespec-util.h b/shared/timespec-util.h
+index edd4ec1..ca0156a 100644
+--- a/shared/timespec-util.h
++++ b/shared/timespec-util.h
+@@ -28,6 +28,8 @@
+
+ #include <stdint.h>
+ #include <assert.h>
++#include <time.h>
++#include <stdbool.h>
+
+ #define NSEC_PER_SEC 1000000000
+
+@@ -49,6 +51,39 @@ timespec_sub(struct timespec *r,
+ }
+ }
+
++/* Add a nanosecond value to a timespec
++ *
++ * \param r[out] result: a + b
++ * \param a[in] base operand as timespec
++ * \param b[in] operand in nanoseconds
++ */
++static inline void
++timespec_add_nsec(struct timespec *r, const struct timespec *a, int64_t b)
++{
++ r->tv_sec = a->tv_sec + (b / NSEC_PER_SEC);
++ r->tv_nsec = a->tv_nsec + (b % NSEC_PER_SEC);
++
++ if (r->tv_nsec >= NSEC_PER_SEC) {
++ r->tv_sec++;
++ r->tv_nsec -= NSEC_PER_SEC;
++ } else if (r->tv_nsec < 0) {
++ r->tv_sec--;
++ r->tv_nsec += NSEC_PER_SEC;
++ }
++}
++
++/* Add a millisecond value to a timespec
++ *
++ * \param r[out] result: a + b
++ * \param a[in] base operand as timespec
++ * \param b[in] operand in milliseconds
++ */
++static inline void
++timespec_add_msec(struct timespec *r, const struct timespec *a, int64_t b)
++{
++ return timespec_add_nsec(r, a, b * 1000000);
++}
++
+ /* Convert timespec to nanoseconds
+ *
+ * \param a timespec
+@@ -60,6 +95,155 @@ timespec_to_nsec(const struct timespec *a)
+ return (int64_t)a->tv_sec * NSEC_PER_SEC + a->tv_nsec;
+ }
+
++/* Subtract timespecs and return result in nanoseconds
++ *
++ * \param a[in] operand
++ * \param b[in] operand
++ * \return to_nanoseconds(a - b)
++ */
++static inline int64_t
++timespec_sub_to_nsec(const struct timespec *a, const struct timespec *b)
++{
++ struct timespec r;
++ timespec_sub(&r, a, b);
++ return timespec_to_nsec(&r);
++}
++
++/* Convert timespec to milliseconds
++ *
++ * \param a timespec
++ * \return milliseconds
++ *
++ * Rounding to integer milliseconds happens always down (floor()).
++ */
++static inline int64_t
++timespec_to_msec(const struct timespec *a)
++{
++ return (int64_t)a->tv_sec * 1000 + a->tv_nsec / 1000000;
++}
++
++/* Subtract timespecs and return result in milliseconds
++ *
++ * \param a[in] operand
++ * \param b[in] operand
++ * \return to_milliseconds(a - b)
++ */
++static inline int64_t
++timespec_sub_to_msec(const struct timespec *a, const struct timespec *b)
++{
++ return timespec_sub_to_nsec(a, b) / 1000000;
++}
++
++/* Convert timespec to microseconds
++ *
++ * \param a timespec
++ * \return microseconds
++ *
++ * Rounding to integer microseconds happens always down (floor()).
++ */
++static inline int64_t
++timespec_to_usec(const struct timespec *a)
++{
++ return (int64_t)a->tv_sec * 1000000 + a->tv_nsec / 1000;
++}
++
++/* Convert timespec to protocol data
++ *
++ * \param a timespec
++ * \param tv_sec_hi[out] the high bytes of the seconds part
++ * \param tv_sec_lo[out] the low bytes of the seconds part
++ * \param tv_nsec[out] the nanoseconds part
++ *
++ * The input timespec must be normalized (the nanoseconds part should
++ * be less than 1 second) and non-negative.
++ */
++static inline void
++timespec_to_proto(const struct timespec *a, uint32_t *tv_sec_hi,
++ uint32_t *tv_sec_lo, uint32_t *tv_nsec)
++{
++ assert(a->tv_sec >= 0);
++ assert(a->tv_nsec >= 0 && a->tv_nsec < NSEC_PER_SEC);
++
++ uint64_t sec64 = a->tv_sec;
++
++ *tv_sec_hi = sec64 >> 32;
++ *tv_sec_lo = sec64 & 0xffffffff;
++ *tv_nsec = a->tv_nsec;
++}
++
++/* Convert nanoseconds to timespec
++ *
++ * \param a timespec
++ * \param b nanoseconds
++ */
++static inline void
++timespec_from_nsec(struct timespec *a, int64_t b)
++{
++ a->tv_sec = b / NSEC_PER_SEC;
++ a->tv_nsec = b % NSEC_PER_SEC;
++}
++
++/* Convert microseconds to timespec
++ *
++ * \param a timespec
++ * \param b microseconds
++ */
++static inline void
++timespec_from_usec(struct timespec *a, int64_t b)
++{
++ timespec_from_nsec(a, b * 1000);
++}
++
++/* Convert milliseconds to timespec
++ *
++ * \param a timespec
++ * \param b milliseconds
++ */
++static inline void
++timespec_from_msec(struct timespec *a, int64_t b)
++{
++ timespec_from_nsec(a, b * 1000000);
++}
++
++/* Convert protocol data to timespec
++ *
++ * \param a[out] timespec
++ * \param tv_sec_hi the high bytes of seconds part
++ * \param tv_sec_lo the low bytes of seconds part
++ * \param tv_nsec the nanoseconds part
++ */
++static inline void
++timespec_from_proto(struct timespec *a, uint32_t tv_sec_hi,
++ uint32_t tv_sec_lo, uint32_t tv_nsec)
++{
++ a->tv_sec = ((uint64_t)tv_sec_hi << 32) + tv_sec_lo;
++ a->tv_nsec = tv_nsec;
++}
++
++/* Check if a timespec is zero
++ *
++ * \param a timespec
++ * \return whether the timespec is zero
++ */
++static inline bool
++timespec_is_zero(const struct timespec *a)
++{
++ return a->tv_sec == 0 && a->tv_nsec == 0;
++}
++
++/* Check if two timespecs are equal
++ *
++ * \param a[in] timespec to check
++ * \param b[in] timespec to check
++ * \return whether timespecs a and b are equal
++ */
++static inline bool
++timespec_eq(const struct timespec *a, const struct timespec *b)
++{
++ return a->tv_sec == b->tv_sec &&
++ a->tv_nsec == b->tv_nsec;
++}
++
+ /* Convert milli-Hertz to nanoseconds
+ *
+ * \param mhz frequency in mHz, not zero
+--
+1.9.1
+
diff --git a/meta/meta-mediatek/recipes-graphics/wayland/weston/0007-PATCH-weston-add-mtk-test-client.patch b/meta/meta-mediatek/recipes-graphics/wayland/weston/0007-PATCH-weston-add-mtk-test-client.patch
new file mode 100644
index 0000000..2eada19
--- /dev/null
+++ b/meta/meta-mediatek/recipes-graphics/wayland/weston/0007-PATCH-weston-add-mtk-test-client.patch
@@ -0,0 +1,1308 @@
+From 62628502047672c190fadc3f98caf427df25dfe6 Mon Sep 17 00:00:00 2001
+From: Qian Hu <Qian.Hu@mediatek.com>
+Date: Tue, 24 Sep 2019 14:31:26 +0800
+Subject: [PATCH 7/8] [PATCH] weston: add mtk test client
+
+add mtk test client
+
+Signed-off-by: Qian Hu <Qian.Hu@mediatek.com>
+---
+ Makefile.am | 14 +
+ clients/simple-configure-mtk.c | 1247 ++++++++++++++++++++++++++++++++++++++++
+ configure.ac | 1 +
+ 3 files changed, 1262 insertions(+)
+ create mode 100644 clients/simple-configure-mtk.c
+
+diff --git a/Makefile.am b/Makefile.am
+index a9e48f8..7efa5a0 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -668,6 +668,20 @@ nodist_weston_simple_screenshooter_mtk_SOURCES = \
+ weston_simple_screenshooter_mtk_CFLAGS = $(AM_CFLAGS) $(CLIENT_CFLAGS)
+ weston_simple_screenshooter_mtk_LDADD = $(EGL_LIBS) $(LIBDRM_LIBS) libtoytoolkit.la
+
++if BUILD_SIMPLE_CONFIGURE_MTK_CLIENT
++demo_clients += weston-simple-configure-mtk
++weston_simple_configure_mtk_SOURCES = clients/simple-configure-mtk.c
++nodist_weston_simple_configure_mtk_SOURCES = \
++ protocol/xdg-shell-unstable-v6-protocol.c \
++ protocol/xdg-shell-unstable-v6-client-protocol.h \
++ protocol/fullscreen-shell-unstable-v1-protocol.c \
++ protocol/fullscreen-shell-unstable-v1-client-protocol.h \
++ protocol/linux-dmabuf-unstable-v1-protocol.c \
++ protocol/linux-dmabuf-unstable-v1-client-protocol.h
++weston_simple_configure_mtk_CFLAGS = $(AM_CFLAGS) $(CLIENT_CFLAGS)
++weston_simple_configure_mtk_LDADD = $(EGL_LIBS) $(LIBDRM_LIBS) libtoytoolkit.la
++BUILT_SOURCES += protocol/linux-dmabuf-unstable-v1-client-protocol.h
++endif
+
+ noinst_LTLIBRARIES += libtoytoolkit.la
+
+diff --git a/clients/simple-configure-mtk.c b/clients/simple-configure-mtk.c
+new file mode 100644
+index 0000000..8b146ff
+--- /dev/null
++++ b/clients/simple-configure-mtk.c
+@@ -0,0 +1,1247 @@
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#include <stdbool.h>
++#include <math.h>
++#include <assert.h>
++#include <sys/mman.h>
++#include <signal.h>
++#include <fcntl.h>
++#include <errno.h>
++#include <linux/input.h>
++
++#include <wayland-client.h>
++#include <wayland-cursor.h>
++
++#include <drm_fourcc.h>
++#include <xf86drm.h>
++#include <xf86drmMode.h>
++
++#include <sys/types.h>
++#include <unistd.h>
++
++//#include "ivi-application-client-protocol.h"
++#include "xdg-shell-unstable-v6-client-protocol.h"
++#include "linux-dmabuf-unstable-v1-client-protocol.h"
++#include "fullscreen-shell-unstable-v1-client-protocol.h"
++#include "weston-configure-mtk-client-protocol.h"
++
++#include <shared/platform.h>
++
++//#define IVI_SURFACE_ID 9000
++#define MAX_IMAGE 16
++#define ALIGN(X,bit) ((X + bit-1) & (~(bit-1)))
++#define MAX_DMABUF_PLANES 4
++#define RES_NUM 4
++#define MAX_LEN 60
++
++struct window;
++struct seat;
++
++struct display {
++ struct wl_display *display;
++ struct wl_registry *registry;
++ struct wl_compositor *compositor;
++ struct zxdg_shell_v6 *shell;
++ struct zwp_fullscreen_shell_v1 *fshell;
++ //struct ivi_application *ivi_application;
++ struct wl_seat *seat;
++ struct wl_pointer *pointer;
++ struct wl_touch *touch;
++ struct wl_keyboard *keyboard;
++ struct wl_shm *shm;
++ struct zwp_linux_dmabuf_v1 *dmabuf;
++ struct wl_list output_list; /* struct output_unit::link */
++ struct wl_cursor_theme *cursor_theme;
++ struct wl_cursor *default_cursor;
++ struct wl_surface *cursor_surface;
++ struct window *window;
++ struct config_switch *config_switch;
++};
++
++struct geometry {
++ int width, height;
++};
++
++struct buffer {
++ struct wl_buffer *buffer;
++ void *dma_map;
++ int busy;
++};
++
++struct file_arg{
++ char filename[MAX_LEN];
++ int width;
++ int height;
++ int format;
++};
++
++struct window {
++ struct display *display;
++ struct geometry geometry, window_size;
++ bool wait_for_configure;
++ struct {
++ struct file_arg fProp;
++ struct buffer out_bufs[RES_NUM];
++ } image;
++ struct img_texture *tex;
++ uint32_t benchmark_time, frames;
++ struct wl_surface *surface;
++ struct zxdg_surface_v6 *xdg_surface;
++ struct zxdg_toplevel_v6 *xdg_toplevel;
++ //struct ivi_surface *ivi_surface;
++ struct wl_callback *callback;
++ int fullscreen, opaque, buffer_size, overlay, format;
++ enum wl_output_transform transform;
++ int drm_card_fd;
++ struct config_switch_set *switch_set;
++};
++
++struct img_texture {
++ struct context *ctx;
++
++ /* input */
++ int width;
++ int height;
++ int drm_format;
++ int bpp;
++ int plane_nums;
++
++ int pitch[MAX_DMABUF_PLANES];
++ int offset[MAX_DMABUF_PLANES];
++ int fds[MAX_DMABUF_PLANES];
++ int handle[MAX_DMABUF_PLANES];
++
++ void *texbuf;
++ int size;
++};
++
++typedef enum _IMG_FORMAT_E {
++ IMG_FORMAT_RGB565 = 0,
++ IMG_FORMAT_XRGB8888,
++ IMG_FORMAT_ARGB8888,
++ IMG_FORMAT_YUYV,
++ IMG_FORMAT_NV12,
++ IMG_FORMAT_NV16,
++ IMG_FORMAT_YUV420,
++ IMG_FORMAT_YVU420,
++ IMG_FORMAT_LAST,
++} IMG_FORMAT_T;
++
++struct drm_fourcc_info {
++ unsigned int drm_format;
++ int plane_cnt;
++ int bpp;
++};
++
++static struct drm_fourcc_info fourcc_tbl[] = {
++ {DRM_FORMAT_RGB565, 1, 16},
++ {DRM_FORMAT_RGBA5551, 1, 16},
++ {DRM_FORMAT_RGBA4444, 1, 16},
++ {DRM_FORMAT_XRGB8888, 1, 32},
++ {DRM_FORMAT_XBGR8888, 1, 32},
++ {DRM_FORMAT_RGBX8888, 1, 32},
++ {DRM_FORMAT_BGRX8888, 1, 32},
++ {DRM_FORMAT_ARGB8888, 1, 32},
++ {DRM_FORMAT_ABGR8888, 1, 32},
++ {DRM_FORMAT_RGBA8888, 1, 32},
++ {DRM_FORMAT_BGRA8888, 1, 32},
++ {DRM_FORMAT_YUYV, 1, 16},
++ {DRM_FORMAT_VYUY, 1, 16},
++ {DRM_FORMAT_NV12, 2, 12},
++ {DRM_FORMAT_NV21, 2, 12},
++ {DRM_FORMAT_NV16, 2, 16},
++ {DRM_FORMAT_NV61, 2, 16},
++ {DRM_FORMAT_YUV420, 3, 12},
++ {DRM_FORMAT_YVU420, 3, 12},
++ {0, 0, 0},
++};
++
++static int running = 1;
++static int debug = 0;
++
++static void
++redraw(void *data, struct wl_callback *callback, uint32_t time);
++
++static int _format_transfer(int format, int *drm_format)
++{
++ int new_format;
++
++ if (!drm_format)
++ return -1;
++
++ switch (format) {
++ case IMG_FORMAT_RGB565:
++ new_format = DRM_FORMAT_RGB565;
++ break;
++ case IMG_FORMAT_XRGB8888:
++ new_format = DRM_FORMAT_XRGB8888;
++ break;
++ case IMG_FORMAT_ARGB8888:
++ new_format = DRM_FORMAT_ARGB8888;
++ break;
++ case IMG_FORMAT_YUYV:
++ new_format = DRM_FORMAT_YUYV;
++ break;
++ case IMG_FORMAT_NV12:
++ new_format = DRM_FORMAT_NV12;
++ break;
++ case IMG_FORMAT_NV16:
++ new_format = DRM_FORMAT_NV16;
++ break;
++ case IMG_FORMAT_YUV420:
++ new_format = DRM_FORMAT_YUV420;
++ break;
++ case IMG_FORMAT_YVU420:
++ new_format = DRM_FORMAT_YVU420;
++ break;
++ default:
++ return -2;
++ }
++ *drm_format = new_format;
++
++ return 0;
++}
++
++static struct drm_fourcc_info *
++get_drm_format_info(unsigned int format)
++{
++ int i;
++
++ for (i = 0; ; i++) {
++ if ( format == fourcc_tbl[i].drm_format){
++ return &fourcc_tbl[i];
++ }
++ if ( fourcc_tbl[i].drm_format == 0)
++ break;
++ }
++ return NULL;
++}
++
++static char *
++_get_tex_resource(int drifd, struct img_texture *tex)
++{
++ void *map = NULL;
++ struct drm_mode_create_dumb create_arg;
++ struct drm_mode_map_dumb map_arg;
++ struct drm_prime_handle prime_arg;
++ struct drm_fourcc_info *format_info;
++ int i, ret;
++ unsigned int alloc_size;
++
++ memset(&create_arg, 0, sizeof(create_arg));
++ memset(&map_arg, 0, sizeof(map_arg));
++ memset(&prime_arg, 0, sizeof(prime_arg));
++
++ for(i = 0; i < MAX_DMABUF_PLANES; i ++ )
++ tex->fds[i] = -1;
++
++ format_info = get_drm_format_info(tex->drm_format);
++ if (format_info == NULL)
++ return NULL;
++
++ tex->bpp = format_info->bpp;
++ if (format_info->plane_cnt == 3) {
++ if (format_info->bpp == 12) {
++ tex->pitch[0] = ALIGN(tex->width, 16);
++ tex->pitch[1] = tex->pitch[0] / 2;
++ tex->pitch[2] = tex->pitch[0] / 2;
++ tex->offset[0] = 0;
++ tex->offset[1] = tex->pitch[0] * tex->height;
++ tex->offset[2] = tex->offset[1] + tex->pitch[1] * tex->height / 2;
++ alloc_size = tex->offset[2] + tex->pitch[2] * tex->height / 2;
++ } else {
++ fprintf(stderr,"debug: please add new format 0x%x\n", tex->drm_format);
++ return NULL;
++ }
++ } else if (format_info->plane_cnt == 2) {
++ tex->pitch[0] = ALIGN(tex->width, 16);
++ tex->offset[0] = 0;
++ if (format_info->bpp == 16) {
++ tex->pitch[1] = tex->pitch[0];
++ tex->offset[1] = tex->pitch[0] * tex->height;
++ alloc_size = tex->offset[1] + tex->pitch[1] * tex->height;
++ fprintf(stderr,"debug: %s %d alloc_size = %d o/p [%d %d]\n",
++ __FUNCTION__, __LINE__, alloc_size, tex->offset[1], tex->pitch[1]);
++ }
++ else if (format_info->bpp == 12) {
++ tex->pitch[1] = tex->pitch[0] / 2;
++ tex->offset[1] = tex->pitch[0] * tex->height;
++ alloc_size = tex->offset[1] + tex->pitch[1] * tex->height;
++ } else {
++ fprintf(stderr,"debug: please add new format 0x%x\n", tex->drm_format);
++ return NULL;
++ }
++ } else {
++ tex->pitch[0] = ALIGN(tex->width * tex->bpp / 8, 16);
++ tex->offset[0] = 0;
++ alloc_size = tex->pitch[0] * tex->height;
++ }
++
++ create_arg.bpp = 8;
++ create_arg.width = alloc_size;
++ create_arg.height = 1;
++
++ ret = drmIoctl(drifd, DRM_IOCTL_MODE_CREATE_DUMB, &create_arg);
++ if (ret) {
++ fprintf(stderr,"error: drmIoctl %d DRM_IOCTL_MODE_CREATE_DUMB fail %d\n", drifd, ret);
++ return NULL;
++ }
++
++ map_arg.handle = create_arg.handle;
++
++ ret = drmIoctl(drifd, DRM_IOCTL_MODE_MAP_DUMB, &map_arg);
++ if (ret) {
++ fprintf(stderr,"error: drmIoctl DRM_IOCTL_MODE_MAP_DUMB fail %d\n", ret);
++ return NULL;
++ }
++
++ map = mmap(0, create_arg.size, PROT_WRITE|PROT_READ , MAP_SHARED, drifd, map_arg.offset);
++ if (map == MAP_FAILED) {
++ fprintf(stderr,"error: mmap fail : %p\n", map);
++ return NULL;
++ }
++
++ prime_arg.handle = create_arg.handle;
++ prime_arg.flags = DRM_CLOEXEC;
++ ret = drmIoctl(drifd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &prime_arg);
++ if (ret || prime_arg.fd == -1) {
++ fprintf(stderr,"error: drmIoctl DRM_IOCTL_PRIME_HANDLE_TO_FD fail %d fd=%d\n",ret,prime_arg.fd);
++ return NULL;
++ }
++
++ for (i = 0; i < format_info->plane_cnt; i++) {
++ tex->fds[i] = prime_arg.fd;
++ tex->handle[i] = create_arg.handle;
++ }
++ tex->plane_nums = format_info->plane_cnt;
++ tex->texbuf = map;
++ tex->size = create_arg.size;
++
++ return map;
++}
++
++static int
++init_img_texture(struct window *window)
++{
++ int ret;
++ struct img_texture *tex;
++ tex = malloc(sizeof *tex);
++ if (tex == NULL)
++ return -1;
++
++ ret = _format_transfer(window->image.fProp.format, &(tex->drm_format));
++ if (ret < 0)
++ return -1;
++
++ tex->width = window->image.fProp.width;
++ tex->height= window->image.fProp.height;
++
++ window->tex = tex;
++ return 0;
++}
++
++static void
++buffer_release(void *data, struct wl_buffer *buffer)
++{
++ struct buffer *mybuf = data;
++
++ mybuf->busy = 0;
++}
++
++static const struct wl_buffer_listener buffer_listener = {
++ buffer_release
++};
++
++static void
++create_succeeded(void *data,
++ struct zwp_linux_buffer_params_v1 *params,
++ struct wl_buffer *new_buffer)
++{
++ struct buffer *buffer = data;
++
++ buffer->buffer = new_buffer;
++ wl_buffer_add_listener(buffer->buffer, &buffer_listener, buffer);
++
++ zwp_linux_buffer_params_v1_destroy(params);
++}
++
++static void
++create_failed(void *data, struct zwp_linux_buffer_params_v1 *params)
++{
++ struct buffer *buffer = data;
++
++ buffer->buffer = NULL;
++
++ zwp_linux_buffer_params_v1_destroy(params);
++
++ running = false;
++
++ fprintf(stderr, "Error: zwp_linux_buffer_params.create failed.\n");
++}
++
++static const struct zwp_linux_buffer_params_v1_listener params_listener = {
++ create_succeeded,
++ create_failed
++};
++
++static int
++create_dmabuf_buffer(struct display *display, struct buffer *buffer)
++{
++ struct zwp_linux_buffer_params_v1 *params;
++ struct img_texture *cbtex = display->window->tex;
++ uint64_t modifier;
++ uint32_t flags;
++ int i;
++ /* output */
++ buffer->dma_map = _get_tex_resource(display->window->drm_card_fd, cbtex);
++
++ if (buffer->dma_map == NULL) {
++ fprintf(stderr, "error: _get_tex_resource failed\n");
++ return -1;
++ }
++
++ modifier = 0;
++ params = zwp_linux_dmabuf_v1_create_params(display->dmabuf);
++
++ for(i = 0; i < cbtex->plane_nums; i ++)
++ {
++ zwp_linux_buffer_params_v1_add(params,
++ cbtex->fds[i],
++ i, /* plane_idx */
++ cbtex->offset[i],/* offset */
++ cbtex->pitch[i],
++ modifier >> 32,
++ modifier & 0xffffffff);
++ }
++ zwp_linux_buffer_params_v1_add_listener(params, ¶ms_listener, buffer);
++ zwp_linux_buffer_params_v1_create(params,
++ cbtex->width,
++ cbtex->height,
++ cbtex->drm_format,
++ flags);
++
++ /* params is destroyed by the event handlers */
++ wl_display_roundtrip(display->display);
++ if (buffer->buffer == NULL) {
++ return -1;
++ }
++
++ return 0;
++}
++
++static int
++_load_file(void *buf, int len, const char *file_name)
++{
++ int ret, nread = 0;
++
++ FILE *fp = fopen(file_name, "rb");
++ if (!fp)
++ {
++ fprintf(stderr,"debug: file %s open failed\n", file_name);
++ return -1;
++ }
++
++ while (nread < len) {
++ ret = fread(buf + nread, 1, len - nread, fp);
++ if (!ret)
++ break;
++ nread += ret;
++ }
++
++ fclose(fp);
++ return 0;
++}
++
++static int
++_kms_device_fd(void)
++{
++ int i;
++ bool has_conn = false;
++ for (i = 0; i < 8; ++i) {
++ char path[99];
++ sprintf(path, "/dev/dri/card%d", i);
++ fprintf(stderr, "debug: trying %s\n", path);
++ int fd = open(path, O_RDWR | O_CLOEXEC);
++ if (fd >= 0) {
++ drmModeResPtr mr = drmModeGetResources(fd);
++ if (mr) {
++ has_conn = mr->count_connectors > 0;
++ drmModeFreeResources(mr);
++ }
++ if (has_conn) {
++ fprintf(stderr, "debug: using %s\n", path);
++ return fd;
++ }
++ close(fd);
++ }
++ }
++ return -1;
++}
++
++static void
++handle_xdg_surface_configure(void *data, struct zxdg_surface_v6 *surface,
++ uint32_t serial)
++{
++ struct window *window = data;
++ fprintf(stderr, "handle_xdg_surface_configure\n");
++
++ zxdg_surface_v6_ack_configure(surface, serial);
++
++ if (window->wait_for_configure) {
++ redraw(window, NULL, 0);
++ window->wait_for_configure = false;
++ }
++}
++
++static const struct zxdg_surface_v6_listener xdg_surface_listener = {
++ handle_xdg_surface_configure,
++};
++
++
++static void
++handle_toplevel_configure(void *data, struct zxdg_toplevel_v6 *toplevel,
++ int32_t width, int32_t height,
++ struct wl_array *states)
++{
++ struct window *window = data;
++ uint32_t *p;
++
++ window->fullscreen = 0;
++ wl_array_for_each(p, states) {
++ uint32_t state = *p;
++ switch (state) {
++ case ZXDG_TOPLEVEL_V6_STATE_FULLSCREEN:
++ window->fullscreen = 1;
++ break;
++ }
++ }
++
++ if (width > 0 && height > 0) {
++ if (!window->fullscreen) {
++ window->window_size.width = width;
++ window->window_size.height = height;
++ }
++ window->geometry.width = width;
++ window->geometry.height = height;
++ } else if (!window->fullscreen) {
++ window->geometry = window->window_size;
++ }
++
++ /*if (window->native)
++ wl_egl_window_resize(window->native,
++ window->geometry.width,
++ window->geometry.height, 0, 0);*/
++}
++
++static void
++handle_toplevel_close(void *data, struct zxdg_toplevel_v6 *xdg_toplevel)
++{
++ running = 0;
++}
++
++static const struct zxdg_toplevel_v6_listener xdg_toplevel_listener = {
++ handle_toplevel_configure,
++ handle_toplevel_close,
++};
++/*
++static void
++handle_ivi_surface_configure(void *data, struct ivi_surface *ivi_surface,
++ int32_t width, int32_t height)
++{
++
++}
++
++static const struct ivi_surface_listener ivi_surface_listener = {
++ handle_ivi_surface_configure,
++};
++*/
++static struct buffer *
++window_next_buffer(struct window *window)
++{
++ struct buffer *buffer = NULL;
++ int i, ret = 0;
++
++ for(i = 0; i < RES_NUM; i++) {
++ if (!window->image.out_bufs[i].busy) {
++ buffer = &window->image.out_bufs[i];
++ break;
++ }
++ }
++
++ if (!buffer)
++ return NULL;
++
++ if (!buffer->buffer) {
++ ret = create_dmabuf_buffer(window->display, buffer);
++ if (ret < 0)
++ return NULL;
++ if(i%2)
++ _load_file(buffer->dma_map, window->tex->size, window->image.fProp.filename);
++ else
++ memset(buffer->dma_map, 0, window->tex->size);
++ }
++
++ return buffer;
++}
++
++static void
++create_surface(struct window *window)
++{
++ struct display *display = window->display;
++
++ window->surface = wl_compositor_create_surface(display->compositor);
++ display->cursor_surface =
++ wl_compositor_create_surface(display->compositor);
++
++ window->switch_set = config_switch_connect(display->config_switch, window->surface);
++
++ if (display->shell) {
++ window->xdg_surface =
++ zxdg_shell_v6_get_xdg_surface(display->shell,
++ window->surface);
++
++ assert(window->xdg_surface);
++
++ zxdg_surface_v6_add_listener(window->xdg_surface,
++ &xdg_surface_listener, window);
++
++ window->xdg_toplevel =
++ zxdg_surface_v6_get_toplevel(window->xdg_surface);
++ zxdg_toplevel_v6_add_listener(window->xdg_toplevel,
++ &xdg_toplevel_listener, window);
++
++ zxdg_toplevel_v6_set_title(window->xdg_toplevel, "simple-configure-mtk");
++ window->wait_for_configure = true;
++ wl_surface_commit(window->surface);
++ } else if (display->fshell) {
++ zwp_fullscreen_shell_v1_present_surface(display->fshell,
++ window->surface,
++ ZWP_FULLSCREEN_SHELL_V1_PRESENT_METHOD_DEFAULT,
++ NULL);
++ //} else if (display->ivi_application ) {
++ // uint32_t id_ivisurf = IVI_SURFACE_ID + (uint32_t)getpid();
++ // window->ivi_surface =
++ // ivi_application_surface_create(display->ivi_application,
++ // id_ivisurf, window->surface);
++ // if (window->ivi_surface == NULL) {
++ // fprintf(stderr, "Failed to create ivi_client_surface\n");
++ // abort();
++ // }
++//
++ // ivi_surface_add_listener(window->ivi_surface,
++ // &ivi_surface_listener, window);
++
++ } else {
++ assert(0);
++ }
++
++}
++
++static void
++destroy_surface(struct window *window)
++{
++ if (window->xdg_toplevel)
++ zxdg_toplevel_v6_destroy(window->xdg_toplevel);
++ if (window->xdg_surface)
++ zxdg_surface_v6_destroy(window->xdg_surface);
++ //if (window->display->ivi_application)
++ // ivi_surface_destroy(window->ivi_surface);
++ if (window->display->fshell)
++ zwp_fullscreen_shell_v1_release(window->display->fshell);
++ wl_surface_destroy(window->surface);
++
++ if (window->callback)
++ wl_callback_destroy(window->callback);
++
++ if (window->image.out_bufs[0].buffer)
++ wl_buffer_destroy(window->image.out_bufs[0].buffer);
++ if (window->image.out_bufs[1].buffer)
++ wl_buffer_destroy(window->image.out_bufs[1].buffer);
++ if (window->image.out_bufs[2].buffer)
++ wl_buffer_destroy(window->image.out_bufs[2].buffer);
++}
++
++static const struct wl_callback_listener frame_listener;
++
++static void
++redraw(void *data, struct wl_callback *callback, uint32_t time)
++{
++ struct window *window = data;
++ struct buffer *buffer;
++ char filename[MAX_LEN] = {0};
++ static const uint32_t benchmark_interval = 5;
++ struct wl_region *region;
++ struct timeval tv;
++ int tmp;
++
++ buffer = window_next_buffer(window);
++ if (!buffer) {
++ fprintf(stderr,
++ !callback ? "error: Failed to create the first buffer.\n" :
++ "error: Both buffers busy at redraw(). Server bug?\n");
++ abort();
++ }
++
++ gettimeofday(&tv, NULL);
++ time = tv.tv_sec * 1000 + tv.tv_usec / 1000;
++ if (window->frames == 0)
++ window->benchmark_time = time;
++ if (time - window->benchmark_time > (benchmark_interval * 1000)) {
++ printf("debug: %d frames in %d seconds: %f fps\n",
++ window->frames,
++ benchmark_interval,
++ (float) window->frames / benchmark_interval);
++ window->benchmark_time = time;
++ window->frames = 0;
++ }
++
++ if (window->opaque || window->fullscreen) {
++ region = wl_compositor_create_region(window->display->compositor);
++ wl_region_add(region, 0, 0,
++ window->geometry.width,
++ window->geometry.height);
++ wl_surface_set_opaque_region(window->surface, region);
++ wl_region_destroy(region);
++ } else {
++ wl_surface_set_opaque_region(window->surface, NULL);
++ }
++
++ wl_surface_attach(window->surface, buffer->buffer, 0, 0);
++ wl_surface_set_buffer_transform(window->surface,
++ window->transform);
++ wl_surface_damage(window->surface,
++ 0, 0, window->geometry.width, window->geometry.height);
++
++ if (callback)
++ wl_callback_destroy(callback);
++
++ window->callback = wl_surface_frame(window->surface);
++ wl_callback_add_listener(window->callback, &frame_listener, window);
++ wl_surface_commit(window->surface);
++ buffer->busy = 1;
++
++ window->frames++;
++}
++
++static const struct wl_callback_listener frame_listener = {
++ redraw
++};
++
++static void
++pointer_handle_enter(void *data, struct wl_pointer *pointer,
++ uint32_t serial, struct wl_surface *surface,
++ wl_fixed_t sx, wl_fixed_t sy)
++{
++ struct display *display = data;
++ struct wl_buffer *buffer;
++ struct wl_cursor *cursor = display->default_cursor;
++ struct wl_cursor_image *image;
++
++ if (display->window->fullscreen)
++ wl_pointer_set_cursor(pointer, serial, NULL, 0, 0);
++ else if (cursor) {
++ image = display->default_cursor->images[0];
++ buffer = wl_cursor_image_get_buffer(image);
++ if (!buffer)
++ return;
++ wl_pointer_set_cursor(pointer, serial,
++ display->cursor_surface,
++ image->hotspot_x,
++ image->hotspot_y);
++ wl_surface_attach(display->cursor_surface, buffer, 0, 0);
++ wl_surface_damage(display->cursor_surface, 0, 0,
++ image->width, image->height);
++ wl_surface_commit(display->cursor_surface);
++ }
++
++}
++
++static void
++pointer_handle_leave(void *data, struct wl_pointer *pointer,
++ uint32_t serial, struct wl_surface *surface)
++{
++}
++
++static void
++pointer_handle_motion(void *data, struct wl_pointer *pointer,
++ uint32_t time, wl_fixed_t sx, wl_fixed_t sy)
++{
++
++}
++
++static void
++pointer_handle_button(void *data, struct wl_pointer *wl_pointer,
++ uint32_t serial, uint32_t time, uint32_t button,
++ uint32_t state)
++{
++ struct display *display = data;
++
++ if (!display->window->xdg_surface)
++ return;
++
++ if (button == BTN_LEFT && state == WL_POINTER_BUTTON_STATE_PRESSED)
++ zxdg_toplevel_v6_move(display->window->xdg_toplevel,
++ display->seat, serial);
++}
++
++static void
++pointer_handle_axis(void *data, struct wl_pointer *wl_pointer,
++ uint32_t time, uint32_t axis, wl_fixed_t value)
++{
++}
++
++static const struct wl_pointer_listener pointer_listener = {
++ pointer_handle_enter,
++ pointer_handle_leave,
++ pointer_handle_motion,
++ pointer_handle_button,
++ pointer_handle_axis,
++};
++
++static void
++touch_handle_down(void *data, struct wl_touch *wl_touch,
++ uint32_t serial, uint32_t time, struct wl_surface *surface,
++ int32_t id, wl_fixed_t x_w, wl_fixed_t y_w)
++{
++ struct display *d = (struct display *)data;
++
++ if (!d->shell)
++ return;
++
++ zxdg_toplevel_v6_move(d->window->xdg_toplevel, d->seat, serial);
++}
++
++static void
++touch_handle_up(void *data, struct wl_touch *wl_touch,
++ uint32_t serial, uint32_t time, int32_t id)
++{
++}
++
++static void
++touch_handle_motion(void *data, struct wl_touch *wl_touch,
++ uint32_t time, int32_t id, wl_fixed_t x_w, wl_fixed_t y_w)
++{
++}
++
++static void
++touch_handle_frame(void *data, struct wl_touch *wl_touch)
++{
++}
++
++static void
++touch_handle_cancel(void *data, struct wl_touch *wl_touch)
++{
++}
++
++static const struct wl_touch_listener touch_listener = {
++ touch_handle_down,
++ touch_handle_up,
++ touch_handle_motion,
++ touch_handle_frame,
++ touch_handle_cancel,
++};
++
++static void
++keyboard_handle_keymap(void *data, struct wl_keyboard *keyboard,
++ uint32_t format, int fd, uint32_t size)
++{
++}
++
++static void
++keyboard_handle_enter(void *data, struct wl_keyboard *keyboard,
++ uint32_t serial, struct wl_surface *surface,
++ struct wl_array *keys)
++{
++}
++
++static void
++keyboard_handle_leave(void *data, struct wl_keyboard *keyboard,
++ uint32_t serial, struct wl_surface *surface)
++{
++}
++
++static void
++keyboard_handle_key(void *data, struct wl_keyboard *keyboard,
++ uint32_t serial, uint32_t time, uint32_t key,
++ uint32_t state)
++{
++ struct display *d = data;
++
++ if (!d->shell)
++ return;
++
++ if (key == KEY_F11 && state) {
++ if (d->window->fullscreen)
++ zxdg_toplevel_v6_unset_fullscreen(d->window->xdg_toplevel);
++ else
++ zxdg_toplevel_v6_set_fullscreen(d->window->xdg_toplevel, NULL);
++ } else if (key == KEY_ESC && state)
++ running = 0;
++}
++
++static void
++keyboard_handle_modifiers(void *data, struct wl_keyboard *keyboard,
++ uint32_t serial, uint32_t mods_depressed,
++ uint32_t mods_latched, uint32_t mods_locked,
++ uint32_t group)
++{
++}
++
++static const struct wl_keyboard_listener keyboard_listener = {
++ keyboard_handle_keymap,
++ keyboard_handle_enter,
++ keyboard_handle_leave,
++ keyboard_handle_key,
++ keyboard_handle_modifiers,
++};
++
++static void
++seat_handle_capabilities(void *data, struct wl_seat *seat,
++ enum wl_seat_capability caps)
++{
++ struct display *d = data;
++
++ if ((caps & WL_SEAT_CAPABILITY_POINTER) && !d->pointer) {
++ d->pointer = wl_seat_get_pointer(seat);
++ wl_pointer_add_listener(d->pointer, &pointer_listener, d);
++ } else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && d->pointer) {
++ wl_pointer_destroy(d->pointer);
++ d->pointer = NULL;
++ }
++
++ if ((caps & WL_SEAT_CAPABILITY_KEYBOARD) && !d->keyboard) {
++ d->keyboard = wl_seat_get_keyboard(seat);
++ wl_keyboard_add_listener(d->keyboard, &keyboard_listener, d);
++ } else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && d->keyboard) {
++ wl_keyboard_destroy(d->keyboard);
++ d->keyboard = NULL;
++ }
++
++ if ((caps & WL_SEAT_CAPABILITY_TOUCH) && !d->touch) {
++ d->touch = wl_seat_get_touch(seat);
++ wl_touch_set_user_data(d->touch, d);
++ wl_touch_add_listener(d->touch, &touch_listener, d);
++ } else if (!(caps & WL_SEAT_CAPABILITY_TOUCH) && d->touch) {
++ wl_touch_destroy(d->touch);
++ d->touch = NULL;
++ }
++}
++
++static const struct wl_seat_listener seat_listener = {
++ seat_handle_capabilities,
++};
++
++
++static void
++xdg_shell_ping(void *data, struct zxdg_shell_v6 *shell, uint32_t serial)
++{
++ zxdg_shell_v6_pong(shell, serial);
++}
++
++static const struct zxdg_shell_v6_listener xdg_shell_listener = {
++ xdg_shell_ping,
++};
++
++static void
++dmabuf_format(void *data, struct zwp_linux_dmabuf_v1 *zwp_linux_dmabuf, uint32_t format)
++{
++ fprintf(stderr, "debug: Support drm_format 0x%x \n", format);
++}
++
++static const struct zwp_linux_dmabuf_v1_listener dmabuf_listener = {
++ dmabuf_format
++};
++
++static void
++registry_handle_global(void *data, struct wl_registry *registry,
++ uint32_t name, const char *interface, uint32_t version)
++{
++ struct display *d = data;
++
++ if (strcmp(interface, "wl_compositor") == 0) {
++ d->compositor =
++ wl_registry_bind(registry, name,
++ &wl_compositor_interface, 2);
++ } else if (strcmp(interface, "zxdg_shell_v6") == 0) {
++ d->shell = wl_registry_bind(registry, name,
++ &zxdg_shell_v6_interface, 1);
++ zxdg_shell_v6_add_listener(d->shell, &xdg_shell_listener, d);
++ } else if (strcmp(interface, "wl_seat") == 0) {
++ d->seat = wl_registry_bind(registry, name,
++ &wl_seat_interface, 1);
++ wl_seat_add_listener(d->seat, &seat_listener, d);
++ } else if (strcmp(interface, "zwp_fullscreen_shell_v1") == 0) {
++ d->fshell = wl_registry_bind(registry, name,
++ &zwp_fullscreen_shell_v1_interface, 1);
++ } else if (strcmp(interface, "wl_shm") == 0) {
++ d->shm = wl_registry_bind(registry, name,
++ &wl_shm_interface, 1);
++ d->cursor_theme = wl_cursor_theme_load(NULL, 32, d->shm);
++ if (!d->cursor_theme) {
++ fprintf(stderr, "unable to load default theme\n");
++ return;
++ }
++ d->default_cursor =
++ wl_cursor_theme_get_cursor(d->cursor_theme, "grabbing");
++ if (!d->default_cursor) {
++ fprintf(stderr, "unable to load default grabbing pointer\n");
++ // TODO: abort ?
++ }
++ //} else if (strcmp(interface, "ivi_application") == 0) {
++ // d->ivi_application =
++ // wl_registry_bind(registry, name,
++ // &ivi_application_interface, 1);
++ } else if (strcmp(interface, "zwp_linux_dmabuf_v1") == 0) {
++ d->dmabuf = wl_registry_bind(registry, name,
++ &zwp_linux_dmabuf_v1_interface, 1);
++ zwp_linux_dmabuf_v1_add_listener(d->dmabuf, &dmabuf_listener, d);
++ } else if (strcmp(interface, "config_switch") == 0) {
++ d->config_switch =
++ wl_registry_bind(registry, name,
++ &config_switch_interface, 1);
++ }
++}
++
++static void
++registry_handle_global_remove(void *data, struct wl_registry *registry,
++ uint32_t name)
++{
++}
++
++static const struct wl_registry_listener registry_listener = {
++ registry_handle_global,
++ registry_handle_global_remove
++};
++
++static void
++destroy_display(struct display *display)
++{
++ if (display->dmabuf)
++ zwp_linux_dmabuf_v1_destroy(display->dmabuf);
++
++ if (display->shell)
++ zxdg_shell_v6_destroy(display->shell);
++
++ if (display->fshell)
++ zwp_fullscreen_shell_v1_release(display->fshell);
++
++ if (display->compositor)
++ wl_compositor_destroy(display->compositor);
++
++ wl_surface_destroy(display->cursor_surface);
++ if (display->cursor_theme)
++ wl_cursor_theme_destroy(display->cursor_theme);
++
++ //if (display->ivi_application)
++ // ivi_application_destroy(display->ivi_application);
++
++ wl_registry_destroy(display->registry);
++ wl_display_flush(display->display);
++ wl_display_disconnect(display->display);
++ free(display);
++}
++
++static struct display *
++create_display(struct window *window)
++{
++ struct display *display;
++
++ display = malloc(sizeof *display);
++ if (display == NULL) {
++ fprintf(stderr, "out of memory\n");
++ exit(1);
++ }
++ display->display = wl_display_connect(NULL);
++ assert(display->display);
++ display->window = window;
++
++ display->registry = wl_display_get_registry(display->display);
++ wl_registry_add_listener(display->registry,
++ ®istry_listener, display);
++ wl_display_roundtrip(display->display);
++ if (display->dmabuf == NULL) {
++ fprintf(stderr, "No zwp_linux_dmabuf_v1 global found\n");
++ exit(1);
++ }
++ wl_display_roundtrip(display->display);
++
++ return display;
++}
++
++static void
++signal_int(int signum)
++{
++ running = 0;
++}
++
++/*
++ * parse the message inputed for rawdata
++ * egg: -F /usr/share/weston/rawdata.nv16:720x480@5
++ * filename:widthxheight@format
++*/
++static int parse_file(struct file_arg *file, char *p)
++{
++ char *end;
++ char *pPos = p;
++ int len, i;
++
++ len = strlen(pPos) + 1;
++ for (i = 0; i < len; i++)
++ if(pPos[i] == ':')
++ pPos[i] = '\0';
++
++ memcpy(file->filename, pPos, strlen(pPos) + 1);
++ pPos = pPos + strlen(pPos) + 1;
++ file->width = strtoul(pPos, &end, 10);
++ if (*end != 'x')
++ return -EINVAL;
++ pPos = end + 1;
++ file->height = strtoul(pPos, &end, 10);
++ if (*end != '@')
++ return -EINVAL;
++ pPos = end + 1;
++ file->format = strtoul(pPos, &end, 10);
++ if (*end != '\0')
++ return -EINVAL;
++ return 0;
++}
++
++static void init_window(struct window *window)
++{
++ window->geometry.width = 0;
++ window->geometry.height = 0;
++ window->buffer_size = 32;
++ window->transform = WL_OUTPUT_TRANSFORM_NORMAL;
++ window->opaque = 1;
++ window->overlay = 0;
++ window->format = 0;
++ window->drm_card_fd = -1;
++}
++
++static void
++usage(int error_code)
++{
++ fprintf(stderr, "Usage: mtkdraw-dma [OPTIONS]\n\n"
++ " -f Run in fullscreen mode(only desktop-shell valid)\n"
++ " -o Create an opaque surface\n"
++ " -s Use a 16 bpp EGL config\n"
++ " -t Set display buffer transform(0~7)\n"
++ " -F rawdata message(rawdata size provided is 320x480)\n"
++ " eg:-F /usr/share/weston/rawdata.nv16:320x480@5\n"
++ " @14 stand for nv16 format, formats supported as follows\n"
++ " now only support 8 formats\n"
++ " 0 --> IMG_FORMAT_RGB565\n"
++ " 1 --> IMG_FORMAT_XRGB8888\n"
++ " 2 --> IMG_FORMAT_ARGB8888\n"
++ " 3 --> IMG_FORMAT_YUYV\n"
++ " 4 --> IMG_FORMAT_NV12\n"
++ " 5 --> IMG_FORMAT_NV16\n"
++ " 6 --> IMG_FORMAT_YUV420\n"
++ " 7 --> IMG_FORMAT_YVU420\n"
++ " -d Enable debug output\n"
++ " -overlay Enable overlay switch\n"
++ " -h This help text\n\n");
++
++ exit(error_code);
++}
++
++int
++main(int argc, char **argv)
++{
++ struct sigaction sigint;
++ struct display *display;
++ struct window window = { 0 };
++ int i, ret = 0;
++ struct file_arg *file;
++
++ init_window(&window);
++
++ for (i = 1; i < argc; i++) {
++ if (strcmp("-f", argv[i]) == 0)
++ window.fullscreen = 1;
++ else if (strcmp("-o", argv[i]) == 0)
++ window.opaque = 0;
++ else if (strcmp("-s", argv[i]) == 0)
++ window.buffer_size = 16;
++ else if (strcmp("-t", argv[i]) == 0)
++ window.transform = atoi(argv[++i]);
++ else if (strcmp("-F", argv[i]) == 0){
++ ret = parse_file(&window.image.fProp, argv[++i]);
++ if (ret < 0)
++ fprintf(stderr, "error: input error, like: -F "
++ "/usr/share/weston/rawdata.nv16:320x480@5\n");
++ }
++ else if (strcmp("-d", argv[i]) == 0)
++ debug = 1;
++ else if (strcmp("-overlay", argv[i]) == 0)
++ window.overlay = 1;
++ else if (strcmp("-h", argv[i]) == 0)
++ usage(EXIT_SUCCESS);
++ else
++ usage(EXIT_FAILURE);
++ }
++
++ file = &window.image.fProp;
++ if((file->width == 0) || (file->height ==0) || (file->filename == 0))
++ {
++ /*default sample*/
++ file->width = 320;
++ file->height = 480;
++ file->format = IMG_FORMAT_NV16;
++ snprintf(file->filename, MAX_LEN, "/usr/share/weston/rawdata.nv16");
++ fprintf(stderr, "debug: You have choose the default example!\n");
++ }
++
++ fprintf(stderr, "debug: The file is %s width/height/format[%d %d %d]\n",
++ file->filename, file->width, file->height, file->format);
++
++ window.geometry.width = file->width;
++ window.geometry.height = file->height;
++ window.window_size = window.geometry;
++
++ display = create_display(&window);
++ window.display = display;
++ //display->window = &window;
++
++ create_surface(&window);
++
++ ret = init_img_texture(&window);
++ if (ret < 0){
++ fprintf(stderr, "error: init_img_texture failed\n");
++ return -1;
++ }
++
++ window.drm_card_fd = _kms_device_fd();
++ if (window.drm_card_fd < 0) {
++ fprintf(stderr, "error: fail to get drm_card_fd !\n");
++ return -1;
++ }
++ /*
++ * setting sprite_switch = 0, indicate not walk overlay
++ * setting sprite_switch = 1, indicate walk overlay
++ */
++ if(window.overlay)
++ config_switch_set_sprite_switch(window.switch_set, 1);
++ else
++ config_switch_set_sprite_switch(window.switch_set, 0);
++
++ sigint.sa_handler = signal_int;
++ sigemptyset(&sigint.sa_mask);
++ sigint.sa_flags = SA_RESETHAND;
++ sigaction(SIGINT, &sigint, NULL);
++
++ if (!window.wait_for_configure)
++ redraw(&window, NULL, 0);
++
++ while (running && ret != -1)
++ ret = wl_display_dispatch(display->display);
++
++ fprintf(stderr, "debug: simple-configure-mtk exiting\n");
++ destroy_surface(&window);
++ destroy_display(display);
++
++ return 0;
++}
++
++
+diff --git a/configure.ac b/configure.ac
+index 96acf75..e91261d 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -440,6 +440,7 @@ if ! test "x$enable_simple_dmabuf_v4l_client" = "xno"; then
+ enable_simple_dmabuf_v4l_client="$have_simple_dmabuf_v4l_client"
+ fi
+ AM_CONDITIONAL(BUILD_SIMPLE_DMABUF_V4L_CLIENT, test "x$enable_simple_dmabuf_v4l_client" = "xyes")
++AM_CONDITIONAL(BUILD_SIMPLE_CONFIGURE_MTK_CLIENT, test "x$enable_simple_dmabuf_v4l_client" = "xyes")
+
+ AC_ARG_ENABLE(clients, [ --enable-clients],, enable_clients=yes)
+ AM_CONDITIONAL(BUILD_CLIENTS, test x$enable_clients = xyes)
+--
+2.6.4
+
diff --git a/meta/meta-mediatek/recipes-graphics/wayland/weston/0007-weston-screen-shot-add-screen-shot.patch b/meta/meta-mediatek/recipes-graphics/wayland/weston/0007-weston-screen-shot-add-screen-shot.patch
new file mode 100644
index 0000000..5703148
--- /dev/null
+++ b/meta/meta-mediatek/recipes-graphics/wayland/weston/0007-weston-screen-shot-add-screen-shot.patch
@@ -0,0 +1,785 @@
+From ae382bde54d71d2b9fdd0228ef084c8fc710eae7 Mon Sep 17 00:00:00 2001
+From: mtk13576 <yr.yang@mediatek.com>
+Date: Thu, 26 Apr 2018 00:23:55 +0800
+Subject: [PATCH 7/9] weston-screen-shot: add screen shot
+
+add screen shot
+Test: ok
+
+Change-Id: I8b724efa64b2b7d542ed8c7c2525ca5c37cf9cc0
+Signed-off-by: mtk13576 <yr.yang@mediatek.com>
+CR-Id: AUTO00016576
+---
+ Makefile.am | 24 +++-
+ clients/simple-screenshooter-mtk.c | 259 +++++++++++++++++++++++++++++++++++
+ libweston/compositor-drm.c | 115 ++++++++++++++++
+ libweston/compositor.c | 3 +
+ libweston/compositor.h | 3 +
+ libweston/pixel-formats.c | 2 +
+ libweston/weston-screenshooter-mtk.c | 129 +++++++++++++++++
+ protocol/weston-configure-mtk.xml | 37 +++++
+ 8 files changed, 569 insertions(+), 3 deletions(-)
+ create mode 100644 clients/simple-screenshooter-mtk.c
+ create mode 100644 libweston/weston-screenshooter-mtk.c
+ create mode 100644 protocol/weston-configure-mtk.xml
+
+diff --git a/Makefile.am b/Makefile.am
+index 238cd2f..e450b95 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -107,6 +107,7 @@ libweston_@LIBWESTON_MAJOR@_la_SOURCES = \
+ libweston/linux-dmabuf.h \
+ libweston/pixel-formats.c \
+ libweston/pixel-formats.h \
++ libweston/weston-screenshooter-mtk.c \
+ shared/helpers.h \
+ shared/matrix.c \
+ shared/matrix.h \
+@@ -180,7 +181,9 @@ nodist_libweston_@LIBWESTON_MAJOR@_la_SOURCES = \
+ protocol/relative-pointer-unstable-v1-protocol.c \
+ protocol/relative-pointer-unstable-v1-server-protocol.h \
+ protocol/pointer-constraints-unstable-v1-protocol.c \
+- protocol/pointer-constraints-unstable-v1-server-protocol.h
++ protocol/pointer-constraints-unstable-v1-server-protocol.h \
++ protocol/weston-configure-mtk-protocol.c \
++ protocol/weston-configure-mtk-server-protocol.h
+
+ BUILT_SOURCES += $(nodist_libweston_@LIBWESTON_MAJOR@_la_SOURCES)
+
+@@ -642,6 +645,18 @@ weston_simple_dmabuf_v4l_LDADD = $(SIMPLE_DMABUF_V4L_CLIENT_LIBS) libshared.la
+ BUILT_SOURCES += protocol/linux-dmabuf-unstable-v1-client-protocol.h
+ endif
+
++demo_clients += weston-simple-screenshooter-mtk
++weston_simple_screenshooter_mtk_SOURCES = clients/simple-screenshooter-mtk.c
++nodist_weston_simple_screenshooter_mtk_SOURCES = \
++ protocol/xdg-shell-unstable-v6-protocol.c \
++ protocol/xdg-shell-unstable-v6-client-protocol.h \
++ protocol/fullscreen-shell-unstable-v1-protocol.c \
++ protocol/fullscreen-shell-unstable-v1-client-protocol.h \
++ protocol/weston-configure-mtk-protocol.c \
++ protocol/weston-configure-mtk-client-protocol.h
++weston_simple_screenshooter_mtk_CFLAGS = $(AM_CFLAGS) $(CLIENT_CFLAGS)
++weston_simple_screenshooter_mtk_LDADD = $(EGL_LIBS) $(LIBDRM_LIBS) libtoytoolkit.la
++
+ noinst_LTLIBRARIES += libtoytoolkit.la
+
+ libtoytoolkit_la_SOURCES = \
+@@ -876,7 +891,9 @@ BUILT_SOURCES += \
+ protocol/ivi-hmi-controller-protocol.c \
+ protocol/ivi-hmi-controller-client-protocol.h \
+ protocol/ivi-application-protocol.c \
+- protocol/ivi-application-client-protocol.h
++ protocol/ivi-application-client-protocol.h \
++ protocol/weston-configure-mtk-protocol.c \
++ protocol/weston-configure-mtk-client-protocol.h
+
+ westondatadir = $(datadir)/weston
+ dist_westondata_DATA = \
+@@ -1509,7 +1526,8 @@ EXTRA_DIST += \
+ protocol/text-cursor-position.xml \
+ protocol/weston-test.xml \
+ protocol/ivi-application.xml \
+- protocol/ivi-hmi-controller.xml
++ protocol/ivi-hmi-controller.xml \
++ protocol/weston-configure-mtk.xml
+
+ #
+ # manual test modules in tests subdirectory
+diff --git a/clients/simple-screenshooter-mtk.c b/clients/simple-screenshooter-mtk.c
+new file mode 100644
+index 0000000..cbca18b
+--- /dev/null
++++ b/clients/simple-screenshooter-mtk.c
+@@ -0,0 +1,259 @@
++/*
++ * Copyright © 2008 Kristian Høgsberg
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software"),
++ * to deal in the Software without restriction, including without limitation
++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ * and/or sell copies of the Software, and to permit persons to whom the
++ * Software is furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the next
++ * paragraph) shall be included in all copies or substantial portions of the
++ * Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
++ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++ * DEALINGS IN THE SOFTWARE.
++ */
++
++#include "config.h"
++
++#include <stdint.h>
++#include <errno.h>
++#include <stdlib.h>
++#include <stdio.h>
++#include <string.h>
++#include <fcntl.h>
++#include <unistd.h>
++#include <limits.h>
++#include <sys/param.h>
++#include <sys/mman.h>
++#include <cairo.h>
++
++#include <wayland-client.h>
++#include "weston-configure-mtk-client-protocol.h"
++#include "shared/os-compatibility.h"
++#include "shared/xalloc.h"
++
++/* The screenshooter is a good example of a custom object exposed by
++ * the compositor and serves as a test bed for implementing client
++ * side marshalling outside libwayland.so */
++
++static struct wl_shm *shm;
++static struct weston_screenshooter_mtk *mtk_screenshooter;
++static struct wl_list output_list;
++int min_x, min_y, max_x, max_y;
++int buffer_copy_done;
++
++struct screenshooter_output {
++ struct wl_output *output;
++ struct wl_buffer *buffer;
++ int width, height, offset_x, offset_y;
++ void *data;
++ struct wl_list link;
++};
++
++static void
++display_handle_geometry(void *data,
++ struct wl_output *wl_output,
++ int x,
++ int y,
++ int physical_width,
++ int physical_height,
++ int subpixel,
++ const char *make,
++ const char *model,
++ int transform)
++{
++ struct screenshooter_output *output;
++
++ output = wl_output_get_user_data(wl_output);
++
++ if (wl_output == output->output) {
++ output->offset_x = x;
++ output->offset_y = y;
++ }
++}
++
++static void
++display_handle_mode(void *data,
++ struct wl_output *wl_output,
++ uint32_t flags,
++ int width,
++ int height,
++ int refresh)
++{
++ struct screenshooter_output *output;
++
++ output = wl_output_get_user_data(wl_output);
++
++ if (wl_output == output->output && (flags & WL_OUTPUT_MODE_CURRENT)) {
++ output->width = width;
++ output->height = height;
++ }
++}
++
++static const struct wl_output_listener output_listener = {
++ display_handle_geometry,
++ display_handle_mode
++};
++
++static void
++screenshooter_done(void *data, struct weston_screenshooter_mtk *mtk_screenshooter)
++{
++ fprintf(stderr, "screenshooter_done\n");
++ buffer_copy_done = 1;
++}
++
++static const struct weston_screenshooter_mtk_listener screenshooter_mtk_listener =
++{
++ screenshooter_done
++};
++
++static void
++handle_global(void *data, struct wl_registry *registry,
++ uint32_t name, const char *interface, uint32_t version)
++{
++ static struct screenshooter_output *output;
++
++ if (strcmp(interface, "wl_output") == 0) {
++ output = xmalloc(sizeof *output);
++ output->output = wl_registry_bind(registry, name,
++ &wl_output_interface, 1);
++ wl_list_insert(&output_list, &output->link);
++ wl_output_add_listener(output->output, &output_listener, output);
++ } else if (strcmp(interface, "wl_shm") == 0) {
++ shm = wl_registry_bind(registry, name, &wl_shm_interface, 1);
++ } else if (strcmp(interface, "weston_screenshooter_mtk") == 0) {
++ mtk_screenshooter = wl_registry_bind(registry, name,
++ &weston_screenshooter_mtk_interface,
++ 1);
++ }
++}
++
++static void
++handle_global_remove(void *data, struct wl_registry *registry, uint32_t name)
++{
++ /* XXX: unimplemented */
++}
++
++static const struct wl_registry_listener registry_listener = {
++ handle_global,
++ handle_global_remove
++};
++
++static struct wl_buffer *
++create_shm_buffer(int width, int height, void **data_out)
++{
++ struct wl_shm_pool *pool;
++ struct wl_buffer *buffer;
++ int fd, size, stride;
++ void *data;
++
++ stride = width * 4;
++ size = stride * height;
++
++ fd = os_create_anonymous_file(size);
++ if (fd < 0) {
++ fprintf(stderr, "creating a buffer file for %d B failed: %m\n",
++ size);
++ return NULL;
++ }
++
++ data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
++ if (data == MAP_FAILED) {
++ fprintf(stderr, "mmap failed: %m\n");
++ close(fd);
++ return NULL;
++ }
++
++ pool = wl_shm_create_pool(shm, fd, size);
++ close(fd);
++ buffer = wl_shm_pool_create_buffer(pool, 0, width, height, stride,
++ WL_SHM_FORMAT_XRGB8888);
++ wl_shm_pool_destroy(pool);
++
++ *data_out = data;
++ fprintf(stderr,"create_shm_buffer\n");
++ return buffer;
++}
++
++static void
++usage(int error_code)
++{
++ fprintf(stderr, "Usage: simple-screenshooter-mtk [OPTIONS]\n\n"
++ " -m dump mainscreen\n"
++ " -s dump subscreen\n"
++ " -h This help text! default dump all screens\n\n");
++
++ exit(error_code);
++}
++
++int main(int argc, char *argv[])
++{
++ struct wl_display *display;
++ struct wl_registry *registry;
++ struct screenshooter_output *output;
++ int i, width, height;
++ int mainscreen=0;
++ int subscreen=0;
++ for (i = 1; i < argc; i++) {
++ if (strcmp("-m", argv[i]) == 0)
++ mainscreen = 1;
++ else if (strcmp("-s", argv[i]) == 0)
++ subscreen = 1;
++ else if (strcmp("-h", argv[i]) == 0)
++ usage(EXIT_SUCCESS);
++ else
++ usage(EXIT_SUCCESS);
++ }
++
++ display = wl_display_connect(NULL);
++ if (display == NULL) {
++ fprintf(stderr, "failed to create display: %m\n");
++ return -1;
++ }
++
++ wl_list_init(&output_list);
++ registry = wl_display_get_registry(display);
++ wl_registry_add_listener(registry, ®istry_listener, NULL);
++ wl_display_dispatch(display);
++ wl_display_roundtrip(display);
++ if (mtk_screenshooter == NULL) {
++ fprintf(stderr, "display doesn't support screenshooter\n");
++ return -1;
++ }
++
++ weston_screenshooter_mtk_add_listener(mtk_screenshooter,
++ &screenshooter_mtk_listener,
++ NULL);
++
++ wl_list_for_each_reverse(output, &output_list, link) {
++ if(mainscreen == 1) {
++ output->buffer = create_shm_buffer(1920, 1080, &output->data);
++ weston_screenshooter_mtk_shoot(mtk_screenshooter,output->output,output->buffer);
++ buffer_copy_done = 0;
++ while (!buffer_copy_done)
++ wl_display_roundtrip(display);
++
++ break;
++ }
++ else if(subscreen == 1) {
++ subscreen = 0;
++ }
++ else {
++ output->buffer = create_shm_buffer(1920, 1080, &output->data);
++ weston_screenshooter_mtk_shoot(mtk_screenshooter,output->output,output->buffer);
++ buffer_copy_done = 0;
++ while (!buffer_copy_done)
++ wl_display_roundtrip(display);
++ }
++ }
++ fprintf(stderr,"end!!!!!\n");
++ return 0;
++}
+diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c
+index bba22b3..064d8c2 100644
+--- a/libweston/compositor-drm.c
++++ b/libweston/compositor-drm.c
+@@ -236,6 +236,7 @@ struct drm_backend {
+ struct gbm_device *gbm;
+ struct wl_listener session_listener;
+ uint32_t gbm_format;
++ uint32_t writeback_connectors;
+
+ /* we need these parameters in order to not fail drmModeAddFB2()
+ * due to out of bounds dimensions, and then mistakenly set
+@@ -411,6 +412,9 @@ struct drm_output {
+ uint32_t connector_id;
+ struct drm_edid edid;
+
++ uint32_t wb_connector_id;
++ uint32_t wb_prop_id;
++
+ /* Holds the properties for the connector */
+ struct drm_property_info props_conn[WDRM_CONNECTOR__COUNT];
+ /* Holds the properties for the CRTC */
+@@ -451,6 +455,7 @@ struct drm_output {
+ struct wl_listener recorder_frame_listener;
+
+ struct wl_event_source *pageflip_timer;
++ struct drm_fb *wb_fb;
+ };
+
+ static struct gl_renderer_interface *gl_renderer;
+@@ -477,6 +482,29 @@ wl_array_remove_uint32(struct wl_array *array, uint32_t elm)
+ }
+ }
+
++static int
++_write_file(void *buf, int len, const char *file_name)
++{
++ int ret, nwrite = 0;
++
++ FILE *fp = fopen(file_name, "wb");
++ if (!fp)
++ {
++ fprintf(stderr,"debug: file %s open failed\n", file_name);
++ return -1;
++ }
++
++ while (nwrite < len) {
++ ret = fwrite(buf + nwrite, 1, len - nwrite, fp);
++ if (!ret)
++ break;
++ nwrite += ret;
++ }
++
++ fclose(fp);
++ return 0;
++}
++
+ static inline struct drm_output *
+ to_drm_output(struct weston_output *base)
+ {
+@@ -749,6 +777,40 @@ drm_output_update_msc(struct drm_output *output, unsigned int seq);
+ static void
+ drm_output_destroy(struct weston_output *output_base);
+
++static uint64_t
++drm_properties_get_writeback_fb_value(struct drm_backend *b,
++ uint32_t obj_id, uint32_t obj_type)
++{
++ drmModeObjectProperties *props;
++ drmModePropertyRes *prop;
++ unsigned i;
++ uint64_t value;
++
++ props = drmModeObjectGetProperties(b->drm.fd, obj_id, obj_type);
++ if (!props) {
++ weston_log("DRM error : get properties for object %u "
++ "of type %#x failed.\n", obj_id, obj_type);
++ return -1;
++ }
++
++ for (i = 0; i < props->count_props; i++) {
++ prop = drmModeGetProperty(b->drm.fd, props->props[i]);
++ if (!prop)
++ continue;
++
++ if (strcmp(prop->name, "WRITEBACK_FB_ID") == 0)
++ break;
++ }
++
++
++ value = prop->prop_id;
++
++ drmModeFreeObjectProperties(props);
++
++ return value;
++}
++
++
+ /**
+ * Returns true if the plane can be used on the given output for its current
+ * repaint cycle.
+@@ -2053,6 +2115,13 @@ drm_output_apply_state_atomic(struct drm_output_state *state,
+ ret |= crtc_add_prop(req, output, WDRM_CRTC_ACTIVE, 1);
+ ret |= connector_add_prop(req, output, WDRM_CONNECTOR_CRTC_ID,
+ output->crtc_id);
++ if(output->wb_connector_id) {
++ if (drmModeAtomicAddProperty(req, output->wb_connector_id,
++ output->props_conn[WDRM_CONNECTOR_CRTC_ID].prop_id,
++ output->crtc_id) < 0)
++ return -1;
++
++ }
+ } else {
+ ret |= crtc_add_prop(req, output, WDRM_CRTC_MODE_ID, 0);
+ ret |= crtc_add_prop(req, output, WDRM_CRTC_ACTIVE, 0);
+@@ -2095,6 +2164,12 @@ drm_output_apply_state_atomic(struct drm_output_state *state,
+ }
+ }
+
++ if(output->base.screenshoot_dump == 1 && output->wb_connector_id) {
++ ret = drmModeAtomicAddProperty(req, output->wb_connector_id,
++ output->wb_prop_id,
++ output->wb_fb->fb_id);
++ }
++
+ return 0;
+ }
+
+@@ -2605,6 +2680,7 @@ atomic_flip_handler(int fd, unsigned int frame, unsigned int sec,
+ uint32_t flags = WP_PRESENTATION_FEEDBACK_KIND_VSYNC |
+ WP_PRESENTATION_FEEDBACK_KIND_HW_COMPLETION |
+ WP_PRESENTATION_FEEDBACK_KIND_HW_CLOCK;
++ char filename[64];
+
+ /* During the initial modeset, we can disable CRTCs which we don't
+ * actually handle during normal operation; this will give us events
+@@ -2612,6 +2688,14 @@ atomic_flip_handler(int fd, unsigned int frame, unsigned int sec,
+ if (!output || !output->base.enabled)
+ return;
+
++ if(output->base.screenshoot_dump == 1 && output->wb_connector_id) {
++ snprintf(filename, 64, "/tmp/screen_dump_%u",
++ weston_compositor_get_time());
++ _write_file(output->wb_fb->map, output->wb_fb->size, filename);
++ output->base.screenshoot_needed = 0;
++ output->base.screenshoot_dump = 0;
++ }
++
+ drm_output_update_msc(output, frame);
+
+ assert(b->atomic_modeset);
+@@ -5011,6 +5095,24 @@ create_output_for_connector(struct drm_backend *b,
+
+ weston_compositor_add_pending_output(&output->base, b->compositor);
+
++ if(b->writeback_connectors) {
++ for(i=0; ;i++) {
++ if(b->writeback_connectors & (1 << i))
++ break;
++ }
++ output->wb_connector_id = resources->connectors[i];
++ output->wb_prop_id = drm_properties_get_writeback_fb_value(b,
++ resources->connectors[i],
++ DRM_MODE_OBJECT_CONNECTOR);
++ b->writeback_connectors &= ~(1 << i);
++ weston_log("output->wb_connector_id=%d,output->wb_prop_id=%d,output->connector_id=%d\n",output->wb_connector_id,output->wb_prop_id,output->connector_id);
++ weston_log("b->writeback_connectors=%d \n",b->writeback_connectors);
++ }
++
++ output->wb_fb = drm_fb_create_dumb(b, 1920, 1080, DRM_FORMAT_RGB888);
++ if (!output->wb_fb)
++ weston_log("writeback drm_fb_create_dumb failed\n");
++
+ return 0;
+
+ err_output:
+@@ -5029,6 +5131,7 @@ create_outputs(struct drm_backend *b, struct udev_device *drm_device)
+ drmModeConnector *connector;
+ drmModeRes *resources;
+ int i;
++ b->writeback_connectors = 0;
+
+ resources = drmModeGetResources(b->drm.fd);
+ if (!resources) {
+@@ -5042,6 +5145,17 @@ create_outputs(struct drm_backend *b, struct udev_device *drm_device)
+ b->max_height = resources->max_height;
+
+ for (i = 0; i < resources->count_connectors; i++) {
++ connector = drmModeGetConnector(b->drm.fd,
++ resources->connectors[i]);
++ if (connector == NULL)
++ continue;
++
++ if (connector->connection == DRM_MODE_DISCONNECTED) {
++ b->writeback_connectors |= 1 << i;
++ }
++ }
++
++ for (i = 0; i < resources->count_connectors; i++) {
+ int ret;
+
+ connector = drmModeGetConnector(b->drm.fd,
+@@ -5853,6 +5967,7 @@ weston_backend_init(struct weston_compositor *compositor,
+ b = drm_backend_create(compositor, &config);
+ if (b == NULL)
+ return -1;
++ screenshooter_mtk_create(compositor);
+
+ return 0;
+ }
+diff --git a/libweston/compositor.c b/libweston/compositor.c
+index fb647da..9d084f5 100644
+--- a/libweston/compositor.c
++++ b/libweston/compositor.c
+@@ -2636,6 +2636,9 @@ weston_output_schedule_repaint(struct weston_output *output)
+ compositor->state == WESTON_COMPOSITOR_OFFSCREEN)
+ return;
+
++ if(output->screenshoot_needed)
++ output->screenshoot_dump = 1;
++
+ if (!output->repaint_needed)
+ TL_POINT("core_repaint_req", TLP_OUTPUT(output), TLP_END);
+
+diff --git a/libweston/compositor.h b/libweston/compositor.h
+index 6070c77..dea88dc 100644
+--- a/libweston/compositor.h
++++ b/libweston/compositor.h
+@@ -183,6 +183,9 @@ struct weston_output {
+ REPAINT_AWAITING_COMPLETION, /**< last repaint not yet finished */
+ } repaint_status;
+
++ int screenshoot_needed;
++ int screenshoot_dump;
++
+ /** If repaint_status is REPAINT_SCHEDULED, contains the time the
+ * next repaint should be run */
+ struct timespec next_repaint;
+diff --git a/libweston/pixel-formats.c b/libweston/pixel-formats.c
+index df84a9f..b45db93 100644
+--- a/libweston/pixel-formats.c
++++ b/libweston/pixel-formats.c
+@@ -145,6 +145,8 @@ static const struct pixel_format_info pixel_format_table[] = {
+ },
+ {
+ .format = DRM_FORMAT_RGB888,
++ .depth = 24,
++ .bpp = 24,
+ },
+ {
+ .format = DRM_FORMAT_BGR888,
+diff --git a/libweston/weston-screenshooter-mtk.c b/libweston/weston-screenshooter-mtk.c
+new file mode 100644
+index 0000000..7ad8f97
+--- /dev/null
++++ b/libweston/weston-screenshooter-mtk.c
+@@ -0,0 +1,129 @@
++/*
++ * Copyright © 2008-2011 Kristian Høgsberg
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#include "config.h"
++
++#include <stdlib.h>
++#include <stdio.h>
++#include <string.h>
++#include <linux/input.h>
++#include <fcntl.h>
++#include <unistd.h>
++#include <sys/uio.h>
++
++#include "compositor.h"
++#include "weston-configure-mtk-server-protocol.h"
++#include "shared/helpers.h"
++
++#include "wcap/wcap-decode.h"
++
++struct screenshooter {
++ struct weston_compositor *ec;
++ struct wl_global *global;
++ struct wl_client *client;
++ //struct weston_process process;
++ struct wl_listener destroy_listener;
++};
++
++struct screenshooter_frame_listener {
++ struct wl_listener listener;
++ struct weston_buffer *buffer;
++ weston_screenshooter_done_func_t done;
++ void *data;
++};
++
++static void
++weston_screenshooter_mtk_shoot(struct wl_client *client,
++ struct wl_resource *resource,
++ struct wl_resource *output_resource,
++ struct wl_resource *buffer_resource)
++{
++ struct weston_output *output =
++ wl_resource_get_user_data(output_resource);
++ struct weston_buffer *buffer =
++ weston_buffer_from_resource(buffer_resource);
++ weston_log("weston_screenshooter_mtk_shoot.\n");
++ output->screenshoot_needed = 1;
++ weston_output_schedule_repaint(output);
++ if (buffer == NULL) {
++ wl_resource_post_no_memory(resource);
++ return;
++ }
++
++ weston_screenshooter_mtk_send_done(resource);
++}
++
++static const struct weston_screenshooter_mtk_interface screenshooter_mtk_implementation = {
++ weston_screenshooter_mtk_shoot
++};
++
++static void
++bind_screenshooter_mtk(struct wl_client *client,
++ void *data, uint32_t version, uint32_t id)
++{
++ struct screenshooter *shooter = data;
++ struct wl_resource *resource;
++
++ resource = wl_resource_create(client,
++ &weston_screenshooter_mtk_interface, 1, id);
++
++ if (resource == NULL) {
++ wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
++ "screenshooter failed: permission denied");
++ wl_client_post_no_memory(client);
++ return;
++ }
++
++ wl_resource_set_implementation(resource, &screenshooter_mtk_implementation,
++ data, NULL);
++}
++
++static void
++screenshooter_destroy(struct wl_listener *listener, void *data)
++{
++ struct screenshooter *shooter =
++ container_of(listener, struct screenshooter, destroy_listener);
++
++ wl_global_destroy(shooter->global);
++ free(shooter);
++}
++
++WL_EXPORT void
++screenshooter_mtk_create(struct weston_compositor *ec)
++{
++ struct screenshooter *shooter;
++
++ shooter = malloc(sizeof *shooter);
++ if (shooter == NULL)
++ return;
++
++ shooter->ec = ec;
++ shooter->global = wl_global_create(ec->wl_display,
++ &weston_screenshooter_mtk_interface, 1,
++ shooter, bind_screenshooter_mtk);
++
++ shooter->destroy_listener.notify = screenshooter_destroy;
++ wl_signal_add(&ec->destroy_signal, &shooter->destroy_listener);
++}
+diff --git a/protocol/weston-configure-mtk.xml b/protocol/weston-configure-mtk.xml
+new file mode 100644
+index 0000000..e19a2ad
+--- /dev/null
++++ b/protocol/weston-configure-mtk.xml
+@@ -0,0 +1,37 @@
++<?xml version="1.0" encoding="UTF-8"?>
++<protocol name="weston_configure_mtk">
++
++ <copyright>
++ Copyright (C) 2016 MediaTek
++
++ Permission is hereby granted, free of charge, to any person obtaining a
++ copy of this software and associated documentation files (the "Software"),
++ to deal in the Software without restriction, including without limitation
++ the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ and/or sell copies of the Software, and to permit persons to whom the
++ Software is furnished to do so, subject to the following conditions:
++
++ The above copyright notice and this permission notice (including the next
++ paragraph) shall be included in all copies or substantial portions of the
++ Software.
++
++ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
++ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++ DEALINGS IN THE SOFTWARE.
++ </copyright>
++
++ <interface name="weston_screenshooter_mtk" version="1">
++ <request name="shoot">
++ <arg name="output" type="object" interface="wl_output"/>
++ <arg name="buffer" type="object" interface="wl_buffer"/>
++ </request>
++ <event name="done">
++ </event>
++ </interface>
++
++</protocol>
++
+--
+1.9.1
+
diff --git a/meta/meta-mediatek/recipes-graphics/wayland/weston/0008-PATCH-weston-add-surface-overlay-assignment-interfac.patch b/meta/meta-mediatek/recipes-graphics/wayland/weston/0008-PATCH-weston-add-surface-overlay-assignment-interfac.patch
new file mode 100644
index 0000000..063dba6
--- /dev/null
+++ b/meta/meta-mediatek/recipes-graphics/wayland/weston/0008-PATCH-weston-add-surface-overlay-assignment-interfac.patch
@@ -0,0 +1,278 @@
+From 949565b2683a3a67060698132a52ea26c75d9952 Mon Sep 17 00:00:00 2001
+From: Qian Hu <Qian.Hu@mediatek.com>
+Date: Tue, 24 Sep 2019 15:01:45 +0800
+Subject: [PATCH 8/8] [PATCH] weston: add surface overlay assignment interface
+
+add surface overlay assignment interface
+
+Signed-off-by: Qian Hu <Qian.Hu@mediatek.com>
+---
+ Makefile.am | 6 +-
+ compositor/main.c | 1 +
+ libweston/compositor.h | 11 ++++
+ libweston/weston-configure-mtk.c | 126 +++++++++++++++++++++++++++++++++++++++
+ libweston/weston-configure-mtk.h | 54 +++++++++++++++++
+ 5 files changed, 197 insertions(+), 1 deletion(-)
+ create mode 100644 libweston/weston-configure-mtk.c
+ create mode 100644 libweston/weston-configure-mtk.h
+
+diff --git a/Makefile.am b/Makefile.am
+index 7efa5a0..008bdfe 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -97,6 +97,8 @@ libweston_@LIBWESTON_MAJOR@_la_SOURCES = \
+ libweston/pixel-formats.c \
+ libweston/pixel-formats.h \
+ libweston/weston-screenshooter-mtk.c \
++ libweston/weston-configure-mtk.c \
++ libweston/weston-configure-mtk.h \
+ shared/helpers.h \
+ shared/matrix.c \
+ shared/matrix.h \
+@@ -677,7 +679,9 @@ nodist_weston_simple_configure_mtk_SOURCES = \
+ protocol/fullscreen-shell-unstable-v1-protocol.c \
+ protocol/fullscreen-shell-unstable-v1-client-protocol.h \
+ protocol/linux-dmabuf-unstable-v1-protocol.c \
+- protocol/linux-dmabuf-unstable-v1-client-protocol.h
++ protocol/linux-dmabuf-unstable-v1-client-protocol.h \
++ protocol/weston-configure-mtk-protocol.c \
++ protocol/weston-configure-mtk-client-protocol.h
+ weston_simple_configure_mtk_CFLAGS = $(AM_CFLAGS) $(CLIENT_CFLAGS)
+ weston_simple_configure_mtk_LDADD = $(EGL_LIBS) $(LIBDRM_LIBS) libtoytoolkit.la
+ BUILT_SOURCES += protocol/linux-dmabuf-unstable-v1-client-protocol.h
+diff --git a/compositor/main.c b/compositor/main.c
+index b5b4fc5..21c501c 100644
+--- a/compositor/main.c
++++ b/compositor/main.c
+@@ -52,6 +52,7 @@
+ #include "git-version.h"
+ #include "version.h"
+ #include "weston.h"
++#include "../libweston/weston-configure-mtk.h"
+
+ #include "compositor-drm.h"
+ #include "compositor-headless.h"
+diff --git a/libweston/compositor.h b/libweston/compositor.h
+index 8736691..ba577b7 100644
+--- a/libweston/compositor.h
++++ b/libweston/compositor.h
+@@ -1362,6 +1362,16 @@ struct weston_surface_state {
+ struct weston_buffer_viewport buffer_viewport;
+ };
+
++/*
++ * For setting whether the views on this surface walk
++ * overlay path; on==>1, off==>0
++*/
++struct config_switch{
++ struct wl_resource *resource;
++ void *private;
++ int sprites_switch;
++};
++
+ struct weston_surface_activation_data {
+ struct weston_surface *surface;
+ struct weston_seat *seat;
+@@ -1483,6 +1493,7 @@ struct weston_surface {
+
+ /* An list of per seat pointer constraints. */
+ struct wl_list pointer_constraints;
++ struct config_switch *config_switch;
+ };
+
+ struct weston_subsurface {
+diff --git a/libweston/weston-configure-mtk.c b/libweston/weston-configure-mtk.c
+new file mode 100644
+index 0000000..185f91c
+--- /dev/null
++++ b/libweston/weston-configure-mtk.c
+@@ -0,0 +1,126 @@
++#include "config.h"
++#include <fcntl.h>
++#include <stdio.h>
++#include <string.h>
++#include <stdlib.h>
++#include <stdint.h>
++#include <limits.h>
++#include <stdarg.h>
++#include <assert.h>
++#include <sys/ioctl.h>
++#include <sys/mman.h>
++#include <sys/wait.h>
++#include <sys/socket.h>
++#include <sys/utsname.h>
++#include <sys/stat.h>
++#include <unistd.h>
++#include <math.h>
++#include <linux/input.h>
++#include <dlfcn.h>
++#include <signal.h>
++#include <setjmp.h>
++#include <sys/time.h>
++#include <time.h>
++#include <errno.h>
++
++#include "timeline.h"
++
++#include "compositor.h"
++//#include "scaler-server-protocol.h"
++#include "shared/helpers.h"
++#include "shared/os-compatibility.h"
++#include "shared/timespec-util.h"
++#include "git-version.h"
++#include "version.h"
++
++#include "weston-configure-mtk.h"
++#include "weston-configure-mtk-server-protocol.h"
++
++static void
++config_set_sprite_switch(struct wl_client *client,
++ struct wl_resource *resource,
++ int32_t spr_switch)
++{
++ struct config_switch *configure = wl_resource_get_user_data(resource);
++
++ configure->sprites_switch = spr_switch;
++}
++
++static const struct config_switch_set_interface switch_set_interface = {
++ config_set_sprite_switch,
++};
++
++static struct config_switch *
++config_interface_create(struct weston_surface *surface)
++{
++ struct config_switch *config_switch;
++
++ config_switch = zalloc(sizeof *config_switch);
++ if (config_switch == NULL)
++ return NULL;
++
++ config_switch->private = (void *)surface;
++ surface->config_switch = config_switch;
++
++ return config_switch;
++}
++
++static void
++config_switch_connect(struct wl_client *client, struct wl_resource *resource,
++ struct wl_resource *wl_surface, uint32_t id)
++{
++ struct config_switch *config_switch = wl_resource_get_user_data(resource);
++ struct weston_surface *surface = wl_resource_get_user_data(wl_surface);
++
++ config_switch = config_interface_create(surface);
++ if (config_switch == NULL) {
++ wl_resource_post_no_memory(resource);
++ return;
++ }
++
++ config_switch->resource =
++ wl_resource_create(client, &config_switch_set_interface,
++ wl_resource_get_version(resource), id);
++ if (config_switch->resource == NULL) {
++ wl_resource_post_no_memory(resource);
++ return;
++ }
++ wl_resource_set_implementation(config_switch->resource, &switch_set_interface,
++ config_switch, NULL);
++}
++
++static const struct config_switch_interface switch_interface = {
++ config_switch_connect,
++};
++
++static void
++bind_config_switch(struct wl_client *client,
++ void *data, uint32_t version, uint32_t id)
++{
++ struct weston_compositor *compositor = data;
++ struct wl_resource *resource;
++
++ resource = wl_resource_create(client, &config_switch_interface,
++ MIN(version, 1), id);
++ if (resource == NULL) {
++ wl_client_post_no_memory(client);
++ return;
++ }
++
++ wl_resource_set_implementation(resource, &switch_interface,
++ compositor, NULL);
++}
++
++WL_EXPORT int
++config_switch_global_create(struct weston_compositor *ec)
++{
++ if(!ec)
++ return -1;
++ if (!wl_global_create(ec->wl_display, &config_switch_interface, 1,
++ ec, bind_config_switch)){
++ fprintf(stderr, "error: failed to config_switch_global_create: %s\n", dlerror());
++ return -1;
++ }
++ return 0;
++}
++
+diff --git a/libweston/weston-configure-mtk.h b/libweston/weston-configure-mtk.h
+new file mode 100644
+index 0000000..0f093fe
+--- /dev/null
++++ b/libweston/weston-configure-mtk.h
+@@ -0,0 +1,54 @@
++/*
++ * Copyright © 2008-2011 Kristian Høgsberg
++ * Copyright © 2012 Collabora, Ltd.
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#ifndef _APP_CONFIGURE_EXTENSION_H_
++#define _APP_CONFIGURE_EXTENSION_H_
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++#include <stdbool.h>
++#include <time.h>
++#include <pixman.h>
++#include <xkbcommon/xkbcommon.h>
++
++#include <wayland-server.h>
++
++#include "version.h"
++#include "matrix.h"
++#include "config-parser.h"
++#include "zalloc.h"
++#include "timeline-object.h"
++
++int config_switch_global_create(struct weston_compositor *ec);
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif
++
+--
+2.6.4
+
diff --git a/meta/meta-mediatek/recipes-graphics/wayland/weston/0008-weston-add-mtk-test-client.patch b/meta/meta-mediatek/recipes-graphics/wayland/weston/0008-weston-add-mtk-test-client.patch
new file mode 100644
index 0000000..0036894
--- /dev/null
+++ b/meta/meta-mediatek/recipes-graphics/wayland/weston/0008-weston-add-mtk-test-client.patch
@@ -0,0 +1,1295 @@
+From 190e1349858bba7e103b03a0f242575425066300 Mon Sep 17 00:00:00 2001
+From: Jia Rong <jia.rong@mediatek.com>
+Date: Thu, 3 May 2018 08:35:18 +0800
+Subject: [PATCH] weston: add mtk test client
+
+add mtk test client
+Test: OK
+
+Change-Id: I89f50f00414c426b00424ab2dc298647330472a6
+Signed-off-by: Jia Rong <jia.rong@mediatek.com>
+CR-Id: AUTO00016576
+---
+ Makefile.am | 15 +
+ clients/simple-configure-mtk.c | 1230 ++++++++++++++++++++++++++++++++++++++++
+ configure.ac | 1 +
+ 3 files changed, 1246 insertions(+)
+ create mode 100644 clients/simple-configure-mtk.c
+
+diff --git a/Makefile.am b/Makefile.am
+index e450b95..576b4a1 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -657,6 +657,21 @@ nodist_weston_simple_screenshooter_mtk_SOURCES = \
+ weston_simple_screenshooter_mtk_CFLAGS = $(AM_CFLAGS) $(CLIENT_CFLAGS)
+ weston_simple_screenshooter_mtk_LDADD = $(EGL_LIBS) $(LIBDRM_LIBS) libtoytoolkit.la
+
++if BUILD_SIMPLE_CONFIGURE_MTK_CLIENT
++demo_clients += weston-simple-configure-mtk
++weston_simple_configure_mtk_SOURCES = clients/simple-configure-mtk.c
++nodist_weston_simple_configure_mtk_SOURCES = \
++ protocol/xdg-shell-unstable-v6-protocol.c \
++ protocol/xdg-shell-unstable-v6-client-protocol.h \
++ protocol/fullscreen-shell-unstable-v1-protocol.c \
++ protocol/fullscreen-shell-unstable-v1-client-protocol.h \
++ protocol/linux-dmabuf-unstable-v1-protocol.c \
++ protocol/linux-dmabuf-unstable-v1-client-protocol.h
++weston_simple_configure_mtk_CFLAGS = $(AM_CFLAGS) $(CLIENT_CFLAGS)
++weston_simple_configure_mtk_LDADD = $(EGL_LIBS) $(LIBDRM_LIBS) libtoytoolkit.la
++BUILT_SOURCES += protocol/linux-dmabuf-unstable-v1-client-protocol.h
++endif
++
+ noinst_LTLIBRARIES += libtoytoolkit.la
+
+ libtoytoolkit_la_SOURCES = \
+diff --git a/clients/simple-configure-mtk.c b/clients/simple-configure-mtk.c
+new file mode 100644
+index 0000000..f94497e
+--- /dev/null
++++ b/clients/simple-configure-mtk.c
+@@ -0,0 +1,1230 @@
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#include <stdbool.h>
++#include <math.h>
++#include <assert.h>
++#include <sys/mman.h>
++#include <signal.h>
++#include <fcntl.h>
++#include <errno.h>
++#include <linux/input.h>
++
++#include <wayland-client.h>
++#include <wayland-cursor.h>
++
++#include <drm_fourcc.h>
++#include <xf86drm.h>
++#include <xf86drmMode.h>
++
++#include <sys/types.h>
++#include <unistd.h>
++
++//#include "ivi-application-client-protocol.h"
++#include "xdg-shell-unstable-v6-client-protocol.h"
++#include "linux-dmabuf-unstable-v1-client-protocol.h"
++#include "fullscreen-shell-unstable-v1-client-protocol.h"
++
++#include <shared/platform.h>
++
++//#define IVI_SURFACE_ID 9000
++#define MAX_IMAGE 16
++#define ALIGN(X,bit) ((X + bit-1) & (~(bit-1)))
++#define MAX_DMABUF_PLANES 4
++#define RES_NUM 4
++#define MAX_LEN 60
++
++struct window;
++struct seat;
++
++struct display {
++ struct wl_display *display;
++ struct wl_registry *registry;
++ struct wl_compositor *compositor;
++ struct zxdg_shell_v6 *shell;
++ struct zwp_fullscreen_shell_v1 *fshell;
++ //struct ivi_application *ivi_application;
++ struct wl_seat *seat;
++ struct wl_pointer *pointer;
++ struct wl_touch *touch;
++ struct wl_keyboard *keyboard;
++ struct wl_shm *shm;
++ struct zwp_linux_dmabuf_v1 *dmabuf;
++ struct wl_list output_list; /* struct output_unit::link */
++ struct wl_cursor_theme *cursor_theme;
++ struct wl_cursor *default_cursor;
++ struct wl_surface *cursor_surface;
++ struct window *window;
++};
++
++struct geometry {
++ int width, height;
++};
++
++struct buffer {
++ struct wl_buffer *buffer;
++ void *dma_map;
++ int busy;
++};
++
++struct file_arg{
++ char filename[MAX_LEN];
++ int width;
++ int height;
++ int format;
++};
++
++struct window {
++ struct display *display;
++ struct geometry geometry, window_size;
++ bool wait_for_configure;
++ struct {
++ struct file_arg fProp;
++ struct buffer out_bufs[RES_NUM];
++ } image;
++ struct img_texture *tex;
++ uint32_t benchmark_time, frames;
++ struct wl_surface *surface;
++ struct zxdg_surface_v6 *xdg_surface;
++ struct zxdg_toplevel_v6 *xdg_toplevel;
++ //struct ivi_surface *ivi_surface;
++ struct wl_callback *callback;
++ int fullscreen, opaque, buffer_size, overlay, format;
++ enum wl_output_transform transform;
++ int drm_card_fd;
++};
++
++struct img_texture {
++ struct context *ctx;
++
++ /* input */
++ int width;
++ int height;
++ int drm_format;
++ int bpp;
++ int plane_nums;
++
++ int pitch[MAX_DMABUF_PLANES];
++ int offset[MAX_DMABUF_PLANES];
++ int fds[MAX_DMABUF_PLANES];
++ int handle[MAX_DMABUF_PLANES];
++
++ void *texbuf;
++ int size;
++};
++
++typedef enum _IMG_FORMAT_E {
++ IMG_FORMAT_RGB565 = 0,
++ IMG_FORMAT_XRGB8888,
++ IMG_FORMAT_ARGB8888,
++ IMG_FORMAT_YUYV,
++ IMG_FORMAT_NV12,
++ IMG_FORMAT_NV16,
++ IMG_FORMAT_YUV420,
++ IMG_FORMAT_YVU420,
++ IMG_FORMAT_LAST,
++} IMG_FORMAT_T;
++
++struct drm_fourcc_info {
++ unsigned int drm_format;
++ int plane_cnt;
++ int bpp;
++};
++
++static struct drm_fourcc_info fourcc_tbl[] = {
++ {DRM_FORMAT_RGB565, 1, 16},
++ {DRM_FORMAT_RGBA5551, 1, 16},
++ {DRM_FORMAT_RGBA4444, 1, 16},
++ {DRM_FORMAT_XRGB8888, 1, 32},
++ {DRM_FORMAT_XBGR8888, 1, 32},
++ {DRM_FORMAT_RGBX8888, 1, 32},
++ {DRM_FORMAT_BGRX8888, 1, 32},
++ {DRM_FORMAT_ARGB8888, 1, 32},
++ {DRM_FORMAT_ABGR8888, 1, 32},
++ {DRM_FORMAT_RGBA8888, 1, 32},
++ {DRM_FORMAT_BGRA8888, 1, 32},
++ {DRM_FORMAT_YUYV, 1, 16},
++ {DRM_FORMAT_VYUY, 1, 16},
++ {DRM_FORMAT_NV12, 2, 12},
++ {DRM_FORMAT_NV21, 2, 12},
++ {DRM_FORMAT_NV16, 2, 16},
++ {DRM_FORMAT_NV61, 2, 16},
++ {DRM_FORMAT_YUV420, 3, 12},
++ {DRM_FORMAT_YVU420, 3, 12},
++ {0, 0, 0},
++};
++
++static int running = 1;
++static int debug = 0;
++
++static void
++redraw(void *data, struct wl_callback *callback, uint32_t time);
++
++static int _format_transfer(int format, int *drm_format)
++{
++ int new_format;
++
++ if (!drm_format)
++ return -1;
++
++ switch (format) {
++ case IMG_FORMAT_RGB565:
++ new_format = DRM_FORMAT_RGB565;
++ break;
++ case IMG_FORMAT_XRGB8888:
++ new_format = DRM_FORMAT_XRGB8888;
++ break;
++ case IMG_FORMAT_ARGB8888:
++ new_format = DRM_FORMAT_ARGB8888;
++ break;
++ case IMG_FORMAT_YUYV:
++ new_format = DRM_FORMAT_YUYV;
++ break;
++ case IMG_FORMAT_NV12:
++ new_format = DRM_FORMAT_NV12;
++ break;
++ case IMG_FORMAT_NV16:
++ new_format = DRM_FORMAT_NV16;
++ break;
++ case IMG_FORMAT_YUV420:
++ new_format = DRM_FORMAT_YUV420;
++ break;
++ case IMG_FORMAT_YVU420:
++ new_format = DRM_FORMAT_YVU420;
++ break;
++ default:
++ return -2;
++ }
++ *drm_format = new_format;
++
++ return 0;
++}
++
++static struct drm_fourcc_info *
++get_drm_format_info(unsigned int format)
++{
++ int i;
++
++ for (i = 0; ; i++) {
++ if ( format == fourcc_tbl[i].drm_format){
++ return &fourcc_tbl[i];
++ }
++ if ( fourcc_tbl[i].drm_format == 0)
++ break;
++ }
++ return NULL;
++}
++
++static char *
++_get_tex_resource(int drifd, struct img_texture *tex)
++{
++ void *map = NULL;
++ struct drm_mode_create_dumb create_arg;
++ struct drm_mode_map_dumb map_arg;
++ struct drm_prime_handle prime_arg;
++ struct drm_fourcc_info *format_info;
++ int i, ret;
++ unsigned int alloc_size;
++
++ memset(&create_arg, 0, sizeof(create_arg));
++ memset(&map_arg, 0, sizeof(map_arg));
++ memset(&prime_arg, 0, sizeof(prime_arg));
++
++ for(i = 0; i < MAX_DMABUF_PLANES; i ++ )
++ tex->fds[i] = -1;
++
++ format_info = get_drm_format_info(tex->drm_format);
++ if (format_info == NULL)
++ return NULL;
++
++ tex->bpp = format_info->bpp;
++ if (format_info->plane_cnt == 3) {
++ if (format_info->bpp == 12) {
++ tex->pitch[0] = ALIGN(tex->width, 16);
++ tex->pitch[1] = tex->pitch[0] / 2;
++ tex->pitch[2] = tex->pitch[0] / 2;
++ tex->offset[0] = 0;
++ tex->offset[1] = tex->pitch[0] * tex->height;
++ tex->offset[2] = tex->offset[1] + tex->pitch[1] * tex->height / 2;
++ alloc_size = tex->offset[2] + tex->pitch[2] * tex->height / 2;
++ } else {
++ fprintf(stderr,"debug: please add new format 0x%x\n", tex->drm_format);
++ return NULL;
++ }
++ } else if (format_info->plane_cnt == 2) {
++ tex->pitch[0] = ALIGN(tex->width, 16);
++ tex->offset[0] = 0;
++ if (format_info->bpp == 16) {
++ tex->pitch[1] = tex->pitch[0];
++ tex->offset[1] = tex->pitch[0] * tex->height;
++ alloc_size = tex->offset[1] + tex->pitch[1] * tex->height;
++ fprintf(stderr,"debug: %s %d alloc_size = %d o/p [%d %d]\n",
++ __FUNCTION__, __LINE__, alloc_size, tex->offset[1], tex->pitch[1]);
++ }
++ else if (format_info->bpp == 12) {
++ tex->pitch[1] = tex->pitch[0] / 2;
++ tex->offset[1] = tex->pitch[0] * tex->height;
++ alloc_size = tex->offset[1] + tex->pitch[1] * tex->height;
++ } else {
++ fprintf(stderr,"debug: please add new format 0x%x\n", tex->drm_format);
++ return NULL;
++ }
++ } else {
++ tex->pitch[0] = ALIGN(tex->width * tex->bpp / 8, 16);
++ tex->offset[0] = 0;
++ alloc_size = tex->pitch[0] * tex->height;
++ }
++
++ create_arg.bpp = 8;
++ create_arg.width = alloc_size;
++ create_arg.height = 1;
++
++ ret = drmIoctl(drifd, DRM_IOCTL_MODE_CREATE_DUMB, &create_arg);
++ if (ret) {
++ fprintf(stderr,"error: drmIoctl %d DRM_IOCTL_MODE_CREATE_DUMB fail %d\n", drifd, ret);
++ return NULL;
++ }
++
++ map_arg.handle = create_arg.handle;
++
++ ret = drmIoctl(drifd, DRM_IOCTL_MODE_MAP_DUMB, &map_arg);
++ if (ret) {
++ fprintf(stderr,"error: drmIoctl DRM_IOCTL_MODE_MAP_DUMB fail %d\n", ret);
++ return NULL;
++ }
++
++ map = mmap(0, create_arg.size, PROT_WRITE|PROT_READ , MAP_SHARED, drifd, map_arg.offset);
++ if (map == MAP_FAILED) {
++ fprintf(stderr,"error: mmap fail : %p\n", map);
++ return NULL;
++ }
++
++ prime_arg.handle = create_arg.handle;
++ prime_arg.flags = DRM_CLOEXEC;
++ ret = drmIoctl(drifd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &prime_arg);
++ if (ret || prime_arg.fd == -1) {
++ fprintf(stderr,"error: drmIoctl DRM_IOCTL_PRIME_HANDLE_TO_FD fail %d fd=%d\n",ret,prime_arg.fd);
++ return NULL;
++ }
++
++ for (i = 0; i < format_info->plane_cnt; i++) {
++ tex->fds[i] = prime_arg.fd;
++ tex->handle[i] = create_arg.handle;
++ }
++ tex->plane_nums = format_info->plane_cnt;
++ tex->texbuf = map;
++ tex->size = create_arg.size;
++
++ return map;
++}
++
++static int
++init_img_texture(struct window *window)
++{
++ int ret;
++ struct img_texture *tex;
++ tex = malloc(sizeof *tex);
++ if (tex == NULL)
++ return -1;
++
++ ret = _format_transfer(window->image.fProp.format, &(tex->drm_format));
++ if (ret < 0)
++ return -1;
++
++ tex->width = window->image.fProp.width;
++ tex->height= window->image.fProp.height;
++
++ window->tex = tex;
++ return 0;
++}
++
++static void
++buffer_release(void *data, struct wl_buffer *buffer)
++{
++ struct buffer *mybuf = data;
++
++ mybuf->busy = 0;
++}
++
++static const struct wl_buffer_listener buffer_listener = {
++ buffer_release
++};
++
++static void
++create_succeeded(void *data,
++ struct zwp_linux_buffer_params_v1 *params,
++ struct wl_buffer *new_buffer)
++{
++ struct buffer *buffer = data;
++
++ buffer->buffer = new_buffer;
++ wl_buffer_add_listener(buffer->buffer, &buffer_listener, buffer);
++
++ zwp_linux_buffer_params_v1_destroy(params);
++}
++
++static void
++create_failed(void *data, struct zwp_linux_buffer_params_v1 *params)
++{
++ struct buffer *buffer = data;
++
++ buffer->buffer = NULL;
++
++ zwp_linux_buffer_params_v1_destroy(params);
++
++ running = false;
++
++ fprintf(stderr, "Error: zwp_linux_buffer_params.create failed.\n");
++}
++
++static const struct zwp_linux_buffer_params_v1_listener params_listener = {
++ create_succeeded,
++ create_failed
++};
++
++static int
++create_dmabuf_buffer(struct display *display, struct buffer *buffer)
++{
++ struct zwp_linux_buffer_params_v1 *params;
++ struct img_texture *cbtex = display->window->tex;
++ uint64_t modifier;
++ uint32_t flags;
++ int i;
++ /* output */
++ buffer->dma_map = _get_tex_resource(display->window->drm_card_fd, cbtex);
++
++ if (buffer->dma_map == NULL) {
++ fprintf(stderr, "error: _get_tex_resource failed\n");
++ return -1;
++ }
++
++ modifier = 0;
++ params = zwp_linux_dmabuf_v1_create_params(display->dmabuf);
++
++ for(i = 0; i < cbtex->plane_nums; i ++)
++ {
++ zwp_linux_buffer_params_v1_add(params,
++ cbtex->fds[i],
++ i, /* plane_idx */
++ cbtex->offset[i],/* offset */
++ cbtex->pitch[i],
++ modifier >> 32,
++ modifier & 0xffffffff);
++ }
++ zwp_linux_buffer_params_v1_add_listener(params, ¶ms_listener, buffer);
++ zwp_linux_buffer_params_v1_create(params,
++ cbtex->width,
++ cbtex->height,
++ cbtex->drm_format,
++ flags);
++
++ /* params is destroyed by the event handlers */
++ wl_display_roundtrip(display->display);
++ if (buffer->buffer == NULL) {
++ return -1;
++ }
++
++ return 0;
++}
++
++static int
++_load_file(void *buf, int len, const char *file_name)
++{
++ int ret, nread = 0;
++
++ FILE *fp = fopen(file_name, "rb");
++ if (!fp)
++ {
++ fprintf(stderr,"debug: file %s open failed\n", file_name);
++ return -1;
++ }
++
++ while (nread < len) {
++ ret = fread(buf + nread, 1, len - nread, fp);
++ if (!ret)
++ break;
++ nread += ret;
++ }
++
++ fclose(fp);
++ return 0;
++}
++
++static int
++_kms_device_fd(void)
++{
++ int i;
++ bool has_conn = false;
++ for (i = 0; i < 8; ++i) {
++ char path[99];
++ sprintf(path, "/dev/dri/card%d", i);
++ fprintf(stderr, "debug: trying %s\n", path);
++ int fd = open(path, O_RDWR | O_CLOEXEC);
++ if (fd >= 0) {
++ drmModeResPtr mr = drmModeGetResources(fd);
++ if (mr) {
++ has_conn = mr->count_connectors > 0;
++ drmModeFreeResources(mr);
++ }
++ if (has_conn) {
++ fprintf(stderr, "debug: using %s\n", path);
++ return fd;
++ }
++ close(fd);
++ }
++ }
++ return -1;
++}
++
++static void
++handle_xdg_surface_configure(void *data, struct zxdg_surface_v6 *surface,
++ uint32_t serial)
++{
++ struct window *window = data;
++ fprintf(stderr, "handle_xdg_surface_configure\n");
++
++ zxdg_surface_v6_ack_configure(surface, serial);
++
++ if (window->wait_for_configure) {
++ redraw(window, NULL, 0);
++ window->wait_for_configure = false;
++ }
++}
++
++static const struct zxdg_surface_v6_listener xdg_surface_listener = {
++ handle_xdg_surface_configure,
++};
++
++
++static void
++handle_toplevel_configure(void *data, struct zxdg_toplevel_v6 *toplevel,
++ int32_t width, int32_t height,
++ struct wl_array *states)
++{
++ struct window *window = data;
++ uint32_t *p;
++
++ window->fullscreen = 0;
++ wl_array_for_each(p, states) {
++ uint32_t state = *p;
++ switch (state) {
++ case ZXDG_TOPLEVEL_V6_STATE_FULLSCREEN:
++ window->fullscreen = 1;
++ break;
++ }
++ }
++
++ if (width > 0 && height > 0) {
++ if (!window->fullscreen) {
++ window->window_size.width = width;
++ window->window_size.height = height;
++ }
++ window->geometry.width = width;
++ window->geometry.height = height;
++ } else if (!window->fullscreen) {
++ window->geometry = window->window_size;
++ }
++
++ /*if (window->native)
++ wl_egl_window_resize(window->native,
++ window->geometry.width,
++ window->geometry.height, 0, 0);*/
++}
++
++static void
++handle_toplevel_close(void *data, struct zxdg_toplevel_v6 *xdg_toplevel)
++{
++ running = 0;
++}
++
++static const struct zxdg_toplevel_v6_listener xdg_toplevel_listener = {
++ handle_toplevel_configure,
++ handle_toplevel_close,
++};
++/*
++static void
++handle_ivi_surface_configure(void *data, struct ivi_surface *ivi_surface,
++ int32_t width, int32_t height)
++{
++
++}
++
++static const struct ivi_surface_listener ivi_surface_listener = {
++ handle_ivi_surface_configure,
++};
++*/
++static struct buffer *
++window_next_buffer(struct window *window)
++{
++ struct buffer *buffer = NULL;
++ int i, ret = 0;
++
++ for(i = 0; i < RES_NUM; i++) {
++ if (!window->image.out_bufs[i].busy) {
++ buffer = &window->image.out_bufs[i];
++ break;
++ }
++ }
++
++ if (!buffer)
++ return NULL;
++
++ if (!buffer->buffer) {
++ ret = create_dmabuf_buffer(window->display, buffer);
++ if (ret < 0)
++ return NULL;
++ if(i%2)
++ _load_file(buffer->dma_map, window->tex->size, window->image.fProp.filename);
++ else
++ memset(buffer->dma_map, 0, window->tex->size);
++ }
++
++ return buffer;
++}
++
++static void
++create_surface(struct window *window)
++{
++ struct display *display = window->display;
++
++ window->surface = wl_compositor_create_surface(display->compositor);
++ display->cursor_surface =
++ wl_compositor_create_surface(display->compositor);
++
++ if (display->shell) {
++ window->xdg_surface =
++ zxdg_shell_v6_get_xdg_surface(display->shell,
++ window->surface);
++
++ assert(window->xdg_surface);
++
++ zxdg_surface_v6_add_listener(window->xdg_surface,
++ &xdg_surface_listener, window);
++
++ window->xdg_toplevel =
++ zxdg_surface_v6_get_toplevel(window->xdg_surface);
++ zxdg_toplevel_v6_add_listener(window->xdg_toplevel,
++ &xdg_toplevel_listener, window);
++
++ zxdg_toplevel_v6_set_title(window->xdg_toplevel, "simple-configure-mtk");
++ window->wait_for_configure = true;
++ wl_surface_commit(window->surface);
++ } else if (display->fshell) {
++ zwp_fullscreen_shell_v1_present_surface(display->fshell,
++ window->surface,
++ ZWP_FULLSCREEN_SHELL_V1_PRESENT_METHOD_DEFAULT,
++ NULL);
++ //} else if (display->ivi_application ) {
++ // uint32_t id_ivisurf = IVI_SURFACE_ID + (uint32_t)getpid();
++ // window->ivi_surface =
++ // ivi_application_surface_create(display->ivi_application,
++ // id_ivisurf, window->surface);
++ // if (window->ivi_surface == NULL) {
++ // fprintf(stderr, "Failed to create ivi_client_surface\n");
++ // abort();
++ // }
++//
++ // ivi_surface_add_listener(window->ivi_surface,
++ // &ivi_surface_listener, window);
++
++ } else {
++ assert(0);
++ }
++
++}
++
++static void
++destroy_surface(struct window *window)
++{
++ if (window->xdg_toplevel)
++ zxdg_toplevel_v6_destroy(window->xdg_toplevel);
++ if (window->xdg_surface)
++ zxdg_surface_v6_destroy(window->xdg_surface);
++ //if (window->display->ivi_application)
++ // ivi_surface_destroy(window->ivi_surface);
++ if (window->display->fshell)
++ zwp_fullscreen_shell_v1_release(window->display->fshell);
++ wl_surface_destroy(window->surface);
++
++ if (window->callback)
++ wl_callback_destroy(window->callback);
++
++ if (window->image.out_bufs[0].buffer)
++ wl_buffer_destroy(window->image.out_bufs[0].buffer);
++ if (window->image.out_bufs[1].buffer)
++ wl_buffer_destroy(window->image.out_bufs[1].buffer);
++ if (window->image.out_bufs[2].buffer)
++ wl_buffer_destroy(window->image.out_bufs[2].buffer);
++}
++
++static const struct wl_callback_listener frame_listener;
++
++static void
++redraw(void *data, struct wl_callback *callback, uint32_t time)
++{
++ struct window *window = data;
++ struct buffer *buffer;
++ char filename[MAX_LEN] = {0};
++ static const uint32_t benchmark_interval = 5;
++ struct wl_region *region;
++ struct timeval tv;
++ int tmp;
++
++ buffer = window_next_buffer(window);
++ if (!buffer) {
++ fprintf(stderr,
++ !callback ? "error: Failed to create the first buffer.\n" :
++ "error: Both buffers busy at redraw(). Server bug?\n");
++ abort();
++ }
++
++ gettimeofday(&tv, NULL);
++ time = tv.tv_sec * 1000 + tv.tv_usec / 1000;
++ if (window->frames == 0)
++ window->benchmark_time = time;
++ if (time - window->benchmark_time > (benchmark_interval * 1000)) {
++ printf("debug: %d frames in %d seconds: %f fps\n",
++ window->frames,
++ benchmark_interval,
++ (float) window->frames / benchmark_interval);
++ window->benchmark_time = time;
++ window->frames = 0;
++ }
++
++ if (window->opaque || window->fullscreen) {
++ region = wl_compositor_create_region(window->display->compositor);
++ wl_region_add(region, 0, 0,
++ window->geometry.width,
++ window->geometry.height);
++ wl_surface_set_opaque_region(window->surface, region);
++ wl_region_destroy(region);
++ } else {
++ wl_surface_set_opaque_region(window->surface, NULL);
++ }
++
++ wl_surface_attach(window->surface, buffer->buffer, 0, 0);
++ wl_surface_set_buffer_transform(window->surface,
++ window->transform);
++ wl_surface_damage(window->surface,
++ 0, 0, window->geometry.width, window->geometry.height);
++
++ if (callback)
++ wl_callback_destroy(callback);
++
++ window->callback = wl_surface_frame(window->surface);
++ wl_callback_add_listener(window->callback, &frame_listener, window);
++ wl_surface_commit(window->surface);
++ buffer->busy = 1;
++
++ window->frames++;
++}
++
++static const struct wl_callback_listener frame_listener = {
++ redraw
++};
++
++static void
++pointer_handle_enter(void *data, struct wl_pointer *pointer,
++ uint32_t serial, struct wl_surface *surface,
++ wl_fixed_t sx, wl_fixed_t sy)
++{
++ struct display *display = data;
++ struct wl_buffer *buffer;
++ struct wl_cursor *cursor = display->default_cursor;
++ struct wl_cursor_image *image;
++
++ if (display->window->fullscreen)
++ wl_pointer_set_cursor(pointer, serial, NULL, 0, 0);
++ else if (cursor) {
++ image = display->default_cursor->images[0];
++ buffer = wl_cursor_image_get_buffer(image);
++ if (!buffer)
++ return;
++ wl_pointer_set_cursor(pointer, serial,
++ display->cursor_surface,
++ image->hotspot_x,
++ image->hotspot_y);
++ wl_surface_attach(display->cursor_surface, buffer, 0, 0);
++ wl_surface_damage(display->cursor_surface, 0, 0,
++ image->width, image->height);
++ wl_surface_commit(display->cursor_surface);
++ }
++
++}
++
++static void
++pointer_handle_leave(void *data, struct wl_pointer *pointer,
++ uint32_t serial, struct wl_surface *surface)
++{
++}
++
++static void
++pointer_handle_motion(void *data, struct wl_pointer *pointer,
++ uint32_t time, wl_fixed_t sx, wl_fixed_t sy)
++{
++
++}
++
++static void
++pointer_handle_button(void *data, struct wl_pointer *wl_pointer,
++ uint32_t serial, uint32_t time, uint32_t button,
++ uint32_t state)
++{
++ struct display *display = data;
++
++ if (!display->window->xdg_surface)
++ return;
++
++ if (button == BTN_LEFT && state == WL_POINTER_BUTTON_STATE_PRESSED)
++ zxdg_toplevel_v6_move(display->window->xdg_toplevel,
++ display->seat, serial);
++}
++
++static void
++pointer_handle_axis(void *data, struct wl_pointer *wl_pointer,
++ uint32_t time, uint32_t axis, wl_fixed_t value)
++{
++}
++
++static const struct wl_pointer_listener pointer_listener = {
++ pointer_handle_enter,
++ pointer_handle_leave,
++ pointer_handle_motion,
++ pointer_handle_button,
++ pointer_handle_axis,
++};
++
++static void
++touch_handle_down(void *data, struct wl_touch *wl_touch,
++ uint32_t serial, uint32_t time, struct wl_surface *surface,
++ int32_t id, wl_fixed_t x_w, wl_fixed_t y_w)
++{
++ struct display *d = (struct display *)data;
++
++ if (!d->shell)
++ return;
++
++ zxdg_toplevel_v6_move(d->window->xdg_toplevel, d->seat, serial);
++}
++
++static void
++touch_handle_up(void *data, struct wl_touch *wl_touch,
++ uint32_t serial, uint32_t time, int32_t id)
++{
++}
++
++static void
++touch_handle_motion(void *data, struct wl_touch *wl_touch,
++ uint32_t time, int32_t id, wl_fixed_t x_w, wl_fixed_t y_w)
++{
++}
++
++static void
++touch_handle_frame(void *data, struct wl_touch *wl_touch)
++{
++}
++
++static void
++touch_handle_cancel(void *data, struct wl_touch *wl_touch)
++{
++}
++
++static const struct wl_touch_listener touch_listener = {
++ touch_handle_down,
++ touch_handle_up,
++ touch_handle_motion,
++ touch_handle_frame,
++ touch_handle_cancel,
++};
++
++static void
++keyboard_handle_keymap(void *data, struct wl_keyboard *keyboard,
++ uint32_t format, int fd, uint32_t size)
++{
++}
++
++static void
++keyboard_handle_enter(void *data, struct wl_keyboard *keyboard,
++ uint32_t serial, struct wl_surface *surface,
++ struct wl_array *keys)
++{
++}
++
++static void
++keyboard_handle_leave(void *data, struct wl_keyboard *keyboard,
++ uint32_t serial, struct wl_surface *surface)
++{
++}
++
++static void
++keyboard_handle_key(void *data, struct wl_keyboard *keyboard,
++ uint32_t serial, uint32_t time, uint32_t key,
++ uint32_t state)
++{
++ struct display *d = data;
++
++ if (!d->shell)
++ return;
++
++ if (key == KEY_F11 && state) {
++ if (d->window->fullscreen)
++ zxdg_toplevel_v6_unset_fullscreen(d->window->xdg_toplevel);
++ else
++ zxdg_toplevel_v6_set_fullscreen(d->window->xdg_toplevel, NULL);
++ } else if (key == KEY_ESC && state)
++ running = 0;
++}
++
++static void
++keyboard_handle_modifiers(void *data, struct wl_keyboard *keyboard,
++ uint32_t serial, uint32_t mods_depressed,
++ uint32_t mods_latched, uint32_t mods_locked,
++ uint32_t group)
++{
++}
++
++static const struct wl_keyboard_listener keyboard_listener = {
++ keyboard_handle_keymap,
++ keyboard_handle_enter,
++ keyboard_handle_leave,
++ keyboard_handle_key,
++ keyboard_handle_modifiers,
++};
++
++static void
++seat_handle_capabilities(void *data, struct wl_seat *seat,
++ enum wl_seat_capability caps)
++{
++ struct display *d = data;
++
++ if ((caps & WL_SEAT_CAPABILITY_POINTER) && !d->pointer) {
++ d->pointer = wl_seat_get_pointer(seat);
++ wl_pointer_add_listener(d->pointer, &pointer_listener, d);
++ } else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && d->pointer) {
++ wl_pointer_destroy(d->pointer);
++ d->pointer = NULL;
++ }
++
++ if ((caps & WL_SEAT_CAPABILITY_KEYBOARD) && !d->keyboard) {
++ d->keyboard = wl_seat_get_keyboard(seat);
++ wl_keyboard_add_listener(d->keyboard, &keyboard_listener, d);
++ } else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && d->keyboard) {
++ wl_keyboard_destroy(d->keyboard);
++ d->keyboard = NULL;
++ }
++
++ if ((caps & WL_SEAT_CAPABILITY_TOUCH) && !d->touch) {
++ d->touch = wl_seat_get_touch(seat);
++ wl_touch_set_user_data(d->touch, d);
++ wl_touch_add_listener(d->touch, &touch_listener, d);
++ } else if (!(caps & WL_SEAT_CAPABILITY_TOUCH) && d->touch) {
++ wl_touch_destroy(d->touch);
++ d->touch = NULL;
++ }
++}
++
++static const struct wl_seat_listener seat_listener = {
++ seat_handle_capabilities,
++};
++
++
++static void
++xdg_shell_ping(void *data, struct zxdg_shell_v6 *shell, uint32_t serial)
++{
++ zxdg_shell_v6_pong(shell, serial);
++}
++
++static const struct zxdg_shell_v6_listener xdg_shell_listener = {
++ xdg_shell_ping,
++};
++
++static void
++dmabuf_format(void *data, struct zwp_linux_dmabuf_v1 *zwp_linux_dmabuf, uint32_t format)
++{
++ fprintf(stderr, "debug: Support drm_format 0x%x \n", format);
++}
++
++static const struct zwp_linux_dmabuf_v1_listener dmabuf_listener = {
++ dmabuf_format
++};
++
++static void
++registry_handle_global(void *data, struct wl_registry *registry,
++ uint32_t name, const char *interface, uint32_t version)
++{
++ struct display *d = data;
++
++ if (strcmp(interface, "wl_compositor") == 0) {
++ d->compositor =
++ wl_registry_bind(registry, name,
++ &wl_compositor_interface, 2);
++ } else if (strcmp(interface, "zxdg_shell_v6") == 0) {
++ d->shell = wl_registry_bind(registry, name,
++ &zxdg_shell_v6_interface, 1);
++ zxdg_shell_v6_add_listener(d->shell, &xdg_shell_listener, d);
++ } else if (strcmp(interface, "wl_seat") == 0) {
++ d->seat = wl_registry_bind(registry, name,
++ &wl_seat_interface, 1);
++ wl_seat_add_listener(d->seat, &seat_listener, d);
++ } else if (strcmp(interface, "zwp_fullscreen_shell_v1") == 0) {
++ d->fshell = wl_registry_bind(registry, name,
++ &zwp_fullscreen_shell_v1_interface, 1);
++ } else if (strcmp(interface, "wl_shm") == 0) {
++ d->shm = wl_registry_bind(registry, name,
++ &wl_shm_interface, 1);
++ d->cursor_theme = wl_cursor_theme_load(NULL, 32, d->shm);
++ if (!d->cursor_theme) {
++ fprintf(stderr, "unable to load default theme\n");
++ return;
++ }
++ d->default_cursor =
++ wl_cursor_theme_get_cursor(d->cursor_theme, "grabbing");
++ if (!d->default_cursor) {
++ fprintf(stderr, "unable to load default grabbing pointer\n");
++ // TODO: abort ?
++ }
++ //} else if (strcmp(interface, "ivi_application") == 0) {
++ // d->ivi_application =
++ // wl_registry_bind(registry, name,
++ // &ivi_application_interface, 1);
++ } else if (strcmp(interface, "zwp_linux_dmabuf_v1") == 0) {
++ d->dmabuf = wl_registry_bind(registry, name,
++ &zwp_linux_dmabuf_v1_interface, 1);
++ zwp_linux_dmabuf_v1_add_listener(d->dmabuf, &dmabuf_listener, d);
++ }
++}
++
++static void
++registry_handle_global_remove(void *data, struct wl_registry *registry,
++ uint32_t name)
++{
++}
++
++static const struct wl_registry_listener registry_listener = {
++ registry_handle_global,
++ registry_handle_global_remove
++};
++
++static void
++destroy_display(struct display *display)
++{
++ if (display->dmabuf)
++ zwp_linux_dmabuf_v1_destroy(display->dmabuf);
++
++ if (display->shell)
++ zxdg_shell_v6_destroy(display->shell);
++
++ if (display->fshell)
++ zwp_fullscreen_shell_v1_release(display->fshell);
++
++ if (display->compositor)
++ wl_compositor_destroy(display->compositor);
++
++ wl_surface_destroy(display->cursor_surface);
++ if (display->cursor_theme)
++ wl_cursor_theme_destroy(display->cursor_theme);
++
++ //if (display->ivi_application)
++ // ivi_application_destroy(display->ivi_application);
++
++ wl_registry_destroy(display->registry);
++ wl_display_flush(display->display);
++ wl_display_disconnect(display->display);
++ free(display);
++}
++
++static struct display *
++create_display(struct window *window)
++{
++ struct display *display;
++
++ display = malloc(sizeof *display);
++ if (display == NULL) {
++ fprintf(stderr, "out of memory\n");
++ exit(1);
++ }
++ display->display = wl_display_connect(NULL);
++ assert(display->display);
++ display->window = window;
++
++ display->registry = wl_display_get_registry(display->display);
++ wl_registry_add_listener(display->registry,
++ ®istry_listener, display);
++ wl_display_roundtrip(display->display);
++ if (display->dmabuf == NULL) {
++ fprintf(stderr, "No zwp_linux_dmabuf_v1 global found\n");
++ exit(1);
++ }
++ wl_display_roundtrip(display->display);
++
++ return display;
++}
++
++static void
++signal_int(int signum)
++{
++ running = 0;
++}
++
++/*
++ * parse the message inputed for rawdata
++ * egg: -F /usr/share/weston/rawdata.nv16:720x480@5
++ * filename:widthxheight@format
++*/
++static int parse_file(struct file_arg *file, char *p)
++{
++ char *end;
++ char *pPos = p;
++ int len, i;
++
++ len = strlen(pPos) + 1;
++ for (i = 0; i < len; i++)
++ if(pPos[i] == ':')
++ pPos[i] = '\0';
++
++ memcpy(file->filename, pPos, strlen(pPos) + 1);
++ pPos = pPos + strlen(pPos) + 1;
++ file->width = strtoul(pPos, &end, 10);
++ if (*end != 'x')
++ return -EINVAL;
++ pPos = end + 1;
++ file->height = strtoul(pPos, &end, 10);
++ if (*end != '@')
++ return -EINVAL;
++ pPos = end + 1;
++ file->format = strtoul(pPos, &end, 10);
++ if (*end != '\0')
++ return -EINVAL;
++ return 0;
++}
++
++static void init_window(struct window *window)
++{
++ window->geometry.width = 0;
++ window->geometry.height = 0;
++ window->buffer_size = 32;
++ window->transform = WL_OUTPUT_TRANSFORM_NORMAL;
++ window->opaque = 1;
++ window->overlay = 0;
++ window->format = 0;
++ window->drm_card_fd = -1;
++}
++
++static void
++usage(int error_code)
++{
++ fprintf(stderr, "Usage: mtkdraw-dma [OPTIONS]\n\n"
++ " -f Run in fullscreen mode(only desktop-shell valid)\n"
++ " -o Create an opaque surface\n"
++ " -s Use a 16 bpp EGL config\n"
++ " -t Set display buffer transform(0~7)\n"
++ " -F rawdata message(rawdata size provided is 320x480)\n"
++ " eg:-F /usr/share/weston/rawdata.nv16:320x480@5\n"
++ " @14 stand for nv16 format, formats supported as follows\n"
++ " now only support 8 formats\n"
++ " 0 --> IMG_FORMAT_RGB565\n"
++ " 1 --> IMG_FORMAT_XRGB8888\n"
++ " 2 --> IMG_FORMAT_ARGB8888\n"
++ " 3 --> IMG_FORMAT_YUYV\n"
++ " 4 --> IMG_FORMAT_NV12\n"
++ " 5 --> IMG_FORMAT_NV16\n"
++ " 6 --> IMG_FORMAT_YUV420\n"
++ " 7 --> IMG_FORMAT_YVU420\n"
++ " -d Enable debug output\n"
++ " -overlay Enable overlay switch\n"
++ " -h This help text\n\n");
++
++ exit(error_code);
++}
++
++int
++main(int argc, char **argv)
++{
++ struct sigaction sigint;
++ struct display *display;
++ struct window window = { 0 };
++ int i, ret = 0;
++ struct file_arg *file;
++
++ init_window(&window);
++
++ for (i = 1; i < argc; i++) {
++ if (strcmp("-f", argv[i]) == 0)
++ window.fullscreen = 1;
++ else if (strcmp("-o", argv[i]) == 0)
++ window.opaque = 0;
++ else if (strcmp("-s", argv[i]) == 0)
++ window.buffer_size = 16;
++ else if (strcmp("-t", argv[i]) == 0)
++ window.transform = atoi(argv[++i]);
++ else if (strcmp("-F", argv[i]) == 0){
++ ret = parse_file(&window.image.fProp, argv[++i]);
++ if (ret < 0)
++ fprintf(stderr, "error: input error, like: -F "
++ "/usr/share/weston/rawdata.nv16:320x480@5\n");
++ }
++ else if (strcmp("-d", argv[i]) == 0)
++ debug = 1;
++ else if (strcmp("-overlay", argv[i]) == 0)
++ window.overlay = 1;
++ else if (strcmp("-h", argv[i]) == 0)
++ usage(EXIT_SUCCESS);
++ else
++ usage(EXIT_FAILURE);
++ }
++
++ file = &window.image.fProp;
++ if((file->width == 0) || (file->height ==0) || (file->filename == 0))
++ {
++ /*default sample*/
++ file->width = 320;
++ file->height = 480;
++ file->format = IMG_FORMAT_NV16;
++ snprintf(file->filename, MAX_LEN, "/usr/share/weston/rawdata.nv16");
++ fprintf(stderr, "debug: You have choose the default example!\n");
++ }
++
++ fprintf(stderr, "debug: The file is %s width/height/format[%d %d %d]\n",
++ file->filename, file->width, file->height, file->format);
++
++ window.geometry.width = file->width;
++ window.geometry.height = file->height;
++ window.window_size = window.geometry;
++
++ display = create_display(&window);
++ window.display = display;
++ //display->window = &window;
++
++ create_surface(&window);
++
++ ret = init_img_texture(&window);
++ if (ret < 0){
++ fprintf(stderr, "error: init_img_texture failed\n");
++ return -1;
++ }
++
++ window.drm_card_fd = _kms_device_fd();
++ if (window.drm_card_fd < 0) {
++ fprintf(stderr, "error: fail to get drm_card_fd !\n");
++ return -1;
++ }
++
++ sigint.sa_handler = signal_int;
++ sigemptyset(&sigint.sa_mask);
++ sigint.sa_flags = SA_RESETHAND;
++ sigaction(SIGINT, &sigint, NULL);
++
++ if (!window.wait_for_configure)
++ redraw(&window, NULL, 0);
++
++ while (running && ret != -1)
++ ret = wl_display_dispatch(display->display);
++
++ fprintf(stderr, "debug: simple-configure-mtk exiting\n");
++ destroy_surface(&window);
++ destroy_display(display);
++
++ return 0;
++}
++
++
+diff --git a/configure.ac b/configure.ac
+index 8b3e17e..e4bf195 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -411,6 +411,7 @@ if ! test "x$enable_simple_dmabuf_v4l_client" = "xno"; then
+ enable_simple_dmabuf_v4l_client="$have_simple_dmabuf_v4l_client"
+ fi
+ AM_CONDITIONAL(BUILD_SIMPLE_DMABUF_V4L_CLIENT, test "x$enable_simple_dmabuf_v4l_client" = "xyes")
++AM_CONDITIONAL(BUILD_SIMPLE_CONFIGURE_MTK_CLIENT, test "x$enable_simple_dmabuf_v4l_client" = "xyes")
+
+ AC_ARG_ENABLE(clients, [ --enable-clients],, enable_clients=yes)
+ AM_CONDITIONAL(BUILD_CLIENTS, test x$enable_clients = xyes)
+--
+1.9.1
+
diff --git a/meta/meta-mediatek/recipes-graphics/wayland/weston/0009-weston-add-surface-overlay-assignment-interface.patch b/meta/meta-mediatek/recipes-graphics/wayland/weston/0009-weston-add-surface-overlay-assignment-interface.patch
new file mode 100644
index 0000000..a1bfe8c
--- /dev/null
+++ b/meta/meta-mediatek/recipes-graphics/wayland/weston/0009-weston-add-surface-overlay-assignment-interface.patch
@@ -0,0 +1,417 @@
+From 5fdbcf3ea4b5f81b4aa7a03ff2bd130a6bb2a022 Mon Sep 17 00:00:00 2001
+From: Jia Rong <jia.rong@mediatek.com>
+Date: Thu, 3 May 2018 09:06:15 +0800
+Subject: [PATCH] weston: add surface overlay assignment interface
+
+add surface overlay assignment interface
+Test: OK
+
+Change-Id: I970797b6c3fe59567590639c2fe1e65784f296aa
+Signed-off-by: Jia Rong <jia.rong@mediatek.com>
+CR-Id: AUTO00016576
+---
+ Makefile.am | 6 +-
+ clients/simple-configure-mtk.c | 17 +++++
+ compositor/main.c | 6 ++
+ libweston/compositor-drm.c | 6 ++
+ libweston/compositor.h | 12 ++++
+ libweston/weston-configure-mtk.c | 126 ++++++++++++++++++++++++++++++++++++++
+ libweston/weston-configure-mtk.h | 54 ++++++++++++++++
+ protocol/weston-configure-mtk.xml | 30 +++++++++
+ 8 files changed, 256 insertions(+), 1 deletion(-)
+ create mode 100644 libweston/weston-configure-mtk.c
+ create mode 100644 libweston/weston-configure-mtk.h
+
+diff --git a/Makefile.am b/Makefile.am
+index 576b4a1..cf92198 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -108,6 +108,8 @@ libweston_@LIBWESTON_MAJOR@_la_SOURCES = \
+ libweston/pixel-formats.c \
+ libweston/pixel-formats.h \
+ libweston/weston-screenshooter-mtk.c \
++ libweston/weston-configure-mtk.c \
++ libweston/weston-configure-mtk.h \
+ shared/helpers.h \
+ shared/matrix.c \
+ shared/matrix.h \
+@@ -666,7 +668,9 @@ nodist_weston_simple_configure_mtk_SOURCES = \
+ protocol/fullscreen-shell-unstable-v1-protocol.c \
+ protocol/fullscreen-shell-unstable-v1-client-protocol.h \
+ protocol/linux-dmabuf-unstable-v1-protocol.c \
+- protocol/linux-dmabuf-unstable-v1-client-protocol.h
++ protocol/linux-dmabuf-unstable-v1-client-protocol.h \
++ protocol/weston-configure-mtk-protocol.c \
++ protocol/weston-configure-mtk-client-protocol.h
+ weston_simple_configure_mtk_CFLAGS = $(AM_CFLAGS) $(CLIENT_CFLAGS)
+ weston_simple_configure_mtk_LDADD = $(EGL_LIBS) $(LIBDRM_LIBS) libtoytoolkit.la
+ BUILT_SOURCES += protocol/linux-dmabuf-unstable-v1-client-protocol.h
+diff --git a/clients/simple-configure-mtk.c b/clients/simple-configure-mtk.c
+index f94497e..8b146ff 100644
+--- a/clients/simple-configure-mtk.c
++++ b/clients/simple-configure-mtk.c
+@@ -24,6 +24,7 @@
+ #include "xdg-shell-unstable-v6-client-protocol.h"
+ #include "linux-dmabuf-unstable-v1-client-protocol.h"
+ #include "fullscreen-shell-unstable-v1-client-protocol.h"
++#include "weston-configure-mtk-client-protocol.h"
+
+ #include <shared/platform.h>
+
+@@ -55,6 +56,7 @@ struct display {
+ struct wl_cursor *default_cursor;
+ struct wl_surface *cursor_surface;
+ struct window *window;
++ struct config_switch *config_switch;
+ };
+
+ struct geometry {
+@@ -92,6 +94,7 @@ struct window {
+ int fullscreen, opaque, buffer_size, overlay, format;
+ enum wl_output_transform transform;
+ int drm_card_fd;
++ struct config_switch_set *switch_set;
+ };
+
+ struct img_texture {
+@@ -591,6 +594,8 @@ create_surface(struct window *window)
+ display->cursor_surface =
+ wl_compositor_create_surface(display->compositor);
+
++ window->switch_set = config_switch_connect(display->config_switch, window->surface);
++
+ if (display->shell) {
+ window->xdg_surface =
+ zxdg_shell_v6_get_xdg_surface(display->shell,
+@@ -991,6 +996,10 @@ registry_handle_global(void *data, struct wl_registry *registry,
+ d->dmabuf = wl_registry_bind(registry, name,
+ &zwp_linux_dmabuf_v1_interface, 1);
+ zwp_linux_dmabuf_v1_add_listener(d->dmabuf, &dmabuf_listener, d);
++ } else if (strcmp(interface, "config_switch") == 0) {
++ d->config_switch =
++ wl_registry_bind(registry, name,
++ &config_switch_interface, 1);
+ }
+ }
+
+@@ -1208,6 +1217,14 @@ main(int argc, char **argv)
+ fprintf(stderr, "error: fail to get drm_card_fd !\n");
+ return -1;
+ }
++ /*
++ * setting sprite_switch = 0, indicate not walk overlay
++ * setting sprite_switch = 1, indicate walk overlay
++ */
++ if(window.overlay)
++ config_switch_set_sprite_switch(window.switch_set, 1);
++ else
++ config_switch_set_sprite_switch(window.switch_set, 0);
+
+ sigint.sa_handler = signal_int;
+ sigemptyset(&sigint.sa_mask);
+diff --git a/compositor/main.c b/compositor/main.c
+index 72c3cd1..5a8fd55 100644
+--- a/compositor/main.c
++++ b/compositor/main.c
+@@ -56,6 +56,7 @@
+ #include "git-version.h"
+ #include "version.h"
+ #include "weston.h"
++#include "../libweston/weston-configure-mtk.h"
+
+ #include "compositor-drm.h"
+ #include "compositor-headless.h"
+@@ -1879,6 +1880,11 @@ int main(int argc, char *argv[])
+
+ weston_pending_output_coldplug(ec);
+
++ if (config_switch_global_create(ec) < 0) {
++ weston_log("fatal: failed to config_switch_global_create\n");
++ goto out;
++ }
++
+ catch_signals();
+ segv_compositor = ec;
+
+diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c
+index 064d8c2..b5b103b 100644
+--- a/libweston/compositor-drm.c
++++ b/libweston/compositor-drm.c
+@@ -2753,6 +2753,12 @@ drm_output_prepare_overlay_view(struct drm_output_state *output_state,
+ uint32_t format;
+ wl_fixed_t sx1, sy1, sx2, sy2;
+
++ /*
++ * if switch controlled by client is off, then return.
++ */
++ if ((!ev->surface->config_switch)||(!ev->surface->config_switch->sprites_switch))
++ return NULL;
++
+ if (b->sprites_are_broken)
+ return NULL;
+
+diff --git a/libweston/compositor.h b/libweston/compositor.h
+index dea88dc..6470173 100644
+--- a/libweston/compositor.h
++++ b/libweston/compositor.h
+@@ -1141,6 +1141,16 @@ struct weston_surface_state {
+ struct weston_buffer_viewport buffer_viewport;
+ };
+
++/*
++ * For setting whether the views on this surface walk
++ * overlay path; on==>1, off==>0
++*/
++struct config_switch{
++ struct wl_resource *resource;
++ void *private;
++ int sprites_switch;
++};
++
+ struct weston_surface_activation_data {
+ struct weston_surface *surface;
+ struct weston_seat *seat;
+@@ -1262,6 +1272,8 @@ struct weston_surface {
+
+ /* An list of per seat pointer constraints. */
+ struct wl_list pointer_constraints;
++
++ struct config_switch *config_switch;
+ };
+
+ struct weston_subsurface {
+diff --git a/libweston/weston-configure-mtk.c b/libweston/weston-configure-mtk.c
+new file mode 100644
+index 0000000..185f91c
+--- /dev/null
++++ b/libweston/weston-configure-mtk.c
+@@ -0,0 +1,126 @@
++#include "config.h"
++#include <fcntl.h>
++#include <stdio.h>
++#include <string.h>
++#include <stdlib.h>
++#include <stdint.h>
++#include <limits.h>
++#include <stdarg.h>
++#include <assert.h>
++#include <sys/ioctl.h>
++#include <sys/mman.h>
++#include <sys/wait.h>
++#include <sys/socket.h>
++#include <sys/utsname.h>
++#include <sys/stat.h>
++#include <unistd.h>
++#include <math.h>
++#include <linux/input.h>
++#include <dlfcn.h>
++#include <signal.h>
++#include <setjmp.h>
++#include <sys/time.h>
++#include <time.h>
++#include <errno.h>
++
++#include "timeline.h"
++
++#include "compositor.h"
++//#include "scaler-server-protocol.h"
++#include "shared/helpers.h"
++#include "shared/os-compatibility.h"
++#include "shared/timespec-util.h"
++#include "git-version.h"
++#include "version.h"
++
++#include "weston-configure-mtk.h"
++#include "weston-configure-mtk-server-protocol.h"
++
++static void
++config_set_sprite_switch(struct wl_client *client,
++ struct wl_resource *resource,
++ int32_t spr_switch)
++{
++ struct config_switch *configure = wl_resource_get_user_data(resource);
++
++ configure->sprites_switch = spr_switch;
++}
++
++static const struct config_switch_set_interface switch_set_interface = {
++ config_set_sprite_switch,
++};
++
++static struct config_switch *
++config_interface_create(struct weston_surface *surface)
++{
++ struct config_switch *config_switch;
++
++ config_switch = zalloc(sizeof *config_switch);
++ if (config_switch == NULL)
++ return NULL;
++
++ config_switch->private = (void *)surface;
++ surface->config_switch = config_switch;
++
++ return config_switch;
++}
++
++static void
++config_switch_connect(struct wl_client *client, struct wl_resource *resource,
++ struct wl_resource *wl_surface, uint32_t id)
++{
++ struct config_switch *config_switch = wl_resource_get_user_data(resource);
++ struct weston_surface *surface = wl_resource_get_user_data(wl_surface);
++
++ config_switch = config_interface_create(surface);
++ if (config_switch == NULL) {
++ wl_resource_post_no_memory(resource);
++ return;
++ }
++
++ config_switch->resource =
++ wl_resource_create(client, &config_switch_set_interface,
++ wl_resource_get_version(resource), id);
++ if (config_switch->resource == NULL) {
++ wl_resource_post_no_memory(resource);
++ return;
++ }
++ wl_resource_set_implementation(config_switch->resource, &switch_set_interface,
++ config_switch, NULL);
++}
++
++static const struct config_switch_interface switch_interface = {
++ config_switch_connect,
++};
++
++static void
++bind_config_switch(struct wl_client *client,
++ void *data, uint32_t version, uint32_t id)
++{
++ struct weston_compositor *compositor = data;
++ struct wl_resource *resource;
++
++ resource = wl_resource_create(client, &config_switch_interface,
++ MIN(version, 1), id);
++ if (resource == NULL) {
++ wl_client_post_no_memory(client);
++ return;
++ }
++
++ wl_resource_set_implementation(resource, &switch_interface,
++ compositor, NULL);
++}
++
++WL_EXPORT int
++config_switch_global_create(struct weston_compositor *ec)
++{
++ if(!ec)
++ return -1;
++ if (!wl_global_create(ec->wl_display, &config_switch_interface, 1,
++ ec, bind_config_switch)){
++ fprintf(stderr, "error: failed to config_switch_global_create: %s\n", dlerror());
++ return -1;
++ }
++ return 0;
++}
++
+diff --git a/libweston/weston-configure-mtk.h b/libweston/weston-configure-mtk.h
+new file mode 100644
+index 0000000..0f093fe
+--- /dev/null
++++ b/libweston/weston-configure-mtk.h
+@@ -0,0 +1,54 @@
++/*
++ * Copyright © 2008-2011 Kristian Høgsberg
++ * Copyright © 2012 Collabora, Ltd.
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#ifndef _APP_CONFIGURE_EXTENSION_H_
++#define _APP_CONFIGURE_EXTENSION_H_
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++#include <stdbool.h>
++#include <time.h>
++#include <pixman.h>
++#include <xkbcommon/xkbcommon.h>
++
++#include <wayland-server.h>
++
++#include "version.h"
++#include "matrix.h"
++#include "config-parser.h"
++#include "zalloc.h"
++#include "timeline-object.h"
++
++int config_switch_global_create(struct weston_compositor *ec);
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif
++
+diff --git a/protocol/weston-configure-mtk.xml b/protocol/weston-configure-mtk.xml
+index e19a2ad..120e904 100644
+--- a/protocol/weston-configure-mtk.xml
++++ b/protocol/weston-configure-mtk.xml
+@@ -33,5 +33,35 @@
+ </event>
+ </interface>
+
++ <interface name="config_switch_set" version="1">
++ <description summary="app interface for setting configure for the surface"/>
++
++ <request name="sprite_switch">
++ <description summary="setting the surface configure">
++ This set view matched with the surface to show in overlay plane if
++ overlay planes are available.Otherwise, it walk primary plane to
++ render, and then send to drm to show.
++ </description>
++ <arg name="sprite_switch" type="int"/>
++ </request>
++ </interface>
++
++ <interface name="config_switch" version="1">
++ <description summary="create app configure path for setting parameter">
++ This interface is exposed as a global singleton.
++ This interface is implemented by server, it mainly provide channel to allow
++ client to control some properties.
++ </description>
++
++ <request name="connect">
++ <description summary="connect to server for setting parameter">
++ This request gives client way to connect server.In fact, parameters set by
++ app all through wl_surface because this is only way can be transmit by app.
++ </description>
++ <arg name="surface" type="object" interface="wl_surface" allow-null="true"/>
++ <arg name="id" type="new_id" interface="config_switch_set"/>
++ </request>
++ </interface>
++
+ </protocol>
+
+--
+1.9.1
+
diff --git a/meta/meta-mediatek/recipes-graphics/wayland/weston/0010-add-writeback-connector-CAP.patch b/meta/meta-mediatek/recipes-graphics/wayland/weston/0010-add-writeback-connector-CAP.patch
new file mode 100644
index 0000000..ac9c8f4
--- /dev/null
+++ b/meta/meta-mediatek/recipes-graphics/wayland/weston/0010-add-writeback-connector-CAP.patch
@@ -0,0 +1,49 @@
+From a4fb658b7d34df3c28a2066b238d8009640e50a7 Mon Sep 17 00:00:00 2001
+From: Ye Huang <ye.huang@mediatek.com>
+Date: Sun, 1 Sep 2019 23:03:44 +0800
+Subject: [PATCH] add-writeback-connector-CAP
+
+---
+ libweston/compositor-drm.c | 12 ++++++++++++
+ 1 file changed, 12 insertions(+)
+
+diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c
+index fcc3307..cad2478 100644
+--- a/libweston/compositor-drm.c
++++ b/libweston/compositor-drm.c
+@@ -76,6 +76,10 @@
+ #define DRM_CLIENT_CAP_UNIVERSAL_PLANES 2
+ #endif
+
++#ifndef DRM_CLIENT_CAP_WRITEBACK_CONNECTORS
++#define DRM_CLIENT_CAP_WRITEBACK_CONNECTORS 5
++#endif
++
+ #ifndef DRM_CAP_CURSOR_WIDTH
+ #define DRM_CAP_CURSOR_WIDTH 0x8
+ #endif
+@@ -266,6 +270,7 @@ struct drm_backend {
+
+ bool universal_planes;
+ bool atomic_modeset;
++ bool wb_connector;
+
+ int use_pixman;
+
+@@ -3577,6 +3582,13 @@ init_kms_caps(struct drm_backend *b)
+ weston_log("DRM: %s atomic modesetting\n",
+ b->atomic_modeset ? "supports" : "does not support");
+
++ if (!getenv("DRM_CLIENT_CAP_WRITEBACK_CONNECTORS")) {
++ ret = drmSetClientCap(b->drm.fd, DRM_CLIENT_CAP_WRITEBACK_CONNECTORS, 1);
++ b->wb_connector = (ret == 0);
++ }
++ weston_log("DRM: %s writeback connectors\n",
++ b->wb_connector ? "supports" : "does not support");
++
+ return 0;
+ }
+
+--
+2.23.0
+
diff --git a/meta/meta-mediatek/recipes-graphics/wayland/weston/rawdata.argb b/meta/meta-mediatek/recipes-graphics/wayland/weston/rawdata.argb
new file mode 100644
index 0000000..a55fa0e
--- /dev/null
+++ b/meta/meta-mediatek/recipes-graphics/wayland/weston/rawdata.argb
Binary files differ
diff --git a/meta/meta-mediatek/recipes-graphics/wayland/weston/rawdata.nv12 b/meta/meta-mediatek/recipes-graphics/wayland/weston/rawdata.nv12
new file mode 100644
index 0000000..cc9fb1f
--- /dev/null
+++ b/meta/meta-mediatek/recipes-graphics/wayland/weston/rawdata.nv12
Binary files differ
diff --git a/meta/meta-mediatek/recipes-graphics/wayland/weston/rawdata.nv16 b/meta/meta-mediatek/recipes-graphics/wayland/weston/rawdata.nv16
new file mode 100644
index 0000000..3261abd
--- /dev/null
+++ b/meta/meta-mediatek/recipes-graphics/wayland/weston/rawdata.nv16
Binary files differ
diff --git a/meta/meta-mediatek/recipes-graphics/wayland/weston/rawdata.rgb565 b/meta/meta-mediatek/recipes-graphics/wayland/weston/rawdata.rgb565
new file mode 100644
index 0000000..21006dc
--- /dev/null
+++ b/meta/meta-mediatek/recipes-graphics/wayland/weston/rawdata.rgb565
Binary files differ
diff --git a/meta/meta-mediatek/recipes-graphics/wayland/weston/rawdata.xrgb b/meta/meta-mediatek/recipes-graphics/wayland/weston/rawdata.xrgb
new file mode 100644
index 0000000..a55fa0e
--- /dev/null
+++ b/meta/meta-mediatek/recipes-graphics/wayland/weston/rawdata.xrgb
Binary files differ
diff --git a/meta/meta-mediatek/recipes-graphics/wayland/weston/rawdata.yu12 b/meta/meta-mediatek/recipes-graphics/wayland/weston/rawdata.yu12
new file mode 100644
index 0000000..bab225d
--- /dev/null
+++ b/meta/meta-mediatek/recipes-graphics/wayland/weston/rawdata.yu12
Binary files differ
diff --git a/meta/meta-mediatek/recipes-graphics/wayland/weston/rawdata.yuyv b/meta/meta-mediatek/recipes-graphics/wayland/weston/rawdata.yuyv
new file mode 100644
index 0000000..207ec59
--- /dev/null
+++ b/meta/meta-mediatek/recipes-graphics/wayland/weston/rawdata.yuyv
Binary files differ
diff --git a/meta/meta-mediatek/recipes-graphics/wayland/weston/rawdata.yv12 b/meta/meta-mediatek/recipes-graphics/wayland/weston/rawdata.yv12
new file mode 100644
index 0000000..7a21d02
--- /dev/null
+++ b/meta/meta-mediatek/recipes-graphics/wayland/weston/rawdata.yv12
Binary files differ
diff --git a/meta/meta-mediatek/recipes-graphics/wayland/weston/rawdatatest.argb b/meta/meta-mediatek/recipes-graphics/wayland/weston/rawdatatest.argb
new file mode 100644
index 0000000..515fb66
--- /dev/null
+++ b/meta/meta-mediatek/recipes-graphics/wayland/weston/rawdatatest.argb
Binary files differ
diff --git a/meta/meta-mediatek/recipes-graphics/wayland/weston/weston.service b/meta/meta-mediatek/recipes-graphics/wayland/weston/weston.service
new file mode 100644
index 0000000..3c9f4a8
--- /dev/null
+++ b/meta/meta-mediatek/recipes-graphics/wayland/weston/weston.service
@@ -0,0 +1,11 @@
+[Unit]
+Description=Weston reference Wayland compositor
+After=dbus.service rc.pvr.service
+
+[Service]
+ExecStart=/usr/bin/weston-launch -u root -- --idle-time=4294967 --tty=1
+ExecStop=/usr/bin/killall -s KILL weston
+Type=simple
+
+[Install]
+WantedBy=multi-user.target
diff --git a/meta/meta-mediatek/recipes-graphics/wayland/weston/weston.sh b/meta/meta-mediatek/recipes-graphics/wayland/weston/weston.sh
new file mode 100644
index 0000000..225a034
--- /dev/null
+++ b/meta/meta-mediatek/recipes-graphics/wayland/weston/weston.sh
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+if test -z "$XDG_RUNTIME_DIR"; then
+ export XDG_RUNTIME_DIR=/run/user/$UID
+ mkdir --parents $XDG_RUNTIME_DIR
+ chmod 0700 $XDG_RUNTIME_DIR
+fi
diff --git a/meta/meta-mediatek/recipes-graphics/wayland/weston_5.0.0.bbappend b/meta/meta-mediatek/recipes-graphics/wayland/weston_5.0.0.bbappend
new file mode 100644
index 0000000..5253869
--- /dev/null
+++ b/meta/meta-mediatek/recipes-graphics/wayland/weston_5.0.0.bbappend
@@ -0,0 +1,45 @@
+FILESEXTRAPATHS_append := ":${THISDIR}/${PN}"
+
+SRC_URI_append = " \
+ file://0001-PATCH-1-9-hmi-controller-use-output_w-h-instead-of-c.patch \
+ file://0003-PATCH-3-9-compose-engine-turn-to-pixman-if-gl-init-f.patch \
+ file://0004-PATCH-4-9-weston-do-not-check-master-fd-for-DRM-driv.patch \
+ file://0005-PATCH-5-9-weston-install-client-protocol-to-sysroot-.patch \
+ file://0006-PATCH-7-9-weston-screen-shot-add-screen-shot.patch \
+ file://0007-PATCH-weston-add-mtk-test-client.patch \
+ file://0008-PATCH-weston-add-surface-overlay-assignment-interfac.patch \
+ file://0001-add-switch_config.patch \
+ file://rawdata.argb \
+ file://rawdata.nv12 \
+ file://rawdata.nv16 \
+ file://rawdata.rgb565 \
+ file://rawdata.xrgb \
+ file://rawdata.yu12 \
+ file://rawdata.yuyv \
+ file://rawdata.yv12 \
+ file://rawdatatest.argb \
+"
+
+DEPENDS += "libdrm"
+FILES_${PN} += "${bindir}/* ${libdir}/weston/* ${sysconfdir}/xdg"
+FILES_${PN}-dbg += "${libdir}/weston/.debug/*"
+
+do_compile() {
+ oe_runmake \
+ CFLAGS+="-I${STAGING_INCDIR}/libdrm"
+}
+do_install_append() {
+ install -d ${D}/usr/share/weston/
+ cp ${WORKDIR}/rawdata* ${D}/usr/share/weston/
+
+ WESTON_INI_CONFIG=${sysconfdir}/xdg/weston
+ install -d ${D}${WESTON_INI_CONFIG}
+ echo "" >> ${D}${WESTON_INI_CONFIG}/weston.ini
+ echo "[output]" >> ${D}${WESTON_INI_CONFIG}/weston.ini
+ echo "name=DSI-1" >> ${D}${WESTON_INI_CONFIG}/weston.ini
+ if test "${DISPLAY_ORIENTATION}" != "";then
+ echo "transform=${DISPLAY_ORIENTATION}" >> ${D}${WESTON_INI_CONFIG}/weston.ini
+ else
+ echo "transform=90" >> ${D}${WESTON_INI_CONFIG}/weston.ini
+ fi
+}
diff --git a/meta/meta-mediatek/recipes-multimedia/asrc-demo/asrc-demo.bb b/meta/meta-mediatek/recipes-multimedia/asrc-demo/asrc-demo.bb
new file mode 100644
index 0000000..f475a34
--- /dev/null
+++ b/meta/meta-mediatek/recipes-multimedia/asrc-demo/asrc-demo.bb
@@ -0,0 +1,17 @@
+inherit workonsrc
+DESCRIPTION = "Audio ASRC test library"
+LICENSE = "MediaTekProprietary"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=34b54c501d1002b2bcab1478dd6b83e1"
+WORKONSRC = "${TOPDIR}/../src/apps/aud-base/progs/asrc_demo"
+TARGET_CC_ARCH += "${LDFLAGS}"
+
+inherit pkgconfig
+do_compile () {
+ oe_runmake \
+ CFLAGS="`pkg-config --cflags` ${CFLAGS} -pthread -lrt" \
+ LDFLAGS="`pkg-config --libs `-lm ${LDFLAGS}"
+}
+do_install () {
+ oe_runmake \
+ PREFIX="${prefix}" DESTDIR="${D}" install
+}
diff --git a/meta/meta-mediatek/recipes-multimedia/camera-calibration/camera-calibration.bb b/meta/meta-mediatek/recipes-multimedia/camera-calibration/camera-calibration.bb
new file mode 100755
index 0000000..cf9cbc3
--- /dev/null
+++ b/meta/meta-mediatek/recipes-multimedia/camera-calibration/camera-calibration.bb
@@ -0,0 +1,35 @@
+DESCRIPTION = "Camera fisheye calibration tool"
+LICENSE = "MediaTekProprietary"
+
+DEPENDS += " opencv rpm-native"
+RDEPENDS_${PN} += " opencv"
+
+inherit workonsrc
+#inherit pkgconfig cmake
+
+SRC_BUILD = "${TOPDIR}/../src/multimedia/camera-calibration/camera_calibration_iab"
+WORKONSRC = "${SRC_BUILD}"
+SRC_URI = "file://in_VID5.xml \
+ file://VID5.xml \
+ "
+
+inherit ${@'pkgconfig' if os.path.exists("${SRC_BUILD}") else ''}
+inherit ${@'cmake' if os.path.exists("${SRC_BUILD}") else ''}
+
+do_install () {
+ if [ -e '${SRC_BUILD}' ]; then
+ install -d ${D}${bindir}
+ install -m 0755 ./fisheye ${D}${bindir}
+
+ else
+ oe_runmake PREFIX="${prefix}" DESTDIR="${D}" install
+ fi
+
+ install -d ${D}${datadir}/fisheye/training_data
+ install -m 644 ${WORKDIR}/in_VID5.xml ${D}${datadir}/fisheye/training_data
+ install -m 644 ${WORKDIR}/VID5.xml ${D}${datadir}/fisheye/training_data
+}
+
+INSANE_SKIP_${PN} += "already-stripped"
+FILES_${PN} += "${datadir}/fisheye/training_data/VID5.xml \
+ ${datadir}/fisheye/training_data/in_VID5.xml"
diff --git a/meta/meta-mediatek/recipes-multimedia/camera-calibration/camera-calibration/VID5.xml b/meta/meta-mediatek/recipes-multimedia/camera-calibration/camera-calibration/VID5.xml
new file mode 100755
index 0000000..f51b2a5
--- /dev/null
+++ b/meta/meta-mediatek/recipes-multimedia/camera-calibration/camera-calibration/VID5.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0"?>
+<opencv_storage>
+<images>
+/usr/share/fisheye/training_data/side_view_1.png
+/usr/share/fisheye/training_data/side_view_2.png
+/usr/share/fisheye/training_data/side_view_3.png
+/usr/share/fisheye/training_data/side_view_4.png
+/usr/share/fisheye/training_data/side_view_5.png
+/usr/share/fisheye/training_data/side_view_6.png
+/usr/share/fisheye/training_data/side_view_7.png
+/usr/share/fisheye/training_data/side_view_8.png
+/usr/share/fisheye/training_data/side_view_9.png
+/usr/share/fisheye/training_data/side_view_10.png
+/usr/share/fisheye/training_data/side_view_11.png
+/usr/share/fisheye/training_data/side_view_12.png
+/usr/share/fisheye/training_data/side_view_13.png
+/usr/share/fisheye/training_data/side_view_14.png
+/usr/share/fisheye/training_data/side_view_15.png
+/usr/share/fisheye/training_data/side_view_16.png
+/usr/share/fisheye/training_data/side_view_17.png
+/usr/share/fisheye/training_data/side_view_18.png
+/usr/share/fisheye/training_data/side_view_19.png
+/usr/share/fisheye/training_data/side_view_20.png
+</images>
+</opencv_storage>
\ No newline at end of file
diff --git a/meta/meta-mediatek/recipes-multimedia/camera-calibration/camera-calibration/in_VID5.xml b/meta/meta-mediatek/recipes-multimedia/camera-calibration/camera-calibration/in_VID5.xml
new file mode 100755
index 0000000..08770c8
--- /dev/null
+++ b/meta/meta-mediatek/recipes-multimedia/camera-calibration/camera-calibration/in_VID5.xml
@@ -0,0 +1,63 @@
+<?xml version="1.0"?>
+<opencv_storage>
+<Settings>
+ <!-- Number of inner corners per a item row and column. (square, circle) -->
+ <BoardSize_Width>9</BoardSize_Width>
+ <BoardSize_Height>6</BoardSize_Height>
+
+ <!-- The size of a square in some user defined metric system (pixel, millimeter)-->
+ <Square_Size>50</Square_Size>
+
+ <!-- The type of input used for camera calibration. One of: CHESSBOARD CIRCLES_GRID ASYMMETRIC_CIRCLES_GRID -->
+ <Calibrate_Pattern>"CHESSBOARD"</Calibrate_Pattern>
+
+ <!-- The input to use for calibration.
+ To use an input camera -> give the ID of the camera, like "1"
+ To use an input video -> give the path of the input video, like "/tmp/x.avi"
+ To use an image list -> give the path to the XML or YAML file containing the list of the images, like "/tmp/circles_list.xml"
+ -->
+ <Input>"/usr/share/fisheye/training_data/VID5.xml"</Input>
+ <!-- If true (non-zero) we flip the input images around the horizontal axis.-->
+ <Input_FlipAroundHorizontalAxis>0</Input_FlipAroundHorizontalAxis>
+
+ <!-- Time delay between frames in case of camera. -->
+ <Input_Delay>100</Input_Delay>
+
+ <!-- Output WarpMap path for distort/undistort map x and map y. -->
+ <Distort_MapX>"/data/distort_in_map_x"</Distort_MapX>
+ <Distort_MapY>"/data/distort_in_map_y"</Distort_MapY>
+ <Undistort_MapX>"/data/undistort_in_map_x"</Undistort_MapX>
+ <Undistort_MapY>"/data/undistort_in_map_y"</Undistort_MapY>
+
+ <!-- How many frames to use, for calibration. -->
+ <Calibrate_NrOfFrameToUse>20</Calibrate_NrOfFrameToUse>
+ <!-- Consider only fy as a free parameter, the ratio fx/fy stays the same as in the input cameraMatrix.
+ Use or not setting. 0 - False Non-Zero - True-->
+ <Calibrate_FixAspectRatio> 1 </Calibrate_FixAspectRatio>
+ <!-- If true (non-zero) tangential distortion coefficients are set to zeros and stay zero.-->
+ <Calibrate_AssumeZeroTangentialDistortion>1</Calibrate_AssumeZeroTangentialDistortion>
+ <!-- If true (non-zero) the principal point is not changed during the global optimization.-->
+ <Calibrate_FixPrincipalPointAtTheCenter> 1 </Calibrate_FixPrincipalPointAtTheCenter>
+
+ <!-- The name of the output log file. -->
+ <Write_outputFileName>"/tmp/out_camera_data.xml"</Write_outputFileName>
+ <!-- If true (non-zero) we write to the output file the feature points.-->
+ <Write_DetectedFeaturePoints>1</Write_DetectedFeaturePoints>
+ <!-- If true (non-zero) we write to the output file the extrinsic camera parameters.-->
+ <Write_extrinsicParameters>1</Write_extrinsicParameters>
+ <!-- If true (non-zero) we show after calibration the undistorted images.-->
+ <Show_UndistortedImage>0</Show_UndistortedImage>
+ <!-- If true (non-zero) will be used fisheye camera model.-->
+ <Calibrate_UseFisheyeModel>1</Calibrate_UseFisheyeModel>
+ <!-- If true (non-zero) distortion coefficient k1 will be equals to zero.-->
+ <Fix_K1>0</Fix_K1>
+ <!-- If true (non-zero) distortion coefficient k2 will be equals to zero.-->
+ <Fix_K2>0</Fix_K2>
+ <!-- If true (non-zero) distortion coefficient k3 will be equals to zero.-->
+ <Fix_K3>0</Fix_K3>
+ <!-- If true (non-zero) distortion coefficient k4 will be equals to zero.-->
+ <Fix_K4>1</Fix_K4>
+ <!-- If true (non-zero) distortion coefficient k5 will be equals to zero.-->
+ <Fix_K5>1</Fix_K5>
+</Settings>
+</opencv_storage>
diff --git a/meta/meta-mediatek/recipes-multimedia/images/mtk-multimedia-image-minimal.bb b/meta/meta-mediatek/recipes-multimedia/images/mtk-multimedia-image-minimal.bb
new file mode 100644
index 0000000..e863f77
--- /dev/null
+++ b/meta/meta-mediatek/recipes-multimedia/images/mtk-multimedia-image-minimal.bb
@@ -0,0 +1,42 @@
+require ../poky/meta/recipes-graphics/images/core-image-weston.bb
+
+IMAGE_LINGUAS = " "
+
+LICENSE = "MIT"
+
+inherit add-pulseaudio-service
+inherit mkstateimage
+inherit slimko
+inherit create-link
+inherit create-nfsb
+inherit create-sparse-image
+
+CORE_IMAGE_EXTRA_INSTALL += " \
+ packagegroup-mtk-gstreamer1.0 \
+ packagegroup-gstreamer1.0-full \
+ packagegroup-mtk-upgrade-kit \
+"
+
+IMAGE_INSTALL_append = " \
+ energy-aware \
+ evtest \
+ fb-test \
+ i2c-tools \
+ libmtp \
+ mali \
+ mtk-alsa-ucm \
+ mtd-utils \
+ udev-extraconf \
+ usbutils \
+ util-linux \
+ vpud \
+ mdpd \
+ mtk-ovl-adapter \
+ ${@bb.utils.contains('TEE_SUPPORT', 'mtee', 'tzapp', '' ,d)} \
+ boot-assist \
+ alsa-utils \
+ pulseaudio-server \
+ pulseaudio-misc \
+"
+
+CORE_IMAGE_BASE_INSTALL_remove = "weston-ini-conf weston-examples gtk+3-demo clutter-1.0-examples"
diff --git a/meta/meta-mediatek/recipes-multimedia/libae/libae.bb b/meta/meta-mediatek/recipes-multimedia/libae/libae.bb
new file mode 100755
index 0000000..067def4
--- /dev/null
+++ b/meta/meta-mediatek/recipes-multimedia/libae/libae.bb
@@ -0,0 +1,24 @@
+inherit workonsrc
+DESCRIPTION = "libae"
+LICENSE = "MediaTekProprietary"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=e1696b147d49d491bcb4da1a57173fff"
+#DEPENDS = ""
+WORKONSRC = "${TOPDIR}/../src/multimedia/libcamera_3a/libae/mt8183"
+PN='libae'
+
+inherit pkgconfig
+
+do_compile () {
+ oe_runmake \
+ CFLAGS="${CFLAGS}" \
+ LDFLAGS="${LDFLAGS}"
+}
+
+do_install() {
+ oe_runmake \
+ PREFIX="${prefix}" DESTDIR="${D}" install
+}
+
+# move libs in -dev to normal rpm
+FILES_SOLIBSDEV = ""
+FILES_${PN} = "${libdir}/*.so ${bindir}"
diff --git a/meta/meta-mediatek/recipes-multimedia/libae_core/libaecore.bb b/meta/meta-mediatek/recipes-multimedia/libae_core/libaecore.bb
new file mode 100755
index 0000000..cb4f7ba
--- /dev/null
+++ b/meta/meta-mediatek/recipes-multimedia/libae_core/libaecore.bb
@@ -0,0 +1,24 @@
+inherit workonsrc
+DESCRIPTION = "libae_core"
+LICENSE = "MediaTekProprietary"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=e1696b147d49d491bcb4da1a57173fff"
+#DEPENDS = ""
+WORKONSRC = "${TOPDIR}/../src/multimedia/libcamera_3a/libae_core/mt8183"
+PN='libae_core'
+
+inherit pkgconfig
+
+do_compile () {
+ oe_runmake \
+ CFLAGS="${CFLAGS}" \
+ LDFLAGS="${LDFLAGS}"
+}
+
+do_install() {
+ oe_runmake \
+ PREFIX="${prefix}" DESTDIR="${D}" install
+}
+
+# move libs in -dev to normal rpm
+FILES_SOLIBSDEV = ""
+FILES_${PN} = "${libdir}/*.so ${bindir}"
diff --git a/meta/meta-mediatek/recipes-multimedia/libaf/libaf.bb b/meta/meta-mediatek/recipes-multimedia/libaf/libaf.bb
new file mode 100755
index 0000000..9602ff5
--- /dev/null
+++ b/meta/meta-mediatek/recipes-multimedia/libaf/libaf.bb
@@ -0,0 +1,24 @@
+inherit workonsrc
+DESCRIPTION = "libaf"
+LICENSE = "MediaTekProprietary"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=e1696b147d49d491bcb4da1a57173fff"
+#DEPENDS = ""
+WORKONSRC = "${TOPDIR}/../src/multimedia/libcamera_3a/libaf/mt8183"
+PN='libaf'
+
+inherit pkgconfig
+
+do_compile () {
+ oe_runmake \
+ CFLAGS="${CFLAGS}" \
+ LDFLAGS="${LDFLAGS}"
+}
+
+do_install() {
+ oe_runmake \
+ PREFIX="${prefix}" DESTDIR="${D}" install
+}
+
+# move libs in -dev to normal rpm
+FILES_SOLIBSDEV = ""
+FILES_${PN} = "${libdir}/*.so ${bindir}"
diff --git a/meta/meta-mediatek/recipes-multimedia/libaf_core/libafcore.bb b/meta/meta-mediatek/recipes-multimedia/libaf_core/libafcore.bb
new file mode 100755
index 0000000..b731c24
--- /dev/null
+++ b/meta/meta-mediatek/recipes-multimedia/libaf_core/libafcore.bb
@@ -0,0 +1,24 @@
+inherit workonsrc
+DESCRIPTION = "libaf_core"
+LICENSE = "MediaTekProprietary"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=e1696b147d49d491bcb4da1a57173fff"
+#DEPENDS = ""
+WORKONSRC = "${TOPDIR}/../src/multimedia/libcamera_3a/libaf_core/mt8183"
+PN='libaf_core'
+
+inherit pkgconfig
+
+do_compile () {
+ oe_runmake \
+ CFLAGS="${CFLAGS}" \
+ LDFLAGS="${LDFLAGS}"
+}
+
+do_install() {
+ oe_runmake \
+ PREFIX="${prefix}" DESTDIR="${D}" install
+}
+
+# move libs in -dev to normal rpm
+FILES_SOLIBSDEV = ""
+FILES_${PN} = "${libdir}/*.so ${bindir}"
diff --git a/meta/meta-mediatek/recipes-multimedia/libawb/libawb.bb b/meta/meta-mediatek/recipes-multimedia/libawb/libawb.bb
new file mode 100755
index 0000000..2bb55b5
--- /dev/null
+++ b/meta/meta-mediatek/recipes-multimedia/libawb/libawb.bb
@@ -0,0 +1,24 @@
+inherit workonsrc
+DESCRIPTION = "libawb"
+LICENSE = "MediaTekProprietary"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=e1696b147d49d491bcb4da1a57173fff"
+#DEPENDS = ""
+WORKONSRC = "${TOPDIR}/../src/multimedia/libcamera_3a/libawb/mt8183"
+PN='libawb'
+
+inherit pkgconfig
+
+do_compile () {
+ oe_runmake \
+ CFLAGS="${CFLAGS}" \
+ LDFLAGS="${LDFLAGS}"
+}
+
+do_install() {
+ oe_runmake \
+ PREFIX="${prefix}" DESTDIR="${D}" install
+}
+
+# move libs in -dev to normal rpm
+FILES_SOLIBSDEV = ""
+FILES_${PN} = "${libdir}/*.so ${bindir}"
diff --git a/meta/meta-mediatek/recipes-multimedia/libawb_core/libawbcore.bb b/meta/meta-mediatek/recipes-multimedia/libawb_core/libawbcore.bb
new file mode 100755
index 0000000..7ef58cf
--- /dev/null
+++ b/meta/meta-mediatek/recipes-multimedia/libawb_core/libawbcore.bb
@@ -0,0 +1,24 @@
+inherit workonsrc
+DESCRIPTION = "libawb_core"
+LICENSE = "MediaTekProprietary"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=e1696b147d49d491bcb4da1a57173fff"
+#DEPENDS = ""
+WORKONSRC = "${TOPDIR}/../src/multimedia/libcamera_3a/libawb_core/mt8183"
+PN='libawb_core'
+
+inherit pkgconfig
+
+do_compile () {
+ oe_runmake \
+ CFLAGS="${CFLAGS}" \
+ LDFLAGS="${LDFLAGS}"
+}
+
+do_install() {
+ oe_runmake \
+ PREFIX="${prefix}" DESTDIR="${D}" install
+}
+
+# move libs in -dev to normal rpm
+FILES_SOLIBSDEV = ""
+FILES_${PN} = "${libdir}/*.so ${bindir}"
diff --git a/meta/meta-mediatek/recipes-multimedia/libdivx/libdivx.bb b/meta/meta-mediatek/recipes-multimedia/libdivx/libdivx.bb
new file mode 100644
index 0000000..4afdeb1
--- /dev/null
+++ b/meta/meta-mediatek/recipes-multimedia/libdivx/libdivx.bb
@@ -0,0 +1,34 @@
+DESCRIPTION = "divx library"
+LICENSE = "MediaTekProprietary"
+LIC_FILES_CHKSUM = "file://NOTICE;md5=e1696b147d49d491bcb4da1a57173fff"
+SECTION = "libs"
+
+inherit workonsrc
+WORKONSRC = "${TOPDIR}/../src/multimedia/divx"
+
+RDEPENDS_${PN} = "libgcc"
+RDEPENDS_${PN} += "libstdc++"
+
+inherit pkgconfig
+
+do_configure() {
+ :
+}
+
+do_compile() {
+ oe_runmake \
+ PACKAGE_ARCH="${PACKAGE_ARCH}" \
+ CFLAGS="`pkg-config` ${CFLAGS}" \
+ LDFLAGS="`pkg-config` ${LDFLAGS}"
+}
+
+do_install() {
+ oe_runmake \
+ PREFIX="${prefix}" DESTDIR="${D}" PACKAGE_ARCH="${PACKAGE_ARCH}" install
+}
+
+INSANE_SKIP_${PN} += "already-stripped"
+FILES_${PN}-dev = "dev-elf"
+FILES_${PN} += "${libdir}"
+
+SECURITY_CFLAGS_pn-${PN} = "${SECURITY_NO_PIE_CFLAGS}"
diff --git a/meta/meta-mediatek/recipes-multimedia/libdngop/libdngop.bb b/meta/meta-mediatek/recipes-multimedia/libdngop/libdngop.bb
new file mode 100755
index 0000000..b032683
--- /dev/null
+++ b/meta/meta-mediatek/recipes-multimedia/libdngop/libdngop.bb
@@ -0,0 +1,24 @@
+inherit workonsrc
+DESCRIPTION = "libdngop"
+LICENSE = "MediaTekProprietary"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=e1696b147d49d491bcb4da1a57173fff"
+#DEPENDS = ""
+WORKONSRC = "${TOPDIR}/../src/multimedia/libcamera_feature/libdngop"
+PN='libdngop'
+
+inherit pkgconfig
+
+do_compile () {
+ oe_runmake \
+ CFLAGS="${CFLAGS}" \
+ LDFLAGS="${LDFLAGS}"
+}
+
+do_install() {
+ oe_runmake \
+ PREFIX="${prefix}" DESTDIR="${D}" install
+}
+
+# move libs in -dev to normal rpm
+FILES_SOLIBSDEV = ""
+FILES_${PN} = "${libdir}/*.so ${bindir}"
\ No newline at end of file
diff --git a/meta/meta-mediatek/recipes-multimedia/libeis/libeis.bb b/meta/meta-mediatek/recipes-multimedia/libeis/libeis.bb
new file mode 100755
index 0000000..e8217d5
--- /dev/null
+++ b/meta/meta-mediatek/recipes-multimedia/libeis/libeis.bb
@@ -0,0 +1,24 @@
+inherit workonsrc
+DESCRIPTION = "libeis"
+LICENSE = "MediaTekProprietary"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=e1696b147d49d491bcb4da1a57173fff"
+#DEPENDS = ""
+WORKONSRC = "${TOPDIR}/../src/multimedia/libcamera_feature/libeis"
+PN='libeis'
+
+inherit pkgconfig
+
+do_compile () {
+ oe_runmake \
+ CFLAGS="${CFLAGS}" \
+ LDFLAGS="${LDFLAGS}"
+}
+
+do_install() {
+ oe_runmake \
+ PREFIX="${prefix}" DESTDIR="${D}" install
+}
+
+# move libs in -dev to normal rpm
+FILES_SOLIBSDEV = ""
+FILES_${PN} = "${libdir}/*.so ${bindir}"
\ No newline at end of file
diff --git a/meta/meta-mediatek/recipes-multimedia/libfdft/libfdft.bb b/meta/meta-mediatek/recipes-multimedia/libfdft/libfdft.bb
new file mode 100755
index 0000000..6763c60
--- /dev/null
+++ b/meta/meta-mediatek/recipes-multimedia/libfdft/libfdft.bb
@@ -0,0 +1,24 @@
+inherit workonsrc
+DESCRIPTION = "libfdft"
+LICENSE = "MediaTekProprietary"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=e1696b147d49d491bcb4da1a57173fff"
+#DEPENDS = ""
+WORKONSRC = "${TOPDIR}/../src/multimedia/libcamera_feature/libfdft"
+PN='libfdft'
+
+inherit pkgconfig
+
+do_compile () {
+ oe_runmake \
+ CFLAGS="${CFLAGS}" \
+ LDFLAGS="${LDFLAGS}"
+}
+
+do_install() {
+ oe_runmake \
+ PREFIX="${prefix}" DESTDIR="${D}" install
+}
+
+# move libs in -dev to normal rpm
+FILES_SOLIBSDEV = ""
+FILES_${PN} = "${libdir}/*.so ${bindir}"
\ No newline at end of file
diff --git a/meta/meta-mediatek/recipes-multimedia/libfdft_p/libfdft.bb b/meta/meta-mediatek/recipes-multimedia/libfdft_p/libfdft.bb
new file mode 100755
index 0000000..6107b68
--- /dev/null
+++ b/meta/meta-mediatek/recipes-multimedia/libfdft_p/libfdft.bb
@@ -0,0 +1,24 @@
+inherit workonsrc
+DESCRIPTION = "libfdft_p"
+LICENSE = "MediaTekProprietary"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=e1696b147d49d491bcb4da1a57173fff"
+#DEPENDS = ""
+WORKONSRC = "${TOPDIR}/../src/multimedia/libcamera_feature/libfdft"
+PN='libfdft_p'
+
+inherit pkgconfig
+
+do_compile () {
+ oe_runmake \
+ CFLAGS="${CFLAGS}" \
+ LDFLAGS="${LDFLAGS}"
+}
+
+do_install() {
+ oe_runmake \
+ PREFIX="${prefix}" DESTDIR="${D}" install
+}
+
+# move libs in -dev to normal rpm
+FILES_SOLIBSDEV = ""
+FILES_${PN} = "${libdir}/*.so ${bindir}"
\ No newline at end of file
diff --git a/meta/meta-mediatek/recipes-multimedia/libflash/libflash.bb b/meta/meta-mediatek/recipes-multimedia/libflash/libflash.bb
new file mode 100755
index 0000000..00e2c8a
--- /dev/null
+++ b/meta/meta-mediatek/recipes-multimedia/libflash/libflash.bb
@@ -0,0 +1,24 @@
+inherit workonsrc
+DESCRIPTION = "libflash"
+LICENSE = "MediaTekProprietary"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=e1696b147d49d491bcb4da1a57173fff"
+#DEPENDS = ""
+WORKONSRC = "${TOPDIR}/../src/multimedia/libcamera_3a/libflash/mt8183"
+PN='libflash'
+
+inherit pkgconfig
+
+do_compile () {
+ oe_runmake \
+ CFLAGS="${CFLAGS}" \
+ LDFLAGS="${LDFLAGS}"
+}
+
+do_install() {
+ oe_runmake \
+ PREFIX="${prefix}" DESTDIR="${D}" install
+}
+
+# move libs in -dev to normal rpm
+FILES_SOLIBSDEV = ""
+FILES_${PN} = "${libdir}/*.so ${bindir}"
diff --git a/meta/meta-mediatek/recipes-multimedia/libflicker/libflicker.bb b/meta/meta-mediatek/recipes-multimedia/libflicker/libflicker.bb
new file mode 100755
index 0000000..637283d
--- /dev/null
+++ b/meta/meta-mediatek/recipes-multimedia/libflicker/libflicker.bb
@@ -0,0 +1,24 @@
+inherit workonsrc
+DESCRIPTION = "libflicker"
+LICENSE = "MediaTekProprietary"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=e1696b147d49d491bcb4da1a57173fff"
+#DEPENDS = ""
+WORKONSRC = "${TOPDIR}/../src/multimedia/libcamera_feature/libflicker/mt8183"
+PN='libflicker'
+
+inherit pkgconfig
+
+do_compile () {
+ oe_runmake \
+ CFLAGS="${CFLAGS}" \
+ LDFLAGS="${LDFLAGS}"
+}
+
+do_install() {
+ oe_runmake \
+ PREFIX="${prefix}" DESTDIR="${D}" install
+}
+
+# move libs in -dev to normal rpm
+FILES_SOLIBSDEV = ""
+FILES_${PN} = "${libdir}/*.so ${bindir}"
diff --git a/meta/meta-mediatek/recipes-multimedia/libgma/libgma.bb b/meta/meta-mediatek/recipes-multimedia/libgma/libgma.bb
new file mode 100755
index 0000000..82d58ce
--- /dev/null
+++ b/meta/meta-mediatek/recipes-multimedia/libgma/libgma.bb
@@ -0,0 +1,24 @@
+inherit workonsrc
+DESCRIPTION = "libgma"
+LICENSE = "MediaTekProprietary"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=e1696b147d49d491bcb4da1a57173fff"
+#DEPENDS = ""
+WORKONSRC = "${TOPDIR}/../src/multimedia/libcamera_3a/libgma/mt8183"
+PN='libgma'
+
+inherit pkgconfig
+
+do_compile () {
+ oe_runmake \
+ CFLAGS="${CFLAGS}" \
+ LDFLAGS="${LDFLAGS}"
+}
+
+do_install() {
+ oe_runmake \
+ PREFIX="${prefix}" DESTDIR="${D}" install
+}
+
+# move libs in -dev to normal rpm
+FILES_SOLIBSDEV = ""
+FILES_${PN} = "${libdir}/*.so ${bindir}"
diff --git a/meta/meta-mediatek/recipes-multimedia/libispfeature/libispfeature.bb b/meta/meta-mediatek/recipes-multimedia/libispfeature/libispfeature.bb
new file mode 100755
index 0000000..581fe8d
--- /dev/null
+++ b/meta/meta-mediatek/recipes-multimedia/libispfeature/libispfeature.bb
@@ -0,0 +1,24 @@
+inherit workonsrc
+DESCRIPTION = "libispfeature"
+LICENSE = "MediaTekProprietary"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=e1696b147d49d491bcb4da1a57173fff"
+#DEPENDS = ""
+WORKONSRC = "${TOPDIR}/../src/multimedia/libcamera_feature/libispfeature/mt8183"
+PN='libispfeature'
+
+inherit pkgconfig
+
+do_compile () {
+ oe_runmake \
+ CFLAGS="${CFLAGS}" \
+ LDFLAGS="${LDFLAGS}"
+}
+
+do_install() {
+ oe_runmake \
+ PREFIX="${prefix}" DESTDIR="${D}" install
+}
+
+# move libs in -dev to normal rpm
+FILES_SOLIBSDEV = ""
+FILES_${PN} = "${libdir}/*.so ${bindir}"
diff --git a/meta/meta-mediatek/recipes-multimedia/liblce/liblce.bb b/meta/meta-mediatek/recipes-multimedia/liblce/liblce.bb
new file mode 100755
index 0000000..5b79908
--- /dev/null
+++ b/meta/meta-mediatek/recipes-multimedia/liblce/liblce.bb
@@ -0,0 +1,24 @@
+inherit workonsrc
+DESCRIPTION = "liblce"
+LICENSE = "MediaTekProprietary"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=e1696b147d49d491bcb4da1a57173fff"
+#DEPENDS = ""
+WORKONSRC = "${TOPDIR}/../src/multimedia/libcamera_3a/liblce/mt8183"
+PN='liblce'
+
+inherit pkgconfig
+
+do_compile () {
+ oe_runmake \
+ CFLAGS="${CFLAGS}" \
+ LDFLAGS="${LDFLAGS}"
+}
+
+do_install() {
+ oe_runmake \
+ PREFIX="${prefix}" DESTDIR="${D}" install
+}
+
+# move libs in -dev to normal rpm
+FILES_SOLIBSDEV = ""
+FILES_${PN} = "${libdir}/*.so ${bindir}"
diff --git a/meta/meta-mediatek/recipes-multimedia/liblsc/liblsc.bb b/meta/meta-mediatek/recipes-multimedia/liblsc/liblsc.bb
new file mode 100755
index 0000000..e39d9a1
--- /dev/null
+++ b/meta/meta-mediatek/recipes-multimedia/liblsc/liblsc.bb
@@ -0,0 +1,24 @@
+inherit workonsrc
+DESCRIPTION = "liblsc"
+LICENSE = "MediaTekProprietary"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=e1696b147d49d491bcb4da1a57173fff"
+#DEPENDS = ""
+WORKONSRC = "${TOPDIR}/../src/multimedia/libcamera_feature/liblsc/mt8183"
+PN='liblsc'
+
+inherit pkgconfig
+
+do_compile () {
+ oe_runmake \
+ CFLAGS="${CFLAGS}" \
+ LDFLAGS="${LDFLAGS}"
+}
+
+do_install() {
+ oe_runmake \
+ PREFIX="${prefix}" DESTDIR="${D}" install
+}
+
+# move libs in -dev to normal rpm
+FILES_SOLIBSDEV = ""
+FILES_${PN} = "${libdir}/*.so ${bindir}"
diff --git a/meta/meta-mediatek/recipes-multimedia/libmdp_prot/libmdp-prot.bb b/meta/meta-mediatek/recipes-multimedia/libmdp_prot/libmdp-prot.bb
new file mode 100644
index 0000000..9113f08
--- /dev/null
+++ b/meta/meta-mediatek/recipes-multimedia/libmdp_prot/libmdp-prot.bb
@@ -0,0 +1,34 @@
+DESCRIPTION = "MediaTek mdp prot library"
+LICENSE = "MediaTekProprietary"
+LIC_FILES_CHKSUM = "file://NOTICE;md5=e1696b147d49d491bcb4da1a57173fff"
+SECTION = "libs"
+
+inherit workonsrc
+WORKONSRC = "${TOPDIR}/../src/multimedia/libmdp_prot"
+
+RDEPENDS_${PN} = "libgcc"
+RDEPENDS_${PN} += "libstdc++"
+
+inherit pkgconfig
+
+do_configure() {
+ :
+}
+
+do_compile() {
+ oe_runmake \
+ PACKAGE_ARCH="${PACKAGE_ARCH}" \
+ CFLAGS="${CFLAGS}" \
+ LDFLAGS="${LDFLAGS}"
+}
+
+do_install() {
+ oe_runmake \
+ PREFIX="${prefix}" DESTDIR="${D}" PACKAGE_ARCH="${PACKAGE_ARCH}" install
+}
+
+INSANE_SKIP_${PN} += "already-stripped"
+FILES_${PN}-dev = "dev-elf"
+FILES_${PN} += "${libdir}"
+
+SECURITY_CFLAGS_pn-${PN} = "${SECURITY_NO_PIE_CFLAGS}"
diff --git a/meta/meta-mediatek/recipes-multimedia/libmfnr/libmfnr.bb b/meta/meta-mediatek/recipes-multimedia/libmfnr/libmfnr.bb
new file mode 100755
index 0000000..be6cb15
--- /dev/null
+++ b/meta/meta-mediatek/recipes-multimedia/libmfnr/libmfnr.bb
@@ -0,0 +1,24 @@
+inherit workonsrc
+DESCRIPTION = "libmfnf"
+LICENSE = "MediaTekProprietary"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=e1696b147d49d491bcb4da1a57173fff"
+#DEPENDS = ""
+WORKONSRC = "${TOPDIR}/../src/multimedia/libcamera_feature/libmfnr/mt8183"
+PN='libmfnr'
+
+inherit pkgconfig
+
+do_compile () {
+ oe_runmake \
+ CFLAGS="${CFLAGS}" \
+ LDFLAGS="${LDFLAGS}"
+}
+
+do_install() {
+ oe_runmake \
+ PREFIX="${prefix}" DESTDIR="${D}" install
+}
+
+# move libs in -dev to normal rpm
+FILES_SOLIBSDEV = ""
+FILES_${PN} = "${libdir}/*.so ${bindir}"
\ No newline at end of file
diff --git a/meta/meta-mediatek/recipes-multimedia/libmtkconv/libmtkconv.bb b/meta/meta-mediatek/recipes-multimedia/libmtkconv/libmtkconv.bb
new file mode 100644
index 0000000..68098ea
--- /dev/null
+++ b/meta/meta-mediatek/recipes-multimedia/libmtkconv/libmtkconv.bb
@@ -0,0 +1,15 @@
+DESCRIPTION = "MediaTek format conversion"
+LICENSE = "MediaTekProprietary"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=e1696b147d49d491bcb4da1a57173fff"
+
+inherit workonsrc
+WORKONSRC = "${TOPDIR}/../src/multimedia/vpu/libmtkconv"
+
+inherit autotools
+
+do_install() {
+ oe_runmake \
+ PREFIX="${prefix}" DESTDIR="${D}" PACKAGE_ARCH="${PACKAGE_ARCH}" install
+}
+
+INSANE_SKIP_${PN} += "already-stripped"
diff --git a/meta/meta-mediatek/recipes-multimedia/libnr/libnr.bb b/meta/meta-mediatek/recipes-multimedia/libnr/libnr.bb
new file mode 100755
index 0000000..4ca5fff
--- /dev/null
+++ b/meta/meta-mediatek/recipes-multimedia/libnr/libnr.bb
@@ -0,0 +1,24 @@
+inherit workonsrc
+DESCRIPTION = "libnr"
+LICENSE = "MediaTekProprietary"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=e1696b147d49d491bcb4da1a57173fff"
+#DEPENDS = ""
+WORKONSRC = "${TOPDIR}/../src/multimedia/libcamera_feature/libnr"
+PN='libnr'
+
+inherit pkgconfig
+
+do_compile () {
+ oe_runmake \
+ CFLAGS="${CFLAGS}" \
+ LDFLAGS="${LDFLAGS}"
+}
+
+do_install() {
+ oe_runmake \
+ PREFIX="${prefix}" DESTDIR="${D}" install
+}
+
+# move libs in -dev to normal rpm
+FILES_SOLIBSDEV = ""
+FILES_${PN} = "${libdir}/*.so ${bindir}"
diff --git a/meta/meta-mediatek/recipes-multimedia/libpq/libmdppq.bb b/meta/meta-mediatek/recipes-multimedia/libpq/libmdppq.bb
new file mode 100644
index 0000000..76e8215
--- /dev/null
+++ b/meta/meta-mediatek/recipes-multimedia/libpq/libmdppq.bb
@@ -0,0 +1,34 @@
+DESCRIPTION = "MediaTek mdp pq library"
+LICENSE = "MediaTekProprietary"
+LIC_FILES_CHKSUM = "file://NOTICE;md5=e1696b147d49d491bcb4da1a57173fff"
+SECTION = "libs"
+
+inherit workonsrc
+WORKONSRC = "${TOPDIR}/../src/multimedia/libpq"
+
+RDEPENDS_${PN} = "libgcc"
+RDEPENDS_${PN} += "libstdc++"
+
+inherit pkgconfig
+
+do_configure() {
+ :
+}
+
+do_compile() {
+ oe_runmake \
+ PACKAGE_ARCH="${PACKAGE_ARCH}" \
+ CFLAGS="`pkg-config` ${CFLAGS}" \
+ LDFLAGS="`pkg-config` ${LDFLAGS}"
+}
+
+do_install() {
+ oe_runmake \
+ PREFIX="${prefix}" DESTDIR="${D}" PACKAGE_ARCH="${PACKAGE_ARCH}" install
+}
+
+INSANE_SKIP_${PN} += "already-stripped"
+FILES_${PN}-dev = "dev-elf"
+FILES_${PN} += "${libdir}"
+
+SECURITY_CFLAGS_pn-${PN} = "${SECURITY_NO_PIE_CFLAGS}"
diff --git a/meta/meta-mediatek/recipes-multimedia/libwarpmap/libwarpmap.bb b/meta/meta-mediatek/recipes-multimedia/libwarpmap/libwarpmap.bb
new file mode 100755
index 0000000..f986d3a
--- /dev/null
+++ b/meta/meta-mediatek/recipes-multimedia/libwarpmap/libwarpmap.bb
@@ -0,0 +1,20 @@
+DESCRIPTION = "MediaTek warpmap generate library"
+LICENSE = "MediaTekProprietary"
+
+inherit workonsrc
+WORKONSRC = "${TOPDIR}/../src/multimedia/warp/libwarpmap"
+
+do_compile() {
+ oe_runmake \
+ LDFLAGS=" -lm ${LDFLAGS}"
+}
+
+do_install() {
+ oe_runmake PREFIX="${prefix}" DESTDIR="${D}" install
+}
+
+INSANE_SKIP_${PN} += "already-stripped"
+FILES_${PN} += " ${libdir}/libwarpmap.so \
+ ${includedir}/warp.h "
+
+ALLOW_EMPTY_${PN} = "1"
diff --git a/meta/meta-mediatek/recipes-multimedia/mdpd/mdpd.bb b/meta/meta-mediatek/recipes-multimedia/mdpd/mdpd.bb
new file mode 100644
index 0000000..93c7232
--- /dev/null
+++ b/meta/meta-mediatek/recipes-multimedia/mdpd/mdpd.bb
@@ -0,0 +1,51 @@
+DESCRIPTION = "MediaTek MDP daemon"
+LICENSE = "MediaTekProprietary"
+LIC_FILES_CHKSUM = "file://NOTICE;md5=e1696b147d49d491bcb4da1a57173fff"
+
+inherit workonsrc
+WORKONSRC = "${TOPDIR}/../src/multimedia/mdpd"
+
+DEPENDS = "libmdppq"
+DEPENDS += "libmdp-prot"
+RDEPENDS_${PN} = "libgcc"
+RDEPENDS_${PN} += "libstdc++"
+RDEPENDS_${PN} += "libmdppq"
+RDEPENDS_${PN} += "libmdp-prot"
+
+inherit pkgconfig
+
+do_configure() {
+ :
+}
+
+do_compile() {
+ oe_runmake \
+ PACKAGE_ARCH="${PACKAGE_ARCH}" \
+ CFLAGS="${CFLAGS}" \
+ LDFLAGS="${LDFLAGS}"
+}
+
+do_install() {
+ oe_runmake \
+ PREFIX="${prefix}" DESTDIR="${D}" PACKAGE_ARCH="${PACKAGE_ARCH}" install
+}
+
+
+inherit systemd
+
+SYSTEMD_PACKAGES = "${PN}"
+SYSTEMD_SERVICE_${PN} = "mdpd.service"
+FILES_${PN} += "${systemd_unitdir}/system/mdpd.service"
+
+do_install_append() {
+ if ${@bb.utils.contains('DISTRO_FEATURES','systemd','true','false',d)}; then
+ install -d ${D}${systemd_unitdir}/system/
+ install -m 0644 ${B}/lib/systemd/system/mdpd.service ${D}${systemd_unitdir}/system
+ fi
+}
+
+INSANE_SKIP_${PN} += "already-stripped"
+FILES_${PN}-dev = "dev-elf"
+FILES_${PN} += "${libdir}"
+
+SECURITY_CFLAGS_pn-${PN} = "${SECURITY_NO_PIE_CFLAGS}"
diff --git a/meta/meta-mediatek/recipes-multimedia/mtk-alsa-ucm/mtk-alsa-ucm.bb b/meta/meta-mediatek/recipes-multimedia/mtk-alsa-ucm/mtk-alsa-ucm.bb
new file mode 100644
index 0000000..302a078
--- /dev/null
+++ b/meta/meta-mediatek/recipes-multimedia/mtk-alsa-ucm/mtk-alsa-ucm.bb
@@ -0,0 +1,15 @@
+DESCRIPTION = "Mediatek ALSA UCM Configration"
+LICENSE = "MediaTekProprietary"
+LIC_FILES_CHKSUM = "file://README;md5=169c5a78ab6dd37dd1e18c95f6ff67b2"
+SRC_URI = "file://README \
+ file://alsa.conf.d/mtk_phonecall.conf \
+"
+
+S = "${WORKDIR}"
+FILES_${PN} = "${datadir}/alsa/ucm/*/*.conf"
+FILES_${PN} += "${datadir}/alsa/alsa.conf.d/*.conf"
+
+do_install () {
+ install -d ${D}${datadir}/alsa/alsa.conf.d
+ install -m 644 ${S}/alsa.conf.d/*.conf ${D}${datadir}/alsa/alsa.conf.d
+}
diff --git a/meta/meta-mediatek/recipes-multimedia/mtk-alsa-ucm/mtk-alsa-ucm/README b/meta/meta-mediatek/recipes-multimedia/mtk-alsa-ucm/mtk-alsa-ucm/README
new file mode 100644
index 0000000..7e1ce66
--- /dev/null
+++ b/meta/meta-mediatek/recipes-multimedia/mtk-alsa-ucm/mtk-alsa-ucm/README
@@ -0,0 +1 @@
+Copy ucm configuration to /usr/share/alsa/ucm
diff --git a/meta/meta-mediatek/recipes-multimedia/mtk-alsa-ucm/mtk-alsa-ucm/alsa.conf.d/mtk_phonecall.conf b/meta/meta-mediatek/recipes-multimedia/mtk-alsa-ucm/mtk-alsa-ucm/alsa.conf.d/mtk_phonecall.conf
new file mode 100755
index 0000000..3a801d8
--- /dev/null
+++ b/meta/meta-mediatek/recipes-multimedia/mtk-alsa-ucm/mtk-alsa-ucm/alsa.conf.d/mtk_phonecall.conf
@@ -0,0 +1,7 @@
+pcm.mtk_phonecall {
+ type mtk_phonecall
+}
+
+ctl.mtk_phonecall {
+ type mtk_phonecall
+}
\ No newline at end of file
diff --git a/meta/meta-mediatek/recipes-multimedia/mtk-audio-patterns/files/16k_2ch_16bit_5s.wav b/meta/meta-mediatek/recipes-multimedia/mtk-audio-patterns/files/16k_2ch_16bit_5s.wav
new file mode 100644
index 0000000..fa73ec8
--- /dev/null
+++ b/meta/meta-mediatek/recipes-multimedia/mtk-audio-patterns/files/16k_2ch_16bit_5s.wav
Binary files differ
diff --git a/meta/meta-mediatek/recipes-multimedia/mtk-audio-patterns/files/44k_2ch_16bit_6s.wav b/meta/meta-mediatek/recipes-multimedia/mtk-audio-patterns/files/44k_2ch_16bit_6s.wav
new file mode 100644
index 0000000..905e55c
--- /dev/null
+++ b/meta/meta-mediatek/recipes-multimedia/mtk-audio-patterns/files/44k_2ch_16bit_6s.wav
Binary files differ
diff --git a/meta/meta-mediatek/recipes-multimedia/mtk-audio-patterns/files/48k_2ch_16bit_6s.wav b/meta/meta-mediatek/recipes-multimedia/mtk-audio-patterns/files/48k_2ch_16bit_6s.wav
new file mode 100644
index 0000000..cb59a35
--- /dev/null
+++ b/meta/meta-mediatek/recipes-multimedia/mtk-audio-patterns/files/48k_2ch_16bit_6s.wav
Binary files differ
diff --git a/meta/meta-mediatek/recipes-multimedia/mtk-audio-patterns/files/48k_2ch_32bit_5s.wav b/meta/meta-mediatek/recipes-multimedia/mtk-audio-patterns/files/48k_2ch_32bit_5s.wav
new file mode 100644
index 0000000..5ae3d63
--- /dev/null
+++ b/meta/meta-mediatek/recipes-multimedia/mtk-audio-patterns/files/48k_2ch_32bit_5s.wav
Binary files differ
diff --git a/meta/meta-mediatek/recipes-multimedia/mtk-audio-patterns/files/48k_8ch_16bit_3s.wav b/meta/meta-mediatek/recipes-multimedia/mtk-audio-patterns/files/48k_8ch_16bit_3s.wav
new file mode 100644
index 0000000..1e82a33
--- /dev/null
+++ b/meta/meta-mediatek/recipes-multimedia/mtk-audio-patterns/files/48k_8ch_16bit_3s.wav
Binary files differ
diff --git a/meta/meta-mediatek/recipes-multimedia/mtk-audio-patterns/files/8k_2ch_16bit_5s.wav b/meta/meta-mediatek/recipes-multimedia/mtk-audio-patterns/files/8k_2ch_16bit_5s.wav
new file mode 100644
index 0000000..ff7aefe
--- /dev/null
+++ b/meta/meta-mediatek/recipes-multimedia/mtk-audio-patterns/files/8k_2ch_16bit_5s.wav
Binary files differ
diff --git a/meta/meta-mediatek/recipes-multimedia/mtk-audio-patterns/files/sample.mp3 b/meta/meta-mediatek/recipes-multimedia/mtk-audio-patterns/files/sample.mp3
new file mode 100644
index 0000000..9952be0
--- /dev/null
+++ b/meta/meta-mediatek/recipes-multimedia/mtk-audio-patterns/files/sample.mp3
Binary files differ
diff --git a/meta/meta-mediatek/recipes-multimedia/mtk-audio-patterns/mtk-audio-patterns.bb b/meta/meta-mediatek/recipes-multimedia/mtk-audio-patterns/mtk-audio-patterns.bb
new file mode 100644
index 0000000..7e30897
--- /dev/null
+++ b/meta/meta-mediatek/recipes-multimedia/mtk-audio-patterns/mtk-audio-patterns.bb
@@ -0,0 +1,24 @@
+DESCRIPTION = "mtk-audio-patterns"
+LICENSE = "MediaTekProprietary"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=e1696b147d49d491bcb4da1a57173fff"
+
+SRC_URI = "file://48k_2ch_16bit_6s.wav \
+file://44k_2ch_16bit_6s.wav \
+file://16k_2ch_16bit_5s.wav \
+file://8k_2ch_16bit_5s.wav \
+file://48k_8ch_16bit_3s.wav \
+file://48k_2ch_32bit_5s.wav \
+file://sample.mp3 \
+"
+
+S = "${WORKDIR}"
+
+PATTERNS_DST = "/data/misc"
+
+FILES_${PN} = "${PATTERNS_DST}/mtk-audio-patterns"
+
+do_install() {
+ install -d ${D}${PATTERNS_DST}/mtk-audio-patterns
+ install -m 0644 ${S}/*.wav ${D}${PATTERNS_DST}/mtk-audio-patterns
+ install -m 0644 ${S}/*.mp3 ${D}${PATTERNS_DST}/mtk-audio-patterns
+}
diff --git a/meta/meta-mediatek/recipes-multimedia/mtk-ovl-adapter/mtk-ovl-adapter.bb b/meta/meta-mediatek/recipes-multimedia/mtk-ovl-adapter/mtk-ovl-adapter.bb
new file mode 100644
index 0000000..9bca7ec
--- /dev/null
+++ b/meta/meta-mediatek/recipes-multimedia/mtk-ovl-adapter/mtk-ovl-adapter.bb
@@ -0,0 +1,26 @@
+DESCRIPTION = "MediaTek OVL ADAPTER"
+LICENSE = "MediaTekProprietary"
+LIC_FILES_CHKSUM = "file://NOTICE;md5=e1696b147d49d491bcb4da1a57173fff"
+SECTION = "libs"
+
+inherit workonsrc
+WORKONSRC = "${TOPDIR}/../src/multimedia/mtk-ovl-adapter"
+
+#RDEPENDS_${PN} = "libgcc"
+#RDEPENDS_${PN} = "libstdc++"
+
+
+FILES_SOLIBSDEV = ""
+FILES_${PN} = "${libdir}/libmtk-ovl-adapter.so"
+
+do_compile() {
+ oe_runmake \
+ CFLAGS="${CFLAGS}" \
+ LDFLAGS="${LDFLAGS}"
+}
+
+do_install() {
+ oe_runmake \
+ DESTDIR="${D}" LIBDIR="${libdir}" INCDIR="${includedir}" install
+}
+
diff --git a/meta/meta-mediatek/recipes-multimedia/pulseaudio/pulseaudio/daemon.conf b/meta/meta-mediatek/recipes-multimedia/pulseaudio/pulseaudio/daemon.conf
new file mode 100644
index 0000000..9101346
--- /dev/null
+++ b/meta/meta-mediatek/recipes-multimedia/pulseaudio/pulseaudio/daemon.conf
@@ -0,0 +1,85 @@
+# This file is part of PulseAudio.
+#
+# PulseAudio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# PulseAudio 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 Lesser General Public License
+# along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
+
+## Configuration file for the PulseAudio daemon. See pulse-daemon.conf(5) for
+## more information. Default values are commented out. Use either ; or # for
+## commenting.
+
+; daemonize = no
+; fail = yes
+; allow-module-loading = yes
+; allow-exit = yes
+; use-pid-file = yes
+; system-instance = no
+; local-server-type = user
+; enable-shm = yes
+; shm-size-bytes = 0 # setting this 0 will use the system-default, usually 64 MiB
+; lock-memory = no
+; cpu-limit = no
+
+; high-priority = yes
+; nice-level = -11
+
+; realtime-scheduling = yes
+; realtime-priority = 5
+
+exit-idle-time = -1
+; scache-idle-time = 20
+
+; dl-search-path = (depends on architecture)
+
+; load-default-script-file = yes
+; default-script-file = /etc/pulse/default.pa
+
+; log-target = auto
+; log-level = notice
+; log-meta = no
+; log-time = no
+; log-backtrace = 0
+
+; resample-method = speex-float-1
+; enable-remixing = yes
+; enable-lfe-remixing = no
+
+; flat-volumes = yes
+
+; rlimit-fsize = -1
+; rlimit-data = -1
+; rlimit-stack = -1
+; rlimit-core = -1
+; rlimit-as = -1
+; rlimit-rss = -1
+; rlimit-nproc = -1
+; rlimit-nofile = 256
+; rlimit-memlock = -1
+; rlimit-locks = -1
+; rlimit-sigpending = -1
+; rlimit-msgqueue = -1
+; rlimit-nice = 31
+; rlimit-rtprio = 9
+; rlimit-rttime = 200000
+
+; default-sample-format = s16le
+; default-sample-rate = 44100
+; alternate-sample-rate = 48000
+; default-sample-channels = 2
+; default-channel-map = front-left,front-right
+
+; default-fragments = 4
+; default-fragment-size-msec = 25
+
+; enable-deferred-volume = yes
+; deferred-volume-safety-margin-usec = 8000
+; deferred-volume-extra-delay-usec = 0
diff --git a/meta/meta-mediatek/recipes-multimedia/pulseaudio/pulseaudio/pulseaudio_user.service b/meta/meta-mediatek/recipes-multimedia/pulseaudio/pulseaudio/pulseaudio_user.service
new file mode 100644
index 0000000..e4e1d55
--- /dev/null
+++ b/meta/meta-mediatek/recipes-multimedia/pulseaudio/pulseaudio/pulseaudio_user.service
@@ -0,0 +1,12 @@
+[Unit]
+Description=pulseaudio server
+Requires=dbus.service
+After=dbus.service
+
+[Service]
+Type=simple
+Environment=HOME=/home/root
+ExecStart=/usr/bin/pulseaudio
+Restart=always
+RestartSec=5
+TimeoutSec=5
diff --git a/meta/meta-mediatek/recipes-multimedia/pulseaudio/pulseaudio_%.bbappend b/meta/meta-mediatek/recipes-multimedia/pulseaudio/pulseaudio_%.bbappend
new file mode 100644
index 0000000..27155be
--- /dev/null
+++ b/meta/meta-mediatek/recipes-multimedia/pulseaudio/pulseaudio_%.bbappend
@@ -0,0 +1,29 @@
+FILESEXTRAPATHS_append := ":${THISDIR}/${PN}"
+
+SRC_URI += "file://daemon.conf \
+ file://pulseaudio_user.service \
+"
+
+do_install_append() {
+ install -m 0644 ${WORKDIR}/daemon.conf ${D}${sysconfdir}/pulse/daemon.conf
+
+ if [ "${MTK_AUDIO_SYSTEM}" = "mt2701-cs42448" ]; then
+ sed -e 's/; default-sample-channels = 2/default-sample-channels = 8/g' \
+ -i ${D}${sysconfdir}/pulse/daemon.conf
+ fi
+ if [ "${MTK_AUDIO_SYSTEM}" = "mt2712-d1v1" ]; then
+ sed -e 's/; default-sample-channels = 2/default-sample-channels = 8/g' \
+ -i ${D}${sysconfdir}/pulse/daemon.conf
+ sed -e 's/; default-sample-format = s16le/default-sample-format = s32le/g' \
+ -i ${D}${sysconfdir}/pulse/daemon.conf
+ sed -e 's/; default-sample-rate = 44100/default-sample-rate = 48000/g' \
+ -i ${D}${sysconfdir}/pulse/daemon.conf
+ sed -e '/load-module module-alsa-sink/a\load-module module-alsa-card\' \
+ -i ${D}${sysconfdir}/pulse/default.pa
+ fi
+
+ mkdir -p ${D}/etc/systemd/user
+ cp ${WORKDIR}/pulseaudio_user.service ${D}/etc/systemd/user/pulseaudio.service
+ mkdir -p ${D}/etc/systemd/user/default.target.wants
+ ln -sf /etc/systemd/user/pulseaudio.service ${D}/etc/systemd/user/default.target.wants/pulseaudio.service
+}
diff --git a/meta/meta-mediatek/recipes-multimedia/tinyalsa/tinyalsa/0001-tinyhostless-app-that-records-from-mic-and-sends-bac.patch b/meta/meta-mediatek/recipes-multimedia/tinyalsa/tinyalsa/0001-tinyhostless-app-that-records-from-mic-and-sends-bac.patch
new file mode 100644
index 0000000..1351ca4
--- /dev/null
+++ b/meta/meta-mediatek/recipes-multimedia/tinyalsa/tinyalsa/0001-tinyhostless-app-that-records-from-mic-and-sends-bac.patch
@@ -0,0 +1,387 @@
+From 00a066fea527c86a85e42cfce05585a7afa42a57 Mon Sep 17 00:00:00 2001
+From: Hidalgo Huang <hidalgo.huang@mediatek.com>
+Date: Thu, 27 Dec 2018 19:23:54 +0800
+Subject: [PATCH 1/2] tinyhostless app that records from mic and sends back out
+
+Record from microphone and then immediately play back to
+headphones. Useful for testing audio hardware ports.
+
+Signed-off-by: Hidalgo Huang <hidalgo.huang@mediatek.com>
+---
+ CMakeLists.txt | 2 +
+ utils/tinyhostless.c | 343 +++++++++++++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 345 insertions(+)
+ create mode 100755 utils/tinyhostless.c
+
+diff --git a/CMakeLists.txt b/CMakeLists.txt
+index 4c78dbf..3276881 100644
+--- a/CMakeLists.txt
++++ b/CMakeLists.txt
+@@ -36,6 +36,7 @@ add_util("tinyplay" "utils/tinyplay.c")
+ add_util("tinycap" "utils/tinycap.c")
+ add_util("tinypcminfo" "utils/tinypcminfo.c")
+ add_util("tinymix" "utils/tinymix.c")
++add_util("tinyhostless" "utils/tinyhostless.c")
+
+ install(FILES ${HDRS}
+ DESTINATION "include/tinyalsa")
+@@ -45,6 +46,7 @@ install(TARGETS "tinyalsa"
+ "tinycap"
+ "tinymix"
+ "tinypcminfo"
++ "tinyhostless"
+ RUNTIME DESTINATION "bin"
+ ARCHIVE DESTINATION "lib"
+ LIBRARY DESTINATION "lib")
+diff --git a/utils/tinyhostless.c b/utils/tinyhostless.c
+new file mode 100755
+index 0000000..e24ae85
+--- /dev/null
++++ b/utils/tinyhostless.c
+@@ -0,0 +1,343 @@
++/* tinyhostless.c
++**
++** Copyright 2011, The Android Open Source Project
++**
++** Redistribution and use in source and binary forms, with or without
++** modification, are permitted provided that the following conditions are met:
++** * Redistributions of source code must retain the above copyright
++** notice, this list of conditions and the following disclaimer.
++** * Redistributions in binary form must reproduce the above copyright
++** notice, this list of conditions and the following disclaimer in the
++** documentation and/or other materials provided with the distribution.
++** * Neither the name of The Android Open Source Project nor the names of
++** its contributors may be used to endorse or promote products derived
++** from this software without specific prior written permission.
++**
++** THIS SOFTWARE IS PROVIDED BY The Android Open Source Project ``AS IS'' AND
++** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
++** ARE DISCLAIMED. IN NO EVENT SHALL The Android Open Source Project BE LIABLE
++** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
++** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
++** SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
++** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
++** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
++** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
++** DAMAGE.
++*/
++
++/* Playback data to a PCM device recorded from a capture PCM device. */
++
++#include <tinyalsa/asoundlib.h>
++#include <errno.h>
++#include <math.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <stdint.h>
++#include <string.h>
++#include <signal.h>
++#include <time.h>
++#include <unistd.h>
++
++/* Used when that particular device isn't opened. */
++#define TINYHOSTLESS_DEVICE_UNDEFINED 255
++
++static int close_h = 0;
++
++int play_sample(unsigned int card, unsigned int p_device,
++ unsigned int c_device, unsigned int channels,
++ unsigned int rate, unsigned int bits, unsigned int period_size,
++ unsigned int period_count, unsigned int play_cap_time,
++ int do_loopback);
++
++static void stream_close(int sig)
++{
++ /* allow the stream to be closed gracefully */
++ signal(sig, SIG_IGN);
++ close_h = 1;
++}
++
++int main(int argc, char **argv)
++{
++ unsigned int card = 0;
++ unsigned int p_device = TINYHOSTLESS_DEVICE_UNDEFINED;
++ unsigned int c_device = TINYHOSTLESS_DEVICE_UNDEFINED;
++ unsigned int period_size = 192;
++ unsigned int period_count = 4;
++ unsigned int number_bits = 16;
++ unsigned int num_channels = 2;
++ unsigned int sample_rate = 48000;
++ unsigned int play_cap_time = 0;
++ unsigned int do_loopback = 0;
++
++ if (argc < 2) {
++ fprintf(stderr, "Usage: %s [-D card] [-P playback device]"
++ " [-C capture device] [-p period_size] [-n n_periods]"
++ " [-c num_channels] [-r sample_rate] [-l]"
++ " [-T playback/capture time]\n\n"
++ "Used to enable 'hostless' mode for audio devices with a DSP back-end.\n"
++ "Alternatively, specify '-l' for loopback mode: this program will read\n"
++ "from the capture device and write to the playback device.\n",
++ argv[0]);
++ return 1;
++ }
++
++ /* parse command line arguments */
++ argv += 1;
++ while (*argv) {
++ if (strcmp(*argv, "-P") == 0) {
++ argv++;
++ if (*argv)
++ p_device = atoi(*argv);
++ }
++ if (strcmp(*argv, "-C") == 0) {
++ argv++;
++ if (*argv)
++ c_device = atoi(*argv);
++ }
++ if (strcmp(*argv, "-p") == 0) {
++ argv++;
++ if (*argv)
++ period_size = atoi(*argv);
++ }
++ if (strcmp(*argv, "-n") == 0) {
++ argv++;
++ if (*argv)
++ period_count = atoi(*argv);
++ }
++ if (strcmp(*argv, "-c") == 0) {
++ argv++;
++ if (*argv)
++ num_channels = atoi(*argv);
++ }
++ if (strcmp(*argv, "-r") == 0) {
++ argv++;
++ if (*argv)
++ sample_rate = atoi(*argv);
++ }
++ if (strcmp(*argv, "-T") == 0) {
++ argv++;
++ if (*argv)
++ play_cap_time = atoi(*argv);
++ }
++ if (strcmp(*argv, "-D") == 0) {
++ argv++;
++ if (*argv)
++ card = atoi(*argv);
++ }
++ if (strcmp(*argv, "-l") == 0) {
++ do_loopback = 1;
++ }
++ if (*argv)
++ argv++;
++ }
++
++ if (p_device == TINYHOSTLESS_DEVICE_UNDEFINED &&
++ c_device == TINYHOSTLESS_DEVICE_UNDEFINED) {
++ fprintf(stderr, "Specify at least one of -C (capture device) or -P (playback device).\n");
++ return EINVAL;
++ }
++
++ if (do_loopback && (p_device == TINYHOSTLESS_DEVICE_UNDEFINED ||
++ c_device == TINYHOSTLESS_DEVICE_UNDEFINED)) {
++ fprintf(stderr, "Loopback requires both playback and capture devices.\n");
++ return EINVAL;
++ }
++
++ return play_sample(card, p_device, c_device, num_channels, sample_rate,
++ number_bits, period_size, period_count, play_cap_time,
++ do_loopback);
++}
++
++static int check_param(struct pcm_params *params, unsigned int param,
++ unsigned int value, char *param_name, char *param_unit)
++{
++ unsigned int min;
++ unsigned int max;
++ int is_within_bounds = 1;
++
++ min = pcm_params_get_min(params, param);
++ if (value < min) {
++ fprintf(stderr, "%s is %u%s, device only supports >= %u%s\n", param_name, value,
++ param_unit, min, param_unit);
++ is_within_bounds = 0;
++ }
++
++ max = pcm_params_get_max(params, param);
++ if (value > max) {
++ fprintf(stderr, "%s is %u%s, device only supports <= %u%s\n", param_name, value,
++ param_unit, max, param_unit);
++ is_within_bounds = 0;
++ }
++
++ return is_within_bounds;
++}
++
++static int check_params(unsigned int card, unsigned int device, unsigned int direction,
++ const struct pcm_config *config)
++{
++ struct pcm_params *params;
++ int can_play;
++ int bits;
++
++ params = pcm_params_get(card, device, direction);
++ if (params == NULL) {
++ fprintf(stderr, "Unable to open PCM %s device %u.\n",
++ direction == PCM_OUT ? "playback" : "capture", device);
++ return 0;
++ }
++
++ switch (config->format) {
++ case PCM_FORMAT_S32_LE:
++ bits = 32;
++ break;
++ case PCM_FORMAT_S24_3LE:
++ bits = 24;
++ break;
++ case PCM_FORMAT_S16_LE:
++ bits = 16;
++ break;
++ default:
++ fprintf(stderr, "Invalid format: %u", config->format);
++ return 0;
++ }
++
++ can_play = check_param(params, PCM_PARAM_RATE, config->rate, "Sample rate", "Hz");
++ can_play &= check_param(params, PCM_PARAM_CHANNELS, config->channels, "Sample", " channels");
++ can_play &= check_param(params, PCM_PARAM_SAMPLE_BITS, bits, "Bitrate", " bits");
++ can_play &= check_param(params, PCM_PARAM_PERIOD_SIZE, config->period_size, "Period size", " frames");
++ can_play &= check_param(params, PCM_PARAM_PERIODS, config->period_count, "Period count", " periods");
++
++ pcm_params_free(params);
++
++ return can_play;
++}
++
++int play_sample(unsigned int card, unsigned int p_device,
++ unsigned int c_device, unsigned int channels,
++ unsigned int rate, unsigned int bits, unsigned int period_size,
++ unsigned int period_count, unsigned int play_cap_time,
++ int do_loopback)
++{
++ struct pcm_config config;
++ struct pcm *pcm_play =NULL, *pcm_cap=NULL;
++#ifdef __ANDOIRD__
++ unsigned int count =0;
++#endif
++ char *buffer = NULL;
++ int size = 0;
++ int rc = 0;
++ struct timespec end;
++ struct timespec now;
++
++ memset(&config, 0, sizeof(config));
++ config.channels = channels;
++ config.rate = rate;
++ config.period_size = period_size;
++ config.period_count = period_count;
++ if (bits == 32)
++ config.format = PCM_FORMAT_S32_LE;
++ else if (bits == 24)
++ config.format = PCM_FORMAT_S24_3LE;
++ else if (bits == 16)
++ config.format = PCM_FORMAT_S16_LE;
++ config.start_threshold = 0;
++ config.stop_threshold = 0;
++#ifdef __ANDOIRD__
++ config.avail_min = 0;
++#endif
++
++ if(p_device < TINYHOSTLESS_DEVICE_UNDEFINED ) {
++ if (!check_params(card, p_device, PCM_OUT, &config))
++ return EINVAL;
++ pcm_play = pcm_open(card, p_device, PCM_OUT, &config);
++ if (!pcm_play || !pcm_is_ready(pcm_play)) {
++ fprintf(stderr, "Unable to open PCM playback device %u (%s)\n",
++ p_device, pcm_get_error(pcm_play));
++ return errno;
++ }
++ }
++
++ if (c_device < TINYHOSTLESS_DEVICE_UNDEFINED ) {
++ if (!check_params(card, c_device, PCM_IN, &config))
++ return EINVAL;
++ pcm_cap = pcm_open(card, c_device, PCM_IN, &config);
++ if (!pcm_cap || !pcm_is_ready(pcm_cap)) {
++ fprintf(stderr, "Unable to open PCM capture device %u (%s)\n",
++ c_device, pcm_get_error(pcm_cap));
++ if (pcm_cap != NULL ) pcm_close(pcm_cap);
++ return errno;
++ }
++ }
++
++ printf("%s: Playing device %u, Capture Device %u\n",
++ do_loopback ? "Loopback" : "Hostless", p_device, c_device);
++ printf("Sample: %u ch, %u hz, %u bit\n", channels, rate, bits);
++ if (play_cap_time)
++ printf("Duration in sec: %u\n", play_cap_time);
++ else
++ printf("Duration in sec: forever\n");
++
++ if (do_loopback) {
++ size = pcm_frames_to_bytes(pcm_cap, pcm_get_buffer_size(pcm_cap));
++ buffer = malloc(size);
++ if (!buffer) {
++ fprintf(stderr, "Unable to allocate %d bytes\n", size);
++ pcm_close(pcm_play);
++ pcm_close(pcm_cap);
++ return ENOMEM;
++ }
++ }
++
++ /* catch ctrl-c to shutdown cleanly */
++ signal(SIGINT, stream_close);
++ signal(SIGHUP, stream_close);
++ signal(SIGTERM, stream_close);
++
++ if (pcm_cap != NULL) pcm_start(pcm_cap);
++ if (pcm_play != NULL) pcm_start(pcm_play);
++
++ clock_gettime(CLOCK_MONOTONIC, &now);
++ end.tv_sec = now.tv_sec + play_cap_time;
++ end.tv_nsec = now.tv_nsec;
++
++ do {
++ if (do_loopback) {
++#ifdef __GNUC__
++ if (pcm_readi(pcm_cap, buffer, pcm_bytes_to_frames(pcm_cap, size))) {
++#else
++ if (pcm_read(pcm_cap, buffer, size)) {
++#endif
++ fprintf(stderr, "Unable to read from PCM capture device %u (%s)\n",
++ c_device, pcm_get_error(pcm_cap));
++ rc = errno;
++ break;
++ }
++#ifdef __GNUC__
++ if (pcm_writei(pcm_play, buffer, pcm_bytes_to_frames(pcm_play, size))) {
++#else
++ if (pcm_write(pcm_play, buffer, size)) {
++#endif
++ fprintf(stderr, "Unable to write to PCM playback device %u (%s)\n",
++ p_device, pcm_get_error(pcm_play));
++ break;
++ }
++ } else {
++ usleep(100000);
++ }
++ if (play_cap_time) {
++ clock_gettime(CLOCK_MONOTONIC, &now);
++ if (now.tv_sec > end.tv_sec ||
++ (now.tv_sec == end.tv_sec && now.tv_nsec >= end.tv_nsec))
++ break;
++ }
++ } while(!close_h);
++
++ if (buffer)
++ free(buffer);
++ if (pcm_play != NULL)
++ pcm_close(pcm_play);
++ if (pcm_cap != NULL)
++ pcm_close(pcm_cap);
++ return rc;
++}
+--
+2.6.4
+
diff --git a/meta/meta-mediatek/recipes-multimedia/tinyalsa/tinyalsa/0002-tinyhostless-support-long-sleep.patch b/meta/meta-mediatek/recipes-multimedia/tinyalsa/tinyalsa/0002-tinyhostless-support-long-sleep.patch
new file mode 100644
index 0000000..e16ffaa
--- /dev/null
+++ b/meta/meta-mediatek/recipes-multimedia/tinyalsa/tinyalsa/0002-tinyhostless-support-long-sleep.patch
@@ -0,0 +1,79 @@
+From 88a6a51946a39e68d97bd5173b963003644c970b Mon Sep 17 00:00:00 2001
+From: Hidalgo Huang <hidalgo.huang@mediatek.com>
+Date: Thu, 31 Jan 2019 14:35:08 +0800
+Subject: [PATCH 2/2] tinyhostless: support long sleep
+
+Check argument '-s' to sleep play_cap_time directly.
+
+Signed-off-by: Hidalgo Huang <hidalgo.huang@mediatek.com>
+---
+ utils/tinyhostless.c | 14 ++++++++++----
+ 1 file changed, 10 insertions(+), 4 deletions(-)
+
+diff --git a/utils/tinyhostless.c b/utils/tinyhostless.c
+index e24ae85..9b130df 100755
+--- a/utils/tinyhostless.c
++++ b/utils/tinyhostless.c
+@@ -48,7 +48,7 @@ int play_sample(unsigned int card, unsigned int p_device,
+ unsigned int c_device, unsigned int channels,
+ unsigned int rate, unsigned int bits, unsigned int period_size,
+ unsigned int period_count, unsigned int play_cap_time,
+- int do_loopback);
++ int do_loopback, unsigned int long_sleep);
+
+ static void stream_close(int sig)
+ {
+@@ -69,11 +69,12 @@ int main(int argc, char **argv)
+ unsigned int sample_rate = 48000;
+ unsigned int play_cap_time = 0;
+ unsigned int do_loopback = 0;
++ unsigned int long_sleep = 0;
+
+ if (argc < 2) {
+ fprintf(stderr, "Usage: %s [-D card] [-P playback device]"
+ " [-C capture device] [-p period_size] [-n n_periods]"
+- " [-c num_channels] [-r sample_rate] [-l]"
++ " [-c num_channels] [-r sample_rate] [-l] [-s]"
+ " [-T playback/capture time]\n\n"
+ "Used to enable 'hostless' mode for audio devices with a DSP back-end.\n"
+ "Alternatively, specify '-l' for loopback mode: this program will read\n"
+@@ -128,6 +129,9 @@ int main(int argc, char **argv)
+ if (strcmp(*argv, "-l") == 0) {
+ do_loopback = 1;
+ }
++ if (strcmp(*argv, "-s") == 0) {
++ long_sleep = 1;
++ }
+ if (*argv)
+ argv++;
+ }
+@@ -146,7 +150,7 @@ int main(int argc, char **argv)
+
+ return play_sample(card, p_device, c_device, num_channels, sample_rate,
+ number_bits, period_size, period_count, play_cap_time,
+- do_loopback);
++ do_loopback, long_sleep);
+ }
+
+ static int check_param(struct pcm_params *params, unsigned int param,
+@@ -217,7 +221,7 @@ int play_sample(unsigned int card, unsigned int p_device,
+ unsigned int c_device, unsigned int channels,
+ unsigned int rate, unsigned int bits, unsigned int period_size,
+ unsigned int period_count, unsigned int play_cap_time,
+- int do_loopback)
++ int do_loopback, unsigned int long_sleep)
+ {
+ struct pcm_config config;
+ struct pcm *pcm_play =NULL, *pcm_cap=NULL;
+@@ -322,6 +326,8 @@ int play_sample(unsigned int card, unsigned int p_device,
+ p_device, pcm_get_error(pcm_play));
+ break;
+ }
++ } else if (long_sleep && play_cap_time) {
++ sleep(play_cap_time);
+ } else {
+ usleep(100000);
+ }
+--
+2.6.4
+
diff --git a/meta/meta-mediatek/recipes-multimedia/tinyalsa/tinyalsa_1.%.bbappend b/meta/meta-mediatek/recipes-multimedia/tinyalsa/tinyalsa_1.%.bbappend
new file mode 100644
index 0000000..243e5c8
--- /dev/null
+++ b/meta/meta-mediatek/recipes-multimedia/tinyalsa/tinyalsa_1.%.bbappend
@@ -0,0 +1,5 @@
+FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
+
+SRC_URI_append = " file://0001-tinyhostless-app-that-records-from-mic-and-sends-bac.patch \
+ file://0002-tinyhostless-support-long-sleep.patch \
+"
diff --git a/meta/meta-mediatek/recipes-multimedia/tinyalsa/tinyalsa_1.1.1.bb b/meta/meta-mediatek/recipes-multimedia/tinyalsa/tinyalsa_1.1.1.bb
new file mode 100644
index 0000000..3eb0b0e
--- /dev/null
+++ b/meta/meta-mediatek/recipes-multimedia/tinyalsa/tinyalsa_1.1.1.bb
@@ -0,0 +1,25 @@
+DESCRIPTION = "TinyALSA is a small library to interface with ALSA in \
+the Linux kernel. It is a lightweight alternative to libasound."
+HOMEPAGE = "https://github.com/tinyalsa/tinyalsa"
+SECTION = "libs/multimedia"
+
+LICENSE = "BSD-3-Clause"
+LIC_FILES_CHKSUM = "file://NOTICE;md5=dbdefe400d894b510a9de14813181d0b"
+
+SRCREV = "67b9210d344c34e8d1aa0cfe638abce71c5221ca"
+SRC_URI = "git://github.com/tinyalsa/tinyalsa"
+PV = "1.1.1+git${SRCPV}"
+
+S = "${WORKDIR}/git"
+
+inherit cmake
+
+# tinyalsa is built as a static library. Enable PIC to avoid relocation
+# errors like these:
+#
+# unresolvable R_AARCH64_ADR_PREL_PG_HI21 relocation against symbol `stderr@@GLIBC_2.17'
+CFLAGS += " -fPIC -DPIC "
+
+PACKAGES =+ "${PN}-tools"
+FILES_${PN}-tools = "${bindir}/*"
+FILES_${PN}-staticdev += "/usr/lib/libtinyalsa.a"
diff --git a/meta/meta-mediatek/recipes-multimedia/tinycompress/tinycompress.bb b/meta/meta-mediatek/recipes-multimedia/tinycompress/tinycompress.bb
new file mode 100644
index 0000000..ab512b1
--- /dev/null
+++ b/meta/meta-mediatek/recipes-multimedia/tinycompress/tinycompress.bb
@@ -0,0 +1,21 @@
+DESCRIPTION = "tinycompress"
+LICENSE = "BSD|LGPLv2.1"
+LIC_FILES_CHKSUM = "file://COPYING;md5=cf9105c1a2d4405cbe04bbe3367373a0"
+
+inherit autotools
+
+SRC_URI = "git://git.alsa-project.org/http/tinycompress.git;protocol=http \
+ file://0001-compress-fix-uncertain-no_wake_mode-setting.patch \
+ file://0002-cplay-add-aac-playback-support.patch \
+ file://0003-cplay-add-sbc-playback-support.patch \
+ file://0004-compress-add-api-to-get-fragment-size-and-fragments.patch \
+ file://0005-cplay-support-low-power-playback.patch \
+ file://0006-compress-fix-the-return-value-of-is_codec_supported.patch \
+ file://0007-comrpess-add-api-to-query-aac-mode-support.patch \
+ file://0008-cplay-add-hostless-mode-support.patch \
+ file://0009-cplay-add-xrun-recovery-support.patch \
+"
+
+SRCREV = "d99dc2875843327feb658d674c8f4d710e8bd432"
+
+S = "${WORKDIR}/git"
diff --git a/meta/meta-mediatek/recipes-multimedia/tinycompress/tinycompress/0001-compress-fix-uncertain-no_wake_mode-setting.patch b/meta/meta-mediatek/recipes-multimedia/tinycompress/tinycompress/0001-compress-fix-uncertain-no_wake_mode-setting.patch
new file mode 100644
index 0000000..d50659c
--- /dev/null
+++ b/meta/meta-mediatek/recipes-multimedia/tinycompress/tinycompress/0001-compress-fix-uncertain-no_wake_mode-setting.patch
@@ -0,0 +1,27 @@
+From fe9df9ce4270926a7bf1caf62f14573aeb173411 Mon Sep 17 00:00:00 2001
+From: Hidalgo Huang <hidalgo.huang@mediatek.com>
+Date: Tue, 18 Dec 2018 17:22:14 +0800
+Subject: [PATCH 1/9] compress: fix uncertain no_wake_mode setting
+
+Initialize struct snd_compr_param explicitly.
+
+Signed-off-by: Hidalgo Huang <hidalgo.huang@mediatek.com>
+---
+ src/lib/compress.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/src/lib/compress.c b/src/lib/compress.c
+index bba4fcf..d8d2ffc 100644
+--- a/src/lib/compress.c
++++ b/src/lib/compress.c
+@@ -228,6 +228,7 @@ struct compress *compress_open(unsigned int card, unsigned int device,
+ config->fragments = caps.max_fragments;
+ }
+
++ memset(¶ms, 0, sizeof(struct snd_compr_params));
+ memcpy(compress->config, config, sizeof(*compress->config));
+ fill_compress_params(config, ¶ms);
+
+--
+2.18.0
+
diff --git a/meta/meta-mediatek/recipes-multimedia/tinycompress/tinycompress/0002-cplay-add-aac-playback-support.patch b/meta/meta-mediatek/recipes-multimedia/tinycompress/tinycompress/0002-cplay-add-aac-playback-support.patch
new file mode 100644
index 0000000..4b63ed9
--- /dev/null
+++ b/meta/meta-mediatek/recipes-multimedia/tinycompress/tinycompress/0002-cplay-add-aac-playback-support.patch
@@ -0,0 +1,361 @@
+From 5e87cad41e7762ee5a097b4be451a3415b763229 Mon Sep 17 00:00:00 2001
+From: Hidalgo Huang <hidalgo.huang@mediatek.com>
+Date: Wed, 19 Dec 2018 16:34:31 +0800
+Subject: [PATCH 2/9] cplay: add aac playback support
+
+Support ADTS/ADIF/LOAS/LATM/RAW files.
+
+Signed-off-by: Hidalgo Huang <hidalgo.huang@mediatek.com>
+---
+ include/tinycompress/tinyaac.h | 77 ++++++++++++++
+ src/utils/cplay.c | 187 ++++++++++++++++++++++++++++++++-
+ 2 files changed, 260 insertions(+), 4 deletions(-)
+ create mode 100644 include/tinycompress/tinyaac.h
+
+diff --git a/include/tinycompress/tinyaac.h b/include/tinycompress/tinyaac.h
+new file mode 100644
+index 0000000..c5ee94e
+--- /dev/null
++++ b/include/tinycompress/tinyaac.h
+@@ -0,0 +1,77 @@
++/*
++ * This file is provided under a dual BSD/LGPLv2.1 license. When using or
++ * redistributing this file, you may do so under either license.
++ *
++ * BSD LICENSE
++ *
++ * aac header and prasing
++ * Copyright (c) 2018, MediaTek Inc.
++ * All rights reserved.
++ *
++ * Author: Hidalgo Huang <hidalgo.huang@mediatek.com>
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * Redistributions in binary form must reproduce the above copyright notice,
++ * this list of conditions and the following disclaimer in the documentation
++ * and/or other materials provided with the distribution.
++ * Neither the name of Intel Corporation nor the names of its contributors
++ * may be used to endorse or promote products derived from this software
++ * without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
++ * THE POSSIBILITY OF SUCH DAMAGE.
++ *
++ * LGPL LICENSE
++ *
++ * aac header and parsing
++ * Copyright (c) 2018, MediaTek inc.
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU Lesser General Public License,
++ * version 2.1, as published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
++ * License for more details.
++ *
++ * You should have received a copy of the GNU Lesser General Public License
++ * along with this program; if not, write to
++ * the Free Software Foundation, Inc.,
++ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
++ */
++
++
++#ifndef __TINYAAC_H
++#define __TINYAAC_H
++
++#if defined(__cplusplus)
++extern "C" {
++#endif
++
++#define ADTS_HEADER_PARSE_SIZE (4)
++#define LOAS_HEADER_PARSE_SIZE (2)
++#define ADIF_HEADER_PARSE_SIZE (4)
++
++static const int aac_sample_rates[16] = {
++ 96000, 88200, 64000, 48000,
++ 44100, 32000, 24000, 22050,
++ 16000, 12000, 11025, 8000,
++ 73500, 0, 0, 0,
++};
++
++#endif
+diff --git a/src/utils/cplay.c b/src/utils/cplay.c
+index 3e9fcac..8cb86c6 100644
+--- a/src/utils/cplay.c
++++ b/src/utils/cplay.c
+@@ -72,6 +72,7 @@
+ #include "sound/compress_params.h"
+ #include "tinycompress/tinycompress.h"
+ #include "tinycompress/tinymp3.h"
++#include "tinycompress/tinyaac.h"
+
+ static int verbose;
+ static const unsigned int DEFAULT_CODEC_ID = SND_AUDIOCODEC_PCM;
+@@ -112,6 +113,8 @@ static void usage(void)
+ "-f\tfragments\n\n"
+ "-v\tverbose mode\n"
+ "-h\tPrints this help list\n\n"
++ "-R\tspecify sample rate\n\n"
++ "-C\tspecify channel count\n\n"
+ "Example:\n"
+ "\tcplay -c 1 -d 2 test.mp3\n"
+ "\tcplay -f 5 test.mp3\n\n"
+@@ -128,7 +131,8 @@ static void usage(void)
+
+ void play_samples(char *name, unsigned int card, unsigned int device,
+ unsigned long buffer_size, unsigned int frag,
+- unsigned long codec_id);
++ unsigned long codec_id, unsigned int rate,
++ unsigned int channels);
+
+ struct mp3_header {
+ uint16_t sync;
+@@ -165,6 +169,143 @@ static int parse_mp3_header(struct mp3_header *header, unsigned int *num_channel
+ return 0;
+ }
+
++static int check_aac_adts_frame(FILE *file, unsigned int *num_channels,
++ unsigned int *sample_rate, unsigned int *format, char *file_name)
++{
++ size_t read;
++ unsigned char data[ADTS_HEADER_PARSE_SIZE];
++ unsigned int freq_index;
++
++ read = fread(&data, 1, sizeof(data), file);
++ if (read != sizeof(data))
++ return -1;
++
++ // check syncword
++ if ((data[0] == 0xff) && ((data[1] & 0xf6) == 0xf0)) {
++ *format = (data[1] & 0x8) ? SND_AUDIOSTREAMFORMAT_MP2ADTS :
++ SND_AUDIOSTREAMFORMAT_MP4ADTS;
++ freq_index = (data[2] >> 2) & 0xf;
++ *sample_rate = aac_sample_rates[freq_index];
++ *num_channels = (data[2] & 0x1) << 2 | (data[3] >> 6);
++ return 0;
++ }
++
++ return -1;
++}
++
++static int check_aac_loas_frame(FILE *file, unsigned int *num_channels,
++ unsigned int *sample_rate, unsigned int *format, char *file_name)
++{
++ size_t read;
++ unsigned char data[LOAS_HEADER_PARSE_SIZE];
++
++ read = fread(&data, 1, sizeof(data), file);
++ if (read != sizeof(data))
++ return -1;
++
++ // check AudioSyncStream syncword 0x2b7 (11bits)
++ if ((data[0] == 0x56) && ((data[1] & 0xe0) == 0xe0)) {
++ *format = SND_AUDIOSTREAMFORMAT_MP4LOAS;
++ *num_channels = 2;
++ if (*sample_rate == 0)
++ *sample_rate = 44100;
++ if (*num_channels == 0)
++ *num_channels = 2;
++ return 0;
++ }
++
++ return -1;
++}
++
++static int check_aac_adif_frame(FILE *file, unsigned int *num_channels,
++ unsigned int *sample_rate, unsigned int *format, char *file_name)
++{
++ size_t read;
++ unsigned char data[ADIF_HEADER_PARSE_SIZE];
++
++ read = fread(&data, 1, sizeof(data), file);
++ if (read != sizeof(data))
++ return -1;
++
++ // check syncword
++ if ((data[0] == 'A') && (data[1] == 'D') &&
++ (data[2] == 'I') && (data[3] == 'F') ) {
++ *format = SND_AUDIOSTREAMFORMAT_ADIF;
++ if (*sample_rate == 0)
++ *sample_rate = 44100;
++ if (*num_channels == 0)
++ *num_channels = 2;
++ return 0;
++ }
++
++ return -1;
++}
++
++static int check_aac_latm_frame(FILE *file, unsigned int *num_channels,
++ unsigned int *sample_rate, unsigned int *format, char *file_name)
++{
++ if (strstr(file_name, ".latm")) {
++ *format = SND_AUDIOSTREAMFORMAT_MP4LATM;
++ if (*sample_rate == 0)
++ *sample_rate = 44100;
++ if (*num_channels == 0)
++ *num_channels = 2;
++ return 0;
++ }
++
++ return -1;
++}
++
++static int check_aac_raw_frame(FILE *file, unsigned int *num_channels,
++ unsigned int *sample_rate, unsigned int *format, char *file_name)
++{
++ if (strstr(file_name, ".aac")) {
++ *format = SND_AUDIOSTREAMFORMAT_RAW;
++ if (*sample_rate == 0)
++ *sample_rate = 44100;
++ if (*num_channels == 0)
++ *num_channels = 2;
++ return 0;
++ }
++
++ return -1;
++}
++
++static int parse_aac_header(FILE *file, unsigned int *num_channels,
++ unsigned int *sample_rate, unsigned int *format, char *file_name)
++{
++ int i;
++ fpos_t init_pos;
++ static int (*aac_parsers[])(FILE *,
++ unsigned int *,
++ unsigned int *,
++ unsigned int *,
++ char *) = {
++ check_aac_adts_frame,
++ check_aac_loas_frame,
++ check_aac_adif_frame,
++ check_aac_latm_frame,
++ check_aac_raw_frame,
++ };
++ int parser_num = sizeof(aac_parsers) / sizeof(aac_parsers[0]);
++
++ fgetpos(file, &init_pos);
++
++ for (i = 0; i < parser_num; i++) {
++ fsetpos(file, &init_pos);
++
++ if (aac_parsers[i](file, num_channels, sample_rate, format, file_name) == 0)
++ goto aac_parsed;
++ }
++
++aac_err:
++ return -1;
++
++aac_parsed:
++ fsetpos(file, &init_pos);
++ return 0;
++}
++
+ static int print_time(struct compress *compress)
+ {
+ unsigned int avail;
+@@ -186,12 +327,13 @@ int main(int argc, char **argv)
+ int c, i;
+ unsigned int card = 0, device = 0, frag = 0;
+ unsigned int codec_id = SND_AUDIOCODEC_MP3;
++ unsigned int rate = 0, channels = 0;
+
+ if (argc < 2)
+ usage();
+
+ verbose = 0;
+- while ((c = getopt(argc, argv, "hvb:f:c:d:I:")) != -1) {
++ while ((c = getopt(argc, argv, "hvb:f:c:d:I:R:C:")) != -1) {
+ switch (c) {
+ case 'h':
+ usage();
+@@ -230,6 +372,12 @@ int main(int argc, char **argv)
+ case 'v':
+ verbose = 1;
+ break;
++ case 'R':
++ rate = strtol(optarg, NULL, 10);
++ break;
++ case 'C':
++ channels = strtol(optarg, NULL, 10);
++ break;
+ default:
+ exit(EXIT_FAILURE);
+ }
+@@ -239,7 +387,7 @@ int main(int argc, char **argv)
+
+ file = argv[optind];
+
+- play_samples(file, card, device, buffer_size, frag, codec_id);
++ play_samples(file, card, device, buffer_size, frag, codec_id, rate, channels);
+
+ fprintf(stderr, "Finish Playing.... Close Normally\n");
+ exit(EXIT_SUCCESS);
+@@ -297,9 +445,37 @@ void get_codec_iec(FILE *file, struct compr_config *config,
+ codec->format = 0;
+ }
+
++void get_codec_aac(FILE *file, struct compr_config *config,
++ struct snd_codec *codec, char *file_name,
++ unsigned int specified_rate,
++ unsigned int specified_channels)
++{
++ unsigned int channels, rate, format;
++
++ rate = specified_rate;
++ channels = specified_channels;
++
++ if (parse_aac_header(file, &channels, &rate, &format, file_name) == -1) {
++ fclose(file);
++ exit(EXIT_FAILURE);
++ }
++
++ codec->id = SND_AUDIOCODEC_AAC;
++ codec->ch_in = channels;
++ codec->ch_out = channels;
++ codec->sample_rate = rate;
++ codec->bit_rate = 0;
++ codec->rate_control = 0;
++ codec->profile = SND_AUDIOPROFILE_AAC;
++ codec->level = 0;
++ codec->ch_mode = 0;
++ codec->format = format;
++}
++
+ void play_samples(char *name, unsigned int card, unsigned int device,
+ unsigned long buffer_size, unsigned int frag,
+- unsigned long codec_id)
++ unsigned long codec_id, unsigned int rate,
++ unsigned int channels)
+ {
+ struct compr_config config;
+ struct snd_codec codec;
+@@ -323,6 +499,9 @@ void play_samples(char *name, unsigned int card, unsigned int device,
+ case SND_AUDIOCODEC_IEC61937:
+ get_codec_iec(file, &config, &codec);
+ break;
++ case SND_AUDIOCODEC_AAC:
++ get_codec_aac(file, &config, &codec, name, rate, channels);
++ break;
+ default:
+ fprintf(stderr, "codec ID %ld is not supported\n", codec_id);
+ exit(EXIT_FAILURE);
+--
+2.18.0
+
diff --git a/meta/meta-mediatek/recipes-multimedia/tinycompress/tinycompress/0003-cplay-add-sbc-playback-support.patch b/meta/meta-mediatek/recipes-multimedia/tinycompress/tinycompress/0003-cplay-add-sbc-playback-support.patch
new file mode 100644
index 0000000..a47ab02
--- /dev/null
+++ b/meta/meta-mediatek/recipes-multimedia/tinycompress/tinycompress/0003-cplay-add-sbc-playback-support.patch
@@ -0,0 +1,253 @@
+From 73e54158d4b9e5d7b2c38f528ae9cf261a7cfe45 Mon Sep 17 00:00:00 2001
+From: Hidalgo Huang <hidalgo.huang@mediatek.com>
+Date: Tue, 25 Dec 2018 15:33:50 +0800
+Subject: [PATCH 3/9] cplay: add sbc playback support
+
+Support .sbc files.
+
+Signed-off-by: Hidalgo Huang <hidalgo.huang@mediatek.com>
+---
+ include/sound/compress_params.h | 21 ++++++++-
+ include/tinycompress/tinysbc.h | 76 +++++++++++++++++++++++++++++++++
+ src/utils/cplay.c | 61 ++++++++++++++++++++++++++
+ 3 files changed, 157 insertions(+), 1 deletion(-)
+ create mode 100644 include/tinycompress/tinysbc.h
+
+diff --git a/include/sound/compress_params.h b/include/sound/compress_params.h
+index 7286556..6f3aa33 100644
+--- a/include/sound/compress_params.h
++++ b/include/sound/compress_params.h
+@@ -39,8 +39,9 @@
+ #define SND_AUDIOCODEC_G723_1 ((__u32) 0x0000000C)
+ #define SND_AUDIOCODEC_G729 ((__u32) 0x0000000D)
+ #define SND_AUDIOCODEC_BESPOKE ((__u32) 0x0000000E)
++#define SND_AUDIOCODEC_SBC ((__u32) 0x0000000F)
+
+-#define SND_AUDIOCODEC_MAX SND_AUDIOCODEC_BESPOKE
++#define SND_AUDIOCODEC_MAX SND_AUDIOCODEC_SBC
+ #define SND_AUDIOPROFILE_PCM ((__u32) 0x00000001)
+
+ #define SND_AUDIOCHANMODE_MP3_MONO ((__u32) 0x00000001)
+@@ -170,6 +171,16 @@
+ #define SND_AUDIOMODE_G729_ANNEX_A ((__u32) 0x00000001)
+ #define SND_AUDIOMODE_G729_ANNEX_B ((__u32) 0x00000002)
+
++#define SND_AUDIOPROFILE_SBC ((__u32) 0x00000001)
++
++#define SND_AUDIOCHANMODE_SBC_MONO ((__u32) 0x00000001)
++#define SND_AUDIOCHANMODE_SBC_STEREO ((__u32) 0x00000002)
++#define SND_AUDIOCHANMODE_SBC_JOINTSTEREO ((__u32) 0x00000004)
++#define SND_AUDIOCHANMODE_SBC_DUAL ((__u32) 0x00000008)
++
++#define SND_BIT_ALLOC_SBC_LOUDNESS ((__u32) 0x00000001)
++#define SND_BIT_ALLOC_SBC_SNR ((__u32) 0x00000002)
++
+ #define SND_RATECONTROLMODE_CONSTANTBITRATE ((__u32) 0x00000001)
+ #define SND_RATECONTROLMODE_VARIABLEBITRATE ((__u32) 0x00000002)
+
+@@ -201,12 +212,20 @@ struct snd_enc_generic {
+ __s32 reserved[15];
+ }__attribute__((packed, aligned(4)));
+
++struct snd_enc_sbc {
++ __u32 bitpool;
++ __u32 num_subbands;
++ __u32 num_blocks;
++ __u32 bit_alloc;
++} __attribute__((packed, aligned(4)));
++
+ union snd_codec_options {
+ struct snd_enc_wma wma;
+ struct snd_enc_vorbis vorbis;
+ struct snd_enc_real real;
+ struct snd_enc_flac flac;
+ struct snd_enc_generic generic;
++ struct snd_enc_sbc sbc;
+ }__attribute__((packed, aligned(4)));
+
+ struct snd_codec_desc {
+diff --git a/include/tinycompress/tinysbc.h b/include/tinycompress/tinysbc.h
+new file mode 100644
+index 0000000..f579ca7
+--- /dev/null
++++ b/include/tinycompress/tinysbc.h
+@@ -0,0 +1,76 @@
++/*
++ * This file is provided under a dual BSD/LGPLv2.1 license. When using or
++ * redistributing this file, you may do so under either license.
++ *
++ * BSD LICENSE
++ *
++ * aac header and prasing
++ * Copyright (c) 2018, MediaTek Inc.
++ * All rights reserved.
++ *
++ * Author: Hidalgo Huang <hidalgo.huang@mediatek.com>
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * Redistributions in binary form must reproduce the above copyright notice,
++ * this list of conditions and the following disclaimer in the documentation
++ * and/or other materials provided with the distribution.
++ * Neither the name of Intel Corporation nor the names of its contributors
++ * may be used to endorse or promote products derived from this software
++ * without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
++ * THE POSSIBILITY OF SUCH DAMAGE.
++ *
++ * LGPL LICENSE
++ *
++ * aac header and parsing
++ * Copyright (c) 2018, MediaTek inc.
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU Lesser General Public License,
++ * version 2.1, as published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
++ * License for more details.
++ *
++ * You should have received a copy of the GNU Lesser General Public License
++ * along with this program; if not, write to
++ * the Free Software Foundation, Inc.,
++ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
++ */
++
++
++#ifndef __TINYSBC_H
++#define __TINYSBC_H
++
++#if defined(__cplusplus)
++extern "C" {
++#endif
++
++#define SBC_HEADER_PARSE_SIZE (4)
++
++static const int sbc_sample_rates[4] = {
++ 16000, 32000, 44100, 48000,
++};
++
++static const int sbc_channels[4] = {
++ 1, 2, 2, 2,
++};
++
++#endif
+diff --git a/src/utils/cplay.c b/src/utils/cplay.c
+index 8cb86c6..e5d2a9d 100644
+--- a/src/utils/cplay.c
++++ b/src/utils/cplay.c
+@@ -73,6 +73,7 @@
+ #include "tinycompress/tinycompress.h"
+ #include "tinycompress/tinymp3.h"
+ #include "tinycompress/tinyaac.h"
++#include "tinycompress/tinysbc.h"
+
+ static int verbose;
+ static const unsigned int DEFAULT_CODEC_ID = SND_AUDIOCODEC_PCM;
+@@ -98,6 +99,7 @@ static const struct {
+ #ifdef SND_AUDIOCODEC_BESPOKE
+ { "BESPOKE", SND_AUDIOCODEC_BESPOKE },
+ #endif
++ { "SBC", SND_AUDIOCODEC_SBC },
+ };
+ #define CPLAY_NUM_CODEC_IDS (sizeof(codec_ids) / sizeof(codec_ids[0]))
+
+@@ -306,6 +308,35 @@ aac_parsed:
+ return 0;
+ }
+
++static int parse_sbc_header(FILE *file, unsigned int *num_channels,
++ unsigned int *sample_rate)
++{
++ int i;
++ fpos_t init_pos;
++ size_t read;
++ unsigned char data[SBC_HEADER_PARSE_SIZE];
++ int ret = 0;
++
++ fgetpos(file, &init_pos);
++
++ read = fread(&data, 1, sizeof(data), file);
++ if (read != sizeof(data))
++ goto sbc_err;
++
++ if (data[0] != 0x9c)
++ goto sbc_err;
++
++ *num_channels = sbc_channels[(data[1] >> 2) & 0x3];
++ *sample_rate = sbc_sample_rates[(data[1] >> 6) & 0x3];
++
++ fsetpos(file, &init_pos);
++ return 0;
++
++sbc_err:
++ fsetpos(file, &init_pos);
++ return -1;
++}
++
+ static int print_time(struct compress *compress)
+ {
+ unsigned int avail;
+@@ -472,6 +503,33 @@ void get_codec_aac(FILE *file, struct compr_config *config,
+ codec->format = format;
+ }
+
++void get_codec_sbc(FILE *file, struct compr_config *config,
++ struct snd_codec *codec)
++{
++ unsigned int channels, rate;
++
++ if (parse_sbc_header(file, &channels, &rate) == -1) {
++ fclose(file);
++ exit(EXIT_FAILURE);
++ }
++
++ codec->id = SND_AUDIOCODEC_SBC;
++ codec->ch_in = channels;
++ codec->ch_out = channels;
++ codec->sample_rate = rate;
++ if (!codec->sample_rate) {
++ fprintf(stderr, "invalid sample rate %d\n", rate);
++ fclose(file);
++ exit(EXIT_FAILURE);
++ }
++ codec->bit_rate = 0;
++ codec->rate_control = 0;
++ codec->profile = SND_AUDIOPROFILE_SBC;
++ codec->level = 0;
++ codec->ch_mode = 0;
++ codec->format = 0;
++}
++
+ void play_samples(char *name, unsigned int card, unsigned int device,
+ unsigned long buffer_size, unsigned int frag,
+ unsigned long codec_id, unsigned int rate,
+@@ -502,6 +560,9 @@ void play_samples(char *name, unsigned int card, unsigned int device,
+ case SND_AUDIOCODEC_AAC:
+ get_codec_aac(file, &config, &codec, name, rate, channels);
+ break;
++ case SND_AUDIOCODEC_SBC:
++ get_codec_sbc(file, &config, &codec);
++ break;
+ default:
+ fprintf(stderr, "codec ID %ld is not supported\n", codec_id);
+ exit(EXIT_FAILURE);
+--
+2.18.0
+
diff --git a/meta/meta-mediatek/recipes-multimedia/tinycompress/tinycompress/0004-compress-add-api-to-get-fragment-size-and-fragments.patch b/meta/meta-mediatek/recipes-multimedia/tinycompress/tinycompress/0004-compress-add-api-to-get-fragment-size-and-fragments.patch
new file mode 100644
index 0000000..3922471
--- /dev/null
+++ b/meta/meta-mediatek/recipes-multimedia/tinycompress/tinycompress/0004-compress-add-api-to-get-fragment-size-and-fragments.patch
@@ -0,0 +1,100 @@
+From f17496d78a75fbc7c2b9eab8e83e8eda25789632 Mon Sep 17 00:00:00 2001
+From: Hidalgo Huang <hidalgo.huang@mediatek.com>
+Date: Mon, 21 Jan 2019 10:09:13 +0800
+Subject: [PATCH 4/9] compress: add api to get fragment size and fragments
+
+Implement get_fragment_config().
+
+Signed-off-by: Hidalgo Huang <hidalgo.huang@mediatek.com>
+---
+ include/tinycompress/tinycompress.h | 10 +++++++
+ src/lib/compress.c | 41 +++++++++++++++++++++++++++++
+ 2 files changed, 51 insertions(+)
+
+diff --git a/include/tinycompress/tinycompress.h b/include/tinycompress/tinycompress.h
+index f0fae30..c3ef6b8 100644
+--- a/include/tinycompress/tinycompress.h
++++ b/include/tinycompress/tinycompress.h
+@@ -82,6 +82,13 @@ struct compr_gapless_mdata {
+ __u32 encoder_padding;
+ };
+
++struct compr_fragment_config {
++ __u32 min_fragment_size;
++ __u32 max_fragment_size;
++ __u32 min_fragments;
++ __u32 max_fragments;
++};
++
+ #define COMPRESS_OUT 0x20000000
+ #define COMPRESS_IN 0x10000000
+
+@@ -276,6 +283,9 @@ int is_compress_ready(struct compress *compress);
+ /* Returns a human readable reason for the last error */
+ const char *compress_get_error(struct compress *compress);
+
++int get_fragment_config(unsigned int card, unsigned int device,
++ unsigned int flags, struct compr_fragment_config *fragment_config);
++
+ #if defined(__cplusplus)
+ } // extern "C"
+ #endif
+diff --git a/src/lib/compress.c b/src/lib/compress.c
+index d8d2ffc..67cab2b 100644
+--- a/src/lib/compress.c
++++ b/src/lib/compress.c
+@@ -172,6 +172,23 @@ fill_compress_params(struct compr_config *config, struct snd_compr_params *param
+ memcpy(¶ms->codec, config->codec, sizeof(params->codec));
+ }
+
++static int _get_fragment_config(int fd, struct compr_fragment_config *fragment_config)
++{
++ struct snd_compr_caps caps;
++
++ if (ioctl(fd, SNDRV_COMPRESS_GET_CAPS, &caps)) {
++ oops(&bad_compress, errno, "cannot get device caps");
++ return -1;
++ }
++
++ fragment_config->min_fragment_size = caps.min_fragment_size;
++ fragment_config->max_fragment_size = caps.max_fragment_size;
++ fragment_config->min_fragments = caps.min_fragments;
++ fragment_config->max_fragments = caps.max_fragments;
++
++ return 0;
++}
++
+ struct compress *compress_open(unsigned int card, unsigned int device,
+ unsigned int flags, struct compr_config *config)
+ {
+@@ -583,3 +600,27 @@ int compress_wait(struct compress *compress, int timeout_ms)
+ return oops(compress, EIO, "poll signalled unhandled event");
+ }
+
++int get_fragment_config(unsigned int card, unsigned int device,
++ unsigned int flags, struct compr_fragment_config *fragment_config)
++{
++ unsigned int dev_flag;
++ int ret;
++ int fd;
++ char fn[256];
++
++ snprintf(fn, sizeof(fn), "/dev/snd/comprC%uD%u", card, device);
++
++ if (flags & COMPRESS_OUT)
++ dev_flag = O_RDONLY;
++ else
++ dev_flag = O_WRONLY;
++
++ fd = open(fn, dev_flag);
++ if (fd < 0)
++ return oops(&bad_compress, errno, "cannot open device '%s'", fn);
++
++ ret = _get_fragment_config(fd, fragment_config);
++
++ close(fd);
++ return ret;
++}
+--
+2.18.0
+
diff --git a/meta/meta-mediatek/recipes-multimedia/tinycompress/tinycompress/0005-cplay-support-low-power-playback.patch b/meta/meta-mediatek/recipes-multimedia/tinycompress/tinycompress/0005-cplay-support-low-power-playback.patch
new file mode 100644
index 0000000..7954d73
--- /dev/null
+++ b/meta/meta-mediatek/recipes-multimedia/tinycompress/tinycompress/0005-cplay-support-low-power-playback.patch
@@ -0,0 +1,68 @@
+From abf3dfe62b2ab7fefd65069d6fbce911b238862b Mon Sep 17 00:00:00 2001
+From: Hidalgo Huang <hidalgo.huang@mediatek.com>
+Date: Mon, 21 Jan 2019 10:12:48 +0800
+Subject: [PATCH 5/9] cplay: support low power playback
+
+Use max fragment size for low power playback.
+
+Signed-off-by: Hidalgo Huang <hidalgo.huang@mediatek.com>
+---
+ src/utils/cplay.c | 16 +++++++++++++++-
+ 1 file changed, 15 insertions(+), 1 deletion(-)
+
+diff --git a/src/utils/cplay.c b/src/utils/cplay.c
+index e5d2a9d..6dc3096 100644
+--- a/src/utils/cplay.c
++++ b/src/utils/cplay.c
+@@ -117,6 +117,7 @@ static void usage(void)
+ "-h\tPrints this help list\n\n"
+ "-R\tspecify sample rate\n\n"
+ "-C\tspecify channel count\n\n"
++ "-L\tlow power mode\n\n"
+ "Example:\n"
+ "\tcplay -c 1 -d 2 test.mp3\n"
+ "\tcplay -f 5 test.mp3\n\n"
+@@ -359,12 +360,13 @@ int main(int argc, char **argv)
+ unsigned int card = 0, device = 0, frag = 0;
+ unsigned int codec_id = SND_AUDIOCODEC_MP3;
+ unsigned int rate = 0, channels = 0;
++ int low_power = 0;
+
+ if (argc < 2)
+ usage();
+
+ verbose = 0;
+- while ((c = getopt(argc, argv, "hvb:f:c:d:I:R:C:")) != -1) {
++ while ((c = getopt(argc, argv, "hvb:f:c:d:I:R:C:L")) != -1) {
+ switch (c) {
+ case 'h':
+ usage();
+@@ -409,6 +411,9 @@ int main(int argc, char **argv)
+ case 'C':
+ channels = strtol(optarg, NULL, 10);
+ break;
++ case 'L':
++ low_power = 1;
++ break;
+ default:
+ exit(EXIT_FAILURE);
+ }
+@@ -418,6 +423,15 @@ int main(int argc, char **argv)
+
+ file = argv[optind];
+
++ if (low_power) {
++ struct compr_fragment_config fragment_config;
++
++ if (get_fragment_config(card, device, COMPRESS_IN, &fragment_config) == 0) {
++ frag = fragment_config.min_fragments;
++ buffer_size = fragment_config.max_fragment_size * frag;
++ }
++ }
++
+ play_samples(file, card, device, buffer_size, frag, codec_id, rate, channels);
+
+ fprintf(stderr, "Finish Playing.... Close Normally\n");
+--
+2.18.0
+
diff --git a/meta/meta-mediatek/recipes-multimedia/tinycompress/tinycompress/0006-compress-fix-the-return-value-of-is_codec_supported.patch b/meta/meta-mediatek/recipes-multimedia/tinycompress/tinycompress/0006-compress-fix-the-return-value-of-is_codec_supported.patch
new file mode 100644
index 0000000..7193ccc
--- /dev/null
+++ b/meta/meta-mediatek/recipes-multimedia/tinycompress/tinycompress/0006-compress-fix-the-return-value-of-is_codec_supported.patch
@@ -0,0 +1,32 @@
+From feaa0588eadaed43a82dcf3b763f3bd059685e33 Mon Sep 17 00:00:00 2001
+From: Hidalgo Huang <hidalgo.huang@mediatek.com>
+Date: Thu, 21 Feb 2019 14:58:24 +0800
+Subject: [PATCH 6/9] compress: fix the return value of is_codec_supported()
+
+Return false when failed to open device node.
+
+Signed-off-by: Hidalgo Huang <hidalgo.huang@mediatek.com>
+---
+ src/lib/compress.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/src/lib/compress.c b/src/lib/compress.c
+index 67cab2b..5cb29e4 100644
+--- a/src/lib/compress.c
++++ b/src/lib/compress.c
+@@ -558,8 +558,10 @@ bool is_codec_supported(unsigned int card, unsigned int device,
+ dev_flag = O_WRONLY;
+
+ fd = open(fn, dev_flag);
+- if (fd < 0)
+- return oops(&bad_compress, errno, "cannot open device '%s'", fn);
++ if (fd < 0) {
++ oops(&bad_compress, errno, "cannot open device '%s'", fn);
++ return false;
++ }
+
+ ret = _is_codec_type_supported(fd, codec);
+
+--
+2.18.0
+
diff --git a/meta/meta-mediatek/recipes-multimedia/tinycompress/tinycompress/0007-comrpess-add-api-to-query-aac-mode-support.patch b/meta/meta-mediatek/recipes-multimedia/tinycompress/tinycompress/0007-comrpess-add-api-to-query-aac-mode-support.patch
new file mode 100644
index 0000000..d00d7d3
--- /dev/null
+++ b/meta/meta-mediatek/recipes-multimedia/tinycompress/tinycompress/0007-comrpess-add-api-to-query-aac-mode-support.patch
@@ -0,0 +1,95 @@
+From f6b42b5bffb1783905d7f3869b73c1228b3471d2 Mon Sep 17 00:00:00 2001
+From: Hidalgo Huang <hidalgo.huang@mediatek.com>
+Date: Mon, 18 Mar 2019 14:56:45 +0800
+Subject: [PATCH 7/9] comrpess: add api to query aac mode support
+
+Implement is_acc_mode_supported().
+
+Signed-off-by: Hidalgo Huang <hidalgo.huang@mediatek.com>
+---
+ include/tinycompress/tinycompress.h | 3 ++
+ src/lib/compress.c | 50 +++++++++++++++++++++++++++++
+ 2 files changed, 53 insertions(+)
+
+diff --git a/include/tinycompress/tinycompress.h b/include/tinycompress/tinycompress.h
+index c3ef6b8..a087a85 100644
+--- a/include/tinycompress/tinycompress.h
++++ b/include/tinycompress/tinycompress.h
+@@ -286,6 +286,9 @@ const char *compress_get_error(struct compress *compress);
+ int get_fragment_config(unsigned int card, unsigned int device,
+ unsigned int flags, struct compr_fragment_config *fragment_config);
+
++bool is_aac_mode_supported(unsigned int card, unsigned int device,
++ unsigned int flags, unsigned int mode);
++
+ #if defined(__cplusplus)
+ } // extern "C"
+ #endif
+diff --git a/src/lib/compress.c b/src/lib/compress.c
+index 5cb29e4..e2644ea 100644
+--- a/src/lib/compress.c
++++ b/src/lib/compress.c
+@@ -189,6 +189,16 @@ static int _get_fragment_config(int fd, struct compr_fragment_config *fragment_c
+ return 0;
+ }
+
++static int _get_codec_caps(int fd, struct snd_compr_codec_caps *caps)
++{
++ if (ioctl(fd, SNDRV_COMPRESS_GET_CODEC_CAPS, caps)) {
++ oops(&bad_compress, errno, "cannot get codec caps");
++ return -1;
++ }
++
++ return 0;
++}
++
+ struct compress *compress_open(unsigned int card, unsigned int device,
+ unsigned int flags, struct compr_config *config)
+ {
+@@ -626,3 +636,43 @@ int get_fragment_config(unsigned int card, unsigned int device,
+ close(fd);
+ return ret;
+ }
++
++bool is_aac_mode_supported(unsigned int card, unsigned int device,
++ unsigned int flags, unsigned int mode)
++{
++ unsigned int dev_flag;
++ bool ret = false;
++ int fd;
++ char fn[256];
++ struct snd_compr_codec_caps codec_caps;
++ unsigned int i;
++
++ snprintf(fn, sizeof(fn), "/dev/snd/comprC%uD%u", card, device);
++
++ if (flags & COMPRESS_OUT)
++ dev_flag = O_RDONLY;
++ else
++ dev_flag = O_WRONLY;
++
++ fd = open(fn, dev_flag);
++ if (fd < 0) {
++ oops(&bad_compress, errno, "cannot open device '%s'", fn);
++ return false;
++ }
++
++ codec_caps.codec = SND_AUDIOCODEC_AAC;
++
++ if (_get_codec_caps(fd, &codec_caps) < 0)
++ goto endofsupport;
++
++ for (i = 0; i < codec_caps.num_descriptors; i++) {
++ if (codec_caps.descriptor[i].modes & mode) {
++ ret = true;
++ goto endofsupport;
++ }
++ }
++
++endofsupport:
++ close(fd);
++ return ret;
++}
+--
+2.18.0
+
diff --git a/meta/meta-mediatek/recipes-multimedia/tinycompress/tinycompress/0008-cplay-add-hostless-mode-support.patch b/meta/meta-mediatek/recipes-multimedia/tinycompress/tinycompress/0008-cplay-add-hostless-mode-support.patch
new file mode 100644
index 0000000..198810b
--- /dev/null
+++ b/meta/meta-mediatek/recipes-multimedia/tinycompress/tinycompress/0008-cplay-add-hostless-mode-support.patch
@@ -0,0 +1,122 @@
+From 2d15d53d4e6775edddcf3980e98a88bc53552fff Mon Sep 17 00:00:00 2001
+From: Hidalgo Huang <hidalgo.huang@mediatek.com>
+Date: Mon, 23 Dec 2019 16:45:26 +0800
+Subject: [PATCH 8/9] cplay: add hostless mode support
+
+E.g. cplay -c 0 -d 27 -H -T 1000 /data/misc/mtk-audio-patterns/sample.mp3
+
+Signed-off-by: Hidalgo Huang <hidalgo.huang@mediatek.com>
+---
+ src/utils/cplay.c | 36 ++++++++++++++++++++++++++++++++----
+ 1 file changed, 32 insertions(+), 4 deletions(-)
+
+diff --git a/src/utils/cplay.c b/src/utils/cplay.c
+index 6dc3096..2198409 100644
+--- a/src/utils/cplay.c
++++ b/src/utils/cplay.c
+@@ -118,6 +118,8 @@ static void usage(void)
+ "-R\tspecify sample rate\n\n"
+ "-C\tspecify channel count\n\n"
+ "-L\tlow power mode\n\n"
++ "-H\thostless mode\n\n"
++ "-T\thostless play time in seconds\n\n"
+ "Example:\n"
+ "\tcplay -c 1 -d 2 test.mp3\n"
+ "\tcplay -f 5 test.mp3\n\n"
+@@ -135,7 +137,7 @@ static void usage(void)
+ void play_samples(char *name, unsigned int card, unsigned int device,
+ unsigned long buffer_size, unsigned int frag,
+ unsigned long codec_id, unsigned int rate,
+- unsigned int channels);
++ unsigned int channels, int hostless, unsigned int play_time);
+
+ struct mp3_header {
+ uint16_t sync;
+@@ -361,12 +363,14 @@ int main(int argc, char **argv)
+ unsigned int codec_id = SND_AUDIOCODEC_MP3;
+ unsigned int rate = 0, channels = 0;
+ int low_power = 0;
++ int hostless = 0;
++ unsigned int play_time = 10;
+
+ if (argc < 2)
+ usage();
+
+ verbose = 0;
+- while ((c = getopt(argc, argv, "hvb:f:c:d:I:R:C:L")) != -1) {
++ while ((c = getopt(argc, argv, "hvb:f:c:d:I:R:C:LHT:")) != -1) {
+ switch (c) {
+ case 'h':
+ usage();
+@@ -414,6 +418,12 @@ int main(int argc, char **argv)
+ case 'L':
+ low_power = 1;
+ break;
++ case 'H':
++ hostless = 1;
++ break;
++ case 'T':
++ play_time = strtol(optarg, NULL, 10);
++ break;
+ default:
+ exit(EXIT_FAILURE);
+ }
+@@ -432,7 +442,7 @@ int main(int argc, char **argv)
+ }
+ }
+
+- play_samples(file, card, device, buffer_size, frag, codec_id, rate, channels);
++ play_samples(file, card, device, buffer_size, frag, codec_id, rate, channels, hostless, play_time);
+
+ fprintf(stderr, "Finish Playing.... Close Normally\n");
+ exit(EXIT_SUCCESS);
+@@ -547,7 +557,7 @@ void get_codec_sbc(FILE *file, struct compr_config *config,
+ void play_samples(char *name, unsigned int card, unsigned int device,
+ unsigned long buffer_size, unsigned int frag,
+ unsigned long codec_id, unsigned int rate,
+- unsigned int channels)
++ unsigned int channels, int hostless, unsigned int play_time)
+ {
+ struct compr_config config;
+ struct snd_codec codec;
+@@ -592,6 +602,11 @@ void play_samples(char *name, unsigned int card, unsigned int device,
+ }
+ config.codec = &codec;
+
++ if (hostless) {
++ codec.reserved[2] &= 0xffff0000;
++ codec.reserved[2] |= 0x6c68;
++ }
++
+ compress = compress_open(card, device, COMPRESS_IN, &config);
+ if (!compress || !is_compress_ready(compress)) {
+ fprintf(stderr, "Unable to open Compress device %d:%d\n",
+@@ -601,6 +616,13 @@ void play_samples(char *name, unsigned int card, unsigned int device,
+ };
+ if (verbose)
+ printf("%s: Opened compress device\n", __func__);
++
++ if (hostless) {
++ compress_start(compress);
++ sleep(play_time);
++ goto HOSTLESS_EXIT;
++ }
++
+ size = config.fragments * config.fragment_size;
+ buffer = malloc(size);
+ if (!buffer) {
+@@ -670,5 +692,11 @@ FILE_EXIT:
+ if (verbose)
+ printf("%s: exit failure\n", __func__);
+ exit(EXIT_FAILURE);
++HOSTLESS_EXIT:
++ if (verbose)
++ printf("%s: hostless exit success\n", __func__);
++ compress_drain(compress);
++ fclose(file);
++ compress_close(compress);
+ }
+
+--
+2.18.0
+
diff --git a/meta/meta-mediatek/recipes-multimedia/tinycompress/tinycompress/0009-cplay-add-xrun-recovery-support.patch b/meta/meta-mediatek/recipes-multimedia/tinycompress/tinycompress/0009-cplay-add-xrun-recovery-support.patch
new file mode 100644
index 0000000..102e241
--- /dev/null
+++ b/meta/meta-mediatek/recipes-multimedia/tinycompress/tinycompress/0009-cplay-add-xrun-recovery-support.patch
@@ -0,0 +1,161 @@
+From a9cd8f898d032098921b7ee8baee7e407bea7ab2 Mon Sep 17 00:00:00 2001
+From: Hidalgo Huang <hidalgo.huang@mediatek.com>
+Date: Tue, 23 Jun 2020 19:54:58 +0800
+Subject: [PATCH 9/9] cplay: add xrun recovery support
+
+E.g. cplay -c 0 -d 24 -L -x /data/misc/mtk-audio-patterns/sample.mp3
+
+Signed-off-by: Hidalgo Huang <hidalgo.huang@mediatek.com>
+---
+ src/lib/compress.c | 12 ++++++++++--
+ src/utils/cplay.c | 33 ++++++++++++++++++++++++++++-----
+ 2 files changed, 38 insertions(+), 7 deletions(-)
+
+diff --git a/src/lib/compress.c b/src/lib/compress.c
+index e2644ea..a268b26 100644
+--- a/src/lib/compress.c
++++ b/src/lib/compress.c
+@@ -110,6 +110,9 @@ static int oops(struct compress *compress, int e, const char *fmt, ...)
+ ": %s", strerror(e));
+ errno = e;
+
++ if (e == EPIPE)
++ return -e;
++
+ return -1;
+ }
+
+@@ -340,7 +343,7 @@ int compress_write(struct compress *compress, const void *buf, unsigned int size
+ if (!is_compress_ready(compress))
+ return oops(compress, ENODEV, "device not ready");
+ fds.fd = compress->fd;
+- fds.events = POLLOUT;
++ fds.events = POLLOUT | POLLNVAL;
+
+ /*TODO: treat auto start here first */
+ while (size) {
+@@ -356,6 +359,9 @@ int compress_write(struct compress *compress, const void *buf, unsigned int size
+ return total;
+
+ ret = poll(&fds, 1, compress->max_poll_wait_ms);
++ if (fds.revents & POLLNVAL) {
++ return oops(compress, EPIPE, "poll returned nval!");
++ }
+ if (fds.revents & POLLERR) {
+ return oops(compress, EIO, "poll returned error!");
+ }
+@@ -595,10 +601,12 @@ int compress_wait(struct compress *compress, int timeout_ms)
+ int ret;
+
+ fds.fd = compress->fd;
+- fds.events = POLLOUT | POLLIN;
++ fds.events = POLLOUT | POLLIN | POLLNVAL;
+
+ ret = poll(&fds, 1, timeout_ms);
+ if (ret > 0) {
++ if (fds.revents & POLLNVAL)
++ return oops(compress, EIO, "poll returned nval!");
+ if (fds.revents & POLLERR)
+ return oops(compress, EIO, "poll returned error!");
+ if (fds.revents & (POLLOUT | POLLIN))
+diff --git a/src/utils/cplay.c b/src/utils/cplay.c
+index 2198409..85c12c2 100644
+--- a/src/utils/cplay.c
++++ b/src/utils/cplay.c
+@@ -120,6 +120,7 @@ static void usage(void)
+ "-L\tlow power mode\n\n"
+ "-H\thostless mode\n\n"
+ "-T\thostless play time in seconds\n\n"
++ "-x\tdo xrun recovery\n\n"
+ "Example:\n"
+ "\tcplay -c 1 -d 2 test.mp3\n"
+ "\tcplay -f 5 test.mp3\n\n"
+@@ -137,7 +138,8 @@ static void usage(void)
+ void play_samples(char *name, unsigned int card, unsigned int device,
+ unsigned long buffer_size, unsigned int frag,
+ unsigned long codec_id, unsigned int rate,
+- unsigned int channels, int hostless, unsigned int play_time);
++ unsigned int channels, int hostless, unsigned int play_time,
++ int xrun_recovery);
+
+ struct mp3_header {
+ uint16_t sync;
+@@ -365,12 +367,13 @@ int main(int argc, char **argv)
+ int low_power = 0;
+ int hostless = 0;
+ unsigned int play_time = 10;
++ int xrun_recovery = 0;
+
+ if (argc < 2)
+ usage();
+
+ verbose = 0;
+- while ((c = getopt(argc, argv, "hvb:f:c:d:I:R:C:LHT:")) != -1) {
++ while ((c = getopt(argc, argv, "hvb:f:c:d:I:R:C:LHT:x")) != -1) {
+ switch (c) {
+ case 'h':
+ usage();
+@@ -424,6 +427,9 @@ int main(int argc, char **argv)
+ case 'T':
+ play_time = strtol(optarg, NULL, 10);
+ break;
++ case 'x':
++ xrun_recovery = 1;
++ break;
+ default:
+ exit(EXIT_FAILURE);
+ }
+@@ -442,7 +448,7 @@ int main(int argc, char **argv)
+ }
+ }
+
+- play_samples(file, card, device, buffer_size, frag, codec_id, rate, channels, hostless, play_time);
++ play_samples(file, card, device, buffer_size, frag, codec_id, rate, channels, hostless, play_time, xrun_recovery);
+
+ fprintf(stderr, "Finish Playing.... Close Normally\n");
+ exit(EXIT_SUCCESS);
+@@ -557,7 +563,8 @@ void get_codec_sbc(FILE *file, struct compr_config *config,
+ void play_samples(char *name, unsigned int card, unsigned int device,
+ unsigned long buffer_size, unsigned int frag,
+ unsigned long codec_id, unsigned int rate,
+- unsigned int channels, int hostless, unsigned int play_time)
++ unsigned int channels, int hostless, unsigned int play_time,
++ int xrun_recovery)
+ {
+ struct compr_config config;
+ struct snd_codec codec;
+@@ -659,6 +666,21 @@ void play_samples(char *name, unsigned int card, unsigned int device,
+ num_read = fread(buffer, 1, size, file);
+ if (num_read > 0) {
+ wrote = compress_write(compress, buffer, num_read);
++ if (wrote == -EPIPE) {
++ fprintf(stderr, "Try to recover %s ...\n", compress_get_error(compress));
++ compress_close(compress);
++ compress = 0;
++ compress = compress_open(card, device, COMPRESS_IN, &config);
++ if (!compress || !is_compress_ready(compress)) {
++ fprintf(stderr, "Unable to recover Compress device %d:%d\n",
++ card, device);
++ fprintf(stderr, "ERR: %s\n", compress_get_error(compress));
++ goto BUF_EXIT;
++ }
++ wrote = compress_write(compress, buffer, num_read);
++ if (wrote > 0)
++ compress_start(compress);
++ }
+ if (wrote < 0) {
+ fprintf(stderr, "Error playing sample\n");
+ fprintf(stderr, "ERR: %s\n", compress_get_error(compress));
+@@ -686,7 +708,8 @@ void play_samples(char *name, unsigned int card, unsigned int device,
+ BUF_EXIT:
+ free(buffer);
+ COMP_EXIT:
+- compress_close(compress);
++ if (compress)
++ compress_close(compress);
+ FILE_EXIT:
+ fclose(file);
+ if (verbose)
+--
+2.18.0
+
diff --git a/meta/meta-mediatek/recipes-multimedia/vp6/vp6_0226.bb b/meta/meta-mediatek/recipes-multimedia/vp6/vp6_0226.bb
new file mode 100644
index 0000000..30efe79
--- /dev/null
+++ b/meta/meta-mediatek/recipes-multimedia/vp6/vp6_0226.bb
@@ -0,0 +1,34 @@
+DESCRIPTION = "VPU IMG"
+LICENSE = "MediaTekProprietary"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=e1696b147d49d491bcb4da1a57173fff"
+
+inherit deploy
+MTK_SRC = "${TOPDIR}/../prebuilt/ml/vp6/MVPU6_0226"
+
+do_compile[nostamp] = "1"
+
+do_compile() {
+ oe_runmake -C ${MTK_SRC}
+ cp ${MTK_SRC}/cam_vpu_a.img ${B}
+ cp ${MTK_SRC}/cam_vpu_b.img ${B}
+ cp ${MTK_SRC}/cam_vpu_c.img ${B}
+}
+
+do_install() {
+ install -d ${D}/lib/firmware/
+ install -m 644 ${B}/cam_vpu_a.img ${D}/lib/firmware/cam_vpu1.img
+ install -m 644 ${B}/cam_vpu_b.img ${D}/lib/firmware/cam_vpu2.img
+ install -m 644 ${B}/cam_vpu_c.img ${D}/lib/firmware/cam_vpu3.img
+}
+
+do_deploy() {
+ install -d ${DEPLOYDIR}
+ install -m 644 ${B}/cam_vpu_a.img -t ${DEPLOYDIR}
+ install -m 644 ${B}/cam_vpu_b.img -t ${DEPLOYDIR}
+ install -m 644 ${B}/cam_vpu_c.img -t ${DEPLOYDIR}
+}
+
+FILES_${PN} += "/lib/firmware/*"
+INSANE_SKIP_${PN} += "already-stripped"
+
+addtask deploy before do_build after do_compile
diff --git a/meta/meta-mediatek/recipes-multimedia/vp6/vp6_0413_Prod.bb b/meta/meta-mediatek/recipes-multimedia/vp6/vp6_0413_Prod.bb
new file mode 100644
index 0000000..5995d06
--- /dev/null
+++ b/meta/meta-mediatek/recipes-multimedia/vp6/vp6_0413_Prod.bb
@@ -0,0 +1,34 @@
+DESCRIPTION = "VPU IMG"
+LICENSE = "MediaTekProprietary"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=e1696b147d49d491bcb4da1a57173fff"
+
+inherit deploy
+MTK_SRC = "${TOPDIR}/../prebuilt/ml/vp6/MVPU6_0413_Prod"
+
+do_compile[nostamp] = "1"
+
+do_compile() {
+ oe_runmake -C ${MTK_SRC}
+ cp ${MTK_SRC}/cam_vpu_a.img ${B}
+ cp ${MTK_SRC}/cam_vpu_b.img ${B}
+ cp ${MTK_SRC}/cam_vpu_c.img ${B}
+}
+
+do_install() {
+ install -d ${D}/lib/firmware/
+ install -m 644 ${B}/cam_vpu_a.img ${D}/lib/firmware/cam_vpu1.img
+ install -m 644 ${B}/cam_vpu_b.img ${D}/lib/firmware/cam_vpu2.img
+ install -m 644 ${B}/cam_vpu_c.img ${D}/lib/firmware/cam_vpu3.img
+}
+
+do_deploy() {
+ install -d ${DEPLOYDIR}
+ install -m 644 ${B}/cam_vpu_a.img -t ${DEPLOYDIR}
+ install -m 644 ${B}/cam_vpu_b.img -t ${DEPLOYDIR}
+ install -m 644 ${B}/cam_vpu_c.img -t ${DEPLOYDIR}
+}
+
+FILES_${PN} += "/lib/firmware/*"
+INSANE_SKIP_${PN} += "already-stripped"
+
+addtask deploy before do_build after do_compile
diff --git a/meta/meta-mediatek/recipes-multimedia/vpud/vpud_1.0.bb b/meta/meta-mediatek/recipes-multimedia/vpud/vpud_1.0.bb
new file mode 100644
index 0000000..bd19151
--- /dev/null
+++ b/meta/meta-mediatek/recipes-multimedia/vpud/vpud_1.0.bb
@@ -0,0 +1,44 @@
+DESCRIPTION = "MediaTek VPU daemon"
+LICENSE = "MediaTekProprietary"
+LIC_FILES_CHKSUM = "file://NOTICE;md5=e1696b147d49d491bcb4da1a57173fff"
+
+inherit workonsrc
+WORKONSRC = "${TOPDIR}/../src/multimedia/vpu"
+
+RDEPENDS_${PN} = "libgcc libstdc++"
+
+inherit pkgconfig
+
+CLEANBROKEN = "1"
+
+do_compile() {
+ oe_runmake \
+ PACKAGE_ARCH="${PACKAGE_ARCH}" \
+ CFLAGS="${CFLAGS}" \
+ LDFLAGS="${LDFLAGS}"
+}
+
+do_install() {
+ oe_runmake \
+ PREFIX="${prefix}" DESTDIR="${D}" PACKAGE_ARCH="${PACKAGE_ARCH}" install
+}
+
+
+inherit systemd
+
+SYSTEMD_PACKAGES = "${PN}"
+SYSTEMD_SERVICE_${PN} = "vpud.service"
+FILES_${PN} += "${systemd_unitdir}/system/vpud.service"
+
+do_install_append() {
+ if ${@bb.utils.contains('DISTRO_FEATURES','systemd','true','false',d)}; then
+ install -d ${D}${systemd_unitdir}/system/
+ install -m 0644 ${B}/lib/systemd/system/vpud.service ${D}${systemd_unitdir}/system
+ fi
+}
+
+INSANE_SKIP_${PN} += "already-stripped"
+FILES_${PN}-dev = "dev-elf"
+FILES_${PN} += "${libdir}"
+
+SECURITY_CFLAGS_pn-${PN} = "${SECURITY_NO_PIE_CFLAGS}"
diff --git a/meta/meta-mediatek/recipes-multimedia/vpud/vpud_2.0.bb b/meta/meta-mediatek/recipes-multimedia/vpud/vpud_2.0.bb
new file mode 100644
index 0000000..67e5d82
--- /dev/null
+++ b/meta/meta-mediatek/recipes-multimedia/vpud/vpud_2.0.bb
@@ -0,0 +1,44 @@
+DESCRIPTION = "MediaTek VPU daemon"
+LICENSE = "MediaTekProprietary"
+LIC_FILES_CHKSUM = "file://NOTICE;md5=e1696b147d49d491bcb4da1a57173fff"
+
+inherit workonsrc
+WORKONSRC = "${TOPDIR}/../src/multimedia/vpu2"
+
+RDEPENDS_${PN} = "libgcc libstdc++"
+
+inherit pkgconfig
+
+CLEANBROKEN = "1"
+
+do_compile() {
+ oe_runmake \
+ PACKAGE_ARCH="${PACKAGE_ARCH}" \
+ CFLAGS="${CFLAGS}" \
+ LDFLAGS="${LDFLAGS}"
+}
+
+do_install() {
+ oe_runmake \
+ PREFIX="${prefix}" DESTDIR="${D}" PACKAGE_ARCH="${PACKAGE_ARCH}" install
+}
+
+
+inherit systemd
+
+SYSTEMD_PACKAGES = "${PN}"
+SYSTEMD_SERVICE_${PN} = "vpud.service"
+FILES_${PN} += "${systemd_unitdir}/system/vpud.service"
+
+do_install_append() {
+ if ${@bb.utils.contains('DISTRO_FEATURES','systemd','true','false',d)}; then
+ install -d ${D}${systemd_unitdir}/system/
+ install -m 0644 ${B}/lib/systemd/system/vpud.service ${D}${systemd_unitdir}/system
+ fi
+}
+
+INSANE_SKIP_${PN} += "already-stripped"
+FILES_${PN}-dev = "dev-elf"
+FILES_${PN} += "${libdir}"
+
+SECURITY_CFLAGS_pn-${PN} = "${SECURITY_NO_PIE_CFLAGS}"
diff --git a/meta/meta-mediatek/recipes-multimedia/vpustream/vpustream.bb b/meta/meta-mediatek/recipes-multimedia/vpustream/vpustream.bb
new file mode 100644
index 0000000..00df052
--- /dev/null
+++ b/meta/meta-mediatek/recipes-multimedia/vpustream/vpustream.bb
@@ -0,0 +1,28 @@
+DESCRIPTION = "MediaTek VPU stream"
+LICENSE = "MediaTekProprietary"
+LIC_FILES_CHKSUM = "file://NOTICE;md5=e1696b147d49d491bcb4da1a57173fff"
+
+inherit workonsrc
+WORKONSRC = "${TOPDIR}/../src/multimedia/vpustream"
+
+DEPENDS += "libion virtual/kernel"
+RDEPENDS_${PN} = "libgcc libstdc++ libion"
+
+inherit pkgconfig
+
+do_compile() {
+ oe_runmake \
+ KERNEL_DIR="${STAGING_KERNEL_DIR}" \
+ CFLAGS="${CFLAGS}" \
+ LDFLAGS="${LDFLAGS}"
+}
+
+do_install() {
+ oe_runmake \
+ PREFIX="${prefix}" DESTDIR="${D}" SRCDIR="${B}" install
+}
+
+FILES_${PN} = "${libdir}/libvpu.so ${bindir}/* /data/*"
+FILES_${PN}-dev = "${includedir}/vpu.h"
+
+INSANE_SKIP_${PN} += "already-stripped"
diff --git a/meta/meta-mediatek/recipes-sensor/hfmanager/hfmanager.bb b/meta/meta-mediatek/recipes-sensor/hfmanager/hfmanager.bb
new file mode 100644
index 0000000..df5787e
--- /dev/null
+++ b/meta/meta-mediatek/recipes-sensor/hfmanager/hfmanager.bb
@@ -0,0 +1,41 @@
+DESCRIPTION = "This module is a hfmanager dynamic library."
+LICENSE = "MediaTekProprietary"
+LIC_FILES_CHKSUM = "file://MediatekProprietary;md5=e81996d00a8343deec9cf9f374a084c4"
+
+inherit deploy workonsrc
+WORKONSRC = "${TOPDIR}/../src/navigation/sensor/2.0/core"
+
+DEPENDS += "platform-libs-common"
+S = "${WORKDIR}"
+
+FILES_${PN}-dev = "${includedir}/*"
+FILES_${PN} = "${bindir}/* ${sbindir}/* ${libexecdir}/* ${libdir}/lib*${SOLIBS}\
+ ${sysconfdir} ${sharedstatedir} ${localstatedir}\
+ ${base_libdir}/*${SOLIBS}\
+ ${base_bindir}/*\
+ ${base_sbindir}\
+ ${libdir}/*.so*\
+ ${base_libdir}/*.so*"
+
+SECTION_${PN}-dev = "devel"
+ALLOW_EMPTY_${PN} = "1"
+RDEPENDS_${PN}-dev = "${PN} (=${EXTENDPKGV})"
+
+# Avoid QA Issue: 'Files/directories were installed but not shipped'
+INSANE_SKIP_${PN} += "installed-vs-shipped"
+
+#Skip strip check in QA test.
+INSANE_SKIP_${PN} += "already-stripped"
+
+do_compile () {
+ oe_runmake -f Makefile
+}
+
+do_install() {
+ install -d ${D}/${libdir}/
+ install -m 0755 ${S}*.so ${D}/${libdir}/
+
+ install -d ${D}/usr/include/
+ install -m 0755 ${S}*.h ${D}/usr/include/
+}
+inherit pkgconfig
diff --git a/meta/meta-mediatek/recipes-sensor/hfsensortool/hfsensortool.bb b/meta/meta-mediatek/recipes-sensor/hfsensortool/hfsensortool.bb
new file mode 100644
index 0000000..88adfde
--- /dev/null
+++ b/meta/meta-mediatek/recipes-sensor/hfsensortool/hfsensortool.bb
@@ -0,0 +1,23 @@
+DESCRIPTION = "This is a high frequency sensor tool."
+LICENSE = "MediaTekProprietary"
+LIC_FILES_CHKSUM = "file://MediatekProprietary;md5=767436d74f211b7f4aa0abe9bebf437f"
+DEPENDS += "hfmanager"
+
+inherit workonsrc
+WORKONSRC = "${TOPDIR}/../src/navigation/sensor/2.0/test"
+
+S = "${WORKDIR}"
+
+inherit pkgconfig
+
+do_compile () {
+ oe_runmake -f MakeTool
+ oe_runmake -f MakeToolWrapper
+}
+
+do_install() {
+
+ install -d ${D}/bin/
+ install -m 0777 ${S}high_freq_sensor_tool ${D}/bin/
+ install -m 0777 ${S}high_freq_sensor_tool_c_wrapper ${D}/bin/
+}
diff --git a/meta/meta-mediatek/recipes-sensor/sensorhal/sensorhal.bb b/meta/meta-mediatek/recipes-sensor/sensorhal/sensorhal.bb
new file mode 100644
index 0000000..d11e6e8
--- /dev/null
+++ b/meta/meta-mediatek/recipes-sensor/sensorhal/sensorhal.bb
@@ -0,0 +1,57 @@
+DESCRIPTION = "sensor hardware abstract layer"
+LICENSE = "MediaTekProprietary"
+MTK_SRC = "${TOPDIR}/../src/navigation/sensor/sensor_hal"
+LIC_FILES_CHKSUM = "file://${MTK_SRC}/LICENSE;md5=e1696b147d49d491bcb4da1a57173fff"
+
+inherit deploy workonsrc
+WORKONSRC = "${MTK_SRC}"
+
+SECURITY_CFLAGS = ""
+
+FILES_${PN} = "${bindir}/* ${sbindir}/* ${libexecdir}/* ${libdir}/lib*${SOLIBS}\
+ ${sysconfdir} ${sharedstatedir} ${localstatedir}\
+ ${base_libdir}/*${SOLIBS}\
+ ${base_bindir}/*\
+ ${base_sbindir}\
+ /usr/lib/*.so*\
+ /lib/*.so*"
+FILES_SOLIBSDEV ?= "${base_libdir}/lib*${SOLIBSDEV} ${libdir}/lib*${SOLIBSDEV}"
+FILES_${PN}-dev = "${includedir} ${FILES_SOLIBSDEV} ${libdir}/*.la \
+ ${libdir}/*.o ${libdir}/pkgconfig ${datadir}/pkgconfig \
+ ${datadir}/aclocal ${base_libdir}/*.o \
+ ${libdir}/${BPN}/*.la ${base_libdir}/*.la "
+
+SECTION_${PN}-dev = "devel"
+ALLOW_EMPTY_${PN} = "1"
+RDEPENDS_${PN}-dev = "${PN} (=${EXTENDPKGV})"
+
+FILES_${PN}-staticdev = "${libdir}/*.a ${base_libdir}/*.a ${libdir}/${BPN}/*.a"
+SECTION_${PN}-staticdev = "devel"
+RDEPENDS_${PN}-staticdev = "${PN}-dev (=${EXTENDPKGV})"
+
+FILES_${PN}-doc += "/doc"
+FILES_${PN}-dbg += "/usr/src/debug \
+ ${base_bindir}/.debug \
+ ${base_libdir}/.debug \
+ ${base_sbindir}/.debug"
+
+# Avoid QA Issue: 'Files/directories were installed but not shipped'
+INSANE_SKIP_${PN} += "installed-vs-shipped"
+
+#Skip strip check in QA test.
+INSANE_SKIP_${PN} += "already-stripped"
+
+# inherit showinfo
+
+do_compile() {
+ oe_runmake PACKAGE_ARCH=${PACKAGE_ARCH}
+}
+
+do_install_append() {
+ install -d ${D}${base_libdir}
+ install -d ${D}${base_bindir}
+ install -d ${D}${base_sbindir}
+ install -d ${D}${includedir}
+}
+
+inherit autotools
diff --git a/meta/meta-mediatek/recipes-sensor/sensorhal/sensorhaltest.bb b/meta/meta-mediatek/recipes-sensor/sensorhal/sensorhaltest.bb
new file mode 100644
index 0000000..67b7ead
--- /dev/null
+++ b/meta/meta-mediatek/recipes-sensor/sensorhal/sensorhaltest.bb
@@ -0,0 +1,13 @@
+#Basic Configuration
+DESCRIPTION = "This module is a sensorhal test library."
+LICENSE = "MediaTekProprietary"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=e1696b147d49d491bcb4da1a57173fff"
+DEPENDS += "sensorhal systemd"
+inherit workonsrc
+WORKONSRC = "${TOPDIR}/../src/navigation/sensor/sensorhaltest"
+
+do_install() {
+ oe_runmake PREFIX="${prefix}" DESTDIR="${D}" install
+}
+
+inherit autotools
diff --git a/meta/meta-mediatek/recipes-sensor/sensortest/sensortest.bb b/meta/meta-mediatek/recipes-sensor/sensortest/sensortest.bb
new file mode 100644
index 0000000..36383d9
--- /dev/null
+++ b/meta/meta-mediatek/recipes-sensor/sensortest/sensortest.bb
@@ -0,0 +1,16 @@
+#Basic Configuration
+DESCRIPTION = "This module is a adr test library."
+LICENSE = "MediaTekProprietary"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=e1696b147d49d491bcb4da1a57173fff"
+
+DEPENDS += "hfmanager"
+RDEPENDS_${PN} += "hfmanager"
+
+inherit workonsrc
+WORKONSRC = "${TOPDIR}/../src/navigation/sensor/sensortest"
+
+do_install() {
+ oe_runmake PREFIX="${prefix}" DESTDIR="${D}" install
+}
+
+inherit autotools
diff --git a/meta/meta-mediatek/recipes-support/ab-tools/abtools.bb b/meta/meta-mediatek/recipes-support/ab-tools/abtools.bb
new file mode 100644
index 0000000..8b2ed6a
--- /dev/null
+++ b/meta/meta-mediatek/recipes-support/ab-tools/abtools.bb
@@ -0,0 +1,63 @@
+DESCRIPTION = "A/B update package tools"
+LICENSE = "Apache-2.0"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=562c740877935f40b262db8af30bca36"
+BBCLASSEXTEND = "native nativesdk"
+
+WORKONSRC = "${TOPDIR}/../src/support/ab_tools"
+OECMAKE_SOURCEPATH = "${S}"
+
+inherit workonsrc
+
+FILES_${PN}-dev = ""
+FILES_${PN} += "${libdir}"
+FILES_${PN} += "${bindir}"
+FILES_${PN} += "${datadir}"
+
+do_install_append() {
+ install -d ${D}${libdir}
+ install -d ${D}${bindir}
+ install -d ${D}${bindir}/lib/shflags
+ install -d ${D}${datadir}/abtools
+ install -d ${D}${datadir}/abtools/scripts
+ install -d ${D}${datadir}/abtools/scripts/lib/shflags
+ install -d ${D}${datadir}/abtools/lib
+ install -d ${D}${datadir}/abtools/security
+
+ install -m 0755 ${S}/security/testkey.pk8 ${D}${datadir}/abtools/security
+ install -m 0755 ${S}/security/testkey.x509.pem ${D}${datadir}/abtools/security
+
+ install -m 0755 ${S}/bin/delta_generator ${D}${bindir}
+ install -m 0755 ${S}/bin/signapk.jar ${D}${bindir}
+ install -m 0755 ${S}/bin/e2fsdroid ${D}${bindir}
+
+ install -m 0755 ${S}/scripts/brillo_update_payload ${D}${datadir}/abtools/scripts
+ install -m 0755 ${S}/scripts/ota_from_target_files.py ${D}${datadir}/abtools/scripts
+ install -m 0755 ${S}/scripts/add_care_map_to_target_files.py ${D}${datadir}/abtools/scripts
+ install -m 0755 ${S}/scripts/common.py ${D}${datadir}/abtools/scripts
+ install -m 0755 ${S}/scripts/blockimgdiff.py ${D}${datadir}/abtools/scripts
+ install -m 0755 ${S}/scripts/rangelib.py ${D}${datadir}/abtools/scripts
+ install -m 0755 ${S}/scripts/edify_generator.py ${D}${datadir}/abtools/scripts
+ install -m 0755 ${S}/scripts/sparse_img.py ${D}${datadir}/abtools/scripts
+ install -m 0755 ${S}/scripts/lib/shflags/shflags ${D}${datadir}/abtools/scripts/lib/shflags
+
+ install -m 0644 ${S}/lib/libc++.so ${D}${libdir}
+ install -m 0644 ${S}/lib/libbase.so ${D}${libdir}
+ install -m 0644 ${S}/lib/libbrillo.so ${D}${libdir}
+ install -m 0644 ${S}/lib/libbrillo-stream.so ${D}${libdir}
+ install -m 0644 ${S}/lib/libchrome.so ${D}${libdir}
+ install -m 0644 ${S}/lib/libcrypto_utils.so ${D}${libdir}
+ install -m 0644 ${S}/lib/libcrypto-host.so ${D}${libdir}
+ install -m 0644 ${S}/lib/libevent-host.so ${D}${libdir}
+ install -m 0644 ${S}/lib/libext2fs-host.so ${D}${libdir}
+ install -m 0644 ${S}/lib/liblog.so ${D}${libdir}
+ install -m 0644 ${S}/lib/libprotobuf-cpp-lite.so ${D}${libdir}
+ install -m 0644 ${S}/lib/libsparse-host.so ${D}${libdir}
+ install -m 0644 ${S}/lib/libssl-host.so ${D}${libdir}
+ install -m 0644 ${S}/lib/libz-host.so ${D}${libdir}
+ install -m 0644 ${S}/lib/libconscrypt_openjdk_jni.so ${D}${libdir}
+}
+
+PATH_prepend = "${STAGING_DIR_NATIVE}${datadir}/abtools/scripts:"
+EXTRANATIVEPATH += ""
+
+
diff --git a/meta/meta-mediatek/recipes-support/bootctrl/bootctrl.bb b/meta/meta-mediatek/recipes-support/bootctrl/bootctrl.bb
new file mode 100644
index 0000000..2bbf7f4
--- /dev/null
+++ b/meta/meta-mediatek/recipes-support/bootctrl/bootctrl.bb
@@ -0,0 +1,25 @@
+inherit workonsrc autotools
+
+DESCRIPTION = "abupdate bootctrl"
+LICENSE = "MediaTekProprietary"
+# LIC_FILES_CHKSUM = "file://LICENSE;md5=e1696b147d49d491bcb4da1a57173fff"
+
+FILESEXTRAPATHS_prepend := "${THISDIR}:"
+
+WORKONSRC = "${TOPDIR}/../src/support/bootctrl"
+
+DEPENDS += "${@bb.utils.contains("BOOTDEV_TYPE", "nand", "nandapi", "", d)} libhardware libavb"
+
+EXTRA_OEMAKE = "NANDAPIDIR=${TOPDIR}/../src/support/libnandapi"
+
+INHIBIT_PACKAGE_STRIP = "1"
+
+do_configure_prepend() {
+ install -d ${S}/include/hardware
+ install -d ${S}/mediatek/bootctrl/avb/libavb
+ install -m 0755 ${STAGING_DIR_HOST}/${includedir}/hardware.h ${S}/include/hardware
+ install -m 0755 ${STAGING_DIR_HOST}/${includedir}/boot_control.h ${S}/include/hardware
+ install -m 0755 ${STAGING_DIR_HOST}/${includedir}/avb_util.h ${S}/mediatek/bootctrl/avb/libavb
+ install -m 0755 ${STAGING_DIR_HOST}/${datadir}/avb_crc32.c ${S}/mediatek/bootctrl/avb/libavb
+ install -m 0755 ${STAGING_DIR_HOST}/${datadir}/avb_util.c ${S}/mediatek/bootctrl/avb/libavb
+}
diff --git a/meta/meta-mediatek/recipes-support/custom/custom_1.0.0.bb b/meta/meta-mediatek/recipes-support/custom/custom_1.0.0.bb
new file mode 100644
index 0000000..aabf68e
--- /dev/null
+++ b/meta/meta-mediatek/recipes-support/custom/custom_1.0.0.bb
@@ -0,0 +1,38 @@
+#Basic Configuration
+DESCRIPTION = "Customization."
+SECTION = "base"
+LICENSE = "MediaTekProprietary"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=e1696b147d49d491bcb4da1a57173fff"
+MTK_SRC = "${TOPDIR}/../src/support/libnvram_custom/CFG"
+
+WORKONSRC = "${MTK_SRC}"
+
+inherit deploy workonsrc
+
+PRJ_FILENAME = "${MTK_PROJECT}"
+
+#Parameters passed to do_compile()
+EXTRA_OEMAKE = "'CROSS=${TARGET_PREFIX}'\
+ 'PRJ_FILENAME=${PRJ_FILENAME}'"
+ALLOW_EMPTY_${PN} = "1"
+
+FILES_${PN}-dev = "*"
+FILES_${PN} = "*"
+do_install () {
+ oe_runmake install ROOT=${D}
+
+ if test -d "${WORKDIR}/${MTK_NVRAM_PROJECT}/cgen"; then
+ mkdir -p ${D}/include/custom/${MTK_PROJECT}
+ cp -rf ${WORKDIR}/${MTK_NVRAM_PROJECT}/cgen ${D}/include/custom/${MTK_PROJECT}
+ fi
+
+ install -d ${D}${includedir}
+ cp -af ${D}/include/* ${D}${includedir}
+ rm -rf ${D}/include
+
+}
+
+addtask nvramclean
+do_nvramclean () {
+ oe_runmake clean
+}
diff --git a/meta/meta-mediatek/recipes-support/db/db/darwin.patch b/meta/meta-mediatek/recipes-support/db/db/darwin.patch
new file mode 100644
index 0000000..5fdccd3
--- /dev/null
+++ b/meta/meta-mediatek/recipes-support/db/db/darwin.patch
@@ -0,0 +1,145 @@
+diff --git a/.pc/0001-atomic-Rename-local-__atomic_compare_exchange-to-avo.patch/src/dbinc/atomic.h b/.pc/0001-atomic-Rename-local-__atomic_compare_exchange-to-avo.patch/src/dbinc/atomic.h
+index 6a858f7..a58e152 100644
+--- a/.pc/0001-atomic-Rename-local-__atomic_compare_exchange-to-avo.patch/src/dbinc/atomic.h
++++ b/.pc/0001-atomic-Rename-local-__atomic_compare_exchange-to-avo.patch/src/dbinc/atomic.h
+@@ -70,7 +70,7 @@ typedef struct {
+ * These have no memory barriers; the caller must include them when necessary.
+ */
+ #define atomic_read(p) ((p)->value)
+-#define atomic_init(p, val) ((p)->value = (val))
++#define atomic_init_(p, val) ((p)->value = (val))
+
+ #ifdef HAVE_ATOMIC_SUPPORT
+
+@@ -206,7 +206,7 @@ static inline int __atomic_compare_exchange(
+ #define atomic_dec(env, p) (--(p)->value)
+ #define atomic_compare_exchange(env, p, oldval, newval) \
+ (DB_ASSERT(env, atomic_read(p) == (oldval)), \
+- atomic_init(p, (newval)), 1)
++ atomic_init_(p, (newval)), 1)
+ #else
+ #define atomic_inc(env, p) __atomic_inc(env, p)
+ #define atomic_dec(env, p) __atomic_dec(env, p)
+diff --git a/src/dbinc/atomic.h b/src/dbinc/atomic.h
+index 1b49de5..8ddda43 100644
+--- a/src/dbinc/atomic.h
++++ b/src/dbinc/atomic.h
+@@ -70,7 +70,7 @@ typedef struct {
+ * These have no memory barriers; the caller must include them when necessary.
+ */
+ #define atomic_read(p) ((p)->value)
+-#define atomic_init(p, val) ((p)->value = (val))
++#define atomic_init_(p, val) ((p)->value = (val))
+
+ #ifdef HAVE_ATOMIC_SUPPORT
+
+@@ -206,7 +206,7 @@ static inline int __db_atomic_compare_exchange(
+ #define atomic_dec(env, p) (--(p)->value)
+ #define atomic_compare_exchange(env, p, oldval, newval) \
+ (DB_ASSERT(env, atomic_read(p) == (oldval)), \
+- atomic_init(p, (newval)), 1)
++ atomic_init_(p, (newval)), 1)
+ #else
+ #define atomic_inc(env, p) __atomic_inc(env, p)
+ #define atomic_dec(env, p) __atomic_dec(env, p)
+diff --git a/src/mp/mp_fget.c b/src/mp/mp_fget.c
+index 16de695..5d553d7 100644
+--- a/src/mp/mp_fget.c
++++ b/src/mp/mp_fget.c
+@@ -649,7 +649,7 @@ alloc: /* Allocate a new buffer header and data space. */
+
+ /* Initialize enough so we can call __memp_bhfree. */
+ alloc_bhp->flags = 0;
+- atomic_init(&alloc_bhp->ref, 1);
++ atomic_init_(&alloc_bhp->ref, 1);
+ #ifdef DIAGNOSTIC
+ if ((uintptr_t)alloc_bhp->buf & (sizeof(size_t) - 1)) {
+ __db_errx(env, DB_STR("3025",
+@@ -955,7 +955,7 @@ alloc: /* Allocate a new buffer header and data space. */
+ MVCC_MPROTECT(bhp->buf, mfp->pagesize,
+ PROT_READ);
+
+- atomic_init(&alloc_bhp->ref, 1);
++ atomic_init_(&alloc_bhp->ref, 1);
+ MUTEX_LOCK(env, alloc_bhp->mtx_buf);
+ alloc_bhp->priority = bhp->priority;
+ alloc_bhp->pgno = bhp->pgno;
+diff --git a/src/mp/mp_mvcc.c b/src/mp/mp_mvcc.c
+index 770bad8..bbf5899 100644
+--- a/src/mp/mp_mvcc.c
++++ b/src/mp/mp_mvcc.c
+@@ -276,7 +276,7 @@ __memp_bh_freeze(dbmp, infop, hp, bhp, need_frozenp)
+ #else
+ memcpy(frozen_bhp, bhp, SSZA(BH, buf));
+ #endif
+- atomic_init(&frozen_bhp->ref, 0);
++ atomic_init_(&frozen_bhp->ref, 0);
+ if (mutex != MUTEX_INVALID)
+ frozen_bhp->mtx_buf = mutex;
+ else if ((ret = __mutex_alloc(env, MTX_MPOOL_BH,
+@@ -428,7 +428,7 @@ __memp_bh_thaw(dbmp, infop, hp, frozen_bhp, alloc_bhp)
+ #endif
+ alloc_bhp->mtx_buf = mutex;
+ MUTEX_LOCK(env, alloc_bhp->mtx_buf);
+- atomic_init(&alloc_bhp->ref, 1);
++ atomic_init_(&alloc_bhp->ref, 1);
+ F_CLR(alloc_bhp, BH_FROZEN);
+ }
+
+diff --git a/src/mp/mp_region.c b/src/mp/mp_region.c
+index 4952030..4fbbea5 100644
+--- a/src/mp/mp_region.c
++++ b/src/mp/mp_region.c
+@@ -245,7 +245,7 @@ __memp_init(env, dbmp, reginfo_off, htab_buckets, max_nreg)
+ MTX_MPOOL_FILE_BUCKET, 0, &htab[i].mtx_hash)) != 0)
+ return (ret);
+ SH_TAILQ_INIT(&htab[i].hash_bucket);
+- atomic_init(&htab[i].hash_page_dirty, 0);
++ atomic_init_(&htab[i].hash_page_dirty, 0);
+ }
+
+ /*
+@@ -302,7 +302,7 @@ no_prealloc:
+ } else
+ hp->mtx_hash = mtx_base + (i % dbenv->mp_mtxcount);
+ SH_TAILQ_INIT(&hp->hash_bucket);
+- atomic_init(&hp->hash_page_dirty, 0);
++ atomic_init_(&hp->hash_page_dirty, 0);
+ #ifdef HAVE_STATISTICS
+ hp->hash_io_wait = 0;
+ hp->hash_frozen = hp->hash_thawed = hp->hash_frozen_freed = 0;
+diff --git a/src/mutex/mut_method.c b/src/mutex/mut_method.c
+index 09353b0..7c17a6f 100644
+--- a/src/mutex/mut_method.c
++++ b/src/mutex/mut_method.c
+@@ -474,7 +474,7 @@ atomic_compare_exchange(env, v, oldval, newval)
+ MUTEX_LOCK(env, mtx);
+ ret = atomic_read(v) == oldval;
+ if (ret)
+- atomic_init(v, newval);
++ atomic_init_(v, newval);
+ MUTEX_UNLOCK(env, mtx);
+
+ return (ret);
+diff --git a/src/mutex/mut_tas.c b/src/mutex/mut_tas.c
+index 106b161..4d662b0 100644
+--- a/src/mutex/mut_tas.c
++++ b/src/mutex/mut_tas.c
+@@ -47,7 +47,7 @@ __db_tas_mutex_init(env, mutex, flags)
+
+ #ifdef HAVE_SHARED_LATCHES
+ if (F_ISSET(mutexp, DB_MUTEX_SHARED))
+- atomic_init(&mutexp->sharecount, 0);
++ atomic_init_(&mutexp->sharecount, 0);
+ else
+ #endif
+ if (MUTEX_INIT(&mutexp->tas)) {
+@@ -536,7 +536,7 @@ __db_tas_mutex_unlock(env, mutex)
+ F_CLR(mutexp, DB_MUTEX_LOCKED);
+ /* Flush flag update before zeroing count */
+ MEMBAR_EXIT();
+- atomic_init(&mutexp->sharecount, 0);
++ atomic_init_(&mutexp->sharecount, 0);
+ } else {
+ DB_ASSERT(env, sharecount > 0);
+ MEMBAR_EXIT();
diff --git a/meta/meta-mediatek/recipes-support/db/db_5.3.28.bbappend b/meta/meta-mediatek/recipes-support/db/db_5.3.28.bbappend
new file mode 100644
index 0000000..11253b1
--- /dev/null
+++ b/meta/meta-mediatek/recipes-support/db/db_5.3.28.bbappend
@@ -0,0 +1,3 @@
+FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
+SRC_URI_append_toolchain-clang = " file://darwin.patch"
+
diff --git a/meta/meta-mediatek/recipes-support/dmsetup/dmsetup_2.02.171.bb b/meta/meta-mediatek/recipes-support/dmsetup/dmsetup_2.02.171.bb
new file mode 100644
index 0000000..d406896
--- /dev/null
+++ b/meta/meta-mediatek/recipes-support/dmsetup/dmsetup_2.02.171.bb
@@ -0,0 +1,14 @@
+require ../../../meta-openembedded/meta-oe/recipes-support/lvm2/lvm2.inc
+
+SRC_URI[md5sum] = "153b7bb643eb26073274968e9026fa8f"
+SRC_URI[sha256sum] = "b815a711a2fabaa5c3dc1a4a284df0268bf0f325f0fc0f5c9530c9bbb54b9964"
+
+DEPENDS += "autoconf-archive-native"
+
+TARGET_CC_ARCH += "${LDFLAGS}"
+
+do_install() {
+ oe_runmake 'DESTDIR=${D}' -C tools install_dmsetup_dynamic
+}
+
+BBCLASSEXTEND = "native nativesdk"
diff --git a/meta/meta-mediatek/recipes-support/dmsetup/files/0001-Avoid-bashisms-in-init-scripts.patch b/meta/meta-mediatek/recipes-support/dmsetup/files/0001-Avoid-bashisms-in-init-scripts.patch
new file mode 100644
index 0000000..e86ab25
--- /dev/null
+++ b/meta/meta-mediatek/recipes-support/dmsetup/files/0001-Avoid-bashisms-in-init-scripts.patch
@@ -0,0 +1,182 @@
+From 916ea0c70fd063ab7b81f16fd917a75dc02edf4f Mon Sep 17 00:00:00 2001
+From: Peter Kjellerstedt <pkj@axis.com>
+Date: Fri, 17 Mar 2017 03:18:28 +0100
+Subject: [PATCH] Avoid bashisms in init scripts
+
+Upstream-Status: Inappropriate
+
+Signed-off-by: Peter Kjellerstedt <peter.kjellerstedt@axis.com>
+---
+ scripts/blk_availability_init_red_hat.in | 4 ++--
+ scripts/clvmd_init_red_hat.in | 6 +++---
+ scripts/cmirrord_init_red_hat.in | 4 ++--
+ scripts/lvm2_cluster_activation_red_hat.sh.in | 4 ++--
+ scripts/lvm2_lvmetad_init_red_hat.in | 4 ++--
+ scripts/lvm2_lvmpolld_init_red_hat.in | 4 ++--
+ scripts/lvm2_monitoring_init_red_hat.in | 4 ++--
+ scripts/lvm2_monitoring_init_rhel4 | 4 ++--
+ 8 files changed, 17 insertions(+), 17 deletions(-)
+
+diff --git a/scripts/blk_availability_init_red_hat.in b/scripts/blk_availability_init_red_hat.in
+index a84ffe7..6b855b7 100644
+--- a/scripts/blk_availability_init_red_hat.in
++++ b/scripts/blk_availability_init_red_hat.in
+@@ -1,4 +1,4 @@
+-#!/bin/bash
++#!/bin/sh
+ #
+ # Copyright (C) 2012 Red Hat, Inc. All rights reserved.
+ #
+@@ -53,6 +53,6 @@ case "$1" in
+ status)
+ ;;
+ *)
+- echo $"Usage: $0 {start|stop|status}"
++ echo "Usage: $0 {start|stop|status}"
+ ;;
+ esac
+diff --git a/scripts/clvmd_init_red_hat.in b/scripts/clvmd_init_red_hat.in
+index d7f3392..abc8011 100644
+--- a/scripts/clvmd_init_red_hat.in
++++ b/scripts/clvmd_init_red_hat.in
+@@ -1,4 +1,4 @@
+-#!/bin/bash
++#!/bin/sh
+ #
+ # clvmd - Clustered LVM Daemon init script
+ #
+@@ -161,7 +161,7 @@ restart() {
+ fi
+ }
+
+-[ "$EUID" != "0" ] && {
++[ "$(id -u)" != "0" ] && {
+ echo "clvmd init script can only be executed as root user"
+ exit 4
+ }
+@@ -206,7 +206,7 @@ case "$1" in
+ ;;
+
+ *)
+- echo $"Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|force-reload}"
++ echo "Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|force-reload}"
+ rtrn=2
+ ;;
+ esac
+diff --git a/scripts/cmirrord_init_red_hat.in b/scripts/cmirrord_init_red_hat.in
+index d4b7e37..d442cbc 100755
+--- a/scripts/cmirrord_init_red_hat.in
++++ b/scripts/cmirrord_init_red_hat.in
+@@ -1,4 +1,4 @@
+-#!/bin/bash
++#!/bin/sh
+ #
+ # chkconfig: - 22 78
+ # description: Starts and stops cmirrord
+@@ -101,7 +101,7 @@ case "$1" in
+ ;;
+
+ *)
+- echo $"Usage: $0 {start|stop|restart|status}"
++ echo "Usage: $0 {start|stop|restart|status}"
+ ;;
+ esac
+
+diff --git a/scripts/lvm2_cluster_activation_red_hat.sh.in b/scripts/lvm2_cluster_activation_red_hat.sh.in
+index abea026..d8cba2e 100644
+--- a/scripts/lvm2_cluster_activation_red_hat.sh.in
++++ b/scripts/lvm2_cluster_activation_red_hat.sh.in
+@@ -1,4 +1,4 @@
+-#!/bin/bash
++#!/bin/sh
+
+ sbindir=@sbindir@
+
+@@ -54,7 +54,7 @@ case "$1" in
+ rtrn=$?
+ ;;
+ *)
+- echo $"Usage: $0 {activate|deactivate}"
++ echo "Usage: $0 {activate|deactivate}"
+ rtrn=3
+ ;;
+ esac
+diff --git a/scripts/lvm2_lvmetad_init_red_hat.in b/scripts/lvm2_lvmetad_init_red_hat.in
+index b2f5d50..96269a9 100644
+--- a/scripts/lvm2_lvmetad_init_red_hat.in
++++ b/scripts/lvm2_lvmetad_init_red_hat.in
+@@ -1,4 +1,4 @@
+-#!/bin/bash
++#!/bin/sh
+ #
+ # Copyright (C) 2012 Red Hat, Inc. All rights reserved.
+ #
+@@ -105,7 +105,7 @@ case "$1" in
+ ;;
+
+ *)
+- echo $"Usage: $0 {start|stop|force-stop|restart|condrestart|try-restart|status}"
++ echo "Usage: $0 {start|stop|force-stop|restart|condrestart|try-restart|status}"
+ ;;
+ esac
+
+diff --git a/scripts/lvm2_lvmpolld_init_red_hat.in b/scripts/lvm2_lvmpolld_init_red_hat.in
+index c521955..cdbaece 100644
+--- a/scripts/lvm2_lvmpolld_init_red_hat.in
++++ b/scripts/lvm2_lvmpolld_init_red_hat.in
+@@ -1,4 +1,4 @@
+-#!/bin/bash
++#!/bin/sh
+ #
+ # Copyright (C) 2015 Red Hat, Inc. All rights reserved.
+ #
+@@ -107,7 +107,7 @@ case "$1" in
+ ;;
+
+ *)
+- echo $"Usage: $0 {start|stop|force-stop|restart|condrestart|try-restart|status}"
++ echo "Usage: $0 {start|stop|force-stop|restart|condrestart|try-restart|status}"
+ ;;
+ esac
+
+diff --git a/scripts/lvm2_monitoring_init_red_hat.in b/scripts/lvm2_monitoring_init_red_hat.in
+index de7ff0d..9ff6bb7 100644
+--- a/scripts/lvm2_monitoring_init_red_hat.in
++++ b/scripts/lvm2_monitoring_init_red_hat.in
+@@ -1,4 +1,4 @@
+-#!/bin/bash
++#!/bin/sh
+ #
+ # Copyright (C) 2007-2009 Red Hat, Inc. All rights reserved.
+ #
+@@ -128,7 +128,7 @@ case "$1" in
+ ;;
+
+ *)
+- echo $"Usage: $0 {start|stop|restart|status|force-stop}"
++ echo "Usage: $0 {start|stop|restart|status|force-stop}"
+ ;;
+ esac
+
+diff --git a/scripts/lvm2_monitoring_init_rhel4 b/scripts/lvm2_monitoring_init_rhel4
+index 8eb06c5..2e8d0f7 100644
+--- a/scripts/lvm2_monitoring_init_rhel4
++++ b/scripts/lvm2_monitoring_init_rhel4
+@@ -1,4 +1,4 @@
+-#!/bin/bash
++#!/bin/sh
+ #
+ # Copyright (C) 2007 Red Hat, Inc. All rights reserved.
+ #
+@@ -93,7 +93,7 @@ case "$1" in
+ ;;
+
+ *)
+- echo $"Usage: $0 {start|stop|restart|status|force-stop}"
++ echo "Usage: $0 {start|stop|restart|status|force-stop}"
+ ;;
+ esac
+
+--
+2.12.0
+
diff --git a/meta/meta-mediatek/recipes-support/dmsetup/files/0001-implement-libc-specific-reopen_stream.patch b/meta/meta-mediatek/recipes-support/dmsetup/files/0001-implement-libc-specific-reopen_stream.patch
new file mode 100644
index 0000000..5d72402
--- /dev/null
+++ b/meta/meta-mediatek/recipes-support/dmsetup/files/0001-implement-libc-specific-reopen_stream.patch
@@ -0,0 +1,79 @@
+From e3103459416616d3b8508e7176e897b0ae6c90f2 Mon Sep 17 00:00:00 2001
+From: Dengke Du <dengke.du@windriver.com>
+Date: Tue, 25 Oct 2016 11:49:40 +0000
+Subject: [PATCH] implement libc specific reopen_stream
+
+musl defines stdin/stdio/stderr as constant types which means
+we can not assign to them as we are doing here but works ok with glibc
+therefore abstract out the _reopen_stream definition depending upon if
+we are using glibc or otherwise
+
+Origin:
+http://git.alpinelinux.org/cgit/aports/tree/main/lvm2/fix-stdio-usage.patch
+
+Signed-off-by: Khem Raj <raj.khem@gmail.com>
+Signed-off-by: Dengke Du <dengke.du@windriver.com>
+
+---
+ lib/log/log.c | 6 ++++++
+ tools/lvmcmdline.c | 6 +++---
+ 2 files changed, 9 insertions(+), 3 deletions(-)
+
+diff --git a/lib/log/log.c b/lib/log/log.c
+index c933154..3581084 100644
+--- a/lib/log/log.c
++++ b/lib/log/log.c
+@@ -161,6 +161,7 @@ static void _check_and_replace_standard_log_streams(FILE *old_stream, FILE *new_
+ * Close and reopen standard stream on file descriptor fd.
+ */
+ int reopen_standard_stream(FILE **stream, const char *mode)
++#ifdef __GLIBC__
+ {
+ int fd, fd_copy, new_fd;
+ const char *name;
+@@ -207,6 +208,11 @@ int reopen_standard_stream(FILE **stream, const char *mode)
+ *stream = new_stream;
+ return 1;
+ }
++#else
++{
++ return (freopen(NULL, mode, *stream) != NULL);
++}
++#endif
+
+ void init_log_fn(lvm2_log_fn_t log_fn)
+ {
+diff --git a/tools/lvmcmdline.c b/tools/lvmcmdline.c
+index 9a4deb7..f1f18e6 100644
+--- a/tools/lvmcmdline.c
++++ b/tools/lvmcmdline.c
+@@ -1818,7 +1818,7 @@ static int _check_standard_fds(void)
+ int err = is_valid_fd(STDERR_FILENO);
+
+ if (!is_valid_fd(STDIN_FILENO) &&
+- !(stdin = fopen(_PATH_DEVNULL, "r"))) {
++ !freopen(_PATH_DEVNULL, "r", stdin)) {
+ if (err)
+ perror("stdin stream open");
+ else
+@@ -1828,7 +1828,7 @@ static int _check_standard_fds(void)
+ }
+
+ if (!is_valid_fd(STDOUT_FILENO) &&
+- !(stdout = fopen(_PATH_DEVNULL, "w"))) {
++ !freopen(_PATH_DEVNULL, "w", stdout)) {
+ if (err)
+ perror("stdout stream open");
+ /* else no stdout */
+@@ -1836,7 +1836,7 @@ static int _check_standard_fds(void)
+ }
+
+ if (!is_valid_fd(STDERR_FILENO) &&
+- !(stderr = fopen(_PATH_DEVNULL, "w"))) {
++ !freopen(_PATH_DEVNULL, "w", stderr)) {
+ printf("stderr stream open: %s\n",
+ strerror(errno));
+ return 0;
+--
+2.12.0
+
diff --git a/meta/meta-mediatek/recipes-support/dmsetup/files/0002-Guard-use-of-mallinfo-with-__GLIBC__.patch b/meta/meta-mediatek/recipes-support/dmsetup/files/0002-Guard-use-of-mallinfo-with-__GLIBC__.patch
new file mode 100644
index 0000000..95dcede
--- /dev/null
+++ b/meta/meta-mediatek/recipes-support/dmsetup/files/0002-Guard-use-of-mallinfo-with-__GLIBC__.patch
@@ -0,0 +1,30 @@
+From 3ae9c0b607ec33fb07f32a41e9d28cc9068dd39a Mon Sep 17 00:00:00 2001
+From: Dengke Du <dengke.du@windriver.com>
+Date: Tue, 25 Oct 2016 11:52:44 +0000
+Subject: [PATCH] Guard use of mallinfo() with __GLIBC__
+
+This API is glibc-only
+
+Signed-off-by: Khem Raj <raj.khem@gmail.com>
+Signed-off-by: Dengke Du <dengke.du@windriver.com>
+
+---
+ lib/mm/memlock.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/lib/mm/memlock.c b/lib/mm/memlock.c
+index da90144..f34f890 100644
+--- a/lib/mm/memlock.c
++++ b/lib/mm/memlock.c
+@@ -150,7 +150,7 @@ static void _touch_memory(void *mem, size_t size)
+
+ static void _allocate_memory(void)
+ {
+-#ifndef VALGRIND_POOL
++#if !defined(VALGRIND_POOL) && defined(__GLIBC__)
+ void *stack_mem;
+ struct rlimit limit;
+ int i, area = 0, missing = _size_malloc_tmp, max_areas = 32, hblks;
+--
+2.12.0
+
diff --git a/meta/meta-mediatek/recipes-support/dmsetup/files/0003-include-fcntl.h-for-O_-defines-and-fcntl-signature.patch b/meta/meta-mediatek/recipes-support/dmsetup/files/0003-include-fcntl.h-for-O_-defines-and-fcntl-signature.patch
new file mode 100644
index 0000000..9ab1c06
--- /dev/null
+++ b/meta/meta-mediatek/recipes-support/dmsetup/files/0003-include-fcntl.h-for-O_-defines-and-fcntl-signature.patch
@@ -0,0 +1,30 @@
+From b1ad91a059d99afd1ce25823b7c0a8d3ac63d2fd Mon Sep 17 00:00:00 2001
+From: Dengke Du <dengke.du@windriver.com>
+Date: Tue, 25 Oct 2016 11:55:49 +0000
+Subject: [PATCH 3/4] include fcntl.h for O_* defines and fcntl() signature
+
+On glibc _somehow_ this header gets pulled in indirectly
+
+Signed-off-by: Khem Raj <raj.khem@gmail.com>
+Signed-off-by: Dengke Du <dengke.du@windriver.com>
+---
+Upstream-Status: Pending
+---
+ libdaemon/server/daemon-server.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/libdaemon/server/daemon-server.c b/libdaemon/server/daemon-server.c
+index 6af6de9..a9590e7 100644
+--- a/libdaemon/server/daemon-server.c
++++ b/libdaemon/server/daemon-server.c
+@@ -18,6 +18,7 @@
+ #include "daemon-server.h"
+ #include "daemon-log.h"
+
++#include <fcntl.h>
+ #include <dlfcn.h>
+ #include <errno.h>
+ #include <pthread.h>
+--
+2.9.3
+
diff --git a/meta/meta-mediatek/recipes-support/dmsetup/files/0004-tweak-MODPROBE_CMD-for-cross-compile.patch b/meta/meta-mediatek/recipes-support/dmsetup/files/0004-tweak-MODPROBE_CMD-for-cross-compile.patch
new file mode 100644
index 0000000..aaeaa72
--- /dev/null
+++ b/meta/meta-mediatek/recipes-support/dmsetup/files/0004-tweak-MODPROBE_CMD-for-cross-compile.patch
@@ -0,0 +1,38 @@
+From 0012ea63f6070a5d41fa380970f9c30b953237d2 Mon Sep 17 00:00:00 2001
+From: Dengke Du <dengke.du@windriver.com>
+Date: Tue, 25 Oct 2016 11:59:40 +0000
+Subject: [PATCH 4/4] tweak MODPROBE_CMD for cross compile
+
+Lvm uses variable MODPROBE_CMD at runtime, so build time detection of modprobe
+is incorrect.
+------
+|lvm lvcreate --thinpool wrl/pool00 --size 5556m --config devices
+{ preferred_names=["^/dev/mapper/", "^/dev/md/", "^/dev/sd"]
+filter=["r|/loop1$|","r|/loop2$|","r|/loop3$|","r|/loop4$|","r|/loop5$|","r|/loop6$|","r|/loop7$|"] }
+|tmp/sysroots/x86_64-linux/usr/bin/modprobe: execvp failed: No such file or directory
+|tmp/sysroots/x86_64-linux/usr/bin/modprobe failed: 2
+------
+
+Upstream-Status: Inappropriate [oe specific]
+
+Signed-off-by: Hongxu Jia <hongxu.jia@windriver.com>
+Signed-off-by: Dengke Du <dengke.du@windriver.com>
+---
+ configure.in | 1 -
+ 1 file changed, 1 deletion(-)
+
+diff --git a/configure.in b/configure.in
+index cc77aab..a3579f2 100644
+--- a/configure.in
++++ b/configure.in
+@@ -1853,7 +1853,6 @@ if test "$UDEV_SYNC" = yes; then
+ fi
+
+ ################################################################################
+-AC_PATH_TOOL(MODPROBE_CMD, modprobe)
+
+ if test -n "$MODPROBE_CMD"; then
+ AC_DEFINE_UNQUOTED([MODPROBE_CMD], ["$MODPROBE_CMD"], [The path to 'modprobe', if available.])
+--
+2.9.3
+
diff --git a/meta/meta-mediatek/recipes-support/dmsetup/files/0005-do-not-build-manual.patch b/meta/meta-mediatek/recipes-support/dmsetup/files/0005-do-not-build-manual.patch
new file mode 100644
index 0000000..15aa9f5
--- /dev/null
+++ b/meta/meta-mediatek/recipes-support/dmsetup/files/0005-do-not-build-manual.patch
@@ -0,0 +1,58 @@
+From d8bb25e34d6533ba78eaae697771ee499a66706f Mon Sep 17 00:00:00 2001
+From: Hongxu Jia <hongxu.jia@windriver.com>
+Date: Wed, 2 Aug 2017 03:41:37 -0400
+Subject: [PATCH] do not build manual
+
+On some host (ubuntu 1404), build manual failed.
+...
+./tools/man-generator --primary lvscan lvscan.8_des
+Failed to stat description file lvscan.8_des.
+...
+
+Do not build man to workaround the issue.
+
+Upstream-Status: Pending
+
+Signed-off-by: Hongxu Jia <hongxu.jia@windriver.com>
+---
+ Makefile.in | 4 ++--
+ configure.in | 1 -
+ 2 files changed, 2 insertions(+), 3 deletions(-)
+
+diff --git a/Makefile.in b/Makefile.in
+index 31d428d..24f89a2 100644
+--- a/Makefile.in
++++ b/Makefile.in
+@@ -18,7 +18,7 @@ top_builddir = @top_builddir@
+ abs_top_builddir = @abs_top_builddir@
+ abs_top_srcdir = @abs_top_srcdir@
+
+-SUBDIRS = conf daemons include lib libdaemon libdm man scripts tools
++SUBDIRS = conf daemons include lib libdaemon libdm scripts tools
+
+ ifeq ("@UDEV_RULES@", "yes")
+ SUBDIRS += udev
+@@ -69,7 +69,7 @@ liblvm.device-mapper: include.device-mapper
+ daemons.device-mapper: libdm.device-mapper
+ tools.device-mapper: libdm.device-mapper
+ scripts.device-mapper: include.device-mapper
+-device-mapper: tools.device-mapper daemons.device-mapper man.device-mapper
++device-mapper: tools.device-mapper daemons.device-mapper
+
+ ifeq ("@INTL@", "yes")
+ lib.pofile: include.pofile
+diff --git a/configure.in b/configure.in
+index 1dc8819..108ace4 100644
+--- a/configure.in
++++ b/configure.in
+@@ -2213,7 +2213,6 @@ libdm/Makefile
+ libdm/libdevmapper.pc
+ liblvm/Makefile
+ liblvm/liblvm2app.pc
+-man/Makefile
+ po/Makefile
+ python/Makefile
+ python/setup.py
+--
+2.8.1
+
diff --git a/meta/meta-mediatek/recipes-support/dmsetup/files/0006-start-lvm2-monitor.service-after-tmp.mount.patch b/meta/meta-mediatek/recipes-support/dmsetup/files/0006-start-lvm2-monitor.service-after-tmp.mount.patch
new file mode 100644
index 0000000..0e68d62
--- /dev/null
+++ b/meta/meta-mediatek/recipes-support/dmsetup/files/0006-start-lvm2-monitor.service-after-tmp.mount.patch
@@ -0,0 +1,32 @@
+From 24a2c47fd01dde1710f1fa66f5c30ce7010c5956 Mon Sep 17 00:00:00 2001
+From: Hongxu Jia <hongxu.jia@windriver.com>
+Date: Thu, 21 Sep 2017 15:28:10 +0800
+Subject: [PATCH] start lvm2-monitor.service after tmp.mount
+
+The lvm2-monitor.service reqires the existence of locking_dir
+("/tmp/lock/lvm"), and unit tmp.mount is to mount /tmp.
+So start lvm2-monitor.service after tmp.mount
+
+Upstream-Status: Inappropriate [oe specific]
+
+Signed-off-by: Hongxu Jia <hongxu.jia@windriver.com>
+---
+ scripts/lvm2_monitoring_systemd_red_hat.service.in | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/scripts/lvm2_monitoring_systemd_red_hat.service.in b/scripts/lvm2_monitoring_systemd_red_hat.service.in
+index 22238b7..93b2bee 100644
+--- a/scripts/lvm2_monitoring_systemd_red_hat.service.in
++++ b/scripts/lvm2_monitoring_systemd_red_hat.service.in
+@@ -2,7 +2,7 @@
+ Description=Monitoring of LVM2 mirrors, snapshots etc. using dmeventd or progress polling
+ Documentation=man:dmeventd(8) man:lvcreate(8) man:lvchange(8) man:vgchange(8)
+ Requires=dm-event.socket lvm2-lvmetad.socket
+-After=dm-event.socket dm-event.service lvm2-lvmetad.socket lvm2-activation.service lvm2-lvmetad.service
++After=dm-event.socket dm-event.service lvm2-lvmetad.socket lvm2-activation.service lvm2-lvmetad.service tmp.mount
+ Before=local-fs-pre.target
+ DefaultDependencies=no
+ Conflicts=shutdown.target
+--
+1.8.3.1
+
diff --git a/meta/meta-mediatek/recipes-support/dmsetup/files/lvm.conf b/meta/meta-mediatek/recipes-support/dmsetup/files/lvm.conf
new file mode 100644
index 0000000..c2bb85d
--- /dev/null
+++ b/meta/meta-mediatek/recipes-support/dmsetup/files/lvm.conf
@@ -0,0 +1,326 @@
+# This is an example configuration file for the LVM2 system.
+# It contains the default settings that would be used if there was no
+# /etc/lvm/lvm.conf file.
+#
+# Refer to 'man lvm.conf' for further information including the file layout.
+#
+# To put this file in a different directory and override /etc/lvm set
+# the environment variable LVM_SYSTEM_DIR before running the tools.
+
+
+# This section allows you to configure which block devices should
+# be used by the LVM system.
+devices {
+
+ # Where do you want your volume groups to appear ?
+ dir = "/dev"
+
+ # An array of directories that contain the device nodes you wish
+ # to use with LVM2.
+ scan = [ "/dev" ]
+
+ # A filter that tells LVM2 to only use a restricted set of devices.
+ # The filter consists of an array of regular expressions. These
+ # expressions can be delimited by a character of your choice, and
+ # prefixed with either an 'a' (for accept) or 'r' (for reject).
+ # The first expression found to match a device name determines if
+ # the device will be accepted or rejected (ignored). Devices that
+ # don't match any patterns are accepted.
+
+ # Be careful if there there are symbolic links or multiple filesystem
+ # entries for the same device as each name is checked separately against
+ # the list of patterns. The effect is that if any name matches any 'a'
+ # pattern, the device is accepted; otherwise if any name matches any 'r'
+ # pattern it is rejected; otherwise it is accepted.
+
+ # Don't have more than one filter line active at once: only one gets used.
+
+ # Run vgscan after you change this parameter to ensure that
+ # the cache file gets regenerated (see below).
+ # If it doesn't do what you expect, check the output of 'vgscan -vvvv'.
+
+
+ # By default we accept every block device:
+ filter = [ "a/.*/" ]
+
+ # Exclude the cdrom drive
+ # filter = [ "r|/dev/cdrom|" ]
+
+ # When testing I like to work with just loopback devices:
+ # filter = [ "a/loop/", "r/.*/" ]
+
+ # Or maybe all loops and ide drives except hdc:
+ # filter =[ "a|loop|", "r|/dev/hdc|", "a|/dev/ide|", "r|.*|" ]
+
+ # Use anchors if you want to be really specific
+ # filter = [ "a|^/dev/hda8$|", "r/.*/" ]
+
+ # The results of the filtering are cached on disk to avoid
+ # rescanning dud devices (which can take a very long time). By
+ # default this cache file is hidden in the /etc/lvm directory.
+ # It is safe to delete this file: the tools regenerate it.
+ cache = "/etc/lvm/.cache"
+
+ # You can turn off writing this cache file by setting this to 0.
+ write_cache_state = 1
+
+ # Advanced settings.
+
+ # List of pairs of additional acceptable block device types found
+ # in /proc/devices with maximum (non-zero) number of partitions.
+ # types = [ "fd", 16 ]
+
+ # If sysfs is mounted (2.6 kernels) restrict device scanning to
+ # the block devices it believes are valid.
+ # 1 enables; 0 disables.
+ sysfs_scan = 1
+
+ # By default, LVM2 will ignore devices used as components of
+ # software RAID (md) devices by looking for md superblocks.
+ # 1 enables; 0 disables.
+ md_component_detection = 1
+}
+
+# This section that allows you to configure the nature of the
+# information that LVM2 reports.
+log {
+
+ # Controls the messages sent to stdout or stderr.
+ # There are three levels of verbosity, 3 being the most verbose.
+ verbose = 0
+
+ # Should we send log messages through syslog?
+ # 1 is yes; 0 is no.
+ syslog = 1
+
+ # Should we log error and debug messages to a file?
+ # By default there is no log file.
+ #file = "/var/log/lvm2.log"
+
+ # Should we overwrite the log file each time the program is run?
+ # By default we append.
+ overwrite = 0
+
+ # What level of log messages should we send to the log file and/or syslog?
+ # There are 6 syslog-like log levels currently in use - 2 to 7 inclusive.
+ # 7 is the most verbose (LOG_DEBUG).
+ level = 0
+
+ # Format of output messages
+ # Whether or not (1 or 0) to indent messages according to their severity
+ indent = 1
+
+ # Whether or not (1 or 0) to display the command name on each line output
+ command_names = 0
+
+ # A prefix to use before the message text (but after the command name,
+ # if selected). Default is two spaces, so you can see/grep the severity
+ # of each message.
+ prefix = " "
+
+ # To make the messages look similar to the original LVM tools use:
+ # indent = 0
+ # command_names = 1
+ # prefix = " -- "
+
+ # Set this if you want log messages during activation.
+ # Don't use this in low memory situations (can deadlock).
+ # activation = 0
+}
+
+# Configuration of metadata backups and archiving. In LVM2 when we
+# talk about a 'backup' we mean making a copy of the metadata for the
+# *current* system. The 'archive' contains old metadata configurations.
+# Backups are stored in a human readeable text format.
+backup {
+
+ # Should we maintain a backup of the current metadata configuration ?
+ # Use 1 for Yes; 0 for No.
+ # Think very hard before turning this off!
+ backup = 1
+
+ # Where shall we keep it ?
+ # Remember to back up this directory regularly!
+ backup_dir = "/etc/lvm/backup"
+
+ # Should we maintain an archive of old metadata configurations.
+ # Use 1 for Yes; 0 for No.
+ # On by default. Think very hard before turning this off.
+ archive = 1
+
+ # Where should archived files go ?
+ # Remember to back up this directory regularly!
+ archive_dir = "/etc/lvm/archive"
+
+ # What is the minimum number of archive files you wish to keep ?
+ retain_min = 10
+
+ # What is the minimum time you wish to keep an archive file for ?
+ retain_days = 30
+}
+
+# Settings for the running LVM2 in shell (readline) mode.
+shell {
+
+ # Number of lines of history to store in ~/.lvm_history
+ history_size = 100
+}
+
+
+# Miscellaneous global LVM2 settings
+global {
+
+ # The file creation mask for any files and directories created.
+ # Interpreted as octal if the first digit is zero.
+ umask = 077
+
+ # Allow other users to read the files
+ #umask = 022
+
+ # Enabling test mode means that no changes to the on disk metadata
+ # will be made. Equivalent to having the -t option on every
+ # command. Defaults to off.
+ test = 0
+
+ # Whether or not to communicate with the kernel device-mapper.
+ # Set to 0 if you want to use the tools to manipulate LVM metadata
+ # without activating any logical volumes.
+ # If the device-mapper kernel driver is not present in your kernel
+ # setting this to 0 should suppress the error messages.
+ activation = 1
+
+ # If we can't communicate with device-mapper, should we try running
+ # the LVM1 tools?
+ # This option only applies to 2.4 kernels and is provided to help you
+ # switch between device-mapper kernels and LVM1 kernels.
+ # The LVM1 tools need to be installed with .lvm1 suffices
+ # e.g. vgscan.lvm1 and they will stop working after you start using
+ # the new lvm2 on-disk metadata format.
+ # The default value is set when the tools are built.
+ # fallback_to_lvm1 = 0
+
+ # The default metadata format that commands should use - "lvm1" or "lvm2".
+ # The command line override is -M1 or -M2.
+ # Defaults to "lvm1" if compiled in, else "lvm2".
+ # format = "lvm1"
+
+ # Location of proc filesystem
+ proc = "/proc"
+
+ # Type of locking to use. Defaults to file-based locking (1).
+ # Turn locking off by setting to 0 (dangerous: risks metadata corruption
+ # if LVM2 commands get run concurrently).
+ locking_type = 1
+
+ # Local non-LV directory that holds file-based locks while commands are
+ # in progress. A directory like /tmp that may get wiped on reboot is OK.
+ locking_dir = "/tmp/lock/lvm"
+
+ # Other entries can go here to allow you to load shared libraries
+ # e.g. if support for LVM1 metadata was compiled as a shared library use
+ # format_libraries = "liblvm2format1.so"
+ # Full pathnames can be given.
+
+ # Search this directory first for shared libraries.
+ # library_dir = "/lib"
+}
+
+activation {
+ # Device used in place of missing stripes if activating incomplete volume.
+ # For now, you need to set this up yourself first (e.g. with 'dmsetup')
+ # For example, you could make it return I/O errors using the 'error'
+ # target or make it return zeros.
+ missing_stripe_filler = "/dev/ioerror"
+
+ # Size (in KB) of each copy operation when mirroring
+ mirror_region_size = 512
+
+ # How much stack (in KB) to reserve for use while devices suspended
+ reserved_stack = 256
+
+ # How much memory (in KB) to reserve for use while devices suspended
+ reserved_memory = 8192
+
+ # Nice value used while devices suspended
+ process_priority = -18
+
+ # If volume_list is defined, each LV is only activated if there is a
+ # match against the list.
+ # "vgname" and "vgname/lvname" are matched exactly.
+ # "@tag" matches any tag set in the LV or VG.
+ # "@*" matches if any tag defined on the host is also set in the LV or VG
+ #
+ # volume_list = [ "vg1", "vg2/lvol1", "@tag1", "@*" ]
+}
+
+
+####################
+# Advanced section #
+####################
+
+# Metadata settings
+#
+# metadata {
+ # Default number of copies of metadata to hold on each PV. 0, 1 or 2.
+ # You might want to override it from the command line with 0
+ # when running pvcreate on new PVs which are to be added to large VGs.
+
+ # pvmetadatacopies = 1
+
+ # Approximate default size of on-disk metadata areas in sectors.
+ # You should increase this if you have large volume groups or
+ # you want to retain a large on-disk history of your metadata changes.
+
+ # pvmetadatasize = 255
+
+ # List of directories holding live copies of text format metadata.
+ # These directories must not be on logical volumes!
+ # It's possible to use LVM2 with a couple of directories here,
+ # preferably on different (non-LV) filesystems, and with no other
+ # on-disk metadata (pvmetadatacopies = 0). Or this can be in
+ # addition to on-disk metadata areas.
+ # The feature was originally added to simplify testing and is not
+ # supported under low memory situations - the machine could lock up.
+ #
+ # Never edit any files in these directories by hand unless you
+ # you are absolutely sure you know what you are doing! Use
+ # the supplied toolset to make changes (e.g. vgcfgrestore).
+
+ # dirs = [ "/etc/lvm/metadata", "/mnt/disk2/lvm/metadata2" ]
+#}
+
+# Event daemon
+#
+dmeventd {
+ # mirror_library is the library used when monitoring a mirror device.
+ #
+ # "libdevmapper-event-lvm2mirror.so" attempts to recover from
+ # failures. It removes failed devices from a volume group and
+ # reconfigures a mirror as necessary. If no mirror library is
+ # provided, mirrors are not monitored through dmeventd.
+
+ mirror_library = "@libdir@/device-mapper/libdevmapper-event-lvm2mirror.so"
+
+ # snapshot_library is the library used when monitoring a snapshot device.
+ #
+ # "libdevmapper-event-lvm2snapshot.so" monitors the filling of
+ # snapshots and emits a warning through syslog when the use of
+ # the snapshot exceeds 80%. The warning is repeated when 85%, 90% and
+ # 95% of the snapshot is filled.
+
+ snapshot_library = "@libdir@/device-mapper/libdevmapper-event-lvm2snapshot.so"
+
+ # thin_library is the library used when monitoring a thin device.
+ #
+ # "libdevmapper-event-lvm2thin.so" monitors the filling of
+ # pool and emits a warning through syslog when the use of
+ # the pool exceeds 80%. The warning is repeated when 85%, 90% and
+ # 95% of the pool is filled.
+
+ thin_library = "@libdir@/device-mapper/libdevmapper-event-lvm2thin.so"
+
+ # Full path of the dmeventd binary.
+ #
+ # executable = "@DMEVENTD_PATH@"
+}
+
diff --git a/meta/meta-mediatek/recipes-support/encrwpart-init/encrwpart-init.bb b/meta/meta-mediatek/recipes-support/encrwpart-init/encrwpart-init.bb
new file mode 100644
index 0000000..aee10f3
--- /dev/null
+++ b/meta/meta-mediatek/recipes-support/encrwpart-init/encrwpart-init.bb
@@ -0,0 +1,37 @@
+inherit workonsrc
+inherit pkgconfig
+inherit systemd
+
+DESCRIPTION = "Encrypted RW Partition Init"
+LICENSE = "MediaTekProprietary"
+LIC_FILES_CHKSUM = "file://COPYING;md5=d7810fab7487fb0aad327b76f1be7cd7"
+APPS_SRC = "${TOPDIR}/../meta/meta-mediatek/recipes-support/encrwpart-init"
+WORKONSRC = "${APPS_SRC}"
+
+#####Customization Start#####
+RWPART_DEVNAME = "/dev/mmcblk0p10"
+RWPART_MOUNT_DIR = "/data"
+RWPART_FILESYSTEM_SIZE = "100"
+RWPART_KEYSTR = "rwpart@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
+#####Customization End#####
+
+SYSTEMD_PACKAGES = "${PN}"
+SYSTEMD_SERVICE_${PN} = "encrwpart-init.service"
+FILES_${PN} += "${systemd_unitdir}/system/encrwpart-init.service"
+FILES_${PN} += "etc/encrwpart-init.sh"
+
+do_install() {
+ install -d ${D}/etc
+ install -m 755 ${S}files/encrwpart-init.sh ${D}/etc/encrwpart-init.sh
+
+ install -d ${D}${systemd_system_unitdir}
+ install -m 0644 ${S}files/encrwpart-init.service ${D}${systemd_system_unitdir}
+
+ sed -e 's%#RWPART_DEVNAME#%${RWPART_DEVNAME}%g' \
+ -e 's%#RWPART_MOUNT_DIR#%${RWPART_MOUNT_DIR}%g' \
+ -e 's%#RWPART_FILESYSTEM_SIZE#%${RWPART_FILESYSTEM_SIZE}%g' \
+ -e 's%#RWPART_KEYSTR#%${RWPART_KEYSTR}%g' \
+ -i ${D}/etc/encrwpart-init.sh
+}
+
+
diff --git a/meta/meta-mediatek/recipes-support/encrwpart-init/files/encrwpart-init.service b/meta/meta-mediatek/recipes-support/encrwpart-init/files/encrwpart-init.service
new file mode 100644
index 0000000..929a1bc
--- /dev/null
+++ b/meta/meta-mediatek/recipes-support/encrwpart-init/files/encrwpart-init.service
@@ -0,0 +1,10 @@
+[Unit]
+Description=EncrwpartInitScript
+
+[Service]
+ExecStart=/etc/encrwpart-init.sh
+Type=oneshot
+
+[Install]
+Alias=EncrwpartInitScript
+WantedBy=multi-user.target
\ No newline at end of file
diff --git a/meta/meta-mediatek/recipes-support/encrwpart-init/files/encrwpart-init.sh b/meta/meta-mediatek/recipes-support/encrwpart-init/files/encrwpart-init.sh
new file mode 100644
index 0000000..da43b45
--- /dev/null
+++ b/meta/meta-mediatek/recipes-support/encrwpart-init/files/encrwpart-init.sh
@@ -0,0 +1,29 @@
+#!/bin/sh
+#
+# @author
+# @brief generate the top index for each module doc
+
+umount #RWPART_MOUNT_DIR#
+
+mount -t ext4 #RWPART_DEVNAME# #RWPART_MOUNT_DIR#
+
+if [ $? -eq 0 ]; then
+ umount #RWPART_MOUNT_DIR#
+ resize2fs -M #RWPART_DEVNAME#
+ dmsetup create $(basename #RWPART_DEVNAME#)_dmcd --table "0 $(blockdev --getsz #RWPART_DEVNAME#) crypt aes-cbc-plain #RWPART_KEYSTR# 0 #RWPART_DEVNAME# 0"
+ if [ $? -eq 0 ]; then
+ dd if=#RWPART_DEVNAME# of=/dev/mapper/$(basename #RWPART_DEVNAME#)_dmcd bs=1M count=#RWPART_FILESYSTEM_SIZE#
+ resize2fs /dev/mapper/$(basename #RWPART_DEVNAME#)_dmcd
+ mount -t ext4 /dev/mapper/$(basename #RWPART_DEVNAME#)_dmcd #RWPART_MOUNT_DIR#
+ else
+ resize2fs #RWPART_DEVNAME#
+ mount -t ext4 #RWPART_DEVNAME# #RWPART_MOUNT_DIR#
+ exit 0
+ fi
+else
+ dmsetup create $(basename #RWPART_DEVNAME#)_dmcd --table "0 $(blockdev --getsz #RWPART_DEVNAME#) crypt aes-cbc-plain #RWPART_KEYSTR# 0 #RWPART_DEVNAME# 0"
+ if [ $? -ne 0 ]; then
+ exit 0
+ fi
+ mount -t ext4 /dev/mapper/$(basename #RWPART_DEVNAME#)_dmcd #RWPART_MOUNT_DIR#
+fi
diff --git a/meta/meta-mediatek/recipes-support/encryptlibrary-init/HOWTO b/meta/meta-mediatek/recipes-support/encryptlibrary-init/HOWTO
new file mode 100644
index 0000000..d0982a1
--- /dev/null
+++ b/meta/meta-mediatek/recipes-support/encryptlibrary-init/HOWTO
@@ -0,0 +1,10 @@
+MTK side:
+1.encrypt library on platform with command "secure_program enc [path/to/library] [path/to/encryptedlibrary]
+2.put encryptedlibrary in folder "files"
+
+Customer side:
+1.put encryptedlibrary in folder "files" after receiving encryptedlibrary
+2.make sure or modify "EncryptedLibraryName" value to library name in encryptlibrary-init.bb
+4.add encryptlibrary-init in image:
+eg: add encryptlibrary-init in section "IMAGE_INSTALL_append" of meta/meta-mediatek-mt8516/recipes-audio/images/mtk-image-aud-8516.bb
+5.at bootup time, the encryptedlibrary will be decrypted and put in /tmp
diff --git a/meta/meta-mediatek/recipes-support/encryptlibrary-init/encryptlibrary-init.bb b/meta/meta-mediatek/recipes-support/encryptlibrary-init/encryptlibrary-init.bb
new file mode 100644
index 0000000..c187b4c
--- /dev/null
+++ b/meta/meta-mediatek/recipes-support/encryptlibrary-init/encryptlibrary-init.bb
@@ -0,0 +1,35 @@
+inherit workonsrc
+inherit pkgconfig
+inherit systemd
+
+DESCRIPTION = "Encrypted Library Decryption Helper"
+LICENSE = "MediaTekProprietary"
+LIC_FILES_CHKSUM = "file://COPYING;md5=d7810fab7487fb0aad327b76f1be7cd7"
+APPS_SRC = "${TOPDIR}/../meta/meta-mediatek/recipes-support/encryptlibrary-init"
+SECURE_PROGRAM = "secure_program"
+WORKONSRC = "${APPS_SRC}"
+
+#####Customization Start#####
+EncryptedLibraryName = "libMtkOmxEac3Dec.so"
+#####Customization End#####
+
+SYSTEMD_PACKAGES = "${PN}"
+SYSTEMD_SERVICE_${PN} = "encryptlibrary-init.service"
+FILES_${PN} += "${systemd_unitdir}/system/encryptlibrary-init.service"
+FILES_${PN} += "etc/encryptlibrary-init.sh"
+FILES_${PN} += "${libdir}/encrypted/${EncryptedLibraryName}"
+
+do_install() {
+ install -d ${D}${systemd_system_unitdir}
+ install -m 0755 ${S}files/encryptlibrary-init.service ${D}${systemd_system_unitdir}
+
+ install -d ${D}/etc
+ install -m 755 ${S}files/encryptlibrary-init.sh ${D}/etc/encryptlibrary-init.sh
+
+ install -d ${D}${libdir}/encrypted
+ install -m 644 ${S}files/${EncryptedLibraryName} ${D}${libdir}/encrypted
+
+ echo "${SECURE_PROGRAM} dec /usr/lib/encrypted/${EncryptedLibraryName} /tmp/${EncryptedLibraryName}" >> ${D}/etc/encryptlibrary-init.sh
+}
+
+
diff --git a/meta/meta-mediatek/recipes-support/encryptlibrary-init/files/encryptlibrary-init.service b/meta/meta-mediatek/recipes-support/encryptlibrary-init/files/encryptlibrary-init.service
new file mode 100644
index 0000000..678f1e8
--- /dev/null
+++ b/meta/meta-mediatek/recipes-support/encryptlibrary-init/files/encryptlibrary-init.service
@@ -0,0 +1,10 @@
+[Unit]
+Description=EncryptedFileDecryptedHelperScript
+
+[Service]
+ExecStart=/etc/encryptlibrary-init.sh
+Type=simple
+
+[Install]
+Alias=DecryptionHelperScript
+WantedBy=multi-user.target
\ No newline at end of file
diff --git a/meta/meta-mediatek/recipes-support/encryptlibrary-init/files/encryptlibrary-init.sh b/meta/meta-mediatek/recipes-support/encryptlibrary-init/files/encryptlibrary-init.sh
new file mode 100644
index 0000000..cf14349
--- /dev/null
+++ b/meta/meta-mediatek/recipes-support/encryptlibrary-init/files/encryptlibrary-init.sh
@@ -0,0 +1,4 @@
+#!/bin/sh
+#
+# @author
+# @brief generate the top index for each module doc
diff --git a/meta/meta-mediatek/recipes-support/ewriter/ewriter.bb b/meta/meta-mediatek/recipes-support/ewriter/ewriter.bb
new file mode 100644
index 0000000..78090cf
--- /dev/null
+++ b/meta/meta-mediatek/recipes-support/ewriter/ewriter.bb
@@ -0,0 +1,24 @@
+DESCRIPTION = "MTK eFuse Writer"
+LICENSE = "MediaTekProprietary"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=e1696b147d49d491bcb4da1a57173fff"
+
+inherit workonsrc
+WORKONSRC = "${TOPDIR}/../src/support/efuse_writer"
+
+DEPENDS += "${@bb.utils.contains('TEE_SUPPORT', 'mtee', 'tzapp', '' ,d)}"
+RDEPENDS_${PN} += "${@bb.utils.contains('TEE_SUPPORT', 'mtee', 'tzapp', '' ,d)}"
+DEPENDS += "${@bb.utils.contains('TEE_SUPPORT', 'optee', 'optee-services', '' ,d)}"
+RDEPENDS_${PN} += "${@bb.utils.contains('TEE_SUPPORT', 'optee', 'optee-services', '' ,d)}"
+
+do_compile() {
+ if test "${TEE_SUPPORT}" = "optee" ;then
+ oe_runmake LDFLAGS='${LDFLAGS} -ltz_efuse'
+ else
+ oe_runmake LDFLAGS='${LDFLAGS} -ltz_efuse -ltz_uree'
+ fi
+}
+
+do_install() {
+ install -d ${D}${bindir}
+ install -m 0755 ewriter ${D}${bindir}/
+}
\ No newline at end of file
diff --git a/meta/meta-mediatek/recipes-support/fsck-msdos/files/makefile.patch b/meta/meta-mediatek/recipes-support/fsck-msdos/files/makefile.patch
new file mode 100755
index 0000000..e4be6f1
--- /dev/null
+++ b/meta/meta-mediatek/recipes-support/fsck-msdos/files/makefile.patch
@@ -0,0 +1,19 @@
+diff --git a/Makefile b/Makefile
+new file mode 100644
+index 0000000..e0cce70
+--- /dev/null
++++ b/Makefile
+@@ -0,0 +1,13 @@
++TARGET := fsck_msdos
++SOURCES := boot.c check.c dir.c fat.c main.c
++OBJECTS := $(SOURCES:.c=.o)
++
++.PHONY: all clean install
++
++all: $(TARGET)
++
++$(TARGET): $(OBJECTS)
++ $(LINK.o) $^ -o $@
++
++clean:
++ $(RM) $(OBJECTS) $(TARGET)
diff --git a/meta/meta-mediatek/recipes-support/libavb/files/libavb.patch b/meta/meta-mediatek/recipes-support/libavb/files/libavb.patch
new file mode 100644
index 0000000..92fe61f
--- /dev/null
+++ b/meta/meta-mediatek/recipes-support/libavb/files/libavb.patch
@@ -0,0 +1,680 @@
+diff --git a/libavb/avb_crc32.c b/libavb/avb_crc32.c
+index 9abed54..491fb36 100644
+--- a/libavb/avb_crc32.c
++++ b/libavb/avb_crc32.c
+@@ -42,11 +42,12 @@
+ * CRC32 code derived from work by Gary S. Brown.
+ */
+
+-#include "avb_sysdeps.h"
++//#include "avb_sysdeps.h"
++#include "avb_util.h"
+
+ /* Code taken from FreeBSD 8 */
+
+-static uint32_t crc32_tab[] = {
++static uint32_t iavb_crc32_tab[] = {
+ 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
+ 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
+ 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
+@@ -98,16 +99,16 @@ static uint32_t crc32_tab[] = {
+ * in sys/libkern.h, where it can be inlined.
+ */
+
+-static uint32_t crc32(uint32_t crc_in, const uint8_t* buf, int size) {
++static uint32_t iavb_crc32(uint32_t crc_in, const uint8_t* buf, int size) {
+ const uint8_t* p = buf;
+ uint32_t crc;
+
+ crc = crc_in ^ ~0U;
+ while (size--)
+- crc = crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8);
++ crc = iavb_crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8);
+ return crc ^ ~0U;
+ }
+
+ uint32_t avb_crc32(const uint8_t* buf, size_t size) {
+- return crc32(0, buf, size);
++ return iavb_crc32(0, buf, size);
+ }
+diff --git a/libavb/avb_util.c b/libavb/avb_util.c
+index 43662b4..4105d38 100644
+--- a/libavb/avb_util.c
++++ b/libavb/avb_util.c
+@@ -24,31 +24,7 @@
+
+ #include "avb_util.h"
+
+-#include <stdarg.h>
+-
+-uint32_t avb_be32toh(uint32_t in) {
+- uint8_t* d = (uint8_t*)∈
+- uint32_t ret;
+- ret = ((uint32_t)d[0]) << 24;
+- ret |= ((uint32_t)d[1]) << 16;
+- ret |= ((uint32_t)d[2]) << 8;
+- ret |= ((uint32_t)d[3]);
+- return ret;
+-}
+-
+-uint64_t avb_be64toh(uint64_t in) {
+- uint8_t* d = (uint8_t*)∈
+- uint64_t ret;
+- ret = ((uint64_t)d[0]) << 56;
+- ret |= ((uint64_t)d[1]) << 48;
+- ret |= ((uint64_t)d[2]) << 40;
+- ret |= ((uint64_t)d[3]) << 32;
+- ret |= ((uint64_t)d[4]) << 24;
+- ret |= ((uint64_t)d[5]) << 16;
+- ret |= ((uint64_t)d[6]) << 8;
+- ret |= ((uint64_t)d[7]);
+- return ret;
+-}
++//#include <stdarg.h>
+
+ /* Converts a 32-bit unsigned integer from host to big-endian byte order. */
+ uint32_t avb_htobe32(uint32_t in) {
+@@ -63,341 +39,3 @@ uint32_t avb_htobe32(uint32_t in) {
+ return ret.word;
+ }
+
+-/* Converts a 64-bit unsigned integer from host to big-endian byte order. */
+-uint64_t avb_htobe64(uint64_t in) {
+- union {
+- uint64_t word;
+- uint8_t bytes[8];
+- } ret;
+- ret.bytes[0] = (in >> 56) & 0xff;
+- ret.bytes[1] = (in >> 48) & 0xff;
+- ret.bytes[2] = (in >> 40) & 0xff;
+- ret.bytes[3] = (in >> 32) & 0xff;
+- ret.bytes[4] = (in >> 24) & 0xff;
+- ret.bytes[5] = (in >> 16) & 0xff;
+- ret.bytes[6] = (in >> 8) & 0xff;
+- ret.bytes[7] = in & 0xff;
+- return ret.word;
+-}
+-
+-int avb_safe_memcmp(const void* s1, const void* s2, size_t n) {
+- const unsigned char* us1 = s1;
+- const unsigned char* us2 = s2;
+- int result = 0;
+-
+- if (0 == n) {
+- return 0;
+- }
+-
+- /*
+- * Code snippet without data-dependent branch due to Nate Lawson
+- * (nate@root.org) of Root Labs.
+- */
+- while (n--) {
+- result |= *us1++ ^ *us2++;
+- }
+-
+- return result != 0;
+-}
+-
+-bool avb_safe_add_to(uint64_t* value, uint64_t value_to_add) {
+- uint64_t original_value;
+-
+- avb_assert(value != NULL);
+-
+- original_value = *value;
+-
+- *value += value_to_add;
+- if (*value < original_value) {
+- avb_error("Overflow when adding values.\n");
+- return false;
+- }
+-
+- return true;
+-}
+-
+-bool avb_safe_add(uint64_t* out_result, uint64_t a, uint64_t b) {
+- uint64_t dummy;
+- if (out_result == NULL) {
+- out_result = &dummy;
+- }
+- *out_result = a;
+- return avb_safe_add_to(out_result, b);
+-}
+-
+-bool avb_validate_utf8(const uint8_t* data, size_t num_bytes) {
+- size_t n;
+- unsigned int num_cc;
+-
+- for (n = 0, num_cc = 0; n < num_bytes; n++) {
+- uint8_t c = data[n];
+-
+- if (num_cc > 0) {
+- if ((c & (0x80 | 0x40)) == 0x80) {
+- /* 10xx xxxx */
+- } else {
+- goto fail;
+- }
+- num_cc--;
+- } else {
+- if (c < 0x80) {
+- num_cc = 0;
+- } else if ((c & (0x80 | 0x40 | 0x20)) == (0x80 | 0x40)) {
+- /* 110x xxxx */
+- num_cc = 1;
+- } else if ((c & (0x80 | 0x40 | 0x20 | 0x10)) == (0x80 | 0x40 | 0x20)) {
+- /* 1110 xxxx */
+- num_cc = 2;
+- } else if ((c & (0x80 | 0x40 | 0x20 | 0x10 | 0x08)) ==
+- (0x80 | 0x40 | 0x20 | 0x10)) {
+- /* 1111 0xxx */
+- num_cc = 3;
+- } else {
+- goto fail;
+- }
+- }
+- }
+-
+- if (num_cc != 0) {
+- goto fail;
+- }
+-
+- return true;
+-
+-fail:
+- return false;
+-}
+-
+-bool avb_str_concat(char* buf,
+- size_t buf_size,
+- const char* str1,
+- size_t str1_len,
+- const char* str2,
+- size_t str2_len) {
+- uint64_t combined_len;
+-
+- if (!avb_safe_add(&combined_len, str1_len, str2_len)) {
+- avb_error("Overflow when adding string sizes.\n");
+- return false;
+- }
+-
+- if (combined_len > buf_size - 1) {
+- avb_error("Insufficient buffer space.\n");
+- return false;
+- }
+-
+- avb_memcpy(buf, str1, str1_len);
+- avb_memcpy(buf + str1_len, str2, str2_len);
+- buf[combined_len] = '\0';
+-
+- return true;
+-}
+-
+-void* avb_malloc(size_t size) {
+- void* ret = avb_malloc_(size);
+- if (ret == NULL) {
+- avb_error("Failed to allocate memory.\n");
+- return NULL;
+- }
+- return ret;
+-}
+-
+-void* avb_calloc(size_t size) {
+- void* ret = avb_malloc(size);
+- if (ret == NULL) {
+- return NULL;
+- }
+-
+- avb_memset(ret, '\0', size);
+- return ret;
+-}
+-
+-char* avb_strdup(const char* str) {
+- size_t len = avb_strlen(str);
+- char* ret = avb_malloc(len + 1);
+- if (ret == NULL) {
+- return NULL;
+- }
+-
+- avb_memcpy(ret, str, len);
+- ret[len] = '\0';
+-
+- return ret;
+-}
+-
+-const char* avb_strstr(const char* haystack, const char* needle) {
+- size_t n, m;
+-
+- /* Look through |haystack| and check if the first character of
+- * |needle| matches. If so, check the rest of |needle|.
+- */
+- for (n = 0; haystack[n] != '\0'; n++) {
+- if (haystack[n] != needle[0]) {
+- continue;
+- }
+-
+- for (m = 1;; m++) {
+- if (needle[m] == '\0') {
+- return haystack + n;
+- }
+-
+- if (haystack[n + m] != needle[m]) {
+- break;
+- }
+- }
+- }
+-
+- return NULL;
+-}
+-
+-const char* avb_strv_find_str(const char* const* strings,
+- const char* str,
+- size_t str_size) {
+- size_t n;
+- for (n = 0; strings[n] != NULL; n++) {
+- if (avb_strlen(strings[n]) == str_size &&
+- avb_memcmp(strings[n], str, str_size) == 0) {
+- return strings[n];
+- }
+- }
+- return NULL;
+-}
+-
+-char* avb_replace(const char* str, const char* search, const char* replace) {
+- char* ret = NULL;
+- size_t ret_len = 0;
+- size_t search_len, replace_len;
+- const char* str_after_last_replace;
+-
+- search_len = avb_strlen(search);
+- replace_len = avb_strlen(replace);
+-
+- str_after_last_replace = str;
+- while (*str != '\0') {
+- const char* s;
+- size_t num_before;
+- size_t num_new;
+-
+- s = avb_strstr(str, search);
+- if (s == NULL) {
+- break;
+- }
+-
+- num_before = s - str;
+-
+- if (ret == NULL) {
+- num_new = num_before + replace_len + 1;
+- ret = avb_malloc(num_new);
+- if (ret == NULL) {
+- goto out;
+- }
+- avb_memcpy(ret, str, num_before);
+- avb_memcpy(ret + num_before, replace, replace_len);
+- ret[num_new - 1] = '\0';
+- ret_len = num_new - 1;
+- } else {
+- char* new_str;
+- num_new = ret_len + num_before + replace_len + 1;
+- new_str = avb_malloc(num_new);
+- if (ret == NULL) {
+- goto out;
+- }
+- avb_memcpy(new_str, ret, ret_len);
+- avb_memcpy(new_str + ret_len, str, num_before);
+- avb_memcpy(new_str + ret_len + num_before, replace, replace_len);
+- new_str[num_new - 1] = '\0';
+- avb_free(ret);
+- ret = new_str;
+- ret_len = num_new - 1;
+- }
+-
+- str = s + search_len;
+- str_after_last_replace = str;
+- }
+-
+- if (ret == NULL) {
+- ret = avb_strdup(str_after_last_replace);
+- if (ret == NULL) {
+- goto out;
+- }
+- } else {
+- size_t num_remaining = avb_strlen(str_after_last_replace);
+- size_t num_new = ret_len + num_remaining + 1;
+- char* new_str = avb_malloc(num_new);
+- if (ret == NULL) {
+- goto out;
+- }
+- avb_memcpy(new_str, ret, ret_len);
+- avb_memcpy(new_str + ret_len, str_after_last_replace, num_remaining);
+- new_str[num_new - 1] = '\0';
+- avb_free(ret);
+- ret = new_str;
+- ret_len = num_new - 1;
+- }
+-
+-out:
+- return ret;
+-}
+-
+-/* We only support a limited amount of strings in avb_strdupv(). */
+-#define AVB_STRDUPV_MAX_NUM_STRINGS 32
+-
+-char* avb_strdupv(const char* str, ...) {
+- va_list ap;
+- const char* strings[AVB_STRDUPV_MAX_NUM_STRINGS];
+- size_t lengths[AVB_STRDUPV_MAX_NUM_STRINGS];
+- size_t num_strings, n;
+- uint64_t total_length;
+- char *ret = NULL, *dest;
+-
+- num_strings = 0;
+- total_length = 0;
+- va_start(ap, str);
+- do {
+- size_t str_len = avb_strlen(str);
+- strings[num_strings] = str;
+- lengths[num_strings] = str_len;
+- if (!avb_safe_add_to(&total_length, str_len)) {
+- avb_fatal("Overflow while determining total length.\n");
+- break;
+- }
+- num_strings++;
+- if (num_strings == AVB_STRDUPV_MAX_NUM_STRINGS) {
+- avb_fatal("Too many strings passed.\n");
+- break;
+- }
+- str = va_arg(ap, const char*);
+- } while (str != NULL);
+- va_end(ap);
+-
+- ret = avb_malloc(total_length + 1);
+- if (ret == NULL) {
+- goto out;
+- }
+-
+- dest = ret;
+- for (n = 0; n < num_strings; n++) {
+- avb_memcpy(dest, strings[n], lengths[n]);
+- dest += lengths[n];
+- }
+- *dest = '\0';
+- avb_assert(dest == ret + total_length);
+-
+-out:
+- return ret;
+-}
+-
+-const char* avb_basename(const char* str) {
+- int64_t n;
+- size_t len;
+-
+- len = avb_strlen(str);
+- if (len >= 2) {
+- for (n = len - 2; n >= 0; n--) {
+- if (str[n] == '/') {
+- return str + n + 1;
+- }
+- }
+- }
+- return str;
+-}
+diff --git a/libavb/avb_util.h b/libavb/avb_util.h
+index 07c3258..589e64c 100644
+--- a/libavb/avb_util.h
++++ b/libavb/avb_util.h
+@@ -22,254 +22,20 @@
+ * SOFTWARE.
+ */
+
+-#if !defined(AVB_INSIDE_LIBAVB_H) && !defined(AVB_COMPILATION)
+-#error "Never include this file directly, include libavb.h instead."
+-#endif
+-
+ #ifndef AVB_UTIL_H_
+ #define AVB_UTIL_H_
+
+-#include "avb_sysdeps.h"
+-
++#include <stdint.h>
++#include <sys/types.h>
+ #ifdef __cplusplus
+ extern "C" {
+ #endif
+-
+-#define AVB_STRINGIFY(x) #x
+-#define AVB_TO_STRING(x) AVB_STRINGIFY(x)
+-
+-#ifdef AVB_ENABLE_DEBUG
+-/* Aborts the program if |expr| is false.
+- *
+- * This has no effect unless AVB_ENABLE_DEBUG is defined.
+- */
+-#define avb_assert(expr) \
+- do { \
+- if (!(expr)) { \
+- avb_fatal("assert fail: " #expr "\n"); \
+- } \
+- } while (0)
+-#else
+-#define avb_assert(expr)
+-#endif
+-
+-/* Aborts the program if reached.
+- *
+- * This has no effect unless AVB_ENABLE_DEBUG is defined.
+- */
+-#ifdef AVB_ENABLE_DEBUG
+-#define avb_assert_not_reached() \
+- do { \
+- avb_fatal("assert_not_reached()\n"); \
+- } while (0)
+-#else
+-#define avb_assert_not_reached()
+-#endif
+-
+-/* Aborts the program if |addr| is not word-aligned.
+- *
+- * This has no effect unless AVB_ENABLE_DEBUG is defined.
+- */
+-#define avb_assert_aligned(addr) \
+- avb_assert((((uintptr_t)addr) & (AVB_ALIGNMENT_SIZE - 1)) == 0)
+-
+-#ifdef AVB_ENABLE_DEBUG
+-/* Print functions, used for diagnostics.
+- *
+- * These have no effect unless AVB_ENABLE_DEBUG is defined.
+- */
+-#define avb_debug(message) \
+- do { \
+- avb_printv(avb_basename(__FILE__), \
+- ":", \
+- AVB_TO_STRING(__LINE__), \
+- ": DEBUG: ", \
+- message, \
+- NULL); \
+- } while (0)
+-#define avb_debugv(message, ...) \
+- do { \
+- avb_printv(avb_basename(__FILE__), \
+- ":", \
+- AVB_TO_STRING(__LINE__), \
+- ": DEBUG: ", \
+- message, \
+- ##__VA_ARGS__); \
+- } while (0)
+-#else
+-#define avb_debug(message)
+-#define avb_debugv(message, ...)
+-#endif
+-
+-/* Prints out a message. This is typically used if a runtime-error
+- * occurs.
+- */
+-#define avb_error(message) \
+- do { \
+- avb_printv(avb_basename(__FILE__), \
+- ":", \
+- AVB_TO_STRING(__LINE__), \
+- ": ERROR: ", \
+- message, \
+- NULL); \
+- } while (0)
+-#define avb_errorv(message, ...) \
+- do { \
+- avb_printv(avb_basename(__FILE__), \
+- ":", \
+- AVB_TO_STRING(__LINE__), \
+- ": ERROR: ", \
+- message, \
+- ##__VA_ARGS__); \
+- } while (0)
+-
+-/* Prints out a message and calls avb_abort().
+- */
+-#define avb_fatal(message) \
+- do { \
+- avb_printv(avb_basename(__FILE__), \
+- ":", \
+- AVB_TO_STRING(__LINE__), \
+- ": FATAL: ", \
+- message, \
+- NULL); \
+- avb_abort(); \
+- } while (0)
+-#define avb_fatalv(message, ...) \
+- do { \
+- avb_printv(avb_basename(__FILE__), \
+- ":", \
+- AVB_TO_STRING(__LINE__), \
+- ": FATAL: ", \
+- message, \
+- ##__VA_ARGS__); \
+- avb_abort(); \
+- } while (0)
+-
+-/* Converts a 32-bit unsigned integer from big-endian to host byte order. */
+-uint32_t avb_be32toh(uint32_t in) AVB_ATTR_WARN_UNUSED_RESULT;
+-
+-/* Converts a 64-bit unsigned integer from big-endian to host byte order. */
+-uint64_t avb_be64toh(uint64_t in) AVB_ATTR_WARN_UNUSED_RESULT;
+-
+ /* Converts a 32-bit unsigned integer from host to big-endian byte order. */
+-uint32_t avb_htobe32(uint32_t in) AVB_ATTR_WARN_UNUSED_RESULT;
+-
+-/* Converts a 64-bit unsigned integer from host to big-endian byte order. */
+-uint64_t avb_htobe64(uint64_t in) AVB_ATTR_WARN_UNUSED_RESULT;
+-
+-/* Compare |n| bytes starting at |s1| with |s2| and return 0 if they
+- * match, 1 if they don't. Returns 0 if |n|==0, since no bytes
+- * mismatched.
+- *
+- * Time taken to perform the comparison is only dependent on |n| and
+- * not on the relationship of the match between |s1| and |s2|.
+- *
+- * Note that unlike avb_memcmp(), this only indicates inequality, not
+- * whether |s1| is less than or greater than |s2|.
+- */
+-int avb_safe_memcmp(const void* s1,
+- const void* s2,
+- size_t n) AVB_ATTR_WARN_UNUSED_RESULT;
+-
+-/* Adds |value_to_add| to |value| with overflow protection.
+- *
+- * Returns false if the addition overflows, true otherwise. In either
+- * case, |value| is always modified.
+- */
+-bool avb_safe_add_to(uint64_t* value,
+- uint64_t value_to_add) AVB_ATTR_WARN_UNUSED_RESULT;
+-
+-/* Adds |a| and |b| with overflow protection, returning the value in
+- * |out_result|.
+- *
+- * It's permissible to pass NULL for |out_result| if you just want to
+- * check that the addition would not overflow.
+- *
+- * Returns false if the addition overflows, true otherwise.
+- */
+-bool avb_safe_add(uint64_t* out_result,
+- uint64_t a,
+- uint64_t b) AVB_ATTR_WARN_UNUSED_RESULT;
+-
+-/* Checks if |num_bytes| data at |data| is a valid UTF-8
+- * string. Returns true if valid UTF-8, false otherwise.
+- */
+-bool avb_validate_utf8(const uint8_t* data,
+- size_t num_bytes) AVB_ATTR_WARN_UNUSED_RESULT;
+-
+-/* Concatenates |str1| (of |str1_len| bytes) and |str2| (of |str2_len|
+- * bytes) and puts the result in |buf| which holds |buf_size|
+- * bytes. The result is also guaranteed to be NUL terminated. Fail if
+- * there is not enough room in |buf| for the resulting string plus
+- * terminating NUL byte.
+- *
+- * Returns true if the operation succeeds, false otherwise.
+- */
+-bool avb_str_concat(char* buf,
+- size_t buf_size,
+- const char* str1,
+- size_t str1_len,
+- const char* str2,
+- size_t str2_len);
+-
+-/* Like avb_malloc_() but prints a error using avb_error() if memory
+- * allocation fails.
+- */
+-void* avb_malloc(size_t size) AVB_ATTR_WARN_UNUSED_RESULT;
+-
+-/* Like avb_malloc() but sets the memory with zeroes. */
+-void* avb_calloc(size_t size) AVB_ATTR_WARN_UNUSED_RESULT;
+-
+-/* Duplicates a NUL-terminated string. Returns NULL on OOM. */
+-char* avb_strdup(const char* str) AVB_ATTR_WARN_UNUSED_RESULT;
+-
+-/* Duplicates a NULL-terminated array of NUL-terminated strings by
+- * concatenating them. The returned string will be
+- * NUL-terminated. Returns NULL on OOM.
+- */
+-char* avb_strdupv(const char* str,
+- ...) AVB_ATTR_WARN_UNUSED_RESULT AVB_ATTR_SENTINEL;
+-
+-/* Finds the first occurrence of |needle| in the string |haystack|
+- * where both strings are NUL-terminated strings. The terminating NUL
+- * bytes are not compared.
+- *
+- * Returns NULL if not found, otherwise points into |haystack| for the
+- * first occurrence of |needle|.
+- */
+-const char* avb_strstr(const char* haystack,
+- const char* needle) AVB_ATTR_WARN_UNUSED_RESULT;
+-
+-/* Finds the first occurrence of |str| in the NULL-terminated string
+- * array |strings|. Each element in |strings| must be
+- * NUL-terminated. The string given by |str| need not be
+- * NUL-terminated but its size must be given in |str_size|.
+- *
+- * Returns NULL if not found, otherwise points into |strings| for the
+- * first occurrence of |str|.
+- */
+-const char* avb_strv_find_str(const char* const* strings,
+- const char* str,
+- size_t str_size);
+-
+-/* Replaces all occurrences of |search| with |replace| in |str|.
+- *
+- * Returns a newly allocated string or NULL if out of memory.
+- */
+-char* avb_replace(const char* str,
+- const char* search,
+- const char* replace) AVB_ATTR_WARN_UNUSED_RESULT;
++uint32_t avb_htobe32(uint32_t in);
+
+ /* Calculates the CRC-32 for data in |buf| of size |buf_size|. */
+ uint32_t avb_crc32(const uint8_t* buf, size_t buf_size);
+
+-/* Returns the basename of |str|. This is defined as the last path
+- * component, assuming the normal POSIX separator '/'. If there are no
+- * separators, returns |str|.
+- */
+-const char* avb_basename(const char* str);
+-
+ #ifdef __cplusplus
+ }
+ #endif
diff --git a/meta/meta-mediatek/recipes-support/libavb/libavb.bb b/meta/meta-mediatek/recipes-support/libavb/libavb.bb
new file mode 100644
index 0000000..63e979b
--- /dev/null
+++ b/meta/meta-mediatek/recipes-support/libavb/libavb.bb
@@ -0,0 +1,25 @@
+inherit deploy
+
+DESCRIPTION = "Android Verify Boot"
+LICENSE = "Apache-2.0"
+LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/Apache-2.0;md5=89aea4e17d99a7cacdbeed46a0096b10"
+SRC_URI = " \
+ git://android.googlesource.com/platform/external/avb;name=platform/external/avb;destsuffix=platform/external/avb/;protocol=https \
+ file://libavb.patch \
+"
+SRCREV = "c68f082d910b674f9e5ecf05ebe77432dbbfe0b6"
+
+SRC_URI[sha256sum] = "833893127582352d05d925e36a2ba82d7837105ec8915cd82c7ba9abdddcf680"
+SRC_URI[md5sum] = "1935b6e637d9413cc48115e7602dec4f"
+
+S = "${WORKDIR}/platform/external/avb"
+
+INSANE_SKIP_${PN} += "installed-vs-shipped"
+
+do_install() {
+ install -d ${D}${includedir}
+ install -d ${D}${datadir}
+ install -m 0644 ${S}/libavb/avb_util.h ${D}${includedir}
+ install -m 0644 ${S}/libavb/avb_crc32.c ${D}${datadir}
+ install -m 0644 ${S}/libavb/avb_util.c ${D}${datadir}
+}
\ No newline at end of file
diff --git a/meta/meta-mediatek/recipes-support/libhardware/files/hardware.patch b/meta/meta-mediatek/recipes-support/libhardware/files/hardware.patch
new file mode 100644
index 0000000..338f369
--- /dev/null
+++ b/meta/meta-mediatek/recipes-support/libhardware/files/hardware.patch
@@ -0,0 +1,15 @@
+diff --git a/include/hardware/hardware.h b/include/hardware/hardware.h
+index bf076f6c..ecc12cb1 100644
+--- a/include/hardware/hardware.h
++++ b/include/hardware/hardware.h
+@@ -20,8 +20,8 @@
+ #include <stdint.h>
+ #include <sys/cdefs.h>
+
+-#include <cutils/native_handle.h>
+-#include <system/graphics.h>
++//#include <cutils/native_handle.h>
++//#include <system/graphics.h>
+
+ __BEGIN_DECLS
+
diff --git a/meta/meta-mediatek/recipes-support/libhardware/libhardware.bb b/meta/meta-mediatek/recipes-support/libhardware/libhardware.bb
new file mode 100644
index 0000000..988c940
--- /dev/null
+++ b/meta/meta-mediatek/recipes-support/libhardware/libhardware.bb
@@ -0,0 +1,18 @@
+DESCRIPTION = "Android libhardware"
+LICENSE = "Apache-2.0"
+LIC_FILES_CHKSUM = "file://NOTICE;md5=9645f39e9db895a4aa6e02cb57294595"
+
+SRC_URI = " \
+ git://android.googlesource.com/platform/hardware/libhardware;name=platform/hardware/libhardware;destsuffix=platform/hardware/libhardware/ \
+ file://hardware.patch \
+"
+
+SRCREV_platform/hardware/libhardware = "51d03179c9ddeeb71f36bfac40e445263b5e76e2"
+
+S = "${WORKDIR}/platform/hardware/libhardware"
+
+do_install(){
+ install -d ${D}${includedir}
+ install -m 0644 ${S}/include/hardware/hardware.h ${D}${includedir}
+ install -m 0644 ${S}/include/hardware/boot_control.h ${D}${includedir}
+}
diff --git a/meta/meta-mediatek/recipes-support/libnvram_custom/libnvramcustom_1.0.0.bb b/meta/meta-mediatek/recipes-support/libnvram_custom/libnvramcustom_1.0.0.bb
new file mode 100644
index 0000000..37cd529
--- /dev/null
+++ b/meta/meta-mediatek/recipes-support/libnvram_custom/libnvramcustom_1.0.0.bb
@@ -0,0 +1,75 @@
+#Basic Configuration
+DESCRIPTION = "Customization."
+SECTION = "base"
+LICENSE = "MediaTekProprietary"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=e1696b147d49d491bcb4da1a57173fff"
+DEPENDS = "custom"
+MTK_SRC = "${TOPDIR}/../src/support/libnvram_custom"
+NVRAM_PREFIX = "${STAGING_DIR}/${MACHINE}${includedir}/install"
+
+WORKONSRC = "${MTK_SRC}"
+BB_INCLUDE_ADD = "--sysroot=${STAGING_DIR_HOST} -I${TOPDIR}/../src/support/nvram/libnvram"
+BB_LDFLAGS_ADD = "--sysroot=${STAGING_DIR_HOST}"
+
+inherit deploy workonsrc
+PRJ_FILENAME = "${MTK_PROJECT}"
+#Parameters passed to do_compile()
+EXTRA_OEMAKE = "'CROSS=${TARGET_PREFIX}'\
+ 'PREFIX=${NVRAM_PREFIX}'\
+ 'PACKAGE_ARCH=${PACKAGE_ARCH}'\
+ 'BB_INCLUDE_ADD=${BB_INCLUDE_ADD}'\
+ 'BB_LDFLAGS_ADD=${BB_LDFLAGS_ADD}'\
+ 'PRJ_FILENAME=${PRJ_FILENAME}'\
+ 'NVRAM_COMBO_CHIP_ID=${COMBO_CHIP_ID}'"
+
+FILES_${PN} = "${base_libdir}/*.so\
+ ${base_bindir}\
+ ${base_sbindir}\
+ /mnt\
+ /tmp\
+ /etc\
+ /test"
+
+FILES_${PN}-dev = "${includedir}"
+
+FILES_${PN}-staticdev = "${base_libdir}/*.a"
+
+FILES_${PN}-doc = "/doc"
+
+FILES_${PN}-dbg = "/usr/src/debug \
+ ${base_bindir}/.debug \
+ ${base_libdir}/.debug \
+ ${base_sbindir}/.debug"
+
+
+#Skip strip check in QA test.
+INSANE_SKIP_${PN} += "already-stripped"
+
+
+do_compile () {
+ unset LDFLAGS
+ oe_runmake all ROOT=${STAGING_DIR_HOST}${exec_prefix} BOOTDEV_TYPE=${BOOTDEV_TYPE}
+}
+
+do_install () {
+ oe_runmake install ROOT=${D}
+
+ if [ -d "${S}/CFG/${PRJ_FILENAME}/cgen/" ]; then
+ install -d ${D}${includedir}
+ cp -af ${S}/CFG/${PRJ_FILENAME}/cgen/* ${D}${includedir}
+ else
+ if [ -d "${D}/include" ]; then
+ install -d ${D}${includedir}
+ cp -af ${D}/include/* ${D}${includedir}
+ rm -rf ${D}/include
+ fi
+ fi
+}
+
+addtask nvramclean
+do_nvramclean () {
+ oe_runmake clean
+}
+
+INSANE_SKIP_${PN} += "ldflags"
+INSANE_SKIP_${PN} += "installed-vs-shipped"
diff --git a/meta/meta-mediatek/recipes-support/nvram/files/nvram_daemon-service b/meta/meta-mediatek/recipes-support/nvram/files/nvram_daemon-service
new file mode 100644
index 0000000..4fdcab7
--- /dev/null
+++ b/meta/meta-mediatek/recipes-support/nvram/files/nvram_daemon-service
@@ -0,0 +1,64 @@
+#!/bin/sh
+### BEGIN INIT INFO
+# Provides: nvram_daemon
+# Required-Start: $syslog $local_fs
+# Required-Stop: $syslog $local_fs
+# Default-Start: 2 3 4 5
+# Default-Stop: 0 1 6
+# Short-Description: nvram_daemon
+### END INIT INFO
+
+. /etc/init.d/init-functions
+prog=nvram_daemon
+PIDFILE=/var/run/$prog.pid
+DESC="nvram_daemon"
+start() {
+ log_daemon_msg "Starting $DESC" "$prog"
+ start_daemon_background -p $PIDFILE /sbin/nvram_daemon
+ if [ $? -ne 0 ]; then
+ log_end_msg 1
+ exit 1
+ fi
+ if [ $? -eq 0 ]; then
+ log_end_msg 0
+ fi
+ exit 0
+}
+
+stop() {
+ log_daemon_msg "Stopping $DESC" "$prog"
+ killproc -p $PIDFILE /sbin/nvram_daemon
+ if [ $? -ne 0 ]; then
+ log_end_msg 1
+ exit 1
+ fi
+ if [ $? -eq 0 ]; then
+ log_end_msg 0
+ fi
+}
+
+force_reload() {
+ stop
+ start
+
+}
+
+case "$1" in
+ start)
+ start
+ ;;
+ stop)
+ stop
+ ;;
+ force-reload)
+ force_reload
+ ;;
+ restart)
+ stop
+ start
+ ;;
+
+ *)
+ echo "$Usage: $prog {start|stop|force-reload|restart}"
+ exit 2
+esac
diff --git a/meta/meta-mediatek/recipes-support/nvram/files/nvram_daemon.service b/meta/meta-mediatek/recipes-support/nvram/files/nvram_daemon.service
new file mode 100644
index 0000000..19cfada
--- /dev/null
+++ b/meta/meta-mediatek/recipes-support/nvram/files/nvram_daemon.service
@@ -0,0 +1,10 @@
+[Unit]
+Description=nvram_daemon
+
+[Service]
+ExecStart=/sbin/nvram_daemon
+Type=simple
+
+[Install]
+Alias=nvramdaemon
+WantedBy=multi-user.target
diff --git a/meta/meta-mediatek/recipes-support/nvram/nvram_1.0.0.bb b/meta/meta-mediatek/recipes-support/nvram/nvram_1.0.0.bb
new file mode 100644
index 0000000..5520ebf
--- /dev/null
+++ b/meta/meta-mediatek/recipes-support/nvram/nvram_1.0.0.bb
@@ -0,0 +1,94 @@
+#Basic Configuration
+DESCRIPTION = "NVRAM."
+SECTION = "base"
+LICENSE = "MediaTekProprietary"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=e1696b147d49d491bcb4da1a57173fff"
+DEPENDS = "libnvramcustom"
+MTK_SRC = "${TOPDIR}/../src/support/nvram"
+NVRAM_PREFIX = "${STAGING_DIR}/${MACHINE}${includedir}/install"
+SRC_URI += "file://nvram_daemon.service"
+
+WORKONSRC = "${MTK_SRC}"
+BB_INCLUDE_ADD = "--sysroot=${STAGING_DIR_HOST}"
+BB_LDFLAGS_ADD = "--sysroot=${STAGING_DIR_HOST}"
+
+inherit deploy workonsrc systemd
+PRJ_FILENAME = "${MTK_PROJECT}"
+#Parameters passed to do_compile()
+EXTRA_OEMAKE = "'CROSS=${TARGET_PREFIX}'\
+ 'PREFIX=${NVRAM_PREFIX}'\
+ 'PACKAGE_ARCH=${PACKAGE_ARCH}'\
+ 'BB_INCLUDE_ADD=${BB_INCLUDE_ADD}'\
+ 'BB_LDFLAGS_ADD=${BB_LDFLAGS_ADD}'\
+ 'PRJ_FILENAME=${PRJ_FILENAME}'"
+
+FILES_${PN} = "${base_libdir}/*.so\
+ ${base_bindir}\
+ ${base_sbindir}\
+ /mnt\
+ /tmp\
+ /etc\
+ /usr/out\
+ /test"
+
+FILES_${PN}-dev = "${includedir} \
+ /out"
+
+FILES_${PN}-staticdev = "${base_libdir}/*.a"
+
+FILES_${PN}-doc = "/doc"
+
+FILES_${PN}-dbg = "/usr/src/debug \
+ ${base_sbindir}/.debug \
+ ${base_libdir}/.debug"
+
+#Skip strip check in QA test.
+INSANE_SKIP_${PN} += "already-stripped"
+
+SYSTEMD_PACKAGES = "${PN}"
+SYSTEMD_SERVICE_${PN} = "nvram_daemon.service"
+FILES_${PN} += "${systemd_unitdir}/system/nvram_daemon.service"
+
+do_compile () {
+ unset LDFLAGS
+ oe_runmake all ROOT=${STAGING_DIR_HOST}${exec_prefix} VA_SUPPORT_GVA_SDK=${VA_SUPPORT_GVA_SDK} AUDIO_SUPPORT_C4A_SDK=${AUDIO_SUPPORT_C4A_SDK} VA_SUPPORT_ALEXA_SDK=${VA_SUPPORT_ALEXA} VA_SUPPORT_ALEXA_SDK_FFS=${VA_SUPPORT_ALEXA_FFS}
+}
+
+do_install () {
+ oe_runmake install ROOT=${D}
+
+ if [ -d "${D}/include" ]; then
+ install -d ${D}${includedir}
+ cp -af ${D}/include/* ${D}${includedir}
+ rm -rf ${D}/include
+ fi
+}
+
+do_install_append() {
+ if ${@bb.utils.contains('DISTRO_FEATURES','systemd','true','false',d)}; then
+ install -d ${D}${systemd_unitdir}/system
+ install -m 644 ${WORKDIR}/nvram_daemon.service ${D}${systemd_unitdir}/system
+ fi
+}
+
+addtask nvramclean
+do_nvramclean () {
+ oe_runmake clean
+}
+
+INSANE_SKIP_${PN} += "ldflags"
+
+
+# Install Sysvinit Scripts #
+DEPENDS_append = " update-rc.d-native"
+INITSCRIPT_NAME_nvram_daemon-service = "nvram_daemon-service"
+INITSCRIPT_PARAMS_nvram_daemon-service = "start 11 3 ."
+FILES_${PN} += "${sysconfdir}/init.d/nvram_daemon-service"
+
+do_install_append() {
+ if ${@bb.utils.contains('DISTRO_FEATURES','sysvinit','true','false',d)}; then
+ install -d ${D}${sysconfdir}/init.d
+ install -m 0755 ${TOPDIR}/../meta/meta-mediatek/recipes-support/nvram/files/nvram_daemon-service ${D}${sysconfdir}/init.d/nvram_daemon-service
+ update-rc.d -r ${D} ${INITSCRIPT_NAME_nvram_daemon-service} ${INITSCRIPT_PARAMS_nvram_daemon-service}
+ fi
+}
diff --git a/meta/meta-mediatek/recipes-support/nvram/rw-nvram.bb b/meta/meta-mediatek/recipes-support/nvram/rw-nvram.bb
new file mode 100644
index 0000000..c345ec3
--- /dev/null
+++ b/meta/meta-mediatek/recipes-support/nvram/rw-nvram.bb
@@ -0,0 +1,22 @@
+DESCRIPTION = "rw_nvram"
+LICENSE = "MPLV2"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=e1696b147d49d491bcb4da1a57173ff"
+DEPENDS = "libnvramcustom nvram"
+WORKING_SRC = "${TOPDIR}/../src/support/nvram/tests"
+
+inherit workonsrc
+
+WORKONSRC = "${WORKING_SRC}"
+
+do_compile() {
+ oe_runmake
+}
+
+do_install() {
+ install -d ${D}/${bindir}
+ install -m 755 ${S}/rw_nvram ${D}/${bindir}
+}
+
+FILES_${PN} += "${bindir}"
+FILES_${PN}-dev = ""
+INSANE_SKIP_${PN} += "already-stripped"
diff --git a/meta/meta-mediatek/recipes-support/pdct/pdct.bb b/meta/meta-mediatek/recipes-support/pdct/pdct.bb
new file mode 100644
index 0000000..96f3cfb
--- /dev/null
+++ b/meta/meta-mediatek/recipes-support/pdct/pdct.bb
@@ -0,0 +1,41 @@
+DESCRIPTION = "MTK PDCT"
+LICENSE = "MediaTekProprietary"
+
+inherit get_toolchain_name
+inherit workonsrc
+WORKONSRC = "${TOPDIR}/../src/support/pdct/asf/"
+
+DEPENDS += "${@bb.utils.contains('TEE_SUPPORT', 'mtee', 'tzapp', '' ,d)}"
+RDEPENDS_${PN} += "${@bb.utils.contains('TEE_SUPPORT', 'mtee', 'tzapp', '' ,d)}"
+DEPENDS += "${@bb.utils.contains('TEE_SUPPORT', 'optee', 'optee-services', '' ,d)}"
+RDEPENDS_${PN} += "${@bb.utils.contains('TEE_SUPPORT', 'optee', 'optee-services', '' ,d)}"
+
+BASE_TARGET_PLATFORM ?= "${TARGET_PLATFORM}"
+
+do_compile() {
+ if test -e ${WORKONSRC} ; then
+ if test "${TEE_SUPPORT}" = "optee" ;then
+ oe_runmake LDFLAGS='${LDFLAGS} -shared -ltz_efuse' CONFIG_MTK_PLATFORM="${BASE_TARGET_PLATFORM}"
+ else
+ oe_runmake LDFLAGS='${LDFLAGS} -shared -ltz_efuse -ltz_uree' CONFIG_MTK_PLATFORM="${BASE_TARGET_PLATFORM}"
+ fi
+ fi
+}
+
+do_install() {
+ if ! test -e ${WORKONSRC} ; then
+ if test "${DEFAULTTUNE}" = "aarch64" ; then
+ make install -C "${TOPDIR}/../prebuilt/support/pdct/${BASE_TARGET_PLATFORM}" DESTDIR="${D}" TOOL_CHAIN=${TOOLCHAIN_NAME} AARCH="arm64"
+ else
+ make install -C "${TOPDIR}/../prebuilt/support/pdct/${BASE_TARGET_PLATFORM}" DESTDIR="${D}" TOOL_CHAIN=${TOOLCHAIN_NAME} AARCH="arm"
+ fi
+ else
+ install -d ${D}${libdir}
+ install -m 644 libpdct.so ${D}${libdir}
+ fi
+}
+
+FILES_${PN}-dev = ""
+FILES_${PN} += "${libdir}/libpdct.so"
+INSANE_SKIP_${PN} = "already-stripped ldflags"
+INHIBIT_PACKAGE_STRIP = "1"
diff --git a/meta/meta-mediatek/recipes-support/platform-libs-common/files/base.patch b/meta/meta-mediatek/recipes-support/platform-libs-common/files/base.patch
new file mode 100644
index 0000000..4f70bf5
--- /dev/null
+++ b/meta/meta-mediatek/recipes-support/platform-libs-common/files/base.patch
@@ -0,0 +1,42 @@
+diff --git a/system/core/base/errors_unix.cpp b/system/core/base/errors_unix.cpp
+old mode 100644
+new mode 100755
+index 296995e..48269b6
+--- a/system/core/base/errors_unix.cpp
++++ b/system/core/base/errors_unix.cpp
+@@ -17,6 +17,7 @@
+ #include "android-base/errors.h"
+
+ #include <errno.h>
++#include <string.h>
+
+ namespace android {
+ namespace base {
+diff --git a/system/core/base/file.cpp b/system/core/base/file.cpp
+old mode 100644
+new mode 100755
+index da1adba..91a3901
+--- a/system/core/base/file.cpp
++++ b/system/core/base/file.cpp
+@@ -20,6 +20,7 @@
+ #include <fcntl.h>
+ #include <sys/stat.h>
+ #include <sys/types.h>
++#include <string.h>
+
+ #include <string>
+
+diff --git a/system/core/base/logging.cpp b/system/core/base/logging.cpp
+old mode 100644
+new mode 100755
+index 1741871..e5a98e3
+--- a/system/core/base/logging.cpp
++++ b/system/core/base/logging.cpp
+@@ -18,6 +18,7 @@
+ #include <windows.h>
+ #endif
+
++#include <string.h>
+ #include "android-base/logging.h"
+
+ #include <libgen.h>
diff --git a/meta/meta-mediatek/recipes-support/platform-libs-common/files/include.patch b/meta/meta-mediatek/recipes-support/platform-libs-common/files/include.patch
new file mode 100644
index 0000000..b13bff7
--- /dev/null
+++ b/meta/meta-mediatek/recipes-support/platform-libs-common/files/include.patch
@@ -0,0 +1,218 @@
+diff --git a/system/core/include/cutils/atomic.h b/system/core/include/cutils/atomic.h
+index ded972a..fb83e77 100644
+--- a/system/core/include/cutils/atomic.h
++++ b/system/core/include/cutils/atomic.h
+@@ -19,7 +19,12 @@
+
+ #include <stdint.h>
+ #include <sys/types.h>
++#ifdef __cplusplus
++#include <atomic>
++using namespace std;
++#else
+ #include <stdatomic.h>
++#endif
+
+ #ifndef ANDROID_ATOMIC_INLINE
+ #define ANDROID_ATOMIC_INLINE static inline
+diff --git a/system/core/include/cutils/properties.h b/system/core/include/cutils/properties.h
+index 24aa224..2957e2c 100644
+--- a/system/core/include/cutils/properties.h
++++ b/system/core/include/cutils/properties.h
+@@ -33,8 +33,8 @@ extern "C" {
+ ** WARNING: system/bionic/include/sys/system_properties.h also defines
+ ** these, but with different names. (TODO: fix that)
+ */
+-#define PROPERTY_KEY_MAX PROP_NAME_MAX
+-#define PROPERTY_VALUE_MAX PROP_VALUE_MAX
++#define PROPERTY_KEY_MAX 64
++#define PROPERTY_VALUE_MAX 96
+
+ /* property_get: returns the length of the value which will never be
+ ** greater than PROPERTY_VALUE_MAX - 1 and will always be zero terminated.
+diff --git a/system/core/include/private/android_filesystem_config.h b/system/core/include/private/android_filesystem_config.h
+index e540de2..dac5eb5 100644
+--- a/system/core/include/private/android_filesystem_config.h
++++ b/system/core/include/private/android_filesystem_config.h
+@@ -40,7 +40,7 @@
+
+ #define AID_ROOT 0 /* traditional unix root user */
+
+-#define AID_SYSTEM 1000 /* system server */
++#define AID_SYSTEM 0 /* system server */
+
+ #define AID_RADIO 1001 /* telephony subsystem, RIL */
+ #define AID_BLUETOOTH 1002 /* bluetooth subsystem */
+diff --git a/system/core/include/sysutils/FrameworkListener.h b/system/core/include/sysutils/FrameworkListener.h
+index 18049cd..2137069 100644
+--- a/system/core/include/sysutils/FrameworkListener.h
++++ b/system/core/include/sysutils/FrameworkListener.h
+@@ -32,6 +32,7 @@ private:
+ int mCommandCount;
+ bool mWithSeq;
+ FrameworkCommandCollection *mCommands;
++ bool mSkipToNextNullByte;
+
+ public:
+ FrameworkListener(const char *socketName);
+diff --git a/system/core/include/sysutils/NetlinkEvent.h b/system/core/include/sysutils/NetlinkEvent.h
+index b80f3ea..fd9cab4 100644
+--- a/system/core/include/sysutils/NetlinkEvent.h
++++ b/system/core/include/sysutils/NetlinkEvent.h
+@@ -34,6 +34,9 @@ public:
+ kRdnss = 8,
+ kRouteUpdated = 9,
+ kRouteRemoved = 10,
++ kIPv6Enable = 100,
++ kIPv6Disable = 101,
++ kNoRA = 108,
+ };
+
+ private:
+@@ -64,6 +67,8 @@ public:
+ bool parseNfPacketMessage(struct nlmsghdr *nh);
+ bool parseRtMessage(const struct nlmsghdr *nh);
+ bool parseNdUserOptMessage(const struct nlmsghdr *nh);
++ bool parseNewPrefixMessage(const struct nlmsghdr *nh);
++ bool parseNoRAMessage(const struct nlmsghdr *nh);
+ };
+
+ #endif
+diff --git a/system/core/include/utils/CallStack.h b/system/core/include/utils/CallStack.h
+index 27e89f4..ee986b7 100644
+--- a/system/core/include/utils/CallStack.h
++++ b/system/core/include/utils/CallStack.h
+@@ -18,7 +18,12 @@
+ #define ANDROID_CALLSTACK_H
+
+ #include <android/log.h>
++#ifdef __ANDROID__
+ #include <backtrace/backtrace_constants.h>
++#else
++#define BACKTRACE_CURRENT_THREAD -1
++#endif
++
+ #include <utils/String8.h>
+ #include <utils/Vector.h>
+
+diff --git a/system/core/include/utils/Printer.h b/system/core/include/utils/Printer.h
+index bb66287..5371afb 100644
+--- a/system/core/include/utils/Printer.h
++++ b/system/core/include/utils/Printer.h
+@@ -17,7 +17,11 @@
+ #ifndef ANDROID_PRINTER_H
+ #define ANDROID_PRINTER_H
+
++#if defined(__ANDROID__)
+ #include <android/log.h>
++#else
++#include <cutils/log.h>
++#endif
+
+ namespace android {
+
+diff --git a/system/core/include/utils/ThreadDefs.h b/system/core/include/utils/ThreadDefs.h
+index ae091e4..7f73c4e 100644
+--- a/system/core/include/utils/ThreadDefs.h
++++ b/system/core/include/utils/ThreadDefs.h
+@@ -19,8 +19,66 @@
+
+ #include <stdint.h>
+ #include <sys/types.h>
++#if defined(__ANDROID__)
+ #include <system/graphics.h>
+ #include <system/thread_defs.h>
++#else
++
++#if defined(__cplusplus)
++extern "C" {
++#endif
++
++enum {
++ /*
++ * ***********************************************
++ * ** Keep in sync with android.os.Process.java **
++ * ***********************************************
++ *
++ * This maps directly to the "nice" priorities we use in Android.
++ * A thread priority should be chosen inverse-proportionally to
++ * the amount of work the thread is expected to do. The more work
++ * a thread will do, the less favorable priority it should get so that
++ * it doesn't starve the system. Threads not behaving properly might
++ * be "punished" by the kernel.
++ * Use the levels below when appropriate. Intermediate values are
++ * acceptable, preferably use the {MORE|LESS}_FAVORABLE constants below.
++ */
++ ANDROID_PRIORITY_LOWEST = 19,
++
++ /* use for background tasks */
++ ANDROID_PRIORITY_BACKGROUND = 10,
++
++ /* most threads run at normal priority */
++ ANDROID_PRIORITY_NORMAL = 0,
++
++ /* threads currently running a UI that the user is interacting with */
++ ANDROID_PRIORITY_FOREGROUND = -2,
++
++ /* the main UI thread has a slightly more favorable priority */
++ ANDROID_PRIORITY_DISPLAY = -4,
++
++ /* ui service treads might want to run at a urgent display (uncommon) */
++ ANDROID_PRIORITY_URGENT_DISPLAY = -8,
++
++ /* all normal audio threads */
++ ANDROID_PRIORITY_AUDIO = -16,
++
++ /* service audio threads (uncommon) */
++ ANDROID_PRIORITY_URGENT_AUDIO = -18,
++
++ /* should never be used in practice. regular process might not
++ * be allowed to use this level */
++ ANDROID_PRIORITY_HIGHEST = -20,
++
++ ANDROID_PRIORITY_DEFAULT = ANDROID_PRIORITY_NORMAL,
++ ANDROID_PRIORITY_MORE_FAVORABLE = -1,
++ ANDROID_PRIORITY_LESS_FAVORABLE = +1,
++};
++
++#if defined(__cplusplus)
++}
++#endif
++#endif
+
+ // ---------------------------------------------------------------------------
+ // C API
+diff --git a/system/core/include/utils/Vector.h b/system/core/include/utils/Vector.h
+index ed7b725..239b33f 100644
+--- a/system/core/include/utils/Vector.h
++++ b/system/core/include/utils/Vector.h
+@@ -242,13 +242,13 @@ Vector<TYPE>::~Vector() {
+
+ template<class TYPE> inline
+ Vector<TYPE>& Vector<TYPE>::operator = (const Vector<TYPE>& rhs) {
+- VectorImpl::operator = (rhs);
++ VectorImpl::operator = (static_cast<const VectorImpl&>(rhs));
+ return *this;
+ }
+
+ template<class TYPE> inline
+ const Vector<TYPE>& Vector<TYPE>::operator = (const Vector<TYPE>& rhs) const {
+- VectorImpl::operator = (static_cast<const VectorImpl&>(rhs));
++ VectorImpl::operator = (rhs);
+ return *this;
+ }
+
+diff --git a/system/core/base/include/android-base/strings.h b/system/core/base/include/android-base/strings.h
+index 69781cd..82f7897 100644
+--- a/system/core/base/include/android-base/strings.h
++++ b/system/core/base/include/android-base/strings.h
+@@ -62,6 +62,9 @@ bool StartsWith(const std::string& s, const char* prefix);
+ // Tests whether 's' ends with 'suffix'.
+ bool EndsWith(const std::string& s, const char* suffix);
+
++// Tests whether 'lhs' equals 'rhs', ignoring case.
++bool EqualsIgnoreCase(const std::string& lhs, const std::string& rhs);
++
+ } // namespace base
+ } // namespace android
+
\ No newline at end of file
diff --git a/meta/meta-mediatek/recipes-support/platform-libs-common/files/liblog.patch b/meta/meta-mediatek/recipes-support/platform-libs-common/files/liblog.patch
new file mode 100644
index 0000000..bac8222
--- /dev/null
+++ b/meta/meta-mediatek/recipes-support/platform-libs-common/files/liblog.patch
@@ -0,0 +1,252 @@
+diff --git a/system/core/liblog/logger_write.c b/system/core/liblog/logger_write.c
+index b802ed7..3061862 100644
+--- a/system/core/liblog/logger_write.c
++++ b/system/core/liblog/logger_write.c
+@@ -31,6 +31,14 @@
+ #include <private/android_filesystem_config.h>
+ #include <private/android_logger.h>
+
++#define __REDIRECT_TO_SYSLOGD__
++
++#if defined(__REDIRECT_TO_SYSLOGD__)
++#include <syslog.h>
++#include <sys/syscall.h>
++#include <unistd.h>
++#endif
++
+ #include "config_write.h"
+ #include "log_portability.h"
+ #include "logger.h"
+@@ -186,8 +194,187 @@ static inline uint32_t get4LE(const uint8_t* src)
+ return src[0] | (src[1] << 8) | (src[2] << 16) | (src[3] << 24);
+ }
+
++#if defined(__REDIRECT_TO_SYSLOGD__)
++static int filterPriAndSysPri (android_LogPriority pri, int *sys_pri)
++{
++ switch (pri) {
++ case ANDROID_LOG_DEBUG:
++ *sys_pri = LOG_DEBUG;
++ return 3;
++ case ANDROID_LOG_INFO:
++ *sys_pri = LOG_INFO;
++ return 4;
++ case ANDROID_LOG_WARN:
++ *sys_pri = LOG_WARNING;
++ return 5;
++ case ANDROID_LOG_ERROR:
++ *sys_pri = LOG_ERR;
++ return 6;
++ case ANDROID_LOG_FATAL:
++ *sys_pri = LOG_CRIT;
++ return 7;
++ case ANDROID_LOG_SILENT:
++ *sys_pri = LOG_EMERG;
++ return 8;
++
++ case ANDROID_LOG_DEFAULT:
++ case ANDROID_LOG_UNKNOWN:
++ default:
++ *sys_pri = LOG_INFO;
++ return 1;
++ }
++}
++
++static char *filterLogId(log_id_t log_id)
++{
++ switch (log_id) {
++ case LOG_ID_MAIN:
++ return "MAIN";
++ case LOG_ID_RADIO :
++ return "RADIO";
++ case LOG_ID_EVENTS:
++ return "EVENT";
++ case LOG_ID_SYSTEM:
++ return "SYSTEM";
++ default:
++ return "UNKOWN";
++ }
++}
++
++/*
++ * Extract an 8-byte value from a byte stream.
++ */
++static inline uint64_t get8LE(const uint8_t* src)
++{
++ uint32_t low, high;
++
++ low = src[0] | (src[1] << 8) | (src[2] << 16) | (src[3] << 24);
++ high = src[4] | (src[5] << 8) | (src[6] << 16) | (src[7] << 24);
++ return ((long long) high << 32) | (long long) low;
++}
++
++static char filterEvtType(char type, char *buf, void *payload, ssize_t len)
++{
++ switch(type) {
++ case EVENT_TYPE_INT:
++ sprintf(buf, "%d", get4LE(payload));
++ return 'I';
++ case EVENT_TYPE_LONG:
++ sprintf(buf, "%lld", get8LE(payload));
++ return 'L';
++ case EVENT_TYPE_STRING:
++ snprintf(buf, len, "%s", payload);
++ buf[len] = '\0';
++ return 'S';
++ default: /* not support */
++ sprintf(buf, "?");
++ return '?';
++ }
++}
++#endif
++
++
+ static int __write_to_log_daemon(log_id_t log_id, struct iovec *vec, size_t nr)
+ {
++#if defined(__REDIRECT_TO_SYSLOGD__)
++ int ret;
++ size_t totalLen = 0, defaultLen = 512, prefixLen;
++ int write_allocate = 0;
++ int sys_pri = LOG_INFO;
++ char *writeBuf = NULL;
++ char defaultBuf[512];
++ char prefixBuf[128];
++ char *idChar;
++ int priChar;
++
++ // for main, system, radio
++ ssize_t msg_len = 0;
++ int priority = ANDROID_LOG_INFO;
++ char *tag, *msg;
++
++ // for event
++ int32_t etag;
++ char type;
++ void *payload;
++
++ // ------------------------------------------------------------------
++ // get log id
++ idChar = filterLogId(log_id);
++
++#if 0 //disable event logid
++ if(log_id == LOG_ID_EVENTS) { /* event type */
++ if(nr == 2) { // __android_log_bwrite
++ etag = *((int32_t *)vec[0].iov_base);
++ type = EVENT_TYPE_INT;
++ payload = (void *)vec[1].iov_base;
++ msg_len = vec[1].iov_len;
++ } else { // __android_log_btwrite
++ etag = *((int32_t *)vec[0].iov_base);
++ type = *((char *)vec[1].iov_base);
++
++ if(!strcmp(&type, ""))
++ type = EVENT_TYPE_STRING;
++
++ payload = (void *)vec[2].iov_base;
++ msg_len = vec[2].iov_len;
++ }
++
++ // get type char
++ priChar = filterEvtType(type, prefixBuf, payload, msg_len);
++
++ // format prefix (brief format)
++ snprintf(defaultBuf, sizeof(defaultBuf),
++ "<%c>/%c/%d(%5d): %s\n",
++ idChar, priChar, etag, getpid(), prefixBuf);
++ // log to syslog
++ syslog(sys_pri, "%s", defaultBuf);
++ ret = strlen(defaultBuf);
++ }
++ else
++#endif
++ { /* radio, system, main */
++ // get messages and tag from io vector
++ msg_len = vec[2].iov_len;
++ priority = *((int *)vec[0].iov_base);
++ tag = (char *)vec[1].iov_base;
++ msg = (char *)vec[2].iov_base;
++
++ /* disable Android VERBOSE log */
++ if (priority == ANDROID_LOG_VERBOSE) {
++ return -EINVAL;
++ }
++
++ // get priority and logid char
++ priChar = filterPriAndSysPri(priority, &sys_pri);
++
++ // format prefix (brief format)
++ prefixLen = snprintf(prefixBuf, sizeof(prefixBuf),
++ "(%5d, %5d),[%s],[%d],[Tag]%s[TAG]: ", getpid(), syscall(SYS_gettid), idChar, priChar, tag);
++
++ // compute size
++ totalLen = prefixLen + msg_len + 1 + 1;
++ if(totalLen <= defaultLen) {
++ writeBuf = defaultBuf;
++ } else {
++ write_allocate = 1;
++ writeBuf = (char *)malloc(totalLen);
++ if(writeBuf == NULL)
++ return 0;
++ }
++
++ // combine final string
++ writeBuf[0] = '\0';
++ strncat(writeBuf, prefixBuf, prefixLen);
++ strncat(writeBuf, msg, msg_len);
++ strcat(writeBuf, "\n");
++
++ // log to syslog
++ syslog(sys_pri, "%s", writeBuf);
++ ret = strlen(writeBuf);
++
++ if(write_allocate) free(writeBuf);
++ }
++#else
+ struct android_log_transport_write *node;
+ int ret;
+ struct timespec ts;
+@@ -316,6 +503,7 @@ static int __write_to_log_daemon(log_id_t log_id, struct iovec *vec, size_t nr)
+ (void)(*node->write)(log_id, &ts, vec, nr);
+ }
+ }
++#endif
+
+ return ret;
+ }
+@@ -327,6 +515,27 @@ static int __write_to_log_init(log_id_t log_id, struct iovec *vec, size_t nr)
+ if (write_to_log == __write_to_log_init) {
+ int ret;
+
++#if defined(__REDIRECT_TO_SYSLOGD__)
++ // open syslogd
++ if (access("/etc/configs/syslog_split", F_OK) == 0) {
++ switch (log_id) {
++ case LOG_ID_MAIN:
++ openlog("ALOG", 0, LOG_LOCAL0);
++ break;
++ case LOG_ID_SYSTEM:
++ openlog("SLOG", 0, LOG_LOCAL1);
++ break;
++ case LOG_ID_RADIO:
++ openlog("RLOG", 0, LOG_LOCAL2);
++ break;
++ default:
++ openlog("ALOG", 0, LOG_LOCAL0);
++ break;
++ }
++ } else {
++ openlog("ALOG", 0, LOG_USER);
++ }
++#else
+ ret = __write_to_log_initialize();
+ if (ret < 0) {
+ __android_log_unlock();
+@@ -335,7 +544,7 @@ static int __write_to_log_init(log_id_t log_id, struct iovec *vec, size_t nr)
+ }
+ return ret;
+ }
+-
++#endif
+ write_to_log = __write_to_log_daemon;
+ }
+
diff --git a/meta/meta-mediatek/recipes-support/platform-libs-common/files/makefiles/platform/Makefile.am b/meta/meta-mediatek/recipes-support/platform-libs-common/files/makefiles/platform/Makefile.am
new file mode 100644
index 0000000..26eb2d2
--- /dev/null
+++ b/meta/meta-mediatek/recipes-support/platform-libs-common/files/makefiles/platform/Makefile.am
@@ -0,0 +1,5 @@
+SUBDIRS = \
+ system/core/base/include \
+ system/core/include \
+ system/core/liblog \
+ system/core/base
diff --git a/meta/meta-mediatek/recipes-support/platform-libs-common/files/makefiles/platform/configure.ac b/meta/meta-mediatek/recipes-support/platform-libs-common/files/makefiles/platform/configure.ac
new file mode 100644
index 0000000..1b9a96d
--- /dev/null
+++ b/meta/meta-mediatek/recipes-support/platform-libs-common/files/makefiles/platform/configure.ac
@@ -0,0 +1,13 @@
+AC_INIT([platform-libs-updateengine], [1.0])
+AM_INIT_AUTOMAKE([foreign subdir-objects])
+AC_PROG_CXX
+AM_PROG_AS
+LT_INIT
+AC_CONFIG_FILES([
+ Makefile
+ system/core/base/include/Makefile
+ system/core/include/Makefile
+ system/core/liblog/Makefile
+ system/core/base/Makefile
+])
+AC_OUTPUT
diff --git a/meta/meta-mediatek/recipes-support/platform-libs-common/files/makefiles/platform/system/core/base/Makefile.am b/meta/meta-mediatek/recipes-support/platform-libs-common/files/makefiles/platform/system/core/base/Makefile.am
new file mode 100644
index 0000000..53de4aa
--- /dev/null
+++ b/meta/meta-mediatek/recipes-support/platform-libs-common/files/makefiles/platform/system/core/base/Makefile.am
@@ -0,0 +1,19 @@
+lib_LTLIBRARIES = libbase.la
+
+libbase_la_SOURCES = \
+ file.cpp \
+ logging.cpp \
+ parsenetaddress.cpp \
+ stringprintf.cpp \
+ strings.cpp \
+ test_utils.cpp \
+ errors_unix.cpp
+
+libbase_la_CPPFLAGS = -Werror -Wall -Wextra -std=c++14
+
+libbase_la_CPPFLAGS += \
+ -I$(top_srcdir)/system/core/base/include \
+ -I$(top_srcdir)/system/core/include
+
+libbase_la_LIBADD = \
+ $(top_builddir)/system/core/liblog/liblog.la
\ No newline at end of file
diff --git a/meta/meta-mediatek/recipes-support/platform-libs-common/files/makefiles/platform/system/core/base/include/Makefile.am b/meta/meta-mediatek/recipes-support/platform-libs-common/files/makefiles/platform/system/core/base/include/Makefile.am
new file mode 100644
index 0000000..6d83983
--- /dev/null
+++ b/meta/meta-mediatek/recipes-support/platform-libs-common/files/makefiles/platform/system/core/base/include/Makefile.am
@@ -0,0 +1,8 @@
+nobase_include_HEADERS = \
+ android-base/unique_fd.h \
+ android-base/file.h \
+ android-base/logging.h \
+ android-base/macros.h \
+ android-base/stringprintf.h \
+ android-base/strings.h \
+ android-base/parseint.h
diff --git a/meta/meta-mediatek/recipes-support/platform-libs-common/files/makefiles/platform/system/core/include/Makefile.am b/meta/meta-mediatek/recipes-support/platform-libs-common/files/makefiles/platform/system/core/include/Makefile.am
new file mode 100644
index 0000000..ec0f4eb
--- /dev/null
+++ b/meta/meta-mediatek/recipes-support/platform-libs-common/files/makefiles/platform/system/core/include/Makefile.am
@@ -0,0 +1,27 @@
+nobase_include_HEADERS = \
+ utils/Compat.h \
+ utils/Errors.h \
+ utils/KeyedVector.h \
+ utils/RefBase.h \
+ utils/SortedVector.h \
+ utils/String8.h \
+ utils/String16.h \
+ utils/SystemClock.h \
+ utils/Timers.h \
+ utils/TypeHelpers.h \
+ utils/Unicode.h \
+ utils/Vector.h \
+ utils/VectorImpl.h \
+ utils/threads.h \
+ utils/StrongPointer.h \
+ utils/CallStack.h \
+ utils/Printer.h \
+ utils/Looper.h \
+ utils/ThreadDefs.h \
+ utils/AndroidThreads.h \
+ utils/Condition.h \
+ utils/Mutex.h \
+ utils/Thread.h \
+ utils/RWLock.h \
+ utils/List.h
+
diff --git a/meta/meta-mediatek/recipes-support/platform-libs-common/files/makefiles/platform/system/core/liblog/Makefile.am b/meta/meta-mediatek/recipes-support/platform-libs-common/files/makefiles/platform/system/core/liblog/Makefile.am
new file mode 100644
index 0000000..1c3443c
--- /dev/null
+++ b/meta/meta-mediatek/recipes-support/platform-libs-common/files/makefiles/platform/system/core/liblog/Makefile.am
@@ -0,0 +1,20 @@
+lib_LTLIBRARIES = liblog.la
+
+liblog_la_SOURCES = \
+ config_write.c \
+ event_tag_map.c \
+ fake_log_device.c \
+ fake_writer.c \
+ log_event_list.c \
+ log_event_write.c \
+ logger_lock.c \
+ logger_name.c \
+ logger_write.c
+
+liblog_la_CFLAGS = -Werror -fvisibility=hidden
+
+liblog_la_CPPFLAGS = \
+ -DFAKE_LOG_DEVICE=1 \
+ -DLIBLOG_LOG_TAG=1005 \
+ -DSNET_EVENT_LOG_TAG=1397638484 \
+ -I$(top_srcdir)/system/core/include
diff --git a/meta/meta-mediatek/recipes-support/platform-libs-common/files/parseint.patch b/meta/meta-mediatek/recipes-support/platform-libs-common/files/parseint.patch
new file mode 100644
index 0000000..136fcc4
--- /dev/null
+++ b/meta/meta-mediatek/recipes-support/platform-libs-common/files/parseint.patch
@@ -0,0 +1,57 @@
+diff --git a/system/core/base/include/android-base/parseint.h b/system/core/base/include/android-base/parseint.h
+index ed75e2d..e3ebce6 100644
+--- a/system/core/base/include/android-base/parseint.h
++++ b/system/core/base/include/android-base/parseint.h
+@@ -21,6 +21,7 @@
+ #include <stdlib.h>
+
+ #include <limits>
++#include <string>
+
+ namespace android {
+ namespace base {
+@@ -31,7 +32,7 @@ namespace base {
+ template <typename T>
+ bool ParseUint(const char* s, T* out,
+ T max = std::numeric_limits<T>::max()) {
+- int base = (s[0] == '0' && s[1] == 'x') ? 16 : 10;
++ int base = (s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) ? 16 : 10;
+ errno = 0;
+ char* end;
+ unsigned long long int result = strtoull(s, &end, base);
+@@ -45,6 +46,12 @@ bool ParseUint(const char* s, T* out,
+ return true;
+ }
+
++// TODO: string_view
++template <typename T>
++bool ParseUint(const std::string& s, T* out,
++ T max = std::numeric_limits<T>::max()) {
++ return ParseUint(s.c_str(), out, max);
++}
+ // Parses the signed decimal integer in the string 's' and sets 'out' to
+ // that value. Optionally allows the caller to define a 'min' and 'max
+ // beyond which otherwise valid values will be rejected. Returns boolean
+@@ -53,7 +60,7 @@ template <typename T>
+ bool ParseInt(const char* s, T* out,
+ T min = std::numeric_limits<T>::min(),
+ T max = std::numeric_limits<T>::max()) {
+- int base = (s[0] == '0' && s[1] == 'x') ? 16 : 10;
++ int base = (s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) ? 16 : 10;
+ errno = 0;
+ char* end;
+ long long int result = strtoll(s, &end, base);
+@@ -67,6 +74,13 @@ bool ParseInt(const char* s, T* out,
+ return true;
+ }
+
++// TODO: string_view
++template <typename T>
++bool ParseInt(const std::string& s, T* out,
++ T min = std::numeric_limits<T>::min(),
++ T max = std::numeric_limits<T>::max()) {
++ return ParseInt(s.c_str(), out, min, max);
++}
+ } // namespace base
+ } // namespace android
+
diff --git a/meta/meta-mediatek/recipes-support/platform-libs-common/files/string.patch b/meta/meta-mediatek/recipes-support/platform-libs-common/files/string.patch
new file mode 100644
index 0000000..aeb0438
--- /dev/null
+++ b/meta/meta-mediatek/recipes-support/platform-libs-common/files/string.patch
@@ -0,0 +1,14 @@
+diff --git a/system/core/base/strings.cpp b/system/core/base/strings.cpp
+index b8775df..eceb844 100644
+--- a/system/core/base/strings.cpp
++++ b/system/core/base/strings.cpp
+@@ -100,5 +100,9 @@ bool EndsWith(const std::string& s, const char* suffix) {
+ return s.compare(offset, suffix_length, suffix) == 0;
+ }
+
++bool EqualsIgnoreCase(const std::string& lhs, const std::string& rhs) {
++ return strcasecmp(lhs.c_str(), rhs.c_str()) == 0;
++}
++
+ } // namespace base
+ } // namespace android
diff --git a/meta/meta-mediatek/recipes-support/platform-libs-common/platform-libs-common.bb b/meta/meta-mediatek/recipes-support/platform-libs-common/platform-libs-common.bb
new file mode 100644
index 0000000..aff39ac
--- /dev/null
+++ b/meta/meta-mediatek/recipes-support/platform-libs-common/platform-libs-common.bb
@@ -0,0 +1,44 @@
+inherit autotools
+DESCRIPTION = "Android platform libraries"
+LICENSE = "Apache-2.0"
+LIC_FILES_CHKSUM = " \
+ file://system/core/NOTICE;md5=c1a3ff0b97f199c7ebcfdd4d3fed238e \
+ "
+
+SRC_URI = " \
+ git://android.googlesource.com/platform/system/core;name=platform/system/core;destsuffix=platform/system/core/ \
+ file://base.patch \
+ file://parseint.patch \
+ file://include.patch \
+ file://liblog.patch \
+ file://string.patch \
+"
+
+SRCREV_platform/system/core = "c6160d2a0ef648ccb3d217c589c60b5c00b80387"
+
+FILESEXTRAPATHS_prepend := "${THISDIR}:"
+
+DEPENDS += "openssl glog "
+
+S = "${WORKDIR}/platform"
+
+LDFLAGS += "-lcrypto -lpthread -lglog"
+
+SECURITY_CFLAGS=""
+
+do_configure_prepend() {
+ install -m 0755 ${TOPDIR}/../meta/meta-mediatek/recipes-support/platform-libs-common/files/makefiles/platform/Makefile.am ${WORKDIR}/platform/Makefile.am
+ install -m 0755 ${TOPDIR}/../meta/meta-mediatek/recipes-support/platform-libs-common/files/makefiles/platform/configure.ac ${WORKDIR}/platform/configure.ac
+ install -m 0755 ${TOPDIR}/../meta/meta-mediatek/recipes-support/platform-libs-common/files/makefiles/platform/system/core/base/Makefile.am ${WORKDIR}/platform/system/core/base/Makefile.am
+ install -m 0755 ${TOPDIR}/../meta/meta-mediatek/recipes-support/platform-libs-common/files/makefiles/platform/system/core/base/include/Makefile.am ${WORKDIR}/platform/system/core/base/include/Makefile.am
+ install -m 0755 ${TOPDIR}/../meta/meta-mediatek/recipes-support/platform-libs-common/files/makefiles/platform/system/core/include/Makefile.am ${WORKDIR}/platform/system/core/include/Makefile.am
+ install -m 0755 ${TOPDIR}/../meta/meta-mediatek/recipes-support/platform-libs-common/files/makefiles/platform/system/core/liblog/Makefile.am ${WORKDIR}/platform/system/core/liblog/Makefile.am
+}
+
+do_install_append() {
+ install -d ${D}${includedir}
+ install -d ${D}${includedir}/log
+ install -d ${D}${includedir}/android
+ install -m 644 ${S}/system/core/include/log/* ${D}/${includedir}/log
+ install -m 644 ${S}/system/core/include/android/* ${D}/${includedir}/android
+}
diff --git a/meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/files/base.patch b/meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/files/base.patch
new file mode 100644
index 0000000..48540dc
--- /dev/null
+++ b/meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/files/base.patch
@@ -0,0 +1,36 @@
+diff --git a/system/core/base/errors_unix.cpp b/system/core/base/errors_unix.cpp
+index 296995e..48269b6 100644
+--- a/system/core/base/errors_unix.cpp
++++ b/system/core/base/errors_unix.cpp
+@@ -17,6 +17,7 @@
+ #include "android-base/errors.h"
+
+ #include <errno.h>
++#include <string.h>
+
+ namespace android {
+ namespace base {
+diff --git a/system/core/base/file.cpp b/system/core/base/file.cpp
+index 2f697a1..b86d1a2 100644
+--- a/system/core/base/file.cpp
++++ b/system/core/base/file.cpp
+@@ -27,6 +27,7 @@
+ #include <mutex>
+ #include <string>
+ #include <vector>
++#include <string.h>
+
+ #include "android-base/logging.h"
+ #include "android-base/macros.h" // For TEMP_FAILURE_RETRY on Darwin.
+diff --git a/system/core/base/logging.cpp b/system/core/base/logging.cpp
+index a31feef..7fd74dc 100644
+--- a/system/core/base/logging.cpp
++++ b/system/core/base/logging.cpp
+@@ -22,6 +22,7 @@
+
+ #include <fcntl.h>
+ #include <libgen.h>
++#include <string.h>
+ #include <time.h>
+
+ // For getprogname(3) or program_invocation_short_name.
diff --git a/meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/files/file_stream.patch b/meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/files/file_stream.patch
new file mode 100644
index 0000000..b5e417c
--- /dev/null
+++ b/meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/files/file_stream.patch
@@ -0,0 +1,117 @@
+diff --git a/external/libbrillo/brillo/streams/file_stream.cc b/brillo/streams/file_stream.cc
+index 7b28a5a..81dff4c 100644
+--- a/external/libbrillo/brillo/streams/file_stream.cc
++++ b/external/libbrillo/brillo/streams/file_stream.cc
+@@ -17,6 +17,16 @@
+ #include <brillo/streams/stream_errors.h>
+ #include <brillo/streams/stream_utils.h>
+
++#define BOOTDEV_TYPE_NAND 1
++#define BOOTDEV_TYPE_EMMC 2
++
++#if MTK_BOOTDEV_TYPE == BOOTDEV_TYPE_NAND
++ extern "C"{
++ #include "mtk_device_wrap.h"
++}
++static int is_partition = 0;
++#endif
++
+ namespace brillo {
+
+ // FileDescriptor is a helper class that serves two purposes:
+@@ -39,14 +49,50 @@ class FileDescriptor : public FileStream::FileDescriptorInterface {
+ bool IsOpen() const override { return fd_ >= 0; }
+
+ ssize_t Read(void* buf, size_t nbyte) override {
++ #if MTK_BOOTDEV_TYPE == BOOTDEV_TYPE_NAND
++ if(is_partition == 1)
++ {
++ //LOG(INFO) << "read partition device";
++ return HANDLE_EINTR(mtk_device_wrap_read(fd_, buf, nbyte));
++ }
++ else
++ {
++ //LOG(INFO) << "read ordinary file";
++ return HANDLE_EINTR(read(fd_, buf, nbyte));
++ }
++ #endif
+ return HANDLE_EINTR(read(fd_, buf, nbyte));
+ }
+
+ ssize_t Write(const void* buf, size_t nbyte) override {
++ #if MTK_BOOTDEV_TYPE == BOOTDEV_TYPE_NAND
++ if(is_partition == 1)
++ {
++ //LOG(INFO) << "write partition device";
++ return HANDLE_EINTR(mtk_device_wrap_write_force(fd_, (void*)buf, nbyte));
++ }
++ else
++ {
++ //LOG(INFO) << "write ordinary file";
++ return HANDLE_EINTR(write(fd_, (void*)buf, nbyte));
++ }
++ #endif
+ return HANDLE_EINTR(write(fd_, buf, nbyte));
+ }
+
+ off64_t Seek(off64_t offset, int whence) override {
++ #if MTK_BOOTDEV_TYPE == BOOTDEV_TYPE_NAND
++ if(is_partition == 1)
++ {
++ //LOG(INFO) << "seek partition device";
++ return mtk_device_wrap_seek64(fd_, offset, whence);
++ }
++ else
++ {
++ //LOG(INFO) << "seek ordinary file";
++ return lseek64(fd_, offset, whence);
++ }
++ #endif
+ return lseek64(fd_, offset, whence);
+ }
+
+@@ -76,6 +122,19 @@ class FileDescriptor : public FileStream::FileDescriptorInterface {
+ // it before exiting.
+ std::swap(fd, fd_);
+ CancelPendingAsyncOperations();
++ #if MTK_BOOTDEV_TYPE == BOOTDEV_TYPE_NAND
++ if(is_partition == 1)
++ {
++ LOG(INFO) << "close partition device";
++ is_partition = 0;
++ return own_ ? IGNORE_EINTR(mtk_device_wrap_close(fd)) : 0;
++ }
++ else
++ {
++ LOG(INFO) << "close ordinary file";
++ return own_ ? IGNORE_EINTR(close(fd)) : 0;
++ }
++ #endif
+ return own_ ? IGNORE_EINTR(close(fd)) : 0;
+ }
+
+@@ -239,7 +298,23 @@ StreamPtr FileStream::Open(const base::FilePath& path,
+ }
+
+ mode_t creation_mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
+- int fd = HANDLE_EINTR(open(path.value().c_str(), open_flags, creation_mode));
++ int fd = -1;
++#if MTK_BOOTDEV_TYPE == BOOTDEV_TYPE_NAND
++ /* because mtk_device_wrap_m_open() can not distinguish between ordinary files and devices files*/
++ if(!memcmp(path.value().c_str(), "/dev/disk/by-partlabel", 22))
++ {
++ LOG(INFO) << "open partition device: " << path.value().c_str();
++ is_partition = 1;
++ fd = HANDLE_EINTR(mtk_device_wrap_m_open(path.value().c_str(), open_flags, creation_mode));
++ }
++ else
++ {
++ LOG(INFO) << "open ordinary file: " << path.value().c_str();
++ fd = HANDLE_EINTR(open(path.value().c_str(), open_flags, creation_mode));
++ }
++#else
++ fd = HANDLE_EINTR(open(path.value().c_str(), open_flags, creation_mode));
++#endif
+ if (fd < 0) {
+ brillo::errors::system::AddSystemError(error, FROM_HERE, errno);
+ return stream;
diff --git a/meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/files/fstab.patch b/meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/files/fstab.patch
new file mode 100644
index 0000000..fc52654
--- /dev/null
+++ b/meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/files/fstab.patch
@@ -0,0 +1,98 @@
+diff --git a/system/core/fs_mgr/fs_mgr_boot_config.cpp b/system/core/fs_mgr/fs_mgr_boot_config.cpp
+index 9c5d3f3..b7e4b81 100644
+--- a/system/core/fs_mgr/fs_mgr_boot_config.cpp
++++ b/system/core/fs_mgr/fs_mgr_boot_config.cpp
+@@ -19,7 +19,7 @@
+ #include <android-base/file.h>
+ #include <android-base/stringprintf.h>
+ #include <android-base/strings.h>
+-#include <android-base/properties.h>
++//#include <android-base/properties.h>
+
+ #include "fs_mgr_priv.h"
+
+@@ -51,12 +51,13 @@ bool fs_mgr_get_boot_config_from_kernel_cmdline(const std::string& key, std::str
+ bool fs_mgr_get_boot_config(const std::string& key, std::string* out_val) {
+ FS_MGR_CHECK(out_val != nullptr);
+
++ #if 0
+ // first check if we have "ro.boot" property already
+ *out_val = android::base::GetProperty("ro.boot." + key, "");
+ if (!out_val->empty()) {
+ return true;
+ }
+-
++ #endif
+ // fallback to kernel cmdline, properties may not be ready yet
+ if (fs_mgr_get_boot_config_from_kernel_cmdline(key, out_val)) {
+ return true;
+diff --git a/system/core/fs_mgr/fs_mgr_fstab.cpp b/system/core/fs_mgr/fs_mgr_fstab.cpp
+index 9b7405a..27fed5e 100644
+--- a/system/core/fs_mgr/fs_mgr_fstab.cpp
++++ b/system/core/fs_mgr/fs_mgr_fstab.cpp
+@@ -115,6 +115,33 @@ static struct flag_list fs_mgr_flags[] = {
+ #define EM_AES_256_CTS 3
+ #define EM_AES_256_HEH 4
+
++size_t
++strlcat(char *dst, const char *src, size_t dsize)
++{
++ const char *odst = dst;
++ const char *osrc = src;
++ size_t n = dsize;
++ size_t dlen;
++
++ /* Find the end of dst and adjust bytes left but don't go past end. */
++ while (n-- != 0 && *dst != '\0')
++ dst++;
++ dlen = dst - odst;
++ n = dsize - dlen;
++
++ if (n-- == 0)
++ return(dlen + strlen(src));
++ while (*src != '\0') {
++ if (n != 0) {
++ *dst++ = *src;
++ n--;
++ }
++ src++;
++ }
++ *dst = '\0';
++
++ return(dlen + (src - osrc)); /* count does not include NUL */
++}
+ static const struct flag_list file_contents_encryption_modes[] = {
+ {"aes-256-xts", EM_AES_256_XTS},
+ {"software", EM_AES_256_XTS}, /* alias for backwards compatibility */
+@@ -362,7 +389,7 @@ static int parse_flags(char *flags, struct flag_list *fl,
+ /* fs_options was not passed in, so if the flag is unknown
+ * it's an error.
+ */
+- LERROR << "Warning: unknown flag " << p;
++ //LERROR << "Warning: unknown flag " << p;
+ }
+ }
+ p = strtok_r(NULL, ",", &savep);
+@@ -704,7 +731,7 @@ struct fstab *fs_mgr_read_fstab_dt()
+ {
+ std::string fstab_buf = read_fstab_from_dt();
+ if (fstab_buf.empty()) {
+- LINFO << __FUNCTION__ << "(): failed to read fstab from dt";
++ //LINFO << __FUNCTION__ << "(): failed to read fstab from dt";
+ return nullptr;
+ }
+
+@@ -744,7 +771,12 @@ static std::string get_fstab_path()
+ }
+ }
+ }
+-
++ for (const char* prefix : {"/odm/etc/fstab", "/vendor/etc/fstab", "/etc/fstab"}) {
++ std::string fstab_path = prefix;
++ if (access(fstab_path.c_str(), F_OK) == 0) {
++ return fstab_path;
++ }
++ }
+ return std::string();
+ }
+
diff --git a/meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/files/libbrillo.patch b/meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/files/libbrillo.patch
new file mode 100644
index 0000000..853a792
--- /dev/null
+++ b/meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/files/libbrillo.patch
@@ -0,0 +1,166 @@
+From 4aaf7bc45cfc0db6de494a1a8dedb114915a261f Mon Sep 17 00:00:00 2001
+From: mtk16536 <Dufre.Wu@mediatek.com>
+Date: Wed, 6 May 2020 10:07:22 +0800
+Subject: [PATCH] brillo_stream
+
+Signed-off-by: mtk16536 <Dufre.Wu@mediatek.com>
+---
+ external/libbrillo/brillo/streams/openssl_stream_bio.cc | 74 +++++++++++++++++++++++++++++-------
+ external/libbrillo/brillo/streams/tls_stream.cc | 6 ++-
+ 2 files changed, 66 insertions(+), 14 deletions(-)
+
+diff --git a/external/libbrillo/brillo/streams/openssl_stream_bio.cc b/brillo/streams/openssl_stream_bio.cc
+index a63d9c0..a2f4b50 100644
+--- a/external/libbrillo/brillo/streams/openssl_stream_bio.cc
++++ b/external/libbrillo/brillo/streams/openssl_stream_bio.cc
+@@ -13,9 +13,31 @@ namespace brillo {
+
+ namespace {
+
++#if OPENSSL_VERSION_NUMBER < 0x10100000L
++static void BIO_set_data(BIO* a, void* ptr) {
++ a->ptr = ptr;
++}
++
++static void* BIO_get_data(BIO* a) {
++ return a->ptr;
++}
++
++static void BIO_set_init(BIO* a, int init) {
++ a->init = init;
++}
++
++static int BIO_get_init(BIO* a) {
++ return a->init;
++}
++
++static void BIO_set_shutdown(BIO* a, int shut) {
++ a->shutdown = shut;
++}
++#endif
++
+ // Internal functions for implementing OpenSSL BIO on brillo::Stream.
+ int stream_write(BIO* bio, const char* buf, int size) {
+- brillo::Stream* stream = static_cast<brillo::Stream*>(bio->ptr);
++ brillo::Stream* stream = static_cast<brillo::Stream*>(BIO_get_data(bio));
+ size_t written = 0;
+ BIO_clear_retry_flags(bio);
+ if (!stream->WriteNonBlocking(buf, size, &written, nullptr))
+@@ -30,7 +52,7 @@ int stream_write(BIO* bio, const char* buf, int size) {
+ }
+
+ int stream_read(BIO* bio, char* buf, int size) {
+- brillo::Stream* stream = static_cast<brillo::Stream*>(bio->ptr);
++ brillo::Stream* stream = static_cast<brillo::Stream*>(BIO_get_data(bio));
+ size_t read = 0;
+ BIO_clear_retry_flags(bio);
+ bool eos = false;
+@@ -49,16 +71,16 @@ int stream_read(BIO* bio, char* buf, int size) {
+ // NOLINTNEXTLINE(runtime/int)
+ long stream_ctrl(BIO* bio, int cmd, long /* num */, void* /* ptr */) {
+ if (cmd == BIO_CTRL_FLUSH) {
+- brillo::Stream* stream = static_cast<brillo::Stream*>(bio->ptr);
++ brillo::Stream* stream = static_cast<brillo::Stream*>(BIO_get_data(bio));
+ return stream->FlushBlocking(nullptr) ? 1 : 0;
+ }
+ return 0;
+ }
+
+ int stream_new(BIO* bio) {
+- bio->shutdown = 0; // By default do not close underlying stream on shutdown.
+- bio->init = 0;
+- bio->num = -1; // not used.
++ // By default do not close underlying stream on shutdown.
++ BIO_set_shutdown(bio, 0);
++ BIO_set_init(bio, 0);
+ return 1;
+ }
+
+@@ -66,13 +88,15 @@ int stream_free(BIO* bio) {
+ if (!bio)
+ return 0;
+
+- if (bio->init) {
+- bio->ptr = nullptr;
+- bio->init = 0;
++ if (BIO_get_init(bio)) {
++ BIO_set_data(bio, nullptr);
++ BIO_set_init(bio, 0);
+ }
+ return 1;
+ }
+
++#if OPENSSL_VERSION_NUMBER < 0x10100000L
++
+ // BIO_METHOD structure describing the BIO built on top of brillo::Stream.
+ BIO_METHOD stream_method = {
+ 0x7F | BIO_TYPE_SOURCE_SINK, // type: 0x7F is an arbitrary unused type ID.
+@@ -87,13 +111,37 @@ BIO_METHOD stream_method = {
+ nullptr, // callback function, not used
+ };
+
+-} // anonymous namespace
++BIO_NETHOD* stream_get_method() {
++ return &stream_method;
++}
++
++#else
++
++BIO_METHOD* stream_get_method() {
++ static BIO_METHOD* stream_method;
++
++ if (!stream_method) {
++ stream_method = BIO_meth_new(BIO_get_new_index() | BIO_TYPE_SOURCE_SINK, "stream");
++
++ BIO_meth_set_write(stream_method, stream_write);
++ BIO_meth_set_read(stream_method, stream_read);
++ BIO_meth_set_ctrl(stream_method, stream_ctrl);
++ BIO_meth_set_create(stream_method, stream_new);
++ BIO_meth_set_destroy(stream_method, stream_free);
++ }
++
++ return stream_method;
++}
++
++#endif
++
++} // anonymous namespaces
+
+ BIO* BIO_new_stream(brillo::Stream* stream) {
+- BIO* bio = BIO_new(&stream_method);
++ BIO* bio = BIO_new(stream_get_method());
+ if (bio) {
+- bio->ptr = stream;
+- bio->init = 1;
++ BIO_set_data(bio, stream);
++ BIO_set_init(bio, 1);
+ }
+ return bio;
+ }
+diff --git a/external/libbrillo/brillo/streams/tls_stream.cc b/brillo/streams/tls_stream.cc
+index ac116a4..0403035 100644
+--- a/external/libbrillo/brillo/streams/tls_stream.cc
++++ b/external/libbrillo/brillo/streams/tls_stream.cc
+@@ -67,6 +67,10 @@ const char kCACertificatePath[] =
+
+ namespace brillo {
+
++#if OPENSSL_VERSION_NUMBER < 0x10100000L
++#define TLS_client_method() TLSv1_2_client_method()
++#endif
++
+ // Helper implementation of TLS stream used to hide most of OpenSSL inner
+ // workings from the users of brillo::TlsStream.
+ class TlsStream::TlsStreamImpl {
+@@ -341,7 +345,7 @@ bool TlsStream::TlsStreamImpl::Init(StreamPtr socket,
+ const base::Closure& success_callback,
+ const Stream::ErrorCallback& error_callback,
+ ErrorPtr* error) {
+- ctx_.reset(SSL_CTX_new(TLSv1_2_client_method()));
++ ctx_.reset(SSL_CTX_new(TLS_client_method()));
+ if (!ctx_)
+ return ReportError(error, FROM_HERE, "Cannot create SSL_CTX");
+
+--
+2.6.4
+
diff --git a/meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/files/libchrome.patch b/meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/files/libchrome.patch
new file mode 100644
index 0000000..d34da7e
--- /dev/null
+++ b/meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/files/libchrome.patch
@@ -0,0 +1,48 @@
+diff --git a/external/libchrome/base/allocator/features.h b/external/libchrome/base/allocator/features.h
+index ea479cd..c4ddf5c 100644
+--- a/external/libchrome/base/allocator/features.h
++++ b/external/libchrome/base/allocator/features.h
+@@ -9,7 +9,7 @@
+ #if defined(__APPLE__) || defined(ANDROID)
+ #define BUILDFLAG_INTERNAL_USE_EXPERIMENTAL_ALLOCATOR_SHIM() (0)
+ #else
+-#define BUILDFLAG_INTERNAL_USE_EXPERIMENTAL_ALLOCATOR_SHIM() (1)
++#define BUILDFLAG_INTERNAL_USE_EXPERIMENTAL_ALLOCATOR_SHIM() (0)
+ #endif
+
+ #endif // BASE_ALLOCATOR_FEATURES_H_
+diff --git a/external/libchrome/build/build_config.h b/external/libchrome/build/build_config.h
+index 80a93d3..d07274e 100644
+--- a/external/libchrome/build/build_config.h
++++ b/external/libchrome/build/build_config.h
+@@ -27,14 +27,14 @@
+ // within the NDK.
+
+ // Android targets and hosts don't use tcmalloc.
+-#if defined(__ANDROID__) || defined(__ANDROID_HOST__)
++//#if defined(__ANDROID__) || defined(__ANDROID_HOST__)
+ #define NO_TCMALLOC
+-#endif // defined(__ANDROID__) || defined(__ANDROID_HOST__)
++//#endif // defined(__ANDROID__) || defined(__ANDROID_HOST__)
+
+ // Use the Chrome OS version of the code for both Android targets and Chrome OS builds.
+-#if !defined(__ANDROID_HOST__)
+-#define OS_CHROMEOS 1
+-#endif // !defined(__ANDROID_HOST__)
++//#if !defined(__ANDROID_HOST__)
++//#define OS_CHROMEOS 0
++//#endif // !defined(__ANDROID_HOST__)
+
+ #if defined(__ANDROID__) // Android targets
+
+@@ -47,8 +47,8 @@
+
+ // TODO: Remove these once the GLib MessageLoopForUI isn't being used:
+ // https://crbug.com/361635
+-#define USE_GLIB 1
+-#define USE_OZONE 1
++//#define USE_GLIB 1
++//#define USE_OZONE 1
+
+ #endif // defined(__ANDROID__)
+
diff --git a/meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/files/libevent.patch b/meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/files/libevent.patch
new file mode 100644
index 0000000..99595f2
--- /dev/null
+++ b/meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/files/libevent.patch
@@ -0,0 +1,13 @@
+diff --git a/external/libevent/buffer.c b/external/libevent/buffer.c
+index b7e3a69..a945211 100644
+--- a/external/libevent/buffer.c
++++ b/external/libevent/buffer.c
+@@ -2484,7 +2484,7 @@ evbuffer_write_sendfile(struct evbuffer *buffer, evutil_socket_t dest_fd,
+ return (len);
+ #elif defined(SENDFILE_IS_LINUX)
+ /* TODO(niels): implement splice */
+- res = sendfile(dest_fd, source_fd, &offset, chain->off);
++ res = sendfile(dest_fd, source_fd, (off_t *)(&offset), chain->off);
+ if (res == -1 && EVUTIL_ERR_RW_RETRIABLE(errno)) {
+ /* if this is EAGAIN or EINTR return 0; otherwise, -1 */
+ return (0);
diff --git a/meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/files/makefiles/platform/Makefile.am b/meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/files/makefiles/platform/Makefile.am
new file mode 100644
index 0000000..642ae6d
--- /dev/null
+++ b/meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/files/makefiles/platform/Makefile.am
@@ -0,0 +1,16 @@
+SUBDIRS = \
+ external/cros/system_api/dbus \
+ external/modp_b64 \
+ external/libchrome \
+ external/libbrillo \
+ external/xz-embedded/linux/include/linux \
+ external/xz-embedded \
+ system/core/fs_mgr/include_fstab \
+ system/core/fs_mgr \
+ external/libdivsufsort \
+ external/brotli \
+ external/bsdiff/include \
+ external/bsdiff \
+ external/puffin/src/include \
+ external/puffin \
+ external/libevent
diff --git a/meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/files/makefiles/platform/configure.ac b/meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/files/makefiles/platform/configure.ac
new file mode 100644
index 0000000..4d65be1
--- /dev/null
+++ b/meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/files/makefiles/platform/configure.ac
@@ -0,0 +1,24 @@
+AC_INIT([platform-libs-updateengine], [1.0])
+AM_INIT_AUTOMAKE([foreign subdir-objects])
+AC_PROG_CXX
+AM_PROG_AS
+LT_INIT
+AC_CONFIG_FILES([
+ Makefile
+ external/cros/system_api/dbus/Makefile
+ external/modp_b64/Makefile
+ external/libchrome/Makefile
+ external/libbrillo/Makefile
+ external/xz-embedded/linux/include/linux/Makefile
+ external/xz-embedded/Makefile
+ system/core/fs_mgr/include_fstab/Makefile
+ system/core/fs_mgr/Makefile
+ external/libdivsufsort/Makefile
+ external/brotli/Makefile
+ external/bsdiff/include/Makefile
+ external/bsdiff/Makefile
+ external/puffin/src/include/Makefile
+ external/puffin/Makefile
+ external/libevent/Makefile
+])
+AC_OUTPUT
diff --git a/meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/files/makefiles/platform/external/brotli/Makefile.am b/meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/files/makefiles/platform/external/brotli/Makefile.am
new file mode 100644
index 0000000..4792f09
--- /dev/null
+++ b/meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/files/makefiles/platform/external/brotli/Makefile.am
@@ -0,0 +1,30 @@
+lib_LTLIBRARIES = libbrotli.la
+libbrotli_la_SOURCES = \
+ c/common/dictionary.c \
+ c/dec/bit_reader.c \
+ c/dec/decode.c \
+ c/dec/huffman.c \
+ c/dec/state.c \
+ c/enc/backward_references.c \
+ c/enc/backward_references_hq.c \
+ c/enc/bit_cost.c \
+ c/enc/block_splitter.c \
+ c/enc/brotli_bit_stream.c \
+ c/enc/cluster.c \
+ c/enc/compress_fragment.c \
+ c/enc/compress_fragment_two_pass.c \
+ c/enc/dictionary_hash.c \
+ c/enc/encode.c \
+ c/enc/entropy_encode.c \
+ c/enc/histogram.c \
+ c/enc/literal_cost.c \
+ c/enc/memory.c \
+ c/enc/metablock.c \
+ c/enc/static_dict.c \
+ c/enc/utf8_util.c
+
+libbrotli_la_CPPFLAGS = -Werror -O2
+
+libbrotli_la_CPPFLAGS += \
+ -I$(top_srcdir)/external/brotli/c/include
+
diff --git a/meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/files/makefiles/platform/external/bsdiff/Makefile.am b/meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/files/makefiles/platform/external/bsdiff/Makefile.am
new file mode 100644
index 0000000..fcac3cc
--- /dev/null
+++ b/meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/files/makefiles/platform/external/bsdiff/Makefile.am
@@ -0,0 +1,26 @@
+lib_LIBRARIES = libbspatch.a
+
+libbspatch_a_SOURCES = \
+ brotli_decompressor.cc \
+ bspatch.cc \
+ bz2_decompressor.cc \
+ buffer_file.cc \
+ decompressor_interface.cc \
+ extents.cc \
+ extents_file.cc \
+ file.cc \
+ logging.cc \
+ memory_file.cc \
+ patch_reader.cc \
+ sink_file.cc \
+ utils.cc
+
+libbspatch_a_CPPFLAGS = -Werror -Wall -Wextra -Wno-unused-parameter -D_FILE_OFFSET_BITS=64
+
+libbspatch_a_CPPFLAGS += \
+ -I$(top_srcdir)/external/bsdiff/include \
+ -I$(top_srcdir)/external \
+ -I$(top_srcdir)/external/brotli/c/include
+
+libbspatch_a_LIBADD = $(top_builddir)/../recipe-sysroot$(libdir)/libbz2.so \
+ $(top_builddir)/external/brotli/libbrotli.la
diff --git a/meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/files/makefiles/platform/external/bsdiff/include/Makefile.am b/meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/files/makefiles/platform/external/bsdiff/include/Makefile.am
new file mode 100644
index 0000000..26c5919
--- /dev/null
+++ b/meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/files/makefiles/platform/external/bsdiff/include/Makefile.am
@@ -0,0 +1,11 @@
+nobase_include_HEADERS = \
+ bsdiff/bsdiff.h \
+ bsdiff/bspatch.h \
+ bsdiff/common.h \
+ bsdiff/constants.h \
+ bsdiff/control_entry.h \
+ bsdiff/extents_file.h \
+ bsdiff/file_interface.h \
+ bsdiff/patch_writer_factory.h \
+ bsdiff/patch_writer_interface.h \
+ bsdiff/suffix_array_index_interface.h
diff --git a/meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/files/makefiles/platform/external/cros/system_api/dbus/Makefile.am b/meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/files/makefiles/platform/external/cros/system_api/dbus/Makefile.am
new file mode 100644
index 0000000..180ba8c
--- /dev/null
+++ b/meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/files/makefiles/platform/external/cros/system_api/dbus/Makefile.am
@@ -0,0 +1,2 @@
+nobase_include_HEADERS = \
+ update_engine/dbus-constants.h
diff --git a/meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/files/makefiles/platform/external/libbrillo/Makefile.am b/meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/files/makefiles/platform/external/libbrillo/Makefile.am
new file mode 100644
index 0000000..4690f82
--- /dev/null
+++ b/meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/files/makefiles/platform/external/libbrillo/Makefile.am
@@ -0,0 +1,164 @@
+libbrillo_core_sources = \
+ brillo/backoff_entry.cc \
+ brillo/data_encoding.cc \
+ brillo/errors/error.cc \
+ brillo/errors/error_codes.cc \
+ brillo/flag_helper.cc \
+ brillo/key_value_store.cc \
+ brillo/message_loops/base_message_loop.cc \
+ brillo/message_loops/message_loop.cc \
+ brillo/message_loops/message_loop_utils.cc \
+ brillo/mime_utils.cc \
+ brillo/osrelease_reader.cc \
+ brillo/process.cc \
+ brillo/process_information.cc \
+ brillo/secure_blob.cc \
+ brillo/strings/string_utils.cc \
+ brillo/syslog_logging.cc \
+ brillo/url_utils.cc \
+ brillo/userdb_utils.cc \
+ brillo/value_conversion.cc
+
+libbrillo_linux_sources = \
+ brillo/asynchronous_signal_handler.cc \
+ brillo/daemons/daemon.cc \
+ brillo/file_utils.cc \
+ brillo/process_reaper.cc
+
+libbrillo_stream_sources = \
+ brillo/streams/file_stream.cc \
+ brillo/streams/input_stream_set.cc \
+ brillo/streams/memory_containers.cc \
+ brillo/streams/memory_stream.cc \
+ brillo/streams/openssl_stream_bio.cc \
+ brillo/streams/stream.cc \
+ brillo/streams/stream_errors.cc \
+ brillo/streams/stream_utils.cc \
+ brillo/streams/tls_stream.cc
+
+lib_LTLIBRARIES = libbrillo.la libbrillo_stream.la
+libbrillo_la_SOURCES = $(libbrillo_core_sources) \
+ $(libbrillo_linux_sources)
+
+libbrillo_la_LIBADD = \
+ $(top_builddir)/external/modp_b64/libmodpb64.a \
+ $(top_builddir)/external/libchrome/libchrome.la
+
+libbrillo_la_CFLAGS = -Wall -Werror
+
+libbrillo_la_CPPFLAGS = \
+ -I$(top_srcdir)/external/libchrome \
+ -I$(top_srcdir)/external/libbrillo \
+ -I$(top_srcdir)/external/modp_b64
+
+libbrillo_stream_la_SOURCES = $(libbrillo_stream_sources)
+libbrillo_stream_la_CFLAGS = -Wall -Werror
+
+libbrillo_stream_la_LIBADD = \
+ libbrillo.la \
+ -lcrypto -lssl -lgtest
+
+libbrillo_stream_la_CPPFLAGS = \
+ -I$(top_srcdir)/external/libchrome \
+ -I$(top_srcdir)/external/libbrillo
+
+nobase_include_HEADERS = \
+ brillo/any.h \
+ brillo/any_internal_impl.h \
+ brillo/asynchronous_signal_handler.h \
+ brillo/asynchronous_signal_handler_interface.h\
+ brillo/backoff_entry.h \
+ brillo/bind_lambda.h \
+ brillo/binder_watcher.h \
+ brillo/brillo_export.h \
+ brillo/cryptohome.h \
+ brillo/data_encoding.h \
+ brillo/enum_flags.h \
+ brillo/file_utils.h \
+ brillo/flag_helper.h \
+ brillo/key_value_store.h \
+ brillo/location_logging.h \
+ brillo/make_unique_ptr.h \
+ brillo/map_utils.h \
+ brillo/mime_utils.h \
+ brillo/osrelease_reader.h \
+ brillo/pointer_utils.h \
+ brillo/process.h \
+ brillo/process_information.h \
+ brillo/process_mock.h \
+ brillo/process_reaper.h \
+ brillo/secure_blob.h \
+ brillo/syslog_logging.h \
+ brillo/test_helpers.h \
+ brillo/type_name_undecorate.h \
+ brillo/unittest_utils.h \
+ brillo/url_utils.h \
+ brillo/userdb_utils.h \
+ brillo/value_conversion.h \
+ brillo/variant_dictionary.h \
+ brillo/daemons/daemon.h \
+ brillo/daemons/dbus_daemon.h \
+ brillo/dbus/async_event_sequencer.h \
+ brillo/dbus/data_serialization.h \
+ brillo/dbus/dbus_connection.h \
+ brillo/dbus/dbus_method_invoker.h \
+ brillo/dbus/dbus_method_response.h \
+ brillo/dbus/dbus_object.h \
+ brillo/dbus/dbus_object_internal_impl.h \
+ brillo/dbus/dbus_object_test_helpers.h \
+ brillo/dbus/dbus_param_reader.h \
+ brillo/dbus/dbus_param_writer.h \
+ brillo/dbus/dbus_property.h \
+ brillo/dbus/dbus_service_watcher.h \
+ brillo/dbus/dbus_signal.h \
+ brillo/dbus/dbus_signal_handler.h \
+ brillo/dbus/exported_object_manager.h \
+ brillo/dbus/exported_property_set.h \
+ brillo/dbus/mock_dbus_object.h \
+ brillo/dbus/mock_exported_object_manager.h \
+ brillo/dbus/utils.h \
+ brillo/errors/error.h \
+ brillo/errors/error_codes.h \
+ brillo/glib/abstract_dbus_service.h \
+ brillo/glib/dbus.h \
+ brillo/glib/object.h \
+ brillo/http/curl_api.h \
+ brillo/http/http_connection.h \
+ brillo/http/http_connection_curl.h \
+ brillo/http/http_connection_fake.h \
+ brillo/http/http_form_data.h \
+ brillo/http/http_request.h \
+ brillo/http/http_transport.h \
+ brillo/http/http_transport_curl.h \
+ brillo/http/http_transport_fake.h \
+ brillo/http/http_utils.h \
+ brillo/http/mock_connection.h \
+ brillo/http/mock_curl_api.h \
+ brillo/http/mock_transport.h \
+ brillo/message_loops/base_message_loop.h \
+ brillo/message_loops/fake_message_loop.h \
+ brillo/message_loops/glib_message_loop.h \
+ brillo/message_loops/message_loop.h \
+ brillo/message_loops/message_loop_utils.h \
+ brillo/message_loops/mock_message_loop.h \
+ brillo/minijail/minijail.h \
+ brillo/minijail/mock_minijail.h \
+ brillo/streams/fake_stream.h \
+ brillo/streams/file_stream.h \
+ brillo/streams/input_stream_set.h \
+ brillo/streams/memory_containers.h \
+ brillo/streams/memory_stream.h \
+ brillo/streams/mock_stream.h \
+ brillo/streams/openssl_stream_bio.h \
+ brillo/streams/stream.h \
+ brillo/streams/stream_errors.h \
+ brillo/streams/stream_utils.h \
+ brillo/streams/tls_stream.h \
+ brillo/strings/string_utils.h \
+ policy/device_policy.h \
+ policy/device_policy_impl.h \
+ policy/libpolicy.h \
+ policy/mock_device_policy.h \
+ policy/mock_libpolicy.h \
+ policy/policy_util.h \
+ policy/resilient_policy_util.h
diff --git a/meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/files/makefiles/platform/external/libchrome/Makefile.am b/meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/files/makefiles/platform/external/libchrome/Makefile.am
new file mode 100644
index 0000000..151c645
--- /dev/null
+++ b/meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/files/makefiles/platform/external/libchrome/Makefile.am
@@ -0,0 +1,356 @@
+libchromeCommonSrc = \
+ base/at_exit.cc \
+ base/base64.cc \
+ base/base64url.cc \
+ base/base_switches.cc \
+ base/bind_helpers.cc \
+ base/build_time.cc \
+ base/callback_helpers.cc \
+ base/callback_internal.cc \
+ base/command_line.cc \
+ base/cpu.cc \
+ base/debug/activity_tracker.cc \
+ base/debug/alias.cc \
+ base/debug/debugger.cc \
+ base/debug/debugger_posix.cc \
+ base/debug/dump_without_crashing.cc \
+ base/debug/profiler.cc \
+ base/debug/stack_trace.cc \
+ base/debug/stack_trace_posix.cc \
+ base/debug/task_annotator.cc \
+ base/environment.cc \
+ base/feature_list.cc \
+ base/files/file.cc \
+ base/files/file_descriptor_watcher_posix.cc \
+ base/files/file_enumerator.cc \
+ base/files/file_enumerator_posix.cc \
+ base/files/file_path.cc \
+ base/files/file_path_constants.cc \
+ base/files/file_path_watcher.cc \
+ base/files/file_posix.cc \
+ base/files/file_tracing.cc \
+ base/files/file_util.cc \
+ base/files/file_util_posix.cc \
+ base/files/important_file_writer.cc \
+ base/files/memory_mapped_file.cc \
+ base/files/memory_mapped_file_posix.cc \
+ base/files/scoped_file.cc \
+ base/files/scoped_temp_dir.cc \
+ base/guid.cc \
+ base/hash.cc \
+ base/json/json_file_value_serializer.cc \
+ base/json/json_parser.cc \
+ base/json/json_reader.cc \
+ base/json/json_string_value_serializer.cc \
+ base/json/json_value_converter.cc \
+ base/json/json_writer.cc \
+ base/json/string_escape.cc \
+ base/lazy_instance.cc \
+ base/location.cc \
+ base/logging.cc \
+ base/md5.cc \
+ base/memory/aligned_memory.cc \
+ base/memory/ref_counted.cc \
+ base/memory/ref_counted_memory.cc \
+ base/memory/shared_memory_helper.cc \
+ base/memory/singleton.cc \
+ base/memory/weak_ptr.cc \
+ base/message_loop/incoming_task_queue.cc \
+ base/message_loop/message_loop.cc \
+ base/message_loop/message_loop_task_runner.cc \
+ base/message_loop/message_pump.cc \
+ base/message_loop/message_pump_default.cc \
+ base/message_loop/message_pump_libevent.cc \
+ base/metrics/bucket_ranges.cc \
+ base/metrics/field_trial.cc \
+ base/metrics/field_trial_param_associator.cc \
+ base/metrics/metrics_hashes.cc \
+ base/metrics/histogram_base.cc \
+ base/metrics/histogram.cc \
+ base/metrics/histogram_samples.cc \
+ base/metrics/histogram_snapshot_manager.cc \
+ base/metrics/persistent_histogram_allocator.cc \
+ base/metrics/persistent_memory_allocator.cc \
+ base/metrics/persistent_sample_map.cc \
+ base/metrics/sample_map.cc \
+ base/metrics/sample_vector.cc \
+ base/metrics/sparse_histogram.cc \
+ base/metrics/statistics_recorder.cc \
+ base/pending_task.cc \
+ base/pickle.cc \
+ base/posix/global_descriptors.cc \
+ base/posix/file_descriptor_shuffle.cc \
+ base/posix/safe_strerror.cc \
+ base/process/kill.cc \
+ base/process/kill_posix.cc \
+ base/process/launch.cc \
+ base/process/launch_posix.cc \
+ base/process/memory.cc \
+ base/process/process_handle.cc \
+ base/process/process_handle_posix.cc \
+ base/process/process_iterator.cc \
+ base/process/process_metrics.cc \
+ base/process/process_metrics_posix.cc \
+ base/process/process_posix.cc \
+ base/profiler/scoped_profile.cc \
+ base/profiler/scoped_tracker.cc \
+ base/profiler/tracked_time.cc \
+ base/rand_util.cc \
+ base/rand_util_posix.cc \
+ base/run_loop.cc \
+ base/sequence_checker_impl.cc \
+ base/sequence_token.cc \
+ base/sequenced_task_runner.cc \
+ base/sha1.cc \
+ base/strings/pattern.cc \
+ base/strings/safe_sprintf.cc \
+ base/strings/string16.cc \
+ base/strings/string_number_conversions.cc \
+ base/strings/string_piece.cc \
+ base/strings/stringprintf.cc \
+ base/strings/string_split.cc \
+ base/strings/string_util.cc \
+ base/strings/string_util_constants.cc \
+ base/strings/utf_string_conversions.cc \
+ base/strings/utf_string_conversion_utils.cc \
+ base/synchronization/atomic_flag.cc \
+ base/synchronization/condition_variable_posix.cc \
+ base/synchronization/lock.cc \
+ base/synchronization/lock_impl_posix.cc \
+ base/synchronization/read_write_lock_posix.cc \
+ base/synchronization/waitable_event_posix.cc \
+ base/sync_socket_posix.cc \
+ base/sys_info.cc \
+ base/sys_info_posix.cc \
+ base/task/cancelable_task_tracker.cc \
+ base/task_runner.cc \
+ base/task_scheduler/scheduler_lock_impl.cc \
+ base/task_scheduler/scoped_set_task_priority_for_current_thread.cc \
+ base/task_scheduler/sequence.cc \
+ base/task_scheduler/sequence_sort_key.cc \
+ base/task_scheduler/task.cc \
+ base/task_scheduler/task_traits.cc \
+ base/third_party/dynamic_annotations/dynamic_annotations.c \
+ base/third_party/icu/icu_utf.cc \
+ base/third_party/nspr/prtime.cc \
+ base/threading/non_thread_safe_impl.cc \
+ base/threading/platform_thread_posix.cc \
+ base/threading/post_task_and_reply_impl.cc \
+ base/threading/sequenced_task_runner_handle.cc \
+ base/threading/sequenced_worker_pool.cc \
+ base/threading/simple_thread.cc \
+ base/threading/thread.cc \
+ base/threading/thread_checker_impl.cc \
+ base/threading/thread_collision_warner.cc \
+ base/threading/thread_id_name_manager.cc \
+ base/threading/thread_local_storage.cc \
+ base/threading/thread_local_storage_posix.cc \
+ base/threading/thread_restrictions.cc \
+ base/threading/thread_task_runner_handle.cc \
+ base/threading/worker_pool.cc \
+ base/threading/worker_pool_posix.cc \
+ base/time/clock.cc \
+ base/time/default_clock.cc \
+ base/time/default_tick_clock.cc \
+ base/time/tick_clock.cc \
+ base/time/time.cc \
+ base/time/time_posix.cc \
+ base/timer/elapsed_timer.cc \
+ base/timer/timer.cc \
+ base/trace_event/category_registry.cc \
+ base/trace_event/event_name_filter.cc \
+ base/trace_event/heap_profiler_allocation_context.cc \
+ base/trace_event/heap_profiler_allocation_context_tracker.cc \
+ base/trace_event/heap_profiler_allocation_register.cc \
+ base/trace_event/heap_profiler_allocation_register_posix.cc \
+ base/trace_event/heap_profiler_event_filter.cc \
+ base/trace_event/heap_profiler_heap_dump_writer.cc \
+ base/trace_event/heap_profiler_stack_frame_deduplicator.cc \
+ base/trace_event/heap_profiler_type_name_deduplicator.cc \
+ base/trace_event/malloc_dump_provider.cc \
+ base/trace_event/memory_allocator_dump.cc \
+ base/trace_event/memory_allocator_dump_guid.cc \
+ base/trace_event/memory_dump_manager.cc \
+ base/trace_event/memory_dump_provider_info.cc \
+ base/trace_event/memory_dump_request_args.cc \
+ base/trace_event/memory_dump_scheduler.cc \
+ base/trace_event/memory_dump_session_state.cc \
+ base/trace_event/memory_infra_background_whitelist.cc \
+ base/trace_event/memory_usage_estimator.cc \
+ base/trace_event/process_memory_dump.cc \
+ base/trace_event/process_memory_maps.cc \
+ base/trace_event/process_memory_totals.cc \
+ base/trace_event/trace_buffer.cc \
+ base/trace_event/trace_config.cc \
+ base/trace_event/trace_config_category_filter.cc \
+ base/trace_event/trace_event_argument.cc \
+ base/trace_event/trace_event_filter.cc \
+ base/trace_event/trace_event_impl.cc \
+ base/trace_event/trace_event_memory_overhead.cc \
+ base/trace_event/trace_event_synthetic_delay.cc \
+ base/trace_event/trace_log.cc \
+ base/trace_event/trace_log_constants.cc \
+ base/tracked_objects.cc \
+ base/tracking_info.cc \
+ base/values.cc \
+ base/version.cc \
+ base/vlog.cc
+
+libchromeLinuxSrc = \
+ base/files/file_path_watcher_linux.cc \
+ base/files/file_util_linux.cc \
+ base/memory/shared_memory_posix.cc \
+ base/memory/shared_memory_tracker.cc \
+ base/posix/unix_domain_socket_linux.cc \
+ base/process/internal_linux.cc \
+ base/process/memory_linux.cc \
+ base/process/process_handle_linux.cc \
+ base/process/process_info_linux.cc \
+ base/process/process_iterator_linux.cc \
+ base/process/process_metrics_linux.cc \
+ base/strings/sys_string_conversions_posix.cc \
+ base/sys_info_linux.cc \
+ base/threading/platform_thread_internal_posix.cc \
+ base/threading/platform_thread_linux.cc \
+ components/timers/alarm_timer_chromeos.cc
+
+libchromeLinuxGlibcSrc = \
+ base/allocator/allocator_shim.cc \
+ base/allocator/allocator_shim_default_dispatch_to_glibc.cc
+
+lib_LTLIBRARIES = libchrome.la
+libchrome_la_SOURCES = $(libchromeCommonSrc) \
+ $(libchromeLinuxSrc)
+
+libchrome_la_LIBADD = \
+ $(top_builddir)/external/modp_b64/libmodpb64.a
+
+libchrome_la_CFLAGS = -Wall \
+ -Werror \
+ -Wno-deprecated-declarations \
+ -Wno-missing-field-initializers \
+ -DOS_LINUX
+# -Wno-unused-parameter
+
+libchrome_la_CPPFLAGS = \
+ -I$(top_srcdir)/external/libchrome \
+ -I$(top_srcdir)/external/valgrind/include \
+ -I$(top_srcdir)/external/valgrind \
+ -I$(top_srcdir)/external/modp_b64 \
+ -I$(top_srcdir)/external/libevent/include
+
+nobase_include_HEADERS = \
+ base/at_exit.h \
+ base/atomic_ref_count.h \
+ base/atomicops_internals_portable.h \
+ base/atomicops.h \
+ base/allocator/features.h \
+ base/bind.h \
+ base/bind_internal.h \
+ base/bind_helpers.h \
+ base/macros.h \
+ base/time/time.h \
+ base/logging.h \
+ base/location.h \
+ base/lazy_instance.h \
+ base/callback.h \
+ base/callback_forward.h \
+ base/callback_internal.h \
+ base/containers/hash_tables.h \
+ base/format_macros.h \
+ base/debug/debugger.h \
+ base/debug/debugging_flags.h \
+ base/debug/thread_heap_usage_tracker.h \
+ base/debug/task_annotator.h \
+ base/debug/leak_annotations.h \
+ base/hash.h \
+ base/memory/aligned_memory.h \
+ base/memory/free_deleter.h \
+ base/memory/linked_ptr.h \
+ base/memory/manual_constructor.h \
+ base/memory/ptr_util.h \
+ base/memory/raw_scoped_refptr_mismatch_checker.h \
+ base/memory/ref_counted.h \
+ base/memory/ref_counted_memory.h \
+ base/memory/scoped_policy.h \
+ base/memory/scoped_vector.h \
+ base/memory/shared_memory.h \
+ base/memory/shared_memory_handle.h \
+ base/memory/shared_memory_helper.h \
+ base/memory/shared_memory_tracker.h \
+ base/memory/singleton.h \
+ base/memory/weak_ptr.h \
+ base/message_loop/message_loop.h \
+ base/message_loop/incoming_task_queue.h \
+ base/message_loop/message_loop_task_runner.h \
+ base/message_loop/message_pump.h \
+ base/message_loop/timer_slack.h \
+ base/message_loop/message_pump_libevent.h \
+ base/metrics/histogram_macros.h \
+ base/metrics/statistics_recorder.h \
+ base/metrics/histogram.h \
+ base/metrics/histogram_base.h \
+ base/metrics/bucket_ranges.h \
+ base/metrics/histogram_samples.h \
+ base/metrics/histogram_macros_internal.h \
+ base/metrics/histogram_macros_local.h \
+ base/metrics/sparse_histogram.h \
+ base/numerics/safe_math.h \
+ base/numerics/safe_math_impl.h \
+ base/numerics/safe_conversions.h \
+ base/numerics/safe_conversions_impl.h \
+ base/file_descriptor_posix.h \
+ base/files/file.h \
+ base/files/file_util.h \
+ base/files/file_path.h \
+ base/files/scoped_temp_dir.h \
+ base/files/scoped_file.h \
+ base/files/dir_reader_posix.h \
+ base/files/file_enumerator.h \
+ base/files/file_tracing.h \
+ base/gtest_prod_util.h \
+ base/command_line.h \
+ base/base_export.h \
+ base/compiler_specific.h \
+ base/stl_util.h \
+ base/single_thread_task_runner.h \
+ base/strings/string16.h \
+ base/strings/string_util.h \
+ base/strings/string_split.h \
+ base/strings/string_number_conversions.h \
+ base/strings/stringprintf.h \
+ base/strings/string_piece.h \
+ base/strings/string_util_posix.h \
+ base/sequence_checker.h \
+ base/sequence_checker_impl.h \
+ base/scoped_generic.h \
+ base/scoped_observer.h \
+ base/sequence_token.h \
+ base/sequenced_task_runner.h \
+ base/sequenced_task_runner_helpers.h \
+ base/synchronization/lock.h \
+ base/synchronization/lock_impl.h \
+ base/synchronization/read_write_lock.h \
+ base/pending_task.h \
+ base/posix/eintr_wrapper.h \
+ base/process/process_handle.h \
+ base/profiler/tracked_time.h \
+ base/tuple.h \
+ base/task_runner.h \
+ base/template_util.h \
+ base/tracked_objects.h \
+ base/tracking_info.h \
+ base/threading/platform_thread.h \
+ base/threading/thread_checker.h \
+ base/threading/thread_checker_impl.h \
+ base/threading/thread_collision_warner.h \
+ base/threading/thread_restrictions.h \
+ base/threading/thread_local_storage.h \
+ base/threading/non_thread_safe.h \
+ base/threading/non_thread_safe_impl.h \
+ base/observer_list.h \
+ base/rand_util.h \
+ build/build_config.h \
+ build/buildflag.h \
+ testing/gtest/include/gtest/gtest.h \
+ testing/gtest/include/gtest/gtest_prod.h
diff --git a/meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/files/makefiles/platform/external/libdivsufsort/Makefile.am b/meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/files/makefiles/platform/external/libdivsufsort/Makefile.am
new file mode 100644
index 0000000..b8df2da
--- /dev/null
+++ b/meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/files/makefiles/platform/external/libdivsufsort/Makefile.am
@@ -0,0 +1,21 @@
+lib_LTLIBRARIES = libdivsufsort.la libdivsufsort64.la
+divsufsort_source = lib/divsufsort.c \
+ lib/sssort.c \
+ lib/trsort.c \
+ lib/utils.c
+divsufsort_cflag = -Wall \
+ -Werror \
+ -Wextra \
+ -DHAVE_CONFIG_H=1
+libdivsufsort_la_SOURCES = $(divsufsort_source)
+libdivsufsort64_la_SOURCES = $(divsufsort_source)
+
+libdivsufsort_la_CFLAGS = $(divsufsort_cflag)
+libdivsufsort64_la_CFLAGS = $(divsufsort_cflag) \
+ -DBUILD_DIVSUFSORT64
+
+libdivsufsort_la_CPPFLAGS = -I$(top_srcdir)/external/libdivsufsort/include \
+ -I$(top_srcdir)/external/libdivsufsort/android_include
+
+libdivsufsort64_la_CPPFLAGS = -I$(top_srcdir)/external/libdivsufsort/include \
+ -I$(top_srcdir)/external/libdivsufsort/android_include
diff --git a/meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/files/makefiles/platform/external/libevent/Makefile.am b/meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/files/makefiles/platform/external/libevent/Makefile.am
new file mode 100644
index 0000000..f05ce51
--- /dev/null
+++ b/meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/files/makefiles/platform/external/libevent/Makefile.am
@@ -0,0 +1,37 @@
+lib_LTLIBRARIES = libevent.la
+libevent_la_SOURCES = \
+ buffer.c \
+ bufferevent.c \
+ bufferevent_filter.c \
+ bufferevent_pair.c \
+ bufferevent_ratelim.c \
+ bufferevent_sock.c \
+ event.c \
+ evmap.c \
+ evthread.c \
+ evutil.c \
+ evutil_rand.c \
+ evutil_time.c \
+ listener.c \
+ log.c \
+ signal.c \
+ strlcpy.c \
+ evdns.c \
+ event_tagging.c \
+ evrpc.c \
+ http.c \
+ poll.c \
+ select.c \
+ epoll.c
+
+libevent_la_CPPFLAGS = \
+ -O3 \
+ -Wno-implicit-function-declaration \
+ -Wno-strict-aliasing \
+ -Wno-unused-parameter \
+ -Werror
+
+libevent_la_CPPFLAGS += \
+ -I$(top_srcdir)/external/libevent/include \
+ -I$(top_srcdir)/external/libevent/compat
+
diff --git a/meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/files/makefiles/platform/external/modp_b64/Makefile.am b/meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/files/makefiles/platform/external/modp_b64/Makefile.am
new file mode 100644
index 0000000..0ad27d2
--- /dev/null
+++ b/meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/files/makefiles/platform/external/modp_b64/Makefile.am
@@ -0,0 +1,15 @@
+lib_LIBRARIES = libmodpb64.a
+
+libmodpb64_a_SOURCES = \
+ modp_b64.cc
+
+
+libmodpb64_a_CPPFLAGS = -Werror -Wall -Wextra -std=c++14 -fPIC
+
+libmodpb64_a_CPPFLAGS += \
+ -I$(top_srcdir)/external/modp_b64 \
+ -I$(top_srcdir)/external/modp_b64/modp_b64
+
+nobase_include_HEADERS = \
+ modp_b64_data.h \
+ modp_b64/modp_b64.h
\ No newline at end of file
diff --git a/meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/files/makefiles/platform/external/puffin/Makefile.am b/meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/files/makefiles/platform/external/puffin/Makefile.am
new file mode 100644
index 0000000..fdaab81
--- /dev/null
+++ b/meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/files/makefiles/platform/external/puffin/Makefile.am
@@ -0,0 +1,23 @@
+lib_LTLIBRARIES = libpuffpatch.la
+
+libpuffpatch_la_SOURCES = \
+ puffin/src/puffin.pb.cc \
+ src/bit_reader.cc \
+ src/bit_writer.cc \
+ src/huffer.cc \
+ src/huffman_table.cc \
+ src/puff_reader.cc \
+ src/puff_writer.cc \
+ src/puffer.cc \
+ src/puffin_stream.cc \
+ src/puffpatch.cc
+
+libpuffpatch_la_CPPFLAGS = -Werror -Wall -Wextra -std=c++14 -DZLIB_CONST -D_FILE_OFFSET_BITS=64 -Werror=implicit-fallthrough=0
+
+#libpuffpatch_la_LIBADD = $(top_builddir)/system/core/liblog/liblog.la
+libpuffpatch_a_LIBADD = -lgflags -lglog -lprotobuf-lite -lgtest -lpthread
+
+libpuffpatch_la_CPPFLAGS += \
+ -I$(top_srcdir)/external/puffin \
+ -I$(top_srcdir)/external/puffin/src/include \
+ -I$(top_srcdir)/external/bsdiff/include
diff --git a/meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/files/makefiles/platform/external/puffin/src/include/Makefile.am b/meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/files/makefiles/platform/external/puffin/src/include/Makefile.am
new file mode 100644
index 0000000..0cdb040
--- /dev/null
+++ b/meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/files/makefiles/platform/external/puffin/src/include/Makefile.am
@@ -0,0 +1,9 @@
+nobase_include_HEADERS = \
+ puffin/common.h \
+ puffin/errors.h \
+ puffin/huffer.h \
+ puffin/puffdiff.h \
+ puffin/puffer.h \
+ puffin/puffpatch.h \
+ puffin/stream.h \
+ puffin/utils.h
diff --git a/meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/files/makefiles/platform/external/xz-embedded/Makefile.am b/meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/files/makefiles/platform/external/xz-embedded/Makefile.am
new file mode 100644
index 0000000..8369af8
--- /dev/null
+++ b/meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/files/makefiles/platform/external/xz-embedded/Makefile.am
@@ -0,0 +1,14 @@
+lib_LIBRARIES = libxz.a
+libxz_a_SOURCES = linux/lib/xz/xz_crc32.c \
+ linux/lib/xz/xz_dec_bcj.c \
+ linux/lib/xz/xz_dec_lzma2.c \
+ linux/lib/xz/xz_dec_stream.c
+
+libxz_a_CFLAGS = -Wall \
+ -Werror \
+ -DXZ_DEC_X86 \
+ -DXZ_DEC_ARM \
+ -DXZ_DEC_ARMTHUMB
+
+libxz_a_CPPFLAGS = -I$(top_srcdir)/external/xz-embedded/userspace \
+ -I$(top_srcdir)/external/xz-embedded/linux/include/linux
diff --git a/meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/files/makefiles/platform/external/xz-embedded/linux/include/linux/Makefile.am b/meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/files/makefiles/platform/external/xz-embedded/linux/include/linux/Makefile.am
new file mode 100644
index 0000000..7b062f9
--- /dev/null
+++ b/meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/files/makefiles/platform/external/xz-embedded/linux/include/linux/Makefile.am
@@ -0,0 +1,3 @@
+nobase_include_HEADERS = \
+ xz.h \
+ decompress/unxz.h
diff --git a/meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/files/makefiles/platform/system/core/base/.clang-format b/meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/files/makefiles/platform/system/core/base/.clang-format
new file mode 100644
index 0000000..2b83a1f
--- /dev/null
+++ b/meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/files/makefiles/platform/system/core/base/.clang-format
@@ -0,0 +1,11 @@
+BasedOnStyle: Google
+AllowShortBlocksOnASingleLine: false
+AllowShortFunctionsOnASingleLine: false
+
+CommentPragmas: NOLINT:.*
+DerivePointerAlignment: false
+IndentWidth: 2
+PointerAlignment: Left
+TabWidth: 2
+UseTab: Never
+PenaltyExcessCharacter: 32
diff --git a/meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/files/makefiles/platform/system/core/base/Makefile.am b/meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/files/makefiles/platform/system/core/base/Makefile.am
new file mode 100644
index 0000000..9134b45
--- /dev/null
+++ b/meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/files/makefiles/platform/system/core/base/Makefile.am
@@ -0,0 +1,20 @@
+lib_LTLIBRARIES = libbase.la
+
+libbase_la_SOURCES = \
+ chrono_utils.cpp \
+ file.cpp \
+ logging.cpp \
+ parsenetaddress.cpp \
+ stringprintf.cpp \
+ strings.cpp \
+ test_utils.cpp \
+ errors_unix.cpp
+
+libbase_la_CPPFLAGS = -Werror -Wall -Wextra -std=c++14
+
+libbase_la_CPPFLAGS += \
+ -I$(top_srcdir)/system/core/base/include \
+ -I$(top_srcdir)/system/core/include
+
+libbase_la_LIBADD = \
+ $(top_builddir)/system/core/liblog/liblog.la
diff --git a/meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/files/makefiles/platform/system/core/base/include/Makefile.am b/meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/files/makefiles/platform/system/core/base/include/Makefile.am
new file mode 100644
index 0000000..355ce20
--- /dev/null
+++ b/meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/files/makefiles/platform/system/core/base/include/Makefile.am
@@ -0,0 +1,3 @@
+nobase_include_HEADERS = \
+ android-base/unique_fd.h \
+ android-base/properties.h
diff --git a/meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/files/makefiles/platform/system/core/fs_mgr/Makefile.am b/meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/files/makefiles/platform/system/core/fs_mgr/Makefile.am
new file mode 100644
index 0000000..7381adf
--- /dev/null
+++ b/meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/files/makefiles/platform/system/core/fs_mgr/Makefile.am
@@ -0,0 +1,14 @@
+lib_LTLIBRARIES = libfstab.la
+
+libfstab_la_SOURCES = \
+ fs_mgr_boot_config.cpp \
+ fs_mgr_fstab.cpp \
+ fs_mgr_slotselect.cpp
+
+libfstab_la_CFLAGS = -Wall \
+ -Werror \
+ -Wno-unused-variable
+
+libfstab_la_CPPFLAGS = \
+ -I$(top_srcdir)/system/core/fs_mgr/include \
+ -I$(top_srcdir)/system/core/fs_mgr/include_fstab
diff --git a/meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/files/makefiles/platform/system/core/fs_mgr/include_fstab/Makefile.am b/meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/files/makefiles/platform/system/core/fs_mgr/include_fstab/Makefile.am
new file mode 100644
index 0000000..59f16b0
--- /dev/null
+++ b/meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/files/makefiles/platform/system/core/fs_mgr/include_fstab/Makefile.am
@@ -0,0 +1,3 @@
+nobase_include_HEADERS = \
+ fstab/fstab.h
+
diff --git a/meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/files/makefiles/platform/system/core/include/Makefile.am b/meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/files/makefiles/platform/system/core/include/Makefile.am
new file mode 100644
index 0000000..ec0f4eb
--- /dev/null
+++ b/meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/files/makefiles/platform/system/core/include/Makefile.am
@@ -0,0 +1,27 @@
+nobase_include_HEADERS = \
+ utils/Compat.h \
+ utils/Errors.h \
+ utils/KeyedVector.h \
+ utils/RefBase.h \
+ utils/SortedVector.h \
+ utils/String8.h \
+ utils/String16.h \
+ utils/SystemClock.h \
+ utils/Timers.h \
+ utils/TypeHelpers.h \
+ utils/Unicode.h \
+ utils/Vector.h \
+ utils/VectorImpl.h \
+ utils/threads.h \
+ utils/StrongPointer.h \
+ utils/CallStack.h \
+ utils/Printer.h \
+ utils/Looper.h \
+ utils/ThreadDefs.h \
+ utils/AndroidThreads.h \
+ utils/Condition.h \
+ utils/Mutex.h \
+ utils/Thread.h \
+ utils/RWLock.h \
+ utils/List.h
+
diff --git a/meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/files/makefiles/platform/system/core/liblog/Makefile.am b/meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/files/makefiles/platform/system/core/liblog/Makefile.am
new file mode 100644
index 0000000..5804679
--- /dev/null
+++ b/meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/files/makefiles/platform/system/core/liblog/Makefile.am
@@ -0,0 +1,22 @@
+lib_LTLIBRARIES = liblog.la
+
+liblog_la_SOURCES = \
+ config_write.c \
+ config_read.c \
+ local_logger.c \
+ fake_log_device.c \
+ fake_writer.c \
+ log_event_list.c \
+ log_event_write.c \
+ logger_lock.c \
+ logger_name.c \
+ logger_write.c \
+ logprint.c \
+ stderr_write.c
+
+liblog_la_CFLAGS = -Werror -fvisibility=hidden
+liblog_la_CPPFLAGS = \
+ -DFAKE_LOG_DEVICE=1 \
+ -DLIBLOG_LOG_TAG=1005 \
+ -DSNET_EVENT_LOG_TAG=1397638484 \
+ -I$(top_srcdir)/system/core/include
diff --git a/meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/files/puffin.patch b/meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/files/puffin.patch
new file mode 100644
index 0000000..c199cb4
--- /dev/null
+++ b/meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/files/puffin.patch
@@ -0,0 +1,1590 @@
+From 75e24f2bc2c004d3b16490d34149d258128ca5d3 Mon Sep 17 00:00:00 2001
+From: mtk16536 <Dufre.Wu@mediatek.com>
+Date: Wed, 6 May 2020 12:11:14 +0800
+Subject: [PATCH] puffin
+
+Signed-off-by: mtk16536 <Dufre.Wu@mediatek.com>
+---
+ external/puffin/src/puffin.pb.cc | 854 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ external/puffin/src/puffin.pb.h | 689 ++++++++++++++++++++++++++++++++++++++++++++
+ external/puffin/src/puffpatch.cc | 4 +-
+ 3 files changed, 1545 insertions(+), 2 deletions(-)
+ create mode 100644 external/puffin/src/puffin.pb.cc
+ create mode 100644 external/puffin/src/puffin.pb.h
+
+diff --git a/external/puffin/src/puffin.pb.cc b/external/puffin/src/puffin.pb.cc
+new file mode 100644
+index 0000000..46f050d
+--- /dev/null
++++ b/external/puffin/src/puffin.pb.cc
+@@ -0,0 +1,854 @@
++// Generated by the protocol buffer compiler. DO NOT EDIT!
++// source: puffin.proto
++
++#include "puffin.pb.h"
++
++#include <algorithm>
++
++#include <google/protobuf/stubs/common.h>
++#include <google/protobuf/stubs/port.h>
++#include <google/protobuf/io/coded_stream.h>
++#include <google/protobuf/wire_format_lite_inl.h>
++#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
++// This is a temporary google only hack
++#ifdef GOOGLE_PROTOBUF_ENFORCE_UNIQUENESS
++#include "third_party/protobuf/version.h"
++#endif
++// @@protoc_insertion_point(includes)
++
++namespace protobuf_puffin_2eproto {
++extern PROTOBUF_INTERNAL_EXPORT_protobuf_puffin_2eproto ::google::protobuf::internal::SCCInfo<0> scc_info_BitExtent;
++extern PROTOBUF_INTERNAL_EXPORT_protobuf_puffin_2eproto ::google::protobuf::internal::SCCInfo<1> scc_info_StreamInfo;
++} // namespace protobuf_puffin_2eproto
++namespace puffin {
++namespace metadata {
++class BitExtentDefaultTypeInternal {
++ public:
++ ::google::protobuf::internal::ExplicitlyConstructed<BitExtent>
++ _instance;
++} _BitExtent_default_instance_;
++class StreamInfoDefaultTypeInternal {
++ public:
++ ::google::protobuf::internal::ExplicitlyConstructed<StreamInfo>
++ _instance;
++} _StreamInfo_default_instance_;
++class PatchHeaderDefaultTypeInternal {
++ public:
++ ::google::protobuf::internal::ExplicitlyConstructed<PatchHeader>
++ _instance;
++} _PatchHeader_default_instance_;
++} // namespace metadata
++} // namespace puffin
++namespace protobuf_puffin_2eproto {
++static void InitDefaultsBitExtent() {
++ GOOGLE_PROTOBUF_VERIFY_VERSION;
++
++ {
++ void* ptr = &::puffin::metadata::_BitExtent_default_instance_;
++ new (ptr) ::puffin::metadata::BitExtent();
++ ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
++ }
++ ::puffin::metadata::BitExtent::InitAsDefaultInstance();
++}
++
++::google::protobuf::internal::SCCInfo<0> scc_info_BitExtent =
++ {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 0, InitDefaultsBitExtent}, {}};
++
++static void InitDefaultsStreamInfo() {
++ GOOGLE_PROTOBUF_VERIFY_VERSION;
++
++ {
++ void* ptr = &::puffin::metadata::_StreamInfo_default_instance_;
++ new (ptr) ::puffin::metadata::StreamInfo();
++ ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
++ }
++ ::puffin::metadata::StreamInfo::InitAsDefaultInstance();
++}
++
++::google::protobuf::internal::SCCInfo<1> scc_info_StreamInfo =
++ {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 1, InitDefaultsStreamInfo}, {
++ &protobuf_puffin_2eproto::scc_info_BitExtent.base,}};
++
++static void InitDefaultsPatchHeader() {
++ GOOGLE_PROTOBUF_VERIFY_VERSION;
++
++ {
++ void* ptr = &::puffin::metadata::_PatchHeader_default_instance_;
++ new (ptr) ::puffin::metadata::PatchHeader();
++ ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
++ }
++ ::puffin::metadata::PatchHeader::InitAsDefaultInstance();
++}
++
++::google::protobuf::internal::SCCInfo<1> scc_info_PatchHeader =
++ {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 1, InitDefaultsPatchHeader}, {
++ &protobuf_puffin_2eproto::scc_info_StreamInfo.base,}};
++
++void InitDefaults() {
++ ::google::protobuf::internal::InitSCC(&scc_info_BitExtent.base);
++ ::google::protobuf::internal::InitSCC(&scc_info_StreamInfo.base);
++ ::google::protobuf::internal::InitSCC(&scc_info_PatchHeader.base);
++}
++
++} // namespace protobuf_puffin_2eproto
++namespace puffin {
++namespace metadata {
++
++// ===================================================================
++
++void BitExtent::InitAsDefaultInstance() {
++}
++#if !defined(_MSC_VER) || _MSC_VER >= 1900
++const int BitExtent::kOffsetFieldNumber;
++const int BitExtent::kLengthFieldNumber;
++#endif // !defined(_MSC_VER) || _MSC_VER >= 1900
++
++BitExtent::BitExtent()
++ : ::google::protobuf::MessageLite(), _internal_metadata_(NULL) {
++ ::google::protobuf::internal::InitSCC(
++ &protobuf_puffin_2eproto::scc_info_BitExtent.base);
++ SharedCtor();
++ // @@protoc_insertion_point(constructor:puffin.metadata.BitExtent)
++}
++BitExtent::BitExtent(const BitExtent& from)
++ : ::google::protobuf::MessageLite(),
++ _internal_metadata_(NULL) {
++ _internal_metadata_.MergeFrom(from._internal_metadata_);
++ ::memcpy(&offset_, &from.offset_,
++ static_cast<size_t>(reinterpret_cast<char*>(&length_) -
++ reinterpret_cast<char*>(&offset_)) + sizeof(length_));
++ // @@protoc_insertion_point(copy_constructor:puffin.metadata.BitExtent)
++}
++
++void BitExtent::SharedCtor() {
++ ::memset(&offset_, 0, static_cast<size_t>(
++ reinterpret_cast<char*>(&length_) -
++ reinterpret_cast<char*>(&offset_)) + sizeof(length_));
++}
++
++BitExtent::~BitExtent() {
++ // @@protoc_insertion_point(destructor:puffin.metadata.BitExtent)
++ SharedDtor();
++}
++
++void BitExtent::SharedDtor() {
++}
++
++void BitExtent::SetCachedSize(int size) const {
++ _cached_size_.Set(size);
++}
++const BitExtent& BitExtent::default_instance() {
++ ::google::protobuf::internal::InitSCC(&protobuf_puffin_2eproto::scc_info_BitExtent.base);
++ return *internal_default_instance();
++}
++
++
++void BitExtent::Clear() {
++// @@protoc_insertion_point(message_clear_start:puffin.metadata.BitExtent)
++ ::google::protobuf::uint32 cached_has_bits = 0;
++ // Prevent compiler warnings about cached_has_bits being unused
++ (void) cached_has_bits;
++
++ ::memset(&offset_, 0, static_cast<size_t>(
++ reinterpret_cast<char*>(&length_) -
++ reinterpret_cast<char*>(&offset_)) + sizeof(length_));
++ _internal_metadata_.Clear();
++}
++
++bool BitExtent::MergePartialFromCodedStream(
++ ::google::protobuf::io::CodedInputStream* input) {
++#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
++ ::google::protobuf::uint32 tag;
++ ::google::protobuf::internal::LiteUnknownFieldSetter unknown_fields_setter(
++ &_internal_metadata_);
++ ::google::protobuf::io::StringOutputStream unknown_fields_output(
++ unknown_fields_setter.buffer());
++ ::google::protobuf::io::CodedOutputStream unknown_fields_stream(
++ &unknown_fields_output, false);
++ // @@protoc_insertion_point(parse_start:puffin.metadata.BitExtent)
++ for (;;) {
++ ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
++ tag = p.first;
++ if (!p.second) goto handle_unusual;
++ switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
++ // uint64 offset = 1;
++ case 1: {
++ if (static_cast< ::google::protobuf::uint8>(tag) ==
++ static_cast< ::google::protobuf::uint8>(8u /* 8 & 0xFF */)) {
++
++ DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
++ ::google::protobuf::uint64, ::google::protobuf::internal::WireFormatLite::TYPE_UINT64>(
++ input, &offset_)));
++ } else {
++ goto handle_unusual;
++ }
++ break;
++ }
++
++ // uint64 length = 2;
++ case 2: {
++ if (static_cast< ::google::protobuf::uint8>(tag) ==
++ static_cast< ::google::protobuf::uint8>(16u /* 16 & 0xFF */)) {
++
++ DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
++ ::google::protobuf::uint64, ::google::protobuf::internal::WireFormatLite::TYPE_UINT64>(
++ input, &length_)));
++ } else {
++ goto handle_unusual;
++ }
++ break;
++ }
++
++ default: {
++ handle_unusual:
++ if (tag == 0) {
++ goto success;
++ }
++ DO_(::google::protobuf::internal::WireFormatLite::SkipField(
++ input, tag, &unknown_fields_stream));
++ break;
++ }
++ }
++ }
++success:
++ // @@protoc_insertion_point(parse_success:puffin.metadata.BitExtent)
++ return true;
++failure:
++ // @@protoc_insertion_point(parse_failure:puffin.metadata.BitExtent)
++ return false;
++#undef DO_
++}
++
++void BitExtent::SerializeWithCachedSizes(
++ ::google::protobuf::io::CodedOutputStream* output) const {
++ // @@protoc_insertion_point(serialize_start:puffin.metadata.BitExtent)
++ ::google::protobuf::uint32 cached_has_bits = 0;
++ (void) cached_has_bits;
++
++ // uint64 offset = 1;
++ if (this->offset() != 0) {
++ ::google::protobuf::internal::WireFormatLite::WriteUInt64(1, this->offset(), output);
++ }
++
++ // uint64 length = 2;
++ if (this->length() != 0) {
++ ::google::protobuf::internal::WireFormatLite::WriteUInt64(2, this->length(), output);
++ }
++
++ output->WriteRaw((::google::protobuf::internal::GetProto3PreserveUnknownsDefault() ? _internal_metadata_.unknown_fields() : _internal_metadata_.default_instance()).data(),
++ static_cast<int>((::google::protobuf::internal::GetProto3PreserveUnknownsDefault() ? _internal_metadata_.unknown_fields() : _internal_metadata_.default_instance()).size()));
++ // @@protoc_insertion_point(serialize_end:puffin.metadata.BitExtent)
++}
++
++size_t BitExtent::ByteSizeLong() const {
++// @@protoc_insertion_point(message_byte_size_start:puffin.metadata.BitExtent)
++ size_t total_size = 0;
++
++ total_size += (::google::protobuf::internal::GetProto3PreserveUnknownsDefault() ? _internal_metadata_.unknown_fields() : _internal_metadata_.default_instance()).size();
++
++ // uint64 offset = 1;
++ if (this->offset() != 0) {
++ total_size += 1 +
++ ::google::protobuf::internal::WireFormatLite::UInt64Size(
++ this->offset());
++ }
++
++ // uint64 length = 2;
++ if (this->length() != 0) {
++ total_size += 1 +
++ ::google::protobuf::internal::WireFormatLite::UInt64Size(
++ this->length());
++ }
++
++ int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
++ SetCachedSize(cached_size);
++ return total_size;
++}
++
++void BitExtent::CheckTypeAndMergeFrom(
++ const ::google::protobuf::MessageLite& from) {
++ MergeFrom(*::google::protobuf::down_cast<const BitExtent*>(&from));
++}
++
++void BitExtent::MergeFrom(const BitExtent& from) {
++// @@protoc_insertion_point(class_specific_merge_from_start:puffin.metadata.BitExtent)
++ GOOGLE_DCHECK_NE(&from, this);
++ _internal_metadata_.MergeFrom(from._internal_metadata_);
++ ::google::protobuf::uint32 cached_has_bits = 0;
++ (void) cached_has_bits;
++
++ if (from.offset() != 0) {
++ set_offset(from.offset());
++ }
++ if (from.length() != 0) {
++ set_length(from.length());
++ }
++}
++
++void BitExtent::CopyFrom(const BitExtent& from) {
++// @@protoc_insertion_point(class_specific_copy_from_start:puffin.metadata.BitExtent)
++ if (&from == this) return;
++ Clear();
++ MergeFrom(from);
++}
++
++bool BitExtent::IsInitialized() const {
++ return true;
++}
++
++void BitExtent::Swap(BitExtent* other) {
++ if (other == this) return;
++ InternalSwap(other);
++}
++void BitExtent::InternalSwap(BitExtent* other) {
++ using std::swap;
++ swap(offset_, other->offset_);
++ swap(length_, other->length_);
++ _internal_metadata_.Swap(&other->_internal_metadata_);
++}
++
++::std::string BitExtent::GetTypeName() const {
++ return "puffin.metadata.BitExtent";
++}
++
++
++// ===================================================================
++
++void StreamInfo::InitAsDefaultInstance() {
++}
++#if !defined(_MSC_VER) || _MSC_VER >= 1900
++const int StreamInfo::kDeflatesFieldNumber;
++const int StreamInfo::kPuffsFieldNumber;
++const int StreamInfo::kPuffLengthFieldNumber;
++#endif // !defined(_MSC_VER) || _MSC_VER >= 1900
++
++StreamInfo::StreamInfo()
++ : ::google::protobuf::MessageLite(), _internal_metadata_(NULL) {
++ ::google::protobuf::internal::InitSCC(
++ &protobuf_puffin_2eproto::scc_info_StreamInfo.base);
++ SharedCtor();
++ // @@protoc_insertion_point(constructor:puffin.metadata.StreamInfo)
++}
++StreamInfo::StreamInfo(const StreamInfo& from)
++ : ::google::protobuf::MessageLite(),
++ _internal_metadata_(NULL),
++ deflates_(from.deflates_),
++ puffs_(from.puffs_) {
++ _internal_metadata_.MergeFrom(from._internal_metadata_);
++ puff_length_ = from.puff_length_;
++ // @@protoc_insertion_point(copy_constructor:puffin.metadata.StreamInfo)
++}
++
++void StreamInfo::SharedCtor() {
++ puff_length_ = GOOGLE_ULONGLONG(0);
++}
++
++StreamInfo::~StreamInfo() {
++ // @@protoc_insertion_point(destructor:puffin.metadata.StreamInfo)
++ SharedDtor();
++}
++
++void StreamInfo::SharedDtor() {
++}
++
++void StreamInfo::SetCachedSize(int size) const {
++ _cached_size_.Set(size);
++}
++const StreamInfo& StreamInfo::default_instance() {
++ ::google::protobuf::internal::InitSCC(&protobuf_puffin_2eproto::scc_info_StreamInfo.base);
++ return *internal_default_instance();
++}
++
++
++void StreamInfo::Clear() {
++// @@protoc_insertion_point(message_clear_start:puffin.metadata.StreamInfo)
++ ::google::protobuf::uint32 cached_has_bits = 0;
++ // Prevent compiler warnings about cached_has_bits being unused
++ (void) cached_has_bits;
++
++ deflates_.Clear();
++ puffs_.Clear();
++ puff_length_ = GOOGLE_ULONGLONG(0);
++ _internal_metadata_.Clear();
++}
++
++bool StreamInfo::MergePartialFromCodedStream(
++ ::google::protobuf::io::CodedInputStream* input) {
++#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
++ ::google::protobuf::uint32 tag;
++ ::google::protobuf::internal::LiteUnknownFieldSetter unknown_fields_setter(
++ &_internal_metadata_);
++ ::google::protobuf::io::StringOutputStream unknown_fields_output(
++ unknown_fields_setter.buffer());
++ ::google::protobuf::io::CodedOutputStream unknown_fields_stream(
++ &unknown_fields_output, false);
++ // @@protoc_insertion_point(parse_start:puffin.metadata.StreamInfo)
++ for (;;) {
++ ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
++ tag = p.first;
++ if (!p.second) goto handle_unusual;
++ switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
++ // repeated .puffin.metadata.BitExtent deflates = 1;
++ case 1: {
++ if (static_cast< ::google::protobuf::uint8>(tag) ==
++ static_cast< ::google::protobuf::uint8>(10u /* 10 & 0xFF */)) {
++ DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
++ input, add_deflates()));
++ } else {
++ goto handle_unusual;
++ }
++ break;
++ }
++
++ // repeated .puffin.metadata.BitExtent puffs = 2;
++ case 2: {
++ if (static_cast< ::google::protobuf::uint8>(tag) ==
++ static_cast< ::google::protobuf::uint8>(18u /* 18 & 0xFF */)) {
++ DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
++ input, add_puffs()));
++ } else {
++ goto handle_unusual;
++ }
++ break;
++ }
++
++ // uint64 puff_length = 3;
++ case 3: {
++ if (static_cast< ::google::protobuf::uint8>(tag) ==
++ static_cast< ::google::protobuf::uint8>(24u /* 24 & 0xFF */)) {
++
++ DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
++ ::google::protobuf::uint64, ::google::protobuf::internal::WireFormatLite::TYPE_UINT64>(
++ input, &puff_length_)));
++ } else {
++ goto handle_unusual;
++ }
++ break;
++ }
++
++ default: {
++ handle_unusual:
++ if (tag == 0) {
++ goto success;
++ }
++ DO_(::google::protobuf::internal::WireFormatLite::SkipField(
++ input, tag, &unknown_fields_stream));
++ break;
++ }
++ }
++ }
++success:
++ // @@protoc_insertion_point(parse_success:puffin.metadata.StreamInfo)
++ return true;
++failure:
++ // @@protoc_insertion_point(parse_failure:puffin.metadata.StreamInfo)
++ return false;
++#undef DO_
++}
++
++void StreamInfo::SerializeWithCachedSizes(
++ ::google::protobuf::io::CodedOutputStream* output) const {
++ // @@protoc_insertion_point(serialize_start:puffin.metadata.StreamInfo)
++ ::google::protobuf::uint32 cached_has_bits = 0;
++ (void) cached_has_bits;
++
++ // repeated .puffin.metadata.BitExtent deflates = 1;
++ for (unsigned int i = 0,
++ n = static_cast<unsigned int>(this->deflates_size()); i < n; i++) {
++ ::google::protobuf::internal::WireFormatLite::WriteMessage(
++ 1,
++ this->deflates(static_cast<int>(i)),
++ output);
++ }
++
++ // repeated .puffin.metadata.BitExtent puffs = 2;
++ for (unsigned int i = 0,
++ n = static_cast<unsigned int>(this->puffs_size()); i < n; i++) {
++ ::google::protobuf::internal::WireFormatLite::WriteMessage(
++ 2,
++ this->puffs(static_cast<int>(i)),
++ output);
++ }
++
++ // uint64 puff_length = 3;
++ if (this->puff_length() != 0) {
++ ::google::protobuf::internal::WireFormatLite::WriteUInt64(3, this->puff_length(), output);
++ }
++
++ output->WriteRaw((::google::protobuf::internal::GetProto3PreserveUnknownsDefault() ? _internal_metadata_.unknown_fields() : _internal_metadata_.default_instance()).data(),
++ static_cast<int>((::google::protobuf::internal::GetProto3PreserveUnknownsDefault() ? _internal_metadata_.unknown_fields() : _internal_metadata_.default_instance()).size()));
++ // @@protoc_insertion_point(serialize_end:puffin.metadata.StreamInfo)
++}
++
++size_t StreamInfo::ByteSizeLong() const {
++// @@protoc_insertion_point(message_byte_size_start:puffin.metadata.StreamInfo)
++ size_t total_size = 0;
++
++ total_size += (::google::protobuf::internal::GetProto3PreserveUnknownsDefault() ? _internal_metadata_.unknown_fields() : _internal_metadata_.default_instance()).size();
++
++ // repeated .puffin.metadata.BitExtent deflates = 1;
++ {
++ unsigned int count = static_cast<unsigned int>(this->deflates_size());
++ total_size += 1UL * count;
++ for (unsigned int i = 0; i < count; i++) {
++ total_size +=
++ ::google::protobuf::internal::WireFormatLite::MessageSize(
++ this->deflates(static_cast<int>(i)));
++ }
++ }
++
++ // repeated .puffin.metadata.BitExtent puffs = 2;
++ {
++ unsigned int count = static_cast<unsigned int>(this->puffs_size());
++ total_size += 1UL * count;
++ for (unsigned int i = 0; i < count; i++) {
++ total_size +=
++ ::google::protobuf::internal::WireFormatLite::MessageSize(
++ this->puffs(static_cast<int>(i)));
++ }
++ }
++
++ // uint64 puff_length = 3;
++ if (this->puff_length() != 0) {
++ total_size += 1 +
++ ::google::protobuf::internal::WireFormatLite::UInt64Size(
++ this->puff_length());
++ }
++
++ int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
++ SetCachedSize(cached_size);
++ return total_size;
++}
++
++void StreamInfo::CheckTypeAndMergeFrom(
++ const ::google::protobuf::MessageLite& from) {
++ MergeFrom(*::google::protobuf::down_cast<const StreamInfo*>(&from));
++}
++
++void StreamInfo::MergeFrom(const StreamInfo& from) {
++// @@protoc_insertion_point(class_specific_merge_from_start:puffin.metadata.StreamInfo)
++ GOOGLE_DCHECK_NE(&from, this);
++ _internal_metadata_.MergeFrom(from._internal_metadata_);
++ ::google::protobuf::uint32 cached_has_bits = 0;
++ (void) cached_has_bits;
++
++ deflates_.MergeFrom(from.deflates_);
++ puffs_.MergeFrom(from.puffs_);
++ if (from.puff_length() != 0) {
++ set_puff_length(from.puff_length());
++ }
++}
++
++void StreamInfo::CopyFrom(const StreamInfo& from) {
++// @@protoc_insertion_point(class_specific_copy_from_start:puffin.metadata.StreamInfo)
++ if (&from == this) return;
++ Clear();
++ MergeFrom(from);
++}
++
++bool StreamInfo::IsInitialized() const {
++ return true;
++}
++
++void StreamInfo::Swap(StreamInfo* other) {
++ if (other == this) return;
++ InternalSwap(other);
++}
++void StreamInfo::InternalSwap(StreamInfo* other) {
++ using std::swap;
++ CastToBase(&deflates_)->InternalSwap(CastToBase(&other->deflates_));
++ CastToBase(&puffs_)->InternalSwap(CastToBase(&other->puffs_));
++ swap(puff_length_, other->puff_length_);
++ _internal_metadata_.Swap(&other->_internal_metadata_);
++}
++
++::std::string StreamInfo::GetTypeName() const {
++ return "puffin.metadata.StreamInfo";
++}
++
++
++// ===================================================================
++
++void PatchHeader::InitAsDefaultInstance() {
++ ::puffin::metadata::_PatchHeader_default_instance_._instance.get_mutable()->src_ = const_cast< ::puffin::metadata::StreamInfo*>(
++ ::puffin::metadata::StreamInfo::internal_default_instance());
++ ::puffin::metadata::_PatchHeader_default_instance_._instance.get_mutable()->dst_ = const_cast< ::puffin::metadata::StreamInfo*>(
++ ::puffin::metadata::StreamInfo::internal_default_instance());
++}
++#if !defined(_MSC_VER) || _MSC_VER >= 1900
++const int PatchHeader::kVersionFieldNumber;
++const int PatchHeader::kSrcFieldNumber;
++const int PatchHeader::kDstFieldNumber;
++#endif // !defined(_MSC_VER) || _MSC_VER >= 1900
++
++PatchHeader::PatchHeader()
++ : ::google::protobuf::MessageLite(), _internal_metadata_(NULL) {
++ ::google::protobuf::internal::InitSCC(
++ &protobuf_puffin_2eproto::scc_info_PatchHeader.base);
++ SharedCtor();
++ // @@protoc_insertion_point(constructor:puffin.metadata.PatchHeader)
++}
++PatchHeader::PatchHeader(const PatchHeader& from)
++ : ::google::protobuf::MessageLite(),
++ _internal_metadata_(NULL) {
++ _internal_metadata_.MergeFrom(from._internal_metadata_);
++ if (from.has_src()) {
++ src_ = new ::puffin::metadata::StreamInfo(*from.src_);
++ } else {
++ src_ = NULL;
++ }
++ if (from.has_dst()) {
++ dst_ = new ::puffin::metadata::StreamInfo(*from.dst_);
++ } else {
++ dst_ = NULL;
++ }
++ version_ = from.version_;
++ // @@protoc_insertion_point(copy_constructor:puffin.metadata.PatchHeader)
++}
++
++void PatchHeader::SharedCtor() {
++ ::memset(&src_, 0, static_cast<size_t>(
++ reinterpret_cast<char*>(&version_) -
++ reinterpret_cast<char*>(&src_)) + sizeof(version_));
++}
++
++PatchHeader::~PatchHeader() {
++ // @@protoc_insertion_point(destructor:puffin.metadata.PatchHeader)
++ SharedDtor();
++}
++
++void PatchHeader::SharedDtor() {
++ if (this != internal_default_instance()) delete src_;
++ if (this != internal_default_instance()) delete dst_;
++}
++
++void PatchHeader::SetCachedSize(int size) const {
++ _cached_size_.Set(size);
++}
++const PatchHeader& PatchHeader::default_instance() {
++ ::google::protobuf::internal::InitSCC(&protobuf_puffin_2eproto::scc_info_PatchHeader.base);
++ return *internal_default_instance();
++}
++
++
++void PatchHeader::Clear() {
++// @@protoc_insertion_point(message_clear_start:puffin.metadata.PatchHeader)
++ ::google::protobuf::uint32 cached_has_bits = 0;
++ // Prevent compiler warnings about cached_has_bits being unused
++ (void) cached_has_bits;
++
++ if (GetArenaNoVirtual() == NULL && src_ != NULL) {
++ delete src_;
++ }
++ src_ = NULL;
++ if (GetArenaNoVirtual() == NULL && dst_ != NULL) {
++ delete dst_;
++ }
++ dst_ = NULL;
++ version_ = 0;
++ _internal_metadata_.Clear();
++}
++
++bool PatchHeader::MergePartialFromCodedStream(
++ ::google::protobuf::io::CodedInputStream* input) {
++#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
++ ::google::protobuf::uint32 tag;
++ ::google::protobuf::internal::LiteUnknownFieldSetter unknown_fields_setter(
++ &_internal_metadata_);
++ ::google::protobuf::io::StringOutputStream unknown_fields_output(
++ unknown_fields_setter.buffer());
++ ::google::protobuf::io::CodedOutputStream unknown_fields_stream(
++ &unknown_fields_output, false);
++ // @@protoc_insertion_point(parse_start:puffin.metadata.PatchHeader)
++ for (;;) {
++ ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
++ tag = p.first;
++ if (!p.second) goto handle_unusual;
++ switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
++ // int32 version = 1;
++ case 1: {
++ if (static_cast< ::google::protobuf::uint8>(tag) ==
++ static_cast< ::google::protobuf::uint8>(8u /* 8 & 0xFF */)) {
++
++ DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
++ ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
++ input, &version_)));
++ } else {
++ goto handle_unusual;
++ }
++ break;
++ }
++
++ // .puffin.metadata.StreamInfo src = 2;
++ case 2: {
++ if (static_cast< ::google::protobuf::uint8>(tag) ==
++ static_cast< ::google::protobuf::uint8>(18u /* 18 & 0xFF */)) {
++ DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
++ input, mutable_src()));
++ } else {
++ goto handle_unusual;
++ }
++ break;
++ }
++
++ // .puffin.metadata.StreamInfo dst = 3;
++ case 3: {
++ if (static_cast< ::google::protobuf::uint8>(tag) ==
++ static_cast< ::google::protobuf::uint8>(26u /* 26 & 0xFF */)) {
++ DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
++ input, mutable_dst()));
++ } else {
++ goto handle_unusual;
++ }
++ break;
++ }
++
++ default: {
++ handle_unusual:
++ if (tag == 0) {
++ goto success;
++ }
++ DO_(::google::protobuf::internal::WireFormatLite::SkipField(
++ input, tag, &unknown_fields_stream));
++ break;
++ }
++ }
++ }
++success:
++ // @@protoc_insertion_point(parse_success:puffin.metadata.PatchHeader)
++ return true;
++failure:
++ // @@protoc_insertion_point(parse_failure:puffin.metadata.PatchHeader)
++ return false;
++#undef DO_
++}
++
++void PatchHeader::SerializeWithCachedSizes(
++ ::google::protobuf::io::CodedOutputStream* output) const {
++ // @@protoc_insertion_point(serialize_start:puffin.metadata.PatchHeader)
++ ::google::protobuf::uint32 cached_has_bits = 0;
++ (void) cached_has_bits;
++
++ // int32 version = 1;
++ if (this->version() != 0) {
++ ::google::protobuf::internal::WireFormatLite::WriteInt32(1, this->version(), output);
++ }
++
++ // .puffin.metadata.StreamInfo src = 2;
++ if (this->has_src()) {
++ ::google::protobuf::internal::WireFormatLite::WriteMessage(
++ 2, this->_internal_src(), output);
++ }
++
++ // .puffin.metadata.StreamInfo dst = 3;
++ if (this->has_dst()) {
++ ::google::protobuf::internal::WireFormatLite::WriteMessage(
++ 3, this->_internal_dst(), output);
++ }
++
++ output->WriteRaw((::google::protobuf::internal::GetProto3PreserveUnknownsDefault() ? _internal_metadata_.unknown_fields() : _internal_metadata_.default_instance()).data(),
++ static_cast<int>((::google::protobuf::internal::GetProto3PreserveUnknownsDefault() ? _internal_metadata_.unknown_fields() : _internal_metadata_.default_instance()).size()));
++ // @@protoc_insertion_point(serialize_end:puffin.metadata.PatchHeader)
++}
++
++size_t PatchHeader::ByteSizeLong() const {
++// @@protoc_insertion_point(message_byte_size_start:puffin.metadata.PatchHeader)
++ size_t total_size = 0;
++
++ total_size += (::google::protobuf::internal::GetProto3PreserveUnknownsDefault() ? _internal_metadata_.unknown_fields() : _internal_metadata_.default_instance()).size();
++
++ // .puffin.metadata.StreamInfo src = 2;
++ if (this->has_src()) {
++ total_size += 1 +
++ ::google::protobuf::internal::WireFormatLite::MessageSize(
++ *src_);
++ }
++
++ // .puffin.metadata.StreamInfo dst = 3;
++ if (this->has_dst()) {
++ total_size += 1 +
++ ::google::protobuf::internal::WireFormatLite::MessageSize(
++ *dst_);
++ }
++
++ // int32 version = 1;
++ if (this->version() != 0) {
++ total_size += 1 +
++ ::google::protobuf::internal::WireFormatLite::Int32Size(
++ this->version());
++ }
++
++ int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
++ SetCachedSize(cached_size);
++ return total_size;
++}
++
++void PatchHeader::CheckTypeAndMergeFrom(
++ const ::google::protobuf::MessageLite& from) {
++ MergeFrom(*::google::protobuf::down_cast<const PatchHeader*>(&from));
++}
++
++void PatchHeader::MergeFrom(const PatchHeader& from) {
++// @@protoc_insertion_point(class_specific_merge_from_start:puffin.metadata.PatchHeader)
++ GOOGLE_DCHECK_NE(&from, this);
++ _internal_metadata_.MergeFrom(from._internal_metadata_);
++ ::google::protobuf::uint32 cached_has_bits = 0;
++ (void) cached_has_bits;
++
++ if (from.has_src()) {
++ mutable_src()->::puffin::metadata::StreamInfo::MergeFrom(from.src());
++ }
++ if (from.has_dst()) {
++ mutable_dst()->::puffin::metadata::StreamInfo::MergeFrom(from.dst());
++ }
++ if (from.version() != 0) {
++ set_version(from.version());
++ }
++}
++
++void PatchHeader::CopyFrom(const PatchHeader& from) {
++// @@protoc_insertion_point(class_specific_copy_from_start:puffin.metadata.PatchHeader)
++ if (&from == this) return;
++ Clear();
++ MergeFrom(from);
++}
++
++bool PatchHeader::IsInitialized() const {
++ return true;
++}
++
++void PatchHeader::Swap(PatchHeader* other) {
++ if (other == this) return;
++ InternalSwap(other);
++}
++void PatchHeader::InternalSwap(PatchHeader* other) {
++ using std::swap;
++ swap(src_, other->src_);
++ swap(dst_, other->dst_);
++ swap(version_, other->version_);
++ _internal_metadata_.Swap(&other->_internal_metadata_);
++}
++
++::std::string PatchHeader::GetTypeName() const {
++ return "puffin.metadata.PatchHeader";
++}
++
++
++// @@protoc_insertion_point(namespace_scope)
++} // namespace metadata
++} // namespace puffin
++namespace google {
++namespace protobuf {
++template<> GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE ::puffin::metadata::BitExtent* Arena::CreateMaybeMessage< ::puffin::metadata::BitExtent >(Arena* arena) {
++ return Arena::CreateInternal< ::puffin::metadata::BitExtent >(arena);
++}
++template<> GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE ::puffin::metadata::StreamInfo* Arena::CreateMaybeMessage< ::puffin::metadata::StreamInfo >(Arena* arena) {
++ return Arena::CreateInternal< ::puffin::metadata::StreamInfo >(arena);
++}
++template<> GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE ::puffin::metadata::PatchHeader* Arena::CreateMaybeMessage< ::puffin::metadata::PatchHeader >(Arena* arena) {
++ return Arena::CreateInternal< ::puffin::metadata::PatchHeader >(arena);
++}
++} // namespace protobuf
++} // namespace google
++
++// @@protoc_insertion_point(global_scope)
+diff --git a/external/puffin/src/puffin.pb.h b/external/puffin/src/puffin.pb.h
+new file mode 100644
+index 0000000..074c4b6
+--- /dev/null
++++ b/src/puffin.pb.h
+@@ -0,0 +1,689 @@
++// Generated by the protocol buffer compiler. DO NOT EDIT!
++// source: puffin.proto
++
++#ifndef PROTOBUF_INCLUDED_puffin_2eproto
++#define PROTOBUF_INCLUDED_puffin_2eproto
++
++#include <string>
++
++#include <google/protobuf/stubs/common.h>
++
++#if GOOGLE_PROTOBUF_VERSION < 3006001
++#error This file was generated by a newer version of protoc which is
++#error incompatible with your Protocol Buffer headers. Please update
++#error your headers.
++#endif
++#if 3006001 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
++#error This file was generated by an older version of protoc which is
++#error incompatible with your Protocol Buffer headers. Please
++#error regenerate this file with a newer version of protoc.
++#endif
++
++#include <google/protobuf/io/coded_stream.h>
++#include <google/protobuf/arena.h>
++#include <google/protobuf/arenastring.h>
++#include <google/protobuf/generated_message_table_driven.h>
++#include <google/protobuf/generated_message_util.h>
++#include <google/protobuf/inlined_string_field.h>
++#include <google/protobuf/metadata_lite.h>
++#include <google/protobuf/message_lite.h>
++#include <google/protobuf/repeated_field.h> // IWYU pragma: export
++#include <google/protobuf/extension_set.h> // IWYU pragma: export
++// @@protoc_insertion_point(includes)
++#define PROTOBUF_INTERNAL_EXPORT_protobuf_puffin_2eproto
++
++namespace protobuf_puffin_2eproto {
++// Internal implementation detail -- do not use these members.
++struct TableStruct {
++ static const ::google::protobuf::internal::ParseTableField entries[];
++ static const ::google::protobuf::internal::AuxillaryParseTableField aux[];
++ static const ::google::protobuf::internal::ParseTable schema[3];
++ static const ::google::protobuf::internal::FieldMetadata field_metadata[];
++ static const ::google::protobuf::internal::SerializationTable serialization_table[];
++ static const ::google::protobuf::uint32 offsets[];
++};
++} // namespace protobuf_puffin_2eproto
++namespace puffin {
++namespace metadata {
++class BitExtent;
++class BitExtentDefaultTypeInternal;
++extern BitExtentDefaultTypeInternal _BitExtent_default_instance_;
++class PatchHeader;
++class PatchHeaderDefaultTypeInternal;
++extern PatchHeaderDefaultTypeInternal _PatchHeader_default_instance_;
++class StreamInfo;
++class StreamInfoDefaultTypeInternal;
++extern StreamInfoDefaultTypeInternal _StreamInfo_default_instance_;
++} // namespace metadata
++} // namespace puffin
++namespace google {
++namespace protobuf {
++template<> ::puffin::metadata::BitExtent* Arena::CreateMaybeMessage<::puffin::metadata::BitExtent>(Arena*);
++template<> ::puffin::metadata::PatchHeader* Arena::CreateMaybeMessage<::puffin::metadata::PatchHeader>(Arena*);
++template<> ::puffin::metadata::StreamInfo* Arena::CreateMaybeMessage<::puffin::metadata::StreamInfo>(Arena*);
++} // namespace protobuf
++} // namespace google
++namespace puffin {
++namespace metadata {
++
++// ===================================================================
++
++class BitExtent : public ::google::protobuf::MessageLite /* @@protoc_insertion_point(class_definition:puffin.metadata.BitExtent) */ {
++ public:
++ BitExtent();
++ virtual ~BitExtent();
++
++ BitExtent(const BitExtent& from);
++
++ inline BitExtent& operator=(const BitExtent& from) {
++ CopyFrom(from);
++ return *this;
++ }
++ #if LANG_CXX11
++ BitExtent(BitExtent&& from) noexcept
++ : BitExtent() {
++ *this = ::std::move(from);
++ }
++
++ inline BitExtent& operator=(BitExtent&& from) noexcept {
++ if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
++ if (this != &from) InternalSwap(&from);
++ } else {
++ CopyFrom(from);
++ }
++ return *this;
++ }
++ #endif
++ static const BitExtent& default_instance();
++
++ static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY
++ static inline const BitExtent* internal_default_instance() {
++ return reinterpret_cast<const BitExtent*>(
++ &_BitExtent_default_instance_);
++ }
++ static constexpr int kIndexInFileMessages =
++ 0;
++
++ void Swap(BitExtent* other);
++ friend void swap(BitExtent& a, BitExtent& b) {
++ a.Swap(&b);
++ }
++
++ // implements Message ----------------------------------------------
++
++ inline BitExtent* New() const final {
++ return CreateMaybeMessage<BitExtent>(NULL);
++ }
++
++ BitExtent* New(::google::protobuf::Arena* arena) const final {
++ return CreateMaybeMessage<BitExtent>(arena);
++ }
++ void CheckTypeAndMergeFrom(const ::google::protobuf::MessageLite& from)
++ final;
++ void CopyFrom(const BitExtent& from);
++ void MergeFrom(const BitExtent& from);
++ void Clear() final;
++ bool IsInitialized() const final;
++
++ size_t ByteSizeLong() const final;
++ bool MergePartialFromCodedStream(
++ ::google::protobuf::io::CodedInputStream* input) final;
++ void SerializeWithCachedSizes(
++ ::google::protobuf::io::CodedOutputStream* output) const final;
++ void DiscardUnknownFields();
++ int GetCachedSize() const final { return _cached_size_.Get(); }
++
++ private:
++ void SharedCtor();
++ void SharedDtor();
++ void SetCachedSize(int size) const;
++ void InternalSwap(BitExtent* other);
++ private:
++ inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
++ return NULL;
++ }
++ inline void* MaybeArenaPtr() const {
++ return NULL;
++ }
++ public:
++
++ ::std::string GetTypeName() const final;
++
++ // nested types ----------------------------------------------------
++
++ // accessors -------------------------------------------------------
++
++ // uint64 offset = 1;
++ void clear_offset();
++ static const int kOffsetFieldNumber = 1;
++ ::google::protobuf::uint64 offset() const;
++ void set_offset(::google::protobuf::uint64 value);
++
++ // uint64 length = 2;
++ void clear_length();
++ static const int kLengthFieldNumber = 2;
++ ::google::protobuf::uint64 length() const;
++ void set_length(::google::protobuf::uint64 value);
++
++ // @@protoc_insertion_point(class_scope:puffin.metadata.BitExtent)
++ private:
++
++ ::google::protobuf::internal::InternalMetadataWithArenaLite _internal_metadata_;
++ ::google::protobuf::uint64 offset_;
++ ::google::protobuf::uint64 length_;
++ mutable ::google::protobuf::internal::CachedSize _cached_size_;
++ friend struct ::protobuf_puffin_2eproto::TableStruct;
++};
++// -------------------------------------------------------------------
++
++class StreamInfo : public ::google::protobuf::MessageLite /* @@protoc_insertion_point(class_definition:puffin.metadata.StreamInfo) */ {
++ public:
++ StreamInfo();
++ virtual ~StreamInfo();
++
++ StreamInfo(const StreamInfo& from);
++
++ inline StreamInfo& operator=(const StreamInfo& from) {
++ CopyFrom(from);
++ return *this;
++ }
++ #if LANG_CXX11
++ StreamInfo(StreamInfo&& from) noexcept
++ : StreamInfo() {
++ *this = ::std::move(from);
++ }
++
++ inline StreamInfo& operator=(StreamInfo&& from) noexcept {
++ if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
++ if (this != &from) InternalSwap(&from);
++ } else {
++ CopyFrom(from);
++ }
++ return *this;
++ }
++ #endif
++ static const StreamInfo& default_instance();
++
++ static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY
++ static inline const StreamInfo* internal_default_instance() {
++ return reinterpret_cast<const StreamInfo*>(
++ &_StreamInfo_default_instance_);
++ }
++ static constexpr int kIndexInFileMessages =
++ 1;
++
++ void Swap(StreamInfo* other);
++ friend void swap(StreamInfo& a, StreamInfo& b) {
++ a.Swap(&b);
++ }
++
++ // implements Message ----------------------------------------------
++
++ inline StreamInfo* New() const final {
++ return CreateMaybeMessage<StreamInfo>(NULL);
++ }
++
++ StreamInfo* New(::google::protobuf::Arena* arena) const final {
++ return CreateMaybeMessage<StreamInfo>(arena);
++ }
++ void CheckTypeAndMergeFrom(const ::google::protobuf::MessageLite& from)
++ final;
++ void CopyFrom(const StreamInfo& from);
++ void MergeFrom(const StreamInfo& from);
++ void Clear() final;
++ bool IsInitialized() const final;
++
++ size_t ByteSizeLong() const final;
++ bool MergePartialFromCodedStream(
++ ::google::protobuf::io::CodedInputStream* input) final;
++ void SerializeWithCachedSizes(
++ ::google::protobuf::io::CodedOutputStream* output) const final;
++ void DiscardUnknownFields();
++ int GetCachedSize() const final { return _cached_size_.Get(); }
++
++ private:
++ void SharedCtor();
++ void SharedDtor();
++ void SetCachedSize(int size) const;
++ void InternalSwap(StreamInfo* other);
++ private:
++ inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
++ return NULL;
++ }
++ inline void* MaybeArenaPtr() const {
++ return NULL;
++ }
++ public:
++
++ ::std::string GetTypeName() const final;
++
++ // nested types ----------------------------------------------------
++
++ // accessors -------------------------------------------------------
++
++ // repeated .puffin.metadata.BitExtent deflates = 1;
++ int deflates_size() const;
++ void clear_deflates();
++ static const int kDeflatesFieldNumber = 1;
++ ::puffin::metadata::BitExtent* mutable_deflates(int index);
++ ::google::protobuf::RepeatedPtrField< ::puffin::metadata::BitExtent >*
++ mutable_deflates();
++ const ::puffin::metadata::BitExtent& deflates(int index) const;
++ ::puffin::metadata::BitExtent* add_deflates();
++ const ::google::protobuf::RepeatedPtrField< ::puffin::metadata::BitExtent >&
++ deflates() const;
++
++ // repeated .puffin.metadata.BitExtent puffs = 2;
++ int puffs_size() const;
++ void clear_puffs();
++ static const int kPuffsFieldNumber = 2;
++ ::puffin::metadata::BitExtent* mutable_puffs(int index);
++ ::google::protobuf::RepeatedPtrField< ::puffin::metadata::BitExtent >*
++ mutable_puffs();
++ const ::puffin::metadata::BitExtent& puffs(int index) const;
++ ::puffin::metadata::BitExtent* add_puffs();
++ const ::google::protobuf::RepeatedPtrField< ::puffin::metadata::BitExtent >&
++ puffs() const;
++
++ // uint64 puff_length = 3;
++ void clear_puff_length();
++ static const int kPuffLengthFieldNumber = 3;
++ ::google::protobuf::uint64 puff_length() const;
++ void set_puff_length(::google::protobuf::uint64 value);
++
++ // @@protoc_insertion_point(class_scope:puffin.metadata.StreamInfo)
++ private:
++
++ ::google::protobuf::internal::InternalMetadataWithArenaLite _internal_metadata_;
++ ::google::protobuf::RepeatedPtrField< ::puffin::metadata::BitExtent > deflates_;
++ ::google::protobuf::RepeatedPtrField< ::puffin::metadata::BitExtent > puffs_;
++ ::google::protobuf::uint64 puff_length_;
++ mutable ::google::protobuf::internal::CachedSize _cached_size_;
++ friend struct ::protobuf_puffin_2eproto::TableStruct;
++};
++// -------------------------------------------------------------------
++
++class PatchHeader : public ::google::protobuf::MessageLite /* @@protoc_insertion_point(class_definition:puffin.metadata.PatchHeader) */ {
++ public:
++ PatchHeader();
++ virtual ~PatchHeader();
++
++ PatchHeader(const PatchHeader& from);
++
++ inline PatchHeader& operator=(const PatchHeader& from) {
++ CopyFrom(from);
++ return *this;
++ }
++ #if LANG_CXX11
++ PatchHeader(PatchHeader&& from) noexcept
++ : PatchHeader() {
++ *this = ::std::move(from);
++ }
++
++ inline PatchHeader& operator=(PatchHeader&& from) noexcept {
++ if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
++ if (this != &from) InternalSwap(&from);
++ } else {
++ CopyFrom(from);
++ }
++ return *this;
++ }
++ #endif
++ static const PatchHeader& default_instance();
++
++ static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY
++ static inline const PatchHeader* internal_default_instance() {
++ return reinterpret_cast<const PatchHeader*>(
++ &_PatchHeader_default_instance_);
++ }
++ static constexpr int kIndexInFileMessages =
++ 2;
++
++ void Swap(PatchHeader* other);
++ friend void swap(PatchHeader& a, PatchHeader& b) {
++ a.Swap(&b);
++ }
++
++ // implements Message ----------------------------------------------
++
++ inline PatchHeader* New() const final {
++ return CreateMaybeMessage<PatchHeader>(NULL);
++ }
++
++ PatchHeader* New(::google::protobuf::Arena* arena) const final {
++ return CreateMaybeMessage<PatchHeader>(arena);
++ }
++ void CheckTypeAndMergeFrom(const ::google::protobuf::MessageLite& from)
++ final;
++ void CopyFrom(const PatchHeader& from);
++ void MergeFrom(const PatchHeader& from);
++ void Clear() final;
++ bool IsInitialized() const final;
++
++ size_t ByteSizeLong() const final;
++ bool MergePartialFromCodedStream(
++ ::google::protobuf::io::CodedInputStream* input) final;
++ void SerializeWithCachedSizes(
++ ::google::protobuf::io::CodedOutputStream* output) const final;
++ void DiscardUnknownFields();
++ int GetCachedSize() const final { return _cached_size_.Get(); }
++
++ private:
++ void SharedCtor();
++ void SharedDtor();
++ void SetCachedSize(int size) const;
++ void InternalSwap(PatchHeader* other);
++ private:
++ inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
++ return NULL;
++ }
++ inline void* MaybeArenaPtr() const {
++ return NULL;
++ }
++ public:
++
++ ::std::string GetTypeName() const final;
++
++ // nested types ----------------------------------------------------
++
++ // accessors -------------------------------------------------------
++
++ // .puffin.metadata.StreamInfo src = 2;
++ bool has_src() const;
++ void clear_src();
++ static const int kSrcFieldNumber = 2;
++ private:
++ const ::puffin::metadata::StreamInfo& _internal_src() const;
++ public:
++ const ::puffin::metadata::StreamInfo& src() const;
++ ::puffin::metadata::StreamInfo* release_src();
++ ::puffin::metadata::StreamInfo* mutable_src();
++ void set_allocated_src(::puffin::metadata::StreamInfo* src);
++
++ // .puffin.metadata.StreamInfo dst = 3;
++ bool has_dst() const;
++ void clear_dst();
++ static const int kDstFieldNumber = 3;
++ private:
++ const ::puffin::metadata::StreamInfo& _internal_dst() const;
++ public:
++ const ::puffin::metadata::StreamInfo& dst() const;
++ ::puffin::metadata::StreamInfo* release_dst();
++ ::puffin::metadata::StreamInfo* mutable_dst();
++ void set_allocated_dst(::puffin::metadata::StreamInfo* dst);
++
++ // int32 version = 1;
++ void clear_version();
++ static const int kVersionFieldNumber = 1;
++ ::google::protobuf::int32 version() const;
++ void set_version(::google::protobuf::int32 value);
++
++ // @@protoc_insertion_point(class_scope:puffin.metadata.PatchHeader)
++ private:
++
++ ::google::protobuf::internal::InternalMetadataWithArenaLite _internal_metadata_;
++ ::puffin::metadata::StreamInfo* src_;
++ ::puffin::metadata::StreamInfo* dst_;
++ ::google::protobuf::int32 version_;
++ mutable ::google::protobuf::internal::CachedSize _cached_size_;
++ friend struct ::protobuf_puffin_2eproto::TableStruct;
++};
++// ===================================================================
++
++
++// ===================================================================
++
++#ifdef __GNUC__
++ #pragma GCC diagnostic push
++ #pragma GCC diagnostic ignored "-Wstrict-aliasing"
++#endif // __GNUC__
++// BitExtent
++
++// uint64 offset = 1;
++inline void BitExtent::clear_offset() {
++ offset_ = GOOGLE_ULONGLONG(0);
++}
++inline ::google::protobuf::uint64 BitExtent::offset() const {
++ // @@protoc_insertion_point(field_get:puffin.metadata.BitExtent.offset)
++ return offset_;
++}
++inline void BitExtent::set_offset(::google::protobuf::uint64 value) {
++
++ offset_ = value;
++ // @@protoc_insertion_point(field_set:puffin.metadata.BitExtent.offset)
++}
++
++// uint64 length = 2;
++inline void BitExtent::clear_length() {
++ length_ = GOOGLE_ULONGLONG(0);
++}
++inline ::google::protobuf::uint64 BitExtent::length() const {
++ // @@protoc_insertion_point(field_get:puffin.metadata.BitExtent.length)
++ return length_;
++}
++inline void BitExtent::set_length(::google::protobuf::uint64 value) {
++
++ length_ = value;
++ // @@protoc_insertion_point(field_set:puffin.metadata.BitExtent.length)
++}
++
++// -------------------------------------------------------------------
++
++// StreamInfo
++
++// repeated .puffin.metadata.BitExtent deflates = 1;
++inline int StreamInfo::deflates_size() const {
++ return deflates_.size();
++}
++inline void StreamInfo::clear_deflates() {
++ deflates_.Clear();
++}
++inline ::puffin::metadata::BitExtent* StreamInfo::mutable_deflates(int index) {
++ // @@protoc_insertion_point(field_mutable:puffin.metadata.StreamInfo.deflates)
++ return deflates_.Mutable(index);
++}
++inline ::google::protobuf::RepeatedPtrField< ::puffin::metadata::BitExtent >*
++StreamInfo::mutable_deflates() {
++ // @@protoc_insertion_point(field_mutable_list:puffin.metadata.StreamInfo.deflates)
++ return &deflates_;
++}
++inline const ::puffin::metadata::BitExtent& StreamInfo::deflates(int index) const {
++ // @@protoc_insertion_point(field_get:puffin.metadata.StreamInfo.deflates)
++ return deflates_.Get(index);
++}
++inline ::puffin::metadata::BitExtent* StreamInfo::add_deflates() {
++ // @@protoc_insertion_point(field_add:puffin.metadata.StreamInfo.deflates)
++ return deflates_.Add();
++}
++inline const ::google::protobuf::RepeatedPtrField< ::puffin::metadata::BitExtent >&
++StreamInfo::deflates() const {
++ // @@protoc_insertion_point(field_list:puffin.metadata.StreamInfo.deflates)
++ return deflates_;
++}
++
++// repeated .puffin.metadata.BitExtent puffs = 2;
++inline int StreamInfo::puffs_size() const {
++ return puffs_.size();
++}
++inline void StreamInfo::clear_puffs() {
++ puffs_.Clear();
++}
++inline ::puffin::metadata::BitExtent* StreamInfo::mutable_puffs(int index) {
++ // @@protoc_insertion_point(field_mutable:puffin.metadata.StreamInfo.puffs)
++ return puffs_.Mutable(index);
++}
++inline ::google::protobuf::RepeatedPtrField< ::puffin::metadata::BitExtent >*
++StreamInfo::mutable_puffs() {
++ // @@protoc_insertion_point(field_mutable_list:puffin.metadata.StreamInfo.puffs)
++ return &puffs_;
++}
++inline const ::puffin::metadata::BitExtent& StreamInfo::puffs(int index) const {
++ // @@protoc_insertion_point(field_get:puffin.metadata.StreamInfo.puffs)
++ return puffs_.Get(index);
++}
++inline ::puffin::metadata::BitExtent* StreamInfo::add_puffs() {
++ // @@protoc_insertion_point(field_add:puffin.metadata.StreamInfo.puffs)
++ return puffs_.Add();
++}
++inline const ::google::protobuf::RepeatedPtrField< ::puffin::metadata::BitExtent >&
++StreamInfo::puffs() const {
++ // @@protoc_insertion_point(field_list:puffin.metadata.StreamInfo.puffs)
++ return puffs_;
++}
++
++// uint64 puff_length = 3;
++inline void StreamInfo::clear_puff_length() {
++ puff_length_ = GOOGLE_ULONGLONG(0);
++}
++inline ::google::protobuf::uint64 StreamInfo::puff_length() const {
++ // @@protoc_insertion_point(field_get:puffin.metadata.StreamInfo.puff_length)
++ return puff_length_;
++}
++inline void StreamInfo::set_puff_length(::google::protobuf::uint64 value) {
++
++ puff_length_ = value;
++ // @@protoc_insertion_point(field_set:puffin.metadata.StreamInfo.puff_length)
++}
++
++// -------------------------------------------------------------------
++
++// PatchHeader
++
++// int32 version = 1;
++inline void PatchHeader::clear_version() {
++ version_ = 0;
++}
++inline ::google::protobuf::int32 PatchHeader::version() const {
++ // @@protoc_insertion_point(field_get:puffin.metadata.PatchHeader.version)
++ return version_;
++}
++inline void PatchHeader::set_version(::google::protobuf::int32 value) {
++
++ version_ = value;
++ // @@protoc_insertion_point(field_set:puffin.metadata.PatchHeader.version)
++}
++
++// .puffin.metadata.StreamInfo src = 2;
++inline bool PatchHeader::has_src() const {
++ return this != internal_default_instance() && src_ != NULL;
++}
++inline void PatchHeader::clear_src() {
++ if (GetArenaNoVirtual() == NULL && src_ != NULL) {
++ delete src_;
++ }
++ src_ = NULL;
++}
++inline const ::puffin::metadata::StreamInfo& PatchHeader::_internal_src() const {
++ return *src_;
++}
++inline const ::puffin::metadata::StreamInfo& PatchHeader::src() const {
++ const ::puffin::metadata::StreamInfo* p = src_;
++ // @@protoc_insertion_point(field_get:puffin.metadata.PatchHeader.src)
++ return p != NULL ? *p : *reinterpret_cast<const ::puffin::metadata::StreamInfo*>(
++ &::puffin::metadata::_StreamInfo_default_instance_);
++}
++inline ::puffin::metadata::StreamInfo* PatchHeader::release_src() {
++ // @@protoc_insertion_point(field_release:puffin.metadata.PatchHeader.src)
++
++ ::puffin::metadata::StreamInfo* temp = src_;
++ src_ = NULL;
++ return temp;
++}
++inline ::puffin::metadata::StreamInfo* PatchHeader::mutable_src() {
++
++ if (src_ == NULL) {
++ auto* p = CreateMaybeMessage<::puffin::metadata::StreamInfo>(GetArenaNoVirtual());
++ src_ = p;
++ }
++ // @@protoc_insertion_point(field_mutable:puffin.metadata.PatchHeader.src)
++ return src_;
++}
++inline void PatchHeader::set_allocated_src(::puffin::metadata::StreamInfo* src) {
++ ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();
++ if (message_arena == NULL) {
++ delete src_;
++ }
++ if (src) {
++ ::google::protobuf::Arena* submessage_arena = NULL;
++ if (message_arena != submessage_arena) {
++ src = ::google::protobuf::internal::GetOwnedMessage(
++ message_arena, src, submessage_arena);
++ }
++
++ } else {
++
++ }
++ src_ = src;
++ // @@protoc_insertion_point(field_set_allocated:puffin.metadata.PatchHeader.src)
++}
++
++// .puffin.metadata.StreamInfo dst = 3;
++inline bool PatchHeader::has_dst() const {
++ return this != internal_default_instance() && dst_ != NULL;
++}
++inline void PatchHeader::clear_dst() {
++ if (GetArenaNoVirtual() == NULL && dst_ != NULL) {
++ delete dst_;
++ }
++ dst_ = NULL;
++}
++inline const ::puffin::metadata::StreamInfo& PatchHeader::_internal_dst() const {
++ return *dst_;
++}
++inline const ::puffin::metadata::StreamInfo& PatchHeader::dst() const {
++ const ::puffin::metadata::StreamInfo* p = dst_;
++ // @@protoc_insertion_point(field_get:puffin.metadata.PatchHeader.dst)
++ return p != NULL ? *p : *reinterpret_cast<const ::puffin::metadata::StreamInfo*>(
++ &::puffin::metadata::_StreamInfo_default_instance_);
++}
++inline ::puffin::metadata::StreamInfo* PatchHeader::release_dst() {
++ // @@protoc_insertion_point(field_release:puffin.metadata.PatchHeader.dst)
++
++ ::puffin::metadata::StreamInfo* temp = dst_;
++ dst_ = NULL;
++ return temp;
++}
++inline ::puffin::metadata::StreamInfo* PatchHeader::mutable_dst() {
++
++ if (dst_ == NULL) {
++ auto* p = CreateMaybeMessage<::puffin::metadata::StreamInfo>(GetArenaNoVirtual());
++ dst_ = p;
++ }
++ // @@protoc_insertion_point(field_mutable:puffin.metadata.PatchHeader.dst)
++ return dst_;
++}
++inline void PatchHeader::set_allocated_dst(::puffin::metadata::StreamInfo* dst) {
++ ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();
++ if (message_arena == NULL) {
++ delete dst_;
++ }
++ if (dst) {
++ ::google::protobuf::Arena* submessage_arena = NULL;
++ if (message_arena != submessage_arena) {
++ dst = ::google::protobuf::internal::GetOwnedMessage(
++ message_arena, dst, submessage_arena);
++ }
++
++ } else {
++
++ }
++ dst_ = dst;
++ // @@protoc_insertion_point(field_set_allocated:puffin.metadata.PatchHeader.dst)
++}
++
++#ifdef __GNUC__
++ #pragma GCC diagnostic pop
++#endif // __GNUC__
++// -------------------------------------------------------------------
++
++// -------------------------------------------------------------------
++
++
++// @@protoc_insertion_point(namespace_scope)
++
++} // namespace metadata
++} // namespace puffin
++
++// @@protoc_insertion_point(global_scope)
++
++#endif // PROTOBUF_INCLUDED_puffin_2eproto
+diff --git a/external/puffin/src/puffpatch.cc b/external/puffin/src/puffpatch.cc
+index 185b1dd..a9114fd 100644
+--- a/external/puffin/src/puffpatch.cc
++++ b/external/puffin/src/puffpatch.cc
+@@ -135,11 +135,11 @@ bool PuffPatch(UniqueStreamPtr src,
+ const uint8_t* patch,
+ size_t patch_length,
+ size_t max_cache_size) {
+- size_t bsdiff_patch_offset; // bsdiff offset in |patch|.
++ size_t bsdiff_patch_offset = 0; // bsdiff offset in |patch|.
+ size_t bsdiff_patch_size = 0;
+ vector<BitExtent> src_deflates, dst_deflates;
+ vector<ByteExtent> src_puffs, dst_puffs;
+- uint64_t src_puff_size, dst_puff_size;
++ uint64_t src_puff_size, dst_puff_size = 0;
+
+ // Decode the patch and get the bsdiff_patch.
+ TEST_AND_RETURN_FALSE(DecodePatch(patch, patch_length, &bsdiff_patch_offset,
+--
+2.6.4
+
diff --git a/meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/platform-libs-updateengine.bb b/meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/platform-libs-updateengine.bb
new file mode 100644
index 0000000..562b94a
--- /dev/null
+++ b/meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/platform-libs-updateengine.bb
@@ -0,0 +1,70 @@
+inherit autotools
+DESCRIPTION = "Android platform libraries"
+LICENSE = "Apache-2.0"
+LIC_FILES_CHKSUM = " \
+ file://system/core/NOTICE;md5=c1a3ff0b97f199c7ebcfdd4d3fed238e \
+ "
+
+SRC_URI = " \
+ git://android.googlesource.com/platform/external/brotli;name=platform/external/brotli;destsuffix=platform/external/brotli/ \
+ git://android.googlesource.com/platform/external/bsdiff;name=platform/external/bsdiff;destsuffix=platform/external/bsdiff/ \
+ git://android.googlesource.com/platform/external/puffin;name=platform/external/puffin;destsuffix=platform/external/puffin/ \
+ git://android.googlesource.com/platform/external/libevent;name=platform/external/libevent;destsuffix=platform/external/libevent/ \
+ git://android.googlesource.com/platform/external/libdivsufsort;name=platform/external/libdivsufsort;destsuffix=platform/external/libdivsufsort/ \
+ git://android.googlesource.com/platform/external/libbrillo;name=platform/external/libbrillo;destsuffix=platform/external/libbrillo/ \
+ git://android.googlesource.com/platform/external/libchrome;name=platform/external/libchrome;destsuffix=platform/external/libchrome/ \
+ git://android.googlesource.com/platform/external/modp_b64;name=platform/external/modp_b64;destsuffix=platform/external/modp_b64/ \
+ git://android.googlesource.com/platform/external/xz-embedded;name=platform/external/xz-embedded;destsuffix=platform/external/xz-embedded/ \
+ git://android.googlesource.com/platform/external/cros/system_api;name=platform/external/cros/system_api;destsuffix=platform/external/cros/system_api/ \
+ git://android.googlesource.com/platform/system/core;name=platform/system/core;destsuffix=platform/system/core/ \
+ file://base.patch \
+ file://libchrome.patch \
+ file://fstab.patch \
+ file://puffin.patch \
+ file://libevent.patch \
+ file://libbrillo.patch \
+ file://file_stream.patch \
+"
+
+SRCREV_platform/external/brotli = "5ccabc48199cb108fd914222cd6bdbe12c7e15e6"
+SRCREV_platform/external/bsdiff = "f0c8211af44d092cf6cc816b1e9af72f14fe80f6"
+SRCREV_platform/external/puffin = "7c492ae6e97dadf21d9282e26711d318ccddfc9b"
+SRCREV_platform/external/libevent = "becbc79be28cd4f92d14c3f395d562995fc73bf9"
+SRCREV_platform/external/libdivsufsort = "fcee868119b5eac60a8cd9fc9ddebb9627ffd172"
+SRCREV_platform/external/libbrillo = "11469312f6dce4ee8a4b98d33a36a0814b7f77c2"
+SRCREV_platform/external/libchrome = "b6fcee758cbc64842e10cb155780818aaad02420"
+SRCREV_platform/external/modp_b64 = "6f11b5c9b4ffb38dc9375f3cf344da4300a2741a"
+SRCREV_platform/external/xz-embedded = "180f9115008b00e7c1a2b35317f2bca709fce8a1"
+SRCREV_platform/external/cros/system_api = "b48922224f13c7323a389cc8b2585d43dc1ba724"
+SRCREV_platform/system/core = "f0c6e2494ebb7fdbb95494fc4e461542e02bdfeb"
+
+FILESEXTRAPATHS_prepend := "${THISDIR}:"
+
+DEPENDS += "openssl-native openssl gtest bzip2 glog protobuf platform-libs-common ${@bb.utils.contains("BOOTDEV_TYPE", "nand", "nandapi", "", d)}"
+
+S = "${WORKDIR}/platform"
+
+LDFLAGS += "-lcrypto -lpthread -lglog -lbase"
+
+SECURITY_CFLAGS=""
+
+do_configure_prepend() {
+ install -m 0755 ${TOPDIR}/../meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/files/makefiles/platform/Makefile.am ${WORKDIR}/platform/Makefile.am
+ install -m 0755 ${TOPDIR}/../meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/files/makefiles/platform/configure.ac ${WORKDIR}/platform/configure.ac
+ install -m 0755 ${TOPDIR}/../meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/files/makefiles/platform/system/core/fs_mgr/Makefile.am ${WORKDIR}/platform/system/core/fs_mgr/Makefile.am
+ install -m 0755 ${TOPDIR}/../meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/files/makefiles/platform/system/core/fs_mgr/include_fstab/Makefile.am ${WORKDIR}/platform/system/core/fs_mgr/include_fstab/Makefile.am
+ install -m 0755 ${TOPDIR}/../meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/files/makefiles/platform/external/modp_b64/Makefile.am ${WORKDIR}/platform/external/modp_b64/Makefile.am
+ install -m 0755 ${TOPDIR}/../meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/files/makefiles/platform/external/libbrillo/Makefile.am ${WORKDIR}/platform/external/libbrillo/Makefile.am
+ install -m 0755 ${TOPDIR}/../meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/files/makefiles/platform/external/libchrome/Makefile.am ${WORKDIR}/platform/external/libchrome/Makefile.am
+ install -m 0755 ${TOPDIR}/../meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/files/makefiles/platform/external/libevent/Makefile.am ${WORKDIR}/platform/external/libevent/Makefile.am
+ install -m 0755 ${TOPDIR}/../meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/files/makefiles/platform/external/cros/system_api/dbus/Makefile.am ${WORKDIR}/platform/external/cros/system_api/dbus/Makefile.am
+ install -m 0755 ${TOPDIR}/../meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/files/makefiles/platform/external/xz-embedded/Makefile.am ${WORKDIR}/platform/external/xz-embedded/Makefile.am
+ install -m 0755 ${TOPDIR}/../meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/files/makefiles/platform/external/xz-embedded/linux/include/linux/Makefile.am ${WORKDIR}/platform/external/xz-embedded/linux/include/linux/Makefile.am
+ install -m 0755 ${TOPDIR}/../meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/files/makefiles/platform/external/bsdiff/Makefile.am ${WORKDIR}/platform/external/bsdiff/Makefile.am
+ install -m 0755 ${TOPDIR}/../meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/files/makefiles/platform/external/bsdiff/include/Makefile.am ${WORKDIR}/platform/external/bsdiff/include/Makefile.am
+ install -m 0755 ${TOPDIR}/../meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/files/makefiles/platform/external/brotli/Makefile.am ${WORKDIR}/platform/external/brotli/Makefile.am
+ install -m 0755 ${TOPDIR}/../meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/files/makefiles/platform/external/puffin/src/include/Makefile.am ${WORKDIR}/platform/external/puffin/src/include/Makefile.am
+ install -m 0755 ${TOPDIR}/../meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/files/makefiles/platform/external/puffin/Makefile.am ${WORKDIR}/platform/external/puffin/Makefile.am
+ install -m 0755 ${TOPDIR}/../meta/meta-mediatek/recipes-support/platform-libs-for-updateengine/files/makefiles/platform/external/libdivsufsort/Makefile.am ${WORKDIR}/platform/external/libdivsufsort/Makefile.am
+}
+
diff --git a/meta/meta-mediatek/recipes-support/softhsm-init/files/softhsm-init.service b/meta/meta-mediatek/recipes-support/softhsm-init/files/softhsm-init.service
new file mode 100644
index 0000000..53d693e
--- /dev/null
+++ b/meta/meta-mediatek/recipes-support/softhsm-init/files/softhsm-init.service
@@ -0,0 +1,11 @@
+[Unit]
+Description=SofthsmInitScript
+RequiresMountsFor=#SOFTHSM_DATA_MOUNT_POINT#
+
+[Service]
+ExecStart=/etc/softhsm-init.sh
+Type=simple
+
+[Install]
+Alias=SofthsmInitScript
+WantedBy=multi-user.target
\ No newline at end of file
diff --git a/meta/meta-mediatek/recipes-support/softhsm-init/files/softhsm-init.sh b/meta/meta-mediatek/recipes-support/softhsm-init/files/softhsm-init.sh
new file mode 100644
index 0000000..4fdf411
--- /dev/null
+++ b/meta/meta-mediatek/recipes-support/softhsm-init/files/softhsm-init.sh
@@ -0,0 +1,12 @@
+#!/bin/sh
+#
+# @author
+# @brief generate the top index for each module doc
+
+if [ -d "#SOFTHSM_DATA_TOKEN_DIR#" ]; then
+ exit 0
+fi
+
+mkdir -p #SOFTHSM_DATA_TOKEN_DIR#
+
+softhsm2-util --init-token --free --label \"#SOFTHSM_DEFAULT_TOKEN_LABEL#\" --pin #SOFTHSM_DEFAULT_TOKEN_PIN# --so-pin #SOFTHSM_DEFAULT_TOKEN_SO_PIN#
\ No newline at end of file
diff --git a/meta/meta-mediatek/recipes-support/softhsm-init/softhsm-init.bb b/meta/meta-mediatek/recipes-support/softhsm-init/softhsm-init.bb
new file mode 100644
index 0000000..d83a056
--- /dev/null
+++ b/meta/meta-mediatek/recipes-support/softhsm-init/softhsm-init.bb
@@ -0,0 +1,45 @@
+inherit workonsrc
+inherit pkgconfig
+inherit systemd
+
+DESCRIPTION = "SoftHSM Init"
+LICENSE = "MediaTekProprietary"
+LIC_FILES_CHKSUM = "file://COPYING;md5=d7810fab7487fb0aad327b76f1be7cd7"
+APPS_SRC = "${TOPDIR}/../meta/meta-mediatek/recipes-support/softhsm-init"
+WORKONSRC = "${APPS_SRC}"
+
+#####Customization Start#####
+SOFTHSM_DATA_MOUNT_POINT = "/data"
+SOFTHSM_DATA_TOKEN_DIR = "/data/softhsm"
+SOFTHSM_DEFAULT_TOKEN_LABEL = "8516softhsm"
+SOFTHSM_DEFAULT_TOKEN_PIN = "85168516"
+SOFTHSM_DEFAULT_TOKEN_SO_PIN = "85168516"
+#####Customization End#####
+
+SYSTEMD_PACKAGES = "${PN}"
+SYSTEMD_SERVICE_${PN} = "softhsm-init.service"
+FILES_${PN} += "${systemd_unitdir}/system/softhsm-init.service"
+FILES_${PN} += "etc/softhsm-init.sh"
+FILES_${PN} += "etc/softhsm2.conf"
+
+do_install() {
+ install -d ${D}/etc
+ install -m 755 ${S}files/softhsm-init.sh ${D}/etc/softhsm-init.sh
+
+ install -d ${D}${systemd_system_unitdir}
+ install -m 0755 ${S}files/softhsm-init.service ${D}${systemd_system_unitdir}
+
+ sed -e 's%#SOFTHSM_DATA_MOUNT_POINT#%${SOFTHSM_DATA_MOUNT_POINT}%g' \
+ -i ${D}${systemd_system_unitdir}/softhsm-init.service
+
+ sed -e 's%#SOFTHSM_DATA_TOKEN_DIR#%${SOFTHSM_DATA_TOKEN_DIR}%g' \
+ -e 's%#SOFTHSM_DEFAULT_TOKEN_LABEL#%${SOFTHSM_DEFAULT_TOKEN_LABEL}%g' \
+ -e 's%#SOFTHSM_DEFAULT_TOKEN_PIN#%${SOFTHSM_DEFAULT_TOKEN_PIN}%g' \
+ -e 's%#SOFTHSM_DEFAULT_TOKEN_SO_PIN#%${SOFTHSM_DEFAULT_TOKEN_SO_PIN}%g' \
+ -i ${D}/etc/softhsm-init.sh
+
+ echo "objectstore.backend = file" > ${D}/etc/softhsm2.conf
+ echo "directories.tokendir = ${SOFTHSM_DATA_TOKEN_DIR}" >> ${D}/etc/softhsm2.conf
+}
+
+
diff --git a/meta/meta-mediatek/recipes-support/update-engine-sideload/files/buildinfo.sh b/meta/meta-mediatek/recipes-support/update-engine-sideload/files/buildinfo.sh
new file mode 100644
index 0000000..76f91a2
--- /dev/null
+++ b/meta/meta-mediatek/recipes-support/update-engine-sideload/files/buildinfo.sh
@@ -0,0 +1,9 @@
+#!/bin/bash
+
+echo "ro.build.version.sdk=28"
+echo "ro.build.version.security_patch=2019-01-05"
+echo "ro.build.version.incremental=eng.mtk941.20190311.151249"
+echo "ro.product.device=mt2712"
+echo "ro.build.fingerprint=mediatek/car_mt2712/mt2712:9/PPR1.181005.003/mtk9412903120944:userdebug/test-keys"
+echo "ro.build.date=`date`"
+echo "ro.build.date.utc=`date +%s`"
diff --git a/meta/meta-mediatek/recipes-support/update-engine-sideload/files/erase_partition.patch b/meta/meta-mediatek/recipes-support/update-engine-sideload/files/erase_partition.patch
new file mode 100644
index 0000000..02a4a23
--- /dev/null
+++ b/meta/meta-mediatek/recipes-support/update-engine-sideload/files/erase_partition.patch
@@ -0,0 +1,22 @@
+diff --git a/payload_consumer/delta_performer.cc b/payload_consumer/delta_performer.cc
+index a619d1d9..2abc3baa 100644
+--- a/payload_consumer/delta_performer.cc
++++ b/payload_consumer/delta_performer.cc
+@@ -367,6 +367,17 @@ bool DeltaPerformer::OpenCurrentPartition() {
+ target_path_ = install_part.target_path;
+ int err;
+
++ if (install_plan_->is_resume == false)
++ {
++ string cmd = "flash_eraseall ";
++ string p_cmd;
++
++ p_cmd = cmd + target_path_;
++ LOG(INFO) << "Erase partition, erase cmd=" << p_cmd;
++
++ system(p_cmd.c_str());
++ }
++
+ int flags = O_RDWR;
+ if (!is_interactive_)
+ flags |= O_DSYNC;
diff --git a/meta/meta-mediatek/recipes-support/update-engine-sideload/files/file_descriptor.patch b/meta/meta-mediatek/recipes-support/update-engine-sideload/files/file_descriptor.patch
new file mode 100644
index 0000000..3f63f57
--- /dev/null
+++ b/meta/meta-mediatek/recipes-support/update-engine-sideload/files/file_descriptor.patch
@@ -0,0 +1,92 @@
+diff --git a/payload_consumer/file_descriptor.cc b/payload_consumer/file_descriptor.cc
+index 4eabb8f..1dc03d6 100644
+--- a/payload_consumer/file_descriptor.cc
++++ b/payload_consumer/file_descriptor.cc
+@@ -24,22 +24,40 @@
+
+ #include <base/posix/eintr_wrapper.h>
+
++#define BOOTDEV_TYPE_NAND 1
++#define BOOTDEV_TYPE_EMMC 2
++
++#if MTK_BOOTDEV_TYPE == BOOTDEV_TYPE_NAND
++ extern "C"{
++ #include "mtk_device_wrap.h"
++}
++#endif
++
+ #include "update_engine/common/utils.h"
+
+ namespace chromeos_update_engine {
+
+ bool EintrSafeFileDescriptor::Open(const char* path, int flags, mode_t mode) {
+ CHECK_EQ(fd_, -1);
++#if MTK_BOOTDEV_TYPE == BOOTDEV_TYPE_NAND
++ return ((fd_ = HANDLE_EINTR(mtk_device_wrap_m_open(path, flags, mode))) >= 0);
++#endif
+ return ((fd_ = HANDLE_EINTR(open(path, flags, mode))) >= 0);
+ }
+
+ bool EintrSafeFileDescriptor::Open(const char* path, int flags) {
+ CHECK_EQ(fd_, -1);
++#if MTK_BOOTDEV_TYPE == BOOTDEV_TYPE_NAND
++ return ((fd_ = HANDLE_EINTR(mtk_device_wrap_open(path, flags))) >= 0);
++#endif
+ return ((fd_ = HANDLE_EINTR(open(path, flags))) >= 0);
+ }
+
+ ssize_t EintrSafeFileDescriptor::Read(void* buf, size_t count) {
+ CHECK_GE(fd_, 0);
++#if MTK_BOOTDEV_TYPE == BOOTDEV_TYPE_NAND
++ return HANDLE_EINTR(mtk_device_wrap_read(fd_, buf, count));
++#endif
+ return HANDLE_EINTR(read(fd_, buf, count));
+ }
+
+@@ -50,7 +68,11 @@ ssize_t EintrSafeFileDescriptor::Write(const void* buf, size_t count) {
+ char* char_buf = const_cast<char*>(reinterpret_cast<const char*>(buf));
+ ssize_t written = 0;
+ while (count > 0) {
++#if MTK_BOOTDEV_TYPE == BOOTDEV_TYPE_NAND
++ ssize_t ret = HANDLE_EINTR(mtk_device_wrap_write_force(fd_, char_buf, count));
++#else
+ ssize_t ret = HANDLE_EINTR(write(fd_, char_buf, count));
++#endif
+
+ // Fail on either an error or no progress.
+ if (ret <= 0)
+@@ -64,6 +86,9 @@ ssize_t EintrSafeFileDescriptor::Write(const void* buf, size_t count) {
+
+ off64_t EintrSafeFileDescriptor::Seek(off64_t offset, int whence) {
+ CHECK_GE(fd_, 0);
++#if MTK_BOOTDEV_TYPE == BOOTDEV_TYPE_NAND
++ return mtk_device_wrap_seek64(fd_, offset, whence);
++#endif
+ return lseek64(fd_, offset, whence);
+ }
+
+@@ -87,6 +112,10 @@ bool EintrSafeFileDescriptor::BlkIoctl(int request,
+ int* result) {
+ // If the ioctl BLKZEROOUT is not defined, just fail to perform any of these
+ // operations.
++#if MTK_BOOTDEV_TYPE == BOOTDEV_TYPE_NAND
++ return false;
++#endif
++
+ #ifndef BLKZEROOUT
+ return false;
+ #else // defined(BLKZEROOUT)
+@@ -130,8 +159,13 @@ bool EintrSafeFileDescriptor::Flush() {
+
+ bool EintrSafeFileDescriptor::Close() {
+ CHECK_GE(fd_, 0);
++#if MTK_BOOTDEV_TYPE == BOOTDEV_TYPE_NAND
++ if (IGNORE_EINTR(mtk_device_wrap_close(fd_)))
++ return false;
++#else
+ if (IGNORE_EINTR(close(fd_)))
+ return false;
++#endif
+ fd_ = -1;
+ return true;
+ }
diff --git a/meta/meta-mediatek/recipes-support/update-engine-sideload/files/makefiles/Makefile.am b/meta/meta-mediatek/recipes-support/update-engine-sideload/files/makefiles/Makefile.am
new file mode 100644
index 0000000..f2b3184
--- /dev/null
+++ b/meta/meta-mediatek/recipes-support/update-engine-sideload/files/makefiles/Makefile.am
@@ -0,0 +1,120 @@
+local_use_binder = 0
+local_use_hwid_override = 0
+local_use_libcros = 0
+local_use_mtd = 0
+
+BUILT_SOURCES =
+EXTRA_DIST =
+
+AM_CPPFLAGS = $(GTEST_CPPFLAGS) $(GMOCK_CPPFLAGS)
+AM_CFLAGS = -fno-exceptions \
+ -fno-strict-aliasing \
+ -Wclobbered \
+ -Wempty-body \
+ -Wignored-qualifiers \
+ -Wmissing-field-initializers \
+ -Wsign-compare \
+ -Wtype-limits \
+ -Wuninitialized \
+ -Wa,--noexecstack \
+ -Wall \
+ -Wextra \
+ -Wformat=2 \
+ -Wno-psabi \
+ -Wno-unused-parameter \
+ -ffunction-sections \
+ -fstack-protector-strong \
+ -fvisibility=hidden \
+ -D__STDC_FORMAT_MACROS=1 \
+ $(GLIB_CFLAGS) $(DEPS_CFLAGS) \
+ -DUSE_BINDER=$(local_use_binder) \
+ -DUSE_HWID_OVERRIDE=$(local_use_hwid_override) \
+ -DUSE_LIBCROS=$(local_use_libcros) \
+ -DUSE_MTD=$(local_use_mtd) \
+ -DUSE_OMAHA=0 \
+ -D_FILE_OFFSET_BITS=64 \
+ -D_POSIX_C_SOURCE=199309L \
+ -D_UE_SIDELOAD=1 \
+ -DUSE_DBUS=0
+
+AM_CXXFLAGS = $(AM_CFLAGS)
+
+EXTRA_DIST += update_metadata.proto
+BUILT_SOURCES += update_metadata.pb.cc \
+ update_metadata.pb.h
+%.pb.cc %.pb.h: %.proto
+ $(AM_V_GEN) $(PROTOC) --proto_path=$(top_srcdir) --cpp_out=$(top_srcdir) $<
+
+noinst_LIBRARIES = libpayload_consumer.a
+
+sbin_PROGRAMS = update_engine_sideload
+
+libpayload_consumer_a_SOURCES = \
+ common/action_processor.cc \
+ common/boot_control_stub.cc \
+ common/clock.cc \
+ common/constants.cc \
+ common/cpu_limiter.cc \
+ common/error_code_utils.cc \
+ common/file_fetcher.cc \
+ common/hash_calculator.cc \
+ common/http_common.cc \
+ common/http_fetcher.cc \
+ common/hwid_override.cc \
+ common/multi_range_http_fetcher.cc \
+ common/platform_constants_android.cc \
+ common/prefs.cc \
+ common/subprocess.cc \
+ common/terminator.cc \
+ common/utils.cc \
+ payload_consumer/bzip_extent_writer.cc \
+ payload_consumer/cached_file_descriptor.cc \
+ payload_consumer/delta_performer.cc \
+ payload_consumer/download_action.cc \
+ payload_consumer/extent_reader.cc \
+ payload_consumer/extent_writer.cc \
+ payload_consumer/file_descriptor.cc \
+ payload_consumer/file_descriptor_utils.cc \
+ payload_consumer/file_writer.cc \
+ payload_consumer/filesystem_verifier_action.cc \
+ payload_consumer/install_plan.cc \
+ payload_consumer/mount_history.cc \
+ payload_consumer/payload_constants.cc \
+ payload_consumer/payload_metadata.cc \
+ payload_consumer/payload_verifier.cc \
+ payload_consumer/postinstall_runner_action.cc \
+ payload_consumer/xz_extent_writer.cc
+
+if NAND
+update_engine_sideload_LDADD = libpayload_consumer.a -lgio-2.0 -lgobject-2.0 -lglib-2.0 -lcrypto \
+ -lcurl -llog -lssl -lprotobuf-lite -lpthread -lbz2 -lgflags -lbase -lchrome -lbrillo -lbrillo_stream \
+ -levent -lbspatch -lfstab -lbootctrl -lxz -lpuffpatch -lbrotli -lnandapi
+else
+update_engine_sideload_LDADD = libpayload_consumer.a -lgio-2.0 -lgobject-2.0 -lglib-2.0 -lcrypto \
+ -lcurl -llog -lssl -lprotobuf-lite -lpthread -lbz2 -lgflags -lbase -lchrome -lbrillo -lbrillo_stream \
+ -levent -lbspatch -lfstab -lbootctrl -lxz -lpuffpatch -lbrotli
+endif
+
+
+update_engine_sideload_SOURCES = \
+ update_metadata.pb.cc \
+ certificate_checker.cc \
+ daemon.cc \
+ daemon_state_android.cc \
+ boot_control_recovery.cc \
+ hardware_android.cc \
+ libcurl_http_fetcher.cc \
+ metrics_reporter_stub.cc \
+ metrics_utils.cc \
+ network_selector_stub.cc \
+ proxy_resolver.cc \
+ sideload_main.cc \
+ update_attempter_android.cc \
+ update_status_utils.cc \
+ utils_android.cc
+
+update_engine_sideload_CFLAGS = -std=c++14 -g -fPIC -c
+
+
+
+
diff --git a/meta/meta-mediatek/recipes-support/update-engine-sideload/files/makefiles/configure.ac b/meta/meta-mediatek/recipes-support/update-engine-sideload/files/makefiles/configure.ac
new file mode 100644
index 0000000..04fbf65
--- /dev/null
+++ b/meta/meta-mediatek/recipes-support/update-engine-sideload/files/makefiles/configure.ac
@@ -0,0 +1,46 @@
+# -*- Autoconf -*-
+# Process this file with autoconf to produce a configure script.
+
+AC_PREREQ([2.69])
+AC_INIT([update_engine],[0.4.7],[https://github.com/coreos/bugs/issues])
+AC_CONFIG_AUX_DIR([build-aux])
+AC_CONFIG_SRCDIR([main.cc])
+AC_USE_SYSTEM_EXTENSIONS
+AC_SYS_LARGEFILE
+
+AM_INIT_AUTOMAKE([foreign 1.13 -Wall -Wno-portability
+ serial-tests silent-rules subdir-objects])
+AM_SILENT_RULES([yes])
+
+# check boot type
+AC_ARG_ENABLE(nand, AC_HELP_STRING([--enable-nand],
+ [enable nand support]),
+ [enable_nand=${enableval}])
+
+AM_CONDITIONAL(NAND, test "$enable_nand" = "yes")
+
+# Checks for programs.
+AC_PROG_CC
+AC_PROG_CXX
+AC_PROG_MKDIR_P
+AC_PROG_RANLIB
+AM_PROG_AR
+
+AC_PATH_PROG([PROTOC], [protoc])
+AS_IF([test "x${PROTOC}" = "x"],
+ [AC_MSG_ERROR([*** protoc not found])])
+
+AC_CHECK_LIB([bz2], [BZ2_bzDecompressInit], [],
+ [AC_MSG_ERROR([*** libbz2 not found])])
+AC_CHECK_HEADERS([bzlib.h], [],
+ [AC_MSG_ERROR([*** bzlib.h not found])])
+
+PKG_CHECK_MODULES([DEPS],
+ [dbus-1
+ dbus-glib-1
+ libcrypto
+ libcurl
+ libssl])
+# protobuf])
+AC_CONFIG_FILES([Makefile])
+AC_OUTPUT
diff --git a/meta/meta-mediatek/recipes-support/update-engine-sideload/files/update-payload-key.pub.pem b/meta/meta-mediatek/recipes-support/update-engine-sideload/files/update-payload-key.pub.pem
new file mode 100644
index 0000000..47e6e4d
--- /dev/null
+++ b/meta/meta-mediatek/recipes-support/update-engine-sideload/files/update-payload-key.pub.pem
@@ -0,0 +1,9 @@
+-----BEGIN PUBLIC KEY-----
+MIIBIDANBgkqhkiG9w0BAQEFAAOCAQ0AMIIBCAKCAQEA1pMZBN7GCySx7cdi4NnY
+JT4+zWzrHeL/Boyo6LyozWvTeG6nCqds5g67D5k1Wf/ZPnepQ+foPUtkuOT+otPm
+VvHiZ6gbv7IwtXjCBEO+THIYuEb1IRWG8DihTonCvjh/jr7Pj8rD2h7jMMnqk9Cn
+w9xK81AiDVAIBzLggJcX7moFM1nmppTsLLPyhKCkZsh6lNg7MQk6ZzcuL2QSwG5t
+QvFYGN/+A4HMDNRE2mzdw7gkWBlIAbMlZBNPv96YySh3SNv1Z2pUDYFUyLvKB7ni
+R1UzEcRrmvdv3uzMjmnnyKLQjngmIJQ/mXJ9PAT+cpkdmd+brjigshd/ox1bav7p
+HwIBAw==
+-----END PUBLIC KEY-----
diff --git a/meta/meta-mediatek/recipes-support/update-engine-sideload/files/update_engine.patch b/meta/meta-mediatek/recipes-support/update-engine-sideload/files/update_engine.patch
new file mode 100644
index 0000000..af502f6
--- /dev/null
+++ b/meta/meta-mediatek/recipes-support/update-engine-sideload/files/update_engine.patch
@@ -0,0 +1,312 @@
+diff --git a/common/platform_constants_android.cc b/common/platform_constants_android.cc
+index 371fe26..ef13058 100644
+--- a/common/platform_constants_android.cc
++++ b/common/platform_constants_android.cc
+@@ -30,7 +30,7 @@ const char kUpdatePayloadPublicKeyPath[] =
+ const char kCACertificatesPath[] = "/system/etc/security/cacerts_google";
+ // No deadline file API support on Android.
+ const char kOmahaResponseDeadlineFile[] = "";
+-const char kNonVolatileDirectory[] = "/data/misc/update_engine";
++const char kNonVolatileDirectory[] = "/var/lib/update_engine";
+ const char kPostinstallMountOptions[] =
+ "context=u:object_r:postinstall_file:s0";
+
+diff --git a/hardware_android.cc b/hardware_android.cc
+index 947b13a..0ccb161 100644
+--- a/hardware_android.cc
++++ b/hardware_android.cc
+@@ -22,10 +22,11 @@
+
+ #include <algorithm>
+ #include <memory>
+-
++#if 0
+ #include <bootloader.h>
+
+ #include <android-base/properties.h>
++#endif
+ #include <base/files/file_util.h>
+ #include <base/strings/stringprintf.h>
+
+@@ -34,9 +35,11 @@
+ #include "update_engine/common/utils.h"
+ #include "update_engine/utils_android.h"
+
++#if 0
+ using android::base::GetBoolProperty;
+ using android::base::GetIntProperty;
+ using android::base::GetProperty;
++#endif
+ using std::string;
+
+ namespace chromeos_update_engine {
+@@ -58,7 +61,7 @@ const char kPropProductManufacturer[] = "ro.product.manufacturer";
+ const char kPropBootHardwareSKU[] = "ro.boot.hardware.sku";
+ const char kPropBootRevision[] = "ro.boot.revision";
+ const char kPropBuildDateUTC[] = "ro.build.date.utc";
+-
++#if 0
+ // Write a recovery command line |message| to the BCB. The arguments to recovery
+ // must be separated by '\n'. An empty string will erase the BCB.
+ bool WriteBootloaderRecoveryMessage(const string& message) {
+@@ -91,7 +94,7 @@ bool WriteBootloaderRecoveryMessage(const string& message) {
+ }
+ return true;
+ }
+-
++#endif
+ } // namespace
+
+ namespace hardware {
+@@ -124,7 +127,7 @@ bool HardwareAndroid::IsOfficialBuild() const {
+ //
+ // In case of a non-bool value, we take the most restrictive option and
+ // assume we are in an official-build.
+- return GetBoolProperty("ro.secure", true);
++ return true;//GetBoolProperty("ro.secure", true);
+ }
+
+ bool HardwareAndroid::IsNormalBootMode() const {
+@@ -132,11 +135,11 @@ bool HardwareAndroid::IsNormalBootMode() const {
+ // update_engine will allow extra developers options, such as providing a
+ // different update URL. In case of error, we assume the build is in
+ // normal-mode.
+- return !GetBoolProperty("ro.debuggable", false);
++ return true;//!GetBoolProperty("ro.debuggable", false);
+ }
+
+ bool HardwareAndroid::AreDevFeaturesEnabled() const {
+- return !IsNormalBootMode();
++ return false;//!IsNormalBootMode();
+ }
+
+ bool HardwareAndroid::IsOOBEEnabled() const {
+@@ -152,19 +155,22 @@ bool HardwareAndroid::IsOOBEComplete(base::Time* out_time_of_oobe) const {
+ }
+
+ string HardwareAndroid::GetHardwareClass() const {
+- auto manufacturer = GetProperty(kPropProductManufacturer, "");
+- auto sku = GetProperty(kPropBootHardwareSKU, "");
+- auto revision = GetProperty(kPropBootRevision, "");
++ //auto manufacturer = GetProperty(kPropProductManufacturer, "");
++ //auto sku = GetProperty(kPropBootHardwareSKU, "");
++ //auto revision = GetProperty(kPropBootRevision, "");
+
+- return manufacturer + ":" + sku + ":" + revision;
++ //return manufacturer + ":" + sku + ":" + revision;
++ return "manufacturer:sku:revision";
+ }
+
+ string HardwareAndroid::GetFirmwareVersion() const {
+- return GetProperty(kPropBootBootloader, "");
++ //return GetProperty(kPropBootBootloader, "");
++ return "1.0";
+ }
+
+ string HardwareAndroid::GetECVersion() const {
+- return GetProperty(kPropBootBaseband, "");
++ //return GetProperty(kPropBootBaseband, "");
++ return "1.0";
+ }
+
+ int HardwareAndroid::GetPowerwashCount() const {
+@@ -174,11 +180,11 @@ int HardwareAndroid::GetPowerwashCount() const {
+
+ bool HardwareAndroid::SchedulePowerwash() {
+ LOG(INFO) << "Scheduling a powerwash to BCB.";
+- return WriteBootloaderRecoveryMessage(kAndroidRecoveryPowerwashCommand);
++ return false;//WriteBootloaderRecoveryMessage(kAndroidRecoveryPowerwashCommand);
+ }
+
+ bool HardwareAndroid::CancelPowerwash() {
+- return WriteBootloaderRecoveryMessage("");
++ return true;//WriteBootloaderRecoveryMessage("");
+ }
+
+ bool HardwareAndroid::GetNonVolatileDirectory(base::FilePath* path) const {
+@@ -197,7 +203,8 @@ bool HardwareAndroid::GetPowerwashSafeDirectory(base::FilePath* path) const {
+ }
+
+ int64_t HardwareAndroid::GetBuildTimestamp() const {
+- return GetIntProperty<int64_t>(kPropBuildDateUTC, 0);
++ //return GetIntProperty<int64_t>(kPropBuildDateUTC, 0);
++ return utils::GetIntProperty(kPropBuildDateUTC, 0);
+ }
+
+ bool HardwareAndroid::GetFirstActiveOmahaPingSent() const {
+diff --git a/sideload_main.cc b/sideload_main.cc
+index ddb312e..b983534 100644
+--- a/sideload_main.cc
++++ b/sideload_main.cc
+@@ -155,7 +155,7 @@ bool ApplyUpdatePayload(const string& payload,
+
+ // During the sideload we don't access the prefs persisted on disk but instead
+ // use a temporary memory storage.
+- MemoryPrefs prefs;
++ //MemoryPrefs prefs;
+
+ std::unique_ptr<BootControlInterface> boot_control =
+ boot_control::CreateBootControl();
+@@ -169,9 +169,21 @@ bool ApplyUpdatePayload(const string& payload,
+ LOG(ERROR) << "Error initializing the HardwareInterface.";
+ return false;
+ }
++ base::FilePath non_volatile_path;
++ if (!hardware->GetNonVolatileDirectory(&non_volatile_path)) {
++ LOG(ERROR) << "Failed to get a non-volatile directory.";
++ return false;
++ }
++ std::unique_ptr<PrefsInterface> prefsIf;
++ Prefs* prefs = new Prefs();
++ if (!prefs->Init(non_volatile_path.Append(kPrefsSubDirectory))) {
++ LOG(ERROR) << "Failed to initialize preferences.";
++ return false;
++ }
++ prefsIf.reset(prefs);
+
+ UpdateAttempterAndroid update_attempter(
+- &sideload_daemon_state, &prefs, boot_control.get(), hardware.get());
++ &sideload_daemon_state, prefsIf.get(), boot_control.get(), hardware.get());
+ update_attempter.Init();
+
+ TEST_AND_RETURN_FALSE(update_attempter.ApplyPayload(
+diff --git a/update_attempter_android.cc b/update_attempter_android.cc
+index 04ccb18..60e96ff 100644
+--- a/update_attempter_android.cc
++++ b/update_attempter_android.cc
+@@ -21,7 +21,7 @@
+ #include <memory>
+ #include <utility>
+
+-#include <android-base/properties.h>
++//#include <android-base/properties.h>
+ #include <base/bind.h>
+ #include <base/logging.h>
+ #include <base/strings/string_number_conversions.h>
+@@ -29,7 +29,7 @@
+ #include <brillo/data_encoding.h>
+ #include <brillo/message_loops/message_loop.h>
+ #include <brillo/strings/string_utils.h>
+-#include <log/log_safetynet.h>
++//#include <log/log_safetynet.h>
+
+ #include "update_engine/common/constants.h"
+ #include "update_engine/common/error_code_utils.h"
+@@ -449,7 +449,7 @@ void UpdateAttempterAndroid::ProcessingDone(const ActionProcessor* processor,
+
+ case ErrorCode::kPayloadTimestampError:
+ // SafetyNet logging, b/36232423
+- android_errorWriteLog(0x534e4554, "36232423");
++ //android_errorWriteLog(0x534e4554, "36232423");
+ break;
+
+ default:
+@@ -599,7 +599,10 @@ void UpdateAttempterAndroid::SetStatusAndNotify(UpdateStatus status) {
+ status_ = status;
+ size_t payload_size =
+ install_plan_.payloads.empty() ? 0 : install_plan_.payloads[0].size;
+- UpdateEngineStatus status_to_send = {.status = status_,
++ UpdateEngineStatus status_to_send = {.last_checked_time = 0,
++ .status = status_,
++ .current_version = "n",
++ .current_system_version = "n",
+ .progress = download_progress_,
+ .new_size_bytes = payload_size};
+
+@@ -764,8 +767,8 @@ void UpdateAttempterAndroid::UpdatePrefsAndReportUpdateMetricsOnReboot() {
+ string current_boot_id;
+ TEST_AND_RETURN(utils::GetBootId(¤t_boot_id));
+ // Example: [ro.build.version.incremental]: [4292972]
+- string current_version =
+- android::base::GetProperty("ro.build.version.incremental", "");
++ string current_version = "4292972";
++ //android::base::GetProperty("ro.build.version.incremental", "");
+ TEST_AND_RETURN(!current_version.empty());
+
+ // If there's no record of previous version (e.g. due to a data wipe), we
+diff --git a/update_manager/policy.h b/update_manager/policy.h
+index b60c4da..a57cfa6 100644
+--- a/update_manager/policy.h
++++ b/update_manager/policy.h
+@@ -202,7 +202,7 @@ class Policy {
+ std::string*, R*,
+ Args...) const) const {
+ std::string class_name = PolicyName() + "::";
+-
++#if 0
+ if (reinterpret_cast<typeof(&Policy::UpdateCheckAllowed)>(
+ policy_method) == &Policy::UpdateCheckAllowed)
+ return class_name + "UpdateCheckAllowed";
+@@ -223,6 +223,7 @@ class Policy {
+ return class_name + "P2PEnabledChanged";
+
+ NOTREACHED();
++#endif
+ return class_name + "(unknown)";
+ }
+
+diff --git a/utils_android.cc b/utils_android.cc
+index 393e65a..40c06b7 100644
+--- a/utils_android.cc
++++ b/utils_android.cc
+@@ -15,8 +15,10 @@
+ //
+
+ #include "update_engine/utils_android.h"
++#include <base/strings/string_number_conversions.h>
++#include <brillo/key_value_store.h>
+
+-#include <fs_mgr.h>
++#include <fstab/fstab.h>
+
+ using std::string;
+
+@@ -40,6 +42,9 @@ static struct fstab* OpenFSTab() {
+ namespace utils {
+
+ bool DeviceForMountPoint(const string& mount_point, base::FilePath* device) {
++ //*device = base::FilePath("/dev/disk/by-partlabel/misc");
++ // return true;
++#if 1
+ struct fstab* fstab;
+ struct fstab_rec* record;
+
+@@ -58,8 +63,26 @@ bool DeviceForMountPoint(const string& mount_point, base::FilePath* device) {
+ *device = base::FilePath(record->blk_device);
+ fs_mgr_free_fstab(fstab);
+ return true;
++#endif
+ }
+
++int64_t GetIntProperty(const string& key, int64_t default_value){
++ brillo::KeyValueStore store;
++ if(store.Load(base::FilePath("/etc/update_engine/build.prop"))){
++ std::string result;
++ int64_t result_value;
++ if(!store.GetString(key, &result)){
++ LOG(ERROR) << "Error get key" << key;
++ return default_value;
++ }
++ if(base::StringToInt64(result,&result_value)){
++ return result_value;
++ }
++ }else{
++ LOG(ERROR) << "Error opening property file.";
++ }
++ return default_value;
++}
+ } // namespace utils
+
+ } // namespace chromeos_update_engine
+diff --git a/utils_android.h b/utils_android.h
+index 18dd8ab..9692610 100644
+--- a/utils_android.h
++++ b/utils_android.h
+@@ -30,6 +30,7 @@ namespace utils {
+ bool DeviceForMountPoint(const std::string& mount_point,
+ base::FilePath* device);
+
++int64_t GetIntProperty(const std::string& key, int64_t default_value);
+ } // namespace utils
+
+ } // namespace chromeos_update_engine
diff --git a/meta/meta-mediatek/recipes-support/update-engine-sideload/update-engine-sideload.bb b/meta/meta-mediatek/recipes-support/update-engine-sideload/update-engine-sideload.bb
new file mode 100644
index 0000000..2dcd158
--- /dev/null
+++ b/meta/meta-mediatek/recipes-support/update-engine-sideload/update-engine-sideload.bb
@@ -0,0 +1,53 @@
+DESCRIPTION = "update engine sideload"
+
+HOMEPAGE = "https://github.com/coreos/update_engine"
+
+LICENSE = "BSD-3-Clause"
+LIC_FILES_CHKSUM = "file://MODULE_LICENSE_APACHE2;md5=d41d8cd98f00b204e9800998ecf8427e"
+
+
+FILESEXTRAPATHS_prepend := "${THISDIR}:"
+SRC_URI = "git://android.googlesource.com/platform/system/update_engine;protocol=https;name=platform/system/update_engine;destsuffix=platform/system/update_engine/ \
+ file://update_engine.patch \
+ file://file_descriptor.patch \
+ file://erase_partition.patch \
+"
+
+SRCREV_platform/system/update_engine = "e5d1deba6185ba59da0345cb970d2d60c312ab76"
+
+S = "${WORKDIR}/platform/system/update_engine"
+
+CPPFLAGS += "-I${WORKDIR}/platform/system/"
+
+
+DEPENDS += "bzip2 glog gtest openssl curl gflags protobuf dbus-glib bootctrl platform-libs-updateengine protobuf-native ${@bb.utils.contains("BOOTDEV_TYPE", "nand", "nandapi", "", d)}"
+
+
+inherit autotools pkgconfig
+
+# Avoid QA Issue: 'Files/directories were installed but not shipped'
+INSANE_SKIP_${PN} += "installed-vs-shipped dev-deps"
+
+EXTRA_OEMAKE = "PACKAGE_ARCH=${PACKAGE_ARCH} LIBDIR=${WORKDIR}/recipe-sysroot/usr/lib64 BOOTDEV_TYPE=${BOOTDEV_TYPE}"
+
+FILES_${PN} += "/etc/update_engine"
+FILES_${PN} += "/etc/update_engine/update-payload-key.pub.pem"
+FILES_${PN} += "/var/lib/update_engine"
+
+EXTRA_OECONF = "${@bb.utils.contains("BOOTDEV_TYPE", "nand", "--enable-nand=yes", "", d)}"
+
+do_configure_prepend() {
+ install -m 0755 ${TOPDIR}/../meta/meta-mediatek/recipes-support/update-engine-sideload/files/makefiles/Makefile.am ${S}/Makefile.am
+ install -m 0755 ${TOPDIR}/../meta/meta-mediatek/recipes-support/update-engine-sideload/files/makefiles/configure.ac ${S}/configure.ac
+ install -m 0755 ${TOPDIR}/../meta/meta-mediatek/recipes-support/update-engine-sideload/files/update-payload-key.pub.pem ${S}/update-payload-key.pub.pem
+ install -m 0755 ${TOPDIR}/../meta/meta-mediatek/recipes-support/update-engine-sideload/files/buildinfo.sh ${S}/buildinfo.sh
+}
+
+do_install_append() {
+ install -d ${D}${libdir}
+ install -d ${D}/etc/update_engine
+ install -d ${D}/var/lib/update_engine
+ install -m 0644 ${S}/update-payload-key.pub.pem ${D}/etc/update_engine/update-payload-key.pub.pem
+ sh ${S}/buildinfo.sh > ${D}/etc/update_engine/build.prop
+ cp ${S}/update_engine.conf ${D}/etc/update_engine/
+}
diff --git a/meta/meta-mediatek/recipes-support/update-verifier/files/Makefile.am b/meta/meta-mediatek/recipes-support/update-verifier/files/Makefile.am
new file mode 100644
index 0000000..b26b317
--- /dev/null
+++ b/meta/meta-mediatek/recipes-support/update-verifier/files/Makefile.am
@@ -0,0 +1,31 @@
+# update_verifier.bin
+bin_PROGRAMS = update_verifier
+
+
+update_verifier_SOURCES = \
+ otautil/rangeset.cpp \
+ update_verifier/update_verifier_main.cpp \
+ update_verifier/update_verifier.cpp
+
+update_verifier_CFLAGS = \
+ -Wall \
+ -Werror \
+ -std=c++11
+
+INCLUDES = \
+ -I$(top_srcdir)/otautil/include \
+ -I$(top_srcdir)/update_verifier/include
+
+AM_CPPFLAGS = \
+ -I$(top_srcdir)/otautil \
+ -I$(top_srcdir)/update_verifier
+
+update_verifier_CPPFLAGS = \
+ -Ibootctrl \
+ -I$(top_srcdir)
+
+if NAND
+update_verifier_LDADD = -llog -lpthread -lbase -lbootctrl -lnandapi
+else
+update_verifier_LDADD = -llog -lpthread -lbase -lbootctrl
+endif
diff --git a/meta/meta-mediatek/recipes-support/update-verifier/files/configure.ac b/meta/meta-mediatek/recipes-support/update-verifier/files/configure.ac
new file mode 100644
index 0000000..ca5e7e1
--- /dev/null
+++ b/meta/meta-mediatek/recipes-support/update-verifier/files/configure.ac
@@ -0,0 +1,14 @@
+AC_INIT(update-verifier, 1.0)
+AM_INIT_AUTOMAKE(foreign)
+
+# check boot type
+AC_ARG_ENABLE(nand, AC_HELP_STRING([--enable-nand],
+ [enable nand support]),
+ [enable_nand=${enableval}])
+
+AM_CONDITIONAL(NAND, test "$enable_nand" = "yes")
+
+AM_MAINTAINER_MODE
+AC_PROG_CXX
+LT_INIT
+AC_OUTPUT([Makefile])
diff --git a/meta/meta-mediatek/recipes-support/update-verifier/files/update-verifier.patch b/meta/meta-mediatek/recipes-support/update-verifier/files/update-verifier.patch
new file mode 100644
index 0000000..3150c93
--- /dev/null
+++ b/meta/meta-mediatek/recipes-support/update-verifier/files/update-verifier.patch
@@ -0,0 +1,317 @@
+diff --git a/update_verifier/include/update_verifier/update_verifier.h b/update_verifier/include/update_verifier/update_verifier.h
+index 16b394e98..c700a170b 100644
+--- a/update_verifier/include/update_verifier/update_verifier.h
++++ b/update_verifier/include/update_verifier/update_verifier.h
+@@ -22,3 +22,4 @@ int update_verifier(int argc, char** argv);
+
+ // Exposed for testing purpose.
+ bool verify_image(const std::string& care_map_name);
++std::string GetProperty(const char* strProperity);
+diff --git a/update_verifier/update_verifier.cpp b/update_verifier/update_verifier.cpp
+index 92d931371..45b12cb9f 100644
+--- a/update_verifier/update_verifier.cpp
++++ b/update_verifier/update_verifier.cpp
+@@ -34,9 +34,6 @@
+ * The current slot will be marked as having booted successfully if the
+ * verifier reaches the end after the verification.
+ */
+-
+-#include "update_verifier/update_verifier.h"
+-
+ #include <dirent.h>
+ #include <errno.h>
+ #include <fcntl.h>
+@@ -52,20 +49,22 @@
+ #include <android-base/file.h>
+ #include <android-base/logging.h>
+ #include <android-base/parseint.h>
+-#include <android-base/properties.h>
+ #include <android-base/strings.h>
+ #include <android-base/unique_fd.h>
+-#include <android/hardware/boot/1.0/IBootControl.h>
+-#include <cutils/android_reboot.h>
++#include <hardware/boot_control.h>
++#include <hardware/hardware.h>
++#include <sys/reboot.h>
+
+ #include "otautil/rangeset.h"
++#include "update_verifier/update_verifier.h"
+
+-using android::sp;
+-using android::hardware::boot::V1_0::IBootControl;
+-using android::hardware::boot::V1_0::BoolResult;
+-using android::hardware::boot::V1_0::CommandResult;
++using std::string;
+
+ // Find directories in format of "/sys/block/dm-X".
++
++extern const hw_module_t HAL_MODULE_INFO_SYM;
++boot_control_module_t* module;
++
+ static int dm_name_filter(const dirent* de) {
+ if (android::base::StartsWith(de->d_name, "dm-")) {
+ return 1;
+@@ -73,6 +72,72 @@ static int dm_name_filter(const dirent* de) {
+ return 0;
+ }
+
++#define COMMAND_LINE_PATH "/proc/cmdline"
++#define COMMAND_LINE_SIZE 2048
++
++std::string GetProperty(const char* strProperity)
++{
++ int fd, err, slot;
++ ssize_t size = COMMAND_LINE_SIZE, sz;
++ char *buf, *ptr;
++ char *str;
++ std::string res;
++
++ fd = open(COMMAND_LINE_PATH, O_RDONLY);
++ if (fd < 0) {
++ err = -errno;
++ LOG(ERROR) << "error reading commandline\n";
++ return NULL;
++ }
++ ptr = buf = (char *)malloc(size);
++ if (!buf) {
++ err = -errno;
++ LOG(ERROR) << "Error allocating memory";
++ close(fd);
++ return NULL;
++ }
++ do {
++ sz = read(fd, buf, size);
++ if (sz == 0) {
++ break;
++ } else if (sz < 0) {
++ if (errno == EINTR) {
++ continue;
++ }
++ err = -errno;
++ LOG(ERROR) << "Error reading file";
++ free(ptr);
++ close(fd);
++ return NULL;
++ }
++ size -= sz;
++ buf += sz;
++ } while(size > 0);
++
++ str = strstr((char *)ptr, strProperity);
++ if (!str) {
++ err = -EIO;
++ LOG(ERROR) << "Cannot find %s in kernel commandline" << strProperity;
++ free(ptr);
++ close(fd);
++ return NULL;
++ }
++ str += strlen(strProperity);
++ while(1){
++ str++;
++ if(((*str == ' ') || (*str == '\0' ) || (*str == '\n'))){
++ break;
++ }else{
++ res.push_back(*str);
++ }
++ }
++ LOG(INFO) << "Find kernel commandline" << res;
++
++ free(ptr);
++ close(fd);
++ return res;
++}
++
+ static bool read_blocks(const std::string& partition, const std::string& range_str) {
+ if (partition != "system" && partition != "vendor" && partition != "product") {
+ LOG(ERROR) << "Invalid partition name \"" << partition << "\"";
+@@ -103,6 +168,7 @@ static bool read_blocks(const std::string& partition, const std::string& range_s
+ PLOG(WARNING) << "Failed to read " << path;
+ } else {
+ std::string dm_block_name = android::base::Trim(content);
++ LOG(ERROR) << "dm_block_name namelist[n]->d_name " << dm_block_name << namelist[n]->d_name;
+ #ifdef BOARD_AVB_ENABLE
+ // AVB is using 'vroot' for the root block device but we're expecting 'system'.
+ if (dm_block_name == "vroot") {
+@@ -135,7 +201,7 @@ static bool read_blocks(const std::string& partition, const std::string& range_s
+ LOG(ERROR) << "Error parsing RangeSet string " << range_str;
+ return false;
+ }
+-
++
+ // RangeSet::Split() splits the ranges into multiple groups with same number of blocks (except for
+ // the last group).
+ size_t thread_num = std::thread::hardware_concurrency() ?: 4;
+@@ -147,13 +213,27 @@ static bool read_blocks(const std::string& partition, const std::string& range_s
+ android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(dm_block_device.c_str(), O_RDONLY)));
+ if (fd.get() == -1) {
+ PLOG(ERROR) << "Error reading " << dm_block_device << " for partition " << partition;
+- return false;
++ //return false;
++ std::string path = "/sys/class/block/dm-0/dev";
++ std::string content;
++ if (!android::base::ReadFileToString(path, &content)) {
++ PLOG(WARNING) << "Failed to read " << path;
++ } else {
++ std::string dev_name = android::base::Trim(content);
++ dm_block_device = DEV_PATH + dev_name;
++ }
+ }
+-
++ fd.reset(open(dm_block_device.c_str(), O_RDONLY));
++ if (fd.get() == -1) {
++ PLOG(ERROR) << "Error reading " << dm_block_device << " for partition " << partition;
++ return false;
++ }
++
+ static constexpr size_t kBlockSize = 4096;
+ std::vector<uint8_t> buf(1024 * kBlockSize);
+
+ size_t block_count = 0;
++
+ for (const auto& range : group) {
+ size_t range_start = range.first;
+ size_t range_end = range.second;
+@@ -161,7 +241,7 @@ static bool read_blocks(const std::string& partition, const std::string& range_s
+ PLOG(ERROR) << "lseek to " << range_start << " failed";
+ return false;
+ }
+-
++ PLOG(ERROR) << "range start " << range_start << " range_end " << range_end;
+ size_t remain = (range_end - range_start) * kBlockSize;
+ while (remain > 0) {
+ size_t to_read = std::min(remain, 1024 * kBlockSize);
+@@ -173,7 +253,7 @@ static bool read_blocks(const std::string& partition, const std::string& range_s
+ }
+ block_count += (range_end - range_start);
+ }
+- LOG(INFO) << "Finished reading " << block_count << " blocks on " << dm_block_device;
++ LOG(ERROR) << "Finished reading " << block_count << " blocks on " << dm_block_device ;
+ return true;
+ };
+
+@@ -238,10 +318,13 @@ bool verify_image(const std::string& care_map_name) {
+ }
+
+ static int reboot_device() {
+- if (android_reboot(ANDROID_RB_RESTART2, 0, nullptr) == -1) {
+- LOG(ERROR) << "Failed to reboot.";
+- return -1;
+- }
++ //if (android_reboot(ANDROID_RB_RESTART2, 0, nullptr) == -1) {
++ // LOG(ERROR) << "Failed to reboot.";
++ // return -1;
++ //}
++ //system("reboot");
++ reboot(RB_AUTOBOOT);
++
+ while (true) pause();
+ }
+
+@@ -250,23 +333,45 @@ int update_verifier(int argc, char** argv) {
+ LOG(INFO) << "Started with arg " << i << ": " << argv[i];
+ }
+
+- sp<IBootControl> module = IBootControl::getService();
++ /************* Bootctrl Init Start *************/
++ //sp<IBootControl> module = IBootControl::getService();
++ const hw_module_t* hw_module;
++ int ret;
++
++ // For update_engine_sideload, we simulate the hw_get_module() by accessing it
++ // from the current process directly.
++ hw_module = &HAL_MODULE_INFO_SYM;
++ ret = 0;
++ if (!hw_module ||
++ strcmp(BOOT_CONTROL_HARDWARE_MODULE_ID, hw_module->id) != 0) {
++ ret = -EINVAL;
++ }
++ if (ret != 0) {
++ LOG(ERROR) << "Error loading boot_control HAL implementation.";
++ return false;
++ }
++
++ module = reinterpret_cast<boot_control_module_t*>(
++ const_cast<hw_module_t*>(hw_module));
++ module->init(module);
++
+ if (module == nullptr) {
+ LOG(ERROR) << "Error getting bootctrl module.";
+ return reboot_device();
+ }
++ /************* Bootctrl Init End *************/
+
+- uint32_t current_slot = module->getCurrentSlot();
+- BoolResult is_successful = module->isSlotMarkedSuccessful(current_slot);
++ uint32_t current_slot = module->getCurrentSlot(module);
++ //bool is_successful = module->isSlotMarkedSuccessful(current_slot);
++ bool is_successful = module->isSlotMarkedSuccessful(module, current_slot);
+ LOG(INFO) << "Booting slot " << current_slot << ": isSlotMarkedSuccessful="
+- << static_cast<int32_t>(is_successful);
++ << is_successful;
+
+- if (is_successful == BoolResult::FALSE) {
++ if (is_successful == false) {
+ // The current slot has not booted successfully.
+-
+ #if defined(PRODUCT_SUPPORTS_VERITY) || defined(BOARD_AVB_ENABLE)
+ bool skip_verification = false;
+- std::string verity_mode = android::base::GetProperty("ro.boot.veritymode", "");
++ std::string verity_mode = GetProperty("androidboot.veritymode");
+ if (verity_mode.empty()) {
+ // With AVB it's possible to disable verification entirely and
+ // in this case ro.boot.veritymode is empty.
+@@ -290,7 +395,7 @@ int update_verifier(int argc, char** argv) {
+ }
+
+ if (!skip_verification) {
+- static constexpr auto CARE_MAP_FILE = "/data/ota_package/care_map.txt";
++ static constexpr auto CARE_MAP_FILE = "/var/lib/update_engine/care_map.txt";
+ if (!verify_image(CARE_MAP_FILE)) {
+ LOG(ERROR) << "Failed to verify all blocks in care map file.";
+ return reboot_device();
+@@ -300,10 +405,10 @@ int update_verifier(int argc, char** argv) {
+ LOG(WARNING) << "dm-verity not enabled; marking without verification.";
+ #endif
+
+- CommandResult cr;
+- module->markBootSuccessful([&cr](CommandResult result) { cr = result; });
+- if (!cr.success) {
+- LOG(ERROR) << "Error marking booted successfully: " << cr.errMsg;
++ //bool cr = module->markBootSuccessful([&cr](CommandResult result) { cr = result; });
++ int cr = module->markBootSuccessful(module);
++ if (cr < 0) {
++ LOG(ERROR) << "Error marking booted successfully: " << cr;
+ return reboot_device();
+ }
+ LOG(INFO) << "Marked slot " << current_slot << " as booted successfully.";
+diff --git a/update_verifier/update_verifier_main.cpp b/update_verifier/update_verifier_main.cpp
+index a86203bfb..c22582341 100644
+--- a/update_verifier/update_verifier_main.cpp
++++ b/update_verifier/update_verifier_main.cpp
+@@ -19,12 +19,15 @@
+ #include <string>
+
+ #include <android-base/logging.h>
+-#include <android-base/properties.h>
++//#include <android-base/properties.h>
+
+ #include "update_verifier/update_verifier.h"
+
+ int main(int argc, char** argv) {
+- std::string s = android::base::GetProperty("ro.boot.slot_suffix", "");
++ //std::string s = android::base::GetProperty("ro.boot.slot_suffix", "");
++
++
++ std::string s = GetProperty("androidboot.slot");
+
+ if (s.empty()) {
+ return 0; // non-A/B update device, so we quit
+@@ -32,7 +35,7 @@ int main(int argc, char** argv) {
+
+ // Set up update_verifier logging to be written to kmsg; because we may not have Logd during
+ // boot time.
+- android::base::InitLogging(argv, &android::base::KernelLogger);
++ android::base::InitLogging(argv, android::base::StderrLogger);
+
+ return update_verifier(argc, argv);
+ }
diff --git a/meta/meta-mediatek/recipes-support/update-verifier/files/update_verifier.service b/meta/meta-mediatek/recipes-support/update-verifier/files/update_verifier.service
new file mode 100644
index 0000000..732bc33
--- /dev/null
+++ b/meta/meta-mediatek/recipes-support/update-verifier/files/update_verifier.service
@@ -0,0 +1,10 @@
+[Unit]
+Description=update_verifier
+
+[Service]
+ExecStart=/usr/bin/update_verifier
+Type=simple
+
+[Install]
+Alias=upgrade
+WantedBy=multi-user.target
\ No newline at end of file
diff --git a/meta/meta-mediatek/recipes-support/update-verifier/update-verifier.bb b/meta/meta-mediatek/recipes-support/update-verifier/update-verifier.bb
new file mode 100644
index 0000000..7f6751e
--- /dev/null
+++ b/meta/meta-mediatek/recipes-support/update-verifier/update-verifier.bb
@@ -0,0 +1,42 @@
+inherit pkgconfig autotools
+DESCRIPTION = "ab update verifier"
+
+LICENSE = "Apache-2.0"
+LIC_FILES_CHKSUM = "file://NOTICE;md5=9645f39e9db895a4aa6e02cb57294595"
+
+DEPENDS += "bootctrl platform-libs-common ${@bb.utils.contains("BOOTDEV_TYPE", "nand", "nandapi", "", d)}"
+
+INHIBIT_PACKAGE_STRIP = "1"
+inherit systemd
+
+FILESEXTRAPATHS_prepend := "${THISDIR}:"
+SRC_URI = " \
+ git://android.googlesource.com/platform/bootable/recovery;name=platform/bootable/recovery;destsuffix=platform/bootable/recovery \
+ file://update-verifier.patch \
+ file://Makefile.am \
+ file://configure.ac \
+ file://update_verifier.service \
+"
+
+SRCREV_platform/bootable/recovery = "896de5423db1ec3824797e11199a08be20b02d1d"
+
+S = "${WORKDIR}/platform/bootable/recovery"
+
+CPPFLAGS += "${@bb.utils.contains("BOARD_AVB_ENABLE","true", "-DBOARD_AVB_ENABLE","",d)}"
+
+SYSTEMD_PACKAGES = "${PN}"
+SYSTEMD_SERVICE_${PN} = "update_verifier.service"
+FILES_${PN} += "${systemd_unitdir}/system/update_verifier.service"
+
+EXTRA_OECONF = "${@bb.utils.contains("BOOTDEV_TYPE", "nand", "--enable-nand=yes", "", d)}"
+
+do_configure_prepend() {
+ install -m 0755 ${WORKDIR}/Makefile.am ${S}/Makefile.am
+ install -m 0755 ${WORKDIR}/configure.ac ${S}/configure.ac
+ install -m 0755 ${WORKDIR}/update_verifier.service ${S}/update_verifier.service
+}
+
+do_install_append() {
+ install -d ${D}${systemd_unitdir}/system
+ install -m 0755 ${S}/update_verifier.service ${D}${systemd_unitdir}/system
+}
diff --git a/meta/meta-mediatek/recipes-tinysys/tinysys/tinysys_1.0.bb b/meta/meta-mediatek/recipes-tinysys/tinysys/tinysys_1.0.bb
new file mode 100644
index 0000000..6fefb7f
--- /dev/null
+++ b/meta/meta-mediatek/recipes-tinysys/tinysys/tinysys_1.0.bb
@@ -0,0 +1,34 @@
+LICENSE = "MIT & MediaTekProprietary"
+
+inherit externalsrc tinysys-fitimage hsm-sign-env deploy
+EXTERNALSRC = "${TOPDIR}/../src/tinysys/ap/${TARGET_PLATFORM}/source"
+
+TINYSYS_IMAGE = "tinysys-${TARGET_PLATFORM}.img"
+TINYSYS_OUT = "${WORKDIR}/out"
+TINYSYS_BIN = "tinysys-${TARGET_PLATFORM}"
+
+CFLAGS_append_toolchain-clang += " -fheinous-gnu-extensions"
+
+do_compile() {
+ LDFLAGS=" " oe_runmake all TINYSYS_BIN=${TINYSYS_BIN} PROJECT=${MTK_PROJECT} \
+ BASE_ADDR=${TINYSYS_LOADADDRESS} \
+ -C ${EXTERNALSRC}
+}
+
+do_install() {
+ install -d ${TINYSYS_OUT}
+ install -m 0755 ${EXTERNALSRC}/${TINYSYS_BIN}.bin ${TINYSYS_OUT}
+
+}
+
+do_deploy () {
+ install -d ${DEPLOYDIR}
+ install ${WORKDIR}/${TINYSYS_IMAGE} ${DEPLOYDIR}/${TINYSYS_IMAGE}
+}
+
+clean_out() {
+ oe_runmake TINYSYS_BIN=${TINYSYS_BIN} PROJECT=${MTK_PROJECT} clean -C ${EXTERNALSRC}
+}
+do_clean[prefuncs] += "clean_out"
+
+addtask deploy before do_build after do_assemble_fitimage