[Feature] add GA346 baseline version
Change-Id: Ic62933698569507dcf98240cdf5d9931ae34348f
diff --git a/meta/meta-mediatek-gpl/COPYING.MIT b/meta/meta-mediatek-gpl/COPYING.MIT
new file mode 100644
index 0000000..fb950dc
--- /dev/null
+++ b/meta/meta-mediatek-gpl/COPYING.MIT
@@ -0,0 +1,17 @@
+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 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.
diff --git a/meta/meta-mediatek-gpl/LICENSE b/meta/meta-mediatek-gpl/LICENSE
new file mode 100644
index 0000000..79d493b
--- /dev/null
+++ b/meta/meta-mediatek-gpl/LICENSE
@@ -0,0 +1 @@
+All metadata in this layer is MIT licensed unless otherwise stated, see COPYING.MIT.
\ No newline at end of file
diff --git a/meta/meta-mediatek-gpl/classes/hsm-sign-env.bbclass b/meta/meta-mediatek-gpl/classes/hsm-sign-env.bbclass
new file mode 100644
index 0000000..4259bc1
--- /dev/null
+++ b/meta/meta-mediatek-gpl/classes/hsm-sign-env.bbclass
@@ -0,0 +1,33 @@
+python __anonymous () {
+ hsm_env_str = ""
+
+ hsm_support = d.getVar('HSM_SUPPORT', True)
+ if hsm_support != 'yes':
+ d.setVar('HSM_SIGN_TOOL','')
+ d.setVar('HSM_SIGN_PARAM','')
+ d.setVar('HSM_ENV', '')
+ return
+ hsm_env_str += "HSM_SUPPORT=yes "
+
+ top_dir = d.getVar('TOPDIR',True)
+ hsm_sign_tool_dir = top_dir+"/../src/devtools/hsmsigntool/"
+
+ hsm_sign_tool = hsm_sign_tool_dir+"hsm_sign_tool"
+ hsm_env_str += "HSM_SIGN_TOOL=\""+hsm_sign_tool+"\" "
+
+ hsm_sign_tool_conf = d.getVar('HSM_SIGN_TOOL_CONF',True)
+ if hsm_sign_tool_conf is None:
+ hsm_sign_tool_conf = hsm_sign_tool_dir+"hsm_sign_tool.conf"
+ hsm_env_str += "HSM_SIGN_TOOL_CONF=\""+hsm_sign_tool_conf+"\" "
+
+ verified_key = d.getVar('VERIFIED_KEY')
+ hsm_env_str += "VERIFIED_KEY=\""+verified_key+"\" "
+
+ softhsm2_conf = d.getVar('SOFTHSM2_CONF',True)
+ if softhsm2_conf is not None:
+ hsm_env_str += "SOFTHSM2_CONF=\""+softhsm2_conf+"\" "
+
+ d.setVar('HSM_SIGN_TOOL',hsm_sign_tool)
+ d.setVar('HSM_SIGN_PARAM',' --signing_helper '+hsm_sign_tool)
+ d.setVar('HSM_ENV', hsm_env_str)
+}
diff --git a/meta/meta-mediatek-gpl/classes/kernel-fitimage-extension.bbclass b/meta/meta-mediatek-gpl/classes/kernel-fitimage-extension.bbclass
new file mode 100755
index 0000000..188b7d2
--- /dev/null
+++ b/meta/meta-mediatek-gpl/classes/kernel-fitimage-extension.bbclass
@@ -0,0 +1,263 @@
+inherit kernel-uboot-extension hsm-sign-env
+
+python __anonymous () {
+ kerneltype = d.getVar('KERNEL_IMAGETYPE', True)
+ if kerneltype == 'fitImage':
+ depends = d.getVar("DEPENDS", True)
+ depends = "%s u-boot-mkimage-native lz4-native dtc-native" % depends
+ d.setVar("DEPENDS", depends)
+
+ # Override KERNEL_IMAGETYPE_FOR_MAKE variable, which is internal
+ # to kernel.bbclass . We have to override it, since we pack zImage
+ # (at least for now) into the fitImage .
+ kernelarch = d.getVar('KERNEL_ARCH', True)
+ if kernelarch == 'arm':
+ d.setVar("KERNEL_IMAGETYPE_FOR_MAKE", "zImage")
+ elif kernelarch == 'arm64':
+ d.setVar("KERNEL_IMAGETYPE_FOR_MAKE", "Image")
+ else:
+ print("please set KERNEL_ARCH variable.")
+ sys.exit(1)
+ image = d.getVar('INITRAMFS_IMAGE', True)
+ if image:
+ d.appendVarFlag('do_assemble_fitimage', 'depends', ' ${INITRAMFS_IMAGE}:do_image_complete')
+}
+
+#
+# Emit the fitImage ITS header
+#
+fitimage_emit_fit_header() {
+ cat << EOF >> fit-image.its
+/dts-v1/;
+
+/ {
+ description = "U-Boot fitImage for ${DISTRO_NAME}/${PV}/${MACHINE}";
+ #address-cells = <1>;
+EOF
+}
+
+#
+# Emit the fitImage section bits
+#
+# $1 ... Section bit type: imagestart - image section start
+# confstart - configuration section start
+# sectend - section end
+# fitend - fitimage end
+#
+fitimage_emit_section_maint() {
+ case $1 in
+ imagestart)
+ cat << EOF >> fit-image.its
+
+ images {
+EOF
+ ;;
+ confstart)
+ cat << EOF >> fit-image.its
+
+ configurations {
+EOF
+ ;;
+ sectend)
+ cat << EOF >> fit-image.its
+ };
+EOF
+ ;;
+ fitend)
+ cat << EOF >> fit-image.its
+};
+EOF
+ ;;
+ esac
+}
+
+#
+# Emit the fitImage ITS kernel section
+#
+# $1 ... Image counter
+# $2 ... Path to kernel image
+# $3 ... Compression type
+fitimage_emit_section_kernel() {
+
+ kernel_csum="sha256"
+
+ ENTRYPOINT=${UBOOT_ENTRYPOINT}
+ if test -n "${UBOOT_ENTRYSYMBOL}"; then
+ ENTRYPOINT=`${HOST_PREFIX}nm ${S}/vmlinux | \
+ awk '$3=="${UBOOT_ENTRYSYMBOL}" {print $1}'`
+ fi
+
+ cat << EOF >> fit-image.its
+ kernel@${1} {
+ description = "Linux kernel";
+ data = /incbin/("${2}");
+ type = "kernel";
+ arch = "${UBOOT_ARCH}";
+ os = "linux";
+ compression = "${3}";
+ load = <${UBOOT_LOADADDRESS}>;
+ entry = <${ENTRYPOINT}>;
+ hash@1 {
+ algo = "${kernel_csum}";
+ };
+ };
+EOF
+}
+
+#
+# Emit the fitImage ITS DTB section
+#
+# $1 ... Image counter
+# $2 ... Path to DTB image
+fitimage_emit_section_dtb() {
+
+ dtb_csum="sha256"
+
+ cat << EOF >> fit-image.its
+ fdt@${1} {
+ description = "Flattened Device Tree blob";
+ data = /incbin/("${2}");
+ type = "flat_dt";
+ arch = "${UBOOT_ARCH}";
+ compression = "none";
+ load = <${DTB_LOADADDRESS}>;
+ hash@1 {
+ algo = "${dtb_csum}";
+ };
+ };
+EOF
+}
+
+#
+# Emit the fitImage ITS configuration section
+#
+# $1 ... Linux kernel ID
+# $2 ... DTB image ID
+fitimage_emit_section_config() {
+
+ conf_csum="sha256,rsa2048"
+ conf_key_name="dev"
+
+ # Test if we have any DTBs at all
+ if [ -z "${2}" ] ; then
+ conf_desc="Boot Linux kernel"
+ fdt_line=""
+ else
+ conf_desc="Boot Linux kernel with FDT blob"
+ fdt_line="fdt = \"fdt@${2}\";"
+ fi
+ kernel_line="kernel = \"kernel@${1}\";"
+
+ cat << EOF >> fit-image.its
+ default = "conf@1";
+ conf@1 {
+ description = "${conf_desc}";
+ ${kernel_line}
+ ${fdt_line}
+ signature@1 {
+ algo = "${conf_csum}";
+ key-name-hint="${conf_key_name}";
+ sign-images="fdt","kernel";
+ };
+ };
+EOF
+}
+
+do_assemble_fitimage() {
+ cd ${B}
+ if test "x${KERNEL_IMAGETYPE}" = "xfitImage" ; then
+ kernelcount=1
+ dtbcount=""
+ rm -f fit-image.its
+
+ fitimage_emit_fit_header
+
+ #
+ # Step 1: Prepare a kernel image section.
+ #
+ fitimage_emit_section_maint imagestart
+
+ uboot_prep_kimage
+ fitimage_emit_section_kernel "${kernelcount}" linux.bin "${linux_comp}"
+
+ #
+ # Step 2: Prepare a DTB image section
+ #
+ if test -n "${KERNEL_DEVICETREE}"; then
+ dtbcount=1
+ for DTB in ${KERNEL_DEVICETREE}; do
+ if echo ${DTB} | grep -q '/dts/'; then
+ bbwarn "${DTB} contains the full path to the the dts file, but only the dtb name should be used."
+ DTB=`basename ${DTB} | sed 's,\.dts$,.dtb,g'`
+ fi
+
+ # go through device tree blob dir for 32/64 bits kernel
+ DTB_PATH="arch/${ARCH}/boot/dts/mediatek/${DTB}"
+ if [ ! -e "${DTB_PATH}" ]; then
+ DTB_PATH="arch/${ARCH}/boot/dts/${DTB}"
+ if [ ! -e "${DTB_PATH}" ]; then
+ DTB_PATH="arch/${ARCH}/boot/${DTB}"
+ fi
+ fi
+
+ fitimage_emit_section_dtb ${dtbcount} ${DTB_PATH}
+ dtbcount=`expr ${dtbcount} + 1`
+ done
+ fi
+
+ fitimage_emit_section_maint sectend
+
+ # Force the first Kernel and DTB in the default config
+ kernelcount=1
+ dtbcount=1
+
+ #
+ # Step 3: Prepare a configurations section
+ #
+ fitimage_emit_section_maint confstart
+
+ fitimage_emit_section_config ${kernelcount} ${dtbcount}
+
+ fitimage_emit_section_maint sectend
+
+ fitimage_emit_section_maint fitend
+
+ #
+ # Step 4: Assemble the image
+ #
+
+ ${HSM_ENV} HSM_KEY_NAME=${VERIFIED_KEY} uboot-mkimage -f fit-image.its arch/${ARCH}/boot/fitImage
+
+ if [ "${SECURE_BOOT_ENABLE}" = "yes" ]; then
+ mkdir -p ./mykeys
+ cp ${MTK_KEY_DIR}/${VERIFIED_KEY}.crt ./mykeys/dev.crt
+ cp ${MTK_KEY_DIR}/${VERIFIED_KEY}.pem ./mykeys/dev.key
+ ${HSM_ENV} HSM_KEY_NAME=${VERIFIED_KEY} uboot-mkimage -D "-I dts -O dtb -p 1024" -k ./mykeys -f fit-image.its -r arch/${ARCH}/boot/fitImage
+ fi
+ fi
+}
+
+addtask assemble_fitimage before do_install after do_compile
+
+kernel_do_deploy[vardepsexclude] = "DATETIME"
+kernel_do_deploy_append() {
+ # Update deploy directory
+ if test "x${KERNEL_IMAGETYPE}" = "xfitImage" ; then
+ cd ${B}
+ echo "Copying fit-image.its source file..."
+ its_base_name="${KERNEL_IMAGETYPE}-its-${PV}-${PR}-${MACHINE}-${DATETIME}"
+ its_symlink_name=${KERNEL_IMAGETYPE}-its-${MACHINE}
+ install -m 0644 fit-image.its ${DEPLOYDIR}/${its_base_name}.its
+ linux_bin_base_name="${KERNEL_IMAGETYPE}-linux.bin-${PV}-${PR}-${MACHINE}-${DATETIME}"
+ linux_bin_symlink_name=${KERNEL_IMAGETYPE}-linux.bin-${MACHINE}
+ install -m 0644 linux.bin ${DEPLOYDIR}/${linux_bin_base_name}.bin
+ if test -n "${RECOVERY_KERNEL_DEVICETREE}"; then
+ find arch/${ARCH}/boot/dts -name "${RECOVERY_KERNEL_DEVICETREE}" -exec install -m 0644 {} ${DEPLOYDIR}/${RECOVERY_KERNEL_DEVICETREE} \;
+ fi
+
+ cd ${DEPLOYDIR}
+ ln -sf ${its_base_name}.its ${its_symlink_name}.its
+ ln -sf ${linux_bin_base_name}.bin ${linux_bin_symlink_name}.bin
+ ln -nfs ${KERNEL_IMAGETYPE}-${KERNEL_IMAGE_BASE_NAME}.bin boot.img
+ fi
+}
diff --git a/meta/meta-mediatek-gpl/classes/kernel-uboot-extension.bbclass b/meta/meta-mediatek-gpl/classes/kernel-uboot-extension.bbclass
new file mode 100644
index 0000000..f00e622
--- /dev/null
+++ b/meta/meta-mediatek-gpl/classes/kernel-uboot-extension.bbclass
@@ -0,0 +1,44 @@
+uboot_prep_kimage() {
+
+ linux_comp=${KERNEL_COMPRESS}
+
+ # uncompressed elf vmlinux
+ vmlinux_path="vmlinux"
+
+ if test "${linux_comp}" = "lz4"; then
+ linux_suffix=".lz4"
+ elif test "${linux_comp}" = "gzip"; then
+ linux_suffix=".gz"
+ else
+ linux_suffix=""
+ fi
+
+ ${OBJCOPY} -O binary -R .note -R .comment -S "${vmlinux_path}" linux.bin
+
+ if test "${linux_comp}" = "lz4"; then
+ lz4 -l -c1 linux.bin > linux.bin${linux_suffix}
+ # append uncompressed filesize info
+ dec_size=0
+ fsize=$(stat -c "%s" "linux.bin")
+ dec_size=$(expr $dec_size + $fsize)
+ printf "%08x\n" $dec_size |
+ sed 's/\(..\)/\1 /g' | {
+ read ch0 ch1 ch2 ch3;
+ for ch in $ch3 $ch2 $ch1 $ch0; do
+ printf `printf '%s%03o' '\\' 0x$ch` >> linux.bin${linux_suffix};
+ done;
+ }
+ elif test "${linux_comp}" = "gzip"; then
+ gzip -9 linux.bin
+ else
+ echo "For none case or another compressing"
+ fi
+
+ if ! test "${linux_comp}" = "none"; then
+ mv -f "linux.bin${linux_suffix}" linux.bin
+ else
+ echo "No kerenl compression"
+ fi
+
+ echo "${linux_comp}"
+}
diff --git a/meta/meta-mediatek-gpl/classes/ramdisk-fitimage-extension.bbclass b/meta/meta-mediatek-gpl/classes/ramdisk-fitimage-extension.bbclass
new file mode 100755
index 0000000..4b864dc
--- /dev/null
+++ b/meta/meta-mediatek-gpl/classes/ramdisk-fitimage-extension.bbclass
@@ -0,0 +1,328 @@
+inherit kernel-uboot-extension
+
+python __anonymous () {
+ kerneltype = d.getVar('KERNEL_IMAGETYPE', True)
+ if kerneltype == 'fitImage':
+ depends = d.getVar("DEPENDS", True)
+ depends = "%s u-boot-mkimage-native lz4-native dtc-native" % depends
+ d.setVar("DEPENDS", depends)
+
+ # Override KERNEL_IMAGETYPE_FOR_MAKE variable, which is internal
+ # to kernel.bbclass . We have to override it, since we pack zImage
+ # (at least for now) into the fitImage .
+ kernelarch = d.getVar('KERNEL_ARCH', True)
+ if kernelarch == 'arm':
+ d.setVar("KERNEL_IMAGETYPE_FOR_MAKE", "zImage")
+ elif kernelarch == 'arm64':
+ d.setVar("KERNEL_IMAGETYPE_FOR_MAKE", "Image")
+ else:
+ print("please set KERNEL_ARCH variable.")
+ sys.exit(1)
+
+ image = d.getVar('INITRAMFS_IMAGE', True)
+ if image:
+ d.appendVarFlag('do_assemble_fitimage', 'depends', ' ${INITRAMFS_IMAGE}:do_image_complete')
+ d.appendVarFlag('do_assemble_fitimage_ramdisk', 'depends', ' ${INITRAMFS_IMAGE}:do_image_complete')
+}
+
+#
+# Emit the fitImage ITS header
+#
+fitimage_emit_fit_header() {
+ cat << EOF >> fit-image.its
+/dts-v1/;
+
+/ {
+ description = "U-Boot fitImage for ${DISTRO_NAME}/${PV}/${MACHINE}";
+ #address-cells = <1>;
+EOF
+}
+
+#
+# Emit the fitImage section bits
+#
+# $1 ... Section bit type: imagestart - image section start
+# confstart - configuration section start
+# sectend - section end
+# fitend - fitimage end
+#
+fitimage_emit_section_maint() {
+ case $1 in
+ imagestart)
+ cat << EOF >> fit-image.its
+
+ images {
+EOF
+ ;;
+ confstart)
+ cat << EOF >> fit-image.its
+
+ configurations {
+EOF
+ ;;
+ sectend)
+ cat << EOF >> fit-image.its
+ };
+EOF
+ ;;
+ fitend)
+ cat << EOF >> fit-image.its
+};
+EOF
+ ;;
+ esac
+}
+
+#
+# Emit the fitImage ITS kernel section
+#
+# $1 ... Image counter
+# $2 ... Path to kernel image
+# $3 ... Compression type
+fitimage_emit_section_kernel() {
+
+ kernel_csum="sha256"
+
+ ENTRYPOINT=${UBOOT_ENTRYPOINT}
+ if test -n "${UBOOT_ENTRYSYMBOL}"; then
+ ENTRYPOINT=`${HOST_PREFIX}nm ${S}/vmlinux | \
+ awk '$3=="${UBOOT_ENTRYSYMBOL}" {print $1}'`
+ fi
+
+ cat << EOF >> fit-image.its
+ kernel@${1} {
+ description = "Linux kernel";
+ data = /incbin/("${2}");
+ type = "kernel";
+ arch = "${UBOOT_ARCH}";
+ os = "linux";
+ compression = "${3}";
+ load = <${UBOOT_LOADADDRESS}>;
+ entry = <${ENTRYPOINT}>;
+ hash@1 {
+ algo = "${kernel_csum}";
+ };
+ };
+EOF
+}
+
+#
+# Emit the fitImage ITS ramdisk section
+#
+# $1 ... Image counter
+# $2 ... Path to ramdifk image
+fitimage_emit_section_ramdisk() {
+
+ ramdisk_csum="sha256"
+
+ cat << EOF >> fit-image.its
+ ramdisk@${1} {
+ description = "Ramdisk Image";
+ data = /incbin/("${2}");
+ type = "ramdisk";
+ arch = "${UBOOT_ARCH}";
+ os = "linux";
+ compression = "none";
+ load = <${RAMDISK_LOADADDRESS}>;
+ entry = <${RAMDISK_LOADADDRESS}>;
+ hash@1 {
+ algo = "${ramdisk_csum}";
+ };
+ };
+EOF
+}
+
+#
+# Emit the fitImage ITS DTB section
+#
+# $1 ... Image counter
+# $2 ... Path to DTB image
+fitimage_emit_section_dtb() {
+
+ dtb_csum="sha256"
+
+ cat << EOF >> fit-image.its
+ fdt@${1} {
+ description = "Flattened Device Tree blob";
+ data = /incbin/("${2}");
+ type = "flat_dt";
+ arch = "${UBOOT_ARCH}";
+ compression = "none";
+ load = <${DTB_LOADADDRESS}>;
+ hash@1 {
+ algo = "${dtb_csum}";
+ };
+ };
+EOF
+}
+
+#
+# Emit the fitImage ITS configuration section
+#
+# $1 ... Linux kernel ID
+# $2 ... DTB image ID
+# $3 ... Ramdisk ID
+fitimage_emit_section_config() {
+
+ conf_csum="sha256,rsa2048"
+ conf_key_name="dev"
+
+ # Test if we have any DTBs at all
+ if [ -z "${2}" ] ; then
+ conf_desc="Boot Linux kernel"
+ fdt_line=""
+ else
+ conf_desc="Boot Linux kernel with FDT blob"
+ fdt_line="fdt = \"fdt@${2}\";"
+ fi
+ kernel_line="kernel = \"kernel@${1}\";"
+
+ # Test if we have ramdisk image
+ if [ -z "${3}" ] ; then
+ ramdisk_line=""
+ else
+ ramdisk_line="ramdisk = \"ramdisk@${3}\";"
+ fi
+
+ cat << EOF >> fit-image.its
+ default = "conf@1";
+ conf@1 {
+ description = "${conf_desc}";
+ ${kernel_line}
+ ${ramdisk_line}
+ ${fdt_line}
+ signature@1 {
+ algo = "${conf_csum}";
+ key-name-hint="${conf_key_name}";
+ sign-images="fdt","kernel";
+ };
+ };
+EOF
+}
+
+#
+# Assemble the ITS format
+#
+# $1 ... Ramdisk ID
+do_assemble_fitimage() {
+ cd ${B}
+ if test "x${KERNEL_IMAGETYPE}" = "xfitImage" ; then
+ kernelcount=1
+ dtbcount=""
+ ramdiskcount="${1}"
+ rm -f fit-image.its
+
+ fitimage_emit_fit_header
+
+ #
+ # Step 1: Prepare a kernel image section.
+ #
+ fitimage_emit_section_maint imagestart
+
+ uboot_prep_kimage
+ fitimage_emit_section_kernel "${kernelcount}" linux.bin "${linux_comp}"
+
+ # Step 1.5: Prepare a ramdisk image section.
+ #
+ if [ "x${ramdiskcount}" = "x1" ] ; then
+ fitimage_emit_section_ramdisk ${ramdiskcount} ${RAMDISK_PATH}
+ fi
+
+ #
+ # Step 2: Prepare a DTB image section
+ #
+ if test -n "${KERNEL_DEVICETREE}"; then
+ dtbcount=1
+ for DTB in ${KERNEL_DEVICETREE}; do
+ if echo ${DTB} | grep -q '/dts/'; then
+ bbwarn "${DTB} contains the full path to the the dts file, but only the dtb name should be used."
+ DTB=`basename ${DTB} | sed 's,\.dts$,.dtb,g'`
+ fi
+
+ # go through device tree blob dir for 32/64 bits kernel
+ DTB_PATH="arch/${ARCH}/boot/dts/mediatek/${DTB}"
+ if [ ! -e "${DTB_PATH}" ]; then
+ DTB_PATH="arch/${ARCH}/boot/dts/${DTB}"
+ if [ ! -e "${DTB_PATH}" ]; then
+ DTB_PATH="arch/${ARCH}/boot/${DTB}"
+ fi
+ fi
+
+ fitimage_emit_section_dtb ${dtbcount} ${DTB_PATH}
+ dtbcount=`expr ${dtbcount} + 1`
+ done
+ fi
+
+ fitimage_emit_section_maint sectend
+
+ # Force the first Kernel and DTB in the default config
+ kernelcount=1
+ dtbcount=1
+
+ #
+ # Step 3: Prepare a configurations section
+ #
+ fitimage_emit_section_maint confstart
+
+ fitimage_emit_section_config ${kernelcount} ${dtbcount} ${ramdiskcount}
+
+ fitimage_emit_section_maint sectend
+
+ fitimage_emit_section_maint fitend
+
+ #
+ # Step 4: Assemble the image
+ #
+
+ uboot-mkimage -f fit-image.its arch/${ARCH}/boot/fitImage
+
+ if [ "${SECURE_BOOT_ENABLE}" = "yes" ]; then
+ mkdir -p ./mykeys
+ cp ${MTK_KEY_DIR}/${VERIFIED_KEY}.crt ./mykeys/dev.crt
+ cp ${MTK_KEY_DIR}/${VERIFIED_KEY}.pem ./mykeys/dev.key
+ uboot-mkimage -D "-I dts -O dtb -p 1024" -k ./mykeys -f fit-image.its -r arch/${ARCH}/boot/fitImage
+ fi
+ fi
+}
+
+do_assemble_fitimage_kernel() {
+ if test "x${KERNEL_IMAGETYPE}" = "xfitImage" ; then
+ do_assemble_fitimage
+ fi
+}
+
+do_assemble_fitimage_ramdisk() {
+ if test "x${KERNEL_IMAGETYPE}" = "xfitImage" -a -n "${INITRAMFS_IMAGE}" ; then
+ do_assemble_fitimage 1
+ fi
+}
+
+addtask assemble_fitimage_kernel before do_install after do_compile
+addtask assemble_fitimage_ramdisk before do_deploy after do_install
+
+kernel_do_deploy[vardepsexclude] = "DATETIME"
+kernel_do_deploy_append() {
+ # Update deploy directory
+ if test "x${KERNEL_IMAGETYPE}" = "xfitImage" ; then
+ cd ${B}
+ echo "Copying fit-image.its source file..."
+ its_base_name="${KERNEL_IMAGETYPE}-its-${PV}-${PR}-${MACHINE}-${DATETIME}"
+ its_symlink_name=${KERNEL_IMAGETYPE}-its-${MACHINE}
+ install -m 0644 fit-image.its ${DEPLOYDIR}/${its_base_name}.its
+ linux_bin_base_name="${KERNEL_IMAGETYPE}-linux.bin-${PV}-${PR}-${MACHINE}-${DATETIME}"
+ linux_bin_symlink_name=${KERNEL_IMAGETYPE}-linux.bin-${MACHINE}
+ install -m 0644 linux.bin ${DEPLOYDIR}/${linux_bin_base_name}.bin
+ if test -n "${RECOVERY_KERNEL_DEVICETREE}"; then
+ find arch/${ARCH}/boot/dts -name "${RECOVERY_KERNEL_DEVICETREE}" -exec install -m 0644 {} ${DEPLOYDIR}/${RECOVERY_KERNEL_DEVICETREE} \;
+ fi
+
+ cd ${DEPLOYDIR}
+ ln -sf ${its_base_name}.its ${its_symlink_name}.its
+ ln -sf ${linux_bin_base_name}.bin ${linux_bin_symlink_name}.bin
+ ln -nfs ${KERNEL_IMAGETYPE}-${KERNEL_IMAGE_BASE_NAME}.bin boot.img
+ fi
+}
+
+do_bundle_initramfs() {
+ :
+}
diff --git a/meta/meta-mediatek-gpl/classes/recovery-kernel-fitimage.bbclass b/meta/meta-mediatek-gpl/classes/recovery-kernel-fitimage.bbclass
new file mode 100755
index 0000000..d92d7ab
--- /dev/null
+++ b/meta/meta-mediatek-gpl/classes/recovery-kernel-fitimage.bbclass
@@ -0,0 +1,243 @@
+inherit kernel-uboot-extension
+
+python __anonymous () {
+ kerneltype = d.getVar('KERNEL_IMAGETYPE', True)
+ recoverykerneldevicetree = d.getVar('RECOVERY_KERNEL_DEVICETREE', True)
+ if kerneltype == 'fitImage' and recoverykerneldevicetree != '' :
+ depends = d.getVar("DEPENDS", True)
+ depends = "%s u-boot-mkimage-native lz4-native dtc-native" % depends
+ d.setVar("DEPENDS", depends)
+
+ # Override KERNEL_IMAGETYPE_FOR_MAKE variable, which is internal
+ # to kernel.bbclass . We have to override it, since we pack zImage
+ # (at least for now) into the fitImage .
+ kernelarch = d.getVar('KERNEL_ARCH', True)
+ if kernelarch == 'arm':
+ d.setVar("KERNEL_IMAGETYPE_FOR_MAKE", "zImage")
+ elif kernelarch == 'arm64':
+ d.setVar("KERNEL_IMAGETYPE_FOR_MAKE", "Image")
+ else:
+ print("please set KERNEL_ARCH variable.")
+ sys.exit(1)
+}
+
+#
+# Emit the fitImage ITS header
+#
+fit_recovery_image_emit_fit_header() {
+ cat << EOF >> fit-recovery-image.its
+/dts-v1/;
+
+/ {
+ description = "U-Boot fitImage for ${DISTRO_NAME}/${PV}/${MACHINE}";
+ #address-cells = <1>;
+EOF
+}
+
+#
+# Emit the fitImage section bits
+#
+# $1 ... Section bit type: imagestart - image section start
+# confstart - configuration section start
+# sectend - section end
+# fitend - fitimage end
+#
+fit_recovery_image_emit_section_maint() {
+ case $1 in
+ imagestart)
+ cat << EOF >> fit-recovery-image.its
+
+ images {
+EOF
+ ;;
+ confstart)
+ cat << EOF >> fit-recovery-image.its
+
+ configurations {
+EOF
+ ;;
+ sectend)
+ cat << EOF >> fit-recovery-image.its
+ };
+EOF
+ ;;
+ fitend)
+ cat << EOF >> fit-recovery-image.its
+};
+EOF
+ ;;
+ esac
+}
+
+#
+# Emit the fitImage ITS kernel section
+#
+# $1 ... Image counter
+# $2 ... Path to kernel image
+# $3 ... Compression type
+fit_recovery_image_emit_section_kernel() {
+
+ kernel_csum="sha256"
+
+ ENTRYPOINT=${UBOOT_ENTRYPOINT}
+ if test -n "${UBOOT_ENTRYSYMBOL}"; then
+ ENTRYPOINT=`${HOST_PREFIX}nm ${S}/vmlinux | \
+ awk '$3=="${UBOOT_ENTRYSYMBOL}" {print $1}'`
+ fi
+
+ cat << EOF >> fit-recovery-image.its
+ kernel@${1} {
+ description = "Linux kernel";
+ data = /incbin/("${2}");
+ type = "kernel";
+ arch = "${UBOOT_ARCH}";
+ os = "linux";
+ compression = "${3}";
+ load = <${UBOOT_LOADADDRESS}>;
+ entry = <${ENTRYPOINT}>;
+ hash@1 {
+ algo = "${kernel_csum}";
+ };
+ };
+EOF
+}
+
+#
+# Emit the fitImage ITS DTB section
+#
+# $1 ... Image counter
+# $2 ... Path to DTB image
+fit_recovery_image_emit_section_dtb() {
+
+ dtb_csum="sha256"
+
+ cat << EOF >> fit-recovery-image.its
+ fdt@${1} {
+ description = "Flattened Device Tree blob";
+ data = /incbin/("${2}");
+ type = "flat_dt";
+ arch = "${UBOOT_ARCH}";
+ compression = "none";
+ load = <${DTB_LOADADDRESS}>;
+ hash@1 {
+ algo = "${dtb_csum}";
+ };
+ };
+EOF
+}
+
+#
+# Emit the fitImage ITS configuration section
+#
+# $1 ... Linux kernel ID
+# $2 ... DTB image ID
+fit_recovery_image_emit_section_config() {
+
+ conf_csum="sha256,rsa2048"
+ conf_key_name="dev"
+
+ # Test if we have any DTBs at all
+ if [ -z "${2}" ] ; then
+ conf_desc="Boot Linux kernel"
+ fdt_line=""
+ else
+ conf_desc="Boot Linux kernel with FDT blob"
+ fdt_line="fdt = \"fdt@${2}\";"
+ fi
+ kernel_line="kernel = \"kernel@${1}\";"
+
+ cat << EOF >> fit-recovery-image.its
+ default = "conf@1";
+ conf@1 {
+ description = "${conf_desc}";
+ ${kernel_line}
+ ${fdt_line}
+ signature@1 {
+ algo = "${conf_csum}";
+ key-name-hint="${conf_key_name}";
+ sign-images="fdt","kernel";
+ };
+ };
+EOF
+}
+
+do_assemble_recovery_fitimage() {
+ cd ${B}
+ if test "x${KERNEL_IMAGETYPE}" = "xfitImage" && test -n "${RECOVERY_KERNEL_DEVICETREE}"; then
+ kernelcount=1
+ dtbcount=""
+ rm -f fit-recovery-image.its
+
+ fit_recovery_image_emit_fit_header
+
+ #
+ # Step 1: Prepare a kernel image section.
+ #
+ fit_recovery_image_emit_section_maint imagestart
+
+ uboot_prep_kimage
+ fit_recovery_image_emit_section_kernel "${kernelcount}" linux.bin "${linux_comp}"
+
+ #
+ # Step 2: Prepare a DTB image section
+ #
+ dtbcount=1
+ for DTB in ${RECOVERY_KERNEL_DEVICETREE}; do
+ if echo ${DTB} | grep -q '/dts/'; then
+ bbwarn "${DTB} contains the full path to the the dts file, but only the dtb name should be used."
+ DTB=`basename ${DTB} | sed 's,\.dts$,.dtb,g'`
+ fi
+
+ # go through device tree blob dir for 32/64 bits kernel
+ DTB_PATH="arch/${ARCH}/boot/dts/mediatek/${DTB}"
+ if [ ! -e "${DTB_PATH}" ]; then
+ DTB_PATH="arch/${ARCH}/boot/dts/${DTB}"
+ if [ ! -e "${DTB_PATH}" ]; then
+ DTB_PATH="arch/${ARCH}/boot/${DTB}"
+ fi
+ fi
+
+ fit_recovery_image_emit_section_dtb ${dtbcount} ${DTB_PATH}
+ dtbcount=`expr ${dtbcount} + 1`
+ done
+
+ fit_recovery_image_emit_section_maint sectend
+ # Force the first Kernel and DTB in the default config
+ kernelcount=1
+ dtbcount=1
+
+ #
+ # Step 3: Prepare a configurations section
+ #
+ fit_recovery_image_emit_section_maint confstart
+
+ fit_recovery_image_emit_section_config ${kernelcount} ${dtbcount}
+
+ fit_recovery_image_emit_section_maint sectend
+
+ fit_recovery_image_emit_section_maint fitend
+
+ #
+ # Step 4: Assemble the image
+ #
+ uboot-mkimage -f fit-recovery-image.its arch/${ARCH}/boot/fitRecoveryImage
+
+ if [ "${SECURE_BOOT_ENABLE}" = "yes" ]; then
+ mkdir -p ./mykeys
+ cp ${MTK_KEY_DIR}/${VERIFIED_KEY}.crt ./mykeys/dev.crt
+ cp ${MTK_KEY_DIR}/${VERIFIED_KEY}.pem ./mykeys/dev.key
+ uboot-mkimage -D "-I dts -O dtb -p 1024" -k ./mykeys -f fit-recovery-image.its -r arch/${ARCH}/boot/fitRecoveryImage
+ fi
+ fi
+}
+
+addtask assemble_recovery_fitimage before do_install after do_compile
+
+kernel_do_deploy_append() {
+ # Update deploy directory
+ if test "x${KERNEL_IMAGETYPE}" = "xfitImage" && test -n "${RECOVERY_KERNEL_DEVICETREE}"; then
+ cd ${B}
+ install -m 0644 fit-recovery-image.its ${DEPLOYDIR}/fit-recovery-image.its
+ install -m 0644 arch/${ARCH}/boot/fitRecoveryImage ${DEPLOYDIR}/recovery.img
+ fi
+}
diff --git a/meta/meta-mediatek-gpl/classes/u-boot-fitimage.bbclass b/meta/meta-mediatek-gpl/classes/u-boot-fitimage.bbclass
new file mode 100644
index 0000000..66fc82a
--- /dev/null
+++ b/meta/meta-mediatek-gpl/classes/u-boot-fitimage.bbclass
@@ -0,0 +1,185 @@
+
+python __anonymous () {
+ depends = d.getVar("DEPENDS", True)
+ depends = "%s u-boot-mkimage-native" % depends
+ d.setVar("DEPENDS", depends)
+}
+
+#
+# Emit the fitImage ITS header
+#
+fitimage_emit_fit_header() {
+ cat << EOF >> ${WORKDIR}/fit-image.its
+/dts-v1/;
+
+/ {
+ description = "U-Boot fitImage for ${DISTRO_NAME}/${PV}/${MACHINE}";
+ #address-cells = <1>;
+EOF
+}
+
+#
+# Emit the fitImage section bits
+#
+# $1 ... Section bit type: imagestart - image section start
+# confstart - configuration section start
+# sectend - section end
+# fitend - fitimage end
+#
+fitimage_emit_section_maint() {
+ case $1 in
+ imagestart)
+ cat << EOF >> ${WORKDIR}/fit-image.its
+
+ images {
+EOF
+ ;;
+ confstart)
+ cat << EOF >> ${WORKDIR}/fit-image.its
+
+ configurations {
+EOF
+ ;;
+ sectend)
+ cat << EOF >> ${WORKDIR}/fit-image.its
+ };
+EOF
+ ;;
+ fitend)
+ cat << EOF >> ${WORKDIR}/fit-image.its
+};
+EOF
+ ;;
+ esac
+}
+
+#
+# Emit the fitImage ITS u-boot section
+#
+# $1 ... Path to u-boot image
+# $2 ... Compression type
+fitimage_emit_section_uboot() {
+
+ uboot_csum="sha256"
+
+ cat << EOF >> ${WORKDIR}/fit-image.its
+ uboot@1 {
+ description = "U-Boot";
+ data = /incbin/("${1}");
+ type = "uboot";
+ arch = "arm";
+ os = "linux";
+ compression = "${2}";
+ load = <${UBOOT_FIT_LOADADDRESS}>;
+ entry = <${UBOOT_FIT_ENTRYPOINT}>;
+ hash@1 {
+ algo = "${uboot_csum}";
+ };
+ };
+EOF
+}
+
+#
+# Emit the fitImage ITS DTB section
+#
+# $1 ... Image counter
+# $2 ... Path to DTB image
+fitimage_emit_section_dtb() {
+
+ dtb_csum="sha256"
+
+ cat << EOF >> ${WORKDIR}/fit-image.its
+ fdt@1 {
+ description = "sig blob for u-boot verified boot";
+ data = /incbin/("${1}");
+ type = "uboot";
+ arch = "arm";
+ os = "linux";
+ compression = "${2}";
+ load = <${UBOOT_DTB_LOADADDRESS}>;
+ entry = <${UBOOT_DTB_LOADADDRESS}>;
+ hash@1 {
+ algo = "${dtb_csum}";
+ };
+ };
+EOF
+}
+
+#
+# Emit the fitImage ITS configuration section
+#
+# $1 ... u-boot image ID
+fitimage_emit_section_config() {
+
+ conf_csum="sha256,rsa2048"
+ conf_key_name="dev"
+
+ conf_desc="${MTK_PROJECT} configuration"
+
+ uboot_line="uboot = \"uboot@1\";"
+ if [ "${SECURE_BOOT_ENABLE}" = "yes" ]; then
+ fdt_line="fdt = \"fdt@1\";"
+ else
+ fdt_line=""
+ fi
+
+ cat << EOF >> ${WORKDIR}/fit-image.its
+ default = "conf@1";
+ conf@1 {
+ description = "${conf_desc}";
+ ${uboot_line}
+ ${fdt_line}
+ signature@1 {
+ algo = "${conf_csum}";
+ key-name-hint="${conf_key_name}";
+ sign-images="fdt","uboot";
+ };
+ };
+EOF
+}
+
+do_assemble_fitimage() {
+
+ rm -f ${WORKDIR}/fit-image.its
+
+ fitimage_emit_fit_header
+
+ #
+ # Step 1: Prepare a u-boot image section.
+ #
+ fitimage_emit_section_maint imagestart
+
+ fitimage_emit_section_uboot ${UBOOT_OUT}/${UBOOT_BINARY} ${UBOOT_COMPRESS}
+
+ if [ "${SECURE_BOOT_ENABLE}" = "yes" ]; then
+ fitimage_emit_section_dtb ${UBOOT_OUT}/sig_blob.dtb none
+ fi
+
+ fitimage_emit_section_maint sectend
+
+ #
+ # Step 2: Prepare a configurations section
+ #
+ fitimage_emit_section_maint confstart
+
+ fitimage_emit_section_config
+
+ fitimage_emit_section_maint sectend
+
+ fitimage_emit_section_maint fitend
+
+ #
+ # Step 3: Assemble the image
+ #
+ uboot-mkimage -f ${WORKDIR}/fit-image.its ${UBOOT_OUT}/${UBOOT_FIT_IMAGE}
+
+ if [ "${SECURE_BOOT_ENABLE}" = "yes" ]; then
+ mkdir -p ./mykeys
+ cp ${MTK_KEY_DIR}/${VERIFIED_KEY}.crt ./mykeys/dev.crt
+ cp ${MTK_KEY_DIR}/${VERIFIED_KEY}.pem ./mykeys/dev.key
+ uboot-mkimage -D "-I dts -O dtb -p 1024" -k ./mykeys -f ${WORKDIR}/fit-image.its -r ${UBOOT_OUT}/${UBOOT_FIT_IMAGE}
+ fi
+}
+
+addtask assemble_fitimage before do_install after do_compile
+
diff --git a/meta/meta-mediatek-gpl/classes/workonsrc.bbclass b/meta/meta-mediatek-gpl/classes/workonsrc.bbclass
new file mode 100755
index 0000000..74a6b77
--- /dev/null
+++ b/meta/meta-mediatek-gpl/classes/workonsrc.bbclass
@@ -0,0 +1,281 @@
+# Copyright (C) 2017 Mediatek
+# Author: Richard Sun
+# Some code and influence taken from externalsrc.bbclass:
+# Copyright (C) 2012 Linux Foundation
+# Author: Richard Purdie
+# Some code and influence taken from srctree.bbclass:
+# Copyright (C) 2009 Chris Larson <clarson@kergoth.com>
+# Released under the MIT license (see COPYING.MIT for the terms)
+#
+# workonsrc.bbclass enables use of an existing source tree, usually workon to
+# the build system to build a piece of software rather than the usual fetch/unpack/patch
+# process.
+#
+# To use, add workonsrc to the global inherit and set WORKONSRC to point at the
+# directory you want to use containing the sources e.g. from local.conf for a recipe
+# called "myrecipe" you would do:
+#
+# INHERIT += "workonsrc"
+# WORKONSRC_pn-myrecipe = "/path/to/my/source/tree"
+#
+# In order to make this class work for both target and native versions (or with
+# multilibs/cross or other BBCLASSEXTEND variants), B is set to point to a separate
+# directory under the work directory (split source and build directories). This is
+# the default, but the build directory can be set to the source directory if
+# circumstances dictate by setting WORKONSRC_BUILD to the same value, e.g.:
+#
+# WORKONSRC_BUILD_pn-myrecipe = "/path/to/my/source/tree"
+#
+
+SRCTREECOVEREDTASKS ?= "do_patch do_unpack do_fetch"
+EXTERNALSRC_SYMLINKS ?= "oe-workdir:${WORKDIR} oe-logs:${T}"
+
+python () {
+ import subprocess, os.path
+
+ depends = d.getVar("DEPENDS")
+ depends = "%s rsync-native" % depends
+ d.setVar("DEPENDS", depends)
+
+ pn = d.getVar('PN')
+ d.appendVarFlag('do_populate_lic', 'depends', ' %s:do_configure' % pn)
+ workonsrc = d.getVar('WORKONSRC')
+ workonprebuilt = workonsrc.replace("build/../src/", "build/../prebuilt/")
+ if not os.path.exists(workonsrc):
+ if os.path.exists(workonprebuilt):
+ workonsrc = workonprebuilt
+ else:
+ bb.warn("Both %s and %s aren't existed" % (workonsrc, workonprebuilt) )
+
+ # If this is the base recipe and WORKONSRC is set for it or any of its
+ # derivatives, then enable BB_DONT_CACHE to force the recipe to always be
+ # re-parsed so that the file-checksums function for do_compile is run every
+ # time.
+ bpn = d.getVar('BPN')
+ if bpn == d.getVar('PN'):
+ classextend = (d.getVar('BBCLASSEXTEND') or '').split()
+ if (workonsrc or
+ ('native' in classextend and
+ d.getVar('WORKONSRC_pn-%s-native' % bpn)) or
+ ('nativesdk' in classextend and
+ d.getVar('WORKONSRC_pn-nativesdk-%s' % bpn)) or
+ ('cross' in classextend and
+ d.getVar('WORKONSRC_pn-%s-cross' % bpn))):
+ d.setVar('BB_DONT_CACHE', '1')
+
+ if workonsrc:
+ d.setVar('S', workonsrc)
+ workonsrcbuild = d.getVar('WORKONSRC_BUILD')
+ if workonsrcbuild:
+ d.setVar('B', workonsrcbuild)
+ else:
+ d.setVar('B', '${WORKDIR}/${BPN}-${PV}/')
+ workonsrcbuild = d.getVar('B')
+
+ if workonsrc != workonsrcbuild:
+ d.setVar('S', workonsrcbuild)
+
+ local_srcuri = []
+ fetch = bb.fetch2.Fetch((d.getVar('SRC_URI') or '').split(), d)
+ for url in fetch.urls:
+ url_data = fetch.ud[url]
+ parm = url_data.parm
+ if (url_data.type == 'file' or
+ 'type' in parm and parm['type'] == 'kmeta'):
+ local_srcuri.append(url)
+
+ d.setVar('SRC_URI', ' '.join(local_srcuri))
+
+ if '{SRCPV}' in d.getVar('PV', False):
+ # Dummy value because the default function can't be called with blank SRC_URI
+ d.setVar('SRCPV', '999')
+
+ tasks = filter(lambda k: d.getVarFlag(k, "task"), d.keys())
+
+ for task in tasks:
+ if task.endswith("_setscene"):
+ # sstate is never going to work for workon source trees, disable it
+ bb.build.deltask(task, d)
+ else:
+ # Since configure will likely touch ${S}, ensure only we lock so one task has access at a time
+ d.appendVarFlag(task, "lockfiles", " ${S}/singletask.lock")
+
+ # We do not want our source to be wiped out, ever (kernel.bbclass does this for do_clean)
+ cleandirs = (d.getVarFlag(task, 'cleandirs', False) or '').split()
+ setvalue = False
+ for cleandir in cleandirs[:]:
+ if d.expand(cleandir) == workonsrc:
+ cleandirs.remove(cleandir)
+ setvalue = True
+ if setvalue:
+ d.setVarFlag(task, 'cleandirs', ' '.join(cleandirs))
+
+ fetch_tasks = ['do_fetch', 'do_unpack']
+ # If we deltask do_patch, there's no dependency to ensure do_unpack gets run, so add one
+ # Note that we cannot use d.appendVarFlag() here because deps is expected to be a list object, not a string
+ d.setVarFlag('do_configure', 'deps', (d.getVarFlag('do_configure', 'deps', False) or []) + ['do_unpack'])
+
+ for task in d.getVar("SRCTREECOVEREDTASKS").split():
+ if local_srcuri and task in fetch_tasks:
+ continue
+ bb.build.deltask(task, d)
+
+ d.prependVarFlag('do_compile', 'prefuncs', "workonsrc_compile_prefunc ")
+ d.prependVarFlag('do_configure', 'prefuncs', "workonsrc_configure_prefunc ")
+
+ d.setVarFlag('do_compile', 'file-checksums', '${@srctree_hash_files(d)}')
+ d.setVarFlag('do_configure', 'file-checksums', '${@srctree_configure_hash_files(d)}')
+
+ # We don't want the workdir to go away
+ d.appendVar('RM_WORK_EXCLUDE', ' ' + d.getVar('PN'))
+
+ bb.build.addtask('do_buildclean',
+ 'do_clean' if d.getVar('S') == d.getVar('B') else None,
+ None, d)
+
+
+ # If B=S the same builddir is used even for different architectures.
+ # Thus, use a shared CONFIGURESTAMPFILE and STAMP directory so that
+ # change of do_configure task hash is correctly detected and stamps are
+ # invalidated if e.g. MACHINE changes.
+ if d.getVar('S') == d.getVar('B'):
+ configstamp = '${TMPDIR}/work-shared/${PN}/${EXTENDPE}${PV}-${PR}/configure.sstate'
+ d.setVar('CONFIGURESTAMPFILE', configstamp)
+ d.setVar('STAMP', '${STAMPS_DIR}/work-shared/${PN}/${EXTENDPE}${PV}-${PR}')
+ d.setVar('STAMPCLEAN', '${STAMPS_DIR}/work-shared/${PN}/*-*')
+}
+
+python workonsrc_configure_prefunc() {
+ srctree_rsync_files(d)
+ s_dir = d.getVar('S')
+ # Create desired symlinks
+ symlinks = (d.getVar('EXTERNALSRC_SYMLINKS') or '').split()
+ newlinks = []
+ for symlink in symlinks:
+ symsplit = symlink.split(':', 1)
+ lnkfile = os.path.join(s_dir, symsplit[0])
+ target = d.expand(symsplit[1])
+ if len(symsplit) > 1:
+ if os.path.islink(lnkfile):
+ # Link already exists, leave it if it points to the right location already
+ if os.readlink(lnkfile) == target:
+ continue
+ os.unlink(lnkfile)
+ elif os.path.exists(lnkfile):
+ # File/dir exists with same name as link, just leave it alone
+ continue
+ os.symlink(target, lnkfile)
+ newlinks.append(symsplit[0])
+ # Hide the symlinks from git
+ try:
+ git_exclude_file = os.path.join(s_dir, '.git/info/exclude')
+ if os.path.exists(git_exclude_file):
+ with open(git_exclude_file, 'r+') as efile:
+ elines = efile.readlines()
+ for link in newlinks:
+ if link in elines or '/'+link in elines:
+ continue
+ efile.write('/' + link + '\n')
+ except IOError as ioe:
+ bb.note('Failed to hide EXTERNALSRC_SYMLINKS from git')
+}
+
+python workonsrc_compile_prefunc() {
+ srctree_rsync_files(d)
+ # Make it obvious that this is happening, since forgetting about it could lead to much confusion
+ bb.plain('NOTE: %s: compiling from workon source tree %s' % (d.getVar('PN'), d.getVar('WORKONSRC')))
+}
+
+do_buildclean[dirs] = "${S} ${B}"
+do_buildclean[nostamp] = "1"
+do_buildclean[doc] = "Call 'make clean' or equivalent in ${B}"
+workonsrc_do_buildclean() {
+ if [ -e Makefile -o -e makefile -o -e GNUmakefile ]; then
+ oe_runmake clean || die "make failed"
+ else
+ bbnote "nothing to do - no makefile found"
+ fi
+}
+
+def srctree_rsync_files(d):
+ import subprocess, os.path
+
+ workonsrc = d.getVar('WORKONSRC')
+ workonprebuilt = workonsrc.replace("build/../src/", "build/../prebuilt/")
+ if not os.path.exists(workonsrc):
+ if os.path.exists(workonprebuilt):
+ workonsrc = workonprebuilt
+ else:
+ bb.warn("Both %s and %s aren't existed" % (workonsrc, workonprebuilt) )
+
+ if workonsrc:
+ d.setVar('S', workonsrc)
+ workonsrcbuild = d.getVar('WORKONSRC_BUILD')
+ if workonsrcbuild:
+ d.setVar('B', workonsrcbuild)
+ else:
+ d.setVar('B', '${WORKDIR}/${BPN}-${PV}/')
+ workonsrcbuild = d.getVar('B')
+
+ if workonsrc != workonsrcbuild:
+ cmd = "mkdir -p %s" % (workonsrcbuild)
+ subprocess.call(cmd, shell=True)
+
+ if os.path.exists(workonsrc):
+ workonsrc_rsync_appended_flag = d.getVar('WORKONSRC_RSYNC_APPENDED_FLAG')
+ if workonsrc_rsync_appended_flag is None:
+ workonsrc_rsync_appended_flag=""
+ cmd = "rsync -aL %s %s/* %s" % (workonsrc_rsync_appended_flag, workonsrc, workonsrcbuild)
+ ret = subprocess.call(cmd, shell=True)
+ if ret != 0:
+ bb.fatal("rsync -aL %s %s/* %s failed." % (workonsrc_rsync_appended_flag, workonsrc, workonsrcbuild))
+ d.setVar('S', workonsrcbuild)
+
+def srctree_hash_files(d, srcdir=None):
+ import shutil
+ import subprocess
+ import tempfile
+
+ s_dir = srcdir or d.getVar('WORKONSRC')
+ git_dir = os.path.join(s_dir, '.git')
+ oe_hash_file = os.path.join(git_dir, 'oe-devtool-tree-sha1')
+
+ ret = " "
+ if os.path.exists(git_dir):
+ with tempfile.NamedTemporaryFile(dir=git_dir, prefix='oe-devtool-index') as tmp_index:
+ # Clone index
+ shutil.copy2(os.path.join(git_dir, 'index'), tmp_index.name)
+ # Update our custom index
+ env = os.environ.copy()
+ env['GIT_INDEX_FILE'] = tmp_index.name
+ subprocess.check_output(['git', 'add', '-A', '.'], cwd=s_dir, env=env)
+ sha1 = subprocess.check_output(['git', 'write-tree'], cwd=s_dir, env=env).decode("utf-8")
+ with open(oe_hash_file, 'w') as fobj:
+ fobj.write(sha1)
+ ret = oe_hash_file + ':True'
+ else:
+ ret = s_dir + '/*:True'
+ return ret
+
+def srctree_configure_hash_files(d):
+ """
+ Get the list of files that should trigger do_configure to re-execute,
+ based on the value of CONFIGURE_FILES
+ """
+ in_files = (d.getVar('CONFIGURE_FILES') or '').split()
+ out_items = []
+ search_files = []
+ for entry in in_files:
+ if entry.startswith('/'):
+ out_items.append('%s:%s' % (entry, os.path.exists(entry)))
+ else:
+ search_files.append(entry)
+ if search_files:
+ s_dir = d.getVar('WORKONSRC')
+ for root, _, files in os.walk(s_dir):
+ for f in files:
+ if f in search_files:
+ out_items.append('%s:True' % os.path.join(root, f))
+ return ' '.join(out_items)
+
+EXPORT_FUNCTIONS do_buildclean
diff --git a/meta/meta-mediatek-gpl/conf/distro/include/default-providers-basic.inc b/meta/meta-mediatek-gpl/conf/distro/include/default-providers-basic.inc
new file mode 100644
index 0000000..7b933ed
--- /dev/null
+++ b/meta/meta-mediatek-gpl/conf/distro/include/default-providers-basic.inc
@@ -0,0 +1,13 @@
+#
+# Default virtual providers
+#
+PREFERRED_PROVIDER_virtual/arm-oe-linux-gnueabi-depmod ?= "kmod-cross"
+PREFERRED_PROVIDER_udev ?= "systemd"
+PREFERRED_PROVIDER_udev-utils ?= "systemd"
+PREFERRED_PROVIDER_node-state-manager ?= "node-state-manager"
+
+#
+# Default jpeg provider
+#
+PREFERRED_PROVIDER_jpeg ?= "jpeg"
+PREFERRED_PROVIDER_jpeg-native ?= "jpeg-native"
diff --git a/meta/meta-mediatek-gpl/conf/distro/poky-basic-systemd.conf b/meta/meta-mediatek-gpl/conf/distro/poky-basic-systemd.conf
new file mode 100644
index 0000000..1754b7a
--- /dev/null
+++ b/meta/meta-mediatek-gpl/conf/distro/poky-basic-systemd.conf
@@ -0,0 +1,114 @@
+DISTRO = "poky-basic-systemd"
+DISTRO_NAME = "Yocto Basic Baseline"
+DISTRO_VERSION = "13.0.0"
+DISTRO_CODENAME ="orion"
+
+MAINTAINER = "meta-mediatek"
+
+TARGET_VENDOR = "-poky"
+
+LOCALCONF_VERSION = "1"
+LAYER_CONF_VERSION ?= "6"
+
+include conf/distro/include/default-providers-basic.inc
+
+VIRTUAL-RUNTIME_init_manager = "systemd"
+VIRTUAL-RUNTIME_initscripts = ""
+
+DISTRO_FEATURES_append = " bluetooth systemd opengl wayland pam bluez5"
+DISTRO_FEATURES_remove = "x11"
+DISTRO_FEATURES_BACKFILL_CONSIDERED = "sysvinit"
+
+# do not use gstreamer 1.2.3 by default
+#PREFERRED_VERSION_gstreamer1.0 ?= "1.10.4"
+#PREFERRED_VERSION_gstreamer1.0-plugins-bad ?= "1.10.4"
+#PREFERRED_VERSION_gstreamer1.0-plugins-base ?= "1.10.4"
+#PREFERRED_VERSION_gstreamer1.0-plugins-good ?= "1.10.4"
+#PREFERRED_VERSION_gstreamer1.0-plugins-ugly ?= "1.10.4"
+#PREFERRED_VERSION_gstreamer1.0-libav ?= "1.10.4"
+#PREFERRED_VERSION_gstreamer1.0-omx ?= "1.10.4"
+
+POKYQEMUDEPS = "${@bb.utils.contains("INCOMPATIBLE_LICENSE", "GPLv3", "", "packagegroup-core-device-devel",d)}"
+DISTRO_EXTRA_RDEPENDS_append_qemuarm = " ${POKYQEMUDEPS}"
+DISTRO_EXTRA_RDEPENDS_append_qemux86 = " ${POKYQEMUDEPS}"
+DISTRO_EXTRA_RDEPENDS_append_qemux86-64 = " ${POKYQEMUDEPS}"
+DISTRO_EXTRA_RDEPENDS_append_vexpressa9 = " ${POKYQEMUDEPS}"
+
+TCLIBCAPPEND = ""
+
+QEMU_TARGETS ?= "arm aarch64 i386 x86_64"
+
+XSERVER ?= "xserver-xorg \
+ xserver-xf86-config \
+ xserver-xorg-extension-dbe \
+ xserver-xorg-extension-dri \
+ xserver-xorg-extension-dri2 \
+ xserver-xorg-extension-extmod \
+ xserver-xorg-extension-glx \
+ xf86-input-evdev \
+ xf86-input-mouse \
+ xf86-input-keyboard \
+ mesa-driver-swrast \
+ ${@bb.utils.contains("MACHINE_ARCH", "qemux86", "xf86-video-vmware", "", d)} \
+ ${@bb.utils.contains("MACHINE_ARCH", "qemux86_64", "xf86-video-vmware", "", d)} \
+ ${@bb.utils.contains("MACHINE_ARCH", "vexpressa9", "xf86-video-fbdev", "", d)} \
+ "
+
+PREMIRRORS ??= "\
+bzr://.*/.* http://downloads.yoctoproject.org/mirror/sources/ \n \
+cvs://.*/.* http://downloads.yoctoproject.org/mirror/sources/ \n \
+git://.*/.* http://downloads.yoctoproject.org/mirror/sources/ \n \
+gitsm://.*/.* http://downloads.yoctoproject.org/mirror/sources/ \n \
+hg://.*/.* http://downloads.yoctoproject.org/mirror/sources/ \n \
+osc://.*/.* http://downloads.yoctoproject.org/mirror/sources/ \n \
+p4://.*/.* http://downloads.yoctoproject.org/mirror/sources/ \n \
+svn://.*/.* http://downloads.yoctoproject.org/mirror/sources/ \n"
+
+MIRRORS =+ "\
+ftp://.*/.* http://downloads.yoctoproject.org/mirror/sources/ \n \
+http://.*/.* http://downloads.yoctoproject.org/mirror/sources/ \n \
+https://.*/.* http://downloads.yoctoproject.org/mirror/sources/ \n"
+
+# The CONNECTIVITY_CHECK_URI's are used to test whether we can succesfully
+# fetch from the network (and warn you if not). To disable the test set
+# the variable to be empty.
+# Git example url: git://git.yoctoproject.org/yocto-firewall-test;protocol=git;rev=HEAD
+
+CONNECTIVITY_CHECK_URIS ?= " \
+ https://eula-downloads.yoctoproject.org/index.php \
+ "
+
+# Default hash policy for distro
+BB_SIGNATURE_HANDLER ?= 'OEBasicHash'
+#
+# OELAYOUT_ABI allows us to notify users when the format of TMPDIR changes in
+# an incompatible way. Such changes should usually be detailed in the commit
+# that breaks the format and have been previously discussed on the mailing list
+# with general agreement from the core team.
+#
+OELAYOUT_ABI = "11"
+
+# add poky sanity bbclass
+INHERIT += "poky-sanity"
+
+# QA check settings - a little stricter than the OE-Core defaults
+WARN_QA = "textrel files-invalid incompatible-license xorg-driver-abi libdir \
+ unknown-configure-option build-deps"
+ERROR_QA = "dev-so debug-deps dev-deps debug-files arch pkgconfig la perms \
+ useless-rpaths rpaths staticdev ldflags pkgvarcheck already-stripped \
+ compile-host-path dep-cmp installed-vs-shipped install-host-path \
+ packages-list perm-config perm-line perm-link pkgv-undefined \
+ pn-overrides split-strip var-undefined version-going-backwards"
+
+# Recent changes in siggen.py check for task hash and generate build errors
+# called Taskhash mismatch when using variables with date and time. Exclude
+# date variables as done.
+# see https://lists.yoctoproject.org/pipermail/poky/2016-April/010470.html
+DISTRO_VERSION[vardepsexclude] = "DATE"
+SDK_VERSION[vardepsexclude] = "DATE"
+
+#
+# TO DO
+# When bug is fixed: https://bugzilla.yoctoproject.org/show_bug.cgi?id=5968
+# In quilt binary diffs are not supported. Use git as tool for applying patches.
+# PATCHTOOL = 'git'
diff --git a/meta/meta-mediatek-gpl/conf/distro/poky-basic-sysvinit.conf b/meta/meta-mediatek-gpl/conf/distro/poky-basic-sysvinit.conf
new file mode 100644
index 0000000..a4e2b7a
--- /dev/null
+++ b/meta/meta-mediatek-gpl/conf/distro/poky-basic-sysvinit.conf
@@ -0,0 +1,114 @@
+DISTRO = "poky-basic-sysvinit"
+DISTRO_NAME = "Yocto Basic Baseline"
+DISTRO_VERSION = "13.0.0"
+DISTRO_CODENAME ="orion"
+
+MAINTAINER = "meta-mediatek"
+
+TARGET_VENDOR = "-poky"
+
+LOCALCONF_VERSION = "1"
+LAYER_CONF_VERSION ?= "6"
+
+include conf/distro/include/default-providers-basic.inc
+
+VIRTUAL-RUNTIME_init_manager = "sysvinit"
+VIRTUAL-RUNTIME_initscripts = "initscripts"
+
+DISTRO_FEATURES_append = " sysvinit bluetooth systemd opengl wayland pam bluez5"
+DISTRO_FEATURES_remove = "x11 systemd"
+DISTRO_FEATURES_BACKFILL_CONSIDERED = "sysvinit"
+
+# do not use gstreamer 1.2.3 by default
+#PREFERRED_VERSION_gstreamer1.0 ?= "1.10.4"
+#PREFERRED_VERSION_gstreamer1.0-plugins-bad ?= "1.10.4"
+#PREFERRED_VERSION_gstreamer1.0-plugins-base ?= "1.10.4"
+#PREFERRED_VERSION_gstreamer1.0-plugins-good ?= "1.10.4"
+#PREFERRED_VERSION_gstreamer1.0-plugins-ugly ?= "1.10.4"
+#PREFERRED_VERSION_gstreamer1.0-libav ?= "1.10.4"
+#PREFERRED_VERSION_gstreamer1.0-omx ?= "1.10.4"
+
+POKYQEMUDEPS = "${@bb.utils.contains("INCOMPATIBLE_LICENSE", "GPLv3", "", "packagegroup-core-device-devel",d)}"
+DISTRO_EXTRA_RDEPENDS_append_qemuarm = " ${POKYQEMUDEPS}"
+DISTRO_EXTRA_RDEPENDS_append_qemux86 = " ${POKYQEMUDEPS}"
+DISTRO_EXTRA_RDEPENDS_append_qemux86-64 = " ${POKYQEMUDEPS}"
+DISTRO_EXTRA_RDEPENDS_append_vexpressa9 = " ${POKYQEMUDEPS}"
+
+TCLIBCAPPEND = ""
+
+QEMU_TARGETS ?= "arm aarch64 i386 x86_64"
+
+XSERVER ?= "xserver-xorg \
+ xserver-xf86-config \
+ xserver-xorg-extension-dbe \
+ xserver-xorg-extension-dri \
+ xserver-xorg-extension-dri2 \
+ xserver-xorg-extension-extmod \
+ xserver-xorg-extension-glx \
+ xf86-input-evdev \
+ xf86-input-mouse \
+ xf86-input-keyboard \
+ mesa-driver-swrast \
+ ${@bb.utils.contains("MACHINE_ARCH", "qemux86", "xf86-video-vmware", "", d)} \
+ ${@bb.utils.contains("MACHINE_ARCH", "qemux86_64", "xf86-video-vmware", "", d)} \
+ ${@bb.utils.contains("MACHINE_ARCH", "vexpressa9", "xf86-video-fbdev", "", d)} \
+ "
+
+PREMIRRORS ??= "\
+bzr://.*/.* http://downloads.yoctoproject.org/mirror/sources/ \n \
+cvs://.*/.* http://downloads.yoctoproject.org/mirror/sources/ \n \
+git://.*/.* http://downloads.yoctoproject.org/mirror/sources/ \n \
+gitsm://.*/.* http://downloads.yoctoproject.org/mirror/sources/ \n \
+hg://.*/.* http://downloads.yoctoproject.org/mirror/sources/ \n \
+osc://.*/.* http://downloads.yoctoproject.org/mirror/sources/ \n \
+p4://.*/.* http://downloads.yoctoproject.org/mirror/sources/ \n \
+svn://.*/.* http://downloads.yoctoproject.org/mirror/sources/ \n"
+
+MIRRORS =+ "\
+ftp://.*/.* http://downloads.yoctoproject.org/mirror/sources/ \n \
+http://.*/.* http://downloads.yoctoproject.org/mirror/sources/ \n \
+https://.*/.* http://downloads.yoctoproject.org/mirror/sources/ \n"
+
+# The CONNECTIVITY_CHECK_URI's are used to test whether we can succesfully
+# fetch from the network (and warn you if not). To disable the test set
+# the variable to be empty.
+# Git example url: git://git.yoctoproject.org/yocto-firewall-test;protocol=git;rev=HEAD
+
+CONNECTIVITY_CHECK_URIS ?= " \
+ https://eula-downloads.yoctoproject.org/index.php \
+ "
+
+# Default hash policy for distro
+BB_SIGNATURE_HANDLER ?= 'OEBasicHash'
+#
+# OELAYOUT_ABI allows us to notify users when the format of TMPDIR changes in
+# an incompatible way. Such changes should usually be detailed in the commit
+# that breaks the format and have been previously discussed on the mailing list
+# with general agreement from the core team.
+#
+OELAYOUT_ABI = "11"
+
+# add poky sanity bbclass
+INHERIT += "poky-sanity"
+
+# QA check settings - a little stricter than the OE-Core defaults
+WARN_QA = "textrel files-invalid incompatible-license xorg-driver-abi libdir \
+ unknown-configure-option build-deps"
+ERROR_QA = "dev-so debug-deps dev-deps debug-files arch pkgconfig la perms \
+ useless-rpaths rpaths staticdev ldflags pkgvarcheck already-stripped \
+ compile-host-path dep-cmp installed-vs-shipped install-host-path \
+ packages-list perm-config perm-line perm-link pkgv-undefined \
+ pn-overrides split-strip var-undefined version-going-backwards"
+
+# Recent changes in siggen.py check for task hash and generate build errors
+# called Taskhash mismatch when using variables with date and time. Exclude
+# date variables as done.
+# see https://lists.yoctoproject.org/pipermail/poky/2016-April/010470.html
+DISTRO_VERSION[vardepsexclude] = "DATE"
+SDK_VERSION[vardepsexclude] = "DATE"
+
+#
+# TO DO
+# When bug is fixed: https://bugzilla.yoctoproject.org/show_bug.cgi?id=5968
+# In quilt binary diffs are not supported. Use git as tool for applying patches.
+# PATCHTOOL = 'git'
diff --git a/meta/meta-mediatek-gpl/conf/layer.conf b/meta/meta-mediatek-gpl/conf/layer.conf
new file mode 100644
index 0000000..5e89b85
--- /dev/null
+++ b/meta/meta-mediatek-gpl/conf/layer.conf
@@ -0,0 +1,12 @@
+# We have a conf and classes directory, add to BBPATH
+BBPATH .= ":${LAYERDIR}"
+
+# We have a packages directory, add to BBFILES
+BBFILES += "${LAYERDIR}/recipes-*/*/*.bb \
+ ${LAYERDIR}/recipes-*/*/*.bbappend"
+
+BBFILE_COLLECTIONS += "mediatek-gpl"
+BBFILE_PATTERN_mediatek-gpl := "^${LAYERDIR}/"
+BBFILE_PRIORITY_mediatek-gpl = "8"
+
+LAYERSERIES_COMPAT_mediatek-gpl = "thud"
diff --git a/meta/meta-mediatek-gpl/recipes-benchmark/stream/stream/HISTORY.txt b/meta/meta-mediatek-gpl/recipes-benchmark/stream/stream/HISTORY.txt
new file mode 100644
index 0000000..496fca6
--- /dev/null
+++ b/meta/meta-mediatek-gpl/recipes-benchmark/stream/stream/HISTORY.txt
@@ -0,0 +1,152 @@
+-------------------------------------------------------------------------
+
+Revisions as of Thu, Jan 17, 2013 3:50:01 PM
+
+Version 5.10 of stream.c has been released.
+This version includes improved validation code and will automatically
+use 64-bit array indices on 64-bit systems to allow very large arrays.
+
+-------------------------------------------------------------------------
+
+Revisions as of Thu Feb 19 08:16:57 CST 2009
+
+Note that the codes in the "Versions" subdirectory should be
+considered obsolete -- the versions of stream.c and stream.f
+in this main directory include the OpenMP directives and structure
+for creating "TUNED" versions.
+
+Only the MPI version in the "Versions" subdirectory should be
+of any interest, and I have not recently checked that version for
+errors or compliance with the current versions of stream.c and
+stream.f.
+
+I added a simple Makefile to this directory. It works under Cygwin
+on my Windows XP box (using gcc and g77).
+
+A user suggested a sneaky trick for "mysecond.c" -- instead of using
+the #ifdef UNDERSCORE to generate the function name that the Fortran
+compiler expects, the new version simply defines both "mysecond()"
+and "mysecond_()", so it should automagically link with most Fortran
+compilers.
+
+-------------------------------------------------------------------------
+
+Revisions as of Wed Nov 17 09:15:37 CST 2004
+
+The most recent "official" versions have been renamed "stream.f" and
+"stream.c" -- all other versions have been moved to the "Versions"
+subdirectory.
+
+The "official" timer (was "second_wall.c") has been renamed "mysecond.c".
+This is embedded in the C version ("stream.c"), but still needs to be
+externally linked to the FORTRAN version ("stream.f").
+
+-------------------------------------------------------------------------
+
+Revisions as of Tue May 27 11:51:23 CDT 2003
+
+Copyright and License info added to stream_d.f, stream_mpi.f, and
+stream_tuned.f
+
+
+-------------------------------------------------------------------------
+
+Revisions as of Tue Apr 8 10:26:48 CDT 2003
+
+I changed the name of the timer interface from "second" to "mysecond"
+and removed the dummy argument in all versions of the source code (but
+not the "Contrib" versions).
+
+
+-------------------------------------------------------------------------
+
+Revisions as of Mon Feb 25 06:48:14 CST 2002
+
+Added an OpenMP version of stream_d.c, called stream_d_omp.c. This is
+still not up to date with the Fortran version, which includes error
+checking and advanced data flow to prevent overoptimization, but it is
+a good start....
+
+
+-------------------------------------------------------------------------
+
+Revisions as of Tue Jun 4 16:31:31 EDT 1996
+
+I have fixed an "off-by-one" error in the RMS time calculation in
+stream_d.f. This was already corrected in stream_d.c. No results are
+invalidated, since I use minimum time instead of RMS time anyway....
+
+-------------------------------------------------------------------------
+
+Revisions as of Fri Dec 8 14:49:56 EST 1995
+
+I have renamed the timer routines to:
+ second_cpu.c
+ second_wall.c
+ second_cpu.f
+
+All have a function interface named 'second' which returns a double
+precision floating point number. It should be possible to link
+second_wall.c with stream_d.f without too much trouble, though the
+details will depend on your environment.
+
+If anyone builds versions of these timers for machines running the
+Macintosh O/S or DOS/Windows, I would appreciate getting a copy.
+
+To clarify:
+ * For single-user machines, the wallclock timer is preferred.
+ * For parallel machines, the wallclock timer is required.
+ * For time-shared systems, the cpu timer is more reliable,
+ though less accurate.
+
+
+-------------------------------------------------------------------------
+
+Revisions as of Wed Oct 25 09:40:32 EDT 1995
+
+(1) NOTICE to C users:
+
+ stream_d.c has been updated to version 4.0 (beta), and
+ should be functionally identical to stream_d.f
+
+ Two timers are provided --- second_cpu.c and second_wall.c
+ second_cpu.c measures cpu time, while second_wall.c measures
+ elapsed (real) time.
+
+ For single-user machines, the wallclock timer is preferred.
+ For parallel machines, the wallclock timer is required.
+ For time-shared systems, the cpu timer is more reliable,
+ though less accurate.
+
+(2) cstream.c has been removed -- use stream_d.c
+
+(3) stream_wall.f has been removed --- to do parallel aggregate
+ bandwidth runs, comment out the definition of FUNCTION SECOND
+ in stream_d.f and compile/link with second_wall.c
+
+(4) stream_offset has been deprecated. It is still here
+ and usable, but stream_d.f is the "standard" version.
+ There are easy hooks in stream_d.f to change the
+ array offsets if you want to.
+
+(5) The rules of the game are clarified as follows:
+
+ The reference case uses array sizes of 2,000,000 elements
+ and no additional offsets. I would like to see results
+ for this case.
+
+ But, you are free to use any array size and any offset
+ you want, provided that the arrays are each bigger than
+ the last-level of cache. The output will show me what
+ parameters you chose.
+
+ I expect that I will report just the best number, but
+ if there is a serious discrepancy between the reference
+ case and the "best" case, I reserve the right to report
+ both.
+
+ Of course, I also reserve the right to reject any results
+ that I do not trust....
+--
+John D. McCalpin, Ph.D.
+john@mccalpin.com
diff --git a/meta/meta-mediatek-gpl/recipes-benchmark/stream/stream/LICENSE.txt b/meta/meta-mediatek-gpl/recipes-benchmark/stream/stream/LICENSE.txt
new file mode 100644
index 0000000..cf1c8e0
--- /dev/null
+++ b/meta/meta-mediatek-gpl/recipes-benchmark/stream/stream/LICENSE.txt
@@ -0,0 +1,34 @@
+*=======================================================================
+*-----------------------------------------------------------------------
+* Copyright 1991-2003: John D. McCalpin
+*-----------------------------------------------------------------------
+* License:
+* 1. You are free to use this program and/or to redistribute
+* this program.
+* 2. You are free to modify this program for your own use,
+* including commercial use, subject to the publication
+* restrictions in item 3.
+* 3. You are free to publish results obtained from running this
+* program, or from works that you derive from this program,
+* with the following limitations:
+* 3a. In order to be referred to as "STREAM benchmark results",
+* published results must be in conformance to the STREAM
+* Run Rules, (briefly reviewed below) published at
+* http://www.cs.virginia.edu/stream/ref.html
+* and incorporated herein by reference.
+* As the copyright holder, John McCalpin retains the
+* right to determine conformity with the Run Rules.
+* 3b. Results based on modified source code or on runs not in
+* accordance with the STREAM Run Rules must be clearly
+* labelled whenever they are published. Examples of
+* proper labelling include:
+* "tuned STREAM benchmark results"
+* "based on a variant of the STREAM benchmark code"
+* Other comparable, clear and reasonable labelling is
+* acceptable.
+* 3c. Submission of results to the STREAM benchmark web site
+* is encouraged, but not required.
+* 4. Use of this program or creation of derived works based on this
+* program constitutes acceptance of these licensing restrictions.
+* 5. Absolutely no warranty is expressed or implied.
+*-----------------------------------------------------------------------
diff --git a/meta/meta-mediatek-gpl/recipes-benchmark/stream/stream/Makefile b/meta/meta-mediatek-gpl/recipes-benchmark/stream/stream/Makefile
new file mode 100644
index 0000000..76034f8
--- /dev/null
+++ b/meta/meta-mediatek-gpl/recipes-benchmark/stream/stream/Makefile
@@ -0,0 +1,15 @@
+CFLAGS = -O2
+
+FF = g77
+FFLAGS = -O2
+
+all: stream_linux
+
+stream_linux: stream.c
+ $(CC) $(CFLAGS) $(LDFLAGS) stream.c -o stream_c
+
+stream_linux_openmp: stream.c
+ $(CC) $(CFLAGS) $(OPTIMIZATIONS) $(LDFLAGS) -fopenmp stream.c -o stream_c_openmp
+
+clean:
+ rm -f stream_c_openmp stream_c *.o
diff --git a/meta/meta-mediatek-gpl/recipes-benchmark/stream/stream/READ.ME b/meta/meta-mediatek-gpl/recipes-benchmark/stream/stream/READ.ME
new file mode 100644
index 0000000..175a3f0
--- /dev/null
+++ b/meta/meta-mediatek-gpl/recipes-benchmark/stream/stream/READ.ME
@@ -0,0 +1,110 @@
+===============================================
+
+STREAM is the de facto industry standard benchmark
+for measuring sustained memory bandwidth.
+
+Documentation for STREAM is on the web at:
+ http://www.cs.virginia.edu/stream/ref.html
+
+===============================================
+NEWS
+===============================================
+UPDATE: October 28 2014:
+
+"stream_mpi.c" released in the Versions directory.
+
+Based on Version 5.10 of stream.c, stream_mpi.c
+brings the following new features:
+* MPI implementation that *distributes* the arrays
+ across all MPI ranks. (The older Fortran version
+ of STREAM in MPI *replicates* the arrays across
+ all MPI ranks.)
+* Data is allocated using "posix_memalign"
+ rather than using static arrays. Different
+ compiler flags may be needed for both portability
+ and optimization.
+ See the READ.ME file in the Versions directory
+ for more details.
+* Error checking and timing done by all ranks and
+ gathered by rank 0 for processing and output.
+* Timing code uses barriers to ensure correct
+ operation even when multiple MPI ranks run on
+ shared memory systems.
+
+NOTE: MPI is not a preferred implementation for
+ STREAM, which is intended to measure memory
+ bandwidth in shared-memory systems. In stream_mpi,
+ the MPI calls are only used to properly synchronize
+ the timers (using MPI_Barrier) and to gather
+ timing and error data, so the performance should
+ scale linearly with the size of the cluster.
+ But it may be useful, and was an interesting
+ exercise to develop and debug.
+
+===============================================
+UPDATE: January 17 2013:
+
+Version 5.10 of stream.c is finally available!
+
+There are no changes to what is being measured, but
+a number of long-awaited improvements have been made:
+
+* Updated validation code does not suffer from
+ accumulated roundoff error for large arrays.
+* Defining the preprocessor variable "VERBOSE"
+ when compiling will (1) cause the code to print the
+ measured average relative absolute error (rather than
+ simply printing "Solution Validates", and (2) print
+ the first 10 array entries with relative error exceeding
+ the error tolerance.
+* Array index variables have been upgraded from
+ "int" to "ssize_t" to allow arrays with more
+ than 2 billion elements on 64-bit systems.
+* Substantial improvements to the comments in
+ the source on how to configure/compile/run the
+ benchmark.
+* The proprocessor variable controlling the array
+ size has been changed from "N" to "STREAM_ARRAY_SIZE".
+* A new preprocessor variable "STREAM_TYPE" can be
+ used to override the data type from the default
+ "double" to "float".
+ This mechanism could also be used to change to
+ non-floating-point types, but several "printf"
+ statements would need to have their formats changed
+ to accomodate the modified data type.
+* Some small changes in output, including printing
+ array sizes is GiB as well as MiB.
+* Change to the default output format to print fewer
+ decimals for the bandwidth and more decimals for
+ the min/max/avg execution times.
+
+
+===============================================
+UPDATE: February 19 2009:
+
+The most recent "official" versions have been renamed
+"stream.f" and "stream.c" -- all other versions have
+been moved to the "Versions" subdirectory and should be
+considered obsolete.
+
+The "official" timer (was "second_wall.c") has been
+renamed "mysecond.c". This is embedded in the C version
+("stream.c"), but still needs to be externally linked to
+the FORTRAN version ("stream.f"). The new version defines
+entry points both with and without trailing underscores,
+so it *should* link automagically with any Fortran compiler.
+
+===============================================
+
+STREAM is a project of "Dr. Bandwidth":
+ John D. McCalpin, Ph.D.
+ john@mccalpin.com
+
+===============================================
+
+The STREAM web and ftp sites are currently hosted at
+the Department of Computer Science at the University of
+Virginia under the generous sponsorship of Professor Bill
+Wulf and Professor Alan Batson.
+
+===============================================
diff --git a/meta/meta-mediatek-gpl/recipes-benchmark/stream/stream/mysecond.c b/meta/meta-mediatek-gpl/recipes-benchmark/stream/stream/mysecond.c
new file mode 100644
index 0000000..d206a4a
--- /dev/null
+++ b/meta/meta-mediatek-gpl/recipes-benchmark/stream/stream/mysecond.c
@@ -0,0 +1,27 @@
+/* A gettimeofday routine to give access to the wall
+ clock timer on most UNIX-like systems.
+
+ This version defines two entry points -- with
+ and without appended underscores, so it *should*
+ automagically link with FORTRAN */
+
+#include <sys/time.h>
+
+double mysecond()
+{
+/* struct timeval { long tv_sec;
+ long tv_usec; };
+
+struct timezone { int tz_minuteswest;
+ int tz_dsttime; }; */
+
+ struct timeval tp;
+ struct timezone tzp;
+ int i;
+
+ i = gettimeofday(&tp,&tzp);
+ return ( (double) tp.tv_sec + (double) tp.tv_usec * 1.e-6 );
+}
+
+double mysecond_() {return mysecond();}
+
diff --git a/meta/meta-mediatek-gpl/recipes-benchmark/stream/stream/stream.c b/meta/meta-mediatek-gpl/recipes-benchmark/stream/stream/stream.c
new file mode 100644
index 0000000..b9a2cee
--- /dev/null
+++ b/meta/meta-mediatek-gpl/recipes-benchmark/stream/stream/stream.c
@@ -0,0 +1,585 @@
+/*-----------------------------------------------------------------------*/
+/* Program: STREAM */
+/* Revision: $Id: stream.c,v 5.10 2013/01/17 16:01:06 mccalpin Exp mccalpin $ */
+/* Original code developed by John D. McCalpin */
+/* Programmers: John D. McCalpin */
+/* Joe R. Zagar */
+/* */
+/* This program measures memory transfer rates in MB/s for simple */
+/* computational kernels coded in C. */
+/*-----------------------------------------------------------------------*/
+/* Copyright 1991-2013: John D. McCalpin */
+/*-----------------------------------------------------------------------*/
+/* License: */
+/* 1. You are free to use this program and/or to redistribute */
+/* this program. */
+/* 2. You are free to modify this program for your own use, */
+/* including commercial use, subject to the publication */
+/* restrictions in item 3. */
+/* 3. You are free to publish results obtained from running this */
+/* program, or from works that you derive from this program, */
+/* with the following limitations: */
+/* 3a. In order to be referred to as "STREAM benchmark results", */
+/* published results must be in conformance to the STREAM */
+/* Run Rules, (briefly reviewed below) published at */
+/* http://www.cs.virginia.edu/stream/ref.html */
+/* and incorporated herein by reference. */
+/* As the copyright holder, John McCalpin retains the */
+/* right to determine conformity with the Run Rules. */
+/* 3b. Results based on modified source code or on runs not in */
+/* accordance with the STREAM Run Rules must be clearly */
+/* labelled whenever they are published. Examples of */
+/* proper labelling include: */
+/* "tuned STREAM benchmark results" */
+/* "based on a variant of the STREAM benchmark code" */
+/* Other comparable, clear, and reasonable labelling is */
+/* acceptable. */
+/* 3c. Submission of results to the STREAM benchmark web site */
+/* is encouraged, but not required. */
+/* 4. Use of this program or creation of derived works based on this */
+/* program constitutes acceptance of these licensing restrictions. */
+/* 5. Absolutely no warranty is expressed or implied. */
+/*-----------------------------------------------------------------------*/
+# include <stdio.h>
+# include <unistd.h>
+# include <math.h>
+# include <float.h>
+# include <limits.h>
+# include <sys/time.h>
+
+/*-----------------------------------------------------------------------
+ * INSTRUCTIONS:
+ *
+ * 1) STREAM requires different amounts of memory to run on different
+ * systems, depending on both the system cache size(s) and the
+ * granularity of the system timer.
+ * You should adjust the value of 'STREAM_ARRAY_SIZE' (below)
+ * to meet *both* of the following criteria:
+ * (a) Each array must be at least 4 times the size of the
+ * available cache memory. I don't worry about the difference
+ * between 10^6 and 2^20, so in practice the minimum array size
+ * is about 3.8 times the cache size.
+ * Example 1: One Xeon E3 with 8 MB L3 cache
+ * STREAM_ARRAY_SIZE should be >= 4 million, giving
+ * an array size of 30.5 MB and a total memory requirement
+ * of 91.5 MB.
+ * Example 2: Two Xeon E5's with 20 MB L3 cache each (using OpenMP)
+ * STREAM_ARRAY_SIZE should be >= 20 million, giving
+ * an array size of 153 MB and a total memory requirement
+ * of 458 MB.
+ * (b) The size should be large enough so that the 'timing calibration'
+ * output by the program is at least 20 clock-ticks.
+ * Example: most versions of Windows have a 10 millisecond timer
+ * granularity. 20 "ticks" at 10 ms/tic is 200 milliseconds.
+ * If the chip is capable of 10 GB/s, it moves 2 GB in 200 msec.
+ * This means the each array must be at least 1 GB, or 128M elements.
+ *
+ * Version 5.10 increases the default array size from 2 million
+ * elements to 10 million elements in response to the increasing
+ * size of L3 caches. The new default size is large enough for caches
+ * up to 20 MB.
+ * Version 5.10 changes the loop index variables from "register int"
+ * to "ssize_t", which allows array indices >2^32 (4 billion)
+ * on properly configured 64-bit systems. Additional compiler options
+ * (such as "-mcmodel=medium") may be required for large memory runs.
+ *
+ * Array size can be set at compile time without modifying the source
+ * code for the (many) compilers that support preprocessor definitions
+ * on the compile line. E.g.,
+ * gcc -O -DSTREAM_ARRAY_SIZE=100000000 stream.c -o stream.100M
+ * will override the default size of 10M with a new size of 100M elements
+ * per array.
+ */
+#ifndef STREAM_ARRAY_SIZE
+# define STREAM_ARRAY_SIZE 10000000
+#endif
+
+/* 2) STREAM runs each kernel "NTIMES" times and reports the *best* result
+ * for any iteration after the first, therefore the minimum value
+ * for NTIMES is 2.
+ * There are no rules on maximum allowable values for NTIMES, but
+ * values larger than the default are unlikely to noticeably
+ * increase the reported performance.
+ * NTIMES can also be set on the compile line without changing the source
+ * code using, for example, "-DNTIMES=7".
+ */
+#ifdef NTIMES
+#if NTIMES<=1
+# define NTIMES 10
+#endif
+#endif
+#ifndef NTIMES
+# define NTIMES 10
+#endif
+
+/* Users are allowed to modify the "OFFSET" variable, which *may* change the
+ * relative alignment of the arrays (though compilers may change the
+ * effective offset by making the arrays non-contiguous on some systems).
+ * Use of non-zero values for OFFSET can be especially helpful if the
+ * STREAM_ARRAY_SIZE is set to a value close to a large power of 2.
+ * OFFSET can also be set on the compile line without changing the source
+ * code using, for example, "-DOFFSET=56".
+ */
+#ifndef OFFSET
+# define OFFSET 0
+#endif
+
+/*
+ * 3) Compile the code with optimization. Many compilers generate
+ * unreasonably bad code before the optimizer tightens things up.
+ * If the results are unreasonably good, on the other hand, the
+ * optimizer might be too smart for me!
+ *
+ * For a simple single-core version, try compiling with:
+ * cc -O stream.c -o stream
+ * This is known to work on many, many systems....
+ *
+ * To use multiple cores, you need to tell the compiler to obey the OpenMP
+ * directives in the code. This varies by compiler, but a common example is
+ * gcc -O -fopenmp stream.c -o stream_omp
+ * The environment variable OMP_NUM_THREADS allows runtime control of the
+ * number of threads/cores used when the resulting "stream_omp" program
+ * is executed.
+ *
+ * To run with single-precision variables and arithmetic, simply add
+ * -DSTREAM_TYPE=float
+ * to the compile line.
+ * Note that this changes the minimum array sizes required --- see (1) above.
+ *
+ * The preprocessor directive "TUNED" does not do much -- it simply causes the
+ * code to call separate functions to execute each kernel. Trivial versions
+ * of these functions are provided, but they are *not* tuned -- they just
+ * provide predefined interfaces to be replaced with tuned code.
+ *
+ *
+ * 4) Optional: Mail the results to mccalpin@cs.virginia.edu
+ * Be sure to include info that will help me understand:
+ * a) the computer hardware configuration (e.g., processor model, memory type)
+ * b) the compiler name/version and compilation flags
+ * c) any run-time information (such as OMP_NUM_THREADS)
+ * d) all of the output from the test case.
+ *
+ * Thanks!
+ *
+ *-----------------------------------------------------------------------*/
+
+# define HLINE "-------------------------------------------------------------\n"
+
+# ifndef MIN
+# define MIN(x,y) ((x)<(y)?(x):(y))
+# endif
+# ifndef MAX
+# define MAX(x,y) ((x)>(y)?(x):(y))
+# endif
+
+#ifndef STREAM_TYPE
+#define STREAM_TYPE double
+#endif
+
+static STREAM_TYPE a[STREAM_ARRAY_SIZE+OFFSET],
+ b[STREAM_ARRAY_SIZE+OFFSET],
+ c[STREAM_ARRAY_SIZE+OFFSET];
+
+static double avgtime[4] = {0}, maxtime[4] = {0},
+ mintime[4] = {FLT_MAX,FLT_MAX,FLT_MAX,FLT_MAX};
+
+static char *label[4] = {"Copy: ", "Scale: ",
+ "Add: ", "Triad: "};
+
+static double bytes[4] = {
+ 2 * sizeof(STREAM_TYPE) * STREAM_ARRAY_SIZE,
+ 2 * sizeof(STREAM_TYPE) * STREAM_ARRAY_SIZE,
+ 3 * sizeof(STREAM_TYPE) * STREAM_ARRAY_SIZE,
+ 3 * sizeof(STREAM_TYPE) * STREAM_ARRAY_SIZE
+ };
+
+extern double mysecond();
+extern void checkSTREAMresults();
+#ifdef TUNED
+extern void tuned_STREAM_Copy();
+extern void tuned_STREAM_Scale(STREAM_TYPE scalar);
+extern void tuned_STREAM_Add();
+extern void tuned_STREAM_Triad(STREAM_TYPE scalar);
+#endif
+#ifdef _OPENMP
+extern int omp_get_num_threads();
+#endif
+int
+main()
+ {
+ int quantum, checktick();
+ int BytesPerWord;
+ int k;
+ ssize_t j;
+ STREAM_TYPE scalar;
+ double t, times[4][NTIMES];
+
+ /* --- SETUP --- determine precision and check timing --- */
+
+ printf(HLINE);
+ printf("STREAM version $Revision: 5.10 $\n");
+ printf(HLINE);
+ BytesPerWord = sizeof(STREAM_TYPE);
+ printf("This system uses %d bytes per array element.\n",
+ BytesPerWord);
+
+ printf(HLINE);
+#ifdef N
+ printf("***** WARNING: ******\n");
+ printf(" It appears that you set the preprocessor variable N when compiling this code.\n");
+ printf(" This version of the code uses the preprocesor variable STREAM_ARRAY_SIZE to control the array size\n");
+ printf(" Reverting to default value of STREAM_ARRAY_SIZE=%llu\n",(unsigned long long) STREAM_ARRAY_SIZE);
+ printf("***** WARNING: ******\n");
+#endif
+
+ printf("Array size = %llu (elements), Offset = %d (elements)\n" , (unsigned long long) STREAM_ARRAY_SIZE, OFFSET);
+ printf("Memory per array = %.1f MiB (= %.1f GiB).\n",
+ BytesPerWord * ( (double) STREAM_ARRAY_SIZE / 1024.0/1024.0),
+ BytesPerWord * ( (double) STREAM_ARRAY_SIZE / 1024.0/1024.0/1024.0));
+ printf("Total memory required = %.1f MiB (= %.1f GiB).\n",
+ (3.0 * BytesPerWord) * ( (double) STREAM_ARRAY_SIZE / 1024.0/1024.),
+ (3.0 * BytesPerWord) * ( (double) STREAM_ARRAY_SIZE / 1024.0/1024./1024.));
+ printf("Each kernel will be executed %d times.\n", NTIMES);
+ printf(" The *best* time for each kernel (excluding the first iteration)\n");
+ printf(" will be used to compute the reported bandwidth.\n");
+
+#ifdef _OPENMP
+ printf(HLINE);
+#pragma omp parallel
+ {
+#pragma omp master
+ {
+ k = omp_get_num_threads();
+ printf ("Number of Threads requested = %i\n",k);
+ }
+ }
+#endif
+
+#ifdef _OPENMP
+ k = 0;
+#pragma omp parallel
+#pragma omp atomic
+ k++;
+ printf ("Number of Threads counted = %i\n",k);
+#endif
+
+ /* Get initial value for system clock. */
+#pragma omp parallel for
+ for (j=0; j<STREAM_ARRAY_SIZE; j++) {
+ a[j] = 1.0;
+ b[j] = 2.0;
+ c[j] = 0.0;
+ }
+
+ printf(HLINE);
+
+ if ( (quantum = checktick()) >= 1)
+ printf("Your clock granularity/precision appears to be "
+ "%d microseconds.\n", quantum);
+ else {
+ printf("Your clock granularity appears to be "
+ "less than one microsecond.\n");
+ quantum = 1;
+ }
+
+ t = mysecond();
+#pragma omp parallel for
+ for (j = 0; j < STREAM_ARRAY_SIZE; j++)
+ a[j] = 2.0E0 * a[j];
+ t = 1.0E6 * (mysecond() - t);
+
+ printf("Each test below will take on the order"
+ " of %d microseconds.\n", (int) t );
+ printf(" (= %d clock ticks)\n", (int) (t/quantum) );
+ printf("Increase the size of the arrays if this shows that\n");
+ printf("you are not getting at least 20 clock ticks per test.\n");
+
+ printf(HLINE);
+
+ printf("WARNING -- The above is only a rough guideline.\n");
+ printf("For best results, please be sure you know the\n");
+ printf("precision of your system timer.\n");
+ printf(HLINE);
+
+ /* --- MAIN LOOP --- repeat test cases NTIMES times --- */
+
+ scalar = 3.0;
+ for (k=0; k<NTIMES; k++)
+ {
+ times[0][k] = mysecond();
+#ifdef TUNED
+ tuned_STREAM_Copy();
+#else
+#pragma omp parallel for
+ for (j=0; j<STREAM_ARRAY_SIZE; j++)
+ c[j] = a[j];
+#endif
+ times[0][k] = mysecond() - times[0][k];
+
+ times[1][k] = mysecond();
+#ifdef TUNED
+ tuned_STREAM_Scale(scalar);
+#else
+#pragma omp parallel for
+ for (j=0; j<STREAM_ARRAY_SIZE; j++)
+ b[j] = scalar*c[j];
+#endif
+ times[1][k] = mysecond() - times[1][k];
+
+ times[2][k] = mysecond();
+#ifdef TUNED
+ tuned_STREAM_Add();
+#else
+#pragma omp parallel for
+ for (j=0; j<STREAM_ARRAY_SIZE; j++)
+ c[j] = a[j]+b[j];
+#endif
+ times[2][k] = mysecond() - times[2][k];
+
+ times[3][k] = mysecond();
+#ifdef TUNED
+ tuned_STREAM_Triad(scalar);
+#else
+#pragma omp parallel for
+ for (j=0; j<STREAM_ARRAY_SIZE; j++)
+ a[j] = b[j]+scalar*c[j];
+#endif
+ times[3][k] = mysecond() - times[3][k];
+ }
+
+ /* --- SUMMARY --- */
+
+ for (k=1; k<NTIMES; k++) /* note -- skip first iteration */
+ {
+ for (j=0; j<4; j++)
+ {
+ avgtime[j] = avgtime[j] + times[j][k];
+ mintime[j] = MIN(mintime[j], times[j][k]);
+ maxtime[j] = MAX(maxtime[j], times[j][k]);
+ }
+ }
+
+ printf("Function Best Rate MB/s Avg time Min time Max time\n");
+ for (j=0; j<4; j++) {
+ avgtime[j] = avgtime[j]/(double)(NTIMES-1);
+
+ printf("%s%12.1f %11.6f %11.6f %11.6f\n", label[j],
+ 1.0E-06 * bytes[j]/mintime[j],
+ avgtime[j],
+ mintime[j],
+ maxtime[j]);
+ }
+ printf(HLINE);
+
+ /* --- Check Results --- */
+ checkSTREAMresults();
+ printf(HLINE);
+
+ return 0;
+}
+
+# define M 20
+
+int
+checktick()
+ {
+ int i, minDelta, Delta;
+ double t1, t2, timesfound[M];
+
+/* Collect a sequence of M unique time values from the system. */
+
+ for (i = 0; i < M; i++) {
+ t1 = mysecond();
+ while( ((t2=mysecond()) - t1) < 1.0E-6 )
+ ;
+ timesfound[i] = t1 = t2;
+ }
+
+/*
+ * Determine the minimum difference between these M values.
+ * This result will be our estimate (in microseconds) for the
+ * clock granularity.
+ */
+
+ minDelta = 1000000;
+ for (i = 1; i < M; i++) {
+ Delta = (int)( 1.0E6 * (timesfound[i]-timesfound[i-1]));
+ minDelta = MIN(minDelta, MAX(Delta,0));
+ }
+
+ return(minDelta);
+ }
+
+
+
+/* A gettimeofday routine to give access to the wall
+ clock timer on most UNIX-like systems. */
+
+#include <sys/time.h>
+
+double mysecond()
+{
+ struct timeval tp;
+ struct timezone tzp;
+ int i;
+
+ i = gettimeofday(&tp,&tzp);
+ return ( (double) tp.tv_sec + (double) tp.tv_usec * 1.e-6 );
+}
+
+#ifndef abs
+#define abs(a) ((a) >= 0 ? (a) : -(a))
+#endif
+void checkSTREAMresults ()
+{
+ STREAM_TYPE aj,bj,cj,scalar;
+ STREAM_TYPE aSumErr,bSumErr,cSumErr;
+ STREAM_TYPE aAvgErr,bAvgErr,cAvgErr;
+ double epsilon;
+ ssize_t j;
+ int k,ierr,err;
+
+ /* reproduce initialization */
+ aj = 1.0;
+ bj = 2.0;
+ cj = 0.0;
+ /* a[] is modified during timing check */
+ aj = 2.0E0 * aj;
+ /* now execute timing loop */
+ scalar = 3.0;
+ for (k=0; k<NTIMES; k++)
+ {
+ cj = aj;
+ bj = scalar*cj;
+ cj = aj+bj;
+ aj = bj+scalar*cj;
+ }
+
+ /* accumulate deltas between observed and expected results */
+ aSumErr = 0.0;
+ bSumErr = 0.0;
+ cSumErr = 0.0;
+ for (j=0; j<STREAM_ARRAY_SIZE; j++) {
+ aSumErr += abs(a[j] - aj);
+ bSumErr += abs(b[j] - bj);
+ cSumErr += abs(c[j] - cj);
+ // if (j == 417) printf("Index 417: c[j]: %f, cj: %f\n",c[j],cj); // MCCALPIN
+ }
+ aAvgErr = aSumErr / (STREAM_TYPE) STREAM_ARRAY_SIZE;
+ bAvgErr = bSumErr / (STREAM_TYPE) STREAM_ARRAY_SIZE;
+ cAvgErr = cSumErr / (STREAM_TYPE) STREAM_ARRAY_SIZE;
+
+ if (sizeof(STREAM_TYPE) == 4) {
+ epsilon = 1.e-6;
+ }
+ else if (sizeof(STREAM_TYPE) == 8) {
+ epsilon = 1.e-13;
+ }
+ else {
+ printf("WEIRD: sizeof(STREAM_TYPE) = %lu\n",sizeof(STREAM_TYPE));
+ epsilon = 1.e-6;
+ }
+
+ err = 0;
+ if (abs(aAvgErr/aj) > epsilon) {
+ err++;
+ printf ("Failed Validation on array a[], AvgRelAbsErr > epsilon (%e)\n",epsilon);
+ printf (" Expected Value: %e, AvgAbsErr: %e, AvgRelAbsErr: %e\n",aj,aAvgErr,abs(aAvgErr)/aj);
+ ierr = 0;
+ for (j=0; j<STREAM_ARRAY_SIZE; j++) {
+ if (abs(a[j]/aj-1.0) > epsilon) {
+ ierr++;
+#ifdef VERBOSE
+ if (ierr < 10) {
+ printf(" array a: index: %ld, expected: %e, observed: %e, relative error: %e\n",
+ j,aj,a[j],abs((aj-a[j])/aAvgErr));
+ }
+#endif
+ }
+ }
+ printf(" For array a[], %d errors were found.\n",ierr);
+ }
+ if (abs(bAvgErr/bj) > epsilon) {
+ err++;
+ printf ("Failed Validation on array b[], AvgRelAbsErr > epsilon (%e)\n",epsilon);
+ printf (" Expected Value: %e, AvgAbsErr: %e, AvgRelAbsErr: %e\n",bj,bAvgErr,abs(bAvgErr)/bj);
+ printf (" AvgRelAbsErr > Epsilon (%e)\n",epsilon);
+ ierr = 0;
+ for (j=0; j<STREAM_ARRAY_SIZE; j++) {
+ if (abs(b[j]/bj-1.0) > epsilon) {
+ ierr++;
+#ifdef VERBOSE
+ if (ierr < 10) {
+ printf(" array b: index: %ld, expected: %e, observed: %e, relative error: %e\n",
+ j,bj,b[j],abs((bj-b[j])/bAvgErr));
+ }
+#endif
+ }
+ }
+ printf(" For array b[], %d errors were found.\n",ierr);
+ }
+ if (abs(cAvgErr/cj) > epsilon) {
+ err++;
+ printf ("Failed Validation on array c[], AvgRelAbsErr > epsilon (%e)\n",epsilon);
+ printf (" Expected Value: %e, AvgAbsErr: %e, AvgRelAbsErr: %e\n",cj,cAvgErr,abs(cAvgErr)/cj);
+ printf (" AvgRelAbsErr > Epsilon (%e)\n",epsilon);
+ ierr = 0;
+ for (j=0; j<STREAM_ARRAY_SIZE; j++) {
+ if (abs(c[j]/cj-1.0) > epsilon) {
+ ierr++;
+#ifdef VERBOSE
+ if (ierr < 10) {
+ printf(" array c: index: %ld, expected: %e, observed: %e, relative error: %e\n",
+ j,cj,c[j],abs((cj-c[j])/cAvgErr));
+ }
+#endif
+ }
+ }
+ printf(" For array c[], %d errors were found.\n",ierr);
+ }
+ if (err == 0) {
+ printf ("Solution Validates: avg error less than %e on all three arrays\n",epsilon);
+ }
+#ifdef VERBOSE
+ printf ("Results Validation Verbose Results: \n");
+ printf (" Expected a(1), b(1), c(1): %f %f %f \n",aj,bj,cj);
+ printf (" Observed a(1), b(1), c(1): %f %f %f \n",a[1],b[1],c[1]);
+ printf (" Rel Errors on a, b, c: %e %e %e \n",abs(aAvgErr/aj),abs(bAvgErr/bj),abs(cAvgErr/cj));
+#endif
+}
+
+#ifdef TUNED
+/* stubs for "tuned" versions of the kernels */
+void tuned_STREAM_Copy()
+{
+ ssize_t j;
+#pragma omp parallel for
+ for (j=0; j<STREAM_ARRAY_SIZE; j++)
+ c[j] = a[j];
+}
+
+void tuned_STREAM_Scale(STREAM_TYPE scalar)
+{
+ ssize_t j;
+#pragma omp parallel for
+ for (j=0; j<STREAM_ARRAY_SIZE; j++)
+ b[j] = scalar*c[j];
+}
+
+void tuned_STREAM_Add()
+{
+ ssize_t j;
+#pragma omp parallel for
+ for (j=0; j<STREAM_ARRAY_SIZE; j++)
+ c[j] = a[j]+b[j];
+}
+
+void tuned_STREAM_Triad(STREAM_TYPE scalar)
+{
+ ssize_t j;
+#pragma omp parallel for
+ for (j=0; j<STREAM_ARRAY_SIZE; j++)
+ a[j] = b[j]+scalar*c[j];
+}
+/* end of stubs for the "tuned" versions of the kernels */
+#endif
diff --git a/meta/meta-mediatek-gpl/recipes-benchmark/stream/stream/stream.f b/meta/meta-mediatek-gpl/recipes-benchmark/stream/stream/stream.f
new file mode 100644
index 0000000..bef13ec
--- /dev/null
+++ b/meta/meta-mediatek-gpl/recipes-benchmark/stream/stream/stream.f
@@ -0,0 +1,462 @@
+*=======================================================================
+* Program: STREAM
+* Programmer: John D. McCalpin
+* RCS Revision: $Id: stream.f,v 5.6 2005/10/04 00:20:48 mccalpin Exp mccalpin $
+*-----------------------------------------------------------------------
+* Copyright 1991-2003: John D. McCalpin
+*-----------------------------------------------------------------------
+* License:
+* 1. You are free to use this program and/or to redistribute
+* this program.
+* 2. You are free to modify this program for your own use,
+* including commercial use, subject to the publication
+* restrictions in item 3.
+* 3. You are free to publish results obtained from running this
+* program, or from works that you derive from this program,
+* with the following limitations:
+* 3a. In order to be referred to as "STREAM benchmark results",
+* published results must be in conformance to the STREAM
+* Run Rules, (briefly reviewed below) published at
+* http://www.cs.virginia.edu/stream/ref.html
+* and incorporated herein by reference.
+* As the copyright holder, John McCalpin retains the
+* right to determine conformity with the Run Rules.
+* 3b. Results based on modified source code or on runs not in
+* accordance with the STREAM Run Rules must be clearly
+* labelled whenever they are published. Examples of
+* proper labelling include:
+* "tuned STREAM benchmark results"
+* "based on a variant of the STREAM benchmark code"
+* Other comparable, clear and reasonable labelling is
+* acceptable.
+* 3c. Submission of results to the STREAM benchmark web site
+* is encouraged, but not required.
+* 4. Use of this program or creation of derived works based on this
+* program constitutes acceptance of these licensing restrictions.
+* 5. Absolutely no warranty is expressed or implied.
+*-----------------------------------------------------------------------
+* This program measures sustained memory transfer rates in MB/s for
+* simple computational kernels coded in FORTRAN.
+*
+* The intent is to demonstrate the extent to which ordinary user
+* code can exploit the main memory bandwidth of the system under
+* test.
+*=======================================================================
+* The STREAM web page is at:
+* http://www.streambench.org
+*
+* Most of the content is currently hosted at:
+* http://www.cs.virginia.edu/stream/
+*
+* BRIEF INSTRUCTIONS:
+* 0) See http://www.cs.virginia.edu/stream/ref.html for details
+* 1) STREAM requires a timing function called mysecond().
+* Several examples are provided in this directory.
+* "CPU" timers are only allowed for uniprocessor runs.
+* "Wall-clock" timers are required for all multiprocessor runs.
+* 2) The STREAM array sizes must be set to size the test.
+* The value "N" must be chosen so that each of the three
+* arrays is at least 4x larger than the sum of all the last-
+* level caches used in the run, or 1 million elements, which-
+* ever is larger.
+* ------------------------------------------------------------
+* Note that you are free to use any array length and offset
+* that makes each array 4x larger than the last-level cache.
+* The intent is to determine the *best* sustainable bandwidth
+* available with this simple coding. Of course, lower values
+* are usually fairly easy to obtain on cached machines, but
+* by keeping the test to the *best* results, the answers are
+* easier to interpret.
+* You may put the arrays in common or not, at your discretion.
+* There is a commented-out COMMON statement below.
+* Fortran90 "allocatable" arrays are fine, too.
+* ------------------------------------------------------------
+* 3) Compile the code with full optimization. Many compilers
+* generate unreasonably bad code before the optimizer tightens
+* things up. If the results are unreasonably good, on the
+* other hand, the optimizer might be too smart for me
+* Please let me know if this happens.
+* 4) Mail the results to mccalpin@cs.virginia.edu
+* Be sure to include:
+* a) computer hardware model number and software revision
+* b) the compiler flags
+* c) all of the output from the test case.
+* Please let me know if you do not want your name posted along
+* with the submitted results.
+* 5) See the web page for more comments about the run rules and
+* about interpretation of the results.
+*
+* Thanks,
+* Dr. Bandwidth
+*=========================================================================
+*
+ PROGRAM stream
+* IMPLICIT NONE
+C .. Parameters ..
+ INTEGER n,offset,ndim,ntimes
+ PARAMETER (n=2000000,offset=0,ndim=n+offset,ntimes=10)
+C ..
+C .. Local Scalars ..
+ DOUBLE PRECISION scalar,t
+ INTEGER j,k,nbpw,quantum
+C ..
+C .. Local Arrays ..
+ DOUBLE PRECISION maxtime(4),mintime(4),avgtime(4),
+ $ times(4,ntimes)
+ INTEGER bytes(4)
+ CHARACTER label(4)*11
+C ..
+C .. External Functions ..
+ DOUBLE PRECISION mysecond
+ INTEGER checktick,realsize
+ EXTERNAL mysecond,checktick,realsize
+!$ INTEGER omp_get_num_threads
+!$ EXTERNAL omp_get_num_threads
+C ..
+C .. Intrinsic Functions ..
+C
+ INTRINSIC dble,max,min,nint,sqrt
+C ..
+C .. Arrays in Common ..
+ DOUBLE PRECISION a(ndim),b(ndim),c(ndim)
+C ..
+C .. Common blocks ..
+* COMMON a,b,c
+C ..
+C .. Data statements ..
+ DATA avgtime/4*0.0D0/,mintime/4*1.0D+36/,maxtime/4*0.0D0/
+ DATA label/'Copy: ','Scale: ','Add: ',
+ $ 'Triad: '/
+ DATA bytes/2,2,3,3/
+C ..
+
+* --- SETUP --- determine precision and check timing ---
+
+ nbpw = realsize()
+
+ PRINT *,'----------------------------------------------'
+ PRINT *,'STREAM Version $Revision: 5.6 $'
+ PRINT *,'----------------------------------------------'
+ WRITE (*,FMT=9010) 'Array size = ',n
+ WRITE (*,FMT=9010) 'Offset = ',offset
+ WRITE (*,FMT=9020) 'The total memory requirement is ',
+ $ 3*nbpw*n/ (1024*1024),' MB'
+ WRITE (*,FMT=9030) 'You are running each test ',ntimes,' times'
+ WRITE (*,FMT=9030) '--'
+ WRITE (*,FMT=9030) 'The *best* time for each test is used'
+ WRITE (*,FMT=9030) '*EXCLUDING* the first and last iterations'
+
+!$OMP PARALLEL
+!$OMP MASTER
+ PRINT *,'----------------------------------------------'
+!$ PRINT *,'Number of Threads = ',OMP_GET_NUM_THREADS()
+!$OMP END MASTER
+!$OMP END PARALLEL
+
+ PRINT *,'----------------------------------------------'
+!$OMP PARALLEL
+ PRINT *,'Printing one line per active thread....'
+!$OMP END PARALLEL
+
+!$OMP PARALLEL DO
+ DO 10 j = 1,n
+ a(j) = 2.0d0
+ b(j) = 0.5D0
+ c(j) = 0.0D0
+ 10 CONTINUE
+ t = mysecond()
+!$OMP PARALLEL DO
+ DO 20 j = 1,n
+ a(j) = 0.5d0*a(j)
+ 20 CONTINUE
+ t = mysecond() - t
+ PRINT *,'----------------------------------------------------'
+ quantum = checktick()
+ WRITE (*,FMT=9000)
+ $ 'Your clock granularity/precision appears to be ',quantum,
+ $ ' microseconds'
+ PRINT *,'----------------------------------------------------'
+
+* --- MAIN LOOP --- repeat test cases NTIMES times ---
+ scalar = 0.5d0*a(1)
+ DO 70 k = 1,ntimes
+
+ t = mysecond()
+ a(1) = a(1) + t
+!$OMP PARALLEL DO
+ DO 30 j = 1,n
+ c(j) = a(j)
+ 30 CONTINUE
+ t = mysecond() - t
+ c(n) = c(n) + t
+ times(1,k) = t
+
+ t = mysecond()
+ c(1) = c(1) + t
+!$OMP PARALLEL DO
+ DO 40 j = 1,n
+ b(j) = scalar*c(j)
+ 40 CONTINUE
+ t = mysecond() - t
+ b(n) = b(n) + t
+ times(2,k) = t
+
+ t = mysecond()
+ a(1) = a(1) + t
+!$OMP PARALLEL DO
+ DO 50 j = 1,n
+ c(j) = a(j) + b(j)
+ 50 CONTINUE
+ t = mysecond() - t
+ c(n) = c(n) + t
+ times(3,k) = t
+
+ t = mysecond()
+ b(1) = b(1) + t
+!$OMP PARALLEL DO
+ DO 60 j = 1,n
+ a(j) = b(j) + scalar*c(j)
+ 60 CONTINUE
+ t = mysecond() - t
+ a(n) = a(n) + t
+ times(4,k) = t
+ 70 CONTINUE
+
+* --- SUMMARY ---
+ DO 90 k = 2,ntimes
+ DO 80 j = 1,4
+ avgtime(j) = avgtime(j) + times(j,k)
+ mintime(j) = min(mintime(j),times(j,k))
+ maxtime(j) = max(maxtime(j),times(j,k))
+ 80 CONTINUE
+ 90 CONTINUE
+ WRITE (*,FMT=9040)
+ DO 100 j = 1,4
+ avgtime(j) = avgtime(j)/dble(ntimes-1)
+ WRITE (*,FMT=9050) label(j),n*bytes(j)*nbpw/mintime(j)/1.0D6,
+ $ avgtime(j),mintime(j),maxtime(j)
+ 100 CONTINUE
+ PRINT *,'----------------------------------------------------'
+ CALL checksums (a,b,c,n,ntimes)
+ PRINT *,'----------------------------------------------------'
+
+ 9000 FORMAT (1x,a,i6,a)
+ 9010 FORMAT (1x,a,i10)
+ 9020 FORMAT (1x,a,i4,a)
+ 9030 FORMAT (1x,a,i3,a,a)
+ 9040 FORMAT ('Function',5x,'Rate (MB/s) Avg time Min time Max time'
+ $ )
+ 9050 FORMAT (a,4 (f10.4,2x))
+ END
+
+*-------------------------------------
+* INTEGER FUNCTION dblesize()
+*
+* A semi-portable way to determine the precision of DOUBLE PRECISION
+* in Fortran.
+* Here used to guess how many bytes of storage a DOUBLE PRECISION
+* number occupies.
+*
+ INTEGER FUNCTION realsize()
+* IMPLICIT NONE
+
+C .. Local Scalars ..
+ DOUBLE PRECISION result,test
+ INTEGER j,ndigits
+C ..
+C .. Local Arrays ..
+ DOUBLE PRECISION ref(30)
+C ..
+C .. External Subroutines ..
+ EXTERNAL confuse
+C ..
+C .. Intrinsic Functions ..
+ INTRINSIC abs,acos,log10,sqrt
+C ..
+
+C Test #1 - compare single(1.0d0+delta) to 1.0d0
+
+ 10 DO 20 j = 1,30
+ ref(j) = 1.0d0 + 10.0d0** (-j)
+ 20 CONTINUE
+
+ DO 30 j = 1,30
+ test = ref(j)
+ ndigits = j
+ CALL confuse(test,result)
+ IF (test.EQ.1.0D0) THEN
+ GO TO 40
+ END IF
+ 30 CONTINUE
+ GO TO 50
+
+ 40 WRITE (*,FMT='(a)')
+ $ '----------------------------------------------'
+ WRITE (*,FMT='(1x,a,i2,a)') 'Double precision appears to have ',
+ $ ndigits,' digits of accuracy'
+ IF (ndigits.LE.8) THEN
+ realsize = 4
+ ELSE
+ realsize = 8
+ END IF
+ WRITE (*,FMT='(1x,a,i1,a)') 'Assuming ',realsize,
+ $ ' bytes per DOUBLE PRECISION word'
+ WRITE (*,FMT='(a)')
+ $ '----------------------------------------------'
+ RETURN
+
+ 50 PRINT *,'Hmmmm. I am unable to determine the size.'
+ PRINT *,'Please enter the number of Bytes per DOUBLE PRECISION',
+ $ ' number : '
+ READ (*,FMT=*) realsize
+ IF (realsize.NE.4 .AND. realsize.NE.8) THEN
+ PRINT *,'Your answer ',realsize,' does not make sense.'
+ PRINT *,'Try again.'
+ PRINT *,'Please enter the number of Bytes per ',
+ $ 'DOUBLE PRECISION number : '
+ READ (*,FMT=*) realsize
+ END IF
+ PRINT *,'You have manually entered a size of ',realsize,
+ $ ' bytes per DOUBLE PRECISION number'
+ WRITE (*,FMT='(a)')
+ $ '----------------------------------------------'
+ END
+
+ SUBROUTINE confuse(q,r)
+* IMPLICIT NONE
+C .. Scalar Arguments ..
+ DOUBLE PRECISION q,r
+C ..
+C .. Intrinsic Functions ..
+ INTRINSIC cos
+C ..
+ r = cos(q)
+ RETURN
+ END
+
+* A semi-portable way to determine the clock granularity
+* Adapted from a code by John Henning of Digital Equipment Corporation
+*
+ INTEGER FUNCTION checktick()
+* IMPLICIT NONE
+
+C .. Parameters ..
+ INTEGER n
+ PARAMETER (n=20)
+C ..
+C .. Local Scalars ..
+ DOUBLE PRECISION t1,t2
+ INTEGER i,j,jmin
+C ..
+C .. Local Arrays ..
+ DOUBLE PRECISION timesfound(n)
+C ..
+C .. External Functions ..
+ DOUBLE PRECISION mysecond
+ EXTERNAL mysecond
+C ..
+C .. Intrinsic Functions ..
+ INTRINSIC max,min,nint
+C ..
+ i = 0
+
+ 10 t2 = mysecond()
+ IF (t2.EQ.t1) GO TO 10
+
+ t1 = t2
+ i = i + 1
+ timesfound(i) = t1
+ IF (i.LT.n) GO TO 10
+
+ jmin = 1000000
+ DO 20 i = 2,n
+ j = nint((timesfound(i)-timesfound(i-1))*1d6)
+ jmin = min(jmin,max(j,0))
+ 20 CONTINUE
+
+ IF (jmin.GT.0) THEN
+ checktick = jmin
+ ELSE
+ PRINT *,'Your clock granularity appears to be less ',
+ $ 'than one microsecond'
+ checktick = 1
+ END IF
+ RETURN
+
+* PRINT 14, timesfound(1)*1d6
+* DO 20 i=2,n
+* PRINT 14, timesfound(i)*1d6,
+* & nint((timesfound(i)-timesfound(i-1))*1d6)
+* 14 FORMAT (1X, F18.4, 1X, i8)
+* 20 CONTINUE
+
+ END
+
+
+
+
+ SUBROUTINE checksums(a,b,c,n,ntimes)
+* IMPLICIT NONE
+C ..
+C .. Arguments ..
+ DOUBLE PRECISION a(*),b(*),c(*)
+ INTEGER n,ntimes
+C ..
+C .. Local Scalars ..
+ DOUBLE PRECISION aa,bb,cc,scalar,suma,sumb,sumc,epsilon
+ INTEGER k
+C ..
+
+C Repeat the main loop, but with scalars only.
+C This is done to check the sum & make sure all
+C iterations have been executed correctly.
+
+ aa = 2.0D0
+ bb = 0.5D0
+ cc = 0.0D0
+ aa = 0.5D0*aa
+ scalar = 0.5d0*aa
+ DO k = 1,ntimes
+ cc = aa
+ bb = scalar*cc
+ cc = aa + bb
+ aa = bb + scalar*cc
+ END DO
+ aa = aa*DBLE(n-2)
+ bb = bb*DBLE(n-2)
+ cc = cc*DBLE(n-2)
+
+C Now sum up the arrays, excluding the first and last
+C elements, which are modified using the timing results
+C to confuse aggressive optimizers.
+
+ suma = 0.0d0
+ sumb = 0.0d0
+ sumc = 0.0d0
+!$OMP PARALLEL DO REDUCTION(+:suma,sumb,sumc)
+ DO 110 j = 2,n-1
+ suma = suma + a(j)
+ sumb = sumb + b(j)
+ sumc = sumc + c(j)
+ 110 CONTINUE
+
+ epsilon = 1.D-6
+
+ IF (ABS(suma-aa)/suma .GT. epsilon) THEN
+ PRINT *,'Failed Validation on array a()'
+ PRINT *,'Target Sum of a is = ',aa
+ PRINT *,'Computed Sum of a is = ',suma
+ ELSEIF (ABS(sumb-bb)/sumb .GT. epsilon) THEN
+ PRINT *,'Failed Validation on array b()'
+ PRINT *,'Target Sum of b is = ',bb
+ PRINT *,'Computed Sum of b is = ',sumb
+ ELSEIF (ABS(sumc-cc)/sumc .GT. epsilon) THEN
+ PRINT *,'Failed Validation on array c()'
+ PRINT *,'Target Sum of c is = ',cc
+ PRINT *,'Computed Sum of c is = ',sumc
+ ELSE
+ PRINT *,'Solution Validates!'
+ ENDIF
+
+ END
+
diff --git a/meta/meta-mediatek-gpl/recipes-benchmark/stream/stream_5.10.bb b/meta/meta-mediatek-gpl/recipes-benchmark/stream/stream_5.10.bb
new file mode 100644
index 0000000..a049ad2
--- /dev/null
+++ b/meta/meta-mediatek-gpl/recipes-benchmark/stream/stream_5.10.bb
@@ -0,0 +1,27 @@
+DESCRIPTION = "Stream Benchmark"
+HOMEPAGE = "http://www.cs.virginia.edu/stream/"
+LICENSE = "Stream_Benchmark_License"
+LIC_FILES_CHKSUM = "file://LICENSE.txt;md5=bca8cbe07976fe64c8946378d08314b0"
+
+SRC_URI = "file://LICENSE.txt \
+ file://Makefile \
+ file://stream.c \
+ "
+
+S = "${WORKDIR}"
+
+PACKAGES =+ "${PN}-openmp"
+
+# Need to override Makefile variables
+EXTRA_OEMAKE = "-e MAKEFLAGS="
+
+do_compile() {
+ # build the release version
+ oe_runmake
+}
+
+do_install() {
+ install -d ${D}/${bindir}
+ install -m 0755 ${S}/stream_c ${D}/${bindir}/
+}
+
diff --git a/meta/meta-mediatek-gpl/recipes-bsp/u-boot/u-boot-common_2016.11.inc b/meta/meta-mediatek-gpl/recipes-bsp/u-boot/u-boot-common_2016.11.inc
new file mode 100644
index 0000000..842228a
--- /dev/null
+++ b/meta/meta-mediatek-gpl/recipes-bsp/u-boot/u-boot-common_2016.11.inc
@@ -0,0 +1,16 @@
+HOMEPAGE = "http://www.denx.de/wiki/U-Boot/WebHome"
+SECTION = "bootloaders"
+
+LICENSE = "GPLv2+"
+LIC_FILES_CHKSUM = "file://Licenses/README;md5=a2c678cfd4a4d97135585cad908541c6"
+
+# This revision corresponds to the tag "v2016.03"
+# We use the revision in order to avoid having to fetch it from the
+# repo during parse
+SRCREV = "29e0cfb4f77f7aa369136302cee14a91e22dca71"
+
+PV = "v2016.11+git${SRCPV}"
+
+SRC_URI = "git://git.denx.de/u-boot.git;branch=master"
+
+S = "${WORKDIR}/git"
diff --git a/meta/meta-mediatek-gpl/recipes-bsp/u-boot/u-boot-common_2018.07.inc b/meta/meta-mediatek-gpl/recipes-bsp/u-boot/u-boot-common_2018.07.inc
new file mode 100644
index 0000000..304978a
--- /dev/null
+++ b/meta/meta-mediatek-gpl/recipes-bsp/u-boot/u-boot-common_2018.07.inc
@@ -0,0 +1,16 @@
+HOMEPAGE = "http://www.denx.de/wiki/U-Boot/WebHome"
+SECTION = "bootloaders"
+DEPENDS += "flex-native bison-native"
+
+LICENSE = "GPLv2+"
+LIC_FILES_CHKSUM = "file://Licenses/README;md5=30503fd321432fc713238f582193b78e"
+PE = "1"
+
+# We use the revision in order to avoid having to fetch it from the
+# repo during parse
+SRCREV = "8c5d4fd0ec222701598a27b26ab7265d4cee45a3"
+
+SRC_URI = "git://git.denx.de/u-boot.git;branch=master"
+
+
+S = "${WORKDIR}/git"
diff --git a/meta/meta-mediatek-gpl/recipes-bsp/u-boot/u-boot-mkimage-2016.11/0001-libfdt-fix-fdt_find_region-incorrectly-adding-parent.patch b/meta/meta-mediatek-gpl/recipes-bsp/u-boot/u-boot-mkimage-2016.11/0001-libfdt-fix-fdt_find_region-incorrectly-adding-parent.patch
new file mode 100644
index 0000000..872ec91
--- /dev/null
+++ b/meta/meta-mediatek-gpl/recipes-bsp/u-boot/u-boot-mkimage-2016.11/0001-libfdt-fix-fdt_find_region-incorrectly-adding-parent.patch
@@ -0,0 +1,31 @@
+From 5f4e6392561efdd6ccda9d37d6677313e539eb3e Mon Sep 17 00:00:00 2001
+From: Jimmy Huang <jimmy.huang@mediatek.com>
+Date: Thu, 19 Jan 2017 16:29:20 +0800
+Subject: [PATCH] libfdt: fix fdt_find_region incorrectly adding parent's end
+ node
+
+This patch fix fdt_find_region incorrectly adding parent's end node to
+regions when it shouldn't. For example, when finding regions for
+/signature/key-dev, the end node of its parent, /signature, will
+also be included which is incorrect behavior.
+
+Change-Id: I4a5de815b1534f6b682e3ed8f2cd8154506c27f9
+---
+ lib/libfdt/fdt_wip.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/lib/libfdt/fdt_wip.c b/lib/libfdt/fdt_wip.c
+index 45fb964..37be286 100644
+--- a/lib/libfdt/fdt_wip.c
++++ b/lib/libfdt/fdt_wip.c
+@@ -180,6 +180,7 @@ int fdt_find_regions(const void *fdt, char * const inc[], int inc_count,
+
+ case FDT_END_NODE:
+ include = want;
++ stop_at = offset;
+ want = stack[depth--];
+ while (end > path && *--end != '/')
+ ;
+--
+1.9.1
+
diff --git a/meta/meta-mediatek-gpl/recipes-bsp/u-boot/u-boot-mkimage-2016.11/0001-rsa-add-sha-256-384-512-rsa-2048-3072-4096-algorithm.patch b/meta/meta-mediatek-gpl/recipes-bsp/u-boot/u-boot-mkimage-2016.11/0001-rsa-add-sha-256-384-512-rsa-2048-3072-4096-algorithm.patch
new file mode 100644
index 0000000..0e3b85e
--- /dev/null
+++ b/meta/meta-mediatek-gpl/recipes-bsp/u-boot/u-boot-mkimage-2016.11/0001-rsa-add-sha-256-384-512-rsa-2048-3072-4096-algorithm.patch
@@ -0,0 +1,1403 @@
+From 37c917d965c6dcbc3509b8776d79ad75a9102678 Mon Sep 17 00:00:00 2001
+From: HC Yen <hc.yen@mediatek.com>
+Date: Tue, 6 Dec 2016 16:38:46 +0800
+Subject: [PATCH 1/3] rsa: add sha{256,384,512},rsa{2048,3072,4096} algorithms
+
+Add support for "sha256,rsa3072", "sha384,rsa2048", "sha384,rsa3072",
+"sha384,rsa4096", "sha512,rsa2048", "sha512,rsa3072", and
+"sha512,rsa4096" signatures in u-boot.
+---
+ common/hash.c | 71 +++++++
+ common/image-fit.c | 9 +
+ common/image-sig.c | 121 +++++++++++-
+ include/hash.h | 2 +-
+ include/image.h | 18 ++
+ include/u-boot/rsa-checksum.h | 12 +-
+ include/u-boot/rsa.h | 1 +
+ include/u-boot/sha4.h | 159 +++++++++++++++
+ lib/Kconfig | 16 ++
+ lib/Makefile | 2 +
+ lib/rsa/rsa-checksum.c | 312 +++++++++++++++++++++++++++++
+ lib/sha4.c | 447 ++++++++++++++++++++++++++++++++++++++++++
+ tools/Makefile | 1 +
+ 13 files changed, 1167 insertions(+), 4 deletions(-)
+ create mode 100644 include/u-boot/sha4.h
+ create mode 100644 lib/sha4.c
+
+diff --git a/common/hash.c b/common/hash.c
+index b645298..d563292 100644
+--- a/common/hash.c
++++ b/common/hash.c
+@@ -28,6 +28,7 @@
+ #include <u-boot/crc.h>
+ #include <u-boot/sha1.h>
+ #include <u-boot/sha256.h>
++#include <u-boot/sha4.h>
+ #include <u-boot/md5.h>
+
+ #ifdef CONFIG_SHA1
+@@ -84,6 +85,58 @@ static int hash_finish_sha256(struct hash_algo *algo, void *ctx, void
+ free(ctx);
+ return 0;
+ }
++
++static int hash_init_sha384(struct hash_algo *algo, void **ctxp)
++{
++ sha4_context *ctx = malloc(sizeof(sha4_context));
++ sha4_starts(ctx, 1);
++ *ctxp = ctx;
++ return 0;
++}
++
++static int hash_update_sha384(struct hash_algo *algo, void *ctx,
++ const void *buf, unsigned int size, int is_last)
++{
++ sha4_update((sha4_context *)ctx, (unsigned char *)buf, size);
++ return 0;
++}
++
++static int hash_finish_sha384(struct hash_algo *algo, void *ctx, void
++ *dest_buf, int size)
++{
++ if (size < algo->digest_size)
++ return -1;
++
++ sha4_finish((sha4_context *)ctx, dest_buf);
++ free(ctx);
++ return 0;
++}
++
++static int hash_init_sha512(struct hash_algo *algo, void **ctxp)
++{
++ sha4_context *ctx = malloc(sizeof(sha4_context));
++ sha4_starts(ctx, 0);
++ *ctxp = ctx;
++ return 0;
++}
++
++static int hash_update_sha512(struct hash_algo *algo, void *ctx,
++ const void *buf, unsigned int size, int is_last)
++{
++ sha4_update((sha4_context *)ctx, (unsigned char *)buf, size);
++ return 0;
++}
++
++static int hash_finish_sha512(struct hash_algo *algo, void *ctx, void
++ *dest_buf, int size)
++{
++ if (size < algo->digest_size)
++ return -1;
++
++ sha4_finish((sha4_context *)ctx, dest_buf);
++ free(ctx);
++ return 0;
++}
+ #endif
+
+ static int hash_init_crc32(struct hash_algo *algo, void **ctxp)
+@@ -166,6 +219,24 @@ static struct hash_algo hash_algo[] = {
+ hash_update_sha256,
+ hash_finish_sha256,
+ },
++ {
++ "sha384",
++ SHA384_SUM_LEN,
++ sha384_csum_wd,
++ CHUNKSZ_SHA384,
++ hash_init_sha384,
++ hash_update_sha384,
++ hash_finish_sha384,
++ },
++ {
++ "sha512",
++ SHA512_SUM_LEN,
++ sha512_csum_wd,
++ CHUNKSZ_SHA512,
++ hash_init_sha512,
++ hash_update_sha512,
++ hash_finish_sha512,
++ },
+ #endif
+ {
+ "crc32",
+diff --git a/common/image-fit.c b/common/image-fit.c
+index 77dc011..2d19e75 100644
+--- a/common/image-fit.c
++++ b/common/image-fit.c
+@@ -27,6 +27,7 @@ DECLARE_GLOBAL_DATA_PTR;
+ #include <u-boot/md5.h>
+ #include <u-boot/sha1.h>
+ #include <u-boot/sha256.h>
++#include <u-boot/sha4.h>
+
+ /*****************************************************************************/
+ /* New uImage format routines */
+@@ -931,6 +932,14 @@ int calculate_hash(const void *data, int data_len, const char *algo,
+ sha256_csum_wd((unsigned char *)data, data_len,
+ (unsigned char *)value, CHUNKSZ_SHA256);
+ *value_len = SHA256_SUM_LEN;
++ } else if (IMAGE_ENABLE_SHA384 && strcmp(algo, "sha384") == 0) {
++ sha384_csum_wd((unsigned char *)data, data_len,
++ (unsigned char *)value, CHUNKSZ_SHA384);
++ *value_len = SHA384_SUM_LEN;
++ } else if (IMAGE_ENABLE_SHA512 && strcmp(algo, "sha512") == 0) {
++ sha512_csum_wd((unsigned char *)data, data_len,
++ (unsigned char *)value, CHUNKSZ_SHA512);
++ *value_len = SHA512_SUM_LEN;
+ } else if (IMAGE_ENABLE_MD5 && strcmp(algo, "md5") == 0) {
+ md5_wd((unsigned char *)data, data_len, value, CHUNKSZ_MD5);
+ *value_len = 16;
+diff --git a/common/image-sig.c b/common/image-sig.c
+index 28f7a20..57eab9f 100644
+--- a/common/image-sig.c
++++ b/common/image-sig.c
+@@ -54,12 +54,82 @@ struct checksum_algo checksum_algos[] = {
+ {
+ "sha256",
+ SHA256_SUM_LEN,
++ RSA3072_BYTES,
++#if IMAGE_ENABLE_SIGN
++ EVP_sha256,
++#endif
++ hash_calculate,
++ padding_sha256_rsa3072,
++ },
++ {
++ "sha256",
++ SHA256_SUM_LEN,
+ RSA4096_BYTES,
+ #if IMAGE_ENABLE_SIGN
+ EVP_sha256,
+ #endif
+ hash_calculate,
+ padding_sha256_rsa4096,
++ },
++ {
++ "sha384",
++ SHA384_SUM_LEN,
++ RSA2048_BYTES,
++#if IMAGE_ENABLE_SIGN
++ EVP_sha384,
++#endif
++ hash_calculate,
++ padding_sha384_rsa2048,
++ },
++ {
++ "sha384",
++ SHA384_SUM_LEN,
++ RSA3072_BYTES,
++#if IMAGE_ENABLE_SIGN
++ EVP_sha384,
++#endif
++ hash_calculate,
++ padding_sha384_rsa3072,
++ },
++ {
++ "sha384",
++ SHA384_SUM_LEN,
++ RSA4096_BYTES,
++#if IMAGE_ENABLE_SIGN
++ EVP_sha384,
++#endif
++ hash_calculate,
++ padding_sha384_rsa4096,
++ },
++ {
++ "sha512",
++ SHA512_SUM_LEN,
++ RSA2048_BYTES,
++#if IMAGE_ENABLE_SIGN
++ EVP_sha512,
++#endif
++ hash_calculate,
++ padding_sha512_rsa2048,
++ },
++ {
++ "sha512",
++ SHA512_SUM_LEN,
++ RSA3072_BYTES,
++#if IMAGE_ENABLE_SIGN
++ EVP_sha512,
++#endif
++ hash_calculate,
++ padding_sha512_rsa3072,
++ },
++ {
++ "sha512",
++ SHA512_SUM_LEN,
++ RSA4096_BYTES,
++#if IMAGE_ENABLE_SIGN
++ EVP_sha512,
++#endif
++ hash_calculate,
++ padding_sha512_rsa4096,
+ }
+
+ };
+@@ -80,11 +150,60 @@ struct image_sig_algo image_sig_algos[] = {
+ &checksum_algos[1],
+ },
+ {
+- "sha256,rsa4096",
++ "sha256,rsa3072",
+ rsa_sign,
+ rsa_add_verify_data,
+ rsa_verify,
+ &checksum_algos[2],
++ },
++ {
++ "sha256,rsa4096",
++ rsa_sign,
++ rsa_add_verify_data,
++ rsa_verify,
++ &checksum_algos[3],
++ },
++ {
++ "sha384,rsa2048",
++ rsa_sign,
++ rsa_add_verify_data,
++ rsa_verify,
++ &checksum_algos[4],
++ },
++ {
++ "sha384,rsa3072",
++ rsa_sign,
++ rsa_add_verify_data,
++ rsa_verify,
++ &checksum_algos[5],
++ },
++ {
++ "sha384,rsa4096",
++ rsa_sign,
++ rsa_add_verify_data,
++ rsa_verify,
++ &checksum_algos[6],
++ },
++ {
++ "sha512,rsa2048",
++ rsa_sign,
++ rsa_add_verify_data,
++ rsa_verify,
++ &checksum_algos[7],
++ },
++ {
++ "sha512,rsa3072",
++ rsa_sign,
++ rsa_add_verify_data,
++ rsa_verify,
++ &checksum_algos[8],
++ },
++ {
++ "sha512,rsa4096",
++ rsa_sign,
++ rsa_add_verify_data,
++ rsa_verify,
++ &checksum_algos[9],
+ }
+
+ };
+diff --git a/include/hash.h b/include/hash.h
+index d814337..59ba707 100644
+--- a/include/hash.h
++++ b/include/hash.h
+@@ -10,7 +10,7 @@
+ * Maximum digest size for all algorithms we support. Having this value
+ * avoids a malloc() or C99 local declaration in common/cmd_hash.c.
+ */
+-#define HASH_MAX_DIGEST_SIZE 32
++#define HASH_MAX_DIGEST_SIZE 64
+
+ enum {
+ HASH_FLAG_VERIFY = 1 << 0, /* Enable verify mode */
+diff --git a/include/image.h b/include/image.h
+index 2b1296c..81735e8 100644
+--- a/include/image.h
++++ b/include/image.h
+@@ -65,15 +65,25 @@ struct lmb;
+ # ifdef CONFIG_SPL_SHA256_SUPPORT
+ # define IMAGE_ENABLE_SHA256 1
+ # endif
++# ifdef CONFIG_SPL_SHA384_SUPPORT
++# define IMAGE_ENABLE_SHA384 1
++# endif
++# ifdef CONFIG_SPL_SHA512_SUPPORT
++# define IMAGE_ENABLE_SHA512 1
++# endif
+ # else
+ # define CONFIG_CRC32 /* FIT images need CRC32 support */
+ # define CONFIG_MD5 /* and MD5 */
+ # define CONFIG_SHA1 /* and SHA1 */
+ # define CONFIG_SHA256 /* and SHA256 */
++# define CONFIG_SHA384 /* and SHA384 */
++# define CONFIG_SHA512 /* and SHA512 */
+ # define IMAGE_ENABLE_CRC32 1
+ # define IMAGE_ENABLE_MD5 1
+ # define IMAGE_ENABLE_SHA1 1
+ # define IMAGE_ENABLE_SHA256 1
++# define IMAGE_ENABLE_SHA384 1
++# define IMAGE_ENABLE_SHA512 1
+ # endif
+
+ #ifdef CONFIG_FIT_DISABLE_SHA256
+@@ -97,6 +107,14 @@ struct lmb;
+ #define IMAGE_ENABLE_SHA256 0
+ #endif
+
++#ifndef IMAGE_ENABLE_SHA384
++#define IMAGE_ENABLE_SHA384 0
++#endif
++
++#ifndef IMAGE_ENABLE_SHA512
++#define IMAGE_ENABLE_SHA512 0
++#endif
++
+ #endif /* IMAGE_ENABLE_FIT */
+
+ #ifdef CONFIG_SYS_BOOT_RAMDISK_HIGH
+diff --git a/include/u-boot/rsa-checksum.h b/include/u-boot/rsa-checksum.h
+index 3c69d85..d8c584a 100644
+--- a/include/u-boot/rsa-checksum.h
++++ b/include/u-boot/rsa-checksum.h
+@@ -11,10 +11,18 @@
+ #include <image.h>
+ #include <u-boot/sha1.h>
+ #include <u-boot/sha256.h>
++#include <u-boot/sha4.h>
+
+-extern const uint8_t padding_sha256_rsa4096[];
+-extern const uint8_t padding_sha256_rsa2048[];
+ extern const uint8_t padding_sha1_rsa2048[];
++extern const uint8_t padding_sha256_rsa2048[];
++extern const uint8_t padding_sha256_rsa3072[];
++extern const uint8_t padding_sha256_rsa4096[];
++extern const uint8_t padding_sha384_rsa2048[];
++extern const uint8_t padding_sha384_rsa3072[];
++extern const uint8_t padding_sha384_rsa4096[];
++extern const uint8_t padding_sha512_rsa2048[];
++extern const uint8_t padding_sha512_rsa3072[];
++extern const uint8_t padding_sha512_rsa4096[];
+
+ /**
+ * hash_calculate() - Calculate hash over the data
+diff --git a/include/u-boot/rsa.h b/include/u-boot/rsa.h
+index 0e96c38..3921250 100644
+--- a/include/u-boot/rsa.h
++++ b/include/u-boot/rsa.h
+@@ -108,6 +108,7 @@ static inline int rsa_verify(struct image_sign_info *info,
+ #endif
+
+ #define RSA2048_BYTES (2048 / 8)
++#define RSA3072_BYTES (3072 / 8)
+ #define RSA4096_BYTES (4096 / 8)
+
+ /* This is the minimum/maximum key size we support, in bits */
+diff --git a/include/u-boot/sha4.h b/include/u-boot/sha4.h
+new file mode 100644
+index 0000000..e9e5865
+--- /dev/null
++++ b/include/u-boot/sha4.h
+@@ -0,0 +1,159 @@
++/**
++ * \file sha4.h
++ *
++ * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine
++ *
++ * Copyright (C) 2009 Paul Bakker <polarssl_maintainer at polarssl dot org>
++ *
++ * All rights reserved.
++ *
++ * 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 names of PolarSSL or XySSL 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.
++ */
++#ifndef _SHA4_H
++#define _SHA4_H
++
++#define SHA384_SUM_LEN 48
++#define SHA512_SUM_LEN 64
++
++/* Reset watchdog each time we process this many bytes */
++#define CHUNKSZ_SHA384 (64 * 1024)
++#define CHUNKSZ_SHA512 (64 * 1024)
++
++#define UL64(x) x##ULL
++#define int64 long long
++
++/**
++ * \brief SHA-512 context structure
++ */
++typedef struct {
++ unsigned int64 total[2]; /*!< number of bytes processed */
++ unsigned int64 state[8]; /*!< intermediate digest state */
++ unsigned char buffer[128]; /*!< data block being processed */
++
++ unsigned char ipad[128]; /*!< HMAC: inner padding */
++ unsigned char opad[128]; /*!< HMAC: outer padding */
++ int is384; /*!< 0 => SHA-512, else SHA-384 */
++} sha4_context;
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++ /**
++ * \brief SHA-512 context setup
++ *
++ * \param ctx context to be initialized
++ * \param is384 0 = use SHA512, 1 = use SHA384
++ */
++ void sha4_starts(sha4_context * ctx, int is384);
++
++ /**
++ * \brief SHA-512 process buffer
++ *
++ * \param ctx SHA-512 context
++ * \param input buffer holding the data
++ * \param ilen length of the input data
++ */
++ void sha4_update(sha4_context * ctx, unsigned char *input, int ilen);
++
++ /**
++ * \brief SHA-512 final digest
++ *
++ * \param ctx SHA-512 context
++ * \param output SHA-384/512 checksum result
++ */
++ void sha4_finish(sha4_context * ctx, unsigned char output[64]);
++
++ /**
++ * \brief Output = SHA-512( input buffer )
++ *
++ * \param input buffer holding the data
++ * \param ilen length of the input data
++ * \param output SHA-384/512 checksum result
++ * \param is384 0 = use SHA512, 1 = use SHA384
++ */
++ void sha4(unsigned char *input, int ilen,
++ unsigned char output[64], int is384);
++
++void sha384_csum_wd(const unsigned char *input, unsigned int ilen,
++ unsigned char *output, unsigned int chunk_sz);
++void sha512_csum_wd(const unsigned char *input, unsigned int ilen,
++ unsigned char *output, unsigned int chunk_sz);
++
++ /**
++ * \brief SHA-512 HMAC context setup
++ *
++ * \param ctx HMAC context to be initialized
++ * \param is384 0 = use SHA512, 1 = use SHA384
++ * \param key HMAC secret key
++ * \param keylen length of the HMAC key
++ */
++ void sha4_hmac_starts(sha4_context * ctx, unsigned char *key,
++ int keylen, int is384);
++
++ /**
++ * \brief SHA-512 HMAC process buffer
++ *
++ * \param ctx HMAC context
++ * \param input buffer holding the data
++ * \param ilen length of the input data
++ */
++ void sha4_hmac_update(sha4_context * ctx, unsigned char *input,
++ int ilen);
++
++ /**
++ * \brief SHA-512 HMAC final digest
++ *
++ * \param ctx HMAC context
++ * \param output SHA-384/512 HMAC checksum result
++ */
++ void sha4_hmac_finish(sha4_context * ctx, unsigned char output[64]);
++
++ /**
++ * \brief Output = HMAC-SHA-512( hmac key, input buffer )
++ *
++ * \param key HMAC secret key
++ * \param keylen length of the HMAC key
++ * \param input buffer holding the data
++ * \param ilen length of the input data
++ * \param output HMAC-SHA-384/512 result
++ * \param is384 0 = use SHA512, 1 = use SHA384
++ */
++ void sha4_hmac(unsigned char *key, int keylen,
++ unsigned char *input, int ilen,
++ unsigned char output[64], int is384);
++
++ /**
++ * \brief Checkup routine
++ *
++ * \return 0 if successful, or 1 if the test failed
++ */
++ int sha4_self_test(int verbose);
++
++#ifdef __cplusplus
++}
++#endif
++#endif /* sha4.h */
+diff --git a/lib/Kconfig b/lib/Kconfig
+index b16062f..1cba1b5 100644
+--- a/lib/Kconfig
++++ b/lib/Kconfig
+@@ -85,6 +85,22 @@ config SHA256
+ The SHA256 algorithm produces a 256-bit (32-byte) hash value
+ (digest).
+
++config SHA384
++ bool "Enable SHA384 support"
++ help
++ This option enables support of hashing using SHA384 algorithm.
++ The hash is calculated in software.
++ The SHA384 algorithm produces a 384-bit (48-byte) hash value
++ (digest).
++
++config SHA512
++ bool "Enable SHA512 support"
++ help
++ This option enables support of hashing using SHA512 algorithm.
++ The hash is calculated in software.
++ The SHA512 algorithm produces a 512-bit (64-byte) hash value
++ (digest).
++
+ config SHA_HW_ACCEL
+ bool "Enable hashing using hardware"
+ help
+diff --git a/lib/Makefile b/lib/Makefile
+index 23e9f1e..ba5ba04 100644
+--- a/lib/Makefile
++++ b/lib/Makefile
+@@ -47,6 +47,8 @@ endif
+ obj-$(CONFIG_$(SPL_)RSA) += rsa/
+ obj-$(CONFIG_$(SPL_)SHA1) += sha1.o
+ obj-$(CONFIG_$(SPL_)SHA256) += sha256.o
++obj-$(CONFIG_$(SPL_)SHA384) += sha4.o
++obj-$(CONFIG_$(SPL_)SHA512) += sha4.o
+
+ obj-$(CONFIG_SPL_SAVEENV) += qsort.o
+ obj-$(CONFIG_$(SPL_)OF_LIBFDT) += libfdt/
+diff --git a/lib/rsa/rsa-checksum.c b/lib/rsa/rsa-checksum.c
+index db183ff..74e289c 100644
+--- a/lib/rsa/rsa-checksum.c
++++ b/lib/rsa/rsa-checksum.c
+@@ -15,6 +15,7 @@
+ #include "fdt_host.h"
+ #include <u-boot/sha1.h>
+ #include <u-boot/sha256.h>
++#include <u-boot/sha4.h>
+ #endif
+ #include <u-boot/rsa.h>
+
+@@ -74,6 +75,53 @@ const uint8_t padding_sha1_rsa2048[RSA2048_BYTES - SHA1_SUM_LEN] = {
+ 0x05, 0x00, 0x04, 0x14
+ };
+
++const uint8_t padding_sha256_rsa3072[RSA3072_BYTES - SHA256_SUM_LEN] = {
++ 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0x00, 0x30, 0x31, 0x30,
++ 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65,
++ 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20
++};
++
+ const uint8_t padding_sha256_rsa4096[RSA4096_BYTES - SHA256_SUM_LEN] = {
+ 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+@@ -137,6 +185,270 @@ const uint8_t padding_sha256_rsa4096[RSA4096_BYTES - SHA256_SUM_LEN] = {
+ 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20
+ };
+
++const uint8_t padding_sha384_rsa2048[RSA2048_BYTES - SHA384_SUM_LEN] = {
++ 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0x00, 0x30, 0x41, 0x30,
++ 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65,
++ 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30
++};
++
++const uint8_t padding_sha384_rsa3072[RSA3072_BYTES - SHA384_SUM_LEN] = {
++ 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0x00, 0x30, 0x41, 0x30,
++ 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65,
++ 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30
++};
++
++const uint8_t padding_sha384_rsa4096[RSA4096_BYTES - SHA384_SUM_LEN] = {
++ 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0x00, 0x30, 0x41, 0x30,
++ 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65,
++ 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30
++};
++
++const uint8_t padding_sha512_rsa2048[RSA2048_BYTES - SHA512_SUM_LEN] = {
++ 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0x00, 0x30, 0x51, 0x30,
++ 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65,
++ 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40
++};
++
++const uint8_t padding_sha512_rsa3072[RSA3072_BYTES - SHA512_SUM_LEN] = {
++ 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0x00, 0x30, 0x51, 0x30,
++ 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65,
++ 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40
++};
++
++const uint8_t padding_sha512_rsa4096[RSA4096_BYTES - SHA512_SUM_LEN] = {
++ 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0x00, 0x30, 0x51, 0x30,
++ 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65,
++ 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40
++};
++
+ int hash_calculate(const char *name,
+ const struct image_region region[],
+ int region_count, uint8_t *checksum)
+diff --git a/lib/sha4.c b/lib/sha4.c
+new file mode 100644
+index 0000000..929d267
+--- /dev/null
++++ b/lib/sha4.c
+@@ -0,0 +1,447 @@
++/*
++ * FIPS-180-2 compliant SHA-384/512 implementation
++ *
++ * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine
++ *
++ * Copyright (C) 2009 Paul Bakker <polarssl_maintainer at polarssl dot org>
++ *
++ * All rights reserved.
++ *
++ * 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 names of PolarSSL or XySSL 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.
++ */
++/*
++ * The SHA-512 Secure Hash Standard was published by NIST in 2002.
++ *
++ * http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf
++ */
++
++#ifndef USE_HOSTCC
++#include <common.h>
++#include <linux/string.h>
++#else
++#include <string.h>
++#endif /* USE_HOSTCC */
++#include <watchdog.h>
++#include <u-boot/sha4.h>
++
++/*
++ * 64-bit integer manipulation macros (big endian)
++ */
++#ifndef GET_UINT64_BE
++#define GET_UINT64_BE(n,b,i) \
++ { \
++ (n) = ( (unsigned int64) (b)[(i) ] << 56 ) \
++ | ( (unsigned int64) (b)[(i) + 1] << 48 ) \
++ | ( (unsigned int64) (b)[(i) + 2] << 40 ) \
++ | ( (unsigned int64) (b)[(i) + 3] << 32 ) \
++ | ( (unsigned int64) (b)[(i) + 4] << 24 ) \
++ | ( (unsigned int64) (b)[(i) + 5] << 16 ) \
++ | ( (unsigned int64) (b)[(i) + 6] << 8 ) \
++ | ( (unsigned int64) (b)[(i) + 7] ); \
++ }
++#endif
++
++#ifndef PUT_UINT64_BE
++#define PUT_UINT64_BE(n,b,i) \
++ { \
++ (b)[(i) ] = (unsigned char) ( (n) >> 56 ); \
++ (b)[(i) + 1] = (unsigned char) ( (n) >> 48 ); \
++ (b)[(i) + 2] = (unsigned char) ( (n) >> 40 ); \
++ (b)[(i) + 3] = (unsigned char) ( (n) >> 32 ); \
++ (b)[(i) + 4] = (unsigned char) ( (n) >> 24 ); \
++ (b)[(i) + 5] = (unsigned char) ( (n) >> 16 ); \
++ (b)[(i) + 6] = (unsigned char) ( (n) >> 8 ); \
++ (b)[(i) + 7] = (unsigned char) ( (n) ); \
++ }
++#endif
++
++/*
++ * Round constants
++ */
++static const unsigned int64 K[80] = {
++ UL64(0x428A2F98D728AE22), UL64(0x7137449123EF65CD),
++ UL64(0xB5C0FBCFEC4D3B2F), UL64(0xE9B5DBA58189DBBC),
++ UL64(0x3956C25BF348B538), UL64(0x59F111F1B605D019),
++ UL64(0x923F82A4AF194F9B), UL64(0xAB1C5ED5DA6D8118),
++ UL64(0xD807AA98A3030242), UL64(0x12835B0145706FBE),
++ UL64(0x243185BE4EE4B28C), UL64(0x550C7DC3D5FFB4E2),
++ UL64(0x72BE5D74F27B896F), UL64(0x80DEB1FE3B1696B1),
++ UL64(0x9BDC06A725C71235), UL64(0xC19BF174CF692694),
++ UL64(0xE49B69C19EF14AD2), UL64(0xEFBE4786384F25E3),
++ UL64(0x0FC19DC68B8CD5B5), UL64(0x240CA1CC77AC9C65),
++ UL64(0x2DE92C6F592B0275), UL64(0x4A7484AA6EA6E483),
++ UL64(0x5CB0A9DCBD41FBD4), UL64(0x76F988DA831153B5),
++ UL64(0x983E5152EE66DFAB), UL64(0xA831C66D2DB43210),
++ UL64(0xB00327C898FB213F), UL64(0xBF597FC7BEEF0EE4),
++ UL64(0xC6E00BF33DA88FC2), UL64(0xD5A79147930AA725),
++ UL64(0x06CA6351E003826F), UL64(0x142929670A0E6E70),
++ UL64(0x27B70A8546D22FFC), UL64(0x2E1B21385C26C926),
++ UL64(0x4D2C6DFC5AC42AED), UL64(0x53380D139D95B3DF),
++ UL64(0x650A73548BAF63DE), UL64(0x766A0ABB3C77B2A8),
++ UL64(0x81C2C92E47EDAEE6), UL64(0x92722C851482353B),
++ UL64(0xA2BFE8A14CF10364), UL64(0xA81A664BBC423001),
++ UL64(0xC24B8B70D0F89791), UL64(0xC76C51A30654BE30),
++ UL64(0xD192E819D6EF5218), UL64(0xD69906245565A910),
++ UL64(0xF40E35855771202A), UL64(0x106AA07032BBD1B8),
++ UL64(0x19A4C116B8D2D0C8), UL64(0x1E376C085141AB53),
++ UL64(0x2748774CDF8EEB99), UL64(0x34B0BCB5E19B48A8),
++ UL64(0x391C0CB3C5C95A63), UL64(0x4ED8AA4AE3418ACB),
++ UL64(0x5B9CCA4F7763E373), UL64(0x682E6FF3D6B2B8A3),
++ UL64(0x748F82EE5DEFB2FC), UL64(0x78A5636F43172F60),
++ UL64(0x84C87814A1F0AB72), UL64(0x8CC702081A6439EC),
++ UL64(0x90BEFFFA23631E28), UL64(0xA4506CEBDE82BDE9),
++ UL64(0xBEF9A3F7B2C67915), UL64(0xC67178F2E372532B),
++ UL64(0xCA273ECEEA26619C), UL64(0xD186B8C721C0C207),
++ UL64(0xEADA7DD6CDE0EB1E), UL64(0xF57D4F7FEE6ED178),
++ UL64(0x06F067AA72176FBA), UL64(0x0A637DC5A2C898A6),
++ UL64(0x113F9804BEF90DAE), UL64(0x1B710B35131C471B),
++ UL64(0x28DB77F523047D84), UL64(0x32CAAB7B40C72493),
++ UL64(0x3C9EBE0A15C9BEBC), UL64(0x431D67C49C100D4C),
++ UL64(0x4CC5D4BECB3E42B6), UL64(0x597F299CFC657E2A),
++ UL64(0x5FCB6FAB3AD6FAEC), UL64(0x6C44198C4A475817)
++};
++
++/*
++ * SHA-512 context setup
++ */
++void sha4_starts(sha4_context * ctx, int is384)
++{
++ ctx->total[0] = 0;
++ ctx->total[1] = 0;
++
++ if (is384 == 0) {
++ /* SHA-512 */
++ ctx->state[0] = UL64(0x6A09E667F3BCC908);
++ ctx->state[1] = UL64(0xBB67AE8584CAA73B);
++ ctx->state[2] = UL64(0x3C6EF372FE94F82B);
++ ctx->state[3] = UL64(0xA54FF53A5F1D36F1);
++ ctx->state[4] = UL64(0x510E527FADE682D1);
++ ctx->state[5] = UL64(0x9B05688C2B3E6C1F);
++ ctx->state[6] = UL64(0x1F83D9ABFB41BD6B);
++ ctx->state[7] = UL64(0x5BE0CD19137E2179);
++ } else {
++ /* SHA-384 */
++ ctx->state[0] = UL64(0xCBBB9D5DC1059ED8);
++ ctx->state[1] = UL64(0x629A292A367CD507);
++ ctx->state[2] = UL64(0x9159015A3070DD17);
++ ctx->state[3] = UL64(0x152FECD8F70E5939);
++ ctx->state[4] = UL64(0x67332667FFC00B31);
++ ctx->state[5] = UL64(0x8EB44A8768581511);
++ ctx->state[6] = UL64(0xDB0C2E0D64F98FA7);
++ ctx->state[7] = UL64(0x47B5481DBEFA4FA4);
++ }
++
++ ctx->is384 = is384;
++}
++
++static void sha4_process(sha4_context * ctx, unsigned char data[128])
++{
++ int i;
++ unsigned int64 temp1, temp2, W[80];
++ unsigned int64 A, B, C, D, E, F, G, H;
++
++#define SHR(x,n) (x >> n)
++#define ROTR(x,n) (SHR(x,n) | (x << (64 - n)))
++
++#define S0(x) (ROTR(x, 1) ^ ROTR(x, 8) ^ SHR(x, 7))
++#define S1(x) (ROTR(x,19) ^ ROTR(x,61) ^ SHR(x, 6))
++
++#define S2(x) (ROTR(x,28) ^ ROTR(x,34) ^ ROTR(x,39))
++#define S3(x) (ROTR(x,14) ^ ROTR(x,18) ^ ROTR(x,41))
++
++#define F0(x,y,z) ((x & y) | (z & (x | y)))
++#define F1(x,y,z) (z ^ (x & (y ^ z)))
++
++#define P(a,b,c,d,e,f,g,h,x,K) \
++ { \
++ temp1 = h + S3(e) + F1(e,f,g) + K + x; \
++ temp2 = S2(a) + F0(a,b,c); \
++ d += temp1; h = temp1 + temp2; \
++ }
++
++ for (i = 0; i < 16; i++) {
++ GET_UINT64_BE(W[i], data, i << 3);
++ }
++
++ for (; i < 80; i++) {
++ W[i] = S1(W[i - 2]) + W[i - 7] + S0(W[i - 15]) + W[i - 16];
++ }
++
++ A = ctx->state[0];
++ B = ctx->state[1];
++ C = ctx->state[2];
++ D = ctx->state[3];
++ E = ctx->state[4];
++ F = ctx->state[5];
++ G = ctx->state[6];
++ H = ctx->state[7];
++ i = 0;
++
++ do {
++ P(A, B, C, D, E, F, G, H, W[i], K[i]);
++ i++;
++ P(H, A, B, C, D, E, F, G, W[i], K[i]);
++ i++;
++ P(G, H, A, B, C, D, E, F, W[i], K[i]);
++ i++;
++ P(F, G, H, A, B, C, D, E, W[i], K[i]);
++ i++;
++ P(E, F, G, H, A, B, C, D, W[i], K[i]);
++ i++;
++ P(D, E, F, G, H, A, B, C, W[i], K[i]);
++ i++;
++ P(C, D, E, F, G, H, A, B, W[i], K[i]);
++ i++;
++ P(B, C, D, E, F, G, H, A, W[i], K[i]);
++ i++;
++ } while (i < 80);
++
++ ctx->state[0] += A;
++ ctx->state[1] += B;
++ ctx->state[2] += C;
++ ctx->state[3] += D;
++ ctx->state[4] += E;
++ ctx->state[5] += F;
++ ctx->state[6] += G;
++ ctx->state[7] += H;
++}
++
++/*
++ * SHA-512 process buffer
++ */
++void sha4_update(sha4_context * ctx, unsigned char *input, int ilen)
++{
++ int fill;
++ unsigned int64 left;
++
++ if (ilen <= 0)
++ return;
++
++ left = ctx->total[0] & 0x7F;
++ fill = (int)(128 - left);
++
++ ctx->total[0] += ilen;
++
++ if (ctx->total[0] < (unsigned int64)ilen)
++ ctx->total[1]++;
++
++ if (left && ilen >= fill) {
++ memcpy((void *)(ctx->buffer + left), (void *)input, fill);
++ sha4_process(ctx, ctx->buffer);
++ input += fill;
++ ilen -= fill;
++ left = 0;
++ }
++
++ while (ilen >= 128) {
++ sha4_process(ctx, input);
++ input += 128;
++ ilen -= 128;
++ }
++
++ if (ilen > 0) {
++ memcpy((void *)(ctx->buffer + left), (void *)input, ilen);
++ }
++}
++
++static const unsigned char sha4_padding[128] = {
++ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
++};
++
++/*
++ * SHA-512 final digest
++ */
++void sha4_finish(sha4_context * ctx, unsigned char output[64])
++{
++ int last, padn;
++ unsigned int64 high, low;
++ unsigned char msglen[16];
++
++ high = (ctx->total[0] >> 61)
++ | (ctx->total[1] << 3);
++ low = (ctx->total[0] << 3);
++
++ PUT_UINT64_BE(high, msglen, 0);
++ PUT_UINT64_BE(low, msglen, 8);
++
++ last = (int)(ctx->total[0] & 0x7F);
++ padn = (last < 112) ? (112 - last) : (240 - last);
++
++ sha4_update(ctx, (unsigned char *)sha4_padding, padn);
++ sha4_update(ctx, msglen, 16);
++
++ PUT_UINT64_BE(ctx->state[0], output, 0);
++ PUT_UINT64_BE(ctx->state[1], output, 8);
++ PUT_UINT64_BE(ctx->state[2], output, 16);
++ PUT_UINT64_BE(ctx->state[3], output, 24);
++ PUT_UINT64_BE(ctx->state[4], output, 32);
++ PUT_UINT64_BE(ctx->state[5], output, 40);
++
++ if (ctx->is384 == 0) {
++ PUT_UINT64_BE(ctx->state[6], output, 48);
++ PUT_UINT64_BE(ctx->state[7], output, 56);
++ }
++}
++
++/*
++ * output = SHA-512( input buffer )
++ */
++void sha4(unsigned char *input, int ilen, unsigned char output[64], int is384)
++{
++ sha4_context ctx;
++
++ sha4_starts(&ctx, is384);
++ sha4_update(&ctx, input, ilen);
++ sha4_finish(&ctx, output);
++
++ memset(&ctx, 0, sizeof(sha4_context));
++}
++
++/*
++ * Output = SHA-4( input buffer ). Trigger the watchdog every 'chunk_sz'
++ * bytes of input processed.
++ */
++static void sha4_csum_wd(const unsigned char *input, unsigned int ilen,
++ unsigned char *output, unsigned int chunk_sz, int is384)
++{
++ sha4_context ctx;
++#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
++ const unsigned char *end;
++ unsigned char *curr;
++ int chunk;
++#endif
++
++ sha4_starts(&ctx, is384);
++
++#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
++ curr = (unsigned char *)input;
++ end = input + ilen;
++ while (curr < end) {
++ chunk = end - curr;
++ if (chunk > chunk_sz)
++ chunk = chunk_sz;
++ sha4_update(&ctx, curr, chunk);
++ curr += chunk;
++ WATCHDOG_RESET();
++ }
++#else
++ sha4_update(&ctx, input, ilen);
++#endif
++
++ sha4_finish(&ctx, output);
++}
++
++void sha384_csum_wd(const unsigned char *input, unsigned int ilen,
++ unsigned char *output, unsigned int chunk_sz)
++{
++ sha4_csum_wd(input, ilen, output, chunk_sz, 1);
++}
++
++void sha512_csum_wd(const unsigned char *input, unsigned int ilen,
++ unsigned char *output, unsigned int chunk_sz)
++{
++ sha4_csum_wd(input, ilen, output, chunk_sz, 0);
++}
++
++/*
++ * SHA-512 HMAC context setup
++ */
++void sha4_hmac_starts(sha4_context * ctx, unsigned char *key, int keylen,
++ int is384)
++{
++ int i;
++ unsigned char sum[64];
++
++ if (keylen > 128) {
++ sha4(key, keylen, sum, is384);
++ keylen = (is384) ? 48 : 64;
++ key = sum;
++ }
++
++ memset(ctx->ipad, 0x36, 128);
++ memset(ctx->opad, 0x5C, 128);
++
++ for (i = 0; i < keylen; i++) {
++ ctx->ipad[i] = (unsigned char)(ctx->ipad[i] ^ key[i]);
++ ctx->opad[i] = (unsigned char)(ctx->opad[i] ^ key[i]);
++ }
++
++ sha4_starts(ctx, is384);
++ sha4_update(ctx, ctx->ipad, 128);
++
++ memset(sum, 0, sizeof(sum));
++}
++
++/*
++ * SHA-512 HMAC process buffer
++ */
++void sha4_hmac_update(sha4_context * ctx, unsigned char *input, int ilen)
++{
++ sha4_update(ctx, input, ilen);
++}
++
++/*
++ * SHA-512 HMAC final digest
++ */
++void sha4_hmac_finish(sha4_context * ctx, unsigned char output[64])
++{
++ int is384, hlen;
++ unsigned char tmpbuf[64];
++
++ is384 = ctx->is384;
++ hlen = (is384 == 0) ? 64 : 48;
++
++ sha4_finish(ctx, tmpbuf);
++ sha4_starts(ctx, is384);
++ sha4_update(ctx, ctx->opad, 128);
++ sha4_update(ctx, tmpbuf, hlen);
++ sha4_finish(ctx, output);
++
++ memset(tmpbuf, 0, sizeof(tmpbuf));
++}
++
++/*
++ * output = HMAC-SHA-512( hmac key, input buffer )
++ */
++void sha4_hmac(unsigned char *key, int keylen,
++ unsigned char *input, int ilen,
++ unsigned char output[64], int is384)
++{
++ sha4_context ctx;
++
++ sha4_hmac_starts(&ctx, key, keylen, is384);
++ sha4_hmac_update(&ctx, input, ilen);
++ sha4_hmac_finish(&ctx, output);
++
++ memset(&ctx, 0, sizeof(sha4_context));
++}
+diff --git a/tools/Makefile b/tools/Makefile
+index 9edb504..59f4911 100644
+--- a/tools/Makefile
++++ b/tools/Makefile
+@@ -95,6 +95,7 @@ dumpimage-mkimage-objs := aisimage.o \
+ socfpgaimage.o \
+ lib/sha1.o \
+ lib/sha256.o \
++ lib/sha4.o \
+ common/hash.o \
+ ublimage.o \
+ zynqimage.o \
+--
+1.9.1
+
diff --git a/meta/meta-mediatek-gpl/recipes-bsp/u-boot/u-boot-mkimage-2016.11/0002-rsa-add-sha-256-384-512-rsassa-pss-2048-3072-4096-al.patch b/meta/meta-mediatek-gpl/recipes-bsp/u-boot/u-boot-mkimage-2016.11/0002-rsa-add-sha-256-384-512-rsassa-pss-2048-3072-4096-al.patch
new file mode 100644
index 0000000..a478bac
--- /dev/null
+++ b/meta/meta-mediatek-gpl/recipes-bsp/u-boot/u-boot-mkimage-2016.11/0002-rsa-add-sha-256-384-512-rsassa-pss-2048-3072-4096-al.patch
@@ -0,0 +1,227 @@
+From f30d0041711c919f6ea8435cbbc3c411801ef953 Mon Sep 17 00:00:00 2001
+From: HC Yen <hc.yen@mediatek.com>
+Date: Tue, 13 Dec 2016 12:56:49 +0800
+Subject: [PATCH 2/3] rsa: add sha{256,384,512},rsassa-pss{2048,3072,4096}
+ algorithms
+
+Add support for "sha256,rsassa-pss2048", "sha256,rsassa-pss3072",
+"sha384,rsassa-pss2048", "sha384,rsassa-pss3072",
+"sha384,rsassa-pss4096", "sha512,rsassa-pss2048",
+"sha512,rsassa-pss3072", and "sha512,rsassa-pss4096" signatures in
+u-boot.
+---
+ common/image-sig.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++++
+ include/u-boot/rsa.h | 11 +++++++++
+ lib/rsa/rsa-sign.c | 60 ++++++++++++++++++++++++++++++++++++++++++++-----
+ 3 files changed, 129 insertions(+), 5 deletions(-)
+
+diff --git a/common/image-sig.c b/common/image-sig.c
+index 57eab9f..f0ee8b3 100644
+--- a/common/image-sig.c
++++ b/common/image-sig.c
+@@ -204,6 +204,69 @@ struct image_sig_algo image_sig_algos[] = {
+ rsa_add_verify_data,
+ rsa_verify,
+ &checksum_algos[9],
++ },
++ {
++ "sha256,rsassa-pss2048",
++ rsassa_pss_sign,
++ rsa_add_verify_data,
++ rsa_verify,
++ &checksum_algos[1],
++ },
++ {
++ "sha256,rsassa-pss3072",
++ rsassa_pss_sign,
++ rsa_add_verify_data,
++ rsa_verify,
++ &checksum_algos[2],
++ },
++ {
++ "sha256,rsassa-pss4096",
++ rsassa_pss_sign,
++ rsa_add_verify_data,
++ rsa_verify,
++ &checksum_algos[3],
++ },
++ {
++ "sha384,rsassa-pss2048",
++ rsassa_pss_sign,
++ rsa_add_verify_data,
++ rsa_verify,
++ &checksum_algos[4],
++ },
++ {
++ "sha384,rsassa-pss3072",
++ rsassa_pss_sign,
++ rsa_add_verify_data,
++ rsa_verify,
++ &checksum_algos[5],
++ },
++ {
++ "sha384,rsassa-pss4096",
++ rsassa_pss_sign,
++ rsa_add_verify_data,
++ rsa_verify,
++ &checksum_algos[6],
++ },
++ {
++ "sha512,rsassa-pss2048",
++ rsassa_pss_sign,
++ rsa_add_verify_data,
++ rsa_verify,
++ &checksum_algos[7],
++ },
++ {
++ "sha512,rsassa-pss3072",
++ rsassa_pss_sign,
++ rsa_add_verify_data,
++ rsa_verify,
++ &checksum_algos[8],
++ },
++ {
++ "sha512,rsassa-pss4096",
++ rsassa_pss_sign,
++ rsa_add_verify_data,
++ rsa_verify,
++ &checksum_algos[9],
+ }
+
+ };
+diff --git a/include/u-boot/rsa.h b/include/u-boot/rsa.h
+index 3921250..cccc1aa 100644
+--- a/include/u-boot/rsa.h
++++ b/include/u-boot/rsa.h
+@@ -54,6 +54,10 @@ int rsa_sign(struct image_sign_info *info,
+ const struct image_region region[],
+ int region_count, uint8_t **sigp, uint *sig_len);
+
++int rsassa_pss_sign(struct image_sign_info *info,
++ const struct image_region region[],
++ int region_count, uint8_t **sigp, uint *sig_len);
++
+ /**
+ * add_verify_data() - Add verification information to FDT
+ *
+@@ -75,6 +79,13 @@ static inline int rsa_sign(struct image_sign_info *info,
+ return -ENXIO;
+ }
+
++static inline int rsassa_pss_sign(struct image_sign_info *info,
++ const struct image_region region[], int region_count,
++ uint8_t **sigp, uint *sig_len)
++{
++ return -ENXIO;
++}
++
+ static inline int rsa_add_verify_data(struct image_sign_info *info,
+ void *keydest)
+ {
+diff --git a/lib/rsa/rsa-sign.c b/lib/rsa/rsa-sign.c
+index c26f741..1f04938 100644
+--- a/lib/rsa/rsa-sign.c
++++ b/lib/rsa/rsa-sign.c
+@@ -162,9 +162,10 @@ static void rsa_remove(void)
+
+ static int rsa_sign_with_key(RSA *rsa, struct checksum_algo *checksum_algo,
+ const struct image_region region[], int region_count,
+- uint8_t **sigp, uint *sig_size)
++ uint8_t **sigp, uint *sig_size, int pad)
+ {
+ EVP_PKEY *key;
++ EVP_PKEY_CTX *keyctx;
+ EVP_MD_CTX *context;
+ int size, ret = 0;
+ uint8_t *sig;
+@@ -179,6 +180,12 @@ static int rsa_sign_with_key(RSA *rsa, struct checksum_algo *checksum_algo,
+ goto err_set;
+ }
+
++ keyctx = EVP_PKEY_CTX_new(key, NULL);
++ if (!keyctx) {
++ ret = rsa_err("EVP_PKEY_CTX object creation failed");
++ goto err_set;
++ }
++
+ size = EVP_PKEY_size(key);
+ sig = malloc(size);
+ if (!sig) {
+@@ -194,19 +201,31 @@ static int rsa_sign_with_key(RSA *rsa, struct checksum_algo *checksum_algo,
+ goto err_create;
+ }
+ EVP_MD_CTX_init(context);
+- if (!EVP_SignInit(context, checksum_algo->calculate_sign())) {
++ if (!EVP_DigestSignInit(context, &keyctx, checksum_algo->calculate_sign(), NULL, key)) {
+ ret = rsa_err("Signer setup failed");
+ goto err_sign;
+ }
+
++ if (pad == RSA_PKCS1_PSS_PADDING) {
++ if (!EVP_PKEY_CTX_set_rsa_padding(keyctx, RSA_PKCS1_PSS_PADDING)) {
++ ret = rsa_err("EVP key setup padding failed");
++ goto err_set;
++ }
++
++ if (!EVP_PKEY_CTX_set_rsa_pss_saltlen(keyctx, -1)) {
++ ret = rsa_err("EVP key setup saltlen failed");
++ goto err_set;
++ }
++ }
++
+ for (i = 0; i < region_count; i++) {
+- if (!EVP_SignUpdate(context, region[i].data, region[i].size)) {
++ if (!EVP_DigestSignUpdate(context, region[i].data, region[i].size)) {
+ ret = rsa_err("Signing data failed");
+ goto err_sign;
+ }
+ }
+
+- if (!EVP_SignFinal(context, sig, sig_size, key)) {
++ if (!EVP_DigestSignFinal(context, sig, (size_t *)sig_size)) {
+ ret = rsa_err("Could not obtain signature");
+ goto err_sign;
+ }
+@@ -245,7 +264,38 @@ int rsa_sign(struct image_sign_info *info,
+ if (ret)
+ goto err_priv;
+ ret = rsa_sign_with_key(rsa, info->algo->checksum, region,
+- region_count, sigp, sig_len);
++ region_count, sigp, sig_len, RSA_PKCS1_PADDING);
++ if (ret)
++ goto err_sign;
++
++ RSA_free(rsa);
++ rsa_remove();
++
++ return ret;
++
++err_sign:
++ RSA_free(rsa);
++err_priv:
++ rsa_remove();
++ return ret;
++}
++
++int rsassa_pss_sign(struct image_sign_info *info,
++ const struct image_region region[], int region_count,
++ uint8_t **sigp, uint *sig_len)
++{
++ RSA *rsa;
++ int ret;
++
++ ret = rsa_init();
++ if (ret)
++ return ret;
++
++ ret = rsa_get_priv_key(info->keydir, info->keyname, &rsa);
++ if (ret)
++ goto err_priv;
++ ret = rsa_sign_with_key(rsa, info->algo->checksum, region,
++ region_count, sigp, sig_len, RSA_PKCS1_PSS_PADDING);
+ if (ret)
+ goto err_sign;
+
+--
+1.9.1
+
diff --git a/meta/meta-mediatek-gpl/recipes-bsp/u-boot/u-boot-mkimage-2016.11/0003-rsa-extend-bits-of-n0-inverse.patch b/meta/meta-mediatek-gpl/recipes-bsp/u-boot/u-boot-mkimage-2016.11/0003-rsa-extend-bits-of-n0-inverse.patch
new file mode 100644
index 0000000..f046b3d
--- /dev/null
+++ b/meta/meta-mediatek-gpl/recipes-bsp/u-boot/u-boot-mkimage-2016.11/0003-rsa-extend-bits-of-n0-inverse.patch
@@ -0,0 +1,117 @@
+From 1cbf181a80d4e4fb9bfdcf41bd686afd3e7dea83 Mon Sep 17 00:00:00 2001
+From: HC Yen <hc.yen@mediatek.com>
+Date: Wed, 21 Dec 2016 11:12:24 +0800
+Subject: [PATCH 3/3] rsa: extend bits of n0-inverse
+
+Extend "rsa,n0-inverse" property to 64 bits.
+---
+ lib/rsa/rsa-sign.c | 39 +++++++++++++++++++++------------------
+ 1 file changed, 21 insertions(+), 18 deletions(-)
+
+diff --git a/lib/rsa/rsa-sign.c b/lib/rsa/rsa-sign.c
+index 1f04938..f7bdb54 100644
+--- a/lib/rsa/rsa-sign.c
++++ b/lib/rsa/rsa-sign.c
+@@ -361,25 +361,26 @@ cleanup:
+ /*
+ * rsa_get_params(): - Get the important parameters of an RSA public key
+ */
+-int rsa_get_params(RSA *key, uint64_t *exponent, uint32_t *n0_invp,
++int rsa_get_params(RSA *key, uint64_t *exponent, BIGNUM **n0_invp,
+ BIGNUM **modulusp, BIGNUM **r_squaredp)
+ {
+- BIGNUM *big1, *big2, *big32, *big2_32;
+- BIGNUM *n, *r, *r_squared, *tmp;
++ BIGNUM *big1, *big2, *big64, *big2_64;
++ BIGNUM *n0, *n, *r, *r_squared, *tmp;
+ BN_CTX *bn_ctx = BN_CTX_new();
+ int ret = 0;
+
+ /* Initialize BIGNUMs */
+ big1 = BN_new();
+ big2 = BN_new();
+- big32 = BN_new();
++ big64 = BN_new();
+ r = BN_new();
+ r_squared = BN_new();
+ tmp = BN_new();
+- big2_32 = BN_new();
++ big2_64 = BN_new();
++ n0 = BN_new();
+ n = BN_new();
+- if (!big1 || !big2 || !big32 || !r || !r_squared || !tmp || !big2_32 ||
+- !n) {
++ if (!big1 || !big2 || !big64 || !r || !r_squared || !tmp || !big2_64 ||
++ !n0 || !n) {
+ fprintf(stderr, "Out of memory (bignum)\n");
+ return -ENOMEM;
+ }
+@@ -388,18 +389,18 @@ int rsa_get_params(RSA *key, uint64_t *exponent, uint32_t *n0_invp,
+ ret = -1;
+
+ if (!BN_copy(n, key->n) || !BN_set_word(big1, 1L) ||
+- !BN_set_word(big2, 2L) || !BN_set_word(big32, 32L))
++ !BN_set_word(big2, 2L) || !BN_set_word(big64, 64L))
+ ret = -1;
+
+- /* big2_32 = 2^32 */
+- if (!BN_exp(big2_32, big2, big32, bn_ctx))
++ /* big2_64 = 2^64 */
++ if (!BN_exp(big2_64, big2, big64, bn_ctx))
+ ret = -1;
+
+- /* Calculate n0_inv = -1 / n[0] mod 2^32 */
+- if (!BN_mod_inverse(tmp, n, big2_32, bn_ctx) ||
+- !BN_sub(tmp, big2_32, tmp))
++ /* Calculate n0_inv = -1 / n[0] mod 2^64 */
++ if (!BN_mod_inverse(n0, n, big2_64, bn_ctx) ||
++ !BN_sub(n0, big2_64, n0))
+ ret = -1;
+- *n0_invp = BN_get_word(tmp);
++ *n0_invp = n0;
+
+ /* Calculate R = 2^(# of key bits) */
+ if (!BN_set_word(tmp, BN_num_bits(n)) ||
+@@ -417,10 +418,10 @@ int rsa_get_params(RSA *key, uint64_t *exponent, uint32_t *n0_invp,
+
+ BN_free(big1);
+ BN_free(big2);
+- BN_free(big32);
++ BN_free(big64);
+ BN_free(r);
+ BN_free(tmp);
+- BN_free(big2_32);
++ BN_free(big2_64);
+ if (ret) {
+ fprintf(stderr, "Bignum operations failed\n");
+ return -ENOMEM;
+@@ -490,7 +491,7 @@ int rsa_add_verify_data(struct image_sign_info *info, void *keydest)
+ {
+ BIGNUM *modulus, *r_squared;
+ uint64_t exponent;
+- uint32_t n0_inv;
++ BIGNUM *n0_inv;
+ int parent, node;
+ char name[100];
+ int ret;
+@@ -544,7 +545,8 @@ int rsa_add_verify_data(struct image_sign_info *info, void *keydest)
+ if (!ret)
+ ret = fdt_setprop_u32(keydest, node, "rsa,num-bits", bits);
+ if (!ret)
+- ret = fdt_setprop_u32(keydest, node, "rsa,n0-inverse", n0_inv);
++ ret = fdt_add_bignum(keydest, node, "rsa,n0-inverse", n0_inv,
++ 64);
+ if (!ret) {
+ ret = fdt_setprop_u64(keydest, node, "rsa,exponent", exponent);
+ }
+@@ -567,6 +569,7 @@ int rsa_add_verify_data(struct image_sign_info *info, void *keydest)
+ done:
+ BN_free(modulus);
+ BN_free(r_squared);
++ BN_free(n0_inv);
+ if (ret)
+ return ret == -FDT_ERR_NOSPACE ? -ENOSPC : -EIO;
+
+--
+1.9.1
+
diff --git a/meta/meta-mediatek-gpl/recipes-bsp/u-boot/u-boot-mkimage-2016.11/0004-security-boot-u-boot-hsm-support.patch b/meta/meta-mediatek-gpl/recipes-bsp/u-boot/u-boot-mkimage-2016.11/0004-security-boot-u-boot-hsm-support.patch
new file mode 100644
index 0000000..af3c0b7
--- /dev/null
+++ b/meta/meta-mediatek-gpl/recipes-bsp/u-boot/u-boot-mkimage-2016.11/0004-security-boot-u-boot-hsm-support.patch
@@ -0,0 +1,174 @@
+From 72b1424a983338f490c2eb00039f107970d7cda5 Mon Sep 17 00:00:00 2001
+From: Yang Xu <yang.xu@mediatek.com>
+Date: Tue, 27 Mar 2018 09:24:43 +0800
+Subject: [PATCH] security boot: u-boot hsm support
+
+add u-boot support hsm_sign_tool
+
+Test: OK
+
+Signed-off-by: Yang Xu <Yang.Xu@mediatek.com>
+CR-Id: AUTO00000778
+---
+ lib/rsa/rsa-sign.c | 132 +++++++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 132 insertions(+)
+
+diff --git a/lib/rsa/rsa-sign.c b/lib/rsa/rsa-sign.c
+index f7bdb54..cf832a1 100644
+--- a/lib/rsa/rsa-sign.c
++++ b/lib/rsa/rsa-sign.c
+@@ -249,12 +249,139 @@ err_set:
+ return ret;
+ }
+
++int rsa_sign_with_hsm(struct image_sign_info *info,
++ const struct image_region region[], int region_count,
++ uint8_t **sigp, uint *sig_len)
++{
++ /* prepare temp file*/
++ char tmpfile[] = "/tmp/hsm_content_XXXXXX";
++ char cmd[1024];
++ char sig[512];
++ int fd;
++ int i,ret,siglen;
++ char* hsm_sign_tool;
++ char* key_name;
++
++ memset(cmd,0,1024);
++ memset(sig,0,512);
++ if((fd = mkstemp(tmpfile))<0)
++ {
++ fprintf(stderr, "Failure to create tmp file\n");
++ return -1;
++ }
++
++ for (i = 0; i < region_count; i++) {
++ ret = write(fd,region[i].data, region[i].size);
++ if(ret != region[i].size)
++ {
++ fprintf(stderr, "Failure to write to tmp file\n");
++ return -1;
++ }
++ }
++
++ close(fd);
++
++ hsm_sign_tool = getenv("HSM_SIGN_TOOL");
++ key_name = getenv("HSM_KEY_NAME");
++ sprintf(cmd,"%s %s %s pkcs1 %s",hsm_sign_tool,key_name,info->algo->checksum->name,tmpfile);
++ ret = system(cmd);
++
++ if(ret != 0)
++ {
++ fprintf(stderr, "hsm sign failed\n");
++ return -1;
++ }
++
++ fd = open(tmpfile,O_RDONLY);
++ if(fd < 0)
++ {
++ fprintf(stderr, "open temp file %s fail\n",cmd);
++ return -1;
++ }
++
++ siglen = read(fd,sig,512);
++ close(fd);
++
++ *sigp = (uint8_t*)malloc(siglen);
++ memcpy(*sigp,sig,siglen);
++
++ *sig_len = siglen;
++
++ return 0;
++}
++
++int rsassa_pss_sign_with_hsm(struct image_sign_info *info,
++ const struct image_region region[], int region_count,
++ uint8_t **sigp, uint *sig_len)
++{
++ /* prepare temp file*/
++ char tmpfile[] = "/tmp/hsm_content_XXXXXX";
++ char cmd[1024];
++ char sig[512];
++ int fd;
++ int i,ret,siglen;
++ char* hsm_sign_tool;
++ char* key_name;
++
++ memset(cmd,0,1024);
++ memset(sig,0,512);
++ if((fd = mkstemp(tmpfile))<0)
++ {
++ fprintf(stderr, "Failure to create tmp file\n");
++ return -1;
++ }
++
++ for (i = 0; i < region_count; i++) {
++ ret = write(fd,region[i].data, region[i].size);
++ if(ret != region[i].size)
++ {
++ fprintf(stderr, "Failure to write to tmp file\n");
++ return -1;
++ }
++ }
++
++ close(fd);
++
++ hsm_sign_tool = getenv("HSM_SIGN_TOOL");
++ key_name = getenv("HSM_KEY_NAME");
++ sprintf(cmd,"%s %s %s pss %s",hsm_sign_tool,key_name,info->algo->checksum->name,tmpfile);
++ ret = system(cmd);
++
++ if(ret != 0)
++ {
++ fprintf(stderr, "hsm sign failed\n");
++ return -1;
++ }
++
++ fd = open(tmpfile,O_RDONLY);
++ if(fd < 0)
++ {
++ fprintf(stderr, "open temp file %s fail\n",cmd);
++ return -1;
++ }
++
++ siglen = read(fd,sig,512);
++ close(fd);
++
++ *sigp = (uint8_t*)malloc(siglen);
++ memcpy(*sigp,sig,siglen);
++
++ *sig_len = siglen;
++
++ return 0;
++}
++
+ int rsa_sign(struct image_sign_info *info,
+ const struct image_region region[], int region_count,
+ uint8_t **sigp, uint *sig_len)
+ {
+ RSA *rsa;
+ int ret;
++ char* hsm_support;
++
++ hsm_support = getenv("HSM_SUPPORT");
++ if( hsm_support && !strcmp(hsm_support,"yes"))
++ return rsa_sign_with_hsm(info,region,region_count,sigp,sig_len);
+
+ ret = rsa_init();
+ if (ret)
+@@ -286,6 +413,11 @@ int rsassa_pss_sign(struct image_sign_info *info,
+ {
+ RSA *rsa;
+ int ret;
++ char* hsm_support;
++
++ hsm_support = getenv("HSM_SUPPORT");
++ if( hsm_support && !strcmp(hsm_support,"yes"))
++ return rsassa_pss_sign_with_hsm(info,region,region_count,sigp,sig_len);
+
+ ret = rsa_init();
+ if (ret)
+--
+1.9.1
+
diff --git a/meta/meta-mediatek-gpl/recipes-bsp/u-boot/u-boot-mkimage-2016.11/default-gcc.patch b/meta/meta-mediatek-gpl/recipes-bsp/u-boot/u-boot-mkimage-2016.11/default-gcc.patch
new file mode 100644
index 0000000..04184df
--- /dev/null
+++ b/meta/meta-mediatek-gpl/recipes-bsp/u-boot/u-boot-mkimage-2016.11/default-gcc.patch
@@ -0,0 +1,39 @@
+OE needs to be able to change the default compiler. If we pass in HOSTCC
+through the make command, it overwrites not only this setting but also the
+setting in tools/Makefile wrapped in ifneq ($(CROSS_BUILD_TOOLS),) which
+breaks the build.
+
+We therefore use override to ensure the value of HOSTCC is overwritten when
+needed.
+
+RP: Updated the patch to the version being submitted to upstream u-boot
+
+Upstream-Status: Submitted [emailed to Masahiro Yamada for discussion]
+RP 2017/3/11
+
+Index: git/tools/Makefile
+===================================================================
+--- git.orig/tools/Makefile
++++ git/tools/Makefile
+@@ -262,7 +262,7 @@ $(LICENSE_H): $(obj)/bin2header $(srctre
+ subdir- += env
+
+ ifneq ($(CROSS_BUILD_TOOLS),)
+-HOSTCC = $(CC)
++override HOSTCC = $(CC)
+
+ quiet_cmd_crosstools_strip = STRIP $^
+ cmd_crosstools_strip = $(STRIP) $^; touch $@
+Index: git/tools/env/Makefile
+===================================================================
+--- git.orig/tools/env/Makefile
++++ git/tools/env/Makefile
+@@ -8,7 +8,7 @@
+ # fw_printenv is supposed to run on the target system, which means it should be
+ # built with cross tools. Although it may look weird, we only replace "HOSTCC"
+ # with "CC" here for the maximum code reuse of scripts/Makefile.host.
+-HOSTCC = $(CC)
++override HOSTCC = $(CC)
+
+ # Compile for a hosted environment on the target
+ HOST_EXTRACFLAGS = $(patsubst -I%,-idirafter%, $(filter -I%, $(UBOOTINCLUDE))) \
diff --git a/meta/meta-mediatek-gpl/recipes-bsp/u-boot/u-boot-mkimage-2018.07/0001-add-u-boot-support-hsm_sign_tool.patch b/meta/meta-mediatek-gpl/recipes-bsp/u-boot/u-boot-mkimage-2018.07/0001-add-u-boot-support-hsm_sign_tool.patch
new file mode 100644
index 0000000..7c29867
--- /dev/null
+++ b/meta/meta-mediatek-gpl/recipes-bsp/u-boot/u-boot-mkimage-2018.07/0001-add-u-boot-support-hsm_sign_tool.patch
@@ -0,0 +1,184 @@
+From c784097d39d813b1bd863cd5c59250f763984821 Mon Sep 17 00:00:00 2001
+From: Jimmy Huang <jimmy.huang@mediatek.com>
+Date: Fri, 5 Oct 2018 08:52:24 +0000
+Subject: [PATCH] add u-boot support hsm_sign_tool
+
+Test: OK
+
+Signed-off-by: Yang Xu <Yang.Xu@mediatek.com>
+CR-Id: AUTO00000778
+---
+ lib/rsa/rsa-sign.c | 136 +++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 136 insertions(+)
+
+diff --git a/lib/rsa/rsa-sign.c b/lib/rsa/rsa-sign.c
+index 9bf625bf2a..bf1edcb1b8 100644
+--- a/lib/rsa/rsa-sign.c
++++ b/lib/rsa/rsa-sign.c
+@@ -478,6 +478,68 @@ err_set:
+ return ret;
+ }
+
++int rsa_sign_with_hsm(struct image_sign_info *info,
++ const struct image_region region[], int region_count,
++ uint8_t **sigp, uint *sig_len)
++{
++ /* prepare temp file*/
++ char tmpfile[] = "/tmp/hsm_content_XXXXXX";
++ char cmd[1024];
++ char sig[512];
++ int fd;
++ int i, ret, siglen;
++ char* hsm_sign_tool;
++ char* key_name;
++
++ memset(cmd, 0, 1024);
++ memset(sig, 0, 512);
++ if ((fd = mkstemp(tmpfile)) < 0)
++ {
++ fprintf(stderr, "Failure to create tmp file\n");
++ return -1;
++ }
++
++ for (i = 0; i < region_count; i++) {
++ ret = write(fd,region[i].data, region[i].size);
++ if (ret != region[i].size)
++ {
++ fprintf(stderr, "Failure to write to tmp file\n");
++ return -1;
++ }
++ }
++
++ close(fd);
++
++ hsm_sign_tool = getenv("HSM_SIGN_TOOL");
++ key_name = getenv("HSM_KEY_NAME");
++ sprintf(cmd, "%s %s %s pkcs1 %s",
++ hsm_sign_tool, key_name, info->checksum->name, tmpfile);
++ ret = system(cmd);
++
++ if (ret != 0)
++ {
++ fprintf(stderr, "hsm sign failed\n");
++ return -1;
++ }
++
++ fd = open(tmpfile, O_RDONLY);
++ if (fd < 0)
++ {
++ fprintf(stderr, "open temp file %s fail\n",cmd);
++ return -1;
++ }
++
++ siglen = read(fd, sig, 512);
++ close(fd);
++
++ *sigp = (uint8_t*)malloc(siglen);
++ memcpy(*sigp, sig, siglen);
++
++ *sig_len = siglen;
++
++ return 0;
++}
++
+ int rsa_sign(struct image_sign_info *info,
+ const struct image_region region[], int region_count,
+ uint8_t **sigp, uint *sig_len)
+@@ -485,6 +547,12 @@ int rsa_sign(struct image_sign_info *info,
+ RSA *rsa;
+ ENGINE *e = NULL;
+ int ret;
++ char* hsm_support;
++
++ hsm_support = getenv("HSM_SUPPORT");
++ if( hsm_support && !strcmp(hsm_support,"yes"))
++ return rsa_sign_with_hsm(info, region, region_count,
++ sigp, sig_len);
+
+ ret = rsa_init();
+ if (ret)
+@@ -521,6 +589,68 @@ err_engine:
+ return ret;
+ }
+
++int rsassa_pss_sign_with_hsm(struct image_sign_info *info,
++ const struct image_region region[], int region_count,
++ uint8_t **sigp, uint *sig_len)
++{
++ /* prepare temp file*/
++ char tmpfile[] = "/tmp/hsm_content_XXXXXX";
++ char cmd[1024];
++ char sig[512];
++ int fd;
++ int i, ret, siglen;
++ char* hsm_sign_tool;
++ char* key_name;
++
++ memset(cmd, 0, 1024);
++ memset(sig, 0, 512);
++ if ((fd = mkstemp(tmpfile)) < 0)
++ {
++ fprintf(stderr, "Failure to create tmp file\n");
++ return -1;
++ }
++
++ for (i = 0; i < region_count; i++) {
++ ret = write(fd, region[i].data, region[i].size);
++ if (ret != region[i].size)
++ {
++ fprintf(stderr, "Failure to write to tmp file\n");
++ return -1;
++ }
++ }
++
++ close(fd);
++
++ hsm_sign_tool = getenv("HSM_SIGN_TOOL");
++ key_name = getenv("HSM_KEY_NAME");
++ sprintf(cmd, "%s %s %s pss %s",
++ hsm_sign_tool, key_name, info->checksum->name, tmpfile);
++ ret = system(cmd);
++
++ if (ret != 0)
++ {
++ fprintf(stderr, "hsm sign failed\n");
++ return -1;
++ }
++
++ fd = open(tmpfile, O_RDONLY);
++ if (fd < 0)
++ {
++ fprintf(stderr, "open temp file %s fail\n", cmd);
++ return -1;
++ }
++
++ siglen = read(fd, sig, 512);
++ close(fd);
++
++ *sigp = (uint8_t*)malloc(siglen);
++ memcpy(*sigp, sig, siglen);
++
++ *sig_len = siglen;
++
++ return 0;
++}
++
+ int rsassa_pss_sign(struct image_sign_info *info,
+ const struct image_region region[], int region_count,
+ uint8_t **sigp, uint *sig_len)
+@@ -528,6 +658,12 @@ int rsassa_pss_sign(struct image_sign_info *info,
+ RSA *rsa;
+ ENGINE *e = NULL;
+ int ret;
++ char* hsm_support;
++
++ hsm_support = getenv("HSM_SUPPORT");
++ if( hsm_support && !strcmp(hsm_support,"yes"))
++ return rsassa_pss_sign_with_hsm(info, region, region_count,
++ sigp, sig_len);
+
+ ret = rsa_init();
+ if (ret)
+--
+2.17.1
+
diff --git a/meta/meta-mediatek-gpl/recipes-bsp/u-boot/u-boot-mkimage-2018.07/0001-libfdt-fix-fdt_find_regions-incorrectly-adding-paren.patch b/meta/meta-mediatek-gpl/recipes-bsp/u-boot/u-boot-mkimage-2018.07/0001-libfdt-fix-fdt_find_regions-incorrectly-adding-paren.patch
new file mode 100644
index 0000000..9781e29
--- /dev/null
+++ b/meta/meta-mediatek-gpl/recipes-bsp/u-boot/u-boot-mkimage-2018.07/0001-libfdt-fix-fdt_find_regions-incorrectly-adding-paren.patch
@@ -0,0 +1,29 @@
+From 5e3f74c4d934bbcdc55ed6bce738d5931c92691d Mon Sep 17 00:00:00 2001
+From: Jimmy Huang <jimmy.huang@mediatek.com>
+Date: Wed, 26 Sep 2018 07:07:13 +0000
+Subject: [PATCH] libfdt: fix fdt_find_regions incorrectly adding parent's end
+ node
+
+This patch fix fdt_find_regions incorrectly adding parent's end node to
+regions when it shouldn't. For example, when finding regions for
+/signature/key-dev, the end node of its parent, /signature, will also
+be included which is incorrect behavior.
+---
+ lib/libfdt/fdt_region.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/lib/libfdt/fdt_region.c b/lib/libfdt/fdt_region.c
+index d3b9a60e99..9d2ca23be1 100644
+--- a/lib/libfdt/fdt_region.c
++++ b/lib/libfdt/fdt_region.c
+@@ -97,6 +97,7 @@ int fdt_find_regions(const void *fdt, char * const inc[], int inc_count,
+
+ case FDT_END_NODE:
+ include = want;
++ stop_at = offset;
+ want = stack[depth--];
+ while (end > path && *--end != '/')
+ ;
+--
+2.17.1
+
diff --git a/meta/meta-mediatek-gpl/recipes-bsp/u-boot/u-boot-mkimage-2018.07/0001-rsa-add-sha-256-384-512-rsa-2048-3072-4096-algorithm.patch b/meta/meta-mediatek-gpl/recipes-bsp/u-boot/u-boot-mkimage-2018.07/0001-rsa-add-sha-256-384-512-rsa-2048-3072-4096-algorithm.patch
new file mode 100644
index 0000000..717883f
--- /dev/null
+++ b/meta/meta-mediatek-gpl/recipes-bsp/u-boot/u-boot-mkimage-2018.07/0001-rsa-add-sha-256-384-512-rsa-2048-3072-4096-algorithm.patch
@@ -0,0 +1,1009 @@
+From 5d11fc28174badacde0acaabd36535e26d26916f Mon Sep 17 00:00:00 2001
+From: Jimmy Huang <jimmy.huang@mediatek.com>
+Date: Mon, 1 Oct 2018 06:13:25 +0000
+Subject: [PATCH 1/3] rsa: add sha{256,384,512},rsa{2048,3072,4096} algorithms
+
+Add support for "sha256,rsa3072", "sha384,rsa2048", "sha384,rsa3072",
+"sha384,rsa4096", "sha512,rsa2048", "sha512,rsa3072", and
+"sha512,rsa4096" signatures in u-boot.
+---
+ Kconfig | 23 +-
+ common/hash.c | 78 +++++-
+ common/image-fit.c | 9 +
+ common/image-sig.c | 27 ++
+ include/hash.h | 2 +-
+ include/image.h | 18 ++
+ include/u-boot/rsa-checksum.h | 1 +
+ include/u-boot/rsa.h | 1 +
+ include/u-boot/sha4.h | 166 ++++++++++++
+ lib/Kconfig | 16 ++
+ lib/Makefile | 2 +
+ lib/sha4.c | 459 ++++++++++++++++++++++++++++++++++
+ tools/Makefile | 1 +
+ 13 files changed, 798 insertions(+), 5 deletions(-)
+ create mode 100644 include/u-boot/sha4.h
+ create mode 100644 lib/sha4.c
+
+diff --git a/Kconfig b/Kconfig
+index 5a82c95dd8..513f23cb4c 100644
+--- a/Kconfig
++++ b/Kconfig
+@@ -245,9 +245,26 @@ config FIT_ENABLE_SHA256_SUPPORT
+ the image contents have not been corrupted. SHA256 is recommended
+ for use in secure applications since (as at 2016) there is no known
+ feasible attack that could produce a 'collision' with differing
+- input data. Use this for the highest security. Note that only the
+- SHA256 variant is supported: SHA512 and others are not currently
+- supported in U-Boot.
++ input data.
++
++config FIT_ENABLE_SHA384_SUPPORT
++ bool "Support SHA384 checksum of FIT image contents"
++ select SHA384
++ default n
++ help
++ Enable this to support SHA384 checksum of FIT image contents. A
++ SHA384 checksum is a 384-bit (48-byte) hash value used to check that
++ the image contents have not been corrupted.
++
++config FIT_ENABLE_SHA512_SUPPORT
++ bool "Support SHA512 checksum of FIT image contents"
++ select SHA512
++ default n
++ help
++ Enable this to support SHA512 checksum of FIT image contents. A
++ SHA512 checksum is a 512-bit (64-byte) hash value used to check that
++ the image contents have not been corrupted. Use this for the highest
++ security.
+
+ config FIT_SIGNATURE
+ bool "Enable signature verification of FIT uImages"
+diff --git a/common/hash.c b/common/hash.c
+index ef146513a0..97d9bbc38a 100644
+--- a/common/hash.c
++++ b/common/hash.c
+@@ -27,6 +27,7 @@
+ #include <u-boot/crc.h>
+ #include <u-boot/sha1.h>
+ #include <u-boot/sha256.h>
++#include <u-boot/sha4.h>
+ #include <u-boot/md5.h>
+
+ #if defined(CONFIG_SHA1) && !defined(CONFIG_SHA_PROG_HW_ACCEL)
+@@ -83,6 +84,58 @@ static int hash_finish_sha256(struct hash_algo *algo, void *ctx, void
+ free(ctx);
+ return 0;
+ }
++
++static int hash_init_sha384(struct hash_algo *algo, void **ctxp)
++{
++ sha4_context *ctx = malloc(sizeof(sha4_context));
++ sha4_starts(ctx, 1);
++ *ctxp = ctx;
++ return 0;
++}
++
++static int hash_update_sha384(struct hash_algo *algo, void *ctx,
++ const void *buf, unsigned int size, int is_last)
++{
++ sha4_update((sha4_context *)ctx, buf, size);
++ return 0;
++}
++
++static int hash_finish_sha384(struct hash_algo *algo, void *ctx, void
++ *dest_buf, int size)
++{
++ if (size < algo->digest_size)
++ return -1;
++
++ sha4_finish((sha4_context *)ctx, dest_buf);
++ free(ctx);
++ return 0;
++}
++
++static int hash_init_sha512(struct hash_algo *algo, void **ctxp)
++{
++ sha4_context *ctx = malloc(sizeof(sha4_context));
++ sha4_starts(ctx, 0);
++ *ctxp = ctx;
++ return 0;
++}
++
++static int hash_update_sha512(struct hash_algo *algo, void *ctx,
++ const void *buf, unsigned int size, int is_last)
++{
++ sha4_update((sha4_context *)ctx, buf, size);
++ return 0;
++}
++
++static int hash_finish_sha512(struct hash_algo *algo, void *ctx, void
++ *dest_buf, int size)
++{
++ if (size < algo->digest_size)
++ return -1;
++
++ sha4_finish((sha4_context *)ctx, dest_buf);
++ free(ctx);
++ return 0;
++}
+ #endif
+
+ static int hash_init_crc32(struct hash_algo *algo, void **ctxp)
+@@ -158,6 +211,28 @@ static struct hash_algo hash_algo[] = {
+ .hash_finish = hash_finish_sha256,
+ #endif
+ },
++#endif
++#ifdef CONFIG_SHA384
++ {
++ .name = "sha384",
++ .digest_size = SHA384_SUM_LEN,
++ .chunk_size = CHUNKSZ_SHA384,
++ .hash_func_ws = sha384_csum_wd,
++ .hash_init = hash_init_sha384,
++ .hash_update = hash_update_sha384,
++ .hash_finish = hash_finish_sha384,
++ },
++#endif
++#ifdef CONFIG_SHA512
++ {
++ .name = "sha512",
++ .digest_size = SHA512_SUM_LEN,
++ .chunk_size = CHUNKSZ_SHA512,
++ .hash_func_ws = sha512_csum_wd,
++ .hash_init = hash_init_sha512,
++ .hash_update = hash_update_sha512,
++ .hash_finish = hash_finish_sha512,
++ },
+ #endif
+ {
+ .name = "crc32",
+@@ -171,7 +246,8 @@ static struct hash_algo hash_algo[] = {
+ };
+
+ /* Try to minimize code size for boards that don't want much hashing */
+-#if defined(CONFIG_SHA256) || defined(CONFIG_CMD_SHA1SUM) || \
++#if defined(CONFIG_SHA256) || defined(CONFIG_SHA384) || \
++ defined(CONFIG_SHA512) || defined(CONFIG_CMD_SHA1SUM) || \
+ defined(CONFIG_CRC32_VERIFY) || defined(CONFIG_CMD_HASH)
+ #define multi_hash() 1
+ #else
+diff --git a/common/image-fit.c b/common/image-fit.c
+index 728187ac88..dadaf79678 100644
+--- a/common/image-fit.c
++++ b/common/image-fit.c
+@@ -28,6 +28,7 @@ DECLARE_GLOBAL_DATA_PTR;
+ #include <u-boot/md5.h>
+ #include <u-boot/sha1.h>
+ #include <u-boot/sha256.h>
++#include <u-boot/sha4.h>
+
+ /*****************************************************************************/
+ /* New uImage format routines */
+@@ -1143,6 +1144,14 @@ int calculate_hash(const void *data, int data_len, const char *algo,
+ sha256_csum_wd((unsigned char *)data, data_len,
+ (unsigned char *)value, CHUNKSZ_SHA256);
+ *value_len = SHA256_SUM_LEN;
++ } else if (IMAGE_ENABLE_SHA384 && strcmp(algo, "sha384") == 0) {
++ sha384_csum_wd((unsigned char *)data, data_len,
++ (unsigned char *)value, CHUNKSZ_SHA384);
++ *value_len = SHA384_SUM_LEN;
++ } else if (IMAGE_ENABLE_SHA512 && strcmp(algo, "sha512") == 0) {
++ sha512_csum_wd((unsigned char *)data, data_len,
++ (unsigned char *)value, CHUNKSZ_SHA512);
++ *value_len = SHA512_SUM_LEN;
+ } else if (IMAGE_ENABLE_MD5 && strcmp(algo, "md5") == 0) {
+ md5_wd((unsigned char *)data, data_len, value, CHUNKSZ_MD5);
+ *value_len = 16;
+diff --git a/common/image-sig.c b/common/image-sig.c
+index f65d883994..aab3a60de2 100644
+--- a/common/image-sig.c
++++ b/common/image-sig.c
+@@ -47,6 +47,26 @@ struct checksum_algo checksum_algos[] = {
+ .der_prefix = sha256_der_prefix,
+ #if IMAGE_ENABLE_SIGN
+ .calculate_sign = EVP_sha256,
++#endif
++ .calculate = hash_calculate,
++ },
++ {
++ .name = "sha384",
++ .checksum_len = SHA384_SUM_LEN,
++ .der_len = SHA384_DER_LEN,
++ .der_prefix = sha384_der_prefix,
++#if IMAGE_ENABLE_SIGN
++ .calculate_sign = EVP_sha384,
++#endif
++ .calculate = hash_calculate,
++ },
++ {
++ .name = "sha512",
++ .checksum_len = SHA512_SUM_LEN,
++ .der_len = SHA512_DER_LEN,
++ .der_prefix = sha512_der_prefix,
++#if IMAGE_ENABLE_SIGN
++ .calculate_sign = EVP_sha512,
+ #endif
+ .calculate = hash_calculate,
+ }
+@@ -61,6 +81,13 @@ struct crypto_algo crypto_algos[] = {
+ .add_verify_data = rsa_add_verify_data,
+ .verify = rsa_verify,
+ },
++ {
++ .name = "rsa3072",
++ .key_len = RSA3072_BYTES,
++ .sign = rsa_sign,
++ .add_verify_data = rsa_add_verify_data,
++ .verify = rsa_verify,
++ },
+ {
+ .name = "rsa4096",
+ .key_len = RSA4096_BYTES,
+diff --git a/include/hash.h b/include/hash.h
+index f4019a9791..aaddf41203 100644
+--- a/include/hash.h
++++ b/include/hash.h
+@@ -10,7 +10,7 @@
+ * Maximum digest size for all algorithms we support. Having this value
+ * avoids a malloc() or C99 local declaration in common/cmd_hash.c.
+ */
+-#define HASH_MAX_DIGEST_SIZE 32
++#define HASH_MAX_DIGEST_SIZE 64
+
+ enum {
+ HASH_FLAG_VERIFY = 1 << 0, /* Enable verify mode */
+diff --git a/include/image.h b/include/image.h
+index 420b8ff576..475af42a7a 100644
+--- a/include/image.h
++++ b/include/image.h
+@@ -31,8 +31,12 @@ struct fdt_region;
+ #define IMAGE_ENABLE_OF_LIBFDT 1
+ #define CONFIG_FIT_VERBOSE 1 /* enable fit_format_{error,warning}() */
+ #define CONFIG_FIT_ENABLE_SHA256_SUPPORT
++#define CONFIG_FIT_ENABLE_SHA384_SUPPORT
++#define CONFIG_FIT_ENABLE_SHA512_SUPPORT
+ #define CONFIG_SHA1
+ #define CONFIG_SHA256
++#define CONFIG_SHA384
++#define CONFIG_SHA512
+
+ #define IMAGE_ENABLE_IGNORE 0
+ #define IMAGE_INDENT_STRING ""
+@@ -92,6 +96,20 @@ struct fdt_region;
+ #define IMAGE_ENABLE_SHA256 0
+ #endif
+
++#if defined(CONFIG_FIT_ENABLE_SHA384_SUPPORT) || \
++ defined(CONFIG_SPL_SHA384_SUPPORT)
++#define IMAGE_ENABLE_SHA384 1
++#else
++#define IMAGE_ENABLE_SHA384 0
++#endif
++
++#if defined(CONFIG_FIT_ENABLE_SHA512_SUPPORT) || \
++ defined(CONFIG_SPL_SHA512_SUPPORT)
++#define IMAGE_ENABLE_SHA512 1
++#else
++#define IMAGE_ENABLE_SHA512 0
++#endif
++
+ #endif /* IMAGE_ENABLE_FIT */
+
+ #ifdef CONFIG_SYS_BOOT_GET_CMDLINE
+diff --git a/include/u-boot/rsa-checksum.h b/include/u-boot/rsa-checksum.h
+index 02b814d34e..d5b168e4ab 100644
+--- a/include/u-boot/rsa-checksum.h
++++ b/include/u-boot/rsa-checksum.h
+@@ -10,6 +10,7 @@
+ #include <image.h>
+ #include <u-boot/sha1.h>
+ #include <u-boot/sha256.h>
++#include <u-boot/sha4.h>
+
+ /**
+ * hash_calculate() - Calculate hash over the data
+diff --git a/include/u-boot/rsa.h b/include/u-boot/rsa.h
+index 68bcb14c74..69aff97fdf 100644
+--- a/include/u-boot/rsa.h
++++ b/include/u-boot/rsa.h
+@@ -107,6 +107,7 @@ static inline int rsa_verify(struct image_sign_info *info,
+ #endif
+
+ #define RSA2048_BYTES (2048 / 8)
++#define RSA3072_BYTES (3072 / 8)
+ #define RSA4096_BYTES (4096 / 8)
+
+ /* This is the minimum/maximum key size we support, in bits */
+diff --git a/include/u-boot/sha4.h b/include/u-boot/sha4.h
+new file mode 100644
+index 0000000000..bed16dbcc8
+--- /dev/null
++++ b/include/u-boot/sha4.h
+@@ -0,0 +1,166 @@
++/**
++ * \file sha4.h
++ *
++ * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine
++ *
++ * Copyright (C) 2009 Paul Bakker <polarssl_maintainer at polarssl dot org>
++ *
++ * All rights reserved.
++ *
++ * 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 names of PolarSSL or XySSL 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.
++ */
++#ifndef _SHA4_H
++#define _SHA4_H
++
++#define SHA384_SUM_LEN 48
++#define SHA512_SUM_LEN 64
++
++#define SHA384_DER_LEN 19
++#define SHA512_DER_LEN 19
++
++extern const uint8_t sha384_der_prefix[];
++extern const uint8_t sha512_der_prefix[];
++
++/* Reset watchdog each time we process this many bytes */
++#define CHUNKSZ_SHA384 (64 * 1024)
++#define CHUNKSZ_SHA512 (64 * 1024)
++
++#define UL64(x) x##ULL
++#define int64 long long
++
++/**
++ * \brief SHA-512 context structure
++ */
++typedef struct {
++ unsigned int64 total[2]; /*!< number of bytes processed */
++ unsigned int64 state[8]; /*!< intermediate digest state */
++ unsigned char buffer[128]; /*!< data block being processed */
++
++ unsigned char ipad[128]; /*!< HMAC: inner padding */
++ unsigned char opad[128]; /*!< HMAC: outer padding */
++ int is384; /*!< 0 => SHA-512, else SHA-384 */
++} sha4_context;
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++ /**
++ * \brief SHA-512 context setup
++ *
++ * \param ctx context to be initialized
++ * \param is384 0 = use SHA512, 1 = use SHA384
++ */
++ void sha4_starts(sha4_context * ctx, int is384);
++
++ /**
++ * \brief SHA-512 process buffer
++ *
++ * \param ctx SHA-512 context
++ * \param input buffer holding the data
++ * \param ilen length of the input data
++ */
++ void sha4_update(sha4_context * ctx, const unsigned char *input,
++ int ilen);
++
++ /**
++ * \brief SHA-512 final digest
++ *
++ * \param ctx SHA-512 context
++ * \param output SHA-384/512 checksum result
++ */
++ void sha4_finish(sha4_context * ctx, unsigned char output[64]);
++
++ /**
++ * \brief Output = SHA-512( input buffer )
++ *
++ * \param input buffer holding the data
++ * \param ilen length of the input data
++ * \param output SHA-384/512 checksum result
++ * \param is384 0 = use SHA512, 1 = use SHA384
++ */
++ void sha4(unsigned char *input, int ilen,
++ unsigned char output[64], int is384);
++
++void sha384_csum_wd(const unsigned char *input, unsigned int ilen,
++ unsigned char *output, unsigned int chunk_sz);
++void sha512_csum_wd(const unsigned char *input, unsigned int ilen,
++ unsigned char *output, unsigned int chunk_sz);
++
++ /**
++ * \brief SHA-512 HMAC context setup
++ *
++ * \param ctx HMAC context to be initialized
++ * \param is384 0 = use SHA512, 1 = use SHA384
++ * \param key HMAC secret key
++ * \param keylen length of the HMAC key
++ */
++ void sha4_hmac_starts(sha4_context * ctx, unsigned char *key,
++ int keylen, int is384);
++
++ /**
++ * \brief SHA-512 HMAC process buffer
++ *
++ * \param ctx HMAC context
++ * \param input buffer holding the data
++ * \param ilen length of the input data
++ */
++ void sha4_hmac_update(sha4_context * ctx, unsigned char *input,
++ int ilen);
++
++ /**
++ * \brief SHA-512 HMAC final digest
++ *
++ * \param ctx HMAC context
++ * \param output SHA-384/512 HMAC checksum result
++ */
++ void sha4_hmac_finish(sha4_context * ctx, unsigned char output[64]);
++
++ /**
++ * \brief Output = HMAC-SHA-512( hmac key, input buffer )
++ *
++ * \param key HMAC secret key
++ * \param keylen length of the HMAC key
++ * \param input buffer holding the data
++ * \param ilen length of the input data
++ * \param output HMAC-SHA-384/512 result
++ * \param is384 0 = use SHA512, 1 = use SHA384
++ */
++ void sha4_hmac(unsigned char *key, int keylen,
++ unsigned char *input, int ilen,
++ unsigned char output[64], int is384);
++
++ /**
++ * \brief Checkup routine
++ *
++ * \return 0 if successful, or 1 if the test failed
++ */
++ int sha4_self_test(int verbose);
++
++#ifdef __cplusplus
++}
++#endif
++#endif /* sha4.h */
+diff --git a/lib/Kconfig b/lib/Kconfig
+index a77bf1c688..c3bed74860 100644
+--- a/lib/Kconfig
++++ b/lib/Kconfig
+@@ -219,6 +219,22 @@ config SHA256
+ The SHA256 algorithm produces a 256-bit (32-byte) hash value
+ (digest).
+
++config SHA384
++ bool "Enable SHA384 support"
++ help
++ This option enables support of hashing using SHA384 algorithm.
++ The hash is calculated in software.
++ The SHA384 algorithm produces a 384-bit (48-byte) hash value
++ (digest).
++
++config SHA512
++ bool "Enable SHA512 support"
++ help
++ This option enables support of hashing using SHA512 algorithm.
++ The hash is calculated in software.
++ The SHA512 algorithm produces a 512-bit (64-byte) hash value
++ (digest).
++
+ config SHA_HW_ACCEL
+ bool "Enable hashing using hardware"
+ help
+diff --git a/lib/Makefile b/lib/Makefile
+index 5f583aed37..b3560729a3 100644
+--- a/lib/Makefile
++++ b/lib/Makefile
+@@ -51,6 +51,8 @@ endif
+ obj-$(CONFIG_RSA) += rsa/
+ obj-$(CONFIG_SHA1) += sha1.o
+ obj-$(CONFIG_SHA256) += sha256.o
++obj-$(CONFIG_SHA384) += sha384.o
++obj-$(CONFIG_SHA512) += sha512.o
+
+ obj-$(CONFIG_$(SPL_)ZLIB) += zlib/
+ obj-$(CONFIG_$(SPL_)GZIP) += gunzip.o
+diff --git a/lib/sha4.c b/lib/sha4.c
+new file mode 100644
+index 0000000000..60ad3ca943
+--- /dev/null
++++ b/lib/sha4.c
+@@ -0,0 +1,459 @@
++/*
++ * FIPS-180-2 compliant SHA-384/512 implementation
++ *
++ * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine
++ *
++ * Copyright (C) 2009 Paul Bakker <polarssl_maintainer at polarssl dot org>
++ *
++ * All rights reserved.
++ *
++ * 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 names of PolarSSL or XySSL 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.
++ */
++/*
++ * The SHA-512 Secure Hash Standard was published by NIST in 2002.
++ *
++ * http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf
++ */
++
++#ifndef USE_HOSTCC
++#include <common.h>
++#include <linux/string.h>
++#else
++#include <string.h>
++#endif /* USE_HOSTCC */
++#include <watchdog.h>
++#include <u-boot/sha4.h>
++
++const uint8_t sha384_der_prefix[SHA384_DER_LEN] = {
++ 0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86,
++ 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05,
++ 0x00, 0x04, 0x30
++};
++
++const uint8_t sha512_der_prefix[SHA512_DER_LEN] = {
++ 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86,
++ 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05,
++ 0x00, 0x04, 0x40
++};
++
++/*
++ * 64-bit integer manipulation macros (big endian)
++ */
++#ifndef GET_UINT64_BE
++#define GET_UINT64_BE(n,b,i) \
++ { \
++ (n) = ( (unsigned int64) (b)[(i) ] << 56 ) \
++ | ( (unsigned int64) (b)[(i) + 1] << 48 ) \
++ | ( (unsigned int64) (b)[(i) + 2] << 40 ) \
++ | ( (unsigned int64) (b)[(i) + 3] << 32 ) \
++ | ( (unsigned int64) (b)[(i) + 4] << 24 ) \
++ | ( (unsigned int64) (b)[(i) + 5] << 16 ) \
++ | ( (unsigned int64) (b)[(i) + 6] << 8 ) \
++ | ( (unsigned int64) (b)[(i) + 7] ); \
++ }
++#endif
++
++#ifndef PUT_UINT64_BE
++#define PUT_UINT64_BE(n,b,i) \
++ { \
++ (b)[(i) ] = (unsigned char) ( (n) >> 56 ); \
++ (b)[(i) + 1] = (unsigned char) ( (n) >> 48 ); \
++ (b)[(i) + 2] = (unsigned char) ( (n) >> 40 ); \
++ (b)[(i) + 3] = (unsigned char) ( (n) >> 32 ); \
++ (b)[(i) + 4] = (unsigned char) ( (n) >> 24 ); \
++ (b)[(i) + 5] = (unsigned char) ( (n) >> 16 ); \
++ (b)[(i) + 6] = (unsigned char) ( (n) >> 8 ); \
++ (b)[(i) + 7] = (unsigned char) ( (n) ); \
++ }
++#endif
++
++/*
++ * Round constants
++ */
++static const unsigned int64 K[80] = {
++ UL64(0x428A2F98D728AE22), UL64(0x7137449123EF65CD),
++ UL64(0xB5C0FBCFEC4D3B2F), UL64(0xE9B5DBA58189DBBC),
++ UL64(0x3956C25BF348B538), UL64(0x59F111F1B605D019),
++ UL64(0x923F82A4AF194F9B), UL64(0xAB1C5ED5DA6D8118),
++ UL64(0xD807AA98A3030242), UL64(0x12835B0145706FBE),
++ UL64(0x243185BE4EE4B28C), UL64(0x550C7DC3D5FFB4E2),
++ UL64(0x72BE5D74F27B896F), UL64(0x80DEB1FE3B1696B1),
++ UL64(0x9BDC06A725C71235), UL64(0xC19BF174CF692694),
++ UL64(0xE49B69C19EF14AD2), UL64(0xEFBE4786384F25E3),
++ UL64(0x0FC19DC68B8CD5B5), UL64(0x240CA1CC77AC9C65),
++ UL64(0x2DE92C6F592B0275), UL64(0x4A7484AA6EA6E483),
++ UL64(0x5CB0A9DCBD41FBD4), UL64(0x76F988DA831153B5),
++ UL64(0x983E5152EE66DFAB), UL64(0xA831C66D2DB43210),
++ UL64(0xB00327C898FB213F), UL64(0xBF597FC7BEEF0EE4),
++ UL64(0xC6E00BF33DA88FC2), UL64(0xD5A79147930AA725),
++ UL64(0x06CA6351E003826F), UL64(0x142929670A0E6E70),
++ UL64(0x27B70A8546D22FFC), UL64(0x2E1B21385C26C926),
++ UL64(0x4D2C6DFC5AC42AED), UL64(0x53380D139D95B3DF),
++ UL64(0x650A73548BAF63DE), UL64(0x766A0ABB3C77B2A8),
++ UL64(0x81C2C92E47EDAEE6), UL64(0x92722C851482353B),
++ UL64(0xA2BFE8A14CF10364), UL64(0xA81A664BBC423001),
++ UL64(0xC24B8B70D0F89791), UL64(0xC76C51A30654BE30),
++ UL64(0xD192E819D6EF5218), UL64(0xD69906245565A910),
++ UL64(0xF40E35855771202A), UL64(0x106AA07032BBD1B8),
++ UL64(0x19A4C116B8D2D0C8), UL64(0x1E376C085141AB53),
++ UL64(0x2748774CDF8EEB99), UL64(0x34B0BCB5E19B48A8),
++ UL64(0x391C0CB3C5C95A63), UL64(0x4ED8AA4AE3418ACB),
++ UL64(0x5B9CCA4F7763E373), UL64(0x682E6FF3D6B2B8A3),
++ UL64(0x748F82EE5DEFB2FC), UL64(0x78A5636F43172F60),
++ UL64(0x84C87814A1F0AB72), UL64(0x8CC702081A6439EC),
++ UL64(0x90BEFFFA23631E28), UL64(0xA4506CEBDE82BDE9),
++ UL64(0xBEF9A3F7B2C67915), UL64(0xC67178F2E372532B),
++ UL64(0xCA273ECEEA26619C), UL64(0xD186B8C721C0C207),
++ UL64(0xEADA7DD6CDE0EB1E), UL64(0xF57D4F7FEE6ED178),
++ UL64(0x06F067AA72176FBA), UL64(0x0A637DC5A2C898A6),
++ UL64(0x113F9804BEF90DAE), UL64(0x1B710B35131C471B),
++ UL64(0x28DB77F523047D84), UL64(0x32CAAB7B40C72493),
++ UL64(0x3C9EBE0A15C9BEBC), UL64(0x431D67C49C100D4C),
++ UL64(0x4CC5D4BECB3E42B6), UL64(0x597F299CFC657E2A),
++ UL64(0x5FCB6FAB3AD6FAEC), UL64(0x6C44198C4A475817)
++};
++
++/*
++ * SHA-512 context setup
++ */
++void sha4_starts(sha4_context * ctx, int is384)
++{
++ ctx->total[0] = 0;
++ ctx->total[1] = 0;
++
++ if (is384 == 0) {
++ /* SHA-512 */
++ ctx->state[0] = UL64(0x6A09E667F3BCC908);
++ ctx->state[1] = UL64(0xBB67AE8584CAA73B);
++ ctx->state[2] = UL64(0x3C6EF372FE94F82B);
++ ctx->state[3] = UL64(0xA54FF53A5F1D36F1);
++ ctx->state[4] = UL64(0x510E527FADE682D1);
++ ctx->state[5] = UL64(0x9B05688C2B3E6C1F);
++ ctx->state[6] = UL64(0x1F83D9ABFB41BD6B);
++ ctx->state[7] = UL64(0x5BE0CD19137E2179);
++ } else {
++ /* SHA-384 */
++ ctx->state[0] = UL64(0xCBBB9D5DC1059ED8);
++ ctx->state[1] = UL64(0x629A292A367CD507);
++ ctx->state[2] = UL64(0x9159015A3070DD17);
++ ctx->state[3] = UL64(0x152FECD8F70E5939);
++ ctx->state[4] = UL64(0x67332667FFC00B31);
++ ctx->state[5] = UL64(0x8EB44A8768581511);
++ ctx->state[6] = UL64(0xDB0C2E0D64F98FA7);
++ ctx->state[7] = UL64(0x47B5481DBEFA4FA4);
++ }
++
++ ctx->is384 = is384;
++}
++
++static void sha4_process(sha4_context * ctx, const unsigned char data[128])
++{
++ int i;
++ unsigned int64 temp1, temp2, W[80];
++ unsigned int64 A, B, C, D, E, F, G, H;
++
++#define SHR(x,n) (x >> n)
++#define ROTR(x,n) (SHR(x,n) | (x << (64 - n)))
++
++#define S0(x) (ROTR(x, 1) ^ ROTR(x, 8) ^ SHR(x, 7))
++#define S1(x) (ROTR(x,19) ^ ROTR(x,61) ^ SHR(x, 6))
++
++#define S2(x) (ROTR(x,28) ^ ROTR(x,34) ^ ROTR(x,39))
++#define S3(x) (ROTR(x,14) ^ ROTR(x,18) ^ ROTR(x,41))
++
++#define F0(x,y,z) ((x & y) | (z & (x | y)))
++#define F1(x,y,z) (z ^ (x & (y ^ z)))
++
++#define P(a,b,c,d,e,f,g,h,x,K) \
++ { \
++ temp1 = h + S3(e) + F1(e,f,g) + K + x; \
++ temp2 = S2(a) + F0(a,b,c); \
++ d += temp1; h = temp1 + temp2; \
++ }
++
++ for (i = 0; i < 16; i++) {
++ GET_UINT64_BE(W[i], data, i << 3);
++ }
++
++ for (; i < 80; i++) {
++ W[i] = S1(W[i - 2]) + W[i - 7] + S0(W[i - 15]) + W[i - 16];
++ }
++
++ A = ctx->state[0];
++ B = ctx->state[1];
++ C = ctx->state[2];
++ D = ctx->state[3];
++ E = ctx->state[4];
++ F = ctx->state[5];
++ G = ctx->state[6];
++ H = ctx->state[7];
++ i = 0;
++
++ do {
++ P(A, B, C, D, E, F, G, H, W[i], K[i]);
++ i++;
++ P(H, A, B, C, D, E, F, G, W[i], K[i]);
++ i++;
++ P(G, H, A, B, C, D, E, F, W[i], K[i]);
++ i++;
++ P(F, G, H, A, B, C, D, E, W[i], K[i]);
++ i++;
++ P(E, F, G, H, A, B, C, D, W[i], K[i]);
++ i++;
++ P(D, E, F, G, H, A, B, C, W[i], K[i]);
++ i++;
++ P(C, D, E, F, G, H, A, B, W[i], K[i]);
++ i++;
++ P(B, C, D, E, F, G, H, A, W[i], K[i]);
++ i++;
++ } while (i < 80);
++
++ ctx->state[0] += A;
++ ctx->state[1] += B;
++ ctx->state[2] += C;
++ ctx->state[3] += D;
++ ctx->state[4] += E;
++ ctx->state[5] += F;
++ ctx->state[6] += G;
++ ctx->state[7] += H;
++}
++
++/*
++ * SHA-512 process buffer
++ */
++void sha4_update(sha4_context * ctx, const unsigned char *input, int ilen)
++{
++ int fill;
++ unsigned int64 left;
++
++ if (ilen <= 0)
++ return;
++
++ left = ctx->total[0] & 0x7F;
++ fill = (int)(128 - left);
++
++ ctx->total[0] += ilen;
++
++ if (ctx->total[0] < (unsigned int64)ilen)
++ ctx->total[1]++;
++
++ if (left && ilen >= fill) {
++ memcpy((void *)(ctx->buffer + left), (void *)input, fill);
++ sha4_process(ctx, ctx->buffer);
++ input += fill;
++ ilen -= fill;
++ left = 0;
++ }
++
++ while (ilen >= 128) {
++ sha4_process(ctx, input);
++ input += 128;
++ ilen -= 128;
++ }
++
++ if (ilen > 0) {
++ memcpy((void *)(ctx->buffer + left), (void *)input, ilen);
++ }
++}
++
++static const unsigned char sha4_padding[128] = {
++ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
++};
++
++/*
++ * SHA-512 final digest
++ */
++void sha4_finish(sha4_context * ctx, unsigned char output[64])
++{
++ int last, padn;
++ unsigned int64 high, low;
++ unsigned char msglen[16];
++
++ high = (ctx->total[0] >> 61)
++ | (ctx->total[1] << 3);
++ low = (ctx->total[0] << 3);
++
++ PUT_UINT64_BE(high, msglen, 0);
++ PUT_UINT64_BE(low, msglen, 8);
++
++ last = (int)(ctx->total[0] & 0x7F);
++ padn = (last < 112) ? (112 - last) : (240 - last);
++
++ sha4_update(ctx, (unsigned char *)sha4_padding, padn);
++ sha4_update(ctx, msglen, 16);
++
++ PUT_UINT64_BE(ctx->state[0], output, 0);
++ PUT_UINT64_BE(ctx->state[1], output, 8);
++ PUT_UINT64_BE(ctx->state[2], output, 16);
++ PUT_UINT64_BE(ctx->state[3], output, 24);
++ PUT_UINT64_BE(ctx->state[4], output, 32);
++ PUT_UINT64_BE(ctx->state[5], output, 40);
++
++ if (ctx->is384 == 0) {
++ PUT_UINT64_BE(ctx->state[6], output, 48);
++ PUT_UINT64_BE(ctx->state[7], output, 56);
++ }
++}
++
++/*
++ * output = SHA-512( input buffer )
++ */
++void sha4(unsigned char *input, int ilen, unsigned char output[64], int is384)
++{
++ sha4_context ctx;
++
++ sha4_starts(&ctx, is384);
++ sha4_update(&ctx, input, ilen);
++ sha4_finish(&ctx, output);
++
++ memset(&ctx, 0, sizeof(sha4_context));
++}
++
++/*
++ * Output = SHA-4( input buffer ). Trigger the watchdog every 'chunk_sz'
++ * bytes of input processed.
++ */
++static void sha4_csum_wd(const unsigned char *input, unsigned int ilen,
++ unsigned char *output, unsigned int chunk_sz, int is384)
++{
++ sha4_context ctx;
++#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
++ const unsigned char *end;
++ unsigned char *curr;
++ int chunk;
++#endif
++
++ sha4_starts(&ctx, is384);
++
++#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
++ curr = (unsigned char *)input;
++ end = input + ilen;
++ while (curr < end) {
++ chunk = end - curr;
++ if (chunk > chunk_sz)
++ chunk = chunk_sz;
++ sha4_update(&ctx, curr, chunk);
++ curr += chunk;
++ WATCHDOG_RESET();
++ }
++#else
++ sha4_update(&ctx, input, ilen);
++#endif
++
++ sha4_finish(&ctx, output);
++}
++
++void sha384_csum_wd(const unsigned char *input, unsigned int ilen,
++ unsigned char *output, unsigned int chunk_sz)
++{
++ sha4_csum_wd(input, ilen, output, chunk_sz, 1);
++}
++
++void sha512_csum_wd(const unsigned char *input, unsigned int ilen,
++ unsigned char *output, unsigned int chunk_sz)
++{
++ sha4_csum_wd(input, ilen, output, chunk_sz, 0);
++}
++
++/*
++ * SHA-512 HMAC context setup
++ */
++void sha4_hmac_starts(sha4_context * ctx, unsigned char *key, int keylen,
++ int is384)
++{
++ int i;
++ unsigned char sum[64];
++
++ if (keylen > 128) {
++ sha4(key, keylen, sum, is384);
++ keylen = (is384) ? 48 : 64;
++ key = sum;
++ }
++
++ memset(ctx->ipad, 0x36, 128);
++ memset(ctx->opad, 0x5C, 128);
++
++ for (i = 0; i < keylen; i++) {
++ ctx->ipad[i] = (unsigned char)(ctx->ipad[i] ^ key[i]);
++ ctx->opad[i] = (unsigned char)(ctx->opad[i] ^ key[i]);
++ }
++
++ sha4_starts(ctx, is384);
++ sha4_update(ctx, ctx->ipad, 128);
++
++ memset(sum, 0, sizeof(sum));
++}
++
++/*
++ * SHA-512 HMAC process buffer
++ */
++void sha4_hmac_update(sha4_context * ctx, unsigned char *input, int ilen)
++{
++ sha4_update(ctx, input, ilen);
++}
++
++/*
++ * SHA-512 HMAC final digest
++ */
++void sha4_hmac_finish(sha4_context * ctx, unsigned char output[64])
++{
++ int is384, hlen;
++ unsigned char tmpbuf[64];
++
++ is384 = ctx->is384;
++ hlen = (is384 == 0) ? 64 : 48;
++
++ sha4_finish(ctx, tmpbuf);
++ sha4_starts(ctx, is384);
++ sha4_update(ctx, ctx->opad, 128);
++ sha4_update(ctx, tmpbuf, hlen);
++ sha4_finish(ctx, output);
++
++ memset(tmpbuf, 0, sizeof(tmpbuf));
++}
++
++/*
++ * output = HMAC-SHA-512( hmac key, input buffer )
++ */
++void sha4_hmac(unsigned char *key, int keylen,
++ unsigned char *input, int ilen,
++ unsigned char output[64], int is384)
++{
++ sha4_context ctx;
++
++ sha4_hmac_starts(&ctx, key, keylen, is384);
++ sha4_hmac_update(&ctx, input, ilen);
++ sha4_hmac_finish(&ctx, output);
++
++ memset(&ctx, 0, sizeof(sha4_context));
++}
+diff --git a/tools/Makefile b/tools/Makefile
+index 5dd33ed4d5..ae6451178b 100644
+--- a/tools/Makefile
++++ b/tools/Makefile
+@@ -107,6 +107,7 @@ dumpimage-mkimage-objs := aisimage.o \
+ socfpgaimage.o \
+ lib/sha1.o \
+ lib/sha256.o \
++ lib/sha4.o \
+ common/hash.o \
+ ublimage.o \
+ zynqimage.o \
+--
+2.17.1
+
diff --git a/meta/meta-mediatek-gpl/recipes-bsp/u-boot/u-boot-mkimage-2018.07/0001-secure-boot-ECC-support.patch b/meta/meta-mediatek-gpl/recipes-bsp/u-boot/u-boot-mkimage-2018.07/0001-secure-boot-ECC-support.patch
new file mode 100644
index 0000000..0659fe0
--- /dev/null
+++ b/meta/meta-mediatek-gpl/recipes-bsp/u-boot/u-boot-mkimage-2018.07/0001-secure-boot-ECC-support.patch
@@ -0,0 +1,699 @@
+From 1e0921b292481b097c612ec581d333ca4c0612dd Mon Sep 17 00:00:00 2001
+From: KH Hung <kh.hung@mediatek.com>
+Date: Tue, 19 Feb 2019 13:35:15 +0800
+Subject: [PATCH] 201807-secure-boot-ECC-support
+
+---
+ Kconfig | 1 +
+ common/image-sig.c | 23 ++-
+ include/image.h | 1 +
+ include/u-boot/ecc.h | 63 +++++++
+ lib/Kconfig | 2 +
+ lib/Makefile | 3 +
+ lib/ecc/Kconfig | 8 +
+ lib/ecc/Makefile | 3 +
+ lib/ecc/ecc-sig.c | 413 +++++++++++++++++++++++++++++++++++++++++++
+ lib/ecc/ecc-verify.c | 26 +++
+ tools/Makefile | 7 +-
+ 11 files changed, 548 insertions(+), 2 deletions(-)
+ create mode 100644 include/u-boot/ecc.h
+ create mode 100644 lib/ecc/Kconfig
+ create mode 100644 lib/ecc/Makefile
+ create mode 100644 lib/ecc/ecc-sig.c
+ create mode 100644 lib/ecc/ecc-verify.c
+
+diff --git a/Kconfig b/Kconfig
+index 513f23cb4c..a9b15d2cfc 100644
+--- a/Kconfig
++++ b/Kconfig
+@@ -271,6 +271,7 @@ config FIT_SIGNATURE
+ depends on DM
+ select RSA
+ select HASH
++ select ECC
+ help
+ This option enables signature verification of FIT uImages,
+ using a hash signed and verified using RSA. If
+diff --git a/common/image-sig.c b/common/image-sig.c
+index acbd1297e4..2ba1eac9fc 100644
+--- a/common/image-sig.c
++++ b/common/image-sig.c
+@@ -14,6 +14,7 @@ DECLARE_GLOBAL_DATA_PTR;
+ #include <image.h>
+ #include <u-boot/rsa.h>
+ #include <u-boot/rsa-checksum.h>
++#include <u-boot/ecc.h>
+
+ #define IMAGE_MAX_HASHED_NODES 100
+
+@@ -115,8 +116,28 @@ struct crypto_algo crypto_algos[] = {
+ .sign = rsassa_pss_sign,
+ .add_verify_data = rsa_add_verify_data,
+ .verify = rsa_verify,
++ },
++ {
++ .name = "nistp256",
++ .key_len = ECC256_BYTES,
++ .sign = ecc_sign,
++ .add_verify_data = ecc_add_verify_data,
++ .verify = ecc_verify,
++ },
++ {
++ .name = "nistp384",
++ .key_len = ECC384_BYTES,
++ .sign = ecc_sign,
++ .add_verify_data = ecc_add_verify_data,
++ .verify = ecc_verify,
++ },
++ {
++ .name = "nistp521",
++ .key_len = ECC521_BYTES,
++ .sign = ecc_sign,
++ .add_verify_data = ecc_add_verify_data,
++ .verify = ecc_verify,
+ }
+-
+ };
+
+ struct checksum_algo *image_get_checksum_algo(const char *full_name)
+diff --git a/include/image.h b/include/image.h
+index 475af42a7a..3bde55763b 100644
+--- a/include/image.h
++++ b/include/image.h
+@@ -37,6 +37,7 @@ struct fdt_region;
+ #define CONFIG_SHA256
+ #define CONFIG_SHA384
+ #define CONFIG_SHA512
++#define CONFIG_ECC
+
+ #define IMAGE_ENABLE_IGNORE 0
+ #define IMAGE_INDENT_STRING ""
+diff --git a/include/u-boot/ecc.h b/include/u-boot/ecc.h
+new file mode 100644
+index 0000000000..e3b564effd
+--- /dev/null
++++ b/include/u-boot/ecc.h
+@@ -0,0 +1,63 @@
++
++#ifndef _ECC_H
++#define _ECC_H
++
++#include <errno.h>
++#include <image.h>
++
++#define ECC256_BYTES (32)
++#define ECC384_BYTES (48)
++#define ECC521_BYTES (66)
++
++/**
++ * sign() - calculate and return signature for given input data
++ *
++ * @info: Specifies key and FIT information
++ * @data: Pointer to the input data
++ * @data_len: Data length
++ * @sigp: Set to an allocated buffer holding the signature
++ * @sig_len: Set to length of the calculated hash
++ *
++ * This computes input data signature according to selected algorithm.
++ * Resulting signature value is placed in an allocated buffer, the
++ * pointer is returned as *sigp. The length of the calculated
++ * signature is returned via the sig_len pointer argument. The caller
++ * should free *sigp.
++ *
++ * @return: 0, on success, -ve on error
++ */
++int ecc_sign(struct image_sign_info *info,
++ const struct image_region region[],
++ int region_count, uint8_t **sigp, uint *sig_len);
++
++/**
++ * add_verify_data() - Add verification information to FDT
++ *
++ * Add public key information to the FDT node, suitable for
++ * verification at run-time. The information added depends on the
++ * algorithm being used.
++ *
++ * @info: Specifies key and FIT information
++ * @keydest: Destination FDT blob for public key data
++ * @return: 0, on success, -ENOSPC if the keydest FDT blob ran out of space,
++ other -ve value on error
++*/
++int ecc_add_verify_data(struct image_sign_info *info, void *keydest);
++
++/**
++ * rsa_verify() - Verify a signature against some data
++ *
++ * Verify a RSA PKCS1.5 signature against an expected hash.
++ *
++ * @info: Specifies key and FIT information
++ * @data: Pointer to the input data
++ * @data_len: Data length
++ * @sig: Signature
++ * @sig_len: Number of bytes in signature
++ * @return 0 if verified, -ve on error
++ */
++int ecc_verify(struct image_sign_info *info,
++ const struct image_region region[], int region_count,
++ uint8_t *sig, uint sig_len);
++
++#endif
+diff --git a/lib/Kconfig b/lib/Kconfig
+index c3bed74860..c2c8160651 100644
+--- a/lib/Kconfig
++++ b/lib/Kconfig
+@@ -174,6 +174,8 @@ config AES
+
+ source lib/rsa/Kconfig
+
++source lib/ecc/Kconfig
++
+ config TPM
+ bool "Trusted Platform Module (TPM) Support"
+ depends on DM
+diff --git a/lib/Makefile b/lib/Makefile
+index b3560729a3..3d9edde6bd 100644
+--- a/lib/Makefile
++++ b/lib/Makefile
+@@ -50,10 +50,13 @@ endif
+
+ obj-$(CONFIG_RSA) += rsa/
+ obj-$(CONFIG_SHA1) += sha1.o
++obj-$(CONFIG_SHA1) += sha4.o
+ obj-$(CONFIG_SHA256) += sha256.o
+ obj-$(CONFIG_SHA384) += sha384.o
+ obj-$(CONFIG_SHA512) += sha512.o
+
++obj-$(CONFIG_ECC) += ecc/
++
+ obj-$(CONFIG_$(SPL_)ZLIB) += zlib/
+ obj-$(CONFIG_$(SPL_)GZIP) += gunzip.o
+ obj-$(CONFIG_$(SPL_)LZO) += lzo/
+diff --git a/lib/ecc/Kconfig b/lib/ecc/Kconfig
+new file mode 100644
+index 0000000000..bd6f99aa19
+--- /dev/null
++++ b/lib/ecc/Kconfig
+@@ -0,0 +1,8 @@
++config ECC
++ bool "Use ECC Library"
++ help
++ ECC support. This enables the ECC algorithm used for FIT image
++ verification in U-Boot.
++ The signing part is build into mkimage regardless of this
++ option. The software based modular exponentiation is built into
++ mkimage irrespective of this option.
+diff --git a/lib/ecc/Makefile b/lib/ecc/Makefile
+new file mode 100644
+index 0000000000..b63aaff164
+--- /dev/null
++++ b/lib/ecc/Makefile
+@@ -0,0 +1,3 @@
++
++obj-$(CONFIG_ECC) += ecc-sig.o
++obj-$(CONFIG_ECC) += ecc-verify.o
+diff --git a/lib/ecc/ecc-sig.c b/lib/ecc/ecc-sig.c
+new file mode 100644
+index 0000000000..582c69e17a
+--- /dev/null
++++ b/lib/ecc/ecc-sig.c
+@@ -0,0 +1,413 @@
++
++#include "mkimage.h"
++#include <stdio.h>
++#include <string.h>
++#include <image.h>
++#include <time.h>
++#include <openssl/bn.h>
++#include <openssl/ec.h>
++#include <openssl/pem.h>
++#include <openssl/err.h>
++#include <openssl/ssl.h>
++#include <openssl/evp.h>
++#include <openssl/engine.h>
++
++static int fdt_add_bignum(void *blob, int noffset, const char *prop_name,
++ BIGNUM *num, int num_bits)
++{
++ int nwords = num_bits / 32;
++ int size;
++ uint32_t *buf, *ptr;
++ BIGNUM *tmp, *big2, *big32, *big2_32;
++ BN_CTX *ctx;
++ int ret;
++
++ tmp = BN_new();
++ big2 = BN_new();
++ big32 = BN_new();
++ big2_32 = BN_new();
++
++ /*
++ * Note: This code assumes that all of the above succeed, or all fail.
++ * In practice memory allocations generally do not fail (unless the
++ * process is killed), so it does not seem worth handling each of these
++ * as a separate case. Technicaly this could leak memory on failure,
++ * but a) it won't happen in practice, and b) it doesn't matter as we
++ * will immediately exit with a failure code.
++ */
++ if (!tmp || !big2 || !big32 || !big2_32) {
++ fprintf(stderr, "Out of memory (bignum)\n");
++ return -ENOMEM;
++ }
++ ctx = BN_CTX_new();
++ if (!tmp) {
++ fprintf(stderr, "Out of memory (bignum context)\n");
++ return -ENOMEM;
++ }
++ BN_set_word(big2, 2L);
++ BN_set_word(big32, 32L);
++ BN_exp(big2_32, big2, big32, ctx); /* B = 2^32 */
++
++ size = nwords * sizeof(uint32_t);
++ buf = malloc(size);
++ if (!buf) {
++ fprintf(stderr, "Out of memory (%d bytes)\n", size);
++ return -ENOMEM;
++ }
++
++ /* Write out modulus as big endian array of integers */
++ for (ptr = buf + nwords - 1; ptr >= buf; ptr--) {
++ BN_mod(tmp, num, big2_32, ctx); /* n = N mod B */
++ *ptr = cpu_to_fdt32(BN_get_word(tmp));
++ BN_rshift(num, num, 32); /* N = N/B */
++ }
++
++ /*
++ * We try signing with successively increasing size values, so this
++ * might fail several times
++ */
++ ret = fdt_setprop(blob, noffset, prop_name, buf, size);
++
++ free(buf);
++ BN_free(tmp);
++ BN_free(big2);
++ BN_free(big32);
++ BN_free(big2_32);
++
++ return ret ? -FDT_ERR_NOSPACE : 0;
++}
++
++static EC_KEY *pkey_get_eckey(EVP_PKEY *key, EC_KEY **eckey)
++{
++ EC_KEY *dtmp;
++ if (!key)
++ return NULL;
++ dtmp = EVP_PKEY_get1_EC_KEY(key);
++ EVP_PKEY_free(key);
++ if (!dtmp)
++ return NULL;
++ if (eckey) {
++ EC_KEY_free(*eckey);
++ *eckey = dtmp;
++ }
++ return dtmp;
++}
++
++/**
++ * ec_pem_get_priv_key() - read a private key from a .key file
++ *
++ * @keydir: Directory containing the key
++ * @name Name of key file (will have a .key extension)
++ * @rsap Returns EC object, or NULL on failure
++ * @return 0 if ok, -ve on error (in which case *ecp will be set to NULL)
++ */
++static int ec_pem_get_priv_key(const char *keydir, const char *name,
++ EC_KEY **ecp)
++{
++ char path[1024];
++ EC_KEY *ec;
++ FILE *f;
++ EVP_PKEY *pktmp;
++
++ *ecp = NULL;
++ snprintf(path, sizeof(path), "%s/%s_priv.key", keydir, name);
++ f = fopen(path, "r");
++ if (!f) {
++ fprintf(stderr, "Couldn't open EC private key: '%s': %s\n",
++ path, strerror(errno));
++ return -ENOENT;
++ }
++
++ pktmp = PEM_read_PrivateKey(f, 0, NULL, path);
++ ec = pkey_get_eckey(pktmp, ecp);
++ if (!ec) {
++ fprintf(stderr, "Failure reading EC private key\n");
++ fclose(f);
++ return -EPROTO;
++ }
++ fclose(f);
++ *ecp = ec;
++
++ return 0;
++}
++
++/**
++ * ec_pem_get_pub_key() - read a public key from a .key file
++ *
++ * @keydir: Directory containing the key
++ * @name Name of key file (will have a .key extension)
++ * @pub_key Returns BIGNUM object, or NULL on failure
++ * @return 0 if ok, -ve on error (in which case *pub_key will be set to NULL)
++ */
++static int ec_pem_get_pub_key(const char *keydir, const char *name, BIGNUM **pub_key)
++{
++ char path[1024];
++ EC_KEY *ec;
++ FILE *f;
++ unsigned char *pub_k_cp = NULL;
++ int ret;
++
++ snprintf(path, sizeof(path), "%s/%s_public.key", keydir, name);
++ f = fopen(path, "r");
++ if (!f) {
++ fprintf(stderr, "Couldn't open EC public key: '%s': %s\n",
++ path, strerror(errno));
++ return -ENOENT;
++ }
++
++ ec = PEM_read_EC_PUBKEY(f, 0, NULL, path);
++
++ if (!ec) {
++ fprintf(stderr, "Failure reading EC public key\n");
++ fclose(f);
++ return -EPROTO;
++ }
++ fclose(f);
++
++ /* Transform from EC_POINT to char */
++ ret = i2o_ECPublicKey(ec, &pub_k_cp);
++ if (ret == 0) {
++ return -1;
++ } else {
++ /* Transform from char to BIGNUM */
++ *pub_key = BN_bin2bn(pub_k_cp, ret , NULL);
++ }
++
++ return 0;
++}
++
++int ecc_add_verify_data(struct image_sign_info *info, void *keydest)
++{
++ BIGNUM *pub_key;
++ int parent, node;
++ char name[100];
++ int ret=0;
++ int bits;
++
++ // get public key
++ ret = ec_pem_get_pub_key(info->keydir, info->keyname, &pub_key);
++
++ if (ret)
++ goto err_get_pub_key;
++
++ parent = fdt_subnode_offset(keydest, 0, FIT_SIG_NODENAME);
++ if (parent == -FDT_ERR_NOTFOUND) {
++ parent = fdt_add_subnode(keydest, 0, FIT_SIG_NODENAME);
++ if (parent < 0) {
++ ret = parent;
++ if (ret != -FDT_ERR_NOSPACE) {
++ fprintf(stderr, "Couldn't create signature node: %s\n",
++ fdt_strerror(parent));
++ }
++ }
++ }
++ if (ret)
++ goto done;
++
++ /* Either create or overwrite the named key node */
++ snprintf(name, sizeof(name), "key-%s", info->keyname);
++ node = fdt_subnode_offset(keydest, parent, name);
++ if (node == -FDT_ERR_NOTFOUND) {
++ node = fdt_add_subnode(keydest, parent, name);
++ if (node < 0) {
++ ret = node;
++ if (ret != -FDT_ERR_NOSPACE) {
++ fprintf(stderr, "Could not create key subnode: %s\n",
++ fdt_strerror(node));
++ }
++ }
++ } else if (node < 0) {
++ fprintf(stderr, "Cannot select keys parent: %s\n",
++ fdt_strerror(node));
++ ret = node;
++ }
++
++ if (!ret) {
++ ret = fdt_setprop_string(keydest, node, "key-name-hint", info->keyname);
++ }
++
++ if (!ret) {
++ bits = info->crypto->key_len * 16;
++ ret = fdt_add_bignum(keydest, node, "ecc,public-key", pub_key, bits);
++ }
++ if (!ret) {
++ ret = fdt_setprop_string(keydest, node, FIT_ALGO_PROP, info->name);
++ }
++ if (!ret && info->require_keys) {
++ ret = fdt_setprop_string(keydest, node, "required", info->require_keys);
++ }
++done:
++ BN_free(pub_key);
++ if (ret) {
++ ret = ret == -FDT_ERR_NOSPACE ? -ENOSPC : -EIO;
++ }
++
++err_get_pub_key:
++
++
++ return ret;
++}
++
++static int ec_sign_with_key(EC_KEY *ec, struct checksum_algo *checksum_algo,
++ const struct image_region region[], int region_count,
++ uint8_t **sigp, uint *sig_size)
++{
++ EVP_PKEY *key;
++ EVP_PKEY_CTX *keyctx;
++ EVP_MD_CTX *context;
++ int size, ret = 0;
++ uint8_t *sig;
++ int i;
++
++ key = EVP_PKEY_new();
++ if (!key) {
++ fprintf(stderr, "EVP_PKEY object creation failed \n");
++ return -1;
++ }
++
++ if (!EVP_PKEY_set1_EC_KEY(key, ec)) {
++ fprintf(stderr, "EVP key setup failed \n");
++ ret = -1;
++ goto err_set;
++ }
++
++ keyctx = EVP_PKEY_CTX_new(key, NULL);
++ if (!keyctx) {
++ fprintf(stderr, "EVP_PKEY_CTX object creation failed \n");
++ ret = -1;
++ goto err_set;
++ }
++
++ size = EVP_PKEY_size(key);
++ sig = malloc(size);
++ if (!sig) {
++ fprintf(stderr, "Out of memory for signature (%d bytes)\n", size);
++ ret = -ENOMEM;
++ goto err_alloc;
++ }
++
++ context = EVP_MD_CTX_create();
++ if (!context) {
++ fprintf(stderr, "EVP context creation failed \n");
++ ret = -1;
++ goto err_create;
++ }
++ EVP_MD_CTX_init(context);
++ if (!EVP_DigestSignInit(context, &keyctx, checksum_algo->calculate_sign(), NULL, key)) {
++ fprintf(stderr, "Signer setup failed \n");
++ ret = -1;
++ goto err_sign;
++ }
++
++ for (i = 0; i < region_count; i++) {
++
++ if (!EVP_DigestSignUpdate(context, region[i].data, region[i].size)) {
++ fprintf(stderr, "Signing data failed \n");
++ ret = -1;
++ goto err_sign;
++ }
++ }
++
++ if (!EVP_DigestSignFinal(context, sig, (size_t *)sig_size)) {
++ fprintf(stderr, "Could not obtain signature \n");
++ ret = -1;
++ goto err_sign;
++ }
++
++#if OPENSSL_VERSION_NUMBER < 0x10100000L
++ EVP_MD_CTX_cleanup(context);
++#else
++ EVP_MD_CTX_reset(context);
++#endif
++ EVP_MD_CTX_destroy(context);
++ EVP_PKEY_free(key);
++
++ fprintf(stderr, "Got signature: %d bytes, expected %d\n", *sig_size, size);
++ *sigp = sig;
++ *sig_size = size;
++
++ return 0;
++
++err_sign:
++ EVP_MD_CTX_destroy(context);
++err_create:
++ free(sig);
++err_alloc:
++err_set:
++ EVP_PKEY_free(key);
++ return ret;
++}
++
++int ecc_sign(struct image_sign_info *info,
++ const struct image_region region[], int region_count,
++ uint8_t **sigp, uint *sig_len)
++{
++ EC_KEY *ec;
++ int ret = 0;
++
++ /* To read private key from pem */
++ ret = ec_pem_get_priv_key(info->keydir, info->keyname, &ec);
++
++ if (ret) {
++ fprintf(stderr, "Failure reading EC private key\n");
++ goto err_priv;
++ }
++
++ /* To signature */
++ ret = ec_sign_with_key(ec, info->checksum, region,
++ region_count, sigp, sig_len);
++ if (ret) {
++ goto err_sign;
++ }
++
++
++err_sign:
++
++err_priv:
++
++ return ret;
++}
++
++/**
++ * ec_pem_get_pub_key_by_path() - read a public key from a .key file
++ *
++ * @path Path of key file (will have a .key extension)
++ * @pub_key Returns BIGNUM object, or NULL on failure
++ * @return 0 if ok, -ve on error (in which case *pub_key will be set to NULL)
++ */
++static int ec_pem_get_pub_key_by_path(const char *keydir, const char *name, BIGNUM **pub_key)
++{
++ char path[1024];
++ EC_KEY *ec;
++ FILE *f;
++ unsigned char *pub_k_cp = NULL;
++ int ret;
++
++ snprintf(path, sizeof(path), "%s/tier_public.key", keydir);
++ f = fopen(path, "r");
++ if (!f) {
++ fprintf(stderr, "Couldn't open EC public key: '%s': %s\n",
++ path, strerror(errno));
++ return -ENOENT;
++ }
++
++ ec = PEM_read_EC_PUBKEY(f, 0, NULL, path);
++
++ if (!ec) {
++ fprintf(stderr, "Failure reading EC public key\n");
++ fclose(f);
++ return -EPROTO;
++ }
++ fclose(f);
++
++ /* Transform from EC_POINT to char */
++ ret = i2o_ECPublicKey(ec, &pub_k_cp);
++ if (ret == 0) {
++ return -1;
++ } else {
++ /* Transform from char to BIGNUM */
++ *pub_key = BN_bin2bn(pub_k_cp, ret , NULL);
++ }
++
++ return 0;
++}
+diff --git a/lib/ecc/ecc-verify.c b/lib/ecc/ecc-verify.c
+new file mode 100644
+index 0000000000..49251a3f11
+--- /dev/null
++++ b/lib/ecc/ecc-verify.c
+@@ -0,0 +1,26 @@
++
++#ifndef USE_HOSTCC
++#include <common.h>
++#include <fdtdec.h>
++#include <asm/types.h>
++#include <asm/byteorder.h>
++#include <linux/errno.h>
++#include <asm/types.h>
++#include <asm/unaligned.h>
++#include <dm.h>
++#else
++#include "fdt_host.h"
++//#include "mkimage.h"
++#include <fdt_support.h>
++#endif
++
++#include <u-boot/ecc.h>
++
++
++int ecc_verify(struct image_sign_info *info,
++ const struct image_region region[], int region_count,
++ uint8_t *sig, uint sig_len)
++{
++
++ return 0;
++}
+diff --git a/tools/Makefile b/tools/Makefile
+index ae6451178b..4ed3489a79 100644
+--- a/tools/Makefile
++++ b/tools/Makefile
+@@ -75,6 +75,9 @@ RSA_OBJS-$(CONFIG_FIT_SIGNATURE) := $(addprefix lib/rsa/, \
+ rsa-sign.o rsa-verify.o rsa-checksum.o \
+ rsa-mod-exp.o)
+
++ECC_OBJS-$(CONFIG_ECC) := $(addprefix lib/ecc/, \
++ ecc-sig.o ecc-verify.o)
++
+ ROCKCHIP_OBS = lib/rc4.o rkcommon.o rkimage.o rksd.o rkspi.o
+
+ # common objs for dumpimage and mkimage
+@@ -116,7 +119,8 @@ dumpimage-mkimage-objs := aisimage.o \
+ $(LIBFDT_OBJS) \
+ gpimage.o \
+ gpimage-common.o \
+- $(RSA_OBJS-y)
++ $(RSA_OBJS-y) \
++ $(ECC_OBJS-y)
+
+ dumpimage-objs := $(dumpimage-mkimage-objs) dumpimage.o
+ mkimage-objs := $(dumpimage-mkimage-objs) mkimage.o
+@@ -155,6 +159,7 @@ ifeq ($(HOSTOS),darwin)
+ HOSTCFLAGS_mxsimage.o += -Wno-deprecated-declarations
+ HOSTCFLAGS_image-sig.o += -Wno-deprecated-declarations
+ HOSTCFLAGS_rsa-sign.o += -Wno-deprecated-declarations
++HOSTCFLAGS_ecc-sig.o += -Wno-deprecated-declarations
+ endif
+ endif
+
+--
+2.18.0
+
diff --git a/meta/meta-mediatek-gpl/recipes-bsp/u-boot/u-boot-mkimage-2018.07/0001-support-trusted-key-certificate.patch b/meta/meta-mediatek-gpl/recipes-bsp/u-boot/u-boot-mkimage-2018.07/0001-support-trusted-key-certificate.patch
new file mode 100644
index 0000000..4e88193
--- /dev/null
+++ b/meta/meta-mediatek-gpl/recipes-bsp/u-boot/u-boot-mkimage-2018.07/0001-support-trusted-key-certificate.patch
@@ -0,0 +1,1093 @@
+From 3c471c36eb118f18d37670b4bc676927c35cf822 Mon Sep 17 00:00:00 2001
+From: KH Hung <kh.hung@mediatek.com>
+Date: Tue, 19 Feb 2019 16:05:18 +0800
+Subject: [PATCH] 201807-support-trusted-key-certificate
+
+---
+ common/image-sig.c | 9 ++
+ include/image.h | 45 ++++++++-
+ include/u-boot/ecc.h | 14 +++
+ include/u-boot/rsa.h | 23 +++++
+ lib/ecc/ecc-sig.c | 206 ++++++++++++++++++++++++++------------
+ lib/rsa/rsa-sign.c | 122 ++++++++++++++++++++++-
+ tools/fit_image.c | 10 +-
+ tools/image-host.c | 230 +++++++++++++++++++++++++++++++++++++++++--
+ tools/imagetool.h | 4 +
+ tools/mkimage.c | 16 ++-
+ 10 files changed, 601 insertions(+), 78 deletions(-)
+
+diff --git a/common/image-sig.c b/common/image-sig.c
+index 2ba1eac9fc..bfc71a6b34 100644
+--- a/common/image-sig.c
++++ b/common/image-sig.c
+@@ -81,6 +81,7 @@ struct crypto_algo crypto_algos[] = {
+ .sign = rsa_sign,
+ .add_verify_data = rsa_add_verify_data,
+ .verify = rsa_verify,
++ .add_tkc_data = rsa_add_tkc_data,
+ },
+ {
+ .name = "rsa3072",
+@@ -88,6 +89,7 @@ struct crypto_algo crypto_algos[] = {
+ .sign = rsa_sign,
+ .add_verify_data = rsa_add_verify_data,
+ .verify = rsa_verify,
++ .add_tkc_data = rsa_add_tkc_data,
+ },
+ {
+ .name = "rsa4096",
+@@ -95,6 +97,7 @@ struct crypto_algo crypto_algos[] = {
+ .sign = rsa_sign,
+ .add_verify_data = rsa_add_verify_data,
+ .verify = rsa_verify,
++ .add_tkc_data = rsa_add_tkc_data,
+ },
+ {
+ .name = "rsassa-pss2048",
+@@ -102,6 +105,7 @@ struct crypto_algo crypto_algos[] = {
+ .sign = rsassa_pss_sign,
+ .add_verify_data = rsa_add_verify_data,
+ .verify = rsa_verify,
++ .add_tkc_data = rsa_add_tkc_data,
+ },
+ {
+ .name = "rsassa-pss3072",
+@@ -109,6 +113,7 @@ struct crypto_algo crypto_algos[] = {
+ .sign = rsassa_pss_sign,
+ .add_verify_data = rsa_add_verify_data,
+ .verify = rsa_verify,
++ .add_tkc_data = rsa_add_tkc_data,
+ },
+ {
+ .name = "rsassa-pss4096",
+@@ -116,6 +121,7 @@ struct crypto_algo crypto_algos[] = {
+ .sign = rsassa_pss_sign,
+ .add_verify_data = rsa_add_verify_data,
+ .verify = rsa_verify,
++ .add_tkc_data = rsa_add_tkc_data,
+ },
+ {
+ .name = "nistp256",
+@@ -123,6 +129,7 @@ struct crypto_algo crypto_algos[] = {
+ .sign = ecc_sign,
+ .add_verify_data = ecc_add_verify_data,
+ .verify = ecc_verify,
++ .add_tkc_data = ecc_add_tkc_data,
+ },
+ {
+ .name = "nistp384",
+@@ -130,6 +137,7 @@ struct crypto_algo crypto_algos[] = {
+ .sign = ecc_sign,
+ .add_verify_data = ecc_add_verify_data,
+ .verify = ecc_verify,
++ .add_tkc_data = ecc_add_tkc_data,
+ },
+ {
+ .name = "nistp521",
+@@ -137,6 +145,7 @@ struct crypto_algo crypto_algos[] = {
+ .sign = ecc_sign,
+ .add_verify_data = ecc_add_verify_data,
+ .verify = ecc_verify,
++ .add_tkc_data = ecc_add_tkc_data,
+ }
+ };
+
+diff --git a/include/image.h b/include/image.h
+index 3bde55763b..432fd671b8 100644
+--- a/include/image.h
++++ b/include/image.h
+@@ -913,6 +913,7 @@ int booti_setup(ulong image, ulong *relocated_addr, ulong *size,
+
+ #define FIT_IMAGES_PATH "/images"
+ #define FIT_CONFS_PATH "/configurations"
++#define FIT_TKC_PATH "/trusted-key-certificate"
+
+ /* hash/signature node */
+ #define FIT_HASH_NODENAME "hash"
+@@ -946,6 +947,12 @@ int booti_setup(ulong image, ulong *relocated_addr, ulong *size,
+ #define FIT_FIRMWARE_PROP "firmware"
+ #define FIT_STANDALONE_PROP "standalone"
+
++/* trusted-key-certificate node */
++#define FIT_TKC_SIGN_PROP "sign-value"
++#define FIT_TKC_NODENAME "trusted-key-certificate"
++#define FIT_TKC_SIGN_NODENAME "sign-node"
++#define FIT_TKC_KEY_NODENAME "trusted-key"
++
+ #define FIT_MAX_HASH_LEN HASH_MAX_DIGEST_SIZE
+
+ #if IMAGE_ENABLE_FIT
+@@ -1023,11 +1030,12 @@ int fit_set_timestamp(void *fit, int noffset, time_t timestamp);
+ * fit_add_verification_data() - add verification data to FIT image nodes
+ *
+ * @keydir: Directory containing keys
+- * @kwydest: FDT blob to write public key information to
++ * @keydest: FDT blob to write public key information to
+ * @fit: Pointer to the FIT format image header
+ * @comment: Comment to add to signature nodes
+ * @require_keys: Mark all keys as 'required'
+ * @engine_id: Engine to use for signing
++ * @params: Image tool params
+ *
+ * Adds hash values for all component images in the FIT blob.
+ * Hashes are calculated for all component images which have hash subnodes
+@@ -1041,7 +1049,26 @@ int fit_set_timestamp(void *fit, int noffset, time_t timestamp);
+ */
+ int fit_add_verification_data(const char *keydir, void *keydest, void *fit,
+ const char *comment, int require_keys,
+- const char *engine_id);
++ const char *engine_id, const void *params_ptr);
++
++/**
++ * fit_add_tkc_data() - add trusted-key-certificate data to FIT image nodes
++ *
++ * @keydir: Directory containing keys
++ * @keydest: FDT blob to write public key information to
++ * @fit: Pointer to the FIT format image header
++ *
++ * Adds hash values for all component images in the FIT blob.
++ * Hashes are calculated for all component images which have hash subnodes
++ * with algorithm property set to one of the supported hash algorithms.
++ *
++ * Also add signatures if signature nodes are present.
++ *
++ * returns
++ * 0, on success
++ * libfdt error code, on failure
++ */
++int fit_add_tkc_data(const char *keydir, void *keydest, void *fit);
+
+ int fit_image_verify_with_data(const void *fit, int image_noffset,
+ const void *data, size_t size);
+@@ -1122,6 +1149,7 @@ struct image_sign_info {
+ int required_keynode; /* Node offset of key to use: -1=any */
+ const char *require_keys; /* Value for 'required' property */
+ const char *engine_id; /* Engine to use for signing */
++ int tkc_tier_flag; /* TKC tier-1 side flag */
+ };
+ #endif /* Allow struct image_region to always be defined for rsa.h */
+
+@@ -1200,6 +1228,19 @@ struct crypto_algo {
+ int (*verify)(struct image_sign_info *info,
+ const struct image_region region[], int region_count,
+ uint8_t *sig, uint sig_len);
++
++ /**
++ * add_tkc_data() - Add trusted-key-certificate data to FDT
++ *
++ * Add Tier-1 public key information to the FDT node, suitable for
++ * verification at run-time. The information added depends on the
++ * algorithm being used.
++ *
++ * @info: Specifies key and FIT information
++ * @keydest: Destination FDT blob for public key data
++ * @return: 0, on success, -ve on error
++ */
++ int (*add_tkc_data)(struct image_sign_info *info, void *keydest);
+ };
+
+ /**
+diff --git a/include/u-boot/ecc.h b/include/u-boot/ecc.h
+index e3b564effd..b41dadc640 100644
+--- a/include/u-boot/ecc.h
++++ b/include/u-boot/ecc.h
+@@ -60,4 +60,18 @@ int ecc_verify(struct image_sign_info *info,
+ const struct image_region region[], int region_count,
+ uint8_t *sig, uint sig_len);
+
++/**
++ * add_tkc_data() - Add trusted-key-certificate information to FDT
++ *
++ * Add Tier-1 public key information to the FDT node, suitable for
++ * verification at run-time. The information added depends on the
++ * algorithm being used.
++ *
++ * @info: Specifies key and FIT information
++ * @keydest: Destination FDT blob for public key data
++ * @return: 0, on success, -ENOSPC if the keydest FDT blob ran out of space,
++ other -ve value on error
++*/
++int ecc_add_tkc_data(struct image_sign_info *info, void *keydest);
++
+ #endif
+diff --git a/include/u-boot/rsa.h b/include/u-boot/rsa.h
+index 8e780e81b9..ff3478f63a 100644
+--- a/include/u-boot/rsa.h
++++ b/include/u-boot/rsa.h
+@@ -70,7 +70,23 @@ int rsassa_pss_sign(struct image_sign_info *info,
+ other -ve value on error
+ */
+ int rsa_add_verify_data(struct image_sign_info *info, void *keydest);
++
++/**
++ * add_tkc_data() - Add trusted-key-certificate information to FDT
++ *
++ * Add Tier-1 public key information to the FDT node, suitable for
++ * verification at run-time. The information added depends on the
++ * algorithm being used.
++ *
++ * @info: Specifies key and FIT information
++ * @keydest: Destination FDT blob for public key data
++ * @return: 0, on success, -ENOSPC if the keydest FDT blob ran out of space,
++ other -ve value on error
++*/
++int rsa_add_tkc_data(struct image_sign_info *info, void *keydest);
++
+ #else
++
+ static inline int rsa_sign(struct image_sign_info *info,
+ const struct image_region region[], int region_count,
+ uint8_t **sigp, uint *sig_len)
+@@ -90,6 +106,13 @@ static inline int rsa_add_verify_data(struct image_sign_info *info,
+ {
+ return -ENXIO;
+ }
++
++static inline int rsa_add_tkc_data(struct image_sign_info *info,
++ void *keydest)
++{
++ return -ENXIO;
++}
++
+ #endif
+
+ #if IMAGE_ENABLE_VERIFY
+diff --git a/lib/ecc/ecc-sig.c b/lib/ecc/ecc-sig.c
+index 582c69e17a..cae79c8a39 100644
+--- a/lib/ecc/ecc-sig.c
++++ b/lib/ecc/ecc-sig.c
+@@ -104,31 +104,31 @@ static EC_KEY *pkey_get_eckey(EVP_PKEY *key, EC_KEY **eckey)
+ static int ec_pem_get_priv_key(const char *keydir, const char *name,
+ EC_KEY **ecp)
+ {
+- char path[1024];
+- EC_KEY *ec;
+- FILE *f;
+- EVP_PKEY *pktmp;
+-
+- *ecp = NULL;
+- snprintf(path, sizeof(path), "%s/%s_priv.key", keydir, name);
+- f = fopen(path, "r");
+- if (!f) {
+- fprintf(stderr, "Couldn't open EC private key: '%s': %s\n",
+- path, strerror(errno));
+- return -ENOENT;
+- }
+-
+- pktmp = PEM_read_PrivateKey(f, 0, NULL, path);
+- ec = pkey_get_eckey(pktmp, ecp);
+- if (!ec) {
+- fprintf(stderr, "Failure reading EC private key\n");
+- fclose(f);
+- return -EPROTO;
+- }
+- fclose(f);
+- *ecp = ec;
+-
+- return 0;
++ char path[1024];
++ EC_KEY *ec;
++ FILE *f;
++ EVP_PKEY *pktmp;
++
++ *ecp = NULL;
++ snprintf(path, sizeof(path), "%s/%s_priv.key", keydir, name);
++ f = fopen(path, "r");
++ if (!f) {
++ fprintf(stderr, "Couldn't open EC private key: '%s': %s\n",
++ path, strerror(errno));
++ return -ENOENT;
++ }
++
++ pktmp = PEM_read_PrivateKey(f, 0, NULL, path);
++ ec = pkey_get_eckey(pktmp, ecp);
++ if (!ec) {
++ fprintf(stderr, "Failure reading EC private key\n");
++ fclose(f);
++ return -EPROTO;
++ }
++ fclose(f);
++ *ecp = ec;
++
++ return 0;
+ }
+
+ /**
+@@ -185,7 +185,11 @@ int ecc_add_verify_data(struct image_sign_info *info, void *keydest)
+ int bits;
+
+ // get public key
+- ret = ec_pem_get_pub_key(info->keydir, info->keyname, &pub_key);
++ if (info->tkc_tier_flag) {
++ ret = ec_pem_get_pub_key(info->keydir, "oem", &pub_key);
++ } else {
++ ret = ec_pem_get_pub_key(info->keydir, info->keyname, &pub_key);
++ }
+
+ if (ret)
+ goto err_get_pub_key;
+@@ -244,10 +248,47 @@ done:
+
+ err_get_pub_key:
+
+-
+ return ret;
+ }
+
++static int ec_init(void)
++{
++ int ret;
++
++#if OPENSSL_VERSION_NUMBER < 0x10100000L
++ ret = SSL_library_init();
++#else
++ ret = OPENSSL_init_ssl(0, NULL);
++#endif
++ if (!ret) {
++ fprintf(stderr, "Failure to init SSL library\n");
++ return -1;
++ }
++#if OPENSSL_VERSION_NUMBER < 0x10100000L
++ SSL_load_error_strings();
++
++ OpenSSL_add_all_algorithms();
++ OpenSSL_add_all_digests();
++ OpenSSL_add_all_ciphers();
++#endif
++
++ return 0;
++}
++
++static void ec_remove(void)
++{
++#if OPENSSL_VERSION_NUMBER < 0x10100000L
++ CRYPTO_cleanup_all_ex_data();
++ ERR_free_strings();
++#ifdef HAVE_ERR_REMOVE_THREAD_STATE
++ ERR_remove_thread_state(NULL);
++#else
++ ERR_remove_state(0);
++#endif
++ EVP_cleanup();
++#endif
++}
++
+ static int ec_sign_with_key(EC_KEY *ec, struct checksum_algo *checksum_algo,
+ const struct image_region region[], int region_count,
+ uint8_t **sigp, uint *sig_size)
+@@ -300,7 +341,6 @@ static int ec_sign_with_key(EC_KEY *ec, struct checksum_algo *checksum_algo,
+ }
+
+ for (i = 0; i < region_count; i++) {
+-
+ if (!EVP_DigestSignUpdate(context, region[i].data, region[i].size)) {
+ fprintf(stderr, "Signing data failed \n");
+ ret = -1;
+@@ -345,6 +385,10 @@ int ecc_sign(struct image_sign_info *info,
+ EC_KEY *ec;
+ int ret = 0;
+
++ ret = ec_init();
++ if (ret)
++ return ret;
++
+ /* To read private key from pem */
+ ret = ec_pem_get_priv_key(info->keydir, info->keyname, &ec);
+
+@@ -364,50 +408,90 @@ int ecc_sign(struct image_sign_info *info,
+ err_sign:
+
+ err_priv:
++ ec_remove();
+
+ return ret;
+ }
+
+-/**
+- * ec_pem_get_pub_key_by_path() - read a public key from a .key file
+- *
+- * @path Path of key file (will have a .key extension)
+- * @pub_key Returns BIGNUM object, or NULL on failure
+- * @return 0 if ok, -ve on error (in which case *pub_key will be set to NULL)
+- */
+-static int ec_pem_get_pub_key_by_path(const char *keydir, const char *name, BIGNUM **pub_key)
++int ecc_add_tkc_data(struct image_sign_info *info, void *keydest)
+ {
+- char path[1024];
+- EC_KEY *ec;
+- FILE *f;
+- unsigned char *pub_k_cp = NULL;
+- int ret;
++ BIGNUM *pub_key;
++ int tkc_parent, sign_node, key_node;
++ int ret=0;
++ int bits;
+
+- snprintf(path, sizeof(path), "%s/tier_public.key", keydir);
+- f = fopen(path, "r");
+- if (!f) {
+- fprintf(stderr, "Couldn't open EC public key: '%s': %s\n",
+- path, strerror(errno));
+- return -ENOENT;
++ // get public key
++ ret = ec_pem_get_pub_key(info->keydir, "tier", &pub_key);
++ if (ret)
++ goto err_get_pub_key;
++
++ // Step 1: detect trusted-key-certificate node
++ // if not found, then create it
++ tkc_parent = fdt_subnode_offset(keydest, 0, FIT_TKC_NODENAME);
++ if (tkc_parent == -FDT_ERR_NOTFOUND) {
++ tkc_parent = fdt_add_subnode(keydest, 0, FIT_TKC_NODENAME);
++ if (tkc_parent < 0) {
++ ret = tkc_parent;
++ if (ret != -FDT_ERR_NOSPACE) {
++ fprintf(stderr, "Couldn't create trusted-key-certificate node: %s\n",
++ fdt_strerror(tkc_parent));
++ }
++ }
+ }
++ if (ret)
++ goto done;
+
+- ec = PEM_read_EC_PUBKEY(f, 0, NULL, path);
++ // Step 2: detect sign-node node
++ // if not found, then create it
++ sign_node = fdt_subnode_offset(keydest, tkc_parent, FIT_TKC_SIGN_NODENAME);
++ if (sign_node == -FDT_ERR_NOTFOUND) {
++ sign_node = fdt_add_subnode(keydest, tkc_parent, FIT_TKC_SIGN_NODENAME);
++ if (sign_node < 0) {
++ ret = sign_node;
++ if (ret != -FDT_ERR_NOSPACE) {
++ fprintf(stderr, "Could not create sign-node subnode: %s\n",
++ fdt_strerror(sign_node));
++ }
++ }
++ }
++ if (ret)
++ goto done;
+
+- if (!ec) {
+- fprintf(stderr, "Failure reading EC public key\n");
+- fclose(f);
+- return -EPROTO;
++ // Step 3: detect trusted-key node
++ // if not found, then create it
++ key_node = fdt_subnode_offset(keydest, sign_node, FIT_TKC_KEY_NODENAME);
++ if (key_node == -FDT_ERR_NOTFOUND) {
++ key_node = fdt_add_subnode(keydest, sign_node, FIT_TKC_KEY_NODENAME);
++ if (key_node < 0) {
++ ret = key_node;
++ if (ret != -FDT_ERR_NOSPACE) {
++ fprintf(stderr, "Could not create trusted-key subnode: %s\n",
++ fdt_strerror(key_node));
++ }
++ }
+ }
+- fclose(f);
++ if (ret)
++ goto done;
+
+- /* Transform from EC_POINT to char */
+- ret = i2o_ECPublicKey(ec, &pub_k_cp);
+- if (ret == 0) {
+- return -1;
+- } else {
+- /* Transform from char to BIGNUM */
+- *pub_key = BN_bin2bn(pub_k_cp, ret , NULL);
++ // start to write key info into key_node
++ if (!ret) {
++ bits = info->crypto->key_len * 16;
++ ret = fdt_add_bignum(keydest, key_node, "ecc,public-key", pub_key, bits);
+ }
+
+- return 0;
++ if (!ret) {
++ if (info->name) {
++ ret = fdt_setprop_string(keydest, key_node, FIT_ALGO_PROP, info->name);
++ }
++ }
++
++done:
++ BN_free(pub_key);
++ if (ret) {
++ ret = ret == -FDT_ERR_NOSPACE ? -ENOSPC : -EIO;
++ }
++
++err_get_pub_key:
++
++ return ret;
+ }
+diff --git a/lib/rsa/rsa-sign.c b/lib/rsa/rsa-sign.c
+index bf1edcb1b8..8cfb7589b6 100644
+--- a/lib/rsa/rsa-sign.c
++++ b/lib/rsa/rsa-sign.c
+@@ -906,7 +906,12 @@ int rsa_add_verify_data(struct image_sign_info *info, void *keydest)
+ if (ret)
+ return ret;
+ }
+- ret = rsa_get_pub_key(info->keydir, info->keyname, e, &rsa);
++
++ if (info->tkc_tier_flag) {
++ ret = rsa_get_pub_key(info->keydir, "oem_public", e, &rsa);
++ } else {
++ ret = rsa_get_pub_key(info->keydir, info->keyname, e, &rsa);
++ }
+ if (ret)
+ goto err_get_pub_key;
+ ret = rsa_get_params(rsa, &exponent, &n0_inv, &modulus, &r_squared);
+@@ -987,3 +992,118 @@ err_get_pub_key:
+
+ return ret;
+ }
++
++int rsa_add_tkc_data(struct image_sign_info *info, void *keydest)
++{
++ BIGNUM *modulus, *r_squared;
++ uint64_t exponent;
++ BIGNUM *n0_inv;
++ int bits;
++ RSA *rsa;
++ ENGINE *e = NULL;
++
++ int tkc_parent, sign_node, key_node;
++ int ret;
++
++ debug("%s: Getting verification data\n", __func__);
++ if (info->engine_id) {
++ ret = rsa_engine_init(info->engine_id, &e);
++ if (ret)
++ return ret;
++ }
++
++ ret = rsa_get_pub_key(info->keydir, "tier_public", e, &rsa);
++ if (ret)
++ goto err_get_pub_key;
++ ret = rsa_get_params(rsa, &exponent, &n0_inv, &modulus, &r_squared);
++ if (ret)
++ goto err_get_params;
++ bits = BN_num_bits(modulus);
++
++ // Step 1: detect trusted-key-certificate node
++ // if not found, then create it
++ tkc_parent = fdt_subnode_offset(keydest, 0, FIT_TKC_NODENAME);
++ if (tkc_parent == -FDT_ERR_NOTFOUND) {
++ tkc_parent = fdt_add_subnode(keydest, 0, FIT_TKC_NODENAME);
++ if (tkc_parent < 0) {
++ ret = tkc_parent;
++ if (ret != -FDT_ERR_NOSPACE) {
++ fprintf(stderr, "Couldn't create trusted-key-certificate node: %s\n",
++ fdt_strerror(tkc_parent));
++ }
++ }
++ }
++ if (ret)
++ goto done;
++
++ // Step 2: detect sign-node node
++ // if not found, then create it
++ sign_node = fdt_subnode_offset(keydest, tkc_parent, FIT_TKC_SIGN_NODENAME);
++ if (sign_node == -FDT_ERR_NOTFOUND) {
++ sign_node = fdt_add_subnode(keydest, tkc_parent, FIT_TKC_SIGN_NODENAME);
++ if (sign_node < 0) {
++ ret = sign_node;
++ if (ret != -FDT_ERR_NOSPACE) {
++ fprintf(stderr, "Could not create sign-node subnode: %s\n",
++ fdt_strerror(sign_node));
++ }
++ }
++ }
++ if (ret)
++ goto done;
++
++ // Step 3: detect trusted-key node
++ // if not found, then create it
++ key_node = fdt_subnode_offset(keydest, sign_node, FIT_TKC_KEY_NODENAME);
++ if (key_node == -FDT_ERR_NOTFOUND) {
++ key_node = fdt_add_subnode(keydest, sign_node, FIT_TKC_KEY_NODENAME);
++ if (key_node < 0) {
++ ret = key_node;
++ if (ret != -FDT_ERR_NOSPACE) {
++ fprintf(stderr, "Could not create trusted-key subnode: %s\n",
++ fdt_strerror(key_node));
++ }
++ }
++ }
++ if (ret)
++ goto done;
++
++ if (!ret)
++ ret = fdt_setprop_u32(keydest, key_node, "rsa,num-bits", bits);
++ if (!ret)
++ ret = fdt_add_bignum(keydest, key_node, "rsa,n0-inverse", n0_inv,
++ 64);
++ if (!ret) {
++ ret = fdt_setprop_u64(keydest, key_node, "rsa,exponent", exponent);
++ }
++ if (!ret) {
++ ret = fdt_add_bignum(keydest, key_node, "rsa,modulus", modulus,
++ bits);
++ }
++ if (!ret) {
++ ret = fdt_add_bignum(keydest, key_node, "rsa,r-squared", r_squared,
++ bits);
++ }
++ if (!ret) {
++ ret = fdt_setprop_string(keydest, key_node, FIT_ALGO_PROP,
++ info->name);
++ }
++ if (!ret && info->require_keys) {
++ ret = fdt_setprop_string(keydest, key_node, "required",
++ info->require_keys);
++ }
++
++done:
++ BN_free(modulus);
++ BN_free(r_squared);
++ BN_free(n0_inv);
++ if (ret)
++ ret = ret == -FDT_ERR_NOSPACE ? -ENOSPC : -EIO;
++err_get_params:
++ RSA_free(rsa);
++err_get_pub_key:
++ if (info->engine_id)
++ rsa_engine_remove(e);
++
++ return ret;
++}
+diff --git a/tools/fit_image.c b/tools/fit_image.c
+index e55a8943e7..d08d42aa27 100644
+--- a/tools/fit_image.c
++++ b/tools/fit_image.c
+@@ -55,11 +55,17 @@ static int fit_add_file_data(struct image_tool_params *params, size_t size_inc,
+ ret = fit_set_timestamp(ptr, 0, time);
+ }
+
++ if (!ret) {
++ if (params->tkc_oem_flag) {
++ ret = fit_add_tkc_data(params->keydir, dest_blob, ptr);
++ }
++ }
++
+ if (!ret) {
+ ret = fit_add_verification_data(params->keydir, dest_blob, ptr,
+ params->comment,
+ params->require_keys,
+- params->engine_id);
++ params->engine_id, params);
+ }
+
+ if (dest_blob) {
+@@ -678,7 +684,7 @@ static int fit_handle_file(struct image_tool_params *params)
+ * would be considerably more complex to implement. Generally a few
+ * steps of this loop is enough to sign with several keys.
+ */
+- for (size_inc = 0; size_inc < 64 * 1024; size_inc += 1024) {
++ for (size_inc = 0; size_inc < 64 * 1024; size_inc += 2048) {
+ ret = fit_add_file_data(params, size_inc, tmpfile);
+ if (!ret || ret != -ENOSPC)
+ break;
+diff --git a/tools/image-host.c b/tools/image-host.c
+index 8e43671714..c5a651e2c1 100644
+--- a/tools/image-host.c
++++ b/tools/image-host.c
+@@ -195,12 +195,14 @@ static int fit_image_setup_sig(struct image_sign_info *info,
+ * @comment: Comment to add to signature nodes
+ * @require_keys: Mark all keys as 'required'
+ * @engine_id: Engine to use for signing
++ * @params: Image tool params
+ * @return 0 if ok, -1 on error
+ */
+ static int fit_image_process_sig(const char *keydir, void *keydest,
+ void *fit, const char *image_name,
+ int noffset, const void *data, size_t size,
+- const char *comment, int require_keys, const char *engine_id)
++ const char *comment, int require_keys, const char *engine_id,
++ const struct image_tool_params *params)
+ {
+ struct image_sign_info info;
+ struct image_region region;
+@@ -240,6 +242,7 @@ static int fit_image_process_sig(const char *keydir, void *keydest,
+
+ /* Get keyname again, as FDT has changed and invalidated our pointer */
+ info.keyname = fdt_getprop(fit, noffset, "key-name-hint", NULL);
++ info.tkc_tier_flag = params->tkc_tier_flag;
+
+ /*
+ * Write the public key into the supplied FDT file; this might fail
+@@ -291,11 +294,12 @@ static int fit_image_process_sig(const char *keydir, void *keydest,
+ * @comment: Comment to add to signature nodes
+ * @require_keys: Mark all keys as 'required'
+ * @engine_id: Engine to use for signing
++ * @params: Image tool params
+ * @return: 0 on success, <0 on failure
+ */
+ int fit_image_add_verification_data(const char *keydir, void *keydest,
+ void *fit, int image_noffset, const char *comment,
+- int require_keys, const char *engine_id)
++ int require_keys, const char *engine_id, const struct image_tool_params *params)
+ {
+ const char *image_name;
+ const void *data;
+@@ -332,7 +336,7 @@ int fit_image_add_verification_data(const char *keydir, void *keydest,
+ strlen(FIT_SIG_NODENAME))) {
+ ret = fit_image_process_sig(keydir, keydest,
+ fit, image_name, noffset, data, size,
+- comment, require_keys, engine_id);
++ comment, require_keys, engine_id, params);
+ }
+ if (ret)
+ return ret;
+@@ -573,7 +577,7 @@ static int fit_config_get_data(void *fit, int conf_noffset, int noffset,
+ static int fit_config_process_sig(const char *keydir, void *keydest,
+ void *fit, const char *conf_name, int conf_noffset,
+ int noffset, const char *comment, int require_keys,
+- const char *engine_id)
++ const char *engine_id, const struct image_tool_params *params)
+ {
+ struct image_sign_info info;
+ const char *node_name;
+@@ -621,6 +625,7 @@ static int fit_config_process_sig(const char *keydir, void *keydest,
+
+ /* Get keyname again, as FDT has changed and invalidated our pointer */
+ info.keyname = fdt_getprop(fit, noffset, "key-name-hint", NULL);
++ info.tkc_tier_flag = params->tkc_tier_flag;
+
+ /* Write the public key into the supplied FDT file */
+ if (keydest) {
+@@ -637,7 +642,8 @@ static int fit_config_process_sig(const char *keydir, void *keydest,
+
+ static int fit_config_add_verification_data(const char *keydir, void *keydest,
+ void *fit, int conf_noffset, const char *comment,
+- int require_keys, const char *engine_id)
++ int require_keys, const char *engine_id,
++ const struct image_tool_params *params)
+ {
+ const char *conf_name;
+ int noffset;
+@@ -656,7 +662,7 @@ static int fit_config_add_verification_data(const char *keydir, void *keydest,
+ strlen(FIT_SIG_NODENAME))) {
+ ret = fit_config_process_sig(keydir, keydest,
+ fit, conf_name, conf_noffset, noffset, comment,
+- require_keys, engine_id);
++ require_keys, engine_id, params);
+ }
+ if (ret)
+ return ret;
+@@ -667,11 +673,12 @@ static int fit_config_add_verification_data(const char *keydir, void *keydest,
+
+ int fit_add_verification_data(const char *keydir, void *keydest, void *fit,
+ const char *comment, int require_keys,
+- const char *engine_id)
++ const char *engine_id, const void *param_ptr)
+ {
+ int images_noffset, confs_noffset;
+ int noffset;
+ int ret;
++ const struct image_tool_params *params = (const struct image_tool_params *)param_ptr;
+
+ /* Find images parent node offset */
+ images_noffset = fdt_path_offset(fit, FIT_IMAGES_PATH);
+@@ -690,7 +697,7 @@ int fit_add_verification_data(const char *keydir, void *keydest, void *fit,
+ * i.e. component image node.
+ */
+ ret = fit_image_add_verification_data(keydir, keydest,
+- fit, noffset, comment, require_keys, engine_id);
++ fit, noffset, comment, require_keys, engine_id, params);
+ if (ret)
+ return ret;
+ }
+@@ -714,7 +721,163 @@ int fit_add_verification_data(const char *keydir, void *keydest, void *fit,
+ ret = fit_config_add_verification_data(keydir, keydest,
+ fit, noffset, comment,
+ require_keys,
+- engine_id);
++ engine_id, params);
++ if (ret) {
++ return ret;
++ }
++ }
++
++ return 0;
++}
++
++/*
++ Only handle the two nodes
++ /trusted-key-certificate/sign-node and
++ /trusted-key-certificate/sign-node/trusted-key
++ Refer to fit_config_check_sig
++*/
++static int fit_tkc_get_hash_data(void *fit,
++ struct image_region **regionp, int *region_countp)
++{
++ int count = 2;
++ char node_name_0[] = "/trusted-key-certificate/sign-node";
++ char node_name_1[] = "/trusted-key-certificate/sign-node/trusted-key";
++ char *node_inc[] = {node_name_0, node_name_1};
++ int max_regions;
++ char path[200];
++ char * const exc_prop[] = {"data"};
++ struct image_region *region;
++
++ /*
++ * Each node can generate one region for each sub-node.
++ */
++ max_regions = 20;
++ struct fdt_region fdt_regions[max_regions];
++
++ /* Get a list of regions to hash */
++ count = fdt_find_regions(fit, node_inc, count,
++ exc_prop, ARRAY_SIZE(exc_prop),
++ fdt_regions, max_regions - 1,
++ path, sizeof(path), 0);
++
++ if (count < 0) {
++ fprintf(stderr, "Failed to hash node\n");
++ return -1;
++ }
++ if (count == 0) {
++ fprintf(stderr, "No data to hash\n");
++ return -1;
++ }
++ if (count >= max_regions - 1) {
++ fprintf(stderr, "Too many hash regions\n");
++ return -1;
++ }
++
++ /* Build our list of data blocks */
++ region = fit_region_make_list(fit, fdt_regions, count, NULL);
++ if (!region) {
++ printf("Out of memory hashing TKC node\n");
++ return -ENOMEM;
++ }
++
++ *region_countp = count;
++ *regionp = region;
++
++ return 0;
++}
++
++static int fit_tkc_add_verification_data(const char *keydir, void *keydest,
++ void *fit, int tkc_noffset, struct image_sign_info *info)
++{
++ int noffset;
++ int ret = 0;
++ struct image_region *region = NULL;
++ int region_count;
++ uint8_t *value;
++ uint value_len;
++
++ /* If there are no keys, we can't sign configurations */
++ if (!IMAGE_ENABLE_SIGN || !keydir) {
++ return 0;
++ }
++
++ /* Process all subnodes of the sign-node node */
++ for (noffset = fdt_first_subnode(fit, tkc_noffset);
++ noffset >= 0;
++ noffset = fdt_next_subnode(fit, noffset)) {
++ const char *node_name;
++
++ node_name = fit_get_name(fit, noffset, NULL);
++
++ if (!strncmp(node_name, FIT_TKC_KEY_NODENAME,
++ strlen(FIT_TKC_KEY_NODENAME))) {
++ if (keydest) {
++ ret = info->crypto->add_tkc_data(info, keydest);
++ }
++ }
++
++ if (ret) {
++ printf("Can't add TKC data\n");
++ return ret;
++ }
++ }
++
++ /* Calculate the hash of
++ /trusted-key-certificate/sign-node and
++ /trusted-key-certificate/sign-node/trusted-key */
++ /* Sign */
++ ret = fit_tkc_get_hash_data(fit, ®ion, ®ion_count);
++ if (ret) {
++ printf("Can't get TKC hash data\n");
++ return ret;
++ }
++
++ ret = info->crypto->sign(info, region, region_count, &value, &value_len);
++ if (ret) {
++ printf("Can't sign TKC node\n");
++ return ret;
++ }
++
++ /* Put into /trusted-key-certificate/ */
++ if (keydest) {
++ // keydest. The sign-value is not the final one.
++ noffset = fdt_subnode_offset(keydest, 0, FIT_TKC_NODENAME);
++ ret = fdt_setprop(keydest, noffset, FIT_TKC_SIGN_PROP, value, value_len);
++ } else {
++ // Write to fit
++ noffset = fdt_subnode_offset(fit, 0, FIT_TKC_NODENAME);
++ ret = fdt_setprop(fit, noffset, FIT_TKC_SIGN_PROP, value, value_len);
++ }
++
++ free(value);
++ free(region);
++
++ if (ret) {
++ printf("Can't write TKC sign\n");
++ return ret;
++ }
++
++ return ret;
++}
++
++static int fit_config_get_sign_info(const char *keydir,
++ void *fit, int conf_noffset, struct image_sign_info *info)
++{
++ int noffset;
++
++ /* Process all hash subnodes of the configuration node */
++ for (noffset = fdt_first_subnode(fit, conf_noffset);
++ noffset >= 0;
++ noffset = fdt_next_subnode(fit, noffset)) {
++ const char *node_name;
++ int ret = 0;
++
++ node_name = fit_get_name(fit, noffset, NULL);
++ if (!strncmp(node_name, FIT_SIG_NODENAME,
++ strlen(FIT_SIG_NODENAME))) {
++ ret = fit_image_setup_sig(info, keydir, fit, node_name, noffset,
++ NULL, NULL);
++ }
+ if (ret)
+ return ret;
+ }
+@@ -722,6 +885,55 @@ int fit_add_verification_data(const char *keydir, void *keydest, void *fit,
+ return 0;
+ }
+
++int fit_add_tkc_data(const char *keydir, void *keydest, void *fit)
++{
++ struct image_sign_info info;
++ int tkc_noffset, confs_noffset;
++ int noffset;
++ int ret;
++
++ /* Find configurations parent node offset */
++ confs_noffset = fdt_path_offset(fit, FIT_CONFS_PATH);
++ if (confs_noffset < 0) {
++ printf("Can't find configurations parent node '%s' (%s)\n",
++ FIT_CONFS_PATH, fdt_strerror(confs_noffset));
++ return -ENOENT;
++ }
++
++ /* Find trusted-key-certificate parent node offset */
++ tkc_noffset = fdt_path_offset(fit, FIT_TKC_PATH);
++ if (tkc_noffset < 0) {
++ printf("Can't find TKC parent node '%s' (%s)\n",
++ FIT_TKC_PATH, fdt_strerror(tkc_noffset));
++ return -ENOENT;
++ }
++
++ /* To get info from configuration */
++ /* Process its subnodes, print out component images details */
++ for (noffset = fdt_first_subnode(fit, confs_noffset);
++ noffset >= 0;
++ noffset = fdt_next_subnode(fit, noffset)) {
++ ret = fit_config_get_sign_info(keydir,
++ fit, noffset, &info);
++ if (ret) {
++ return ret;
++ }
++ }
++
++ /* Process its subnodes, print out component details */
++ for (noffset = fdt_first_subnode(fit, tkc_noffset);
++ noffset >= 0;
++ noffset = fdt_next_subnode(fit, noffset)) {
++ ret = fit_tkc_add_verification_data(keydir, keydest,
++ fit, noffset, &info);
++ if (ret) {
++ return ret;
++ }
++ }
++
++ return 0;
++}
++
+ #ifdef CONFIG_FIT_SIGNATURE
+ int fit_check_sign(const void *fit, const void *key)
+ {
+diff --git a/tools/imagetool.h b/tools/imagetool.h
+index d191b9cfe7..f99aa02313 100644
+--- a/tools/imagetool.h
++++ b/tools/imagetool.h
+@@ -77,6 +77,10 @@ struct image_tool_params {
+ bool quiet; /* Don't output text in normal operation */
+ unsigned int external_offset; /* Add padding to external data */
+ const char *engine_id; /* Engine to use for signing */
++ int tkc_oem_flag; /* Handle in OEM part */
++ int tkc_tier_flag; /* Handle in Tier-1 part */
++ char *tkc_oem_pubkey_file; /* TKC: Tier-1 need the public key of OEM */
++ char *tkc_tier_pubkey_file; /* TKC: OEM need the public key of Tier-1 */
+ };
+
+ /*
+diff --git a/tools/mkimage.c b/tools/mkimage.c
+index e0d4d20be4..1d15adb2a1 100644
+--- a/tools/mkimage.c
++++ b/tools/mkimage.c
+@@ -97,7 +97,7 @@ static void usage(const char *msg)
+ " -i => input filename for ramdisk file\n");
+ #ifdef CONFIG_FIT_SIGNATURE
+ fprintf(stderr,
+- "Signing / verified boot options: [-E] [-k keydir] [-K dtb] [ -c <comment>] [-p addr] [-r] [-N engine]\n"
++ "Signing / verified boot options: [-E] [-k keydir] [-K dtb] [ -c <comment>] [-p addr] [-r] [-N engine] [-g Tier_pubkey] [-u OEM_pubkey]\n"
+ " -E => place data outside of the FIT structure\n"
+ " -k => set directory containing private keys\n"
+ " -K => write public keys to this .dtb file\n"
+@@ -105,7 +105,9 @@ static void usage(const char *msg)
+ " -F => re-sign existing FIT image\n"
+ " -p => place external data at a static position\n"
+ " -r => mark keys used as 'required' in dtb\n"
+- " -N => engine to use for signing (pkcs11)\n");
++ " -N => engine to use for signing (pkcs11)\n"
++ " -g => indicate to handle TKC in OEM part\n"
++ " -u => indicate to handle TKC in Tier-1 part\n");
+ #else
+ fprintf(stderr,
+ "Signing / verified boot not supported (CONFIG_FIT_SIGNATURE undefined)\n");
+@@ -143,7 +145,7 @@ static void process_args(int argc, char **argv)
+ int opt;
+
+ while ((opt = getopt(argc, argv,
+- "a:A:b:c:C:d:D:e:Ef:Fk:i:K:ln:N:p:O:rR:qsT:vVx")) != -1) {
++ "a:A:b:c:C:d:D:e:Ef:Fk:g:i:K:ln:N:p:O:rR:qsT:u:vVx")) != -1) {
+ switch (opt) {
+ case 'a':
+ params.addr = strtoull(optarg, &ptr, 16);
+@@ -209,6 +211,10 @@ static void process_args(int argc, char **argv)
+ params.type = IH_TYPE_FLATDT;
+ params.fflag = 1;
+ break;
++ case 'g':
++ params.tkc_oem_flag = 1;
++ params.tkc_tier_pubkey_file = optarg;
++ break;
+ case 'i':
+ params.fit_ramdisk = optarg;
+ break;
+@@ -269,6 +275,10 @@ static void process_args(int argc, char **argv)
+ usage("Invalid image type");
+ }
+ break;
++ case 'u':
++ params.tkc_tier_flag = 1;
++ params.tkc_oem_pubkey_file = optarg;
++ break;
+ case 'v':
+ params.vflag++;
+ break;
+--
+2.18.0
+
diff --git a/meta/meta-mediatek-gpl/recipes-bsp/u-boot/u-boot-mkimage-2018.07/0001-tools-image-add-configurations-node-to-hashed-node.patch b/meta/meta-mediatek-gpl/recipes-bsp/u-boot/u-boot-mkimage-2018.07/0001-tools-image-add-configurations-node-to-hashed-node.patch
new file mode 100644
index 0000000..943f3c3
--- /dev/null
+++ b/meta/meta-mediatek-gpl/recipes-bsp/u-boot/u-boot-mkimage-2018.07/0001-tools-image-add-configurations-node-to-hashed-node.patch
@@ -0,0 +1,128 @@
+From 46017bf4b1c21a301cf2640051d2cc3df8b899dd Mon Sep 17 00:00:00 2001
+From: Jimmy Huang <jimmy.huang@mediatek.com>
+Date: Wed, 27 May 2020 13:39:27 +0800
+Subject: [PATCH] tools: image: add /configurations node to hashed-node
+
+To fix fit signature bypass problem.
+---
+ tools/image-host.c | 12 ++++++++----
+ tools/imagetool.h | 1 +
+ tools/mkimage.c | 23 +++++++++++++++++++++++
+ 3 files changed, 32 insertions(+), 4 deletions(-)
+
+diff --git a/tools/image-host.c b/tools/image-host.c
+index c5a651e2c1..f9f11b2730 100644
+--- a/tools/image-host.c
++++ b/tools/image-host.c
+@@ -400,7 +400,8 @@ static const char *fit_config_get_image_list(void *fit, int noffset,
+ }
+
+ static int fit_config_get_hash_list(void *fit, int conf_noffset,
+- int sig_offset, struct strlist *node_inc)
++ int sig_offset, struct strlist *node_inc,
++ const struct image_tool_params *params)
+ {
+ int allow_missing;
+ const char *prop, *iname, *end;
+@@ -419,6 +420,7 @@ static int fit_config_get_hash_list(void *fit, int conf_noffset,
+ strlist_init(node_inc);
+ snprintf(name, sizeof(name), "%s/%s", FIT_CONFS_PATH, conf_name);
+ if (strlist_add(node_inc, "/") ||
++ (params->brom_flag && strlist_add(node_inc, FIT_CONFS_PATH)) ||
+ strlist_add(node_inc, name))
+ goto err_mem;
+
+@@ -504,7 +506,8 @@ err_path:
+
+ static int fit_config_get_data(void *fit, int conf_noffset, int noffset,
+ struct image_region **regionp, int *region_countp,
+- char **region_propp, int *region_proplen)
++ char **region_propp, int *region_proplen,
++ const struct image_tool_params *params)
+ {
+ char * const exc_prop[] = {"data"};
+ struct strlist node_inc;
+@@ -521,7 +524,8 @@ static int fit_config_get_data(void *fit, int conf_noffset, int noffset,
+ debug("%s: conf='%s', sig='%s'\n", __func__, conf_name, sig_name);
+
+ /* Get a list of nodes we want to hash */
+- ret = fit_config_get_hash_list(fit, conf_noffset, noffset, &node_inc);
++ ret = fit_config_get_hash_list(fit, conf_noffset, noffset, &node_inc,
++ params);
+ if (ret)
+ return ret;
+
+@@ -591,7 +595,7 @@ static int fit_config_process_sig(const char *keydir, void *keydest,
+
+ node_name = fit_get_name(fit, noffset, NULL);
+ if (fit_config_get_data(fit, conf_noffset, noffset, ®ion,
+- ®ion_count, ®ion_prop, ®ion_proplen))
++ ®ion_count, ®ion_prop, ®ion_proplen, params))
+ return -1;
+
+ if (fit_image_setup_sig(&info, keydir, fit, conf_name, noffset,
+diff --git a/tools/imagetool.h b/tools/imagetool.h
+index f99aa02313..265279dd16 100644
+--- a/tools/imagetool.h
++++ b/tools/imagetool.h
+@@ -75,6 +75,7 @@ struct image_tool_params {
+ struct content_info *content_tail;
+ bool external_data; /* Store data outside the FIT */
+ bool quiet; /* Don't output text in normal operation */
++ bool brom_flag; /* Make FIT for bootrom */
+ unsigned int external_offset; /* Add padding to external data */
+ const char *engine_id; /* Engine to use for signing */
+ int tkc_oem_flag; /* Handle in OEM part */
+diff --git a/tools/mkimage.c b/tools/mkimage.c
+index 1d15adb2a1..fc517ff7ac 100644
+--- a/tools/mkimage.c
++++ b/tools/mkimage.c
+@@ -10,8 +10,12 @@
+ #include "mkimage.h"
+ #include "imximage.h"
+ #include <image.h>
++#include <libgen.h>
++#include <string.h>
+ #include <version.h>
+
++const char *brom_mkimage_basename = "brom-mkimage";
++
+ static void copy_file(int, const char *, int);
+
+ /* parameters initialized by core will be used by the image type code */
+@@ -144,6 +148,23 @@ static void process_args(int argc, char **argv)
+ char *datafile = NULL;
+ int opt;
+
++ /*
++ * If the base name of the program is "brom-mkimage", set brom_flag to
++ * indicate special handling is needed for the fit image
++ */
++ ptr = strdup(params.cmdname);
++ if (ptr) {
++ char *bname = basename(ptr);
++ if (strncmp(brom_mkimage_basename, bname, strlen(bname)) == 0)
++ params.brom_flag = true;
++ free(ptr);
++ ptr = NULL;
++ } else {
++ fprintf(stderr, "%s: not enough memory for strdup '%s'\n",
++ params.cmdname, params.cmdname);
++ exit(EXIT_FAILURE);
++ }
++
+ while ((opt = getopt(argc, argv,
+ "a:A:b:c:C:d:D:e:Ef:Fk:g:i:K:ln:N:p:O:rR:qsT:u:vVx")) != -1) {
+ switch (opt) {
+@@ -283,6 +304,8 @@ static void process_args(int argc, char **argv)
+ params.vflag++;
+ break;
+ case 'V':
++ if (params.brom_flag)
++ printf("Image tool for BL2 FIT construction\n");
+ printf("mkimage version %s\n", PLAIN_VERSION);
+ exit(EXIT_SUCCESS);
+ case 'x':
+--
+2.18.0
+
diff --git a/meta/meta-mediatek-gpl/recipes-bsp/u-boot/u-boot-mkimage-2018.07/0002-rsa-add-sha-256-384-512-rsassa-pss-2048-3072-4096-al.patch b/meta/meta-mediatek-gpl/recipes-bsp/u-boot/u-boot-mkimage-2018.07/0002-rsa-add-sha-256-384-512-rsassa-pss-2048-3072-4096-al.patch
new file mode 100644
index 0000000..7f938ff
--- /dev/null
+++ b/meta/meta-mediatek-gpl/recipes-bsp/u-boot/u-boot-mkimage-2018.07/0002-rsa-add-sha-256-384-512-rsassa-pss-2048-3072-4096-al.patch
@@ -0,0 +1,201 @@
+From d845b812163342d33643fc194f2be57bfa09fcb7 Mon Sep 17 00:00:00 2001
+From: Jimmy Huang <jimmy.huang@mediatek.com>
+Date: Tue, 2 Oct 2018 06:53:55 +0000
+Subject: [PATCH 2/3] rsa: add sha{256,384,512},rsassa-pss{2048,3072,4096}
+ algorithms
+
+Add support for "sha256,rsassa-pss2048", "sha256,rsassa-pss3072",
+"sha384,rsassa-pss2048", "sha384,rsassa-pss3072",
+"sha384,rsassa-pss4096", "sha512,rsassa-pss2048",
+"sha512,rsassa-pss3072", and "sha512,rsassa-pss4096" signatures in
+u-boot.
+---
+ common/image-sig.c | 21 ++++++++++++
+ include/u-boot/rsa.h | 11 +++++++
+ lib/rsa/rsa-sign.c | 76 +++++++++++++++++++++++++++++++++++++++++---
+ 3 files changed, 103 insertions(+), 5 deletions(-)
+
+diff --git a/common/image-sig.c b/common/image-sig.c
+index aab3a60de2..acbd1297e4 100644
+--- a/common/image-sig.c
++++ b/common/image-sig.c
+@@ -94,6 +94,27 @@ struct crypto_algo crypto_algos[] = {
+ .sign = rsa_sign,
+ .add_verify_data = rsa_add_verify_data,
+ .verify = rsa_verify,
++ },
++ {
++ .name = "rsassa-pss2048",
++ .key_len = RSA2048_BYTES,
++ .sign = rsassa_pss_sign,
++ .add_verify_data = rsa_add_verify_data,
++ .verify = rsa_verify,
++ },
++ {
++ .name = "rsassa-pss3072",
++ .key_len = RSA3072_BYTES,
++ .sign = rsassa_pss_sign,
++ .add_verify_data = rsa_add_verify_data,
++ .verify = rsa_verify,
++ },
++ {
++ .name = "rsassa-pss4096",
++ .key_len = RSA4096_BYTES,
++ .sign = rsassa_pss_sign,
++ .add_verify_data = rsa_add_verify_data,
++ .verify = rsa_verify,
+ }
+
+ };
+diff --git a/include/u-boot/rsa.h b/include/u-boot/rsa.h
+index 69aff97fdf..8e780e81b9 100644
+--- a/include/u-boot/rsa.h
++++ b/include/u-boot/rsa.h
+@@ -53,6 +53,10 @@ int rsa_sign(struct image_sign_info *info,
+ const struct image_region region[],
+ int region_count, uint8_t **sigp, uint *sig_len);
+
++int rsassa_pss_sign(struct image_sign_info *info,
++ const struct image_region region[],
++ int region_count, uint8_t **sigp, uint *sig_len);
++
+ /**
+ * add_verify_data() - Add verification information to FDT
+ *
+@@ -74,6 +78,13 @@ static inline int rsa_sign(struct image_sign_info *info,
+ return -ENXIO;
+ }
+
++static inline int rsassa_pss_sign(struct image_sign_info *info,
++ const struct image_region region[], int region_count,
++ uint8_t *sigp, uint *sig_len)
++{
++ return -ENXIO;
++}
++
+ static inline int rsa_add_verify_data(struct image_sign_info *info,
+ void *keydest)
+ {
+diff --git a/lib/rsa/rsa-sign.c b/lib/rsa/rsa-sign.c
+index cfe09cc94c..83ec44bf73 100644
+--- a/lib/rsa/rsa-sign.c
++++ b/lib/rsa/rsa-sign.c
+@@ -384,9 +384,10 @@ static void rsa_engine_remove(ENGINE *e)
+
+ static int rsa_sign_with_key(RSA *rsa, struct checksum_algo *checksum_algo,
+ const struct image_region region[], int region_count,
+- uint8_t **sigp, uint *sig_size)
++ uint8_t **sigp, uint *sig_size, int pad)
+ {
+ EVP_PKEY *key;
++ EVP_PKEY_CTX *keyctx;
+ EVP_MD_CTX *context;
+ int size, ret = 0;
+ uint8_t *sig;
+@@ -401,6 +402,12 @@ static int rsa_sign_with_key(RSA *rsa, struct checksum_algo *checksum_algo,
+ goto err_set;
+ }
+
++ keyctx = EVP_PKEY_CTX_new(key, NULL);
++ if (!keyctx) {
++ ret = rsa_err("EVP_PKEY_CTX object creation failed");
++ goto err_set;
++ }
++
+ size = EVP_PKEY_size(key);
+ sig = malloc(size);
+ if (!sig) {
+@@ -416,19 +423,34 @@ static int rsa_sign_with_key(RSA *rsa, struct checksum_algo *checksum_algo,
+ goto err_create;
+ }
+ EVP_MD_CTX_init(context);
+- if (!EVP_SignInit(context, checksum_algo->calculate_sign())) {
++ if (!EVP_DigestSignInit(context, &keyctx,
++ checksum_algo->calculate_sign(), NULL, key)) {
+ ret = rsa_err("Signer setup failed");
+ goto err_sign;
+ }
+
++ if (pad == RSA_PKCS1_PSS_PADDING) {
++ if (!EVP_PKEY_CTX_set_rsa_padding(keyctx,
++ RSA_PKCS1_PSS_PADDING)) {
++ ret = rsa_err("EVP key setup padding failed");
++ goto err_set;
++ }
++
++ if (!EVP_PKEY_CTX_set_rsa_pss_saltlen(keyctx, -1)) {
++ ret = rsa_err("EVP key setup saltlen failed");
++ goto err_set;
++ }
++ }
++
+ for (i = 0; i < region_count; i++) {
+- if (!EVP_SignUpdate(context, region[i].data, region[i].size)) {
++ if (!EVP_DigestSignUpdate(context, region[i].data,
++ region[i].size)) {
+ ret = rsa_err("Signing data failed");
+ goto err_sign;
+ }
+ }
+
+- if (!EVP_SignFinal(context, sig, sig_size, key)) {
++ if (!EVP_DigestSignFinal(context, sig, (size_t *)sig_size)) {
+ ret = rsa_err("Could not obtain signature");
+ goto err_sign;
+ }
+@@ -478,7 +500,51 @@ int rsa_sign(struct image_sign_info *info,
+ if (ret)
+ goto err_priv;
+ ret = rsa_sign_with_key(rsa, info->checksum, region,
+- region_count, sigp, sig_len);
++ region_count, sigp, sig_len, RSA_PKCS1_PADDING);
++ if (ret)
++ goto err_sign;
++
++ RSA_free(rsa);
++ if (info->engine_id)
++ rsa_engine_remove(e);
++ rsa_remove();
++
++ return ret;
++
++err_sign:
++ RSA_free(rsa);
++err_priv:
++ if (info->engine_id)
++ rsa_engine_remove(e);
++err_engine:
++ rsa_remove();
++ return ret;
++}
++
++int rsassa_pss_sign(struct image_sign_info *info,
++ const struct image_region region[], int region_count,
++ uint8_t **sigp, uint *sig_len)
++{
++ RSA *rsa;
++ ENGINE *e = NULL;
++ int ret;
++
++ ret = rsa_init();
++ if (ret)
++ return ret;
++
++ if (info->engine_id) {
++ ret = rsa_engine_init(info->engine_id, &e);
++ if (ret)
++ goto err_engine;
++ }
++
++ ret = rsa_get_priv_key(info->keydir, info->keyname, e, &rsa);
++ if (ret)
++ goto err_priv;
++ ret = rsa_sign_with_key(rsa, info->checksum, region,
++ region_count, sigp, sig_len,
++ RSA_PKCS1_PSS_PADDING);
+ if (ret)
+ goto err_sign;
+
+--
+2.17.1
+
diff --git a/meta/meta-mediatek-gpl/recipes-bsp/u-boot/u-boot-mkimage-2018.07/0003-rsa-extend-bits-of-n0-inverse.patch b/meta/meta-mediatek-gpl/recipes-bsp/u-boot/u-boot-mkimage-2018.07/0003-rsa-extend-bits-of-n0-inverse.patch
new file mode 100644
index 0000000..017409e
--- /dev/null
+++ b/meta/meta-mediatek-gpl/recipes-bsp/u-boot/u-boot-mkimage-2018.07/0003-rsa-extend-bits-of-n0-inverse.patch
@@ -0,0 +1,118 @@
+From eaf345a7a4b74ee12970cb44718b31793d10235f Mon Sep 17 00:00:00 2001
+From: Jimmy Huang <jimmy.huang@mediatek.com>
+Date: Tue, 2 Oct 2018 09:04:49 +0000
+Subject: [PATCH 3/3] rsa: extend bits of n0-inverse
+
+Extend "rsa,n0-inverse" property to 64 bits.
+---
+ lib/rsa/rsa-sign.c | 39 +++++++++++++++++++++------------------
+ 1 file changed, 21 insertions(+), 18 deletions(-)
+
+diff --git a/lib/rsa/rsa-sign.c b/lib/rsa/rsa-sign.c
+index 83ec44bf73..9bf625bf2a 100644
+--- a/lib/rsa/rsa-sign.c
++++ b/lib/rsa/rsa-sign.c
+@@ -617,11 +617,11 @@ cleanup:
+ /*
+ * rsa_get_params(): - Get the important parameters of an RSA public key
+ */
+-int rsa_get_params(RSA *key, uint64_t *exponent, uint32_t *n0_invp,
++int rsa_get_params(RSA *key, uint64_t *exponent, BIGNUM **n0_invp,
+ BIGNUM **modulusp, BIGNUM **r_squaredp)
+ {
+- BIGNUM *big1, *big2, *big32, *big2_32;
+- BIGNUM *n, *r, *r_squared, *tmp;
++ BIGNUM *big1, *big2, *big64, *big2_64;
++ BIGNUM *n0, *n, *r, *r_squared, *tmp;
+ const BIGNUM *key_n;
+ BN_CTX *bn_ctx = BN_CTX_new();
+ int ret = 0;
+@@ -629,14 +629,15 @@ int rsa_get_params(RSA *key, uint64_t *exponent, uint32_t *n0_invp,
+ /* Initialize BIGNUMs */
+ big1 = BN_new();
+ big2 = BN_new();
+- big32 = BN_new();
++ big64 = BN_new();
+ r = BN_new();
+ r_squared = BN_new();
+ tmp = BN_new();
+- big2_32 = BN_new();
++ big2_64 = BN_new();
++ n0 = BN_new();
+ n = BN_new();
+- if (!big1 || !big2 || !big32 || !r || !r_squared || !tmp || !big2_32 ||
+- !n) {
++ if (!big1 || !big2 || !big64 || !r || !r_squared || !tmp || !big2_64 ||
++ !n0 || !n) {
+ fprintf(stderr, "Out of memory (bignum)\n");
+ return -ENOMEM;
+ }
+@@ -646,18 +647,18 @@ int rsa_get_params(RSA *key, uint64_t *exponent, uint32_t *n0_invp,
+
+ RSA_get0_key(key, &key_n, NULL, NULL);
+ if (!BN_copy(n, key_n) || !BN_set_word(big1, 1L) ||
+- !BN_set_word(big2, 2L) || !BN_set_word(big32, 32L))
++ !BN_set_word(big2, 2L) || !BN_set_word(big64, 64L))
+ ret = -1;
+
+- /* big2_32 = 2^32 */
+- if (!BN_exp(big2_32, big2, big32, bn_ctx))
++ /* big2_64 = 2^64 */
++ if (!BN_exp(big2_64, big2, big64, bn_ctx))
+ ret = -1;
+
+- /* Calculate n0_inv = -1 / n[0] mod 2^32 */
+- if (!BN_mod_inverse(tmp, n, big2_32, bn_ctx) ||
+- !BN_sub(tmp, big2_32, tmp))
++ /* Calculate n0_inv = -1 / n[0] mod 2^64 */
++ if (!BN_mod_inverse(n0, n, big2_64, bn_ctx) ||
++ !BN_sub(n0, big2_64, n0))
+ ret = -1;
+- *n0_invp = BN_get_word(tmp);
++ *n0_invp = n0;
+
+ /* Calculate R = 2^(# of key bits) */
+ if (!BN_set_word(tmp, BN_num_bits(n)) ||
+@@ -675,10 +676,10 @@ int rsa_get_params(RSA *key, uint64_t *exponent, uint32_t *n0_invp,
+
+ BN_free(big1);
+ BN_free(big2);
+- BN_free(big32);
++ BN_free(big64);
+ BN_free(r);
+ BN_free(tmp);
+- BN_free(big2_32);
++ BN_free(big2_64);
+ if (ret) {
+ fprintf(stderr, "Bignum operations failed\n");
+ return -ENOMEM;
+@@ -755,7 +756,7 @@ int rsa_add_verify_data(struct image_sign_info *info, void *keydest)
+ {
+ BIGNUM *modulus, *r_squared;
+ uint64_t exponent;
+- uint32_t n0_inv;
++ BIGNUM *n0_inv;
+ int parent, node;
+ char name[100];
+ int ret;
+@@ -815,7 +816,8 @@ int rsa_add_verify_data(struct image_sign_info *info, void *keydest)
+ if (!ret)
+ ret = fdt_setprop_u32(keydest, node, "rsa,num-bits", bits);
+ if (!ret)
+- ret = fdt_setprop_u32(keydest, node, "rsa,n0-inverse", n0_inv);
++ ret = fdt_add_bignum(keydest, node, "rsa,n0-inverse", n0_inv,
++ 64);
+ if (!ret) {
+ ret = fdt_setprop_u64(keydest, node, "rsa,exponent", exponent);
+ }
+@@ -838,6 +840,7 @@ int rsa_add_verify_data(struct image_sign_info *info, void *keydest)
+ done:
+ BN_free(modulus);
+ BN_free(r_squared);
++ BN_free(n0_inv);
+ if (ret)
+ ret = ret == -FDT_ERR_NOSPACE ? -ENOSPC : -EIO;
+ err_get_params:
+--
+2.17.1
+
diff --git a/meta/meta-mediatek-gpl/recipes-bsp/u-boot/u-boot-mkimage-common.inc b/meta/meta-mediatek-gpl/recipes-bsp/u-boot/u-boot-mkimage-common.inc
new file mode 100644
index 0000000..bb82b1e
--- /dev/null
+++ b/meta/meta-mediatek-gpl/recipes-bsp/u-boot/u-boot-mkimage-common.inc
@@ -0,0 +1,27 @@
+SUMMARY = "U-Boot bootloader image creation tool"
+DEPENDS += "openssl"
+
+PATCHTOOL = "git"
+
+EXTRA_OEMAKE_class-target = 'CROSS_COMPILE="${TARGET_PREFIX}" CC="${CC} ${CFLAGS} ${LDFLAGS}" HOSTCC="${BUILD_CC} ${BUILD_CFLAGS} ${BUILD_LDFLAGS}" STRIP=true V=1'
+EXTRA_OEMAKE_class-native = 'CC="${BUILD_CC} ${BUILD_CFLAGS} ${BUILD_LDFLAGS}" HOSTCC="${BUILD_CC} ${BUILD_CFLAGS} ${BUILD_LDFLAGS}" STRIP=true V=1'
+EXTRA_OEMAKE_class-nativesdk = 'CROSS_COMPILE="${HOST_PREFIX}" CC="${CC} ${CFLAGS} ${LDFLAGS}" HOSTCC="${BUILD_CC} ${BUILD_CFLAGS} ${BUILD_LDFLAGS}" STRIP=true V=1'
+
+do_compile () {
+ oe_runmake sandbox_defconfig
+
+ # Disable CONFIG_CMD_LICENSE, license.h is not used by tools and
+ # generating it requires bin2header tool, which for target build
+ # is built with target tools and thus cannot be executed on host.
+ sed -i "s/CONFIG_CMD_LICENSE=.*/# CONFIG_CMD_LICENSE is not set/" .config
+
+ oe_runmake cross_tools NO_SDL=1
+}
+
+do_install () {
+ install -d ${D}${bindir}
+ install -m 0755 tools/mkimage ${D}${bindir}/uboot-mkimage
+ ln -sf uboot-mkimage ${D}${bindir}/mkimage
+}
+
+BBCLASSEXTEND = "native nativesdk"
diff --git a/meta/meta-mediatek-gpl/recipes-bsp/u-boot/u-boot-mkimage_2016.11.bb b/meta/meta-mediatek-gpl/recipes-bsp/u-boot/u-boot-mkimage_2016.11.bb
new file mode 100644
index 0000000..9fdb4e1
--- /dev/null
+++ b/meta/meta-mediatek-gpl/recipes-bsp/u-boot/u-boot-mkimage_2016.11.bb
@@ -0,0 +1,12 @@
+require u-boot-common_${PV}.inc
+require u-boot-mkimage-common.inc
+
+FILESEXTRAPATHS_append := ":${THISDIR}/${PN}-2016.11"
+
+SRC_URI += "file://default-gcc.patch \
+ file://0001-rsa-add-sha-256-384-512-rsa-2048-3072-4096-algorithm.patch \
+ file://0002-rsa-add-sha-256-384-512-rsassa-pss-2048-3072-4096-al.patch \
+ file://0003-rsa-extend-bits-of-n0-inverse.patch \
+ file://0001-libfdt-fix-fdt_find_region-incorrectly-adding-parent.patch \
+ file://0004-security-boot-u-boot-hsm-support.patch \
+"
diff --git a/meta/meta-mediatek-gpl/recipes-bsp/u-boot/u-boot-mkimage_2018.07.bb b/meta/meta-mediatek-gpl/recipes-bsp/u-boot/u-boot-mkimage_2018.07.bb
new file mode 100644
index 0000000..2b57b2d
--- /dev/null
+++ b/meta/meta-mediatek-gpl/recipes-bsp/u-boot/u-boot-mkimage_2018.07.bb
@@ -0,0 +1,14 @@
+require u-boot-common_${PV}.inc
+require u-boot-mkimage-common.inc
+
+SRC_URI += "file://0001-libfdt-fix-fdt_find_regions-incorrectly-adding-paren.patch \
+ file://0001-rsa-add-sha-256-384-512-rsa-2048-3072-4096-algorithm.patch \
+ file://0002-rsa-add-sha-256-384-512-rsassa-pss-2048-3072-4096-al.patch \
+ file://0003-rsa-extend-bits-of-n0-inverse.patch \
+ file://0001-add-u-boot-support-hsm_sign_tool.patch \
+ file://0001-secure-boot-ECC-support.patch \
+ file://0001-support-trusted-key-certificate.patch \
+ file://0001-tools-image-add-configurations-node-to-hashed-node.patch \
+"
+
+RDEPENDS_${PN} += "dtc"
diff --git a/meta/meta-mediatek-gpl/recipes-bsp/u-boot/u-boot_2014.04.bb b/meta/meta-mediatek-gpl/recipes-bsp/u-boot/u-boot_2014.04.bb
new file mode 100644
index 0000000..d570036
--- /dev/null
+++ b/meta/meta-mediatek-gpl/recipes-bsp/u-boot/u-boot_2014.04.bb
@@ -0,0 +1,38 @@
+inherit deploy u-boot-fitimage
+
+UBOOT_SRC = "${TOPDIR}/../src/bsp/u-boot"
+LIC_FILES_CHKSUM = "file://${UBOOT_SRC}/Licenses/README;md5=025bf9f768cbcb1a165dbe1a110babfb"
+PV = "v2014.04-rc1+git+src"
+
+SECTION = "bootloaders"
+PROVIDES = "virtual/bootloader"
+
+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-fit.${UBOOT_SUFFIX}"
+UBOOT_MAKE_TARGET ?= "all"
+
+
+do_compile () {
+ cd ${UBOOT_SRC}
+ make clobber
+ make V=1 -f Makefile
+ cd -
+}
+
+do_deploy () {
+ install -d ${DEPLOYDIR}
+ install ${UBOOT_SRC}/${UBOOT_FIT_IMAGE} ${DEPLOYDIR}/${UBOOT_FIT_IMAGE}
+}
+
+addtask deploy before do_build after do_assemble_fitimage
+
diff --git a/meta/meta-mediatek-gpl/recipes-bsp/u-boot/u-boot_2016.11.bb b/meta/meta-mediatek-gpl/recipes-bsp/u-boot/u-boot_2016.11.bb
new file mode 100644
index 0000000..bf42e8b
--- /dev/null
+++ b/meta/meta-mediatek-gpl/recipes-bsp/u-boot/u-boot_2016.11.bb
@@ -0,0 +1,37 @@
+require u-boot-common_${PV}.inc
+inherit deploy u-boot-fitimage
+
+UBOOT_SRC = "${TOPDIR}/../src/bsp/u-boot-201611"
+UBOOT_OUT = "${WORKDIR}/out"
+
+PROVIDES = "virtual/bootloader"
+
+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-fit.${UBOOT_SUFFIX}"
+UBOOT_MAKE_TARGET ?= "all"
+
+EXTRA_OEMAKE = 'CROSS_COMPILE="${TARGET_PREFIX}" KBUILD_OUTPUT="${UBOOT_OUT}" STRIP=true V=1'
+
+do_compile () {
+ cd ${UBOOT_SRC}
+ oe_runmake mrproper
+ oe_runmake mt8521_defconfig
+ oe_runmake -f Makefile
+ cd -
+}
+
+do_deploy () {
+ install -d ${DEPLOYDIR}
+ install ${UBOOT_OUT}/${UBOOT_FIT_IMAGE} ${DEPLOYDIR}/${UBOOT_FIT_IMAGE}
+}
+
+addtask deploy before do_build after do_assemble_fitimage
+
diff --git a/meta/meta-mediatek-gpl/recipes-connectivity/libmtp/libmtp-1.1.5/69-libmtp.rules b/meta/meta-mediatek-gpl/recipes-connectivity/libmtp/libmtp-1.1.5/69-libmtp.rules
new file mode 100644
index 0000000..4cd27c7
--- /dev/null
+++ b/meta/meta-mediatek-gpl/recipes-connectivity/libmtp/libmtp-1.1.5/69-libmtp.rules
@@ -0,0 +1,999 @@
+# UDEV-style hotplug map for libmtp
+# Put this file in /etc/udev/rules.d
+
+ACTION!="add", GOTO="libmtp_rules_end"
+ENV{MAJOR}!="?*", GOTO="libmtp_rules_end"
+SUBSYSTEM=="usb", GOTO="libmtp_usb_rules"
+GOTO="libmtp_rules_end"
+
+LABEL="libmtp_usb_rules"
+
+# Some sensitive devices we surely don't wanna probe
+# Color instruments
+ATTR{idVendor}=="0670", GOTO="libmtp_rules_end"
+ATTR{idVendor}=="0765", GOTO="libmtp_rules_end"
+ATTR{idVendor}=="085c", GOTO="libmtp_rules_end"
+ATTR{idVendor}=="0971", GOTO="libmtp_rules_end"
+# Canon scanners that look like MTP devices (PID 0x22nn)
+ATTR{idVendor}=="04a9", ATTR{idProduct}=="22*", GOTO="libmtp_rules_end"
+# Canon digital camera (EOS 3D) that looks like MTP device (PID 0x3113)
+ATTR{idVendor}=="04a9", ATTR{idProduct}=="3113", GOTO="libmtp_rules_end"
+# Sensitive Atheros devices that look like MTP devices
+ATTR{idVendor}=="0cf3", GOTO="libmtp_rules_end"
+# Sensitive Atmel JTAG programmers
+ATTR{idVendor}=="03eb", GOTO="libmtp_rules_end"
+# Creative ZEN Vision
+ATTR{idVendor}=="041e", ATTR{idProduct}=="411f", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Creative Portable Media Center
+ATTR{idVendor}=="041e", ATTR{idProduct}=="4123", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Creative ZEN Xtra (MTP mode)
+ATTR{idVendor}=="041e", ATTR{idProduct}=="4128", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Dell DJ (2nd generation)
+ATTR{idVendor}=="041e", ATTR{idProduct}=="412f", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Creative ZEN Micro (MTP mode)
+ATTR{idVendor}=="041e", ATTR{idProduct}=="4130", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Creative ZEN Touch (MTP mode)
+ATTR{idVendor}=="041e", ATTR{idProduct}=="4131", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Dell Dell Pocket DJ (MTP mode)
+ATTR{idVendor}=="041e", ATTR{idProduct}=="4132", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Creative ZEN MicroPhoto (alternate version)
+ATTR{idVendor}=="041e", ATTR{idProduct}=="4133", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Creative ZEN Sleek (MTP mode)
+ATTR{idVendor}=="041e", ATTR{idProduct}=="4137", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Creative ZEN MicroPhoto
+ATTR{idVendor}=="041e", ATTR{idProduct}=="413c", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Creative ZEN Sleek Photo
+ATTR{idVendor}=="041e", ATTR{idProduct}=="413d", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Creative ZEN Vision:M
+ATTR{idVendor}=="041e", ATTR{idProduct}=="413e", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Creative ZEN V
+ATTR{idVendor}=="041e", ATTR{idProduct}=="4150", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Creative ZEN Vision:M (DVP-HD0004)
+ATTR{idVendor}=="041e", ATTR{idProduct}=="4151", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Creative ZEN V Plus
+ATTR{idVendor}=="041e", ATTR{idProduct}=="4152", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Creative ZEN Vision W
+ATTR{idVendor}=="041e", ATTR{idProduct}=="4153", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Creative ZEN
+ATTR{idVendor}=="041e", ATTR{idProduct}=="4157", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Creative ZEN V 2GB
+ATTR{idVendor}=="041e", ATTR{idProduct}=="4158", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Creative ZEN Mozaic
+ATTR{idVendor}=="041e", ATTR{idProduct}=="4161", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Creative ZEN X-Fi
+ATTR{idVendor}=="041e", ATTR{idProduct}=="4162", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Creative ZEN X-Fi 3
+ATTR{idVendor}=="041e", ATTR{idProduct}=="4169", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# ZiiLABS Zii EGG
+ATTR{idVendor}=="041e", ATTR{idProduct}=="6000", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Samsung YP-900
+ATTR{idVendor}=="04e8", ATTR{idProduct}=="0409", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Samsung I550W Phone
+ATTR{idVendor}=="04e8", ATTR{idProduct}=="04a4", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Samsung Jet S8000
+ATTR{idVendor}=="04e8", ATTR{idProduct}=="4f1f", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Samsung YH-920 (501d)
+ATTR{idVendor}=="04e8", ATTR{idProduct}=="501d", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Samsung YH-920 (5022)
+ATTR{idVendor}=="04e8", ATTR{idProduct}=="5022", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Samsung YH-925GS
+ATTR{idVendor}=="04e8", ATTR{idProduct}=="5024", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Samsung YH-820
+ATTR{idVendor}=="04e8", ATTR{idProduct}=="502e", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Samsung YH-925(-GS)
+ATTR{idVendor}=="04e8", ATTR{idProduct}=="502f", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Samsung YH-J70J
+ATTR{idVendor}=="04e8", ATTR{idProduct}=="5033", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Samsung YP-Z5
+ATTR{idVendor}=="04e8", ATTR{idProduct}=="503c", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Samsung YP-T7J
+ATTR{idVendor}=="04e8", ATTR{idProduct}=="5047", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Samsung YP-U2J (YP-U2JXB/XAA)
+ATTR{idVendor}=="04e8", ATTR{idProduct}=="5054", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Samsung YP-F2J
+ATTR{idVendor}=="04e8", ATTR{idProduct}=="5057", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Samsung YP-K5
+ATTR{idVendor}=="04e8", ATTR{idProduct}=="505a", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Samsung YP-U3
+ATTR{idVendor}=="04e8", ATTR{idProduct}=="507d", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Samsung YP-T9
+ATTR{idVendor}=="04e8", ATTR{idProduct}=="507f", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Samsung YP-K3
+ATTR{idVendor}=="04e8", ATTR{idProduct}=="5081", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Samsung YP-P2
+ATTR{idVendor}=="04e8", ATTR{idProduct}=="5083", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Samsung YP-T10
+ATTR{idVendor}=="04e8", ATTR{idProduct}=="508a", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Samsung YP-S5
+ATTR{idVendor}=="04e8", ATTR{idProduct}=="508b", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Samsung YP-S3
+ATTR{idVendor}=="04e8", ATTR{idProduct}=="5091", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Samsung YP-U4
+ATTR{idVendor}=="04e8", ATTR{idProduct}=="5093", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Samsung YP-R1
+ATTR{idVendor}=="04e8", ATTR{idProduct}=="510f", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Samsung YP-Q1
+ATTR{idVendor}=="04e8", ATTR{idProduct}=="5115", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Samsung YP-M1
+ATTR{idVendor}=="04e8", ATTR{idProduct}=="5118", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Samsung YP-P3
+ATTR{idVendor}=="04e8", ATTR{idProduct}=="511a", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Samsung YP-Q2
+ATTR{idVendor}=="04e8", ATTR{idProduct}=="511d", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Samsung YP-U5
+ATTR{idVendor}=="04e8", ATTR{idProduct}=="5121", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Samsung YP-R0
+ATTR{idVendor}=="04e8", ATTR{idProduct}=="5125", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Samsung YP-Q3
+ATTR{idVendor}=="04e8", ATTR{idProduct}=="5130", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Samsung YP-Z3
+ATTR{idVendor}=="04e8", ATTR{idProduct}=="5137", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Samsung YH-999 Portable Media Center/SGH-A707/SGH-L760V/SGH-U900/Verizon Intensity/Fascinate
+ATTR{idVendor}=="04e8", ATTR{idProduct}=="5a0f", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Samsung M7600 Beat/GT-S8300T/SGH-F490/S8300
+ATTR{idVendor}=="04e8", ATTR{idProduct}=="6642", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Samsung X830 Mobile Phone
+ATTR{idVendor}=="04e8", ATTR{idProduct}=="6702", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Samsung U600 Mobile Phone
+ATTR{idVendor}=="04e8", ATTR{idProduct}=="6709", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Samsung F250 Mobile Phone
+ATTR{idVendor}=="04e8", ATTR{idProduct}=="6727", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Samsung Juke (SCH-U470)
+ATTR{idVendor}=="04e8", ATTR{idProduct}=="6734", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Samsung GT-B2700
+ATTR{idVendor}=="04e8", ATTR{idProduct}=="6752", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Samsung SAMSUNG Trance
+ATTR{idVendor}=="04e8", ATTR{idProduct}=="6763", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Samsung GT-S8500
+ATTR{idVendor}=="04e8", ATTR{idProduct}=="6819", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Samsung Galaxy models (MTP+ADB)
+ATTR{idVendor}=="04e8", ATTR{idProduct}=="685c", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Samsung Galaxy Y
+ATTR{idVendor}=="04e8", ATTR{idProduct}=="685e", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Samsung Galaxy models (MTP)
+ATTR{idVendor}=="04e8", ATTR{idProduct}=="6860", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Samsung Galaxy models Kies mode
+ATTR{idVendor}=="04e8", ATTR{idProduct}=="6877", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Samsung Vibrant SGH-T959/Captivate/Media player mode
+ATTR{idVendor}=="04e8", ATTR{idProduct}=="68a9", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Samsung GT-B2710/Xcover 271
+ATTR{idVendor}=="04e8", ATTR{idProduct}=="68af", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Samsung GT-S5230
+ATTR{idVendor}=="04e8", ATTR{idProduct}=="e20c", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Microsoft/Intel Bandon Portable Media Center
+ATTR{idVendor}=="045e", ATTR{idProduct}=="00c9", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Microsoft Windows Phone
+ATTR{idVendor}=="045e", ATTR{idProduct}=="04ec", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Microsoft Windows MTP Simulator
+ATTR{idVendor}=="045e", ATTR{idProduct}=="0622", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Microsoft Zune HD
+ATTR{idVendor}=="045e", ATTR{idProduct}=="063e", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Microsoft Kin 1
+ATTR{idVendor}=="045e", ATTR{idProduct}=="0640", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Microsoft/Sharp/nVidia Kin TwoM
+ATTR{idVendor}=="045e", ATTR{idProduct}=="0641", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Microsoft Zune
+ATTR{idVendor}=="045e", ATTR{idProduct}=="0710", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# JVC Alneo XA-HD500
+ATTR{idVendor}=="04f1", ATTR{idProduct}=="6105", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Philips HDD6320/00 or HDD6330/17
+ATTR{idVendor}=="0471", ATTR{idProduct}=="014b", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Philips HDD14XX,HDD1620 or HDD1630/17
+ATTR{idVendor}=="0471", ATTR{idProduct}=="014c", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Philips HDD085/00 or HDD082/17
+ATTR{idVendor}=="0471", ATTR{idProduct}=="014d", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Philips GoGear SA9200
+ATTR{idVendor}=="0471", ATTR{idProduct}=="014f", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Philips SA1115/55
+ATTR{idVendor}=="0471", ATTR{idProduct}=="0164", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Philips GoGear Audio
+ATTR{idVendor}=="0471", ATTR{idProduct}=="0165", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Philips Shoqbox
+ATTR{idVendor}=="0471", ATTR{idProduct}=="0172", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Philips PSA610
+ATTR{idVendor}=="0471", ATTR{idProduct}=="0181", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Philips HDD6320
+ATTR{idVendor}=="0471", ATTR{idProduct}=="01eb", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Philips GoGear SA6014/SA6015/SA6024/SA6025/SA6044/SA6045
+ATTR{idVendor}=="0471", ATTR{idProduct}=="084e", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Philips GoGear SA5145
+ATTR{idVendor}=="0471", ATTR{idProduct}=="0857", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Philips GoGear SA6125/SA6145/SA6185
+ATTR{idVendor}=="0471", ATTR{idProduct}=="2002", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Philips GoGear SA3345
+ATTR{idVendor}=="0471", ATTR{idProduct}=="2004", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Philips SA5285
+ATTR{idVendor}=="0471", ATTR{idProduct}=="2022", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Philips GoGear ViBE SA1VBE04
+ATTR{idVendor}=="0471", ATTR{idProduct}=="2075", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Philips GoGear Muse
+ATTR{idVendor}=="0471", ATTR{idProduct}=="2077", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Philips GoGear ViBE SA1VBE04/08
+ATTR{idVendor}=="0471", ATTR{idProduct}=="207b", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Philips GoGear Aria
+ATTR{idVendor}=="0471", ATTR{idProduct}=="207c", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Philips GoGear SA1VBE08KX/78
+ATTR{idVendor}=="0471", ATTR{idProduct}=="208e", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Philips GoGear VIBE SA2VBE[08|16]K/02
+ATTR{idVendor}=="0471", ATTR{idProduct}=="20b7", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Philips GoGear Ariaz
+ATTR{idVendor}=="0471", ATTR{idProduct}=="20b9", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Philips GoGear Vibe/02
+ATTR{idVendor}=="0471", ATTR{idProduct}=="20e5", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Philips PSA235
+ATTR{idVendor}=="0471", ATTR{idProduct}=="7e01", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Acer Iconia TAB A500 (ID1)
+ATTR{idVendor}=="0502", ATTR{idProduct}=="3325", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Acer Iconia TAB A500 (ID2)
+ATTR{idVendor}=="0502", ATTR{idProduct}=="3341", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Acer Iconia TAB A501
+ATTR{idVendor}=="0502", ATTR{idProduct}=="3344", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Acer Iconia TAB A100 (ID1)
+ATTR{idVendor}=="0502", ATTR{idProduct}=="3348", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Acer Iconia TAB A100 (ID2)
+ATTR{idVendor}=="0502", ATTR{idProduct}=="3349", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Acer Iconia TAB A700
+ATTR{idVendor}=="0502", ATTR{idProduct}=="3378", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Acer Iconia TAB A200 (ID1)
+ATTR{idVendor}=="0502", ATTR{idProduct}=="337c", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Acer Iconia TAB A200 (ID2)
+ATTR{idVendor}=="0502", ATTR{idProduct}=="337d", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Acer Iconia TAB A510
+ATTR{idVendor}=="0502", ATTR{idProduct}=="338a", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Acer E350 Liquid Gallant Duo
+ATTR{idVendor}=="0502", ATTR{idProduct}=="33c3", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# SanDisk Sansa m230/m240
+ATTR{idVendor}=="0781", ATTR{idProduct}=="7400", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# SanDisk Sansa m200-tcc (MTP mode)
+ATTR{idVendor}=="0781", ATTR{idProduct}=="7401", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# SanDisk Sansa c150
+ATTR{idVendor}=="0781", ATTR{idProduct}=="7410", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# SanDisk Sansa e200/e250/e260/e270/e280
+ATTR{idVendor}=="0781", ATTR{idProduct}=="7420", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# SanDisk Sansa e260/e280 v2
+ATTR{idVendor}=="0781", ATTR{idProduct}=="7422", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# SanDisk Sansa m240/m250
+ATTR{idVendor}=="0781", ATTR{idProduct}=="7430", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# SanDisk Sansa Clip
+ATTR{idVendor}=="0781", ATTR{idProduct}=="7432", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# SanDisk Sansa Clip v2
+ATTR{idVendor}=="0781", ATTR{idProduct}=="7434", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# SanDisk Sansa c240/c250
+ATTR{idVendor}=="0781", ATTR{idProduct}=="7450", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# SanDisk Sansa c250 v2
+ATTR{idVendor}=="0781", ATTR{idProduct}=="7452", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# SanDisk Sansa Express
+ATTR{idVendor}=="0781", ATTR{idProduct}=="7460", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# SanDisk Sansa Connect
+ATTR{idVendor}=="0781", ATTR{idProduct}=="7480", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# SanDisk Sansa View
+ATTR{idVendor}=="0781", ATTR{idProduct}=="74b0", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# SanDisk Sansa Fuze
+ATTR{idVendor}=="0781", ATTR{idProduct}=="74c0", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# SanDisk Sansa Fuze v2
+ATTR{idVendor}=="0781", ATTR{idProduct}=="74c2", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# SanDisk Sansa Clip+
+ATTR{idVendor}=="0781", ATTR{idProduct}=="74d0", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# SanDisk Sansa Fuze+
+ATTR{idVendor}=="0781", ATTR{idProduct}=="74e0", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# SanDisk Sansa Clip Zip
+ATTR{idVendor}=="0781", ATTR{idProduct}=="74e4", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# iRiver H300 Series MTP
+ATTR{idVendor}=="1006", ATTR{idProduct}=="3004", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# iRiver Portable Media Center
+ATTR{idVendor}=="1006", ATTR{idProduct}=="4002", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# iRiver Portable Media Center
+ATTR{idVendor}=="1006", ATTR{idProduct}=="4003", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# iRiver T7 Volcano
+ATTR{idVendor}=="1042", ATTR{idProduct}=="1143", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# iRiver iFP-880
+ATTR{idVendor}=="4102", ATTR{idProduct}=="1008", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# iRiver T10
+ATTR{idVendor}=="4102", ATTR{idProduct}=="1113", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# iRiver T20 FM
+ATTR{idVendor}=="4102", ATTR{idProduct}=="1114", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# iRiver T20
+ATTR{idVendor}=="4102", ATTR{idProduct}=="1115", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# iRiver U10
+ATTR{idVendor}=="4102", ATTR{idProduct}=="1116", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# iRiver T10a
+ATTR{idVendor}=="4102", ATTR{idProduct}=="1117", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# iRiver T20
+ATTR{idVendor}=="4102", ATTR{idProduct}=="1118", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# iRiver T30
+ATTR{idVendor}=="4102", ATTR{idProduct}=="1119", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# iRiver T10 2GB
+ATTR{idVendor}=="4102", ATTR{idProduct}=="1120", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# iRiver N12
+ATTR{idVendor}=="4102", ATTR{idProduct}=="1122", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# iRiver Clix2
+ATTR{idVendor}=="4102", ATTR{idProduct}=="1126", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# iRiver Clix
+ATTR{idVendor}=="4102", ATTR{idProduct}=="112a", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# iRiver X20
+ATTR{idVendor}=="4102", ATTR{idProduct}=="1132", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# iRiver T60
+ATTR{idVendor}=="4102", ATTR{idProduct}=="1134", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# iRiver E100
+ATTR{idVendor}=="4102", ATTR{idProduct}=="1141", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# iRiver E100 v2/Lplayer
+ATTR{idVendor}=="4102", ATTR{idProduct}=="1142", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# iRiver Spinn
+ATTR{idVendor}=="4102", ATTR{idProduct}=="1147", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# iRiver E50
+ATTR{idVendor}=="4102", ATTR{idProduct}=="1151", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# iRiver T5
+ATTR{idVendor}=="4102", ATTR{idProduct}=="1153", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# iRiver E30
+ATTR{idVendor}=="4102", ATTR{idProduct}=="1167", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# iRiver H10 20GB
+ATTR{idVendor}=="4102", ATTR{idProduct}=="2101", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# iRiver H10 5GB
+ATTR{idVendor}=="4102", ATTR{idProduct}=="2102", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# iRiver H10 5.6GB
+ATTR{idVendor}=="4102", ATTR{idProduct}=="2105", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Dell, Inc DJ Itty
+ATTR{idVendor}=="413c", ATTR{idProduct}=="4500", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Dell, Inc Dell Streak 7
+ATTR{idVendor}=="413c", ATTR{idProduct}=="b10b", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Toshiba Gigabeat MEGF-40
+ATTR{idVendor}=="0930", ATTR{idProduct}=="0009", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Toshiba Gigabeat
+ATTR{idVendor}=="0930", ATTR{idProduct}=="000c", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Toshiba Gigabeat P20
+ATTR{idVendor}=="0930", ATTR{idProduct}=="000f", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Toshiba Gigabeat S
+ATTR{idVendor}=="0930", ATTR{idProduct}=="0010", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Toshiba Gigabeat P10
+ATTR{idVendor}=="0930", ATTR{idProduct}=="0011", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Toshiba Gigabeat V30
+ATTR{idVendor}=="0930", ATTR{idProduct}=="0014", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Toshiba Gigabeat U
+ATTR{idVendor}=="0930", ATTR{idProduct}=="0016", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Toshiba Gigabeat MEU202
+ATTR{idVendor}=="0930", ATTR{idProduct}=="0018", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Toshiba Gigabeat T
+ATTR{idVendor}=="0930", ATTR{idProduct}=="0019", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Toshiba Gigabeat MEU201
+ATTR{idVendor}=="0930", ATTR{idProduct}=="001a", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Toshiba Gigabeat MET401
+ATTR{idVendor}=="0930", ATTR{idProduct}=="001d", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Toshiba Excite AT300
+ATTR{idVendor}=="0930", ATTR{idProduct}=="0963", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Toshiba Thrive AT100/AT105
+ATTR{idVendor}=="0930", ATTR{idProduct}=="7100", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Archos Gmini XS100
+ATTR{idVendor}=="0e79", ATTR{idProduct}=="1207", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Archos XS202 (MTP mode)
+ATTR{idVendor}=="0e79", ATTR{idProduct}=="1208", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Archos 104 (MTP mode)
+ATTR{idVendor}=="0e79", ATTR{idProduct}=="120a", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Archos 204 (MTP mode)
+ATTR{idVendor}=="0e79", ATTR{idProduct}=="120c", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Archos 404 (MTP mode)
+ATTR{idVendor}=="0e79", ATTR{idProduct}=="1301", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Archos 404CAM (MTP mode)
+ATTR{idVendor}=="0e79", ATTR{idProduct}=="1303", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Archos 504 (MTP mode)
+ATTR{idVendor}=="0e79", ATTR{idProduct}=="1307", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Archos 604 (MTP mode)
+ATTR{idVendor}=="0e79", ATTR{idProduct}=="1309", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Archos 604WIFI (MTP mode)
+ATTR{idVendor}=="0e79", ATTR{idProduct}=="130b", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Archos 704 mobile dvr
+ATTR{idVendor}=="0e79", ATTR{idProduct}=="130d", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Archos 704TV (MTP mode)
+ATTR{idVendor}=="0e79", ATTR{idProduct}=="130f", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Archos 405 (MTP mode)
+ATTR{idVendor}=="0e79", ATTR{idProduct}=="1311", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Archos 605 (MTP mode)
+ATTR{idVendor}=="0e79", ATTR{idProduct}=="1313", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Archos 605F (MTP mode)
+ATTR{idVendor}=="0e79", ATTR{idProduct}=="1315", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Archos 705 (MTP mode)
+ATTR{idVendor}=="0e79", ATTR{idProduct}=="1319", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Archos TV+ (MTP mode)
+ATTR{idVendor}=="0e79", ATTR{idProduct}=="131b", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Archos 105 (MTP mode)
+ATTR{idVendor}=="0e79", ATTR{idProduct}=="131d", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Archos 405HDD (MTP mode)
+ATTR{idVendor}=="0e79", ATTR{idProduct}=="1321", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Archos 5 (MTP mode)
+ATTR{idVendor}=="0e79", ATTR{idProduct}=="1331", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Archos 5 (MTP mode)
+ATTR{idVendor}=="0e79", ATTR{idProduct}=="1333", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Archos 7 (MTP mode)
+ATTR{idVendor}=="0e79", ATTR{idProduct}=="1335", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Archos SPOD (MTP mode)
+ATTR{idVendor}=="0e79", ATTR{idProduct}=="1341", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Archos 5S IT (MTP mode)
+ATTR{idVendor}=="0e79", ATTR{idProduct}=="1351", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Archos 5H IT (MTP mode)
+ATTR{idVendor}=="0e79", ATTR{idProduct}=="1357", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Archos Arnova Childpad
+ATTR{idVendor}=="0e79", ATTR{idProduct}=="1458", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Archos 8o G9 (MTP mode)
+ATTR{idVendor}=="0e79", ATTR{idProduct}=="1508", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Archos 8o G9 Turbo (MTP mode)
+ATTR{idVendor}=="0e79", ATTR{idProduct}=="1509", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Archos 80G9
+ATTR{idVendor}=="0e79", ATTR{idProduct}=="1518", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Archos 101 G9
+ATTR{idVendor}=="0e79", ATTR{idProduct}=="1528", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Archos 101 G9 (v2)
+ATTR{idVendor}=="0e79", ATTR{idProduct}=="1529", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Archos 101 G9 Turbo 250 HD
+ATTR{idVendor}=="0e79", ATTR{idProduct}=="1538", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Archos 101 G9 Turbo
+ATTR{idVendor}=="0e79", ATTR{idProduct}=="1539", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Archos 70it2 (mode 1)
+ATTR{idVendor}=="0e79", ATTR{idProduct}=="1568", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Archos 70it2 (mode 2)
+ATTR{idVendor}=="0e79", ATTR{idProduct}=="1569", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Dunlop MP3 player 1GB / EGOMAN MD223AFD
+ATTR{idVendor}=="10d6", ATTR{idProduct}=="2200", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Memorex or iRiver MMP 8585/8586 or iRiver E200
+ATTR{idVendor}=="10d6", ATTR{idProduct}=="2300", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Sirius Stiletto
+ATTR{idVendor}=="18f6", ATTR{idProduct}=="0102", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Sirius Stiletto 2
+ATTR{idVendor}=="18f6", ATTR{idProduct}=="0110", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Canon Ixus Digital 700 (PTP/MTP mode)
+ATTR{idVendor}=="04a9", ATTR{idProduct}=="30f2", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Canon PowerShot A640 (PTP/MTP mode)
+ATTR{idVendor}=="04a9", ATTR{idProduct}=="3139", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Canon PowerShot SX20IS (PTP/MTP mode)
+ATTR{idVendor}=="04a9", ATTR{idProduct}=="31e4", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Nokia N81 Mobile Phone
+ATTR{idVendor}=="0421", ATTR{idProduct}=="000a", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Nokia 6120c Classic Mobile Phone
+ATTR{idVendor}=="0421", ATTR{idProduct}=="002e", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Nokia N96 Mobile Phone
+ATTR{idVendor}=="0421", ATTR{idProduct}=="0039", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Nokia 6500c Classic Mobile Phone
+ATTR{idVendor}=="0421", ATTR{idProduct}=="003c", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Nokia 3110c Mobile Phone
+ATTR{idVendor}=="0421", ATTR{idProduct}=="005f", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Nokia 3109c Mobile Phone
+ATTR{idVendor}=="0421", ATTR{idProduct}=="0065", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Nokia 5310 XpressMusic
+ATTR{idVendor}=="0421", ATTR{idProduct}=="006c", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Nokia N95 Mobile Phone 8GB
+ATTR{idVendor}=="0421", ATTR{idProduct}=="006e", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Nokia N82 Mobile Phone
+ATTR{idVendor}=="0421", ATTR{idProduct}=="0074", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Nokia N78 Mobile Phone
+ATTR{idVendor}=="0421", ATTR{idProduct}=="0079", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Nokia 6220 Classic
+ATTR{idVendor}=="0421", ATTR{idProduct}=="008d", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Nokia N85 Mobile Phone
+ATTR{idVendor}=="0421", ATTR{idProduct}=="0092", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Nokia 6210 Navigator
+ATTR{idVendor}=="0421", ATTR{idProduct}=="0098", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Nokia E71
+ATTR{idVendor}=="0421", ATTR{idProduct}=="00e4", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Nokia E66
+ATTR{idVendor}=="0421", ATTR{idProduct}=="00e5", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Nokia 5320 XpressMusic
+ATTR{idVendor}=="0421", ATTR{idProduct}=="00ea", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Nokia 5800 XpressMusic
+ATTR{idVendor}=="0421", ATTR{idProduct}=="0154", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Nokia 5800 XpressMusic v2
+ATTR{idVendor}=="0421", ATTR{idProduct}=="0155", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Nokia 5800 XpressMusic v3
+ATTR{idVendor}=="0421", ATTR{idProduct}=="0159", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Nokia E63
+ATTR{idVendor}=="0421", ATTR{idProduct}=="0179", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Nokia N79
+ATTR{idVendor}=="0421", ATTR{idProduct}=="0186", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Nokia E71x
+ATTR{idVendor}=="0421", ATTR{idProduct}=="01a1", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Nokia E52
+ATTR{idVendor}=="0421", ATTR{idProduct}=="01cf", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Nokia 3710
+ATTR{idVendor}=="0421", ATTR{idProduct}=="01ee", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Nokia N97-1
+ATTR{idVendor}=="0421", ATTR{idProduct}=="01f4", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Nokia N97
+ATTR{idVendor}=="0421", ATTR{idProduct}=="01f5", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Nokia 5130 XpressMusic
+ATTR{idVendor}=="0421", ATTR{idProduct}=="0209", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Nokia E72
+ATTR{idVendor}=="0421", ATTR{idProduct}=="0221", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Nokia 5530
+ATTR{idVendor}=="0421", ATTR{idProduct}=="0229", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Nokia N97 mini
+ATTR{idVendor}=="0421", ATTR{idProduct}=="026b", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Nokia X6
+ATTR{idVendor}=="0421", ATTR{idProduct}=="0274", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Nokia 6600i
+ATTR{idVendor}=="0421", ATTR{idProduct}=="0297", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Nokia 2710
+ATTR{idVendor}=="0421", ATTR{idProduct}=="02c1", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Nokia 5230
+ATTR{idVendor}=="0421", ATTR{idProduct}=="02e2", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Nokia N8
+ATTR{idVendor}=="0421", ATTR{idProduct}=="02fe", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Nokia N8 (Ovi mode)
+ATTR{idVendor}=="0421", ATTR{idProduct}=="0302", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Nokia E7
+ATTR{idVendor}=="0421", ATTR{idProduct}=="0334", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Nokia E7 (Ovi mode)
+ATTR{idVendor}=="0421", ATTR{idProduct}=="0335", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Nokia C7
+ATTR{idVendor}=="0421", ATTR{idProduct}=="03c1", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Nokia C7 (ID2)
+ATTR{idVendor}=="0421", ATTR{idProduct}=="03cd", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Nokia N950
+ATTR{idVendor}=="0421", ATTR{idProduct}=="03d2", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Nokia 3250 Mobile Phone
+ATTR{idVendor}=="0421", ATTR{idProduct}=="0462", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Nokia N93 Mobile Phone
+ATTR{idVendor}=="0421", ATTR{idProduct}=="0478", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Nokia 5500 Sport Mobile Phone
+ATTR{idVendor}=="0421", ATTR{idProduct}=="047e", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Nokia N91 Mobile Phone
+ATTR{idVendor}=="0421", ATTR{idProduct}=="0485", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Nokia 5700 XpressMusic Mobile Phone
+ATTR{idVendor}=="0421", ATTR{idProduct}=="04b4", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Nokia 5300 Mobile Phone
+ATTR{idVendor}=="0421", ATTR{idProduct}=="04ba", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Nokia 5200 Mobile Phone
+ATTR{idVendor}=="0421", ATTR{idProduct}=="04be", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Nokia N73 Mobile Phone
+ATTR{idVendor}=="0421", ATTR{idProduct}=="04d1", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Nokia N75 Mobile Phone
+ATTR{idVendor}=="0421", ATTR{idProduct}=="04e1", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Nokia N93i Mobile Phone
+ATTR{idVendor}=="0421", ATTR{idProduct}=="04e5", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Nokia N95 Mobile Phone
+ATTR{idVendor}=="0421", ATTR{idProduct}=="04ef", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Nokia N80 Internet Edition (Media Player)
+ATTR{idVendor}=="0421", ATTR{idProduct}=="04f1", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Nokia N9
+ATTR{idVendor}=="0421", ATTR{idProduct}=="051a", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Nokia 5530 Xpressmusic
+ATTR{idVendor}=="05c6", ATTR{idProduct}=="0229", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Nokia/Verizon 6205 Balboa/Verizon Music Phone
+ATTR{idVendor}=="05c6", ATTR{idProduct}=="3196", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Logik LOG DAX MP3 and DAB Player
+ATTR{idVendor}=="13d1", ATTR{idProduct}=="7002", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Technika MP-709
+ATTR{idVendor}=="13d1", ATTR{idProduct}=="7017", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Thomson EM28 Series
+ATTR{idVendor}=="069b", ATTR{idProduct}=="0774", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Thomson / RCA Opal / Lyra MC4002
+ATTR{idVendor}=="069b", ATTR{idProduct}=="0777", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Thomson Lyra MC5104B (M51 Series)
+ATTR{idVendor}=="069b", ATTR{idProduct}=="077c", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Thomson RCA H106
+ATTR{idVendor}=="069b", ATTR{idProduct}=="301a", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Thomson scenium E308
+ATTR{idVendor}=="069b", ATTR{idProduct}=="3028", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Thomson / RCA Lyra HC308A
+ATTR{idVendor}=="069b", ATTR{idProduct}=="3035", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# FOMA F903iX HIGH-SPEED
+ATTR{idVendor}=="04c5", ATTR{idProduct}=="1140", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# NormSoft, Inc. Pocket Tunes
+ATTR{idVendor}=="1703", ATTR{idProduct}=="0001", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# NormSoft, Inc. Pocket Tunes 4
+ATTR{idVendor}=="1703", ATTR{idProduct}=="0002", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# TrekStor Vibez 8/12GB
+ATTR{idVendor}=="066f", ATTR{idProduct}=="842a", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Medion MD8333
+ATTR{idVendor}=="066f", ATTR{idProduct}=="8550", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Medion MD8333
+ATTR{idVendor}=="066f", ATTR{idProduct}=="8588", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Medion MD99000 (P9514)/Olivetti Olipad 110
+ATTR{idVendor}=="0408", ATTR{idProduct}=="b009", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Medion Lifetab P9514
+ATTR{idVendor}=="0408", ATTR{idProduct}=="b00a", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Maxfield G-Flash NG 1GB
+ATTR{idVendor}=="066f", ATTR{idProduct}=="846c", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# SigmaTel Inc. MTPMSCN Audio Player
+ATTR{idVendor}=="066f", ATTR{idProduct}=="a010", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# TrekStor i.Beat Sweez FM
+ATTR{idVendor}=="0402", ATTR{idProduct}=="0611", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# TrekStor i.Beat Organix 2.0
+ATTR{idVendor}=="1e68", ATTR{idProduct}=="0002", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Disney MixMax
+ATTR{idVendor}=="0aa6", ATTR{idProduct}=="6021", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Tevion MD 81488
+ATTR{idVendor}=="0aa6", ATTR{idProduct}=="3011", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# MyMusix PD-6070
+ATTR{idVendor}=="0aa6", ATTR{idProduct}=="9601", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Cowon iAudio U3 (MTP mode)
+ATTR{idVendor}=="0e21", ATTR{idProduct}=="0701", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Cowon iAudio 6 (MTP mode)
+ATTR{idVendor}=="0e21", ATTR{idProduct}=="0711", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Cowon iAudio 7 (MTP mode)
+ATTR{idVendor}=="0e21", ATTR{idProduct}=="0751", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Cowon iAudio U5 (MTP mode)
+ATTR{idVendor}=="0e21", ATTR{idProduct}=="0761", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Cowon iAudio D2 (MTP mode)
+ATTR{idVendor}=="0e21", ATTR{idProduct}=="0801", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Cowon iAudio D2+ FW 2.x (MTP mode)
+ATTR{idVendor}=="0e21", ATTR{idProduct}=="0861", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Cowon iAudio D2+ DAB FW 4.x (MTP mode)
+ATTR{idVendor}=="0e21", ATTR{idProduct}=="0871", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Cowon iAudio D2+ FW 3.x (MTP mode)
+ATTR{idVendor}=="0e21", ATTR{idProduct}=="0881", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Cowon iAudio D2+ DMB FW 1.x (MTP mode)
+ATTR{idVendor}=="0e21", ATTR{idProduct}=="0891", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Cowon iAudio S9 (MTP mode)
+ATTR{idVendor}=="0e21", ATTR{idProduct}=="0901", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Cowon iAudio 9 (MTP mode)
+ATTR{idVendor}=="0e21", ATTR{idProduct}=="0911", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Cowon iAudio J3 (MTP mode)
+ATTR{idVendor}=="0e21", ATTR{idProduct}=="0921", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Cowon iAudio X7 (MTP mode)
+ATTR{idVendor}=="0e21", ATTR{idProduct}=="0931", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Cowon iAudio C2 (MTP mode)
+ATTR{idVendor}=="0e21", ATTR{idProduct}=="0941", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Cowon iAudio 10 (MTP mode)
+ATTR{idVendor}=="0e21", ATTR{idProduct}=="0952", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Insignia NS-DV45
+ATTR{idVendor}=="19ff", ATTR{idProduct}=="0303", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Insignia Sport Player
+ATTR{idVendor}=="19ff", ATTR{idProduct}=="0307", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Insignia Pilot 4GB
+ATTR{idVendor}=="19ff", ATTR{idProduct}=="0309", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# LG Electronics Inc. T54
+ATTR{idVendor}=="043e", ATTR{idProduct}=="7040", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# LG Electronics Inc. UP3
+ATTR{idVendor}=="043e", ATTR{idProduct}=="70b1", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# LG Electronics Inc. VX8550 V CAST Mobile Phone
+ATTR{idVendor}=="1004", ATTR{idProduct}=="6010", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# LG Electronics Inc. KC910 Renoir Mobile Phone
+ATTR{idVendor}=="1004", ATTR{idProduct}=="608f", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# LG Electronics Inc. GR-500 Music Player
+ATTR{idVendor}=="1004", ATTR{idProduct}=="611b", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# LG Electronics Inc. KM900
+ATTR{idVendor}=="1004", ATTR{idProduct}=="6132", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# LG Electronics Inc. LG8575
+ATTR{idVendor}=="1004", ATTR{idProduct}=="619a", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# LG Electronics Inc. V909 G-Slate
+ATTR{idVendor}=="1004", ATTR{idProduct}=="61f9", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# LG Electronics Inc. LG-E617G/P700
+ATTR{idVendor}=="1004", ATTR{idProduct}=="631c", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Sony Walkman NWZ-A815/NWZ-A818
+ATTR{idVendor}=="054c", ATTR{idProduct}=="0325", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Sony Walkman NWZ-S516
+ATTR{idVendor}=="054c", ATTR{idProduct}=="0326", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Sony Walkman NWZ-S615F/NWZ-S616F/NWZ-S618F
+ATTR{idVendor}=="054c", ATTR{idProduct}=="0327", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Sony Walkman NWZ-S716F
+ATTR{idVendor}=="054c", ATTR{idProduct}=="035a", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Sony Walkman NWZ-A826/NWZ-A828/NWZ-A829
+ATTR{idVendor}=="054c", ATTR{idProduct}=="035b", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Sony Walkman NWZ-A726/NWZ-A728/NWZ-A768
+ATTR{idVendor}=="054c", ATTR{idProduct}=="035c", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Sony Walkman NWZ-B135
+ATTR{idVendor}=="054c", ATTR{idProduct}=="036e", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Sony Walkman NWZ-E436F
+ATTR{idVendor}=="054c", ATTR{idProduct}=="0385", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Sony Walkman NWZ-W202
+ATTR{idVendor}=="054c", ATTR{idProduct}=="0388", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Sony Walkman NWZ-S739F
+ATTR{idVendor}=="054c", ATTR{idProduct}=="038c", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Sony Walkman NWZ-S638F
+ATTR{idVendor}=="054c", ATTR{idProduct}=="038e", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Sony Walkman NWZ-X1050B/NWZ-X1060B
+ATTR{idVendor}=="054c", ATTR{idProduct}=="0397", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Sony Walkman NWZ-X1051/NWZ-X1061
+ATTR{idVendor}=="054c", ATTR{idProduct}=="0398", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Sony Walkman NWZ-B142F
+ATTR{idVendor}=="054c", ATTR{idProduct}=="03d8", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Sony Walkman NWZ-E344
+ATTR{idVendor}=="054c", ATTR{idProduct}=="03fc", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Sony Walkman NWZ-E445
+ATTR{idVendor}=="054c", ATTR{idProduct}=="03fd", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Sony Walkman NWZ-S545
+ATTR{idVendor}=="054c", ATTR{idProduct}=="03fe", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Sony Walkman NWZ-A845
+ATTR{idVendor}=="054c", ATTR{idProduct}=="0404", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Sony Walkman NWZ-W252B
+ATTR{idVendor}=="054c", ATTR{idProduct}=="04bb", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Sony Walkman NWZ-B153F
+ATTR{idVendor}=="054c", ATTR{idProduct}=="04be", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Sony Walkman NWZ-E354
+ATTR{idVendor}=="054c", ATTR{idProduct}=="04cb", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Sony Walkman NWZ-S754
+ATTR{idVendor}=="054c", ATTR{idProduct}=="04cc", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Sony NWZ-B163F
+ATTR{idVendor}=="054c", ATTR{idProduct}=="059a", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Sony Walkman NWZ-E464
+ATTR{idVendor}=="054c", ATTR{idProduct}=="05a6", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Sony NWZ-S765
+ATTR{idVendor}=="054c", ATTR{idProduct}=="05a8", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Sony Sony Tablet S
+ATTR{idVendor}=="054c", ATTR{idProduct}=="05b3", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Sony Sony Tablet S1
+ATTR{idVendor}=="054c", ATTR{idProduct}=="05b4", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Sony DCR-SR75
+ATTR{idVendor}=="054c", ATTR{idProduct}=="1294", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# SonyEricsson K850i
+ATTR{idVendor}=="0fce", ATTR{idProduct}=="0075", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# SonyEricsson W910
+ATTR{idVendor}=="0fce", ATTR{idProduct}=="0076", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# SonyEricsson W890i
+ATTR{idVendor}=="0fce", ATTR{idProduct}=="00b3", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# SonyEricsson W760i
+ATTR{idVendor}=="0fce", ATTR{idProduct}=="00c6", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# SonyEricsson C902
+ATTR{idVendor}=="0fce", ATTR{idProduct}=="00d4", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# SonyEricsson C702
+ATTR{idVendor}=="0fce", ATTR{idProduct}=="00d9", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# SonyEricsson W980
+ATTR{idVendor}=="0fce", ATTR{idProduct}=="00da", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# SonyEricsson C905
+ATTR{idVendor}=="0fce", ATTR{idProduct}=="00ef", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# SonyEricsson W595
+ATTR{idVendor}=="0fce", ATTR{idProduct}=="00f3", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# SonyEricsson W902
+ATTR{idVendor}=="0fce", ATTR{idProduct}=="00f5", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# SonyEricsson T700
+ATTR{idVendor}=="0fce", ATTR{idProduct}=="00fb", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# SonyEricsson W705/W715
+ATTR{idVendor}=="0fce", ATTR{idProduct}=="0105", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# SonyEricsson W995
+ATTR{idVendor}=="0fce", ATTR{idProduct}=="0112", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# SonyEricsson U5
+ATTR{idVendor}=="0fce", ATTR{idProduct}=="0133", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# SonyEricsson U8i
+ATTR{idVendor}=="0fce", ATTR{idProduct}=="013a", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# SonyEricsson j10i2 (Elm)
+ATTR{idVendor}=="0fce", ATTR{idProduct}=="0144", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# SonyEricsson j108i (Cedar)
+ATTR{idVendor}=="0fce", ATTR{idProduct}=="014e", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# SonyEricsson W302
+ATTR{idVendor}=="0fce", ATTR{idProduct}=="10c8", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# SonyEricsson j10i (Elm)
+ATTR{idVendor}=="0fce", ATTR{idProduct}=="d144", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# SonyEricsson K550i
+ATTR{idVendor}=="0fce", ATTR{idProduct}=="e000", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# SonyEricsson LT15i (Xperia arc S)
+ATTR{idVendor}=="0fce", ATTR{idProduct}=="014f", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# SonyEricsson MT11i Xperia Neo
+ATTR{idVendor}=="0fce", ATTR{idProduct}=="0156", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# SonyEricsson MK16i Xperia
+ATTR{idVendor}=="0fce", ATTR{idProduct}=="015a", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# SonyEricsson ST18a Xperia Ray
+ATTR{idVendor}=="0fce", ATTR{idProduct}=="0161", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# SonyEricsson SK17i Xperia Mini Pro
+ATTR{idVendor}=="0fce", ATTR{idProduct}=="0166", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# SonyEricsson ST15i Xperia Mini
+ATTR{idVendor}=="0fce", ATTR{idProduct}=="0167", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# SonyEricsson ST17i Xperia Active
+ATTR{idVendor}=="0fce", ATTR{idProduct}=="0168", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# SONY LT26i Xperia S
+ATTR{idVendor}=="0fce", ATTR{idProduct}=="0169", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# SONY WT19i Live Walkman
+ATTR{idVendor}=="0fce", ATTR{idProduct}=="016d", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# SONY ST21i Xperia Tipo
+ATTR{idVendor}=="0fce", ATTR{idProduct}=="0170", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# SONY ST15i Xperia U
+ATTR{idVendor}=="0fce", ATTR{idProduct}=="0171", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# SONY LT22i Xperia P
+ATTR{idVendor}=="0fce", ATTR{idProduct}=="0172", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# SONY LT26w Xperia Acro S
+ATTR{idVendor}=="0fce", ATTR{idProduct}=="0176", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# SonyEricsson ST17i Xperia Active (MTP+UMS mode)
+ATTR{idVendor}=="0fce", ATTR{idProduct}=="4168", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# SONY LT26i Xperia S (MTP+UMS mode)
+ATTR{idVendor}=="0fce", ATTR{idProduct}=="4169", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# SONY ST21i Xperia Tipo (MTP+UMS mode)
+ATTR{idVendor}=="0fce", ATTR{idProduct}=="4170", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# SONY ST25i Xperia U (MTP+UMS mode)
+ATTR{idVendor}=="0fce", ATTR{idProduct}=="4171", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# SONY LT22i Xperia P (MTP+UMS mode)
+ATTR{idVendor}=="0fce", ATTR{idProduct}=="4172", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# SONY LT26w Xperia Acro S (MTP+UMS mode)
+ATTR{idVendor}=="0fce", ATTR{idProduct}=="4176", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# SonyEricsson LT15i Xperia Arc (MTP+ADB mode)
+ATTR{idVendor}=="0fce", ATTR{idProduct}=="514f", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# SonyEricsson MT11i Xperia Neo (MTP+ADB mode)
+ATTR{idVendor}=="0fce", ATTR{idProduct}=="5156", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# SonyEricsson ST17i Xperia Active (MTP+ADB mode)
+ATTR{idVendor}=="0fce", ATTR{idProduct}=="5168", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# SONY LT26i Xperia S (MTP+ADB mode)
+ATTR{idVendor}=="0fce", ATTR{idProduct}=="5169", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# SonyEricsson MK16i Xperia (MTP+ADB mode)
+ATTR{idVendor}=="0fce", ATTR{idProduct}=="515a", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# SonyEricsson ST18i Xperia Ray (MTP+ADB mode)
+ATTR{idVendor}=="0fce", ATTR{idProduct}=="5161", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# SonyEricsson SK17i Xperia Mini Pro (MTP+ADB mode)
+ATTR{idVendor}=="0fce", ATTR{idProduct}=="5166", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# SonyEricsson ST15i Xperia Mini (MTP+ADB mode)
+ATTR{idVendor}=="0fce", ATTR{idProduct}=="5167", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# SonyEricsson SK17i Xperia Mini Pro (MTP+ADB mode)
+ATTR{idVendor}=="0fce", ATTR{idProduct}=="516d", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# SONY ST21i Xperia Tipo (MTP+ADB mode)
+ATTR{idVendor}=="0fce", ATTR{idProduct}=="5170", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# SONY ST25i Xperia U (MTP+ADB mode)
+ATTR{idVendor}=="0fce", ATTR{idProduct}=="5171", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# SONY LT22i Xperia P (MTP+ADB mode)
+ATTR{idVendor}=="0fce", ATTR{idProduct}=="5172", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# SONY LT26w Xperia Acro S (MTP+ADB mode)
+ATTR{idVendor}=="0fce", ATTR{idProduct}=="5176", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# SONY MT27i Xperia Sola (MTP+UMS+? mode)
+ATTR{idVendor}=="0fce", ATTR{idProduct}=="a173", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# SONY ST27i Xperia Go (MTP+UMS+? mode)
+ATTR{idVendor}=="0fce", ATTR{idProduct}=="a17e", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Motorola V3m/V750 verizon
+ATTR{idVendor}=="22b8", ATTR{idProduct}=="2a65", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Motorola Xoom 2 Media Edition (ID2)
+ATTR{idVendor}=="22b8", ATTR{idProduct}=="41cf", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Motorola Droid X/MB525 (Defy)
+ATTR{idVendor}=="22b8", ATTR{idProduct}=="41d6", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Motorola Milestone / Verizon Droid
+ATTR{idVendor}=="22b8", ATTR{idProduct}=="41dc", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Motorola DROID2
+ATTR{idVendor}=="22b8", ATTR{idProduct}=="42a7", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Motorola Xoom 2 Media Edition
+ATTR{idVendor}=="22b8", ATTR{idProduct}=="4311", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Motorola XT912/XT928
+ATTR{idVendor}=="22b8", ATTR{idProduct}=="4362", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Motorola DROID4
+ATTR{idVendor}=="22b8", ATTR{idProduct}=="437f", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Motorola IdeaPad K1
+ATTR{idVendor}=="22b8", ATTR{idProduct}=="4811", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Motorola A1200
+ATTR{idVendor}=="22b8", ATTR{idProduct}=="60ca", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Motorola MTP Test Command Interface
+ATTR{idVendor}=="22b8", ATTR{idProduct}=="6413", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Motorola RAZR2 V8/U9/Z6
+ATTR{idVendor}=="22b8", ATTR{idProduct}=="6415", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Motorola Xoom (Factory test)
+ATTR{idVendor}=="22b8", ATTR{idProduct}=="70a3", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Motorola Xoom (MTP)
+ATTR{idVendor}=="22b8", ATTR{idProduct}=="70a8", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Motorola Xoom (MTP+ADB)
+ATTR{idVendor}=="22b8", ATTR{idProduct}=="70a9", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Motorola Milestone X2
+ATTR{idVendor}=="22b8", ATTR{idProduct}=="70ca", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Google Inc (for Sony) S1
+ATTR{idVendor}=="18d1", ATTR{idProduct}=="05b3", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Google Inc (for Barnes & Noble) Nook Color
+ATTR{idVendor}=="18d1", ATTR{idProduct}=="2d02", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Google Inc (for Asus) TF101 Transformer
+ATTR{idVendor}=="18d1", ATTR{idProduct}=="4e0f", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Google Inc (for Samsung) Nexus S
+ATTR{idVendor}=="18d1", ATTR{idProduct}=="4e21", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Google Inc (for Asus) Nexus 7 (MTP)
+ATTR{idVendor}=="18d1", ATTR{idProduct}=="4e41", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Google Inc (for Asus) Nexus 7 (MTP+ADB)
+ATTR{idVendor}=="18d1", ATTR{idProduct}=="4e42", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Google Inc (for Motorola) Xoom (MZ604)
+ATTR{idVendor}=="18d1", ATTR{idProduct}=="70a8", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Google Inc (for Toshiba) Thrive 7/AT105
+ATTR{idVendor}=="18d1", ATTR{idProduct}=="7102", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Google Inc (for Lenovo) Ideapad K1
+ATTR{idVendor}=="18d1", ATTR{idProduct}=="740a", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Google Inc (for Medion) MD99000 (P9514)
+ATTR{idVendor}=="18d1", ATTR{idProduct}=="b00a", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Google Inc (for LG Electronics) P990/Optimus (Cyanogen)
+ATTR{idVendor}=="18d1", ATTR{idProduct}=="d109", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Google Inc (for LG Electronics) P990/Optimus
+ATTR{idVendor}=="18d1", ATTR{idProduct}=="d10a", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Kenwood Media Keg HD10GB7 Sport Player
+ATTR{idVendor}=="0b28", ATTR{idProduct}=="100c", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Micro-Star International P610/Model MS-5557
+ATTR{idVendor}=="0db0", ATTR{idProduct}=="5572", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# FOMA D905i
+ATTR{idVendor}=="06d3", ATTR{idProduct}=="21ba", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Haier Ibiza Rhapsody
+ATTR{idVendor}=="1302", ATTR{idProduct}=="1016", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Haier Ibiza Rhapsody
+ATTR{idVendor}=="1302", ATTR{idProduct}=="1017", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Panasonic P905i
+ATTR{idVendor}=="04da", ATTR{idProduct}=="2145", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Panasonic P906i
+ATTR{idVendor}=="04da", ATTR{idProduct}=="2158", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Polaroid Freescape/MPU-433158
+ATTR{idVendor}=="0546", ATTR{idProduct}=="2035", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Pioneer XMP3
+ATTR{idVendor}=="08e4", ATTR{idProduct}=="0148", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Slacker Inc. Slacker Portable Media Player
+ATTR{idVendor}=="1bdc", ATTR{idProduct}=="fabf", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Conceptronic CMTD2
+ATTR{idVendor}=="1e53", ATTR{idProduct}=="0005", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# O2 Sistemas ZoltarTV
+ATTR{idVendor}=="1e53", ATTR{idProduct}=="0006", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Wyplay Wyplayer
+ATTR{idVendor}=="1e53", ATTR{idProduct}=="0007", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Perception Digital, Ltd Gigaware GX400
+ATTR{idVendor}=="0aa6", ATTR{idProduct}=="9702", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# RIM BlackBerry Storm/9650
+ATTR{idVendor}=="0fca", ATTR{idProduct}=="8007", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Nextar MA715A-8R
+ATTR{idVendor}=="0402", ATTR{idProduct}=="5668", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Coby COBY MP705
+ATTR{idVendor}=="1e74", ATTR{idProduct}=="6512", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Apple iPhone
+ATTR{idVendor}=="05ac", ATTR{idProduct}=="1290", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Apple iPod Touch 1st Gen
+ATTR{idVendor}=="05ac", ATTR{idProduct}=="1291", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Apple iPhone 3G
+ATTR{idVendor}=="05ac", ATTR{idProduct}=="1292", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Apple iPod Touch 2nd Gen
+ATTR{idVendor}=="05ac", ATTR{idProduct}=="1293", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Apple iPhone 3GS
+ATTR{idVendor}=="05ac", ATTR{idProduct}=="1294", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Apple 0x1296
+ATTR{idVendor}=="05ac", ATTR{idProduct}=="1296", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Apple 0x1297
+ATTR{idVendor}=="05ac", ATTR{idProduct}=="1297", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Apple 0x1298
+ATTR{idVendor}=="05ac", ATTR{idProduct}=="1298", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Apple iPod Touch 3rd Gen
+ATTR{idVendor}=="05ac", ATTR{idProduct}=="1299", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Apple iPad
+ATTR{idVendor}=="05ac", ATTR{idProduct}=="129a", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Curitel Communications, Inc. Verizon Wireless Device
+ATTR{idVendor}=="106c", ATTR{idProduct}=="3215", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Pantech Crux
+ATTR{idVendor}=="106c", ATTR{idProduct}=="f003", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Asus TF300 Transformer
+ATTR{idVendor}=="0b05", ATTR{idProduct}=="4c80", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Asus TF300 Transformer (USB debug mode)
+ATTR{idVendor}=="0b05", ATTR{idProduct}=="4c81", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Asus TF700 Transformer
+ATTR{idVendor}=="0b05", ATTR{idProduct}=="4c90", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Asus TF201 Transformer Prime (keyboard dock)
+ATTR{idVendor}=="0b05", ATTR{idProduct}=="4d00", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Asus TF201 Transformer Prime (tablet only)
+ATTR{idVendor}=="0b05", ATTR{idProduct}=="4d01", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Asus TFXXX Transformer Prime (unknown version)
+ATTR{idVendor}=="0b05", ATTR{idProduct}=="4d04", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Asus TF101 Eeepad Slider
+ATTR{idVendor}=="0b05", ATTR{idProduct}=="4e01", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Asus TF101 Eeepad Transformer
+ATTR{idVendor}=="0b05", ATTR{idProduct}=="4e0f", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Asus TF101 Eeepad Transformer (debug mode)
+ATTR{idVendor}=="0b05", ATTR{idProduct}=="4e1f", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Lenovo K1
+ATTR{idVendor}=="17ef", ATTR{idProduct}=="740a", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Lenovo ThinkPad Tablet
+ATTR{idVendor}=="17ef", ATTR{idProduct}=="741c", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Lenovo P700
+ATTR{idVendor}=="17ef", ATTR{idProduct}=="7497", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Lenovo Lifetab S9512
+ATTR{idVendor}=="17ef", ATTR{idProduct}=="74cc", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Huawei Honor U8860
+ATTR{idVendor}=="12d1", ATTR{idProduct}=="1051", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Huawei Mediapad (mode 0)
+ATTR{idVendor}=="12d1", ATTR{idProduct}=="360f", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Huawei Mediapad (mode 1)
+ATTR{idVendor}=="12d1", ATTR{idProduct}=="361f", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# ZTE V55 ID 1
+ATTR{idVendor}=="19d2", ATTR{idProduct}=="0244", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# ZTE V55 ID 2
+ATTR{idVendor}=="19d2", ATTR{idProduct}=="0245", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# HTC Zopo ZP100 (ID1)
+ATTR{idVendor}=="0bb4", ATTR{idProduct}=="0c02", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# HTC EVO 4G LTE
+ATTR{idVendor}=="0bb4", ATTR{idProduct}=="0c93", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# HTC EVO 4G LTE (second ID)
+ATTR{idVendor}=="0bb4", ATTR{idProduct}=="0ca8", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Hewlett-Packard HP Touchpad
+ATTR{idVendor}=="0bb4", ATTR{idProduct}=="685c", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Hewlett-Packard HP Touchpad (debug mode)
+ATTR{idVendor}=="0bb4", ATTR{idProduct}=="6860", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# HTC Zopo ZP100 (ID2)
+ATTR{idVendor}=="0bb4", ATTR{idProduct}=="2008", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# NEC FOMA N01A
+ATTR{idVendor}=="0409", ATTR{idProduct}=="0242", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# nVidia CM9-Adam
+ATTR{idVendor}=="0955", ATTR{idProduct}=="70a9", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Vizio VTAB1008
+ATTR{idVendor}=="0489", ATTR{idProduct}=="e040", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Various Viewpia DR/bq Kepler
+ATTR{idVendor}=="2207", ATTR{idProduct}=="0001", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+# Isabella Her Prototype
+ATTR{idVendor}=="0b20", ATTR{idProduct}=="ddee", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+
+# Autoprobe vendor-specific, communication and PTP devices
+ENV{ID_MTP_DEVICE}!="1", ENV{MTP_NO_PROBE}!="1", ENV{COLOR_MEASUREMENT_DEVICE}!="1", ENV{libsane_matched}!="yes", ATTR{bDeviceClass}=="00|02|06|ef|ff", PROGRAM="mtp-probe /sys$env{DEVPATH} $attr{busnum} $attr{devnum}", RESULT=="1", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
+
+LABEL="libmtp_rules_end"
diff --git a/meta/meta-mediatek-gpl/recipes-connectivity/libmtp/libmtp-1.1.5/glibc-2.20.patch b/meta/meta-mediatek-gpl/recipes-connectivity/libmtp/libmtp-1.1.5/glibc-2.20.patch
new file mode 100644
index 0000000..38b45c2
--- /dev/null
+++ b/meta/meta-mediatek-gpl/recipes-connectivity/libmtp/libmtp-1.1.5/glibc-2.20.patch
@@ -0,0 +1,36 @@
+
+Include config.h so we get the defines available for subsequent
+include files
+
+Fixes errors like
+
+| In file included from /home/ubuntu/work/upstream/openembedded-core/build/tmp-glibc/sysroots/beaglebone/usr/include/string.h:634:0,
+| from /home/ubuntu/work/upstream/openembedded-core/build/tmp-glibc/work/cortexa8t2hf-vfp-neon-oe-linux-gnueabi/libmtp/1.1.5-r0/libmtp-1.1.5/src/util.c:36:
+| /home/ubuntu/work/upstream/openembedded-core/build/tmp-glibc/work/cortexa8t2hf-vfp-neon-oe-linux-gnueabi/libmtp/1.1.5-r0/libmtp-1.1.5/src/util.h:29:7: error: expected identifier or '(' before '__extension
+__'
+| char *strndup (const char *s, size_t n);
+| ^
+| /home/ubuntu/work/upstream/openembedded-core/build/tmp-glibc/work/cortexa8t2hf-vfp-neon-oe-linux-gnueabi/libmtp/1.1.5-r0/libmtp-1.1.5/src/util.c:111:7: error: expected identifier or '(' before '__extensio
+n__'
+| char *strndup (const char *s, size_t n)
+| ^
+| make[2]: *** [libmtp_la-util.lo] Error 1
+
+
+Signed-off-by: Khem Raj <raj.khem@gmail.com>
+
+Upstream-Status: Pending
+
+Index: libmtp-1.1.5/src/util.c
+===================================================================
+--- libmtp-1.1.5.orig/src/util.c 2011-01-10 05:37:21.000000000 -0800
++++ libmtp-1.1.5/src/util.c 2014-09-03 23:50:44.703563888 -0700
+@@ -22,6 +22,8 @@
+ * Boston, MA 02111-1307, USA.
+ */
+
++#include "config.h"
++
+ /* MSVC does not have these */
+ #ifndef _MSC_VER
+ #include <sys/time.h>
diff --git a/meta/meta-mediatek-gpl/recipes-connectivity/libmtp/libmtp_1.1.5.bb b/meta/meta-mediatek-gpl/recipes-connectivity/libmtp/libmtp_1.1.5.bb
new file mode 100644
index 0000000..798b170
--- /dev/null
+++ b/meta/meta-mediatek-gpl/recipes-connectivity/libmtp/libmtp_1.1.5.bb
@@ -0,0 +1,58 @@
+# TODO: include debian's mtp-tools man page (needs xsltproc-native and
+# docbook-xsl-native, or we pregenerate it), add support for doxygen
+# generation fully with -natives
+DESCRIPTION = "libmtp is an Initiator implementation of the Media Transfer \
+Protocol (MTP) in the form of a library suitable primarily for POSIX \
+compliant operating systems"
+SUMMARY = "libmtp is an Initiator implementation of the Media Transfer Protocol (MTP)"
+HOMEPAGE = "http://libmtp.sourceforge.net/"
+LICENSE = "LGPL-2.1+"
+LIC_FILES_CHKSUM = "\
+ file://COPYING;md5=0448d3676bc0de00406af227d341a4d1 \
+ file://src/ptp.c;beginline=3;endline=22;md5=dafe6cfd1782f56471bb94ab06624c1f \
+ file://examples/albums.c;beginline=5;endline=21;md5=84f4e55dfec49e898b7f68a828c15620 \
+"
+
+DEPENDS += "libusb1 gettext-native"
+
+SCM_URI = "git://git.code.sf.net/p/libmtp/code"
+SRC_URI = "\
+ ${SOURCEFORGE_MIRROR}/${BPN}/${BPN}-${PV}.tar.gz \
+ file://69-libmtp.rules \
+ file://glibc-2.20.patch \
+"
+SRC_URI[md5sum] = "f80e45c0e6e5798c434bb1c26a7b602d"
+SRC_URI[sha256sum] = "787679171baf8b3cf2fcc03196c705ab4d7cbc969bd71f9d3696be1ce7f1c63a"
+
+# Currently we use a pregenerated rules file produced by mtp-hotplug, rather
+# than having to depend upon libmtp-native or run mtp-hotplug in a postinst.
+do_unpack[vardeps] += "skip_udev_rules_generation"
+do_unpack[postfuncs] += "skip_udev_rules_generation"
+
+skip_udev_rules_generation () {
+ sed -i -e '/^noinst_DATA=/,/util\/mtp-hotplug -H/d' ${S}/Makefile.am
+ cp ${WORKDIR}/69-libmtp.rules ${S}/
+}
+
+inherit autotools pkgconfig lib_package
+
+EXTRA_OECONF += "--disable-rpath"
+
+PACKAGECONFIG ?= "\
+ ${@bb.utils.contains('DISTRO_FEATURES', 'largefile$', 'largefile', '', d)} \
+"
+PACKAGECONFIG[doxygen] = "--enable-doxygen,--disable-doxygen"
+PACKAGECONFIG[largefile] = "--enable-largefile,--disable-largefile"
+PACKAGECONFIG[mtpz] = "--enable-mtpz,--disable-mtpz,libgcrypt"
+
+PACKAGES =+ "libmtp-common libmtp-runtime"
+
+RDEPENDS_${PN} += "libmtp-common"
+RRECOMMENDS_${PN} += "libmtp-runtime ${PN}-bin"
+FILES_${PN}-dbg += "${nonarch_base_libdir}/udev/.debug/*"
+FILES_libmtp-common = "${nonarch_base_libdir}/udev/rules.d/*"
+SUMMARY_libmtp-common = "The udev rules file for MTP devices"
+FILES_libmtp-runtime = "${nonarch_base_libdir}/udev/mtp-probe"
+DEPENDS_libmtp-runtime = "libmtp-common"
+SUMMARY_libmtp-runtime = "mtp-probe, used for the MTP udev rules"
+DESCRIPTION_libmtp-runtime = "This package provides mtp-probe, a program to probe newly connected device interfaces from userspace to determine if they are MTP devices, used for udev rules."
diff --git a/meta/meta-mediatek-gpl/recipes-devtools/android-tools/android-tools-avbtool.bb b/meta/meta-mediatek-gpl/recipes-devtools/android-tools/android-tools-avbtool.bb
new file mode 100644
index 0000000..b4b5a95
--- /dev/null
+++ b/meta/meta-mediatek-gpl/recipes-devtools/android-tools/android-tools-avbtool.bb
@@ -0,0 +1,28 @@
+inherit deploy
+
+DESCRIPTION = "Android Verify Boot sign tool from Android external/avb"
+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;protocol=https \
+ file://0001-security-boot-add-avbtool-support-hsm.patch \
+ file://tmp.patch \
+"
+SRCREV = "c68f082d910b674f9e5ecf05ebe77432dbbfe0b6"
+
+SRC_URI[sha256sum] = "833893127582352d05d925e36a2ba82d7837105ec8915cd82c7ba9abdddcf680"
+SRC_URI[md5sum] = "1935b6e637d9413cc48115e7602dec4f"
+S = "${WORKDIR}/git"
+
+do_compile () {
+}
+
+do_install () {
+}
+
+do_deploy () {
+ install -d ${DEPLOYDIR}
+ install -m 755 ${S}/avbtool -t ${DEPLOYDIR}
+}
+
+addtask deploy before do_build after do_compile
diff --git a/meta/meta-mediatek-gpl/recipes-devtools/android-tools/android-tools-avbtool/0001-security-boot-add-avbtool-support-hsm.patch b/meta/meta-mediatek-gpl/recipes-devtools/android-tools/android-tools-avbtool/0001-security-boot-add-avbtool-support-hsm.patch
new file mode 100644
index 0000000..a4e96e1
--- /dev/null
+++ b/meta/meta-mediatek-gpl/recipes-devtools/android-tools/android-tools-avbtool/0001-security-boot-add-avbtool-support-hsm.patch
@@ -0,0 +1,64 @@
+From 92eac8dd843a5f00b837b6eff79c91a500ba85e3 Mon Sep 17 00:00:00 2001
+From: darrenchen <Darren.Chen@mediatek.com>
+Date: Fri, 16 Nov 2018 11:48:02 +0800
+Subject: [PATCH] security boot: add avbtool support hsm
+
+add avbtool support hsm
+modify signing_helper to signing_helper_with_files
+
+Test: OK
+
+Signed-off-by: Darren Chen <Darren.Chen@mediatek.com>
+CR-Id: AUTO00000778
+---
+ avbtool | 27 ++++++++++++++++-----------
+ 1 file changed, 16 insertions(+), 11 deletions(-)
+
+diff --git a/avbtool b/avbtool
+index 10ff39a..81f1f7b 100755
+--- a/avbtool
++++ b/avbtool
+@@ -420,24 +420,29 @@ def raw_sign(signing_helper, algorithm_name, signature_num_bytes, key_path,
+ """
+ p = None
+ if signing_helper is not None:
++ signing_file = tempfile.NamedTemporaryFile()
++ signing_file.write(str(raw_data_to_sign))
++ signing_file.flush()
+ p = subprocess.Popen(
+- [signing_helper, algorithm_name, key_path],
+- stdin=subprocess.PIPE,
+- stdout=subprocess.PIPE,
+- stderr=subprocess.PIPE)
++ [signing_helper, os.getenv("VERIFIED_KEY"), "none", "raw", signing_file.name])
++ retcode = p.wait()
++ if retcode != 0:
++ raise AvbError('Error signing')
++ signing_file.seek(0)
++ signature = bytearray(signing_file.read())
+ else:
+ p = subprocess.Popen(
+ ['openssl', 'rsautl', '-sign', '-inkey', key_path, '-raw'],
+ stdin=subprocess.PIPE,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE)
+- (pout, perr) = p.communicate(str(raw_data_to_sign))
+- retcode = p.wait()
+- if retcode != 0:
+- raise AvbError('Error signing: {}'.format(perr))
+- signature = bytearray(pout)
+- if len(signature) != signature_num_bytes:
+- raise AvbError('Error signing: Invalid length of signature')
++ (pout, perr) = p.communicate(str(raw_data_to_sign))
++ retcode = p.wait()
++ if retcode != 0:
++ raise AvbError('Error signing')
++ signature = bytearray(pout)
++ if len(signature) != signature_num_bytes:
++ raise AvbError('Error signing: Invalid length of signature')
+ return signature
+
+
+--
+2.18.0
+
diff --git a/meta/meta-mediatek-gpl/recipes-devtools/android-tools/android-tools-avbtool/tmp.patch b/meta/meta-mediatek-gpl/recipes-devtools/android-tools/android-tools-avbtool/tmp.patch
new file mode 100644
index 0000000..10a3e67
--- /dev/null
+++ b/meta/meta-mediatek-gpl/recipes-devtools/android-tools/android-tools-avbtool/tmp.patch
@@ -0,0 +1,18 @@
+diff --git a/avbtool b/avbtool
+index 81f1f7b..bcf447b 100755
+--- a/avbtool
++++ b/avbtool
+@@ -1576,7 +1576,12 @@ class AvbVBMetaHeader(object):
+ Exception: If the given data is malformed.
+ """
+ assert struct.calcsize(self.FORMAT_STRING) == self.SIZE
+-
++ if data:
++ if len(data)!=256:
++ print ('data length',len(data))
++ raise AvbError('data length is not 256.')
++ else:
++ print ('data length',len(data))
+ if data:
+ (self.magic, self.required_libavb_version_major,
+ self.required_libavb_version_minor,
diff --git a/meta/meta-mediatek-gpl/recipes-devtools/android-tools/android-tools-fastboot/disable-selinux-support.patch b/meta/meta-mediatek-gpl/recipes-devtools/android-tools/android-tools-fastboot/disable-selinux-support.patch
new file mode 100644
index 0000000..738f575
--- /dev/null
+++ b/meta/meta-mediatek-gpl/recipes-devtools/android-tools/android-tools-fastboot/disable-selinux-support.patch
@@ -0,0 +1,137 @@
+diff --git a/extras/ext4_utils/make_ext4fs.c b/extras/ext4_utils/make_ext4fs.c
+index b2d1426..94e92d6 100644
+--- a/extras/ext4_utils/make_ext4fs.c
++++ b/extras/ext4_utils/make_ext4fs.c
+@@ -59,9 +59,11 @@
+
+ #else
+
++#if 0
+ #include <selinux/selinux.h>
+ #include <selinux/label.h>
+ #include <selinux/android.h>
++#endif
+
+ #define O_BINARY 0
+
+@@ -178,6 +180,7 @@ static u32 build_directory_structure(const char *full_path, const char *dir_path
+ error("can't set android permissions - built without android support");
+ #endif
+ }
++#if 0
+ #ifndef USE_MINGW
+ if (sehnd) {
+ if (selabel_lookup(sehnd, &dentries[i].secon, dentries[i].path, stat.st_mode) < 0) {
+@@ -188,6 +191,7 @@ static u32 build_directory_structure(const char *full_path, const char *dir_path
+ printf("Labeling %s as %s\n", dentries[i].path, dentries[i].secon);
+ }
+ #endif
++#endif
+
+ if (S_ISREG(stat.st_mode)) {
+ dentries[i].file_type = EXT4_FT_REG_FILE;
+@@ -229,10 +233,12 @@ static u32 build_directory_structure(const char *full_path, const char *dir_path
+ dentries[0].file_type = EXT4_FT_DIR;
+ dentries[0].uid = 0;
+ dentries[0].gid = 0;
++#if 0
+ if (sehnd) {
+ if (selabel_lookup(sehnd, &dentries[0].secon, dentries[0].path, dentries[0].mode) < 0)
+ error("cannot lookup security context for %s", dentries[0].path);
+ }
++#endif
+ entries++;
+ dirs++;
+ }
+@@ -270,9 +276,11 @@ static u32 build_directory_structure(const char *full_path, const char *dir_path
+ dentries[i].mtime);
+ if (ret)
+ error("failed to set permissions on %s\n", dentries[i].path);
++#if 0
+ ret = inode_set_selinux(entry_inode, dentries[i].secon);
+ if (ret)
+ error("failed to set SELinux context on %s\n", dentries[i].path);
++#endif
+
+ free(dentries[i].path);
+ free(dentries[i].full_path);
+@@ -562,6 +570,7 @@ int make_ext4fs_internal(int fd, const char *_directory,
+ root_mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
+ inode_set_permissions(root_inode_num, root_mode, 0, 0, 0);
+
++#if 0
+ #ifndef USE_MINGW
+ if (sehnd) {
+ char *secontext = NULL;
+@@ -578,6 +587,7 @@ int make_ext4fs_internal(int fd, const char *_directory,
+ freecon(secontext);
+ }
+ #endif
++#endif
+
+ ext4_update_free();
+
+diff --git a/extras/ext4_utils/make_ext4fs_main.c b/extras/ext4_utils/make_ext4fs_main.c
+index b6c740d..ce31764 100644
+--- a/extras/ext4_utils/make_ext4fs_main.c
++++ b/extras/ext4_utils/make_ext4fs_main.c
+@@ -29,6 +29,7 @@
+ #include <private/android_filesystem_config.h>
+ #endif
+
++#if 0
+ #ifndef USE_MINGW
+ #include <selinux/selinux.h>
+ #include <selinux/label.h>
+@@ -36,6 +37,7 @@
+ #else
+ struct selabel_handle;
+ #endif
++#endif
+
+ #include "make_ext4fs.h"
+ #include "ext4_utils.h"
+@@ -72,9 +74,11 @@ int main(int argc, char **argv)
+ int exitcode;
+ int verbose = 0;
+ struct selabel_handle *sehnd = NULL;
++#if 0
+ #ifndef USE_MINGW
+ struct selinux_opt seopts[] = { { SELABEL_OPT_PATH, "" } };
+ #endif
++#endif
+
+ while ((opt = getopt(argc, argv, "l:j:b:g:i:I:L:a:S:fwzJsctv")) != -1) {
+ switch (opt) {
+@@ -131,6 +135,7 @@ int main(int argc, char **argv)
+ fprintf(stderr, "Warning: -t (initialize inode tables) is deprecated\n");
+ break;
+ case 'S':
++#if 0
+ #ifndef USE_MINGW
+ seopts[0].value = optarg;
+ sehnd = selabel_open(SELABEL_CTX_FILE, seopts, 1);
+@@ -139,6 +144,7 @@ int main(int argc, char **argv)
+ exit(EXIT_FAILURE);
+ }
+ #endif
++#endif
+ break;
+ case 'v':
+ verbose = 1;
+@@ -149,6 +155,7 @@ int main(int argc, char **argv)
+ }
+ }
+
++#if 0
+ #if !defined(HOST)
+ // Use only if -S option not requested
+ if (!sehnd && mountpoint) {
+@@ -160,6 +167,7 @@ int main(int argc, char **argv)
+ }
+ }
+ #endif
++#endif
+
+ if (wipe && sparse) {
+ fprintf(stderr, "Cannot specifiy both wipe and sparse\n");
diff --git a/meta/meta-mediatek-gpl/recipes-devtools/android-tools/android-tools-fastboot/reboot-syscall.patch b/meta/meta-mediatek-gpl/recipes-devtools/android-tools/android-tools-fastboot/reboot-syscall.patch
new file mode 100644
index 0000000..0055416
--- /dev/null
+++ b/meta/meta-mediatek-gpl/recipes-devtools/android-tools/android-tools-fastboot/reboot-syscall.patch
@@ -0,0 +1,25 @@
+Subject: port android_reboot() to call the reboot syscall via syscall() (glibc) rather than __reboot (bionic)
+Author: Loïc Minier <loic.minier@ubuntu.com>
+
+--- a/core/libcutils/android_reboot.c
++++ b/core/libcutils/android_reboot.c
+@@ -21,6 +21,8 @@
+ #include <fcntl.h>
+ #include <stdio.h>
+ #include <string.h>
++#include <linux/reboot.h>
++#include <sys/syscall.h>
+
+ #include <cutils/android_reboot.h>
+
+@@ -121,8 +123,8 @@
+ break;
+
+ case ANDROID_RB_RESTART2:
+- ret = __reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,
+- LINUX_REBOOT_CMD_RESTART2, arg);
++ ret = syscall(SYS_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,
++ LINUX_REBOOT_CMD_RESTART2, arg);
+ break;
+
+ default:
diff --git a/meta/meta-mediatek-gpl/recipes-devtools/android-tools/android-tools-fastboot/remove-libselinux.patch b/meta/meta-mediatek-gpl/recipes-devtools/android-tools/android-tools-fastboot/remove-libselinux.patch
new file mode 100644
index 0000000..0544675
--- /dev/null
+++ b/meta/meta-mediatek-gpl/recipes-devtools/android-tools/android-tools-fastboot/remove-libselinux.patch
@@ -0,0 +1,13 @@
+diff --git a/debian/makefiles/fastboot.mk b/debian/makefiles/fastboot.mk
+index 9e8b751..9f047ed 100644
+--- a/debian/makefiles/fastboot.mk
++++ b/debian/makefiles/fastboot.mk
+@@ -37,7 +37,7 @@ CPPFLAGS+= -I../mkbootimg
+ CPPFLAGS+= -I../../extras/ext4_utils/
+ CPPFLAGS+= -I../libsparse/include/
+
+-LIBS+= -lz -lselinux
++LIBS+= -lz
+
+ OBJS= $(SRCS:.c=.o)
+
diff --git a/meta/meta-mediatek-gpl/recipes-devtools/android-tools/android-tools-fastboot_4.2.2.bb b/meta/meta-mediatek-gpl/recipes-devtools/android-tools/android-tools-fastboot_4.2.2.bb
new file mode 100644
index 0000000..3a429d5
--- /dev/null
+++ b/meta/meta-mediatek-gpl/recipes-devtools/android-tools/android-tools-fastboot_4.2.2.bb
@@ -0,0 +1,60 @@
+DESCRIPTION = "Different utilities from Android - based on the corresponding ubuntu \
+package"
+SECTION = "console/utils"
+LICENSE = "Apache-2.0 & GPL-2.0 & BSD-2-Clause & BSD-3-Clause"
+LIC_FILES_CHKSUM = " \
+ file://${COMMON_LICENSE_DIR}/Apache-2.0;md5=89aea4e17d99a7cacdbeed46a0096b10 \
+ file://${COMMON_LICENSE_DIR}/GPL-2.0;md5=801f80980d171dd6425610833a22dbe6 \
+ file://${COMMON_LICENSE_DIR}/BSD-2-Clause;md5=8bef8e6712b1be5aa76af1ebde9d6378 \
+ file://${COMMON_LICENSE_DIR}/BSD-3-Clause;md5=550794465ba0ec5312d6919e203a55f9 \
+ file://${WORKDIR}/debian/copyright;md5=141efd1050596168ca05ced04e4f498b \
+"
+
+DEPENDS = "zlib openssl"
+
+# Use same version than ubuntu does here
+BASE_PV = "4.2.2+git20130218"
+PV = "${BASE_PV}-3ubuntu13"
+
+ALLOW_EMPTY_${PN} = "1"
+
+SRC_URI = " \
+ https://launchpad.net/ubuntu/+archive/primary/+files/android-tools_${BASE_PV}.orig.tar.xz;name=source \
+ https://launchpad.net/ubuntu/+archive/primary/+files/android-tools_${PV}.debian.tar.gz;name=debian \
+ file://reboot-syscall.patch \
+ file://disable-selinux-support.patch \
+ file://remove-libselinux.patch;patchdir=.. \
+"
+S = "${WORKDIR}/android-tools"
+
+SRC_URI[source.md5sum] = "0e653b129ab0c95bdffa91410c8b55be"
+SRC_URI[source.sha256sum] = "9bfba987e1351b12aa983787b9ae4424ab752e9e646d8e93771538dc1e5d932f"
+SRC_URI[debian.md5sum] = "5e409d01caf3c33fc60a2100464754ff"
+SRC_URI[debian.sha256sum] = "320757edc8af015f40335c41dc96bf37e2d50c9f3a40a31e64264ff6e2dba5e3"
+
+do_compile() {
+ # Setting both variables below causing our makefiles to not work with implicit make
+ # rules
+ unset CFLAGS
+ unset CPPFLAGS
+
+ sed -i "s%^CPPFLAGS+= -I/usr/include%# we don't want to include headers from host CPPFLAGS+= -I/usr/include%g" ${WORKDIR}/debian/makefiles/ext4_utils.mk
+
+ oe_runmake -f ${WORKDIR}/debian/makefiles/fastboot.mk -C ${S}/core/fastboot clean
+ oe_runmake -f ${WORKDIR}/debian/makefiles/fastboot.mk -C ${S}/core/fastboot
+}
+
+do_install() {
+ install -d ${D}${bindir}
+ install -m 0755 ${S}/core/fastboot/fastboot ${D}${bindir}
+}
+
+inherit deploy
+
+do_deploy () {
+ install -d ${DEPLOYDIR}
+ install -m 0755 ${S}/core/fastboot/fastboot ${DEPLOYDIR}/fastboot-linux-arm
+}
+
+addtask deploy before do_build after do_compile
+
diff --git a/meta/meta-mediatek-gpl/recipes-devtools/android-tools/android-tools-fsutils/build.patch b/meta/meta-mediatek-gpl/recipes-devtools/android-tools/android-tools-fsutils/build.patch
new file mode 100644
index 0000000..50c2c7d
--- /dev/null
+++ b/meta/meta-mediatek-gpl/recipes-devtools/android-tools/android-tools-fsutils/build.patch
@@ -0,0 +1,49 @@
+diff --git a/Makefile.am b/Makefile.am
+new file mode 100644
+index 0000000..361667f
+--- /dev/null
++++ b/Makefile.am
+@@ -0,0 +1 @@
++SUBDIRS = libsparse/
+diff --git a/configure.ac b/configure.ac
+new file mode 100644
+index 0000000..cc354e3
+--- /dev/null
++++ b/configure.ac
+@@ -0,0 +1,12 @@
++AC_INIT([img2simg], [1.0])
++AM_INIT_AUTOMAKE([foreign])
++AC_PROG_CC
++AC_PROG_RANLIB
++AC_DISABLE_SHARED
++AC_ENABLE_STATIC
++LT_INIT
++AC_CONFIG_FILES([
++ Makefile
++ libsparse/Makefile
++])
++AC_OUTPUT
+diff --git a/libsparse/Makefile.am b/libsparse/Makefile.am
+new file mode 100644
+index 0000000..02bea1a
+--- /dev/null
++++ b/libsparse/Makefile.am
+@@ -0,0 +1,18 @@
++lib_LIBRARIES = libsparse.a
++libsparse_a_CPPFLAGS = -I$(top_srcdir)/libsparse/include
++libsparse_a_CFLAGS = -Werror
++libsparse_a_SOURCES = \
++ backed_block.c \
++ output_file.c \
++ sparse.c \
++ sparse_crc32.c \
++ sparse_err.c \
++ sparse_read.c
++
++bin_PROGRAMS = img2simg simg2img
++img2simg_SOURCES = img2simg.c
++img2simg_CPPFLAGS = -I$(top_srcdir)/libsparse/include
++img2simg_LDADD = libsparse.a -lz
++simg2img_SOURCES = simg2img.c
++simg2img_CPPFLAGS = -I$(top_srcdir)/libsparse/include
++simg2img_LDADD = libsparse.a -lz
diff --git a/meta/meta-mediatek-gpl/recipes-devtools/android-tools/android-tools-fsutils_git.bb b/meta/meta-mediatek-gpl/recipes-devtools/android-tools/android-tools-fsutils_git.bb
new file mode 100644
index 0000000..15252bd
--- /dev/null
+++ b/meta/meta-mediatek-gpl/recipes-devtools/android-tools/android-tools-fsutils_git.bb
@@ -0,0 +1,14 @@
+DESCRIPTION = "android-tools-fsutils libraries"
+LICENSE = "Apache-2.0"
+LIC_FILES_CHKSUM = "file://NOTICE;md5=c1a3ff0b97f199c7ebcfdd4d3fed238e"
+SRC_URI = " \
+ git://android.googlesource.com/platform/system/core;protocol=https \
+ file://build.patch \
+"
+SRCREV = "c6160d2a0ef648ccb3d217c589c60b5c00b80387"
+S = "${WORKDIR}/git"
+FILES_${PN} = "${bindir}/* ${libdir}/*"
+DEPENDS += "zlib"
+BBCLASSEXTEND = "native nativesdk"
+
+inherit autotools
diff --git a/meta/meta-mediatek-gpl/recipes-devtools/android-tools/platform-tools_r26.0.2.bb b/meta/meta-mediatek-gpl/recipes-devtools/android-tools/platform-tools_r26.0.2.bb
new file mode 100644
index 0000000..5753c5f
--- /dev/null
+++ b/meta/meta-mediatek-gpl/recipes-devtools/android-tools/platform-tools_r26.0.2.bb
@@ -0,0 +1,42 @@
+DESCRIPTION = "Android Platform Tools"
+LICENSE = "Apache-2.0 & GPL-2.0 & BSD-2-Clause & BSD-3-Clause"
+
+LIC_FILES_CHKSUM = "file://${S}/platform-tools-linux/platform-tools/NOTICE.txt;md5=d4b39e3d79095f051d1f61901cec410e"
+
+BBCLASSEXTEND = "native"
+
+SRC_URI = " \
+ https://dl.google.com/android/repository/platform-tools_${PV}-windows.zip;name=platform-tools-windows \
+ https://dl.google.com/android/repository/platform-tools_${PV}-darwin.zip;name=platform-tools-darwin \
+ https://dl.google.com/android/repository/platform-tools_${PV}-linux.zip;name=platform-tools-linux \
+"
+
+SRC_URI[platform-tools-windows.md5sum] = "4a2d2e09d3ffdce8252c9136754a1ce9"
+SRC_URI[platform-tools-windows.sha256sum] = "4850c695724ad0328d9100cc3b4475dcd1af1bec904675362259595a3e03ae2e"
+SRC_URI[platform-tools-darwin.md5sum] = "00fa1426da56ed9477f65219213ae1a5"
+SRC_URI[platform-tools-darwin.sha256sum] = "a6d0504e560713af2a3ae71449bcadf011b50ba78f7bf303a9d6d69bf855c73f"
+SRC_URI[platform-tools-linux.md5sum] = "ef952bb31497f7535e061ad0e712bed8"
+SRC_URI[platform-tools-linux.sha256sum] = "63b15a38c2b64e6ec8b54febe9f69fce5fe6c898c554c73b826b49daf7b52519"
+
+SSTATE_DUPWHITELIST += "${DEPLOY_DIR_IMAGE}"
+
+do_unpack () {
+ unzip -q ${DL_DIR}/platform-tools_${PV}-linux.zip -d ${S}/platform-tools-linux
+ unzip -q ${DL_DIR}/platform-tools_${PV}-darwin.zip -d ${S}/platform-tools-darwin
+ unzip -q ${DL_DIR}/platform-tools_${PV}-windows.zip -d ${S}/platform-tools-windows
+}
+
+inherit deploy
+
+do_deploy () {
+ install -d ${DEPLOYDIR}
+ install -m 0755 ${S}/platform-tools-linux/platform-tools/fastboot ${DEPLOYDIR}/fastboot-linux-x86_64
+ install -m 0755 ${S}/platform-tools-darwin/platform-tools/fastboot ${DEPLOYDIR}/fastboot-darwin
+ install -m 0755 ${S}/platform-tools-windows/platform-tools/fastboot.exe ${DEPLOYDIR}/fastboot.exe
+ install -m 0755 ${S}/platform-tools-linux/platform-tools/adb ${DEPLOYDIR}/adb-linux-x86_64
+ install -m 0755 ${S}/platform-tools-darwin/platform-tools/adb ${DEPLOYDIR}/adb-darwin
+ install -m 0755 ${S}/platform-tools-windows/platform-tools/adb.exe ${DEPLOYDIR}/adb.exe
+}
+
+addtask deploy before do_build after do_compile
+
diff --git a/meta/meta-mediatek-gpl/recipes-devtools/datool/fbtool.bb b/meta/meta-mediatek-gpl/recipes-devtools/datool/fbtool.bb
new file mode 100644
index 0000000..655b3a6
--- /dev/null
+++ b/meta/meta-mediatek-gpl/recipes-devtools/datool/fbtool.bb
@@ -0,0 +1,21 @@
+inherit deploy externalsrc
+
+DESCRIPTION = "MediaTek fastboot DA tool"
+EXTERNALSRC = "${TOPDIR}/../src/devtools/datool"
+EXTERNALSRC_BUILD = "${TOPDIR}/../src/devtools/datool"
+
+LICENSE = "BSD-3-Clause"
+LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/BSD-3-Clause;md5=550794465ba0ec5312d6919e203a55f9"
+BBCLASSEXTEND = "native nativesdk"
+ALLOW_EMPTY_${PN} = "1"
+
+do_install () {
+}
+
+do_deploy () {
+ install -d ${DEPLOYDIR}
+ install -m 0644 fbtool.py -t ${DEPLOYDIR}
+ cp -af pyserial ${DEPLOYDIR}
+}
+
+addtask deploy before do_build after do_compile
diff --git a/meta/meta-mediatek-gpl/recipes-devtools/gcc-arm-none-eabi/gcc-arm-none-eabi-native_4.8.4-2014.07.25.bb b/meta/meta-mediatek-gpl/recipes-devtools/gcc-arm-none-eabi/gcc-arm-none-eabi-native_4.8.4-2014.07.25.bb
new file mode 100644
index 0000000..24bc24c
--- /dev/null
+++ b/meta/meta-mediatek-gpl/recipes-devtools/gcc-arm-none-eabi/gcc-arm-none-eabi-native_4.8.4-2014.07.25.bb
@@ -0,0 +1,29 @@
+inherit native
+
+DESCRIPTION = "ARM's Baremetal GCC"
+
+LICENSE = "GPL-2.0 & GPL-3.0 & GPL-2.0-with-GCC-exception & GPL-3.0-with-GCC-exception & LGPL-2.0 & LGPL-2.1 & LGPL-3.0 & MIT"
+LIC_FILES_CHKSUM = "file://share/doc/gcc-arm-none-eabi/license.txt;md5=cba77c7fde3ed13e866b04a2f3d93918"
+SRC_URI = "https://launchpad.net/gcc-arm-embedded/4.8/4.8-2014-q3-update/+download/gcc-arm-none-eabi-4_8-2014q3-20140805-linux.tar.bz2;name=gcc-arm-none"
+SRC_URI[gcc-arm-none.md5sum] = "acc8c8ff45f8801e2155934214309a87"
+GCC_ARM_NONE_TOOLCHAIN_VERSION = "4_8-2014q3"
+GCC_ARM_NONE_TOOLCHAIN = "gcc-arm-none-eabi"
+
+S = "${WORKDIR}/${GCC_ARM_NONE_TOOLCHAIN}-${GCC_ARM_NONE_TOOLCHAIN_VERSION}"
+B = "${WORKDIR}/${GCC_ARM_NONE_TOOLCHAIN}-${GCC_ARM_NONE_TOOLCHAIN_VERSION}"
+
+
+#UNINATIVE_LOADER = ""
+
+do_install () {
+ install -d ${D}/${bindir}/${GCC_ARM_NONE_TOOLCHAIN}
+ cp -r ${S}/. ${D}/${bindir}/${GCC_ARM_NONE_TOOLCHAIN}
+ rm -rf ${D}/${bindir}/${GCC_ARM_NONE_TOOLCHAIN}/oe-logs
+ rm -rf ${D}/${bindir}/${GCC_ARM_NONE_TOOLCHAIN}/oe-workdir
+ rm -rf ${D}/${bindir}/${GCC_ARM_NONE_TOOLCHAIN}/singletask.lock
+}
+
+
+INSANE_SKIP_${PN} = "already-stripped"
+
+FILES_${PN} = "${bindir}/${GCC_ARM_NONE_TOOLCHAIN}/*"
diff --git a/meta/meta-mediatek-gpl/recipes-devtools/gobject-introspection-prebuilt/gobject-introspection-prebuilt.bb b/meta/meta-mediatek-gpl/recipes-devtools/gobject-introspection-prebuilt/gobject-introspection-prebuilt.bb
new file mode 100755
index 0000000..3400731
--- /dev/null
+++ b/meta/meta-mediatek-gpl/recipes-devtools/gobject-introspection-prebuilt/gobject-introspection-prebuilt.bb
@@ -0,0 +1,30 @@
+SUMMARY = "gobject-introspection prebuilt"
+DESCRIPTION = "gobject-introspection cross-compile build fail on MAC OS, use prebuilt rpm instead."
+
+LICENSE = "LGPLv2+ & GPLv2+"
+PREBUILT_PATH = "${TOPDIR}/../prebuilt/gobject/gobject-introspection"
+
+inherit workonsrc
+WORKONSRC = "${TOPDIR}/../src/gobject/gobject-introspection/"
+
+DEPENDS = "rpm-native glib-2.0"
+
+do_configure () {
+ :
+}
+
+do_compile () {
+ :
+}
+
+do_install () {
+ oe_runmake \
+ D=${D} bindir=${bindir} libdir=${libdir} \
+ includedir=${includedir} datadir=${datadir} install
+}
+
+FILES_${PN} = "${bindir}/* \
+ ${libdir}/* \
+ ${includedir}/* \
+ "
+INSANE_SKIP_${PN} = "already-stripped"
diff --git a/meta/meta-mediatek-gpl/recipes-devtools/python/python3-pycairo_1.15.4.bb b/meta/meta-mediatek-gpl/recipes-devtools/python/python3-pycairo_1.15.4.bb
new file mode 100644
index 0000000..a6c9e5a
--- /dev/null
+++ b/meta/meta-mediatek-gpl/recipes-devtools/python/python3-pycairo_1.15.4.bb
@@ -0,0 +1,31 @@
+SUMMARY = "Python bindings for the Cairo canvas library"
+HOMEPAGE = "http://cairographics.org/pycairo"
+BUGTRACKER = "http://bugs.freedesktop.org"
+SECTION = "python-devel"
+LICENSE = "LGPLv2.1 & MPLv1.1"
+LIC_FILES_CHKSUM = "file://COPYING;md5=f2e071ab72978431b294a0d696327421 \
+ file://COPYING-LGPL-2.1;md5=fad9b3332be894bab9bc501572864b29 \
+ file://COPYING-MPL-1.1;md5=bfe1f75d606912a4111c90743d6c7325"
+
+# cairo >= 1.14
+DEPENDS = "cairo"
+
+SRC_URI = "https://github.com/pygobject/pycairo/releases/download/v${PV}/pycairo-${PV}.tar.gz"
+UPSTREAM_CHECK_URI = "https://github.com/pygobject/pycairo/releases/"
+
+SRC_URI[md5sum] = "89f04740078fb5f4e4dd92a0c4d3b537"
+SRC_URI[sha256sum] = "ee4c3068c048230e5ce74bb8994a024711129bde1af1d76e3276c7acd81c4357"
+
+S = "${WORKDIR}/pycairo-${PV}"
+
+inherit setuptools3 pkgconfig
+
+CFLAGS += "-fPIC"
+
+BBCLASSEXTEND = "native"
+
+do_install_append() {
+ install -d ${D}${includedir}/pycairo/
+ install -m 0644 ${D}${datadir}/include/pycairo/py3cairo.h ${D}${includedir}/pycairo/
+}
+FILES_${PN} += "${datadir}/include/pycairo/py3cairo.h"
diff --git a/meta/meta-mediatek-gpl/recipes-kernel/linux/linux-mtk-extension.inc b/meta/meta-mediatek-gpl/recipes-kernel/linux/linux-mtk-extension.inc
new file mode 100644
index 0000000..756a1b1
--- /dev/null
+++ b/meta/meta-mediatek-gpl/recipes-kernel/linux/linux-mtk-extension.inc
@@ -0,0 +1,97 @@
+inherit kernel externalsrc kernel-fitimage-extension recovery-kernel-fitimage
+
+DEPENDS_append_aarch64 = " libgcc"
+KERNEL_CC_append_aarch64 = " ${TOOLCHAIN_OPTIONS}"
+KERNEL_LD_append_aarch64 = " ${TOOLCHAIN_OPTIONS}"
+
+LICENSE = "GPL-2.0"
+LIC_FILES_CHKSUM = "file://COPYING;md5=d7810fab7487fb0aad327b76f1be7cd7"
+EXTERNALSRC = "${KERNEL_SRC}"
+STAGING_KERNEL_DIR = "${KERNEL_SRC}"
+LINUX_VERSION_EXTENSION = "-custom"
+KERNEL_EXTRA_ARGS = "dtbs"
+KERNEL_CONFIG_COMMAND = "oe_runmake_call -C ${S} O=${B} ${KBUILD_DEFCONFIG}"
+
+DST_IMG_KEY_FILE = "${TOPDIR}/../src/devtools/nfsb/rsa.key"
+MTD_DST_IMG_KEY_FILE = "${TOPDIR}/../src/devtools/nfsb/mtd_verity/rsa.key"
+
+do_configure_prepend() {
+ install -d ${TMPDIR}/work-shared/${MACHINE}
+ ln -nfs ${STAGING_KERNEL_DIR} ${TMPDIR}/work-shared/${MACHINE}/kernel-source
+}
+
+do_compile_prepend() {
+
+ SRC_IMG_KEY_FILE=""
+
+ 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
+
+ #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
+ echo "SECURE_BOOT_ENABLE is ${SECURE_BOOT_ENABLE},SECURE_BOOT_TYPE is ${SECURE_BOOT_TYPE}"
+ if [ "${SECURE_BOOT_ENABLE}" = "yes" ] && [ "${SECURE_BOOT_TYPE}" = "avb" ]; then
+ ENABLE_DM_VERITY="yes"
+ fi
+ echo "ENABLE_DM_VERITY is ${ENABLE_DM_VERITY}"
+ if [ "${SECURE_BOOT_ENABLE}" = "yes" ] && [ "${ENABLE_DM_NFSB}" = "yes" ]; then
+ if ! grep -Fxq "CONFIG_DM_NFSB=y" ${B}/.config ; then
+ echo "Error: If SECURE_BOOT_ENABLE is set to yes,kernel must be configed CONFIG_DM_NFSB=y"
+ exit 1
+ fi
+
+ if test -e ${SRC_IMG_KEY_FILE}; then
+ cp ${SRC_IMG_KEY_FILE} ${DST_IMG_KEY_FILE}
+ python ${TOPDIR}/../src/devtools/nfsb/pretreat-key.py ${TOPDIR} ${KERNEL_SRC}
+ fi
+ else
+ if grep -Fxq "CONFIG_DM_NFSB=y" ${B}/.config ; then
+ echo "Error: If SECURE_BOOT_ENABLE is set to no,kernel must be configed CONFIG_DM_NFSB=n"
+ exit 1
+ fi
+ fi
+
+ if [ "${SECURE_BOOT_ENABLE}" = "yes" ] && [ "${ENABLE_DM_VERITY}" = "yes" ]; then
+ if ! grep -Fxq "CONFIG_DM_VERITY=y" ${B}/.config ; then
+ echo "Error: If SECURE_BOOT_ENABLE is set to yes,kernel must be configed CONFIG_DM_VERITY=y"
+ exit 1
+ fi
+ fi
+
+ if [ "${ENABLE_MTD_VERITY}" = "yes" ]; then
+ echo "ENABLE_MTD_VERITY is abandoned, plese use ENABLE_ROOTFS_CHECK in [project].config and CONFIG_ROOTFS_CHECK in kernel config"
+ exit 1
+ fi
+
+ if [ "${SECURE_BOOT_ENABLE}" = "yes" ] && [ "${ENABLE_ROOTFS_CHECK}" = "yes" ]; then
+ if ! grep -Fxq "CONFIG_ROOTFS_CHECK=y" ${B}/.config ; then
+ echo "Error: If SECURE_BOOT_ENABLE and ENABLE_ROOTFS_CHECK is set to yes,kernel must be configed CONFIG_ROOTFS_CHECK=y"
+ exit 1
+ fi
+
+ if test -e ${SRC_IMG_KEY_FILE}; then
+ cp ${SRC_IMG_KEY_FILE} ${MTD_DST_IMG_KEY_FILE}
+ python ${TOPDIR}/../src/devtools/nfsb/mtd_verity/pretreat-key.py ${TOPDIR} ${KERNEL_SRC}
+ fi
+ else
+ if grep -Fxq "CONFIG_ROOTFS_CHECK=y" ${B}/.config ; then
+ echo "Error: If SECURE_BOOT_ENABLE and ENABLE_ROOTFS_CHECK is set to no,kernel must be configed CONFIG_ROOTFS_CHECK=n"
+ exit 1
+ fi
+ fi
+
+ if [ "${ENABLE_USRDATA_DM_CRYPT}" = "yes" ]; then
+ if ! grep -Fxq "CONFIG_DM_CRYPT=y" ${B}/.config ; then
+ echo "Error: If ENABLE_USRDATA_DM_CRYPT is set to yes,kernel must be configed CONFIG_DM_CRYPT=y"
+ exit 1
+ fi
+ fi
+}
diff --git a/meta/meta-mediatek-gpl/recipes-kernel/linux/linux-mtk-extension_3.18.bb b/meta/meta-mediatek-gpl/recipes-kernel/linux/linux-mtk-extension_3.18.bb
new file mode 100644
index 0000000..694ff27
--- /dev/null
+++ b/meta/meta-mediatek-gpl/recipes-kernel/linux/linux-mtk-extension_3.18.bb
@@ -0,0 +1,11 @@
+require linux-mtk-extension.inc
+
+KERNEL_SRC = "${TOPDIR}/../src/kernel/linux/v3.18"
+LINUX_VERSION = "3.18.22"
+
+#align with kernel4.9 to avoid gcc7.2 checking
+KERNEL_CC_append += "-Wno-format-truncation -Wno-frame-address -Wno-format-overflow -Wno-int-in-bool-context"
+#align with kernel 3.18 to avoid gcc checking
+KERNEL_CC_append += "-Wno-format -Wno-duplicate-decl-specifier -Wno-return-type -Wno-unused-variable -Wno-unused-result -Wno-unused-function -Wno-incompatible-pointer-types -Wno-array-bounds -Wno-unused-value -Wno-array-bounds -Wno-switch-bool -Wno-unused-label -Wno-declaration-after-statement -Wno-misleading-indentation -Wno-declaration-after-statement -Wno-implicit-int -Wno-uninitialized"
+#in drm_dp_mst_topology.c, function strncat trigger the warning
+KERNEL_CC_append += "-Wno-stringop-overflow"
diff --git a/meta/meta-mediatek-gpl/recipes-kernel/linux/linux-mtk-extension_4.14.bb b/meta/meta-mediatek-gpl/recipes-kernel/linux/linux-mtk-extension_4.14.bb
new file mode 100644
index 0000000..2f13077
--- /dev/null
+++ b/meta/meta-mediatek-gpl/recipes-kernel/linux/linux-mtk-extension_4.14.bb
@@ -0,0 +1,4 @@
+require linux-mtk-extension.inc
+
+KERNEL_SRC = "${TOPDIR}/../src/kernel/linux/v4.14"
+LINUX_VERSION = "4.14.24"
diff --git a/meta/meta-mediatek-gpl/recipes-kernel/linux/linux-mtk-extension_4.19.bb b/meta/meta-mediatek-gpl/recipes-kernel/linux/linux-mtk-extension_4.19.bb
new file mode 100644
index 0000000..6d954ca
--- /dev/null
+++ b/meta/meta-mediatek-gpl/recipes-kernel/linux/linux-mtk-extension_4.19.bb
@@ -0,0 +1,4 @@
+require linux-mtk-extension.inc
+
+KERNEL_SRC = "${TOPDIR}/../src/kernel/linux/v4.19"
+LINUX_VERSION = "4.19.21"
diff --git a/meta/meta-mediatek-gpl/recipes-kernel/linux/linux-mtk-extension_4.4.bb b/meta/meta-mediatek-gpl/recipes-kernel/linux/linux-mtk-extension_4.4.bb
new file mode 100644
index 0000000..a9d3a9b
--- /dev/null
+++ b/meta/meta-mediatek-gpl/recipes-kernel/linux/linux-mtk-extension_4.4.bb
@@ -0,0 +1,4 @@
+require linux-mtk-extension.inc
+
+KERNEL_SRC = "${TOPDIR}/../src/kernel/linux/v4.4"
+LINUX_VERSION = "4.4.0"
diff --git a/meta/meta-mediatek-gpl/recipes-kernel/linux/linux-mtk-extension_4.9.bb b/meta/meta-mediatek-gpl/recipes-kernel/linux/linux-mtk-extension_4.9.bb
new file mode 100644
index 0000000..e1787a7
--- /dev/null
+++ b/meta/meta-mediatek-gpl/recipes-kernel/linux/linux-mtk-extension_4.9.bb
@@ -0,0 +1,4 @@
+require linux-mtk-extension.inc
+
+KERNEL_SRC = "${TOPDIR}/../src/kernel/linux/v4.9"
+LINUX_VERSION = "4.9.17"
diff --git a/meta/meta-mediatek-gpl/recipes-kernel/linux/linux-mtk-extension_99.9.9.bb b/meta/meta-mediatek-gpl/recipes-kernel/linux/linux-mtk-extension_99.9.9.bb
new file mode 100644
index 0000000..43a1a25
--- /dev/null
+++ b/meta/meta-mediatek-gpl/recipes-kernel/linux/linux-mtk-extension_99.9.9.bb
@@ -0,0 +1,4 @@
+require linux-mtk-extension.inc
+
+KERNEL_SRC = "${TOPDIR}/../src/kernel/linux/upstream"
+LINUX_VERSION = "99.9.9"
diff --git a/meta/meta-mediatek-gpl/recipes-kernel/linux/linux-mtk-ramdisk-extension.inc b/meta/meta-mediatek-gpl/recipes-kernel/linux/linux-mtk-ramdisk-extension.inc
new file mode 100644
index 0000000..38cdcbc
--- /dev/null
+++ b/meta/meta-mediatek-gpl/recipes-kernel/linux/linux-mtk-ramdisk-extension.inc
@@ -0,0 +1,24 @@
+inherit kernel externalsrc ramdisk-fitimage-extension
+DEPENDS_append_aarch64 = " libgcc"
+KERNEL_CC_append_aarch64 = " ${TOOLCHAIN_OPTIONS}"
+KERNEL_LD_append_aarch64 = " ${TOOLCHAIN_OPTIONS}"
+
+LICENSE = "GPLv2"
+LIC_FILES_CHKSUM = "file://COPYING;md5=d7810fab7487fb0aad327b76f1be7cd7"
+EXTERNALSRC = "${KERNEL_SRC}"
+STAGING_KERNEL_DIR = "${KERNEL_SRC}"
+LINUX_VERSION_EXTENSION = "-custom"
+KERNEL_EXTRA_ARGS = "dtbs"
+KERNEL_CONFIG_COMMAND = "oe_runmake_call -C ${S} O=${B} ${KBUILD_DEFCONFIG}"
+
+INITRAMFS_IMAGE = "mtk-core-image-minimal-initramfs"
+INITRAMFS_IMAGE_BUNDLE = "1"
+
+SRC_IMG_KEY_FILE = "${MTK_KEY_DIR}/${VERIFIED_KEY}.pem"
+DST_IMG_KEY_FILE = "${TOPDIR}/../src/devtools/nfsb/rsa.key"
+
+do_configure_prepend() {
+ install -d ${TMPDIR}/work-shared/${MACHINE}
+ ln -nfs ${STAGING_KERNEL_DIR} ${TMPDIR}/work-shared/${MACHINE}/kernel-source
+}
+
diff --git a/meta/meta-mediatek-gpl/recipes-kernel/linux/linux-mtk-ramdisk-extension_3.18.bb b/meta/meta-mediatek-gpl/recipes-kernel/linux/linux-mtk-ramdisk-extension_3.18.bb
new file mode 100644
index 0000000..0c276a0
--- /dev/null
+++ b/meta/meta-mediatek-gpl/recipes-kernel/linux/linux-mtk-ramdisk-extension_3.18.bb
@@ -0,0 +1,4 @@
+require linux-mtk-ramdisk-extension.inc
+
+KERNEL_SRC = "${TOPDIR}/../src/kernel/linux/v3.18"
+LINUX_VERSION = "3.18.22"
diff --git a/meta/meta-mediatek-gpl/recipes-kernel/linux/linux-mtk-ramdisk-extension_4.14.bb b/meta/meta-mediatek-gpl/recipes-kernel/linux/linux-mtk-ramdisk-extension_4.14.bb
new file mode 100644
index 0000000..8fca69c
--- /dev/null
+++ b/meta/meta-mediatek-gpl/recipes-kernel/linux/linux-mtk-ramdisk-extension_4.14.bb
@@ -0,0 +1,4 @@
+require linux-mtk-ramdisk-extension.inc
+
+KERNEL_SRC = "${TOPDIR}/../src/kernel/linux/v4.14"
+LINUX_VERSION = "4.14.24"
diff --git a/meta/meta-mediatek-gpl/recipes-kernel/linux/linux-mtk-ramdisk-extension_4.4.bb b/meta/meta-mediatek-gpl/recipes-kernel/linux/linux-mtk-ramdisk-extension_4.4.bb
new file mode 100644
index 0000000..2a57ce7
--- /dev/null
+++ b/meta/meta-mediatek-gpl/recipes-kernel/linux/linux-mtk-ramdisk-extension_4.4.bb
@@ -0,0 +1,4 @@
+require linux-mtk-ramdisk-extension.inc
+
+KERNEL_SRC = "${TOPDIR}/../src/kernel/linux/v4.4"
+LINUX_VERSION = "4.4.0"
diff --git a/meta/meta-mediatek-gpl/recipes-kernel/linux/linux-mtk-ramdisk-extension_4.9.bb b/meta/meta-mediatek-gpl/recipes-kernel/linux/linux-mtk-ramdisk-extension_4.9.bb
new file mode 100644
index 0000000..5d7cee1
--- /dev/null
+++ b/meta/meta-mediatek-gpl/recipes-kernel/linux/linux-mtk-ramdisk-extension_4.9.bb
@@ -0,0 +1,4 @@
+require linux-mtk-ramdisk-extension.inc
+
+KERNEL_SRC = "${TOPDIR}/../src/kernel/linux/v4.9"
+LINUX_VERSION = "4.9.17"
diff --git a/meta/meta-mediatek-gpl/recipes-kernel/modules/mt7615-ap-mod.bb b/meta/meta-mediatek-gpl/recipes-kernel/modules/mt7615-ap-mod.bb
new file mode 100755
index 0000000..fc9fd60
--- /dev/null
+++ b/meta/meta-mediatek-gpl/recipes-kernel/modules/mt7615-ap-mod.bb
@@ -0,0 +1,16 @@
+DESCRIPTION = "MT7615 AP Wlan Driver"
+LICENSE = "MediaTekProprietary"
+inherit module workonsrc
+
+LIC_FILES_CHKSUM = "file://LICENSE;md5=cfae02679eba352c5d667a0cda7ef56e"
+WORKONSRC = "${TOPDIR}/../src/kernel/modules/wlan_driver/mt7615_AP"
+
+PR = "r0"
+FILES_${PN} += " ${sysconfdir} ${libdir}"
+
+do_install_append() {
+ install -d ${D}${sysconfdir}/Wireless/RT2860AP
+ install -m 0755 ${S}/embedded/conf/RT2860AP1.dat ${D}${sysconfdir}/Wireless/RT2860AP/RT2860AP1.dat
+ install -m 0755 ${S}/embedded/conf/RT2860AP2.dat ${D}${sysconfdir}/Wireless/RT2860AP/RT2860AP2.dat
+ install -m 0755 ${S}/embedded/conf/RT2860APCard.dat ${D}${sysconfdir}/Wireless/RT2860AP/RT2860APCard.dat
+}
diff --git a/meta/meta-mediatek-gpl/recipes-multimedia/gmrender/gmediarender/0001-gmrender.patch b/meta/meta-mediatek-gpl/recipes-multimedia/gmrender/gmediarender/0001-gmrender.patch
new file mode 100644
index 0000000..1ceb652
--- /dev/null
+++ b/meta/meta-mediatek-gpl/recipes-multimedia/gmrender/gmediarender/0001-gmrender.patch
@@ -0,0 +1,1275 @@
+From dd4c9924424f7b32fc164335ed7a64668c29e059 Mon Sep 17 00:00:00 2001
+From: "jun.zeng" <jun.zeng@mediatek.com>
+Date: Mon, 16 Apr 2018 20:34:35 +0800
+Subject: [PATCH] gmrender
+
+---
+ configure.ac | 11 +++
+ src/Makefile.am | 2 +-
+ src/dmr_ipc.c | 201 +++++++++++++++++++++++++++++++++++++++++++++++++
+ src/dmr_ipc.h | 22 ++++++
+ src/logging.c | 19 +++++
+ src/logging.h | 29 ++++++-
+ src/main.c | 14 ++--
+ src/output.c | 44 +++++++++--
+ src/output.h | 1 +
+ src/output_gstreamer.c | 97 ++++++++++++++++++++++--
+ src/output_module.h | 1 +
+ src/song-meta-data.c | 28 +++++--
+ src/upnp_connmgr.c | 9 ++-
+ src/upnp_control.c | 4 +-
+ src/upnp_device.c | 10 +--
+ src/upnp_transport.c | 145 ++++++++++++++++++++++++++---------
+ src/webserver.c | 8 +-
+ 17 files changed, 560 insertions(+), 85 deletions(-)
+ create mode 100644 src/dmr_ipc.c
+ create mode 100644 src/dmr_ipc.h
+
+diff --git a/configure.ac b/configure.ac
+index 0107f34..6e10f6b 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -23,6 +23,17 @@ if test -n "$GCC"; then
+ CXXFLAGS+=" -Wall -Wpointer-arith"
+ fi
+
++
++
++if test "${BOARD_NAME}" = "MT8516_M3"; then
++ CFLAGS+=" -DMT8516_M3=1"
++fi
++
++if test "${BOARD_NAME}" = "MT8516_P1"; then
++ CFLAGS+=" -DMT8516_P1=1"
++fi
++
++
+ AC_CHECK_FUNCS([asprintf])
+ AC_CHECK_LIB([m],[exp])
+
+diff --git a/src/Makefile.am b/src/Makefile.am
+index 00323cf..84103ba 100644
+--- a/src/Makefile.am
++++ b/src/Makefile.am
+@@ -1,6 +1,6 @@
+ bin_PROGRAMS = gmediarender
+
+-gmediarender_SOURCES = main.c git-version.h \
++gmediarender_SOURCES = main.c git-version.h dmr_ipc.h dmr_ipc.c \
+ upnp.c upnp_control.c upnp_connmgr.c upnp_transport.c \
+ upnp.h upnp_control.h upnp_connmgr.h upnp_transport.h \
+ song-meta-data.h song-meta-data.c \
+diff --git a/src/dmr_ipc.c b/src/dmr_ipc.c
+new file mode 100644
+index 0000000..69f2328
+--- /dev/null
++++ b/src/dmr_ipc.c
+@@ -0,0 +1,201 @@
++#include "dmr_ipc.h"
++
++
++
++char buf_r[100];
++
++#define FIFO_TO_APP "/tmp/dlna_rev_fifo"
++#define FIFO_TO_DMR "/tmp/dlna_send_fifo"
++
++#define ipc_info(fmt...) \
++ printf("[GMR_IPC | %s][%d]: ", __FUNCTION__, __LINE__); \
++ printf(fmt); \
++ printf("\n");
++
++struct ipc_notify {
++ int (*play)(struct action_event *event);
++ int (*pause)(struct action_event *event);
++ int (*stop)(struct action_event *event);
++};
++
++struct ipc_notify* dmr_ipc_notify = NULL;
++
++static int recv_msg_from_app(void *arg)
++{
++ ipc_info("begin msg thread\n");
++ char buf_r[100];
++ int fd;
++ int nread;
++ if((mkfifo(FIFO_TO_DMR, O_CREAT | O_EXCL) < 0) && ( errno != EEXIST))
++ {
++ ipc_info("cann't craate fifoserver \n");
++ }
++
++ memset(buf_r, 0, sizeof(buf_r));
++
++ fd = open(FIFO_TO_DMR, O_RDONLY | O_NONBLOCK, 0);
++ if(-1 == fd)
++ {
++ ipc_info("open");
++ exit(1);
++ }
++
++ while(1)
++ {
++ memset(buf_r, 0, sizeof(buf_r));
++ nread = read(fd, buf_r, 100);
++ if (nread > 0 && dmr_ipc_notify != NULL)
++ {
++ if (0 == strcmp("0", buf_r))
++ {
++ ipc_info("recv stop msg from app\n");
++ dmr_ipc_notify->stop(NULL);
++ }else if (0 == strcmp("1", buf_r))
++ {
++ ipc_info("recv play msg from app\n");
++ dmr_ipc_notify->play(NULL);
++ }else if(0 == strcmp("2", buf_r))
++ {
++ ipc_info("recv pause msg from app\n");
++ dmr_ipc_notify->pause(NULL);
++ }
++ }else if (dmr_ipc_notify == NULL)
++ {
++ ipc_info("dmr_ipc_notify is null\n");
++ }
++ sleep(1);
++ }
++ pause();
++ ipc_info("end msg thread\n");
++ return 0;
++}
++
++
++static int create_thread()
++{
++ pthread_t a_thread;
++ int res;
++ res = pthread_create(&a_thread, NULL, recv_msg_from_app, NULL);
++ if(res != 0)
++ {
++ ipc_info("Thread creation failed");
++ return -1;
++ }
++ return 0;
++}
++
++int InitIPC(void *play_func, void *pause_func, void *stop_func)
++{
++ if(access(FIFO_TO_APP, F_OK) == -1)
++ {
++ if(mkfifo(FIFO_TO_APP, 0777 ) < 0)
++ {
++ ipc_info("cann't craate FIFO_TO_APP file\n");
++ return -1;
++ }
++ }
++ if(access(FIFO_TO_DMR, F_OK) == -1)
++ {
++ if(mkfifo(FIFO_TO_DMR, 0777 ) < 0)
++ {
++ ipc_info("cann't craate FIFO_TO_DMR file\n");
++ return -1;
++ }
++ }
++
++ dmr_ipc_notify = (struct ipc_notify *) malloc(sizeof(struct ipc_notify));
++ dmr_ipc_notify->play = play_func;
++ dmr_ipc_notify->pause = pause_func;
++ dmr_ipc_notify->stop = stop_func;
++
++ create_thread();
++ ipc_info("exit from InitIPC()\n");
++ return 0;
++
++}
++
++int ReadIPC(void)
++{
++ int fd = open(FIFO_TO_APP, O_WRONLY, 0);
++ if(-1 == fd)
++ {
++ ipc_info("open error\n");
++ return -1;
++ }
++ else
++ {
++ ipc_info("open sus, fd:%d\n", fd);
++ }
++ int nread;
++ while(1)
++ {
++ memset(buf_r, 0, sizeof(buf_r));
++ nread = read(fd, buf_r, 100);
++ ipc_info("read %s from FIFO\n", buf_r);
++ sleep(1);
++ }
++ close(fd);
++ return 0;
++}
++
++int WriteIPC(int int_status)
++{
++ int fd = open(FIFO_TO_APP, O_WRONLY, 0);
++ if(-1 == fd)
++ {
++ ipc_info("open error\n");
++ return -1;
++ }
++
++ int nwrite = 0;
++ char dmr_status = '0' + int_status;
++ if(-1 == (nwrite = write(fd, &dmr_status, 1)))
++ {
++ if(errno == EAGAIN)
++ {
++ ipc_info("Error, The FIFO has not been read yet, Please try later\n");
++ return -1;
++ }
++ else
++ {
++ ipc_info("write error\n");
++ }
++
++ }
++ else
++ { if ('0' == dmr_status)
++ {
++ ipc_info("send stop cmd to the APP\n");
++ }else if ('1' == dmr_status)
++ {
++ ipc_info("send play cmd to the APP\n");
++ }else if ('2' == dmr_status)
++ {
++ ipc_info("send pause cmd to the APP\n");
++ }else if ('3' == dmr_status)
++ {
++ ipc_info("send stopped done cmd to the APP\n");
++ }else if ('4' == dmr_status)
++ {
++ ipc_info("send played done cmd to the APP\n");
++ }else if ('5' == dmr_status)
++ {
++ ipc_info("send paused done cmd to the APP\n");
++ }
++ }
++ return 0;
++ close(fd);
++}
++
++
++int StopIPC(void)
++{
++ unlink(FIFO_TO_APP);
++ ipc_info(" stop finish\n");
++ if (NULL != dmr_ipc_notify)
++ {
++ dmr_ipc_notify = NULL;
++ }
++ return 0;
++}
++
+diff --git a/src/dmr_ipc.h b/src/dmr_ipc.h
+new file mode 100644
+index 0000000..398289b
+--- /dev/null
++++ b/src/dmr_ipc.h
+@@ -0,0 +1,22 @@
++#ifndef _DMRIPC_H
++#define _DMRIPC_H
++
++#include <sys/types.h>
++#include <sys/stat.h>
++#include <errno.h>
++#include <fcntl.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#include <unistd.h>
++
++#define FIFO_NAME "dmr_fifo"
++#define BUFFER_SIZE PIPE_BUF
++#define TEN_MEG (1024 * 1024 * 10)
++
++int InitIPC(void *play_func, void *pause_func, void *stop_func);
++int ReadIPC(void);
++int StopIPC(void);
++int WriteIPC(int int_status);
++
++#endif
+diff --git a/src/logging.c b/src/logging.c
+index 2d01477..e462d94 100644
+--- a/src/logging.c
++++ b/src/logging.c
+@@ -41,6 +41,7 @@
+
+ static int log_fd = -1;
+ static int enable_color = 0;
++int dlna_enable = 1;
+
+ static const char *const kInfoHighlight = "\033[1mINFO ";
+ static const char *const kErrorHighlight = "\033[1m\033[31mERROR ";
+@@ -78,6 +79,18 @@ int Log_color_allowed(void) { return enable_color; }
+ int Log_info_enabled(void) { return log_fd >= 0; }
+ int Log_error_enabled(void) { return 1; }
+
++void enable_dlna_log()
++{
++ if(access(DLNA_ENABLE_PATH, F_OK) != -1)
++ {
++ Log_info("Logging", "dlna log enable");
++ dlna_enable = 1;
++ }else
++ {
++ Log_info("Logging", "dlna log disable");
++ dlna_enable = 0;
++ }
++}
+ static void Log_internal(int fd, const char *markup_start,
+ const char *category, const char *format,
+ va_list ap) {
+@@ -106,6 +119,11 @@ static void Log_internal(int fd, const char *markup_start,
+ free(parts[1].iov_base);
+ }
+
++
++
++
++
++/*
+ void Log_info(const char *category, const char *format, ...) {
+ if (log_fd < 0) return;
+ va_list ap;
+@@ -121,3 +139,4 @@ void Log_error(const char *category, const char *format, ...) {
+ error_markup_start_, category, format, ap);
+ va_end(ap);
+ }
++*/
+diff --git a/src/logging.h b/src/logging.h
+index 6e4cd19..3635ce9 100644
+--- a/src/logging.h
++++ b/src/logging.h
+@@ -35,9 +35,30 @@ int Log_color_allowed(void); // Returns if we're allowed to use terminal color.
+ int Log_info_enabled(void);
+ int Log_error_enabled(void);
+
+-void Log_info(const char *category, const char *format, ...)
+- PRINTF_FMT_CHECK(2, 3);
+-void Log_error(const char *category, const char *format, ...)
+- PRINTF_FMT_CHECK(2, 3);
++#define DLNA_LOG_ENABLE 0
+
++#define Log_info(category, fmt...) \
++ printf("[GMR_%s | I | %s][%d]: ", category, __FUNCTION__, __LINE__); \
++ printf(fmt); \
++ printf("\n");
++
++
++#define Log_error(category, fmt...) \
++ printf("[GMR_%s | E | %s][%d]: ", category, __FUNCTION__, __LINE__); \
++ printf(fmt); \
++ printf("\n");
++
++#define Log_debug(category, fmt...) \
++ if (DLNA_LOG_ENABLE) \
++ {\
++ printf("[GMR_%s | D | %s][%d]: ", category, __FUNCTION__, __LINE__); \
++ printf(fmt); \
++ printf("\n"); \
++ }
++
++#ifndef GMR_IPC
++#define GMR_IPC 1
++#endif
++
++#define DLNA_ENABLE_PATH "/data/dlna_enable"
+ #endif /* _LOGGING_H */
+diff --git a/src/main.c b/src/main.c
+index 7b25014..631d895 100644
+--- a/src/main.c
++++ b/src/main.c
+@@ -164,7 +164,7 @@ static void log_variable_change(void *userdata, int var_num,
+ // Silly terminal codes. Set to empty strings if not needed.
+ const char *var_start = Log_color_allowed() ? "\033[1m\033[34m" : "";
+ const char *var_end = Log_color_allowed() ? "\033[0m" : "";
+- Log_info(category, "%s%s%s: %s%s",
++ Log_debug(category, "%s%s%s: %s%s",
+ var_start, variable_name, var_end,
+ variable_value, needs_newline ? "\n" : "");
+ }
+@@ -205,11 +205,10 @@ int main(int argc, char **argv)
+ #if !GLIB_CHECK_VERSION(2,32,0)
+ g_thread_init (NULL); // Was necessary < glib 2.32, deprecated since.
+ #endif
+-
+ if (!process_cmdline(argc, argv)) {
+ return EXIT_FAILURE;
+ }
+-
++
+ if (show_version) {
+ do_show_version();
+ exit(EXIT_SUCCESS);
+@@ -259,14 +258,12 @@ int main(int argc, char **argv)
+ if (upnp_renderer == NULL) {
+ return EXIT_FAILURE;
+ }
+-
+- rc = output_init(output);
++ rc = output_init(NULL);
+ if (rc != 0) {
+ Log_error("main",
+ "ERROR: Failed to initialize Output subsystem");
+ return EXIT_FAILURE;
+ }
+-
+ struct upnp_device *device;
+ if (listen_port != 0 &&
+ (listen_port < 49152 || listen_port > 65535)) {
+@@ -306,14 +303,13 @@ int main(int argc, char **argv)
+
+ // Write both to the log (which might be disabled) and console.
+ Log_info("main", "Ready for rendering.");
+- fprintf(stderr, "Ready for rendering.\n");
++ Log_info("main", "Ready for rendering.\n");
+
+ output_loop();
+
+ // We're here, because the loop exited. Probably due to catching
+ // a signal.
+- Log_info("main", "Exiting.");
+ upnp_device_shutdown(device);
+-
++ Log_info("main", "Exiting.");
+ return EXIT_SUCCESS;
+ }
+diff --git a/src/output.c b/src/output.c
+index 451c6a3..0a575a2 100644
+--- a/src/output.c
++++ b/src/output.c
+@@ -50,6 +50,7 @@ static struct output_module *modules[] = {
+ #endif
+ };
+
++
+ static struct output_module *output_module = NULL;
+
+ void output_dump_modules(void)
+@@ -70,8 +71,27 @@ void output_dump_modules(void)
+ }
+ }
+
++int output_gst_init()
++{
++ if (output_module->init) {
++ return output_module->init();
++ }
++}
++
++int output_gst_destroy()
++{
++ if (output_module->destroy) {
++ return output_module->destroy();
++ }
++}
++
+ int output_init(const char *shortname)
+ {
++ if (output_module != NULL)
++ {
++ Log_error("output", "[%s]: no need, already init\n");
++ return 0;
++ }
+ int count;
+
+ count = sizeof(modules) / sizeof(struct output_module *);
+@@ -99,11 +119,11 @@ int output_init(const char *shortname)
+
+ Log_info("output", "Using output module: %s (%s)",
+ output_module->shortname, output_module->description);
+-
+- if (output_module->init) {
+- return output_module->init();
++
++ if (output_module->init)
++ {
++ output_module->init();
+ }
+-
+ return 0;
+ }
+
+@@ -148,6 +168,9 @@ int output_add_options(GOptionContext *ctx)
+ void output_set_uri(const char *uri, output_update_meta_cb_t meta_cb) {
+ if (output_module && output_module->set_uri) {
+ output_module->set_uri(uri, meta_cb);
++ }else
++ {
++ Log_error("output", "function pointer not be inited");
+ }
+ }
+ void output_set_next_uri(const char *uri) {
+@@ -158,7 +181,11 @@ void output_set_next_uri(const char *uri) {
+
+ int output_play(output_transition_cb_t transition_callback) {
+ if (output_module && output_module->play) {
++ output_module->init();
+ return output_module->play(transition_callback);
++ }else
++ {
++ Log_error("output", "function pointer not be inited");
+ }
+ return -1;
+ }
+@@ -172,7 +199,12 @@ int output_pause(void) {
+
+ int output_stop(void) {
+ if (output_module && output_module->stop) {
+- return output_module->stop();
++
++ output_module->stop();
++ return output_module->destroy();
++ }else
++ {
++ Log_error("output", "function pointer not be inited");
+ }
+ return -1;
+ }
+@@ -199,7 +231,7 @@ int output_get_volume(float *value) {
+ }
+ int output_set_volume(float value) {
+ if (output_module && output_module->set_volume) {
+- return output_module->set_volume(value);
++ return output_module->set_volume(value * 10);
+ }
+ return -1;
+ }
+diff --git a/src/output.h b/src/output.h
+index 9230752..9134460 100644
+--- a/src/output.h
++++ b/src/output.h
+@@ -40,6 +40,7 @@ typedef void (*output_transition_cb_t)(enum PlayFeedback);
+ typedef void (*output_update_meta_cb_t)(const struct SongMetaData *);
+
+ int output_init(const char *shortname);
++int output_gst_init(void);
+ int output_add_options(GOptionContext *ctx);
+ void output_dump_modules(void);
+
+diff --git a/src/output_gstreamer.c b/src/output_gstreamer.c
+index 72b9dfc..d74ef47 100644
+--- a/src/output_gstreamer.c
++++ b/src/output_gstreamer.c
+@@ -40,6 +40,8 @@
+ #include "output_module.h"
+ #include "output_gstreamer.h"
+
++static gboolean gst_has_inited = FALSE;
++
+ static void scan_caps(const GstCaps * caps)
+ {
+ guint i;
+@@ -181,6 +183,11 @@ static void output_gstreamer_set_uri(const char *uri,
+ }
+
+ static int output_gstreamer_play(output_transition_cb_t callback) {
++ if (!gst_has_inited)
++ {
++ Log_info("gstreamer", "error, not init");
++ return -1;
++ }
+ play_trans_callback_ = callback;
+ if (get_current_player_state() != GST_STATE_PAUSED) {
+ if (gst_element_set_state(player_, GST_STATE_READY) ==
+@@ -188,6 +195,7 @@ static int output_gstreamer_play(output_transition_cb_t callback) {
+ Log_error("gstreamer", "setting play state failed (1)");
+ // Error, but continue; can't get worse :)
+ }
++ Log_info("gsteamer", "play url:%s", gsuri_);
+ g_object_set(G_OBJECT(player_), "uri", gsuri_, NULL);
+ }
+ if (gst_element_set_state(player_, GST_STATE_PLAYING) ==
+@@ -198,7 +206,27 @@ static int output_gstreamer_play(output_transition_cb_t callback) {
+ return 0;
+ }
+
++static int output_gstreamer_destroy(void)
++{
++ if (!gst_has_inited)
++ {
++ Log_info("gstreamer", "error, not init");
++ return -1;
++ }
++ SongMetaData_clear(&song_meta_);
++ gst_element_set_state(player_, GST_STATE_NULL);
++ gst_object_unref(GST_OBJECT (player_));
++ gst_has_inited = FALSE;
++ Log_info("gstreamer", "gstreamer destroy successfully");
++ return 0;
++}
++
+ static int output_gstreamer_stop(void) {
++ if (!gst_has_inited)
++ {
++ Log_info("gstreamer", "error, not init");
++ return -1;
++ }
+ if (gst_element_set_state(player_, GST_STATE_READY) ==
+ GST_STATE_CHANGE_FAILURE) {
+ return -1;
+@@ -208,6 +236,11 @@ static int output_gstreamer_stop(void) {
+ }
+
+ static int output_gstreamer_pause(void) {
++ if (!gst_has_inited)
++ {
++ Log_info("gstreamer", "error, not init");
++ return -1;
++ }
+ if (gst_element_set_state(player_, GST_STATE_PAUSED) ==
+ GST_STATE_CHANGE_FAILURE) {
+ return -1;
+@@ -217,6 +250,11 @@ static int output_gstreamer_pause(void) {
+ }
+
+ static int output_gstreamer_seek(gint64 position_nanos) {
++ if (!gst_has_inited)
++ {
++ Log_info("gstreamer", "error, not init");
++ return -1;
++ }
+ if (gst_element_seek(player_, 1.0, GST_FORMAT_TIME,
+ GST_SEEK_FLAG_FLUSH,
+ GST_SEEK_TYPE_SET, position_nanos,
+@@ -376,8 +414,8 @@ static gboolean my_bus_callback(GstBus * bus, GstMessage * msg,
+ return TRUE;
+ }
+
+-static gchar *audio_sink = NULL;
+-static gchar *audio_device = NULL;
++static gchar *audio_sink = "alsasink";
++static gchar *audio_device = "hw:0,0";
+ static gchar *videosink = NULL;
+ static double initial_db = 0.0;
+
+@@ -417,6 +455,10 @@ static int output_gstreamer_add_options(GOptionContext *ctx)
+
+ static int output_gstreamer_get_position(gint64 *track_duration,
+ gint64 *track_pos) {
++ if (!gst_has_inited)
++ {
++ return -1;
++ }
+ *track_duration = last_known_time_.duration;
+ *track_pos = last_known_time_.position;
+
+@@ -446,6 +488,11 @@ static int output_gstreamer_get_position(gint64 *track_duration,
+ }
+
+ static int output_gstreamer_get_volume(float *v) {
++ if (!gst_has_inited)
++ {
++ Log_info("gstreamer", "error, not init");
++ return -1;
++ }
+ double volume;
+ g_object_get(player_, "volume", &volume, NULL);
+ Log_info("gstreamer", "Query volume fraction: %f", volume);
+@@ -453,17 +500,32 @@ static int output_gstreamer_get_volume(float *v) {
+ return 0;
+ }
+ static int output_gstreamer_set_volume(float value) {
++ if (!gst_has_inited)
++ {
++ Log_info("gstreamer", "error, not init");
++ return -1;
++ }
+ Log_info("gstreamer", "Set volume fraction to %f", value);
+ g_object_set(player_, "volume", (double) value, NULL);
+ return 0;
+ }
+ static int output_gstreamer_get_mute(int *m) {
++ if (!gst_has_inited)
++ {
++ Log_info("gstreamer", "error, not init");
++ return -1;
++ }
+ gboolean val;
+ g_object_get(player_, "mute", &val, NULL);
+ *m = val;
+ return 0;
+ }
+ static int output_gstreamer_set_mute(int m) {
++ if (!gst_has_inited)
++ {
++ Log_info("gstreamer", "error, not init");
++ return -1;
++ }
+ Log_info("gstreamer", "Set mute to %s", m ? "on" : "off");
+ g_object_set(player_, "mute", (gboolean) m, NULL);
+ return 0;
+@@ -472,10 +534,10 @@ static int output_gstreamer_set_mute(int m) {
+ static void prepare_next_stream(GstElement *obj, gpointer userdata) {
+ Log_info("gstreamer", "about-to-finish cb: setting uri %s",
+ gs_next_uri_);
+- free(gsuri_);
+- gsuri_ = gs_next_uri_;
+- gs_next_uri_ = NULL;
+- if (gsuri_ != NULL) {
++ if (gs_next_uri_ != NULL) {
++ free(gsuri_);
++ gsuri_ = gs_next_uri_;
++ gs_next_uri_ = NULL;
+ g_object_set(G_OBJECT(player_), "uri", gsuri_, NULL);
+ if (play_trans_callback_) {
+ // TODO(hzeller): can we figure out when we _actually_
+@@ -486,8 +548,15 @@ static void prepare_next_stream(GstElement *obj, gpointer userdata) {
+ }
+ }
+
++
+ static int output_gstreamer_init(void)
+ {
++
++ if (gst_has_inited)
++ {
++ Log_info("gstreamer", "no need, already init");
++ return -1;
++ }
+ GstBus *bus;
+
+ SongMetaData_init(&song_meta_);
+@@ -506,6 +575,16 @@ static int output_gstreamer_init(void)
+ gst_bus_add_watch(bus, my_bus_callback, NULL);
+ gst_object_unref(bus);
+
++#ifdef MT8516_M3
++ audio_device = "hw:0,6";
++ Log_info("gstreamer", " M3 patform, set audio_device = hw:0,6");
++#endif
++
++#ifdef MT8516_P1
++ audio_device = "hw:0,0";
++ Log_info("gstreamer", "P1 patform, set audio_device = hw:0,0");
++#endif
++
+ if (audio_sink != NULL) {
+ GstElement *sink = NULL;
+ Log_info("gstreamer", "Setting audio sink to %s; device=%s\n",
+@@ -521,6 +600,7 @@ static int output_gstreamer_init(void)
+ g_object_set (G_OBJECT (player_), "audio-sink", sink, NULL);
+ }
+ }
++
+ if (videosink != NULL) {
+ GstElement *sink = NULL;
+ Log_info("gstreamer", "Setting video sink to %s", videosink);
+@@ -539,7 +619,9 @@ static int output_gstreamer_init(void)
+ if (initial_db < 0) {
+ output_gstreamer_set_volume(exp(initial_db / 20 * log(10)));
+ }
+-
++
++ Log_info("gstreamer", "gstreamer init successfully");
++ gst_has_inited = TRUE;
+ return 0;
+ }
+
+@@ -547,6 +629,7 @@ struct output_module gstreamer_output = {
+ .shortname = "gst",
+ .description = "GStreamer multimedia framework",
+ .init = output_gstreamer_init,
++ .destroy = output_gstreamer_destroy,
+ .add_options = output_gstreamer_add_options,
+ .set_uri = output_gstreamer_set_uri,
+ .set_next_uri= output_gstreamer_set_next_uri,
+diff --git a/src/output_module.h b/src/output_module.h
+index d4250ef..9afa152 100644
+--- a/src/output_module.h
++++ b/src/output_module.h
+@@ -33,6 +33,7 @@ struct output_module {
+
+ // Commands.
+ int (*init)(void);
++ int (*destroy)(void);
+ void (*set_uri)(const char *uri, output_update_meta_cb_t meta_info);
+ void (*set_next_uri)(const char *uri);
+ int (*play)(output_transition_cb_t transition_callback);
+diff --git a/src/song-meta-data.c b/src/song-meta-data.c
+index 1727d2e..c6c3850 100644
+--- a/src/song-meta-data.c
++++ b/src/song-meta-data.c
+@@ -38,14 +38,26 @@ void SongMetaData_init(struct SongMetaData *value) {
+ memset(value, 0, sizeof(struct SongMetaData));
+ }
+ void SongMetaData_clear(struct SongMetaData *value) {
+- free((char*)value->title);
+- value->title = NULL;
+- free((char*)value->artist);
+- value->artist = NULL;
+- free((char*)value->album);
+- value->album = NULL;
+- free((char*)value->genre);
+- value->genre = NULL;
++ if (value->title != NULL)
++ {
++ free((char*)value->title);
++ value->title = NULL;
++ }
++ if (value->artist != NULL)
++ {
++ free((char*)value->artist);
++ value->artist = NULL;
++ }
++ if (value->album != NULL)
++ {
++ free((char*)value->album);
++ value->album = NULL;
++ }
++ if (value->genre != NULL)
++ {
++ free((char*)value->genre);
++ value->genre = NULL;
++ }
+ }
+
+ static const char kDidlHeader[] = "<DIDL-Lite "
+diff --git a/src/upnp_connmgr.c b/src/upnp_connmgr.c
+index 97257e7..9ccf258 100644
+--- a/src/upnp_connmgr.c
++++ b/src/upnp_connmgr.c
+@@ -198,7 +198,7 @@ static void register_mime_type_internal(const char *mime_type) {
+ return;
+ }
+ }
+- Log_info("connmgr", "Registering support for '%s'", mime_type);
++ Log_debug("connmgr", "Registering support for '%s'", mime_type);
+
+ entry = malloc(sizeof(struct mime_type));
+ entry->mime_type = strdup(mime_type);
+@@ -207,6 +207,10 @@ static void register_mime_type_internal(const char *mime_type) {
+ }
+
+ void register_mime_type(const char *mime_type) {
++ if (strstr(mime_type, "audio/")== NULL)
++ {
++ return;
++ }
+ register_mime_type_internal(mime_type);
+ if (strcmp("audio/mpeg", mime_type) == 0) {
+ register_mime_type_internal("audio/x-mpeg");
+@@ -290,7 +294,6 @@ int connmgr_init(void) {
+ *p = '\0';
+ }
+ *p = '\0';
+-
+ VariableContainer_change(srv->variable_container,
+ CONNMGR_VAR_SINK_PROTO_INFO, buf);
+ free(buf);
+@@ -328,7 +331,7 @@ static int get_current_conn_info(struct action_event *event)
+ if (value == NULL) {
+ return -1;
+ }
+- Log_info("connmgr", "Query ConnectionID='%s'", value);
++ Log_debug("connmgr", "Query ConnectionID='%s'", value);
+
+ upnp_append_variable(event, CONNMGR_VAR_AAT_RCS_ID, "RcsID");
+ upnp_append_variable(event, CONNMGR_VAR_AAT_AVT_ID, "AVTransportID");
+diff --git a/src/upnp_control.c b/src/upnp_control.c
+index a1ad1cd..61b6db1 100644
+--- a/src/upnp_control.c
++++ b/src/upnp_control.c
+@@ -519,7 +519,7 @@ static int cmd_obtain_variable(struct action_event *event,
+ if (instance == NULL) {
+ return -1;
+ }
+- Log_info("control", "%s: %s for instance %s\n",
++ Log_debug("control", "%s: %s for instance %s\n",
+ __FUNCTION__, paramname, instance);
+
+ upnp_append_variable(event, varnum, paramname);
+@@ -611,6 +611,7 @@ static int get_mute(struct action_event *event)
+ }
+
+ static void set_mute_toggle(int do_mute) {
++ Log_info("upnp", "call output_set_mute");
+ replace_var(CONTROL_VAR_MUTE, do_mute ? "1" : "0");
+ output_set_mute(do_mute);
+ }
+@@ -792,6 +793,7 @@ void upnp_control_init(struct upnp_device *device) {
+
+ // Set initial volume.
+ float volume_fraction = 0;
++ Log_info("upnp", "call output_get_volume");
+ if (output_get_volume(&volume_fraction) == 0) {
+ Log_info("control", "Output inital volume is %f; setting "
+ "control variables accordingly.", volume_fraction);
+diff --git a/src/upnp_device.c b/src/upnp_device.c
+index a31b420..729f4fd 100644
+--- a/src/upnp_device.c
++++ b/src/upnp_device.c
+@@ -161,8 +161,8 @@ static int handle_subscription_request(struct upnp_device *priv,
+
+ assert(priv != NULL);
+
+- Log_info("upnp", "Subscription request for %s (%s)",
+- sr_event->ServiceId, sr_event->UDN);
++ Log_debug("upnp", "event:%p, Subscription request for %s (%s)",
++ sr_event, sr_event->ServiceId, sr_event->UDN);
+
+ srv = find_service(priv->upnp_device_descriptor, sr_event->ServiceId);
+ if (srv == NULL) {
+@@ -203,7 +203,7 @@ static int handle_subscription_request(struct upnp_device *priv,
+ }
+ ithread_mutex_unlock(srv->service_mutex);
+ char *xml_value = UPnPLastChangeBuilder_to_xml(builder);
+- Log_info("upnp", "Initial variable sync: %s", xml_value);
++ Log_debug("upnp", "event:%p, Initial variable sync: %s", sr_event, xml_value);
+ eventvar_values[0] = xmlescape(xml_value, 0);
+ free(xml_value);
+ UPnPLastChangeBuilder_delete(builder);
+@@ -341,7 +341,7 @@ static int handle_action_request(struct upnp_device *priv,
+ char *action_result_xml = NULL;
+ action_result_xml = ixmlDocumenttoString(
+ ar_event->ActionResult);
+- Log_info("upnp", "Action '%s' OK; Response %s",
++ Log_debug("upnp", "Action '%s' OK; Response %s",
+ ar_event->ActionName,
+ action_result_xml);
+ free(action_result_xml);
+@@ -417,7 +417,7 @@ static gboolean initialize_device(struct upnp_device_descriptor *device_def,
+ ip_address, port, UpnpGetErrorMessage(rc), rc);
+ return FALSE;
+ }
+- Log_info("upnp", "Registered IP=%s port=%d\n",
++ Log_debug("upnp", "Registered IP=%s port=%d\n",
+ UpnpGetServerIpAddress(), UpnpGetServerPort());
+
+ rc = UpnpEnableWebserver(TRUE);
+diff --git a/src/upnp_transport.c b/src/upnp_transport.c
+index f9c97fb..4de63ba 100644
+--- a/src/upnp_transport.c
++++ b/src/upnp_transport.c
+@@ -26,6 +26,7 @@
+ #endif
+
+ #include "upnp_transport.h"
++#include "dmr_ipc.h"
+
+ #define _GNU_SOURCE
+ #include <stdio.h>
+@@ -35,16 +36,16 @@
+ #include <assert.h>
+
+ #include <glib.h>
+-
+ #include <upnp/upnp.h>
+ #include <upnp/ithread.h>
+
+ #include "output.h"
+ #include "upnp.h"
++
+ #include "upnp_device.h"
+ #include "variable-container.h"
+ #include "xmlescape.h"
+-
++#include "logging.h"
+ #define TRANSPORT_TYPE "urn:schemas-upnp-org:service:AVTransport:1"
+ #define TRANSPORT_SERVICE_ID "urn:upnp-org:serviceId:AVTransport"
+
+@@ -56,6 +57,15 @@
+ #define TRANSPORT_EVENT_XML_NS "urn:schemas-upnp-org:metadata-1-0/AVT/"
+
+ typedef enum {
++ DLNA_STOP_REQ = 0,
++ DLNA_PLAY_REQ,
++ DLNA_PAUSE_REQ,
++ DLNA_STOP_DONE,
++ DLNA_PLAY_DONE,
++ DLNA_PUASE_DONE
++}DLNA_MSG;
++
++typedef enum {
+ TRANSPORT_VAR_TRANSPORT_STATUS,
+ TRANSPORT_VAR_NEXT_AV_URI,
+ TRANSPORT_VAR_NEXT_AV_URI_META,
+@@ -655,9 +665,15 @@ static int set_avtransport_uri(struct action_event *event)
+ if (uri == NULL) {
+ return -1;
+ }
++ if (TRANSPORT_STOPPED != transport_state_ && TRANSPORT_NO_MEDIA_PRESENT != transport_state_)
++ {
++ stop(NULL);
++ }
+
+ service_lock();
+ const char *meta = upnp_get_string(event, "CurrentURIMetaData");
++ Log_info("transport", "url : %s", uri);
++ Log_info("transport", "meta: %s", meta);
+ // Transport URI/Meta set now, current URI/Meta when it starts playing.
+ int requires_meta_update = replace_transport_uri_and_meta(uri, meta);
+
+@@ -669,12 +685,12 @@ static int set_avtransport_uri(struct action_event *event)
+ // current URI/Meta as well to reflect the state best.
+ replace_current_uri_and_meta(uri, meta);
+ }
+-
++
++ Log_info("transport", "call output_set_uri");
+ output_set_uri(uri, (requires_meta_update
+ ? update_meta_from_stream
+ : NULL));
+ service_unlock();
+-
+ return 0;
+ }
+
+@@ -772,7 +788,7 @@ static void *thread_update_track_time(void *userdata) {
+ char tbuf[32];
+ gint64 last_duration = -1, last_position = -1;
+ for (;;) {
+- usleep(500000); // 500ms
++ usleep(1 * 1000 * 1000); // 1000ms
+ service_lock();
+ gint64 duration, position;
+ const int pos_result = output_get_position(&duration, &position);
+@@ -787,6 +803,10 @@ static void *thread_update_track_time(void *userdata) {
+ replace_var(TRANSPORT_VAR_REL_TIME_POS, tbuf);
+ last_position = position / one_sec_unit;
+ }
++ if (TRANSPORT_STOPPED != transport_state_ && TRANSPORT_NO_MEDIA_PRESENT != transport_state_)
++ {
++ Log_debug("transport", "progress : %lld / %lld", last_position, last_duration / one_sec_unit);
++ }
+ }
+ service_unlock();
+ }
+@@ -822,16 +842,29 @@ static int get_device_caps(struct action_event *event)
+ return 0;
+ }
+
+-static int stop(struct action_event *event)
+-{
+- if (obtain_instanceid(event, NULL) < 0) {
+- return -1;
++int stop(struct action_event *event)
++{
++ if (event != NULL)
++ {
++ if (obtain_instanceid(event, NULL) < 0) {
++ return -1;
++ }
++ if (TRANSPORT_STOPPED != transport_state_
++ && TRANSPORT_NO_MEDIA_PRESENT != transport_state_)
++ {
++ Log_info("transport", "recv stop cmd from dmc");
++#if GMR_IPC
++ WriteIPC(DLNA_STOP_REQ);
++ return 0;
++#endif
++ }
+ }
+-
+ service_lock();
+ switch (transport_state_) {
+ case TRANSPORT_STOPPED:
+ // nothing to change.
++ Log_info("transport", "no need, already sttopped");
++ output_gst_destroy();
+ break;
+ case TRANSPORT_PLAYING:
+ case TRANSPORT_TRANSITIONING:
+@@ -839,19 +872,25 @@ static int stop(struct action_event *event)
+ case TRANSPORT_RECORDING:
+ case TRANSPORT_PAUSED_PLAYBACK:
+ output_stop();
++#if GMR_IPC
++ WriteIPC(DLNA_STOP_DONE);
++#endif
+ change_transport_state(TRANSPORT_STOPPED);
+ break;
+
+ case TRANSPORT_NO_MEDIA_PRESENT:
+- /* action not allowed in these states - error 701 */
+- upnp_set_error(event, UPNP_TRANSPORT_E_TRANSITION_NA,
++ /* action not allowed in these states - error 701 */
++ output_gst_destroy();
++ if (event != NULL)
++ {
++ Log_info("transport", "no need, gmrender status : TRANSPORT_NO_MEDIA_PRESENT");
++ upnp_set_error(event, UPNP_TRANSPORT_E_TRANSITION_NA,
+ "Transition to STOP not allowed; allowed=%s",
+ get_var(TRANSPORT_VAR_CUR_TRANSPORT_ACTIONS));
+-
++ }
+ break;
+ }
+ service_unlock();
+-
+ return 0;
+ }
+
+@@ -877,12 +916,20 @@ static void inform_play_transition_from_output(enum PlayFeedback fb) {
+ service_unlock();
+ }
+
+-static int play(struct action_event *event)
++int play(struct action_event *event)
+ {
+- if (obtain_instanceid(event, NULL) < 0) {
+- return -1;
++ if (event != NULL)
++ {
++ if (obtain_instanceid(event, NULL) < 0) {
++ return -1;
++ }
++ Log_info("transport", "recv play cmd from dmc");
++#if GMR_IPC
++ WriteIPC(DLNA_PLAY_REQ);
++ return 0;
++#endif
+ }
+-
++ output_gst_init();
+ int rc = 0;
+ service_lock();
+ switch (transport_state_) {
+@@ -901,10 +948,16 @@ static int play(struct action_event *event)
+
+ case TRANSPORT_PAUSED_PLAYBACK:
+ if (output_play(&inform_play_transition_from_output)) {
+- upnp_set_error(event, 704, "Playing failed");
+- rc = -1;
++ if (event != NULL)
++ {
++ upnp_set_error(event, 704, "Playing failed");
++ rc = -1;
++ }
+ } else {
+- change_transport_state(TRANSPORT_PLAYING);
++#if GMR_IPC
++ WriteIPC(DLNA_PLAY_DONE);
++#endif
++ change_transport_state(TRANSPORT_PLAYING);
+ const char *av_uri = get_var(TRANSPORT_VAR_AV_URI);
+ const char *av_meta = get_var(TRANSPORT_VAR_AV_URI_META);
+ replace_current_uri_and_meta(av_uri, av_meta);
+@@ -923,15 +976,22 @@ static int play(struct action_event *event)
+ break;
+ }
+ service_unlock();
+-
+ return rc;
+ }
+
+-static int pause_stream(struct action_event *event)
+-{
+- if (obtain_instanceid(event, NULL) < 0) {
+- return -1;
+- }
++int pause_stream(struct action_event *event)
++{
++ if (event != NULL)
++ {
++ if (obtain_instanceid(event, NULL) < 0) {
++ return -1;
++ }
++ Log_info("transport", "recv pause cmd from dmc");
++#if GMR_IPC
++ WriteIPC(DLNA_PAUSE_REQ);
++ return 0;
++#endif
++}
+
+ int rc = 0;
+ service_lock();
+@@ -942,22 +1002,30 @@ static int pause_stream(struct action_event *event)
+
+ case TRANSPORT_PLAYING:
+ if (output_pause()) {
+- upnp_set_error(event, 704, "Pause failed");
+- rc = -1;
++ if (event != NULL)
++ {
++ upnp_set_error(event, 704, "Pause failed");
++ rc = -1;
++ }
+ } else {
+- change_transport_state(TRANSPORT_PAUSED_PLAYBACK);
++#if GMR_IPC
++ WriteIPC(DLNA_PUASE_DONE);
++#endif
++ change_transport_state(TRANSPORT_PAUSED_PLAYBACK);
+ }
+ break;
+
+- default:
++ default:
++ if (event != NULL)
++ {
+ /* action not allowed in these states - error 701 */
+- upnp_set_error(event, UPNP_TRANSPORT_E_TRANSITION_NA,
+- "Transition to PAUSE not allowed; allowed=%s",
+- get_var(TRANSPORT_VAR_CUR_TRANSPORT_ACTIONS));
+- rc = -1;
+- }
++ upnp_set_error(event, UPNP_TRANSPORT_E_TRANSITION_NA,
++ "Transition to PAUSE not allowed; allowed=%s",
++ get_var(TRANSPORT_VAR_CUR_TRANSPORT_ACTIONS));
++ rc = -1;
++ }
++ }
+ service_unlock();
+-
+ return rc;
+ }
+
+@@ -1036,6 +1104,9 @@ void upnp_transport_init(struct upnp_device *device) {
+ TRANSPORT_VAR_ABS_CTR_POS);
+
+ pthread_t thread;
++#if GMR_IPC
++ InitIPC(play, pause_stream, stop);
++#endif
+ pthread_create(&thread, NULL, thread_update_track_time, NULL);
+ }
+
+diff --git a/src/webserver.c b/src/webserver.c
+index eaf0331..14e00e3 100644
+--- a/src/webserver.c
++++ b/src/webserver.c
+@@ -63,7 +63,7 @@ int webserver_register_buf(const char *path, const char *contents,
+ {
+ struct virtual_file *entry;
+
+- Log_info("webserver", "Provide %s (%s) from buffer",
++ Log_debug("webserver", "Provide %s (%s) from buffer",
+ path, content_type);
+
+ assert(path != NULL);
+@@ -94,7 +94,7 @@ int webserver_register_file(const char *path, const char *content_type)
+ snprintf(local_fname, sizeof(local_fname), "%s%s", PKG_DATADIR,
+ strrchr(path, '/'));
+
+- Log_info("webserver", "Provide %s (%s) from %s", path, content_type,
++ Log_debug("webserver", "Provide %s (%s) from %s", path, content_type,
+ local_fname);
+
+ rc = stat(local_fname, &buf);
+@@ -154,14 +154,14 @@ static int webserver_get_info(const char *filename, struct File_Info *info)
+ info->is_readable = 1;
+ info->content_type =
+ ixmlCloneDOMString(virtfile->content_type);
+- Log_info("webserver", "Access %s (%s) len=%zd",
++ Log_debug("webserver", "Access %s (%s) len=%zd",
+ filename, info->content_type, virtfile->len);
+ return 0;
+ }
+ virtfile = virtfile->next;
+ }
+
+- Log_info("webserver", "404 Not found. (attempt to access "
++ Log_debug("webserver", "404 Not found. (attempt to access "
+ "non-existent '%s')", filename);
+
+ return -1;
+--
+1.9.1
+
diff --git a/meta/meta-mediatek-gpl/recipes-multimedia/gmrender/gmediarender_0.0.7.bb b/meta/meta-mediatek-gpl/recipes-multimedia/gmrender/gmediarender_0.0.7.bb
new file mode 100644
index 0000000..a99c4a2
--- /dev/null
+++ b/meta/meta-mediatek-gpl/recipes-multimedia/gmrender/gmediarender_0.0.7.bb
@@ -0,0 +1,40 @@
+SUMMARY = "gmrender"
+DESCRIPTION = "gmediarender"
+
+LICENSE = "GPLv2+"
+LICENSE_FLAGS = "commercial"
+LIC_FILES_CHKSUM = "file://NOTICE;md5=c1a3ff0b97f199c7ebcfdd4d3fed238e"
+SECTION = "libs"
+
+S="${WORKDIR}/git"
+SRC_URI[md5sum] = "4fc1d5ce6ef2c27fae01d3e3fdc46240"
+SRC_URI[sha256sum] = "85d3251ce3095394d389b56f8b47e7f79e906022e51ce92a4cf822ee2a5fee2c"
+
+SRC_URI = "git://anonscm.debian.org/git/collab-maint/gmrender-resurrect.git;protocol=http;branch=master \
+file://0001-gmrender.patch"
+
+SRCREV = "9306fc5ad1d032f387d41fbce7dcba8cf22c8527"
+
+inherit autotools pkgconfig
+
+DEPENDS += "libupnp gstreamer1.0 gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-plugins-base gstreamer1.0-plugins-ugly gstreamer1.0-libav"
+
+do_configure() {
+ if test "${BOARD_NAME}" = "mt8516-som"; then
+ cd ${S} && ./autogen.sh && ./configure --host --host-alias BOARD_NAME=MT8516_M3
+ else
+ cd ${S} && ./autogen.sh && ./configure --host --host-alias BOARD_NAME=MT8516_P1
+ fi
+}
+
+do_compile() {
+ cd ${S} && make clean && make
+}
+
+do_install() {
+ install -d ${D}${bindir}
+ rm -rf ${D}/usr/share
+ install -m 775 ${S}/src/gmediarender ${D}${bindir}
+}
+
+FILES_${PN} = "${bindir} ${libdir}"