#!/bin/sh

set -e

is_enabled() {
	grep -q "^$1=y" include/config/auto.conf
}

if_enabled_echo() {
	if is_enabled "$1"; then
		echo -n "$2"
	elif [ $# -ge 3 ]; then
		echo -n "$3"
	fi
}

create_package() {
	local pname="$1" pdir="$2"

	mkdir -m 755 -p "$pdir/DEBIAN"
	mkdir -p "$pdir/usr/share/doc/$pname"
	cp debian/copyright "$pdir/usr/share/doc/$pname/"
	cp debian/changelog "$pdir/usr/share/doc/$pname/changelog.Debian"
	gzip -9 "$pdir/usr/share/doc/$pname/changelog.Debian"
	sh -c "cd '$pdir'; find . -type f ! -path './DEBIAN/*' -printf '%P\0' \
		| xargs -r0 md5sum > DEBIAN/md5sums"

	# Fix ownership and permissions
	chown -R root:root "$pdir"
	chmod -R go-w "$pdir"
	# in case we are in a restrictive umask environment like 0077
	chmod -R a+rX "$pdir"

	# Create the package
	dpkg-gencontrol -p$pname -P"$pdir"
	dpkg-deb -Z$compression --build "$pdir" ..
}

if [ -f "scripts/package/pkgvars" ]; then
	. scripts/package/pkgvars
	if [ -f "dtclist.txt" ] && [ -f "initrd" ] && [ -f "headers-byteshift.patch" ]; then
		:;
	else
		echo -e "A builddeb dependency file is missing."
		exit 0
	fi
else
	echo "Missing: pkgvars"
	exit 0
fi

version=$KERNELRELEASE
tmpdir="$objtree/debian/tmp"
kernel_headers_dir="$objtree/debian/hdrtmp"
libc_headers_dir="$objtree/debian/headertmp"
dbg_dir="$objtree/debian/dbgtmp"
libc_headers_packagename=linux-libc-dev
dbg_packagename=$packagename-dbg
packagename=$linux_name
kernel_headers_packagename=$headers_name

if [ "$ARCH" = "um" ] ; then
	packagename=user-mode-linux-$version
fi

# Not all arches have the same installed path in debian
# XXX: have each arch Makefile export a variable of the canonical image install
# path instead
case $ARCH in
um)
	installed_image_path="usr/bin/linux-$version"
	;;
parisc|mips|powerpc)
	installed_image_path="boot/vmlinux-$version"
	;;
*)
	installed_image_path="boot/vmlinuz-$version"
esac

BUILD_DEBUG=$(if_enabled_echo CONFIG_DEBUG_INFO Yes)

# Setup the directory structure
rm -rf "$tmpdir" "$kernel_headers_dir" "$libc_headers_dir" "$dbg_dir" $objtree/debian/files
mkdir -m 755 -p "$tmpdir/DEBIAN"
mkdir -p "$tmpdir/lib" "$tmpdir/boot"
mkdir -p "$kernel_headers_dir/lib/modules/$version/"

# Build and install the kernel
if [ "$ARCH" = "um" ] ; then
	mkdir -p "$tmpdir/usr/lib/uml/modules/$version" "$tmpdir/usr/bin" "$tmpdir/usr/share/doc/$packagename"
	$MAKE linux
	cp System.map "$tmpdir/usr/lib/uml/modules/$version/System.map"
	cp $KCONFIG_CONFIG "$tmpdir/usr/share/doc/$packagename/config"
	gzip "$tmpdir/usr/share/doc/$packagename/config"
else
	cp System.map "$tmpdir/boot/System.map-$version"
	cp $KCONFIG_CONFIG "$tmpdir/boot/config-$version"
	if [ -f arch/arm/boot/zImage ]; then
		mkdir -p "$tmpdir/$boot_path"
		cp arch/arm/boot/zImage "$tmpdir/boot/Image"
		cp arch/arm/boot/zImage "$tmpdir/$boot_path/kernel.img"
		cp arch/arm/boot/zImage "$tmpdir/$boot_path/kernel7.img"
		cp arch/arm/boot/zImage "$tmpdir/$boot_path/kernel7l.img"
	fi
	if [ -f arch/arm64/boot/Image ]; then
		mkdir -p "$tmpdir/$boot_path"
		cp arch/arm64/boot/Image "$tmpdir/boot/Image"
		cp arch/arm64/boot/Image "$tmpdir/$boot_path/kernel8.img"
		cp arch/arm64/boot/Image "$tmpdir/$boot_path/kernel_2712.img"
	fi
	if [ -f firmware/bootcode.bin ]; then
		install -m 0644 firmware/bootcode.bin "$tmpdir/$boot_path"
	fi
	if [ -f firmware/fixup.dat ]; then
		install -m 0644 firmware/fixup*.dat "$tmpdir/$boot_path"
	fi
	if [ -f firmware/start.elf ]; then
		install -m 0644 firmware/start*.elf "$tmpdir/$boot_path"
	fi
	if [ -f firmware/fixup4.dat ]; then
		install -m 0644 firmware/fixup4*.dat "$tmpdir/$boot_path"
	fi
	if [ -f firmware/start4.elf ]; then
		install -m 0644 firmware/start4*.elf "$tmpdir/$boot_path"
	fi
	if [ -f firmware/LICENCE.broadcom ]; then
		install -m 0644 firmware/LICENCE.broadcom "$tmpdir/$boot_path"
	fi
	if [ -f firmware/COPYING.linux ]; then
		install -m 0644 firmware/COPYING.linux "$tmpdir/$boot_path"
	fi
fi
cp "$($MAKE -s -f $srctree/Makefile image_name)" "$tmpdir/$installed_image_path"

if is_enabled CONFIG_OF_EARLY_FLATTREE; then
	# Only some architectures with OF support have this target
	if [ -d "${srctree}/arch/$SRCARCH/boot/dts" ]; then
		$MAKE -f $srctree/Makefile INSTALL_DTBS_PATH="$tmpdir/usr/lib/$packagename" dtbs_install
	fi
fi

if is_enabled CONFIG_MODULES; then
	INSTALL_MOD_PATH="$tmpdir" $MAKE -f $srctree/Makefile modules_install
	rm -f "$tmpdir/lib/modules/$version/build"
	rm -f "$tmpdir/lib/modules/$version/source"
	if [ "$ARCH" = "um" ] ; then
		mv "$tmpdir/lib/modules/$version"/* "$tmpdir/usr/lib/uml/modules/$version/"
		rmdir "$tmpdir/lib/modules/$version"
	fi
	if [ -n "$BUILD_DEBUG" ] ; then
		for module in $(find $tmpdir/lib/modules/ -name *.ko -printf '%P\n'); do
			module=lib/modules/$module
			mkdir -p $(dirname $dbg_dir/usr/lib/debug/$module)
			# only keep debug symbols in the debug file
			$OBJCOPY --only-keep-debug $tmpdir/$module $dbg_dir/usr/lib/debug/$module
			# strip original module from debug symbols
			$OBJCOPY --strip-debug $tmpdir/$module
			# then add a link to those
			$OBJCOPY --add-gnu-debuglink=$dbg_dir/usr/lib/debug/$module $tmpdir/$module
		done

		# resign stripped modules
		if is_enabled CONFIG_MODULE_SIG_ALL; then
			INSTALL_MOD_PATH="$tmpdir" $MAKE -f $srctree/Makefile modules_sign
		fi
	fi
fi

if [ "$ARCH" != "um" ]; then
	$MAKE -f $srctree/Makefile headers
	$MAKE -f $srctree/Makefile headers_install INSTALL_HDR_PATH="$libc_headers_dir/usr"
	# move asm headers to /usr/include/<libc-machine>/asm to match the structure
	# used by Debian-based distros (to support multi-arch)
	host_arch=$(dpkg-architecture -a$(cat debian/arch) -qDEB_HOST_MULTIARCH)
	mkdir $libc_headers_dir/usr/include/$host_arch
	mv $libc_headers_dir/usr/include/asm $libc_headers_dir/usr/include/$host_arch/
fi

# Update dtb list
for dtclist in `cat dtclist.txt`; do ls $tmpdir/$linux_path/$dtclist 2>/dev/null | tee -a dtclist.new > /dev/null 2>&1; done
grep ".dtb" "dtclist.txt" | echo "  CHKLIST `wc -l`"
rm -f "dtclist.txt"; mv -f "dtclist.new" "dtclist.txt"

# Installing dtb files
if [ -d $tmpdir/$linux_path ]; then
	mkdir -p "$tmpdir/$boot_path"
	grep ".dtb" "dtclist.txt" | echo "  CHKINST `wc -l`"
	grep ".dtb" "dtclist.txt" | sed 's/^/  DTBINST /' | sed "s/.\/debian\/tmp\/usr\/lib\/$linux_name/boot/g"
	for dtclist in `cat dtclist.txt`; do cp -r "$dtclist" 2>/dev/null "$tmpdir/$boot_path"; done
	rm -f dtclist.txt
	# install overlays
	if ls "$tmpdir/$linux_path/*.dtbo" > /dev/null 2>&1; then
		mkdir -p "$tmpdir/$linux_path/overlays"
		cp -r "$tmpdir/$linux_path/*.dtbo" "$tmpdir/$linux_path/overlays/"
		rm -f "$tmpdir/$linux_path/*.dtbo"
	fi
	if [ -d "$tmpdir/$overlays_path" ]; then
		mkdir -p "$tmpdir/$boot_path/overlays"
		cp -r "$tmpdir/$overlays_path/" "$tmpdir/$boot_path"
	else
		if [ -d "$tmpdir/$linux_path/overlays" ]; then
			mkdir -p "$tmpdir/$boot_path/overlays"
			cp -r "$tmpdir/$linux_path/overlays" "$tmpdir/$boot_path"
		fi
	fi
fi

# Install initramfs post-update script
if [ -f "initrd" ]; then
	mkdir -p "$tmpdir/etc/initramfs/post-update.d"
	mv -f "initrd" "$tmpdir/etc/initramfs/post-update.d/99-initrd"
	chmod 755 "$tmpdir/etc/initramfs/post-update.d/99-initrd"
fi

# Install the maintainer scripts
debhookdir=${KDEB_HOOKDIR:-/etc/kernel}
for script in postinst postrm preinst prerm ; do
	mkdir -p "$tmpdir$debhookdir/$script.d"
	cat <<EOF > "$tmpdir/DEBIAN/$script"
#!/bin/sh

set -e

# Pass maintainer script parameters to hook scripts
export DEB_MAINT_PARAMS="\$*"

# Tell initramfs builder whether it's wanted
export INITRD=$(if_enabled_echo CONFIG_BLK_DEV_INITRD Yes No)

test -d $debhookdir/$script.d && run-parts --arg="$version" --arg="/$installed_image_path" $debhookdir/$script.d
exit 0
EOF
	chmod 755 "$tmpdir/DEBIAN/$script"
done

# clean boot directory
cat <<EOF > "$tmpdir/DEBIAN/preinst"
#!/bin/bash
set -e

if [ -f /boot/Image ]; then
	rm -fr /boot/{Image,vmlinuz-*,System.map-*,config-*,initrd.img*,initrd.gz};
fi
if [ -d /$boot_path ]; then
	rm -fr /$boot_path/{Image,*.img,initrd.gz,initrd.img*,System.map-*,config-*,vmlinuz-*,*.dtb,bootcode.bin,fixup*.dat,start*.elf,LICENCE.broadcom,COPYING.linux};
fi
if [ -d /$boot_path/overlays ]; then
	rm -fdr /$boot_path/overlays;
fi
if [ -f /etc/initramfs/post-update.d/99-initrd ]; then
	rm -f /etc/initramfs/post-update.d/99-initrd
fi

sync
exit 0
EOF
chmod 755 "$tmpdir/DEBIAN/preinst"

# Build kernel header package
(cd $srctree; find . -name Makefile\* -o -name Kconfig\* -o -name \*.pl) > "$objtree/debian/hdrsrcfiles"
(cd $srctree; find arch/*/include include scripts -type f -o -type l) >> "$objtree/debian/hdrsrcfiles"
(cd $srctree; find arch/$SRCARCH -name module.lds -o -name Kbuild.platforms -o -name Platform) >> "$objtree/debian/hdrsrcfiles"
(cd $srctree; find $(find arch/$SRCARCH -name include -o -name scripts -type d) -type f) >> "$objtree/debian/hdrsrcfiles"
if is_enabled CONFIG_STACK_VALIDATION; then
	(cd $objtree; find tools/objtool -type f -executable) >> "$objtree/debian/hdrobjfiles"
fi
(cd $objtree; find arch/$SRCARCH/include Module.symvers include scripts -type f) >> "$objtree/debian/hdrobjfiles"
if is_enabled CONFIG_GCC_PLUGINS; then
	(cd $objtree; find scripts/gcc-plugins -name \*.so -o -name gcc-common.h) >> "$objtree/debian/hdrobjfiles"
fi
destdir=$kernel_headers_dir/usr/src/linux-headers-$version
mkdir -p "$destdir"
(cd $srctree; tar -c -f - -T -) < "$objtree/debian/hdrsrcfiles" | (cd $destdir; tar -xf -)
(cd $objtree; tar -c -f - -T -) < "$objtree/debian/hdrobjfiles" | (cd $destdir; tar -xf -)
(cd $objtree; cp $KCONFIG_CONFIG $destdir/.config) # copy .config manually to be where it's expected to be
ln -sf "/usr/src/linux-headers-$version" "$kernel_headers_dir/lib/modules/$version/build"
rm -f "$objtree/debian/hdrsrcfiles" "$objtree/debian/hdrobjfiles"

# Clean and compile headers
if [ -f headers-byteshift.patch ]; then
	cp headers-byteshift.patch $destdir/
	cp $srctree/scripts/module.lds $destdir/
	mkdir -p $kernel_headers_dir/DEBIAN
	cat <<EOF > "$kernel_headers_dir/DEBIAN/postinst"
#!/bin/bash
set -e

clean_headers(){
find -type f -exec touch {} +
if grep -w "Linux/arm" ".config"; then
	echo 'y' | make ARCH=arm M=scripts clean;
else
	echo 'y' | make M=scripts clean;
fi
if [ -f headers-byteshift.patch ]; then
	patch -p1 < headers-byteshift.patch;
fi
if [ -f scripts/module.lds ]; then
	:;
else
	install -m 0644 module.lds scripts/;
fi
rm -f {headers-byteshift.patch,module.lds}
if grep -w "Linux/arm" ".config"; then
	echo 'y' | make ARCH=arm -j\$(grep -c 'processor' /proc/cpuinfo) -s scripts;
	echo 'y' | make ARCH=arm -j\$(grep -c 'processor' /proc/cpuinfo) -s M=scripts/mod/;
else
	echo 'y' | make -j\$(grep -c 'processor' /proc/cpuinfo) -s scripts;
	echo 'y' | make -j\$(grep -c 'processor' /proc/cpuinfo) -s M=scripts/mod/;
fi
if [ -f .config.old ]; then
	rm -f .config.old;
fi
}

cd /usr/src/linux-headers-$version
echo -e "Compiling headers ..."
clean_headers > /dev/null 2>&1

sync
exit 0
EOF
	chmod 755 "$kernel_headers_dir/DEBIAN/postinst"
fi

# Remove old headers
mkdir -p $kernel_headers_dir/DEBIAN
cat <<EOF > "$kernel_headers_dir/DEBIAN/preinst"
#!/bin/bash

set -e

rm -fdr /usr/src/linux-headers-*

sync
exit 0
EOF
chmod 755 "$kernel_headers_dir/DEBIAN/preinst"

if [ "$ARCH" != "um" ]; then
	create_package "$kernel_headers_packagename" "$kernel_headers_dir"
	create_package "$libc_headers_packagename" "$libc_headers_dir"
fi

create_package "$packagename" "$tmpdir"

if [ -n "$BUILD_DEBUG" ] ; then
	# Build debug package
	# Different tools want the image in different locations
	# perf
	mkdir -p $dbg_dir/usr/lib/debug/lib/modules/$version/
	cp vmlinux $dbg_dir/usr/lib/debug/lib/modules/$version/
	# systemtap
	mkdir -p $dbg_dir/usr/lib/debug/boot/
	ln -s ../lib/modules/$version/vmlinux $dbg_dir/usr/lib/debug/boot/vmlinux-$version
	# kdump-tools
	ln -s lib/modules/$version/vmlinux $dbg_dir/usr/lib/debug/vmlinux-$version
	create_package "$dbg_packagename" "$dbg_dir"
fi

exit 0
